summaryrefslogtreecommitdiff
path: root/source3/smbd
diff options
context:
space:
mode:
Diffstat (limited to 'source3/smbd')
-rw-r--r--source3/smbd/aio.c72
-rw-r--r--source3/smbd/chgpasswd.c18
-rw-r--r--source3/smbd/close.c29
-rw-r--r--source3/smbd/files.c32
-rw-r--r--source3/smbd/nttrans.c2
-rw-r--r--source3/smbd/open.c2
-rw-r--r--source3/smbd/posix_acls.c62
-rw-r--r--source3/smbd/process.c30
-rw-r--r--source3/smbd/reply.c94
-rw-r--r--source3/smbd/service.c6
-rw-r--r--source3/smbd/vfs.c38
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,