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/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)
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;
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;
75
if (!req->do_not_free) {
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);
97
/* setup the request context */
98
req->state = SMBCLI_REQUEST_INIT;
99
req->transport = transport;
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) {
112
SIVAL(req->out.buffer, 0, 0);
119
setup a SMB packet at transport level
121
struct smbcli_request *smbcli_request_setup_transport(struct smbcli_transport *transport,
122
uint8_t command, uint_t wct, uint_t 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;
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) {
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);
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, uint_t 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);
189
setup a request for tree based commands
191
struct smbcli_request *smbcli_request_setup(struct smbcli_tree *tree,
193
uint_t wct, uint_t buflen)
195
struct smbcli_request *req;
197
req = smbcli_request_setup_session(tree->session, command, wct, buflen);
200
SSVAL(req->out.hdr,HDR_TID,tree->tid);
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, uint_t new_size)
219
delta = new_size - req->out.data_size;
220
if (delta + req->out.size <= req->out.allocated) {
221
/* it fits in the preallocation */
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);
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 */
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
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, uint_t new_size)
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,
277
uint_t wct, size_t buflen)
279
uint_t 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;
297
aadvance to the next chained reply in a request
299
NTSTATUS smbcli_chained_advance(struct smbcli_request *req)
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;
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);
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 (event_loop_once(req->transport->socket->event.ctx) != 0) {
366
return req->state == SMBCLI_REQUEST_DONE;
371
handle oplock break requests from the server - return true if the request was
374
bool smbcli_handle_oplock_break(struct smbcli_transport *transport, uint_t 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) {
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);
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, uint_t flags)
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);
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, uint_t flags, int *len)
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;
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, uint_t flags)
495
smbcli_req_append_bytes(req, (const uint8_t *)"\4", 1);
496
size = smbcli_req_append_string(req, str, flags);
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);
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);
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 */
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);
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, uint_t flags)
560
int src_len, src_len2, alignment=0;
564
if (!(flags & STR_NOALIGN) && ucs2_align(bufinfo->align_base, src, flags)) {
567
if (byte_len != -1) {
572
src_len = bufinfo->data_size - PTR_DIFF(src, bufinfo->data);
577
if (byte_len != -1 && src_len > byte_len) {
581
src_len2 = utf16_len_n(src, src_len);
583
/* ucs2 strings must be at least 2 bytes long */
589
ret = convert_string_talloc(mem_ctx, CH_UTF16, CH_UNIX, src, src_len2, (void **)dest, &ret_size, false);
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, uint_t flags)
614
int src_len, src_len2;
618
src_len = bufinfo->data_size - PTR_DIFF(src, bufinfo->data);
623
if (byte_len != -1 && 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 */
632
ret = convert_string_talloc(mem_ctx, CH_DOS, CH_UNIX, src, src_len2, (void **)dest, &ret_size, false);
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, uint_t 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)
677
src_len = bufinfo->data_size - PTR_DIFF(src, bufinfo->data);
680
return data_blob(NULL, 0);
683
if (byte_len != -1 && 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
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) {
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)) {
717
memcpy(dest, src, len);
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);
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, uint_t flags)
756
int src_len, src_len2, alignment=0;
761
if (src < blob->data ||
762
src >= (blob->data + blob->length)) {
767
src_len = blob->length - PTR_DIFF(src, blob->data);
769
if (byte_len != -1 && src_len > byte_len) {
773
if (!(flags & STR_NOALIGN) && ucs2_align(blob->data, src, flags)) {
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, false);
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, uint_t flags)
813
int src_len, src_len2;
818
src_len = blob->length - PTR_DIFF(src, blob->data);
823
if (byte_len != -1 && 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 */
833
ret = convert_string_talloc(mem_ctx, CH_DOS, CH_UNIX, src, src_len2, (void **)&dest2, &ret_size, false);
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,
860
const DATA_BLOB *blob,
861
struct smb_wire_string *dest,
862
uint16_t len_offset, uint16_t str_offset,
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) {
883
dest->private_length = CVAL(blob->data, len_offset);
885
if (len_offset > blob->length-4) {
888
dest->private_length = IVAL(blob->data, len_offset);
892
if (!(flags & STR_ASCII) && (flags & STR_UNICODE)) {
894
if ((str_offset&1) && !(flags & STR_NOALIGN)) {
897
if (flags & STR_LEN_NOTERM) {
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) {
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,
935
if (!(flags & STR_ASCII) &&
936
((flags & STR_UNICODE) ||
937
(session->transport->negotiate.capabilities & CAP_UNICODE))) {
939
if ((str_offset&1) && !(flags & STR_NOALIGN)) {
942
if (flags & STR_LEN_NOTERM) {
945
return align + extra + smbcli_blob_pull_ucs2(mem_ctx, blob, dest,
946
blob->data+str_offset+align,
950
if (flags & STR_LEN_NOTERM) {
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, uint_t flags)
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);
983
len = push_string(blob->data + blob->length, str, max_len, flags);
991
pull a GUID structure from the wire. The buffer must be at least 16
994
enum ndr_err_code smbcli_pull_guid(void *base, uint16_t offset,
998
TALLOC_CTX *tmp_ctx = talloc_new(NULL);
999
enum ndr_err_code ndr_err;
1003
blob.data = offset + (uint8_t *)base;
1005
ndr_err = ndr_pull_struct_blob(&blob, tmp_ctx, NULL, guid,
1006
(ndr_pull_flags_fn_t)ndr_pull_GUID);
1007
talloc_free(tmp_ctx);
1012
push a guid onto the wire. The buffer must hold 16 bytes
1014
enum ndr_err_code smbcli_push_guid(void *base, uint16_t offset,
1015
const struct GUID *guid)
1017
TALLOC_CTX *tmp_ctx = talloc_new(NULL);
1018
enum ndr_err_code ndr_err;
1020
ndr_err = ndr_push_struct_blob(&blob, tmp_ctx, NULL,
1021
guid, (ndr_push_flags_fn_t)ndr_push_GUID);
1022
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err) || blob.length != 16) {
1023
talloc_free(tmp_ctx);
1026
memcpy(offset + (uint8_t *)base, blob.data, blob.length);
1027
talloc_free(tmp_ctx);