From 4b9cc7d478438e34217add83b2647d47d52268a7 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 3 Oct 2008 14:05:33 -0700 Subject: Document "cups connection timeout". Jeremy. --- .../smbdotconf/printing/cupsconnectiontimeout.xml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 docs-xml/smbdotconf/printing/cupsconnectiontimeout.xml 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 @@ + + + + This parameter is only applicable if is set to cups. + + + + 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. + + + +30 +60 + -- cgit From f6c883b4b00f4cd751cd312a27bddffb3be9c059 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 3 Oct 2008 14:18:35 -0700 Subject: Simply our main loop processing. A lot :-). Correctly use events for all the previous "special" cases. A step on the way to adding signals to the events and being able to merge the S3 event system with the S4 one. Jeremy. --- source3/auth/auth_domain.c | 65 +++++++++++++++ source3/include/proto.h | 3 +- source3/lib/dummysmbd.c | 15 ++++ source3/printing/notify.c | 26 ++++++ source3/smbd/process.c | 193 +++------------------------------------------ source3/smbd/reply.c | 3 - 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; } /* @@ -1836,23 +1831,6 @@ void chain_reply(struct smb_request *req) return; } -/**************************************************************************** - 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. ****************************************************************************/ @@ -1906,114 +1884,19 @@ 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()) { -- cgit From a9390d3047b7b7aba6f73c20e3dff292f7600a9f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 3 Oct 2008 14:58:41 -0700 Subject: Correctly fix smbclient to terminate on eof from server. Jeremy. --- source3/client/client.c | 13 +++++++++++-- source3/include/proto.h | 1 + source3/lib/readline.c | 13 ++++++++++++- 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/source3/client/client.c b/source3/client/client.c index 7af7d30108..4d6bf8f198 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); @@ -4419,7 +4423,12 @@ static void readline_callback(void) { unsigned char garbage[16]; memset(garbage, 0xf0, sizeof(garbage)); - cli_echo(cli, 1, data_blob_const(garbage, sizeof(garbage))); + if (!cli_echo(cli, 1, data_blob_const(garbage, sizeof(garbage)))) { + DEBUG(0, ("SMBecho failed. Maybe server has closed " + "the connection\n")); + finished = true; + smb_readline_done(); + } } } @@ -4431,7 +4440,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 6799106217..7cdcba19ab 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -708,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/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; } /**************************************************************************** -- cgit From af9dc6381da52c686d797a54d69b486214000cb5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 3 Oct 2008 17:57:37 -0700 Subject: Fix the build farm. In this branch cli_echo returns NTSTATUS. Jeremy --- source3/client/client.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/source3/client/client.c b/source3/client/client.c index 4d6bf8f198..eb9f31bdf2 100644 --- a/source3/client/client.c +++ b/source3/client/client.c @@ -4421,9 +4421,12 @@ 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)); - if (!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; -- cgit From 0e0371b78a8d445cd0a08bd102a9a2c4952c235f Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 4 Oct 2008 21:52:11 +0200 Subject: "gwen/cc" does not like the double const :-) --- source3/libnet/libnet_proto.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 -- cgit From 87f496f3c1ff5c8fd72bcfb6b4af7cb539d5bc47 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 4 Oct 2008 22:07:14 +0200 Subject: Fix a potential NULL deref in line 258 found by the IBM checker --- source3/libaddns/dnsmarshall.c | 1 + 1 file changed, 1 insertion(+) 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); -- cgit From 9eea6929e3420a0035ec3c0e3f1b4dd24847bbfa Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 4 Oct 2008 22:15:03 +0200 Subject: Fix an uninitialized variable found by the IBM Checker --- source3/libads/ldap.c | 1 + 1 file changed, 1 insertion(+) 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; -- cgit From 80665a0b5abbdd8df735e1ccdab3206399beba0b Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 4 Oct 2008 22:17:30 +0200 Subject: Fix an unlikely memleak found by the IBM checker --- source3/libads/util.c | 2 ++ 1 file changed, 2 insertions(+) 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); } -- cgit