1
0
mirror of https://github.com/samba-team/samba.git synced 2025-11-07 12:23:51 +03:00

r11758: unified the parse code for the SMB and SMB2 qfsinfo and qfileinfo calls

This commit is contained in:
Andrew Tridgell
2005-11-17 11:06:13 +00:00
committed by Gerald (Jerry) Carter
parent b606d5664d
commit ba897e537b
7 changed files with 335 additions and 440 deletions

View File

@@ -315,7 +315,6 @@ enum smb_fileinfo_level {
RAW_FILEINFO_ACCESS_INFORMATION = SMB_QFILEINFO_ACCESS_INFORMATION, RAW_FILEINFO_ACCESS_INFORMATION = SMB_QFILEINFO_ACCESS_INFORMATION,
RAW_FILEINFO_NAME_INFORMATION = SMB_QFILEINFO_NAME_INFORMATION, RAW_FILEINFO_NAME_INFORMATION = SMB_QFILEINFO_NAME_INFORMATION,
RAW_FILEINFO_POSITION_INFORMATION = SMB_QFILEINFO_POSITION_INFORMATION, RAW_FILEINFO_POSITION_INFORMATION = SMB_QFILEINFO_POSITION_INFORMATION,
RAW_FILEINFO_FULL_EA_INFORMATION = SMB_QFILEINFO_FULL_EA_INFORMATION,
RAW_FILEINFO_MODE_INFORMATION = SMB_QFILEINFO_MODE_INFORMATION, RAW_FILEINFO_MODE_INFORMATION = SMB_QFILEINFO_MODE_INFORMATION,
RAW_FILEINFO_ALIGNMENT_INFORMATION = SMB_QFILEINFO_ALIGNMENT_INFORMATION, RAW_FILEINFO_ALIGNMENT_INFORMATION = SMB_QFILEINFO_ALIGNMENT_INFORMATION,
RAW_FILEINFO_ALL_INFORMATION = SMB_QFILEINFO_ALL_INFORMATION, RAW_FILEINFO_ALL_INFORMATION = SMB_QFILEINFO_ALL_INFORMATION,
@@ -323,7 +322,17 @@ enum smb_fileinfo_level {
RAW_FILEINFO_STREAM_INFORMATION = SMB_QFILEINFO_STREAM_INFORMATION, RAW_FILEINFO_STREAM_INFORMATION = SMB_QFILEINFO_STREAM_INFORMATION,
RAW_FILEINFO_COMPRESSION_INFORMATION = SMB_QFILEINFO_COMPRESSION_INFORMATION, RAW_FILEINFO_COMPRESSION_INFORMATION = SMB_QFILEINFO_COMPRESSION_INFORMATION,
RAW_FILEINFO_NETWORK_OPEN_INFORMATION = SMB_QFILEINFO_NETWORK_OPEN_INFORMATION, RAW_FILEINFO_NETWORK_OPEN_INFORMATION = SMB_QFILEINFO_NETWORK_OPEN_INFORMATION,
RAW_FILEINFO_ATTRIBUTE_TAG_INFORMATION = SMB_QFILEINFO_ATTRIBUTE_TAG_INFORMATION RAW_FILEINFO_ATTRIBUTE_TAG_INFORMATION = SMB_QFILEINFO_ATTRIBUTE_TAG_INFORMATION,
/* SMB2 specific levels */
RAW_FILEINFO_SMB2_ALL_EAS = 0x0f01,
RAW_FILEINFO_SMB2_ALL_INFORMATION = 0x1201
};
/*
file handles in SMB2 are 16 bytes
*/
struct smb2_handle {
uint64_t data[2];
}; };
@@ -335,11 +344,14 @@ union smb_fileinfo {
enum smb_fileinfo_level level; enum smb_fileinfo_level level;
/* each level can be called on either a pathname or a /* each level can be called on either a pathname or a
* filename, in either case the return format is filename, in either case the return format is
* identical */ identical
On SMB2 a 16 byte handle is used
*/
union smb_fileinfo_in { union smb_fileinfo_in {
const char *fname; const char *fname;
uint16_t fnum; uint16_t fnum;
struct smb2_handle handle;
} in; } in;
struct { struct {
@@ -445,7 +457,7 @@ union smb_fileinfo {
} out; } out;
} ea_list; } ea_list;
/* trans2 RAW_FILEINFO_ALL_EAS interface */ /* trans2 RAW_FILEINFO_ALL_EAS and RAW_FILEINFO_FULL_EA_INFORMATION interfaces */
struct { struct {
enum smb_fileinfo_level level; enum smb_fileinfo_level level;
union smb_fileinfo_in in; union smb_fileinfo_in in;
@@ -530,6 +542,33 @@ union smb_fileinfo {
} out; } out;
} all_info; } all_info;
/* RAW_FILEINFO_SMB2_ALL_INFORMATION interface */
struct {
enum smb_fileinfo_level level;
union smb_fileinfo_in in;
struct {
NTTIME create_time;
NTTIME access_time;
NTTIME write_time;
NTTIME change_time;
uint32_t attrib;
uint32_t unknown1;
uint64_t alloc_size;
uint64_t size;
uint32_t nlink;
uint8_t delete_pending;
uint8_t directory;
/* uint16_t _pad; */
uint64_t file_id;
uint32_t ea_size;
uint32_t access_mask;
uint64_t unknown2;
uint64_t unknown3;
WIRE_STRING fname;
} out;
} all_info2;
/* RAW_FILEINFO_ALT_NAME_INFO and RAW_FILEINFO_ALT_NAME_INFORMATION interfaces */ /* RAW_FILEINFO_ALT_NAME_INFO and RAW_FILEINFO_ALT_NAME_INFORMATION interfaces */
struct { struct {
enum smb_fileinfo_level level; enum smb_fileinfo_level level;
@@ -917,6 +956,7 @@ union smb_fsinfo {
/* generic interface */ /* generic interface */
struct { struct {
enum smb_fsinfo_level level; enum smb_fsinfo_level level;
struct smb2_handle handle; /* only for smb2 */
struct { struct {
uint32_t block_size; uint32_t block_size;
@@ -976,6 +1016,7 @@ union smb_fsinfo {
/* TRANS2 RAW_QFS_VOLUME_INFO and RAW_QFS_VOLUME_INFORMATION interfaces */ /* TRANS2 RAW_QFS_VOLUME_INFO and RAW_QFS_VOLUME_INFORMATION interfaces */
struct { struct {
enum smb_fsinfo_level level; enum smb_fsinfo_level level;
struct smb2_handle handle; /* only for smb2 */
struct { struct {
NTTIME create_time; NTTIME create_time;
@@ -987,6 +1028,7 @@ union smb_fsinfo {
/* trans2 RAW_QFS_SIZE_INFO and RAW_QFS_SIZE_INFORMATION interfaces */ /* trans2 RAW_QFS_SIZE_INFO and RAW_QFS_SIZE_INFORMATION interfaces */
struct { struct {
enum smb_fsinfo_level level; enum smb_fsinfo_level level;
struct smb2_handle handle; /* only for smb2 */
struct { struct {
uint64_t total_alloc_units; uint64_t total_alloc_units;
@@ -999,6 +1041,7 @@ union smb_fsinfo {
/* TRANS2 RAW_QFS_DEVICE_INFO and RAW_QFS_DEVICE_INFORMATION interfaces */ /* TRANS2 RAW_QFS_DEVICE_INFO and RAW_QFS_DEVICE_INFORMATION interfaces */
struct { struct {
enum smb_fsinfo_level level; enum smb_fsinfo_level level;
struct smb2_handle handle; /* only for smb2 */
struct { struct {
uint32_t device_type; uint32_t device_type;
@@ -1010,6 +1053,7 @@ union smb_fsinfo {
/* TRANS2 RAW_QFS_ATTRIBUTE_INFO and RAW_QFS_ATTRIBUTE_INFORMATION interfaces */ /* TRANS2 RAW_QFS_ATTRIBUTE_INFO and RAW_QFS_ATTRIBUTE_INFORMATION interfaces */
struct { struct {
enum smb_fsinfo_level level; enum smb_fsinfo_level level;
struct smb2_handle handle; /* only for smb2 */
struct { struct {
uint32_t fs_attr; uint32_t fs_attr;
@@ -1033,6 +1077,7 @@ union smb_fsinfo {
/* trans2 RAW_QFS_QUOTA_INFORMATION interface */ /* trans2 RAW_QFS_QUOTA_INFORMATION interface */
struct { struct {
enum smb_fsinfo_level level; enum smb_fsinfo_level level;
struct smb2_handle handle; /* only for smb2 */
struct { struct {
uint64_t unknown[3]; uint64_t unknown[3];
@@ -1045,6 +1090,7 @@ union smb_fsinfo {
/* trans2 RAW_QFS_FULL_SIZE_INFORMATION interface */ /* trans2 RAW_QFS_FULL_SIZE_INFORMATION interface */
struct { struct {
enum smb_fsinfo_level level; enum smb_fsinfo_level level;
struct smb2_handle handle; /* only for smb2 */
struct { struct {
uint64_t total_alloc_units; uint64_t total_alloc_units;
@@ -1058,6 +1104,7 @@ union smb_fsinfo {
/* trans2 RAW_QFS_OBJECTID_INFORMATION interface */ /* trans2 RAW_QFS_OBJECTID_INFORMATION interface */
struct { struct {
enum smb_fsinfo_level level; enum smb_fsinfo_level level;
struct smb2_handle handle; /* only for smb2 */
struct { struct {
struct GUID guid; struct GUID guid;

View File

@@ -147,7 +147,6 @@ Found 8 aliased levels
#define SMB_QFILEINFO_ACCESS_INFORMATION 1008 #define SMB_QFILEINFO_ACCESS_INFORMATION 1008
#define SMB_QFILEINFO_NAME_INFORMATION 1009 #define SMB_QFILEINFO_NAME_INFORMATION 1009
#define SMB_QFILEINFO_POSITION_INFORMATION 1014 #define SMB_QFILEINFO_POSITION_INFORMATION 1014
#define SMB_QFILEINFO_FULL_EA_INFORMATION 1015 /* only on SMB2 */
#define SMB_QFILEINFO_MODE_INFORMATION 1016 #define SMB_QFILEINFO_MODE_INFORMATION 1016
#define SMB_QFILEINFO_ALIGNMENT_INFORMATION 1017 #define SMB_QFILEINFO_ALIGNMENT_INFORMATION 1017
#define SMB_QFILEINFO_ALL_INFORMATION 1018 #define SMB_QFILEINFO_ALL_INFORMATION 1018

View File

@@ -176,12 +176,6 @@ NTSTATUS smb_raw_fileinfo_passthru_parse(const DATA_BLOB *blob, TALLOC_CTX *mem_
parms->position_information.out.position = BVAL(blob->data, 0); parms->position_information.out.position = BVAL(blob->data, 0);
return NT_STATUS_OK; return NT_STATUS_OK;
case RAW_FILEINFO_FULL_EA_INFORMATION:
FINFO_CHECK_MIN_SIZE(4);
return ea_pull_list_chained(blob, mem_ctx,
&parms->all_eas.out.num_eas,
&parms->all_eas.out.eas);
case RAW_FILEINFO_MODE_INFORMATION: case RAW_FILEINFO_MODE_INFORMATION:
FINFO_CHECK_SIZE(4); FINFO_CHECK_SIZE(4);
parms->mode_information.out.mode = IVAL(blob->data, 0); parms->mode_information.out.mode = IVAL(blob->data, 0);
@@ -220,6 +214,51 @@ NTSTATUS smb_raw_fileinfo_passthru_parse(const DATA_BLOB *blob, TALLOC_CTX *mem_
parms->attribute_tag_information.out.reparse_tag = IVAL(blob->data, 4); parms->attribute_tag_information.out.reparse_tag = IVAL(blob->data, 4);
return NT_STATUS_OK; return NT_STATUS_OK;
case RAW_FILEINFO_SMB2_ALL_EAS:
FINFO_CHECK_MIN_SIZE(4);
return ea_pull_list_chained(blob, mem_ctx,
&parms->all_eas.out.num_eas,
&parms->all_eas.out.eas);
case RAW_FILEINFO_SMB2_ALL_INFORMATION:
FINFO_CHECK_MIN_SIZE(0x64);
parms->all_info2.out.create_time = smbcli_pull_nttime(blob->data, 0x00);
parms->all_info2.out.access_time = smbcli_pull_nttime(blob->data, 0x08);
parms->all_info2.out.write_time = smbcli_pull_nttime(blob->data, 0x10);
parms->all_info2.out.change_time = smbcli_pull_nttime(blob->data, 0x18);
parms->all_info2.out.attrib = IVAL(blob->data, 0x20);
parms->all_info2.out.unknown1 = IVAL(blob->data, 0x24);
parms->all_info2.out.alloc_size = BVAL(blob->data, 0x28);
parms->all_info2.out.size = BVAL(blob->data, 0x30);
parms->all_info2.out.nlink = IVAL(blob->data, 0x38);
parms->all_info2.out.delete_pending = CVAL(blob->data, 0x3C);
parms->all_info2.out.directory = CVAL(blob->data, 0x3D);
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);
smbcli_blob_pull_string(NULL, mem_ctx, blob,
&parms->all_info2.out.fname, 0x60, 0x64, STR_UNICODE);
return NT_STATUS_OK;
case RAW_FILEINFO_SEC_DESC: {
struct ndr_pull *ndr;
NTSTATUS status;
ndr = ndr_pull_init_blob(blob, mem_ctx);
if (!ndr) {
return NT_STATUS_NO_MEMORY;
}
parms->query_secdesc.out.sd = talloc(mem_ctx, struct security_descriptor);
if (parms->query_secdesc.out.sd == NULL) {
return NT_STATUS_NO_MEMORY;
}
status = ndr_pull_security_descriptor(ndr, NDR_SCALARS|NDR_BUFFERS,
parms->query_secdesc.out.sd);
talloc_free(ndr);
return status;
}
default: default:
break; break;
} }
@@ -335,10 +374,6 @@ static NTSTATUS smb_raw_info_backend(struct smbcli_session *session,
return smb_raw_fileinfo_passthru_parse(blob, mem_ctx, return smb_raw_fileinfo_passthru_parse(blob, mem_ctx,
RAW_FILEINFO_POSITION_INFORMATION, parms); RAW_FILEINFO_POSITION_INFORMATION, parms);
case RAW_FILEINFO_FULL_EA_INFORMATION:
return smb_raw_fileinfo_passthru_parse(blob, mem_ctx,
RAW_FILEINFO_FULL_EA_INFORMATION, parms);
case RAW_FILEINFO_MODE_INFORMATION: case RAW_FILEINFO_MODE_INFORMATION:
return smb_raw_fileinfo_passthru_parse(blob, mem_ctx, return smb_raw_fileinfo_passthru_parse(blob, mem_ctx,
RAW_FILEINFO_MODE_INFORMATION, parms); RAW_FILEINFO_MODE_INFORMATION, parms);
@@ -381,6 +416,15 @@ static NTSTATUS smb_raw_info_backend(struct smbcli_session *session,
case RAW_FILEINFO_ATTRIBUTE_TAG_INFORMATION: case RAW_FILEINFO_ATTRIBUTE_TAG_INFORMATION:
return smb_raw_fileinfo_passthru_parse(blob, mem_ctx, return smb_raw_fileinfo_passthru_parse(blob, mem_ctx,
RAW_FILEINFO_ATTRIBUTE_TAG_INFORMATION, parms); RAW_FILEINFO_ATTRIBUTE_TAG_INFORMATION, parms);
case RAW_FILEINFO_SMB2_ALL_INFORMATION:
return smb_raw_fileinfo_passthru_parse(blob, mem_ctx,
RAW_FILEINFO_SMB2_ALL_INFORMATION, parms);
case RAW_FILEINFO_SMB2_ALL_EAS:
return smb_raw_fileinfo_passthru_parse(blob, mem_ctx,
RAW_FILEINFO_SMB2_ALL_EAS, parms);
} }
return NT_STATUS_INVALID_LEVEL; return NT_STATUS_INVALID_LEVEL;

View File

@@ -41,8 +41,8 @@ struct smb2_request *smb2_getinfo_send(struct smb2_tree *tree, struct smb2_getin
SSVAL(req->out.body, 0x02, io->in.level); SSVAL(req->out.body, 0x02, io->in.level);
SIVAL(req->out.body, 0x04, io->in.max_response_size); SIVAL(req->out.body, 0x04, io->in.max_response_size);
SIVAL(req->out.body, 0x08, io->in.unknown1); SIVAL(req->out.body, 0x08, io->in.unknown1);
SIVAL(req->out.body, 0x0C, io->in.flags); SIVAL(req->out.body, 0x0C, io->in.unknown2);
SIVAL(req->out.body, 0x10, io->in.unknown3); SIVAL(req->out.body, 0x10, io->in.flags);
SIVAL(req->out.body, 0x14, io->in.unknown4); SIVAL(req->out.body, 0x14, io->in.unknown4);
smb2_push_handle(req->out.body+0x18, &io->in.handle); smb2_push_handle(req->out.body+0x18, &io->in.handle);
@@ -86,204 +86,11 @@ NTSTATUS smb2_getinfo(struct smb2_tree *tree, TALLOC_CTX *mem_ctx,
} }
/*
parse a returned getinfo data blob
*/
NTSTATUS smb2_getinfo_parse(TALLOC_CTX *mem_ctx,
uint16_t level,
DATA_BLOB blob,
union smb2_fileinfo *io)
{
switch (level) {
case SMB2_GETINFO_FILE_BASIC_INFO:
if (blob.length != 0x28) {
return NT_STATUS_INFO_LENGTH_MISMATCH;
}
io->basic_info.create_time = smbcli_pull_nttime(blob.data, 0x00);
io->basic_info.access_time = smbcli_pull_nttime(blob.data, 0x08);
io->basic_info.write_time = smbcli_pull_nttime(blob.data, 0x10);
io->basic_info.change_time = smbcli_pull_nttime(blob.data, 0x18);
io->basic_info.file_attr = IVAL(blob.data, 0x20);
io->basic_info.unknown = IVAL(blob.data, 0x24);
break;
case SMB2_GETINFO_FILE_SIZE_INFO:
if (blob.length != 0x18) {
return NT_STATUS_INFO_LENGTH_MISMATCH;
}
io->size_info.alloc_size = BVAL(blob.data, 0x00);
io->size_info.size = BVAL(blob.data, 0x08);
io->size_info.nlink = IVAL(blob.data, 0x10);
io->size_info.delete_pending = CVAL(blob.data, 0x14);
io->size_info.directory = CVAL(blob.data, 0x15);
break;
case SMB2_GETINFO_FILE_ID:
if (blob.length != 0x8) {
return NT_STATUS_INFO_LENGTH_MISMATCH;
}
io->file_id.file_id = BVAL(blob.data, 0x00);
break;
case SMB2_GETINFO_FILE_EA_SIZE:
if (blob.length != 0x4) {
return NT_STATUS_INFO_LENGTH_MISMATCH;
}
io->ea_size.ea_size = IVAL(blob.data, 0x00);
break;
case SMB2_GETINFO_FILE_ACCESS_INFO:
if (blob.length != 0x4) {
return NT_STATUS_INFO_LENGTH_MISMATCH;
}
io->access_info.access_mask = IVAL(blob.data, 0x00);
break;
case SMB2_GETINFO_FILE_0E:
if (blob.length != 0x8) {
return NT_STATUS_INFO_LENGTH_MISMATCH;
}
io->unknown0e.unknown1 = IVAL(blob.data, 0x00);
io->unknown0e.unknown2 = IVAL(blob.data, 0x04);
break;
case SMB2_GETINFO_FILE_ALL_EAS:
return ea_pull_list_chained(&blob, mem_ctx,
&io->all_eas.num_eas,
&io->all_eas.eas);
case SMB2_GETINFO_FILE_10:
if (blob.length != 0x4) {
return NT_STATUS_INFO_LENGTH_MISMATCH;
}
io->unknown10.unknown = IVAL(blob.data, 0x00);
break;
case SMB2_GETINFO_FILE_11:
if (blob.length != 0x4) {
return NT_STATUS_INFO_LENGTH_MISMATCH;
}
io->unknown11.unknown = IVAL(blob.data, 0x00);
break;
case SMB2_GETINFO_FILE_ALL_INFO: {
uint32_t nlen;
ssize_t size;
void *vstr;
if (blob.length < 0x64) {
return NT_STATUS_INFO_LENGTH_MISMATCH;
}
io->all_info.create_time = smbcli_pull_nttime(blob.data, 0x00);
io->all_info.access_time = smbcli_pull_nttime(blob.data, 0x08);
io->all_info.write_time = smbcli_pull_nttime(blob.data, 0x10);
io->all_info.change_time = smbcli_pull_nttime(blob.data, 0x18);
io->all_info.file_attr = IVAL(blob.data, 0x20);
io->all_info.unknown1 = IVAL(blob.data, 0x24);
io->all_info.alloc_size = BVAL(blob.data, 0x28);
io->all_info.size = BVAL(blob.data, 0x30);
io->all_info.nlink = IVAL(blob.data, 0x38);
io->all_info.delete_pending = CVAL(blob.data, 0x3C);
io->all_info.directory = CVAL(blob.data, 0x3D);
io->all_info.file_id = BVAL(blob.data, 0x40);
io->all_info.ea_size = IVAL(blob.data, 0x48);
io->all_info.access_mask = IVAL(blob.data, 0x4C);
io->all_info.unknown5 = BVAL(blob.data, 0x50);
io->all_info.unknown6 = BVAL(blob.data, 0x58);
nlen = IVAL(blob.data, 0x60);
if (nlen > blob.length - 0x64) {
return NT_STATUS_INFO_LENGTH_MISMATCH;
}
size = convert_string_talloc(mem_ctx, CH_UTF16, CH_UNIX,
blob.data+0x64, nlen, &vstr);
if (size == -1) {
return NT_STATUS_ILLEGAL_CHARACTER;
}
io->all_info.fname = vstr;
break;
}
case SMB2_GETINFO_FILE_SHORT_INFO: {
uint32_t nlen;
ssize_t size;
void *vstr;
if (blob.length < 0x04) {
return NT_STATUS_INFO_LENGTH_MISMATCH;
}
nlen = IVAL(blob.data, 0x00);
if (nlen > blob.length - 0x04) {
return NT_STATUS_INFO_LENGTH_MISMATCH;
}
size = convert_string_talloc(mem_ctx, CH_UTF16, CH_UNIX,
blob.data+0x04, nlen, &vstr);
if (size == -1) {
return NT_STATUS_ILLEGAL_CHARACTER;
}
io->short_info.short_name = vstr;
break;
}
case SMB2_GETINFO_FILE_STREAM_INFO:
return smbcli_parse_stream_info(blob, mem_ctx, &io->stream_info);
case SMB2_GETINFO_FILE_EOF_INFO:
if (blob.length != 0x10) {
return NT_STATUS_INFO_LENGTH_MISMATCH;
}
io->eof_info.size = BVAL(blob.data, 0x00);
io->eof_info.unknown = BVAL(blob.data, 0x08);
break;
case SMB2_GETINFO_FILE_STANDARD_INFO:
if (blob.length != 0x38) {
return NT_STATUS_INFO_LENGTH_MISMATCH;
}
io->standard_info.create_time = smbcli_pull_nttime(blob.data, 0x00);
io->standard_info.access_time = smbcli_pull_nttime(blob.data, 0x08);
io->standard_info.write_time = smbcli_pull_nttime(blob.data, 0x10);
io->standard_info.change_time = smbcli_pull_nttime(blob.data, 0x18);
io->standard_info.alloc_size = BVAL(blob.data, 0x20);
io->standard_info.size = BVAL(blob.data, 0x28);
io->standard_info.file_attr = IVAL(blob.data, 0x30);
io->standard_info.unknown = IVAL(blob.data, 0x34);
break;
case SMB2_GETINFO_FILE_ATTRIB_INFO:
if (blob.length != 0x08) {
return NT_STATUS_INFO_LENGTH_MISMATCH;
}
io->attrib_info.file_attr = IVAL(blob.data, 0x00);
io->attrib_info.unknown = IVAL(blob.data, 0x04);
break;
case SMB2_GETINFO_SECURITY: {
struct ndr_pull *ndr;
NTSTATUS status;
ndr = ndr_pull_init_blob(&blob, mem_ctx);
if (!ndr) {
return NT_STATUS_NO_MEMORY;
}
io->security.sd = talloc(mem_ctx, struct security_descriptor);
if (io->security.sd == NULL) {
return NT_STATUS_NO_MEMORY;
}
status = ndr_pull_security_descriptor(ndr, NDR_SCALARS|NDR_BUFFERS, io->security.sd);
talloc_free(ndr);
return status;
}
default:
return NT_STATUS_INVALID_INFO_CLASS;
}
return NT_STATUS_OK;
}
/* /*
recv a getinfo reply and parse the level info recv a getinfo reply and parse the level info
*/ */
NTSTATUS smb2_getinfo_level_recv(struct smb2_request *req, TALLOC_CTX *mem_ctx, NTSTATUS smb2_getinfo_file_recv(struct smb2_request *req, TALLOC_CTX *mem_ctx,
uint16_t level, union smb2_fileinfo *io) union smb_fileinfo *io)
{ {
struct smb2_getinfo b; struct smb2_getinfo b;
NTSTATUS status; NTSTATUS status;
@@ -291,7 +98,7 @@ NTSTATUS smb2_getinfo_level_recv(struct smb2_request *req, TALLOC_CTX *mem_ctx,
status = smb2_getinfo_recv(req, mem_ctx, &b); status = smb2_getinfo_recv(req, mem_ctx, &b);
NT_STATUS_NOT_OK_RETURN(status); NT_STATUS_NOT_OK_RETURN(status);
status = smb2_getinfo_parse(mem_ctx, level, b.out.blob, io); status = smb_raw_fileinfo_passthru_parse(&b.out.blob, mem_ctx, io->generic.level, io);
data_blob_free(&b.out.blob); data_blob_free(&b.out.blob);
return status; return status;
@@ -300,19 +107,83 @@ NTSTATUS smb2_getinfo_level_recv(struct smb2_request *req, TALLOC_CTX *mem_ctx,
/* /*
level specific getinfo call level specific getinfo call
*/ */
NTSTATUS smb2_getinfo_level(struct smb2_tree *tree, TALLOC_CTX *mem_ctx, NTSTATUS smb2_getinfo_file(struct smb2_tree *tree, TALLOC_CTX *mem_ctx,
struct smb2_handle handle, union smb_fileinfo *io)
uint16_t level, union smb2_fileinfo *io)
{ {
struct smb2_getinfo b; struct smb2_getinfo b;
struct smb2_request *req; struct smb2_request *req;
uint16_t smb2_level;
if (io->generic.level == RAW_FILEINFO_SEC_DESC) {
smb2_level = SMB2_GETINFO_SECURITY;
} else if ((io->generic.level & 0xFF) == SMB2_GETINFO_FILE) {
smb2_level = io->generic.level;
} else if (io->generic.level > 1000) {
smb2_level = ((io->generic.level-1000)<<8) | SMB2_GETINFO_FILE;
} else {
/* SMB2 only does the passthru levels */
return NT_STATUS_INVALID_LEVEL;
}
ZERO_STRUCT(b); ZERO_STRUCT(b);
b.in.max_response_size = 0x10000; b.in.max_response_size = 0x10000;
b.in.handle = handle; b.in.handle = io->generic.in.handle;
b.in.level = level; b.in.level = smb2_level;
if (io->generic.level == RAW_FILEINFO_SEC_DESC) {
b.in.flags = io->query_secdesc.secinfo_flags;
}
req = smb2_getinfo_send(tree, &b); req = smb2_getinfo_send(tree, &b);
return smb2_getinfo_level_recv(req, mem_ctx, level, io); return smb2_getinfo_file_recv(req, mem_ctx, io);
} }
/*
recv a getinfo reply and parse the level info
*/
NTSTATUS smb2_getinfo_fs_recv(struct smb2_request *req, TALLOC_CTX *mem_ctx,
union smb_fsinfo *io)
{
struct smb2_getinfo b;
NTSTATUS status;
status = smb2_getinfo_recv(req, mem_ctx, &b);
NT_STATUS_NOT_OK_RETURN(status);
status = smb_raw_fsinfo_passthru_parse(b.out.blob, mem_ctx, io->generic.level, io);
data_blob_free(&b.out.blob);
return status;
}
/*
level specific getinfo call
*/
NTSTATUS smb2_getinfo_fs(struct smb2_tree *tree, TALLOC_CTX *mem_ctx,
union smb_fsinfo *io)
{
struct smb2_getinfo b;
struct smb2_request *req;
uint16_t smb2_level;
if ((io->generic.level & 0xFF) == SMB2_GETINFO_FS) {
smb2_level = io->generic.level;
} else if (io->generic.level > 1000) {
smb2_level = ((io->generic.level-1000)<<8) | SMB2_GETINFO_FS;
} else {
/* SMB2 only does the passthru levels */
return NT_STATUS_INVALID_LEVEL;
}
ZERO_STRUCT(b);
b.in.max_response_size = 0x10000;
b.in.handle = io->generic.handle;
b.in.level = smb2_level;
req = smb2_getinfo_send(tree, &b);
return smb2_getinfo_fs_recv(req, mem_ctx, io);
}

View File

@@ -103,14 +103,6 @@ struct smb2_tree_connect {
} out; } out;
}; };
/*
file handles in SMB2 are 16 bytes
*/
struct smb2_handle {
uint64_t data[2];
};
#define SMB2_CREATE_FLAG_REQUEST_OPLOCK 0x0100 #define SMB2_CREATE_FLAG_REQUEST_OPLOCK 0x0100
#define SMB2_CREATE_FLAG_REQUEST_EXCLUSIVE_OPLOCK 0x0800 #define SMB2_CREATE_FLAG_REQUEST_EXCLUSIVE_OPLOCK 0x0800
#define SMB2_CREATE_FLAG_GRANT_OPLOCK 0x0001 #define SMB2_CREATE_FLAG_GRANT_OPLOCK 0x0001
@@ -190,35 +182,14 @@ struct smb2_close {
} out; } out;
}; };
/* fs information levels */ /* getinfo classes */
#define SMB2_GETINFO_FS_VOLUME_INFO 0x0102 #define SMB2_GETINFO_FILE 0x01
#define SMB2_GETINFO_FS_SIZE_INFO 0x0302 #define SMB2_GETINFO_FS 0x02
#define SMB2_GETINFO_FS_DEVICE_INFO 0x0402 #define SMB2_GETINFO_SECURITY 0x03
#define SMB2_GETINFO_FS_ATTRIBUTE_INFO 0x0502
#define SMB2_GETINFO_FS_QUOTA_INFO 0x0602
#define SMB2_GETINFO_FS_FULL_SIZE_INFO 0x0702
#define SMB2_GETINFO_FS_OBJECTID_INFO 0x0802
/* class 3 levels */
#define SMB2_GETINFO_SECURITY 0x0003
/* file information levels */
#define SMB2_GETINFO_FILE_BASIC_INFO 0x0401
#define SMB2_GETINFO_FILE_SIZE_INFO 0x0501
#define SMB2_GETINFO_FILE_ID 0x0601
#define SMB2_GETINFO_FILE_EA_SIZE 0x0701
#define SMB2_GETINFO_FILE_ACCESS_INFO 0x0801
#define SMB2_GETINFO_FILE_0E 0x0e01
#define SMB2_GETINFO_FILE_ALL_EAS 0x0f01
#define SMB2_GETINFO_FILE_10 0x1001
#define SMB2_GETINFO_FILE_11 0x1101
#define SMB2_GETINFO_FILE_ALL_INFO 0x1201
#define SMB2_GETINFO_FILE_SHORT_INFO 0x1501
#define SMB2_GETINFO_FILE_STREAM_INFO 0x1601
#define SMB2_GETINFO_FILE_EOF_INFO 0x1c01
#define SMB2_GETINFO_FILE_STANDARD_INFO 0x2201
#define SMB2_GETINFO_FILE_ATTRIB_INFO 0x2301
/* 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 */
struct smb2_getinfo { struct smb2_getinfo {
struct { struct {
@@ -227,8 +198,8 @@ struct smb2_getinfo {
uint16_t level; uint16_t level;
uint32_t max_response_size; uint32_t max_response_size;
uint32_t unknown1; uint32_t unknown1;
uint32_t unknown2;
uint32_t flags; /* level specific */ uint32_t flags; /* level specific */
uint32_t unknown3;
uint32_t unknown4; uint32_t unknown4;
struct smb2_handle handle; struct smb2_handle handle;
} in; } in;
@@ -244,105 +215,6 @@ struct smb2_getinfo {
} out; } out;
}; };
union smb2_fileinfo {
struct {
NTTIME create_time;
NTTIME access_time;
NTTIME write_time;
NTTIME change_time;
uint32_t file_attr;
uint32_t unknown;
} basic_info;
struct {
uint64_t alloc_size;
uint64_t size;
uint32_t nlink;
uint8_t delete_pending;
uint8_t directory;
} size_info;
struct {
uint64_t file_id;
} file_id;
struct {
uint32_t ea_size;
} ea_size;
struct {
uint32_t access_mask;
} access_info;
struct {
uint32_t unknown1;
uint32_t unknown2;
} unknown0e;
struct smb_ea_list all_eas;
struct {
uint32_t unknown;
} unknown10;
struct {
uint32_t unknown;
} unknown11;
struct {
NTTIME create_time;
NTTIME access_time;
NTTIME write_time;
NTTIME change_time;
uint32_t file_attr;
uint32_t unknown1;
uint64_t alloc_size;
uint64_t size;
uint32_t nlink;
uint8_t delete_pending;
uint8_t directory;
/* uint16_t _pad; */
uint64_t file_id;
uint32_t ea_size;
uint32_t access_mask;
uint64_t unknown5;
uint64_t unknown6;
const char *fname;
} all_info;
struct {
const char *short_name;
} short_info;
struct stream_information stream_info;
struct {
uint64_t size;
uint64_t unknown;
} eof_info;
struct {
NTTIME create_time;
NTTIME access_time;
NTTIME write_time;
NTTIME change_time;
uint64_t alloc_size;
uint64_t size;
uint32_t file_attr;
uint32_t unknown;
} standard_info;
struct {
uint32_t file_attr;
uint32_t unknown;
} attrib_info;
struct {
struct security_descriptor *sd;
} security;
};
struct smb2_write { struct smb2_write {
struct { struct {
/* static body buffer 48 (0x30) bytes */ /* static body buffer 48 (0x30) bytes */

View File

@@ -23,63 +23,63 @@
#include "includes.h" #include "includes.h"
#include "libcli/smb2/smb2.h" #include "libcli/smb2/smb2.h"
#include "libcli/smb2/smb2_calls.h" #include "libcli/smb2/smb2_calls.h"
#include "librpc/gen_ndr/security.h"
static struct { static struct {
const char *name; const char *name;
uint16_t level; uint16_t level;
NTSTATUS fstatus; NTSTATUS fstatus;
NTSTATUS dstatus; NTSTATUS dstatus;
union smb2_fileinfo finfo; union smb_fileinfo finfo;
union smb2_fileinfo dinfo; union smb_fileinfo dinfo;
} levels[] = { } file_levels[] = {
#define LEVEL(x) #x, x #define LEVEL(x) #x, x
{ LEVEL(SMB2_GETINFO_FS_VOLUME_INFO) }, { LEVEL(RAW_FILEINFO_BASIC_INFORMATION) },
{ LEVEL(SMB2_GETINFO_FS_SIZE_INFO) }, { LEVEL(RAW_FILEINFO_STANDARD_INFORMATION) },
{ LEVEL(SMB2_GETINFO_FS_DEVICE_INFO) }, { LEVEL(RAW_FILEINFO_INTERNAL_INFORMATION) },
{ LEVEL(SMB2_GETINFO_FS_ATTRIBUTE_INFO) }, { LEVEL(RAW_FILEINFO_EA_INFORMATION) },
{ LEVEL(SMB2_GETINFO_FS_QUOTA_INFO) }, { LEVEL(RAW_FILEINFO_ACCESS_INFORMATION) },
{ LEVEL(SMB2_GETINFO_FS_FULL_SIZE_INFO) }, { LEVEL(RAW_FILEINFO_POSITION_INFORMATION) },
{ LEVEL(SMB2_GETINFO_FS_OBJECTID_INFO) }, { LEVEL(RAW_FILEINFO_MODE_INFORMATION) },
{ LEVEL(SMB2_GETINFO_SECURITY) }, { LEVEL(RAW_FILEINFO_ALIGNMENT_INFORMATION) },
{ LEVEL(SMB2_GETINFO_FILE_BASIC_INFO) }, { LEVEL(RAW_FILEINFO_ALL_INFORMATION) },
{ LEVEL(SMB2_GETINFO_FILE_SIZE_INFO) }, { LEVEL(RAW_FILEINFO_ALT_NAME_INFORMATION) },
{ LEVEL(SMB2_GETINFO_FILE_ID) }, { LEVEL(RAW_FILEINFO_STREAM_INFORMATION) },
{ LEVEL(SMB2_GETINFO_FILE_EA_SIZE) }, { LEVEL(RAW_FILEINFO_COMPRESSION_INFORMATION) },
{ LEVEL(SMB2_GETINFO_FILE_ACCESS_INFO) }, { LEVEL(RAW_FILEINFO_NETWORK_OPEN_INFORMATION) },
{ LEVEL(SMB2_GETINFO_FILE_0E) }, { LEVEL(RAW_FILEINFO_ATTRIBUTE_TAG_INFORMATION) },
{ LEVEL(SMB2_GETINFO_FILE_ALL_EAS) }, { LEVEL(RAW_FILEINFO_SMB2_ALL_EAS) },
{ LEVEL(SMB2_GETINFO_FILE_10) }, { LEVEL(RAW_FILEINFO_SMB2_ALL_INFORMATION) },
{ LEVEL(SMB2_GETINFO_FILE_11) }, { LEVEL(RAW_FILEINFO_SEC_DESC) }
{ LEVEL(SMB2_GETINFO_FILE_ALL_INFO) }, };
{ LEVEL(SMB2_GETINFO_FILE_SHORT_INFO) },
{ LEVEL(SMB2_GETINFO_FILE_STREAM_INFO) }, static struct {
{ LEVEL(SMB2_GETINFO_FILE_EOF_INFO) }, const char *name;
{ LEVEL(SMB2_GETINFO_FILE_STANDARD_INFO) }, uint16_t level;
{ LEVEL(SMB2_GETINFO_FILE_ATTRIB_INFO) } NTSTATUS status;
union smb_fsinfo info;
} fs_levels[] = {
{ LEVEL(RAW_QFS_VOLUME_INFORMATION) },
{ LEVEL(RAW_QFS_SIZE_INFORMATION) },
{ LEVEL(RAW_QFS_DEVICE_INFORMATION) },
{ LEVEL(RAW_QFS_ATTRIBUTE_INFORMATION) },
{ LEVEL(RAW_QFS_QUOTA_INFORMATION) },
{ LEVEL(RAW_QFS_FULL_SIZE_INFORMATION) },
{ LEVEL(RAW_QFS_OBJECTID_INFORMATION) }
}; };
#define FNAME "testsmb2_file.dat" #define FNAME "testsmb2_file.dat"
#define DNAME "testsmb2_dir" #define DNAME "testsmb2_dir"
/* basic testing of all SMB2 getinfo levels /*
test fileinfo levels
*/ */
BOOL torture_smb2_getinfo(void) static BOOL torture_smb2_fileinfo(struct smb2_tree *tree)
{ {
TALLOC_CTX *mem_ctx = talloc_new(NULL);
struct smb2_handle hfile, hdir; struct smb2_handle hfile, hdir;
struct smb2_tree *tree;
NTSTATUS status; NTSTATUS status;
int i; int i;
if (!torture_smb2_connection(mem_ctx, &tree)) {
goto failed;
}
torture_setup_complex_file(FNAME);
torture_setup_complex_file(FNAME ":streamtwo");
torture_setup_complex_dir(DNAME);
torture_setup_complex_file(DNAME ":streamtwo");
status = torture_smb2_testfile(tree, FNAME, &hfile); status = torture_smb2_testfile(tree, FNAME, &hfile);
if (!NT_STATUS_IS_OK(status)) { if (!NT_STATUS_IS_OK(status)) {
printf("Unable to create test file '%s' - %s\n", FNAME, nt_errstr(status)); printf("Unable to create test file '%s' - %s\n", FNAME, nt_errstr(status));
@@ -95,22 +95,81 @@ BOOL torture_smb2_getinfo(void)
torture_smb2_all_info(tree, hfile); torture_smb2_all_info(tree, hfile);
torture_smb2_all_info(tree, hdir); torture_smb2_all_info(tree, hdir);
for (i=0;i<ARRAY_SIZE(levels);i++) { for (i=0;i<ARRAY_SIZE(file_levels);i++) {
levels[i].fstatus = smb2_getinfo_level(tree, mem_ctx, hfile, if (file_levels[i].level == RAW_FILEINFO_SEC_DESC) {
levels[i].level, &levels[i].finfo); file_levels[i].finfo.query_secdesc.secinfo_flags = 0x7;
if (!NT_STATUS_IS_OK(levels[i].fstatus)) { file_levels[i].dinfo.query_secdesc.secinfo_flags = 0x7;
printf("%s failed on file - %s\n", levels[i].name, nt_errstr(levels[i].fstatus));
} }
levels[i].dstatus = smb2_getinfo_level(tree, mem_ctx, hdir, file_levels[i].finfo.generic.level = file_levels[i].level;
levels[i].level, &levels[i].dinfo); file_levels[i].finfo.generic.in.handle = hfile;
if (!NT_STATUS_IS_OK(levels[i].dstatus)) { file_levels[i].fstatus = smb2_getinfo_file(tree, tree, &file_levels[i].finfo);
printf("%s failed on dir - %s\n", levels[i].name, nt_errstr(levels[i].dstatus)); if (!NT_STATUS_IS_OK(file_levels[i].fstatus)) {
printf("%s failed on file - %s\n", file_levels[i].name, nt_errstr(file_levels[i].fstatus));
}
file_levels[i].dinfo.generic.level = file_levels[i].level;
file_levels[i].dinfo.generic.in.handle = hdir;
file_levels[i].dstatus = smb2_getinfo_file(tree, tree, &file_levels[i].dinfo);
if (!NT_STATUS_IS_OK(file_levels[i].dstatus)) {
printf("%s failed on dir - %s\n", file_levels[i].name, nt_errstr(file_levels[i].dstatus));
} }
} }
return True; return True;
failed: failed:
talloc_free(mem_ctx);
return False; return False;
} }
/*
test fsinfo levels
*/
static BOOL torture_smb2_fsinfo(struct smb2_tree *tree)
{
int i;
NTSTATUS status;
struct smb2_handle handle;
status = torture_smb2_testdir(tree, DNAME, &handle);
if (!NT_STATUS_IS_OK(status)) {
printf("Unable to create test directory '%s' - %s\n", DNAME, nt_errstr(status));
return False;
}
for (i=0;i<ARRAY_SIZE(fs_levels);i++) {
fs_levels[i].info.generic.level = fs_levels[i].level;
fs_levels[i].info.generic.handle = handle;
fs_levels[i].status = smb2_getinfo_fs(tree, tree, &fs_levels[i].info);
if (!NT_STATUS_IS_OK(fs_levels[i].status)) {
printf("%s failed - %s\n", fs_levels[i].name, nt_errstr(fs_levels[i].status));
}
}
return True;
}
/* basic testing of all SMB2 getinfo levels
*/
BOOL torture_smb2_getinfo(void)
{
TALLOC_CTX *mem_ctx = talloc_new(NULL);
struct smb2_tree *tree;
BOOL ret = True;
if (!torture_smb2_connection(mem_ctx, &tree)) {
return False;
}
torture_setup_complex_file(FNAME);
torture_setup_complex_file(FNAME ":streamtwo");
torture_setup_complex_dir(DNAME);
torture_setup_complex_file(DNAME ":streamtwo");
ret &= torture_smb2_fileinfo(tree);
ret &= torture_smb2_fsinfo(tree);
talloc_free(mem_ctx);
return ret;
}

View File

@@ -34,65 +34,68 @@ void torture_smb2_all_info(struct smb2_tree *tree, struct smb2_handle handle)
{ {
NTSTATUS status; NTSTATUS status;
TALLOC_CTX *tmp_ctx = talloc_new(tree); TALLOC_CTX *tmp_ctx = talloc_new(tree);
union smb2_fileinfo io; union smb_fileinfo io;
status = smb2_getinfo_level(tree, tmp_ctx, handle, SMB2_GETINFO_FILE_ALL_INFO, &io); io.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
io.generic.in.handle = handle;
status = smb2_getinfo_file(tree, tmp_ctx, &io);
if (!NT_STATUS_IS_OK(status)) { if (!NT_STATUS_IS_OK(status)) {
DEBUG(0,("getinfo failed - %s\n", nt_errstr(status))); DEBUG(0,("getinfo failed - %s\n", nt_errstr(status)));
talloc_free(tmp_ctx); talloc_free(tmp_ctx);
return; return;
} }
d_printf("\tcreate_time: %s\n", nt_time_string(tmp_ctx, io.all_info.create_time)); d_printf("\tcreate_time: %s\n", nt_time_string(tmp_ctx, io.all_info2.out.create_time));
d_printf("\taccess_time: %s\n", nt_time_string(tmp_ctx, io.all_info.access_time)); d_printf("\taccess_time: %s\n", nt_time_string(tmp_ctx, io.all_info2.out.access_time));
d_printf("\twrite_time: %s\n", nt_time_string(tmp_ctx, io.all_info.write_time)); d_printf("\twrite_time: %s\n", nt_time_string(tmp_ctx, io.all_info2.out.write_time));
d_printf("\tchange_time: %s\n", nt_time_string(tmp_ctx, io.all_info.change_time)); d_printf("\tchange_time: %s\n", nt_time_string(tmp_ctx, io.all_info2.out.change_time));
d_printf("\tattrib: 0x%x\n", io.all_info.file_attr); d_printf("\tattrib: 0x%x\n", io.all_info2.out.attrib);
d_printf("\tunknown1: 0x%x\n", io.all_info.unknown1); d_printf("\tunknown1: 0x%x\n", io.all_info2.out.unknown1);
d_printf("\talloc_size: %llu\n", (uint64_t)io.all_info.alloc_size); d_printf("\talloc_size: %llu\n", (uint64_t)io.all_info2.out.alloc_size);
d_printf("\tsize: %llu\n", (uint64_t)io.all_info.size); d_printf("\tsize: %llu\n", (uint64_t)io.all_info2.out.size);
d_printf("\tnlink: %u\n", io.all_info.nlink); d_printf("\tnlink: %u\n", io.all_info2.out.nlink);
d_printf("\tdelete_pending: %u\n", io.all_info.delete_pending); d_printf("\tdelete_pending: %u\n", io.all_info2.out.delete_pending);
d_printf("\tdirectory: %u\n", io.all_info.directory); d_printf("\tdirectory: %u\n", io.all_info2.out.directory);
d_printf("\tfile_id: %llu\n", io.all_info.file_id); d_printf("\tfile_id: %llu\n", io.all_info2.out.file_id);
d_printf("\tea_size: %u\n", io.all_info.ea_size); d_printf("\tea_size: %u\n", io.all_info2.out.ea_size);
d_printf("\taccess_mask: 0x%08x\n", io.all_info.access_mask); d_printf("\taccess_mask: 0x%08x\n", io.all_info2.out.access_mask);
d_printf("\tunknown5: 0x%llx\n", io.all_info.unknown5); d_printf("\tunknown2: 0x%llx\n", io.all_info2.out.unknown2);
d_printf("\tunknown6: 0x%llx\n", io.all_info.unknown6); d_printf("\tunknown3: 0x%llx\n", io.all_info2.out.unknown3);
d_printf("\tfname: '%s'\n", io.all_info.fname); d_printf("\tfname: '%s'\n", io.all_info2.out.fname.s);
/* short name, if any */ /* short name, if any */
status = smb2_getinfo_level(tree, tmp_ctx, handle, io.generic.level = RAW_FILEINFO_ALT_NAME_INFORMATION;
SMB2_GETINFO_FILE_SHORT_INFO, &io); status = smb2_getinfo_file(tree, tmp_ctx, &io);
if (NT_STATUS_IS_OK(status)) { if (NT_STATUS_IS_OK(status)) {
d_printf("\tshort name: '%s'\n", io.short_info.short_name); d_printf("\tshort name: '%s'\n", io.alt_name_info.out.fname.s);
} }
/* the EAs, if any */ /* the EAs, if any */
status = smb2_getinfo_level(tree, tmp_ctx, handle, io.generic.level = RAW_FILEINFO_SMB2_ALL_EAS;
SMB2_GETINFO_FILE_ALL_EAS, &io); status = smb2_getinfo_file(tree, tmp_ctx, &io);
if (NT_STATUS_IS_OK(status)) { if (NT_STATUS_IS_OK(status)) {
int i; int i;
for (i=0;i<io.all_eas.num_eas;i++) { for (i=0;i<io.all_eas.out.num_eas;i++) {
d_printf("\tEA[%d] flags=%d len=%d '%s'\n", i, d_printf("\tEA[%d] flags=%d len=%d '%s'\n", i,
io.all_eas.eas[i].flags, io.all_eas.out.eas[i].flags,
(int)io.all_eas.eas[i].value.length, (int)io.all_eas.out.eas[i].value.length,
io.all_eas.eas[i].name.s); io.all_eas.out.eas[i].name.s);
} }
} }
/* streams, if available */ /* streams, if available */
status = smb2_getinfo_level(tree, tmp_ctx, handle, io.generic.level = RAW_FILEINFO_STREAM_INFORMATION;
SMB2_GETINFO_FILE_STREAM_INFO, &io); status = smb2_getinfo_file(tree, tmp_ctx, &io);
if (NT_STATUS_IS_OK(status)) { if (NT_STATUS_IS_OK(status)) {
int i; int i;
for (i=0;i<io.stream_info.num_streams;i++) { for (i=0;i<io.stream_info.out.num_streams;i++) {
d_printf("\tstream %d:\n", i); d_printf("\tstream %d:\n", i);
d_printf("\t\tsize %ld\n", d_printf("\t\tsize %ld\n",
(long)io.stream_info.streams[i].size); (long)io.stream_info.out.streams[i].size);
d_printf("\t\talloc size %ld\n", d_printf("\t\talloc size %ld\n",
(long)io.stream_info.streams[i].alloc_size); (long)io.stream_info.out.streams[i].alloc_size);
d_printf("\t\tname %s\n", io.stream_info.streams[i].stream_name.s); d_printf("\t\tname %s\n", io.stream_info.out.streams[i].stream_name.s);
} }
} }
@@ -173,7 +176,7 @@ NTSTATUS torture_smb2_testdir(struct smb2_tree *tree, const char *fname,
io.in.access_mask = SEC_RIGHTS_DIR_ALL; io.in.access_mask = SEC_RIGHTS_DIR_ALL;
io.in.file_attr = FILE_ATTRIBUTE_DIRECTORY; io.in.file_attr = FILE_ATTRIBUTE_DIRECTORY;
io.in.open_disposition = NTCREATEX_DISP_OPEN_IF; io.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
io.in.share_access = NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE; io.in.share_access = NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE;
io.in.create_options = NTCREATEX_OPTIONS_DIRECTORY; io.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
io.in.fname = fname; io.in.fname = fname;
io.in.blob = data_blob(NULL, 0); io.in.blob = data_blob(NULL, 0);