r11697: - added a generic SMB2 getinfo call
authorAndrew Tridgell <tridge@samba.org>
Sat, 12 Nov 2005 07:48:56 +0000 (07:48 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:46:15 +0000 (13:46 -0500)
- added a SMB2-SCANGETINFO test for scanning for available info levels

- added names for the info levels I recognise to smb2.h
(This used to be commit fe5986067e2aaca039d70393ccc8761434f18fe6)

12 files changed:
source4/include/structs.h
source4/libcli/smb2/close.c
source4/libcli/smb2/config.mk
source4/libcli/smb2/create.c
source4/libcli/smb2/getinfo.c [new file with mode: 0644]
source4/libcli/smb2/request.c
source4/libcli/smb2/smb2.h
source4/libcli/smb2/smb2_calls.h
source4/libcli/smb2/transport.c
source4/torture/smb2/connect.c
source4/torture/smb2/scan.c
source4/torture/torture.c

index 059466bc59867dbdb1e180de13dbb355f8c69396..e519c52b5209629fbbb67823356904f5415284f4 100644 (file)
@@ -343,3 +343,4 @@ struct smb2_tree;
 struct smb2_tree_connect;
 struct smb2_create;
 struct smb2_close;
+struct smb2_getinfo;
index b60c1b307126d8ee6a5ad15cfedb95a884d2b49d..2802e2f27e181f7943508dd360622a562c0b234d 100644 (file)
@@ -1,7 +1,7 @@
 /* 
    Unix SMB/CIFS implementation.
 
-   SMB2 client tree handling
+   SMB2 client close handling
 
    Copyright (C) Andrew Tridgell 2005
    
@@ -61,7 +61,8 @@ NTSTATUS smb2_close_recv(struct smb2_request *req, struct smb2_close *io)
                return NT_STATUS_BUFFER_TOO_SMALL;
        }
 
-       io->out.buffer_code = SVAL(req->in.body, 0x00);
+       SMB2_CHECK_BUFFER_CODE(req, 0x3C);
+
        io->out.flags       = SVAL(req->in.body, 0x02);
        io->out._pad        = IVAL(req->in.body, 0x04);
        io->out.create_time = smbcli_pull_nttime(req->in.body, 0x08);
index 097ed6df12b89d155696acae84b8cd799315d52b..b7ecdcb98db657b53c6582a05e12de54ecd28fc8 100644 (file)
@@ -7,5 +7,6 @@ OBJ_FILES = \
        tcon.o \
        create.o \
        close.o \
-       connect.o
+       connect.o \
+       getinfo.o
 REQUIRED_SUBSYSTEMS = LIBCLI_RAW LIBPACKET
index 13166264324aa416f8134b67f5a9782d6408a0b4..9483f35ca1722932a30a434987b6be7c390ce7fd 100644 (file)
@@ -85,9 +85,6 @@ struct smb2_request *smb2_create_send(struct smb2_tree *tree, struct smb2_create
 */
 NTSTATUS smb2_create_recv(struct smb2_request *req, struct smb2_create *io)
 {
-       smb2_request_receive(req);
-       dump_data(0, req->in.body, req->in.body_size);
-
        if (!smb2_request_receive(req) || 
            smb2_request_is_error(req)) {
                return smb2_request_destroy(req);
diff --git a/source4/libcli/smb2/getinfo.c b/source4/libcli/smb2/getinfo.c
new file mode 100644 (file)
index 0000000..c8976e4
--- /dev/null
@@ -0,0 +1,90 @@
+/* 
+   Unix SMB/CIFS implementation.
+
+   SMB2 client getinfo 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 getinfo request
+*/
+struct smb2_request *smb2_getinfo_send(struct smb2_tree *tree, struct smb2_getinfo *io)
+{
+       struct smb2_request *req;
+
+       req = smb2_request_init_tree(tree, SMB2_OP_GETINFO, 0x28);
+       if (req == NULL) return NULL;
+
+       SSVAL(req->out.body, 0x00, io->in.buffer_code);
+       SSVAL(req->out.body, 0x02, io->in.level);
+       SIVAL(req->out.body, 0x04, io->in.max_response_size);
+       SIVAL(req->out.body, 0x08, io->in.unknown1);
+       SIVAL(req->out.body, 0x0C, io->in.unknown2);
+       SIVAL(req->out.body, 0x10, io->in.unknown3);
+       SIVAL(req->out.body, 0x14, io->in.unknown4);
+       SBVAL(req->out.body, 0x18, io->in.handle.data[0]);
+       SBVAL(req->out.body, 0x20, io->in.handle.data[1]);
+
+       smb2_transport_send(req);
+
+       return req;
+}
+
+
+/*
+  recv a getinfo reply
+*/
+NTSTATUS smb2_getinfo_recv(struct smb2_request *req, TALLOC_CTX *mem_ctx,
+                          struct smb2_getinfo *io)
+{
+       NTSTATUS status;
+
+       if (!smb2_request_receive(req) || 
+           smb2_request_is_error(req)) {
+               return smb2_request_destroy(req);
+       }
+
+       if (req->in.body_size < 0x08) {
+               return NT_STATUS_BUFFER_TOO_SMALL;
+       }
+
+       SMB2_CHECK_BUFFER_CODE(req, 0x09);
+
+       status = smb2_pull_ofs_blob(req, req->in.body+0x02, &io->out.blob);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+       talloc_steal(mem_ctx, io->out.blob.data);
+
+       return smb2_request_destroy(req);
+}
+
+/*
+  sync getinfo request
+*/
+NTSTATUS smb2_getinfo(struct smb2_tree *tree, TALLOC_CTX *mem_ctx,
+                     struct smb2_getinfo *io)
+{
+       struct smb2_request *req = smb2_getinfo_send(tree, io);
+       return smb2_getinfo_recv(req, mem_ctx, io);
+}
index ccffef9b8814af1fe3a865765f53349a3b072412..4b95d141a388ad88ac7e872dfca147131b69b6f0 100644 (file)
@@ -188,7 +188,7 @@ DATA_BLOB smb2_pull_blob(struct smb2_request *req, uint8_t *ptr, uint_t size)
 }
 
 /*
-  pull a ofs/length/blob triple into a data blob
+  pull a ofs/length/blob triple from a data blob
   the ptr points to the start of the offset/length pair
 */
 NTSTATUS smb2_pull_ofs_blob(struct smb2_request *req, uint8_t *ptr, DATA_BLOB *blob)
index f77eab22d18e2b9349830f8ebd464b77e99cab17..e99e8d39453c3487ca91a34575e94882f488ccb3 100644 (file)
@@ -166,7 +166,9 @@ struct smb2_request {
 #define SMB2_OP_CLOSE     0x06
 #define SMB2_OP_READ      0x08
 #define SMB2_OP_WRITE     0x09
+#define SMB2_OP_CANCEL    0x0c
 #define SMB2_OP_FIND      0x0e
+#define SMB2_OP_NOTIFY    0x0f
 #define SMB2_OP_GETINFO   0x10
 #define SMB2_OP_SETINFO   0x11
 #define SMB2_OP_BREAK     0x12
index 859655355dcbd8fef9a12bf1beba9373c5720712..5e9efd286813d791c2fbe393173debce856afa07 100644 (file)
@@ -155,3 +155,50 @@ struct smb2_close {
        } out;
 };
 
+/* fs information levels */
+#define SMB2_GETINFO_FS_01            0x0102
+#define SMB2_GETINFO_FS_03            0x0302
+#define SMB2_GETINFO_FS_04            0x0402
+#define SMB2_GETINFO_FS_ATTRIB_INFO   0x0502
+#define SMB2_GETINFO_FS_06            0x0602
+#define SMB2_GETINFO_FS_07            0x0702
+#define SMB2_GETINFO_FS_08            0x0802
+
+/* class 3 levels */
+#define SMB2_GETINFO_3_00            0x0003
+
+/* file information levels */
+#define SMB2_GETINFO_FILE_BASIC_INFO    0x0401
+#define SMB2_GETINFO_FILE_05            0x0501
+#define SMB2_GETINFO_FILE_06            0x0601
+#define SMB2_GETINFO_FILE_07            0x0701
+#define SMB2_GETINFO_FILE_ACCESS_INFO   0x0801
+#define SMB2_GETINFO_FILE_0E            0x0e01
+#define SMB2_GETINFO_FILE_10            0x1001
+#define SMB2_GETINFO_FILE_11            0x1101
+#define SMB2_GETINFO_FILE_ALL_INFO      0x1201
+#define SMB2_GETINFO_FILE_NAME_INFO     0x1501
+#define SMB2_GETINFO_FILE_STREAM_INFO   0x1601
+#define SMB2_GETINFO_FILE_1C            0x1c01
+#define SMB2_GETINFO_FILE_STANDARD_INFO 0x2201
+#define SMB2_GETINFO_FILE_ATTRIB_INFO   0x2301
+
+
+struct smb2_getinfo {
+       struct {
+               uint16_t buffer_code;
+               uint16_t level;
+               uint32_t max_response_size;
+               uint32_t unknown1;
+               uint32_t unknown2;
+               uint32_t unknown3;
+               uint32_t unknown4;
+               struct smb2_handle handle;
+       } in;
+
+       struct {
+               uint16_t buffer_code;
+               DATA_BLOB blob;
+       } out;
+};
+
index 9940379f982dbb48101de52eea3bff4425a49aa7..e87c7a68c02dd64481d9d16900c29b52e0b6f6d4 100644 (file)
@@ -184,7 +184,7 @@ static NTSTATUS smb2_transport_finish_recv(void *private, DATA_BLOB blob)
        req->status       = NT_STATUS(IVAL(hdr, SMB2_HDR_STATUS));
 
        DEBUG(2, ("SMB2 RECV seqnum=0x%llx\n", req->seqnum));
-       dump_data(2, req->in.body, req->in.body_size);
+       dump_data(5, req->in.body, req->in.body_size);
 
        /* if this request has an async handler then call that to
           notify that the reply has been received. This might destroy
@@ -197,7 +197,7 @@ static NTSTATUS smb2_transport_finish_recv(void *private, DATA_BLOB blob)
        return NT_STATUS_OK;
 
 error:
-       dump_data(2, buffer, len);
+       dump_data(5, buffer, len);
        if (req) {
                DLIST_REMOVE(transport->pending_recv, req);
                req->state = SMB2_REQUEST_ERROR;
@@ -253,7 +253,7 @@ void smb2_transport_send(struct smb2_request *req)
        _smb_setlen(req->out.buffer, req->out.size - NBT_HDR_SIZE);
 
        DEBUG(2, ("SMB2 send seqnum=0x%llx\n", req->seqnum));
-       dump_data(2, req->out.body, req->out.body_size);
+       dump_data(5, req->out.body, req->out.body_size);
 
        /* check if the transport is dead */
        if (req->transport->socket->sock == NULL) {
index 6a9a80315547b9ea6178a45dce3beb643807bf8f..54991e27bab6626d2bea6b6c6021cbca1dbe2c21 100644 (file)
@@ -46,14 +46,16 @@ static NTSTATUS torture_smb2_close(struct smb2_tree *tree, struct smb2_handle ha
                return status;
        }
 
-       printf("Close gave:\n");
-       printf("create_time     = %s\n", nt_time_string(tmp_ctx, io.out.create_time));
-       printf("access_time     = %s\n", nt_time_string(tmp_ctx, io.out.access_time));
-       printf("write_time      = %s\n", nt_time_string(tmp_ctx, io.out.write_time));
-       printf("change_time     = %s\n", nt_time_string(tmp_ctx, io.out.change_time));
-       printf("alloc_size      = %lld\n", io.out.alloc_size);
-       printf("size            = %lld\n", io.out.size);
-       printf("file_attr       = 0x%x\n", io.out.file_attr);
+       if (DEBUGLVL(1)) {
+               printf("Close gave:\n");
+               printf("create_time     = %s\n", nt_time_string(tmp_ctx, io.out.create_time));
+               printf("access_time     = %s\n", nt_time_string(tmp_ctx, io.out.access_time));
+               printf("write_time      = %s\n", nt_time_string(tmp_ctx, io.out.write_time));
+               printf("change_time     = %s\n", nt_time_string(tmp_ctx, io.out.change_time));
+               printf("alloc_size      = %lld\n", io.out.alloc_size);
+               printf("size            = %lld\n", io.out.size);
+               printf("file_attr       = 0x%x\n", io.out.file_attr);
+       }
 
        talloc_free(tmp_ctx);
        
@@ -90,25 +92,28 @@ static struct smb2_handle torture_smb2_create(struct smb2_tree *tree,
                return io.out.handle;
        }
 
-       printf("Open gave:\n");
-       printf("oplock_flags    = 0x%x\n", io.out.oplock_flags);
-       printf("create_action   = 0x%x\n", io.out.create_action);
-       printf("create_time     = %s\n", nt_time_string(tmp_ctx, io.out.create_time));
-       printf("access_time     = %s\n", nt_time_string(tmp_ctx, io.out.access_time));
-       printf("write_time      = %s\n", nt_time_string(tmp_ctx, io.out.write_time));
-       printf("change_time     = %s\n", nt_time_string(tmp_ctx, io.out.change_time));
-       printf("alloc_size      = %lld\n", io.out.alloc_size);
-       printf("size            = %lld\n", io.out.size);
-       printf("file_attr       = 0x%x\n", io.out.file_attr);
-       printf("handle          = %016llx%016llx\n", 
-              io.out.handle.data[0], 
-              io.out.handle.data[1]);
+       if (DEBUGLVL(1)) {
+               printf("Open gave:\n");
+               printf("oplock_flags    = 0x%x\n", io.out.oplock_flags);
+               printf("create_action   = 0x%x\n", io.out.create_action);
+               printf("create_time     = %s\n", nt_time_string(tmp_ctx, io.out.create_time));
+               printf("access_time     = %s\n", nt_time_string(tmp_ctx, io.out.access_time));
+               printf("write_time      = %s\n", nt_time_string(tmp_ctx, io.out.write_time));
+               printf("change_time     = %s\n", nt_time_string(tmp_ctx, io.out.change_time));
+               printf("alloc_size      = %lld\n", io.out.alloc_size);
+               printf("size            = %lld\n", io.out.size);
+               printf("file_attr       = 0x%x\n", io.out.file_attr);
+               printf("handle          = %016llx%016llx\n", 
+                      io.out.handle.data[0], 
+                      io.out.handle.data[1]);
+       }
 
        talloc_free(tmp_ctx);
        
        return io.out.handle;
 }
 
+
 /* 
    basic testing of SMB2 connection calls
 */
index 0fcd3250fbaf2f48d8d6eb67300278e2e9576225..3946d1949662a5fcad68fe1a855cf5e83e87f59a 100644 (file)
 #include "lib/events/events.h"
 
 
+/* 
+   scan for valid SMB2 getinfo levels
+*/
+BOOL torture_smb2_getinfo_scan(void)
+{
+       TALLOC_CTX *mem_ctx = talloc_new(NULL);
+       struct smb2_tree *tree;
+       const char *host = lp_parm_string(-1, "torture", "host");
+       const char *share = lp_parm_string(-1, "torture", "share");
+       struct cli_credentials *credentials = cmdline_credentials;
+       NTSTATUS status;
+       struct smb2_getinfo io;
+       struct smb2_create cr;
+       struct smb2_handle handle;
+       int c, i;
+       const char *fname = "scan-getinfo.dat";
+
+       status = smb2_connect(mem_ctx, host, share, credentials, &tree, 
+                             event_context_find(mem_ctx));
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("Connection failed - %s\n", nt_errstr(status));
+               return False;
+       }
+
+       ZERO_STRUCT(cr);
+       cr.in.buffer_code = 0x39;
+       cr.in.oplock_flags = 0;
+       cr.in.access_mask = SEC_RIGHTS_FILE_ALL;
+       cr.in.file_attr   = FILE_ATTRIBUTE_NORMAL;
+       cr.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
+       cr.in.share_access = 
+               NTCREATEX_SHARE_ACCESS_DELETE|
+               NTCREATEX_SHARE_ACCESS_READ|
+               NTCREATEX_SHARE_ACCESS_WRITE;
+       cr.in.create_options = NTCREATEX_OPTIONS_WRITE_THROUGH;
+       cr.in.fname = fname;
+
+       status = smb2_create(tree, &cr);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("create of '%s' failed - %s\n", fname, nt_errstr(status));
+               return False;
+       }
+
+       handle = cr.out.handle;
+
+
+       ZERO_STRUCT(io);
+       io.in.buffer_code       = 0x29;
+       io.in.max_response_size = 0xFFFF;
+       io.in.handle            = handle;
+
+       for (c=0;c<5;c++) {
+               for (i=0;i<0x100;i++) {
+                       io.in.level = (i<<8) | c;
+                       status = smb2_getinfo(tree, mem_ctx, &io);
+                       if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER) ||
+                           NT_STATUS_EQUAL(status, NT_STATUS_INVALID_INFO_CLASS) ||
+                           NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) {
+                               continue;
+                       }
+                       if (NT_STATUS_IS_OK(status)) {
+                               printf("level 0x%04x is %d bytes\n", 
+                                      io.in.level, io.out.blob.length);
+                               dump_data(1, io.out.blob.data, io.out.blob.length);
+                       }
+               }
+       }
+
+       talloc_free(mem_ctx);
+
+       return True;
+}
+
 /* 
    scan for valid SMB2 opcodes
 */
index 021c4b3ab4ff73caed04c5986039f1156b90f599..ff9584ed5cfdcb196f7e1f082c50046085213dd1 100644 (file)
@@ -2254,6 +2254,7 @@ static struct {
        /* SMB2 tests */
        {"SMB2-CONNECT", torture_smb2_connect, 0},
        {"SMB2-SCAN", torture_smb2_scan, 0},
+       {"SMB2-SCANGETINFO", torture_smb2_getinfo_scan, 0},
 
        /* protocol scanners */
        {"SCAN-TRANS2", torture_trans2_scan, 0},