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;
76 if (!req->do_not_free) {
85 low-level function to setup a request buffer for a non-SMB packet
86 at the transport level
88 struct smbcli_request *smbcli_request_setup_nonsmb(struct smbcli_transport *transport, size_t size)
90 struct smbcli_request *req;
92 req = talloc(transport, struct smbcli_request);
98 /* setup the request context */
99 req->state = SMBCLI_REQUEST_INIT;
100 req->transport = transport;
103 req->out.size = size;
105 /* over allocate by a small amount */
106 req->out.allocated = req->out.size + REQ_OVER_ALLOCATION;
108 req->out.buffer = talloc_array(req, uint8_t, req->out.allocated);
109 if (!req->out.buffer) {
113 SIVAL(req->out.buffer, 0, 0);
120 setup a SMB packet at transport level
122 struct smbcli_request *smbcli_request_setup_transport(struct smbcli_transport *transport,
123 uint8_t command, uint_t wct, uint_t buflen)
125 struct smbcli_request *req;
127 req = smbcli_request_setup_nonsmb(transport, NBT_HDR_SIZE + MIN_SMB_SIZE + wct*2 + buflen);
129 if (!req) return NULL;
131 req->out.hdr = req->out.buffer + NBT_HDR_SIZE;
132 req->out.vwv = req->out.hdr + HDR_VWV;
134 req->out.data = req->out.vwv + VWV(wct) + 2;
135 req->out.data_size = buflen;
136 req->out.ptr = req->out.data;
138 SCVAL(req->out.hdr, HDR_WCT, wct);
139 SSVAL(req->out.vwv, VWV(wct), buflen);
141 memcpy(req->out.hdr, "\377SMB", 4);
142 SCVAL(req->out.hdr,HDR_COM,command);
144 SCVAL(req->out.hdr,HDR_FLG, FLAG_CASELESS_PATHNAMES);
145 SSVAL(req->out.hdr,HDR_FLG2, 0);
147 if (command != SMBtranss && command != SMBtranss2) {
149 req->mid = smbcli_transport_next_mid(transport);
152 /* copy the pid, uid and mid to the request */
153 SSVAL(req->out.hdr, HDR_PID, 0);
154 SSVAL(req->out.hdr, HDR_UID, 0);
155 SSVAL(req->out.hdr, HDR_MID, req->mid);
156 SSVAL(req->out.hdr, HDR_TID,0);
157 SSVAL(req->out.hdr, HDR_PIDHIGH,0);
158 SIVAL(req->out.hdr, HDR_RCLS, 0);
159 memset(req->out.hdr+HDR_SS_FIELD, 0, 10);
165 setup a reply in req->out with the given word count and initial data
166 buffer size. the caller will then fill in the command words and
167 data before calling smbcli_request_send() to send the reply on its
168 way. This interface is used before a session is setup.
170 struct smbcli_request *smbcli_request_setup_session(struct smbcli_session *session,
171 uint8_t command, uint_t wct, size_t buflen)
173 struct smbcli_request *req;
175 req = smbcli_request_setup_transport(session->transport, command, wct, buflen);
177 if (!req) return NULL;
179 req->session = session;
181 SSVAL(req->out.hdr, HDR_FLG2, session->flags2);
182 SSVAL(req->out.hdr, HDR_PID, session->pid & 0xFFFF);
183 SSVAL(req->out.hdr, HDR_PIDHIGH, session->pid >> 16);
184 SSVAL(req->out.hdr, HDR_UID, session->vuid);
190 setup a request for tree based commands
192 struct smbcli_request *smbcli_request_setup(struct smbcli_tree *tree,
194 uint_t wct, uint_t buflen)
196 struct smbcli_request *req;
198 req = smbcli_request_setup_session(tree->session, command, wct, buflen);
201 SSVAL(req->out.hdr,HDR_TID,tree->tid);
208 grow the allocation of the data buffer portion of a reply
209 packet. Note that as this can reallocate the packet buffer this
210 invalidates any local pointers into the packet.
212 To cope with this req->out.ptr is supplied. This will be updated to
213 point at the same offset into the packet as before this call
215 static void smbcli_req_grow_allocation(struct smbcli_request *req, uint_t new_size)
220 delta = new_size - req->out.data_size;
221 if (delta + req->out.size <= req->out.allocated) {
222 /* it fits in the preallocation */
226 /* we need to realloc */
227 req->out.allocated = req->out.size + delta + REQ_OVER_ALLOCATION;
228 buf2 = talloc_realloc(req, req->out.buffer, uint8_t, req->out.allocated);
230 smb_panic("out of memory in req_grow_allocation");
233 if (buf2 == req->out.buffer) {
234 /* the malloc library gave us the same pointer */
238 /* update the pointers into the packet */
239 req->out.data = buf2 + PTR_DIFF(req->out.data, req->out.buffer);
240 req->out.ptr = buf2 + PTR_DIFF(req->out.ptr, req->out.buffer);
241 req->out.vwv = buf2 + PTR_DIFF(req->out.vwv, req->out.buffer);
242 req->out.hdr = buf2 + PTR_DIFF(req->out.hdr, req->out.buffer);
244 req->out.buffer = buf2;
249 grow the data buffer portion of a reply packet. Note that as this
250 can reallocate the packet buffer this invalidates any local pointers
253 To cope with this req->out.ptr is supplied. This will be updated to
254 point at the same offset into the packet as before this call
256 static void smbcli_req_grow_data(struct smbcli_request *req, uint_t new_size)
260 smbcli_req_grow_allocation(req, new_size);
262 delta = new_size - req->out.data_size;
264 req->out.size += delta;
265 req->out.data_size += delta;
267 /* set the BCC to the new data size */
268 SSVAL(req->out.vwv, VWV(req->out.wct), new_size);
273 setup a chained reply in req->out with the given word count and
274 initial data buffer size.
276 NTSTATUS smbcli_chained_request_setup(struct smbcli_request *req,
278 uint_t wct, size_t buflen)
280 uint_t new_size = 1 + (wct*2) + 2 + buflen;
282 SSVAL(req->out.vwv, VWV(0), command);
283 SSVAL(req->out.vwv, VWV(1), req->out.size - NBT_HDR_SIZE);
285 smbcli_req_grow_allocation(req, req->out.data_size + new_size);
287 req->out.vwv = req->out.buffer + req->out.size + 1;
288 SCVAL(req->out.vwv, -1, wct);
289 SSVAL(req->out.vwv, VWV(wct), buflen);
291 req->out.size += new_size;
292 req->out.data_size += new_size;
298 aadvance to the next chained reply in a request
300 NTSTATUS smbcli_chained_advance(struct smbcli_request *req)
304 if (CVAL(req->in.vwv, VWV(0)) == SMB_CHAIN_NONE) {
305 return NT_STATUS_NOT_FOUND;
308 buffer = req->in.hdr + SVAL(req->in.vwv, VWV(1));
310 if (buffer + 3 > req->in.buffer + req->in.size) {
311 return NT_STATUS_BUFFER_TOO_SMALL;
314 req->in.vwv = buffer + 1;
315 req->in.wct = CVAL(buffer, 0);
316 if (buffer + 3 + req->in.wct*2 > req->in.buffer + req->in.size) {
317 return NT_STATUS_BUFFER_TOO_SMALL;
319 req->in.data = req->in.vwv + 2 + req->in.wct * 2;
320 req->in.data_size = SVAL(req->in.vwv, VWV(req->in.wct));
322 /* fix the bufinfo */
323 smb_setup_bufinfo(req);
325 if (buffer + 3 + req->in.wct*2 + req->in.data_size >
326 req->in.buffer + req->in.size) {
327 return NT_STATUS_BUFFER_TOO_SMALL;
337 bool smbcli_request_send(struct smbcli_request *req)
339 if (IVAL(req->out.buffer, 0) == 0) {
340 _smb_setlen(req->out.buffer, req->out.size - NBT_HDR_SIZE);
343 smbcli_request_calculate_sign_mac(req);
345 smbcli_transport_send(req);
352 receive a response to a packet
354 bool smbcli_request_receive(struct smbcli_request *req)
356 /* req can be NULL when a send has failed. This eliminates lots of NULL
357 checks in each module */
358 if (!req) return false;
360 /* keep receiving packets until this one is replied to */
361 while (req->state <= SMBCLI_REQUEST_RECV) {
362 if (event_loop_once(req->transport->socket->event.ctx) != 0) {
367 return req->state == SMBCLI_REQUEST_DONE;
372 handle oplock break requests from the server - return true if the request was
375 bool smbcli_handle_oplock_break(struct smbcli_transport *transport, uint_t len, const uint8_t *hdr, const uint8_t *vwv)
377 /* we must be very fussy about what we consider an oplock break to avoid
378 matching readbraw replies */
379 if (len != MIN_SMB_SIZE + VWV(8) + NBT_HDR_SIZE ||
380 (CVAL(hdr, HDR_FLG) & FLAG_REPLY) ||
381 CVAL(hdr,HDR_COM) != SMBlockingX ||
382 SVAL(hdr, HDR_MID) != 0xFFFF ||
383 SVAL(vwv,VWV(6)) != 0 ||
384 SVAL(vwv,VWV(7)) != 0) {
388 if (transport->oplock.handler) {
389 uint16_t tid = SVAL(hdr, HDR_TID);
390 uint16_t fnum = SVAL(vwv,VWV(2));
391 uint8_t level = CVAL(vwv,VWV(3)+1);
392 transport->oplock.handler(transport, tid, fnum, level, transport->oplock.private);
399 wait for a reply to be received for a packet that just returns an error
400 code and nothing more
402 _PUBLIC_ NTSTATUS smbcli_request_simple_recv(struct smbcli_request *req)
404 (void) smbcli_request_receive(req);
405 return smbcli_request_destroy(req);
409 /* Return true if the last packet was in error */
410 bool smbcli_request_is_error(struct smbcli_request *req)
412 return NT_STATUS_IS_ERR(req->status);
416 append a string into the data portion of the request packet
418 return the number of bytes added to the packet
420 size_t smbcli_req_append_string(struct smbcli_request *req, const char *str, uint_t flags)
424 /* determine string type to use */
425 if (!(flags & (STR_ASCII|STR_UNICODE))) {
426 flags |= (req->transport->negotiate.capabilities & CAP_UNICODE) ? STR_UNICODE : STR_ASCII;
429 len = (strlen(str)+2) * MAX_BYTES_PER_CHAR;
431 smbcli_req_grow_allocation(req, len + req->out.data_size);
433 len = push_string(lp_iconv_convenience(global_loadparm), req->out.data + req->out.data_size, str, len, flags);
435 smbcli_req_grow_data(req, len + req->out.data_size);
442 this is like smbcli_req_append_string but it also return the
443 non-terminated string byte length, which can be less than the number
444 of bytes consumed in the packet for 2 reasons:
446 1) the string in the packet may be null terminated
447 2) the string in the packet may need a 1 byte UCS2 alignment
449 this is used in places where the non-terminated string byte length is
450 placed in the packet as a separate field
452 size_t smbcli_req_append_string_len(struct smbcli_request *req, const char *str, uint_t flags, int *len)
457 /* determine string type to use */
458 if (!(flags & (STR_ASCII|STR_UNICODE))) {
459 flags |= (req->transport->negotiate.capabilities & CAP_UNICODE) ? STR_UNICODE : STR_ASCII;
462 /* see if an alignment byte will be used */
463 if ((flags & STR_UNICODE) && !(flags & STR_NOALIGN)) {
464 diff = ucs2_align(NULL, req->out.data + req->out.data_size, flags);
467 /* do the hard work */
468 ret = smbcli_req_append_string(req, str, flags);
470 /* see if we need to subtract the termination */
471 if (flags & STR_TERMINATE) {
472 diff += (flags & STR_UNICODE) ? 2 : 1;
486 push a string into the data portion of the request packet, growing it if necessary
487 this gets quite tricky - please be very careful to cover all cases when modifying this
489 if dest is NULL, then put the string at the end of the data portion of the packet
491 if dest_len is -1 then no limit applies
493 size_t smbcli_req_append_ascii4(struct smbcli_request *req, const char *str, uint_t flags)
496 smbcli_req_append_bytes(req, (const uint8_t *)"\4", 1);
497 size = smbcli_req_append_string(req, str, flags);
503 push a blob into the data portion of the request packet, growing it if necessary
504 this gets quite tricky - please be very careful to cover all cases when modifying this
506 if dest is NULL, then put the blob at the end of the data portion of the packet
508 size_t smbcli_req_append_blob(struct smbcli_request *req, const DATA_BLOB *blob)
510 smbcli_req_grow_allocation(req, req->out.data_size + blob->length);
511 memcpy(req->out.data + req->out.data_size, blob->data, blob->length);
512 smbcli_req_grow_data(req, req->out.data_size + blob->length);
517 append raw bytes into the data portion of the request packet
518 return the number of bytes added
520 size_t smbcli_req_append_bytes(struct smbcli_request *req, const uint8_t *bytes, size_t byte_len)
522 smbcli_req_grow_allocation(req, byte_len + req->out.data_size);
523 memcpy(req->out.data + req->out.data_size, bytes, byte_len);
524 smbcli_req_grow_data(req, byte_len + req->out.data_size);
529 append variable block (type 5 buffer) into the data portion of the request packet
530 return the number of bytes added
532 size_t smbcli_req_append_var_block(struct smbcli_request *req, const uint8_t *bytes, uint16_t byte_len)
534 smbcli_req_grow_allocation(req, byte_len + 3 + req->out.data_size);
535 SCVAL(req->out.data + req->out.data_size, 0, 5);
536 SSVAL(req->out.data + req->out.data_size, 1, byte_len); /* add field length */
538 memcpy(req->out.data + req->out.data_size + 3, bytes, byte_len);
540 smbcli_req_grow_data(req, byte_len + 3 + req->out.data_size);
546 pull a UCS2 string from a request packet, returning a talloced unix string
548 the string length is limited by the 3 things:
549 - the data size in the request (end of packet)
550 - the passed 'byte_len' if it is not -1
551 - the end of string (null termination)
553 Note that 'byte_len' is the number of bytes in the packet
555 on failure zero is returned and *dest is set to NULL, otherwise the number
556 of bytes consumed in the packet is returned
558 static size_t smbcli_req_pull_ucs2(struct request_bufinfo *bufinfo, TALLOC_CTX *mem_ctx,
559 char **dest, const uint8_t *src, int byte_len, uint_t flags)
561 int src_len, src_len2, alignment=0;
564 if (!(flags & STR_NOALIGN) && ucs2_align(bufinfo->align_base, src, flags)) {
567 if (byte_len != -1) {
572 src_len = bufinfo->data_size - PTR_DIFF(src, bufinfo->data);
577 if (byte_len != -1 && src_len > byte_len) {
581 src_len2 = utf16_len_n(src, src_len);
583 /* ucs2 strings must be at least 2 bytes long */
589 ret = convert_string_talloc(mem_ctx, lp_iconv_convenience(global_loadparm), CH_UTF16, CH_UNIX, src, src_len2, (void **)dest);
595 return src_len2 + alignment;
599 pull a ascii string from a request packet, returning a talloced string
601 the string length is limited by the 3 things:
602 - the data size in the request (end of packet)
603 - the passed 'byte_len' if it is not -1
604 - the end of string (null termination)
606 Note that 'byte_len' is the number of bytes in the packet
608 on failure zero is returned and *dest is set to NULL, otherwise the number
609 of bytes consumed in the packet is returned
611 size_t smbcli_req_pull_ascii(struct request_bufinfo *bufinfo, TALLOC_CTX *mem_ctx,
612 char **dest, const uint8_t *src, int byte_len, uint_t flags)
614 int src_len, src_len2;
617 src_len = bufinfo->data_size - PTR_DIFF(src, bufinfo->data);
622 if (byte_len != -1 && src_len > byte_len) {
625 src_len2 = strnlen((const char *)src, src_len);
626 if (src_len2 < src_len - 1) {
627 /* include the termination if we didn't reach the end of the packet */
631 ret = convert_string_talloc(mem_ctx, lp_iconv_convenience(global_loadparm), CH_DOS, CH_UNIX, src, src_len2, (void **)dest);
642 pull a string from a request packet, returning a talloced string
644 the string length is limited by the 3 things:
645 - the data size in the request (end of packet)
646 - the passed 'byte_len' if it is not -1
647 - the end of string (null termination)
649 Note that 'byte_len' is the number of bytes in the packet
651 on failure zero is returned and *dest is set to NULL, otherwise the number
652 of bytes consumed in the packet is returned
654 size_t smbcli_req_pull_string(struct request_bufinfo *bufinfo, TALLOC_CTX *mem_ctx,
655 char **dest, const uint8_t *src, int byte_len, uint_t flags)
657 if (!(flags & STR_ASCII) &&
658 (((flags & STR_UNICODE) || (bufinfo->flags & BUFINFO_FLAG_UNICODE)))) {
659 return smbcli_req_pull_ucs2(bufinfo, mem_ctx, dest, src, byte_len, flags);
662 return smbcli_req_pull_ascii(bufinfo, mem_ctx, dest, src, byte_len, flags);
667 pull a DATA_BLOB from a reply packet, returning a talloced blob
668 make sure we don't go past end of packet
670 if byte_len is -1 then limit the blob only by packet size
672 DATA_BLOB smbcli_req_pull_blob(struct request_bufinfo *bufinfo, TALLOC_CTX *mem_ctx, const uint8_t *src, int byte_len)
676 src_len = bufinfo->data_size - PTR_DIFF(src, bufinfo->data);
679 return data_blob(NULL, 0);
682 if (byte_len != -1 && src_len > byte_len) {
686 return data_blob_talloc(mem_ctx, src, src_len);
689 /* check that a lump of data in a request is within the bounds of the data section of
691 static bool smbcli_req_data_oob(struct request_bufinfo *bufinfo, const uint8_t *ptr, uint32_t count)
693 /* be careful with wraparound! */
694 if ((uintptr_t)ptr < (uintptr_t)bufinfo->data ||
695 (uintptr_t)ptr >= (uintptr_t)bufinfo->data + bufinfo->data_size ||
696 count > bufinfo->data_size ||
697 (uintptr_t)ptr + count > (uintptr_t)bufinfo->data + bufinfo->data_size) {
704 pull a lump of data from a request packet
706 return false if any part is outside the data portion of the packet
708 bool smbcli_raw_pull_data(struct request_bufinfo *bufinfo, const uint8_t *src, int len, uint8_t *dest)
710 if (len == 0) return true;
712 if (smbcli_req_data_oob(bufinfo, src, len)) {
716 memcpy(dest, src, len);
722 put a NTTIME into a packet
724 void smbcli_push_nttime(void *base, uint16_t offset, NTTIME t)
726 SBVAL(base, offset, t);
730 pull a NTTIME from a packet
732 NTTIME smbcli_pull_nttime(void *base, uint16_t offset)
734 NTTIME ret = BVAL(base, offset);
739 pull a UCS2 string from a blob, returning a talloced unix string
741 the string length is limited by the 3 things:
742 - the data size in the blob
743 - the passed 'byte_len' if it is not -1
744 - the end of string (null termination)
746 Note that 'byte_len' is the number of bytes in the packet
748 on failure zero is returned and *dest is set to NULL, otherwise the number
749 of bytes consumed in the blob is returned
751 size_t smbcli_blob_pull_ucs2(TALLOC_CTX* mem_ctx,
752 const DATA_BLOB *blob, const char **dest,
753 const uint8_t *src, int byte_len, uint_t flags)
755 int src_len, src_len2, alignment=0;
759 if (src < blob->data ||
760 src >= (blob->data + blob->length)) {
765 src_len = blob->length - PTR_DIFF(src, blob->data);
767 if (byte_len != -1 && src_len > byte_len) {
771 if (!(flags & STR_NOALIGN) && ucs2_align(blob->data, src, flags)) {
782 src_len2 = utf16_len_n(src, src_len);
784 ret = convert_string_talloc(mem_ctx, lp_iconv_convenience(global_loadparm), CH_UTF16, CH_UNIX, src, src_len2, (void **)&dest2);
791 return src_len2 + alignment;
795 pull a ascii string from a blob, returning a talloced string
797 the string length is limited by the 3 things:
798 - the data size in the blob
799 - the passed 'byte_len' if it is not -1
800 - the end of string (null termination)
802 Note that 'byte_len' is the number of bytes in the blob
804 on failure zero is returned and *dest is set to NULL, otherwise the number
805 of bytes consumed in the blob is returned
807 static size_t smbcli_blob_pull_ascii(TALLOC_CTX *mem_ctx,
808 const DATA_BLOB *blob, const char **dest,
809 const uint8_t *src, int byte_len, uint_t flags)
811 int src_len, src_len2;
815 src_len = blob->length - PTR_DIFF(src, blob->data);
820 if (byte_len != -1 && src_len > byte_len) {
823 src_len2 = strnlen((const char *)src, src_len);
825 if (src_len2 < src_len - 1) {
826 /* include the termination if we didn't reach the end of the packet */
830 ret = convert_string_talloc(mem_ctx, lp_iconv_convenience(global_loadparm), CH_DOS, CH_UNIX, src, src_len2, (void **)&dest2);
842 pull a string from a blob, returning a talloced struct smb_wire_string
844 the string length is limited by the 3 things:
845 - the data size in the blob
846 - length field on the wire
847 - the end of string (null termination)
849 if STR_LEN8BIT is set in the flags then assume the length field is
850 8 bits, instead of 32
852 on failure zero is returned and dest->s is set to NULL, otherwise the number
853 of bytes consumed in the blob is returned
855 size_t smbcli_blob_pull_string(struct smbcli_session *session,
857 const DATA_BLOB *blob,
858 struct smb_wire_string *dest,
859 uint16_t len_offset, uint16_t str_offset,
865 if (!(flags & STR_ASCII)) {
866 /* this is here to cope with SMB2 calls using the SMB
867 parsers. SMB2 will pass smbcli_session==NULL, which forces
868 unicode on (as used by SMB2) */
869 if (session == NULL) {
870 flags |= STR_UNICODE;
871 } else if (session->transport->negotiate.capabilities & CAP_UNICODE) {
872 flags |= STR_UNICODE;
876 if (flags & STR_LEN8BIT) {
877 if (len_offset > blob->length-1) {
880 dest->private_length = CVAL(blob->data, len_offset);
882 if (len_offset > blob->length-4) {
885 dest->private_length = IVAL(blob->data, len_offset);
889 if (!(flags & STR_ASCII) && (flags & STR_UNICODE)) {
891 if ((str_offset&1) && !(flags & STR_NOALIGN)) {
894 if (flags & STR_LEN_NOTERM) {
897 return align + extra + smbcli_blob_pull_ucs2(mem_ctx, blob, &dest->s,
898 blob->data+str_offset+align,
899 dest->private_length, flags);
902 if (flags & STR_LEN_NOTERM) {
906 return extra + smbcli_blob_pull_ascii(mem_ctx, blob, &dest->s,
907 blob->data+str_offset, dest->private_length, flags);
911 pull a string from a blob, returning a talloced char *
913 Currently only used by the UNIX search info level.
915 the string length is limited by 2 things:
916 - the data size in the blob
917 - the end of string (null termination)
919 on failure zero is returned and dest->s is set to NULL, otherwise the number
920 of bytes consumed in the blob is returned
922 size_t smbcli_blob_pull_unix_string(struct smbcli_session *session,
932 if (!(flags & STR_ASCII) &&
933 ((flags & STR_UNICODE) ||
934 (session->transport->negotiate.capabilities & CAP_UNICODE))) {
936 if ((str_offset&1) && !(flags & STR_NOALIGN)) {
939 if (flags & STR_LEN_NOTERM) {
942 return align + extra + smbcli_blob_pull_ucs2(mem_ctx, blob, dest,
943 blob->data+str_offset+align,
947 if (flags & STR_LEN_NOTERM) {
951 return extra + smbcli_blob_pull_ascii(mem_ctx, blob, dest,
952 blob->data+str_offset, -1, flags);
957 append a string into a blob
959 size_t smbcli_blob_append_string(struct smbcli_session *session,
960 TALLOC_CTX *mem_ctx, DATA_BLOB *blob,
961 const char *str, uint_t flags)
968 /* determine string type to use */
969 if (!(flags & (STR_ASCII|STR_UNICODE))) {
970 flags |= (session->transport->negotiate.capabilities & CAP_UNICODE) ? STR_UNICODE : STR_ASCII;
973 max_len = (strlen(str)+2) * MAX_BYTES_PER_CHAR;
975 blob->data = talloc_realloc(mem_ctx, blob->data, uint8_t, blob->length + max_len);
980 len = push_string(lp_iconv_convenience(global_loadparm), blob->data + blob->length, str, max_len, flags);
988 pull a GUID structure from the wire. The buffer must be at least 16
991 enum ndr_err_code smbcli_pull_guid(void *base, uint16_t offset,
995 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
996 enum ndr_err_code ndr_err;
1000 blob.data = offset + (uint8_t *)base;
1002 ndr_err = ndr_pull_struct_blob(&blob, tmp_ctx, NULL, guid,
1003 (ndr_pull_flags_fn_t)ndr_pull_GUID);
1004 talloc_free(tmp_ctx);
1009 push a guid onto the wire. The buffer must hold 16 bytes
1011 enum ndr_err_code smbcli_push_guid(void *base, uint16_t offset,
1012 const struct GUID *guid)
1014 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
1015 enum ndr_err_code ndr_err;
1017 ndr_err = ndr_push_struct_blob(&blob, tmp_ctx, NULL,
1018 guid, (ndr_push_flags_fn_t)ndr_push_GUID);
1019 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err) || blob.length != 16) {
1020 talloc_free(tmp_ctx);
1023 memcpy(offset + (uint8_t *)base, blob.data, blob.length);
1024 talloc_free(tmp_ctx);