diff options
| -rw-r--r-- | source3/Makefile.in | 6 | ||||
| -rw-r--r-- | source3/auth/auth_domain.c | 100 | ||||
| -rw-r--r-- | source3/include/smb.h | 8 | ||||
| -rw-r--r-- | source3/libsmb/namequery_dc.c | 104 | ||||
| -rw-r--r-- | source3/nsswitch/winbindd_cm.c | 50 | ||||
| -rw-r--r-- | source3/passdb/secrets.c | 30 | 
6 files changed, 156 insertions, 142 deletions
diff --git a/source3/Makefile.in b/source3/Makefile.in index 7fa27a24cd..5044609d13 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -196,7 +196,7 @@ LIBMSRPC_OBJ = rpc_client/cli_lsarpc.o rpc_client/cli_samr.o \  	       rpc_client/cli_wkssvc.o rpc_client/cli_dfs.o \  	       rpc_client/cli_reg.o rpc_client/cli_pipe.o \  	       rpc_client/cli_spoolss.o rpc_client/cli_spoolss_notify.o  \ -		rpc_client/cli_ds.o +	       rpc_client/cli_ds.o libsmb/namequery_dc.o  LIBMSRPC_SERVER_OBJ = libsmb/trust_passwd.o @@ -228,7 +228,7 @@ RPC_PARSE_OBJ = rpc_parse/parse_lsa.o rpc_parse/parse_net.o \  		$(REGOBJS_OBJ) -RPC_CLIENT_OBJ = rpc_client/cli_pipe.o +RPC_CLIENT_OBJ = rpc_client/cli_pipe.o   LOCKING_OBJ = locking/locking.o locking/brlock.o locking/posix.o @@ -469,7 +469,7 @@ LOCKTEST2_OBJ = torture/locktest2.o $(LOCKING_OBJ) $(LIBSMB_OBJ) $(PARAM_OBJ) \  SMBCACLS_OBJ = utils/smbcacls.o $(LOCKING_OBJ) $(LIBSMB_OBJ) $(PARAM_OBJ) \                   $(UBIQX_OBJ) $(LIB_OBJ) $(RPC_PARSE_OBJ) $(PASSDB_GET_SET_OBJ) \ -		 $(LIBMSRPC_OBJ)  +		 $(LIBMSRPC_OBJ) $(SECRETS_OBJ)  TALLOCTORT_OBJ = lib/talloctort.o  $(LIB_OBJ) $(PARAM_OBJ) $(UBIQX_OBJ) diff --git a/source3/auth/auth_domain.c b/source3/auth/auth_domain.c index f3fd2284d2..79cf5b156d 100644 --- a/source3/auth/auth_domain.c +++ b/source3/auth/auth_domain.c @@ -262,103 +262,23 @@ static NTSTATUS attempt_connect_to_dc(struct cli_state **cli,   We have been asked to dynamically determine the IP addresses of   the PDC and BDC's for DOMAIN, and query them in turn.  ************************************************************************/ -static NTSTATUS find_connect_pdc(struct cli_state **cli,  +static NTSTATUS find_connect_dc(struct cli_state **cli,   				 const char *domain,  				 const char *setup_creds_as,  				 uint16 sec_chan,  				 unsigned char *trust_passwd,   				 time_t last_change_time)  { -	struct in_addr *ip_list = NULL; -	int count = 0; -	int i; -	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 -	 * was less than an hour ago then we need to contact -	 * the PDC only, as we cannot be sure domain replication -	 * has yet taken place. Bug found by Gerald (way to go -	 * Gerald !). JRA. -	 */ - -	if (time_now - last_change_time < 3600) -		use_pdc_only = True; - -	if (use_pdc_only) { -		struct in_addr pdc_ip; - -		if (!get_pdc_ip(domain, &pdc_ip)) -			return NT_STATUS_NO_LOGON_SERVERS; - -		if ((ip_list = (struct in_addr *) -		     malloc(sizeof(struct in_addr))) == NULL)  -			return NT_STATUS_NO_MEMORY; - -		ip_list[0] = pdc_ip; -		count = 1; - -	} else { -		if (!get_dc_list(domain, &ip_list, &count, &list_ordered)) -			return NT_STATUS_NO_LOGON_SERVERS; -	} +	struct in_addr dc_ip; +	fstring srv_name; -	/* -	 * Firstly try and contact a PDC/BDC who has the same -	 * network address as any of our interfaces. -	 */ -	for(i = 0; i < count; i++) { -		if( !list_ordered && !is_local_net(ip_list[i]) ) -			continue; - -		if(NT_STATUS_IS_OK(nt_status =  -				   attempt_connect_to_dc(cli, domain,  -							 &ip_list[i], setup_creds_as,  -							 sec_chan, trust_passwd)))  -			break; -		 -		zero_ip(&ip_list[i]); /* Tried and failed. */ -	} - -	/* -	 * Secondly try and contact a random PDC/BDC. -	 */ -	if(!NT_STATUS_IS_OK(nt_status)) { -		i = (sys_random() % count); - -		if (!is_zero_ip(ip_list[i])) { -			if (!NT_STATUS_IS_OK(nt_status =  -					     attempt_connect_to_dc(cli, domain,  -								   &ip_list[i], setup_creds_as,  -								   sec_chan, trust_passwd))) -				zero_ip(&ip_list[i]); /* Tried and failed. */ -		} -	} - -	/* -	 * Finally go through the IP list in turn, ignoring any addresses -	 * we have already tried. -	 */ -	if(!NT_STATUS_IS_OK(nt_status)) { -		/* -		 * Try and connect to any of the other IP addresses in the PDC/BDC list. -		 * Note that from a WINS server the #1 IP address is the PDC. -		 */ -		for(i = 0; i < count; i++) { -			if (is_zero_ip(ip_list[i])) -				continue; - -			if (NT_STATUS_IS_OK(nt_status = attempt_connect_to_dc(cli, domain,  -						  &ip_list[i], setup_creds_as, sec_chan, trust_passwd))) -				break; -		} +	if ( !rpc_find_dc(lp_workgroup(), srv_name, &dc_ip) ) { +		DEBUG(0,("find_connect_dc: Failed to find an DCs for %s\n", lp_workgroup())); +		return NT_STATUS_NO_LOGON_SERVERS;  	} - -	SAFE_FREE(ip_list); -	return nt_status; +	 +	return attempt_connect_to_dc( cli, domain, &dc_ip, setup_creds_as,  +			sec_chan, trust_passwd );  }  /*********************************************************************** @@ -393,7 +313,7 @@ static NTSTATUS domain_client_validate(TALLOC_CTX *mem_ctx,  	while (!NT_STATUS_IS_OK(nt_status) &&  	       next_token(&server,remote_machine,LIST_SEP,sizeof(remote_machine))) {  		if(lp_security() != SEC_ADS && strequal(remote_machine, "*")) { -			nt_status = find_connect_pdc(&cli, domain, setup_creds_as, sec_chan, trust_passwd, last_change_time); +			nt_status = find_connect_dc(&cli, domain, setup_creds_as, sec_chan, trust_passwd, last_change_time);  		} else {  			int i;  			BOOL retry = True; diff --git a/source3/include/smb.h b/source3/include/smb.h index de0f10b3c5..b389020e23 100644 --- a/source3/include/smb.h +++ b/source3/include/smb.h @@ -221,6 +221,14 @@ typedef struct nttime_info  #define MAX_HOURS_LEN 32 +/*  + * window during which we must talk to the PDC to avoid + * sam sync delays; expressed in seconds (15 minutes is the  + * default period for SAM replication under Windows NT 4.0 + */ +#define SAM_SYNC_WINDOW		900 + +  #ifndef MAXSUBAUTHS  #define MAXSUBAUTHS 15 /* max sub authorities in a SID */  #endif diff --git a/source3/libsmb/namequery_dc.c b/source3/libsmb/namequery_dc.c new file mode 100644 index 0000000000..ffc64139e9 --- /dev/null +++ b/source3/libsmb/namequery_dc.c @@ -0,0 +1,104 @@ +/*  +   Unix SMB/CIFS implementation. + +   Winbind daemon connection manager + +   Copyright (C) Tim Potter 2001 +   Copyright (C) Andrew Bartlett 2002 +    +   This program is free software; you can redistribute it and/or modify +   it under the terms of the GNU General Public License as published by +   the Free Software Foundation; either version 2 of the License, or +   (at your option) any later version. +    +   This program is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the +   GNU General Public License for more details. +    +   You should have received a copy of the GNU General Public License +   along with this program; if not, write to the Free Software +   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + + +#include "includes.h" + + +/* +  find the DC for a domain using methods appropriate for a RPC domain +*/ +BOOL rpc_find_dc(const char *domain, fstring srv_name, struct in_addr *ip_out) +{ +	struct in_addr *ip_list = NULL, dc_ip, exclude_ip; +	int count, i; +	BOOL list_ordered; +	BOOL use_pdc_only; +	 +	zero_ip(&exclude_ip); + +	use_pdc_only = must_use_pdc(domain); +	 +	/* Lookup domain controller name */ +	    +	if ( use_pdc_only && get_pdc_ip(domain, &dc_ip) ) { +		DEBUG(10,("rpc_find_dc: Atempting to lookup PDC to avoid sam sync delays\n")); +		 +		if (name_status_find(domain, 0x1c, 0x20, dc_ip, srv_name)) { +			goto done; +		} +		/* Didn't get name, remember not to talk to this DC. */ +		exclude_ip = dc_ip; +	} + +	/* get a list of all domain controllers */ +	 +	if (!get_dc_list( domain, &ip_list, &count, &list_ordered) ) { +		DEBUG(3, ("Could not look up dc's for domain %s\n", domain)); +		return False; +	} + +	/* Remove the entry we've already failed with (should be the PDC). */ + +	if ( use_pdc_only ) { +		for (i = 0; i < count; i++) {	 +			if (ip_equal( exclude_ip, ip_list[i])) +				zero_ip(&ip_list[i]); +		} +	} + +	/* 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); +	} + +	for (i = 0; i < count; i++) { +		if (is_zero_ip(ip_list[i])) +			continue; + +		if (name_status_find(domain, 0x1c, 0x20, ip_list[i], srv_name)) { +			dc_ip = ip_list[i]; +			goto done; +		} +	} + + +	SAFE_FREE(ip_list); + +	return False; +done: +	/* We have the netbios name and IP address of a domain controller. +	   Ideally we should sent a SAMLOGON request to determine whether +	   the DC is alive and kicking.  If we can catch a dead DC before +	   performing a cli_connect() we can avoid a 30-second timeout. */ + +	DEBUG(3, ("rpc_find_dc: Returning DC %s (%s) for domain %s\n", srv_name, +		  inet_ntoa(dc_ip), domain)); + +	*ip_out = dc_ip; + +	SAFE_FREE(ip_list); + +	return True; +} + diff --git a/source3/nsswitch/winbindd_cm.c b/source3/nsswitch/winbindd_cm.c index 403bc38052..075da1e2b2 100644 --- a/source3/nsswitch/winbindd_cm.c +++ b/source3/nsswitch/winbindd_cm.c @@ -135,54 +135,6 @@ static BOOL cm_ads_find_dc(const char *domain, struct in_addr *dc_ip, fstring sr  	return True;  } -/* -  find the DC for a domain using methods appropriate for a RPC domain -*/ -static BOOL cm_rpc_find_dc(const char *domain, struct in_addr *dc_ip, fstring srv_name) -{ -	struct in_addr *ip_list = NULL; -	int count, i; -	BOOL list_ordered; - -	if (!get_dc_list(domain, &ip_list, &count, &list_ordered)) { -		struct in_addr pdc_ip; -		 -		if (!get_pdc_ip(domain, &pdc_ip)) { -			DEBUG(3, ("Could not look up any DCs for domain %s\n",  -				  domain)); -			return False; -		} - -		ip_list = (struct in_addr *)malloc(sizeof(struct in_addr)); - -		if (!ip_list) -			return False; - -		ip_list[0] = pdc_ip; -		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); -	} - -	for (i = 0; i < count; i++) { -		if (is_zero_ip(ip_list[i])) -			continue; - -		if (name_status_find(domain, 0x1c, 0x20, ip_list[i], srv_name)) { -			*dc_ip = ip_list[i]; -			SAFE_FREE(ip_list); -			return True; -		} -	} - - -	SAFE_FREE(ip_list); - -	return False; -}  static BOOL cm_get_dc_name(const char *domain, fstring srv_name, struct in_addr *ip_out) @@ -247,7 +199,7 @@ static BOOL cm_get_dc_name(const char *domain, fstring srv_name, struct in_addr  	}  	if (!ret) {  		/* fall back on rpc methods if the ADS methods fail */ -		ret = cm_rpc_find_dc(domain, &dc_ip, srv_name); +		ret = rpc_find_dc(domain, srv_name, &dc_ip);  	}  	if (!ret) { diff --git a/source3/passdb/secrets.c b/source3/passdb/secrets.c index 29afaddea3..b93ea74d8b 100644 --- a/source3/passdb/secrets.c +++ b/source3/passdb/secrets.c @@ -610,3 +610,33 @@ void secrets_named_mutex_release(const char *name)  	tdb_unlock_bystring(tdb, name);  	DEBUG(10,("secrets_named_mutex: released mutex for %s\n", name ));  } + +/********************************************************* + Check to see if we must talk to the PDC to avoid sam  + sync delays + ********************************************************/ +  +BOOL must_use_pdc( const char *domain ) +{ +	time_t	now = time(NULL); +	time_t  last_change_time; +	unsigned char	passwd[16];    +	 +	if ( !secrets_fetch_trust_account_password(domain, passwd, &last_change_time) ) +		return False; +		 +	/* +	 * If the time the machine password has changed +	 * was less than about 15 minutes then we need to contact +	 * the PDC only, as we cannot be sure domain replication +	 * has yet taken place. Bug found by Gerald (way to go +	 * Gerald !). JRA. +	 */ +	  +	if ( now - last_change_time < SAM_SYNC_WINDOW ) +		return True; +		 +	return False; + +} +  | 
