diff options
-rw-r--r-- | source3/include/proto.h | 1 | ||||
-rw-r--r-- | source3/modules/vfs_acl_common.c | 30 | ||||
-rw-r--r-- | source3/modules/vfs_acl_tdb.c | 50 | ||||
-rw-r--r-- | source3/smbd/close.c | 29 | ||||
-rw-r--r-- | source3/smbd/posix_acls.c | 32 | ||||
-rw-r--r-- | source3/smbd/reply.c | 81 | ||||
-rw-r--r-- | source3/smbd/vfs.c | 25 |
7 files changed, 91 insertions, 157 deletions
diff --git a/source3/include/proto.h b/source3/include/proto.h index c9f57b46a6..c8e4fe1916 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -7116,6 +7116,7 @@ int vfs_stat_smb_fname(struct connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf); int vfs_lstat_smb_fname(struct connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf); +NTSTATUS vfs_stat_fsp(files_struct *fsp); /* The following definitions come from torture/denytest.c */ diff --git a/source3/modules/vfs_acl_common.c b/source3/modules/vfs_acl_common.c index 5fdd2b4725..39fd2ad0ed 100644 --- a/source3/modules/vfs_acl_common.c +++ b/source3/modules/vfs_acl_common.c @@ -380,21 +380,26 @@ static NTSTATUS inherit_new_acl(vfs_handle_struct *handle, } if (!psd || psd->dacl == NULL) { - int ret; TALLOC_FREE(psd); - if (fsp && !fsp->is_directory && fsp->fh->fd != -1) { - ret = SMB_VFS_FSTAT(fsp, &smb_fname->st); + if (fsp) { + status = vfs_stat_fsp(fsp); + smb_fname->st = fsp->fsp_name->st; } else { - if (fsp && fsp->posix_open) { + int ret; + if (lp_posix_pathnames()) { ret = SMB_VFS_LSTAT(handle->conn, smb_fname); } else { ret = SMB_VFS_STAT(handle->conn, smb_fname); } + if (ret == -1) { + status = map_nt_error_from_unix(errno); + } } - if (ret == -1) { - return map_nt_error_from_unix(errno); + if (!NT_STATUS_IS_OK(status)) { + return status; } + psd = default_file_sd(ctx, &smb_fname->st); if (!psd) { return NT_STATUS_NO_MEMORY; @@ -580,23 +585,14 @@ static NTSTATUS fset_nt_acl_common(vfs_handle_struct *handle, files_struct *fsp, /* Ensure owner and group are set. */ if (!psd->owner_sid || !psd->group_sid) { - int ret; DOM_SID owner_sid, group_sid; struct security_descriptor *nc_psd = dup_sec_desc(talloc_tos(), psd); if (!nc_psd) { return NT_STATUS_OK; } - 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); - } - } else { - ret = SMB_VFS_FSTAT(fsp, &fsp->fsp_name->st); - } - if (ret == -1) { + status = vfs_stat_fsp(fsp); + if (!NT_STATUS_IS_OK(status)) { /* Lower level acl set succeeded, * so still return OK. */ return NT_STATUS_OK; diff --git a/source3/modules/vfs_acl_tdb.c b/source3/modules/vfs_acl_tdb.c index 285c58ed9d..424ecbf65b 100644 --- a/source3/modules/vfs_acl_tdb.c +++ b/source3/modules/vfs_acl_tdb.c @@ -147,24 +147,26 @@ static NTSTATUS get_acl_blob(TALLOC_CTX *ctx, TDB_DATA data; struct file_id id; struct db_context *db; - int ret = -1; + NTSTATUS status; SMB_STRUCT_STAT sbuf; SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context, return NT_STATUS_INTERNAL_DB_CORRUPTION); - if (fsp && fsp->fh->fd != -1) { - ret = SMB_VFS_FSTAT(fsp, &sbuf); + ZERO_STRUCT(sbuf); + + if (fsp) { + status = vfs_stat_fsp(fsp); + sbuf = fsp->fsp_name->st; } else { - if (fsp && fsp->posix_open) { - ret = vfs_lstat_smb_fname(handle->conn, name, &sbuf); - } else { - ret = vfs_stat_smb_fname(handle->conn, name, &sbuf); + int ret = vfs_stat_smb_fname(handle->conn, name, &sbuf); + if (ret == -1) { + status = map_nt_error_from_unix(errno); } } - if (ret == -1) { - return map_nt_error_from_unix(errno); + if (!NT_STATUS_IS_OK(status)) { + return status; } id = vfs_file_id_from_sbuf(handle->conn, &sbuf); @@ -204,7 +206,7 @@ static NTSTATUS store_acl_blob_fsp(vfs_handle_struct *handle, TDB_DATA data; struct db_context *db; struct db_record *rec; - int ret = -1; + NTSTATUS status; DEBUG(10,("store_acl_blob_fsp: storing blob length %u on file %s\n", (unsigned int)pblob->length, fsp_str_dbg(fsp))); @@ -212,18 +214,9 @@ static NTSTATUS store_acl_blob_fsp(vfs_handle_struct *handle, SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context, return NT_STATUS_INTERNAL_DB_CORRUPTION); - if (fsp->fh->fd != -1) { - ret = SMB_VFS_FSTAT(fsp, &fsp->fsp_name->st); - } else { - if (fsp->posix_open) { - ret = SMB_VFS_LSTAT(handle->conn, fsp->fsp_name); - } else { - ret = SMB_VFS_STAT(handle->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; } id = vfs_file_id_from_sbuf(handle->conn, &fsp->fsp_name->st); @@ -438,20 +431,13 @@ static int sys_acl_set_fd_tdb(vfs_handle_struct *handle, SMB_ACL_T theacl) { struct db_context *db; + NTSTATUS status; int ret; SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context, return -1); - 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); - } - } else { - ret = SMB_VFS_FSTAT(fsp, &fsp->fsp_name->st); - } - if (ret == -1) { + status = vfs_stat_fsp(fsp); + if (!NT_STATUS_IS_OK(status)) { return -1; } 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/posix_acls.c b/source3/smbd/posix_acls.c index 6b5a9af45b..32a04c51e4 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -3739,7 +3739,6 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC bool set_acl_as_root = false; bool acl_set_support = false; bool ret = false; - int sret; DEBUG(10,("set_nt_acl: called for file %s\n", fsp_str_dbg(fsp))); @@ -3753,19 +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 (fsp->posix_open) { - sret = SMB_VFS_LSTAT(fsp->conn, fsp->fsp_name); - } else { - sret = SMB_VFS_STAT(fsp->conn, fsp->fsp_name); - } - if (sret == -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); - } + status = vfs_stat_fsp(fsp); + if (!NT_STATUS_IS_OK(status)) { + return status; } /* Save the original element we check against. */ @@ -3809,18 +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 || fsp->fh->fd == -1) { - if (fsp->posix_open) { - sret = SMB_VFS_LSTAT(fsp->conn, fsp->fsp_name); - } else { - sret = SMB_VFS_STAT(fsp->conn, fsp->fsp_name); - } - } else { - sret = SMB_VFS_FSTAT(fsp, &fsp->fsp_name->st); - } - - if(sret == -1) { - 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/reply.c b/source3/smbd/reply.c index a3280cb9d4..abc316315a 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -5860,25 +5860,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 +5898,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 +5976,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 +5986,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 +6004,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 +6023,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 +6053,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 +6097,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 +7683,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/vfs.c b/source3/smbd/vfs.c index 171c803204..966742a6d0 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -1049,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 */ |