mirror of
https://github.com/samba-team/samba.git
synced 2025-11-15 16:23:49 +03:00
r11730: added parsing and tests for a bunch more SMB2 getinfo levels
This commit is contained in:
committed by
Gerald (Jerry) Carter
parent
681451af72
commit
ca65bf0235
@@ -34,6 +34,51 @@
|
||||
return NT_STATUS_INFO_LENGTH_MISMATCH; \
|
||||
}
|
||||
|
||||
/*
|
||||
parse a stream information structure
|
||||
*/
|
||||
NTSTATUS smbcli_parse_stream_info(DATA_BLOB blob, TALLOC_CTX *mem_ctx,
|
||||
struct stream_information *io)
|
||||
{
|
||||
uint32_t ofs = 0;
|
||||
io->num_streams = 0;
|
||||
io->streams = NULL;
|
||||
|
||||
while (blob.length - ofs >= 24) {
|
||||
uint_t n = io->num_streams;
|
||||
uint32_t nlen, len;
|
||||
ssize_t size;
|
||||
void *vstr;
|
||||
io->streams =
|
||||
talloc_realloc(mem_ctx, io->streams, struct stream_struct, n+1);
|
||||
if (!io->streams) {
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
nlen = IVAL(blob.data, ofs + 0x04);
|
||||
io->streams[n].size = BVAL(blob.data, ofs + 0x08);
|
||||
io->streams[n].alloc_size = BVAL(blob.data, ofs + 0x10);
|
||||
if (nlen > blob.length - (ofs + 24)) {
|
||||
return NT_STATUS_INFO_LENGTH_MISMATCH;
|
||||
}
|
||||
size = convert_string_talloc(io->streams, CH_UTF16, CH_UNIX,
|
||||
blob.data+ofs+24, nlen, &vstr);
|
||||
if (size == -1) {
|
||||
return NT_STATUS_ILLEGAL_CHARACTER;
|
||||
}
|
||||
io->streams[n].stream_name.s = vstr;
|
||||
io->streams[n].stream_name.private_length = nlen;
|
||||
io->num_streams++;
|
||||
len = IVAL(blob.data, ofs);
|
||||
if (len > blob.length - ofs) {
|
||||
return NT_STATUS_INFO_LENGTH_MISMATCH;
|
||||
}
|
||||
if (len == 0) break;
|
||||
ofs += len;
|
||||
}
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Handle qfileinfo/qpathinfo trans2 backend.
|
||||
****************************************************************************/
|
||||
@@ -42,8 +87,6 @@ static NTSTATUS smb_raw_info_backend(struct smbcli_session *session,
|
||||
union smb_fileinfo *parms,
|
||||
DATA_BLOB *blob)
|
||||
{
|
||||
uint_t len, ofs;
|
||||
|
||||
switch (parms->generic.level) {
|
||||
case RAW_FILEINFO_GENERIC:
|
||||
case RAW_FILEINFO_GETATTR:
|
||||
@@ -175,32 +218,7 @@ static NTSTATUS smb_raw_info_backend(struct smbcli_session *session,
|
||||
|
||||
case RAW_FILEINFO_STREAM_INFO:
|
||||
case RAW_FILEINFO_STREAM_INFORMATION:
|
||||
ofs = 0;
|
||||
parms->stream_info.out.num_streams = 0;
|
||||
parms->stream_info.out.streams = NULL;
|
||||
|
||||
while (blob->length - ofs >= 24) {
|
||||
uint_t n = parms->stream_info.out.num_streams;
|
||||
parms->stream_info.out.streams =
|
||||
talloc_realloc(mem_ctx,
|
||||
parms->stream_info.out.streams,
|
||||
struct stream_struct,
|
||||
n+1);
|
||||
if (!parms->stream_info.out.streams) {
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
parms->stream_info.out.streams[n].size = BVAL(blob->data, ofs + 8);
|
||||
parms->stream_info.out.streams[n].alloc_size = BVAL(blob->data, ofs + 16);
|
||||
smbcli_blob_pull_string(session, mem_ctx, blob,
|
||||
&parms->stream_info.out.streams[n].stream_name,
|
||||
ofs+4, ofs+24, STR_UNICODE);
|
||||
parms->stream_info.out.num_streams++;
|
||||
len = IVAL(blob->data, ofs);
|
||||
if (len > blob->length - ofs) return NT_STATUS_INFO_LENGTH_MISMATCH;
|
||||
if (len == 0) break;
|
||||
ofs += len;
|
||||
}
|
||||
return NT_STATUS_OK;
|
||||
return smbcli_parse_stream_info(*blob, mem_ctx, &parms->stream_info.out);
|
||||
|
||||
case RAW_FILEINFO_INTERNAL_INFORMATION:
|
||||
FINFO_CHECK_SIZE(8);
|
||||
|
||||
@@ -113,18 +113,18 @@ NTSTATUS smb2_getinfo_parse(TALLOC_CTX *mem_ctx,
|
||||
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.unknown = IVAL(blob.data, 0x14);
|
||||
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_06:
|
||||
case SMB2_GETINFO_FILE_ID:
|
||||
if (blob.length != 0x8) {
|
||||
return NT_STATUS_INFO_LENGTH_MISMATCH;
|
||||
}
|
||||
io->unknown06.unknown1 = IVAL(blob.data, 0x00);
|
||||
io->unknown06.unknown2 = IVAL(blob.data, 0x04);
|
||||
io->file_id.file_id = BVAL(blob.data, 0x00);
|
||||
break;
|
||||
|
||||
case SMB2_GETINFO_FILE_EA_SIZE:
|
||||
@@ -172,37 +172,105 @@ NTSTATUS smb2_getinfo_parse(TALLOC_CTX *mem_ctx,
|
||||
uint32_t nlen;
|
||||
ssize_t size;
|
||||
void *vstr;
|
||||
if (blob.length != 0x60) {
|
||||
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.unknown2 = IVAL(blob.data, 0x3C);
|
||||
io->all_info.unknown3 = IVAL(blob.data, 0x40);
|
||||
io->all_info.unknown4 = IVAL(blob.data, 0x44);
|
||||
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, 0x5C);
|
||||
if (nlen > blob.length - 0x60) {
|
||||
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.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+0x60, nlen, &vstr);
|
||||
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->standard_info.file_attr = IVAL(blob.data, 0x00);
|
||||
io->standard_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;
|
||||
@@ -230,3 +298,23 @@ NTSTATUS smb2_getinfo_level_recv(struct smb2_request *req, TALLOC_CTX *mem_ctx,
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
level specific getinfo call
|
||||
*/
|
||||
NTSTATUS smb2_getinfo_level(struct smb2_tree *tree, TALLOC_CTX *mem_ctx,
|
||||
struct smb2_handle handle,
|
||||
uint16_t level, union smb2_fileinfo *io)
|
||||
{
|
||||
struct smb2_getinfo b;
|
||||
struct smb2_request *req;
|
||||
|
||||
ZERO_STRUCT(b);
|
||||
b.in.buffer_code = 0x29;
|
||||
b.in.max_response_size = 0x10000;
|
||||
b.in.handle = handle;
|
||||
b.in.level = level;
|
||||
|
||||
req = smb2_getinfo_send(tree, &b);
|
||||
|
||||
return smb2_getinfo_level_recv(req, mem_ctx, level, io);
|
||||
}
|
||||
|
||||
@@ -170,7 +170,7 @@ struct smb2_close {
|
||||
/* file information levels */
|
||||
#define SMB2_GETINFO_FILE_BASIC_INFO 0x0401
|
||||
#define SMB2_GETINFO_FILE_SIZE_INFO 0x0501
|
||||
#define SMB2_GETINFO_FILE_06 0x0601
|
||||
#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
|
||||
@@ -217,13 +217,13 @@ union smb2_fileinfo {
|
||||
uint64_t alloc_size;
|
||||
uint64_t size;
|
||||
uint32_t nlink;
|
||||
uint32_t unknown;
|
||||
uint8_t delete_pending;
|
||||
uint8_t directory;
|
||||
} size_info;
|
||||
|
||||
struct {
|
||||
uint32_t unknown1;
|
||||
uint32_t unknown2;
|
||||
} unknown06;
|
||||
uint64_t file_id;
|
||||
} file_id;
|
||||
|
||||
struct {
|
||||
uint32_t ea_size;
|
||||
@@ -256,13 +256,14 @@ union smb2_fileinfo {
|
||||
NTTIME write_time;
|
||||
NTTIME change_time;
|
||||
uint32_t file_attr;
|
||||
uint32_t unknown1;
|
||||
/* uint32_t _pad; */
|
||||
uint64_t alloc_size;
|
||||
uint64_t size;
|
||||
uint32_t nlink;
|
||||
uint32_t unknown2;
|
||||
uint32_t unknown3;
|
||||
uint32_t unknown4;
|
||||
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;
|
||||
@@ -274,12 +275,7 @@ union smb2_fileinfo {
|
||||
const char *short_name;
|
||||
} short_info;
|
||||
|
||||
struct {
|
||||
uint32_t unknown;
|
||||
uint64_t size;
|
||||
uint64_t alloc_size;
|
||||
const char *stream_name;
|
||||
} stream_info;
|
||||
struct stream_information stream_info;
|
||||
|
||||
struct {
|
||||
uint64_t size;
|
||||
@@ -301,6 +297,10 @@ union smb2_fileinfo {
|
||||
uint32_t file_attr;
|
||||
uint32_t unknown;
|
||||
} attrib_info;
|
||||
|
||||
struct {
|
||||
struct security_descriptor *sd;
|
||||
} security;
|
||||
};
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user