diff options
| -rw-r--r-- | source3/auth/auth_domain.c | 65 | ||||
| -rw-r--r-- | source3/include/proto.h | 3 | ||||
| -rw-r--r-- | source3/lib/dummysmbd.c | 15 | ||||
| -rw-r--r-- | source3/printing/notify.c | 26 | ||||
| -rw-r--r-- | source3/smbd/process.c | 193 | ||||
| -rw-r--r-- | source3/smbd/reply.c | 3 | ||||
| -rw-r--r-- | source3/smbd/server.c | 31 | 
7 files changed, 148 insertions, 188 deletions
diff --git a/source3/auth/auth_domain.c b/source3/auth/auth_domain.c index c25e62ab80..f11dbe60ee 100644 --- a/source3/auth/auth_domain.c +++ b/source3/auth/auth_domain.c @@ -26,6 +26,71 @@  extern bool global_machine_password_needs_changing;  static struct named_mutex *mutex; +/* + * Change machine password (called from main loop + * idle timeout. Must be done as root. + */ + +void attempt_machine_password_change(void) +{ +	unsigned char trust_passwd_hash[16]; +	time_t lct; +	void *lock; + +	if (!global_machine_password_needs_changing) { +		return; +	} + +	if (lp_security() != SEC_DOMAIN) { +		return; +	} + +	/* +	 * We're in domain level security, and the code that +	 * read the machine password flagged that the machine +	 * password needs changing. +	 */ + +	/* +	 * First, open the machine password file with an exclusive lock. +	 */ + +	lock = secrets_get_trust_account_lock(NULL, lp_workgroup()); + +	if (lock == NULL) { +		DEBUG(0,("attempt_machine_password_change: unable to lock " +			"the machine account password for machine %s in " +			"domain %s.\n", +			global_myname(), lp_workgroup() )); +		return; +	} + +	if(!secrets_fetch_trust_account_password(lp_workgroup(), +			trust_passwd_hash, &lct, NULL)) { +		DEBUG(0,("attempt_machine_password_change: unable to read the " +			"machine account password for %s in domain %s.\n", +			global_myname(), lp_workgroup())); +		TALLOC_FREE(lock); +		return; +	} + +	/* +	 * Make sure someone else hasn't already done this. +	 */ + +	if(time(NULL) < lct + lp_machine_password_timeout()) { +		global_machine_password_needs_changing = false; +		TALLOC_FREE(lock); +		return; +	} + +	/* always just contact the PDC here */ + +	change_trust_account_password( lp_workgroup(), NULL); +	global_machine_password_needs_changing = false; +	TALLOC_FREE(lock); +} +  /**   * Connect to a remote server for (inter)domain security authenticaion.   * diff --git a/source3/include/proto.h b/source3/include/proto.h index 2ccf3b15f7..6799106217 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -43,7 +43,8 @@ bool password_ok(const char *smb_name, DATA_BLOB password_blob);  /* The following definitions come from auth/auth_domain.c  */ -NTSTATUS auth_domain_init(void) ; +void attempt_machine_password_change(void); +NTSTATUS auth_domain_init(void);  /* The following definitions come from auth/auth_ntlmssp.c  */ diff --git a/source3/lib/dummysmbd.c b/source3/lib/dummysmbd.c index dbe886e3d1..5c624bdebf 100644 --- a/source3/lib/dummysmbd.c +++ b/source3/lib/dummysmbd.c @@ -51,3 +51,18 @@ NTSTATUS can_delete_directory(struct connection_struct *conn,  {  	return NT_STATUS_OK;  } + +bool change_to_root_user(void) +{ +	return false; +} + +struct event_context *smbd_event_context(void) +{ +	return NULL; +} + +struct messaging_context *smbd_messaging_context(void) +{ +	return NULL; +} diff --git a/source3/printing/notify.c b/source3/printing/notify.c index 23df17c389..f6599c413d 100644 --- a/source3/printing/notify.c +++ b/source3/printing/notify.c @@ -34,6 +34,7 @@ static struct notify_queue {  	size_t buflen;  } *notify_queue_head = NULL; +static struct timed_event *notify_event;  static bool create_send_ctx(void)  { @@ -214,6 +215,22 @@ void print_notify_send_messages(struct messaging_context *msg_ctx,  	num_messages = 0;  } +/******************************************************************* + Event handler to send the messages. +*******************************************************************/ + +static void print_notify_event_send_messages(struct event_context *event_ctx, +					struct timed_event *te, +					const struct timeval *now, +					void *private_data) +{ +	/* Remove this timed event handler. */ +	TALLOC_FREE(notify_event); + +	change_to_root_user(); +	print_notify_send_messages(smbd_messaging_context(), 0); +} +  /**********************************************************************   deep copy a SPOOLSS_NOTIFY_MSG structure using a TALLOC_CTX   *********************************************************************/ @@ -304,6 +321,15 @@ to notify_queue_head\n", msg->type, msg->field, msg->printer));  	DLIST_ADD_END(notify_queue_head, pnqueue, struct notify_queue *);  	num_messages++; + +	if (smbd_event_context()) { +		/* Add an event for 1 second's time to send this queue. */ +		notify_event = event_add_timed(smbd_event_context(), NULL, +					timeval_current_ofs(1,0), +					"print_notify", +					print_notify_event_send_messages, NULL); +	} +  }  static void send_notify_field_values(const char *sharename, uint32 type, diff --git a/source3/smbd/process.c b/source3/smbd/process.c index b2d19e11e3..32629fd392 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -706,7 +706,7 @@ The timeout is in milliseconds  ****************************************************************************/  static NTSTATUS receive_message_or_smb(TALLOC_CTX *mem_ctx, char **buffer, -				       size_t *buffer_len, int timeout, +				       size_t *buffer_len,  				       size_t *p_unread, bool *p_encrypted)  {  	fd_set r_fds, w_fds; @@ -720,13 +720,8 @@ static NTSTATUS receive_message_or_smb(TALLOC_CTX *mem_ctx, char **buffer,   again: -	if (timeout >= 0) { -		to.tv_sec = timeout / 1000; -		to.tv_usec = (timeout % 1000) * 1000; -	} else { -		to.tv_sec = SMBD_SELECT_TIMEOUT; -		to.tv_usec = 0; -	} +	to.tv_sec = SMBD_SELECT_TIMEOUT; +	to.tv_usec = 0;  	/*  	 * Note that this call must be before processing any SMB @@ -869,7 +864,7 @@ static NTSTATUS receive_message_or_smb(TALLOC_CTX *mem_ctx, char **buffer,  	/* Did we timeout ? */  	if (selrtn == 0) { -		return NT_STATUS_IO_TIMEOUT; +		goto again;  	}  	/* @@ -1837,23 +1832,6 @@ void chain_reply(struct smb_request *req)  }  /**************************************************************************** - Setup the needed select timeout in milliseconds. -****************************************************************************/ - -static int setup_select_timeout(void) -{ -	int select_timeout; - -	select_timeout = SMBD_SELECT_TIMEOUT*1000; - -	if (print_notify_messages_pending()) { -		select_timeout = MIN(select_timeout, 1000); -	} - -	return select_timeout; -} - -/****************************************************************************   Check if services need reloading.  ****************************************************************************/ @@ -1907,113 +1885,18 @@ void check_reload(time_t t)  }  /**************************************************************************** - Process any timeout housekeeping. Return False if the caller should exit. -****************************************************************************/ - -static void timeout_processing(int *select_timeout, -			       time_t *last_timeout_processing_time) -{ -	time_t t; - -	*last_timeout_processing_time = t = time(NULL); - -	/* become root again if waiting */ -	change_to_root_user(); - -	/* check if we need to reload services */ -	check_reload(t); - -	if(global_machine_password_needs_changing &&  -			/* for ADS we need to do a regular ADS password change, not a domain -					password change */ -			lp_security() == SEC_DOMAIN) { - -		unsigned char trust_passwd_hash[16]; -		time_t lct; -		void *lock; - -		/* -		 * We're in domain level security, and the code that -		 * read the machine password flagged that the machine -		 * password needs changing. -		 */ - -		/* -		 * First, open the machine password file with an exclusive lock. -		 */ - -		lock = secrets_get_trust_account_lock(NULL, lp_workgroup()); - -		if (lock == NULL) { -			DEBUG(0,("process: unable to lock the machine account password for \ -machine %s in domain %s.\n", global_myname(), lp_workgroup() )); -			return; -		} - -		if(!secrets_fetch_trust_account_password(lp_workgroup(), trust_passwd_hash, &lct, NULL)) { -			DEBUG(0,("process: unable to read the machine account password for \ -machine %s in domain %s.\n", global_myname(), lp_workgroup())); -			TALLOC_FREE(lock); -			return; -		} - -		/* -		 * Make sure someone else hasn't already done this. -		 */ - -		if(t < lct + lp_machine_password_timeout()) { -			global_machine_password_needs_changing = False; -			TALLOC_FREE(lock); -			return; -		} - -		/* always just contact the PDC here */ -     -		change_trust_account_password( lp_workgroup(), NULL); -		global_machine_password_needs_changing = False; -		TALLOC_FREE(lock); -	} - -	/* update printer queue caches if necessary */ -   -	update_monitored_printq_cache(); -   -	/* -	 * Now we are root, check if the log files need pruning. -	 * Force a log file check. -	 */ -	force_check_log_size(); -	check_log_size(); - -	/* Send any queued printer notify message to interested smbd's. */ - -	print_notify_send_messages(smbd_messaging_context(), 0); - -	/* -	 * Modify the select timeout depending upon -	 * what we have remaining in our queues. -	 */ - -	*select_timeout = setup_select_timeout(); - -	return; -} - -/****************************************************************************   Process commands from the client  ****************************************************************************/  void smbd_process(void)  { -	time_t last_timeout_processing_time = time(NULL);  	unsigned int num_smbs = 0;  	size_t unread_bytes = 0;  	max_recv = MIN(lp_maxxmit(),BUFFER_SIZE);  	while (True) { -		int select_timeout = setup_select_timeout(); -		int num_echos; +		NTSTATUS status;  		char *inbuf = NULL;  		size_t inbuf_len = 0;  		bool encrypted = false; @@ -2021,82 +1904,24 @@ void smbd_process(void)  		errno = 0; -		/* Did someone ask for immediate checks on things like blocking locks ? */ -		if (select_timeout == 0) { -			timeout_processing(&select_timeout, -					   &last_timeout_processing_time); -			num_smbs = 0; /* Reset smb counter. */ -		} -  		run_events(smbd_event_context(), 0, NULL, NULL); -		while (True) { -			NTSTATUS status; - -			status = receive_message_or_smb( -				talloc_tos(), &inbuf, &inbuf_len, -				select_timeout,	&unread_bytes, &encrypted); - -			if (NT_STATUS_IS_OK(status)) { -				break; -			} - -			if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) { -				timeout_processing( -					&select_timeout, -					&last_timeout_processing_time); -				continue; -			} +		status = receive_message_or_smb( +			talloc_tos(), &inbuf, &inbuf_len, +			&unread_bytes, &encrypted); +		if (!NT_STATUS_IS_OK(status)) {  			DEBUG(3, ("receive_message_or_smb failed: %s, "  				  "exiting\n", nt_errstr(status)));  			return; - -			num_smbs = 0; /* Reset smb counter. */  		} - -		/* -		 * Ensure we do timeout processing if the SMB we just got was -		 * only an echo request. This allows us to set the select -		 * timeout in 'receive_message_or_smb()' to any value we like -		 * without worrying that the client will send echo requests -		 * faster than the select timeout, thus starving out the -		 * essential processing (change notify, blocking locks) that -		 * the timeout code does. JRA. -		 */ -		num_echos = smb_echo_count; -  		process_smb(inbuf, inbuf_len, unread_bytes, encrypted);  		TALLOC_FREE(inbuf); -		if (smb_echo_count != num_echos) { -			timeout_processing(&select_timeout, -					   &last_timeout_processing_time); -			num_smbs = 0; /* Reset smb counter. */ -		} -  		num_smbs++; -		/* -		 * If we are getting smb requests in a constant stream -		 * with no echos, make sure we attempt timeout processing -		 * every select_timeout milliseconds - but only check for this -		 * every 200 smb requests. -		 */ -		 -		if ((num_smbs % 200) == 0) { -			time_t new_check_time = time(NULL); -			if(new_check_time - last_timeout_processing_time >= (select_timeout/1000)) { -				timeout_processing( -					&select_timeout, -					&last_timeout_processing_time); -				num_smbs = 0; /* Reset smb counter. */ -				last_timeout_processing_time = new_check_time; /* Reset time. */ -			} -		} -  		/* The timeout_processing function isn't run nearly  		   often enough to implement 'max log size' without  		   overrunning the size of the file by many megabytes. diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 8bfa28faea..0226d314f7 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -29,7 +29,6 @@  /* look in server.c for some explanation of these variables */  extern enum protocol_types Protocol;  extern int max_recv; -unsigned int smb_echo_count = 0;  extern uint32 global_client_caps;  extern bool global_encrypted_passwords_negotiated; @@ -4611,8 +4610,6 @@ void reply_echo(struct smb_request *req)  	TALLOC_FREE(req->outbuf); -	smb_echo_count++; -  	END_PROFILE(SMBecho);  	return;  } diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 53116f3d98..69a483e4fc 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -1067,6 +1067,30 @@ static bool deadtime_fn(const struct timeval *now, void *private_data)  	return True;  } +/* + * Do the recurring log file and smb.conf reload checks. + */ + +static bool housekeeping_fn(const struct timeval *now, void *private_data) +{ +	change_to_root_user(); + +	/* update printer queue caches if necessary */ +	update_monitored_printq_cache(); + +	/* check if we need to reload services */ +	check_reload(time(NULL)); + +	/* Change machine password if neccessary. */ +	attempt_machine_password_change(); + +        /* +	 * Force a log file check. +	 */ +        force_check_log_size(); +        check_log_size(); +	return true; +}  /****************************************************************************   main program. @@ -1426,6 +1450,13 @@ extern void build_options(bool screen);  		exit(1);  	} +	if (!(event_add_idle(smbd_event_context(), NULL, +			     timeval_set(SMBD_SELECT_TIMEOUT, 0), +			     "housekeeping", housekeeping_fn, NULL))) { +		DEBUG(0, ("Could not add housekeeping event\n")); +		exit(1); +	} +  #ifdef CLUSTER_SUPPORT  	if (lp_clustering()) {  | 
