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 3 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, see <http://www.gnu.org/licenses/>.
22 this file implements functions for manipulating the 'struct smbcli_request' structure in libsmb
26 #include "libcli/raw/libcliraw.h"
27 #include "lib/util/dlinklist.h"
28 #include "lib/events/events.h"
29 #include "param/param.h"
31 /* we over allocate the data buffer to prevent too many realloc calls */
32 #define REQ_OVER_ALLOCATION 0
34 /* assume that a character will not consume more than 3 bytes per char */
35 #define MAX_BYTES_PER_CHAR 3
37 /* destroy a request structure and return final status */
38 NTSTATUS smbcli_request_destroy(struct smbcli_request *req)
42 /* this is the error code we give the application for when a
43 _send() call fails completely */
44 if (!req) return NT_STATUS_UNSUCCESSFUL;
47 /* remove it from the list of pending requests (a null op if
48 its not in the list) */
49 DLIST_REMOVE(req->transport->pending_recv, req);
52 if (req->state == SMBCLI_REQUEST_ERROR &&
53 NT_STATUS_IS_OK(req->status)) {
54 req->status = NT_STATUS_INTERNAL_ERROR;
64 low-level function to setup a request buffer for a non-SMB packet
65 at the transport level
67 struct smbcli_request *smbcli_request_setup_nonsmb(struct smbcli_transport *transport, size_t size)
69 struct smbcli_request *req;
71 req = talloc(transport, struct smbcli_request);
77 /* setup the request context */
78 req->state = SMBCLI_REQUEST_INIT;
79 req->transport = transport;
84 /* over allocate by a small amount */
85 req->out.allocated = req->out.size + REQ_OVER_ALLOCATION;
87 req->out.buffer = talloc_array(req, uint8_t, req->out.allocated);
88 if (!req->out.buffer) {
92 SIVAL(req->out.buffer, 0, 0);
99 setup a SMB packet at transport level
101 struct smbcli_request *smbcli_request_setup_transport(struct smbcli_transport *transport,
102 uint8_t command, uint_t wct, uint_t buflen)
104 struct smbcli_request *req;
106 req = smbcli_request_setup_nonsmb(transport, NBT_HDR_SIZE + MIN_SMB_SIZE + wct*2 + buflen);
108 if (!req) return NULL;
110 req->out.hdr = req->out.buffer + NBT_HDR_SIZE;
111 req->out.vwv = req->out.hdr + HDR_VWV;
113 req->out.data = req->out.vwv + VWV(wct) + 2;
114 req->out.data_size = buflen;
115 req->out.ptr = req->out.data;
117 SCVAL(req->out.hdr, HDR_WCT, wct);
118 SSVAL(req->out.vwv, VWV(wct), buflen);
120 memcpy(req->out.hdr, "\377SMB", 4);
121 SCVAL(req->out.hdr,HDR_COM,command);
123 SCVAL(req->out.hdr,HDR_FLG, FLAG_CASELESS_PATHNAMES);
124 SSVAL(req->out.hdr,HDR_FLG2, 0);
126 if (command != SMBtranss && command != SMBtranss2) {
128 req->mid = smbcli_transport_next_mid(transport);
131 /* copy the pid, uid and mid to the request */
132 SSVAL(req->out.hdr, HDR_PID, 0);
133 SSVAL(req->out.hdr, HDR_UID, 0);
134 SSVAL(req->out.hdr, HDR_MID, req->mid);
135 SSVAL(req->out.hdr, HDR_TID,0);
136 SSVAL(req->out.hdr, HDR_PIDHIGH,0);
137 SIVAL(req->out.hdr, HDR_RCLS, 0);
138 memset(req->out.hdr+HDR_SS_FIELD, 0, 10);
144 setup a reply in req->out with the given word count and initial data
145 buffer size. the caller will then fill in the command words and
146 data before calling smbcli_request_send() to send the reply on its
147 way. This interface is used before a session is setup.
149 struct smbcli_request *smbcli_request_setup_session(struct smbcli_session *session,
150 uint8_t command, uint_t wct, size_t buflen)
152 struct smbcli_request *req;
154 req = smbcli_request_setup_transport(session->transport, command, wct, buflen);
156 if (!req) return NULL;
158 req->session = session;
160 SSVAL(req->out.hdr, HDR_FLG2, session->flags2);
161 SSVAL(req->out.hdr, HDR_PID, session->pid & 0xFFFF);
162 SSVAL(req->out.hdr, HDR_PIDHIGH, session->pid >> 16);
163 SSVAL(req->out.hdr, HDR_UID, session->vuid);
169 setup a request for tree based commands
171 struct smbcli_request *smbcli_request_setup(struct smbcli_tree *tree,
173 uint_t wct, uint_t buflen)
175 struct smbcli_request *req;
177 req = smbcli_request_setup_session(tree->session, command, wct, buflen);
180 SSVAL(req->out.hdr,HDR_TID,tree->tid);
187 grow the allocation of the data buffer portion of a reply
188 packet. Note that as this can reallocate the packet buffer this
189 invalidates any local pointers into the packet.
191 To cope with this req->out.ptr is supplied. This will be updated to
192 point at the same offset into the packet as before this call
194 static void smbcli_req_grow_allocation(struct smbcli_request *req, uint_t new_size)
199 delta = new_size - req->out.data_size;
200 if (delta + req->out.size <= req->out.allocated) {
201 /* it fits in the preallocation */
205 /* we need to realloc */
206 req->out.allocated = req->out.size + delta + REQ_OVER_ALLOCATION;
207 buf2 = talloc_realloc(req, req->out.buffer, uint8_t, req->out.allocated);
209 smb_panic("out of memory in req_grow_allocation");
212 if (buf2 == req->out.buffer) {
213 /* the malloc library gave us the same pointer */
217 /* update the pointers into the packet */
218 req->out.data = buf2 + PTR_DIFF(req->out.data, req->out.buffer);
219 req->out.ptr = buf2 + PTR_DIFF(req->out.ptr, req->out.buffer);
220 req->out.vwv = buf2 + PTR_DIFF(req->out.vwv, req->out.buffer);
221 req->out.hdr = buf2 + PTR_DIFF(req->out.hdr, req->out.buffer);
223 req->out.buffer = buf2;
228 grow the data buffer portion of a reply packet. Note that as this
229 can reallocate the packet buffer this invalidates any local pointers
232 To cope with this req->out.ptr is supplied. This will be updated to
233 point at the same offset into the packet as before this call
235 static void smbcli_req_grow_data(struct smbcli_request *req, uint_t new_size)
239 smbcli_req_grow_allocation(req, new_size);
241 delta = new_size - req->out.data_size;
243 req->out.size += delta;
244 req->out.data_size += delta;
246 /* set the BCC to the new data size */
247 SSVAL(req->out.vwv, VWV(req->out.wct), new_size);
252 setup a chained reply in req->out with the given word count and
253 initial data buffer size.
255 NTSTATUS smbcli_chained_request_setup(struct smbcli_request *req,
257 uint_t wct, size_t buflen)
259 uint_t new_size = 1 + (wct*2) + 2 + buflen;
261 SSVAL(req->out.vwv, VWV(0), command);
262 SSVAL(req->out.vwv, VWV(1), req->out.size - NBT_HDR_SIZE);
264 smbcli_req_grow_allocation(req, req->out.data_size + new_size);
266 req->out.vwv = req->out.buffer + req->out.size + 1;
267 SCVAL(req->out.vwv, -1, wct);
268 SSVAL(req->out.vwv, VWV(wct), buflen);
270 req->out.size += new_size;
271 req->out.data_size += new_size;
277 aadvance to the next chained reply in a request
279 NTSTATUS smbcli_chained_advance(struct smbcli_request *req)
283 if (CVAL(req->in.vwv, VWV(0)) == SMB_CHAIN_NONE) {
284 return NT_STATUS_NOT_FOUND;
287 buffer = req->in.hdr + SVAL(req->in.vwv, VWV(1));
289 if (buffer + 3 > req->in.buffer + req->in.size) {
290 return NT_STATUS_BUFFER_TOO_SMALL;
293 req->in.vwv = buffer + 1;
294 req->in.wct = CVAL(buffer, 0);
295 if (buffer + 3 + req->in.wct*2 > req->in.buffer + req->in.size) {
296 return NT_STATUS_BUFFER_TOO_SMALL;
298 req->in.data = req->in.vwv + 2 + req->in.wct * 2;
299 req->in.data_size = SVAL(req->in.vwv, VWV(req->in.wct));
301 if (buffer + 3 + req->in.wct*2 + req->in.data_size >
302 req->in.buffer + req->in.size) {
303 return NT_STATUS_BUFFER_TOO_SMALL;
313 bool smbcli_request_send(struct smbcli_request *req)
315 if (IVAL(req->out.buffer, 0) == 0) {
316 _smb_setlen(req->out.buffer, req->out.size - NBT_HDR_SIZE);
319 smbcli_request_calculate_sign_mac(req);
321 smbcli_transport_send(req);
328 receive a response to a packet
330 bool smbcli_request_receive(struct smbcli_request *req)
332 /* req can be NULL when a send has failed. This eliminates lots of NULL
333 checks in each module */
334 if (!req) return false;
336 /* keep receiving packets until this one is replied to */
337 while (req->state <= SMBCLI_REQUEST_RECV) {
338 if (event_loop_once(req->transport->socket->event.ctx) != 0) {
343 return req->state == SMBCLI_REQUEST_DONE;
348 receive another reply to a request - this is used for requests that
349 have multi-part replies (such as SMBtrans2)
351 bool smbcli_request_receive_more(struct smbcli_request *req)
353 req->state = SMBCLI_REQUEST_RECV;
354 DLIST_ADD(req->transport->pending_recv, req);
356 return smbcli_request_receive(req);
361 handle oplock break requests from the server - return true if the request was
364 bool smbcli_handle_oplock_break(struct smbcli_transport *transport, uint_t len, const uint8_t *hdr, const uint8_t *vwv)
366 /* we must be very fussy about what we consider an oplock break to avoid
367 matching readbraw replies */
368 if (len != MIN_SMB_SIZE + VWV(8) + NBT_HDR_SIZE ||
369 (CVAL(hdr, HDR_FLG) & FLAG_REPLY) ||
370 CVAL(hdr,HDR_COM) != SMBlockingX ||
371 SVAL(hdr, HDR_MID) != 0xFFFF ||
372 SVAL(vwv,VWV(6)) != 0 ||
373 SVAL(vwv,VWV(7)) != 0) {
377 if (transport->oplock.handler) {
378 uint16_t tid = SVAL(hdr, HDR_TID);
379 uint16_t fnum = SVAL(vwv,VWV(2));
380 uint8_t level = CVAL(vwv,VWV(3)+1);
381 transport->oplock.handler(transport, tid, fnum, level, transport->oplock.private);
388 wait for a reply to be received for a packet that just returns an error
389 code and nothing more
391 NTSTATUS smbcli_request_simple_recv(struct smbcli_request *req)
393 (void) smbcli_request_receive(req);
394 return smbcli_request_destroy(req);
398 /* Return true if the last packet was in error */
399 bool smbcli_request_is_error(struct smbcli_request *req)
401 return NT_STATUS_IS_ERR(req->status);
405 append a string into the data portion of the request packet
407 return the number of bytes added to the packet
409 size_t smbcli_req_append_string(struct smbcli_request *req, const char *str, uint_t flags)
413 /* determine string type to use */
414 if (!(flags & (STR_ASCII|STR_UNICODE))) {
415 flags |= (req->transport->negotiate.capabilities & CAP_UNICODE) ? STR_UNICODE : STR_ASCII;
418 len = (strlen(str)+2) * MAX_BYTES_PER_CHAR;
420 smbcli_req_grow_allocation(req, len + req->out.data_size);
422 len = push_string(lp_iconv_convenience(global_loadparm), req->out.data + req->out.data_size, str, len, flags);
424 smbcli_req_grow_data(req, len + req->out.data_size);
431 this is like smbcli_req_append_string but it also return the
432 non-terminated string byte length, which can be less than the number
433 of bytes consumed in the packet for 2 reasons:
435 1) the string in the packet may be null terminated
436 2) the string in the packet may need a 1 byte UCS2 alignment
438 this is used in places where the non-terminated string byte length is
439 placed in the packet as a separate field
441 size_t smbcli_req_append_string_len(struct smbcli_request *req, const char *str, uint_t flags, int *len)
446 /* determine string type to use */
447 if (!(flags & (STR_ASCII|STR_UNICODE))) {
448 flags |= (req->transport->negotiate.capabilities & CAP_UNICODE) ? STR_UNICODE : STR_ASCII;
451 /* see if an alignment byte will be used */
452 if ((flags & STR_UNICODE) && !(flags & STR_NOALIGN)) {
453 diff = ucs2_align(NULL, req->out.data + req->out.data_size, flags);
456 /* do the hard work */
457 ret = smbcli_req_append_string(req, str, flags);
459 /* see if we need to subtract the termination */
460 if (flags & STR_TERMINATE) {
461 diff += (flags & STR_UNICODE) ? 2 : 1;
475 push a string into the data portion of the request packet, growing it if necessary
476 this gets quite tricky - please be very careful to cover all cases when modifying this
478 if dest is NULL, then put the string at the end of the data portion of the packet
480 if dest_len is -1 then no limit applies
482 size_t smbcli_req_append_ascii4(struct smbcli_request *req, const char *str, uint_t flags)
485 smbcli_req_append_bytes(req, (const uint8_t *)"\4", 1);
486 size = smbcli_req_append_string(req, str, flags);
492 push a blob into the data portion of the request packet, growing it if necessary
493 this gets quite tricky - please be very careful to cover all cases when modifying this
495 if dest is NULL, then put the blob at the end of the data portion of the packet
497 size_t smbcli_req_append_blob(struct smbcli_request *req, const DATA_BLOB *blob)
499 smbcli_req_grow_allocation(req, req->out.data_size + blob->length);
500 memcpy(req->out.data + req->out.data_size, blob->data, blob->length);
501 smbcli_req_grow_data(req, req->out.data_size + blob->length);
506 append raw bytes into the data portion of the request packet
507 return the number of bytes added
509 size_t smbcli_req_append_bytes(struct smbcli_request *req, const uint8_t *bytes, size_t byte_len)
511 smbcli_req_grow_allocation(req, byte_len + req->out.data_size);
512 memcpy(req->out.data + req->out.data_size, bytes, byte_len);
513 smbcli_req_grow_data(req, byte_len + req->out.data_size);
518 append variable block (type 5 buffer) into the data portion of the request packet
519 return the number of bytes added
521 size_t smbcli_req_append_var_block(struct smbcli_request *req, const uint8_t *bytes, uint16_t byte_len)
523 smbcli_req_grow_allocation(req, byte_len + 3 + req->out.data_size);
524 SCVAL(req->out.data + req->out.data_size, 0, 5);
525 SSVAL(req->out.data + req->out.data_size, 1, byte_len); /* add field length */
527 memcpy(req->out.data + req->out.data_size + 3, bytes, byte_len);
529 smbcli_req_grow_data(req, byte_len + 3 + req->out.data_size);
535 pull a UCS2 string from a request packet, returning a talloced unix string
537 the string length is limited by the 3 things:
538 - the data size in the request (end of packet)
539 - the passed 'byte_len' if it is not -1
540 - the end of string (null termination)
542 Note that 'byte_len' is the number of bytes in the packet
544 on failure zero is returned and *dest is set to NULL, otherwise the number
545 of bytes consumed in the packet is returned
547 static size_t smbcli_req_pull_ucs2(struct smbcli_request *req, TALLOC_CTX *mem_ctx,
548 char **dest, const uint8_t *src, int byte_len, uint_t flags)
550 int src_len, src_len2, alignment=0;
553 if (!(flags & STR_NOALIGN) && ucs2_align(req->in.buffer, src, flags)) {
556 if (byte_len != -1) {
561 src_len = req->in.data_size - PTR_DIFF(src, req->in.data);
566 if (byte_len != -1 && src_len > byte_len) {
570 src_len2 = utf16_len_n(src, src_len);
572 /* ucs2 strings must be at least 2 bytes long */
578 ret = convert_string_talloc(mem_ctx, lp_iconv_convenience(global_loadparm), CH_UTF16, CH_UNIX, src, src_len2, (void **)dest);
584 return src_len2 + alignment;
588 pull a ascii string from a request packet, returning a talloced string
590 the string length is limited by the 3 things:
591 - the data size in the request (end of packet)
592 - the passed 'byte_len' if it is not -1
593 - the end of string (null termination)
595 Note that 'byte_len' is the number of bytes in the packet
597 on failure zero is returned and *dest is set to NULL, otherwise the number
598 of bytes consumed in the packet is returned
600 size_t smbcli_req_pull_ascii(struct smbcli_request *req, TALLOC_CTX *mem_ctx,
601 char **dest, const uint8_t *src, int byte_len, uint_t flags)
603 int src_len, src_len2;
606 src_len = req->in.data_size - PTR_DIFF(src, req->in.data);
611 if (byte_len != -1 && src_len > byte_len) {
614 src_len2 = strnlen((const char *)src, src_len);
615 if (src_len2 < src_len - 1) {
616 /* include the termination if we didn't reach the end of the packet */
620 ret = convert_string_talloc(mem_ctx, lp_iconv_convenience(global_loadparm), CH_DOS, CH_UNIX, src, src_len2, (void **)dest);
631 pull a string from a request packet, returning a talloced string
633 the string length is limited by the 3 things:
634 - the data size in the request (end of packet)
635 - the passed 'byte_len' if it is not -1
636 - the end of string (null termination)
638 Note that 'byte_len' is the number of bytes in the packet
640 on failure zero is returned and *dest is set to NULL, otherwise the number
641 of bytes consumed in the packet is returned
643 size_t smbcli_req_pull_string(struct smbcli_request *req, TALLOC_CTX *mem_ctx,
644 char **dest, const uint8_t *src, int byte_len, uint_t flags)
646 if (!(flags & STR_ASCII) &&
647 (((flags & STR_UNICODE) || (req->flags2 & FLAGS2_UNICODE_STRINGS)))) {
648 return smbcli_req_pull_ucs2(req, mem_ctx, dest, src, byte_len, flags);
651 return smbcli_req_pull_ascii(req, mem_ctx, dest, src, byte_len, flags);
656 pull a DATA_BLOB from a reply packet, returning a talloced blob
657 make sure we don't go past end of packet
659 if byte_len is -1 then limit the blob only by packet size
661 DATA_BLOB smbcli_req_pull_blob(struct smbcli_request *req, TALLOC_CTX *mem_ctx, const uint8_t *src, int byte_len)
665 src_len = req->in.data_size - PTR_DIFF(src, req->in.data);
668 return data_blob(NULL, 0);
671 if (byte_len != -1 && src_len > byte_len) {
675 return data_blob_talloc(mem_ctx, src, src_len);
678 /* check that a lump of data in a request is within the bounds of the data section of
680 static bool smbcli_req_data_oob(struct smbcli_request *req, const uint8_t *ptr, uint32_t count)
682 /* be careful with wraparound! */
683 if (ptr < req->in.data ||
684 ptr >= req->in.data + req->in.data_size ||
685 count > req->in.data_size ||
686 ptr + count > req->in.data + req->in.data_size) {
693 pull a lump of data from a request packet
695 return false if any part is outside the data portion of the packet
697 bool smbcli_raw_pull_data(struct smbcli_request *req, const uint8_t *src, int len, uint8_t *dest)
699 if (len == 0) return true;
701 if (smbcli_req_data_oob(req, src, len)) {
705 memcpy(dest, src, len);
711 put a NTTIME into a packet
713 void smbcli_push_nttime(void *base, uint16_t offset, NTTIME t)
715 SBVAL(base, offset, t);
719 pull a NTTIME from a packet
721 NTTIME smbcli_pull_nttime(void *base, uint16_t offset)
723 NTTIME ret = BVAL(base, offset);
728 pull a UCS2 string from a blob, returning a talloced unix string
730 the string length is limited by the 3 things:
731 - the data size in the blob
732 - the passed 'byte_len' if it is not -1
733 - the end of string (null termination)
735 Note that 'byte_len' is the number of bytes in the packet
737 on failure zero is returned and *dest is set to NULL, otherwise the number
738 of bytes consumed in the blob is returned
740 size_t smbcli_blob_pull_ucs2(TALLOC_CTX* mem_ctx,
741 const DATA_BLOB *blob, const char **dest,
742 const uint8_t *src, int byte_len, uint_t flags)
744 int src_len, src_len2, alignment=0;
748 if (src < blob->data ||
749 src >= (blob->data + blob->length)) {
754 src_len = blob->length - PTR_DIFF(src, blob->data);
756 if (byte_len != -1 && src_len > byte_len) {
760 if (!(flags & STR_NOALIGN) && ucs2_align(blob->data, src, flags)) {
771 src_len2 = utf16_len_n(src, src_len);
773 ret = convert_string_talloc(mem_ctx, lp_iconv_convenience(global_loadparm), CH_UTF16, CH_UNIX, src, src_len2, (void **)&dest2);
780 return src_len2 + alignment;
784 pull a ascii string from a blob, returning a talloced string
786 the string length is limited by the 3 things:
787 - the data size in the blob
788 - the passed 'byte_len' if it is not -1
789 - the end of string (null termination)
791 Note that 'byte_len' is the number of bytes in the blob
793 on failure zero is returned and *dest is set to NULL, otherwise the number
794 of bytes consumed in the blob is returned
796 static size_t smbcli_blob_pull_ascii(TALLOC_CTX *mem_ctx,
797 const DATA_BLOB *blob, const char **dest,
798 const uint8_t *src, int byte_len, uint_t flags)
800 int src_len, src_len2;
804 src_len = blob->length - PTR_DIFF(src, blob->data);
809 if (byte_len != -1 && src_len > byte_len) {
812 src_len2 = strnlen((const char *)src, src_len);
814 if (src_len2 < src_len - 1) {
815 /* include the termination if we didn't reach the end of the packet */
819 ret = convert_string_talloc(mem_ctx, lp_iconv_convenience(global_loadparm), CH_DOS, CH_UNIX, src, src_len2, (void **)&dest2);
831 pull a string from a blob, returning a talloced struct smb_wire_string
833 the string length is limited by the 3 things:
834 - the data size in the blob
835 - length field on the wire
836 - the end of string (null termination)
838 if STR_LEN8BIT is set in the flags then assume the length field is
839 8 bits, instead of 32
841 on failure zero is returned and dest->s is set to NULL, otherwise the number
842 of bytes consumed in the blob is returned
844 size_t smbcli_blob_pull_string(struct smbcli_session *session,
846 const DATA_BLOB *blob,
847 struct smb_wire_string *dest,
848 uint16_t len_offset, uint16_t str_offset,
854 if (!(flags & STR_ASCII)) {
855 /* this is here to cope with SMB2 calls using the SMB
856 parsers. SMB2 will pass smbcli_session==NULL, which forces
857 unicode on (as used by SMB2) */
858 if (session == NULL) {
859 flags |= STR_UNICODE;
860 } else if (session->transport->negotiate.capabilities & CAP_UNICODE) {
861 flags |= STR_UNICODE;
865 if (flags & STR_LEN8BIT) {
866 if (len_offset > blob->length-1) {
869 dest->private_length = CVAL(blob->data, len_offset);
871 if (len_offset > blob->length-4) {
874 dest->private_length = IVAL(blob->data, len_offset);
878 if (!(flags & STR_ASCII) && (flags & STR_UNICODE)) {
880 if ((str_offset&1) && !(flags & STR_NOALIGN)) {
883 if (flags & STR_LEN_NOTERM) {
886 return align + extra + smbcli_blob_pull_ucs2(mem_ctx, blob, &dest->s,
887 blob->data+str_offset+align,
888 dest->private_length, flags);
891 if (flags & STR_LEN_NOTERM) {
895 return extra + smbcli_blob_pull_ascii(mem_ctx, blob, &dest->s,
896 blob->data+str_offset, dest->private_length, flags);
900 pull a string from a blob, returning a talloced char *
902 Currently only used by the UNIX search info level.
904 the string length is limited by 2 things:
905 - the data size in the blob
906 - the end of string (null termination)
908 on failure zero is returned and dest->s is set to NULL, otherwise the number
909 of bytes consumed in the blob is returned
911 size_t smbcli_blob_pull_unix_string(struct smbcli_session *session,
921 if (!(flags & STR_ASCII) &&
922 ((flags & STR_UNICODE) ||
923 (session->transport->negotiate.capabilities & CAP_UNICODE))) {
925 if ((str_offset&1) && !(flags & STR_NOALIGN)) {
928 if (flags & STR_LEN_NOTERM) {
931 return align + extra + smbcli_blob_pull_ucs2(mem_ctx, blob, dest,
932 blob->data+str_offset+align,
936 if (flags & STR_LEN_NOTERM) {
940 return extra + smbcli_blob_pull_ascii(mem_ctx, blob, dest,
941 blob->data+str_offset, -1, flags);
946 append a string into a blob
948 size_t smbcli_blob_append_string(struct smbcli_session *session,
949 TALLOC_CTX *mem_ctx, DATA_BLOB *blob,
950 const char *str, uint_t flags)
957 /* determine string type to use */
958 if (!(flags & (STR_ASCII|STR_UNICODE))) {
959 flags |= (session->transport->negotiate.capabilities & CAP_UNICODE) ? STR_UNICODE : STR_ASCII;
962 max_len = (strlen(str)+2) * MAX_BYTES_PER_CHAR;
964 blob->data = talloc_realloc(mem_ctx, blob->data, uint8_t, blob->length + max_len);
969 len = push_string(lp_iconv_convenience(global_loadparm), blob->data + blob->length, str, max_len, flags);
977 pull a GUID structure from the wire. The buffer must be at least 16
980 enum ndr_err_code smbcli_pull_guid(void *base, uint16_t offset,
984 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
985 enum ndr_err_code ndr_err;
989 blob.data = offset + (uint8_t *)base;
991 ndr_err = ndr_pull_struct_blob(&blob, tmp_ctx, NULL, guid,
992 (ndr_pull_flags_fn_t)ndr_pull_GUID);
993 talloc_free(tmp_ctx);
998 push a guid onto the wire. The buffer must hold 16 bytes
1000 enum ndr_err_code smbcli_push_guid(void *base, uint16_t offset,
1001 const struct GUID *guid)
1003 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
1004 enum ndr_err_code ndr_err;
1006 ndr_err = ndr_push_struct_blob(&blob, tmp_ctx, NULL,
1007 guid, (ndr_push_flags_fn_t)ndr_push_GUID);
1008 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err) || blob.length != 16) {
1009 talloc_free(tmp_ctx);
1012 memcpy(offset + (uint8_t *)base, blob.data, blob.length);
1013 talloc_free(tmp_ctx);