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
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;
65 req = talloc_p(transport, struct smbcli_request);
71 /* setup the request context */
72 req->state = SMBCLI_REQUEST_INIT;
73 req->transport = transport;
78 /* over allocate by a small amount */
79 req->out.allocated = req->out.size + REQ_OVER_ALLOCATION;
81 req->out.buffer = talloc(req, req->out.allocated);
82 if (!req->out.buffer) {
86 SIVAL(req->out.buffer, 0, 0);
93 setup a SMB packet at transport level
95 struct smbcli_request *smbcli_request_setup_transport(struct smbcli_transport *transport,
96 uint8_t command, uint_t wct, uint_t buflen)
98 struct smbcli_request *req;
100 req = smbcli_request_setup_nonsmb(transport, NBT_HDR_SIZE + MIN_SMB_SIZE + wct*2 + buflen);
102 if (!req) return NULL;
104 req->out.hdr = req->out.buffer + NBT_HDR_SIZE;
105 req->out.vwv = req->out.hdr + HDR_VWV;
107 req->out.data = req->out.vwv + VWV(wct) + 2;
108 req->out.data_size = buflen;
109 req->out.ptr = req->out.data;
111 SCVAL(req->out.hdr, HDR_WCT, wct);
112 SSVAL(req->out.vwv, VWV(wct), buflen);
114 memcpy(req->out.hdr, "\377SMB", 4);
115 SCVAL(req->out.hdr,HDR_COM,command);
117 SCVAL(req->out.hdr,HDR_FLG, FLAG_CASELESS_PATHNAMES);
118 SSVAL(req->out.hdr,HDR_FLG2, 0);
121 req->mid = smbcli_transport_next_mid(transport);
123 /* copy the pid, uid and mid to the request */
124 SSVAL(req->out.hdr, HDR_PID, 0);
125 SSVAL(req->out.hdr, HDR_UID, 0);
126 SSVAL(req->out.hdr, HDR_MID, req->mid);
127 SSVAL(req->out.hdr, HDR_TID,0);
128 SSVAL(req->out.hdr, HDR_PIDHIGH,0);
129 SIVAL(req->out.hdr, HDR_RCLS, 0);
130 memset(req->out.hdr+HDR_SS_FIELD, 0, 10);
136 setup a reply in req->out with the given word count and initial data
137 buffer size. the caller will then fill in the command words and
138 data before calling smbcli_request_send() to send the reply on its
139 way. This interface is used before a session is setup.
141 struct smbcli_request *smbcli_request_setup_session(struct smbcli_session *session,
142 uint8_t command, uint_t wct, uint_t buflen)
144 struct smbcli_request *req;
146 req = smbcli_request_setup_transport(session->transport, command, wct, buflen);
148 if (!req) return NULL;
150 req->session = session;
152 SSVAL(req->out.hdr, HDR_FLG2, session->flags2);
153 SSVAL(req->out.hdr, HDR_PID, session->pid & 0xFFFF);
154 SSVAL(req->out.hdr, HDR_PIDHIGH, session->pid >> 16);
155 SSVAL(req->out.hdr, HDR_UID, session->vuid);
161 setup a request for tree based commands
163 struct smbcli_request *smbcli_request_setup(struct smbcli_tree *tree,
165 uint_t wct, uint_t buflen)
167 struct smbcli_request *req;
169 req = smbcli_request_setup_session(tree->session, command, wct, buflen);
172 SSVAL(req->out.hdr,HDR_TID,tree->tid);
178 grow the allocation of the data buffer portion of a reply
179 packet. Note that as this can reallocate the packet buffer this
180 invalidates any local pointers into the packet.
182 To cope with this req->out.ptr is supplied. This will be updated to
183 point at the same offset into the packet as before this call
185 static void smbcli_req_grow_allocation(struct smbcli_request *req, uint_t new_size)
190 delta = new_size - req->out.data_size;
191 if (delta + req->out.size <= req->out.allocated) {
192 /* it fits in the preallocation */
196 /* we need to realloc */
197 req->out.allocated = req->out.size + delta + REQ_OVER_ALLOCATION;
198 buf2 = talloc_realloc(req, req->out.buffer, req->out.allocated);
200 smb_panic("out of memory in req_grow_allocation");
203 if (buf2 == req->out.buffer) {
204 /* the malloc library gave us the same pointer */
208 /* update the pointers into the packet */
209 req->out.data = buf2 + PTR_DIFF(req->out.data, req->out.buffer);
210 req->out.ptr = buf2 + PTR_DIFF(req->out.ptr, req->out.buffer);
211 req->out.vwv = buf2 + PTR_DIFF(req->out.vwv, req->out.buffer);
212 req->out.hdr = buf2 + PTR_DIFF(req->out.hdr, req->out.buffer);
214 req->out.buffer = buf2;
219 grow the data buffer portion of a reply packet. Note that as this
220 can reallocate the packet buffer this invalidates any local pointers
223 To cope with this req->out.ptr is supplied. This will be updated to
224 point at the same offset into the packet as before this call
226 void smbcli_req_grow_data(struct smbcli_request *req, uint_t new_size)
230 smbcli_req_grow_allocation(req, new_size);
232 delta = new_size - req->out.data_size;
234 req->out.size += delta;
235 req->out.data_size += delta;
237 /* set the BCC to the new data size */
238 SSVAL(req->out.vwv, VWV(req->out.wct), new_size);
245 BOOL smbcli_request_send(struct smbcli_request *req)
247 if (IVAL(req->out.buffer, 0) == 0) {
248 _smb_setlen(req->out.buffer, req->out.size - NBT_HDR_SIZE);
251 smbcli_request_calculate_sign_mac(req);
253 smbcli_transport_send(req);
260 receive a response to a packet
262 BOOL smbcli_request_receive(struct smbcli_request *req)
264 /* req can be NULL when a send has failed. This eliminates lots of NULL
265 checks in each module */
266 if (!req) return False;
268 /* keep receiving packets until this one is replied to */
269 while (req->state <= SMBCLI_REQUEST_RECV) {
270 if (event_loop_once(req->transport->event.ctx) != 0) {
275 return req->state == SMBCLI_REQUEST_DONE;
280 receive another reply to a request - this is used for requests that
281 have multi-part replies (such as SMBtrans2)
283 BOOL smbcli_request_receive_more(struct smbcli_request *req)
285 req->state = SMBCLI_REQUEST_RECV;
286 DLIST_ADD(req->transport->pending_recv, req);
288 return smbcli_request_receive(req);
293 handle oplock break requests from the server - return True if the request was
296 BOOL handle_oplock_break(struct smbcli_transport *transport, uint_t len, const char *hdr, const char *vwv)
298 /* we must be very fussy about what we consider an oplock break to avoid
299 matching readbraw replies */
300 if (len != MIN_SMB_SIZE + VWV(8) + NBT_HDR_SIZE ||
301 (CVAL(hdr, HDR_FLG) & FLAG_REPLY) ||
302 CVAL(hdr,HDR_COM) != SMBlockingX ||
303 SVAL(hdr, HDR_MID) != 0xFFFF ||
304 SVAL(vwv,VWV(6)) != 0 ||
305 SVAL(vwv,VWV(7)) != 0) {
309 if (transport->oplock.handler) {
310 uint16_t tid = SVAL(hdr, HDR_TID);
311 uint16_t fnum = SVAL(vwv,VWV(2));
312 uint8_t level = CVAL(vwv,VWV(3)+1);
313 transport->oplock.handler(transport, tid, fnum, level, transport->oplock.private);
320 wait for a reply to be received for a packet that just returns an error
321 code and nothing more
323 NTSTATUS smbcli_request_simple_recv(struct smbcli_request *req)
325 smbcli_request_receive(req);
326 return smbcli_request_destroy(req);
330 /* Return true if the last packet was in error */
331 BOOL smbcli_request_is_error(struct smbcli_request *req)
333 return NT_STATUS_IS_ERR(req->status);
337 append a string into the data portion of the request packet
339 return the number of bytes added to the packet
341 size_t smbcli_req_append_string(struct smbcli_request *req, const char *str, uint_t flags)
345 /* determine string type to use */
346 if (!(flags & (STR_ASCII|STR_UNICODE))) {
347 flags |= (req->transport->negotiate.capabilities & CAP_UNICODE) ? STR_UNICODE : STR_ASCII;
350 len = (strlen(str)+2) * MAX_BYTES_PER_CHAR;
352 smbcli_req_grow_allocation(req, len + req->out.data_size);
354 len = push_string(req->out.data + req->out.data_size, str, len, flags);
356 smbcli_req_grow_data(req, len + req->out.data_size);
363 this is like smbcli_req_append_string but it also return the
364 non-terminated string byte length, which can be less than the number
365 of bytes consumed in the packet for 2 reasons:
367 1) the string in the packet may be null terminated
368 2) the string in the packet may need a 1 byte UCS2 alignment
370 this is used in places where the non-terminated string byte length is
371 placed in the packet as a separate field
373 size_t smbcli_req_append_string_len(struct smbcli_request *req, const char *str, uint_t flags, int *len)
378 /* determine string type to use */
379 if (!(flags & (STR_ASCII|STR_UNICODE))) {
380 flags |= (req->transport->negotiate.capabilities & CAP_UNICODE) ? STR_UNICODE : STR_ASCII;
383 /* see if an alignment byte will be used */
384 if ((flags & STR_UNICODE) && !(flags & STR_NOALIGN)) {
385 diff = ucs2_align(NULL, req->out.data + req->out.data_size, flags);
388 /* do the hard work */
389 ret = smbcli_req_append_string(req, str, flags);
391 /* see if we need to subtract the termination */
392 if (flags & STR_TERMINATE) {
393 diff += (flags & STR_UNICODE) ? 2 : 1;
407 push a string into the data portion of the request packet, growing it if necessary
408 this gets quite tricky - please be very careful to cover all cases when modifying this
410 if dest is NULL, then put the string at the end of the data portion of the packet
412 if dest_len is -1 then no limit applies
414 size_t smbcli_req_append_ascii4(struct smbcli_request *req, const char *str, uint_t flags)
417 smbcli_req_append_bytes(req, (const uint8_t *)"\4", 1);
418 size = smbcli_req_append_string(req, str, flags);
424 push a blob into the data portion of the request packet, growing it if necessary
425 this gets quite tricky - please be very careful to cover all cases when modifying this
427 if dest is NULL, then put the blob at the end of the data portion of the packet
429 size_t smbcli_req_append_blob(struct smbcli_request *req, const DATA_BLOB *blob)
431 smbcli_req_grow_allocation(req, req->out.data_size + blob->length);
432 memcpy(req->out.data + req->out.data_size, blob->data, blob->length);
433 smbcli_req_grow_data(req, req->out.data_size + blob->length);
438 append raw bytes into the data portion of the request packet
439 return the number of bytes added
441 size_t smbcli_req_append_bytes(struct smbcli_request *req, const uint8_t *bytes, size_t byte_len)
443 smbcli_req_grow_allocation(req, byte_len + req->out.data_size);
444 memcpy(req->out.data + req->out.data_size, bytes, byte_len);
445 smbcli_req_grow_data(req, byte_len + req->out.data_size);
450 append variable block (type 5 buffer) into the data portion of the request packet
451 return the number of bytes added
453 size_t smbcli_req_append_var_block(struct smbcli_request *req, const uint8_t *bytes, uint16_t byte_len)
455 smbcli_req_grow_allocation(req, byte_len + 3 + req->out.data_size);
456 SCVAL(req->out.data + req->out.data_size, 0, 5);
457 SSVAL(req->out.data + req->out.data_size, 1, byte_len); /* add field length */
459 memcpy(req->out.data + req->out.data_size + 3, bytes, byte_len);
461 smbcli_req_grow_data(req, byte_len + 3 + req->out.data_size);
467 pull a UCS2 string from a request packet, returning a talloced unix string
469 the string length is limited by the 3 things:
470 - the data size in the request (end of packet)
471 - the passed 'byte_len' if it is not -1
472 - the end of string (null termination)
474 Note that 'byte_len' is the number of bytes in the packet
476 on failure zero is returned and *dest is set to NULL, otherwise the number
477 of bytes consumed in the packet is returned
479 static size_t smbcli_req_pull_ucs2(struct smbcli_request *req, TALLOC_CTX *mem_ctx,
480 char **dest, const char *src, int byte_len, uint_t flags)
482 int src_len, src_len2, alignment=0;
485 if (!(flags & STR_NOALIGN) && ucs2_align(req->in.buffer, src, flags)) {
488 if (byte_len != -1) {
493 src_len = req->in.data_size - PTR_DIFF(src, req->in.data);
498 if (byte_len != -1 && src_len > byte_len) {
502 src_len2 = utf16_len_n(src, src_len);
504 /* ucs2 strings must be at least 2 bytes long */
510 ret = convert_string_talloc(mem_ctx, CH_UTF16, CH_UNIX, src, src_len2, (void **)dest);
516 return src_len2 + alignment;
520 pull a ascii string from a request packet, returning a talloced string
522 the string length is limited by the 3 things:
523 - the data size in the request (end of packet)
524 - the passed 'byte_len' if it is not -1
525 - the end of string (null termination)
527 Note that 'byte_len' is the number of bytes in the packet
529 on failure zero is returned and *dest is set to NULL, otherwise the number
530 of bytes consumed in the packet is returned
532 size_t smbcli_req_pull_ascii(struct smbcli_request *req, TALLOC_CTX *mem_ctx,
533 char **dest, const char *src, int byte_len, uint_t flags)
535 int src_len, src_len2;
538 src_len = req->in.data_size - PTR_DIFF(src, req->in.data);
543 if (byte_len != -1 && src_len > byte_len) {
546 src_len2 = strnlen(src, src_len);
547 if (src_len2 < src_len - 1) {
548 /* include the termination if we didn't reach the end of the packet */
552 ret = convert_string_talloc(mem_ctx, CH_DOS, CH_UNIX, src, src_len2, (void **)dest);
563 pull a string from a request packet, returning a talloced string
565 the string length is limited by the 3 things:
566 - the data size in the request (end of packet)
567 - the passed 'byte_len' if it is not -1
568 - the end of string (null termination)
570 Note that 'byte_len' is the number of bytes in the packet
572 on failure zero is returned and *dest is set to NULL, otherwise the number
573 of bytes consumed in the packet is returned
575 size_t smbcli_req_pull_string(struct smbcli_request *req, TALLOC_CTX *mem_ctx,
576 char **dest, const char *src, int byte_len, uint_t flags)
578 if (!(flags & STR_ASCII) &&
579 (((flags & STR_UNICODE) || (req->flags2 & FLAGS2_UNICODE_STRINGS)))) {
580 return smbcli_req_pull_ucs2(req, mem_ctx, dest, src, byte_len, flags);
583 return smbcli_req_pull_ascii(req, mem_ctx, dest, src, byte_len, flags);
588 pull a DATA_BLOB from a reply packet, returning a talloced blob
589 make sure we don't go past end of packet
591 if byte_len is -1 then limit the blob only by packet size
593 DATA_BLOB smbcli_req_pull_blob(struct smbcli_request *req, TALLOC_CTX *mem_ctx, const char *src, int byte_len)
597 src_len = req->in.data_size - PTR_DIFF(src, req->in.data);
600 return data_blob(NULL, 0);
603 if (byte_len != -1 && src_len > byte_len) {
607 return data_blob_talloc(mem_ctx, src, src_len);
610 /* check that a lump of data in a request is within the bounds of the data section of
612 static BOOL smbcli_req_data_oob(struct smbcli_request *req, const char *ptr, uint32_t count)
614 /* be careful with wraparound! */
615 if (ptr < req->in.data ||
616 ptr >= req->in.data + req->in.data_size ||
617 count > req->in.data_size ||
618 ptr + count > req->in.data + req->in.data_size) {
625 pull a lump of data from a request packet
627 return False if any part is outside the data portion of the packet
629 BOOL smbcli_raw_pull_data(struct smbcli_request *req, const char *src, int len, char *dest)
631 if (len == 0) return True;
633 if (smbcli_req_data_oob(req, src, len)) {
637 memcpy(dest, src, len);
643 put a NTTIME into a packet
645 void smbcli_push_nttime(void *base, uint16_t offset, NTTIME t)
647 SBVAL(base, offset, t);
651 pull a NTTIME from a packet
653 NTTIME smbcli_pull_nttime(void *base, uint16_t offset)
655 NTTIME ret = BVAL(base, offset);
660 pull a UCS2 string from a blob, returning a talloced unix string
662 the string length is limited by the 3 things:
663 - the data size in the blob
664 - the passed 'byte_len' if it is not -1
665 - the end of string (null termination)
667 Note that 'byte_len' is the number of bytes in the packet
669 on failure zero is returned and *dest is set to NULL, otherwise the number
670 of bytes consumed in the blob is returned
672 static size_t smbcli_blob_pull_ucs2(TALLOC_CTX* mem_ctx,
673 DATA_BLOB *blob, const char **dest,
674 const char *src, int byte_len, uint_t flags)
676 int src_len, src_len2, alignment=0;
680 if (src < (const char *)blob->data ||
681 src >= (const char *)(blob->data + blob->length)) {
686 src_len = blob->length - PTR_DIFF(src, blob->data);
688 if (byte_len != -1 && src_len > byte_len) {
692 if (!(flags & STR_NOALIGN) && ucs2_align(blob->data, src, flags)) {
703 src_len2 = utf16_len_n(src, src_len);
705 ret = convert_string_talloc(mem_ctx, CH_UTF16, CH_UNIX, src, src_len2, (void **)&dest2);
712 return src_len2 + alignment;
716 pull a ascii string from a blob, returning a talloced string
718 the string length is limited by the 3 things:
719 - the data size in the blob
720 - the passed 'byte_len' if it is not -1
721 - the end of string (null termination)
723 Note that 'byte_len' is the number of bytes in the blob
725 on failure zero is returned and *dest is set to NULL, otherwise the number
726 of bytes consumed in the blob is returned
728 static size_t smbcli_blob_pull_ascii(TALLOC_CTX *mem_ctx,
729 DATA_BLOB *blob, const char **dest,
730 const char *src, int byte_len, uint_t flags)
732 int src_len, src_len2;
736 src_len = blob->length - PTR_DIFF(src, blob->data);
741 if (byte_len != -1 && src_len > byte_len) {
744 src_len2 = strnlen(src, src_len);
746 if (src_len2 < src_len - 1) {
747 /* include the termination if we didn't reach the end of the packet */
751 ret = convert_string_talloc(mem_ctx, CH_DOS, CH_UNIX, src, src_len2, (void **)&dest2);
763 pull a string from a blob, returning a talloced WIRE_STRING
765 the string length is limited by the 3 things:
766 - the data size in the blob
767 - length field on the wire
768 - the end of string (null termination)
770 if STR_LEN8BIT is set in the flags then assume the length field is
771 8 bits, instead of 32
773 on failure zero is returned and dest->s is set to NULL, otherwise the number
774 of bytes consumed in the blob is returned
776 size_t smbcli_blob_pull_string(struct smbcli_session *session,
780 uint16_t len_offset, uint16_t str_offset,
786 if (flags & STR_LEN8BIT) {
787 if (len_offset > blob->length-1) {
790 dest->private_length = CVAL(blob->data, len_offset);
792 if (len_offset > blob->length-4) {
795 dest->private_length = IVAL(blob->data, len_offset);
799 if (!(flags & STR_ASCII) &&
800 ((flags & STR_UNICODE) ||
801 (session->transport->negotiate.capabilities & CAP_UNICODE))) {
803 if ((str_offset&1) && !(flags & STR_NOALIGN)) {
806 if (flags & STR_LEN_NOTERM) {
809 return align + extra + smbcli_blob_pull_ucs2(mem_ctx, blob, &dest->s,
810 blob->data+str_offset+align,
811 dest->private_length, flags);
814 if (flags & STR_LEN_NOTERM) {
818 return extra + smbcli_blob_pull_ascii(mem_ctx, blob, &dest->s,
819 blob->data+str_offset, dest->private_length, flags);
823 pull a string from a blob, returning a talloced char *
825 Currently only used by the UNIX search info level.
827 the string length is limited by 2 things:
828 - the data size in the blob
829 - the end of string (null termination)
831 on failure zero is returned and dest->s is set to NULL, otherwise the number
832 of bytes consumed in the blob is returned
834 size_t smbcli_blob_pull_unix_string(struct smbcli_session *session,
844 if (!(flags & STR_ASCII) &&
845 ((flags & STR_UNICODE) ||
846 (session->transport->negotiate.capabilities & CAP_UNICODE))) {
848 if ((str_offset&1) && !(flags & STR_NOALIGN)) {
851 if (flags & STR_LEN_NOTERM) {
854 return align + extra + smbcli_blob_pull_ucs2(mem_ctx, blob, dest,
855 blob->data+str_offset+align,
859 if (flags & STR_LEN_NOTERM) {
863 return extra + smbcli_blob_pull_ascii(mem_ctx, blob, dest,
864 blob->data+str_offset, -1, flags);
869 append a string into a blob
871 size_t smbcli_blob_append_string(struct smbcli_session *session,
872 TALLOC_CTX *mem_ctx, DATA_BLOB *blob,
873 const char *str, uint_t flags)
880 /* determine string type to use */
881 if (!(flags & (STR_ASCII|STR_UNICODE))) {
882 flags |= (session->transport->negotiate.capabilities & CAP_UNICODE) ? STR_UNICODE : STR_ASCII;
885 max_len = (strlen(str)+2) * MAX_BYTES_PER_CHAR;
887 blob->data = talloc_realloc(mem_ctx, blob->data, blob->length + max_len);
892 len = push_string(blob->data + blob->length, str, max_len, flags);