diff options
-rw-r--r-- | source3/libaddns/dns.h | 2 | ||||
-rw-r--r-- | source3/libaddns/dnsrecord.c | 4 | ||||
-rw-r--r-- | source3/libads/ads_struct.c | 22 | ||||
-rw-r--r-- | source3/utils/net_ads.c | 106 | ||||
-rw-r--r-- | source3/utils/net_dns.c | 26 |
5 files changed, 90 insertions, 70 deletions
diff --git a/source3/libaddns/dns.h b/source3/libaddns/dns.h index e8fa12c492..1240174076 100644 --- a/source3/libaddns/dns.h +++ b/source3/libaddns/dns.h @@ -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); diff --git a/source3/libaddns/dnsrecord.c b/source3/libaddns/dnsrecord.c index 0cf4793935..11c6884d9d 100644 --- a/source3/libaddns/dnsrecord.c +++ b/source3/libaddns/dnsrecord.c @@ -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; diff --git a/source3/libads/ads_struct.c b/source3/libads/ads_struct.c index 130d86b8dc..545995ddcc 100644 --- a/source3/libads/ads_struct.c +++ b/source3/libads/ads_struct.c @@ -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 diff --git a/source3/utils/net_ads.c b/source3/utils/net_ads.c index 359e1ef240..8c35f201ad 100644 --- a/source3/utils/net_ads.c +++ b/source3/utils/net_ads.c @@ -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 diff --git a/source3/utils/net_dns.c b/source3/utils/net_dns.c index 81d7dd596a..16f50ae4cd 100644 --- a/source3/utils/net_dns.c +++ b/source3/utils/net_dns.c @@ -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 ); |