Convert the CLDAP server to use the new netlogon structures.
authorAndrew Bartlett <abartlet@samba.org>
Sat, 17 May 2008 02:41:42 +0000 (12:41 +1000)
committerAndrew Bartlett <abartlet@samba.org>
Sat, 17 May 2008 02:41:42 +0000 (12:41 +1000)
This also makes the CLDAP server the place where we create the
NETLOGON SAMLOGON replies, regardless of protocol (NBT mailslots or
CLDAP).

Andrew Bartlett
(This used to be commit 8b00a9429470c9ad3646255c340e6a963bd226bd)

source4/cldap_server/netlogon.c

index a524a6f8bdb3c1551ee28b44724dbaa85f0aa804..b59a54ade793601a12dc36cd6f988da4b8152add 100644 (file)
@@ -4,6 +4,7 @@
    CLDAP server - netlogon handling
 
    Copyright (C) Andrew Tridgell       2005
+   Copyright (C) Andrew Bartlett <abartlet@samba.org> 2008
    
    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
 #include "cldap_server/cldap_server.h"
 #include "librpc/gen_ndr/ndr_misc.h"
 #include "libcli/ldap/ldap_ndr.h"
+#include "libcli/security/security.h"
 #include "dsdb/samdb/samdb.h"
 #include "auth/auth.h"
 #include "ldb_wrap.h"
 #include "system/network.h"
 #include "lib/socket/netif.h"
 #include "param/param.h"
-
 /*
   fill in the cldap netlogon union for a given version
 */
