diff options
-rw-r--r-- | source4/include/smb_interfaces.h | 5 | ||||
-rw-r--r-- | source4/libcli/raw/rawfileinfo.c | 8 | ||||
-rw-r--r-- | source4/libcli/smb2/getinfo.c | 5 | ||||
-rw-r--r-- | source4/libcli/smb2/smb2_calls.h | 6 | ||||
-rw-r--r-- | source4/torture/smb2/getinfo.c | 10 | ||||
-rw-r--r-- | source4/torture/smb2/setinfo.c | 33 | ||||
-rw-r--r-- | source4/torture/smb2/util.c | 47 |
7 files changed, 84 insertions, 30 deletions
diff --git a/source4/include/smb_interfaces.h b/source4/include/smb_interfaces.h index ed01a014c2b..9d42494fc5d 100644 --- a/source4/include/smb_interfaces.h +++ b/source4/include/smb_interfaces.h @@ -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; diff --git a/source4/libcli/raw/rawfileinfo.c b/source4/libcli/raw/rawfileinfo.c index 7119eed5e71..92d31b30ef1 100644 --- a/source4/libcli/raw/rawfileinfo.c +++ b/source4/libcli/raw/rawfileinfo.c @@ -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; diff --git a/source4/libcli/smb2/getinfo.c b/source4/libcli/smb2/getinfo.c index 85411fab925..62418a05b7f 100644 --- a/source4/libcli/smb2/getinfo.c +++ b/source4/libcli/smb2/getinfo.c @@ -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); } diff --git a/source4/libcli/smb2/smb2_calls.h b/source4/libcli/smb2/smb2_calls.h index 1c41d4cd661..e6e1872d5e5 100644 --- a/source4/libcli/smb2/smb2_calls.h +++ b/source4/libcli/smb2/smb2_calls.h @@ -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; diff --git a/source4/torture/smb2/getinfo.c b/source4/torture/smb2/getinfo.c index b8e61ebe344..7c0fe7fbd7d 100644 --- a/source4/torture/smb2/getinfo.c +++ b/source4/torture/smb2/getinfo.c @@ -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; diff --git a/source4/torture/smb2/setinfo.c b/source4/torture/smb2/setinfo.c index 5d0055a1bb2..72a75db57e9 100644 --- a/source4/torture/smb2/setinfo.c +++ b/source4/torture/smb2/setinfo.c @@ -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); diff --git a/source4/torture/smb2/util.c b/source4/torture/smb2/util.c index b39f53d8e1e..886aaea09fe 100644 --- a/source4/torture/smb2/util.c +++ b/source4/torture/smb2/util.c @@ -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; +} |