summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/auth/auth_domain.c65
-rw-r--r--source3/include/proto.h3
-rw-r--r--source3/lib/dummysmbd.c15
-rw-r--r--source3/printing/notify.c26
-rw-r--r--source3/smbd/process.c193
-rw-r--r--source3/smbd/reply.c3
-rw-r--r--source3/smbd/server.c31
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()) {