2 Unix SMB/CIFS implementation.
4 Copyright (C) Andrew Tridgell 2003
5 Copyright (C) James Myers 2003 <myersjj@samba.org>
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 this file implements functions for manipulating the 'struct smbcli_request' structure in libsmb
28 /* we over allocate the data buffer to prevent too many realloc calls */
29 #define REQ_OVER_ALLOCATION 256
31 /* assume that a character will not consume more than 3 bytes per char */
32 #define MAX_BYTES_PER_CHAR 3
34 /* destroy a request structure and return final status */
35 NTSTATUS smbcli_request_destroy(struct smbcli_request *req)
39 /* this is the error code we give the application for when a
40 _send() call fails completely */
41 if (!req) return NT_STATUS_UNSUCCESSFUL;
44 /* remove it from the list of pending requests (a null op if
45 its not in the list) */
46 DLIST_REMOVE(req->transport->pending_recv, req);
49 /* ahh, its so nice to destroy a complex structure in such a
52 talloc_destroy(req->mem_ctx);
58 low-level function to setup a request buffer for a non-SMB packet
59 at the transport level
61 struct smbcli_request *smbcli_request_setup_nonsmb(struct smbcli_transport *transport, uint_t size)
63 struct smbcli_request *req;
66 /* each request gets its own talloc context. The request
67 structure itself is also allocated inside this context,
68 so we need to allocate it before we construct the request
70 mem_ctx = talloc_init("smbcli_request");
75 req = talloc(mem_ctx, sizeof(struct smbcli_request));
81 /* setup the request context */
82 req->state = SMBCLI_REQUEST_INIT;
83 req->mem_ctx = mem_ctx;
84 req->transport = transport;
89 /* over allocate by a small amount */
90 req->out.allocated = req->out.size + REQ_OVER_ALLOCATION;
92 req->out.buffer = talloc(req->mem_ctx, req->out.allocated);
93 if (!req->out.buffer) {
97 SIVAL(req->out.buffer, 0, 0);
104 setup a SMB packet at transport level
106 struct smbcli_request *smbcli_request_setup_transport(struct smbcli_transport *transport,
107 uint8_t command, uint_t wct, uint_t buflen)
109 struct smbcli_request *req;
111 req = smbcli_request_setup_nonsmb(transport, NBT_HDR_SIZE + MIN_SMB_SIZE + wct*2 + buflen);
113 if (!req) return NULL;
115 req->out.hdr = req->out.buffer + NBT_HDR_SIZE;
116 req->out.vwv = req->out.hdr + HDR_VWV;
118 req->out.data = req->out.vwv + VWV(wct) + 2;
119 req->out.data_size = buflen;
120 req->out.ptr = req->out.data;
122 SCVAL(req->out.hdr, HDR_WCT, wct);
123 SSVAL(req->out.vwv, VWV(wct), buflen);
125 memcpy(req->out.hdr, "\377SMB", 4);
126 SCVAL(req->out.hdr,HDR_COM,command);
128 SCVAL(req->out.hdr,HDR_FLG, FLAG_CASELESS_PATHNAMES);
129 SSVAL(req->out.hdr,HDR_FLG2, 0);
132 req->mid = smbcli_transport_next_mid(transport);
134 /* copy the pid, uid and mid to the request */
135 SSVAL(req->out.hdr, HDR_PID, 0);
136 SSVAL(req->out.hdr, HDR_UID, 0);
137 SSVAL(req->out.hdr, HDR_MID, req->mid);
138 SSVAL(req->out.hdr, HDR_TID,0);
139 SSVAL(req->out.hdr, HDR_PIDHIGH,0);
140 SIVAL(req->out.hdr, HDR_RCLS, 0);
141 memset(req->out.hdr+HDR_SS_FIELD, 0, 10);
147 setup a reply in req->out with the given word count and initial data
148 buffer size. the caller will then fill in the command words and
149 data before calling smbcli_request_send() to send the reply on its
150 way. This interface is used before a session is setup.
152 struct smbcli_request *smbcli_request_setup_session(struct smbcli_session *session,
153 uint8_t command, uint_t wct, uint_t buflen)
155 struct smbcli_request *req;
157 uint32_t capabilities;
159 req = smbcli_request_setup_transport(session->transport, command, wct, buflen);
161 if (!req) return NULL;
163 req->session = session;
165 flags2 = FLAGS2_LONG_PATH_COMPONENTS;
166 capabilities = session->transport->negotiate.capabilities;
168 if (capabilities & CAP_UNICODE) {
169 flags2 |= FLAGS2_UNICODE_STRINGS;
171 if (capabilities & CAP_STATUS32) {
172 flags2 |= FLAGS2_32_BIT_ERROR_CODES;
174 if (capabilities & CAP_EXTENDED_SECURITY) {
175 flags2 |= FLAGS2_EXTENDED_SECURITY;
177 if (session->transport->negotiate.sign_info.doing_signing) {
178 flags2 |= FLAGS2_SMB_SECURITY_SIGNATURES;
181 SSVAL(req->out.hdr, HDR_FLG2, flags2);
182 SSVAL(req->out.hdr, HDR_PID, session->pid & 0xFFFF);
183 SSVAL(req->out.hdr, HDR_PIDHIGH, session->pid >> 16);
184 SSVAL(req->out.hdr, HDR_UID, session->vuid);
190 setup a request for tree based commands
192 struct smbcli_request *smbcli_request_setup(struct smbcli_tree *tree,
194 uint_t wct, uint_t buflen)
196 struct smbcli_request *req;
198 req = smbcli_request_setup_session(tree->session, command, wct, buflen);
201 SSVAL(req->out.hdr,HDR_TID,tree->tid);
207 grow the allocation of the data buffer portion of a reply
208 packet. Note that as this can reallocate the packet buffer this
209 invalidates any local pointers into the packet.
211 To cope with this req->out.ptr is supplied. This will be updated to
212 point at the same offset into the packet as before this call
214 static void smbcli_req_grow_allocation(struct smbcli_request *req, uint_t new_size)
219 delta = new_size - req->out.data_size;
220 if (delta + req->out.size <= req->out.allocated) {
221 /* it fits in the preallocation */
225 /* we need to realloc */
226 req->out.allocated = req->out.size + delta + REQ_OVER_ALLOCATION;
227 buf2 = talloc_realloc(req->mem_ctx, req->out.buffer, req->out.allocated);
229 smb_panic("out of memory in req_grow_allocation");
232 if (buf2 == req->out.buffer) {
233 /* the malloc library gave us the same pointer */
237 /* update the pointers into the packet */
238 req->out.data = buf2 + PTR_DIFF(req->out.data, req->out.buffer);
239 req->out.ptr = buf2 + PTR_DIFF(req->out.ptr, req->out.buffer);
240 req->out.vwv = buf2 + PTR_DIFF(req->out.vwv, req->out.buffer);
241 req->out.hdr = buf2 + PTR_DIFF(req->out.hdr, req->out.buffer);
243 req->out.buffer = buf2;
248 grow the data buffer portion of a reply packet. Note that as this
249 can reallocate the packet buffer this invalidates any local pointers
252 To cope with this req->out.ptr is supplied. This will be updated to
253 point at the same offset into the packet as before this call
255 static void smbcli_req_grow_data(struct smbcli_request *req, uint_t new_size)
259 smbcli_req_grow_allocation(req, new_size);
261 delta = new_size - req->out.data_size;
263 req->out.size += delta;
264 req->out.data_size += delta;
266 /* set the BCC to the new data size */
267 SSVAL(req->out.vwv, VWV(req->out.wct), new_size);
274 BOOL smbcli_request_send(struct smbcli_request *req)
276 if (IVAL(req->out.buffer, 0) == 0) {
277 _smb_setlen(req->out.buffer, req->out.size - NBT_HDR_SIZE);
280 smbcli_request_calculate_sign_mac(req);
282 smbcli_transport_send(req);
289 receive a response to a packet
291 BOOL smbcli_request_receive(struct smbcli_request *req)
293 /* req can be NULL when a send has failed. This eliminates lots of NULL
294 checks in each module */
295 if (!req) return False;
297 /* keep receiving packets until this one is replied to */
298 while (req->state <= SMBCLI_REQUEST_RECV) {
299 event_loop_once(req->transport->event.ctx);
307 receive another reply to a request - this is used for requests that
308 have multi-part replies (such as SMBtrans2)
310 BOOL smbcli_request_receive_more(struct smbcli_request *req)
312 req->state = SMBCLI_REQUEST_RECV;
313 DLIST_ADD(req->transport->pending_recv, req);
315 return smbcli_request_receive(req);
320 handle oplock break requests from the server - return True if the request was
323 BOOL handle_oplock_break(struct smbcli_transport *transport, uint_t len, const char *hdr, const char *vwv)
325 /* we must be very fussy about what we consider an oplock break to avoid
326 matching readbraw replies */
327 if (len != MIN_SMB_SIZE + VWV(8) + NBT_HDR_SIZE ||
328 (CVAL(hdr, HDR_FLG) & FLAG_REPLY) ||
329 CVAL(hdr,HDR_COM) != SMBlockingX ||
330 SVAL(hdr, HDR_MID) != 0xFFFF ||
331 SVAL(vwv,VWV(6)) != 0 ||
332 SVAL(vwv,VWV(7)) != 0) {
336 if (transport->oplock.handler) {
337 uint16_t tid = SVAL(hdr, HDR_TID);
338 uint16_t fnum = SVAL(vwv,VWV(2));
339 uint8_t level = CVAL(vwv,VWV(3)+1);
340 transport->oplock.handler(transport, tid, fnum, level, transport->oplock.private);
347 wait for a reply to be received for a packet that just returns an error
348 code and nothing more
350 NTSTATUS smbcli_request_simple_recv(struct smbcli_request *req)
352 smbcli_request_receive(req);
353 return smbcli_request_destroy(req);
357 /* Return true if the last packet was in error */
358 BOOL smbcli_request_is_error(struct smbcli_request *req)
360 return NT_STATUS_IS_ERR(req->status);
364 append a string into the data portion of the request packet
366 return the number of bytes added to the packet
368 size_t smbcli_req_append_string(struct smbcli_request *req, const char *str, uint_t flags)
372 /* determine string type to use */
373 if (!(flags & (STR_ASCII|STR_UNICODE))) {
374 flags |= (req->transport->negotiate.capabilities & CAP_UNICODE) ? STR_UNICODE : STR_ASCII;
377 len = (strlen(str)+2) * MAX_BYTES_PER_CHAR;
379 smbcli_req_grow_allocation(req, len + req->out.data_size);
381 len = push_string(NULL, req->out.data + req->out.data_size, str, len, flags);
383 smbcli_req_grow_data(req, len + req->out.data_size);
389 this is like smbcli_req_append_string but it also return the
390 non-terminated string byte length, which can be less than the number
391 of bytes consumed in the packet for 2 reasons:
393 1) the string in the packet may be null terminated
394 2) the string in the packet may need a 1 byte UCS2 alignment
396 this is used in places where the non-terminated string byte length is
397 placed in the packet as a separate field
399 size_t smbcli_req_append_string_len(struct smbcli_request *req, const char *str, uint_t flags, int *len)
404 /* determine string type to use */
405 if (!(flags & (STR_ASCII|STR_UNICODE))) {
406 flags |= (req->transport->negotiate.capabilities & CAP_UNICODE) ? STR_UNICODE : STR_ASCII;
409 /* see if an alignment byte will be used */
410 if ((flags & STR_UNICODE) && !(flags & STR_NOALIGN)) {
411 diff = ucs2_align(NULL, req->out.data + req->out.data_size, flags);
414 /* do the hard work */
415 ret = smbcli_req_append_string(req, str, flags);
417 /* see if we need to subtract the termination */
418 if (flags & STR_TERMINATE) {
419 diff += (flags & STR_UNICODE) ? 2 : 1;
433 push a string into the data portion of the request packet, growing it if necessary
434 this gets quite tricky - please be very careful to cover all cases when modifying this
436 if dest is NULL, then put the string at the end of the data portion of the packet
438 if dest_len is -1 then no limit applies
440 size_t smbcli_req_append_ascii4(struct smbcli_request *req, const char *str, uint_t flags)
443 smbcli_req_append_bytes(req, (const uint8_t *)"\4", 1);
444 size = smbcli_req_append_string(req, str, flags);
450 push a blob into the data portion of the request packet, growing it if necessary
451 this gets quite tricky - please be very careful to cover all cases when modifying this
453 if dest is NULL, then put the blob at the end of the data portion of the packet
455 size_t smbcli_req_append_blob(struct smbcli_request *req, const DATA_BLOB *blob)
457 smbcli_req_grow_allocation(req, req->out.data_size + blob->length);
458 memcpy(req->out.data + req->out.data_size, blob->data, blob->length);
459 smbcli_req_grow_data(req, req->out.data_size + blob->length);
464 append raw bytes into the data portion of the request packet
465 return the number of bytes added
467 size_t smbcli_req_append_bytes(struct smbcli_request *req, const uint8_t *bytes, size_t byte_len)
469 smbcli_req_grow_allocation(req, byte_len + req->out.data_size);
470 memcpy(req->out.data + req->out.data_size, bytes, byte_len);
471 smbcli_req_grow_data(req, byte_len + req->out.data_size);
476 append variable block (type 5 buffer) into the data portion of the request packet
477 return the number of bytes added
479 size_t smbcli_req_append_var_block(struct smbcli_request *req, const uint8_t *bytes, uint16_t byte_len)
481 smbcli_req_grow_allocation(req, byte_len + 3 + req->out.data_size);
482 SCVAL(req->out.data + req->out.data_size, 0, 5);
483 SSVAL(req->out.data + req->out.data_size, 1, byte_len); /* add field length */
485 memcpy(req->out.data + req->out.data_size + 3, bytes, byte_len);
487 smbcli_req_grow_data(req, byte_len + 3 + req->out.data_size);
493 pull a UCS2 string from a request packet, returning a talloced unix string
495 the string length is limited by the 3 things:
496 - the data size in the request (end of packet)
497 - the passed 'byte_len' if it is not -1
498 - the end of string (null termination)
500 Note that 'byte_len' is the number of bytes in the packet
502 on failure zero is returned and *dest is set to NULL, otherwise the number
503 of bytes consumed in the packet is returned
505 static size_t smbcli_req_pull_ucs2(struct smbcli_request *req, TALLOC_CTX *mem_ctx,
506 char **dest, const char *src, int byte_len, uint_t flags)
508 int src_len, src_len2, alignment=0;
511 if (!(flags & STR_NOALIGN) && ucs2_align(req->in.buffer, src, flags)) {
514 if (byte_len != -1) {
519 src_len = req->in.data_size - PTR_DIFF(src, req->in.data);
524 if (byte_len != -1 && src_len > byte_len) {
528 src_len2 = strnlen_w((const smb_ucs2_t *)src, src_len/2) * 2;
529 if (src_len2 < src_len - 2) {
530 /* include the termination if we didn't reach the end of the packet */
534 /* ucs2 strings must be at least 2 bytes long */
540 ret = convert_string_talloc(mem_ctx, CH_UCS2, CH_UNIX, src, src_len2, (const void **)dest);
546 return src_len2 + alignment;
550 pull a ascii string from a request packet, returning a talloced string
552 the string length is limited by the 3 things:
553 - the data size in the request (end of packet)
554 - the passed 'byte_len' if it is not -1
555 - the end of string (null termination)
557 Note that 'byte_len' is the number of bytes in the packet
559 on failure zero is returned and *dest is set to NULL, otherwise the number
560 of bytes consumed in the packet is returned
562 size_t smbcli_req_pull_ascii(struct smbcli_request *req, TALLOC_CTX *mem_ctx,
563 char **dest, const char *src, int byte_len, uint_t flags)
565 int src_len, src_len2;
568 src_len = req->in.data_size - PTR_DIFF(src, req->in.data);
573 if (byte_len != -1 && src_len > byte_len) {
576 src_len2 = strnlen(src, src_len);
577 if (src_len2 < src_len - 1) {
578 /* include the termination if we didn't reach the end of the packet */
582 ret = convert_string_talloc(mem_ctx, CH_DOS, CH_UNIX, src, src_len2, (const void **)dest);
593 pull a string from a request packet, returning a talloced string
595 the string length is limited by the 3 things:
596 - the data size in the request (end of packet)
597 - the passed 'byte_len' if it is not -1
598 - the end of string (null termination)
600 Note that 'byte_len' is the number of bytes in the packet
602 on failure zero is returned and *dest is set to NULL, otherwise the number
603 of bytes consumed in the packet is returned
605 size_t smbcli_req_pull_string(struct smbcli_request *req, TALLOC_CTX *mem_ctx,
606 char **dest, const char *src, int byte_len, uint_t flags)
608 if (!(flags & STR_ASCII) &&
609 (((flags & STR_UNICODE) || (req->flags2 & FLAGS2_UNICODE_STRINGS)))) {
610 return smbcli_req_pull_ucs2(req, mem_ctx, dest, src, byte_len, flags);
613 return smbcli_req_pull_ascii(req, mem_ctx, dest, src, byte_len, flags);
618 pull a DATA_BLOB from a reply packet, returning a talloced blob
619 make sure we don't go past end of packet
621 if byte_len is -1 then limit the blob only by packet size
623 DATA_BLOB smbcli_req_pull_blob(struct smbcli_request *req, TALLOC_CTX *mem_ctx, const char *src, int byte_len)
627 src_len = req->in.data_size - PTR_DIFF(src, req->in.data);
630 return data_blob(NULL, 0);
633 if (byte_len != -1 && src_len > byte_len) {
637 return data_blob_talloc(mem_ctx, src, src_len);
640 /* check that a lump of data in a request is within the bounds of the data section of
642 static BOOL smbcli_req_data_oob(struct smbcli_request *req, const char *ptr, uint32_t count)
644 /* be careful with wraparound! */
645 if (ptr < req->in.data ||
646 ptr >= req->in.data + req->in.data_size ||
647 count > req->in.data_size ||
648 ptr + count > req->in.data + req->in.data_size) {
655 pull a lump of data from a request packet
657 return False if any part is outside the data portion of the packet
659 BOOL smbcli_raw_pull_data(struct smbcli_request *req, const char *src, int len, char *dest)
661 if (len == 0) return True;
663 if (smbcli_req_data_oob(req, src, len)) {
667 memcpy(dest, src, len);
673 put a NTTIME into a packet
675 void smbcli_push_nttime(void *base, uint16_t offset, NTTIME t)
677 SBVAL(base, offset, t);
681 pull a NTTIME from a packet
683 NTTIME smbcli_pull_nttime(void *base, uint16_t offset)
685 NTTIME ret = BVAL(base, offset);
690 pull a UCS2 string from a blob, returning a talloced unix string
692 the string length is limited by the 3 things:
693 - the data size in the blob
694 - the passed 'byte_len' if it is not -1
695 - the end of string (null termination)
697 Note that 'byte_len' is the number of bytes in the packet
699 on failure zero is returned and *dest is set to NULL, otherwise the number
700 of bytes consumed in the blob is returned
702 static size_t smbcli_blob_pull_ucs2(TALLOC_CTX* mem_ctx,
703 DATA_BLOB *blob, const char **dest,
704 const char *src, int byte_len, uint_t flags)
706 int src_len, src_len2, alignment=0;
709 if (src < (const char *)blob->data ||
710 src >= (const char *)(blob->data + blob->length)) {
715 src_len = blob->length - PTR_DIFF(src, blob->data);
717 if (byte_len != -1 && src_len > byte_len) {
721 if (!(flags & STR_NOALIGN) && ucs2_align(blob->data, src, flags)) {
732 src_len2 = strnlen_w((const smb_ucs2_t *)src, src_len/2) * 2;
734 if (src_len2 < src_len - 2) {
735 /* include the termination if we didn't reach the end of the packet */
739 ret = convert_string_talloc(mem_ctx, CH_UCS2, CH_UNIX, src, src_len2, (const void **)dest);
745 return src_len2 + alignment;
749 pull a ascii string from a blob, returning a talloced string
751 the string length is limited by the 3 things:
752 - the data size in the blob
753 - the passed 'byte_len' if it is not -1
754 - the end of string (null termination)
756 Note that 'byte_len' is the number of bytes in the blob
758 on failure zero is returned and *dest is set to NULL, otherwise the number
759 of bytes consumed in the blob is returned
761 static size_t smbcli_blob_pull_ascii(TALLOC_CTX *mem_ctx,
762 DATA_BLOB *blob, const char **dest,
763 const char *src, int byte_len, uint_t flags)
765 int src_len, src_len2;
768 src_len = blob->length - PTR_DIFF(src, blob->data);
773 if (byte_len != -1 && src_len > byte_len) {
776 src_len2 = strnlen(src, src_len);
778 if (src_len2 < src_len - 1) {
779 /* include the termination if we didn't reach the end of the packet */
783 ret = convert_string_talloc(mem_ctx, CH_DOS, CH_UNIX, src, src_len2, (const void **)dest);
794 pull a string from a blob, returning a talloced WIRE_STRING
796 the string length is limited by the 3 things:
797 - the data size in the blob
798 - length field on the wire
799 - the end of string (null termination)
801 if STR_LEN8BIT is set in the flags then assume the length field is
802 8 bits, instead of 32
804 on failure zero is returned and dest->s is set to NULL, otherwise the number
805 of bytes consumed in the blob is returned
807 size_t smbcli_blob_pull_string(struct smbcli_session *session,
811 uint16_t len_offset, uint16_t str_offset,
817 if (len_offset > blob->length-4) {
820 if (flags & STR_LEN8BIT) {
821 dest->private_length = CVAL(blob->data, len_offset);
823 dest->private_length = IVAL(blob->data, len_offset);
827 if (!(flags & STR_ASCII) &&
828 ((flags & STR_UNICODE) ||
829 (session->transport->negotiate.capabilities & CAP_UNICODE))) {
831 if ((str_offset&1) && !(flags & STR_NOALIGN)) {
834 if (flags & STR_LEN_NOTERM) {
837 return align + extra + smbcli_blob_pull_ucs2(mem_ctx, blob, &dest->s,
838 blob->data+str_offset+align,
839 dest->private_length, flags);
842 if (flags & STR_LEN_NOTERM) {
846 return extra + smbcli_blob_pull_ascii(mem_ctx, blob, &dest->s,
847 blob->data+str_offset, dest->private_length, flags);
851 pull a string from a blob, returning a talloced char *
853 Currently only used by the UNIX search info level.
855 the string length is limited by 2 things:
856 - the data size in the blob
857 - the end of string (null termination)
859 on failure zero is returned and dest->s is set to NULL, otherwise the number
860 of bytes consumed in the blob is returned
862 size_t smbcli_blob_pull_unix_string(struct smbcli_session *session,
872 if (!(flags & STR_ASCII) &&
873 ((flags & STR_UNICODE) ||
874 (session->transport->negotiate.capabilities & CAP_UNICODE))) {
876 if ((str_offset&1) && !(flags & STR_NOALIGN)) {
879 if (flags & STR_LEN_NOTERM) {
882 return align + extra + smbcli_blob_pull_ucs2(mem_ctx, blob, dest,
883 blob->data+str_offset+align,
887 if (flags & STR_LEN_NOTERM) {
891 return extra + smbcli_blob_pull_ascii(mem_ctx, blob, dest,
892 blob->data+str_offset, -1, flags);
897 append a string into a blob
899 size_t smbcli_blob_append_string(struct smbcli_session *session,
900 TALLOC_CTX *mem_ctx, DATA_BLOB *blob,
901 const char *str, uint_t flags)
908 /* determine string type to use */
909 if (!(flags & (STR_ASCII|STR_UNICODE))) {
910 flags |= (session->transport->negotiate.capabilities & CAP_UNICODE) ? STR_UNICODE : STR_ASCII;
913 max_len = (strlen(str)+2) * MAX_BYTES_PER_CHAR;
915 blob->data = talloc_realloc(mem_ctx, blob->data, blob->length + max_len);
920 len = push_string(NULL, blob->data + blob->length, str, max_len, flags);