diff options
author | Jelmer Vernooij <jelmer@samba.org> | 2008-02-14 12:03:11 +0100 |
---|---|---|
committer | Jelmer Vernooij <jelmer@samba.org> | 2008-02-14 12:03:11 +0100 |
commit | 02af3663a457ebc6aa30e79614e44fb16be8cadd (patch) | |
tree | c4497d370126fbf328df34e7a1257eac2c58f386 /source4/libcli | |
parent | 21c0f266616e093cccbaf9378b3a915e56ba6079 (diff) | |
parent | b640f475be9b0f83e7812a5c7756344c5891cba3 (diff) | |
download | samba-02af3663a457ebc6aa30e79614e44fb16be8cadd.tar.gz samba-02af3663a457ebc6aa30e79614e44fb16be8cadd.tar.bz2 samba-02af3663a457ebc6aa30e79614e44fb16be8cadd.zip |
Merge branch 'v4-0-test' of ssh://git.samba.org/data/git/samba into v4-0-trivial
(This used to be commit 50697762fd28e2fc77142c5fea528b12d4cc0ebc)
Diffstat (limited to 'source4/libcli')
-rw-r--r-- | source4/libcli/raw/clisession.c | 20 | ||||
-rw-r--r-- | source4/libcli/raw/clitransport.c | 4 | ||||
-rw-r--r-- | source4/libcli/raw/clitree.c | 6 | ||||
-rw-r--r-- | source4/libcli/raw/interfaces.h | 7 | ||||
-rw-r--r-- | source4/libcli/raw/libcliraw.h | 4 | ||||
-rw-r--r-- | source4/libcli/raw/rawfile.c | 4 | ||||
-rw-r--r-- | source4/libcli/raw/rawioctl.c | 2 | ||||
-rw-r--r-- | source4/libcli/raw/rawnegotiate.c | 10 | ||||
-rw-r--r-- | source4/libcli/raw/rawreadwrite.c | 6 | ||||
-rw-r--r-- | source4/libcli/raw/rawrequest.c | 53 | ||||
-rw-r--r-- | source4/libcli/raw/rawsearch.c | 2 | ||||
-rw-r--r-- | source4/libcli/raw/rawsetfileinfo.c | 11 | ||||
-rw-r--r-- | source4/libcli/raw/request.h | 19 | ||||
-rw-r--r-- | source4/libcli/raw/smb_signing.c | 6 | ||||
-rw-r--r-- | source4/libcli/smb2/connect.c | 2 | ||||
-rw-r--r-- | source4/libcli/smb2/getinfo.c | 45 | ||||
-rw-r--r-- | source4/libcli/smb2/request.c | 42 | ||||
-rw-r--r-- | source4/libcli/smb2/setinfo.c | 6 | ||||
-rw-r--r-- | source4/libcli/smb2/smb2.h | 8 | ||||
-rw-r--r-- | source4/libcli/smb2/smb2_calls.h | 24 | ||||
-rw-r--r-- | source4/libcli/smb2/transport.c | 2 |
21 files changed, 205 insertions, 78 deletions
diff --git a/source4/libcli/raw/clisession.c b/source4/libcli/raw/clisession.c index 617131c53c..55cb3ef305 100644 --- a/source4/libcli/raw/clisession.c +++ b/source4/libcli/raw/clisession.c @@ -177,9 +177,9 @@ NTSTATUS smb_raw_sesssetup_recv(struct smbcli_request *req, parms->old.out.action = SVAL(req->in.vwv, VWV(2)); p = req->in.data; if (p) { - p += smbcli_req_pull_string(req, mem_ctx, &parms->old.out.os, p, -1, STR_TERMINATE); - p += smbcli_req_pull_string(req, mem_ctx, &parms->old.out.lanman, p, -1, STR_TERMINATE); - p += smbcli_req_pull_string(req, mem_ctx, &parms->old.out.domain, p, -1, STR_TERMINATE); + p += smbcli_req_pull_string(&req->in.bufinfo, mem_ctx, &parms->old.out.os, p, -1, STR_TERMINATE); + p += smbcli_req_pull_string(&req->in.bufinfo, mem_ctx, &parms->old.out.lanman, p, -1, STR_TERMINATE); + p += smbcli_req_pull_string(&req->in.bufinfo, mem_ctx, &parms->old.out.domain, p, -1, STR_TERMINATE); } break; @@ -190,10 +190,10 @@ NTSTATUS smb_raw_sesssetup_recv(struct smbcli_request *req, parms->nt1.out.action = SVAL(req->in.vwv, VWV(2)); p = req->in.data; if (p) { - p += smbcli_req_pull_string(req, mem_ctx, &parms->nt1.out.os, p, -1, STR_TERMINATE); - p += smbcli_req_pull_string(req, mem_ctx, &parms->nt1.out.lanman, p, -1, STR_TERMINATE); + p += smbcli_req_pull_string(&req->in.bufinfo, mem_ctx, &parms->nt1.out.os, p, -1, STR_TERMINATE); + p += smbcli_req_pull_string(&req->in.bufinfo, mem_ctx, &parms->nt1.out.lanman, p, -1, STR_TERMINATE); if (p < (req->in.data + req->in.data_size)) { - p += smbcli_req_pull_string(req, mem_ctx, &parms->nt1.out.domain, p, -1, STR_TERMINATE); + p += smbcli_req_pull_string(&req->in.bufinfo, mem_ctx, &parms->nt1.out.domain, p, -1, STR_TERMINATE); } } break; @@ -209,11 +209,11 @@ NTSTATUS smb_raw_sesssetup_recv(struct smbcli_request *req, break; } - parms->spnego.out.secblob = smbcli_req_pull_blob(req, mem_ctx, p, len); + parms->spnego.out.secblob = smbcli_req_pull_blob(&req->in.bufinfo, mem_ctx, p, len); p += parms->spnego.out.secblob.length; - p += smbcli_req_pull_string(req, mem_ctx, &parms->spnego.out.os, p, -1, STR_TERMINATE); - p += smbcli_req_pull_string(req, mem_ctx, &parms->spnego.out.lanman, p, -1, STR_TERMINATE); - p += smbcli_req_pull_string(req, mem_ctx, &parms->spnego.out.workgroup, p, -1, STR_TERMINATE); + p += smbcli_req_pull_string(&req->in.bufinfo, mem_ctx, &parms->spnego.out.os, p, -1, STR_TERMINATE); + p += smbcli_req_pull_string(&req->in.bufinfo, mem_ctx, &parms->spnego.out.lanman, p, -1, STR_TERMINATE); + p += smbcli_req_pull_string(&req->in.bufinfo, mem_ctx, &parms->spnego.out.workgroup, p, -1, STR_TERMINATE); break; case RAW_SESSSETUP_SMB2: diff --git a/source4/libcli/raw/clitransport.c b/source4/libcli/raw/clitransport.c index 62c32d3058..288f0612de 100644 --- a/source4/libcli/raw/clitransport.c +++ b/source4/libcli/raw/clitransport.c @@ -444,6 +444,8 @@ static NTSTATUS smbcli_transport_finish_recv(void *private, DATA_BLOB blob) req->in.ptr = req->in.data; req->flags2 = SVAL(req->in.hdr, HDR_FLG2); + smb_setup_bufinfo(req); + if (!(req->flags2 & FLAGS2_32_BIT_ERROR_CODES)) { int class = CVAL(req->in.hdr,HDR_RCLS); int code = SVAL(req->in.hdr,HDR_ERR); @@ -637,7 +639,7 @@ NTSTATUS smb_raw_echo_recv(struct smbcli_request *req, TALLOC_CTX *mem_ctx, p->out.data = talloc_array(mem_ctx, uint8_t, p->out.size); NT_STATUS_HAVE_NO_MEMORY(p->out.data); - if (!smbcli_raw_pull_data(req, req->in.data, p->out.size, p->out.data)) { + if (!smbcli_raw_pull_data(&req->in.bufinfo, req->in.data, p->out.size, p->out.data)) { req->status = NT_STATUS_BUFFER_TOO_SMALL; } diff --git a/source4/libcli/raw/clitree.c b/source4/libcli/raw/clitree.c index 35f3335322..507bde999a 100644 --- a/source4/libcli/raw/clitree.c +++ b/source4/libcli/raw/clitree.c @@ -123,9 +123,9 @@ NTSTATUS smb_raw_tcon_recv(struct smbcli_request *req, TALLOC_CTX *mem_ctx, p = req->in.data; if (!p) break; - p += smbcli_req_pull_string(req, mem_ctx, &parms->tconx.out.dev_type, - p, -1, STR_ASCII | STR_TERMINATE); - p += smbcli_req_pull_string(req, mem_ctx, &parms->tconx.out.fs_type, + p += smbcli_req_pull_string(&req->in.bufinfo, mem_ctx, &parms->tconx.out.dev_type, + p, -1, STR_ASCII | STR_TERMINATE); + p += smbcli_req_pull_string(&req->in.bufinfo, mem_ctx, &parms->tconx.out.fs_type, p, -1, STR_TERMINATE); break; diff --git a/source4/libcli/raw/interfaces.h b/source4/libcli/raw/interfaces.h index ce6323f2e5..24e8ad4afc 100644 --- a/source4/libcli/raw/interfaces.h +++ b/source4/libcli/raw/interfaces.h @@ -902,7 +902,10 @@ enum smb_setfileinfo_level { RAW_SFILEINFO_1029 = SMB_SFILEINFO_1029, RAW_SFILEINFO_1032 = SMB_SFILEINFO_1032, RAW_SFILEINFO_1039 = SMB_SFILEINFO_1039, - RAW_SFILEINFO_1040 = SMB_SFILEINFO_1040 + RAW_SFILEINFO_1040 = SMB_SFILEINFO_1040, + + /* cope with breakage in SMB2 */ + RAW_SFILEINFO_RENAME_INFORMATION_SMB2 = SMB_SFILEINFO_RENAME_INFORMATION|0x80000000, }; /* union used in setfileinfo() and setpathinfo() calls */ @@ -1000,7 +1003,7 @@ union smb_setfileinfo { struct { union smb_handle_or_path file; uint8_t overwrite; - uint32_t root_fid; + uint64_t root_fid; const char *new_name; } in; } rename_information; diff --git a/source4/libcli/raw/libcliraw.h b/source4/libcli/raw/libcliraw.h index 0032eb4e94..7111649fc1 100644 --- a/source4/libcli/raw/libcliraw.h +++ b/source4/libcli/raw/libcliraw.h @@ -250,8 +250,8 @@ struct smbcli_request { /* the mid of this packet - used to match replies */ uint16_t mid; - struct request_buffer in; - struct request_buffer out; + struct smb_request_buffer in; + struct smb_request_buffer out; /* information on what to do with a reply when it is received asyncronously. If this is not setup when a reply is received then diff --git a/source4/libcli/raw/rawfile.c b/source4/libcli/raw/rawfile.c index 3b6ca68526..d9383401b7 100644 --- a/source4/libcli/raw/rawfile.c +++ b/source4/libcli/raw/rawfile.c @@ -616,7 +616,7 @@ NTSTATUS smb_raw_open_recv(struct smbcli_request *req, TALLOC_CTX *mem_ctx, unio case RAW_OPEN_CTEMP: SMBCLI_CHECK_WCT(req, 1); parms->ctemp.out.file.fnum = SVAL(req->in.vwv, VWV(0)); - smbcli_req_pull_string(req, mem_ctx, &parms->ctemp.out.name, req->in.data, -1, STR_TERMINATE | STR_ASCII); + smbcli_req_pull_string(&req->in.bufinfo, mem_ctx, &parms->ctemp.out.name, req->in.data, -1, STR_TERMINATE | STR_ASCII); break; case RAW_OPEN_SPLOPEN: @@ -675,7 +675,7 @@ NTSTATUS smb_raw_open_recv(struct smbcli_request *req, TALLOC_CTX *mem_ctx, unio parms->openxreadx.out.nread = SVAL(req->in.vwv, VWV(5)); if (parms->openxreadx.out.nread > MAX(parms->openxreadx.in.mincnt, parms->openxreadx.in.maxcnt) || - !smbcli_raw_pull_data(req, req->in.hdr + SVAL(req->in.vwv, VWV(6)), + !smbcli_raw_pull_data(&req->in.bufinfo, req->in.hdr + SVAL(req->in.vwv, VWV(6)), parms->openxreadx.out.nread, parms->openxreadx.out.data)) { req->status = NT_STATUS_BUFFER_TOO_SMALL; diff --git a/source4/libcli/raw/rawioctl.c b/source4/libcli/raw/rawioctl.c index 9205f84e86..957e554c6b 100644 --- a/source4/libcli/raw/rawioctl.c +++ b/source4/libcli/raw/rawioctl.c @@ -59,7 +59,7 @@ static NTSTATUS smb_raw_smbioctl_recv(struct smbcli_request *req, return smbcli_request_destroy(req); } - parms->ioctl.out.blob = smbcli_req_pull_blob(req, mem_ctx, req->in.data, -1); + parms->ioctl.out.blob = smbcli_req_pull_blob(&req->in.bufinfo, mem_ctx, req->in.data, -1); return smbcli_request_destroy(req); } diff --git a/source4/libcli/raw/rawnegotiate.c b/source4/libcli/raw/rawnegotiate.c index 1f5e34779b..ec2ada53ff 100644 --- a/source4/libcli/raw/rawnegotiate.c +++ b/source4/libcli/raw/rawnegotiate.c @@ -135,14 +135,14 @@ NTSTATUS smb_raw_negotiate_recv(struct smbcli_request *req) if (req->in.data_size < 16) { goto failed; } - transport->negotiate.server_guid = smbcli_req_pull_blob(req, transport, req->in.data, 16); - transport->negotiate.secblob = smbcli_req_pull_blob(req, transport, req->in.data + 16, req->in.data_size - 16); + transport->negotiate.server_guid = smbcli_req_pull_blob(&req->in.bufinfo, transport, req->in.data, 16); + transport->negotiate.secblob = smbcli_req_pull_blob(&req->in.bufinfo, transport, req->in.data + 16, req->in.data_size - 16); } else { if (req->in.data_size < (transport->negotiate.key_len)) { goto failed; } - transport->negotiate.secblob = smbcli_req_pull_blob(req, transport, req->in.data, transport->negotiate.key_len); - smbcli_req_pull_string(req, transport, &transport->negotiate.server_domain, + transport->negotiate.secblob = smbcli_req_pull_blob(&req->in.bufinfo, transport, req->in.data, transport->negotiate.key_len); + smbcli_req_pull_string(&req->in.bufinfo, transport, &transport->negotiate.server_domain, req->in.data+transport->negotiate.key_len, req->in.data_size-transport->negotiate.key_len, STR_UNICODE|STR_NOALIGN); /* here comes the server name */ @@ -168,7 +168,7 @@ NTSTATUS smb_raw_negotiate_recv(struct smbcli_request *req) if ((SVAL(req->in.vwv,VWV(5)) & 0x2)) { transport->negotiate.writebraw_supported = 1; } - transport->negotiate.secblob = smbcli_req_pull_blob(req, transport, + transport->negotiate.secblob = smbcli_req_pull_blob(&req->in.bufinfo, transport, req->in.data, req->in.data_size); } else { /* the old core protocol */ diff --git a/source4/libcli/raw/rawreadwrite.c b/source4/libcli/raw/rawreadwrite.c index b0c49ddab7..2005e36e04 100644 --- a/source4/libcli/raw/rawreadwrite.c +++ b/source4/libcli/raw/rawreadwrite.c @@ -137,7 +137,7 @@ NTSTATUS smb_raw_read_recv(struct smbcli_request *req, union smb_read *parms) SMBCLI_CHECK_WCT(req, 5); parms->lockread.out.nread = SVAL(req->in.vwv, VWV(0)); if (parms->lockread.out.nread > parms->lockread.in.count || - !smbcli_raw_pull_data(req, req->in.data+3, + !smbcli_raw_pull_data(&req->in.bufinfo, req->in.data+3, parms->lockread.out.nread, parms->lockread.out.data)) { req->status = NT_STATUS_BUFFER_TOO_SMALL; } @@ -148,7 +148,7 @@ NTSTATUS smb_raw_read_recv(struct smbcli_request *req, union smb_read *parms) SMBCLI_CHECK_WCT(req, 5); parms->read.out.nread = SVAL(req->in.vwv, VWV(0)); if (parms->read.out.nread > parms->read.in.count || - !smbcli_raw_pull_data(req, req->in.data+3, + !smbcli_raw_pull_data(&req->in.bufinfo, req->in.data+3, parms->read.out.nread, parms->read.out.data)) { req->status = NT_STATUS_BUFFER_TOO_SMALL; } @@ -175,7 +175,7 @@ NTSTATUS smb_raw_read_recv(struct smbcli_request *req, union smb_read *parms) } if (parms->readx.out.nread > MAX(parms->readx.in.mincnt, parms->readx.in.maxcnt) || - !smbcli_raw_pull_data(req, req->in.hdr + SVAL(req->in.vwv, VWV(6)), + !smbcli_raw_pull_data(&req->in.bufinfo, req->in.hdr + SVAL(req->in.vwv, VWV(6)), parms->readx.out.nread, parms->readx.out.data)) { req->status = NT_STATUS_BUFFER_TOO_SMALL; diff --git a/source4/libcli/raw/rawrequest.c b/source4/libcli/raw/rawrequest.c index 3551e5d441..355d092583 100644 --- a/source4/libcli/raw/rawrequest.c +++ b/source4/libcli/raw/rawrequest.c @@ -34,6 +34,20 @@ /* assume that a character will not consume more than 3 bytes per char */ #define MAX_BYTES_PER_CHAR 3 +/* setup the bufinfo used for strings and range checking */ +void smb_setup_bufinfo(struct smbcli_request *req) +{ + req->in.bufinfo.mem_ctx = req; + req->in.bufinfo.flags = 0; + if (req->flags2 & FLAGS2_UNICODE_STRINGS) { + req->in.bufinfo.flags = BUFINFO_FLAG_UNICODE; + } + req->in.bufinfo.align_base = req->in.buffer; + req->in.bufinfo.data = req->in.data; + req->in.bufinfo.data_size = req->in.data_size; +} + + /* destroy a request structure and return final status */ NTSTATUS smbcli_request_destroy(struct smbcli_request *req) { @@ -298,6 +312,9 @@ NTSTATUS smbcli_chained_advance(struct smbcli_request *req) req->in.data = req->in.vwv + 2 + req->in.wct * 2; req->in.data_size = SVAL(req->in.vwv, VWV(req->in.wct)); + /* fix the bufinfo */ + smb_setup_bufinfo(req); + if (buffer + 3 + req->in.wct*2 + req->in.data_size > req->in.buffer + req->in.size) { return NT_STATUS_BUFFER_TOO_SMALL; @@ -544,13 +561,13 @@ size_t smbcli_req_append_var_block(struct smbcli_request *req, const uint8_t *by on failure zero is returned and *dest is set to NULL, otherwise the number of bytes consumed in the packet is returned */ -static size_t smbcli_req_pull_ucs2(struct smbcli_request *req, TALLOC_CTX *mem_ctx, +static size_t smbcli_req_pull_ucs2(struct request_bufinfo *bufinfo, TALLOC_CTX *mem_ctx, char **dest, const uint8_t *src, int byte_len, uint_t flags) { int src_len, src_len2, alignment=0; ssize_t ret; - if (!(flags & STR_NOALIGN) && ucs2_align(req->in.buffer, src, flags)) { + if (!(flags & STR_NOALIGN) && ucs2_align(bufinfo->align_base, src, flags)) { src++; alignment=1; if (byte_len != -1) { @@ -558,7 +575,7 @@ static size_t smbcli_req_pull_ucs2(struct smbcli_request *req, TALLOC_CTX *mem_c } } - src_len = req->in.data_size - PTR_DIFF(src, req->in.data); + src_len = bufinfo->data_size - PTR_DIFF(src, bufinfo->data); if (src_len < 0) { *dest = NULL; return 0; @@ -597,13 +614,13 @@ static size_t smbcli_req_pull_ucs2(struct smbcli_request *req, TALLOC_CTX *mem_c on failure zero is returned and *dest is set to NULL, otherwise the number of bytes consumed in the packet is returned */ -size_t smbcli_req_pull_ascii(struct smbcli_request *req, TALLOC_CTX *mem_ctx, +size_t smbcli_req_pull_ascii(struct request_bufinfo *bufinfo, TALLOC_CTX *mem_ctx, char **dest, const uint8_t *src, int byte_len, uint_t flags) { int src_len, src_len2; ssize_t ret; - src_len = req->in.data_size - PTR_DIFF(src, req->in.data); + src_len = bufinfo->data_size - PTR_DIFF(src, bufinfo->data); if (src_len < 0) { *dest = NULL; return 0; @@ -640,15 +657,15 @@ size_t smbcli_req_pull_ascii(struct smbcli_request *req, TALLOC_CTX *mem_ctx, on failure zero is returned and *dest is set to NULL, otherwise the number of bytes consumed in the packet is returned */ -size_t smbcli_req_pull_string(struct smbcli_request *req, TALLOC_CTX *mem_ctx, +size_t smbcli_req_pull_string(struct request_bufinfo *bufinfo, TALLOC_CTX *mem_ctx, char **dest, const uint8_t *src, int byte_len, uint_t flags) { if (!(flags & STR_ASCII) && - (((flags & STR_UNICODE) || (req->flags2 & FLAGS2_UNICODE_STRINGS)))) { - return smbcli_req_pull_ucs2(req, mem_ctx, dest, src, byte_len, flags); + (((flags & STR_UNICODE) || (bufinfo->flags & BUFINFO_FLAG_UNICODE)))) { + return smbcli_req_pull_ucs2(bufinfo, mem_ctx, dest, src, byte_len, flags); } - return smbcli_req_pull_ascii(req, mem_ctx, dest, src, byte_len, flags); + return smbcli_req_pull_ascii(bufinfo, mem_ctx, dest, src, byte_len, flags); } @@ -658,11 +675,11 @@ size_t smbcli_req_pull_string(struct smbcli_request *req, TALLOC_CTX *mem_ctx, if byte_len is -1 then limit the blob only by packet size */ -DATA_BLOB smbcli_req_pull_blob(struct smbcli_request *req, TALLOC_CTX *mem_ctx, const uint8_t *src, int byte_len) +DATA_BLOB smbcli_req_pull_blob(struct request_bufinfo *bufinfo, TALLOC_CTX *mem_ctx, const uint8_t *src, int byte_len) { int src_len; - src_len = req->in.data_size - PTR_DIFF(src, req->in.data); + src_len = bufinfo->data_size - PTR_DIFF(src, bufinfo->data); if (src_len < 0) { return data_blob(NULL, 0); @@ -677,13 +694,13 @@ DATA_BLOB smbcli_req_pull_blob(struct smbcli_request *req, TALLOC_CTX *mem_ctx, /* check that a lump of data in a request is within the bounds of the data section of the packet */ -static bool smbcli_req_data_oob(struct smbcli_request *req, const uint8_t *ptr, uint32_t count) +static bool smbcli_req_data_oob(struct request_bufinfo *bufinfo, const uint8_t *ptr, uint32_t count) { /* be careful with wraparound! */ - if (ptr < req->in.data || - ptr >= req->in.data + req->in.data_size || - count > req->in.data_size || - ptr + count > req->in.data + req->in.data_size) { + if (ptr < bufinfo->data || + ptr >= bufinfo->data + bufinfo->data_size || + count > bufinfo->data_size || + ptr + count > bufinfo->data + bufinfo->data_size) { return true; } return false; @@ -694,11 +711,11 @@ static bool smbcli_req_data_oob(struct smbcli_request *req, const uint8_t *ptr, return false if any part is outside the data portion of the packet */ -bool smbcli_raw_pull_data(struct smbcli_request *req, const uint8_t *src, int len, uint8_t *dest) +bool smbcli_raw_pull_data(struct request_bufinfo *bufinfo, const uint8_t *src, int len, uint8_t *dest) { if (len == 0) return true; - if (smbcli_req_data_oob(req, src, len)) { + if (smbcli_req_data_oob(bufinfo, src, len)) { return false; } diff --git a/source4/libcli/raw/rawsearch.c b/source4/libcli/raw/rawsearch.c index 33fa90d68d..fb2b09467c 100644 --- a/source4/libcli/raw/rawsearch.c +++ b/source4/libcli/raw/rawsearch.c @@ -54,7 +54,7 @@ static void smb_raw_search_backend(struct smbcli_request *req, search_data.search.write_time = raw_pull_dos_date(req->transport, p + 22); search_data.search.size = IVAL(p, 26); - smbcli_req_pull_ascii(req, mem_ctx, &name, p+30, 13, STR_ASCII); + smbcli_req_pull_ascii(&req->in.bufinfo, mem_ctx, &name, p+30, 13, STR_ASCII); search_data.search.name = name; if (!callback(private, &search_data)) { break; diff --git a/source4/libcli/raw/rawsetfileinfo.c b/source4/libcli/raw/rawsetfileinfo.c index a9a1a3547e..f1e4ee3686 100644 --- a/source4/libcli/raw/rawsetfileinfo.c +++ b/source4/libcli/raw/rawsetfileinfo.c @@ -75,6 +75,16 @@ bool smb_raw_setfileinfo_passthru(TALLOC_CTX *mem_ctx, SIVAL(blob->data, 8, len - 2); return true; + case RAW_SFILEINFO_RENAME_INFORMATION_SMB2: + NEED_BLOB(20); + SIVAL(blob->data, 0, parms->rename_information.in.overwrite); + SBVAL(blob->data, 8, parms->rename_information.in.root_fid); + len = smbcli_blob_append_string(NULL, mem_ctx, blob, + parms->rename_information.in.new_name, + STR_UNICODE|STR_TERMINATE); + SIVAL(blob->data, 16, len - 2); + return true; + case RAW_SFILEINFO_POSITION_INFORMATION: NEED_BLOB(8); SBVAL(blob->data, 0, parms->position_information.in.position); @@ -229,6 +239,7 @@ static bool smb_raw_setinfo_backend(struct smbcli_tree *tree, case RAW_SFILEINFO_UNIX_LINK: case RAW_SFILEINFO_UNIX_HLINK: + case RAW_SFILEINFO_RENAME_INFORMATION_SMB2: break; } diff --git a/source4/libcli/raw/request.h b/source4/libcli/raw/request.h index 803a450e3c..2a572e58ee 100644 --- a/source4/libcli/raw/request.h +++ b/source4/libcli/raw/request.h @@ -22,11 +22,25 @@ #include "libcli/raw/signing.h" +#define BUFINFO_FLAG_UNICODE 0x0001 +#define BUFINFO_FLAG_SMB2 0x0002 + +/* + buffer limit structure used by both SMB and SMB2 + */ +struct request_bufinfo { + TALLOC_CTX *mem_ctx; + uint32_t flags; + const uint8_t *align_base; + const uint8_t *data; + size_t data_size; +}; + /* Shared state structure between client and server, representing the basic packet. */ -struct request_buffer { +struct smb_request_buffer { /* the raw SMB buffer, including the 4 byte length header */ uint8_t *buffer; @@ -56,6 +70,9 @@ struct request_buffer { * a send packet is done we need to move this * pointer */ uint8_t *ptr; + + /* this is used to range check and align strings and buffers */ + struct request_bufinfo bufinfo; }; #endif diff --git a/source4/libcli/raw/smb_signing.c b/source4/libcli/raw/smb_signing.c index 0053710aaf..4acfb9d16d 100644 --- a/source4/libcli/raw/smb_signing.c +++ b/source4/libcli/raw/smb_signing.c @@ -65,7 +65,7 @@ static bool smbcli_set_smb_signing_common(struct smbcli_transport *transport) return true; } -void mark_packet_signed(struct request_buffer *out) +void mark_packet_signed(struct smb_request_buffer *out) { uint16_t flags2; flags2 = SVAL(out->hdr, HDR_FLG2); @@ -101,7 +101,7 @@ bool signing_good(struct smb_signing_context *sign_info, return true; } -void sign_outgoing_message(struct request_buffer *out, DATA_BLOB *mac_key, unsigned int seq_num) +void sign_outgoing_message(struct smb_request_buffer *out, DATA_BLOB *mac_key, unsigned int seq_num) { uint8_t calc_md5_mac[16]; struct MD5Context md5_ctx; @@ -133,7 +133,7 @@ void sign_outgoing_message(struct request_buffer *out, DATA_BLOB *mac_key, unsig Uncomment this to test if the remote server actually verifies signitures...*/ } -bool check_signed_incoming_message(struct request_buffer *in, DATA_BLOB *mac_key, uint_t seq_num) +bool check_signed_incoming_message(struct smb_request_buffer *in, DATA_BLOB *mac_key, uint_t seq_num) { bool good; uint8_t calc_md5_mac[16]; diff --git a/source4/libcli/smb2/connect.c b/source4/libcli/smb2/connect.c index 535df11d9d..85ddafc031 100644 --- a/source4/libcli/smb2/connect.c +++ b/source4/libcli/smb2/connect.c @@ -133,7 +133,7 @@ static void continue_socket(struct composite_context *creq) state->negprot.in.security_mode = 0; state->negprot.in.capabilities = 0; unix_to_nt_time(&state->negprot.in.start_time, time(NULL)); - dialects[0] = 0; + dialects[0] = SMB2_DIALECT_REVISION; state->negprot.in.dialects = dialects; req = smb2_negprot_send(transport, &state->negprot); diff --git a/source4/libcli/smb2/getinfo.c b/source4/libcli/smb2/getinfo.c index 0665dd441c..e9f47140f5 100644 --- a/source4/libcli/smb2/getinfo.c +++ b/source4/libcli/smb2/getinfo.c @@ -30,21 +30,27 @@ struct smb2_request *smb2_getinfo_send(struct smb2_tree *tree, struct smb2_getinfo *io) { struct smb2_request *req; + NTSTATUS status; - req = smb2_request_init_tree(tree, SMB2_OP_GETINFO, 0x28, false, 0); + req = smb2_request_init_tree(tree, SMB2_OP_GETINFO, 0x28, true, + io->in.blob.length); if (req == NULL) return NULL; - /* this seems to be a bug, they use 0x29 but only send 0x28 bytes */ - SSVAL(req->out.body, 0x00, 0x29); - - SSVAL(req->out.body, 0x02, io->in.level); - SIVAL(req->out.body, 0x04, io->in.max_response_size); - 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.flags2); + SCVAL(req->out.body, 0x02, io->in.info_type); + SCVAL(req->out.body, 0x03, io->in.info_class); + SIVAL(req->out.body, 0x04, io->in.output_buffer_length); + SIVAL(req->out.body, 0x0C, io->in.reserved); + SIVAL(req->out.body, 0x08, io->in.input_buffer_length); + SIVAL(req->out.body, 0x10, io->in.additional_information); + SIVAL(req->out.body, 0x14, io->in.getinfo_flags); smb2_push_handle(req->out.body+0x18, &io->in.file.handle); + /* this blob is used for quota queries */ + status = smb2_push_o32s32_blob(&req->out, 0x08, io->in.blob); + if (!NT_STATUS_IS_OK(status)) { + talloc_free(req); + return NULL; + } smb2_transport_send(req); return req; @@ -116,15 +122,17 @@ struct smb2_request *smb2_getinfo_file_send(struct smb2_tree *tree, union smb_fi } ZERO_STRUCT(b); - b.in.max_response_size = 0x10000; - b.in.file.handle = io->generic.in.file.handle; - b.in.level = smb2_level; + b.in.info_type = smb2_level & 0xFF; + b.in.info_class = smb2_level >> 8; + b.in.output_buffer_length = 0x10000; + b.in.input_buffer_length = 0; + b.in.file.handle = io->generic.in.file.handle; if (io->generic.level == RAW_FILEINFO_SEC_DESC) { - b.in.flags = io->query_secdesc.in.secinfo_flags; + b.in.additional_information = io->query_secdesc.in.secinfo_flags; } if (io->generic.level == RAW_FILEINFO_SMB2_ALL_EAS) { - b.in.flags2 = io->all_eas.in.continue_flags; + b.in.getinfo_flags = io->all_eas.in.continue_flags; } return smb2_getinfo_send(tree, &b); @@ -172,9 +180,10 @@ struct smb2_request *smb2_getinfo_fs_send(struct smb2_tree *tree, union smb_fsin } ZERO_STRUCT(b); - b.in.max_response_size = 0x10000; - b.in.file.handle = io->generic.handle; - b.in.level = smb2_level; + b.in.output_buffer_length = 0x10000; + b.in.file.handle = io->generic.handle; + b.in.info_type = smb2_level & 0xFF; + b.in.info_class = smb2_level >> 8; return smb2_getinfo_send(tree, &b); } diff --git a/source4/libcli/smb2/request.c b/source4/libcli/smb2/request.c index 46ec24145f..7a0311f886 100644 --- a/source4/libcli/smb2/request.c +++ b/source4/libcli/smb2/request.c @@ -28,6 +28,21 @@ #include "libcli/smb2/smb2_calls.h" #include "param/param.h" +/* fill in the bufinfo */ +void smb2_setup_bufinfo(struct smb2_request *req) +{ + req->in.bufinfo.mem_ctx = req; + req->in.bufinfo.flags = BUFINFO_FLAG_UNICODE | BUFINFO_FLAG_SMB2; + req->in.bufinfo.align_base = req->in.buffer; + if (req->in.dynamic) { + req->in.bufinfo.data = req->in.dynamic; + req->in.bufinfo.data_size = req->in.body_size - req->in.body_fixed; + } else { + req->in.bufinfo.data = NULL; + req->in.bufinfo.data_size = 0; + } +} + /* initialise a smb2 request */ @@ -534,6 +549,33 @@ NTSTATUS smb2_pull_o32s32_blob(struct smb2_request_buffer *buf, TALLOC_CTX *mem_ } /* + pull a uint16_t ofs/ uint32_t length/blob triple from a data blob + the ptr points to the start of the offset/length pair + + In this varient the uint16_t is padded by an extra 2 bytes, making + the size aligned on 4 byte boundary +*/ +NTSTATUS smb2_pull_o16As32_blob(struct smb2_request_buffer *buf, TALLOC_CTX *mem_ctx, uint8_t *ptr, DATA_BLOB *blob) +{ + uint32_t ofs, size; + if (smb2_oob(buf, ptr, 8)) { + return NT_STATUS_BUFFER_TOO_SMALL; + } + ofs = SVAL(ptr, 0); + size = IVAL(ptr, 4); + if (ofs == 0 || size == 0) { + *blob = data_blob(NULL, 0); + return NT_STATUS_OK; + } + if (smb2_oob(buf, buf->hdr + ofs, size)) { + return NT_STATUS_BUFFER_TOO_SMALL; + } + *blob = data_blob_talloc(mem_ctx, buf->hdr + ofs, size); + NT_STATUS_HAVE_NO_MEMORY(blob->data); + return NT_STATUS_OK; +} + +/* pull a uint32_t length/ uint32_t ofs/blob triple from a data blob the ptr points to the start of the offset/length pair */ diff --git a/source4/libcli/smb2/setinfo.c b/source4/libcli/smb2/setinfo.c index d942568a2d..a6e22d9a68 100644 --- a/source4/libcli/smb2/setinfo.c +++ b/source4/libcli/smb2/setinfo.c @@ -92,6 +92,12 @@ struct smb2_request *smb2_setinfo_file_send(struct smb2_tree *tree, union smb_se ZERO_STRUCT(b); b.in.level = smb2_level; b.in.file.handle = io->generic.in.file.handle; + + /* change levels so the parsers know it is SMB2 */ + if (io->generic.level == RAW_SFILEINFO_RENAME_INFORMATION) { + io->generic.level = RAW_SFILEINFO_RENAME_INFORMATION_SMB2; + } + if (!smb_raw_setfileinfo_passthru(tree, io->generic.level, io, &b.in.blob)) { return NULL; } diff --git a/source4/libcli/smb2/smb2.h b/source4/libcli/smb2/smb2.h index db13ab69b3..726df64090 100644 --- a/source4/libcli/smb2/smb2.h +++ b/source4/libcli/smb2/smb2.h @@ -19,6 +19,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ +#include "libcli/raw/request.h" + struct smb2_options { uint32_t timeout; }; @@ -102,6 +104,9 @@ struct smb2_request_buffer { * this will be moved when some dynamic data is pushed */ uint8_t *dynamic; + + /* this is used to range check and align strings and buffers */ + struct request_bufinfo bufinfo; }; @@ -195,6 +200,9 @@ struct smb2_request { #define SMB2_MAGIC 0x424D53FE /* 0xFE 'S' 'M' 'B' */ +/* the dialect we support */ +#define SMB2_DIALECT_REVISION 0x202 + /* SMB2 negotiate security_mode */ #define SMB2_NEGOTIATE_SIGNING_ENABLED 0x01 #define SMB2_NEGOTIATE_SIGNING_REQUIRED 0x02 diff --git a/source4/libcli/smb2/smb2_calls.h b/source4/libcli/smb2/smb2_calls.h index f2e3019d83..f66236af30 100644 --- a/source4/libcli/smb2/smb2_calls.h +++ b/source4/libcli/smb2/smb2_calls.h @@ -56,6 +56,13 @@ struct smb2_negprot { #define SMB2_GETINFO_FILE 0x01 #define SMB2_GETINFO_FS 0x02 #define SMB2_GETINFO_SECURITY 0x03 +#define SMB2_GETINFO_QUOTA 0x04 + +#define SMB2_GETINFO_ADD_OWNER_SECURITY 0x01 +#define SMB2_GETINFO_ADD_GROUP_SECURITY 0x02 +#define SMB2_GETINFO_ADD_DACL_SECURITY 0x04 +#define SMB2_GETINFO_ADD_SACL_SECURITY 0x08 +#define SMB2_GETINFO_ADD_LABEL_SECURITY 0x10 /* NOTE! the getinfo fs and file levels exactly match up with the 'passthru' SMB levels, which are levels >= 1000. The SMB2 client @@ -64,14 +71,17 @@ struct smb2_negprot { struct smb2_getinfo { struct { /* static body buffer 40 (0x28) bytes */ - /* uint16_t buffer_code; 0x29 = 0x28 + 1 (why???) */ - uint16_t level; - uint32_t max_response_size; - uint32_t unknown1; - uint32_t unknown2; - uint32_t flags; /* level specific */ - uint32_t flags2; /* used by all_eas level */ + /* uint16_t buffer_code; 0x29 = 0x28 + 1 */ + uint8_t info_type; + uint8_t info_class; + uint32_t output_buffer_length; + /* uint32_t input_buffer_offset; */ + uint32_t reserved; + uint32_t input_buffer_length; + uint32_t additional_information; /* SMB2_GETINFO_ADD_* */ + uint32_t getinfo_flags; /* level specific */ union smb_handle file; + DATA_BLOB blob; } in; struct { diff --git a/source4/libcli/smb2/transport.c b/source4/libcli/smb2/transport.c index dceb78382a..1d601fdbfe 100644 --- a/source4/libcli/smb2/transport.c +++ b/source4/libcli/smb2/transport.c @@ -216,6 +216,8 @@ static NTSTATUS smb2_transport_finish_recv(void *private, DATA_BLOB blob) } } + smb2_setup_bufinfo(req); + DEBUG(2, ("SMB2 RECV seqnum=0x%llx\n", (long long)req->seqnum)); dump_data(5, req->in.body, req->in.body_size); |