[merge from APP_HEAD]
authorGerald Carter <jerry@samba.org>
Sat, 23 Nov 2002 14:52:34 +0000 (14:52 +0000)
committerGerald Carter <jerry@samba.org>
Sat, 23 Nov 2002 14:52:34 +0000 (14:52 +0000)
90% fix for CR 1076.  The password server parameter will no take things
like

        password server = DC1 *

which means to contact DC1 first and the go to auto lookup if it
fails.

jerry

source/auth/auth_domain.c
source/libads/ldap.c
source/libsmb/namequery.c
source/nsswitch/winbindd_cm.c
source/utils/net_lookup.c

index 2a6614e28e686a07ad3b0590fbc6f50d4a4b72c0..eebe647ec022f2b742289f91b481d5ec050258d4 100644 (file)
@@ -275,6 +275,7 @@ static NTSTATUS find_connect_pdc(struct cli_state **cli,
        NTSTATUS nt_status = NT_STATUS_NO_LOGON_SERVERS;
        time_t time_now = time(NULL);
        BOOL use_pdc_only = False;
+       BOOL list_ordered;
 
        /*
         * If the time the machine password has changed
@@ -301,7 +302,7 @@ static NTSTATUS find_connect_pdc(struct cli_state **cli,
                count = 1;
 
        } else {
-               if (!get_dc_list(domain, &ip_list, &count))
+               if (!get_dc_list(domain, &ip_list, &count, &list_ordered))
                        return NT_STATUS_NO_LOGON_SERVERS;
        }
 
@@ -310,7 +311,7 @@ static NTSTATUS find_connect_pdc(struct cli_state **cli,
         * network address as any of our interfaces.
         */
        for(i = 0; i < count; i++) {
-               if(!is_local_net(ip_list[i]))
+               if( !list_ordered && !is_local_net(ip_list[i]) )
                        continue;
 
                if(NT_STATUS_IS_OK(nt_status = 
index 60427323b0b779b566064b57b349dc13aa819b36..fcb96dd174e9849673675e87667cd2c4e8411484 100644 (file)
@@ -186,6 +186,7 @@ static BOOL ads_try_netbios(ADS_STRUCT *ads)
        int count;
        int i;
        const char *workgroup = ads->server.workgroup;
+       BOOL list_ordered;
 
        if (!workgroup) {
                workgroup = lp_workgroup();
@@ -202,7 +203,7 @@ static BOOL ads_try_netbios(ADS_STRUCT *ads)
        }
 
        /* now any DC, including backups */
-       if (get_dc_list(workgroup, &ip_list, &count)) { 
+       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])));
index 5c3d942b906674254575ac05f688e34fb95da367..6190c872ee20930598bf4b005761a3493e71b7ad 100644 (file)
@@ -1235,19 +1235,24 @@ BOOL get_pdc_ip(const char *domain, struct in_addr *ip)
  a domain.
 *********************************************************/
 
-BOOL get_dc_list(const char *domain, struct in_addr **ip_list, int *count)
+BOOL get_dc_list(const char *domain, struct in_addr **ip_list, int *count, int *ordered)
 {
-       /*
-        * If it's our domain then
-        * use the 'password server' parameter.
-        */
+
+       *ordered = False;
+               
+       /* If it's our domain then use the 'password server' parameter. */
 
        if (strequal(domain, lp_workgroup())) {
-               const char *p;
-               char *pserver = lp_passwordserver();
+               char *p;
+               char *pserver = lp_passwordserver(); /* UNIX charset. */
                fstring name;
-               int num_adresses = 0;
+               int num_addresses = 0;
+               int  local_count, i, j;
                struct in_addr *return_iplist = NULL;
+               struct in_addr *auto_ip_list = NULL;
+               BOOL done_auto_lookup = False;
+               int auto_count = 0;
+               
 
                if (!*pserver)
                        return internal_resolve_name(
@@ -1255,19 +1260,31 @@ BOOL get_dc_list(const char *domain, struct in_addr **ip_list, int *count)
 
                p = pserver;
 
+               /*
+                * if '*' appears in the "password server" list then add
+                * an auto lookup to the list of manually configured
+                * DC's.  If any DC is listed by name, then the list should be 
+                * considered to be ordered 
+                */
+                
                while (next_token(&p,name,LIST_SEP,sizeof(name))) {
-                       if (strequal(name, "*"))
-                               return internal_resolve_name(
-                                       domain, 0x1C, ip_list, count);
-                       num_adresses++;
+                       if (strequal(name, "*")) {
+                               if ( internal_resolve_name(domain, 0x1C, &auto_ip_list, &auto_count) )
+                                       num_addresses += auto_count;
+                               done_auto_lookup = True;
+                               DEBUG(8,("Adding %d DC's from auto lookup\n", auto_count));
+                       }
+                       else 
+                               num_addresses++;
                }
 
-               if (num_adresses == 0)
-                       return internal_resolve_name(
-                               domain, 0x1C, ip_list, count);
+               /* if we have no addresses and haven't done the auto lookup, then
+                  just return the list of DC's */
+                  
+               if ( (num_addresses == 0) && !done_auto_lookup )
+                       return internal_resolve_name(domain, 0x1C, ip_list, count);
 
-               return_iplist = (struct in_addr *)malloc(
-                       num_adresses * sizeof(struct in_addr));
+               return_iplist = (struct in_addr *)malloc(num_addresses * sizeof(struct in_addr));
 
                if (return_iplist == NULL) {
                        DEBUG(3,("get_dc_list: malloc fail !\n"));
@@ -1275,19 +1292,84 @@ BOOL get_dc_list(const char *domain, struct in_addr **ip_list, int *count)
                }
 
                p = pserver;
-               *count = 0;
+               local_count = 0;
 
-               while (next_token(&p,name,LIST_SEP,sizeof(name))) {
+               /* fill in the return list now with real IP's */
+                               
+               while ( (local_count<num_addresses) && next_token(&p,name,LIST_SEP,sizeof(name)) ) 
+               {
                        struct in_addr name_ip;
-                       if (resolve_name( name, &name_ip, 0x20) == False)
+                       
+                       /* copy any addersses from the auto lookup */
+                       
+                       if ( strequal(name, "*") ) {
+                               for ( j=0; j<auto_count; j++ ) 
+                                       return_iplist[local_count++] = auto_ip_list[j];
                                continue;
-                       return_iplist[(*count)++] = name_ip;
+                       }
+                       
+                       /* explicit lookup */
+                                       
+                       if ( resolve_name( name, &name_ip, 0x20) ) {
+                               return_iplist[local_count++] = name_ip;
+                               *ordered = True;
+                       }
+                               
                }
-
+                               
+               /* need to remove duplicates in the list if we have 
+                  any explicit password servers */
+                  
+               if ( *ordered )
+               {               
+                       int hole_index = -1;
+
+                       /* one loop to remove duplicates */
+                       for ( i=0; i<local_count; i++ )
+                       {
+                               if ( is_zero_ip(return_iplist[i]) )
+                                       continue;
+                                       
+                               for ( j=i+1; j<local_count; j++ ) {
+                                       if ( ip_equal( return_iplist[i], return_iplist[j]) )
+                                               zero_ip(&return_iplist[j]);
+                               }
+                       }
+                       
+                       /* one loop to clean up any holes we left */
+                       /* first ip can never be a zero_ip() */
+                       i = 0;
+                       while ( i<local_count )
+                       {
+                               if ( !is_zero_ip(return_iplist[i]) ) {
+                                       i++;
+                                       continue;
+                               }
+                               
+                               hole_index = i;
+                               i++;
+                               
+                               while ( i<local_count ) {
+                                       if ( !is_zero_ip(return_iplist[i]) )
+                                               return_iplist[hole_index++] = return_iplist[i];
+                                       i++;
+                               }
+                               
+                               /* we should exit the loop implicitly here, but ... */
+                               break;
+                       }
+                       
+                       local_count = hole_index;
+               }
+               
                *ip_list = return_iplist;
+               *count = local_count;
+               
+               DEBUG(8,("get_dc_list: return %d ip addresses\n", *count));
 
                return (*count != 0);
        }
        
        return internal_resolve_name(domain, 0x1C, ip_list, count);
 }
+
index d44219d1725866bb23b3bd740a07b9d1aba07c14..403bc38052e51733894e7986a3e798f3e3e086b4 100644 (file)
@@ -142,8 +142,9 @@ static BOOL cm_rpc_find_dc(const char *domain, struct in_addr *dc_ip, fstring sr
 {
        struct in_addr *ip_list = NULL;
        int count, i;
+       BOOL list_ordered;
 
-       if (!get_dc_list(domain, &ip_list, &count)) {
+       if (!get_dc_list(domain, &ip_list, &count, &list_ordered)) {
                struct in_addr pdc_ip;
                
                if (!get_pdc_ip(domain, &pdc_ip)) {
@@ -161,8 +162,8 @@ static BOOL cm_rpc_find_dc(const char *domain, struct in_addr *dc_ip, fstring sr
                count = 1;
        }
 
-       /* Pick a nice close server */
-       if (count > 1) {
+       /* Pick a nice close server, but only if the list was not ordered */
+       if (!list_ordered && (count > 1) ) {
                qsort(ip_list, count, sizeof(struct in_addr), QSORT_CAST ip_compare);
        }
 
index 32921de620f695915846c6ca81b3aabb33646c2e..271094480c312c30c488e86c0a39cee817d147c6 100644 (file)
@@ -128,6 +128,7 @@ static int net_lookup_dc(int argc, const char **argv)
        char *pdc_str = NULL;
        const char *domain=opt_target_workgroup;
        int count, i;
+       BOOL list_ordered;
 
        if (argc > 0)
                domain=argv[0];
@@ -139,7 +140,7 @@ static int net_lookup_dc(int argc, const char **argv)
        asprintf(&pdc_str, "%s", inet_ntoa(addr));
        d_printf("%s\n", pdc_str);
 
-       if (!get_dc_list(domain, &ip_list, &count)) {
+       if (!get_dc_list(domain, &ip_list, &count, &list_ordered)) {
                SAFE_FREE(pdc_str);
                return 0;
        }