s3:auth: add missing auth_samba4_init() prototype
[Samba.git] / source4 / libcli / raw / rawrequest.c
blob9cabea5c78078c14bc2f2acb2c723084d299f94e
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 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
25 #include "includes.h"
26 #include "libcli/raw/libcliraw.h"
27 #include "libcli/raw/raw_proto.h"
28 #include "lib/events/events.h"
29 #include "librpc/ndr/libndr.h"
30 #include "librpc/gen_ndr/ndr_misc.h"
31 #include "../libcli/smb/smbXcli_base.h"
33 /* we over allocate the data buffer to prevent too many realloc calls */
34 #define REQ_OVER_ALLOCATION 0
36 /* assume that a character will not consume more than 3 bytes per char */
37 #define MAX_BYTES_PER_CHAR 3
39 /* setup the bufinfo used for strings and range checking */
40 void smb_setup_bufinfo(struct smbcli_request *req)
42 req->in.bufinfo.mem_ctx = req;
43 req->in.bufinfo.flags = 0;
44 if (req->flags2 & FLAGS2_UNICODE_STRINGS) {
45 req->in.bufinfo.flags = BUFINFO_FLAG_UNICODE;
47 req->in.bufinfo.align_base = req->in.buffer;
48 req->in.bufinfo.data = req->in.data;
49 req->in.bufinfo.data_size = req->in.data_size;
53 /* destroy a request structure and return final status */
54 _PUBLIC_ NTSTATUS smbcli_request_destroy(struct smbcli_request *req)
56 NTSTATUS status;
58 /* this is the error code we give the application for when a
59 _send() call fails completely */
60 if (!req) return NT_STATUS_UNSUCCESSFUL;
62 if (req->state == SMBCLI_REQUEST_ERROR &&
63 NT_STATUS_IS_OK(req->status)) {
64 req->status = NT_STATUS_INTERNAL_ERROR;
67 status = req->status;
69 if (!req->do_not_free) {
70 talloc_free(req);
73 return status;
78 setup a SMB packet at transport level
80 struct smbcli_request *smbcli_request_setup_transport(struct smbcli_transport *transport,
81 uint8_t command, unsigned int wct, unsigned int buflen)
83 struct smbcli_request *req;
84 size_t size;
86 size = NBT_HDR_SIZE + MIN_SMB_SIZE + wct*2 + buflen;
88 req = talloc_zero(transport, struct smbcli_request);
89 if (!req) {
90 return NULL;
93 /* setup the request context */
94 req->state = SMBCLI_REQUEST_INIT;
95 req->transport = transport;
96 req->out.size = size;
98 /* over allocate by a small amount */
99 req->out.allocated = req->out.size + REQ_OVER_ALLOCATION;
101 req->out.buffer = talloc_zero_array(req, uint8_t, req->out.allocated);
102 if (!req->out.buffer) {
103 return NULL;
106 req->out.hdr = req->out.buffer + NBT_HDR_SIZE;
107 req->out.vwv = req->out.hdr + HDR_VWV;
108 req->out.wct = wct;
109 req->out.data = req->out.vwv + VWV(wct) + 2;
110 req->out.data_size = buflen;
111 req->out.ptr = req->out.data;
113 SCVAL(req->out.hdr, HDR_WCT, wct);
114 SSVAL(req->out.vwv, VWV(wct), buflen);
116 memcpy(req->out.hdr, "\377SMB", 4);
117 SCVAL(req->out.hdr,HDR_COM,command);
119 SCVAL(req->out.hdr,HDR_FLG, FLAG_CASELESS_PATHNAMES);
120 SSVAL(req->out.hdr,HDR_FLG2, 0);
122 /* copy the pid, uid and mid to the request */
123 SSVAL(req->out.hdr, HDR_PID, 0);
124 SSVAL(req->out.hdr, HDR_UID, 0);
125 SSVAL(req->out.hdr, HDR_MID, 0);
126 SSVAL(req->out.hdr, HDR_TID,0);
127 SSVAL(req->out.hdr, HDR_PIDHIGH,0);
128 SIVAL(req->out.hdr, HDR_RCLS, 0);
129 memset(req->out.hdr+HDR_SS_FIELD, 0, 10);
131 return req;
135 setup a reply in req->out with the given word count and initial data
136 buffer size. the caller will then fill in the command words and
137 data before calling smbcli_request_send() to send the reply on its
138 way. This interface is used before a session is setup.
140 struct smbcli_request *smbcli_request_setup_session(struct smbcli_session *session,
141 uint8_t command, unsigned int wct, size_t buflen)
143 struct smbcli_request *req;
145 req = smbcli_request_setup_transport(session->transport, command, wct, buflen);
147 if (!req) return NULL;
149 smb1cli_session_set_id(session->smbXcli, session->vuid);
151 req->session = session;
153 SSVAL(req->out.hdr, HDR_FLG2, session->flags2);
154 SSVAL(req->out.hdr, HDR_PID, session->pid & 0xFFFF);
155 SSVAL(req->out.hdr, HDR_PIDHIGH, session->pid >> 16);
156 SSVAL(req->out.hdr, HDR_UID, session->vuid);
158 return req;
162 setup a request for tree based commands
164 struct smbcli_request *smbcli_request_setup(struct smbcli_tree *tree,
165 uint8_t command,
166 unsigned int wct, unsigned int buflen)
168 struct smbcli_request *req;
170 req = smbcli_request_setup_session(tree->session, command, wct, buflen);
171 if (req) {
172 smb1cli_tcon_set_id(tree->smbXcli, tree->tid);
174 req->tree = tree;
175 SSVAL(req->out.hdr,HDR_TID,tree->tid);
177 return req;
182 grow the allocation of the data buffer portion of a reply
183 packet. Note that as this can reallocate the packet buffer this
184 invalidates any local pointers into the packet.
186 To cope with this req->out.ptr is supplied. This will be updated to
187 point at the same offset into the packet as before this call
189 static void smbcli_req_grow_allocation(struct smbcli_request *req, unsigned int new_size)
191 int delta;
192 uint8_t *buf2;
194 delta = new_size - req->out.data_size;
195 if (delta + req->out.size <= req->out.allocated) {
196 /* it fits in the preallocation */
197 return;
200 /* we need to realloc */
201 req->out.allocated = req->out.size + delta + REQ_OVER_ALLOCATION;
202 buf2 = talloc_realloc(req, req->out.buffer, uint8_t, req->out.allocated);
203 if (buf2 == NULL) {
204 smb_panic("out of memory in req_grow_allocation");
207 if (buf2 == req->out.buffer) {
208 /* the malloc library gave us the same pointer */
209 return;
212 /* update the pointers into the packet */
213 req->out.data = buf2 + PTR_DIFF(req->out.data, req->out.buffer);
214 req->out.ptr = buf2 + PTR_DIFF(req->out.ptr, req->out.buffer);
215 req->out.vwv = buf2 + PTR_DIFF(req->out.vwv, req->out.buffer);
216 req->out.hdr = buf2 + PTR_DIFF(req->out.hdr, req->out.buffer);
218 req->out.buffer = buf2;
223 grow the data buffer portion of a reply packet. Note that as this
224 can reallocate the packet buffer this invalidates any local pointers
225 into the packet.
227 To cope with this req->out.ptr is supplied. This will be updated to
228 point at the same offset into the packet as before this call
230 static void smbcli_req_grow_data(struct smbcli_request *req, unsigned int new_size)
232 int delta;
234 smbcli_req_grow_allocation(req, new_size);
236 delta = new_size - req->out.data_size;
238 req->out.size += delta;
239 req->out.data_size += delta;
241 /* set the BCC to the new data size */
242 SSVAL(req->out.vwv, VWV(req->out.wct), new_size);
247 setup a chained reply in req->out with the given word count and
248 initial data buffer size.
250 NTSTATUS smbcli_chained_request_setup(struct smbcli_request *req,
251 uint8_t command,
252 unsigned int wct, size_t buflen)
254 size_t wct_ofs;
255 size_t size;
258 * here we only support one chained command
259 * If someone needs longer chains, the low
260 * level code should be used directly.
262 if (req->subreqs[0] != NULL) {
263 return NT_STATUS_INVALID_PARAMETER_MIX;
265 if (req->subreqs[1] != NULL) {
266 return NT_STATUS_INVALID_PARAMETER_MIX;
269 req->subreqs[0] = smbcli_transport_setup_subreq(req);
270 if (req->subreqs[0] == NULL) {
271 return NT_STATUS_NO_MEMORY;
274 wct_ofs = smb1cli_req_wct_ofs(req->subreqs, 1);
276 size = NBT_HDR_SIZE + wct_ofs + 1 + VWV(wct) + 2 + buflen;
278 req->out.size = size;
280 /* over allocate by a small amount */
281 req->out.allocated = req->out.size + REQ_OVER_ALLOCATION;
283 req->out.buffer = talloc_zero_array(req, uint8_t, req->out.allocated);
284 if (!req->out.buffer) {
285 return NT_STATUS_NO_MEMORY;
288 req->out.hdr = req->out.buffer + NBT_HDR_SIZE;
289 req->out.vwv = req->out.hdr + wct_ofs;
290 req->out.wct = wct;
291 req->out.data = req->out.vwv + VWV(wct) + 2;
292 req->out.data_size = buflen;
293 req->out.ptr = req->out.data;
295 SCVAL(req->out.hdr, HDR_WCT, wct);
296 SSVAL(req->out.vwv, VWV(wct), buflen);
298 memcpy(req->out.hdr, "\377SMB", 4);
299 SCVAL(req->out.hdr,HDR_COM,command);
301 SCVAL(req->out.hdr,HDR_FLG, FLAG_CASELESS_PATHNAMES);
302 SSVAL(req->out.hdr,HDR_FLG2, 0);
304 /* copy the pid, uid and mid to the request */
305 SSVAL(req->out.hdr, HDR_PID, 0);
306 SSVAL(req->out.hdr, HDR_UID, 0);
307 SSVAL(req->out.hdr, HDR_MID, 0);
308 SSVAL(req->out.hdr, HDR_TID,0);
309 SSVAL(req->out.hdr, HDR_PIDHIGH,0);
310 SIVAL(req->out.hdr, HDR_RCLS, 0);
311 memset(req->out.hdr+HDR_SS_FIELD, 0, 10);
313 if (req->session != NULL) {
314 SSVAL(req->out.hdr, HDR_FLG2, req->session->flags2);
315 SSVAL(req->out.hdr, HDR_PID, req->session->pid & 0xFFFF);
316 SSVAL(req->out.hdr, HDR_PIDHIGH, req->session->pid >> 16);
317 SSVAL(req->out.hdr, HDR_UID, req->session->vuid);
320 if (req->tree != NULL) {
321 SSVAL(req->out.hdr, HDR_TID, req->tree->tid);
324 return NT_STATUS_OK;
328 advance to the next chained reply in a request
330 NTSTATUS smbcli_chained_advance(struct smbcli_request *req)
332 struct smbcli_transport *transport = req->transport;
333 uint8_t *hdr = NULL;
334 uint8_t wct = 0;
335 uint16_t *vwv = NULL;
336 uint32_t num_bytes = 0;
337 uint8_t *bytes = NULL;
338 struct iovec *recv_iov = NULL;
339 uint8_t *inbuf = NULL;
341 if (req->subreqs[0] != NULL) {
342 return NT_STATUS_INVALID_PARAMETER_MIX;
344 if (req->subreqs[1] == NULL) {
345 return NT_STATUS_INVALID_PARAMETER_MIX;
348 req->status = smb1cli_req_recv(req->subreqs[1], req,
349 &recv_iov,
350 &hdr,
351 &wct,
352 &vwv,
353 NULL, /* pvwv_offset */
354 &num_bytes,
355 &bytes,
356 NULL, /* pbytes_offset */
357 &inbuf,
358 NULL, 0); /* expected */
359 TALLOC_FREE(req->subreqs[1]);
360 if (!NT_STATUS_IS_OK(req->status)) {
361 if (recv_iov == NULL) {
362 req->state = SMBCLI_REQUEST_ERROR;
363 return req->status;
367 /* fill in the 'in' portion of the matching request */
368 req->in.buffer = inbuf;
369 req->in.size = NBT_HDR_SIZE + PTR_DIFF(bytes, hdr) + num_bytes;
370 req->in.allocated = req->in.size;
372 req->in.hdr = hdr;
373 req->in.vwv = (uint8_t *)vwv;
374 req->in.wct = wct;
375 req->in.data = bytes;
376 req->in.data_size = num_bytes;
377 req->in.ptr = req->in.data;
378 req->flags2 = SVAL(req->in.hdr, HDR_FLG2);
380 smb_setup_bufinfo(req);
382 transport->error.e.nt_status = req->status;
383 if (NT_STATUS_IS_OK(req->status)) {
384 transport->error.etype = ETYPE_NONE;
385 } else {
386 transport->error.etype = ETYPE_SMB;
389 req->state = SMBCLI_REQUEST_DONE;
391 return NT_STATUS_OK;
396 send a message
398 bool smbcli_request_send(struct smbcli_request *req)
400 smbcli_transport_send(req);
401 return true;
406 receive a response to a packet
408 bool smbcli_request_receive(struct smbcli_request *req)
410 /* req can be NULL when a send has failed. This eliminates lots of NULL
411 checks in each module */
412 if (!req) return false;
414 /* keep receiving packets until this one is replied to */
415 while (req->state <= SMBCLI_REQUEST_RECV) {
416 if (tevent_loop_once(req->transport->ev) != 0) {
417 return false;
421 return req->state == SMBCLI_REQUEST_DONE;
425 wait for a reply to be received for a packet that just returns an error
426 code and nothing more
428 _PUBLIC_ NTSTATUS smbcli_request_simple_recv(struct smbcli_request *req)
430 (void) smbcli_request_receive(req);
431 return smbcli_request_destroy(req);
435 /* Return true if the last packet was in error */
436 bool smbcli_request_is_error(struct smbcli_request *req)
438 return NT_STATUS_IS_ERR(req->status);
442 append a string into the data portion of the request packet
444 return the number of bytes added to the packet
446 size_t smbcli_req_append_string(struct smbcli_request *req, const char *str, unsigned int flags)
448 size_t len;
450 /* determine string type to use */
451 if (!(flags & (STR_ASCII|STR_UNICODE))) {
452 flags |= (req->transport->negotiate.capabilities & CAP_UNICODE) ? STR_UNICODE : STR_ASCII;
455 len = (strlen(str)+2) * MAX_BYTES_PER_CHAR;
457 smbcli_req_grow_allocation(req, len + req->out.data_size);
459 len = push_string(req->out.data + req->out.data_size, str, len, flags);
461 smbcli_req_grow_data(req, len + req->out.data_size);
463 return len;
468 this is like smbcli_req_append_string but it also return the
469 non-terminated string byte length, which can be less than the number
470 of bytes consumed in the packet for 2 reasons:
472 1) the string in the packet may be null terminated
473 2) the string in the packet may need a 1 byte UCS2 alignment
475 this is used in places where the non-terminated string byte length is
476 placed in the packet as a separate field
478 size_t smbcli_req_append_string_len(struct smbcli_request *req, const char *str, unsigned int flags, int *len)
480 int diff = 0;
481 size_t ret;
483 /* determine string type to use */
484 if (!(flags & (STR_ASCII|STR_UNICODE))) {
485 flags |= (req->transport->negotiate.capabilities & CAP_UNICODE) ? STR_UNICODE : STR_ASCII;
488 /* see if an alignment byte will be used */
489 if ((flags & STR_UNICODE) && !(flags & STR_NOALIGN)) {
490 diff = ucs2_align(NULL, req->out.data + req->out.data_size, flags);
493 /* do the hard work */
494 ret = smbcli_req_append_string(req, str, flags);
496 /* see if we need to subtract the termination */
497 if (flags & STR_TERMINATE) {
498 diff += (flags & STR_UNICODE) ? 2 : 1;
501 if (ret >= diff) {
502 (*len) = ret - diff;
503 } else {
504 (*len) = ret;
507 return ret;
512 push a string into the data portion of the request packet, growing it if necessary
513 this gets quite tricky - please be very careful to cover all cases when modifying this
515 if dest is NULL, then put the string at the end of the data portion of the packet
517 if dest_len is -1 then no limit applies
519 size_t smbcli_req_append_ascii4(struct smbcli_request *req, const char *str, unsigned int flags)
521 size_t size;
522 smbcli_req_append_bytes(req, (const uint8_t *)"\4", 1);
523 size = smbcli_req_append_string(req, str, flags);
524 return size + 1;
529 push a blob into the data portion of the request packet, growing it if necessary
530 this gets quite tricky - please be very careful to cover all cases when modifying this
532 if dest is NULL, then put the blob at the end of the data portion of the packet
534 size_t smbcli_req_append_blob(struct smbcli_request *req, const DATA_BLOB *blob)
536 smbcli_req_grow_allocation(req, req->out.data_size + blob->length);
537 memcpy(req->out.data + req->out.data_size, blob->data, blob->length);
538 smbcli_req_grow_data(req, req->out.data_size + blob->length);
539 return blob->length;
543 append raw bytes into the data portion of the request packet
544 return the number of bytes added
546 size_t smbcli_req_append_bytes(struct smbcli_request *req, const uint8_t *bytes, size_t byte_len)
548 smbcli_req_grow_allocation(req, byte_len + req->out.data_size);
549 memcpy(req->out.data + req->out.data_size, bytes, byte_len);
550 smbcli_req_grow_data(req, byte_len + req->out.data_size);
551 return byte_len;
555 append variable block (type 5 buffer) into the data portion of the request packet
556 return the number of bytes added
558 size_t smbcli_req_append_var_block(struct smbcli_request *req, const uint8_t *bytes, uint16_t byte_len)
560 smbcli_req_grow_allocation(req, byte_len + 3 + req->out.data_size);
561 SCVAL(req->out.data + req->out.data_size, 0, 5);
562 SSVAL(req->out.data + req->out.data_size, 1, byte_len); /* add field length */
563 if (byte_len > 0) {
564 memcpy(req->out.data + req->out.data_size + 3, bytes, byte_len);
566 smbcli_req_grow_data(req, byte_len + 3 + req->out.data_size);
567 return byte_len + 3;
572 pull a UCS2 string from a request packet, returning a talloced unix string
574 the string length is limited by the 3 things:
575 - the data size in the request (end of packet)
576 - the passed 'byte_len' if it is not -1
577 - the end of string (null termination)
579 Note that 'byte_len' is the number of bytes in the packet
581 on failure zero is returned and *dest is set to NULL, otherwise the number
582 of bytes consumed in the packet is returned
584 static size_t smbcli_req_pull_ucs2(struct request_bufinfo *bufinfo, TALLOC_CTX *mem_ctx,
585 char **dest, const uint8_t *src, int byte_len, unsigned int flags)
587 int src_len, src_len2, alignment=0;
588 bool ret;
589 size_t ret_size;
591 if (!(flags & STR_NOALIGN) && ucs2_align(bufinfo->align_base, src, flags)) {
592 src++;
593 alignment=1;
594 if (byte_len != -1) {
595 byte_len--;
599 src_len = bufinfo->data_size - PTR_DIFF(src, bufinfo->data);
600 if (src_len < 0) {
601 *dest = NULL;
602 return 0;
604 if (byte_len != -1 && src_len > byte_len) {
605 src_len = byte_len;
608 src_len2 = utf16_len_n(src, src_len);
610 /* ucs2 strings must be at least 2 bytes long */
611 if (src_len2 < 2) {
612 *dest = NULL;
613 return 0;
616 ret = convert_string_talloc(mem_ctx, CH_UTF16, CH_UNIX, src, src_len2, (void **)dest, &ret_size);
617 if (!ret) {
618 *dest = NULL;
619 return 0;
622 return src_len2 + alignment;
626 pull a ascii string from a request packet, returning a talloced string
628 the string length is limited by the 3 things:
629 - the data size in the request (end of packet)
630 - the passed 'byte_len' if it is not -1
631 - the end of string (null termination)
633 Note that 'byte_len' is the number of bytes in the packet
635 on failure zero is returned and *dest is set to NULL, otherwise the number
636 of bytes consumed in the packet is returned
638 size_t smbcli_req_pull_ascii(struct request_bufinfo *bufinfo, TALLOC_CTX *mem_ctx,
639 char **dest, const uint8_t *src, int byte_len, unsigned int flags)
641 int src_len, src_len2;
642 bool ret;
643 size_t ret_size;
645 src_len = bufinfo->data_size - PTR_DIFF(src, bufinfo->data);
646 if (src_len < 0) {
647 *dest = NULL;
648 return 0;
650 if (byte_len != -1 && src_len > byte_len) {
651 src_len = byte_len;
653 src_len2 = strnlen((const char *)src, src_len);
654 if (src_len2 < src_len - 1) {
655 /* include the termination if we didn't reach the end of the packet */
656 src_len2++;
659 ret = convert_string_talloc(mem_ctx, CH_DOS, CH_UNIX, src, src_len2, (void **)dest, &ret_size);
661 if (!ret) {
662 *dest = NULL;
663 return 0;
666 return ret_size;
670 pull a string from a request packet, returning a talloced string
672 the string length is limited by the 3 things:
673 - the data size in the request (end of packet)
674 - the passed 'byte_len' if it is not -1
675 - the end of string (null termination)
677 Note that 'byte_len' is the number of bytes in the packet
679 on failure zero is returned and *dest is set to NULL, otherwise the number
680 of bytes consumed in the packet is returned
682 size_t smbcli_req_pull_string(struct request_bufinfo *bufinfo, TALLOC_CTX *mem_ctx,
683 char **dest, const uint8_t *src, int byte_len, unsigned int flags)
685 if (!(flags & STR_ASCII) &&
686 (((flags & STR_UNICODE) || (bufinfo->flags & BUFINFO_FLAG_UNICODE)))) {
687 return smbcli_req_pull_ucs2(bufinfo, mem_ctx, dest, src, byte_len, flags);
690 return smbcli_req_pull_ascii(bufinfo, mem_ctx, dest, src, byte_len, flags);
695 pull a DATA_BLOB from a reply packet, returning a talloced blob
696 make sure we don't go past end of packet
698 if byte_len is -1 then limit the blob only by packet size
700 DATA_BLOB smbcli_req_pull_blob(struct request_bufinfo *bufinfo, TALLOC_CTX *mem_ctx, const uint8_t *src, int byte_len)
702 int src_len;
704 src_len = bufinfo->data_size - PTR_DIFF(src, bufinfo->data);
706 if (src_len < 0) {
707 return data_blob(NULL, 0);
710 if (byte_len != -1 && src_len > byte_len) {
711 src_len = byte_len;
714 return data_blob_talloc(mem_ctx, src, src_len);
717 /* check that a lump of data in a request is within the bounds of the data section of
718 the packet */
719 static bool smbcli_req_data_oob(struct request_bufinfo *bufinfo, const uint8_t *ptr, uint32_t count)
721 /* be careful with wraparound! */
722 if ((uintptr_t)ptr < (uintptr_t)bufinfo->data ||
723 (uintptr_t)ptr >= (uintptr_t)bufinfo->data + bufinfo->data_size ||
724 count > bufinfo->data_size ||
725 (uintptr_t)ptr + count > (uintptr_t)bufinfo->data + bufinfo->data_size) {
726 return true;
728 return false;
732 pull a lump of data from a request packet
734 return false if any part is outside the data portion of the packet
736 bool smbcli_raw_pull_data(struct request_bufinfo *bufinfo, const uint8_t *src, int len, uint8_t *dest)
738 if (len == 0) return true;
740 if (smbcli_req_data_oob(bufinfo, src, len)) {
741 return false;
744 memcpy(dest, src, len);
745 return true;
750 put a NTTIME into a packet
752 void smbcli_push_nttime(void *base, uint16_t offset, NTTIME t)
754 SBVAL(base, offset, t);
758 pull a NTTIME from a packet
760 NTTIME smbcli_pull_nttime(void *base, uint16_t offset)
762 NTTIME ret = BVAL(base, offset);
763 return ret;
767 pull a UCS2 string from a blob, returning a talloced unix string
769 the string length is limited by the 3 things:
770 - the data size in the blob
771 - the passed 'byte_len' if it is not -1
772 - the end of string (null termination)
774 Note that 'byte_len' is the number of bytes in the packet
776 on failure zero is returned and *dest is set to NULL, otherwise the number
777 of bytes consumed in the blob is returned
779 size_t smbcli_blob_pull_ucs2(TALLOC_CTX* mem_ctx,
780 const DATA_BLOB *blob, const char **dest,
781 const uint8_t *src, int byte_len, unsigned int flags)
783 int src_len, src_len2, alignment=0;
784 size_t ret_size;
785 bool ret;
786 char *dest2;
788 if (src < blob->data ||
789 src >= (blob->data + blob->length)) {
790 *dest = NULL;
791 return 0;
794 src_len = blob->length - PTR_DIFF(src, blob->data);
796 if (byte_len != -1 && src_len > byte_len) {
797 src_len = byte_len;
800 if (!(flags & STR_NOALIGN) && ucs2_align(blob->data, src, flags)) {
801 src++;
802 alignment=1;
803 src_len--;
806 if (src_len < 2) {
807 *dest = NULL;
808 return 0;
811 src_len2 = utf16_len_n(src, src_len);
813 ret = convert_string_talloc(mem_ctx, CH_UTF16, CH_UNIX, src, src_len2, (void **)&dest2, &ret_size);
814 if (!ret) {
815 *dest = NULL;
816 return 0;
818 *dest = dest2;
820 return src_len2 + alignment;
824 pull a ascii string from a blob, returning a talloced string
826 the string length is limited by the 3 things:
827 - the data size in the blob
828 - the passed 'byte_len' if it is not -1
829 - the end of string (null termination)
831 Note that 'byte_len' is the number of bytes in the blob
833 on failure zero is returned and *dest is set to NULL, otherwise the number
834 of bytes consumed in the blob is returned
836 static size_t smbcli_blob_pull_ascii(TALLOC_CTX *mem_ctx,
837 const DATA_BLOB *blob, const char **dest,
838 const uint8_t *src, int byte_len, unsigned int flags)
840 int src_len, src_len2;
841 size_t ret_size;
842 bool ret;
843 char *dest2;
845 src_len = blob->length - PTR_DIFF(src, blob->data);
846 if (src_len < 0) {
847 *dest = NULL;
848 return 0;
850 if (byte_len != -1 && src_len > byte_len) {
851 src_len = byte_len;
853 src_len2 = strnlen((const char *)src, src_len);
855 if (src_len2 < src_len - 1) {
856 /* include the termination if we didn't reach the end of the packet */
857 src_len2++;
860 ret = convert_string_talloc(mem_ctx, CH_DOS, CH_UNIX, src, src_len2, (void **)&dest2, &ret_size);
862 if (!ret) {
863 *dest = NULL;
864 return 0;
866 *dest = dest2;
868 return ret_size;
872 pull a string from a blob, returning a talloced struct smb_wire_string
874 the string length is limited by the 3 things:
875 - the data size in the blob
876 - length field on the wire
877 - the end of string (null termination)
879 if STR_LEN8BIT is set in the flags then assume the length field is
880 8 bits, instead of 32
882 on failure zero is returned and dest->s is set to NULL, otherwise the number
883 of bytes consumed in the blob is returned
885 size_t smbcli_blob_pull_string(struct smbcli_session *session,
886 TALLOC_CTX *mem_ctx,
887 const DATA_BLOB *blob,
888 struct smb_wire_string *dest,
889 uint16_t len_offset, uint16_t str_offset,
890 unsigned int flags)
892 int extra;
893 dest->s = NULL;
895 if (!(flags & STR_ASCII)) {
896 /* this is here to cope with SMB2 calls using the SMB
897 parsers. SMB2 will pass smbcli_session==NULL, which forces
898 unicode on (as used by SMB2) */
899 if (session == NULL) {
900 flags |= STR_UNICODE;
901 } else if (session->transport->negotiate.capabilities & CAP_UNICODE) {
902 flags |= STR_UNICODE;
906 if (flags & STR_LEN8BIT) {
907 if (len_offset > blob->length-1) {
908 return 0;
910 dest->private_length = CVAL(blob->data, len_offset);
911 } else {
912 if (len_offset > blob->length-4) {
913 return 0;
915 dest->private_length = IVAL(blob->data, len_offset);
917 extra = 0;
918 dest->s = NULL;
919 if (!(flags & STR_ASCII) && (flags & STR_UNICODE)) {
920 int align = 0;
921 if ((str_offset&1) && !(flags & STR_NOALIGN)) {
922 align = 1;
924 if (flags & STR_LEN_NOTERM) {
925 extra = 2;
927 return align + extra + smbcli_blob_pull_ucs2(mem_ctx, blob, &dest->s,
928 blob->data+str_offset+align,
929 dest->private_length, flags);
932 if (flags & STR_LEN_NOTERM) {
933 extra = 1;
936 return extra + smbcli_blob_pull_ascii(mem_ctx, blob, &dest->s,
937 blob->data+str_offset, dest->private_length, flags);
941 pull a string from a blob, returning a talloced char *
943 Currently only used by the UNIX search info level.
945 the string length is limited by 2 things:
946 - the data size in the blob
947 - the end of string (null termination)
949 on failure zero is returned and dest->s is set to NULL, otherwise the number
950 of bytes consumed in the blob is returned
952 size_t smbcli_blob_pull_unix_string(struct smbcli_session *session,
953 TALLOC_CTX *mem_ctx,
954 DATA_BLOB *blob,
955 const char **dest,
956 uint16_t str_offset,
957 unsigned int flags)
959 int extra = 0;
960 *dest = NULL;
962 if (!(flags & STR_ASCII) &&
963 ((flags & STR_UNICODE) ||
964 (session->transport->negotiate.capabilities & CAP_UNICODE))) {
965 int align = 0;
966 if ((str_offset&1) && !(flags & STR_NOALIGN)) {
967 align = 1;
969 if (flags & STR_LEN_NOTERM) {
970 extra = 2;
972 return align + extra + smbcli_blob_pull_ucs2(mem_ctx, blob, dest,
973 blob->data+str_offset+align,
974 -1, flags);
977 if (flags & STR_LEN_NOTERM) {
978 extra = 1;
981 return extra + smbcli_blob_pull_ascii(mem_ctx, blob, dest,
982 blob->data+str_offset, -1, flags);
987 append a string into a blob
989 size_t smbcli_blob_append_string(struct smbcli_session *session,
990 TALLOC_CTX *mem_ctx, DATA_BLOB *blob,
991 const char *str, unsigned int flags)
993 size_t max_len;
994 int len;
996 if (!str) return 0;
998 /* determine string type to use */
999 if (!(flags & (STR_ASCII|STR_UNICODE))) {
1000 flags |= (session->transport->negotiate.capabilities & CAP_UNICODE) ? STR_UNICODE : STR_ASCII;
1003 max_len = (strlen(str)+2) * MAX_BYTES_PER_CHAR;
1005 blob->data = talloc_realloc(mem_ctx, blob->data, uint8_t, blob->length + max_len);
1006 if (!blob->data) {
1007 return 0;
1010 len = push_string(blob->data + blob->length, str, max_len, flags);
1012 blob->length += len;
1014 return len;
1018 pull a GUID structure from the wire. The buffer must be at least 16
1019 bytes long
1021 NTSTATUS smbcli_pull_guid(void *base, uint16_t offset,
1022 struct GUID *guid)
1024 DATA_BLOB blob;
1026 ZERO_STRUCTP(guid);
1028 blob.data = offset + (uint8_t *)base;
1029 blob.length = 16;
1031 return GUID_from_ndr_blob(&blob, guid);
1035 push a guid onto the wire. The buffer must hold 16 bytes
1037 NTSTATUS smbcli_push_guid(void *base, uint16_t offset, const struct GUID *guid)
1039 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
1040 NTSTATUS status;
1041 DATA_BLOB blob;
1042 status = GUID_to_ndr_blob(guid, tmp_ctx, &blob);
1043 if (!NT_STATUS_IS_OK(status)) {
1044 talloc_free(tmp_ctx);
1045 return status;
1047 memcpy(offset + (uint8_t *)base, blob.data, blob.length);
1048 talloc_free(tmp_ctx);
1049 return NT_STATUS_OK;