diff options
| -rw-r--r-- | docs-xml/smbdotconf/printing/cupsconnectiontimeout.xml | 20 | ||||
| -rw-r--r-- | source3/auth/auth_domain.c | 65 | ||||
| -rw-r--r-- | source3/client/client.c | 16 | ||||
| -rw-r--r-- | source3/include/proto.h | 4 | ||||
| -rw-r--r-- | source3/lib/dummysmbd.c | 15 | ||||
| -rw-r--r-- | source3/lib/readline.c | 13 | ||||
| -rw-r--r-- | source3/libaddns/dnsmarshall.c | 1 | ||||
| -rw-r--r-- | source3/libads/ldap.c | 1 | ||||
| -rw-r--r-- | source3/libads/util.c | 2 | ||||
| -rw-r--r-- | source3/libnet/libnet_proto.h | 2 | ||||
| -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 | 
14 files changed, 200 insertions, 192 deletions
diff --git a/docs-xml/smbdotconf/printing/cupsconnectiontimeout.xml b/docs-xml/smbdotconf/printing/cupsconnectiontimeout.xml new file mode 100644 index 0000000000..1c7df15c3c --- /dev/null +++ b/docs-xml/smbdotconf/printing/cupsconnectiontimeout.xml @@ -0,0 +1,20 @@ +<samba:parameter name="cups connection timeout" +                 context="G" +		 type="integer" +		 print="1" +                 xmlns:samba="http://www.samba.org/samba/DTD/samba-doc"> +<description> +    <para> +    This parameter is only applicable if <smbconfoption name="printing"/> is set to <constant>cups</constant>. +    </para> + +   <para> +   If set, this option specifies the number of seconds that smbd will wait +   whilst trying to contact to the CUPS server. The connection will fail +   if it takes longer than this number of seconds. +   </para> +</description> + +<value type="default">30</value> +<value type="example">60</value> +</samba:parameter> 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/client/client.c b/source3/client/client.c index 7af7d30108..eb9f31bdf2 100644 --- a/source3/client/client.c +++ b/source3/client/client.c @@ -4345,6 +4345,8 @@ cleanup:  	}  } +static bool finished; +  /****************************************************************************   Make sure we swallow keepalives during idle time.  ****************************************************************************/ @@ -4391,6 +4393,8 @@ static void readline_callback(void)  			DEBUG(0, ("Read from server failed, maybe it closed "  				  "the connection\n")); +			finished = true; +			smb_readline_done();  			if (NT_STATUS_EQUAL(status, NT_STATUS_END_OF_FILE)) {  				set_smb_read_error(&cli->smb_rw_error,  						   SMB_READ_EOF); @@ -4417,9 +4421,17 @@ static void readline_callback(void)  	/* Ping the server to keep the connection alive using SMBecho. */  	{ +		NTSTATUS status;  		unsigned char garbage[16];  		memset(garbage, 0xf0, sizeof(garbage)); -		cli_echo(cli, 1, data_blob_const(garbage, sizeof(garbage))); +		status = cli_echo(cli, 1, data_blob_const(garbage, sizeof(garbage))); + +		if (!NT_STATUS_IS_OK(status)) { +			DEBUG(0, ("SMBecho failed. Maybe server has closed " +				"the connection\n")); +			finished = true; +			smb_readline_done(); +		}  	}  } @@ -4431,7 +4443,7 @@ static int process_stdin(void)  {  	int rc = 0; -	while (1) { +	while (!finished) {  		TALLOC_CTX *frame = talloc_stackframe();  		char *tok = NULL;  		char *the_prompt = NULL; diff --git a/source3/include/proto.h b/source3/include/proto.h index 2ccf3b15f7..7cdcba19ab 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  */ @@ -707,6 +708,7 @@ bool privilege_set_to_se_priv( SE_PRIV *mask, struct lsa_PrivilegeSet *privset )  /* The following definitions come from lib/readline.c  */ +void smb_readline_done(void);  char *smb_readline(const char *prompt, void (*callback)(void),  		   char **(completion_fn)(const char *text, int start, int end));  const char *smb_readline_get_line_buffer(void); 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/lib/readline.c b/source3/lib/readline.c index 254f55c86a..fd57799b57 100644 --- a/source3/lib/readline.c +++ b/source3/lib/readline.c @@ -45,6 +45,16 @@  #  define RL_COMPLETION_CAST  #endif /* HAVE_NEW_LIBREADLINE */ +static bool smb_rl_done; + +void smb_readline_done(void) +{ +	smb_rl_done = true; +#if HAVE_LIBREADLINE +	rl_done = 1; +#endif +} +  /****************************************************************************   Display the prompt and wait for input. Call callback() regularly  ****************************************************************************/ @@ -69,7 +79,7 @@ static char *smb_readline_replacement(const char *prompt, void (*callback)(void)  		return NULL;  	} -	while (1) { +	while (!smb_rl_done) {  		timeout.tv_sec = 5;  		timeout.tv_usec = 0; @@ -87,6 +97,7 @@ static char *smb_readline_replacement(const char *prompt, void (*callback)(void)  			callback();  		}  	} +	return NULL;  }  /**************************************************************************** diff --git a/source3/libaddns/dnsmarshall.c b/source3/libaddns/dnsmarshall.c index 8c3389eb9b..5530290c57 100644 --- a/source3/libaddns/dnsmarshall.c +++ b/source3/libaddns/dnsmarshall.c @@ -252,6 +252,7 @@ void dns_unmarshall_domain_name(TALLOC_CTX *mem_ctx,  	if (!(name = talloc(mem_ctx, struct dns_domain_name))) {  		buf->error = ERROR_DNS_NO_MEMORY; +		return;  	}  	dns_unmarshall_label(name, 0, buf, &name->pLabelList); diff --git a/source3/libads/ldap.c b/source3/libads/ldap.c index bfcfcf30b9..40f052281d 100644 --- a/source3/libads/ldap.c +++ b/source3/libads/ldap.c @@ -2828,6 +2828,7 @@ ADS_STATUS ads_domain_func_level(ADS_STRUCT *ads, uint32 *val)  		if ( (ads_s = ads_init( ads->server.realm, ads->server.workgroup,   			ads->server.ldap_server )) == NULL )  		{ +			status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);  			goto done;  		}  		ads_s->auth.flags = ADS_AUTH_ANON_BIND; diff --git a/source3/libads/util.c b/source3/libads/util.c index 72f5dee80c..d23c36f326 100644 --- a/source3/libads/util.c +++ b/source3/libads/util.c @@ -86,6 +86,8 @@ ADS_STATUS ads_guess_service_principal(ADS_STRUCT *ads,  		server_realm = SMB_STRDUP(ads->config.realm);  		if (!server || !server_realm) { +			SAFE_FREE(server); +			SAFE_FREE(server_realm);  			return ADS_ERROR(LDAP_NO_MEMORY);  		} diff --git a/source3/libnet/libnet_proto.h b/source3/libnet/libnet_proto.h index 43046a44c0..69a16c1c7d 100644 --- a/source3/libnet/libnet_proto.h +++ b/source3/libnet/libnet_proto.h @@ -53,7 +53,7 @@ krb5_error_code libnet_keytab_add(struct libnet_keytab_context *ctx);  struct libnet_keytab_entry *libnet_keytab_search(struct libnet_keytab_context *ctx,  						 const char *principal, int kvno, -						 const const krb5_enctype enctype, +						 const krb5_enctype enctype,  						 TALLOC_CTX *mem_ctx);  #endif 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()) {  | 
