r20173: DNS update fixes:
authorGerald Carter <jerry@samba.org>
Thu, 14 Dec 2006 17:00:10 +0000 (17:00 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 17:16:29 +0000 (12:16 -0500)
* Fix DNS updates for multi-homed hosts
* Child domains often don't have an NS record in
  DNS so we have to fall back to looking up the the NS
  records for the forest root.
* Fix compile warning caused by mismatched 'struct in_addr'
  and 'in_addr_t' parameters called to DoDNSUpdate()
(This used to be commit 3486acd3c3ebefae8f98dcc72d1c3d6b06fffcc7)

source3/libaddns/dns.h
source3/libaddns/dnsrecord.c
source3/libads/ads_struct.c
source3/utils/net_ads.c
source3/utils/net_dns.c

index e8fa12c492ddf281a122d15433b01302840e47c4..1240174076144d29508eb76fa010a02362b8adb8 100644 (file)
@@ -493,7 +493,7 @@ DNS_ERROR dns_sign_update(struct dns_update_request *req,
 DNS_ERROR dns_create_update_request(TALLOC_CTX *mem_ctx,
                                    const char *domainname,
                                    const char *hostname,
-                                   const in_addr_t *ip_addr,
+                                   const struct in_addr *ip_addr,
                                    size_t num_adds,
                                    struct dns_update_request **preq);
 
index 0cf4793935d0ac204a8165870504cfb18cf32e91..11c6884d9d5f88d545ceac6350362bbc2ac31bf4 100644 (file)
@@ -356,7 +356,7 @@ DNS_ERROR dns_create_probe(TALLOC_CTX *mem_ctx, const char *zone,
 DNS_ERROR dns_create_update_request(TALLOC_CTX *mem_ctx,
                                    const char *domainname,
                                    const char *hostname,
-                                   const in_addr_t *ip_addr,
+                                   const struct in_addr *ip_addrs,
                                    size_t num_addrs,
                                    struct dns_update_request **preq)
 {
@@ -395,7 +395,7 @@ DNS_ERROR dns_create_update_request(TALLOC_CTX *mem_ctx,
         */
 
        for ( i=0; i<num_addrs; i++ ) {         
-               err = dns_create_a_record(req, hostname, 3600, ip_addr[i], &rec);
+               err = dns_create_a_record(req, hostname, 3600, ip_addrs[i].s_addr, &rec);
                if (!ERR_DNS_IS_OK(err)) 
                        goto error;
 
index 130d86b8dc8a10b3be30cd588eaec7200d802827..545995ddccc103c5df87276f3385de717b31afd8 100644 (file)
@@ -75,6 +75,28 @@ char *ads_build_dn(const char *realm)
        return ads_build_path(realm, ".", "dc=", 0);
 }
 
+/* return a DNS name in the for aa.bb.cc from the DN  
+   "dc=AA,dc=BB,dc=CC".  caller must free
+*/
+char *ads_build_domain(const char *dn)
+{
+       char *dnsdomain = NULL;
+       
+       /* result should always be shorter than the DN */
+
+       if ( (dnsdomain = SMB_STRDUP( dn )) == NULL ) {
+               DEBUG(0,("ads_build_domain: malloc() failed!\n"));              
+               return NULL;            
+       }       
+
+       strlower_m( dnsdomain );        
+       all_string_sub( dnsdomain, "dc=", "", 0);
+       all_string_sub( dnsdomain, ",", ".", 0 );
+
+       return dnsdomain;       
+}
+
+
 
 #ifndef LDAP_PORT
 #define LDAP_PORT 389
index 359e1ef2407d218ffe2a21ecf075333893e4a7ff..8c35f201ad733298e09add68baeeafd3e63f2268 100644 (file)
@@ -1221,7 +1221,7 @@ static BOOL net_derive_salting_principal( TALLOC_CTX *ctx, ADS_STRUCT *ads )
 
 #if defined(WITH_DNS_UPDATES)
 #include "dns.h"
-DNS_ERROR DoDNSUpdate(ADS_STRUCT *ads, char *pszServerName,
+DNS_ERROR DoDNSUpdate(char *pszServerName,
                      const char *pszDomainName,
                      const char *pszHostName,
                      const struct in_addr *iplist, int num_addrs );
@@ -1237,7 +1237,8 @@ static NTSTATUS net_update_dns_internal(TALLOC_CTX *ctx, ADS_STRUCT *ads,
        NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
        DNS_ERROR dns_err;
        fstring dns_server;
-       const char *dnsdomain;
+       const char *dnsdomain = NULL;   
+       char *root_domain = NULL;       
 
        if ( (dnsdomain = strchr_m( machine_name, '.')) == NULL ) {
                d_printf("No DNS domain configured for %s. "
@@ -1249,9 +1250,52 @@ static NTSTATUS net_update_dns_internal(TALLOC_CTX *ctx, ADS_STRUCT *ads,
 
        status = ads_dns_lookup_ns( ctx, dnsdomain, &nameservers, &ns_count );
        if ( !NT_STATUS_IS_OK(status) || (ns_count == 0)) {
-               DEBUG(3,("net_ads_join: Failed to find name server for the %s "
+               /* Child domains often do not have NS records.  Look
+                  for the NS record for the forest root domain 
+                  (rootDomainNamingContext in therootDSE) */
+
+               const char *rootname_attrs[] =  { "rootDomainNamingContext", NULL };
+               LDAPMessage *msg = NULL;
+               char *root_dn;
+               ADS_STATUS ads_status;
+               
+               if ( !ads->ld ) {
+                       ads_status = ads_connect( ads );
+                       if ( !ADS_ERR_OK(ads_status) ) {
+                               DEBUG(0,("net_update_dns_internal: Failed to connect to our DC!\n"));
+                               goto done;                              
+                       }                       
+               }
+               
+               ads_status = ads_do_search(ads, "", LDAP_SCOPE_BASE, 
+                                      "(objectclass=*)", rootname_attrs, &msg);
+               if (!ADS_ERR_OK(ads_status)) {
+                       goto done;
+               }
+
+               root_dn = ads_pull_string(ads, ctx, msg,  "rootDomainNamingContext");
+               if ( !root_dn ) {
+                       ads_msgfree( ads, msg );                        
+                       goto done;
+               }
+
+               root_domain = ads_build_domain( root_dn );
+
+               /* cleanup */
+               ads_msgfree( ads, msg );
+
+               /* try again for NS servers */
+
+               status = ads_dns_lookup_ns( ctx, root_domain, &nameservers, &ns_count );
+               
+               if ( !NT_STATUS_IS_OK(status) || (ns_count == 0)) {                     
+                       DEBUG(3,("net_ads_join: Failed to find name server for the %s "
                         "realm\n", ads->config.realm));
-               goto done;
+                       goto done;
+               }
+
+               dnsdomain = root_domain;                
+               
        }
 
        /* Now perform the dns update - we'll try non-secure and if we fail,
@@ -1259,14 +1303,17 @@ static NTSTATUS net_update_dns_internal(TALLOC_CTX *ctx, ADS_STRUCT *ads,
 
        fstrcpy( dns_server, nameservers[0].hostname );
 
-       dns_err = DoDNSUpdate(ads, dns_server, dnsdomain, machine_name, addrs, num_addrs);
+       dns_err = DoDNSUpdate(dns_server, dnsdomain, machine_name, addrs, num_addrs);
        if (!ERR_DNS_IS_OK(dns_err)) {
                status = NT_STATUS_UNSUCCESSFUL;
        }
 
 done:
+
+       SAFE_FREE( root_domain );
+       
        return status;
-       }
+}
 
 static NTSTATUS net_update_dns(TALLOC_CTX *mem_ctx, ADS_STRUCT *ads)
 {
@@ -1345,6 +1392,8 @@ int net_ads_join(int argc, const char **argv)
        const char *machineupn = NULL;
        const char *create_in_ou = NULL;
        int i;
+       fstring dc_name;
+       struct in_addr dcip;
        
        nt_status = check_ads_config();
        if (!NT_STATUS_IS_OK(nt_status)) {
@@ -1352,6 +1401,10 @@ int net_ads_join(int argc, const char **argv)
                goto fail;
        }
 
+       /* find a DC to initialize the server affinity cache */
+
+       get_dc_name( lp_workgroup(), lp_realm(), dc_name, &dcip );
+
        status = ads_startup(True, &ads);
        if (!ADS_ERR_OK(status)) {
                DEBUG(1, ("error on ads_startup: %s\n", ads_errstr(status)));
@@ -1575,15 +1628,12 @@ static int net_ads_dns_register(int argc, const char **argv)
        ADS_STRUCT *ads;
        ADS_STATUS status;
        TALLOC_CTX *ctx;
-       fstring name;
-       int num_addrs;
-       struct in_addr *iplist = NULL;
        
 #ifdef DEVELOPER
        talloc_enable_leak_report();
 #endif
        
-       if (argc > 2) {
+       if (argc > 0) {
                d_fprintf(stderr, "net ads dns register <name> <ip>\n");
                return -1;
        }
@@ -1593,48 +1643,17 @@ static int net_ads_dns_register(int argc, const char **argv)
                return -1;
        }
 
-       if (argc > 0) {
-               fstrcpy(name, argv[0]);
-       } else {
-               name_to_fqdn(name, global_myname());
-       }
-       strlower_m(name);
-       
-       if (argc > 1) {
-               if (!(iplist = SMB_MALLOC_ARRAY(struct in_addr, 1))) {
-                       d_fprintf(stderr, "net_ads_dns_register: malloc "
-                                 "failed\n");
-                       return -1;
-               }
-               if (inet_aton(argv[1], iplist) == 0) {
-                       d_fprintf(stderr, "net_ads_dns_register: %s is not "
-                                 "a valid IP address\n", argv[1]);
-                       SAFE_FREE(iplist);
-                       return -1;
-               }
-               num_addrs = 1;
-       } else {
-               num_addrs = get_my_ip_address( &iplist );
-               if ( num_addrs <= 0 ) {
-                       d_fprintf(stderr, "net_ads_dns_regiser: Failed to "
-                                 "find my non-loopback IP addresses!\n");
-                       return -1;
-               }
-       }
-       
-       status = ads_startup_nobind(True, &ads);
+       status = ads_startup(True, &ads);
        if ( !ADS_ERR_OK(status) ) {
                DEBUG(1, ("error on ads_startup: %s\n", ads_errstr(status)));
                TALLOC_FREE(ctx);
                return -1;
        }
 
-       if ( !NT_STATUS_IS_OK(net_update_dns_internal(ctx, ads, name,
-                                                     iplist, num_addrs)) ) {
+       if ( !NT_STATUS_IS_OK(net_update_dns(ctx, ads)) ) {             
                d_fprintf( stderr, "DNS update failed!\n" );
                ads_destroy( &ads );
                TALLOC_FREE( ctx );
-               SAFE_FREE(iplist);
                return -1;
        }
        
@@ -1642,7 +1661,6 @@ static int net_ads_dns_register(int argc, const char **argv)
 
        ads_destroy(&ads);
        TALLOC_FREE( ctx );
-       SAFE_FREE(iplist);
        
        return 0;
 #else
index 81d7dd596a8fea1c8fc99c580d448c125ae4172d..16f50ae4cd876d816a410ae70a94bc5acbedf94a 100644 (file)
@@ -30,9 +30,9 @@
 /*********************************************************************
 *********************************************************************/
 
-DNS_ERROR DoDNSUpdate(ADS_STRUCT *ads, char *pszServerName,
+DNS_ERROR DoDNSUpdate(char *pszServerName,
                      const char *pszDomainName, const char *pszHostName,
-                     const struct in_addr *iplist, int num_addrs )
+                     const struct in_addr *iplist, size_t num_addrs )
 {
        DNS_ERROR err;
        struct dns_connection *conn;
@@ -74,7 +74,7 @@ DNS_ERROR DoDNSUpdate(ADS_STRUCT *ads, char *pszServerName,
         */
 
        err = dns_create_update_request(mem_ctx, pszDomainName, pszHostName,
-                                       iplist[0].s_addr, &req);
+                                       iplist, num_addrs, &req);
        if (!ERR_DNS_IS_OK(err)) goto error;
 
        err = dns_update_transaction(mem_ctx, conn, req, &resp);
@@ -89,9 +89,7 @@ DNS_ERROR DoDNSUpdate(ADS_STRUCT *ads, char *pszServerName,
         * Okay, we have to try with signing
         */
        {
-               ADS_STRUCT *ads_s;
                gss_ctx_id_t gss_context;
-               int res;
                char *keyname;
 
                if (!(keyname = dns_generate_keyname( mem_ctx ))) {
@@ -99,24 +97,6 @@ DNS_ERROR DoDNSUpdate(ADS_STRUCT *ads, char *pszServerName,
                        goto error;
                }
 
-               if (!(ads_s = ads_init(ads->server.realm, ads->server.workgroup,
-                                      ads->server.ldap_server))) {
-                       return ERROR_DNS_NO_MEMORY;
-               }
-               
-               /* kinit with the machine password */
-               setenv(KRB5_ENV_CCNAME, "MEMORY:net_ads", 1);
-               asprintf( &ads_s->auth.user_name, "%s$", global_myname() );
-               ads_s->auth.password = secrets_fetch_machine_password(
-                       lp_workgroup(), NULL, NULL );
-               ads_s->auth.realm = SMB_STRDUP( lp_realm() );
-               res = ads_kinit_password( ads_s );
-               ads_destroy(&ads_s);
-               if (res) {
-                       err = ERROR_DNS_GSS_ERROR;
-                       goto error;
-               }
-
                err = dns_negotiate_sec_ctx( pszDomainName, pszServerName,
                                             keyname, &gss_context, DNS_SRV_ANY );