diff options
Diffstat (limited to 'source3/smbd')
-rw-r--r-- | source3/smbd/blocking.c | 498 | ||||
-rw-r--r-- | source3/smbd/change_trust_pw.c | 2 | ||||
-rw-r--r-- | source3/smbd/chgpasswd.c | 15 | ||||
-rw-r--r-- | source3/smbd/close.c | 4 | ||||
-rw-r--r-- | source3/smbd/ipc.c | 11 | ||||
-rw-r--r-- | source3/smbd/lanman.c | 112 | ||||
-rw-r--r-- | source3/smbd/mangle_hash.c | 7 | ||||
-rw-r--r-- | source3/smbd/negprot.c | 20 | ||||
-rw-r--r-- | source3/smbd/notify.c | 6 | ||||
-rw-r--r-- | source3/smbd/ntquotas.c | 2 | ||||
-rw-r--r-- | source3/smbd/nttrans.c | 7 | ||||
-rw-r--r-- | source3/smbd/open.c | 24 | ||||
-rw-r--r-- | source3/smbd/oplock.c | 14 | ||||
-rw-r--r-- | source3/smbd/password.c | 56 | ||||
-rw-r--r-- | source3/smbd/process.c | 671 | ||||
-rw-r--r-- | source3/smbd/reply.c | 58 | ||||
-rw-r--r-- | source3/smbd/service.c | 2 | ||||
-rw-r--r-- | source3/smbd/sesssetup.c | 71 | ||||
-rw-r--r-- | source3/smbd/statcache.c | 33 | ||||
-rw-r--r-- | source3/smbd/trans2.c | 16 | ||||
-rw-r--r-- | source3/smbd/utmp.c | 4 |
21 files changed, 897 insertions, 736 deletions
diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 2802fbb151..fed3a51b88 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -28,16 +28,16 @@ extern char *OutBuffer; *****************************************************************************/ typedef struct { - ubi_slNode msg_next; - int com_type; - files_struct *fsp; - time_t expire_time; - int lock_num; - SMB_BIG_UINT offset; - SMB_BIG_UINT count; - uint16 lock_pid; - char *inbuf; - int length; + ubi_slNode msg_next; + int com_type; + files_struct *fsp; + time_t expire_time; + int lock_num; + SMB_BIG_UINT offset; + SMB_BIG_UINT count; + uint16 lock_pid; + char *inbuf; + int length; } blocking_lock_record; static ubi_slList blocking_lock_queue = { NULL, (ubi_slNodePtr)&blocking_lock_queue, 0}; @@ -48,8 +48,8 @@ static ubi_slList blocking_lock_queue = { NULL, (ubi_slNodePtr)&blocking_lock_qu static void free_blocking_lock_record(blocking_lock_record *blr) { - SAFE_FREE(blr->inbuf); - SAFE_FREE(blr); + SAFE_FREE(blr->inbuf); + SAFE_FREE(blr); } /**************************************************************************** @@ -58,17 +58,17 @@ static void free_blocking_lock_record(blocking_lock_record *blr) static files_struct *get_fsp_from_pkt(char *inbuf) { - switch(CVAL(inbuf,smb_com)) { - case SMBlock: - case SMBlockread: - return file_fsp(inbuf,smb_vwv0); - case SMBlockingX: - return file_fsp(inbuf,smb_vwv2); - default: - DEBUG(0,("get_fsp_from_pkt: PANIC - unknown type on blocking lock queue - exiting.!\n")); - exit_server("PANIC - unknown type on blocking lock queue"); - } - return NULL; /* Keep compiler happy. */ + switch(CVAL(inbuf,smb_com)) { + case SMBlock: + case SMBlockread: + return file_fsp(inbuf,smb_vwv0); + case SMBlockingX: + return file_fsp(inbuf,smb_vwv2); + default: + DEBUG(0,("get_fsp_from_pkt: PANIC - unknown type on blocking lock queue - exiting.!\n")); + exit_server("PANIC - unknown type on blocking lock queue"); + } + return NULL; /* Keep compiler happy. */ } /**************************************************************************** @@ -77,7 +77,7 @@ static files_struct *get_fsp_from_pkt(char *inbuf) static BOOL in_chained_smb(void) { - return (chain_size != 0); + return (chain_size != 0); } static void received_unlock_msg(int msg_type, pid_t src, void *buf, size_t len); @@ -89,66 +89,68 @@ static void received_unlock_msg(int msg_type, pid_t src, void *buf, size_t len); BOOL push_blocking_lock_request( char *inbuf, int length, int lock_timeout, int lock_num, uint16 lock_pid, SMB_BIG_UINT offset, SMB_BIG_UINT count) { - static BOOL set_lock_msg; - blocking_lock_record *blr; - NTSTATUS status; - - if(in_chained_smb() ) { - DEBUG(0,("push_blocking_lock_request: cannot queue a chained request (currently).\n")); - return False; - } - - /* - * Now queue an entry on the blocking lock queue. We setup - * the expiration time here. - */ - - if((blr = (blocking_lock_record *)malloc(sizeof(blocking_lock_record))) == NULL) { - DEBUG(0,("push_blocking_lock_request: Malloc fail !\n" )); - return False; - } - - if((blr->inbuf = (char *)malloc(length)) == NULL) { - DEBUG(0,("push_blocking_lock_request: Malloc fail (2)!\n" )); - SAFE_FREE(blr); - return False; - } - - blr->com_type = CVAL(inbuf,smb_com); - blr->fsp = get_fsp_from_pkt(inbuf); - blr->expire_time = (lock_timeout == -1) ? (time_t)-1 : time(NULL) + (time_t)lock_timeout; - blr->lock_num = lock_num; - blr->lock_pid = lock_pid; - blr->offset = offset; - blr->count = count; - memcpy(blr->inbuf, inbuf, length); - blr->length = length; - - /* Add a pending lock record for this. */ - status = brl_lock(blr->fsp->dev, blr->fsp->inode, blr->fsp->fnum, - lock_pid, sys_getpid(), blr->fsp->conn->cnum, - offset, count, - PENDING_LOCK); - - if (!NT_STATUS_IS_OK(status)) { - DEBUG(0,("push_blocking_lock_request: failed to add PENDING_LOCK record.\n")); - free_blocking_lock_record(blr); - return False; - } + static BOOL set_lock_msg; + blocking_lock_record *blr; + NTSTATUS status; + + if(in_chained_smb() ) { + DEBUG(0,("push_blocking_lock_request: cannot queue a chained request (currently).\n")); + return False; + } + + /* + * Now queue an entry on the blocking lock queue. We setup + * the expiration time here. + */ - ubi_slAddTail(&blocking_lock_queue, blr); + if((blr = (blocking_lock_record *)malloc(sizeof(blocking_lock_record))) == NULL) { + DEBUG(0,("push_blocking_lock_request: Malloc fail !\n" )); + return False; + } + + if((blr->inbuf = (char *)malloc(length)) == NULL) { + DEBUG(0,("push_blocking_lock_request: Malloc fail (2)!\n" )); + SAFE_FREE(blr); + return False; + } - /* Ensure we'll receive messages when this is unlocked. */ - if (!set_lock_msg) { - message_register(MSG_SMB_UNLOCK, received_unlock_msg); - set_lock_msg = True; - } + blr->com_type = CVAL(inbuf,smb_com); + blr->fsp = get_fsp_from_pkt(inbuf); + blr->expire_time = (lock_timeout == -1) ? (time_t)-1 : time(NULL) + (time_t)lock_timeout; + blr->lock_num = lock_num; + blr->lock_pid = lock_pid; + blr->offset = offset; + blr->count = count; + memcpy(blr->inbuf, inbuf, length); + blr->length = length; + + /* Add a pending lock record for this. */ + status = brl_lock(blr->fsp->dev, blr->fsp->inode, blr->fsp->fnum, + lock_pid, sys_getpid(), blr->fsp->conn->cnum, + offset, count, PENDING_LOCK); + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("push_blocking_lock_request: failed to add PENDING_LOCK record.\n")); + free_blocking_lock_record(blr); + return False; + } + + ubi_slAddTail(&blocking_lock_queue, blr); + + /* Ensure we'll receive messages when this is unlocked. */ + if (!set_lock_msg) { + message_register(MSG_SMB_UNLOCK, received_unlock_msg); + set_lock_msg = True; + } - DEBUG(3,("push_blocking_lock_request: lock request length=%d blocked with expiry time %d (+%d) \ + DEBUG(3,("push_blocking_lock_request: lock request length=%d blocked with expiry time %d (+%d) \ for fnum = %d, name = %s\n", length, (int)blr->expire_time, lock_timeout, - blr->fsp->fnum, blr->fsp->fsp_name )); + blr->fsp->fnum, blr->fsp->fsp_name )); - return True; + /* Push the MID of this packet on the signing queue. */ + srv_defer_sign_response(SVAL(inbuf,smb_mid)); + + return True; } /**************************************************************************** @@ -170,27 +172,27 @@ static void send_blocking_reply(char *outbuf, int outsize) static void reply_lockingX_success(blocking_lock_record *blr) { - char *outbuf = OutBuffer; - int bufsize = BUFFER_SIZE; - char *inbuf = blr->inbuf; - int outsize = 0; + char *outbuf = OutBuffer; + int bufsize = BUFFER_SIZE; + char *inbuf = blr->inbuf; + int outsize = 0; - construct_reply_common(inbuf, outbuf); - set_message(outbuf,2,0,True); + construct_reply_common(inbuf, outbuf); + set_message(outbuf,2,0,True); - /* - * As this message is a lockingX call we must handle - * any following chained message correctly. - * This is normally handled in construct_reply(), - * but as that calls switch_message, we can't use - * that here and must set up the chain info manually. - */ + /* + * As this message is a lockingX call we must handle + * any following chained message correctly. + * This is normally handled in construct_reply(), + * but as that calls switch_message, we can't use + * that here and must set up the chain info manually. + */ - outsize = chain_reply(inbuf,outbuf,blr->length,bufsize); + outsize = chain_reply(inbuf,outbuf,blr->length,bufsize); - outsize += chain_size; + outsize += chain_size; - send_blocking_reply(outbuf,outsize); + send_blocking_reply(outbuf,outsize); } /**************************************************************************** @@ -492,18 +494,18 @@ Waiting....\n", static BOOL blocking_lock_record_process(blocking_lock_record *blr) { - switch(blr->com_type) { - case SMBlock: - return process_lock(blr); - case SMBlockread: - return process_lockread(blr); - case SMBlockingX: - return process_lockingX(blr); - default: - DEBUG(0,("blocking_lock_record_process: PANIC - unknown type on blocking lock queue - exiting.!\n")); - exit_server("PANIC - unknown type on blocking lock queue"); - } - return False; /* Keep compiler happy. */ + switch(blr->com_type) { + case SMBlock: + return process_lock(blr); + case SMBlockread: + return process_lockread(blr); + case SMBlockingX: + return process_lockingX(blr); + default: + DEBUG(0,("blocking_lock_record_process: PANIC - unknown type on blocking lock queue - exiting.!\n")); + exit_server("PANIC - unknown type on blocking lock queue"); + } + return False; /* Keep compiler happy. */ } /**************************************************************************** @@ -512,27 +514,27 @@ static BOOL blocking_lock_record_process(blocking_lock_record *blr) void remove_pending_lock_requests_by_fid(files_struct *fsp) { - blocking_lock_record *blr = (blocking_lock_record *)ubi_slFirst( &blocking_lock_queue ); - blocking_lock_record *prev = NULL; + blocking_lock_record *blr = (blocking_lock_record *)ubi_slFirst( &blocking_lock_queue ); + blocking_lock_record *prev = NULL; - while(blr != NULL) { - if(blr->fsp->fnum == fsp->fnum) { + while(blr != NULL) { + if(blr->fsp->fnum == fsp->fnum) { - DEBUG(10,("remove_pending_lock_requests_by_fid - removing request type %d for \ + DEBUG(10,("remove_pending_lock_requests_by_fid - removing request type %d for \ file %s fnum = %d\n", blr->com_type, fsp->fsp_name, fsp->fnum )); - brl_unlock(blr->fsp->dev, blr->fsp->inode, blr->fsp->fnum, - blr->lock_pid, sys_getpid(), blr->fsp->conn->cnum, - blr->offset, blr->count, True, NULL, NULL); + brl_unlock(blr->fsp->dev, blr->fsp->inode, blr->fsp->fnum, + blr->lock_pid, sys_getpid(), blr->fsp->conn->cnum, + blr->offset, blr->count, True, NULL, NULL); - free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); - blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue)); - continue; - } + free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); + blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue)); + continue; + } - prev = blr; - blr = (blocking_lock_record *)ubi_slNext(blr); - } + prev = blr; + blr = (blocking_lock_record *)ubi_slNext(blr); + } } /**************************************************************************** @@ -541,28 +543,28 @@ file %s fnum = %d\n", blr->com_type, fsp->fsp_name, fsp->fnum )); void remove_pending_lock_requests_by_mid(int mid) { - blocking_lock_record *blr = (blocking_lock_record *)ubi_slFirst( &blocking_lock_queue ); - blocking_lock_record *prev = NULL; + blocking_lock_record *blr = (blocking_lock_record *)ubi_slFirst( &blocking_lock_queue ); + blocking_lock_record *prev = NULL; - while(blr != NULL) { - if(SVAL(blr->inbuf,smb_mid) == mid) { - files_struct *fsp = blr->fsp; + while(blr != NULL) { + if(SVAL(blr->inbuf,smb_mid) == mid) { + files_struct *fsp = blr->fsp; - DEBUG(10,("remove_pending_lock_requests_by_mid - removing request type %d for \ + DEBUG(10,("remove_pending_lock_requests_by_mid - removing request type %d for \ file %s fnum = %d\n", blr->com_type, fsp->fsp_name, fsp->fnum )); - blocking_lock_reply_error(blr,NT_STATUS_CANCELLED); - brl_unlock(blr->fsp->dev, blr->fsp->inode, blr->fsp->fnum, - blr->lock_pid, sys_getpid(), blr->fsp->conn->cnum, - blr->offset, blr->count, True, NULL, NULL); - free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); - blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue)); - continue; - } - - prev = blr; - blr = (blocking_lock_record *)ubi_slNext(blr); - } + blocking_lock_reply_error(blr,NT_STATUS_CANCELLED); + brl_unlock(blr->fsp->dev, blr->fsp->inode, blr->fsp->fnum, + blr->lock_pid, sys_getpid(), blr->fsp->conn->cnum, + blr->offset, blr->count, True, NULL, NULL); + free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); + blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue)); + continue; + } + + prev = blr; + blr = (blocking_lock_record *)ubi_slNext(blr); + } } /**************************************************************************** @@ -611,112 +613,112 @@ unsigned blocking_locks_timeout(unsigned default_timeout) void process_blocking_lock_queue(time_t t) { - blocking_lock_record *blr = (blocking_lock_record *)ubi_slFirst( &blocking_lock_queue ); - blocking_lock_record *prev = NULL; - - if(blr == NULL) - return; - - /* - * Go through the queue and see if we can get any of the locks. - */ - - while(blr != NULL) { - connection_struct *conn = NULL; - uint16 vuid; - files_struct *fsp = NULL; - - /* - * Ensure we don't have any old chain_fsp values - * sitting around.... - */ - chain_size = 0; - file_chain_reset(); - fsp = blr->fsp; - - conn = conn_find(SVAL(blr->inbuf,smb_tid)); - vuid = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : - SVAL(blr->inbuf,smb_uid); - - DEBUG(5,("process_blocking_lock_queue: examining pending lock fnum = %d for file %s\n", - fsp->fnum, fsp->fsp_name )); - - if((blr->expire_time != -1) && (blr->expire_time <= t)) { - /* - * Lock expired - throw away all previously - * obtained locks and return lock error. - */ - DEBUG(5,("process_blocking_lock_queue: pending lock fnum = %d for file %s timed out.\n", - fsp->fnum, fsp->fsp_name )); - - brl_unlock(fsp->dev, fsp->inode, fsp->fnum, - blr->lock_pid, sys_getpid(), conn->cnum, - blr->offset, blr->count, True, NULL, NULL); - - blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT); - free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); - blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue)); - continue; - } - - if(!change_to_user(conn,vuid)) { - DEBUG(0,("process_blocking_lock_queue: Unable to become user vuid=%d.\n", - vuid )); - /* - * Remove the entry and return an error to the client. - */ - blocking_lock_reply_error(blr,NT_STATUS_ACCESS_DENIED); - - brl_unlock(fsp->dev, fsp->inode, fsp->fnum, - blr->lock_pid, sys_getpid(), conn->cnum, - blr->offset, blr->count, True, NULL, NULL); - - free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); - blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue)); - continue; - } - - if(!set_current_service(conn,True)) { - DEBUG(0,("process_blocking_lock_queue: Unable to become service Error was %s.\n", strerror(errno) )); - /* - * Remove the entry and return an error to the client. - */ - blocking_lock_reply_error(blr,NT_STATUS_ACCESS_DENIED); - - brl_unlock(fsp->dev, fsp->inode, fsp->fnum, - blr->lock_pid, sys_getpid(), conn->cnum, - blr->offset, blr->count, True, NULL, NULL); - - free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); - blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue)); - change_to_root_user(); - continue; - } - - /* - * Go through the remaining locks and try and obtain them. - * The call returns True if all locks were obtained successfully - * and False if we still need to wait. - */ - - if(blocking_lock_record_process(blr)) { - - brl_unlock(fsp->dev, fsp->inode, fsp->fnum, - blr->lock_pid, sys_getpid(), conn->cnum, - blr->offset, blr->count, True, NULL, NULL); - - free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); - blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue)); - change_to_root_user(); - continue; - } - - change_to_root_user(); - - /* - * Move to the next in the list. - */ - prev = blr; - blr = (blocking_lock_record *)ubi_slNext(blr); - } + blocking_lock_record *blr = (blocking_lock_record *)ubi_slFirst( &blocking_lock_queue ); + blocking_lock_record *prev = NULL; + + if(blr == NULL) + return; + + /* + * Go through the queue and see if we can get any of the locks. + */ + + while(blr != NULL) { + connection_struct *conn = NULL; + uint16 vuid; + files_struct *fsp = NULL; + + /* + * Ensure we don't have any old chain_fsp values + * sitting around.... + */ + chain_size = 0; + file_chain_reset(); + fsp = blr->fsp; + + conn = conn_find(SVAL(blr->inbuf,smb_tid)); + vuid = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : + SVAL(blr->inbuf,smb_uid); + + DEBUG(5,("process_blocking_lock_queue: examining pending lock fnum = %d for file %s\n", + fsp->fnum, fsp->fsp_name )); + + if((blr->expire_time != -1) && (blr->expire_time <= t)) { + /* + * Lock expired - throw away all previously + * obtained locks and return lock error. + */ + DEBUG(5,("process_blocking_lock_queue: pending lock fnum = %d for file %s timed out.\n", + fsp->fnum, fsp->fsp_name )); + + brl_unlock(fsp->dev, fsp->inode, fsp->fnum, + blr->lock_pid, sys_getpid(), conn->cnum, + blr->offset, blr->count, True, NULL, NULL); + + blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT); + free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); + blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue)); + continue; + } + + if(!change_to_user(conn,vuid)) { + DEBUG(0,("process_blocking_lock_queue: Unable to become user vuid=%d.\n", + vuid )); + /* + * Remove the entry and return an error to the client. + */ + blocking_lock_reply_error(blr,NT_STATUS_ACCESS_DENIED); + + brl_unlock(fsp->dev, fsp->inode, fsp->fnum, + blr->lock_pid, sys_getpid(), conn->cnum, + blr->offset, blr->count, True, NULL, NULL); + + free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); + blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue)); + continue; + } + + if(!set_current_service(conn,True)) { + DEBUG(0,("process_blocking_lock_queue: Unable to become service Error was %s.\n", strerror(errno) )); + /* + * Remove the entry and return an error to the client. + */ + blocking_lock_reply_error(blr,NT_STATUS_ACCESS_DENIED); + + brl_unlock(fsp->dev, fsp->inode, fsp->fnum, + blr->lock_pid, sys_getpid(), conn->cnum, + blr->offset, blr->count, True, NULL, NULL); + + free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); + blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue)); + change_to_root_user(); + continue; + } + + /* + * Go through the remaining locks and try and obtain them. + * The call returns True if all locks were obtained successfully + * and False if we still need to wait. + */ + + if(blocking_lock_record_process(blr)) { + + brl_unlock(fsp->dev, fsp->inode, fsp->fnum, + blr->lock_pid, sys_getpid(), conn->cnum, + blr->offset, blr->count, True, NULL, NULL); + + free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); + blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue)); + change_to_root_user(); + continue; + } + + change_to_root_user(); + + /* + * Move to the next in the list. + */ + prev = blr; + blr = (blocking_lock_record *)ubi_slNext(blr); + } } diff --git a/source3/smbd/change_trust_pw.c b/source3/smbd/change_trust_pw.c index 4993e285ca..2eff77b1f7 100644 --- a/source3/smbd/change_trust_pw.c +++ b/source3/smbd/change_trust_pw.c @@ -58,7 +58,7 @@ NTSTATUS change_trust_account_password( const char *domain, const char *remote_m NULL, 0, "IPC$", "IPC", "", "", - "", 0, NULL))) + "", 0, Undefined, NULL))) { DEBUG(0,("modify_trust_password: Connection to %s failed!\n", remote_machine)); nt_status = NT_STATUS_UNSUCCESSFUL; diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 5c1d9a79a6..6bc8626d81 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -674,6 +674,8 @@ BOOL check_lanman_password(char *user, uchar * pass1, Code to change the lanman hashed password. It nulls out the NT hashed password as it will no longer be valid. + NOTE this function is designed to be called as root. Check the old password + is correct before calling. JRA. ************************************************************/ BOOL change_lanman_password(SAM_ACCOUNT *sampass, uchar *pass2) @@ -730,9 +732,7 @@ BOOL change_lanman_password(SAM_ACCOUNT *sampass, uchar *pass2) } /* Now flush the sam_passwd struct to persistent storage */ - become_root(); ret = pdb_update_sam_account (sampass); - unbecome_root(); return ret; } @@ -740,6 +740,7 @@ BOOL change_lanman_password(SAM_ACCOUNT *sampass, uchar *pass2) /*********************************************************** Code to check and change the OEM hashed password. ************************************************************/ + NTSTATUS pass_oem_change(char *user, uchar * lmdata, uchar * lmhash, uchar * ntdata, uchar * nthash) @@ -747,8 +748,7 @@ NTSTATUS pass_oem_change(char *user, fstring new_passwd; const char *unix_user; SAM_ACCOUNT *sampass = NULL; - NTSTATUS nt_status - = check_oem_password(user, lmdata, lmhash, ntdata, nthash, + NTSTATUS nt_status = check_oem_password(user, lmdata, lmhash, ntdata, nthash, &sampass, new_passwd, sizeof(new_passwd)); if (!NT_STATUS_IS_OK(nt_status)) @@ -765,7 +765,10 @@ NTSTATUS pass_oem_change(char *user, unix_user = pdb_get_username(sampass); + /* We've already checked the old password here.... */ + become_root(); nt_status = change_oem_password(sampass, NULL, new_passwd); + unbecome_root(); memset(new_passwd, 0, sizeof(new_passwd)); @@ -942,6 +945,8 @@ static NTSTATUS check_oem_password(const char *user, /*********************************************************** Code to change the oem password. Changes both the lanman and NT hashes. Old_passwd is almost always NULL. + NOTE this function is designed to be called as root. Check the old password + is correct before calling. JRA. ************************************************************/ NTSTATUS change_oem_password(SAM_ACCOUNT *hnd, char *old_passwd, char *new_passwd) @@ -997,9 +1002,7 @@ NTSTATUS change_oem_password(SAM_ACCOUNT *hnd, char *old_passwd, char *new_passw } /* Now write it into the file. */ - become_root(); ret = pdb_update_sam_account (hnd); - unbecome_root(); if (!ret) { return NT_STATUS_ACCESS_DENIED; diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 1be13270ba..0700aeaa0a 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -163,8 +163,8 @@ static int close_normal_file(files_struct *fsp, BOOL normal_close) share_entry_count = del_share_mode(fsp, &share_entry); - DEBUG(10,("close_normal_file: share_entry_count = %d for file %s\n", - share_entry_count, fsp->fsp_name )); + DEBUG(10,("close_normal_file: share_entry_count = %lu for file %s\n", + (unsigned long)share_entry_count, fsp->fsp_name )); /* * We delete on close if it's the last open, and the diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 85e28f5d17..39072f9b91 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -428,6 +428,8 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int } + srv_signing_trans_start(SVAL(inbuf,smb_mid)); + if (pscnt < tpscnt || dscnt < tdscnt) { /* We need to send an interim response then receive the rest of the parameter/data bytes */ @@ -455,6 +457,7 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int SAFE_FREE(data); SAFE_FREE(setup); END_PROFILE(SMBtrans); + srv_signing_trans_stop(); return(ERROR_DOS(ERRSRV,ERRerror)); } @@ -506,11 +509,10 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int memcpy(data+ddisp,smb_base(inbuf)+doff,dcnt); } } - - + DEBUG(3,("trans <%s> data=%u params=%u setup=%u\n", name,tdscnt,tpscnt,suwcnt)); - + /* * WinCE wierdness.... */ @@ -542,6 +544,8 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int SAFE_FREE(params); SAFE_FREE(setup); + srv_signing_trans_stop(); + if (close_on_completion) close_cnum(conn,vuid); @@ -561,6 +565,7 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int bad_param: + srv_signing_trans_stop(); DEBUG(0,("reply_trans: invalid trans parameters\n")); SAFE_FREE(data); SAFE_FREE(params); diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 04d6a9a8a8..a5f7a7b2ea 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -1897,76 +1897,78 @@ static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param char **rdata,char **rparam, int *rdata_len,int *rparam_len) { - char *p = skip_string(param+2,2); - fstring user; - fstring pass1,pass2; + char *p = skip_string(param+2,2); + fstring user; + fstring pass1,pass2; - pull_ascii_fstring(user,p); + pull_ascii_fstring(user,p); - p = skip_string(p,1); + p = skip_string(p,1); - memset(pass1,'\0',sizeof(pass1)); - memset(pass2,'\0',sizeof(pass2)); - memcpy(pass1,p,16); - memcpy(pass2,p+16,16); + memset(pass1,'\0',sizeof(pass1)); + memset(pass2,'\0',sizeof(pass2)); + memcpy(pass1,p,16); + memcpy(pass2,p+16,16); - *rparam_len = 4; - *rparam = REALLOC(*rparam,*rparam_len); + *rparam_len = 4; + *rparam = REALLOC(*rparam,*rparam_len); - *rdata_len = 0; + *rdata_len = 0; - SSVAL(*rparam,0,NERR_badpass); - SSVAL(*rparam,2,0); /* converter word */ + SSVAL(*rparam,0,NERR_badpass); + SSVAL(*rparam,2,0); /* converter word */ - DEBUG(3,("Set password for <%s>\n",user)); + DEBUG(3,("Set password for <%s>\n",user)); - /* - * Attempt to verify the old password against smbpasswd entries - * Win98 clients send old and new password in plaintext for this call. - */ + /* + * Attempt to verify the old password against smbpasswd entries + * Win98 clients send old and new password in plaintext for this call. + */ - { - auth_serversupplied_info *server_info = NULL; - DATA_BLOB password = data_blob(pass1, strlen(pass1)+1); - if (NT_STATUS_IS_OK(check_plaintext_password(user,password,&server_info))) { - - if (NT_STATUS_IS_OK(change_oem_password(server_info->sam_account, pass1, pass2))) - { - SSVAL(*rparam,0,NERR_Success); - } - - free_server_info(&server_info); - } - data_blob_clear_free(&password); - } + { + auth_serversupplied_info *server_info = NULL; + DATA_BLOB password = data_blob(pass1, strlen(pass1)+1); - /* - * If the plaintext change failed, attempt - * the old encrypted method. NT will generate this - * after trying the samr method. Note that this - * method is done as a last resort as this - * password change method loses the NT password hash - * and cannot change the UNIX password as no plaintext - * is received. - */ + if (NT_STATUS_IS_OK(check_plaintext_password(user,password,&server_info))) { - if(SVAL(*rparam,0) != NERR_Success) - { - SAM_ACCOUNT *hnd = NULL; + become_root(); + if (NT_STATUS_IS_OK(change_oem_password(server_info->sam_account, pass1, pass2))) { + SSVAL(*rparam,0,NERR_Success); + } + unbecome_root(); - if (check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &hnd) && - change_lanman_password(hnd,pass2)) - { - SSVAL(*rparam,0,NERR_Success); - } - pdb_free_sam(&hnd); - } + free_server_info(&server_info); + } + data_blob_clear_free(&password); + } + /* + * If the plaintext change failed, attempt + * the old encrypted method. NT will generate this + * after trying the samr method. Note that this + * method is done as a last resort as this + * password change method loses the NT password hash + * and cannot change the UNIX password as no plaintext + * is received. + */ + + if(SVAL(*rparam,0) != NERR_Success) { + SAM_ACCOUNT *hnd = NULL; - memset((char *)pass1,'\0',sizeof(fstring)); - memset((char *)pass2,'\0',sizeof(fstring)); + if (check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &hnd)) { + become_root(); + if (change_lanman_password(hnd,pass2)) { + SSVAL(*rparam,0,NERR_Success); + } + unbecome_root(); + pdb_free_sam(&hnd); + } + } + + memset((char *)pass1,'\0',sizeof(fstring)); + memset((char *)pass2,'\0',sizeof(fstring)); - return(True); + return(True); } /**************************************************************************** diff --git a/source3/smbd/mangle_hash.c b/source3/smbd/mangle_hash.c index ac8e425fd3..ac2d7681e8 100644 --- a/source3/smbd/mangle_hash.c +++ b/source3/smbd/mangle_hash.c @@ -313,6 +313,7 @@ static BOOL is_8_3(const char *fname, BOOL check_case, BOOL allow_wildcards) const char *f; smb_ucs2_t *ucs2name; NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; + size_t size; if (!fname || !*fname) return False; @@ -324,9 +325,9 @@ static BOOL is_8_3(const char *fname, BOOL check_case, BOOL allow_wildcards) if (strlen(f) > 12) return False; - ucs2name = acnv_uxu2(f); - if (!ucs2name) { - DEBUG(0,("is_8_3: internal error acnv_uxu2() failed!\n")); + size = push_ucs2_allocate(&ucs2name, f); + if (size == (size_t)-1) { + DEBUG(0,("is_8_3: internal error push_ucs2_allocate() failed!\n")); goto done; } diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index f452dd845b..28e3cf97d1 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -277,6 +277,22 @@ static int reply_nt1(char *inbuf, char *outbuf) if (global_encrypted_passwords_negotiated) secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE; + if (lp_server_signing()) { + if (lp_security() >= SEC_USER) { + secword |= NEGOTIATE_SECURITY_SIGNATURES_ENABLED; + /* No raw mode with smb signing. */ + capabilities &= ~CAP_RAW_MODE; + if (lp_server_signing() == Required) + secword |=NEGOTIATE_SECURITY_SIGNATURES_REQUIRED; + srv_set_signing_negotiated(); + } else { + DEBUG(0,("reply_nt1: smb signing is incompatible with share level security !\n")); + if (lp_server_signing() == Required) { + exit_server("reply_nt1: smb signing required and share level security selected."); + } + } + } + set_message(outbuf,17,0,True); SCVAL(outbuf,smb_vwv1,secword); @@ -521,6 +537,10 @@ int reply_negprot(connection_struct *conn, DEBUG( 5, ( "negprot index=%d\n", choice ) ); + if ((lp_server_signing() == Required) && (Protocol < PROTOCOL_NT1)) { + exit_server("SMB signing is required and client negotiated a downlevel protocol"); + } + END_PROFILE(SMBnegprot); return(outsize); } diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index de1b331778..9adf827c79 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -44,6 +44,7 @@ static struct change_notify *change_notify_list; /**************************************************************************** Setup the common parts of the return packet and send it. *****************************************************************************/ + static void change_notify_reply_packet(char *inbuf, NTSTATUS error_code) { char outbuf[smb_size+38]; @@ -178,7 +179,7 @@ BOOL change_notify_set(char *inbuf, files_struct *fsp, connection_struct *conn, struct change_notify *cnbp; if((cnbp = (struct change_notify *)malloc(sizeof(*cnbp))) == NULL) { - DEBUG(0,("call_nt_transact_notify_change: malloc fail !\n" )); + DEBUG(0,("change_notify_set: malloc fail !\n" )); return -1; } @@ -197,6 +198,9 @@ BOOL change_notify_set(char *inbuf, files_struct *fsp, connection_struct *conn, DLIST_ADD(change_notify_list, cnbp); + /* Push the MID of this packet on the signing queue. */ + srv_defer_sign_response(SVAL(inbuf,smb_mid)); + return True; } diff --git a/source3/smbd/ntquotas.c b/source3/smbd/ntquotas.c index 2e865000ec..88d7c4e164 100644 --- a/source3/smbd/ntquotas.c +++ b/source3/smbd/ntquotas.c @@ -188,7 +188,7 @@ int vfs_get_user_ntquota_list(files_struct *fsp, SMB_NTQUOTA_LIST **qt_list) } if (vfs_get_ntquota(fsp, SMB_USER_QUOTA_TYPE, &sid, &tmp_qt)!=0) { - DEBUG(1,("no quota entry for sid[%s] path[%s]\n", + DEBUG(5,("no quota entry for sid[%s] path[%s]\n", sid_string_static(&sid),fsp->conn->connectpath)); continue; } diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index c574d9d563..3ffa6efa77 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1443,6 +1443,7 @@ int reply_ntcancel(connection_struct *conn, START_PROFILE(SMBntcancel); remove_pending_change_notify_requests_by_mid(mid); remove_pending_lock_requests_by_mid(mid); + srv_cancel_sign_response(mid); DEBUG(3,("reply_ntcancel: cancel called on mid = %d.\n", mid)); @@ -2321,6 +2322,8 @@ due to being in oplock break state.\n", (unsigned int)function_code )); dump_data(10, data, data_count); } + srv_signing_trans_start(SVAL(inbuf,smb_mid)); + if(num_data_sofar < total_data_count || num_params_sofar < total_parameter_count) { /* We need to send an interim response then receive the rest of the parameter/data bytes */ @@ -2484,6 +2487,7 @@ due to being in oplock break state.\n", (unsigned int)function_code )); SAFE_FREE(params); SAFE_FREE(data); END_PROFILE(SMBnttrans); + srv_signing_trans_stop(); return ERROR_DOS(ERRSRV,ERRerror); } @@ -2494,6 +2498,8 @@ due to being in oplock break state.\n", (unsigned int)function_code )); an error packet. */ + srv_signing_trans_stop(); + SAFE_FREE(setup); SAFE_FREE(params); SAFE_FREE(data); @@ -2504,6 +2510,7 @@ due to being in oplock break state.\n", (unsigned int)function_code )); bad_param: + srv_signing_trans_stop(); SAFE_FREE(params); SAFE_FREE(data); SAFE_FREE(setup); diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 6d03eaa29a..5f49640aa4 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -125,6 +125,7 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, directory. */ flags &= ~O_CREAT; + local_flags &= ~O_CREAT; } } @@ -166,6 +167,14 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, local_flags |= O_NONBLOCK; #endif + /* Don't create files with Microsoft wildcard characters. */ + if ((local_flags & O_CREAT) && !VALID_STAT(*psbuf) && ms_has_wild(fname)) { + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRinvalidname; + unix_ERR_ntstatus = NT_STATUS_OBJECT_NAME_INVALID; + return False; + } + /* Actually do the open */ fsp->fd = fd_open(conn, fname, local_flags, mode); if (fsp->fd == -1) { @@ -675,8 +684,8 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou dev = %x, inode = %.0f. Deleting it to continue...\n", (int)broken_entry.pid, fname, (unsigned int)dev, (double)inode)); if (process_exists(broken_entry.pid)) { - DEBUG(0,("open_mode_check: Existent process %d left active oplock.\n", - broken_entry.pid )); + DEBUG(0,("open_mode_check: Existent process %lu left active oplock.\n", + (unsigned long)broken_entry.pid )); } if (del_share_entry(dev, inode, &broken_entry, NULL) == -1) { @@ -874,7 +883,7 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ if (file_existed && (GET_FILE_OPEN_DISPOSITION(ofun) == FILE_EXISTS_TRUNCATE)) { if (!open_match_attributes(conn, fname, psbuf->st_mode, mode, &new_mode)) { DEBUG(5,("open_file_shared: attributes missmatch for file %s (0%o, 0%o)\n", - fname, psbuf->st_mode, mode )); + fname, (int)psbuf->st_mode, (int)mode )); file_free(fsp); errno = EACCES; return NULL; @@ -1290,6 +1299,15 @@ files_struct *open_directory(connection_struct *conn, char *fname, SMB_STRUCT_ST return NULL; } + if (ms_has_wild(fname)) { + file_free(fsp); + DEBUG(5,("open_directory: failing create on filename %s with wildcards\n", fname)); + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRinvalidname; + unix_ERR_ntstatus = NT_STATUS_OBJECT_NAME_INVALID; + return NULL; + } + if(vfs_MkDir(conn,fname, unix_mode(conn,aDIR, fname)) < 0) { DEBUG(2,("open_directory: unable to create %s. Error was %s\n", fname, strerror(errno) )); diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 8525687793..19e6956d9e 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -660,6 +660,7 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, unsigned long file_id, time_t start_time; BOOL shutdown_server = False; BOOL oplock_timeout = False; + BOOL sign_state; connection_struct *saved_user_conn; connection_struct *saved_fsp_conn; int saved_vuid; @@ -742,8 +743,16 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, unsigned long file_id, /* Remember if we just sent a break to level II on this file. */ fsp->sent_oplock_break = using_levelII? LEVEL_II_BREAK_SENT:EXCLUSIVE_BREAK_SENT; - if (!send_smb(smbd_server_fd(), outbuf)) + /* Save the server smb signing state. */ + sign_state = srv_oplock_set_signing(False); + + if (!send_smb(smbd_server_fd(), outbuf)) { + srv_oplock_set_signing(sign_state); exit_server("oplock_break: send_smb failed."); + } + + /* Restore the sign state to what it was. */ + srv_oplock_set_signing(sign_state); /* We need this in case a readraw crosses on the wire. */ global_oplock_break = True; @@ -791,6 +800,9 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, unsigned long file_id, } else if (smb_read_error == READ_ERROR) { DEBUG( 0, ("oplock_break: receive_smb error (%s)\n", strerror(errno)) ); shutdown_server = True; + } else if (smb_read_error == READ_BAD_SIG) { + DEBUG( 0, ("oplock_break: bad signature from client\n" )); + shutdown_server = True; } else if (smb_read_error == READ_TIMEOUT) { DEBUG( 0, ( "oplock_break: receive_smb timed out after %d seconds.\n", OPLOCK_BREAK_TIMEOUT ) ); oplock_timeout = True; diff --git a/source3/smbd/password.c b/source3/smbd/password.c index e2c143f1e2..b988f2ec74 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -29,10 +29,11 @@ static int next_vuid = VUID_OFFSET; static int num_validated_vuids; /**************************************************************************** -check if a uid has been validated, and return an pointer to the user_struct -if it has. NULL if not. vuid is biased by an offset. This allows us to -tell random client vuid's (normally zero) from valid vuids. + Check if a uid has been validated, and return an pointer to the user_struct + if it has. NULL if not. vuid is biased by an offset. This allows us to + tell random client vuid's (normally zero) from valid vuids. ****************************************************************************/ + user_struct *get_valid_user_struct(uint16 vuid) { user_struct *usp; @@ -54,8 +55,9 @@ user_struct *get_valid_user_struct(uint16 vuid) } /**************************************************************************** -invalidate a uid + Invalidate a uid. ****************************************************************************/ + void invalidate_vuid(uint16 vuid) { user_struct *vuser = get_valid_user_struct(vuid); @@ -85,8 +87,9 @@ void invalidate_vuid(uint16 vuid) } /**************************************************************************** -invalidate all vuid entries for this process + Invalidate all vuid entries for this process. ****************************************************************************/ + void invalidate_all_vuids(void) { user_struct *usp, *next=NULL; @@ -108,7 +111,7 @@ void invalidate_all_vuids(void) * */ -int register_vuid(auth_serversupplied_info *server_info, const char *smb_name) +int register_vuid(auth_serversupplied_info *server_info, DATA_BLOB response_blob, const char *smb_name) { user_struct *vuser = NULL; @@ -238,38 +241,42 @@ int register_vuid(auth_serversupplied_info *server_info, const char *smb_name) vuser->homes_snum = -1; } + if (lp_server_signing() && !vuser->guest && !srv_is_signing_active()) { + /* Try and turn on server signing on the first non-guest sessionsetup. */ + srv_set_signing(vuser->session_key, response_blob); + } + return vuser->vuid; } - /**************************************************************************** -add a name to the session users list + Add a name to the session users list. ****************************************************************************/ + void add_session_user(const char *user) { - fstring suser; - struct passwd *passwd; + fstring suser; + struct passwd *passwd; - if (!(passwd = Get_Pwnam(user))) return; + if (!(passwd = Get_Pwnam(user))) + return; - fstrcpy(suser,passwd->pw_name); + fstrcpy(suser,passwd->pw_name); - if (suser && *suser && !in_list(suser,session_users,False)) - { - if (strlen(suser) + strlen(session_users) + 2 >= sizeof(pstring)) - DEBUG(1,("Too many session users??\n")); - else - { - pstrcat(session_users," "); - pstrcat(session_users,suser); + if (suser && *suser && !in_list(suser,session_users,False)) { + if (strlen(suser) + strlen(session_users) + 2 >= sizeof(pstring)) { + DEBUG(1,("Too many session users??\n")); + } else { + pstrcat(session_users," "); + pstrcat(session_users,suser); + } } - } } - /**************************************************************************** -check if a username is valid + Check if a username is valid. ****************************************************************************/ + BOOL user_ok(const char *user,int snum, gid_t *groups, size_t n_groups) { char **valid, **invalid; @@ -308,8 +315,9 @@ BOOL user_ok(const char *user,int snum, gid_t *groups, size_t n_groups) } /**************************************************************************** -validate a group username entry. Return the username or NULL + Validate a group username entry. Return the username or NULL. ****************************************************************************/ + static char *validate_group(char *group, DATA_BLOB password,int snum) { #ifdef HAVE_NETGROUP diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 18acb35f7a..dce1c4bc03 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -53,9 +53,9 @@ extern int max_send; ****************************************************************************/ typedef struct { - ubi_slNode msg_next; - char *msg_buf; - int msg_len; + ubi_slNode msg_next; + char *msg_buf; + int msg_len; } pending_message_list; static ubi_slList smb_oplock_queue = { NULL, (ubi_slNodePtr)&smb_oplock_queue, 0}; @@ -67,29 +67,30 @@ static ubi_slList smb_oplock_queue = { NULL, (ubi_slNodePtr)&smb_oplock_queue, 0 static BOOL push_message(ubi_slList *list_head, char *buf, int msg_len) { - pending_message_list *msg = (pending_message_list *) + pending_message_list *msg = (pending_message_list *) malloc(sizeof(pending_message_list)); - if(msg == NULL) - { - DEBUG(0,("push_message: malloc fail (1)\n")); - return False; - } + if(msg == NULL) { + DEBUG(0,("push_message: malloc fail (1)\n")); + return False; + } - msg->msg_buf = (char *)malloc(msg_len); - if(msg->msg_buf == NULL) - { - DEBUG(0,("push_message: malloc fail (2)\n")); - SAFE_FREE(msg); - return False; - } + msg->msg_buf = (char *)malloc(msg_len); + if(msg->msg_buf == NULL) { + DEBUG(0,("push_message: malloc fail (2)\n")); + SAFE_FREE(msg); + return False; + } + + memcpy(msg->msg_buf, buf, msg_len); + msg->msg_len = msg_len; - memcpy(msg->msg_buf, buf, msg_len); - msg->msg_len = msg_len; + ubi_slAddTail( list_head, msg); - ubi_slAddTail( list_head, msg); + /* Push the MID of this packet on the signing queue. */ + srv_defer_sign_response(SVAL(buf,smb_mid)); - return True; + return True; } /**************************************************************************** @@ -295,28 +296,29 @@ BOOL receive_next_smb(char *inbuf, int bufsize, int timeout) void respond_to_all_remaining_local_messages(void) { - char buffer[1024]; - - /* - * Assert we have no exclusive open oplocks. - */ - - if(get_number_of_exclusive_open_oplocks()) { - DEBUG(0,("respond_to_all_remaining_local_messages: PANIC : we have %d exclusive oplocks.\n", - get_number_of_exclusive_open_oplocks() )); - return; - } - - /* - * Keep doing receive_local_message with a 1 ms timeout until - * we have no more messages. - */ - while(receive_local_message(buffer, sizeof(buffer), 1)) { - /* Deal with oplock break requests from other smbd's. */ - process_local_message(buffer, sizeof(buffer)); - } - - return; + char buffer[1024]; + + /* + * Assert we have no exclusive open oplocks. + */ + + if(get_number_of_exclusive_open_oplocks()) { + DEBUG(0,("respond_to_all_remaining_local_messages: PANIC : we have %d exclusive oplocks.\n", + get_number_of_exclusive_open_oplocks() )); + return; + } + + /* + * Keep doing receive_local_message with a 1 ms timeout until + * we have no more messages. + */ + + while(receive_local_message(buffer, sizeof(buffer), 1)) { + /* Deal with oplock break requests from other smbd's. */ + process_local_message(buffer, sizeof(buffer)); + } + + return; } @@ -339,13 +341,11 @@ force write permissions on print services. functions. Any message that has a NULL function is unimplemented - please feel free to contribute implementations! */ -static const struct smb_message_struct -{ - const char *name; - int (*fn)(connection_struct *conn, char *, char *, int, int); - int flags; -} - smb_messages[256] = { +static const struct smb_message_struct { + const char *name; + int (*fn)(connection_struct *conn, char *, char *, int, int); + int flags; +} smb_messages[256] = { /* 0x00 */ { "SMBmkdir",reply_mkdir,AS_USER | NEED_WRITE}, /* 0x01 */ { "SMBrmdir",reply_rmdir,AS_USER | NEED_WRITE}, @@ -849,67 +849,62 @@ set. Ignoring max smbd restriction.\n")); } /**************************************************************************** - process an smb from the client - split out from the smbd_process() code so - it can be used by the oplock break code. + Process an smb from the client - split out from the smbd_process() code so + it can be used by the oplock break code. ****************************************************************************/ + void process_smb(char *inbuf, char *outbuf) { - static int trans_num; - int msg_type = CVAL(inbuf,0); - int32 len = smb_len(inbuf); - int nread = len + 4; - - DO_PROFILE_INC(smb_count); - - if (trans_num == 0) { - /* on the first packet, check the global hosts allow/ hosts - deny parameters before doing any parsing of the packet - passed to us by the client. This prevents attacks on our - parsing code from hosts not in the hosts allow list */ - if (smbd_process_limit() || - !check_access(smbd_server_fd(), lp_hostsallow(-1), lp_hostsdeny(-1))) { - /* send a negative session response "not listening on calling - name" */ - static unsigned char buf[5] = {0x83, 0, 0, 1, 0x81}; - DEBUG( 1, ( "Connection denied from %s\n", - client_addr() ) ); - (void)send_smb(smbd_server_fd(),(char *)buf); - exit_server("connection denied"); - } - } - - DEBUG( 6, ( "got message type 0x%x of len 0x%x\n", msg_type, len ) ); - DEBUG( 3, ( "Transaction %d of length %d\n", trans_num, nread ) ); - - if (msg_type == 0) - show_msg(inbuf); - else if(msg_type == SMBkeepalive) - return; /* Keepalive packet. */ - - nread = construct_reply(inbuf,outbuf,nread,max_send); + static int trans_num; + int msg_type = CVAL(inbuf,0); + int32 len = smb_len(inbuf); + int nread = len + 4; + + DO_PROFILE_INC(smb_count); + + if (trans_num == 0) { + /* on the first packet, check the global hosts allow/ hosts + deny parameters before doing any parsing of the packet + passed to us by the client. This prevents attacks on our + parsing code from hosts not in the hosts allow list */ + if (smbd_process_limit() || + !check_access(smbd_server_fd(), lp_hostsallow(-1), lp_hostsdeny(-1))) { + /* send a negative session response "not listening on calling name" */ + static unsigned char buf[5] = {0x83, 0, 0, 1, 0x81}; + DEBUG( 1, ( "Connection denied from %s\n", client_addr() ) ); + (void)send_smb(smbd_server_fd(),(char *)buf); + exit_server("connection denied"); + } + } + + DEBUG( 6, ( "got message type 0x%x of len 0x%x\n", msg_type, len ) ); + DEBUG( 3, ( "Transaction %d of length %d\n", trans_num, nread ) ); + + if (msg_type == 0) + show_msg(inbuf); + else if(msg_type == SMBkeepalive) + return; /* Keepalive packet. */ + + nread = construct_reply(inbuf,outbuf,nread,max_send); - if(nread > 0) - { - if (CVAL(outbuf,0) == 0) - show_msg(outbuf); + if(nread > 0) { + if (CVAL(outbuf,0) == 0) + show_msg(outbuf); - if (nread != smb_len(outbuf) + 4) - { - DEBUG(0,("ERROR: Invalid message response size! %d %d\n", - nread, smb_len(outbuf))); - } - else - if (!send_smb(smbd_server_fd(),outbuf)) - exit_server("process_smb: send_smb failed."); - } - trans_num++; + if (nread != smb_len(outbuf) + 4) { + DEBUG(0,("ERROR: Invalid message response size! %d %d\n", + nread, smb_len(outbuf))); + } else if (!send_smb(smbd_server_fd(),outbuf)) { + exit_server("process_smb: send_smb failed."); + } + } + trans_num++; } - - /**************************************************************************** -return a string containing the function name of a SMB command + Return a string containing the function name of a SMB command. ****************************************************************************/ + const char *smb_fn_name(int type) { const char *unknown_name = "SMBunknown"; @@ -949,92 +944,94 @@ void construct_reply_common(char *inbuf,char *outbuf) } /**************************************************************************** - construct a chained reply and add it to the already made reply - **************************************************************************/ + Construct a chained reply and add it to the already made reply +****************************************************************************/ + int chain_reply(char *inbuf,char *outbuf,int size,int bufsize) { - static char *orig_inbuf; - static char *orig_outbuf; - int smb_com1, smb_com2 = CVAL(inbuf,smb_vwv0); - unsigned smb_off2 = SVAL(inbuf,smb_vwv1); - char *inbuf2, *outbuf2; - int outsize2; - char inbuf_saved[smb_wct]; - char outbuf_saved[smb_wct]; - int wct = CVAL(outbuf,smb_wct); - int outsize = smb_size + 2*wct + SVAL(outbuf,smb_vwv0+2*wct); - - /* maybe its not chained */ - if (smb_com2 == 0xFF) { - SCVAL(outbuf,smb_vwv0,0xFF); - return outsize; - } - - if (chain_size == 0) { - /* this is the first part of the chain */ - orig_inbuf = inbuf; - orig_outbuf = outbuf; - } - - /* - * The original Win95 redirector dies on a reply to - * a lockingX and read chain unless the chain reply is - * 4 byte aligned. JRA. - */ - - outsize = (outsize + 3) & ~3; - - /* we need to tell the client where the next part of the reply will be */ - SSVAL(outbuf,smb_vwv1,smb_offset(outbuf+outsize,outbuf)); - SCVAL(outbuf,smb_vwv0,smb_com2); - - /* remember how much the caller added to the chain, only counting stuff - after the parameter words */ - chain_size += outsize - smb_wct; - - /* work out pointers into the original packets. The - headers on these need to be filled in */ - inbuf2 = orig_inbuf + smb_off2 + 4 - smb_wct; - outbuf2 = orig_outbuf + SVAL(outbuf,smb_vwv1) + 4 - smb_wct; - - /* remember the original command type */ - smb_com1 = CVAL(orig_inbuf,smb_com); - - /* save the data which will be overwritten by the new headers */ - memcpy(inbuf_saved,inbuf2,smb_wct); - memcpy(outbuf_saved,outbuf2,smb_wct); - - /* give the new packet the same header as the last part of the SMB */ - memmove(inbuf2,inbuf,smb_wct); - - /* create the in buffer */ - SCVAL(inbuf2,smb_com,smb_com2); - - /* create the out buffer */ - construct_reply_common(inbuf2, outbuf2); - - DEBUG(3,("Chained message\n")); - show_msg(inbuf2); - - /* process the request */ - outsize2 = switch_message(smb_com2,inbuf2,outbuf2,size-chain_size, - bufsize-chain_size); - - /* copy the new reply and request headers over the old ones, but - preserve the smb_com field */ - memmove(orig_outbuf,outbuf2,smb_wct); - SCVAL(orig_outbuf,smb_com,smb_com1); - - /* restore the saved data, being careful not to overwrite any - data from the reply header */ - memcpy(inbuf2,inbuf_saved,smb_wct); - { - int ofs = smb_wct - PTR_DIFF(outbuf2,orig_outbuf); - if (ofs < 0) ofs = 0; - memmove(outbuf2+ofs,outbuf_saved+ofs,smb_wct-ofs); - } - - return outsize2; + static char *orig_inbuf; + static char *orig_outbuf; + int smb_com1, smb_com2 = CVAL(inbuf,smb_vwv0); + unsigned smb_off2 = SVAL(inbuf,smb_vwv1); + char *inbuf2, *outbuf2; + int outsize2; + char inbuf_saved[smb_wct]; + char outbuf_saved[smb_wct]; + int wct = CVAL(outbuf,smb_wct); + int outsize = smb_size + 2*wct + SVAL(outbuf,smb_vwv0+2*wct); + + /* maybe its not chained */ + if (smb_com2 == 0xFF) { + SCVAL(outbuf,smb_vwv0,0xFF); + return outsize; + } + + if (chain_size == 0) { + /* this is the first part of the chain */ + orig_inbuf = inbuf; + orig_outbuf = outbuf; + } + + /* + * The original Win95 redirector dies on a reply to + * a lockingX and read chain unless the chain reply is + * 4 byte aligned. JRA. + */ + + outsize = (outsize + 3) & ~3; + + /* we need to tell the client where the next part of the reply will be */ + SSVAL(outbuf,smb_vwv1,smb_offset(outbuf+outsize,outbuf)); + SCVAL(outbuf,smb_vwv0,smb_com2); + + /* remember how much the caller added to the chain, only counting stuff + after the parameter words */ + chain_size += outsize - smb_wct; + + /* work out pointers into the original packets. The + headers on these need to be filled in */ + inbuf2 = orig_inbuf + smb_off2 + 4 - smb_wct; + outbuf2 = orig_outbuf + SVAL(outbuf,smb_vwv1) + 4 - smb_wct; + + /* remember the original command type */ + smb_com1 = CVAL(orig_inbuf,smb_com); + + /* save the data which will be overwritten by the new headers */ + memcpy(inbuf_saved,inbuf2,smb_wct); + memcpy(outbuf_saved,outbuf2,smb_wct); + + /* give the new packet the same header as the last part of the SMB */ + memmove(inbuf2,inbuf,smb_wct); + + /* create the in buffer */ + SCVAL(inbuf2,smb_com,smb_com2); + + /* create the out buffer */ + construct_reply_common(inbuf2, outbuf2); + + DEBUG(3,("Chained message\n")); + show_msg(inbuf2); + + /* process the request */ + outsize2 = switch_message(smb_com2,inbuf2,outbuf2,size-chain_size, + bufsize-chain_size); + + /* copy the new reply and request headers over the old ones, but + preserve the smb_com field */ + memmove(orig_outbuf,outbuf2,smb_wct); + SCVAL(orig_outbuf,smb_com,smb_com1); + + /* restore the saved data, being careful not to overwrite any + data from the reply header */ + memcpy(inbuf2,inbuf_saved,smb_wct); + + { + int ofs = smb_wct - PTR_DIFF(outbuf2,orig_outbuf); + if (ofs < 0) ofs = 0; + memmove(outbuf2+ofs,outbuf_saved+ofs,smb_wct-ofs); + } + + return outsize2; } /**************************************************************************** @@ -1065,17 +1062,16 @@ static int setup_select_timeout(void) void check_reload(int t) { - static time_t last_smb_conf_reload_time = 0; + static time_t last_smb_conf_reload_time = 0; - if(last_smb_conf_reload_time == 0) - last_smb_conf_reload_time = t; + if(last_smb_conf_reload_time == 0) + last_smb_conf_reload_time = t; - if (reload_after_sighup || (t >= last_smb_conf_reload_time+SMBD_RELOAD_CHECK)) - { - reload_services(True); - reload_after_sighup = False; - last_smb_conf_reload_time = t; - } + if (reload_after_sighup || (t >= last_smb_conf_reload_time+SMBD_RELOAD_CHECK)) { + reload_services(True); + reload_after_sighup = False; + last_smb_conf_reload_time = t; + } } /**************************************************************************** @@ -1084,165 +1080,164 @@ void check_reload(int t) static BOOL timeout_processing(int deadtime, int *select_timeout, time_t *last_timeout_processing_time) { - static time_t last_keepalive_sent_time = 0; - static time_t last_idle_closed_check = 0; - time_t t; - BOOL allidle = True; - extern int keepalive; - - if (smb_read_error == READ_EOF) - { - DEBUG(3,("end of file from client\n")); - return False; - } - - if (smb_read_error == READ_ERROR) - { - DEBUG(3,("receive_smb error (%s) exiting\n", - strerror(errno))); - return False; - } - - *last_timeout_processing_time = t = time(NULL); - - if(last_keepalive_sent_time == 0) - last_keepalive_sent_time = t; - - if(last_idle_closed_check == 0) - last_idle_closed_check = t; - - /* become root again if waiting */ - change_to_root_user(); - - /* run all registered idle events */ - smb_run_idle_events(t); - - /* check if we need to reload services */ - check_reload(t); - - /* automatic timeout if all connections are closed */ - if (conn_num_open()==0 && (t - last_idle_closed_check) >= IDLE_CLOSED_TIMEOUT) - { - DEBUG( 2, ( "Closing idle connection\n" ) ); - return False; - } - else - last_idle_closed_check = t; - - if (keepalive && (t - last_keepalive_sent_time)>keepalive) - { - extern struct auth_context *negprot_global_auth_context; - if (!send_keepalive(smbd_server_fd())) { - DEBUG( 2, ( "Keepalive failed - exiting.\n" ) ); - return False; - } - - /* send a keepalive for a password server or the like. - This is attached to the auth_info created in the - negprot */ - if (negprot_global_auth_context - && negprot_global_auth_context->challenge_set_method - && negprot_global_auth_context->challenge_set_method->send_keepalive) { - negprot_global_auth_context->challenge_set_method->send_keepalive - (&negprot_global_auth_context->challenge_set_method->private_data); - } - - last_keepalive_sent_time = t; - } - - /* check for connection timeouts */ - allidle = conn_idle_all(t, deadtime); - - if (allidle && conn_num_open()>0) { - DEBUG(2,("Closing idle connection 2.\n")); - return False; - } - - 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; - - /* - * 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. - */ - - if (secrets_lock_trust_account_password(lp_workgroup(), True) == False) { - DEBUG(0,("process: unable to lock the machine account password for \ + static time_t last_keepalive_sent_time = 0; + static time_t last_idle_closed_check = 0; + time_t t; + BOOL allidle = True; + extern int keepalive; + + if (smb_read_error == READ_EOF) { + DEBUG(3,("timeout_processing: End of file from client (client has disconnected).\n")); + return False; + } + + if (smb_read_error == READ_ERROR) { + DEBUG(3,("timeout_processing: receive_smb error (%s) Exiting\n", + strerror(errno))); + return False; + } + + if (smb_read_error == READ_BAD_SIG) { + DEBUG(3,("timeout_processing: receive_smb error bad smb signature. Exiting\n")); + return False; + } + + *last_timeout_processing_time = t = time(NULL); + + if(last_keepalive_sent_time == 0) + last_keepalive_sent_time = t; + + if(last_idle_closed_check == 0) + last_idle_closed_check = t; + + /* become root again if waiting */ + change_to_root_user(); + + /* run all registered idle events */ + smb_run_idle_events(t); + + /* check if we need to reload services */ + check_reload(t); + + /* automatic timeout if all connections are closed */ + if (conn_num_open()==0 && (t - last_idle_closed_check) >= IDLE_CLOSED_TIMEOUT) { + DEBUG( 2, ( "Closing idle connection\n" ) ); + return False; + } else { + last_idle_closed_check = t; + } + + if (keepalive && (t - last_keepalive_sent_time)>keepalive) { + extern struct auth_context *negprot_global_auth_context; + if (!send_keepalive(smbd_server_fd())) { + DEBUG( 2, ( "Keepalive failed - exiting.\n" ) ); + return False; + } + + /* send a keepalive for a password server or the like. + This is attached to the auth_info created in the + negprot */ + if (negprot_global_auth_context && negprot_global_auth_context->challenge_set_method + && negprot_global_auth_context->challenge_set_method->send_keepalive) { + + negprot_global_auth_context->challenge_set_method->send_keepalive + (&negprot_global_auth_context->challenge_set_method->private_data); + } + + last_keepalive_sent_time = t; + } + + /* check for connection timeouts */ + allidle = conn_idle_all(t, deadtime); + + if (allidle && conn_num_open()>0) { + DEBUG(2,("Closing idle connection 2.\n")); + return False; + } + + 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; + + /* + * 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. + */ + + if (secrets_lock_trust_account_password(lp_workgroup(), True) == False) { + DEBUG(0,("process: unable to lock the machine account password for \ machine %s in domain %s.\n", global_myname(), lp_workgroup() )); - return True; - } + return True; + } - if(!secrets_fetch_trust_account_password(lp_workgroup(), - trust_passwd_hash, - &lct, NULL)) { - DEBUG(0,("process: unable to read the machine account password for \ + 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())); - secrets_lock_trust_account_password(lp_workgroup(), False); - return True; - } + secrets_lock_trust_account_password(lp_workgroup(), False); + return True; + } - /* - * Make sure someone else hasn't already done this. - */ + /* + * Make sure someone else hasn't already done this. + */ - if(t < lct + lp_machine_password_timeout()) { - global_machine_password_needs_changing = False; - secrets_lock_trust_account_password(lp_workgroup(), False); - return True; - } + if(t < lct + lp_machine_password_timeout()) { + global_machine_password_needs_changing = False; + secrets_lock_trust_account_password(lp_workgroup(), False); + return True; + } - /* always just contact the PDC here */ + /* always just contact the PDC here */ - change_trust_account_password( lp_workgroup(), NULL); - global_machine_password_needs_changing = False; - secrets_lock_trust_account_password(lp_workgroup(), False); - } - - /* - * Check to see if we have any blocking locks - * outstanding on the queue. - */ - process_blocking_lock_queue(t); - - /* update printer queue caches if necessary */ + change_trust_account_password( lp_workgroup(), NULL); + global_machine_password_needs_changing = False; + secrets_lock_trust_account_password(lp_workgroup(), False); + } + + /* + * Check to see if we have any blocking locks + * outstanding on the queue. + */ + process_blocking_lock_queue(t); + + /* update printer queue caches if necessary */ - update_monitored_printq_cache(); + update_monitored_printq_cache(); - /* - * Check to see if we have any change notifies - * outstanding on the queue. - */ - process_pending_change_notify_queue(t); + /* + * Check to see if we have any change notifies + * outstanding on the queue. + */ + process_pending_change_notify_queue(t); - /* - * Now we are root, check if the log files need pruning. - * Force a log file check. - */ - force_check_log_size(); - check_log_size(); + /* + * 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. */ + /* Send any queued printer notify message to interested smbd's. */ - print_notify_send_messages(0); + print_notify_send_messages(0); - /* - * Modify the select timeout depending upon - * what we have remaining in our queues. - */ + /* + * Modify the select timeout depending upon + * what we have remaining in our queues. + */ - *select_timeout = setup_select_timeout(); + *select_timeout = setup_select_timeout(); - return True; + return True; } /**************************************************************************** diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index e7f01ad02f..71312295f4 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -48,8 +48,6 @@ int reply_special(char *inbuf,char *outbuf) int msg_type = CVAL(inbuf,0); int msg_flags = CVAL(inbuf,1); pstring name1,name2; - - int len; char name_type = 0; static BOOL already_got_session = False; @@ -75,23 +73,16 @@ int reply_special(char *inbuf,char *outbuf) return(0); } name_extract(inbuf,4,name1); - name_extract(inbuf,4 + name_len(inbuf + 4),name2); + name_type = name_extract(inbuf,4 + name_len(inbuf + 4),name2); DEBUG(2,("netbios connect: name1=%s name2=%s\n", name1,name2)); - name1[15] = 0; - - len = strlen(name2); - if (len == 16) { - name_type = name2[15]; - name2[15] = 0; - } - set_local_machine_name(name1, True); set_remote_machine_name(name2, True); - DEBUG(2,("netbios connect: local=%s remote=%s\n", - get_local_machine_name(), get_remote_machine_name() )); + DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n", + get_local_machine_name(), get_remote_machine_name(), + name_type)); if (name_type == 'R') { /* We are being asked for a pathworks session --- @@ -1281,6 +1272,16 @@ NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name) *directory = *mask = 0; + /* We must check for wildcards in the name given + * directly by the client - before any unmangling. + * This prevents an unmangling of a UNIX name containing + * a DOS wildcard like '*' or '?' from unmangling into + * a wildcard delete which was not intended. + * FIX for #226. JRA. + */ + + has_wild = ms_has_wild(name); + rc = unix_convert(name,conn,0,&bad_path,&sbuf); p = strrchr_m(name,'/'); @@ -1305,13 +1306,12 @@ NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name) if (!rc && mangle_is_mangled(mask)) mangle_check_cache( mask ); - has_wild = ms_has_wild(mask); - if (!has_wild) { pstrcat(directory,"/"); pstrcat(directory,mask); error = can_delete(directory,conn,dirtype); - if (!NT_STATUS_IS_OK(error)) return error; + if (!NT_STATUS_IS_OK(error)) + return error; if (SMB_VFS_UNLINK(conn,directory) == 0) { count++; @@ -1338,12 +1338,15 @@ NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name) pstring fname; pstrcpy(fname,dname); - if(!mask_match(fname, mask, case_sensitive)) continue; + if(!mask_match(fname, mask, case_sensitive)) + continue; slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname); error = can_delete(fname,conn,dirtype); - if (!NT_STATUS_IS_OK(error)) continue; - if (SMB_VFS_UNLINK(conn,fname) == 0) count++; + if (!NT_STATUS_IS_OK(error)) + continue; + if (SMB_VFS_UNLINK(conn,fname) == 0) + count++; DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname)); } CloseDir(dirptr); @@ -1379,7 +1382,8 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size DEBUG(3,("reply_unlink : %s\n",name)); status = unlink_internals(conn, dirtype, name); - if (!NT_STATUS_IS_OK(status)) return ERROR_NT(status); + if (!NT_STATUS_IS_OK(status)) + return ERROR_NT(status); /* * Win2k needs a changenotify request response before it will @@ -1472,6 +1476,10 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s files_struct *fsp; START_PROFILE(SMBreadbraw); + if (srv_is_signing_active()) { + exit_server("reply_readbraw: SMB signing is active - raw reads/writes are disallowed."); + } + /* * Special check if an oplock break has been issued * and the readraw request croses on the wire, we must @@ -1870,6 +1878,10 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int outsize = 0; START_PROFILE(SMBwritebraw); + if (srv_is_signing_active()) { + exit_server("reply_readbraw: SMB signing is active - raw reads/writes are disallowed."); + } + CHECK_FSP(fsp,conn); CHECK_WRITE(fsp); @@ -2828,7 +2840,11 @@ NTSTATUS mkdir_internal(connection_struct *conn, pstring directory) int ret= -1; unix_convert(directory,conn,0,&bad_path,&sbuf); - + + if (ms_has_wild(directory)) { + return NT_STATUS_OBJECT_NAME_INVALID; + } + if (check_name(directory, conn)) ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory)); diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 18e0887071..c2855487a5 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -661,7 +661,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, #else /* the alternative is just to check the directory exists */ if (stat(conn->connectpath, &st) != 0 || !S_ISDIR(st.st_mode)) { - DEBUG(0,("'%s' is not a directory, when connecting to [%s]\n", conn->connectpath, lp_servicename(SNUM(conn)))); + DEBUG(0,("'%s' does not exist or is not a directory, when connecting to [%s]\n", conn->connectpath, lp_servicename(SNUM(conn)))); change_to_root_user(); yield_connection(conn, lp_servicename(SNUM(conn))); conn_free(conn); diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 7d77ed3071..88b442215d 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -3,7 +3,7 @@ handle SMBsessionsetup Copyright (C) Andrew Tridgell 1998-2001 Copyright (C) Andrew Bartlett 2001 - Copyright (C) Jim McDonough 2002 + Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2002 Copyright (C) Luke Howard 2003 This program is free software; you can redistribute it and/or modify @@ -62,7 +62,7 @@ static int add_signature(char *outbuf, char *p) char *start = p; fstring lanman; - snprintf( lanman, sizeof(lanman), "Samba %s", VERSION ); + fstr_sprintf( lanman, "Samba %s", VERSION ); p += srvstr_push(outbuf, p, "Unix", -1, STR_TERMINATE); p += srvstr_push(outbuf, p, lanman, -1, STR_TERMINATE); @@ -153,6 +153,7 @@ static int reply_spnego_kerberos(connection_struct *conn, uint8 session_key[16]; uint8 tok_id[2]; BOOL foreign = False; + DATA_BLOB nullblob = data_blob(NULL, 0); ZERO_STRUCT(ticket); ZERO_STRUCT(auth_data); @@ -235,7 +236,7 @@ static int reply_spnego_kerberos(connection_struct *conn, memcpy(server_info->session_key, session_key, sizeof(session_key)); /* register_vuid keeps the server info */ - sess_vuid = register_vuid(server_info, user); + sess_vuid = register_vuid(server_info, nullblob, user); free(user); @@ -250,6 +251,16 @@ static int reply_spnego_kerberos(connection_struct *conn, } SSVAL(outbuf, smb_uid, sess_vuid); + + if (!server_info->guest) { + /* We need to start the signing engine + * here but a W2K client sends the old + * "BSRSPYL " signature instead of the + * correct one. Subsequent packets will + * be correct. + */ + srv_check_sign_mac(inbuf); + } } /* wrap that up in a nice GSS-API wrapping */ @@ -275,7 +286,7 @@ static int reply_spnego_kerberos(connection_struct *conn, End the NTLMSSP exchange context if we are OK/complete fail ***************************************************************************/ -static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *outbuf, +static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *outbuf, AUTH_NTLMSSP_STATE **auth_ntlmssp_state, DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status) { @@ -294,8 +305,10 @@ static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *outbuf, if (NT_STATUS_IS_OK(nt_status)) { int sess_vuid; + DATA_BLOB nullblob = data_blob(NULL, 0); + /* register_vuid keeps the server info */ - sess_vuid = register_vuid(server_info, (*auth_ntlmssp_state)->ntlmssp_state->user); + sess_vuid = register_vuid(server_info, nullblob, (*auth_ntlmssp_state)->ntlmssp_state->user); (*auth_ntlmssp_state)->server_info = NULL; if (sess_vuid == -1) { @@ -310,6 +323,16 @@ static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *outbuf, } SSVAL(outbuf,smb_uid,sess_vuid); + + if (!server_info->guest) { + /* We need to start the signing engine + * here but a W2K client sends the old + * "BSRSPYL " signature instead of the + * correct one. Subsequent packets will + * be correct. + */ + srv_check_sign_mac(inbuf); + } } } @@ -348,16 +371,27 @@ static int reply_spnego_negotiate(connection_struct *conn, if (!parse_negTokenTarg(blob1, OIDs, &secblob)) { return ERROR_NT(NT_STATUS_LOGON_FAILURE); } + + /* only look at the first OID for determining the mechToken -- + accoirding to RFC2478, we should choose the one we want + and renegotiate, but i smell a client bug here.. + + Problem observed when connecting to a member (samba box) + of an AD domain as a user in a Samba domain. Samba member + server sent back krb5/mskrb5/ntlmssp as mechtypes, but the + client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an + NTLMSSP mechtoken. --jerry */ + if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 || + strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) { + got_kerberos = True; + } + for (i=0;OIDs[i];i++) { DEBUG(3,("Got OID %s\n", OIDs[i])); - if (strcmp(OID_KERBEROS5, OIDs[i]) == 0 || - strcmp(OID_KERBEROS5_OLD, OIDs[i]) == 0) { - got_kerberos = True; - } free(OIDs[i]); } - DEBUG(3,("Got secblob of size %d\n", secblob.length)); + DEBUG(3,("Got secblob of size %lu\n", (unsigned long)secblob.length)); #ifdef HAVE_KRB5 if (got_kerberos && (SEC_ADS == lp_security())) { @@ -382,7 +416,7 @@ static int reply_spnego_negotiate(connection_struct *conn, data_blob_free(&secblob); - reply_spnego_ntlmssp(conn, outbuf, &global_ntlmssp_state, + reply_spnego_ntlmssp(conn, inbuf, outbuf, &global_ntlmssp_state, &chal, nt_status); data_blob_free(&chal); @@ -419,7 +453,7 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf, data_blob_free(&auth); - reply_spnego_ntlmssp(conn, outbuf, &global_ntlmssp_state, + reply_spnego_ntlmssp(conn, inbuf, outbuf, &global_ntlmssp_state, &auth_reply, nt_status); data_blob_free(&auth_reply); @@ -742,7 +776,6 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, free_user_info(&user_info); data_blob_free(&lm_resp); - data_blob_free(&nt_resp); data_blob_clear_free(&plaintext_password); if (!NT_STATUS_IS_OK(nt_status)) { @@ -750,9 +783,10 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, } if (!NT_STATUS_IS_OK(nt_status)) { + data_blob_free(&nt_resp); return ERROR_NT(nt_status_squash(nt_status)); } - + /* it's ok - setup a reply */ set_message(outbuf,3,0,True); if (Protocol >= PROTOCOL_NT1) { @@ -770,12 +804,17 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, to a uid can get through without a password, on the same VC */ /* register_vuid keeps the server info */ - sess_vuid = register_vuid(server_info, sub_user); - + sess_vuid = register_vuid(server_info, nt_resp, sub_user); + data_blob_free(&nt_resp); + if (sess_vuid == -1) { return ERROR_NT(NT_STATUS_LOGON_FAILURE); } + if (!server_info->guest && !srv_check_sign_mac(inbuf)) { + exit_server("reply_sesssetup_and_X: bad smb signature"); + } + SSVAL(outbuf,smb_uid,sess_vuid); SSVAL(inbuf,smb_uid,sess_vuid); diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index 22b8a33a1e..fbebdb240f 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -98,7 +98,12 @@ void stat_cache_add( const char *full_orig_name, const char *orig_translated_pat translated_path_length--; } - original_path = strdup(full_orig_name); + if(case_sensitive) { + original_path = strdup(full_orig_name); + } else { + original_path = strdup_upper(full_orig_name); + } + if (!original_path) { SAFE_FREE(translated_path); return; @@ -111,9 +116,6 @@ void stat_cache_add( const char *full_orig_name, const char *orig_translated_pat original_path_length--; } - if(!case_sensitive) - strupper_m(original_path); - if (original_path_length != translated_path_length) { if (original_path_length < translated_path_length) { DEBUG(0, ("OOPS - tried to store stat cache entry for werid length paths [%s] %u and [%s] %u)!\n", @@ -161,6 +163,7 @@ void stat_cache_add( const char *full_orig_name, const char *orig_translated_pat } scp->original_path = scp->names; + /* pointer into the structure... */ scp->translated_path = scp->names + original_path_length + 1; safe_strcpy(scp->original_path, original_path, original_path_length); safe_strcpy(scp->translated_path, translated_path, translated_path_length); @@ -194,7 +197,7 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, char **start, SMB_STRUCT_STAT *pst) { stat_cache_entry *scp; - pstring chk_name; + char *chk_name; size_t namelen; hash_element *hash_elem; char *sp; @@ -218,10 +221,20 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, return False; } - pstrcpy(chk_name, name); + if (case_sensitive) { + chk_name = strdup(name); + if (!chk_name) { + DEBUG(0, ("stat_cache_lookup: strdup failed!\n")); + return False; + } + + } else { + chk_name = strdup_upper(name); + if (!chk_name) { + DEBUG(0, ("stat_cache_lookup: strdup_upper failed!\n")); + return False; + } - if(!case_sensitive) { - strupper_m( chk_name ); /* * In some language encodings the length changes * if we uppercase. We need to treat this differently @@ -252,11 +265,13 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, * We reached the end of the name - no match. */ DO_PROFILE_INC(statcache_misses); + SAFE_FREE(chk_name); return False; } if((*chk_name == '\0') || (strcmp(chk_name, ".") == 0) || (strcmp(chk_name, "..") == 0)) { DO_PROFILE_INC(statcache_misses); + SAFE_FREE(chk_name); return False; } } else { @@ -265,6 +280,7 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, if(SMB_VFS_STAT(conn,scp->translated_path, pst) != 0) { /* Discard this entry - it doesn't exist in the filesystem. */ hash_remove(&stat_cache, hash_elem); + SAFE_FREE(chk_name); return False; } @@ -290,6 +306,7 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, ++*start; pstrcpy(dirpath, scp->translated_path); + SAFE_FREE(chk_name); return (namelen == scp->translated_path_length); } } diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index bdcd04443e..86906fa5be 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -326,7 +326,13 @@ static BOOL exact_match(char *str,char *mask, BOOL case_sig) return False; if (case_sig) return strcmp(str,mask)==0; - return StrCaseCmp(str,mask) == 0; + if (StrCaseCmp(str,mask) != 0) { + return False; + } + if (ms_has_wild(str)) { + return False; + } + return True; } /**************************************************************************** @@ -1906,7 +1912,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, if (strequal(base_name,".")) { pstrcpy(dos_fname, "\\"); } else { - snprintf(dos_fname, sizeof(dos_fname), "\\%s", fname); + pstr_sprintf(dos_fname, "\\%s", fname); string_replace(dos_fname, '/', '\\'); } @@ -3353,6 +3359,8 @@ int reply_trans2(connection_struct *conn, memcpy( data, smb_base(inbuf) + dsoff, num_data); } + srv_signing_trans_start(SVAL(inbuf,smb_mid)); + if(num_data_sofar < total_data || num_params_sofar < total_params) { /* We need to send an interim response then receive the rest of the parameter/data bytes */ @@ -3525,6 +3533,7 @@ int reply_trans2(connection_struct *conn, SAFE_FREE(params); SAFE_FREE(data); END_PROFILE(SMBtrans2); + srv_signing_trans_stop(); return ERROR_DOS(ERRSRV,ERRerror); } @@ -3535,6 +3544,8 @@ int reply_trans2(connection_struct *conn, an error packet. */ + srv_signing_trans_stop(); + SAFE_FREE(params); SAFE_FREE(data); END_PROFILE(SMBtrans2); @@ -3544,6 +3555,7 @@ int reply_trans2(connection_struct *conn, bad_param: + srv_signing_trans_stop(); SAFE_FREE(params); SAFE_FREE(data); END_PROFILE(SMBtrans2); diff --git a/source3/smbd/utmp.c b/source3/smbd/utmp.c index 9833a11f2d..6ff2f586ba 100644 --- a/source3/smbd/utmp.c +++ b/source3/smbd/utmp.c @@ -491,8 +491,8 @@ static BOOL sys_utmp_fill(struct utmp *u, * If size limit proves troublesome, then perhaps use "ut_id_encode()". */ if (strlen(id_str) > sizeof(u->ut_line)) { - DEBUG(1,("id_str [%s] is too long for %d char utmp field\n", - id_str, sizeof(u->ut_line))); + DEBUG(1,("id_str [%s] is too long for %lu char utmp field\n", + id_str, (unsigned long)sizeof(u->ut_line))); return False; } utmp_strcpy(u->ut_line, id_str, sizeof(u->ut_line)); |