r11800: - filled in unknown fields in SMB2 all_info level
authorAndrew Tridgell <tridge@samba.org>
Sat, 19 Nov 2005 05:55:08 +0000 (05:55 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:46:29 +0000 (13:46 -0500)
- allow setting of the ALL_EAS flags bits in SMB2 getinfo
(This used to be commit 8c7c54a46dfb91c053d07a5e606892a41213c605)

source4/include/smb_interfaces.h
source4/libcli/raw/rawfileinfo.c
source4/libcli/smb2/getinfo.c
source4/libcli/smb2/smb2_calls.h
source4/torture/smb2/getinfo.c
source4/torture/smb2/setinfo.c
source4/torture/smb2/util.c

index ed01a014c2b3b0f03866f27629497ccff2f9534c..9d42494fc5de2f5df6079e788648affcd6dbaa46 100644 (file)
@@ -461,6 +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_* */
 
                struct smb_ea_list out;
        } all_eas;
@@ -563,8 +564,8 @@ union smb_fileinfo {
                        uint64_t file_id;
                        uint32_t ea_size;
                        uint32_t access_mask;
-                       uint64_t unknown2;
-                       uint64_t unknown3;
+                       uint64_t position;
+                       uint64_t mode;
                        WIRE_STRING fname;
                } out;
        } all_info2;    
index 7119eed5e7147d9da258008899f946210180eb81..92d31b30ef108aa2b77a36b9b4efa57887d2d7ae 100644 (file)
@@ -95,9 +95,9 @@ NTSTATUS smb_raw_fileinfo_passthru_parse(const DATA_BLOB *blob, TALLOC_CTX *mem_
                }
                parms->basic_info.out.create_time = smbcli_pull_nttime(blob->data, 0);
                parms->basic_info.out.access_time = smbcli_pull_nttime(blob->data, 8);
-               parms->basic_info.out.write_time  smbcli_pull_nttime(blob->data, 16);
+               parms->basic_info.out.write_time  = smbcli_pull_nttime(blob->data, 16);
                parms->basic_info.out.change_time = smbcli_pull_nttime(blob->data, 24);
-               parms->basic_info.out.attrib =                 IVAL(blob->data, 32);
+               parms->basic_info.out.attrib      = IVAL(blob->data, 32);
                return NT_STATUS_OK;
 
        case RAW_FILEINFO_STANDARD_INFORMATION:
