lib/replace: define HAVE_WORKING_STRPTIME instead of REPLACE_STRPTIME
[Samba/gebeck_regimport.git] / source4 / libcli / raw / rawrequest.c
blob1b4c8c7524aa926a21217e0002b6d611cd39a2ae
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 req->session = session;
151 SSVAL(req->out.hdr, HDR_FLG2, session->flags2);
152 SSVAL(req->out.hdr, HDR_PID, session->pid & 0xFFFF);
153 SSVAL(req->out.hdr, HDR_PIDHIGH, session->pid >> 16);
154 SSVAL(req->out.hdr, HDR_UID, session->vuid);
156 return req;
160 setup a request for tree based commands
162 struct smbcli_request *smbcli_request_setup(struct smbcli_tree *tree,
163 uint8_t command,
164 unsigned int wct, unsigned int buflen)
166 struct smbcli_request *req;
168 req = smbcli_request_setup_session(tree->session, command, wct, buflen);
169 if (req) {
170 req->tree = tree;
171 SSVAL(req->out.hdr,HDR_TID,tree->tid);
173 return req;
178 grow the allocation of the data buffer portion of a reply
179 packet. Note that as this can reallocate the packet buffer this
180 invalidates any local pointers into the packet.
182 To cope with this req->out.ptr is supplied. This will be updated to
183 point at the same offset into the packet as before this call
185 static void smbcli_req_grow_allocation(struct smbcli_request *req, unsigned int new_size)
187 int delta;
188 uint8_t *buf2;
190 delta = new_size - req->out.data_size;
191 if (delta + req->out.size <= req->out.allocated) {
192 /* it fits in the preallocation */
193 return;
196 /* we need to realloc */
197 req->out.allocated = req->out.size + delta + REQ_OVER_ALLOCATION;
198 buf2 = talloc_realloc(req, req->out.buffer, uint8_t, req->out.allocated);
199 if (buf2 == NULL) {
200 smb_panic("out of memory in req_grow_allocation");
203 if (buf2 == req->out.buffer) {
204 /* the malloc library gave us the same pointer */
205 return;
208 /* update the pointers into the packet */
209 req->out.data = buf2 + PTR_DIFF(req->out.data, req->out.buffer);
210 req->out.ptr = buf2 + PTR_DIFF(req->out.ptr, req->out.buffer);
211 req->out.vwv = buf2 + PTR_DIFF(req->out.vwv, req->out.buffer);
212 req->out.hdr = buf2 + PTR_DIFF(req->out.hdr, req->out.buffer);
214 req->out.buffer = buf2;
219 grow the data buffer portion of a reply packet. Note that as this
220 can reallocate the packet buffer this invalidates any local pointers
221 into the packet.
223 To cope with this req->out.ptr is supplied. This will be updated to
224 point at the same offset into the packet as before this call
226 static void smbcli_req_grow_data(struct smbcli_request *req, unsigned int new_size)
228 int delta;
230 smbcli_req_grow_allocation(req, new_size);
232 delta = new_size - req->out.data_size;
234 req->out.size += delta;
235 req->out.data_size += delta;
237 /* set the BCC to the new data size */
238 SSVAL(req->out.vwv, VWV(req->out.wct), new_size);
243 setup a chained reply in req->out with the given word count and
244 initial data buffer size.
246 NTSTATUS smbcli_chained_request_setup(struct smbcli_request *req,
247 uint8_t command,
248 unsigned int wct, size_t buflen)
250 size_t wct_ofs;
251 size_t size;
254 * here we only support one chained command
255 * If someone needs longer chains, the low
256 * level code should be used directly.
258 if (req->subreqs[0] != NULL) {
259 return NT_STATUS_INVALID_PARAMETER_MIX;
261 if (req->subreqs[1] != NULL) {
262 return NT_STATUS_INVALID_PARAMETER_MIX;
265 req->subreqs[0] = smbcli_transport_setup_subreq(req);
266 if (req->subreqs[0] == NULL) {
267 return NT_STATUS_NO_MEMORY;
270 wct_ofs = smb1cli_req_wct_ofs(req->subreqs, 1);
272 size = NBT_HDR_SIZE + wct_ofs + 1 + VWV(wct) + 2 + buflen;
274 req->out.size = size;
276 /* over allocate by a small amount */
277 req->out.allocated = req->out.size + REQ_OVER_ALLOCATION;
279 req->out.buffer = talloc_zero_array(req, uint8_t, req->out.allocated);
280 if (!req->out.buffer) {
281 return NT_STATUS_NO_MEMORY;
284 req->out.hdr = req->out.buffer + NBT_HDR_SIZE;
285 req->out.vwv = req->out.hdr + wct_ofs;
286 req->out.wct = wct;
287 req->out.data = req->out.vwv + VWV(wct) + 2;
288 req->out.data_size = buflen;
289 req->out.ptr = req->out.data;
291 SCVAL(req->out.hdr, HDR_WCT, wct);
292 SSVAL(req->out.vwv, VWV(wct), buflen);
294 memcpy(req->out.hdr, "\377SMB", 4);
295 SCVAL(req->out.hdr,HDR_COM,command);
297 SCVAL(req->out.hdr,HDR_FLG, FLAG_CASELESS_PATHNAMES);
298 SSVAL(req->out.hdr,HDR_FLG2, 0);
300 /* copy the pid, uid and mid to the request */
301 SSVAL(req->out.hdr, HDR_PID, 0);
302 SSVAL(req->out.hdr, HDR_UID, 0);
303 SSVAL(req->out.hdr, HDR_MID, 0);
304 SSVAL(req->out.hdr, HDR_TID,0);
305 SSVAL(req->out.hdr, HDR_PIDHIGH,0);
306 SIVAL(req->out.hdr, HDR_RCLS, 0);
307 memset(req->out.hdr+HDR_SS_FIELD, 0, 10);
309 if (req->session != NULL) {
310 SSVAL(req->out.hdr, HDR_FLG2, req->session->flags2);
311 SSVAL(req->out.hdr, HDR_PID, req->session->pid & 0xFFFF);
312 SSVAL(req->out.hdr, HDR_PIDHIGH, req->session->pid >> 16);
313 SSVAL(req->out.hdr, HDR_UID, req->session->vuid);
316 if (req->tree != NULL) {
317 SSVAL(req->out.hdr, HDR_TID, req->tree->tid);
320 return NT_STATUS_OK;
324 advance to the next chained reply in a request
326 NTSTATUS smbcli_chained_advance(struct smbcli_request *req)
328 struct smbcli_transport *transport = req->transport;
329 uint8_t *hdr = NULL;
330 uint8_t wct = 0;
331 uint16_t *vwv = NULL;
332 uint32_t num_bytes = 0;
333 uint8_t *bytes = NULL;
334 struct iovec *recv_iov = NULL;
335 uint8_t *inbuf = NULL;
337 if (req->subreqs[0] != NULL) {
338 return NT_STATUS_INVALID_PARAMETER_MIX;
340 if (req->subreqs[1] == NULL) {
341 return NT_STATUS_INVALID_PARAMETER_MIX;
344 req->status = smb1cli_req_recv(req->subreqs[1], req,
345 &recv_iov,
346 &hdr,
347 &wct,
348 &vwv,
349 NULL, /* pvwv_offset */
350 &num_bytes,
351 &bytes,
352 NULL, /* pbytes_offset */
353 &inbuf,
354 NULL, 0); /* expected */
355 TALLOC_FREE(req->subreqs[1]);
356 if (!NT_STATUS_IS_OK(req->status)) {
357 if (recv_iov == NULL) {
358 req->state = SMBCLI_REQUEST_ERROR;
359 return req->status;
363 /* fill in the 'in' portion of the matching request */
364 req->in.buffer = inbuf;
365 req->in.size = NBT_HDR_SIZE + PTR_DIFF(bytes, hdr) + num_bytes;
366 req->in.allocated = req->in.size;
368 req->in.hdr = hdr;
369 req->in.vwv = (uint8_t *)vwv;
370 req->in.wct = wct;
371 req->in.data = bytes;
372 req->in.data_size = num_bytes;
373 req->in.ptr = req->in.data;
374 req->flags2 = SVAL(req->in.hdr, HDR_FLG2);
376 smb_setup_bufinfo(req);
378 transport->error.e.nt_status = req->status;
379 if (NT_STATUS_IS_OK(req->status)) {
380 transport->error.etype = ETYPE_NONE;
381 } else {
382 transport->error.etype = ETYPE_SMB;
385 req->state = SMBCLI_REQUEST_DONE;
387 return NT_STATUS_OK;
392 send a message
394 bool smbcli_request_send(struct smbcli_request *req)
396 smbcli_transport_send(req);
397 return true;
402 receive a response to a packet
404 bool smbcli_request_receive(struct smbcli_request *req)
406 /* req can be NULL when a send has failed. This eliminates lots of NULL
407 checks in each module */
408 if (!req) return false;
410 /* keep receiving packets until this one is replied to */
411 while (req->state <= SMBCLI_REQUEST_RECV) {
412 if (tevent_loop_once(req->transport->ev) != 0) {
413 return false;
417 return req->state == SMBCLI_REQUEST_DONE;
421 wait for a reply to be received for a packet that just returns an error
422 code and nothing more
424 _PUBLIC_ NTSTATUS smbcli_request_simple_recv(struct smbcli_request *req)
426 (void) smbcli_request_receive(req);
427 return smbcli_request_destroy(req);
431 /* Return true if the last packet was in error */
432 bool smbcli_request_is_error(struct smbcli_request *req)
434 return NT_STATUS_IS_ERR(req->status);
438 append a string into the data portion of the request packet
440 return the number of bytes added to the packet
442 size_t smbcli_req_append_string(struct smbcli_request *req, const char *str, unsigned int flags)
444 size_t len;
446 /* determine string type to use */
447 if (!(flags & (STR_ASCII|STR_UNICODE))) {
448 flags |= (req->transport->negotiate.capabilities & CAP_UNICODE) ? STR_UNICODE : STR_ASCII;
451 len = (strlen(str)+2) * MAX_BYTES_PER_CHAR;
453 smbcli_req_grow_allocation(req, len + req->out.data_size);
455 len = push_string(req->out.data + req->out.data_size, str, len, flags);
457 smbcli_req_grow_data(req, len + req->out.data_size);
459 return len;
464 this is like smbcli_req_append_string but it also return the
465 non-terminated string byte length, which can be less than the number
466 of bytes consumed in the packet for 2 reasons:
468 1) the string in the packet may be null terminated
469 2) the string in the packet may need a 1 byte UCS2 alignment
471 this is used in places where the non-terminated string byte length is
472 placed in the packet as a separate field
474 size_t smbcli_req_append_string_len(struct smbcli_request *req, const char *str, unsigned int flags, int *len)
476 int diff = 0;
477 size_t ret;
479 /* determine string type to use */
480 if (!(flags & (STR_ASCII|STR_UNICODE))) {
481 flags |= (req->transport->negotiate.capabilities & CAP_UNICODE) ? STR_UNICODE : STR_ASCII;
484 /* see if an alignment byte will be used */
485 if ((flags & STR_UNICODE) && !(flags & STR_NOALIGN)) {
486 diff = ucs2_align(NULL, req->out.data + req->out.data_size, flags);
489 /* do the hard work */
490 ret = smbcli_req_append_string(req, str, flags);
492 /* see if we need to subtract the termination */
493 if (flags & STR_TERMINATE) {
494 diff += (flags & STR_UNICODE) ? 2 : 1;
497 if (ret >= diff) {
498 (*len) = ret - diff;
499 } else {
500 (*len) = ret;
503 return ret;
508 push a string into the data portion of the request packet, growing it if necessary
509 this gets quite tricky - please be very careful to cover all cases when modifying this
511 if dest is NULL, then put the string at the end of the data portion of the packet
513 if dest_len is -1 then no limit applies
515 size_t smbcli_req_append_ascii4(struct smbcli_request *req, const char *str, unsigned int flags)
517 size_t size;
518 smbcli_req_append_bytes(req, (const uint8_t *)"\4", 1);
519 size = smbcli_req_append_string(req, str, flags);
520 return size + 1;
525 push a blob into the data portion of the request packet, growing it if necessary
526 this gets quite tricky - please be very careful to cover all cases when modifying this
528 if dest is NULL, then put the blob at the end of the data portion of the packet
530 size_t smbcli_req_append_blob(struct smbcli_request *req, const DATA_BLOB *blob)
532 smbcli_req_grow_allocation(req, req->out.data_size + blob->length);
533 memcpy(req->out.data + req->out.data_size, blob->data, blob->length);
534 smbcli_req_grow_data(req, req->out.data_size + blob->length);
535 return blob->length;
539 append raw bytes into the data portion of the request packet
540 return the number of bytes added
542 size_t smbcli_req_append_bytes(struct smbcli_request *req, const uint8_t *bytes, size_t byte_len)
544 smbcli_req_grow_allocation(req, byte_len + req->out.data_size);
545 memcpy(req->out.data + req->out.data_size, bytes, byte_len);
546 smbcli_req_grow_data(req, byte_len + req->out.data_size);
547 return byte_len;
551 append variable block (type 5 buffer) into the data portion of the request packet
552 return the number of bytes added
554 size_t smbcli_req_append_var_block(struct smbcli_request *req, const uint8_t *bytes, uint16_t byte_len)
556 smbcli_req_grow_allocation(req, byte_len + 3 + req->out.data_size);
557 SCVAL(req->out.data + req->out.data_size, 0, 5);
558 SSVAL(req->out.data + req->out.data_size, 1, byte_len); /* add field length */
559 if (byte_len > 0) {
560 memcpy(req->out.data + req->out.data_size + 3, bytes, byte_len);
562 smbcli_req_grow_data(req, byte_len + 3 + req->out.data_size);
563 return byte_len + 3;
568 pull a UCS2 string from a request packet, returning a talloced unix string
570 the string length is limited by the 3 things:
571 - the data size in the request (end of packet)
572 - the passed 'byte_len' if it is not -1
573 - the end of string (null termination)
575 Note that 'byte_len' is the number of bytes in the packet
577 on failure zero is returned and *dest is set to NULL, otherwise the number
578 of bytes consumed in the packet is returned
580 static size_t smbcli_req_pull_ucs2(struct request_bufinfo *bufinfo, TALLOC_CTX *mem_ctx,
581 char **dest, const uint8_t *src, int byte_len, unsigned int flags)
583 int src_len, src_len2, alignment=0;
584 bool ret;
585 size_t ret_size;
587 if (!(flags & STR_NOALIGN) && ucs2_align(bufinfo->align_base, src, flags)) {
588 src++;
589 alignment=1;
590 if (byte_len != -1) {
591 byte_len--;
595 src_len = bufinfo->data_size - PTR_DIFF(src, bufinfo->data);
596 if (src_len < 0) {
597 *dest = NULL;
598 return 0;
600 if (byte_len != -1 && src_len > byte_len) {
601 src_len = byte_len;
604 src_len2 = utf16_len_n(src, src_len);
606 /* ucs2 strings must be at least 2 bytes long */
607 if (src_len2 < 2) {
608 *dest = NULL;
609 return 0;
612 ret = convert_string_talloc(mem_ctx, CH_UTF16, CH_UNIX, src, src_len2, (void **)dest, &ret_size);
613 if (!ret) {
614 *dest = NULL;
615 return 0;
618 return src_len2 + alignment;
622 pull a ascii string from a request packet, returning a talloced string
624 the string length is limited by the 3 things:
625 - the data size in the request (end of packet)
626 - the passed 'byte_len' if it is not -1
627 - the end of string (null termination)
629 Note that 'byte_len' is the number of bytes in the packet
631 on failure zero is returned and *dest is set to NULL, otherwise the number
632 of bytes consumed in the packet is returned
634 size_t smbcli_req_pull_ascii(struct request_bufinfo *bufinfo, TALLOC_CTX *mem_ctx,
635 char **dest, const uint8_t *src, int byte_len, unsigned int flags)
637 int src_len, src_len2;
638 bool ret;
639 size_t ret_size;
641 src_len = bufinfo->data_size - PTR_DIFF(src, bufinfo->data);
642 if (src_len < 0) {
643 *dest = NULL;
644 return 0;
646 if (byte_len != -1 && src_len > byte_len) {
647 src_len = byte_len;
649 src_len2 = strnlen((const char *)src, src_len);
650 if (src_len2 < src_len - 1) {
651 /* include the termination if we didn't reach the end of the packet */
652 src_len2++;
655 ret = convert_string_talloc(mem_ctx, CH_DOS, CH_UNIX, src, src_len2, (void **)dest, &ret_size);
657 if (!ret) {
658 *dest = NULL;
659 return 0;
662 return ret_size;
666 pull a string from a request packet, returning a talloced string
668 the string length is limited by the 3 things:
669 - the data size in the request (end of packet)
670 - the passed 'byte_len' if it is not -1
671 - the end of string (null termination)
673 Note that 'byte_len' is the number of bytes in the packet
675 on failure zero is returned and *dest is set to NULL, otherwise the number
676 of bytes consumed in the packet is returned
678 size_t smbcli_req_pull_string(struct request_bufinfo *bufinfo, TALLOC_CTX *mem_ctx,
679 char **dest, const uint8_t *src, int byte_len, unsigned int flags)
681 if (!(flags & STR_ASCII) &&
682 (((flags & STR_UNICODE) || (bufinfo->flags & BUFINFO_FLAG_UNICODE)))) {
683 return smbcli_req_pull_ucs2(bufinfo, mem_ctx, dest, src, byte_len, flags);
686 return smbcli_req_pull_ascii(bufinfo, mem_ctx, dest, src, byte_len, flags);
691 pull a DATA_BLOB from a reply packet, returning a talloced blob
692 make sure we don't go past end of packet
694 if byte_len is -1 then limit the blob only by packet size
696 DATA_BLOB smbcli_req_pull_blob(struct request_bufinfo *bufinfo, TALLOC_CTX *mem_ctx, const uint8_t *src, int byte_len)
698 int src_len;
700 src_len = bufinfo->data_size - PTR_DIFF(src, bufinfo->data);
702 if (src_len < 0) {
703 return data_blob(NULL, 0);
706 if (byte_len != -1 && src_len > byte_len) {
707 src_len = byte_len;
710 return data_blob_talloc(mem_ctx, src, src_len);
713 /* check that a lump of data in a request is within the bounds of the data section of
714 the packet */
715 static bool smbcli_req_data_oob(struct request_bufinfo *bufinfo, const uint8_t *ptr, uint32_t count)
717 /* be careful with wraparound! */
718 if ((uintptr_t)ptr < (uintptr_t)bufinfo->data ||
719 (uintptr_t)ptr >= (uintptr_t)bufinfo->data + bufinfo->data_size ||
720 count > bufinfo->data_size ||
721 (uintptr_t)ptr + count > (uintptr_t)bufinfo->data + bufinfo->data_size) {
722 return true;
724 return false;
728 pull a lump of data from a request packet
730 return false if any part is outside the data portion of the packet
732 bool smbcli_raw_pull_data(struct request_bufinfo *bufinfo, const uint8_t *src, int len, uint8_t *dest)
734 if (len == 0) return true;
736 if (smbcli_req_data_oob(bufinfo, src, len)) {
737 return false;
740 memcpy(dest, src, len);
741 return true;
746 put a NTTIME into a packet
748 void smbcli_push_nttime(void *base, uint16_t offset, NTTIME t)
750 SBVAL(base, offset, t);
754 pull a NTTIME from a packet
756 NTTIME smbcli_pull_nttime(void *base, uint16_t offset)
758 NTTIME ret = BVAL(base, offset);
759 return ret;
763 pull a UCS2 string from a blob, returning a talloced unix string
765 the string length is limited by the 3 things:
766 - the data size in the blob
767 - the passed 'byte_len' if it is not -1
768 - the end of string (null termination)
770 Note that 'byte_len' is the number of bytes in the packet
772 on failure zero is returned and *dest is set to NULL, otherwise the number
773 of bytes consumed in the blob is returned
775 size_t smbcli_blob_pull_ucs2(TALLOC_CTX* mem_ctx,
776 const DATA_BLOB *blob, const char **dest,
777 const uint8_t *src, int byte_len, unsigned int flags)
779 int src_len, src_len2, alignment=0;
780 size_t ret_size;
781 bool ret;
782 char *dest2;
784 if (src < blob->data ||
785 src >= (blob->data + blob->length)) {
786 *dest = NULL;
787 return 0;
790 src_len = blob->length - PTR_DIFF(src, blob->data);
792 if (byte_len != -1 && src_len > byte_len) {
793 src_len = byte_len;
796 if (!(flags & STR_NOALIGN) && ucs2_align(blob->data, src, flags)) {
797 src++;
798 alignment=1;
799 src_len--;
802 if (src_len < 2) {
803 *dest = NULL;
804 return 0;
807 src_len2 = utf16_len_n(src, src_len);
809 ret = convert_string_talloc(mem_ctx, CH_UTF16, CH_UNIX, src, src_len2, (void **)&dest2, &ret_size);
810 if (!ret) {
811 *dest = NULL;
812 return 0;
814 *dest = dest2;
816 return src_len2 + alignment;
820 pull a ascii string from a blob, returning a talloced string
822 the string length is limited by the 3 things:
823 - the data size in the blob
824 - the passed 'byte_len' if it is not -1
825 - the end of string (null termination)
827 Note that 'byte_len' is the number of bytes in the blob
829 on failure zero is returned and *dest is set to NULL, otherwise the number
830 of bytes consumed in the blob is returned
832 static size_t smbcli_blob_pull_ascii(TALLOC_CTX *mem_ctx,
833 const DATA_BLOB *blob, const char **dest,
834 const uint8_t *src, int byte_len, unsigned int flags)
836 int src_len, src_len2;
837 size_t ret_size;
838 bool ret;
839 char *dest2;
841 src_len = blob->length - PTR_DIFF(src, blob->data);
842 if (src_len < 0) {
843 *dest = NULL;
844 return 0;
846 if (byte_len != -1 && src_len > byte_len) {
847 src_len = byte_len;
849 src_len2 = strnlen((const char *)src, src_len);
851 if (src_len2 < src_len - 1) {
852 /* include the termination if we didn't reach the end of the packet */
853 src_len2++;
856 ret = convert_string_talloc(mem_ctx, CH_DOS, CH_UNIX, src, src_len2, (void **)&dest2, &ret_size);
858 if (!ret) {
859 *dest = NULL;
860 return 0;
862 *dest = dest2;
864 return ret_size;
868 pull a string from a blob, returning a talloced struct smb_wire_string
870 the string length is limited by the 3 things:
871 - the data size in the blob
872 - length field on the wire
873 - the end of string (null termination)
875 if STR_LEN8BIT is set in the flags then assume the length field is
876 8 bits, instead of 32
878 on failure zero is returned and dest->s is set to NULL, otherwise the number
879 of bytes consumed in the blob is returned
881 size_t smbcli_blob_pull_string(struct smbcli_session *session,
882 TALLOC_CTX *mem_ctx,
883 const DATA_BLOB *blob,
884 struct smb_wire_string *dest,
885 uint16_t len_offset, uint16_t str_offset,
886 unsigned int flags)
888 int extra;
889 dest->s = NULL;
891 if (!(flags & STR_ASCII)) {
892 /* this is here to cope with SMB2 calls using the SMB
893 parsers. SMB2 will pass smbcli_session==NULL, which forces
894 unicode on (as used by SMB2) */
895 if (session == NULL) {
896 flags |= STR_UNICODE;
897 } else if (session->transport->negotiate.capabilities & CAP_UNICODE) {
898 flags |= STR_UNICODE;
902 if (flags & STR_LEN8BIT) {
903 if (len_offset > blob->length-1) {
904 return 0;
906 dest->private_length = CVAL(blob->data, len_offset);
907 } else {
908 if (len_offset > blob->length-4) {
909 return 0;
911 dest->private_length = IVAL(blob->data, len_offset);
913 extra = 0;
914 dest->s = NULL;
915 if (!(flags & STR_ASCII) && (flags & STR_UNICODE)) {
916 int align = 0;
917 if ((str_offset&1) && !(flags & STR_NOALIGN)) {
918 align = 1;
920 if (flags & STR_LEN_NOTERM) {
921 extra = 2;
923 return align + extra + smbcli_blob_pull_ucs2(mem_ctx, blob, &dest->s,
924 blob->data+str_offset+align,
925 dest->private_length, flags);
928 if (flags & STR_LEN_NOTERM) {
929 extra = 1;
932 return extra + smbcli_blob_pull_ascii(mem_ctx, blob, &dest->s,
933 blob->data+str_offset, dest->private_length, flags);
937 pull a string from a blob, returning a talloced char *
939 Currently only used by the UNIX search info level.
941 the string length is limited by 2 things:
942 - the data size in the blob
943 - the end of string (null termination)
945 on failure zero is returned and dest->s is set to NULL, otherwise the number
946 of bytes consumed in the blob is returned
948 size_t smbcli_blob_pull_unix_string(struct smbcli_session *session,
949 TALLOC_CTX *mem_ctx,
950 DATA_BLOB *blob,
951 const char **dest,
952 uint16_t str_offset,
953 unsigned int flags)
955 int extra = 0;
956 *dest = NULL;
958 if (!(flags & STR_ASCII) &&
959 ((flags & STR_UNICODE) ||
960 (session->transport->negotiate.capabilities & CAP_UNICODE))) {
961 int align = 0;
962 if ((str_offset&1) && !(flags & STR_NOALIGN)) {
963 align = 1;
965 if (flags & STR_LEN_NOTERM) {
966 extra = 2;
968 return align + extra + smbcli_blob_pull_ucs2(mem_ctx, blob, dest,
969 blob->data+str_offset+align,
970 -1, flags);
973 if (flags & STR_LEN_NOTERM) {
974 extra = 1;
977 return extra + smbcli_blob_pull_ascii(mem_ctx, blob, dest,
978 blob->data+str_offset, -1, flags);
983 append a string into a blob
985 size_t smbcli_blob_append_string(struct smbcli_session *session,
986 TALLOC_CTX *mem_ctx, DATA_BLOB *blob,
987 const char *str, unsigned int flags)
989 size_t max_len;
990 int len;
992 if (!str) return 0;
994 /* determine string type to use */
995 if (!(flags & (STR_ASCII|STR_UNICODE))) {
996 flags |= (session->transport->negotiate.capabilities & CAP_UNICODE) ? STR_UNICODE : STR_ASCII;
999 max_len = (strlen(str)+2) * MAX_BYTES_PER_CHAR;
1001 blob->data = talloc_realloc(mem_ctx, blob->data, uint8_t, blob->length + max_len);
1002 if (!blob->data) {
1003 return 0;
1006 len = push_string(blob->data + blob->length, str, max_len, flags);
1008 blob->length += len;
1010 return len;
1014 pull a GUID structure from the wire. The buffer must be at least 16
1015 bytes long
1017 NTSTATUS smbcli_pull_guid(void *base, uint16_t offset,
1018 struct GUID *guid)
1020 DATA_BLOB blob;
1022 ZERO_STRUCTP(guid);
1024 blob.data = offset + (uint8_t *)base;
1025 blob.length = 16;
1027 return GUID_from_ndr_blob(&blob, guid);
1031 push a guid onto the wire. The buffer must hold 16 bytes
1033 NTSTATUS smbcli_push_guid(void *base, uint16_t offset, const struct GUID *guid)
1035 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
1036 NTSTATUS status;
1037 DATA_BLOB blob;
1038 status = GUID_to_ndr_blob(guid, tmp_ctx, &blob);
1039 if (!NT_STATUS_IS_OK(status)) {
1040 talloc_free(tmp_ctx);
1041 return status;
1043 memcpy(offset + (uint8_t *)base, blob.data, blob.length);
1044 talloc_free(tmp_ctx);
1045 return NT_STATUS_OK;