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
27 #include "libcli/raw/libcliraw.h"
28 #include "dlinklist.h"
30 /* we over allocate the data buffer to prevent too many realloc calls */
31 #define REQ_OVER_ALLOCATION 0
33 /* assume that a character will not consume more than 3 bytes per char */
34 #define MAX_BYTES_PER_CHAR 3
36 /* destroy a request structure and return final status */
37 NTSTATUS smbcli_request_destroy(struct smbcli_request *req)
41 /* this is the error code we give the application for when a
42 _send() call fails completely */
43 if (!req) return NT_STATUS_UNSUCCESSFUL;
46 /* remove it from the list of pending requests (a null op if
47 its not in the list) */
48 DLIST_REMOVE(req->transport->pending_recv, req);
51 /* ahh, its so nice to destroy a complex structure in such a
60 low-level function to setup a request buffer for a non-SMB packet
61 at the transport level
63 struct smbcli_request *smbcli_request_setup_nonsmb(struct smbcli_transport *transport, uint_t size)
65 struct smbcli_request *req;
67 req = talloc_p(transport, struct smbcli_request);
73 /* setup the request context */
74 req->state = SMBCLI_REQUEST_INIT;
75 req->transport = transport;
80 /* over allocate by a small amount */
81 req->out.allocated = req->out.size + REQ_OVER_ALLOCATION;
83 req->out.buffer = talloc(req, req->out.allocated);
84 if (!req->out.buffer) {
88 SIVAL(req->out.buffer, 0, 0);
95 setup a SMB packet at transport level
97 struct smbcli_request *smbcli_request_setup_transport(struct smbcli_transport *transport,
98 uint8_t command, uint_t wct, uint_t buflen)
100 struct smbcli_request *req;
102 req = smbcli_request_setup_nonsmb(transport, NBT_HDR_SIZE + MIN_SMB_SIZE + wct*2 + buflen);
104 if (!req) return NULL;
106 req->out.hdr = req->out.buffer + NBT_HDR_SIZE;
107 req->out.vwv = req->out.hdr + HDR_VWV;
109 req->out.data = req->out.vwv + VWV(wct) + 2;
110 req->out.data_size = buflen;
111 req->out.ptr = req->out.data;
113 SCVAL(req->out.hdr, HDR_WCT, wct);
114 SSVAL(req->out.vwv, VWV(wct), buflen);
116 memcpy(req->out.hdr, "\377SMB", 4);
117 SCVAL(req->out.hdr,HDR_COM,command);
119 SCVAL(req->out.hdr,HDR_FLG, FLAG_CASELESS_PATHNAMES);
120 SSVAL(req->out.hdr,HDR_FLG2, 0);
123 req->mid = smbcli_transport_next_mid(transport);
125 /* copy the pid, uid and mid to the request */
126 SSVAL(req->out.hdr, HDR_PID, 0);
127 SSVAL(req->out.hdr, HDR_UID, 0);
128 SSVAL(req->out.hdr, HDR_MID, req->mid);
129 SSVAL(req->out.hdr, HDR_TID,0);
130 SSVAL(req->out.hdr, HDR_PIDHIGH,0);
131 SIVAL(req->out.hdr, HDR_RCLS, 0);
132 memset(req->out.hdr+HDR_SS_FIELD, 0, 10);
138 setup a reply in req->out with the given word count and initial data
139 buffer size. the caller will then fill in the command words and
140 data before calling smbcli_request_send() to send the reply on its
141 way. This interface is used before a session is setup.
143 struct smbcli_request *smbcli_request_setup_session(struct smbcli_session *session,
144 uint8_t command, uint_t wct, uint_t buflen)
146 struct smbcli_request *req;
148 req = smbcli_request_setup_transport(session->transport, command, wct, buflen);
150 if (!req) return NULL;
152 req->session = session;
154 SSVAL(req->out.hdr, HDR_FLG2, session->flags2);
155 SSVAL(req->out.hdr, HDR_PID, session->pid & 0xFFFF);
156 SSVAL(req->out.hdr, HDR_PIDHIGH, session->pid >> 16);
157 SSVAL(req->out.hdr, HDR_UID, session->vuid);
163 setup a request for tree based commands
165 struct smbcli_request *smbcli_request_setup(struct smbcli_tree *tree,
167 uint_t wct, uint_t buflen)
169 struct smbcli_request *req;
171 req = smbcli_request_setup_session(tree->session, command, wct, buflen);
174 SSVAL(req->out.hdr,HDR_TID,tree->tid);
180 grow the allocation of the data buffer portion of a reply
181 packet. Note that as this can reallocate the packet buffer this
182 invalidates any local pointers into the packet.
184 To cope with this req->out.ptr is supplied. This will be updated to
185 point at the same offset into the packet as before this call
187 static void smbcli_req_grow_allocation(struct smbcli_request *req, uint_t new_size)
192 delta = new_size - req->out.data_size;
193 if (delta + req->out.size <= req->out.allocated) {
194 /* it fits in the preallocation */
198 /* we need to realloc */
199 req->out.allocated = req->out.size + delta + REQ_OVER_ALLOCATION;
200 buf2 = talloc_realloc(req, req->out.buffer, req->out.allocated);
202 smb_panic("out of memory in req_grow_allocation");
205 if (buf2 == req->out.buffer) {
206 /* the malloc library gave us the same pointer */
210 /* update the pointers into the packet */
211 req->out.data = buf2 + PTR_DIFF(req->out.data, req->out.buffer);
212 req->out.ptr = buf2 + PTR_DIFF(req->out.ptr, req->out.buffer);
213 req->out.vwv = buf2 + PTR_DIFF(req->out.vwv, req->out.buffer);
214 req->out.hdr = buf2 + PTR_DIFF(req->out.hdr, req->out.buffer);
216 req->out.buffer = buf2;
221 grow the data buffer portion of a reply packet. Note that as this
222 can reallocate the packet buffer this invalidates any local pointers
225 To cope with this req->out.ptr is supplied. This will be updated to
226 point at the same offset into the packet as before this call
228 void smbcli_req_grow_data(struct smbcli_request *req, uint_t new_size)
232 smbcli_req_grow_allocation(req, new_size);
234 delta = new_size - req->out.data_size;
236 req->out.size += delta;
237 req->out.data_size += delta;
239 /* set the BCC to the new data size */
240 SSVAL(req->out.vwv, VWV(req->out.wct), new_size);
247 BOOL smbcli_request_send(struct smbcli_request *req)
249 if (IVAL(req->out.buffer, 0) == 0) {
250 _smb_setlen(req->out.buffer, req->out.size - NBT_HDR_SIZE);
253 smbcli_request_calculate_sign_mac(req);
255 smbcli_transport_send(req);
262 receive a response to a packet
264 BOOL smbcli_request_receive(struct smbcli_request *req)
266 /* req can be NULL when a send has failed. This eliminates lots of NULL
267 checks in each module */
268 if (!req) return False;
270 /* keep receiving packets until this one is replied to */
271 while (req->state <= SMBCLI_REQUEST_RECV) {
272 if (event_loop_once(req->transport->event.ctx) != 0) {
277 return req->state == SMBCLI_REQUEST_DONE;
282 receive another reply to a request - this is used for requests that
283 have multi-part replies (such as SMBtrans2)
285 BOOL smbcli_request_receive_more(struct smbcli_request *req)
287 req->state = SMBCLI_REQUEST_RECV;
288 DLIST_ADD(req->transport->pending_recv, req);
290 return smbcli_request_receive(req);
295 handle oplock break requests from the server - return True if the request was
298 BOOL handle_oplock_break(struct smbcli_transport *transport, uint_t len, const char *hdr, const char *vwv)
300 /* we must be very fussy about what we consider an oplock break to avoid
301 matching readbraw replies */
302 if (len != MIN_SMB_SIZE + VWV(8) + NBT_HDR_SIZE ||
303 (CVAL(hdr, HDR_FLG) & FLAG_REPLY) ||
304 CVAL(hdr,HDR_COM) != SMBlockingX ||
305 SVAL(hdr, HDR_MID) != 0xFFFF ||
306 SVAL(vwv,VWV(6)) != 0 ||
307 SVAL(vwv,VWV(7)) != 0) {
311 if (transport->oplock.handler) {
312 uint16_t tid = SVAL(hdr, HDR_TID);
313 uint16_t fnum = SVAL(vwv,VWV(2));
314 uint8_t level = CVAL(vwv,VWV(3)+1);
315 transport->oplock.handler(transport, tid, fnum, level, transport->oplock.private);
322 wait for a reply to be received for a packet that just returns an error
323 code and nothing more
325 NTSTATUS smbcli_request_simple_recv(struct smbcli_request *req)
327 smbcli_request_receive(req);
328 return smbcli_request_destroy(req);
332 /* Return true if the last packet was in error */
333 BOOL smbcli_request_is_error(struct smbcli_request *req)
335 return NT_STATUS_IS_ERR(req->status);
339 append a string into the data portion of the request packet
341 return the number of bytes added to the packet
343 size_t smbcli_req_append_string(struct smbcli_request *req, const char *str, uint_t flags)
347 /* determine string type to use */
348 if (!(flags & (STR_ASCII|STR_UNICODE))) {
349 flags |= (req->transport->negotiate.capabilities & CAP_UNICODE) ? STR_UNICODE : STR_ASCII;
352 len = (strlen(str)+2) * MAX_BYTES_PER_CHAR;
354 smbcli_req_grow_allocation(req, len + req->out.data_size);
356 len = push_string(req->out.data + req->out.data_size, str, len, flags);
358 smbcli_req_grow_data(req, len + req->out.data_size);
365 this is like smbcli_req_append_string but it also return the
366 non-terminated string byte length, which can be less than the number
367 of bytes consumed in the packet for 2 reasons:
369 1) the string in the packet may be null terminated
370 2) the string in the packet may need a 1 byte UCS2 alignment
372 this is used in places where the non-terminated string byte length is
373 placed in the packet as a separate field
375 size_t smbcli_req_append_string_len(struct smbcli_request *req, const char *str, uint_t flags, int *len)
380 /* determine string type to use */
381 if (!(flags & (STR_ASCII|STR_UNICODE))) {
382 flags |= (req->transport->negotiate.capabilities & CAP_UNICODE) ? STR_UNICODE : STR_ASCII;
385 /* see if an alignment byte will be used */
386 if ((flags & STR_UNICODE) && !(flags & STR_NOALIGN)) {
387 diff = ucs2_align(NULL, req->out.data + req->out.data_size, flags);
390 /* do the hard work */
391 ret = smbcli_req_append_string(req, str, flags);
393 /* see if we need to subtract the termination */
394 if (flags & STR_TERMINATE) {
395 diff += (flags & STR_UNICODE) ? 2 : 1;
409 push a string into the data portion of the request packet, growing it if necessary
410 this gets quite tricky - please be very careful to cover all cases when modifying this
412 if dest is NULL, then put the string at the end of the data portion of the packet
414 if dest_len is -1 then no limit applies
416 size_t smbcli_req_append_ascii4(struct smbcli_request *req, const char *str, uint_t flags)
419 smbcli_req_append_bytes(req, (const uint8_t *)"\4", 1);
420 size = smbcli_req_append_string(req, str, flags);
426 push a blob into the data portion of the request packet, growing it if necessary
427 this gets quite tricky - please be very careful to cover all cases when modifying this
429 if dest is NULL, then put the blob at the end of the data portion of the packet
431 size_t smbcli_req_append_blob(struct smbcli_request *req, const DATA_BLOB *blob)
433 smbcli_req_grow_allocation(req, req->out.data_size + blob->length);
434 memcpy(req->out.data + req->out.data_size, blob->data, blob->length);
435 smbcli_req_grow_data(req, req->out.data_size + blob->length);
440 append raw bytes into the data portion of the request packet
441 return the number of bytes added
443 size_t smbcli_req_append_bytes(struct smbcli_request *req, const uint8_t *bytes, size_t byte_len)
445 smbcli_req_grow_allocation(req, byte_len + req->out.data_size);
446 memcpy(req->out.data + req->out.data_size, bytes, byte_len);
447 smbcli_req_grow_data(req, byte_len + req->out.data_size);
452 append variable block (type 5 buffer) into the data portion of the request packet
453 return the number of bytes added
455 size_t smbcli_req_append_var_block(struct smbcli_request *req, const uint8_t *bytes, uint16_t byte_len)
457 smbcli_req_grow_allocation(req, byte_len + 3 + req->out.data_size);
458 SCVAL(req->out.data + req->out.data_size, 0, 5);
459 SSVAL(req->out.data + req->out.data_size, 1, byte_len); /* add field length */
461 memcpy(req->out.data + req->out.data_size + 3, bytes, byte_len);
463 smbcli_req_grow_data(req, byte_len + 3 + req->out.data_size);
469 pull a UCS2 string from a request packet, returning a talloced unix string
471 the string length is limited by the 3 things:
472 - the data size in the request (end of packet)
473 - the passed 'byte_len' if it is not -1
474 - the end of string (null termination)
476 Note that 'byte_len' is the number of bytes in the packet
478 on failure zero is returned and *dest is set to NULL, otherwise the number
479 of bytes consumed in the packet is returned
481 static size_t smbcli_req_pull_ucs2(struct smbcli_request *req, TALLOC_CTX *mem_ctx,
482 char **dest, const char *src, int byte_len, uint_t flags)
484 int src_len, src_len2, alignment=0;
487 if (!(flags & STR_NOALIGN) && ucs2_align(req->in.buffer, src, flags)) {
490 if (byte_len != -1) {
495 src_len = req->in.data_size - PTR_DIFF(src, req->in.data);
500 if (byte_len != -1 && src_len > byte_len) {
504 src_len2 = utf16_len_n(src, src_len);
506 /* ucs2 strings must be at least 2 bytes long */
512 ret = convert_string_talloc(mem_ctx, CH_UTF16, CH_UNIX, src, src_len2, (void **)dest);
518 return src_len2 + alignment;
522 pull a ascii string from a request packet, returning a talloced string
524 the string length is limited by the 3 things:
525 - the data size in the request (end of packet)
526 - the passed 'byte_len' if it is not -1
527 - the end of string (null termination)
529 Note that 'byte_len' is the number of bytes in the packet
531 on failure zero is returned and *dest is set to NULL, otherwise the number
532 of bytes consumed in the packet is returned
534 size_t smbcli_req_pull_ascii(struct smbcli_request *req, TALLOC_CTX *mem_ctx,
535 char **dest, const char *src, int byte_len, uint_t flags)
537 int src_len, src_len2;
540 src_len = req->in.data_size - PTR_DIFF(src, req->in.data);
545 if (byte_len != -1 && src_len > byte_len) {
548 src_len2 = strnlen(src, src_len);
549 if (src_len2 < src_len - 1) {
550 /* include the termination if we didn't reach the end of the packet */
554 ret = convert_string_talloc(mem_ctx, CH_DOS, CH_UNIX, src, src_len2, (void **)dest);
565 pull a string from a request packet, returning a talloced string
567 the string length is limited by the 3 things:
568 - the data size in the request (end of packet)
569 - the passed 'byte_len' if it is not -1
570 - the end of string (null termination)
572 Note that 'byte_len' is the number of bytes in the packet
574 on failure zero is returned and *dest is set to NULL, otherwise the number
575 of bytes consumed in the packet is returned
577 size_t smbcli_req_pull_string(struct smbcli_request *req, TALLOC_CTX *mem_ctx,
578 char **dest, const char *src, int byte_len, uint_t flags)
580 if (!(flags & STR_ASCII) &&
581 (((flags & STR_UNICODE) || (req->flags2 & FLAGS2_UNICODE_STRINGS)))) {
582 return smbcli_req_pull_ucs2(req, mem_ctx, dest, src, byte_len, flags);
585 return smbcli_req_pull_ascii(req, mem_ctx, dest, src, byte_len, flags);
590 pull a DATA_BLOB from a reply packet, returning a talloced blob
591 make sure we don't go past end of packet
593 if byte_len is -1 then limit the blob only by packet size
595 DATA_BLOB smbcli_req_pull_blob(struct smbcli_request *req, TALLOC_CTX *mem_ctx, const char *src, int byte_len)
599 src_len = req->in.data_size - PTR_DIFF(src, req->in.data);
602 return data_blob(NULL, 0);
605 if (byte_len != -1 && src_len > byte_len) {
609 return data_blob_talloc(mem_ctx, src, src_len);
612 /* check that a lump of data in a request is within the bounds of the data section of
614 static BOOL smbcli_req_data_oob(struct smbcli_request *req, const char *ptr, uint32_t count)
616 /* be careful with wraparound! */
617 if (ptr < req->in.data ||
618 ptr >= req->in.data + req->in.data_size ||
619 count > req->in.data_size ||
620 ptr + count > req->in.data + req->in.data_size) {
627 pull a lump of data from a request packet
629 return False if any part is outside the data portion of the packet
631 BOOL smbcli_raw_pull_data(struct smbcli_request *req, const char *src, int len, char *dest)
633 if (len == 0) return True;
635 if (smbcli_req_data_oob(req, src, len)) {
639 memcpy(dest, src, len);
645 put a NTTIME into a packet
647 void smbcli_push_nttime(void *base, uint16_t offset, NTTIME t)
649 SBVAL(base, offset, t);
653 pull a NTTIME from a packet
655 NTTIME smbcli_pull_nttime(void *base, uint16_t offset)
657 NTTIME ret = BVAL(base, offset);
662 pull a UCS2 string from a blob, returning a talloced unix string
664 the string length is limited by the 3 things:
665 - the data size in the blob
666 - the passed 'byte_len' if it is not -1
667 - the end of string (null termination)
669 Note that 'byte_len' is the number of bytes in the packet
671 on failure zero is returned and *dest is set to NULL, otherwise the number
672 of bytes consumed in the blob is returned
674 static size_t smbcli_blob_pull_ucs2(TALLOC_CTX* mem_ctx,
675 DATA_BLOB *blob, const char **dest,
676 const char *src, int byte_len, uint_t flags)
678 int src_len, src_len2, alignment=0;
682 if (src < (const char *)blob->data ||
683 src >= (const char *)(blob->data + blob->length)) {
688 src_len = blob->length - PTR_DIFF(src, blob->data);
690 if (byte_len != -1 && src_len > byte_len) {
694 if (!(flags & STR_NOALIGN) && ucs2_align(blob->data, src, flags)) {
705 src_len2 = utf16_len_n(src, src_len);
707 ret = convert_string_talloc(mem_ctx, CH_UTF16, CH_UNIX, src, src_len2, (void **)&dest2);
714 return src_len2 + alignment;
718 pull a ascii string from a blob, returning a talloced string
720 the string length is limited by the 3 things:
721 - the data size in the blob
722 - the passed 'byte_len' if it is not -1
723 - the end of string (null termination)
725 Note that 'byte_len' is the number of bytes in the blob
727 on failure zero is returned and *dest is set to NULL, otherwise the number
728 of bytes consumed in the blob is returned
730 static size_t smbcli_blob_pull_ascii(TALLOC_CTX *mem_ctx,
731 DATA_BLOB *blob, const char **dest,
732 const char *src, int byte_len, uint_t flags)
734 int src_len, src_len2;
738 src_len = blob->length - PTR_DIFF(src, blob->data);
743 if (byte_len != -1 && src_len > byte_len) {
746 src_len2 = strnlen(src, src_len);
748 if (src_len2 < src_len - 1) {
749 /* include the termination if we didn't reach the end of the packet */
753 ret = convert_string_talloc(mem_ctx, CH_DOS, CH_UNIX, src, src_len2, (void **)&dest2);
765 pull a string from a blob, returning a talloced WIRE_STRING
767 the string length is limited by the 3 things:
768 - the data size in the blob
769 - length field on the wire
770 - the end of string (null termination)
772 if STR_LEN8BIT is set in the flags then assume the length field is
773 8 bits, instead of 32
775 on failure zero is returned and dest->s is set to NULL, otherwise the number
776 of bytes consumed in the blob is returned
778 size_t smbcli_blob_pull_string(struct smbcli_session *session,
782 uint16_t len_offset, uint16_t str_offset,
788 if (flags & STR_LEN8BIT) {
789 if (len_offset > blob->length-1) {
792 dest->private_length = CVAL(blob->data, len_offset);
794 if (len_offset > blob->length-4) {
797 dest->private_length = IVAL(blob->data, len_offset);
801 if (!(flags & STR_ASCII) &&
802 ((flags & STR_UNICODE) ||
803 (session->transport->negotiate.capabilities & CAP_UNICODE))) {
805 if ((str_offset&1) && !(flags & STR_NOALIGN)) {
808 if (flags & STR_LEN_NOTERM) {
811 return align + extra + smbcli_blob_pull_ucs2(mem_ctx, blob, &dest->s,
812 blob->data+str_offset+align,
813 dest->private_length, flags);
816 if (flags & STR_LEN_NOTERM) {
820 return extra + smbcli_blob_pull_ascii(mem_ctx, blob, &dest->s,
821 blob->data+str_offset, dest->private_length, flags);
825 pull a string from a blob, returning a talloced char *
827 Currently only used by the UNIX search info level.
829 the string length is limited by 2 things:
830 - the data size in the blob
831 - the end of string (null termination)
833 on failure zero is returned and dest->s is set to NULL, otherwise the number
834 of bytes consumed in the blob is returned
836 size_t smbcli_blob_pull_unix_string(struct smbcli_session *session,
846 if (!(flags & STR_ASCII) &&
847 ((flags & STR_UNICODE) ||
848 (session->transport->negotiate.capabilities & CAP_UNICODE))) {
850 if ((str_offset&1) && !(flags & STR_NOALIGN)) {
853 if (flags & STR_LEN_NOTERM) {
856 return align + extra + smbcli_blob_pull_ucs2(mem_ctx, blob, dest,
857 blob->data+str_offset+align,
861 if (flags & STR_LEN_NOTERM) {
865 return extra + smbcli_blob_pull_ascii(mem_ctx, blob, dest,
866 blob->data+str_offset, -1, flags);
871 append a string into a blob
873 size_t smbcli_blob_append_string(struct smbcli_session *session,
874 TALLOC_CTX *mem_ctx, DATA_BLOB *blob,
875 const char *str, uint_t flags)
882 /* determine string type to use */
883 if (!(flags & (STR_ASCII|STR_UNICODE))) {
884 flags |= (session->transport->negotiate.capabilities & CAP_UNICODE) ? STR_UNICODE : STR_ASCII;
887 max_len = (strlen(str)+2) * MAX_BYTES_PER_CHAR;
889 blob->data = talloc_realloc(mem_ctx, blob->data, blob->length + max_len);
894 len = push_string(blob->data + blob->length, str, max_len, flags);