r2552: Character set conversion and string handling updates.
[Samba/gebeck_regimport.git] / source4 / libcli / raw / rawrequest.c
blob1ff36d0a8dc96956e45c2863868732bf362900a0
1 /*
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
26 #include "includes.h"
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)
37 NTSTATUS status;
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;
43 if (req->transport) {
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
50 simple way! */
51 status = req->status;
52 talloc_free(req);
53 return status;
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_named(NULL, sizeof(struct smbcli_request), "smcli_request");
66 if (!req) {
67 return NULL;
69 ZERO_STRUCTP(req);
71 /* setup the request context */
72 req->state = SMBCLI_REQUEST_INIT;
73 req->transport = transport;
74 req->session = NULL;
75 req->tree = NULL;
76 req->out.size = size;
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) {
83 return NULL;
86 SIVAL(req->out.buffer, 0, 0);
88 return req;
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;
106 req->out.wct = wct;
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);
120 /* assign a mid */
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);
132 return req;
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;
145 uint16_t flags2;
146 uint32_t capabilities;
148 req = smbcli_request_setup_transport(session->transport, command, wct, buflen);
150 if (!req) return NULL;
152 req->session = session;
154 flags2 = FLAGS2_LONG_PATH_COMPONENTS;
155 capabilities = session->transport->negotiate.capabilities;
157 if (capabilities & CAP_UNICODE) {
158 flags2 |= FLAGS2_UNICODE_STRINGS;
160 if (capabilities & CAP_STATUS32) {
161 flags2 |= FLAGS2_32_BIT_ERROR_CODES;
163 if (capabilities & CAP_EXTENDED_SECURITY) {
164 flags2 |= FLAGS2_EXTENDED_SECURITY;
166 if (session->transport->negotiate.sign_info.doing_signing) {
167 flags2 |= FLAGS2_SMB_SECURITY_SIGNATURES;
170 SSVAL(req->out.hdr, HDR_FLG2, flags2);
171 SSVAL(req->out.hdr, HDR_PID, session->pid & 0xFFFF);
172 SSVAL(req->out.hdr, HDR_PIDHIGH, session->pid >> 16);
173 SSVAL(req->out.hdr, HDR_UID, session->vuid);
175 return req;
179 setup a request for tree based commands
181 struct smbcli_request *smbcli_request_setup(struct smbcli_tree *tree,
182 uint8_t command,
183 uint_t wct, uint_t buflen)
185 struct smbcli_request *req;
187 req = smbcli_request_setup_session(tree->session, command, wct, buflen);
188 if (req) {
189 req->tree = tree;
190 SSVAL(req->out.hdr,HDR_TID,tree->tid);
192 return req;
196 grow the allocation of the data buffer portion of a reply
197 packet. Note that as this can reallocate the packet buffer this
198 invalidates any local pointers into the packet.
200 To cope with this req->out.ptr is supplied. This will be updated to
201 point at the same offset into the packet as before this call
203 static void smbcli_req_grow_allocation(struct smbcli_request *req, uint_t new_size)
205 int delta;
206 char *buf2;
208 delta = new_size - req->out.data_size;
209 if (delta + req->out.size <= req->out.allocated) {
210 /* it fits in the preallocation */
211 return;
214 /* we need to realloc */
215 req->out.allocated = req->out.size + delta + REQ_OVER_ALLOCATION;
216 buf2 = talloc_realloc(req->out.buffer, req->out.allocated);
217 if (buf2 == NULL) {
218 smb_panic("out of memory in req_grow_allocation");
221 if (buf2 == req->out.buffer) {
222 /* the malloc library gave us the same pointer */
223 return;
226 /* update the pointers into the packet */
227 req->out.data = buf2 + PTR_DIFF(req->out.data, req->out.buffer);
228 req->out.ptr = buf2 + PTR_DIFF(req->out.ptr, req->out.buffer);
229 req->out.vwv = buf2 + PTR_DIFF(req->out.vwv, req->out.buffer);
230 req->out.hdr = buf2 + PTR_DIFF(req->out.hdr, req->out.buffer);
232 req->out.buffer = buf2;
237 grow the data buffer portion of a reply packet. Note that as this
238 can reallocate the packet buffer this invalidates any local pointers
239 into the packet.
241 To cope with this req->out.ptr is supplied. This will be updated to
242 point at the same offset into the packet as before this call
244 void smbcli_req_grow_data(struct smbcli_request *req, uint_t new_size)
246 int delta;
248 smbcli_req_grow_allocation(req, new_size);
250 delta = new_size - req->out.data_size;
252 req->out.size += delta;
253 req->out.data_size += delta;
255 /* set the BCC to the new data size */
256 SSVAL(req->out.vwv, VWV(req->out.wct), new_size);
261 send a message
263 BOOL smbcli_request_send(struct smbcli_request *req)
265 if (IVAL(req->out.buffer, 0) == 0) {
266 _smb_setlen(req->out.buffer, req->out.size - NBT_HDR_SIZE);
269 smbcli_request_calculate_sign_mac(req);
271 smbcli_transport_send(req);
273 return True;
278 receive a response to a packet
280 BOOL smbcli_request_receive(struct smbcli_request *req)
282 /* req can be NULL when a send has failed. This eliminates lots of NULL
283 checks in each module */
284 if (!req) return False;
286 /* keep receiving packets until this one is replied to */
287 while (req->state <= SMBCLI_REQUEST_RECV) {
288 if (event_loop_once(req->transport->event.ctx) != 0) {
289 return False;
293 return req->state == SMBCLI_REQUEST_DONE;
298 receive another reply to a request - this is used for requests that
299 have multi-part replies (such as SMBtrans2)
301 BOOL smbcli_request_receive_more(struct smbcli_request *req)
303 req->state = SMBCLI_REQUEST_RECV;
304 DLIST_ADD(req->transport->pending_recv, req);
306 return smbcli_request_receive(req);
311 handle oplock break requests from the server - return True if the request was
312 an oplock break
314 BOOL handle_oplock_break(struct smbcli_transport *transport, uint_t len, const char *hdr, const char *vwv)
316 /* we must be very fussy about what we consider an oplock break to avoid
317 matching readbraw replies */
318 if (len != MIN_SMB_SIZE + VWV(8) + NBT_HDR_SIZE ||
319 (CVAL(hdr, HDR_FLG) & FLAG_REPLY) ||
320 CVAL(hdr,HDR_COM) != SMBlockingX ||
321 SVAL(hdr, HDR_MID) != 0xFFFF ||
322 SVAL(vwv,VWV(6)) != 0 ||
323 SVAL(vwv,VWV(7)) != 0) {
324 return False;
327 if (transport->oplock.handler) {
328 uint16_t tid = SVAL(hdr, HDR_TID);
329 uint16_t fnum = SVAL(vwv,VWV(2));
330 uint8_t level = CVAL(vwv,VWV(3)+1);
331 transport->oplock.handler(transport, tid, fnum, level, transport->oplock.private);
334 return True;
338 wait for a reply to be received for a packet that just returns an error
339 code and nothing more
341 NTSTATUS smbcli_request_simple_recv(struct smbcli_request *req)
343 smbcli_request_receive(req);
344 return smbcli_request_destroy(req);
348 /* Return true if the last packet was in error */
349 BOOL smbcli_request_is_error(struct smbcli_request *req)
351 return NT_STATUS_IS_ERR(req->status);
355 append a string into the data portion of the request packet
357 return the number of bytes added to the packet
359 size_t smbcli_req_append_string(struct smbcli_request *req, const char *str, uint_t flags)
361 size_t len;
363 /* determine string type to use */
364 if (!(flags & (STR_ASCII|STR_UNICODE))) {
365 flags |= (req->transport->negotiate.capabilities & CAP_UNICODE) ? STR_UNICODE : STR_ASCII;
368 len = (strlen(str)+2) * MAX_BYTES_PER_CHAR;
370 smbcli_req_grow_allocation(req, len + req->out.data_size);
372 len = push_string(req->out.data + req->out.data_size, str, len, flags);
374 smbcli_req_grow_data(req, len + req->out.data_size);
376 return len;
381 this is like smbcli_req_append_string but it also return the
382 non-terminated string byte length, which can be less than the number
383 of bytes consumed in the packet for 2 reasons:
385 1) the string in the packet may be null terminated
386 2) the string in the packet may need a 1 byte UCS2 alignment
388 this is used in places where the non-terminated string byte length is
389 placed in the packet as a separate field
391 size_t smbcli_req_append_string_len(struct smbcli_request *req, const char *str, uint_t flags, int *len)
393 int diff = 0;
394 size_t ret;
396 /* determine string type to use */
397 if (!(flags & (STR_ASCII|STR_UNICODE))) {
398 flags |= (req->transport->negotiate.capabilities & CAP_UNICODE) ? STR_UNICODE : STR_ASCII;
401 /* see if an alignment byte will be used */
402 if ((flags & STR_UNICODE) && !(flags & STR_NOALIGN)) {
403 diff = ucs2_align(NULL, req->out.data + req->out.data_size, flags);
406 /* do the hard work */
407 ret = smbcli_req_append_string(req, str, flags);
409 /* see if we need to subtract the termination */
410 if (flags & STR_TERMINATE) {
411 diff += (flags & STR_UNICODE) ? 2 : 1;
414 if (ret >= diff) {
415 (*len) = ret - diff;
416 } else {
417 (*len) = ret;
420 return ret;
425 push a string into the data portion of the request packet, growing it if necessary
426 this gets quite tricky - please be very careful to cover all cases when modifying this
428 if dest is NULL, then put the string at the end of the data portion of the packet
430 if dest_len is -1 then no limit applies
432 size_t smbcli_req_append_ascii4(struct smbcli_request *req, const char *str, uint_t flags)
434 size_t size;
435 smbcli_req_append_bytes(req, (const uint8_t *)"\4", 1);
436 size = smbcli_req_append_string(req, str, flags);
437 return size + 1;
442 push a blob into the data portion of the request packet, growing it if necessary
443 this gets quite tricky - please be very careful to cover all cases when modifying this
445 if dest is NULL, then put the blob at the end of the data portion of the packet
447 size_t smbcli_req_append_blob(struct smbcli_request *req, const DATA_BLOB *blob)
449 smbcli_req_grow_allocation(req, req->out.data_size + blob->length);
450 memcpy(req->out.data + req->out.data_size, blob->data, blob->length);
451 smbcli_req_grow_data(req, req->out.data_size + blob->length);
452 return blob->length;
456 append raw bytes into the data portion of the request packet
457 return the number of bytes added
459 size_t smbcli_req_append_bytes(struct smbcli_request *req, const uint8_t *bytes, size_t byte_len)
461 smbcli_req_grow_allocation(req, byte_len + req->out.data_size);
462 memcpy(req->out.data + req->out.data_size, bytes, byte_len);
463 smbcli_req_grow_data(req, byte_len + req->out.data_size);
464 return byte_len;
468 append variable block (type 5 buffer) into the data portion of the request packet
469 return the number of bytes added
471 size_t smbcli_req_append_var_block(struct smbcli_request *req, const uint8_t *bytes, uint16_t byte_len)
473 smbcli_req_grow_allocation(req, byte_len + 3 + req->out.data_size);
474 SCVAL(req->out.data + req->out.data_size, 0, 5);
475 SSVAL(req->out.data + req->out.data_size, 1, byte_len); /* add field length */
476 if (byte_len > 0) {
477 memcpy(req->out.data + req->out.data_size + 3, bytes, byte_len);
479 smbcli_req_grow_data(req, byte_len + 3 + req->out.data_size);
480 return byte_len + 3;
485 pull a UCS2 string from a request packet, returning a talloced unix string
487 the string length is limited by the 3 things:
488 - the data size in the request (end of packet)
489 - the passed 'byte_len' if it is not -1
490 - the end of string (null termination)
492 Note that 'byte_len' is the number of bytes in the packet
494 on failure zero is returned and *dest is set to NULL, otherwise the number
495 of bytes consumed in the packet is returned
497 static size_t smbcli_req_pull_ucs2(struct smbcli_request *req, TALLOC_CTX *mem_ctx,
498 char **dest, const char *src, int byte_len, uint_t flags)
500 int src_len, src_len2, alignment=0;
501 ssize_t ret;
503 if (!(flags & STR_NOALIGN) && ucs2_align(req->in.buffer, src, flags)) {
504 src++;
505 alignment=1;
506 if (byte_len != -1) {
507 byte_len--;
511 src_len = req->in.data_size - PTR_DIFF(src, req->in.data);
512 if (src_len < 0) {
513 *dest = NULL;
514 return 0;
516 if (byte_len != -1 && src_len > byte_len) {
517 src_len = byte_len;
520 src_len2 = strnlen_w((const smb_ucs2_t *)src, src_len/2) * 2;
521 if (src_len2 < src_len - 2) {
522 /* include the termination if we didn't reach the end of the packet */
523 src_len2 += 2;
526 /* ucs2 strings must be at least 2 bytes long */
527 if (src_len2 < 2) {
528 *dest = NULL;
529 return 0;
532 ret = convert_string_talloc(mem_ctx, CH_UTF16, CH_UNIX, src, src_len2, (void **)dest);
533 if (ret == -1) {
534 *dest = NULL;
535 return 0;
538 return src_len2 + alignment;
542 pull a ascii string from a request packet, returning a talloced string
544 the string length is limited by the 3 things:
545 - the data size in the request (end of packet)
546 - the passed 'byte_len' if it is not -1
547 - the end of string (null termination)
549 Note that 'byte_len' is the number of bytes in the packet
551 on failure zero is returned and *dest is set to NULL, otherwise the number
552 of bytes consumed in the packet is returned
554 size_t smbcli_req_pull_ascii(struct smbcli_request *req, TALLOC_CTX *mem_ctx,
555 char **dest, const char *src, int byte_len, uint_t flags)
557 int src_len, src_len2;
558 ssize_t ret;
560 src_len = req->in.data_size - PTR_DIFF(src, req->in.data);
561 if (src_len < 0) {
562 *dest = NULL;
563 return 0;
565 if (byte_len != -1 && src_len > byte_len) {
566 src_len = byte_len;
568 src_len2 = strnlen(src, src_len);
569 if (src_len2 < src_len - 1) {
570 /* include the termination if we didn't reach the end of the packet */
571 src_len2++;
574 ret = convert_string_talloc(mem_ctx, CH_DOS, CH_UNIX, src, src_len2, (void **)dest);
576 if (ret == -1) {
577 *dest = NULL;
578 return 0;
581 return ret;
585 pull a string from a request packet, returning a talloced string
587 the string length is limited by the 3 things:
588 - the data size in the request (end of packet)
589 - the passed 'byte_len' if it is not -1
590 - the end of string (null termination)
592 Note that 'byte_len' is the number of bytes in the packet
594 on failure zero is returned and *dest is set to NULL, otherwise the number
595 of bytes consumed in the packet is returned
597 size_t smbcli_req_pull_string(struct smbcli_request *req, TALLOC_CTX *mem_ctx,
598 char **dest, const char *src, int byte_len, uint_t flags)
600 if (!(flags & STR_ASCII) &&
601 (((flags & STR_UNICODE) || (req->flags2 & FLAGS2_UNICODE_STRINGS)))) {
602 return smbcli_req_pull_ucs2(req, mem_ctx, dest, src, byte_len, flags);
605 return smbcli_req_pull_ascii(req, mem_ctx, dest, src, byte_len, flags);
610 pull a DATA_BLOB from a reply packet, returning a talloced blob
611 make sure we don't go past end of packet
613 if byte_len is -1 then limit the blob only by packet size
615 DATA_BLOB smbcli_req_pull_blob(struct smbcli_request *req, TALLOC_CTX *mem_ctx, const char *src, int byte_len)
617 int src_len;
619 src_len = req->in.data_size - PTR_DIFF(src, req->in.data);
621 if (src_len < 0) {
622 return data_blob(NULL, 0);
625 if (byte_len != -1 && src_len > byte_len) {
626 src_len = byte_len;
629 return data_blob_talloc(mem_ctx, src, src_len);
632 /* check that a lump of data in a request is within the bounds of the data section of
633 the packet */
634 static BOOL smbcli_req_data_oob(struct smbcli_request *req, const char *ptr, uint32_t count)
636 /* be careful with wraparound! */
637 if (ptr < req->in.data ||
638 ptr >= req->in.data + req->in.data_size ||
639 count > req->in.data_size ||
640 ptr + count > req->in.data + req->in.data_size) {
641 return True;
643 return False;
647 pull a lump of data from a request packet
649 return False if any part is outside the data portion of the packet
651 BOOL smbcli_raw_pull_data(struct smbcli_request *req, const char *src, int len, char *dest)
653 if (len == 0) return True;
655 if (smbcli_req_data_oob(req, src, len)) {
656 return False;
659 memcpy(dest, src, len);
660 return True;
665 put a NTTIME into a packet
667 void smbcli_push_nttime(void *base, uint16_t offset, NTTIME t)
669 SBVAL(base, offset, t);
673 pull a NTTIME from a packet
675 NTTIME smbcli_pull_nttime(void *base, uint16_t offset)
677 NTTIME ret = BVAL(base, offset);
678 return ret;
682 pull a UCS2 string from a blob, returning a talloced unix string
684 the string length is limited by the 3 things:
685 - the data size in the blob
686 - the passed 'byte_len' if it is not -1
687 - the end of string (null termination)
689 Note that 'byte_len' is the number of bytes in the packet
691 on failure zero is returned and *dest is set to NULL, otherwise the number
692 of bytes consumed in the blob is returned
694 static size_t smbcli_blob_pull_ucs2(TALLOC_CTX* mem_ctx,
695 DATA_BLOB *blob, const char **dest,
696 const char *src, int byte_len, uint_t flags)
698 int src_len, src_len2, alignment=0;
699 ssize_t ret;
700 char *dest2;
702 if (src < (const char *)blob->data ||
703 src >= (const char *)(blob->data + blob->length)) {
704 *dest = NULL;
705 return 0;
708 src_len = blob->length - PTR_DIFF(src, blob->data);
710 if (byte_len != -1 && src_len > byte_len) {
711 src_len = byte_len;
714 if (!(flags & STR_NOALIGN) && ucs2_align(blob->data, src, flags)) {
715 src++;
716 alignment=1;
717 src_len--;
720 if (src_len < 2) {
721 *dest = NULL;
722 return 0;
725 src_len2 = strnlen_w((const smb_ucs2_t *)src, src_len/2) * 2;
727 if (src_len2 < src_len - 2) {
728 /* include the termination if we didn't reach the end of the packet */
729 src_len2 += 2;
732 ret = convert_string_talloc(mem_ctx, CH_UTF16, CH_UNIX, src, src_len2, (void **)&dest2);
733 if (ret == -1) {
734 *dest = NULL;
735 return 0;
737 *dest = dest2;
739 return src_len2 + alignment;
743 pull a ascii string from a blob, returning a talloced string
745 the string length is limited by the 3 things:
746 - the data size in the blob
747 - the passed 'byte_len' if it is not -1
748 - the end of string (null termination)
750 Note that 'byte_len' is the number of bytes in the blob
752 on failure zero is returned and *dest is set to NULL, otherwise the number
753 of bytes consumed in the blob is returned
755 static size_t smbcli_blob_pull_ascii(TALLOC_CTX *mem_ctx,
756 DATA_BLOB *blob, const char **dest,
757 const char *src, int byte_len, uint_t flags)
759 int src_len, src_len2;
760 ssize_t ret;
761 char *dest2;
763 src_len = blob->length - PTR_DIFF(src, blob->data);
764 if (src_len < 0) {
765 *dest = NULL;
766 return 0;
768 if (byte_len != -1 && src_len > byte_len) {
769 src_len = byte_len;
771 src_len2 = strnlen(src, src_len);
773 if (src_len2 < src_len - 1) {
774 /* include the termination if we didn't reach the end of the packet */
775 src_len2++;
778 ret = convert_string_talloc(mem_ctx, CH_DOS, CH_UNIX, src, src_len2, (void **)&dest2);
780 if (ret == -1) {
781 *dest = NULL;
782 return 0;
784 *dest = dest2;
786 return ret;
790 pull a string from a blob, returning a talloced WIRE_STRING
792 the string length is limited by the 3 things:
793 - the data size in the blob
794 - length field on the wire
795 - the end of string (null termination)
797 if STR_LEN8BIT is set in the flags then assume the length field is
798 8 bits, instead of 32
800 on failure zero is returned and dest->s is set to NULL, otherwise the number
801 of bytes consumed in the blob is returned
803 size_t smbcli_blob_pull_string(struct smbcli_session *session,
804 TALLOC_CTX *mem_ctx,
805 DATA_BLOB *blob,
806 WIRE_STRING *dest,
807 uint16_t len_offset, uint16_t str_offset,
808 uint_t flags)
810 int extra;
811 dest->s = NULL;
813 if (flags & STR_LEN8BIT) {
814 if (len_offset > blob->length-1) {
815 return 0;
817 dest->private_length = CVAL(blob->data, len_offset);
818 } else {
819 if (len_offset > blob->length-4) {
820 return 0;
822 dest->private_length = IVAL(blob->data, len_offset);
824 extra = 0;
825 dest->s = NULL;
826 if (!(flags & STR_ASCII) &&
827 ((flags & STR_UNICODE) ||
828 (session->transport->negotiate.capabilities & CAP_UNICODE))) {
829 int align = 0;
830 if ((str_offset&1) && !(flags & STR_NOALIGN)) {
831 align = 1;
833 if (flags & STR_LEN_NOTERM) {
834 extra = 2;
836 return align + extra + smbcli_blob_pull_ucs2(mem_ctx, blob, &dest->s,
837 blob->data+str_offset+align,
838 dest->private_length, flags);
841 if (flags & STR_LEN_NOTERM) {
842 extra = 1;
845 return extra + smbcli_blob_pull_ascii(mem_ctx, blob, &dest->s,
846 blob->data+str_offset, dest->private_length, flags);
850 pull a string from a blob, returning a talloced char *
852 Currently only used by the UNIX search info level.
854 the string length is limited by 2 things:
855 - the data size in the blob
856 - the end of string (null termination)
858 on failure zero is returned and dest->s is set to NULL, otherwise the number
859 of bytes consumed in the blob is returned
861 size_t smbcli_blob_pull_unix_string(struct smbcli_session *session,
862 TALLOC_CTX *mem_ctx,
863 DATA_BLOB *blob,
864 const char **dest,
865 uint16_t str_offset,
866 uint_t flags)
868 int extra = 0;
869 *dest = NULL;
871 if (!(flags & STR_ASCII) &&
872 ((flags & STR_UNICODE) ||
873 (session->transport->negotiate.capabilities & CAP_UNICODE))) {
874 int align = 0;
875 if ((str_offset&1) && !(flags & STR_NOALIGN)) {
876 align = 1;
878 if (flags & STR_LEN_NOTERM) {
879 extra = 2;
881 return align + extra + smbcli_blob_pull_ucs2(mem_ctx, blob, dest,
882 blob->data+str_offset+align,
883 -1, flags);
886 if (flags & STR_LEN_NOTERM) {
887 extra = 1;
890 return extra + smbcli_blob_pull_ascii(mem_ctx, blob, dest,
891 blob->data+str_offset, -1, flags);
896 append a string into a blob
898 size_t smbcli_blob_append_string(struct smbcli_session *session,
899 TALLOC_CTX *mem_ctx, DATA_BLOB *blob,
900 const char *str, uint_t flags)
902 size_t max_len;
903 int len;
905 if (!str) return 0;
907 /* determine string type to use */
908 if (!(flags & (STR_ASCII|STR_UNICODE))) {
909 flags |= (session->transport->negotiate.capabilities & CAP_UNICODE) ? STR_UNICODE : STR_ASCII;
912 max_len = (strlen(str)+2) * MAX_BYTES_PER_CHAR;
914 blob->data = talloc_realloc(blob->data, blob->length + max_len);
915 if (!blob->data) {
916 return 0;
919 len = push_string(blob->data + blob->length, str, max_len, flags);
921 blob->length += len;
923 return len;