@@ -236,8 +236,8 @@ NTSTATUS smb_raw_fileinfo_passthru_parse(const DATA_BLOB *blob, TALLOC_CTX *mem_
                parms->all_info2.out.file_id        = BVAL(blob->data, 0x40);
                parms->all_info2.out.ea_size        = IVAL(blob->data, 0x48);
                parms->all_info2.out.access_mask    = IVAL(blob->data, 0x4C);
-               parms->all_info2.out.unknown2       = BVAL(blob->data, 0x50);
-               parms->all_info2.out.unknown3       = BVAL(blob->data, 0x58);
+               parms->all_info2.out.position       = BVAL(blob->data, 0x50);
+               parms->all_info2.out.mode           = BVAL(blob->data, 0x58);
                smbcli_blob_pull_string(NULL, mem_ctx, blob,
                                        &parms->all_info2.out.fname, 0x60, 0x64, STR_UNICODE);
                return NT_STATUS_OK;
index 85411fab92517a14cbbc9620a7aaee762d136d5a..62418a05b7fd26e9b5b606791ccd981c725d5145 100644 (file)
@@ -43,7 +43,7 @@ struct smb2_request *smb2_getinfo_send(struct smb2_tree *tree, struct smb2_getin
        SIVAL(req->out.body, 0x08, io->in.unknown1);
        SIVAL(req->out.body, 0x0C, io->in.unknown2);
        SIVAL(req->out.body, 0x10, io->in.flags);
-       SIVAL(req->out.body, 0x14, io->in.unknown4);
+       SIVAL(req->out.body, 0x14, io->in.flags2);
        smb2_push_handle(req->out.body+0x18, &io->in.handle);
 
        smb2_transport_send(req);
@@ -124,6 +124,9 @@ struct smb2_request *smb2_getinfo_file_send(struct smb2_tree *tree, union smb_fi
        if (io->generic.level == RAW_FILEINFO_SEC_DESC) {
                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;
+       }
 
        return smb2_getinfo_send(tree, &b);
 }
index 1c41d4cd661c723bd596d40a6b8a1e786f88846b..e6e1872d5e5349b8f240b61b5418fd31eada722b 100644 (file)
@@ -188,6 +188,10 @@ struct smb2_close {
 #define SMB2_GETINFO_FS                 0x02
 #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
+
 /* NOTE! the getinfo fs and file levels exactly match up with the
    'passthru' SMB levels, which are levels >= 1000. The SMB2 client
    lib uses the names from the libcli/raw/ library */
@@ -201,7 +205,7 @@ struct smb2_getinfo {
                uint32_t unknown1;
                uint32_t unknown2;
                uint32_t flags; /* level specific */
-               uint32_t unknown4;
+               uint32_t flags2; /* used by all_eas level */
                struct smb2_handle handle;
        } in;
 
index b8e61ebe344dff704264da4de8d47a078f78148e..7c0fe7fbd7d0c9a36349e6b909ebf6afc2598e8d 100644 (file)
@@ -92,6 +92,7 @@ static BOOL torture_smb2_fileinfo(struct smb2_tree *tree)
                goto failed;
        }
 
+       printf("Testing file info levels\n");
        torture_smb2_all_info(tree, hfile);
        torture_smb2_all_info(tree, hdir);
 
@@ -100,6 +101,12 @@ static BOOL torture_smb2_fileinfo(struct smb2_tree *tree)
                        file_levels[i].finfo.query_secdesc.secinfo_flags = 0x7;
                        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.generic.level = file_levels[i].level;
                file_levels[i].finfo.generic.in.handle = hfile;
                file_levels[i].fstatus = smb2_getinfo_file(tree, tree, &file_levels[i].finfo);
@@ -130,7 +137,8 @@ static BOOL torture_smb2_fsinfo(struct smb2_tree *tree)
        NTSTATUS status;
        struct smb2_handle handle;
 
-       status = torture_smb2_testdir(tree, DNAME, &handle);
+       printf("Testing fsinfo levels\n");
+       status = smb2_util_roothandle(tree, &handle);
        if (!NT_STATUS_IS_OK(status)) {
                printf("Unable to create test directory '%s' - %s\n", DNAME, nt_errstr(status));
                return False;
index 5d0055a1bb2a25ed543fe36b5cd69748a2f769cd..72a75db57e90c3717dcee555ce41683923e66f71 100644 (file)
@@ -37,7 +37,7 @@ BOOL torture_smb2_setinfo(void)
        struct smb2_handle handle;
        char *fname;
        char *fname_new;
-       union smb_fileinfo finfo1, finfo2;
+       union smb_fileinfo finfo2;
        union smb_setfileinfo sfinfo;
        NTSTATUS status, status2;
        const char *call_name;
@@ -77,13 +77,7 @@ BOOL torture_smb2_setinfo(void)
                        nt_errstr(status), nt_errstr(rightstatus)); \
                ret = False; \
        } \
-       finfo1.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION; \
-       finfo1.generic.in.handle = handle; \
-       status2 = smb2_getinfo_file(tree, mem_ctx, &finfo1); \
-       if (!NT_STATUS_IS_OK(status2)) { \
-               printf("(%s) %s pathinfo - %s\n", __location__, #call, nt_errstr(status)); \
-               ret = False; \
-       }} while (0)
+       } while (0)
 
 #define CHECK1(call) \
        do { if (NT_STATUS_IS_OK(status)) { \
@@ -101,7 +95,7 @@ BOOL torture_smb2_setinfo(void)
                printf("(%s) %s - %s/%s should be 0x%x - 0x%x\n", __location__, \
                       call_name, #stype, #field, \
                       (uint_t)value, (uint_t)finfo2.stype.out.field); \
-               dump_all_info(mem_ctx, &finfo1); \
+               torture_smb2_all_info(tree, handle); \
        }} while (0)
 
 #define CHECK_TIME(call, stype, field, value) do { \
@@ -113,7 +107,7 @@ BOOL torture_smb2_setinfo(void)
                        (uint_t)nt_time_to_unix(finfo2.stype.out.field)); \
                printf("\t%s", timestring(mem_ctx, value)); \
                printf("\t%s\n", nt_time_string(mem_ctx, finfo2.stype.out.field)); \
-               dump_all_info(mem_ctx, &finfo1); \
+               torture_smb2_all_info(tree, handle); \
        }} while (0)
 
 #define CHECK_STR(call, stype, field, value) do { \
@@ -123,7 +117,7 @@ BOOL torture_smb2_setinfo(void)
                        call_name, #stype, #field, \
                        value, \
                        finfo2.stype.out.field); \
-               dump_all_info(mem_ctx, &finfo1); \
+               torture_smb2_all_info(tree, handle); \
        }} while (0)
 
 #define CHECK_STATUS(status, correct) do { \
@@ -164,6 +158,21 @@ BOOL torture_smb2_setinfo(void)
        CHECK_TIME(SMB2_ALL_INFORMATION, all_info2, change_time, basetime + 400);
        CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, attrib,     FILE_ATTRIBUTE_NORMAL);
 
