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 "libcli/raw/raw_proto.h"
28 #include "lib/util/dlinklist.h"
29 #include "lib/events/events.h"
30 #include "param/param.h"
31 #include "librpc/ndr/libndr.h"
32 #include "librpc/gen_ndr/ndr_misc.h"
34 /* we over allocate the data buffer to prevent too many realloc calls */
35 #define REQ_OVER_ALLOCATION 0
37 /* assume that a character will not consume more than 3 bytes per char */
38 #define MAX_BYTES_PER_CHAR 3
40 /* setup the bufinfo used for strings and range checking */
41 void smb_setup_bufinfo(struct smbcli_request *req)
43 req->in.bufinfo.mem_ctx = req;
44 req->in.bufinfo.flags = 0;
45 if (req->flags2 & FLAGS2_UNICODE_STRINGS) {
46 req->in.bufinfo.flags = BUFINFO_FLAG_UNICODE;
48 req->in.bufinfo.align_base = req->in.buffer;
49 req->in.bufinfo.data = req->in.data;
50 req->in.bufinfo.data_size = req->in.data_size;
54 /* destroy a request structure and return final status */
55 _PUBLIC_ NTSTATUS smbcli_request_destroy(struct smbcli_request *req)
59 /* this is the error code we give the application for when a
60 _send() call fails completely */
61 if (!req) return NT_STATUS_UNSUCCESSFUL;
64 /* remove it from the list of pending requests (a null op if
65 its not in the list) */
66 DLIST_REMOVE(req->transport->pending_recv, req);
69 if (req->state == SMBCLI_REQUEST_ERROR &&
70 NT_STATUS_IS_OK(req->status)) {
71 req->status = NT_STATUS_INTERNAL_ERROR;
81 low-level function to setup a request buffer for a non-SMB packet
82 at the transport level
84 struct smbcli_request *smbcli_request_setup_nonsmb(struct smbcli_transport *transport, size_t size)
86 struct smbcli_request *req;
88 req = talloc(transport, struct smbcli_request);
94 /* setup the request context */
95 req->state = SMBCLI_REQUEST_INIT;
96 req->transport = transport;
101 /* over allocate by a small amount */
102 req->out.allocated = req->out.size + REQ_OVER_ALLOCATION;
104 req->out.buffer = talloc_array(req, uint8_t, req->out.allocated);
105 if (!req->out.buffer) {
109 SIVAL(req->out.buffer, 0, 0);
116 setup a SMB packet at transport level
118 struct smbcli_request *smbcli_request_setup_transport(struct smbcli_transport *transport,
119 uint8_t command, uint_t wct, uint_t buflen)
121 struct smbcli_request *req;
123 req = smbcli_request_setup_nonsmb(transport, NBT_HDR_SIZE + MIN_SMB_SIZE + wct*2 + buflen);
125 if (!req) return NULL;
127 req->out.hdr = req->out.buffer + NBT_HDR_SIZE;
128 req->out.vwv = req->out.hdr + HDR_VWV;
130 req->out.data = req->out.vwv + VWV(wct) + 2;
131 req->out.data_size = buflen;
132 req->out.ptr = req->out.data;
134 SCVAL(req->out.hdr, HDR_WCT, wct);
135 SSVAL(req->out.vwv, VWV(wct), buflen);
137 memcpy(req->out.hdr, "\377SMB", 4);
138 SCVAL(req->out.hdr,HDR_COM,command);
140 SCVAL(req->out.hdr,HDR_FLG, FLAG_CASELESS_PATHNAMES);
141 SSVAL(req->out.hdr,HDR_FLG2, 0);
143 if (command != SMBtranss && command != SMBtranss2) {
145 req->mid = smbcli_transport_next_mid(transport);
148 /* copy the pid, uid and mid to the request */
149 SSVAL(req->out.hdr, HDR_PID, 0);
150 SSVAL(req->out.hdr, HDR_UID, 0);
151 SSVAL(req->out.hdr, HDR_MID, req->mid);
152 SSVAL(req->out.hdr, HDR_TID,0);
153 SSVAL(req->out.hdr, HDR_PIDHIGH,0);
154 SIVAL(req->out.hdr, HDR_RCLS, 0);
155 memset(req->out.hdr+HDR_SS_FIELD, 0, 10);
161 setup a reply in req->out with the given word count and initial data
162 buffer size. the caller will then fill in the command words and
163 data before calling smbcli_request_send() to send the reply on its
164 way. This interface is used before a session is setup.
166 struct smbcli_request *smbcli_request_setup_session(struct smbcli_session *session,
167 uint8_t command, uint_t wct, size_t buflen)
169 struct smbcli_request *req;
171 req = smbcli_request_setup_transport(session->transport, command, wct, buflen);
173 if (!req) return NULL;
175 req->session = session;
177 SSVAL(req->out.hdr, HDR_FLG2, session->flags2);
178 SSVAL(req->out.hdr, HDR_PID, session->pid & 0xFFFF);
179 SSVAL(req->out.hdr, HDR_PIDHIGH, session->pid >> 16);
180 SSVAL(req->out.hdr, HDR_UID, session->vuid);
186 setup a request for tree based commands
188 struct smbcli_request *smbcli_request_setup(struct smbcli_tree *tree,
190 uint_t wct, uint_t buflen)
192 struct smbcli_request *req;
194 req = smbcli_request_setup_session(tree->session, command, wct, buflen);
197 SSVAL(req->out.hdr,HDR_TID,tree->tid);
204 grow the allocation of the data buffer portion of a reply
205 packet. Note that as this can reallocate the packet buffer this
206 invalidates any local pointers into the packet.
208 To cope with this req->out.ptr is supplied. This will be updated to
209 point at the same offset into the packet as before this call
211 static void smbcli_req_grow_allocation(struct smbcli_request *req, uint_t new_size)
216 delta = new_size - req->out.data_size;
217 if (delta + req->out.size <= req->out.allocated) {
218 /* it fits in the preallocation */
222 /* we need to realloc */
223 req->out.allocated = req->out.size + delta + REQ_OVER_ALLOCATION;
224 buf2 = talloc_realloc(req, req->out.buffer, uint8_t, req->out.allocated);
226 smb_panic("out of memory in req_grow_allocation");
229 if (buf2 == req->out.buffer) {
230 /* the malloc library gave us the same pointer */
234 /* update the pointers into the packet */
235 req->out.data = buf2 + PTR_DIFF(req->out.data, req->out.buffer);
236 req->out.ptr = buf2 + PTR_DIFF(req->out.ptr, req->out.buffer);
237 req->out.vwv = buf2 + PTR_DIFF(req->out.vwv, req->out.buffer);
238 req->out.hdr = buf2 + PTR_DIFF(req->out.hdr, req->out.buffer);
240 req->out.buffer = buf2;
245 grow the data buffer portion of a reply packet. Note that as this
246 can reallocate the packet buffer this invalidates any local pointers
249 To cope with this req->out.ptr is supplied. This will be updated to
250 point at the same offset into the packet as before this call
252 static void smbcli_req_grow_data(struct smbcli_request *req, uint_t new_size)
256 smbcli_req_grow_allocation(req, new_size);
258 delta = new_size - req->out.data_size;
260 req->out.size += delta;
261 req->out.data_size += delta;
263 /* set the BCC to the new data size */
264 SSVAL(req->out.vwv, VWV(req->out.wct), new_size);
269 setup a chained reply in req->out with the given word count and
270 initial data buffer size.
272 NTSTATUS smbcli_chained_request_setup(struct smbcli_request *req,
274 uint_t wct, size_t buflen)
276 uint_t new_size = 1 + (wct*2) + 2 + buflen;
278 SSVAL(req->out.vwv, VWV(0), command);
279 SSVAL(req->out.vwv, VWV(1), req->out.size - NBT_HDR_SIZE);
281 smbcli_req_grow_allocation(req, req->out.data_size + new_size);
283 req->out.vwv = req->out.buffer + req->out.size + 1;
284 SCVAL(req->out.vwv, -1, wct);
285 SSVAL(req->out.vwv, VWV(wct), buflen);
287 req->out.size += new_size;
288 req->out.data_size += new_size;
294 aadvance to the next chained reply in a request
296 NTSTATUS smbcli_chained_advance(struct smbcli_request *req)
300 if (CVAL(req->in.vwv, VWV(0)) == SMB_CHAIN_NONE) {
301 return NT_STATUS_NOT_FOUND;
304 buffer = req->in.hdr + SVAL(req->in.vwv, VWV(1));
306 if (buffer + 3 > req->in.buffer + req->in.size) {
307 return NT_STATUS_BUFFER_TOO_SMALL;
310 req->in.vwv = buffer + 1;
311 req->in.wct = CVAL(buffer, 0);
312 if (buffer + 3 + req->in.wct*2 > req->in.buffer + req->in.size) {
313 return NT_STATUS_BUFFER_TOO_SMALL;
315 req->in.data = req->in.vwv + 2 + req->in.wct * 2;
316 req->in.data_size = SVAL(req->in.vwv, VWV(req->in.wct));
318 /* fix the bufinfo */
319 smb_setup_bufinfo(req);
321 if (buffer + 3 + req->in.wct*2 + req->in.data_size >
322 req->in.buffer + req->in.size) {
323 return NT_STATUS_BUFFER_TOO_SMALL;
333 bool smbcli_request_send(struct smbcli_request *req)
335 if (IVAL(req->out.buffer, 0) == 0) {
336 _smb_setlen(req->out.buffer, req->out.size - NBT_HDR_SIZE);
339 smbcli_request_calculate_sign_mac(req);
341 smbcli_transport_send(req);
348 receive a response to a packet
350 bool smbcli_request_receive(struct smbcli_request *req)
352 /* req can be NULL when a send has failed. This eliminates lots of NULL
353 checks in each module */
354 if (!req) return false;
356 /* keep receiving packets until this one is replied to */
357 while (req->state <= SMBCLI_REQUEST_RECV) {
358 if (event_loop_once(req->transport->socket->event.ctx) != 0) {
363 return req->state == SMBCLI_REQUEST_DONE;
368 receive another reply to a request - this is used for requests that
369 have multi-part replies (such as SMBtrans2)
371 bool smbcli_request_receive_more(struct smbcli_request *req)
373 req->state = SMBCLI_REQUEST_RECV;
374 DLIST_ADD(req->transport->pending_recv, req);
376 return smbcli_request_receive(req);
381 handle oplock break requests from the server - return true if the request was
384 bool smbcli_handle_oplock_break(struct smbcli_transport *transport, uint_t len, const uint8_t *hdr, const uint8_t *vwv)
386 /* we must be very fussy about what we consider an oplock break to avoid
387 matching readbraw replies */
388 if (len != MIN_SMB_SIZE + VWV(8) + NBT_HDR_SIZE ||
389 (CVAL(hdr, HDR_FLG) & FLAG_REPLY) ||
390 CVAL(hdr,HDR_COM) != SMBlockingX ||
391 SVAL(hdr, HDR_MID) != 0xFFFF ||
392 SVAL(vwv,VWV(6)) != 0 ||
393 SVAL(vwv,VWV(7)) != 0) {
397 if (transport->oplock.handler) {
398 uint16_t tid = SVAL(hdr, HDR_TID);
399 uint16_t fnum = SVAL(vwv,VWV(2));
400 uint8_t level = CVAL(vwv,VWV(3)+1);
401 transport->oplock.handler(transport, tid, fnum, level, transport->oplock.private);
408 wait for a reply to be received for a packet that just returns an error
409 code and nothing more
411 _PUBLIC_ NTSTATUS smbcli_request_simple_recv(struct smbcli_request *req)
413 (void) smbcli_request_receive(req);
414 return smbcli_request_destroy(req);
418 /* Return true if the last packet was in error */
419 bool smbcli_request_is_error(struct smbcli_request *req)
421 return NT_STATUS_IS_ERR(req->status);
425 append a string into the data portion of the request packet
427 return the number of bytes added to the packet
429 size_t smbcli_req_append_string(struct smbcli_request *req, const char *str, uint_t flags)
433 /* determine string type to use */
434 if (!(flags & (STR_ASCII|STR_UNICODE))) {
435 flags |= (req->transport->negotiate.capabilities & CAP_UNICODE) ? STR_UNICODE : STR_ASCII;
438 len = (strlen(str)+2) * MAX_BYTES_PER_CHAR;
440 smbcli_req_grow_allocation(req, len + req->out.data_size);
442 len = push_string(lp_iconv_convenience(global_loadparm), req->out.data + req->out.data_size, str, len, flags);
444 smbcli_req_grow_data(req, len + req->out.data_size);
451 this is like smbcli_req_append_string but it also return the
452 non-terminated string byte length, which can be less than the number
453 of bytes consumed in the packet for 2 reasons:
455 1) the string in the packet may be null terminated
456 2) the string in the packet may need a 1 byte UCS2 alignment
458 this is used in places where the non-terminated string byte length is
459 placed in the packet as a separate field
461 size_t smbcli_req_append_string_len(struct smbcli_request *req, const char *str, uint_t flags, int *len)
466 /* determine string type to use */
467 if (!(flags & (STR_ASCII|STR_UNICODE))) {
468 flags |= (req->transport->negotiate.capabilities & CAP_UNICODE) ? STR_UNICODE : STR_ASCII;
471 /* see if an alignment byte will be used */
472 if ((flags & STR_UNICODE) && !(flags & STR_NOALIGN)) {
473 diff = ucs2_align(NULL, req->out.data + req->out.data_size, flags);
476 /* do the hard work */
477 ret = smbcli_req_append_string(req, str, flags);
479 /* see if we need to subtract the termination */
480 if (flags & STR_TERMINATE) {
481 diff += (flags & STR_UNICODE) ? 2 : 1;
495 push a string into the data portion of the request packet, growing it if necessary
496 this gets quite tricky - please be very careful to cover all cases when modifying this
498 if dest is NULL, then put the string at the end of the data portion of the packet
500 if dest_len is -1 then no limit applies
502 size_t smbcli_req_append_ascii4(struct smbcli_request *req, const char *str, uint_t flags)
505 smbcli_req_append_bytes(req, (const uint8_t *)"\4", 1);
506 size = smbcli_req_append_string(req, str, flags);
512 push a blob into the data portion of the request packet, growing it if necessary
513 this gets quite tricky - please be very careful to cover all cases when modifying this
515 if dest is NULL, then put the blob at the end of the data portion of the packet
517 size_t smbcli_req_append_blob(struct smbcli_request *req, const DATA_BLOB *blob)
519 smbcli_req_grow_allocation(req, req->out.data_size + blob->length);
520 memcpy(req->out.data + req->out.data_size, blob->data, blob->length);
521 smbcli_req_grow_data(req, req->out.data_size + blob->length);
526 append raw bytes into the data portion of the request packet
527 return the number of bytes added
529 size_t smbcli_req_append_bytes(struct smbcli_request *req, const uint8_t *bytes, size_t byte_len)
531 smbcli_req_grow_allocation(req, byte_len + req->out.data_size);
532 memcpy(req->out.data + req->out.data_size, bytes, byte_len);
533 smbcli_req_grow_data(req, byte_len + req->out.data_size);
538 append variable block (type 5 buffer) into the data portion of the request packet
539 return the number of bytes added
541 size_t smbcli_req_append_var_block(struct smbcli_request *req, const uint8_t *bytes, uint16_t byte_len)
543 smbcli_req_grow_allocation(req, byte_len + 3 + req->out.data_size);
544 SCVAL(req->out.data + req->out.data_size, 0, 5);
545 SSVAL(req->out.data + req->out.data_size, 1, byte_len); /* add field length */
547 memcpy(req->out.data + req->out.data_size + 3, bytes, byte_len);
549 smbcli_req_grow_data(req, byte_len + 3 + req->out.data_size);
555 pull a UCS2 string from a request packet, returning a talloced unix string
557 the string length is limited by the 3 things:
558 - the data size in the request (end of packet)
559 - the passed 'byte_len' if it is not -1
560 - the end of string (null termination)
562 Note that 'byte_len' is the number of bytes in the packet
564 on failure zero is returned and *dest is set to NULL, otherwise the number
565 of bytes consumed in the packet is returned
567 static size_t smbcli_req_pull_ucs2(struct request_bufinfo *bufinfo, TALLOC_CTX *mem_ctx,
568 char **dest, const uint8_t *src, int byte_len, uint_t flags)
570 int src_len, src_len2, alignment=0;
573 if (!(flags & STR_NOALIGN) && ucs2_align(bufinfo->align_base, src, flags)) {
576 if (byte_len != -1) {
581 src_len = bufinfo->data_size - PTR_DIFF(src, bufinfo->data);
586 if (byte_len != -1 && src_len > byte_len) {
590 src_len2 = utf16_len_n(src, src_len);
592 /* ucs2 strings must be at least 2 bytes long */
598 ret = convert_string_talloc(mem_ctx, lp_iconv_convenience(global_loadparm), CH_UTF16, CH_UNIX, src, src_len2, (void **)dest);
604 return src_len2 + alignment;
608 pull a ascii string from a request packet, returning a talloced string
610 the string length is limited by the 3 things:
611 - the data size in the request (end of packet)
612 - the passed 'byte_len' if it is not -1
613 - the end of string (null termination)
615 Note that 'byte_len' is the number of bytes in the packet
617 on failure zero is returned and *dest is set to NULL, otherwise the number
618 of bytes consumed in the packet is returned
620 size_t smbcli_req_pull_ascii(struct request_bufinfo *bufinfo, TALLOC_CTX *mem_ctx,
621 char **dest, const uint8_t *src, int byte_len, uint_t flags)
623 int src_len, src_len2;
626 src_len = bufinfo->data_size - PTR_DIFF(src, bufinfo->data);
631 if (byte_len != -1 && src_len > byte_len) {
634 src_len2 = strnlen((const char *)src, src_len);
635 if (src_len2 < src_len - 1) {
636 /* include the termination if we didn't reach the end of the packet */
640 ret = convert_string_talloc(mem_ctx, lp_iconv_convenience(global_loadparm), CH_DOS, CH_UNIX, src, src_len2, (void **)dest);
651 pull a string from a request packet, returning a talloced string
653 the string length is limited by the 3 things:
654 - the data size in the request (end of packet)
655 - the passed 'byte_len' if it is not -1
656 - the end of string (null termination)
658 Note that 'byte_len' is the number of bytes in the packet
660 on failure zero is returned and *dest is set to NULL, otherwise the number
661 of bytes consumed in the packet is returned
663 size_t smbcli_req_pull_string(struct request_bufinfo *bufinfo, TALLOC_CTX *mem_ctx,
664 char **dest, const uint8_t *src, int byte_len, uint_t flags)
666 if (!(flags & STR_ASCII) &&
667 (((flags & STR_UNICODE) || (bufinfo->flags & BUFINFO_FLAG_UNICODE)))) {
668 return smbcli_req_pull_ucs2(bufinfo, mem_ctx, dest, src, byte_len, flags);
671 return smbcli_req_pull_ascii(bufinfo, mem_ctx, dest, src, byte_len, flags);
676 pull a DATA_BLOB from a reply packet, returning a talloced blob
677 make sure we don't go past end of packet
679 if byte_len is -1 then limit the blob only by packet size
681 DATA_BLOB smbcli_req_pull_blob(struct request_bufinfo *bufinfo, TALLOC_CTX *mem_ctx, const uint8_t *src, int byte_len)
685 src_len = bufinfo->data_size - PTR_DIFF(src, bufinfo->data);
688 return data_blob(NULL, 0);
691 if (byte_len != -1 && src_len > byte_len) {
695 return data_blob_talloc(mem_ctx, src, src_len);
698 /* check that a lump of data in a request is within the bounds of the data section of
700 static bool smbcli_req_data_oob(struct request_bufinfo *bufinfo, const uint8_t *ptr, uint32_t count)
702 /* be careful with wraparound! */
703 if (ptr < bufinfo->data ||
704 ptr >= bufinfo->data + bufinfo->data_size ||
705 count > bufinfo->data_size ||
706 ptr + count > bufinfo->data + bufinfo->data_size) {
713 pull a lump of data from a request packet
715 return false if any part is outside the data portion of the packet
717 bool smbcli_raw_pull_data(struct request_bufinfo *bufinfo, const uint8_t *src, int len, uint8_t *dest)
719 if (len == 0) return true;
721 if (smbcli_req_data_oob(bufinfo, src, len)) {
725 memcpy(dest, src, len);
731 put a NTTIME into a packet
733 void smbcli_push_nttime(void *base, uint16_t offset, NTTIME t)
735 SBVAL(base, offset, t);
739 pull a NTTIME from a packet
741 NTTIME smbcli_pull_nttime(void *base, uint16_t offset)
743 NTTIME ret = BVAL(base, offset);
748 pull a UCS2 string from a blob, returning a talloced unix string
750 the string length is limited by the 3 things:
751 - the data size in the blob
752 - the passed 'byte_len' if it is not -1
753 - the end of string (null termination)
755 Note that 'byte_len' is the number of bytes in the packet
757 on failure zero is returned and *dest is set to NULL, otherwise the number
758 of bytes consumed in the blob is returned
760 size_t smbcli_blob_pull_ucs2(TALLOC_CTX* mem_ctx,
761 const DATA_BLOB *blob, const char **dest,
762 const uint8_t *src, int byte_len, uint_t flags)
764 int src_len, src_len2, alignment=0;
768 if (src < blob->data ||
769 src >= (blob->data + blob->length)) {
774 src_len = blob->length - PTR_DIFF(src, blob->data);
776 if (byte_len != -1 && src_len > byte_len) {
780 if (!(flags & STR_NOALIGN) && ucs2_align(blob->data, src, flags)) {
791 src_len2 = utf16_len_n(src, src_len);
793 ret = convert_string_talloc(mem_ctx, lp_iconv_convenience(global_loadparm), CH_UTF16, CH_UNIX, src, src_len2, (void **)&dest2);
800 return src_len2 + alignment;
804 pull a ascii string from a blob, returning a talloced string
806 the string length is limited by the 3 things:
807 - the data size in the blob
808 - the passed 'byte_len' if it is not -1
809 - the end of string (null termination)
811 Note that 'byte_len' is the number of bytes in the blob
813 on failure zero is returned and *dest is set to NULL, otherwise the number
814 of bytes consumed in the blob is returned
816 static size_t smbcli_blob_pull_ascii(TALLOC_CTX *mem_ctx,
817 const DATA_BLOB *blob, const char **dest,
818 const uint8_t *src, int byte_len, uint_t flags)
820 int src_len, src_len2;
824 src_len = blob->length - PTR_DIFF(src, blob->data);
829 if (byte_len != -1 && src_len > byte_len) {
832 src_len2 = strnlen((const char *)src, src_len);
834 if (src_len2 < src_len - 1) {
835 /* include the termination if we didn't reach the end of the packet */
839 ret = convert_string_talloc(mem_ctx, lp_iconv_convenience(global_loadparm), CH_DOS, CH_UNIX, src, src_len2, (void **)&dest2);
851 pull a string from a blob, returning a talloced struct smb_wire_string
853 the string length is limited by the 3 things:
854 - the data size in the blob
855 - length field on the wire
856 - the end of string (null termination)
858 if STR_LEN8BIT is set in the flags then assume the length field is
859 8 bits, instead of 32
861 on failure zero is returned and dest->s is set to NULL, otherwise the number
862 of bytes consumed in the blob is returned
864 size_t smbcli_blob_pull_string(struct smbcli_session *session,
866 const DATA_BLOB *blob,
867 struct smb_wire_string *dest,
868 uint16_t len_offset, uint16_t str_offset,
874 if (!(flags & STR_ASCII)) {
875 /* this is here to cope with SMB2 calls using the SMB
876 parsers. SMB2 will pass smbcli_session==NULL, which forces
877 unicode on (as used by SMB2) */
878 if (session == NULL) {
879 flags |= STR_UNICODE;
880 } else if (session->transport->negotiate.capabilities & CAP_UNICODE) {
881 flags |= STR_UNICODE;
885 if (flags & STR_LEN8BIT) {
886 if (len_offset > blob->length-1) {
889 dest->private_length = CVAL(blob->data, len_offset);
891 if (len_offset > blob->length-4) {
894 dest->private_length = IVAL(blob->data, len_offset);
898 if (!(flags & STR_ASCII) && (flags & STR_UNICODE)) {
900 if ((str_offset&1) && !(flags & STR_NOALIGN)) {
903 if (flags & STR_LEN_NOTERM) {
906 return align + extra + smbcli_blob_pull_ucs2(mem_ctx, blob, &dest->s,
907 blob->data+str_offset+align,
908 dest->private_length, flags);
911 if (flags & STR_LEN_NOTERM) {
915 return extra + smbcli_blob_pull_ascii(mem_ctx, blob, &dest->s,
916 blob->data+str_offset, dest->private_length, flags);
920 pull a string from a blob, returning a talloced char *
922 Currently only used by the UNIX search info level.
924 the string length is limited by 2 things:
925 - the data size in the blob
926 - the end of string (null termination)
928 on failure zero is returned and dest->s is set to NULL, otherwise the number
929 of bytes consumed in the blob is returned
931 size_t smbcli_blob_pull_unix_string(struct smbcli_session *session,
941 if (!(flags & STR_ASCII) &&
942 ((flags & STR_UNICODE) ||
943 (session->transport->negotiate.capabilities & CAP_UNICODE))) {
945 if ((str_offset&1) && !(flags & STR_NOALIGN)) {
948 if (flags & STR_LEN_NOTERM) {
951 return align + extra + smbcli_blob_pull_ucs2(mem_ctx, blob, dest,
952 blob->data+str_offset+align,
956 if (flags & STR_LEN_NOTERM) {
960 return extra + smbcli_blob_pull_ascii(mem_ctx, blob, dest,
961 blob->data+str_offset, -1, flags);
966 append a string into a blob
968 size_t smbcli_blob_append_string(struct smbcli_session *session,
969 TALLOC_CTX *mem_ctx, DATA_BLOB *blob,
970 const char *str, uint_t flags)
977 /* determine string type to use */
978 if (!(flags & (STR_ASCII|STR_UNICODE))) {
979 flags |= (session->transport->negotiate.capabilities & CAP_UNICODE) ? STR_UNICODE : STR_ASCII;
982 max_len = (strlen(str)+2) * MAX_BYTES_PER_CHAR;
984 blob->data = talloc_realloc(mem_ctx, blob->data, uint8_t, blob->length + max_len);
989 len = push_string(lp_iconv_convenience(global_loadparm), blob->data + blob->length, str, max_len, flags);
997 pull a GUID structure from the wire. The buffer must be at least 16
1000 enum ndr_err_code smbcli_pull_guid(void *base, uint16_t offset,
1004 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
1005 enum ndr_err_code ndr_err;
1009 blob.data = offset + (uint8_t *)base;
1011 ndr_err = ndr_pull_struct_blob(&blob, tmp_ctx, NULL, guid,
1012 (ndr_pull_flags_fn_t)ndr_pull_GUID);
1013 talloc_free(tmp_ctx);
1018 push a guid onto the wire. The buffer must hold 16 bytes
1020 enum ndr_err_code smbcli_push_guid(void *base, uint16_t offset,
1021 const struct GUID *guid)
1023 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
1024 enum ndr_err_code ndr_err;
1026 ndr_err = ndr_push_struct_blob(&blob, tmp_ctx, NULL,
1027 guid, (ndr_push_flags_fn_t)ndr_push_GUID);
1028 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err) || blob.length != 16) {
1029 talloc_free(tmp_ctx);
1032 memcpy(offset + (uint8_t *)base, blob.data, blob.length);
1033 talloc_free(tmp_ctx);