-static NTSTATUS cldapd_netlogon_fill(struct cldapd_server *cldapd,
-                                    TALLOC_CTX *mem_ctx,
-                                    const char *domain,
-                                    const char *domain_guid,
-                                    const char *user,
-                                    const char *src_address,
-                                    uint32_t version,
-                                    struct loadparm_context *lp_ctx,
-                                    union nbt_cldap_netlogon *netlogon)
+NTSTATUS fill_netlogon_samlogon_response(struct ldb_context *sam_ctx,
+                                        TALLOC_CTX *mem_ctx,
+                                        const char *domain,
+                                        struct dom_sid *domain_sid,
+                                        const char *domain_guid,
+                                        const char *user,
+                                        const char *src_address,
+                                        uint32_t version,
+                                        struct loadparm_context *lp_ctx,
+                                        struct netlogon_samlogon_response *netlogon)
 {
        const char *ref_attrs[] = {"nETBIOSName", "dnsRoot", "ncName", NULL};
        const char *dom_attrs[] = {"objectGUID", NULL};
@@ -66,7 +68,7 @@ static NTSTATUS cldapd_netlogon_fill(struct cldapd_server *cldapd,
        struct ldb_dn *partitions_basedn;
        struct interface *ifaces;
 
-       partitions_basedn = samdb_partitions_dn(cldapd->samctx, mem_ctx);
+       partitions_basedn = samdb_partitions_dn(sam_ctx, mem_ctx);
 
        /* the domain has an optional trailing . */
        if (domain && domain[strlen(domain)-1] == '.') {
@@ -77,7 +79,7 @@ static NTSTATUS cldapd_netlogon_fill(struct cldapd_server *cldapd,
                struct ldb_dn *dom_dn;
                /* try and find the domain */
 
-               ret = ldb_search_exp_fmt(cldapd->samctx, mem_ctx, &ref_res, 
+               ret = ldb_search_exp_fmt(sam_ctx, mem_ctx, &ref_res, 
                                         partitions_basedn, LDB_SCOPE_ONELEVEL, 
                                         ref_attrs, 
                                         "(&(&(objectClass=crossRef)(dnsRoot=%s))(nETBIOSName=*))",
@@ -86,19 +88,19 @@ static NTSTATUS cldapd_netlogon_fill(struct cldapd_server *cldapd,
                if (ret != LDB_SUCCESS) {
                        DEBUG(2,("Unable to find referece to '%s' in sam: %s\n",
                                 domain, 
-                                ldb_errstring(cldapd->samctx)));
+                                ldb_errstring(sam_ctx)));
                        return NT_STATUS_NO_SUCH_DOMAIN;
                } else if (ref_res->count == 1) {
                        talloc_steal(mem_ctx, dom_res);
-                       dom_dn = ldb_msg_find_attr_as_dn(cldapd->samctx, mem_ctx, ref_res->msgs[0], "ncName");
+                       dom_dn = ldb_msg_find_attr_as_dn(sam_ctx, mem_ctx, ref_res->msgs[0], "ncName");
                        if (!dom_dn) {
                                return NT_STATUS_NO_SUCH_DOMAIN;
                        }
-                       ret = ldb_search(cldapd->samctx, dom_dn,
+                       ret = ldb_search(sam_ctx, dom_dn,
                                         LDB_SCOPE_BASE, "objectClass=domain", 
                                         dom_attrs, &dom_res);
                        if (ret != LDB_SUCCESS) {
-                               DEBUG(2,("Error finding domain '%s'/'%s' in sam: %s\n", domain, ldb_dn_get_linearized(dom_dn), ldb_errstring(cldapd->samctx)));
+                               DEBUG(2,("Error finding domain '%s'/'%s' in sam: %s\n", domain, ldb_dn_get_linearized(dom_dn), ldb_errstring(sam_ctx)));
                                return NT_STATUS_NO_SUCH_DOMAIN;
                        }
                        talloc_steal(mem_ctx, dom_res);
@@ -112,23 +114,31 @@ static NTSTATUS cldapd_netlogon_fill(struct cldapd_server *cldapd,
                }
        }
 
-       if ((dom_res == NULL || dom_res->count == 0) && domain_guid) {
+       if ((dom_res == NULL || dom_res->count == 0) && (domain_guid || domain_sid)) {
                ref_res = NULL;
 
-               ret = ldb_search_exp_fmt(cldapd->samctx, mem_ctx, &dom_res,
-                                NULL, LDB_SCOPE_SUBTREE, 
-                                dom_attrs, 
-                                "(&(objectClass=domainDNS)(objectGUID=%s))", 
-                                domain_guid);
+               if (domain_guid) {
+                       ret = ldb_search_exp_fmt(sam_ctx, mem_ctx, &dom_res,
+                                                NULL, LDB_SCOPE_SUBTREE, 
+                                                dom_attrs, 
+                                                "(&(objectClass=domainDNS)(objectGUID=%s))", 
+                                                domain_guid);
+               } else { /* domain_sid case */
+                       ret = ldb_search_exp_fmt(sam_ctx, mem_ctx, &dom_res,
+                                                NULL, LDB_SCOPE_SUBTREE, 
+                                                dom_attrs, 
+                                                "(&(objectClass=domainDNS)(objectSID=%s))", 
+                                                dom_sid_string(mem_ctx, domain_sid));
+               }
                
                if (ret != LDB_SUCCESS) {
-                       DEBUG(2,("Unable to find referece to GUID '%s' in sam: %s\n",
-                                domain_guid, 
-                                ldb_errstring(cldapd->samctx)));
+                       DEBUG(2,("Unable to find referece to GUID '%s' or SID %s in sam: %s\n",
+                                domain_guid, dom_sid_string(mem_ctx, domain_sid),
+                                ldb_errstring(sam_ctx)));
                        return NT_STATUS_NO_SUCH_DOMAIN;
                } else if (dom_res->count == 1) {
                        /* try and find the domain */
-                       ret = ldb_search_exp_fmt(cldapd->samctx, mem_ctx, &ref_res,
+                       ret = ldb_search_exp_fmt(sam_ctx, mem_ctx, &ref_res,
                                                 partitions_basedn, LDB_SCOPE_ONELEVEL, 
                                                 ref_attrs, 
                                                 "(&(objectClass=crossRef)(ncName=%s))", 
@@ -137,7 +147,7 @@ static NTSTATUS cldapd_netlogon_fill(struct cldapd_server *cldapd,
                        if (ret != LDB_SUCCESS) {
                                DEBUG(2,("Unable to find referece to '%s' in sam: %s\n",
                                         ldb_dn_get_linearized(dom_res->msgs[0]->dn), 
-                                        ldb_errstring(cldapd->samctx)));
+                                        ldb_errstring(sam_ctx)));
                                return NT_STATUS_NO_SUCH_DOMAIN;
                                
                        } else if (ref_res->count != 1) {
@@ -166,11 +176,11 @@ static NTSTATUS cldapd_netlogon_fill(struct cldapd_server *cldapd,
                NBT_SERVER_CLOSEST | NBT_SERVER_WRITABLE | 
                NBT_SERVER_GOOD_TIMESERV;
 
-       if (samdb_is_pdc(cldapd->samctx)) {
+       if (samdb_is_pdc(sam_ctx)) {
                server_type |= NBT_SERVER_PDC;
        }
 
-       if (samdb_is_gc(cldapd->samctx)) {
+       if (samdb_is_gc(sam_ctx)) {
                server_type |= NBT_SERVER_GC;
        }
 
@@ -200,68 +210,61 @@ static NTSTATUS cldapd_netlogon_fill(struct cldapd_server *cldapd,
 
        ZERO_STRUCTP(netlogon);
 
-       switch (version & 0xF) {
-       case 0:
-       case 1:
-               netlogon->logon1.type        = (user?19+2:19);
-               netlogon->logon1.pdc_name    = pdc_name;
-               netlogon->logon1.user_name   = user;
-               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->logon3.type         = (user?19+2:19);
-               netlogon->logon3.pdc_name     = pdc_name;
-               netlogon->logon3.user_name    = user;
-               netlogon->logon3.domain_name  = flatname;
-               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.pdc_ip       = pdc_ip;
-               netlogon->logon3.server_type  = server_type;
-               netlogon->logon3.lmnt_token   = 0xFFFF;
-               netlogon->logon3.lm20_token   = 0xFFFF;
-               break;
-       case 4:
-       case 5:
-       case 6:
-       case 7:
-               netlogon->logon5.type         = (user?NETLOGON_RESPONSE_FROM_PDC_USER:NETLOGON_RESPONSE_FROM_PDC2);
-               netlogon->logon5.server_type  = server_type;
-               netlogon->logon5.domain_uuid  = domain_uuid;
-               netlogon->logon5.forest       = realm;
-               netlogon->logon5.dns_domain   = dns_domain;
-               netlogon->logon5.pdc_dns_name = pdc_dns_name;
-               netlogon->logon5.domain       = flatname;
-               netlogon->logon5.pdc_name     = lp_netbios_name(lp_ctx);
-               netlogon->logon5.user_name    = user;
-               netlogon->logon5.server_site  = server_site;
-               netlogon->logon5.client_site  = client_site;
-               netlogon->logon5.lmnt_token   = 0xFFFF;
-               netlogon->logon5.lm20_token   = 0xFFFF;
-               break;
-       default:
-               netlogon->logon13.type         = (user?NETLOGON_RESPONSE_FROM_PDC_USER:NETLOGON_RESPONSE_FROM_PDC2);
-               netlogon->logon13.server_type  = server_type;
-               netlogon->logon13.domain_uuid  = domain_uuid;
-               netlogon->logon13.forest       = realm;
-               netlogon->logon13.dns_domain   = dns_domain;
-               netlogon->logon13.pdc_dns_name = pdc_dns_name;
-               netlogon->logon13.domain       = flatname;
-               netlogon->logon13.pdc_name     = lp_netbios_name(lp_ctx);
-               netlogon->logon13.user_name    = user;
-               netlogon->logon13.server_site  = server_site;
-               netlogon->logon13.client_site  = client_site;
-               netlogon->logon13.unknown      = 10;
-               netlogon->logon13.unknown2     = 2;
-               netlogon->logon13.pdc_ip       = pdc_ip;
-               netlogon->logon13.lmnt_token   = 0xFFFF;
-               netlogon->logon13.lm20_token   = 0xFFFF;
-               break;
+       if (version & NETLOGON_NT_VERSION_5EX) {
+               uint32_t extra_flags;
+               netlogon->ntver = NETLOGON_NT_VERSION_5EX;
+
+               /* could check if the user exists */
+               netlogon->nt5_ex.command      = LOGON_SAM_LOGON_RESPONSE_EX;
+               netlogon->nt5_ex.server_type  = server_type;
+               netlogon->nt5_ex.domain_uuid  = domain_uuid;
+               netlogon->nt5_ex.forest       = realm;
+               netlogon->nt5_ex.dns_domain   = dns_domain;
+               netlogon->nt5_ex.pdc_dns_name = pdc_dns_name;
+               netlogon->nt5_ex.domain       = flatname;
+               netlogon->nt5_ex.pdc_name     = lp_netbios_name(lp_ctx);
+               netlogon->nt5_ex.user_name    = user;
+               netlogon->nt5_ex.server_site  = server_site;
+               netlogon->nt5_ex.client_site  = client_site;
+
+               if (version & NETLOGON_NT_VERSION_5EX_WITH_IP) {
+                       /* Clearly this needs to be fixed up for IPv6 */
+                       extra_flags = NETLOGON_NT_VERSION_5EX_WITH_IP;
+                       netlogon->nt5_ex.sockaddr.sa_family    = 2;
+                       netlogon->nt5_ex.sockaddr.pdc_ip       = pdc_ip;
+               }
+               netlogon->nt5_ex.nt_version   = NETLOGON_NT_VERSION_1|NETLOGON_NT_VERSION_5|extra_flags;
+               netlogon->nt5_ex.lmnt_token   = 0xFFFF;
+               netlogon->nt5_ex.lm20_token   = 0xFFFF;
+
+       } else if (version & NETLOGON_NT_VERSION_5) {
+               netlogon->ntver = NETLOGON_NT_VERSION_5;
+
+               /* could check if the user exists */
+               netlogon->nt5.command      = LOGON_SAM_LOGON_RESPONSE;
+               netlogon->nt5.pdc_name     = pdc_name;
+               netlogon->nt5.user_name    = user;
+               netlogon->nt5.domain_name  = flatname;
+               netlogon->nt5.domain_uuid  = domain_uuid;
+               netlogon->nt5.forest       = realm;
+               netlogon->nt5.dns_domain   = dns_domain;
+               netlogon->nt5.pdc_dns_name = pdc_dns_name;
+               netlogon->nt5.pdc_ip       = pdc_ip;
+               netlogon->nt5.server_type  = server_type;
+               netlogon->nt5.nt_version   = NETLOGON_NT_VERSION_1|NETLOGON_NT_VERSION_5;
+               netlogon->nt5.lmnt_token   = 0xFFFF;
+               netlogon->nt5.lm20_token   = 0xFFFF;
+       } else {
+               netlogon->ntver = NETLOGON_NT_VERSION_1;
+               /* could check if the user exists */
+               netlogon->nt4.command     = LOGON_SAM_LOGON_RESPONSE;
+               netlogon->nt4.server      = pdc_name;
+               netlogon->nt4.user_name   = user;
+               netlogon->nt4.domain      = flatname;
+               netlogon->nt4.nt_version  = NETLOGON_NT_VERSION_1;
+               netlogon->nt4.lmnt_token  = 0xFFFF;
+               netlogon->nt4.lm20_token  = 0xFFFF;
+               
        }
 
        return NT_STATUS_OK;
@@ -285,7 +288,7 @@ void cldapd_netlogon_request(struct cldap_socket *cldap,
        const char *domain_sid = NULL;
        int acct_control = -1;
        int version = -1;
-       union nbt_cldap_netlogon netlogon;
+       struct netlogon_samlogon_response netlogon;
        NTSTATUS status = NT_STATUS_INVALID_PARAMETER;
 
        TALLOC_CTX *tmp_ctx = talloc_new(cldap);
@@ -346,9 +349,9 @@ void cldapd_netlogon_request(struct cldap_socket *cldap,
        DEBUG(5,("cldap netlogon query domain=%s host=%s user=%s version=%d guid=%s\n",
                 domain, host, user, version, domain_guid));
 
-       status = cldapd_netlogon_fill(cldapd, tmp_ctx, domain, domain_guid, 
-                                     user, src->addr, 
-                                     version, cldapd->task->lp_ctx, &netlogon);
+       status = fill_netlogon_samlogon_response(cldapd->samctx, tmp_ctx, domain, NULL, domain_guid,
+                                                user, src->addr, 
+                                                version, cldapd->task->lp_ctx, &netlogon);
        if (!NT_STATUS_IS_OK(status)) {
                goto failed;
        }