dns: The QCLASS is called IN, not IP
[Samba/gebeck_regimport.git] / source4 / libcli / raw / rawrequest.c
blobc9b78d726b212d52335779dc38e1a719c8a5bd6d
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/util/dlinklist.h"
29 #include "lib/events/events.h"
30 #include "librpc/ndr/libndr.h"
31 #include "librpc/gen_ndr/ndr_misc.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->transport) {
63 /* remove it from the list of pending requests (a null op if
64 its not in the list) */
65 DLIST_REMOVE(req->transport->pending_recv, req);
68 if (req->state == SMBCLI_REQUEST_ERROR &&
69 NT_STATUS_IS_OK(req->status)) {
70 req->status = NT_STATUS_INTERNAL_ERROR;
73 status = req->status;
75 if (!req->do_not_free) {
76 talloc_free(req);
79 return status;
84 low-level function to setup a request buffer for a non-SMB packet
85 at the transport level
87 struct smbcli_request *smbcli_request_setup_nonsmb(struct smbcli_transport *transport, size_t size)
89 struct smbcli_request *req;
91 req = talloc(transport, struct smbcli_request);
92 if (!req) {
93 return NULL;
95 ZERO_STRUCTP(req);
97 /* setup the request context */
98 req->state = SMBCLI_REQUEST_INIT;
99 req->transport = transport;
100 req->session = NULL;
101 req->tree = NULL;
102 req->out.size = size;
104 /* over allocate by a small amount */
105 req->out.allocated = req->out.size + REQ_OVER_ALLOCATION;
107 req->out.buffer = talloc_array(req, uint8_t, req->out.allocated);
108 if (!req->out.buffer) {
109 return NULL;
112 SIVAL(req->out.buffer, 0, 0);
114 return req;
119 setup a SMB packet at transport level
121 struct smbcli_request *smbcli_request_setup_transport(struct smbcli_transport *transport,
122 uint8_t command, unsigned int wct, unsigned int buflen)
124 struct smbcli_request *req;
126 req = smbcli_request_setup_nonsmb(transport, NBT_HDR_SIZE + MIN_SMB_SIZE + wct*2 + buflen);
128 if (!req) return NULL;
130 req->out.hdr = req->out.buffer + NBT_HDR_SIZE;
131 req->out.vwv = req->out.hdr + HDR_VWV;
132 req->out.wct = wct;
133 req->out.data = req->out.vwv + VWV(wct) + 2;
134 req->out.data_size = buflen;
135 req->out.ptr = req->out.data;
137 SCVAL(req->out.hdr, HDR_WCT, wct);
138 SSVAL(req->out.vwv, VWV(wct), buflen);
140 memcpy(req->out.hdr, "\377SMB", 4);
141 SCVAL(req->out.hdr,HDR_COM,command);
143 SCVAL(req->out.hdr,HDR_FLG, FLAG_CASELESS_PATHNAMES);
144 SSVAL(req->out.hdr,HDR_FLG2, 0);
146 if (command != SMBtranss && command != SMBtranss2) {
147 /* assign a mid */
148 req->mid = smbcli_transport_next_mid(transport);
151 /* copy the pid, uid and mid to the request */
152 SSVAL(req->out.hdr, HDR_PID, 0);
153 SSVAL(req->out.hdr, HDR_UID, 0);
154 SSVAL(req->out.hdr, HDR_MID, req->mid);
155 SSVAL(req->out.hdr, HDR_TID,0);
156 SSVAL(req->out.hdr, HDR_PIDHIGH,0);
157 SIVAL(req->out.hdr, HDR_RCLS, 0);
158 memset(req->out.hdr+HDR_SS_FIELD, 0, 10);
160 return req;
164 setup a reply in req->out with the given word count and initial data
165 buffer size. the caller will then fill in the command words and
166 data before calling smbcli_request_send() to send the reply on its
167 way. This interface is used before a session is setup.
169 struct smbcli_request *smbcli_request_setup_session(struct smbcli_session *session,
170 uint8_t command, unsigned int wct, size_t buflen)
172 struct smbcli_request *req;
174 req = smbcli_request_setup_transport(session->transport, command, wct, buflen);
176 if (!req) return NULL;
178 req->session = session;
180 SSVAL(req->out.hdr, HDR_FLG2, session->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);
185 return req;
189 setup a request for tree based commands
191 struct smbcli_request *smbcli_request_setup(struct smbcli_tree *tree,
192 uint8_t command,
193 unsigned int wct, unsigned int buflen)
195 struct smbcli_request *req;
197 req = smbcli_request_setup_session(tree->session, command, wct, buflen);
198 if (req) {
199 req->tree = tree;
200 SSVAL(req->out.hdr,HDR_TID,tree->tid);
202 return req;
207 grow the allocation of the data buffer portion of a reply
208 packet. Note that as this can reallocate the packet buffer this
209 invalidates any local pointers into the packet.
211 To cope with this req->out.ptr is supplied. This will be updated to
212 point at the same offset into the packet as before this call
214 static void smbcli_req_grow_allocation(struct smbcli_request *req, unsigned int new_size)
216 int delta;
217 uint8_t *buf2;
219 delta = new_size - req->out.data_size;
220 if (delta + req->out.size <= req->out.allocated) {
221 /* it fits in the preallocation */
222 return;
225 /* we need to realloc */
226 req->out.allocated = req->out.size + delta + REQ_OVER_ALLOCATION;
227 buf2 = talloc_realloc(req, req->out.buffer, uint8_t, req->out.allocated);
228 if (buf2 == NULL) {
229 smb_panic("out of memory in req_grow_allocation");
232 if (buf2 == req->out.buffer) {
233 /* the malloc library gave us the same pointer */
234 return;
237 /* update the pointers into the packet */
238 req->out.data = buf2 + PTR_DIFF(req->out.data, req->out.buffer);
239 req->out.ptr = buf2 + PTR_DIFF(req->out.ptr, req->out.buffer);
240 req->out.vwv = buf2 + PTR_DIFF(req->out.vwv, req->out.buffer);
241 req->out.hdr = buf2 + PTR_DIFF(req->out.hdr, req->out.buffer);
243 req->out.buffer = buf2;
248 grow the data buffer portion of a reply packet. Note that as this
249 can reallocate the packet buffer this invalidates any local pointers
250 into the packet.
252 To cope with this req->out.ptr is supplied. This will be updated to
253 point at the same offset into the packet as before this call
255 static void smbcli_req_grow_data(struct smbcli_request *req, unsigned int new_size)
257 int delta;
259 smbcli_req_grow_allocation(req, new_size);
261 delta = new_size - req->out.data_size;
263 req->out.size += delta;
264 req->out.data_size += delta;
266 /* set the BCC to the new data size */
267 SSVAL(req->out.vwv, VWV(req->out.wct), new_size);
272 setup a chained reply in req->out with the given word count and
273 initial data buffer size.
275 NTSTATUS smbcli_chained_request_setup(struct smbcli_request *req,
276 uint8_t command,
277 unsigned int wct, size_t buflen)
279 unsigned int new_size = 1 + (wct*2) + 2 + buflen;
281 SSVAL(req->out.vwv, VWV(0), command);
282 SSVAL(req->out.vwv, VWV(1), req->out.size - NBT_HDR_SIZE);
284 smbcli_req_grow_allocation(req, req->out.data_size + new_size);
286 req->out.vwv = req->out.buffer + req->out.size + 1;
287 SCVAL(req->out.vwv, -1, wct);
288 SSVAL(req->out.vwv, VWV(wct), buflen);
290 req->out.size += new_size;
291 req->out.data_size += new_size;
293 return NT_STATUS_OK;
297 aadvance to the next chained reply in a request
299 NTSTATUS smbcli_chained_advance(struct smbcli_request *req)
301 uint8_t *buffer;
303 if (CVAL(req->in.vwv, VWV(0)) == SMB_CHAIN_NONE) {
304 return NT_STATUS_NOT_FOUND;
307 buffer = req->in.hdr + SVAL(req->in.vwv, VWV(1));
309 if (buffer + 3 > req->in.buffer + req->in.size) {
310 return NT_STATUS_BUFFER_TOO_SMALL;
313 req->in.vwv = buffer + 1;
314 req->in.wct = CVAL(buffer, 0);
315 if (buffer + 3 + req->in.wct*2 > req->in.buffer + req->in.size) {
316 return NT_STATUS_BUFFER_TOO_SMALL;
318 req->in.data = req->in.vwv + 2 + req->in.wct * 2;
319 req->in.data_size = SVAL(req->in.vwv, VWV(req->in.wct));
321 /* fix the bufinfo */
322 smb_setup_bufinfo(req);
324 if (buffer + 3 + req->in.wct*2 + req->in.data_size >
325 req->in.buffer + req->in.size) {
326 return NT_STATUS_BUFFER_TOO_SMALL;
329 return NT_STATUS_OK;
334 send a message
336 bool smbcli_request_send(struct smbcli_request *req)
338 if (IVAL(req->out.buffer, 0) == 0) {
339 _smb_setlen(req->out.buffer, req->out.size - NBT_HDR_SIZE);
342 smbcli_request_calculate_sign_mac(req);
344 smbcli_transport_send(req);
346 return true;
351 receive a response to a packet
353 bool smbcli_request_receive(struct smbcli_request *req)
355 /* req can be NULL when a send has failed. This eliminates lots of NULL
356 checks in each module */
357 if (!req) return false;
359 /* keep receiving packets until this one is replied to */
360 while (req->state <= SMBCLI_REQUEST_RECV) {
361 if (tevent_loop_once(req->transport->socket->event.ctx) != 0) {
362 return false;
366 return req->state == SMBCLI_REQUEST_DONE;
371 handle oplock break requests from the server - return true if the request was
372 an oplock break
374 bool smbcli_handle_oplock_break(struct smbcli_transport *transport, unsigned int len, const uint8_t *hdr, const uint8_t *vwv)
376 /* we must be very fussy about what we consider an oplock break to avoid
377 matching readbraw replies */
378 if (len != MIN_SMB_SIZE + VWV(8) + NBT_HDR_SIZE ||
379 (CVAL(hdr, HDR_FLG) & FLAG_REPLY) ||
380 CVAL(hdr,HDR_COM) != SMBlockingX ||
381 SVAL(hdr, HDR_MID) != 0xFFFF ||
382 SVAL(vwv,VWV(6)) != 0 ||
383 SVAL(vwv,VWV(7)) != 0) {
384 return false;
387 if (transport->oplock.handler) {
388 uint16_t tid = SVAL(hdr, HDR_TID);
389 uint16_t fnum = SVAL(vwv,VWV(2));
390 uint8_t level = CVAL(vwv,VWV(3)+1);
391 transport->oplock.handler(transport, tid, fnum, level, transport->oplock.private_data);
394 return true;
398 wait for a reply to be received for a packet that just returns an error
399 code and nothing more
401 _PUBLIC_ NTSTATUS smbcli_request_simple_recv(struct smbcli_request *req)
403 (void) smbcli_request_receive(req);
404 return smbcli_request_destroy(req);
408 /* Return true if the last packet was in error */
409 bool smbcli_request_is_error(struct smbcli_request *req)
411 return NT_STATUS_IS_ERR(req->status);
415 append a string into the data portion of the request packet
417 return the number of bytes added to the packet
419 size_t smbcli_req_append_string(struct smbcli_request *req, const char *str, unsigned int flags)
421 size_t len;
423 /* determine string type to use */
424 if (!(flags & (STR_ASCII|STR_UNICODE))) {
425 flags |= (req->transport->negotiate.capabilities & CAP_UNICODE) ? STR_UNICODE : STR_ASCII;
428 len = (strlen(str)+2) * MAX_BYTES_PER_CHAR;
430 smbcli_req_grow_allocation(req, len + req->out.data_size);
432 len = push_string(req->out.data + req->out.data_size, str, len, flags);
434 smbcli_req_grow_data(req, len + req->out.data_size);
436 return len;
441 this is like smbcli_req_append_string but it also return the
442 non-terminated string byte length, which can be less than the number
443 of bytes consumed in the packet for 2 reasons:
445 1) the string in the packet may be null terminated
446 2) the string in the packet may need a 1 byte UCS2 alignment
448 this is used in places where the non-terminated string byte length is
449 placed in the packet as a separate field
451 size_t smbcli_req_append_string_len(struct smbcli_request *req, const char *str, unsigned int flags, int *len)
453 int diff = 0;
454 size_t ret;
456 /* determine string type to use */
457 if (!(flags & (STR_ASCII|STR_UNICODE))) {
458 flags |= (req->transport->negotiate.capabilities & CAP_UNICODE) ? STR_UNICODE : STR_ASCII;
461 /* see if an alignment byte will be used */
462 if ((flags & STR_UNICODE) && !(flags & STR_NOALIGN)) {
463 diff = ucs2_align(NULL, req->out.data + req->out.data_size, flags);
466 /* do the hard work */
467 ret = smbcli_req_append_string(req, str, flags);
469 /* see if we need to subtract the termination */
470 if (flags & STR_TERMINATE) {
471 diff += (flags & STR_UNICODE) ? 2 : 1;
474 if (ret >= diff) {
475 (*len) = ret - diff;
476 } else {
477 (*len) = ret;
480 return ret;
485 push a string into the data portion of the request packet, growing it if necessary
486 this gets quite tricky - please be very careful to cover all cases when modifying this
488 if dest is NULL, then put the string at the end of the data portion of the packet
490 if dest_len is -1 then no limit applies
492 size_t smbcli_req_append_ascii4(struct smbcli_request *req, const char *str, unsigned int flags)
494 size_t size;
495 smbcli_req_append_bytes(req, (const uint8_t *)"\4", 1);
496 size = smbcli_req_append_string(req, str, flags);
497 return size + 1;
502 push a blob into the data portion of the request packet, growing it if necessary
503 this gets quite tricky - please be very careful to cover all cases when modifying this
505 if dest is NULL, then put the blob at the end of the data portion of the packet
507 size_t smbcli_req_append_blob(struct smbcli_request *req, const DATA_BLOB *blob)
509 smbcli_req_grow_allocation(req, req->out.data_size + blob->length);
510 memcpy(req->out.data + req->out.data_size, blob->data, blob->length);
511 smbcli_req_grow_data(req, req->out.data_size + blob->length);
512 return blob->length;
516 append raw bytes into the data portion of the request packet
517 return the number of bytes added
519 size_t smbcli_req_append_bytes(struct smbcli_request *req, const uint8_t *bytes, size_t byte_len)
521 smbcli_req_grow_allocation(req, byte_len + req->out.data_size);
522 memcpy(req->out.data + req->out.data_size, bytes, byte_len);
523 smbcli_req_grow_data(req, byte_len + req->out.data_size);
524 return byte_len;
528 append variable block (type 5 buffer) into the data portion of the request packet
529 return the number of bytes added
531 size_t smbcli_req_append_var_block(struct smbcli_request *req, const uint8_t *bytes, uint16_t byte_len)
533 smbcli_req_grow_allocation(req, byte_len + 3 + req->out.data_size);
534 SCVAL(req->out.data + req->out.data_size, 0, 5);
535 SSVAL(req->out.data + req->out.data_size, 1, byte_len); /* add field length */
536 if (byte_len > 0) {
537 memcpy(req->out.data + req->out.data_size + 3, bytes, byte_len);
539 smbcli_req_grow_data(req, byte_len + 3 + req->out.data_size);
540 return byte_len + 3;
545 pull a UCS2 string from a request packet, returning a talloced unix string
547 the string length is limited by the 3 things:
548 - the data size in the request (end of packet)
549 - the passed 'byte_len' if it is not -1
550 - the end of string (null termination)
552 Note that 'byte_len' is the number of bytes in the packet
554 on failure zero is returned and *dest is set to NULL, otherwise the number
555 of bytes consumed in the packet is returned
557 static size_t smbcli_req_pull_ucs2(struct request_bufinfo *bufinfo, TALLOC_CTX *mem_ctx,
558 char **dest, const uint8_t *src, int byte_len, unsigned int flags)
560 int src_len, src_len2, alignment=0;
561 bool ret;
562 size_t ret_size;
564 if (!(flags & STR_NOALIGN) && ucs2_align(bufinfo->align_base, src, flags)) {
565 src++;
566 alignment=1;
567 if (byte_len != -1) {
568 byte_len--;
572 src_len = bufinfo->data_size - PTR_DIFF(src, bufinfo->data);
573 if (src_len < 0) {
574 *dest = NULL;
575 return 0;
577 if (byte_len != -1 && src_len > byte_len) {
578 src_len = byte_len;
581 src_len2 = utf16_len_n(src, src_len);
583 /* ucs2 strings must be at least 2 bytes long */
584 if (src_len2 < 2) {
585 *dest = NULL;
586 return 0;
589 ret = convert_string_talloc(mem_ctx, CH_UTF16, CH_UNIX, src, src_len2, (void **)dest, &ret_size);
590 if (!ret) {
591 *dest = NULL;
592 return 0;
595 return src_len2 + alignment;
599 pull a ascii string from a request packet, returning a talloced string
601 the string length is limited by the 3 things:
602 - the data size in the request (end of packet)
603 - the passed 'byte_len' if it is not -1
604 - the end of string (null termination)
606 Note that 'byte_len' is the number of bytes in the packet
608 on failure zero is returned and *dest is set to NULL, otherwise the number
609 of bytes consumed in the packet is returned
611 size_t smbcli_req_pull_ascii(struct request_bufinfo *bufinfo, TALLOC_CTX *mem_ctx,
612 char **dest, const uint8_t *src, int byte_len, unsigned int flags)
614 int src_len, src_len2;
615 bool ret;
616 size_t ret_size;
618 src_len = bufinfo->data_size - PTR_DIFF(src, bufinfo->data);
619 if (src_len < 0) {
620 *dest = NULL;
621 return 0;
623 if (byte_len != -1 && src_len > byte_len) {
624 src_len = byte_len;
626 src_len2 = strnlen((const char *)src, src_len);
627 if (src_len2 < src_len - 1) {
628 /* include the termination if we didn't reach the end of the packet */
629 src_len2++;
632 ret = convert_string_talloc(mem_ctx, CH_DOS, CH_UNIX, src, src_len2, (void **)dest, &ret_size);
634 if (!ret) {
635 *dest = NULL;
636 return 0;
639 return ret_size;
643 pull a string from a request packet, returning a talloced string
645 the string length is limited by the 3 things:
646 - the data size in the request (end of packet)
647 - the passed 'byte_len' if it is not -1
648 - the end of string (null termination)
650 Note that 'byte_len' is the number of bytes in the packet
652 on failure zero is returned and *dest is set to NULL, otherwise the number
653 of bytes consumed in the packet is returned
655 size_t smbcli_req_pull_string(struct request_bufinfo *bufinfo, TALLOC_CTX *mem_ctx,
656 char **dest, const uint8_t *src, int byte_len, unsigned int flags)
658 if (!(flags & STR_ASCII) &&
659 (((flags & STR_UNICODE) || (bufinfo->flags & BUFINFO_FLAG_UNICODE)))) {
660 return smbcli_req_pull_ucs2(bufinfo, mem_ctx, dest, src, byte_len, flags);
663 return smbcli_req_pull_ascii(bufinfo, mem_ctx, dest, src, byte_len, flags);
668 pull a DATA_BLOB from a reply packet, returning a talloced blob
669 make sure we don't go past end of packet
671 if byte_len is -1 then limit the blob only by packet size
673 DATA_BLOB smbcli_req_pull_blob(struct request_bufinfo *bufinfo, TALLOC_CTX *mem_ctx, const uint8_t *src, int byte_len)
675 int src_len;
677 src_len = bufinfo->data_size - PTR_DIFF(src, bufinfo->data);
679 if (src_len < 0) {
680 return data_blob(NULL, 0);
683 if (byte_len != -1 && src_len > byte_len) {
684 src_len = byte_len;
687 return data_blob_talloc(mem_ctx, src, src_len);
690 /* check that a lump of data in a request is within the bounds of the data section of
691 the packet */
692 static bool smbcli_req_data_oob(struct request_bufinfo *bufinfo, const uint8_t *ptr, uint32_t count)
694 /* be careful with wraparound! */
695 if ((uintptr_t)ptr < (uintptr_t)bufinfo->data ||
696 (uintptr_t)ptr >= (uintptr_t)bufinfo->data + bufinfo->data_size ||
697 count > bufinfo->data_size ||
698 (uintptr_t)ptr + count > (uintptr_t)bufinfo->data + bufinfo->data_size) {
699 return true;
701 return false;
705 pull a lump of data from a request packet
707 return false if any part is outside the data portion of the packet
709 bool smbcli_raw_pull_data(struct request_bufinfo *bufinfo, const uint8_t *src, int len, uint8_t *dest)
711 if (len == 0) return true;
713 if (smbcli_req_data_oob(bufinfo, src, len)) {
714 return false;
717 memcpy(dest, src, len);
718 return true;
723 put a NTTIME into a packet
725 void smbcli_push_nttime(void *base, uint16_t offset, NTTIME t)
727 SBVAL(base, offset, t);
731 pull a NTTIME from a packet
733 NTTIME smbcli_pull_nttime(void *base, uint16_t offset)
735 NTTIME ret = BVAL(base, offset);
736 return ret;
740 pull a UCS2 string from a blob, returning a talloced unix string
742 the string length is limited by the 3 things:
743 - the data size in the blob
744 - the passed 'byte_len' if it is not -1
745 - the end of string (null termination)
747 Note that 'byte_len' is the number of bytes in the packet
749 on failure zero is returned and *dest is set to NULL, otherwise the number
750 of bytes consumed in the blob is returned
752 size_t smbcli_blob_pull_ucs2(TALLOC_CTX* mem_ctx,
753 const DATA_BLOB *blob, const char **dest,
754 const uint8_t *src, int byte_len, unsigned int flags)
756 int src_len, src_len2, alignment=0;
757 size_t ret_size;
758 bool ret;
759 char *dest2;
761 if (src < blob->data ||
762 src >= (blob->data + blob->length)) {
763 *dest = NULL;
764 return 0;
767 src_len = blob->length - PTR_DIFF(src, blob->data);
769 if (byte_len != -1 && src_len > byte_len) {
770 src_len = byte_len;
773 if (!(flags & STR_NOALIGN) && ucs2_align(blob->data, src, flags)) {
774 src++;
775 alignment=1;
776 src_len--;
779 if (src_len < 2) {
780 *dest = NULL;
781 return 0;
784 src_len2 = utf16_len_n(src, src_len);
786 ret = convert_string_talloc(mem_ctx, CH_UTF16, CH_UNIX, src, src_len2, (void **)&dest2, &ret_size);
787 if (!ret) {
788 *dest = NULL;
789 return 0;
791 *dest = dest2;
793 return src_len2 + alignment;
797 pull a ascii string from a blob, returning a talloced string
799 the string length is limited by the 3 things:
800 - the data size in the blob
801 - the passed 'byte_len' if it is not -1
802 - the end of string (null termination)
804 Note that 'byte_len' is the number of bytes in the blob
806 on failure zero is returned and *dest is set to NULL, otherwise the number
807 of bytes consumed in the blob is returned
809 static size_t smbcli_blob_pull_ascii(TALLOC_CTX *mem_ctx,
810 const DATA_BLOB *blob, const char **dest,
811 const uint8_t *src, int byte_len, unsigned int flags)
813 int src_len, src_len2;
814 size_t ret_size;
815 bool ret;
816 char *dest2;
818 src_len = blob->length - PTR_DIFF(src, blob->data);
819 if (src_len < 0) {
820 *dest = NULL;
821 return 0;
823 if (byte_len != -1 && src_len > byte_len) {
824 src_len = byte_len;
826 src_len2 = strnlen((const char *)src, src_len);
828 if (src_len2 < src_len - 1) {
829 /* include the termination if we didn't reach the end of the packet */
830 src_len2++;
833 ret = convert_string_talloc(mem_ctx, CH_DOS, CH_UNIX, src, src_len2, (void **)&dest2, &ret_size);
835 if (!ret) {
836 *dest = NULL;
837 return 0;
839 *dest = dest2;
841 return ret_size;
845 pull a string from a blob, returning a talloced struct smb_wire_string
847 the string length is limited by the 3 things:
848 - the data size in the blob
849 - length field on the wire
850 - the end of string (null termination)
852 if STR_LEN8BIT is set in the flags then assume the length field is
853 8 bits, instead of 32
855 on failure zero is returned and dest->s is set to NULL, otherwise the number
856 of bytes consumed in the blob is returned
858 size_t smbcli_blob_pull_string(struct smbcli_session *session,
859 TALLOC_CTX *mem_ctx,
860 const DATA_BLOB *blob,
861 struct smb_wire_string *dest,
862 uint16_t len_offset, uint16_t str_offset,
863 unsigned int flags)
865 int extra;
866 dest->s = NULL;
868 if (!(flags & STR_ASCII)) {
869 /* this is here to cope with SMB2 calls using the SMB
870 parsers. SMB2 will pass smbcli_session==NULL, which forces
871 unicode on (as used by SMB2) */
872 if (session == NULL) {
873 flags |= STR_UNICODE;
874 } else if (session->transport->negotiate.capabilities & CAP_UNICODE) {
875 flags |= STR_UNICODE;
879 if (flags & STR_LEN8BIT) {
880 if (len_offset > blob->length-1) {
881 return 0;
883 dest->private_length = CVAL(blob->data, len_offset);
884 } else {
885 if (len_offset > blob->length-4) {
886 return 0;
888 dest->private_length = IVAL(blob->data, len_offset);
890 extra = 0;
891 dest->s = NULL;
892 if (!(flags & STR_ASCII) && (flags & STR_UNICODE)) {
893 int align = 0;
894 if ((str_offset&1) && !(flags & STR_NOALIGN)) {
895 align = 1;
897 if (flags & STR_LEN_NOTERM) {
898 extra = 2;
900 return align + extra + smbcli_blob_pull_ucs2(mem_ctx, blob, &dest->s,
901 blob->data+str_offset+align,
902 dest->private_length, flags);
905 if (flags & STR_LEN_NOTERM) {
906 extra = 1;
909 return extra + smbcli_blob_pull_ascii(mem_ctx, blob, &dest->s,
910 blob->data+str_offset, dest->private_length, flags);
914 pull a string from a blob, returning a talloced char *
916 Currently only used by the UNIX search info level.
918 the string length is limited by 2 things:
919 - the data size in the blob
920 - the end of string (null termination)
922 on failure zero is returned and dest->s is set to NULL, otherwise the number
923 of bytes consumed in the blob is returned
925 size_t smbcli_blob_pull_unix_string(struct smbcli_session *session,
926 TALLOC_CTX *mem_ctx,
927 DATA_BLOB *blob,
928 const char **dest,
929 uint16_t str_offset,
930 unsigned int flags)
932 int extra = 0;
933 *dest = NULL;
935 if (!(flags & STR_ASCII) &&
936 ((flags & STR_UNICODE) ||
937 (session->transport->negotiate.capabilities & CAP_UNICODE))) {
938 int align = 0;
939 if ((str_offset&1) && !(flags & STR_NOALIGN)) {
940 align = 1;
942 if (flags & STR_LEN_NOTERM) {
943 extra = 2;
945 return align + extra + smbcli_blob_pull_ucs2(mem_ctx, blob, dest,
946 blob->data+str_offset+align,
947 -1, flags);
950 if (flags & STR_LEN_NOTERM) {
951 extra = 1;
954 return extra + smbcli_blob_pull_ascii(mem_ctx, blob, dest,
955 blob->data+str_offset, -1, flags);
960 append a string into a blob
962 size_t smbcli_blob_append_string(struct smbcli_session *session,
963 TALLOC_CTX *mem_ctx, DATA_BLOB *blob,
964 const char *str, unsigned int flags)
966 size_t max_len;
967 int len;
969 if (!str) return 0;
971 /* determine string type to use */
972 if (!(flags & (STR_ASCII|STR_UNICODE))) {
973 flags |= (session->transport->negotiate.capabilities & CAP_UNICODE) ? STR_UNICODE : STR_ASCII;
976 max_len = (strlen(str)+2) * MAX_BYTES_PER_CHAR;
978 blob->data = talloc_realloc(mem_ctx, blob->data, uint8_t, blob->length + max_len);
979 if (!blob->data) {
980 return 0;
983 len = push_string(blob->data + blob->length, str, max_len, flags);
985 blob->length += len;
987 return len;
991 pull a GUID structure from the wire. The buffer must be at least 16
992 bytes long
994 NTSTATUS smbcli_pull_guid(void *base, uint16_t offset,
995 struct GUID *guid)
997 DATA_BLOB blob;
999 ZERO_STRUCTP(guid);
1001 blob.data = offset + (uint8_t *)base;
1002 blob.length = 16;
1004 return GUID_from_ndr_blob(&blob, guid);
1008 push a guid onto the wire. The buffer must hold 16 bytes
1010 NTSTATUS smbcli_push_guid(void *base, uint16_t offset, const struct GUID *guid)
1012 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
1013 NTSTATUS status;
1014 DATA_BLOB blob;
1015 status = GUID_to_ndr_blob(guid, tmp_ctx, &blob);
1016 if (!NT_STATUS_IS_OK(status)) {
1017 talloc_free(tmp_ctx);
1018 return status;
1020 memcpy(offset + (uint8_t *)base, blob.data, blob.length);
1021 talloc_free(tmp_ctx);
1022 return NT_STATUS_OK;