From 56ac1efc700a4cd5a5326f845bd5dd9e0f560710 Mon Sep 17 00:00:00 2001 From: David Mulder Date: Thu, 17 Mar 2022 11:10:51 -0600 Subject: [PATCH] smbd: Move unlink_internals to smb2_reply.c Signed-off-by: David Mulder Reviewed-by: Jeremy Allison --- source3/smbd/proto.h | 8 +-- source3/smbd/reply.c | 148 -------------------------------------- source3/smbd/smb2_reply.c | 148 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 152 insertions(+), 152 deletions(-) diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h index f791ad5dad9..a9500064292 100644 --- a/source3/smbd/proto.h +++ b/source3/smbd/proto.h @@ -927,10 +927,6 @@ void reply_open_and_X(struct smb_request *req); void reply_ulogoffX(struct smb_request *req); void reply_mknew(struct smb_request *req); void reply_ctemp(struct smb_request *req); -NTSTATUS unlink_internals(connection_struct *conn, - struct smb_request *req, - uint32_t dirtype, - struct smb_filename *smb_fname); void reply_unlink(struct smb_request *req); ssize_t fake_sendfile(struct smbXsrv_connection *xconn, files_struct *fsp, off_t startpos, size_t nread); @@ -1036,6 +1032,10 @@ bool check_fsp(connection_struct *conn, struct smb_request *req, bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req, files_struct *fsp); void reply_special(struct smbXsrv_connection *xconn, char *inbuf, size_t inbuf_size); +NTSTATUS unlink_internals(connection_struct *conn, + struct smb_request *req, + uint32_t dirtype, + struct smb_filename *smb_fname); /* The following definitions come from smbd/seal.c */ diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index dc06d467cf7..757133320d0 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2361,154 +2361,6 @@ static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp, return NT_STATUS_ACCESS_DENIED; } -/******************************************************************* - * unlink a file with all relevant access checks - *******************************************************************/ - -NTSTATUS unlink_internals(connection_struct *conn, - struct smb_request *req, - uint32_t dirtype, - struct smb_filename *smb_fname) -{ - uint32_t fattr; - files_struct *fsp; - uint32_t dirtype_orig = dirtype; - NTSTATUS status; - int ret; - struct smb2_create_blobs *posx = NULL; - - if (dirtype == 0) { - dirtype = FILE_ATTRIBUTE_NORMAL; - } - - DBG_DEBUG("%s, dirtype = %d\n", - smb_fname_str_dbg(smb_fname), - dirtype); - - if (!CAN_WRITE(conn)) { - return NT_STATUS_MEDIA_WRITE_PROTECTED; - } - - ret = vfs_stat(conn, smb_fname); - if (ret != 0) { - return map_nt_error_from_unix(errno); - } - - fattr = fdos_mode(smb_fname->fsp); - - if (dirtype & FILE_ATTRIBUTE_NORMAL) { - dirtype = FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY; - } - - dirtype &= (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM); - if (!dirtype) { - return NT_STATUS_NO_SUCH_FILE; - } - - if (!dir_check_ftype(fattr, dirtype)) { - if (fattr & FILE_ATTRIBUTE_DIRECTORY) { - return NT_STATUS_FILE_IS_A_DIRECTORY; - } - return NT_STATUS_NO_SUCH_FILE; - } - - if (dirtype_orig & 0x8000) { - /* These will never be set for POSIX. */ - return NT_STATUS_NO_SUCH_FILE; - } - -#if 0 - if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) { - return NT_STATUS_FILE_IS_A_DIRECTORY; - } - - if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) { - return NT_STATUS_NO_SUCH_FILE; - } - - if (dirtype & 0xFF00) { - /* These will never be set for POSIX. */ - return NT_STATUS_NO_SUCH_FILE; - } - - dirtype &= 0xFF; - if (!dirtype) { - return NT_STATUS_NO_SUCH_FILE; - } - - /* Can't delete a directory. */ - if (fattr & FILE_ATTRIBUTE_DIRECTORY) { - return NT_STATUS_FILE_IS_A_DIRECTORY; - } -#endif - -#if 0 /* JRATEST */ - else if (dirtype & FILE_ATTRIBUTE_DIRECTORY) /* Asked for a directory and it isn't. */ - return NT_STATUS_OBJECT_NAME_INVALID; -#endif /* JRATEST */ - - if (smb_fname->flags & SMB_FILENAME_POSIX_PATH) { - status = make_smb2_posix_create_ctx( - talloc_tos(), &posx, 0777); - if (!NT_STATUS_IS_OK(status)) { - DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n", - nt_errstr(status)); - return status; - } - } - - /* On open checks the open itself will check the share mode, so - don't do it here as we'll get it wrong. */ - - status = SMB_VFS_CREATE_FILE - (conn, /* conn */ - req, /* req */ - smb_fname, /* fname */ - DELETE_ACCESS, /* access_mask */ - FILE_SHARE_NONE, /* share_access */ - FILE_OPEN, /* create_disposition*/ - FILE_NON_DIRECTORY_FILE, /* create_options */ - FILE_ATTRIBUTE_NORMAL, /* file_attributes */ - 0, /* oplock_request */ - NULL, /* lease */ - 0, /* allocation_size */ - 0, /* private_flags */ - NULL, /* sd */ - NULL, /* ea_list */ - &fsp, /* result */ - NULL, /* pinfo */ - posx, /* in_context_blobs */ - NULL); /* out_context_blobs */ - - TALLOC_FREE(posx); - - if (!NT_STATUS_IS_OK(status)) { - DBG_DEBUG("SMB_VFS_CREATEFILE failed: %s\n", - nt_errstr(status)); - return status; - } - - status = can_set_delete_on_close(fsp, fattr); - if (!NT_STATUS_IS_OK(status)) { - DBG_DEBUG("can_set_delete_on_close for file %s - " - "(%s)\n", - smb_fname_str_dbg(smb_fname), - nt_errstr(status)); - close_file_free(req, &fsp, NORMAL_CLOSE); - return status; - } - - /* The set is across all open files on this dev/inode pair. */ - if (!set_delete_on_close(fsp, True, - conn->session_info->security_token, - conn->session_info->unix_token)) { - close_file_free(req, &fsp, NORMAL_CLOSE); - return NT_STATUS_ACCESS_DENIED; - } - - return close_file_free(req, &fsp, NORMAL_CLOSE); -} - /**************************************************************************** Reply to a unlink ****************************************************************************/ diff --git a/source3/smbd/smb2_reply.c b/source3/smbd/smb2_reply.c index fda1b8a9ac9..138bb8d3cb2 100644 --- a/source3/smbd/smb2_reply.c +++ b/source3/smbd/smb2_reply.c @@ -742,3 +742,151 @@ void reply_special(struct smbXsrv_connection *xconn, char *inbuf, size_t inbuf_s } return; } + +/******************************************************************* + * unlink a file with all relevant access checks + *******************************************************************/ + +NTSTATUS unlink_internals(connection_struct *conn, + struct smb_request *req, + uint32_t dirtype, + struct smb_filename *smb_fname) +{ + uint32_t fattr; + files_struct *fsp; + uint32_t dirtype_orig = dirtype; + NTSTATUS status; + int ret; + struct smb2_create_blobs *posx = NULL; + + if (dirtype == 0) { + dirtype = FILE_ATTRIBUTE_NORMAL; + } + + DBG_DEBUG("%s, dirtype = %d\n", + smb_fname_str_dbg(smb_fname), + dirtype); + + if (!CAN_WRITE(conn)) { + return NT_STATUS_MEDIA_WRITE_PROTECTED; + } + + ret = vfs_stat(conn, smb_fname); + if (ret != 0) { + return map_nt_error_from_unix(errno); + } + + fattr = fdos_mode(smb_fname->fsp); + + if (dirtype & FILE_ATTRIBUTE_NORMAL) { + dirtype = FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY; + } + + dirtype &= (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM); + if (!dirtype) { + return NT_STATUS_NO_SUCH_FILE; + } + + if (!dir_check_ftype(fattr, dirtype)) { + if (fattr & FILE_ATTRIBUTE_DIRECTORY) { + return NT_STATUS_FILE_IS_A_DIRECTORY; + } + return NT_STATUS_NO_SUCH_FILE; + } + + if (dirtype_orig & 0x8000) { + /* These will never be set for POSIX. */ + return NT_STATUS_NO_SUCH_FILE; + } + +#if 0 + if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) { + return NT_STATUS_FILE_IS_A_DIRECTORY; + } + + if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) { + return NT_STATUS_NO_SUCH_FILE; + } + + if (dirtype & 0xFF00) { + /* These will never be set for POSIX. */ + return NT_STATUS_NO_SUCH_FILE; + } + + dirtype &= 0xFF; + if (!dirtype) { + return NT_STATUS_NO_SUCH_FILE; + } + + /* Can't delete a directory. */ + if (fattr & FILE_ATTRIBUTE_DIRECTORY) { + return NT_STATUS_FILE_IS_A_DIRECTORY; + } +#endif + +#if 0 /* JRATEST */ + else if (dirtype & FILE_ATTRIBUTE_DIRECTORY) /* Asked for a directory and it isn't. */ + return NT_STATUS_OBJECT_NAME_INVALID; +#endif /* JRATEST */ + + if (smb_fname->flags & SMB_FILENAME_POSIX_PATH) { + status = make_smb2_posix_create_ctx( + talloc_tos(), &posx, 0777); + if (!NT_STATUS_IS_OK(status)) { + DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n", + nt_errstr(status)); + return status; + } + } + + /* On open checks the open itself will check the share mode, so + don't do it here as we'll get it wrong. */ + + status = SMB_VFS_CREATE_FILE + (conn, /* conn */ + req, /* req */ + smb_fname, /* fname */ + DELETE_ACCESS, /* access_mask */ + FILE_SHARE_NONE, /* share_access */ + FILE_OPEN, /* create_disposition*/ + FILE_NON_DIRECTORY_FILE, /* create_options */ + FILE_ATTRIBUTE_NORMAL, /* file_attributes */ + 0, /* oplock_request */ + NULL, /* lease */ + 0, /* allocation_size */ + 0, /* private_flags */ + NULL, /* sd */ + NULL, /* ea_list */ + &fsp, /* result */ + NULL, /* pinfo */ + posx, /* in_context_blobs */ + NULL); /* out_context_blobs */ + + TALLOC_FREE(posx); + + if (!NT_STATUS_IS_OK(status)) { + DBG_DEBUG("SMB_VFS_CREATEFILE failed: %s\n", + nt_errstr(status)); + return status; + } + + status = can_set_delete_on_close(fsp, fattr); + if (!NT_STATUS_IS_OK(status)) { + DBG_DEBUG("can_set_delete_on_close for file %s - " + "(%s)\n", + smb_fname_str_dbg(smb_fname), + nt_errstr(status)); + close_file_free(req, &fsp, NORMAL_CLOSE); + return status; + } + + /* The set is across all open files on this dev/inode pair. */ + if (!set_delete_on_close(fsp, True, + conn->session_info->security_token, + conn->session_info->unix_token)) { + close_file_free(req, &fsp, NORMAL_CLOSE); + return NT_STATUS_ACCESS_DENIED; + } + + return close_file_free(req, &fsp, NORMAL_CLOSE); +}