+       printf("change the attribute\n");
+       sfinfo.basic_info.in.attrib = FILE_ATTRIBUTE_HIDDEN;
+       CHECK_CALL(BASIC_INFORMATION, NT_STATUS_OK);
+       CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, attrib, FILE_ATTRIBUTE_HIDDEN);
+
+       printf("zero attrib means don't change\n");
+       sfinfo.basic_info.in.attrib = 0;
+       CHECK_CALL(BASIC_INFORMATION, NT_STATUS_OK);
+       CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, attrib, FILE_ATTRIBUTE_HIDDEN);
+
+       printf("restore attribute\n");
+       sfinfo.basic_info.in.attrib = FILE_ATTRIBUTE_NORMAL;
+       CHECK_CALL(BASIC_INFORMATION, NT_STATUS_OK);
+       CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, attrib, FILE_ATTRIBUTE_NORMAL);
+
        printf("test disposition_information level\n");
        sfinfo.disposition_info.in.delete_on_close = 1;
        CHECK_CALL(DISPOSITION_INFORMATION, NT_STATUS_OK);
@@ -199,11 +208,13 @@ BOOL torture_smb2_setinfo(void)
        sfinfo.position_information.in.position = 123456;
        CHECK_CALL(POSITION_INFORMATION, NT_STATUS_OK);
        CHECK_VALUE(POSITION_INFORMATION, position_information, position, 123456);
+       CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, position, 123456);
 
        printf("test mode_information level\n");
        sfinfo.mode_information.in.mode = 2;
        CHECK_CALL(MODE_INFORMATION, NT_STATUS_OK);
        CHECK_VALUE(MODE_INFORMATION, mode_information, mode, 2);
+       CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, mode, 2);
 
        sfinfo.mode_information.in.mode = 1;
        CHECK_CALL(MODE_INFORMATION, NT_STATUS_INVALID_PARAMETER);
index b39f53d8e1e78e973e826abf9e7ac47e20397573..886aaea09fe8f64b18f24b43b0ef7c28dbd8b6fc 100644 (file)
@@ -232,8 +232,8 @@ void torture_smb2_all_info(struct smb2_tree *tree, struct smb2_handle handle)
        d_printf("\tfile_id:        %llu\n", io.all_info2.out.file_id);
        d_printf("\tea_size:        %u\n", io.all_info2.out.ea_size);
        d_printf("\taccess_mask:    0x%08x\n", io.all_info2.out.access_mask);
-       d_printf("\tunknown2:       0x%llx\n", io.all_info2.out.unknown2);
-       d_printf("\tunknown3:       0x%llx\n", io.all_info2.out.unknown3);
+       d_printf("\tposition:       0x%llx\n", io.all_info2.out.position);
+       d_printf("\tmode:           0x%llx\n", io.all_info2.out.mode);
 
        /* short name, if any */
        io.generic.level = RAW_FILEINFO_ALT_NAME_INFORMATION;
@@ -270,14 +270,16 @@ void torture_smb2_all_info(struct smb2_tree *tree, struct smb2_handle handle)
                }
        }       
 
-       /* the security descriptor */
-       io.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
-       io.query_secdesc.secinfo_flags = 
-               SECINFO_OWNER|SECINFO_GROUP|
-               SECINFO_DACL;
-       status = smb2_getinfo_file(tree, tmp_ctx, &io);
-       if (NT_STATUS_IS_OK(status)) {
-               NDR_PRINT_DEBUG(security_descriptor, io.query_secdesc.out.sd);
+       if (DEBUGLVL(1)) {
+               /* the security descriptor */
+               io.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
+               io.query_secdesc.secinfo_flags = 
+                       SECINFO_OWNER|SECINFO_GROUP|
+                       SECINFO_DACL;
+               status = smb2_getinfo_file(tree, tmp_ctx, &io);
+               if (NT_STATUS_IS_OK(status)) {
+                       NDR_PRINT_DEBUG(security_descriptor, io.query_secdesc.out.sd);
+               }
        }
 
        talloc_free(tmp_ctx);   
@@ -394,3 +396,28 @@ NTSTATUS torture_setup_complex_dir(struct smb2_tree *tree, const char *fname)
        return smb2_util_close(tree, handle);
 }
 
+
+/*
+  return a handle to the root of the share
+*/
+NTSTATUS smb2_util_roothandle(struct smb2_tree *tree, struct smb2_handle *handle)
+{
+       struct smb2_create io;
+       NTSTATUS status;
+
+       ZERO_STRUCT(io);
+       io.in.oplock_flags = 0;
+       io.in.access_mask = SEC_STD_SYNCHRONIZE | SEC_DIR_READ_ATTRIBUTE | SEC_DIR_LIST;
+       io.in.file_attr   = 0;
+       io.in.open_disposition = NTCREATEX_DISP_OPEN;
+       io.in.share_access = NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_DELETE;
+       io.in.create_options = NTCREATEX_OPTIONS_ASYNC_ALERT;
+       io.in.fname = "";
+
+       status = smb2_create(tree, tree, &io);
+       NT_STATUS_NOT_OK_RETURN(status);
+
+       *handle = io.out.handle;
+
+       return NT_STATUS_OK;
+}