diff options
Diffstat (limited to 'source3/smbd')
-rw-r--r-- | source3/smbd/aio.c | 72 | ||||
-rw-r--r-- | source3/smbd/chgpasswd.c | 18 | ||||
-rw-r--r-- | source3/smbd/close.c | 29 | ||||
-rw-r--r-- | source3/smbd/files.c | 32 | ||||
-rw-r--r-- | source3/smbd/nttrans.c | 2 | ||||
-rw-r--r-- | source3/smbd/open.c | 2 | ||||
-rw-r--r-- | source3/smbd/posix_acls.c | 62 | ||||
-rw-r--r-- | source3/smbd/process.c | 30 | ||||
-rw-r--r-- | source3/smbd/reply.c | 94 | ||||
-rw-r--r-- | source3/smbd/service.c | 6 | ||||
-rw-r--r-- | source3/smbd/vfs.c | 38 |
11 files changed, 193 insertions, 192 deletions
diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c index c0367a5ee8..751fed168f 100644 --- a/source3/smbd/aio.c +++ b/source3/smbd/aio.c @@ -45,11 +45,11 @@ struct aio_extra { files_struct *fsp; struct smb_request *req; char *outbuf; - int (*handle_completion)(struct aio_extra *ex); + int (*handle_completion)(struct aio_extra *ex, int errcode); }; -static int handle_aio_read_complete(struct aio_extra *aio_ex); -static int handle_aio_write_complete(struct aio_extra *aio_ex); +static int handle_aio_read_complete(struct aio_extra *aio_ex, int errcode); +static int handle_aio_write_complete(struct aio_extra *aio_ex, int errcode); static int aio_extra_destructor(struct aio_extra *aio_ex) { @@ -184,6 +184,7 @@ bool schedule_aio_read_and_X(connection_struct *conn, return False; } + outstanding_aio_calls++; aio_ex->req = talloc_move(aio_ex, &req); DEBUG(10,("schedule_aio_read_and_X: scheduled aio_read for file %s, " @@ -191,7 +192,6 @@ bool schedule_aio_read_and_X(connection_struct *conn, fsp_str_dbg(fsp), (double)startpos, (unsigned int)smb_maxcnt, (unsigned int)aio_ex->req->mid )); - outstanding_aio_calls++; return True; } @@ -279,6 +279,7 @@ bool schedule_aio_write_and_X(connection_struct *conn, return False; } + outstanding_aio_calls++; aio_ex->req = talloc_move(aio_ex, &req); /* This should actually be improved to span the write. */ @@ -302,7 +303,6 @@ bool schedule_aio_write_and_X(connection_struct *conn, DEBUG(10,("schedule_aio_write_and_X: scheduled aio_write " "behind for file %s\n", fsp_str_dbg(fsp))); } - outstanding_aio_calls++; DEBUG(10,("schedule_aio_write_and_X: scheduled aio_write for file " "%s, offset %.0f, len = %u (mid = %u) " @@ -319,9 +319,8 @@ bool schedule_aio_write_and_X(connection_struct *conn, Returns errno or zero if all ok. *****************************************************************************/ -static int handle_aio_read_complete(struct aio_extra *aio_ex) +static int handle_aio_read_complete(struct aio_extra *aio_ex, int errcode) { - int ret = 0; int outsize; char *outbuf = aio_ex->outbuf; char *data = smb_buf(outbuf); @@ -333,18 +332,11 @@ static int handle_aio_read_complete(struct aio_extra *aio_ex) will return an error. Hopefully this is true.... JRA. */ - /* If errno is ECANCELED then don't return anything to the - * client. */ - if (errno == ECANCELED) { - return 0; - } - - DEBUG( 3,( "handle_aio_read_complete: file %s nread == -1. " + DEBUG( 3,( "handle_aio_read_complete: file %s nread == %d. " "Error = %s\n", - fsp_str_dbg(aio_ex->fsp), strerror(errno))); + fsp_str_dbg(aio_ex->fsp), (int)nread, strerror(errcode))); - ret = errno; - ERROR_NT(map_nt_error_from_unix(ret)); + ERROR_NT(map_nt_error_from_unix(errcode)); outsize = srv_set_message(outbuf,0,0,true); } else { outsize = srv_set_message(outbuf,12,nread,False); @@ -377,17 +369,16 @@ static int handle_aio_read_complete(struct aio_extra *aio_ex) fsp_str_dbg(aio_ex->fsp), (double)aio_ex->acb.aio_offset, (unsigned int)nread )); - return ret; + return errcode; } /**************************************************************************** Complete the write and return the data or error back to the client. - Returns errno or zero if all ok. + Returns error code or zero if all ok. *****************************************************************************/ -static int handle_aio_write_complete(struct aio_extra *aio_ex) +static int handle_aio_write_complete(struct aio_extra *aio_ex, int errcode) { - int ret = 0; files_struct *fsp = aio_ex->fsp; char *outbuf = aio_ex->outbuf; ssize_t numtowrite = aio_ex->acb.aio_nbytes; @@ -399,8 +390,7 @@ static int handle_aio_write_complete(struct aio_extra *aio_ex) DEBUG(5,("handle_aio_write_complete: " "aio_write_behind failed ! File %s " "is corrupt ! Error %s\n", - fsp_str_dbg(fsp), strerror(errno))); - ret = errno; + fsp_str_dbg(fsp), strerror(errcode))); } else { DEBUG(0,("handle_aio_write_complete: " "aio_write_behind failed ! File %s " @@ -408,13 +398,14 @@ static int handle_aio_write_complete(struct aio_extra *aio_ex) "only wrote %d\n", fsp_str_dbg(fsp), (unsigned int)numtowrite, (int)nwritten )); - ret = EIO; + errcode = EIO; } } else { DEBUG(10,("handle_aio_write_complete: " "aio_write_behind completed for file %s\n", fsp_str_dbg(fsp))); } + /* TODO: should no return 0 in case of an error !!! */ return 0; } @@ -425,16 +416,9 @@ static int handle_aio_write_complete(struct aio_extra *aio_ex) DEBUG( 3,( "handle_aio_write: file %s wanted %u bytes. " "nwritten == %d. Error = %s\n", fsp_str_dbg(fsp), (unsigned int)numtowrite, - (int)nwritten, strerror(errno) )); + (int)nwritten, strerror(errcode) )); - /* If errno is ECANCELED then don't return anything to the - * client. */ - if (errno == ECANCELED) { - return 0; - } - - ret = errno; - ERROR_BOTH(map_nt_error_from_unix(ret), ERRHRD, ERRdiskfull); + ERROR_NT(map_nt_error_from_unix(errcode)); srv_set_message(outbuf,0,0,true); } else { bool write_through = BITSETW(aio_ex->req->vwv+7,0); @@ -451,8 +435,8 @@ static int handle_aio_write_complete(struct aio_extra *aio_ex) fsp->fnum, (int)numtowrite, (int)nwritten)); status = sync_file(fsp->conn,fsp, write_through); if (!NT_STATUS_IS_OK(status)) { - ret = errno; - ERROR_BOTH(map_nt_error_from_unix(ret), + errcode = errno; + ERROR_BOTH(map_nt_error_from_unix(errcode), ERRHRD, ERRdiskfull); srv_set_message(outbuf,0,0,true); DEBUG(5,("handle_aio_write: sync_file for %s returned %s\n", @@ -475,7 +459,7 @@ static int handle_aio_write_complete(struct aio_extra *aio_ex) fsp_str_dbg(fsp), (double)aio_ex->acb.aio_offset, (unsigned int)numtowrite, (unsigned int)nwritten )); - return ret; + return errcode; } /**************************************************************************** @@ -493,14 +477,21 @@ static bool handle_aio_completed(struct aio_extra *aio_ex, int *perr) } /* Ensure the operation has really completed. */ - if (SMB_VFS_AIO_ERROR(aio_ex->fsp, &aio_ex->acb) == EINPROGRESS) { + err = SMB_VFS_AIO_ERROR(aio_ex->fsp, &aio_ex->acb); + if (err == EINPROGRESS) { DEBUG(10,( "handle_aio_completed: operation mid %u still in " "process for file %s\n", aio_ex->req->mid, fsp_str_dbg(aio_ex->fsp))); return False; - } + } else if (err == ECANCELED) { + /* If error is ECANCELED then don't return anything to the + * client. */ + DEBUG(10,( "handle_aio_completed: operation mid %u" + " canceled\n", aio_ex->req->mid)); + return True; + } - err = aio_ex->handle_completion(aio_ex); + err = aio_ex->handle_completion(aio_ex, err); if (err) { *perr = err; /* Only save non-zero errors. */ } @@ -510,7 +501,6 @@ static bool handle_aio_completed(struct aio_extra *aio_ex, int *perr) /**************************************************************************** Handle any aio completion inline. - Returns non-zero errno if fail or zero if all ok. *****************************************************************************/ void smbd_aio_complete_mid(unsigned int mid) @@ -519,6 +509,8 @@ void smbd_aio_complete_mid(unsigned int mid) struct aio_extra *aio_ex = find_aio_ex(mid); int ret = 0; + outstanding_aio_calls--; + DEBUG(10,("smbd_aio_complete_mid: mid[%u]\n", mid)); if (!aio_ex) { diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index eaee3d8509..e2069060aa 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -778,7 +778,7 @@ NTSTATUS pass_oem_change(char *user, const uchar old_lm_hash_encrypted[16], uchar password_encrypted_with_nt_hash[516], const uchar old_nt_hash_encrypted[16], - uint32 *reject_reason) + enum samPwdChangeReason *reject_reason) { char *new_passwd = NULL; struct samu *sampass = NULL; @@ -1081,7 +1081,7 @@ static bool check_passwd_history(struct samu *sampass, const char *plaintext) is correct before calling. JRA. ************************************************************/ -NTSTATUS change_oem_password(struct samu *hnd, char *old_passwd, char *new_passwd, bool as_root, uint32 *samr_reject_reason) +NTSTATUS change_oem_password(struct samu *hnd, char *old_passwd, char *new_passwd, bool as_root, enum samPwdChangeReason *samr_reject_reason) { uint32 min_len; uint32 refuse; @@ -1091,14 +1091,14 @@ NTSTATUS change_oem_password(struct samu *hnd, char *old_passwd, char *new_passw time_t can_change_time = pdb_get_pass_can_change_time(hnd); if (samr_reject_reason) { - *samr_reject_reason = Undefined; + *samr_reject_reason = SAM_PWD_CHANGE_NO_ERROR; } /* check to see if the secdesc has previously been set to disallow */ if (!pdb_get_pass_can_change(hnd)) { DEBUG(1, ("user %s does not have permissions to change password\n", username)); if (samr_reject_reason) { - *samr_reject_reason = SAMR_REJECT_OTHER; + *samr_reject_reason = SAM_PWD_CHANGE_NO_ERROR; } return NT_STATUS_ACCOUNT_RESTRICTION; } @@ -1112,7 +1112,7 @@ NTSTATUS change_oem_password(struct samu *hnd, char *old_passwd, char *new_passw "denied by Refuse Machine Password Change policy\n", username)); if (samr_reject_reason) { - *samr_reject_reason = SAMR_REJECT_OTHER; + *samr_reject_reason = SAM_PWD_CHANGE_NO_ERROR; } return NT_STATUS_ACCOUNT_RESTRICTION; } @@ -1125,7 +1125,7 @@ NTSTATUS change_oem_password(struct samu *hnd, char *old_passwd, char *new_passw "wait until %s\n", username, http_timestring(tosctx, can_change_time))); if (samr_reject_reason) { - *samr_reject_reason = SAMR_REJECT_OTHER; + *samr_reject_reason = SAM_PWD_CHANGE_NO_ERROR; } return NT_STATUS_ACCOUNT_RESTRICTION; } @@ -1135,7 +1135,7 @@ NTSTATUS change_oem_password(struct samu *hnd, char *old_passwd, char *new_passw username)); DEBUGADD(1, (" account policy min password len = %d\n", min_len)); if (samr_reject_reason) { - *samr_reject_reason = SAMR_REJECT_TOO_SHORT; + *samr_reject_reason = SAM_PWD_CHANGE_PASSWORD_TOO_SHORT; } return NT_STATUS_PASSWORD_RESTRICTION; /* return NT_STATUS_PWD_TOO_SHORT; */ @@ -1143,7 +1143,7 @@ NTSTATUS change_oem_password(struct samu *hnd, char *old_passwd, char *new_passw if (check_passwd_history(hnd,new_passwd)) { if (samr_reject_reason) { - *samr_reject_reason = SAMR_REJECT_IN_HISTORY; + *samr_reject_reason = SAM_PWD_CHANGE_PWD_IN_HISTORY; } return NT_STATUS_PASSWORD_RESTRICTION; } @@ -1171,7 +1171,7 @@ NTSTATUS change_oem_password(struct samu *hnd, char *old_passwd, char *new_passw if (check_ret != 0) { DEBUG(1, ("change_oem_password: check password script said new password is not good enough!\n")); if (samr_reject_reason) { - *samr_reject_reason = SAMR_REJECT_COMPLEXITY; + *samr_reject_reason = SAM_PWD_CHANGE_NOT_COMPLEX; } TALLOC_FREE(pass); return NT_STATUS_PASSWORD_RESTRICTION; diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 1f2e4604c2..642864f27e 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -271,7 +271,7 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp, bool changed_user = false; struct share_mode_lock *lck = NULL; NTSTATUS status = NT_STATUS_OK; - int ret; + NTSTATUS tmp_status; struct file_id id; /* @@ -387,16 +387,11 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp, /* We can only delete the file if the name we have is still valid and hasn't been renamed. */ - if (fsp->posix_open) { - ret = SMB_VFS_LSTAT(conn, fsp->fsp_name); - } else { - ret = SMB_VFS_STAT(conn, fsp->fsp_name); - } - - if (ret != 0) { + tmp_status = vfs_stat_fsp(fsp); + if (!NT_STATUS_IS_OK(tmp_status)) { DEBUG(5,("close_remove_share_mode: file %s. Delete on close " "was set and stat failed with error %s\n", - fsp_str_dbg(fsp), strerror(errno))); + fsp_str_dbg(fsp), nt_errstr(tmp_status))); /* * Don't save the errno here, we ignore this error */ @@ -494,7 +489,6 @@ static NTSTATUS update_write_time_on_close(struct files_struct *fsp) { struct smb_file_time ft; NTSTATUS status; - int ret = -1; ZERO_STRUCT(ft); @@ -507,18 +501,9 @@ static NTSTATUS update_write_time_on_close(struct files_struct *fsp) } /* Ensure we have a valid stat struct for the source. */ - if (fsp->fh->fd != -1) { - ret = SMB_VFS_FSTAT(fsp, &fsp->fsp_name->st); - } else { - if (fsp->posix_open) { - ret = SMB_VFS_LSTAT(fsp->conn, fsp->fsp_name); - } else { - ret = SMB_VFS_STAT(fsp->conn, fsp->fsp_name); - } - } - - if (ret == -1) { - return map_nt_error_from_unix(errno); + status = vfs_stat_fsp(fsp); + if (!NT_STATUS_IS_OK(status)) { + return status; } if (!VALID_STAT(fsp->fsp_name->st)) { diff --git a/source3/smbd/files.c b/source3/smbd/files.c index 146d809738..2bc5ba6816 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -405,14 +405,13 @@ bool file_find_subpath(files_struct *dir_fsp) files_struct *fsp; size_t dlen; char *d_fullname = NULL; - bool ret = false; d_fullname = talloc_asprintf(talloc_tos(), "%s/%s", dir_fsp->conn->connectpath, dir_fsp->fsp_name->base_name); if (!d_fullname) { - goto out; + return false; } dlen = strlen(d_fullname); @@ -429,28 +428,21 @@ bool file_find_subpath(files_struct *dir_fsp) fsp->conn->connectpath, fsp->fsp_name->base_name); - if (strnequal(d_fullname, d1_fullname, dlen)) { - int d1_len = strlen(d1_fullname); - - /* - * If the open file is a second file handle to the - * same name or is a stream on the original file, then - * don't return true. - */ - if (d1_len == dlen) { - TALLOC_FREE(d1_fullname); - continue; - } - + /* + * If the open file has a path that is a longer + * component, then it's a subpath. + */ + if (strnequal(d_fullname, d1_fullname, dlen) && + (d1_fullname[dlen] == '/')) { TALLOC_FREE(d1_fullname); - ret = true; - goto out; + TALLOC_FREE(d_fullname); + return true; } TALLOC_FREE(d1_fullname); - } - out: + } + TALLOC_FREE(d_fullname); - return ret; + return false; } /**************************************************************************** diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index cf955d9651..0cc05dbd52 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -2036,7 +2036,7 @@ static void call_nt_transact_ioctl(connection_struct *conn, } /* needed_data_count 4 bytes */ - SIVAL(pdata,8,labels_data_count); + SIVAL(pdata, 8, labels_data_count+4); cur_pdata+=12; diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 492164ceee..85b7d9106d 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -2091,7 +2091,7 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn, note that GPFS supports it as well - jmcd */ if (fsp->fh->fd != -1) { - ret_flock = SMB_VFS_KERNEL_FLOCK(fsp, share_access); + ret_flock = SMB_VFS_KERNEL_FLOCK(fsp, share_access, access_mask); if(ret_flock == -1 ){ TALLOC_FREE(lck); diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index b61421dc8f..32a04c51e4 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -3377,6 +3377,7 @@ NTSTATUS posix_get_nt_acl(struct connection_struct *conn, const char *name, struct pai_val *pal; struct smb_filename *smb_fname = NULL; NTSTATUS status; + int ret; *ppdesc = NULL; @@ -3389,7 +3390,13 @@ NTSTATUS posix_get_nt_acl(struct connection_struct *conn, const char *name, } /* Get the stat struct for the owner info. */ - if(SMB_VFS_STAT(conn, smb_fname) != 0) { + if (lp_posix_pathnames()) { + ret = SMB_VFS_LSTAT(conn, smb_fname); + } else { + ret = SMB_VFS_STAT(conn, smb_fname); + } + + if (ret == -1) { status = map_nt_error_from_unix(errno); goto out; } @@ -3435,7 +3442,12 @@ int try_chown(connection_struct *conn, struct smb_filename *smb_fname, /* Case (1). */ /* try the direct way first */ - ret = SMB_VFS_CHOWN(conn, smb_fname->base_name, uid, gid); + if (lp_posix_pathnames()) { + ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name, uid, gid); + } else { + ret = SMB_VFS_CHOWN(conn, smb_fname->base_name, uid, gid); + } + if (ret == 0) return 0; @@ -3454,8 +3466,13 @@ int try_chown(connection_struct *conn, struct smb_filename *smb_fname, become_root(); /* Keep the current file gid the same - take ownership doesn't imply group change. */ - ret = SMB_VFS_CHOWN(conn, smb_fname->base_name, uid, - (gid_t)-1); + if (lp_posix_pathnames()) { + ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name, uid, + (gid_t)-1); + } else { + ret = SMB_VFS_CHOWN(conn, smb_fname->base_name, uid, + (gid_t)-1); + } unbecome_root(); return ret; } @@ -3476,7 +3493,13 @@ int try_chown(connection_struct *conn, struct smb_filename *smb_fname, return -1; } - if (SMB_VFS_STAT(conn, smb_fname)) { + if (lp_posix_pathnames()) { + ret = SMB_VFS_LSTAT(conn, smb_fname); + } else { + ret = SMB_VFS_STAT(conn, smb_fname); + } + + if (ret == -1) { return -1; } @@ -3729,14 +3752,9 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC * Get the current state of the file. */ - if(fsp->is_directory || fsp->fh->fd == -1) { - if(SMB_VFS_STAT(fsp->conn, fsp->fsp_name) != 0) { - return map_nt_error_from_unix(errno); - } - } else { - if(SMB_VFS_FSTAT(fsp, &fsp->fsp_name->st) != 0) { - return map_nt_error_from_unix(errno); - } + status = vfs_stat_fsp(fsp); + if (!NT_STATUS_IS_OK(status)) { + return status; } /* Save the original element we check against. */ @@ -3780,21 +3798,9 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC * (suid/sgid bits, for instance) */ - if(fsp->is_directory) { - if(SMB_VFS_STAT(fsp->conn, fsp->fsp_name) != 0) { - return map_nt_error_from_unix(errno); - } - } else { - - int sret; - - if(fsp->fh->fd == -1) - sret = SMB_VFS_STAT(fsp->conn, fsp->fsp_name); - else - sret = SMB_VFS_FSTAT(fsp, &fsp->fsp_name->st); - - if(sret != 0) - return map_nt_error_from_unix(errno); + status = vfs_stat_fsp(fsp); + if (!NT_STATUS_IS_OK(status)) { + return status; } /* Save the original element we check against. */ diff --git a/source3/smbd/process.c b/source3/smbd/process.c index ccb7f9dce3..fbaa9dee29 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -417,6 +417,7 @@ static void smbd_deferred_open_timer(struct event_context *ev, struct pending_message_list *msg = talloc_get_type(private_data, struct pending_message_list); TALLOC_CTX *mem_ctx = talloc_tos(); + uint16_t mid = SVAL(msg->buf.data,smb_mid); uint8_t *inbuf; inbuf = (uint8_t *)talloc_memdup(mem_ctx, msg->buf.data, @@ -429,11 +430,21 @@ static void smbd_deferred_open_timer(struct event_context *ev, /* We leave this message on the queue so the open code can know this is a retry. */ DEBUG(5,("smbd_deferred_open_timer: trigger mid %u.\n", - (unsigned int)SVAL(msg->buf.data,smb_mid))); + (unsigned int)mid )); + + /* Mark the message as processed so this is not + * re-processed in error. */ + msg->processed = true; process_smb(smbd_server_conn, inbuf, msg->buf.length, 0, msg->seqnum, msg->encrypted, &msg->pcd); + + /* If it's still there and was processed, remove it. */ + msg = get_open_deferred_message(mid); + if (msg && msg->processed) { + remove_deferred_open_smb_message(mid); + } } /**************************************************************************** @@ -466,6 +477,7 @@ static bool push_queued_message(struct smb_request *req, msg->request_time = request_time; msg->seqnum = req->seqnum; msg->encrypted = req->encrypted; + msg->processed = false; SMB_PERFCOUNT_DEFER_OP(&req->pcd, &msg->pcd); if (private_data) { @@ -507,7 +519,7 @@ void remove_deferred_open_smb_message(uint16 mid) for (pml = deferred_open_queue; pml; pml = pml->next) { if (mid == SVAL(pml->buf.data,smb_mid)) { - DEBUG(10,("remove_sharing_violation_open_smb_message: " + DEBUG(10,("remove_deferred_open_smb_message: " "deleting mid %u len %u\n", (unsigned int)mid, (unsigned int)pml->buf.length )); @@ -537,6 +549,15 @@ void schedule_deferred_open_smb_message(uint16 mid) if (mid == msg_mid) { struct timed_event *te; + if (pml->processed) { + /* A processed message should not be + * rescheduled. */ + DEBUG(0,("schedule_deferred_open_smb_message: LOGIC ERROR " + "message mid %u was already processed\n", + msg_mid )); + continue; + } + DEBUG(10,("schedule_deferred_open_smb_message: scheduling mid %u\n", mid )); @@ -563,7 +584,7 @@ void schedule_deferred_open_smb_message(uint16 mid) } /**************************************************************************** - Return true if this mid is on the deferred queue. + Return true if this mid is on the deferred queue and was not yet processed. ****************************************************************************/ bool open_was_deferred(uint16 mid) @@ -571,7 +592,7 @@ bool open_was_deferred(uint16 mid) struct pending_message_list *pml; for (pml = deferred_open_queue; pml; pml = pml->next) { - if (SVAL(pml->buf.data,smb_mid) == mid) { + if (SVAL(pml->buf.data,smb_mid) == mid && !pml->processed) { return True; } } @@ -1309,7 +1330,6 @@ static connection_struct *switch_message(uint8 type, struct smb_request *req, in DEBUG(0, ("Error: Could not change to user. Removing " "deferred open, mid=%d.\n", req->mid)); reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRbaduid)); - remove_deferred_open_smb_message(req->mid); return conn; } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index a3280cb9d4..2365ed1da1 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2383,6 +2383,8 @@ static NTSTATUS do_unlink(connection_struct *conn, files_struct *fsp; uint32 dirtype_orig = dirtype; NTSTATUS status; + int ret; + bool posix_paths = lp_posix_pathnames(); DEBUG(10,("do_unlink: %s, dirtype = %d\n", smb_fname_str_dbg(smb_fname), @@ -2392,7 +2394,12 @@ static NTSTATUS do_unlink(connection_struct *conn, return NT_STATUS_MEDIA_WRITE_PROTECTED; } - if (SMB_VFS_LSTAT(conn, smb_fname) != 0) { + if (posix_paths) { + ret = SMB_VFS_LSTAT(conn, smb_fname); + } else { + ret = SMB_VFS_LSTAT(conn, smb_fname); + } + if (ret != 0) { return map_nt_error_from_unix(errno); } @@ -2479,7 +2486,9 @@ static NTSTATUS do_unlink(connection_struct *conn, FILE_SHARE_NONE, /* share_access */ FILE_OPEN, /* create_disposition*/ FILE_NON_DIRECTORY_FILE, /* create_options */ - FILE_ATTRIBUTE_NORMAL, /* file_attributes */ + /* file_attributes */ + posix_paths ? FILE_FLAG_POSIX_SEMANTICS|0777 : + FILE_ATTRIBUTE_NORMAL, 0, /* oplock_request */ 0, /* allocation_size */ NULL, /* sd */ @@ -5860,25 +5869,17 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, bool replace_if_exists) { TALLOC_CTX *ctx = talloc_tos(); - struct smb_filename *smb_fname_src = NULL; struct smb_filename *smb_fname_dst = NULL; - SMB_STRUCT_STAT sbuf; NTSTATUS status = NT_STATUS_OK; struct share_mode_lock *lck = NULL; bool dst_exists, old_is_stream, new_is_stream; - ZERO_STRUCT(sbuf); - status = check_name(conn, smb_fname_dst_in->base_name); if (!NT_STATUS_IS_OK(status)) { return status; } - /* Make a copy of the src and dst smb_fname structs */ - status = copy_smb_filename(ctx, fsp->fsp_name, &smb_fname_src); - if (!NT_STATUS_IS_OK(status)) { - goto out; - } + /* Make a copy of the dst smb_fname structs */ status = copy_smb_filename(ctx, smb_fname_dst_in, &smb_fname_dst); if (!NT_STATUS_IS_OK(status)) { @@ -5906,8 +5907,8 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, * filename). */ if((conn->case_sensitive == False) && (conn->case_preserve == True) && - strequal(smb_fname_src->base_name, smb_fname_dst->base_name) && - strequal(smb_fname_src->stream_name, smb_fname_dst->stream_name)) { + strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) && + strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) { char *last_slash; char *fname_dst_lcomp_base_mod = NULL; struct smb_filename *smb_fname_orig_lcomp = NULL; @@ -5984,8 +5985,8 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, * don't do the rename, just return success. */ - if (strcsequal(smb_fname_src->base_name, smb_fname_dst->base_name) && - strcsequal(smb_fname_src->stream_name, + if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) && + strcsequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) { DEBUG(3, ("rename_internals_fsp: identical names in rename %s " "- returning success\n", @@ -5994,7 +5995,7 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, goto out; } - old_is_stream = is_ntfs_stream_smb_fname(smb_fname_src); + old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name); new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst); /* Return the correct error code if both names aren't streams. */ @@ -6012,7 +6013,7 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, if(!replace_if_exists && dst_exists) { DEBUG(3, ("rename_internals_fsp: dest exists doing rename " - "%s -> %s\n", smb_fname_str_dbg(smb_fname_src), + "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name), smb_fname_str_dbg(smb_fname_dst))); status = NT_STATUS_OBJECT_NAME_COLLISION; goto out; @@ -6031,38 +6032,23 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, } /* Ensure we have a valid stat struct for the source. */ - if (fsp->fh->fd != -1) { - if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) { - status = map_nt_error_from_unix(errno); - goto out; - } - } else { - int ret = -1; - if (fsp->posix_open) { - ret = SMB_VFS_LSTAT(conn, smb_fname_src); - } else { - - ret = SMB_VFS_STAT(conn, smb_fname_src); - } - if (ret == -1) { - status = map_nt_error_from_unix(errno); - goto out; - } - sbuf = smb_fname_src->st; + status = vfs_stat_fsp(fsp); + if (!NT_STATUS_IS_OK(status)) { + goto out; } - status = can_rename(conn, fsp, attrs, &sbuf); + status = can_rename(conn, fsp, attrs, &fsp->fsp_name->st); if (!NT_STATUS_IS_OK(status)) { DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n", - nt_errstr(status), smb_fname_str_dbg(smb_fname_src), + nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name), smb_fname_str_dbg(smb_fname_dst))); if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION)) status = NT_STATUS_ACCESS_DENIED; goto out; } - if (rename_path_prefix_equal(smb_fname_src, smb_fname_dst)) { + if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) { status = NT_STATUS_ACCESS_DENIED; } @@ -6076,14 +6062,14 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, SMB_ASSERT(lck != NULL); - if(SMB_VFS_RENAME(conn, smb_fname_src, smb_fname_dst) == 0) { + if(SMB_VFS_RENAME(conn, fsp->fsp_name, smb_fname_dst) == 0) { uint32 create_options = fsp->fh->private_options; DEBUG(3, ("rename_internals_fsp: succeeded doing rename on " - "%s -> %s\n", smb_fname_str_dbg(smb_fname_src), + "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name), smb_fname_str_dbg(smb_fname_dst))); - notify_rename(conn, fsp->is_directory, smb_fname_src, + notify_rename(conn, fsp->is_directory, fsp->fsp_name, smb_fname_dst); rename_open_files(conn, lck, smb_fname_dst); @@ -6120,11 +6106,10 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, } DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n", - nt_errstr(status), smb_fname_str_dbg(smb_fname_src), + nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name), smb_fname_str_dbg(smb_fname_dst))); out: - TALLOC_FREE(smb_fname_src); TALLOC_FREE(smb_fname_dst); return status; @@ -7707,25 +7692,10 @@ void reply_setattrE(struct smb_request *req) */ /* Ensure we have a valid stat struct for the source. */ - if (fsp->fh->fd != -1) { - if (SMB_VFS_FSTAT(fsp, &fsp->fsp_name->st) == -1) { - status = map_nt_error_from_unix(errno); - reply_nterror(req, status); - goto out; - } - } else { - int ret = -1; - - if (fsp->posix_open) { - ret = SMB_VFS_LSTAT(conn, fsp->fsp_name); - } else { - ret = SMB_VFS_STAT(conn, fsp->fsp_name); - } - if (ret == -1) { - status = map_nt_error_from_unix(errno); - reply_nterror(req, status); - goto out; - } + status = vfs_stat_fsp(fsp); + if (!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); + goto out; } status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true); diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 3520f0d411..b5946f0335 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -56,6 +56,10 @@ bool set_conn_connectpath(connection_struct *conn, const char *connectpath) const char *s = connectpath; bool start_of_name_component = true; + if (connectpath == NULL || connectpath[0] == '\0') { + return false; + } + destname = SMB_STRDUP(connectpath); if (!destname) { return false; @@ -259,7 +263,7 @@ int add_home_service(const char *service, const char *username, const char *home { int iHomeService; - if (!service || !homedir) + if (!service || !homedir || homedir[0] == '\0') return -1; if ((iHomeService = lp_servicenumber(HOMES_NAME)) < 0) { diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 9b2df42c58..35e4f3f986 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -1008,7 +1008,12 @@ int vfs_stat_smb_fname(struct connection_struct *conn, const char *fname, return -1; } - ret = SMB_VFS_STAT(conn, smb_fname); + if (lp_posix_pathnames()) { + ret = SMB_VFS_LSTAT(conn, smb_fname); + } else { + ret = SMB_VFS_STAT(conn, smb_fname); + } + if (ret != -1) { *psbuf = smb_fname->st; } @@ -1044,6 +1049,31 @@ int vfs_lstat_smb_fname(struct connection_struct *conn, const char *fname, return ret; } +/** + * Ensure LSTAT is called for POSIX paths. + */ + +NTSTATUS vfs_stat_fsp(files_struct *fsp) +{ + int ret; + + if(fsp->is_directory || fsp->fh->fd == -1) { + if (fsp->posix_open) { + ret = SMB_VFS_LSTAT(fsp->conn, fsp->fsp_name); + } else { + ret = SMB_VFS_STAT(fsp->conn, fsp->fsp_name); + } + if (ret == -1) { + return map_nt_error_from_unix(errno); + } + } else { + if(SMB_VFS_FSTAT(fsp, &fsp->fsp_name->st) != 0) { + return map_nt_error_from_unix(errno); + } + } + return NT_STATUS_OK; +} + /* generate a file_id from a stat structure */ @@ -1387,10 +1417,12 @@ int smb_vfs_call_ftruncate(struct vfs_handle_struct *handle, } int smb_vfs_call_kernel_flock(struct vfs_handle_struct *handle, - struct files_struct *fsp, uint32 share_mode) + struct files_struct *fsp, uint32 share_mode, + uint32_t access_mask) { VFS_FIND(kernel_flock); - return handle->fns->kernel_flock(handle, fsp, share_mode); + return handle->fns->kernel_flock(handle, fsp, share_mode, + access_mask); } int smb_vfs_call_linux_setlease(struct vfs_handle_struct *handle, |