mirror of
https://github.com/samba-team/samba.git
synced 2025-01-11 05:18:09 +03:00
r11800: - filled in unknown fields in SMB2 all_info level
- allow setting of the ALL_EAS flags bits in SMB2 getinfo
(This used to be commit 8c7c54a46d
)
This commit is contained in:
parent
931b1974a2
commit
7d6f36682e
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user