diff options
author | Andrew Tridgell <tridge@samba.org> | 2005-11-15 04:38:59 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 13:46:18 -0500 |
commit | b51703baf152c309ce325ce573c1683d7e503122 (patch) | |
tree | 89fb1a5bfd9a3659be89185c198430ab8c35f9a6 /source4/libcli | |
parent | f7732560eea1c5d1de316fb2d64b78ad7507549b (diff) | |
download | samba-b51703baf152c309ce325ce573c1683d7e503122.tar.gz samba-b51703baf152c309ce325ce573c1683d7e503122.tar.bz2 samba-b51703baf152c309ce325ce573c1683d7e503122.zip |
r11730: added parsing and tests for a bunch more SMB2 getinfo levels
(This used to be commit ca65bf0235cbfab451e5d5ceac9f714acc0cd46c)
Diffstat (limited to 'source4/libcli')
-rw-r--r-- | source4/libcli/raw/rawfileinfo.c | 74 | ||||
-rw-r--r-- | source4/libcli/smb2/getinfo.c | 142 | ||||
-rw-r--r-- | source4/libcli/smb2/smb2_calls.h | 30 |
3 files changed, 176 insertions, 70 deletions
diff --git a/source4/libcli/raw/rawfileinfo.c b/source4/libcli/raw/rawfileinfo.c index ede4391824..f631522182 100644 --- a/source4/libcli/raw/rawfileinfo.c +++ b/source4/libcli/raw/rawfileinfo.c @@ -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); diff --git a/source4/libcli/smb2/getinfo.c b/source4/libcli/smb2/getinfo.c index 9ad2b77310..7a362b24d9 100644 --- a/source4/libcli/smb2/getinfo.c +++ b/source4/libcli/smb2/getinfo.c @@ -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); +} diff --git a/source4/libcli/smb2/smb2_calls.h b/source4/libcli/smb2/smb2_calls.h index aa2fb717b2..127a9d229c 100644 --- a/source4/libcli/smb2/smb2_calls.h +++ b/source4/libcli/smb2/smb2_calls.h @@ -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; }; |