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
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
)
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
;
69 if (!req
->do_not_free
) {
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
;
86 size
= NBT_HDR_SIZE
+ MIN_SMB_SIZE
+ wct
*2 + buflen
;
88 req
= talloc_zero(transport
, struct smbcli_request
);
93 /* setup the request context */
94 req
->state
= SMBCLI_REQUEST_INIT
;
95 req
->transport
= transport
;
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
) {
106 req
->out
.hdr
= req
->out
.buffer
+ NBT_HDR_SIZE
;
107 req
->out
.vwv
= req
->out
.hdr
+ HDR_VWV
;
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);
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
);
162 setup a request for tree based commands
164 struct smbcli_request
*smbcli_request_setup(struct smbcli_tree
*tree
,
166 unsigned int wct
, unsigned int buflen
)
168 struct smbcli_request
*req
;
170 req
= smbcli_request_setup_session(tree
->session
, command
, wct
, buflen
);
172 smb1cli_tcon_set_id(tree
->smbXcli
, tree
->tid
);
175 SSVAL(req
->out
.hdr
,HDR_TID
,tree
->tid
);
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
)
194 delta
= new_size
- req
->out
.data_size
;
195 if (delta
+ req
->out
.size
<= req
->out
.allocated
) {
196 /* it fits in the preallocation */
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
);
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 */
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
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
)
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
,
252 unsigned int wct
, size_t buflen
)
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
;
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
);
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
;
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
,
353 NULL
, /* pvwv_offset */
356 NULL
, /* pbytes_offset */
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
;
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
;
373 req
->in
.vwv
= (uint8_t *)vwv
;
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
;
386 transport
->error
.etype
= ETYPE_SMB
;
389 req
->state
= SMBCLI_REQUEST_DONE
;
398 bool smbcli_request_send(struct smbcli_request
*req
)
400 smbcli_transport_send(req
);
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) {
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
)
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
);
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
)
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;
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
)
522 smbcli_req_append_bytes(req
, (const uint8_t *)"\4", 1);
523 size
= smbcli_req_append_string(req
, str
, flags
);
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
);
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
);
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 */
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
);
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;
591 if (!(flags
& STR_NOALIGN
) && ucs2_align(bufinfo
->align_base
, src
, flags
)) {
594 if (byte_len
!= -1) {
599 src_len
= bufinfo
->data_size
- PTR_DIFF(src
, bufinfo
->data
);
604 if (byte_len
!= -1 && src_len
> byte_len
) {
608 src_len2
= utf16_len_n(src
, src_len
);
610 /* ucs2 strings must be at least 2 bytes long */
616 ret
= convert_string_talloc(mem_ctx
, CH_UTF16
, CH_UNIX
, src
, src_len2
, (void **)dest
, &ret_size
);
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
;
645 src_len
= bufinfo
->data_size
- PTR_DIFF(src
, bufinfo
->data
);
650 if (byte_len
!= -1 && 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 */
659 ret
= convert_string_talloc(mem_ctx
, CH_DOS
, CH_UNIX
, src
, src_len2
, (void **)dest
, &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
)
704 src_len
= bufinfo
->data_size
- PTR_DIFF(src
, bufinfo
->data
);
707 return data_blob(NULL
, 0);
710 if (byte_len
!= -1 && 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
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
) {
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
)) {
744 memcpy(dest
, src
, len
);
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
);
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;
788 if (src
< blob
->data
||
789 src
>= (blob
->data
+ blob
->length
)) {
794 src_len
= blob
->length
- PTR_DIFF(src
, blob
->data
);
796 if (byte_len
!= -1 && src_len
> byte_len
) {
800 if (!(flags
& STR_NOALIGN
) && ucs2_align(blob
->data
, src
, flags
)) {
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
);
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
;
845 src_len
= blob
->length
- PTR_DIFF(src
, blob
->data
);
850 if (byte_len
!= -1 && 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 */
860 ret
= convert_string_talloc(mem_ctx
, CH_DOS
, CH_UNIX
, src
, src_len2
, (void **)&dest2
, &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
,
887 const DATA_BLOB
*blob
,
888 struct smb_wire_string
*dest
,
889 uint16_t len_offset
, uint16_t str_offset
,
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) {
910 dest
->private_length
= CVAL(blob
->data
, len_offset
);
912 if (len_offset
> blob
->length
-4) {
915 dest
->private_length
= IVAL(blob
->data
, len_offset
);
919 if (!(flags
& STR_ASCII
) && (flags
& STR_UNICODE
)) {
921 if ((str_offset
&1) && !(flags
& STR_NOALIGN
)) {
924 if (flags
& STR_LEN_NOTERM
) {
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
) {
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
,
962 if (!(flags
& STR_ASCII
) &&
963 ((flags
& STR_UNICODE
) ||
964 (session
->transport
->negotiate
.capabilities
& CAP_UNICODE
))) {
966 if ((str_offset
&1) && !(flags
& STR_NOALIGN
)) {
969 if (flags
& STR_LEN_NOTERM
) {
972 return align
+ extra
+ smbcli_blob_pull_ucs2(mem_ctx
, blob
, dest
,
973 blob
->data
+str_offset
+align
,
977 if (flags
& STR_LEN_NOTERM
) {
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
)
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
);
1010 len
= push_string(blob
->data
+ blob
->length
, str
, max_len
, flags
);
1012 blob
->length
+= len
;
1018 pull a GUID structure from the wire. The buffer must be at least 16
1021 NTSTATUS
smbcli_pull_guid(void *base
, uint16_t offset
,
1028 blob
.data
= offset
+ (uint8_t *)base
;
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
);
1042 status
= GUID_to_ndr_blob(guid
, tmp_ctx
, &blob
);
1043 if (!NT_STATUS_IS_OK(status
)) {
1044 talloc_free(tmp_ctx
);
1047 memcpy(offset
+ (uint8_t *)base
, blob
.data
, blob
.length
);
1048 talloc_free(tmp_ctx
);
1049 return NT_STATUS_OK
;