summaryrefslogtreecommitdiff
path: root/source3/smbd/process.c
diff options
context:
space:
mode:
Diffstat (limited to 'source3/smbd/process.c')
-rw-r--r--source3/smbd/process.c288
1 files changed, 147 insertions, 141 deletions
diff --git a/source3/smbd/process.c b/source3/smbd/process.c
index 55234ec896..0f7cfd0e9c 100644
--- a/source3/smbd/process.c
+++ b/source3/smbd/process.c
@@ -42,8 +42,8 @@ extern int last_message;
extern int global_oplock_break;
extern userdom_struct current_user_info;
extern int smb_read_error;
-SIG_ATOMIC_T reload_after_sighup;
-SIG_ATOMIC_T got_sig_term;
+SIG_ATOMIC_T reload_after_sighup = 0;
+SIG_ATOMIC_T got_sig_term = 0;
extern BOOL global_machine_password_needs_changing;
extern fstring global_myworkgroup;
extern pstring global_myname;
@@ -609,8 +609,9 @@ const static struct smb_message_struct
};
/*******************************************************************
-dump a prs to a file
- ********************************************************************/
+ Dump a packet to a file.
+********************************************************************/
+
static void smb_dump(const char *name, int type, char *data, ssize_t len)
{
int fd, i;
@@ -635,178 +636,171 @@ static void smb_dump(const char *name, int type, char *data, ssize_t len)
/****************************************************************************
-do a switch on the message type, and return the response size
+ Do a switch on the message type, and return the response size
****************************************************************************/
+
static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize)
{
- static pid_t pid= (pid_t)-1;
- int outsize = 0;
- extern uint16 global_smbpid;
-
- type &= 0xff;
+ static pid_t pid= (pid_t)-1;
+ int outsize = 0;
+ extern uint16 global_smbpid;
- if (pid == (pid_t)-1)
- pid = sys_getpid();
+ type &= 0xff;
- errno = 0;
- last_message = type;
-
- /* make sure this is an SMB packet */
- if (strncmp(smb_base(inbuf),"\377SMB",4) != 0)
- {
- DEBUG(2,("Non-SMB packet of length %d\n",smb_len(inbuf)));
- return(-1);
- }
+ if (pid == (pid_t)-1)
+ pid = sys_getpid();
- /* yuck! this is an interim measure before we get rid of our
- current inbuf/outbuf system */
- global_smbpid = SVAL(inbuf,smb_pid);
+ errno = 0;
+ last_message = type;
- if (smb_messages[type].fn == NULL)
- {
- DEBUG(0,("Unknown message type %d!\n",type));
- smb_dump("Unknown", 1, inbuf, size);
- outsize = reply_unknown(inbuf,outbuf);
- }
- else
- {
- int flags = smb_messages[type].flags;
- static uint16 last_session_tag = UID_FIELD_INVALID;
- /* In share mode security we must ignore the vuid. */
- uint16 session_tag = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : SVAL(inbuf,smb_uid);
- connection_struct *conn = conn_find(SVAL(inbuf,smb_tid));
+ /* Make sure this is an SMB packet. smb_size contains NetBIOS header so subtract 4 from it. */
+ if ((strncmp(smb_base(inbuf),"\377SMB",4) != 0) || (size < (smb_size - 4))) {
+ DEBUG(2,("Non-SMB packet of length %d. Terminating server\n",smb_len(inbuf)));
+ exit_server("Non-SMB packet");
+ return(-1);
+ }
- DEBUG(3,("switch message %s (pid %d)\n",smb_fn_name(type),(int)pid));
+ /* yuck! this is an interim measure before we get rid of our
+ current inbuf/outbuf system */
+ global_smbpid = SVAL(inbuf,smb_pid);
+
+ if (smb_messages[type].fn == NULL) {
+ DEBUG(0,("Unknown message type %d!\n",type));
+ smb_dump("Unknown", 1, inbuf, size);
+ outsize = reply_unknown(inbuf,outbuf);
+ } else {
+ int flags = smb_messages[type].flags;
+ static uint16 last_session_tag = UID_FIELD_INVALID;
+ /* In share mode security we must ignore the vuid. */
+ uint16 session_tag = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : SVAL(inbuf,smb_uid);
+ connection_struct *conn = conn_find(SVAL(inbuf,smb_tid));
+
+ DEBUG(3,("switch message %s (pid %d)\n",smb_fn_name(type),(int)pid));
+
+ smb_dump(smb_fn_name(type), 1, inbuf, size);
+ if(global_oplock_break) {
+ if(flags & QUEUE_IN_OPLOCK) {
+ /*
+ * Queue this message as we are the process of an oplock break.
+ */
+
+ DEBUG( 2, ( "switch_message: queueing message due to being in " ) );
+ DEBUGADD( 2, ( "oplock break state.\n" ) );
+
+ push_oplock_pending_smb_message( inbuf, size );
+ return -1;
+ }
+ }
- smb_dump(smb_fn_name(type), 1, inbuf, size);
- if(global_oplock_break)
- {
- if(flags & QUEUE_IN_OPLOCK)
- {
- /*
- * Queue this message as we are the process of an oplock break.
- */
-
- DEBUG( 2, ( "switch_message: queueing message due to being in " ) );
- DEBUGADD( 2, ( "oplock break state.\n" ) );
-
- push_oplock_pending_smb_message( inbuf, size );
- return -1;
- }
- }
+ /* Ensure this value is replaced in the incoming packet. */
+ SSVAL(inbuf,smb_uid,session_tag);
- /* Ensure this value is replaced in the incoming packet. */
- SSVAL(inbuf,smb_uid,session_tag);
+ /*
+ * Ensure the correct username is in current_user_info.
+ * This is a really ugly bugfix for problems with
+ * multiple session_setup_and_X's being done and
+ * allowing %U and %G substitutions to work correctly.
+ * There is a reason this code is done here, don't
+ * move it unless you know what you're doing... :-).
+ * JRA.
+ */
- /*
- * Ensure the correct username is in current_user_info.
- * This is a really ugly bugfix for problems with
- * multiple session_setup_and_X's being done and
- * allowing %U and %G substitutions to work correctly.
- * There is a reason this code is done here, don't
- * move it unless you know what you're doing... :-).
- * JRA.
- */
+ if (session_tag != last_session_tag) {
+ user_struct *vuser = NULL;
- if (session_tag != last_session_tag) {
- user_struct *vuser = NULL;
+ last_session_tag = session_tag;
+ if(session_tag != UID_FIELD_INVALID)
+ vuser = get_valid_user_struct(session_tag);
+ if(vuser != NULL)
+ current_user_info = vuser->user;
+ }
- last_session_tag = session_tag;
- if(session_tag != UID_FIELD_INVALID)
- vuser = get_valid_user_struct(session_tag);
- if(vuser != NULL)
- current_user_info = vuser->user;
- }
+ /* does this protocol need to be run as root? */
+ if (!(flags & AS_USER))
+ change_to_root_user();
- /* does this protocol need to be run as root? */
- if (!(flags & AS_USER))
- change_to_root_user();
+ /* does this protocol need a valid tree connection? */
+ if ((flags & AS_USER) && !conn)
+ return ERROR_DOS(ERRSRV, ERRinvnid);
- /* does this protocol need a valid tree connection? */
- if ((flags & AS_USER) && !conn) {
- return ERROR_DOS(ERRSRV, ERRinvnid);
- }
+ /* does this protocol need to be run as the connected user? */
+ if ((flags & AS_USER) && !change_to_user(conn,session_tag)) {
+ if (flags & AS_GUEST)
+ flags &= ~AS_USER;
+ else
+ return(ERROR_DOS(ERRSRV,ERRaccess));
+ }
- /* does this protocol need to be run as the connected user? */
- if ((flags & AS_USER) && !change_to_user(conn,session_tag)) {
- if (flags & AS_GUEST)
- flags &= ~AS_USER;
- else
- return(ERROR_DOS(ERRSRV,ERRaccess));
- }
-
- /* this code is to work around a bug is MS client 3 without
- introducing a security hole - it needs to be able to do
- print queue checks as guest if it isn't logged in properly */
- if (flags & AS_USER)
- flags &= ~AS_GUEST;
+ /* this code is to work around a bug is MS client 3 without
+ introducing a security hole - it needs to be able to do
+ print queue checks as guest if it isn't logged in properly */
+ if (flags & AS_USER)
+ flags &= ~AS_GUEST;
- /* does it need write permission? */
- if ((flags & NEED_WRITE) && !CAN_WRITE(conn))
- return(ERROR_DOS(ERRSRV,ERRaccess));
+ /* does it need write permission? */
+ if ((flags & NEED_WRITE) && !CAN_WRITE(conn))
+ return(ERROR_DOS(ERRSRV,ERRaccess));
- /* ipc services are limited */
- if (IS_IPC(conn) && (flags & AS_USER) && !(flags & CAN_IPC)) {
- return(ERROR_DOS(ERRSRV,ERRaccess));
- }
+ /* ipc services are limited */
+ if (IS_IPC(conn) && (flags & AS_USER) && !(flags & CAN_IPC))
+ return(ERROR_DOS(ERRSRV,ERRaccess));
- /* load service specific parameters */
- if (conn && !set_current_service(conn,(flags & AS_USER)?True:False)) {
- return(ERROR_DOS(ERRSRV,ERRaccess));
- }
+ /* load service specific parameters */
+ if (conn && !set_current_service(conn,(flags & AS_USER)?True:False))
+ return(ERROR_DOS(ERRSRV,ERRaccess));
- /* does this protocol need to be run as guest? */
- if ((flags & AS_GUEST) &&
- (!change_to_guest() ||
- !check_access(smbd_server_fd(), lp_hostsallow(-1), lp_hostsdeny(-1)))) {
- return(ERROR_DOS(ERRSRV,ERRaccess));
- }
+ /* does this protocol need to be run as guest? */
+ if ((flags & AS_GUEST) && (!change_to_guest() ||
+ !check_access(smbd_server_fd(), lp_hostsallow(-1), lp_hostsdeny(-1))))
+ return(ERROR_DOS(ERRSRV,ERRaccess));
- last_inbuf = inbuf;
+ last_inbuf = inbuf;
- outsize = smb_messages[type].fn(conn, inbuf,outbuf,size,bufsize);
- }
+ outsize = smb_messages[type].fn(conn, inbuf,outbuf,size,bufsize);
+ }
- smb_dump(smb_fn_name(type), 0, outbuf, outsize);
+ smb_dump(smb_fn_name(type), 0, outbuf, outsize);
- return(outsize);
+ return(outsize);
}
/****************************************************************************
- construct a reply to the incoming packet
+ Construct a reply to the incoming packet.
****************************************************************************/
+
static int construct_reply(char *inbuf,char *outbuf,int size,int bufsize)
{
- int type = CVAL(inbuf,smb_com);
- int outsize = 0;
- int msg_type = CVAL(inbuf,0);
+ int type = CVAL(inbuf,smb_com);
+ int outsize = 0;
+ int msg_type = CVAL(inbuf,0);
- GetTimeOfDay(&smb_last_time);
+ GetTimeOfDay(&smb_last_time);
- chain_size = 0;
- file_chain_reset();
- reset_chain_p();
+ chain_size = 0;
+ file_chain_reset();
+ reset_chain_p();
- if (msg_type != 0)
- return(reply_special(inbuf,outbuf));
+ if (msg_type != 0)
+ return(reply_special(inbuf,outbuf));
- construct_reply_common(inbuf, outbuf);
+ construct_reply_common(inbuf, outbuf);
- outsize = switch_message(type,inbuf,outbuf,size,bufsize);
+ outsize = switch_message(type,inbuf,outbuf,size,bufsize);
- outsize += chain_size;
+ outsize += chain_size;
- if(outsize > 4)
- smb_setlen(outbuf,outsize - 4);
- return(outsize);
+ if(outsize > 4)
+ smb_setlen(outbuf,outsize - 4);
+ return(outsize);
}
/****************************************************************************
- Keep track of the number of running smbd's. This functionality is used to
- 'hard' limit Samba overhead on resource constrained systems.
+ Keep track of the number of running smbd's. This functionality is used to
+ 'hard' limit Samba overhead on resource constrained systems.
****************************************************************************/
+
static BOOL smbd_process_limit(void)
{
int32 total_smbds;
@@ -1032,16 +1026,15 @@ static int setup_select_timeout(void)
int select_timeout;
int t;
- /*
- * Increase the select timeout back to SMBD_SELECT_TIMEOUT if we
- * have removed any blocking locks. JRA.
- */
-
- select_timeout = blocking_locks_pending() ? SMBD_SELECT_TIMEOUT_WITH_PENDING_LOCKS*1000 :
- SMBD_SELECT_TIMEOUT*1000;
+ select_timeout = blocking_locks_timeout(SMBD_SELECT_TIMEOUT);
+ select_timeout *= 1000;
t = change_notify_timeout();
- if (t != -1) select_timeout = MIN(select_timeout, t*1000);
+ if (t != -1)
+ select_timeout = MIN(select_timeout, t*1000);
+
+ if (print_notify_messages_pending())
+ select_timeout = MIN(select_timeout, 1000);
return select_timeout;
}
@@ -1161,9 +1154,16 @@ static BOOL timeout_processing(int deadtime, int *select_timeout, time_t *last_t
* First, open the machine password file with an exclusive lock.
*/
+ if (secrets_lock_trust_account_password(global_myworkgroup, True) == False) {
+ DEBUG(0,("process: unable to lock the machine account password for \
+machine %s in domain %s.\n", global_myname, global_myworkgroup ));
+ return True;
+ }
+
if(!secrets_fetch_trust_account_password(global_myworkgroup, trust_passwd_hash, &lct)) {
DEBUG(0,("process: unable to read the machine account password for \
machine %s in domain %s.\n", global_myname, global_myworkgroup ));
+ secrets_lock_trust_account_password(global_myworkgroup, False);
return True;
}
@@ -1173,6 +1173,7 @@ machine %s in domain %s.\n", global_myname, global_myworkgroup ));
if(t < lct + lp_machine_password_timeout()) {
global_machine_password_needs_changing = False;
+ secrets_lock_trust_account_password(global_myworkgroup, False);
return True;
}
@@ -1180,6 +1181,7 @@ machine %s in domain %s.\n", global_myname, global_myworkgroup ));
change_trust_account_password( global_myworkgroup, remote_machine_list);
global_machine_password_needs_changing = False;
+ secrets_lock_trust_account_password(global_myworkgroup, False);
}
/*
@@ -1201,6 +1203,10 @@ machine %s in domain %s.\n", global_myname, global_myworkgroup ));
force_check_log_size();
check_log_size();
+ /* Send any queued printer notify message to interested smbd's. */
+
+ print_notify_send_messages();
+
/*
* Modify the select timeout depending upon
* what we have remaining in our queues.