fixed the fallback to a BDC for ADS connections
authorAndrew Tridgell <tridge@samba.org>
Thu, 18 Apr 2002 06:56:44 +0000 (06:56 +0000)
committerAndrew Tridgell <tridge@samba.org>
Thu, 18 Apr 2002 06:56:44 +0000 (06:56 +0000)
(This used to be commit 3e58a1ee83ea0b4347ce24e566445cc6cb67bb3a)

source3/include/ads.h
source3/libads/ads_struct.c
source3/libads/ldap.c
source3/nsswitch/winbindd_ads.c
source3/smbd/negprot.c
source3/smbd/sesssetup.c
source3/utils/net_ads.c

index 8658e72f6acb2fe29131b67402e10cefef688f0c..b3e18f18b8ddd29d1a63dbc2f1452df54ae49192 100644 (file)
@@ -7,6 +7,7 @@
 typedef struct {
        void *ld;
        char *realm;
+       char *workgroup;
        char *ldap_server;
        char *ldap_server_name;
        char *kdc_server;
index 489f301ae2e26caafcb02a2a535785eda8349f0c..816b61609734046dd6d96654bcd49918eae5242b 100644 (file)
@@ -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(...)'
 */
index e2e351bd4b3b79283ae3caffb40672472195f930..3b787c6a8fb18b91b85cde477792c5dc19fb34c6 100644 (file)
@@ -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;i<count;i++) {
+                               ads->ld = 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"));
index af0933716b8296e24e7f0dc959a170b221ae128e..6c00ddb95fa4930c0512605be602befa2f637d04 100644 (file)
@@ -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;
index 18682e6c9ffd1a51f1a1549e537bcc8350ccd347..c548ee61967693fddfa024586cd24041cc440ea2 100644 (file)
@@ -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);
index 8b9d826067f3fd57b062bf4015991a40f810a476..66eb6a2d92b9e89e954fcda9117fb341589f8a06 100644 (file)
@@ -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)) {
index 68fa89ea35d6569dac4564b7062bf3eca1b5601d..ea261187ce42ba794e781eb193f07c3055e8cdf1 100644 (file)
@@ -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);