From f54ef3aac5beff8b004db1de3b6344db9194ea0c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 12 Nov 2013 15:17:26 -0800 Subject: [PATCH 1/3] Bug #10260 - smbclient shows no error if deleting a directory with del failed Remove unneeded conn argument to dir_check_ftype(). Move to correct uint32_t types. Signed-off-by: Jeremy Allison --- source3/smbd/dir.c | 6 +++--- source3/smbd/proto.h | 2 +- source3/smbd/reply.c | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index d99eec2..6b7cce2 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -966,9 +966,9 @@ struct dptr_struct *dptr_fetch_lanman2(struct smbd_server_connection *sconn, Check that a file matches a particular file type. ****************************************************************************/ -bool dir_check_ftype(connection_struct *conn, uint32 mode, uint32 dirtype) +bool dir_check_ftype(uint32_t mode, uint32_t dirtype) { - uint32 mask; + uint32_t mask; /* Check the "may have" search bits. */ if (((mode & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_DIRECTORY)) != 0) @@ -1106,7 +1106,7 @@ bool smbd_dirptr_get_entry(TALLOC_CTX *ctx, continue; } - if (!dir_check_ftype(conn, mode, dirtype)) { + if (!dir_check_ftype(mode, dirtype)) { DEBUG(5,("[%s] attribs 0x%x didn't match 0x%x\n", fname, (unsigned int)mode, (unsigned int)dirtype)); TALLOC_FREE(dname); diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h index a15d520..a373cd6 100644 --- a/source3/smbd/proto.h +++ b/source3/smbd/proto.h @@ -218,7 +218,7 @@ struct dptr_struct *dptr_fetch(struct smbd_server_connection *sconn, char *buf,int *num); struct dptr_struct *dptr_fetch_lanman2(struct smbd_server_connection *sconn, int dptr_num); -bool dir_check_ftype(connection_struct *conn, uint32 mode, uint32 dirtype); +bool dir_check_ftype(uint32_t mode, uint32_t dirtype); bool get_dir_entry(TALLOC_CTX *ctx, struct dptr_struct *dirptr, const char *mask, diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 3f59df8..b160290 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2655,7 +2655,7 @@ static NTSTATUS do_unlink(connection_struct *conn, return NT_STATUS_NO_SUCH_FILE; } - if (!dir_check_ftype(conn, fattr, dirtype)) { + if (!dir_check_ftype(fattr, dirtype)) { if (fattr & FILE_ATTRIBUTE_DIRECTORY) { return NT_STATUS_FILE_IS_A_DIRECTORY; } -- 1.8.4.1 From a061a0df6e3fa3ce9b32864ac3bb269f027f4b95 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 12 Nov 2013 15:32:42 -0800 Subject: [PATCH 2/3] Bug #10260 - smbclient shows no error if deleting a directory with del failed Move dir_check_ftype() to util.c Signed-off-by: Jeremy Allison --- source3/include/proto.h | 1 + source3/lib/util.c | 42 ++++++++++++++++++++++++++++++++++++++++++ source3/smbd/dir.c | 26 -------------------------- source3/smbd/proto.h | 1 - 4 files changed, 43 insertions(+), 27 deletions(-) diff --git a/source3/include/proto.h b/source3/include/proto.h index 277547b..fc7f24d 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -475,6 +475,7 @@ bool map_open_params_to_ntcreate(const char *smb_base_fname, uint32 *pcreate_options, uint32_t *pprivate_flags); struct security_unix_token *copy_unix_token(TALLOC_CTX *ctx, const struct security_unix_token *tok); +bool dir_check_ftype(uint32_t mode, uint32_t dirtype); void init_modules(void); /* The following definitions come from lib/util_builtin.c */ diff --git a/source3/lib/util.c b/source3/lib/util.c index 5168092..551beab 100644 --- a/source3/lib/util.c +++ b/source3/lib/util.c @@ -2393,3 +2393,45 @@ struct security_unix_token *copy_unix_token(TALLOC_CTX *ctx, const struct securi } return cpy; } + +/**************************************************************************** + Check that a file matches a particular file type. +****************************************************************************/ + +bool dir_check_ftype(uint32_t mode, uint32_t dirtype) +{ + uint32_t mask; + + /* Check the "may have" search bits. */ + if (((mode & ~dirtype) & + (FILE_ATTRIBUTE_HIDDEN | + FILE_ATTRIBUTE_SYSTEM | + FILE_ATTRIBUTE_DIRECTORY)) != 0) { + return false; + } + + /* Check the "must have" bits, + which are the may have bits shifted eight */ + /* If must have bit is set, the file/dir can + not be returned in search unless the matching + file attribute is set */ + mask = ((dirtype >> 8) & (FILE_ATTRIBUTE_DIRECTORY| + FILE_ATTRIBUTE_ARCHIVE| + FILE_ATTRIBUTE_READONLY| + FILE_ATTRIBUTE_HIDDEN| + FILE_ATTRIBUTE_SYSTEM)); /* & 0x37 */ + if(mask) { + if((mask & (mode & (FILE_ATTRIBUTE_DIRECTORY| + FILE_ATTRIBUTE_ARCHIVE| + FILE_ATTRIBUTE_READONLY| + FILE_ATTRIBUTE_HIDDEN| + FILE_ATTRIBUTE_SYSTEM))) == mask) { + /* check if matching attribute present */ + return true; + } else { + return false; + } + } + + return true; +} diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 6b7cce2..8fa320b 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -962,32 +962,6 @@ struct dptr_struct *dptr_fetch_lanman2(struct smbd_server_connection *sconn, return(dptr); } -/**************************************************************************** - Check that a file matches a particular file type. -****************************************************************************/ - -bool dir_check_ftype(uint32_t mode, uint32_t dirtype) -{ - uint32_t mask; - - /* Check the "may have" search bits. */ - if (((mode & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_DIRECTORY)) != 0) - return False; - - /* Check the "must have" bits, which are the may have bits shifted eight */ - /* If must have bit is set, the file/dir can not be returned in search unless the matching - file attribute is set */ - mask = ((dirtype >> 8) & (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)); /* & 0x37 */ - if(mask) { - if((mask & (mode & (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM))) == mask) /* check if matching attribute present */ - return True; - else - return False; - } - - return True; -} - static bool mangle_mask_match(connection_struct *conn, const char *filename, const char *mask) diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h index a373cd6..a550dd7 100644 --- a/source3/smbd/proto.h +++ b/source3/smbd/proto.h @@ -218,7 +218,6 @@ struct dptr_struct *dptr_fetch(struct smbd_server_connection *sconn, char *buf,int *num); struct dptr_struct *dptr_fetch_lanman2(struct smbd_server_connection *sconn, int dptr_num); -bool dir_check_ftype(uint32_t mode, uint32_t dirtype); bool get_dir_entry(TALLOC_CTX *ctx, struct dptr_struct *dirptr, const char *mask, -- 1.8.4.1 From 09a1d7a7b3145b93d26bb26ee72205aa9f53a15a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 12 Nov 2013 15:55:51 -0800 Subject: [PATCH 3/3] Bug #10260 - smbclient shows no error if deleting a directory with del failed In SMB1 the server filters by attribute requested, in SMB2 there is no attribute sent. Emulate this on the client to provide the same ABI to callers. In SMB1 the server returns NT_STATUS_NO_SUCH_FILE if FindFirst finds no files. Emulate this on the client. Signed-off-by: Jeremy Allison --- source3/libsmb/cli_smb2_fnum.c | 29 ++++++++++++++++++++++++++--- source3/libsmb/cli_smb2_fnum.h | 1 + source3/libsmb/clilist.c | 2 +- 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/source3/libsmb/cli_smb2_fnum.c b/source3/libsmb/cli_smb2_fnum.c index 202000f..eec04d6 100644 --- a/source3/libsmb/cli_smb2_fnum.c +++ b/source3/libsmb/cli_smb2_fnum.c @@ -486,6 +486,7 @@ static bool windows_parent_dirname(TALLOC_CTX *mem_ctx, NTSTATUS cli_smb2_list(struct cli_state *cli, const char *pathname, + uint16_t attribute, NTSTATUS (*fn)(const char *, struct file_info *, const char *, @@ -497,6 +498,7 @@ NTSTATUS cli_smb2_list(struct cli_state *cli, char *parent_dir = NULL; const char *mask = NULL; struct smb2_hnd *ph = NULL; + unsigned int num_files = 0; TALLOC_CTX *frame = talloc_stackframe(); TALLOC_CTX *subframe = NULL; @@ -590,13 +592,26 @@ NTSTATUS cli_smb2_list(struct cli_state *cli, goto fail; } - status = fn(cli->dfs_mountpoint, + if (dir_check_ftype((uint32_t)finfo->mode, + (uint32_t)attribute)) { + /* + * Only process if attributes match. + * On SMB1 server does this, so on + * SMB2 we need to emulate in the + * client. + * + * https://bugzilla.samba.org/show_bug.cgi?id=10260 + */ + num_files++; + + status = fn(cli->dfs_mountpoint, finfo, pathname, state); - if (!NT_STATUS_IS_OK(status)) { - break; + if (!NT_STATUS_IS_OK(status)) { + break; + } } TALLOC_FREE(finfo); @@ -616,6 +631,14 @@ NTSTATUS cli_smb2_list(struct cli_state *cli, status = NT_STATUS_OK; } + if (NT_STATUS_IS_OK(status) && num_files == 0) { + /* + * In SMB1 findfirst returns NT_STATUS_NO_SUCH_FILE + * if no files match. Emulate this in the client. + */ + status = NT_STATUS_NO_SUCH_FILE; + } + fail: if (fnum != 0xffff) { diff --git a/source3/libsmb/cli_smb2_fnum.h b/source3/libsmb/cli_smb2_fnum.h index 0068686..a5cae25 100644 --- a/source3/libsmb/cli_smb2_fnum.h +++ b/source3/libsmb/cli_smb2_fnum.h @@ -42,6 +42,7 @@ NTSTATUS cli_smb2_rmdir(struct cli_state *cli, const char *dirname); NTSTATUS cli_smb2_unlink(struct cli_state *cli,const char *fname); NTSTATUS cli_smb2_list(struct cli_state *cli, const char *pathname, + uint16_t attribute, NTSTATUS (*fn)(const char *, struct file_info *, const char *, diff --git a/source3/libsmb/clilist.c b/source3/libsmb/clilist.c index ed970cd..3080fb8 100644 --- a/source3/libsmb/clilist.c +++ b/source3/libsmb/clilist.c @@ -942,7 +942,7 @@ NTSTATUS cli_list(struct cli_state *cli, const char *mask, uint16 attribute, uint16_t info_level; if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) { - return cli_smb2_list(cli, mask, fn, state); + return cli_smb2_list(cli, mask, attribute, fn, state); } frame = talloc_stackframe(); -- 1.8.4.1