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;
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_requests, req);
49 /* ahh, its so nice to destroy a complex structure in such a
52 talloc_destroy(req->mem_ctx);
58 low-level function to setup a request buffer for a non-SMB packet
59 at the transport level
61 struct cli_request *cli_request_setup_nonsmb(struct cli_transport *transport, uint_t size)
63 struct cli_request *req;
66 /* each request gets its own talloc context. The request
67 structure itself is also allocated inside this context,
68 so we need to allocate it before we construct the request
70 mem_ctx = talloc_init("cli_request");
75 req = talloc(mem_ctx, sizeof(struct cli_request));
81 /* setup the request context */
82 req->mem_ctx = mem_ctx;
83 req->transport = transport;
88 /* over allocate by a small amount */
89 req->out.allocated = req->out.size + REQ_OVER_ALLOCATION;
91 req->out.buffer = talloc(req->mem_ctx, req->out.allocated);
92 if (!req->out.buffer) {
96 SIVAL(req->out.buffer, 0, 0);
103 setup a SMB packet at transport level
105 struct cli_request *cli_request_setup_transport(struct cli_transport *transport,
106 uint8 command, unsigned wct, unsigned buflen)
108 struct cli_request *req;
110 req = cli_request_setup_nonsmb(transport, NBT_HDR_SIZE + MIN_SMB_SIZE + wct*2 + buflen);
112 if (!req) return NULL;
114 req->out.hdr = req->out.buffer + NBT_HDR_SIZE;
115 req->out.vwv = req->out.hdr + HDR_VWV;
117 req->out.data = req->out.vwv + VWV(wct) + 2;
118 req->out.data_size = buflen;
119 req->out.ptr = req->out.data;
121 SCVAL(req->out.hdr, HDR_WCT, wct);
122 SSVAL(req->out.vwv, VWV(wct), buflen);
124 memcpy(req->out.hdr, "\377SMB", 4);
125 SCVAL(req->out.hdr,HDR_COM,command);
127 SCVAL(req->out.hdr,HDR_FLG, FLAG_CASELESS_PATHNAMES);
128 SSVAL(req->out.hdr,HDR_FLG2, 0);
131 req->mid = cli_transport_next_mid(transport);
133 /* copy the pid, uid and mid to the request */
134 SSVAL(req->out.hdr, HDR_PID, 0);
135 SSVAL(req->out.hdr, HDR_UID, 0);
136 SSVAL(req->out.hdr, HDR_MID, req->mid);
137 SSVAL(req->out.hdr, HDR_TID,0);
138 SSVAL(req->out.hdr, HDR_PIDHIGH,0);
139 SIVAL(req->out.hdr, HDR_RCLS, 0);
140 memset(req->out.hdr+HDR_SS_FIELD, 0, 10);
146 setup a reply in req->out with the given word count and initial data
147 buffer size. the caller will then fill in the command words and
148 data before calling cli_request_send() to send the reply on its
149 way. This interface is used before a session is setup.
151 struct cli_request *cli_request_setup_session(struct cli_session *session,
152 uint8 command, unsigned wct, unsigned buflen)
154 struct cli_request *req;
158 req = cli_request_setup_transport(session->transport, command, wct, buflen);
160 if (!req) return NULL;
162 req->session = session;
164 flags2 = FLAGS2_LONG_PATH_COMPONENTS;
165 capabilities = session->transport->negotiate.capabilities;
167 if (capabilities & CAP_UNICODE) {
168 flags2 |= FLAGS2_UNICODE_STRINGS;
170 if (capabilities & CAP_STATUS32) {
171 flags2 |= FLAGS2_32_BIT_ERROR_CODES;
173 if (capabilities & CAP_EXTENDED_SECURITY) {
174 flags2 |= FLAGS2_EXTENDED_SECURITY;
176 if (session->transport->negotiate.sign_info.doing_signing) {
177 flags2 |= FLAGS2_SMB_SECURITY_SIGNATURES;
180 SSVAL(req->out.hdr, HDR_FLG2, flags2);
181 SSVAL(req->out.hdr, HDR_PID, session->pid & 0xFFFF);
182 SSVAL(req->out.hdr, HDR_PIDHIGH, session->pid >> 16);
183 SSVAL(req->out.hdr, HDR_UID, session->vuid);
189 setup a request for tree based commands
191 struct cli_request *cli_request_setup(struct cli_tree *tree,
193 unsigned wct, unsigned buflen)
195 struct cli_request *req;
197 req = cli_request_setup_session(tree->session, command, wct, buflen);
200 SSVAL(req->out.hdr,HDR_TID,tree->tid);
206 grow the allocation of the data buffer portion of a reply
207 packet. Note that as this can reallocate the packet buffer this
208 invalidates any local pointers into the packet.
210 To cope with this req->out.ptr is supplied. This will be updated to
211 point at the same offset into the packet as before this call
213 static void cli_req_grow_allocation(struct cli_request *req, unsigned new_size)
218 delta = new_size - req->out.data_size;
219 if (delta + req->out.size <= req->out.allocated) {
220 /* it fits in the preallocation */
224 /* we need to realloc */
225 req->out.allocated = req->out.size + delta + REQ_OVER_ALLOCATION;
226 buf2 = talloc_realloc(req->mem_ctx, req->out.buffer, req->out.allocated);
228 smb_panic("out of memory in req_grow_allocation");
231 if (buf2 == req->out.buffer) {
232 /* the malloc library gave us the same pointer */
236 /* update the pointers into the packet */
237 req->out.data = buf2 + PTR_DIFF(req->out.data, req->out.buffer);
238 req->out.ptr = buf2 + PTR_DIFF(req->out.ptr, req->out.buffer);
239 req->out.vwv = buf2 + PTR_DIFF(req->out.vwv, req->out.buffer);
240 req->out.hdr = buf2 + PTR_DIFF(req->out.hdr, req->out.buffer);
242 req->out.buffer = buf2;
247 grow the data buffer portion of a reply packet. Note that as this
248 can reallocate the packet buffer this invalidates any local pointers
251 To cope with this req->out.ptr is supplied. This will be updated to
252 point at the same offset into the packet as before this call
254 static void cli_req_grow_data(struct cli_request *req, unsigned new_size)
258 cli_req_grow_allocation(req, new_size);
260 delta = new_size - req->out.data_size;
262 req->out.size += delta;
263 req->out.data_size += delta;
265 /* set the BCC to the new data size */
266 SSVAL(req->out.vwv, VWV(req->out.wct), new_size);
272 BOOL cli_request_send(struct cli_request *req)
276 if (IVAL(req->out.buffer, 0) == 0) {
277 _smb_setlen(req->out.buffer, req->out.size - NBT_HDR_SIZE);
280 cli_request_calculate_sign_mac(req);
282 ret = cli_sock_write(req->transport->socket, req->out.buffer, req->out.size);
284 if (req->out.size != ret) {
285 req->transport->error.etype = ETYPE_SOCKET;
286 req->transport->error.e.socket_error = SOCKET_WRITE_ERROR;
287 DEBUG(0,("Error writing %d bytes to server - %s\n",
288 (int)req->out.size, strerror(errno)));
292 /* add it to the list of pending requests */
293 DLIST_ADD(req->transport->pending_requests, req);
300 receive a response to a packet
302 BOOL cli_request_receive(struct cli_request *req)
304 /* req can be NULL when a send has failed. This eliminates lots of NULL
305 checks in each module */
306 if (!req) return False;
308 /* keep receiving packets until this one is replied to */
309 while (!req->in.buffer) {
310 if (!cli_transport_select(req->transport)) {
311 req->status = NT_STATUS_UNSUCCESSFUL;
315 if (!cli_request_receive_next(req->transport)) {
316 cli_transport_dead(req->transport);
317 req->status = NT_STATUS_UNEXPECTED_NETWORK_ERROR;
327 handle oplock break requests from the server - return True if the request was
330 static BOOL handle_oplock_break(struct cli_transport *transport, uint_t len, const char *hdr, const char *vwv)
332 /* we must be very fussy about what we consider an oplock break to avoid
333 matching readbraw replies */
334 if (len != MIN_SMB_SIZE + VWV(8) ||
335 (CVAL(hdr, HDR_FLG) & FLAG_REPLY) ||
336 CVAL(hdr,HDR_COM) != SMBlockingX ||
337 SVAL(hdr, HDR_MID) != 0xFFFF ||
338 SVAL(vwv,VWV(6)) != 0 ||
339 SVAL(vwv,VWV(7)) != 0) {
343 if (transport->oplock.handler) {
344 uint16 tid = SVAL(hdr, HDR_TID);
345 uint16 fnum = SVAL(vwv,VWV(2));
346 uint8 level = CVAL(vwv,VWV(3)+1);
347 transport->oplock.handler(transport, tid, fnum, level, transport->oplock.private);
355 receive an async message from the server
356 this function assumes that the caller already knows that the socket is readable
357 and that there is a packet waiting
359 The packet is not actually returned by this function, instead any
360 registered async message handlers are called
362 return True if a packet was successfully received and processed
363 return False if the socket appears to be dead
365 BOOL cli_request_receive_next(struct cli_transport *transport)
369 char header[NBT_HDR_SIZE];
370 char *buffer, *hdr, *vwv;
372 struct cli_request *req;
375 len = cli_sock_read(transport->socket, header, 4);
380 len = smb_len(header);
382 mem_ctx = talloc_init("cli_request_receive_next");
384 /* allocate the incoming buffer at the right size */
385 buffer = talloc(mem_ctx, len+NBT_HDR_SIZE);
387 talloc_destroy(mem_ctx);
391 /* fill in the already received header */
392 memcpy(buffer, header, NBT_HDR_SIZE);
394 ret = cli_sock_read(transport->socket, buffer + NBT_HDR_SIZE, len);
395 /* If the server is not responding, note that now */
400 hdr = buffer+NBT_HDR_SIZE;
403 /* see if it could be an oplock break request */
404 if (handle_oplock_break(transport, len, hdr, vwv)) {
408 /* at this point we need to check for a readbraw reply, as these can be any length */
409 if (transport->readbraw_pending) {
410 transport->readbraw_pending = 0;
412 /* it must match the first entry in the pending queue as the client is not allowed
413 to have outstanding readbraw requests */
414 req = transport->pending_requests;
417 req->in.buffer = buffer;
418 talloc_steal(mem_ctx, req->mem_ctx, buffer);
419 req->in.size = len + NBT_HDR_SIZE;
420 req->in.allocated = req->in.size;
424 if (len >= MIN_SMB_SIZE) {
425 /* extract the mid for matching to pending requests */
426 mid = SVAL(hdr, HDR_MID);
427 wct = CVAL(hdr, HDR_WCT);
430 /* match the incoming request against the list of pending requests */
431 for (req=transport->pending_requests; req; req=req->next) {
432 if (req->mid == mid) break;
436 DEBUG(3,("Discarding unmatched reply with mid %d\n", mid));
440 /* fill in the 'in' portion of the matching request */
441 req->in.buffer = buffer;
442 talloc_steal(mem_ctx, req->mem_ctx, buffer);
443 req->in.size = len + NBT_HDR_SIZE;
444 req->in.allocated = req->in.size;
446 /* handle non-SMB replies */
447 if (req->in.size < NBT_HDR_SIZE + MIN_SMB_SIZE) {
451 if (req->in.size < NBT_HDR_SIZE + MIN_SMB_SIZE + VWV(wct)) {
452 DEBUG(2,("bad reply size for mid %d\n", mid));
453 req->status = NT_STATUS_UNSUCCESSFUL;
460 if (req->in.size >= NBT_HDR_SIZE + MIN_SMB_SIZE + VWV(wct)) {
461 req->in.data = req->in.vwv + VWV(wct) + 2;
462 req->in.data_size = SVAL(req->in.vwv, VWV(wct));
463 if (req->in.size < NBT_HDR_SIZE + MIN_SMB_SIZE + VWV(wct) + req->in.data_size) {
464 DEBUG(3,("bad data size for mid %d\n", mid));
465 /* blergh - w2k3 gives a bogus data size values in some
467 req->in.data_size = req->in.size - (NBT_HDR_SIZE + MIN_SMB_SIZE + VWV(wct));
470 req->in.ptr = req->in.data;
471 req->flags2 = SVAL(req->in.hdr, HDR_FLG2);
473 if (!(req->flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
474 transport->error.etype = ETYPE_DOS;
475 transport->error.e.dos.eclass = CVAL(req->in.hdr,HDR_RCLS);
476 transport->error.e.dos.ecode = SVAL(req->in.hdr,HDR_ERR);
477 req->status = dos_to_ntstatus(transport->error.e.dos.eclass,
478 transport->error.e.dos.ecode);
480 transport->error.etype = ETYPE_NT;
481 transport->error.e.nt_status = NT_STATUS(IVAL(req->in.hdr, HDR_RCLS));
482 req->status = transport->error.e.nt_status;
485 if (!cli_request_check_sign_mac(req)) {
486 transport->error.etype = ETYPE_SOCKET;
487 transport->error.e.socket_error = SOCKET_READ_BAD_SIG;
492 /* if this request has an async handler then call that to
493 notify that the reply has been received. This might destroy
494 the request so it must happen last */
500 talloc_destroy(mem_ctx);
506 wait for a reply to be received for a packet that just returns an error
507 code and nothing more
509 NTSTATUS cli_request_simple_recv(struct cli_request *req)
511 cli_request_receive(req);
512 return cli_request_destroy(req);
516 /* Return true if the last packet was in error */
517 BOOL cli_request_is_error(struct cli_request *req)
519 return NT_STATUS_IS_ERR(req->status);
523 append a string into the data portion of the request packet
525 return the number of bytes added to the packet
527 size_t cli_req_append_string(struct cli_request *req, const char *str, unsigned flags)
531 /* determine string type to use */
532 if (!(flags & (STR_ASCII|STR_UNICODE))) {
533 flags |= (req->transport->negotiate.capabilities & CAP_UNICODE) ? STR_UNICODE : STR_ASCII;
536 len = (strlen(str)+2) * MAX_BYTES_PER_CHAR;
538 cli_req_grow_allocation(req, len + req->out.data_size);
540 len = push_string(NULL, req->out.data + req->out.data_size, str, len, flags);
542 cli_req_grow_data(req, len + req->out.data_size);
548 this is like cli_req_append_string but it also return the
549 non-terminated string byte length, which can be less than the number
550 of bytes consumed in the packet for 2 reasons:
552 1) the string in the packet may be null terminated
553 2) the string in the packet may need a 1 byte UCS2 alignment
555 this is used in places where the non-terminated string byte length is
556 placed in the packet as a separate field
558 size_t cli_req_append_string_len(struct cli_request *req, const char *str, unsigned flags, int *len)
563 /* determine string type to use */
564 if (!(flags & (STR_ASCII|STR_UNICODE))) {
565 flags |= (req->transport->negotiate.capabilities & CAP_UNICODE) ? STR_UNICODE : STR_ASCII;
568 /* see if an alignment byte will be used */
569 if ((flags & STR_UNICODE) && !(flags & STR_NOALIGN)) {
570 diff = ucs2_align(NULL, req->out.data + req->out.data_size, flags);
573 /* do the hard work */
574 ret = cli_req_append_string(req, str, flags);
576 /* see if we need to subtract the termination */
577 if (flags & STR_TERMINATE) {
578 diff += (flags & STR_UNICODE) ? 2 : 1;
592 push a string into the data portion of the request packet, growing it if necessary
593 this gets quite tricky - please be very careful to cover all cases when modifying this
595 if dest is NULL, then put the string at the end of the data portion of the packet
597 if dest_len is -1 then no limit applies
599 size_t cli_req_append_ascii4(struct cli_request *req, const char *str, unsigned flags)
602 cli_req_append_bytes(req, (const uint8 *)"\4", 1);
603 size = cli_req_append_string(req, str, flags);
609 push a blob into the data portion of the request packet, growing it if necessary
610 this gets quite tricky - please be very careful to cover all cases when modifying this
612 if dest is NULL, then put the blob at the end of the data portion of the packet
614 size_t cli_req_append_blob(struct cli_request *req, const DATA_BLOB *blob)
616 cli_req_grow_allocation(req, req->out.data_size + blob->length);
617 memcpy(req->out.data + req->out.data_size, blob->data, blob->length);
618 cli_req_grow_data(req, req->out.data_size + blob->length);
623 append raw bytes into the data portion of the request packet
624 return the number of bytes added
626 size_t cli_req_append_bytes(struct cli_request *req, const uint8 *bytes, size_t byte_len)
628 cli_req_grow_allocation(req, byte_len + req->out.data_size);
629 memcpy(req->out.data + req->out.data_size, bytes, byte_len);
630 cli_req_grow_data(req, byte_len + req->out.data_size);
635 append variable block (type 5 buffer) into the data portion of the request packet
636 return the number of bytes added
638 size_t cli_req_append_var_block(struct cli_request *req, const uint8 *bytes, uint16 byte_len)
640 cli_req_grow_allocation(req, byte_len + 3 + req->out.data_size);
641 SCVAL(req->out.data + req->out.data_size, 0, 5);
642 SSVAL(req->out.data + req->out.data_size, 1, byte_len); /* add field length */
644 memcpy(req->out.data + req->out.data_size + 3, bytes, byte_len);
646 cli_req_grow_data(req, byte_len + 3 + req->out.data_size);
652 pull a UCS2 string from a request packet, returning a talloced unix string
654 the string length is limited by the 3 things:
655 - the data size in the request (end of packet)
656 - the passed 'byte_len' if it is not -1
657 - the end of string (null termination)
659 Note that 'byte_len' is the number of bytes in the packet
661 on failure zero is returned and *dest is set to NULL, otherwise the number
662 of bytes consumed in the packet is returned
664 static size_t cli_req_pull_ucs2(struct cli_request *req, TALLOC_CTX *mem_ctx,
665 char **dest, const char *src, int byte_len, unsigned flags)
667 int src_len, src_len2, alignment=0;
670 if (!(flags & STR_NOALIGN) && ucs2_align(req->in.buffer, src, flags)) {
673 if (byte_len != -1) {
678 src_len = req->in.data_size - PTR_DIFF(src, req->in.data);
683 if (byte_len != -1 && src_len > byte_len) {
687 src_len2 = strnlen_w((const smb_ucs2_t *)src, src_len/2) * 2;
688 if (src_len2 < src_len - 2) {
689 /* include the termination if we didn't reach the end of the packet */
693 /* ucs2 strings must be at least 2 bytes long */
699 ret = convert_string_talloc(mem_ctx, CH_UCS2, CH_UNIX, src, src_len2, (const void **)dest);
705 return src_len2 + alignment;
709 pull a ascii string from a request packet, returning a talloced string
711 the string length is limited by the 3 things:
712 - the data size in the request (end of packet)
713 - the passed 'byte_len' if it is not -1
714 - the end of string (null termination)
716 Note that 'byte_len' is the number of bytes in the packet
718 on failure zero is returned and *dest is set to NULL, otherwise the number
719 of bytes consumed in the packet is returned
721 size_t cli_req_pull_ascii(struct cli_request *req, TALLOC_CTX *mem_ctx,
722 char **dest, const char *src, int byte_len, unsigned flags)
724 int src_len, src_len2;
727 src_len = req->in.data_size - PTR_DIFF(src, req->in.data);
732 if (byte_len != -1 && src_len > byte_len) {
735 src_len2 = strnlen(src, src_len);
736 if (src_len2 < src_len - 1) {
737 /* include the termination if we didn't reach the end of the packet */
741 ret = convert_string_talloc(mem_ctx, CH_DOS, CH_UNIX, src, src_len2, (const void **)dest);
752 pull a string from a request packet, returning a talloced string
754 the string length is limited by the 3 things:
755 - the data size in the request (end of packet)
756 - the passed 'byte_len' if it is not -1
757 - the end of string (null termination)
759 Note that 'byte_len' is the number of bytes in the packet
761 on failure zero is returned and *dest is set to NULL, otherwise the number
762 of bytes consumed in the packet is returned
764 size_t cli_req_pull_string(struct cli_request *req, TALLOC_CTX *mem_ctx,
765 char **dest, const char *src, int byte_len, unsigned flags)
767 if (!(flags & STR_ASCII) &&
768 (((flags & STR_UNICODE) || (req->flags2 & FLAGS2_UNICODE_STRINGS)))) {
769 return cli_req_pull_ucs2(req, mem_ctx, dest, src, byte_len, flags);
772 return cli_req_pull_ascii(req, mem_ctx, dest, src, byte_len, flags);
777 pull a DATA_BLOB from a reply packet, returning a talloced blob
778 make sure we don't go past end of packet
780 if byte_len is -1 then limit the blob only by packet size
782 DATA_BLOB cli_req_pull_blob(struct cli_request *req, TALLOC_CTX *mem_ctx, const char *src, int byte_len)
786 src_len = req->in.data_size - PTR_DIFF(src, req->in.data);
789 return data_blob(NULL, 0);
792 if (byte_len != -1 && src_len > byte_len) {
796 return data_blob_talloc(mem_ctx, src, src_len);
799 /* check that a lump of data in a request is within the bounds of the data section of
801 static BOOL cli_req_data_oob(struct cli_request *req, const char *ptr, uint32 count)
803 /* be careful with wraparound! */
804 if (ptr < req->in.data ||
805 ptr >= req->in.data + req->in.data_size ||
806 count > req->in.data_size ||
807 ptr + count > req->in.data + req->in.data_size) {
814 pull a lump of data from a request packet
816 return False if any part is outside the data portion of the packet
818 BOOL cli_raw_pull_data(struct cli_request *req, const char *src, int len, char *dest)
820 if (len == 0) return True;
822 if (cli_req_data_oob(req, src, len)) {
826 memcpy(dest, src, len);
832 put a NTTIME into a packet
834 void cli_push_nttime(void *base, uint16 offset, NTTIME t)
836 SBVAL(base, offset, t);
840 pull a NTTIME from a packet
842 NTTIME cli_pull_nttime(void *base, uint16 offset)
844 NTTIME ret = BVAL(base, offset);
849 pull a UCS2 string from a blob, returning a talloced unix string
851 the string length is limited by the 3 things:
852 - the data size in the blob
853 - the passed 'byte_len' if it is not -1
854 - the end of string (null termination)
856 Note that 'byte_len' is the number of bytes in the packet
858 on failure zero is returned and *dest is set to NULL, otherwise the number
859 of bytes consumed in the blob is returned
861 static size_t cli_blob_pull_ucs2(TALLOC_CTX* mem_ctx,
862 DATA_BLOB *blob, const char **dest,
863 const char *src, int byte_len, unsigned flags)
865 int src_len, src_len2, alignment=0;
868 if (src < (const char *)blob->data ||
869 src >= (const char *)(blob->data + blob->length)) {
874 src_len = blob->length - PTR_DIFF(src, blob->data);
876 if (byte_len != -1 && src_len > byte_len) {
880 if (!(flags & STR_NOALIGN) && ucs2_align(blob->data, src, flags)) {
891 src_len2 = strnlen_w((const smb_ucs2_t *)src, src_len/2) * 2;
893 if (src_len2 < src_len - 2) {
894 /* include the termination if we didn't reach the end of the packet */
898 ret = convert_string_talloc(mem_ctx, CH_UCS2, CH_UNIX, src, src_len2, (const void **)dest);
904 return src_len2 + alignment;
908 pull a ascii string from a blob, returning a talloced string
910 the string length is limited by the 3 things:
911 - the data size in the blob
912 - the passed 'byte_len' if it is not -1
913 - the end of string (null termination)
915 Note that 'byte_len' is the number of bytes in the blob
917 on failure zero is returned and *dest is set to NULL, otherwise the number
918 of bytes consumed in the blob is returned
920 static size_t cli_blob_pull_ascii(TALLOC_CTX *mem_ctx,
921 DATA_BLOB *blob, const char **dest,
922 const char *src, int byte_len, unsigned flags)
924 int src_len, src_len2;
927 src_len = blob->length - PTR_DIFF(src, blob->data);
932 if (byte_len != -1 && src_len > byte_len) {
935 src_len2 = strnlen(src, src_len);
937 if (src_len2 < src_len - 1) {
938 /* include the termination if we didn't reach the end of the packet */
942 ret = convert_string_talloc(mem_ctx, CH_DOS, CH_UNIX, src, src_len2, (const void **)dest);
953 pull a string from a blob, returning a talloced WIRE_STRING
955 the string length is limited by the 3 things:
956 - the data size in the blob
957 - length field on the wire
958 - the end of string (null termination)
960 if STR_LEN8BIT is set in the flags then assume the length field is
961 8 bits, instead of 32
963 on failure zero is returned and dest->s is set to NULL, otherwise the number
964 of bytes consumed in the blob is returned
966 size_t cli_blob_pull_string(struct cli_session *session,
970 uint16 len_offset, uint16 str_offset,
976 if (len_offset > blob->length-4) {
979 if (flags & STR_LEN8BIT) {
980 dest->private_length = CVAL(blob->data, len_offset);
982 dest->private_length = IVAL(blob->data, len_offset);
986 if (!(flags & STR_ASCII) &&
987 ((flags & STR_UNICODE) ||
988 (session->transport->negotiate.capabilities & CAP_UNICODE))) {
990 if ((str_offset&1) && !(flags & STR_NOALIGN)) {
993 if (flags & STR_LEN_NOTERM) {
996 return align + extra + cli_blob_pull_ucs2(mem_ctx, blob, &dest->s,
997 blob->data+str_offset+align,
998 dest->private_length, flags);
1001 if (flags & STR_LEN_NOTERM) {
1005 return extra + cli_blob_pull_ascii(mem_ctx, blob, &dest->s,
1006 blob->data+str_offset, dest->private_length, flags);
1010 pull a string from a blob, returning a talloced char *
1012 Currently only used by the UNIX search info level.
1014 the string length is limited by 2 things:
1015 - the data size in the blob
1016 - the end of string (null termination)
1018 on failure zero is returned and dest->s is set to NULL, otherwise the number
1019 of bytes consumed in the blob is returned
1021 size_t cli_blob_pull_unix_string(struct cli_session *session,
1022 TALLOC_CTX *mem_ctx,
1031 if (!(flags & STR_ASCII) &&
1032 ((flags & STR_UNICODE) ||
1033 (session->transport->negotiate.capabilities & CAP_UNICODE))) {
1035 if ((str_offset&1) && !(flags & STR_NOALIGN)) {
1038 if (flags & STR_LEN_NOTERM) {
1041 return align + extra + cli_blob_pull_ucs2(mem_ctx, blob, dest,
1042 blob->data+str_offset+align,
1046 if (flags & STR_LEN_NOTERM) {
1050 return extra + cli_blob_pull_ascii(mem_ctx, blob, dest,
1051 blob->data+str_offset, -1, flags);
1056 append a string into a blob
1058 size_t cli_blob_append_string(struct cli_session *session,
1059 TALLOC_CTX *mem_ctx, DATA_BLOB *blob,
1060 const char *str, unsigned flags)
1067 /* determine string type to use */
1068 if (!(flags & (STR_ASCII|STR_UNICODE))) {
1069 flags |= (session->transport->negotiate.capabilities & CAP_UNICODE) ? STR_UNICODE : STR_ASCII;
1072 max_len = (strlen(str)+2) * MAX_BYTES_PER_CHAR;
1074 blob->data = talloc_realloc(mem_ctx, blob->data, blob->length + max_len);
1079 len = push_string(NULL, blob->data + blob->length, str, max_len, flags);
1081 blob->length += len;