From c0a991943044e038b78f796fb35d7625eb843d85 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 18 Apr 2002 06:56:44 +0000 Subject: fixed the fallback to a BDC for ADS connections (This used to be commit 3e58a1ee83ea0b4347ce24e566445cc6cb67bb3a) --- source3/include/ads.h | 1 + source3/libads/ads_struct.c | 19 ++++++++++++++++++- source3/libads/ldap.c | 24 ++++++++++++++++++++++++ source3/nsswitch/winbindd_ads.c | 4 +++- source3/smbd/negprot.c | 2 +- source3/smbd/sesssetup.c | 2 +- source3/utils/net_ads.c | 9 ++++----- 7 files changed, 52 insertions(+), 9 deletions(-) diff --git a/source3/include/ads.h b/source3/include/ads.h index 8658e72f6a..b3e18f18b8 100644 --- a/source3/include/ads.h +++ b/source3/include/ads.h @@ -7,6 +7,7 @@ typedef struct { void *ld; char *realm; + char *workgroup; char *ldap_server; char *ldap_server_name; char *kdc_server; diff --git a/source3/libads/ads_struct.c b/source3/libads/ads_struct.c index 489f301ae2..816b616097 100644 --- a/source3/libads/ads_struct.c +++ b/source3/libads/ads_struct.c @@ -90,7 +90,12 @@ static char *find_ldap_server(ADS_STRUCT *ads) } /* get desperate, find the domain controller IP */ - if (resolve_name(lp_workgroup(), &ip, 0x1B)) { + if (resolve_name(ads->workgroup, &ip, 0x1B)) { + return strdup(inet_ntoa(ip)); + } + + /* or a BDC ... */ + if (resolve_name(ads->workgroup, &ip, 0x1C)) { return strdup(inet_ntoa(ip)); } @@ -115,6 +120,7 @@ static char *find_ldap_server(ADS_STRUCT *ads) initialise a ADS_STRUCT, ready for some ads_ ops */ ADS_STRUCT *ads_init(const char *realm, + const char *workgroup, const char *ldap_server, const char *bind_path, const char *password) @@ -124,7 +130,12 @@ ADS_STRUCT *ads_init(const char *realm, ads = (ADS_STRUCT *)smb_xmalloc(sizeof(*ads)); ZERO_STRUCTP(ads); + if (!workgroup) { + workgroup = lp_workgroup(); + } + ads->realm = realm? strdup(realm) : NULL; + ads->workgroup = strdup(workgroup); ads->ldap_server = ldap_server? strdup(ldap_server) : NULL; ads->bind_path = bind_path? strdup(bind_path) : NULL; ads->ldap_port = LDAP_PORT; @@ -153,6 +164,12 @@ ADS_STRUCT *ads_init(const char *realm, return ads; } +/* a simpler ads_init() interface using all defaults */ +ADS_STRUCT *ads_init_simple(void) +{ + return ads_init(NULL, NULL, NULL, NULL, NULL); +} + /* free the memory used by the ADS structure initialized with 'ads_init(...)' */ diff --git a/source3/libads/ldap.c b/source3/libads/ldap.c index e2e351bd4b..3b787c6a8f 100644 --- a/source3/libads/ldap.c +++ b/source3/libads/ldap.c @@ -46,9 +46,33 @@ ADS_STATUS ads_connect(ADS_STRUCT *ads) ads->last_attempt = time(NULL); ads->ld = ldap_open(ads->ldap_server, ads->ldap_port); + + /* if that failed then try each of the BDC's in turn */ + if (!ads->ld) { + struct in_addr *ip_list; + int count; + + if (get_dc_list(False, ads->workgroup, &ip_list, &count)) { + int i; + for (i=0;ild = ldap_open(inet_ntoa(ip_list[i]), + ads->ldap_port); + if (ads->ld) break; + } + if (ads->ld) { + free(ads->ldap_server); + ads->ldap_server = strdup(inet_ntoa(ip_list[i])); + } + free(ip_list); + } + } + if (!ads->ld) { return ADS_ERROR_SYSTEM(errno); } + + DEBUG(3,("Connected to LDAP server %s\n", ads->ldap_server)); + status = ads_server_info(ads); if (!ADS_ERR_OK(status)) { DEBUG(1,("Failed to get ldap server info\n")); diff --git a/source3/nsswitch/winbindd_ads.c b/source3/nsswitch/winbindd_ads.c index af0933716b..6c00ddb95f 100644 --- a/source3/nsswitch/winbindd_ads.c +++ b/source3/nsswitch/winbindd_ads.c @@ -119,6 +119,8 @@ static ADS_STRUCT *ads_cached_connection(struct winbindd_domain *domain) if (resolve_name(domain->name, &server_ip, 0x1b)) { sname = inet_ntoa(server_ip); + } else if (resolve_name(domain->name, &server_ip, 0x1c)) { + sname = inet_ntoa(server_ip); } else { if (strcasecmp(domain->name, lp_workgroup()) != 0) { DEBUG(1,("can't find domain controller for %s\n", domain->name)); @@ -127,7 +129,7 @@ static ADS_STRUCT *ads_cached_connection(struct winbindd_domain *domain) sname = NULL; } - ads = ads_init(primary_realm, sname, NULL, NULL); + ads = ads_init(primary_realm, domain->name, NULL, NULL, NULL); if (!ads) { DEBUG(1,("ads_init for domain %s failed\n", domain->name)); return NULL; diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 18682e6c9f..c548ee6196 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -197,7 +197,7 @@ static int negprot_spnego(char *p) blob = spnego_gen_negTokenInit(guid, OIDs_plain, "NONE"); } else { ADS_STRUCT *ads; - ads = ads_init(NULL, NULL, NULL, NULL); + ads = ads_init_simple(); /* win2000 uses host$@REALM, which we will probably use eventually, but for now this works */ asprintf(&principal, "HOST/%s@%s", guid, ads->realm); diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 8b9d826067..66eb6a2d92 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -120,7 +120,7 @@ static int reply_spnego_kerberos(connection_struct *conn, return ERROR_NT(NT_STATUS_LOGON_FAILURE); } - ads = ads_init(NULL, NULL, NULL, NULL); + ads = ads_init_simple(); ret = ads_verify_ticket(ads, &ticket, &client, &auth_data); if (!NT_STATUS_IS_OK(ret)) { diff --git a/source3/utils/net_ads.c b/source3/utils/net_ads.c index 68fa89ea35..ea261187ce 100644 --- a/source3/utils/net_ads.c +++ b/source3/utils/net_ads.c @@ -56,7 +56,7 @@ static int net_ads_info(int argc, const char **argv) { ADS_STRUCT *ads; - ads = ads_init(NULL, opt_host, NULL, NULL); + ads = ads_init(NULL, NULL, opt_host, NULL, NULL); ads_connect(ads); if (!ads) { @@ -81,7 +81,7 @@ static ADS_STRUCT *ads_startup(void) BOOL need_password = False; BOOL second_time = False; - ads = ads_init(NULL, opt_host, NULL, NULL); + ads = ads_init(NULL, NULL, opt_host, NULL, NULL); if (!opt_user_name) { opt_user_name = "administrator"; @@ -650,7 +650,7 @@ static int net_ads_password(int argc, const char **argv) /* use the realm so we can eventually change passwords for users in realms other than default */ - if (!(ads = ads_init(realm, NULL, NULL, NULL))) return -1; + if (!(ads = ads_init(realm, NULL, NULL, NULL, NULL))) return -1; asprintf(&prompt, "Enter new password for %s:", argv[0]); @@ -681,8 +681,7 @@ static int net_ads_change_localhost_pass(int argc, const char **argv) char *hostname; ADS_STATUS ret; - - if (!(ads = ads_init(NULL, NULL, NULL, NULL))) return -1; + if (!(ads = ads_init_simple())) return -1; hostname = strdup(global_myname); strlower(hostname); -- cgit