diff options
Diffstat (limited to 'source/libads')
-rw-r--r-- | source/libads/ads_ldap.c | 16 | ||||
-rw-r--r-- | source/libads/ads_struct.c | 3 | ||||
-rw-r--r-- | source/libads/ldap.c | 193 | ||||
-rw-r--r-- | source/libads/ldap_printer.c | 8 | ||||
-rw-r--r-- | source/libads/sasl.c | 5 |
5 files changed, 86 insertions, 139 deletions
diff --git a/source/libads/ads_ldap.c b/source/libads/ads_ldap.c index 97f12de0f7f..dcceaaeb835 100644 --- a/source/libads/ads_ldap.c +++ b/source/libads/ads_ldap.c @@ -34,7 +34,7 @@ NTSTATUS ads_name_to_sid(ADS_STRUCT *ads, int count; ADS_STATUS rc; void *res = NULL; - char *exp; + char *ldap_exp; uint32 t; NTSTATUS status = NT_STATUS_UNSUCCESSFUL; char *escaped_name = escape_ldap_string_alloc(name); @@ -45,15 +45,15 @@ NTSTATUS ads_name_to_sid(ADS_STRUCT *ads, goto done; } - if (asprintf(&exp, "(|(sAMAccountName=%s)(userPrincipalName=%s@%s))", + if (asprintf(&ldap_exp, "(|(sAMAccountName=%s)(userPrincipalName=%s@%s))", escaped_name, escaped_name, escaped_realm) == -1) { DEBUG(1,("ads_name_to_sid: asprintf failed!\n")); status = NT_STATUS_NO_MEMORY; goto done; } - rc = ads_search_retry(ads, &res, exp, attrs); - free(exp); + rc = ads_search_retry(ads, &res, ldap_exp, attrs); + free(ldap_exp); if (!ADS_ERR_OK(rc)) { DEBUG(1,("name_to_sid ads_search: %s\n", ads_errstr(rc))); goto done; @@ -102,7 +102,7 @@ NTSTATUS ads_sid_to_name(ADS_STRUCT *ads, "sAMAccountType", NULL}; ADS_STATUS rc; void *msg = NULL; - char *exp = NULL; + char *ldap_exp = NULL; char *sidstr = NULL; uint32 atype; NTSTATUS status = NT_STATUS_UNSUCCESSFUL; @@ -113,13 +113,13 @@ NTSTATUS ads_sid_to_name(ADS_STRUCT *ads, goto done; } - if (asprintf(&exp, "(objectSid=%s)", sidstr) == -1) { + if (asprintf(&ldap_exp, "(objectSid=%s)", sidstr) == -1) { DEBUG(1,("ads_sid_to_name: asprintf failed!\n")); status = NT_STATUS_NO_MEMORY; goto done; } - rc = ads_search_retry(ads, &msg, exp, attrs); + rc = ads_search_retry(ads, &msg, ldap_exp, attrs); if (!ADS_ERR_OK(rc)) { status = ads_ntstatus(rc); DEBUG(1,("ads_sid_to_name ads_search: %s\n", ads_errstr(rc))); @@ -146,7 +146,7 @@ NTSTATUS ads_sid_to_name(ADS_STRUCT *ads, done: if (msg) ads_msgfree(ads, msg); - SAFE_FREE(exp); + SAFE_FREE(ldap_exp); SAFE_FREE(sidstr); return status; diff --git a/source/libads/ads_struct.c b/source/libads/ads_struct.c index 652bfe31be8..dd31439d830 100644 --- a/source/libads/ads_struct.c +++ b/source/libads/ads_struct.c @@ -94,8 +94,7 @@ ADS_STRUCT *ads_init(const char *realm, ads->server.workgroup = workgroup ? strdup(workgroup) : NULL; ads->server.ldap_server = ldap_server? strdup(ldap_server) : NULL; - /* we need to know if this is a foreign realm to know if we can - use lp_ads_server() */ + /* we need to know if this is a foreign realm */ if (realm && *realm && strcasecmp(lp_realm(), realm) != 0) { ads->server.foreign = 1; } diff --git a/source/libads/ldap.c b/source/libads/ldap.c index 3ce80975da4..60bbef821ca 100644 --- a/source/libads/ldap.c +++ b/source/libads/ldap.c @@ -41,6 +41,9 @@ /* try a connection to a given ldap server, returning True and setting the servers IP in the ads struct if successful + + TODO : add a negative connection cache in here leveraged off of the one + found in the rpc code. --jerry */ static BOOL ads_try_connect(ADS_STRUCT *ads, const char *server, unsigned port) { @@ -90,133 +93,81 @@ static BOOL ads_try_connect_uri(ADS_STRUCT *ads) return False; } -/* used by the IP comparison function */ -struct ldap_ip { - struct in_addr ip; - unsigned port; -}; - -/* compare 2 ldap IPs by nearness to our interfaces - used in qsort */ -static int ldap_ip_compare(struct ldap_ip *ip1, struct ldap_ip *ip2) -{ - return ip_compare(&ip1->ip, &ip2->ip); -} +/********************************************************************** + Try to find an AD dc using our internal name resolution routines + Try the realm first and then then workgroup name if netbios is not + disabled +**********************************************************************/ -/* try connecting to a ldap server via DNS */ -static BOOL ads_try_dns(ADS_STRUCT *ads) +static BOOL ads_find_dc(ADS_STRUCT *ads) { const char *c_realm; - const char *ptr; - char *realm; - char *list = NULL; - pstring tok; - struct ldap_ip *ip_list; int count, i=0; + struct ip_service *ip_list; + pstring realm; + BOOL got_realm = False; + /* realm */ c_realm = ads->server.realm; if (!c_realm || !*c_realm) { c_realm = lp_realm(); } - if (!c_realm || !*c_realm) { - c_realm = ads->server.workgroup; - } - if (!c_realm || !*c_realm) { - c_realm = lp_workgroup(); - } - if (!c_realm) { - return False; - } - realm = smb_xstrdup(c_realm); + if ( c_realm ) + got_realm = True; - DEBUG(6,("ads_try_dns: looking for realm '%s'\n", realm)); - if (ldap_domain2hostlist(realm, &list) != LDAP_SUCCESS) { - SAFE_FREE(realm); - return False; + +again: + /* we need to try once with the realm name and fallback to the + netbios domain name if we fail (if netbios has not been disabled */ + + if ( !got_realm && !lp_disable_netbios() ) { + c_realm = ads->server.workgroup; + if (!c_realm || !*c_realm) + c_realm = lp_workgroup(); + if (!c_realm) + return False; } + + pstrcpy( realm, c_realm ); - DEBUG(6,("ads_try_dns: ldap realm '%s' host list '%s'\n", realm, list)); - SAFE_FREE(realm); + DEBUG(6,("ads_find_dc: looking for %s '%s'\n", + (got_realm ? "realm" : "domain"), realm)); - count = count_chars(list, ' ') + 1; - ip_list = malloc(count * sizeof(struct ldap_ip)); - if (!ip_list) { - return False; - } - - ptr = list; - while (next_token(&ptr, tok, " ", sizeof(tok))) { - unsigned port = LDAP_PORT; - char *p = strchr(tok, ':'); - if (p) { - *p = 0; - port = atoi(p+1); - } - ip_list[i].ip = *interpret_addr2(tok); - ip_list[i].port = port; - if (!is_zero_ip(ip_list[i].ip)) { - i++; + if ( !get_sorted_dc_list(realm, &ip_list, &count, got_realm) ) { + /* fall back to netbios if we can */ + if ( got_realm && !lp_disable_netbios() ) { + got_realm = False; + goto again; } + + return False; } - free(list); - - count = i; - - /* we sort the list of addresses by closeness to our interfaces. This - tries to prevent us using a DC on the other side of the country */ - if (count > 1) { - qsort(ip_list, count, sizeof(struct ldap_ip), - QSORT_CAST ldap_ip_compare); - } - - for (i=0;i<count;i++) { - if (ads_try_connect(ads, inet_ntoa(ip_list[i].ip), ip_list[i].port)) { - free(ip_list); + + /* if we fail this loop, then giveup since all the IP addresses returned were dead */ + for ( i=0; i<count; i++ ) { + /* since this is an ads conection request, default to LDAP_PORT is not set */ + int port = (ip_list[i].port!=PORT_NONE) ? ip_list[i].port : LDAP_PORT; + fstring server; + + fstrcpy( server, inet_ntoa(ip_list[i].ip) ); + + if ( !NT_STATUS_IS_OK(check_negative_conn_cache(realm, server)) ) + continue; + + if ( ads_try_connect(ads, server, port) ) { + SAFE_FREE(ip_list); return True; } + + /* keep track of failures */ + add_failed_connection_entry( realm, server, NT_STATUS_UNSUCCESSFUL ); } SAFE_FREE(ip_list); + return False; } -/* try connecting to a ldap server via netbios */ -static BOOL ads_try_netbios(ADS_STRUCT *ads) -{ - struct in_addr *ip_list, pdc_ip; - int count; - int i; - const char *workgroup = ads->server.workgroup; - BOOL list_ordered; - - if (!workgroup) { - workgroup = lp_workgroup(); - } - - DEBUG(6,("ads_try_netbios: looking for workgroup '%s'\n", workgroup)); - - /* try the PDC first */ - if (get_pdc_ip(workgroup, &pdc_ip)) { - DEBUG(6,("ads_try_netbios: trying server '%s'\n", - inet_ntoa(pdc_ip))); - if (ads_try_connect(ads, inet_ntoa(pdc_ip), LDAP_PORT)) - return True; - } - - /* now any DC, including backups */ - if (get_dc_list(workgroup, &ip_list, &count, &list_ordered)) { - for (i=0;i<count;i++) { - DEBUG(6,("ads_try_netbios: trying server '%s'\n", - inet_ntoa(ip_list[i]))); - if (ads_try_connect(ads, inet_ntoa(ip_list[i]), LDAP_PORT)) { - free(ip_list); - return True; - } - } - free(ip_list); - } - - return False; -} /** * Connect to the LDAP server @@ -244,20 +195,7 @@ ADS_STATUS ads_connect(ADS_STRUCT *ads) goto got_connection; } - /* try with a smb.conf ads server setting if we are connecting - to the primary workgroup or realm */ - if (!ads->server.foreign && - ads_try_connect(ads, lp_ads_server(), LDAP_PORT)) { - goto got_connection; - } - - /* try via DNS */ - if (ads_try_dns(ads)) { - goto got_connection; - } - - /* try via netbios lookups */ - if (!lp_disable_netbios() && ads_try_netbios(ads)) { + if (ads_find_dc(ads)) { goto got_connection; } @@ -749,14 +687,15 @@ void ads_memfree(ADS_STRUCT *ads, void *mem) /** * Get a dn from search results * @param ads connection to ads server - * @param res Search results + * @param msg Search result * @return dn string **/ -char *ads_get_dn(ADS_STRUCT *ads, void *res) +char *ads_get_dn(ADS_STRUCT *ads, void *msg) { char *utf8_dn, *unix_dn; - utf8_dn = ldap_get_dn(ads->ld, res); + utf8_dn = ldap_get_dn(ads->ld, msg); + pull_utf8_allocate((void **) &unix_dn, utf8_dn); ldap_memfree(utf8_dn); return unix_dn; @@ -1078,6 +1017,7 @@ static ADS_STATUS ads_add_machine_acct(ADS_STRUCT *ads, const char *hostname, #ifndef ENCTYPE_ARCFOUR_HMAC acct_control |= UF_USE_DES_KEY_ONLY; #endif + if (!(controlstr = talloc_asprintf(ctx, "%u", acct_control))) goto done; @@ -1142,7 +1082,7 @@ static void dump_guid(const char *field, struct berval **values) GUID guid; for (i=0; values[i]; i++) { memcpy(guid.info, values[i]->bv_val, sizeof(guid.info)); - printf("%s: %s\n", field, uuid_string_static(guid)); + printf("%s: %s\n", field, smb_uuid_string_static(guid)); } } @@ -1384,7 +1324,7 @@ ADS_STATUS ads_join_realm(ADS_STRUCT *ads, const char *hostname, ADS_STATUS ads_leave_realm(ADS_STRUCT *ads, const char *hostname) { ADS_STATUS status; - void *res; + void *res, *msg; char *hostnameDN, *host; int rc; @@ -1398,7 +1338,12 @@ ADS_STATUS ads_leave_realm(ADS_STRUCT *ads, const char *hostname) return status; } - hostnameDN = ads_get_dn(ads, (LDAPMessage *)res); + msg = ads_first_entry(ads, res); + if (!msg) { + return ADS_ERROR_SYSTEM(ENOENT); + } + + hostnameDN = ads_get_dn(ads, (LDAPMessage *)msg); rc = ldap_delete_s(ads->ld, hostnameDN); ads_memfree(ads, hostnameDN); if (rc != LDAP_SUCCESS) { diff --git a/source/libads/ldap_printer.c b/source/libads/ldap_printer.c index f5cd4f2885d..aa5ac15b5dd 100644 --- a/source/libads/ldap_printer.c +++ b/source/libads/ldap_printer.c @@ -31,7 +31,7 @@ ADS_STATUS ads_find_printer_on_server(ADS_STRUCT *ads, void **res, const char *printer, const char *servername) { ADS_STATUS status; - char *srv_dn, **srv_cn, *exp; + char *srv_dn, **srv_cn, *s; const char *attrs[] = {"*", "nTSecurityDescriptor", NULL}; status = ads_find_machine_acct(ads, res, servername); @@ -44,12 +44,12 @@ ADS_STATUS ads_find_printer_on_server(ADS_STRUCT *ads, void **res, srv_cn = ldap_explode_dn(srv_dn, 1); ads_msgfree(ads, *res); - asprintf(&exp, "(cn=%s-%s)", srv_cn[0], printer); - status = ads_search(ads, res, exp, attrs); + asprintf(&s, "(cn=%s-%s)", srv_cn[0], printer); + status = ads_search(ads, res, s, attrs); ldap_memfree(srv_dn); ldap_value_free(srv_cn); - free(exp); + free(s); return status; } diff --git a/source/libads/sasl.c b/source/libads/sasl.c index 29d4533a54f..598208b17f8 100644 --- a/source/libads/sasl.c +++ b/source/libads/sasl.c @@ -198,8 +198,11 @@ static ADS_STATUS ads_sasl_spnego_bind(ADS_STRUCT *ads) if (ads_kinit_password(ads) == 0) { status = ads_sasl_spnego_krb5_bind(ads, principal); } - if (ADS_ERR_OK(status)) + /* only fallback to NTLMSSP if allowed */ + if (ADS_ERR_OK(status) || + !(ads->auth.flags & ADS_AUTH_ALLOW_NTLMSSP)) { return status; + } } #endif |