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 cli_request' structure in libsmb
28 /* we over allocate the data buffer to prevent too many realloc calls */
29 #define REQ_OVER_ALLOCATION 256
31 /* assume that a character will not consume more than 3 bytes per char */
32 #define MAX_BYTES_PER_CHAR 3
34 /* destroy a request structure and return final status */
35 NTSTATUS cli_request_destroy(struct cli_request *req)
39 /* this is the error code we give the application for when a
40 _send() call fails completely */
41 if (!req) return NT_STATUS_UNSUCCESSFUL;
43 /* remove it from the list of pending requests (a null op if
44 its not in the list) */
45 DLIST_REMOVE(req->transport->pending_requests, req);
47 /* ahh, its so nice to destroy a complex structure in such a
50 talloc_destroy(req->mem_ctx);
56 low-level function to setup a request buffer for a non-SMB packet
57 at the transport level
59 struct cli_request *cli_request_setup_nonsmb(struct cli_transport *transport, uint_t size)
61 struct cli_request *req;
64 /* each request gets its own talloc context. The request
65 structure itself is also allocated inside this context,
66 so we need to allocate it before we construct the request
68 mem_ctx = talloc_init("cli_request");
73 req = talloc(mem_ctx, sizeof(struct cli_request));
79 /* setup the request context */
80 req->mem_ctx = mem_ctx;
81 req->transport = transport;
86 /* over allocate by a small amount */
87 req->out.allocated = req->out.size + REQ_OVER_ALLOCATION;
89 req->out.buffer = talloc(req->mem_ctx, req->out.allocated);
90 if (!req->out.buffer) {
94 SIVAL(req->out.buffer, 0, 0);
101 setup a SMB packet at transport level
103 struct cli_request *cli_request_setup_transport(struct cli_transport *transport,
104 uint8 command, unsigned wct, unsigned buflen)
106 struct cli_request *req;
108 req = cli_request_setup_nonsmb(transport, NBT_HDR_SIZE + MIN_SMB_SIZE + wct*2 + buflen);
110 if (!req) return NULL;
112 req->out.hdr = req->out.buffer + NBT_HDR_SIZE;
113 req->out.vwv = req->out.hdr + HDR_VWV;
115 req->out.data = req->out.vwv + VWV(wct) + 2;
116 req->out.data_size = buflen;
117 req->out.ptr = req->out.data;
119 SCVAL(req->out.hdr, HDR_WCT, wct);
120 SSVAL(req->out.vwv, VWV(wct), buflen);
122 memcpy(req->out.hdr, "\377SMB", 4);
123 SCVAL(req->out.hdr,HDR_COM,command);
125 SCVAL(req->out.hdr,HDR_FLG, FLAG_CASELESS_PATHNAMES);
126 SSVAL(req->out.hdr,HDR_FLG2, 0);
129 req->mid = cli_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 cli_request_send() to send the reply on its
147 way. This interface is used before a session is setup.
149 struct cli_request *cli_request_setup_session(struct cli_session *session,
150 uint8 command, unsigned wct, unsigned buflen)
152 struct cli_request *req;
156 req = cli_request_setup_transport(session->transport, command, wct, buflen);
158 if (!req) return NULL;
160 req->session = session;
162 flags2 = FLAGS2_LONG_PATH_COMPONENTS;
163 capabilities = session->transport->negotiate.capabilities;
165 if (capabilities & CAP_UNICODE) {
166 flags2 |= FLAGS2_UNICODE_STRINGS;
168 if (capabilities & CAP_STATUS32) {
169 flags2 |= FLAGS2_32_BIT_ERROR_CODES;
171 if (capabilities & CAP_EXTENDED_SECURITY) {
172 flags2 |= FLAGS2_EXTENDED_SECURITY;
174 if (session->transport->negotiate.sign_info.doing_signing) {
175 flags2 |= FLAGS2_SMB_SECURITY_SIGNATURES;
178 SSVAL(req->out.hdr, HDR_FLG2, flags2);
179 SSVAL(req->out.hdr, HDR_PID, session->pid & 0xFFFF);
180 SSVAL(req->out.hdr, HDR_PIDHIGH, session->pid >> 16);
181 SSVAL(req->out.hdr, HDR_UID, session->vuid);
187 setup a request for tree based commands
189 struct cli_request *cli_request_setup(struct cli_tree *tree,
191 unsigned wct, unsigned buflen)
193 struct cli_request *req;
195 req = cli_request_setup_session(tree->session, command, wct, buflen);
198 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 cli_req_grow_allocation(struct cli_request *req, unsigned 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->mem_ctx, req->out.buffer, 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 cli_req_grow_data(struct cli_request *req, unsigned new_size)
256 cli_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);
270 BOOL cli_request_send(struct cli_request *req)
272 if (IVAL(req->out.buffer, 0) == 0) {
273 _smb_setlen(req->out.buffer, req->out.size - NBT_HDR_SIZE);
276 cli_request_calculate_sign_mac(req);
278 if (req->out.size != cli_sock_write(req->transport->socket, req->out.buffer, req->out.size)) {
279 req->transport->error.etype = ETYPE_SOCKET;
280 req->transport->error.e.socket_error = SOCKET_WRITE_ERROR;
281 DEBUG(0,("Error writing %d bytes to server - %s\n",
282 (int)req->out.size, strerror(errno)));
286 /* add it to the list of pending requests */
287 DLIST_ADD(req->transport->pending_requests, req);
294 receive a response to a packet
296 BOOL cli_request_receive(struct cli_request *req)
298 /* req can be NULL when a send has failed. This eliminates lots of NULL
299 checks in each module */
300 if (!req) return False;
302 /* keep receiving packets until this one is replied to */
303 while (!req->in.buffer) {
304 if (!cli_transport_select(req->transport)) {
308 cli_request_receive_next(req->transport);
316 handle oplock break requests from the server - return True if the request was
319 static BOOL handle_oplock_break(struct cli_transport *transport, uint_t len, const char *hdr, const char *vwv)
321 /* we must be very fussy about what we consider an oplock break to avoid
322 matching readbraw replies */
323 if (len != MIN_SMB_SIZE + VWV(8) ||
324 (CVAL(hdr, HDR_FLG) & FLAG_REPLY) ||
325 CVAL(hdr,HDR_COM) != SMBlockingX ||
326 SVAL(hdr, HDR_MID) != 0xFFFF ||
327 SVAL(vwv,VWV(6)) != 0 ||
328 SVAL(vwv,VWV(7)) != 0) {
332 if (transport->oplock.handler) {
333 uint16 tid = SVAL(hdr, HDR_TID);
334 uint16 fnum = SVAL(vwv,VWV(2));
335 uint8 level = CVAL(vwv,VWV(3));
336 transport->oplock.handler(transport, tid, fnum, level, transport->oplock.private);
344 receive an async message from the server
345 this function assumes that the caller already knows that the socket is readable
346 and that there is a packet waiting
348 The packet is not actually returned by this function, instead any
349 registered async message handlers are called
351 return True if a packet was successfully received and processed
352 return False if the socket appears to be dead
354 BOOL cli_request_receive_next(struct cli_transport *transport)
358 char header[NBT_HDR_SIZE];
359 char *buffer, *hdr, *vwv;
361 struct cli_request *req;
364 len = cli_sock_read(transport->socket, header, 4);
369 len = smb_len(header);
371 mem_ctx = talloc_init("cli_request_receive_next");
373 /* allocate the incoming buffer at the right size */
374 buffer = talloc(mem_ctx, len+NBT_HDR_SIZE);
376 talloc_destroy(mem_ctx);
380 /* fill in the already received header */
381 memcpy(buffer, header, NBT_HDR_SIZE);
383 ret = cli_sock_read(transport->socket, buffer + NBT_HDR_SIZE, len);
384 /* If the server is not responding, note that now */
389 hdr = buffer+NBT_HDR_SIZE;
392 /* see if it could be an oplock break request */
393 if (handle_oplock_break(transport, len, hdr, vwv)) {
397 /* at this point we need to check for a readbraw reply, as these can be any length */
398 if (transport->readbraw_pending) {
399 transport->readbraw_pending = 0;
401 /* it must match the first entry in the pending queue as the client is not allowed
402 to have outstanding readbraw requests */
403 req = transport->pending_requests;
406 req->in.buffer = buffer;
407 talloc_steal(mem_ctx, req->mem_ctx, buffer);
408 req->in.size = len + NBT_HDR_SIZE;
409 req->in.allocated = req->in.size;
413 if (len >= MIN_SMB_SIZE) {
414 /* extract the mid for matching to pending requests */
415 mid = SVAL(hdr, HDR_MID);
416 wct = CVAL(hdr, HDR_WCT);
419 /* match the incoming request against the list of pending requests */
420 for (req=transport->pending_requests; req; req=req->next) {
421 if (req->mid == mid) break;
425 DEBUG(3,("Discarding unmatched reply with mid %d\n", mid));
429 /* fill in the 'in' portion of the matching request */
430 req->in.buffer = buffer;
431 talloc_steal(mem_ctx, req->mem_ctx, buffer);
432 req->in.size = len + NBT_HDR_SIZE;
433 req->in.allocated = req->in.size;
435 /* handle non-SMB replies */
436 if (req->in.size < NBT_HDR_SIZE + MIN_SMB_SIZE) {
440 if (req->in.size < NBT_HDR_SIZE + MIN_SMB_SIZE + VWV(wct)) {
441 DEBUG(2,("bad reply size for mid %d\n", mid));
442 req->status = NT_STATUS_UNSUCCESSFUL;
449 if (req->in.size >= NBT_HDR_SIZE + MIN_SMB_SIZE + VWV(wct)) {
450 req->in.data = req->in.vwv + VWV(wct) + 2;
451 req->in.data_size = SVAL(req->in.vwv, VWV(wct));
452 if (req->in.size < NBT_HDR_SIZE + MIN_SMB_SIZE + VWV(wct) + req->in.data_size) {
453 DEBUG(3,("bad data size for mid %d\n", mid));
454 /* blergh - w2k3 gives a bogus data size values in some
456 req->in.data_size = req->in.size - (NBT_HDR_SIZE + MIN_SMB_SIZE + VWV(wct));
459 req->in.ptr = req->in.data;
460 req->flags2 = SVAL(req->in.hdr, HDR_FLG2);
462 if (!(req->flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
463 transport->error.etype = ETYPE_DOS;
464 transport->error.e.dos.eclass = CVAL(req->in.hdr,HDR_RCLS);
465 transport->error.e.dos.ecode = SVAL(req->in.hdr,HDR_ERR);
466 req->status = dos_to_ntstatus(transport->error.e.dos.eclass,
467 transport->error.e.dos.ecode);
469 transport->error.etype = ETYPE_NT;
470 transport->error.e.nt_status = NT_STATUS(IVAL(req->in.hdr, HDR_RCLS));
471 req->status = transport->error.e.nt_status;
474 if (!cli_request_check_sign_mac(req)) {
475 transport->error.etype = ETYPE_SOCKET;
476 transport->error.e.socket_error = SOCKET_READ_BAD_SIG;
481 /* if this request has an async handler then call that to
482 notify that the reply has been received. This might destroy
483 the request so it must happen last */
489 talloc_destroy(mem_ctx);
495 wait for a reply to be received for a packet that just returns an error
496 code and nothing more
498 NTSTATUS cli_request_simple_recv(struct cli_request *req)
500 cli_request_receive(req);
501 return cli_request_destroy(req);
505 /* Return true if the last packet was in error */
506 BOOL cli_request_is_error(struct cli_request *req)
508 return NT_STATUS_IS_ERR(req->status);
512 append a string into the data portion of the request packet
514 return the number of bytes added to the packet
516 size_t cli_req_append_string(struct cli_request *req, const char *str, unsigned flags)
520 /* determine string type to use */
521 if (!(flags & (STR_ASCII|STR_UNICODE))) {
522 flags |= (req->transport->negotiate.capabilities & CAP_UNICODE) ? STR_UNICODE : STR_ASCII;
525 len = (strlen(str)+2) * MAX_BYTES_PER_CHAR;
527 cli_req_grow_allocation(req, len + req->out.data_size);
529 len = push_string(NULL, req->out.data + req->out.data_size, str, len, flags);
531 cli_req_grow_data(req, len + req->out.data_size);
537 this is like cli_req_append_string but it also return the
538 non-terminated string byte length, which can be less than the number
539 of bytes consumed in the packet for 2 reasons:
541 1) the string in the packet may be null terminated
542 2) the string in the packet may need a 1 byte UCS2 alignment
544 this is used in places where the non-terminated string byte length is
545 placed in the packet as a separate field
547 size_t cli_req_append_string_len(struct cli_request *req, const char *str, unsigned flags, int *len)
552 /* determine string type to use */
553 if (!(flags & (STR_ASCII|STR_UNICODE))) {
554 flags |= (req->transport->negotiate.capabilities & CAP_UNICODE) ? STR_UNICODE : STR_ASCII;
557 /* see if an alignment byte will be used */
558 if ((flags & STR_UNICODE) && !(flags & STR_NOALIGN)) {
559 diff = ucs2_align(NULL, req->out.data + req->out.data_size, flags);
562 /* do the hard work */
563 ret = cli_req_append_string(req, str, flags);
565 /* see if we need to subtract the termination */
566 if (flags & STR_TERMINATE) {
567 diff += (flags & STR_UNICODE) ? 2 : 1;
581 push a string into the data portion of the request packet, growing it if necessary
582 this gets quite tricky - please be very careful to cover all cases when modifying this
584 if dest is NULL, then put the string at the end of the data portion of the packet
586 if dest_len is -1 then no limit applies
588 size_t cli_req_append_ascii4(struct cli_request *req, const char *str, unsigned flags)
591 cli_req_append_bytes(req, (const uint8 *)"\4", 1);
592 size = cli_req_append_string(req, str, flags);
598 push a blob into the data portion of the request packet, growing it if necessary
599 this gets quite tricky - please be very careful to cover all cases when modifying this
601 if dest is NULL, then put the blob at the end of the data portion of the packet
603 size_t cli_req_append_blob(struct cli_request *req, const DATA_BLOB *blob)
605 cli_req_grow_allocation(req, req->out.data_size + blob->length);
606 memcpy(req->out.data + req->out.data_size, blob->data, blob->length);
607 cli_req_grow_data(req, req->out.data_size + blob->length);
612 append raw bytes into the data portion of the request packet
613 return the number of bytes added
615 size_t cli_req_append_bytes(struct cli_request *req, const uint8 *bytes, size_t byte_len)
617 cli_req_grow_allocation(req, byte_len + req->out.data_size);
618 memcpy(req->out.data + req->out.data_size, bytes, byte_len);
619 cli_req_grow_data(req, byte_len + req->out.data_size);
624 append variable block (type 5 buffer) into the data portion of the request packet
625 return the number of bytes added
627 size_t cli_req_append_var_block(struct cli_request *req, const uint8 *bytes, uint16 byte_len)
629 cli_req_grow_allocation(req, byte_len + 3 + req->out.data_size);
630 SCVAL(req->out.data + req->out.data_size, 0, 5);
631 SSVAL(req->out.data + req->out.data_size, 1, byte_len); /* add field length */
633 memcpy(req->out.data + req->out.data_size + 3, bytes, byte_len);
635 cli_req_grow_data(req, byte_len + 3 + req->out.data_size);
641 pull a UCS2 string from a request packet, returning a talloced unix string
643 the string length is limited by the 3 things:
644 - the data size in the request (end of packet)
645 - the passed 'byte_len' if it is not -1
646 - the end of string (null termination)
648 Note that 'byte_len' is the number of bytes in the packet
650 on failure zero is returned and *dest is set to NULL, otherwise the number
651 of bytes consumed in the packet is returned
653 static size_t cli_req_pull_ucs2(struct cli_request *req, TALLOC_CTX *mem_ctx,
654 char **dest, const char *src, int byte_len, unsigned flags)
656 int src_len, src_len2, alignment=0;
659 if (!(flags & STR_NOALIGN) && ucs2_align(req->in.buffer, src, flags)) {
662 if (byte_len != -1) {
667 src_len = req->in.data_size - PTR_DIFF(src, req->in.data);
672 if (byte_len != -1 && src_len > byte_len) {
676 src_len2 = strnlen_w((const smb_ucs2_t *)src, src_len/2) * 2;
677 if (src_len2 < src_len - 2) {
678 /* include the termination if we didn't reach the end of the packet */
682 /* ucs2 strings must be at least 2 bytes long */
688 ret = convert_string_talloc(mem_ctx, CH_UCS2, CH_UNIX, src, src_len2, (const void **)dest);
694 return src_len2 + alignment;
698 pull a ascii string from a request packet, returning a talloced string
700 the string length is limited by the 3 things:
701 - the data size in the request (end of packet)
702 - the passed 'byte_len' if it is not -1
703 - the end of string (null termination)
705 Note that 'byte_len' is the number of bytes in the packet
707 on failure zero is returned and *dest is set to NULL, otherwise the number
708 of bytes consumed in the packet is returned
710 size_t cli_req_pull_ascii(struct cli_request *req, TALLOC_CTX *mem_ctx,
711 char **dest, const char *src, int byte_len, unsigned flags)
713 int src_len, src_len2;
716 src_len = req->in.data_size - PTR_DIFF(src, req->in.data);
721 if (byte_len != -1 && src_len > byte_len) {
724 src_len2 = strnlen(src, src_len);
725 if (src_len2 < src_len - 1) {
726 /* include the termination if we didn't reach the end of the packet */
730 ret = convert_string_talloc(mem_ctx, CH_DOS, CH_UNIX, src, src_len2, (const void **)dest);
741 pull a string from a request packet, returning a talloced string
743 the string length is limited by the 3 things:
744 - the data size in the request (end of packet)
745 - the passed 'byte_len' if it is not -1
746 - the end of string (null termination)
748 Note that 'byte_len' is the number of bytes in the packet
750 on failure zero is returned and *dest is set to NULL, otherwise the number
751 of bytes consumed in the packet is returned
753 size_t cli_req_pull_string(struct cli_request *req, TALLOC_CTX *mem_ctx,
754 char **dest, const char *src, int byte_len, unsigned flags)
756 if (!(flags & STR_ASCII) &&
757 (((flags & STR_UNICODE) || (req->flags2 & FLAGS2_UNICODE_STRINGS)))) {
758 return cli_req_pull_ucs2(req, mem_ctx, dest, src, byte_len, flags);
761 return cli_req_pull_ascii(req, mem_ctx, dest, src, byte_len, flags);
766 pull a DATA_BLOB from a reply packet, returning a talloced blob
767 make sure we don't go past end of packet
769 if byte_len is -1 then limit the blob only by packet size
771 DATA_BLOB cli_req_pull_blob(struct cli_request *req, TALLOC_CTX *mem_ctx, const char *src, int byte_len)
775 src_len = req->in.data_size - PTR_DIFF(src, req->in.data);
778 return data_blob(NULL, 0);
781 if (byte_len != -1 && src_len > byte_len) {
785 return data_blob_talloc(mem_ctx, src, src_len);
788 /* check that a lump of data in a request is within the bounds of the data section of
790 static BOOL cli_req_data_oob(struct cli_request *req, const char *ptr, uint32 count)
792 /* be careful with wraparound! */
793 if (ptr < req->in.data ||
794 ptr >= req->in.data + req->in.data_size ||
795 count > req->in.data_size ||
796 ptr + count > req->in.data + req->in.data_size) {
803 pull a lump of data from a request packet
805 return False if any part is outside the data portion of the packet
807 BOOL cli_raw_pull_data(struct cli_request *req, const char *src, int len, char *dest)
809 if (len == 0) return True;
811 if (cli_req_data_oob(req, src, len)) {
815 memcpy(dest, src, len);
821 put a NTTIME into a packet
824 void cli_push_nttime(void *base, uint16 offset, NTTIME *t)
826 SIVAL(base, offset, t->low);
827 SIVAL(base, offset+4, t->high);
831 pull a NTTIME from a packet
833 NTTIME cli_pull_nttime(void *base, uint16 offset)
836 ret.low = IVAL(base, offset);
837 ret.high = IVAL(base, offset+4);
842 pull a UCS2 string from a blob, returning a talloced unix string
844 the string length is limited by the 3 things:
845 - the data size in the blob
846 - the passed 'byte_len' if it is not -1
847 - the end of string (null termination)
849 Note that 'byte_len' is the number of bytes in the packet
851 on failure zero is returned and *dest is set to NULL, otherwise the number
852 of bytes consumed in the blob is returned
854 static size_t cli_blob_pull_ucs2(TALLOC_CTX* mem_ctx,
855 DATA_BLOB *blob, const char **dest,
856 const char *src, int byte_len, unsigned flags)
858 int src_len, src_len2, alignment=0;
861 if (src < (const char *)blob->data ||
862 src >= (const char *)(blob->data + blob->length)) {
867 src_len = blob->length - PTR_DIFF(src, blob->data);
869 if (byte_len != -1 && src_len > byte_len) {
873 if (!(flags & STR_NOALIGN) && ucs2_align(blob->data, src, flags)) {
884 src_len2 = strnlen_w((const smb_ucs2_t *)src, src_len/2) * 2;
886 if (src_len2 < src_len - 2) {
887 /* include the termination if we didn't reach the end of the packet */
891 ret = convert_string_talloc(mem_ctx, CH_UCS2, CH_UNIX, src, src_len2, (const void **)dest);
897 return src_len2 + alignment;
901 pull a ascii string from a blob, returning a talloced string
903 the string length is limited by the 3 things:
904 - the data size in the blob
905 - the passed 'byte_len' if it is not -1
906 - the end of string (null termination)
908 Note that 'byte_len' is the number of bytes in the blob
910 on failure zero is returned and *dest is set to NULL, otherwise the number
911 of bytes consumed in the blob is returned
913 static size_t cli_blob_pull_ascii(TALLOC_CTX *mem_ctx,
914 DATA_BLOB *blob, const char **dest,
915 const char *src, int byte_len, unsigned flags)
917 int src_len, src_len2;
920 src_len = blob->length - PTR_DIFF(src, blob->data);
925 if (byte_len != -1 && src_len > byte_len) {
928 src_len2 = strnlen(src, src_len);
930 if (src_len2 < src_len - 1) {
931 /* include the termination if we didn't reach the end of the packet */
935 ret = convert_string_talloc(mem_ctx, CH_DOS, CH_UNIX, src, src_len2, (const void **)dest);
946 pull a string from a blob, returning a talloced WIRE_STRING
948 the string length is limited by the 3 things:
949 - the data size in the blob
950 - length field on the wire
951 - the end of string (null termination)
953 if STR_LEN8BIT is set in the flags then assume the length field is
954 8 bits, instead of 32
956 on failure zero is returned and dest->s is set to NULL, otherwise the number
957 of bytes consumed in the blob is returned
959 size_t cli_blob_pull_string(struct cli_session *session,
963 uint16 len_offset, uint16 str_offset,
969 if (len_offset > blob->length-4) {
972 if (flags & STR_LEN8BIT) {
973 dest->private_length = CVAL(blob->data, len_offset);
975 dest->private_length = IVAL(blob->data, len_offset);
979 if (!(flags & STR_ASCII) &&
980 ((flags & STR_UNICODE) ||
981 (session->transport->negotiate.capabilities & CAP_UNICODE))) {
983 if ((str_offset&1) && !(flags & STR_NOALIGN)) {
986 if (flags & STR_LEN_NOTERM) {
989 return align + extra + cli_blob_pull_ucs2(mem_ctx, blob, &dest->s,
990 blob->data+str_offset+align,
991 dest->private_length, flags);
994 if (flags & STR_LEN_NOTERM) {
998 return extra + cli_blob_pull_ascii(mem_ctx, blob, &dest->s,
999 blob->data+str_offset, dest->private_length, flags);
1003 append a string into a blob
1005 size_t cli_blob_append_string(struct cli_session *session,
1006 TALLOC_CTX *mem_ctx, DATA_BLOB *blob,
1007 const char *str, unsigned flags)
1014 /* determine string type to use */
1015 if (!(flags & (STR_ASCII|STR_UNICODE))) {
1016 flags |= (session->transport->negotiate.capabilities & CAP_UNICODE) ? STR_UNICODE : STR_ASCII;
1019 max_len = (strlen(str)+2) * MAX_BYTES_PER_CHAR;
1021 blob->data = talloc_realloc(mem_ctx, blob->data, blob->length + max_len);
1026 len = push_string(NULL, blob->data + blob->length, str, max_len, flags);
1028 blob->length += len;