diff options
-rw-r--r-- | source4/include/smb_interfaces.h | 2 | ||||
-rw-r--r-- | source4/include/structs.h | 3 | ||||
-rw-r--r-- | source4/libcli/smb2/config.mk | 3 | ||||
-rw-r--r-- | source4/libcli/smb2/find.c | 90 | ||||
-rw-r--r-- | source4/libcli/smb2/getinfo.c | 2 | ||||
-rw-r--r-- | source4/libcli/smb2/smb2_calls.h | 19 | ||||
-rw-r--r-- | source4/torture/smb2/getinfo.c | 8 | ||||
-rw-r--r-- | source4/torture/smb2/scan.c | 48 | ||||
-rw-r--r-- | source4/torture/torture.c | 1 |
9 files changed, 165 insertions, 11 deletions
diff --git a/source4/include/smb_interfaces.h b/source4/include/smb_interfaces.h index 9d42494fc5..49fe085f2c 100644 --- a/source4/include/smb_interfaces.h +++ b/source4/include/smb_interfaces.h @@ -461,7 +461,7 @@ union smb_fileinfo { struct { enum smb_fileinfo_level level; union smb_fileinfo_in in; - uint8_t ea_flags; /* SMB2 only - SMB2_GETINFO_EA_FLAG_* */ + uint8_t continue_flags; /* SMB2 only - SMB2_CONTINUE_FLAG_* */ struct smb_ea_list out; } all_eas; diff --git a/source4/include/structs.h b/source4/include/structs.h index 68f7f9af14..a846b39bcf 100644 --- a/source4/include/structs.h +++ b/source4/include/structs.h @@ -354,6 +354,5 @@ struct smb2_getinfo; struct smb2_setinfo; struct smb2_read; struct smb2_write; +struct smb2_find; struct smb2_handle; - -union smb2_fileinfo; diff --git a/source4/libcli/smb2/config.mk b/source4/libcli/smb2/config.mk index fcea996f01..c0974dbfa5 100644 --- a/source4/libcli/smb2/config.mk +++ b/source4/libcli/smb2/config.mk @@ -11,5 +11,6 @@ OBJ_FILES = \ getinfo.o \ write.o \ read.o \ - setinfo.o + setinfo.o \ + find.o REQUIRED_SUBSYSTEMS = LIBCLI_RAW LIBPACKET diff --git a/source4/libcli/smb2/find.c b/source4/libcli/smb2/find.c new file mode 100644 index 0000000000..91be5e4bb1 --- /dev/null +++ b/source4/libcli/smb2/find.c @@ -0,0 +1,90 @@ +/* + Unix SMB/CIFS implementation. + + SMB2 client find calls + + Copyright (C) Andrew Tridgell 2005 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" +#include "libcli/raw/libcliraw.h" +#include "libcli/smb2/smb2.h" +#include "libcli/smb2/smb2_calls.h" + +/* + send a find request +*/ +struct smb2_request *smb2_find_send(struct smb2_tree *tree, struct smb2_find *io) +{ + struct smb2_request *req; + NTSTATUS status; + + req = smb2_request_init_tree(tree, SMB2_OP_FIND, 0x20, 1); + if (req == NULL) return NULL; + + SCVAL(req->out.body, 0x02, io->in.level); + SCVAL(req->out.body, 0x03, io->in.continue_flags); + SIVAL(req->out.body, 0x04, io->in.unknown); + smb2_push_handle(req->out.body+0x08, &io->in.handle); + SIVAL(req->out.body, 0x1C, io->in.max_response_size); + + status = smb2_push_o16s16_string(&req->out, 0x18, io->in.pattern); + if (!NT_STATUS_IS_OK(status)) { + talloc_free(req); + return NULL; + } + + smb2_transport_send(req); + + return req; +} + + +/* + recv a find reply +*/ +NTSTATUS smb2_find_recv(struct smb2_request *req, TALLOC_CTX *mem_ctx, + struct smb2_find *io) +{ + NTSTATUS status; + + if (!smb2_request_receive(req) || + smb2_request_is_error(req)) { + return smb2_request_destroy(req); + } + + SMB2_CHECK_PACKET_RECV(req, 0x08, True); + + status = smb2_pull_o16s32_blob(&req->in, mem_ctx, + req->in.body+0x02, &io->out.blob); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + return smb2_request_destroy(req); +} + +/* + sync find request +*/ +NTSTATUS smb2_find(struct smb2_tree *tree, TALLOC_CTX *mem_ctx, + struct smb2_find *io) +{ + struct smb2_request *req = smb2_find_send(tree, io); + return smb2_find_recv(req, mem_ctx, io); +} + diff --git a/source4/libcli/smb2/getinfo.c b/source4/libcli/smb2/getinfo.c index 62418a05b7..e406fdf45c 100644 --- a/source4/libcli/smb2/getinfo.c +++ b/source4/libcli/smb2/getinfo.c @@ -125,7 +125,7 @@ struct smb2_request *smb2_getinfo_file_send(struct smb2_tree *tree, union smb_fi b.in.flags = io->query_secdesc.secinfo_flags; } if (io->generic.level == RAW_FILEINFO_SMB2_ALL_EAS) { - b.in.flags2 = io->all_eas.ea_flags; + b.in.flags2 = io->all_eas.continue_flags; } return smb2_getinfo_send(tree, &b); diff --git a/source4/libcli/smb2/smb2_calls.h b/source4/libcli/smb2/smb2_calls.h index e6e1872d5e..10d6cda7a3 100644 --- a/source4/libcli/smb2/smb2_calls.h +++ b/source4/libcli/smb2/smb2_calls.h @@ -189,8 +189,8 @@ struct smb2_close { #define SMB2_GETINFO_SECURITY 0x03 /* flags for RAW_FILEINFO_SMB2_ALL_EAS */ -#define SMB2_GETINFO_EA_FLAG_RESTART 0x01 -#define SMB2_GETINFO_EA_FLAG_SINGLE 0x02 +#define SMB2_CONTINUE_FLAG_RESTART 0x01 +#define SMB2_CONTINUE_FLAG_SINGLE 0x02 /* NOTE! the getinfo fs and file levels exactly match up with the 'passthru' SMB levels, which are levels >= 1000. The SMB2 client @@ -278,3 +278,18 @@ struct smb2_read { DATA_BLOB data; } out; }; + +struct smb2_find { + struct { + uint8_t level; + uint8_t continue_flags; /* SMB2_CONTINUE_FLAG_* */ + uint32_t unknown; /* perhaps a continue token? */ + struct smb2_handle handle; + uint32_t max_response_size; + const char *pattern; + } in; + + struct { + DATA_BLOB blob; + } out; +}; diff --git a/source4/torture/smb2/getinfo.c b/source4/torture/smb2/getinfo.c index 7c0fe7fbd7..209c220e60 100644 --- a/source4/torture/smb2/getinfo.c +++ b/source4/torture/smb2/getinfo.c @@ -102,10 +102,10 @@ static BOOL torture_smb2_fileinfo(struct smb2_tree *tree) file_levels[i].dinfo.query_secdesc.secinfo_flags = 0x7; } if (file_levels[i].level == RAW_FILEINFO_SMB2_ALL_EAS) { - file_levels[i].finfo.all_eas.ea_flags = - SMB2_GETINFO_EA_FLAG_RESTART; - file_levels[i].dinfo.all_eas.ea_flags = - SMB2_GETINFO_EA_FLAG_RESTART; + file_levels[i].finfo.all_eas.continue_flags = + SMB2_CONTINUE_FLAG_RESTART; + file_levels[i].dinfo.all_eas.continue_flags = + SMB2_CONTINUE_FLAG_RESTART; } file_levels[i].finfo.generic.level = file_levels[i].level; file_levels[i].finfo.generic.in.handle = hfile; diff --git a/source4/torture/smb2/scan.c b/source4/torture/smb2/scan.c index 81e0bea69a..b0c4ba4c8d 100644 --- a/source4/torture/smb2/scan.c +++ b/source4/torture/smb2/scan.c @@ -146,6 +146,54 @@ BOOL torture_smb2_setinfo_scan(void) return True; } + +/* + scan for valid SMB2 scan levels +*/ +BOOL torture_smb2_find_scan(void) +{ + TALLOC_CTX *mem_ctx = talloc_new(NULL); + struct smb2_tree *tree; + NTSTATUS status; + struct smb2_find io; + struct smb2_handle handle; + int i; + + if (!torture_smb2_connection(mem_ctx, &tree)) { + return False; + } + + status = smb2_util_roothandle(tree, &handle); + if (!NT_STATUS_IS_OK(status)) { + printf("Failed to open roothandle - %s\n", nt_errstr(status)); + return False; + } + + ZERO_STRUCT(io); + io.in.pattern = "*"; + io.in.continue_flags = SMB2_CONTINUE_FLAG_RESTART; + io.in.max_response_size = 0x10000; + io.in.handle = handle; + + for (i=1;i<0x100;i++) { + io.in.level = i; + + io.in.handle = handle; + status = smb2_find(tree, mem_ctx, &io); + if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_INFO_CLASS) && + !NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER) && + !NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) { + printf("find level 0x%04x is %d bytes - %s\n", + io.in.level, io.out.blob.length, nt_errstr(status)); + dump_data(1, io.out.blob.data, io.out.blob.length); + } + } + + talloc_free(mem_ctx); + + return True; +} + /* scan for valid SMB2 opcodes */ diff --git a/source4/torture/torture.c b/source4/torture/torture.c index 434bca2500..e4ceffc02a 100644 --- a/source4/torture/torture.c +++ b/source4/torture/torture.c @@ -2256,6 +2256,7 @@ static struct { {"SMB2-SCAN", torture_smb2_scan, 0}, {"SMB2-SCANGETINFO", torture_smb2_getinfo_scan, 0}, {"SMB2-SCANSETINFO", torture_smb2_setinfo_scan, 0}, + {"SMB2-SCANFIND", torture_smb2_find_scan, 0}, {"SMB2-GETINFO", torture_smb2_getinfo, 0}, {"SMB2-SETINFO", torture_smb2_setinfo, 0}, |