From 2279d1ebfb0a750d92ca0c4a9dc9803c35c845d9 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 12 May 2005 08:28:07 +0000 Subject: r6747: first working version of cldapd server. It is missing 'sites' support, and filling in some of the returned parameters is quite rough, but it seems to work OK (This used to be commit e564e3e596915414fad07c94f7ea8a0d9c3a1140) --- source4/cldap_server/cldap_server.c | 20 +++- source4/cldap_server/cldap_server.h | 1 + source4/cldap_server/config.mk | 2 + source4/cldap_server/netlogon.c | 233 ++++++++++++++++++++++++++++++++++++ source4/include/structs.h | 1 + 5 files changed, 252 insertions(+), 5 deletions(-) create mode 100644 source4/cldap_server/netlogon.c (limited to 'source4') diff --git a/source4/cldap_server/cldap_server.c b/source4/cldap_server/cldap_server.c index 8397a624c0..ad4779da01 100644 --- a/source4/cldap_server/cldap_server.c +++ b/source4/cldap_server/cldap_server.c @@ -27,7 +27,6 @@ #include "smbd/service_task.h" #include "cldap_server/cldap_server.h" - /* handle incoming cldap requests */ @@ -35,16 +34,27 @@ static void cldapd_request_handler(struct cldap_socket *cldap, struct ldap_message *ldap_msg, const char *src_address, int src_port) { - struct cldapd_server *cldapd = talloc_get_type(cldap->incoming.private, - struct cldapd_server); + struct ldap_SearchRequest *search; if (ldap_msg->type != LDAP_TAG_SearchRequest) { DEBUG(0,("Invalid CLDAP request type %d from %s:%d\n", ldap_msg->type, src_address, src_port)); return; } - DEBUG(0,("CLDAP search for '%s'\n", ldap_msg->r.SearchRequest.filter)); + + search = &ldap_msg->r.SearchRequest; + + if (search->num_attributes == 1 && + strcasecmp(search->attributes[0], "netlogon") == 0) { + cldapd_netlogon_request(cldap, ldap_msg->messageid, + search->filter, src_address, src_port); + } else { + DEBUG(0,("Unknown CLDAP search for '%s'\n", + ldap_msg->r.SearchRequest.filter)); + cldap_empty_reply(cldap, ldap_msg->messageid, src_address, src_port); + } } + /* start listening on the given address */ @@ -81,7 +91,7 @@ NTSTATUS cldapd_startup_interfaces(struct cldapd_server *cldapd) NTSTATUS status; /* if we are allowing incoming packets from any address, then - we also need to bind to the wildcard address */ + we need to bind to the wildcard address */ if (!lp_bind_interfaces_only()) { status = cldapd_add_socket(cldapd, "0.0.0.0"); NT_STATUS_NOT_OK_RETURN(status); diff --git a/source4/cldap_server/cldap_server.h b/source4/cldap_server/cldap_server.h index f110d05d16..e3d7c06ab3 100644 --- a/source4/cldap_server/cldap_server.h +++ b/source4/cldap_server/cldap_server.h @@ -27,4 +27,5 @@ */ struct cldapd_server { struct task_server *task; + const char *dns_domain; }; diff --git a/source4/cldap_server/config.mk b/source4/cldap_server/config.mk index 225fb1cf08..a2042cecc5 100644 --- a/source4/cldap_server/config.mk +++ b/source4/cldap_server/config.mk @@ -5,6 +5,8 @@ [SUBSYSTEM::CLDAPD] INIT_OBJ_FILES = \ cldap_server/cldap_server.o +ADD_OBJ_FILES = \ + cldap_server/netlogon.o REQUIRED_SUBSYSTEMS = \ LIBCLI_CLDAP # End SUBSYSTEM CLDAPD diff --git a/source4/cldap_server/netlogon.c b/source4/cldap_server/netlogon.c new file mode 100644 index 0000000000..ca77ea17b2 --- /dev/null +++ b/source4/cldap_server/netlogon.c @@ -0,0 +1,233 @@ +/* + Unix SMB/CIFS implementation. + + CLDAP server - netlogon handling + + Copyright (C) Andrew Tridgell 2005 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" +#include "libcli/ldap/ldap.h" +#include "lib/events/events.h" +#include "lib/socket/socket.h" +#include "smbd/service_task.h" +#include "cldap_server/cldap_server.h" + +/* + fill in the cldap netlogon union for a given version +*/ +static NTSTATUS cldapd_netlogon_fill(struct cldap_socket *cldap, + TALLOC_CTX *mem_ctx, + const char *domain, + const char *src_address, + uint32_t version, + union nbt_cldap_netlogon *netlogon) +{ + struct ldb_context *samctx; + const char *attrs[] = {"realm", "dnsDomain", "objectGUID", "name", NULL}; + struct ldb_message **res; + int ret; + const char **services = lp_server_services(); + uint32_t server_type; + const char *pdc_name; + struct GUID domain_uuid; + const char *realm; + const char *dns_domain; + const char *pdc_dns_name; + const char *flatname; + const char *site_name; + const char *site_name2; + const char *pdc_ip; + + samctx = samdb_connect(mem_ctx); + if (samctx == NULL) { + DEBUG(2,("Unable to open sam in cldap netlogon reply\n")); + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } + + /* try and find the domain */ + ret = gendb_search(samctx, samctx, NULL, &res, attrs, + "(&(dnsDomain=%s)(objectClass=domainDNS))", domain); + if (ret != 1) { + DEBUG(2,("Unable to find domain '%s' in sam\n", domain)); + return NT_STATUS_NO_SUCH_DOMAIN; + } + + server_type = + NBT_SERVER_PDC | NBT_SERVER_GC | + NBT_SERVER_DS | NBT_SERVER_TIMESERV | + NBT_SERVER_CLOSEST | NBT_SERVER_WRITABLE | + NBT_SERVER_GOOD_TIMESERV; + + if (lp_parm_bool(-1, "gensec", "krb5", True)) { + server_type |= NBT_SERVER_KDC; + } + if (str_list_check(services, "ldap")) { + server_type |= NBT_SERVER_LDAP; + } + + pdc_name = talloc_asprintf(mem_ctx, "\\\\%s", lp_netbios_name()); + domain_uuid = samdb_result_guid(res[0], "objectGUID"); + realm = samdb_result_string(res[0], "realm", lp_realm()); + dns_domain = samdb_result_string(res[0], "dnsDomain", lp_realm()); + pdc_dns_name = talloc_asprintf(mem_ctx, "%s.%s", + lp_netbios_name(), dns_domain); + flatname = samdb_result_string(res[0], "name", lp_workgroup()); + site_name = "Default-First-Site-Name"; + site_name2 = ""; + pdc_ip = iface_best_ip(src_address); + + ZERO_STRUCTP(netlogon); + + switch (version & 0xF) { + case 0: + case 1: + netlogon->logon1.pdc_name = pdc_name; + netlogon->logon1.unknown = ""; + netlogon->logon1.domain_name = flatname; + netlogon->logon1.nt_version = 1; + netlogon->logon1.lmnt_token = 0xFFFF; + netlogon->logon1.lm20_token = 0xFFFF; + break; + case 2: + case 3: + netlogon->logon2.pdc_name = pdc_name; + netlogon->logon2.unknown = ""; + netlogon->logon2.domain_name = flatname; + netlogon->logon2.domain_uuid = domain_uuid; + netlogon->logon2.forest = realm; + netlogon->logon2.dns_domain = dns_domain; + netlogon->logon2.pdc_dns_name = pdc_dns_name; + netlogon->logon2.pdc_ip = pdc_ip; + netlogon->logon2.server_type = server_type; + netlogon->logon2.nt_version = 3; + netlogon->logon2.lmnt_token = 0xFFFF; + netlogon->logon2.lm20_token = 0xFFFF; + break; + case 4: + case 5: + case 6: + case 7: + netlogon->logon3.server_type = server_type; + netlogon->logon3.domain_uuid = domain_uuid; + netlogon->logon3.forest = realm; + netlogon->logon3.dns_domain = dns_domain; + netlogon->logon3.pdc_dns_name = pdc_dns_name; + netlogon->logon3.domain = flatname; + netlogon->logon3.pdc_name = pdc_name; + netlogon->logon3.user_name = ""; + netlogon->logon3.site_name = site_name; + netlogon->logon3.site_name2 = site_name2; + netlogon->logon3.nt_version = 3; + netlogon->logon3.lmnt_token = 0xFFFF; + netlogon->logon3.lm20_token = 0xFFFF; + break; + default: + netlogon->logon4.server_type = server_type; + netlogon->logon4.domain_uuid = domain_uuid; + netlogon->logon4.forest = realm; + netlogon->logon4.dns_domain = dns_domain; + netlogon->logon4.pdc_dns_name = pdc_dns_name; + netlogon->logon4.domain = flatname; + netlogon->logon4.pdc_name = lp_netbios_name(); + netlogon->logon4.user_name = ""; + netlogon->logon4.site_name = site_name; + netlogon->logon4.site_name2 = site_name2; + netlogon->logon4.unknown = 10; + netlogon->logon4.unknown2 = 2; + netlogon->logon4.pdc_ip = pdc_ip; + netlogon->logon4.nt_version = 5; + netlogon->logon4.lmnt_token = 0xFFFF; + netlogon->logon4.lm20_token = 0xFFFF; + break; + } + + return NT_STATUS_OK; +} + + +/* + handle incoming cldap requests +*/ +void cldapd_netlogon_request(struct cldap_socket *cldap, + uint32_t message_id, + const char *filter, + const char *src_address, int src_port) +{ + struct ldap_parse_tree *tree; + int i; + const char *domain = NULL; + const char *host = NULL; + int version = -1; + union nbt_cldap_netlogon netlogon; + NTSTATUS status = NT_STATUS_INVALID_PARAMETER; + + TALLOC_CTX *tmp_ctx = talloc_new(cldap); + + tree = ldap_parse_filter_string(tmp_ctx, filter); + if (tree == NULL) goto failed; + + if (tree->operation != LDAP_OP_AND) goto failed; + + /* extract the query elements */ + for (i=0;iu.list.num_elements;i++) { + struct ldap_parse_tree *t = tree->u.list.elements[i]; + if (t->operation != LDAP_OP_SIMPLE) goto failed; + if (strcasecmp(t->u.simple.attr, "DnsDomain") == 0) { + domain = talloc_strndup(tmp_ctx, + t->u.simple.value.data, + t->u.simple.value.length); + } + if (strcasecmp(t->u.simple.attr, "Host") == 0) { + host = talloc_strndup(tmp_ctx, + t->u.simple.value.data, + t->u.simple.value.length); + } + if (strcasecmp(t->u.simple.attr, "NtVer") == 0 && + t->u.simple.value.length == 4) { + version = IVAL(t->u.simple.value.data, 0); + } + } + + if (domain == NULL || host == NULL || version == -1) { + goto failed; + } + + DEBUG(2,("cldap netlogon query domain=%s host=%s version=%d\n", + domain, host, version)); + + status = cldapd_netlogon_fill(cldap, tmp_ctx, domain, src_address, + version, &netlogon); + if (!NT_STATUS_IS_OK(status)) { + goto failed; + } + + status = cldap_netlogon_reply(cldap, message_id, src_address, src_port, version, + &netlogon); + if (!NT_STATUS_IS_OK(status)) { + goto failed; + } + + talloc_free(tmp_ctx); + return; + +failed: + DEBUG(0,("cldap netlogon query failed domain=%s host=%s version=%d - %s\n", + domain, host, version, nt_errstr(status))); + talloc_free(tmp_ctx); + cldap_empty_reply(cldap, message_id, src_address, src_port); +} diff --git a/source4/include/structs.h b/source4/include/structs.h index 6fec1ff257..8204cb769d 100644 --- a/source4/include/structs.h +++ b/source4/include/structs.h @@ -192,6 +192,7 @@ struct nbtd_server; struct nbtd_interface; struct wins_server; +struct cldap_socket; struct cldapd_server; struct mutex_ops; -- cgit