Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 :
4 : Copyright (C) Andrew Tridgell 2003
5 : Copyright (C) James Myers 2003 <myersjj@samba.org>
6 :
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.
11 :
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.
16 :
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/>.
19 : */
20 :
21 : /*
22 : this file implements functions for manipulating the 'struct smbcli_request' structure in libsmb
23 : */
24 :
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"
32 :
33 : /* we over allocate the data buffer to prevent too many realloc calls */
34 : #define REQ_OVER_ALLOCATION 0
35 :
36 : /* assume that a character will not consume more than 3 bytes per char */
37 : #define MAX_BYTES_PER_CHAR 3
38 :
39 : /* setup the bufinfo used for strings and range checking */
40 441298 : void smb_setup_bufinfo(struct smbcli_request *req)
41 : {
42 441298 : req->in.bufinfo.mem_ctx = req;
43 441298 : req->in.bufinfo.flags = 0;
44 441298 : if (req->flags2 & FLAGS2_UNICODE_STRINGS) {
45 440749 : req->in.bufinfo.flags = BUFINFO_FLAG_UNICODE;
46 : }
47 441298 : req->in.bufinfo.align_base = req->in.buffer;
48 441298 : req->in.bufinfo.data = req->in.data;
49 441298 : req->in.bufinfo.data_size = req->in.data_size;
50 441298 : }
51 :
52 :
53 : /* destroy a request structure and return final status */
54 513914 : _PUBLIC_ NTSTATUS smbcli_request_destroy(struct smbcli_request *req)
55 : {
56 7718 : NTSTATUS status;
57 :
58 : /* this is the error code we give the application for when a
59 : _send() call fails completely */
60 513914 : if (!req) return NT_STATUS_UNSUCCESSFUL;
61 :
62 513908 : if (req->state == SMBCLI_REQUEST_ERROR &&
63 32203 : NT_STATUS_IS_OK(req->status)) {
64 0 : req->status = NT_STATUS_INTERNAL_ERROR;
65 : }
66 :
67 513908 : status = req->status;
68 :
69 513908 : if (!req->do_not_free) {
70 508138 : talloc_free(req);
71 : }
72 :
73 513908 : return status;
74 : }
75 :
76 :
77 : /*
78 : setup a SMB packet at transport level
79 : */
80 514238 : struct smbcli_request *smbcli_request_setup_transport(struct smbcli_transport *transport,
81 : uint8_t command, unsigned int wct, unsigned int buflen)
82 : {
83 7718 : struct smbcli_request *req;
84 7718 : size_t size;
85 :
86 514238 : size = NBT_HDR_SIZE + MIN_SMB_SIZE + wct*2 + buflen;
87 :
88 514238 : req = talloc_zero(transport, struct smbcli_request);
89 514238 : if (!req) {
90 0 : return NULL;
91 : }
92 :
93 : /* setup the request context */
94 514238 : req->state = SMBCLI_REQUEST_INIT;
95 514238 : req->transport = transport;
96 514238 : req->out.size = size;
97 :
98 : /* over allocate by a small amount */
99 514238 : req->out.allocated = req->out.size + REQ_OVER_ALLOCATION;
100 :
101 514238 : req->out.buffer = talloc_zero_array(req, uint8_t, req->out.allocated);
102 514238 : if (!req->out.buffer) {
103 0 : return NULL;
104 : }
105 :
106 514238 : req->out.hdr = req->out.buffer + NBT_HDR_SIZE;
107 514238 : req->out.vwv = req->out.hdr + HDR_VWV;
108 514238 : req->out.wct = wct;
109 514238 : req->out.data = req->out.vwv + VWV(wct) + 2;
110 514238 : req->out.data_size = buflen;
111 514238 : req->out.ptr = req->out.data;
112 :
113 514238 : SCVAL(req->out.hdr, HDR_WCT, wct);
114 514238 : SSVAL(req->out.vwv, VWV(wct), buflen);
115 :
116 514238 : memcpy(req->out.hdr, "\377SMB", 4);
117 514238 : SCVAL(req->out.hdr,HDR_COM,command);
118 :
119 514238 : SCVAL(req->out.hdr,HDR_FLG, FLAG_CASELESS_PATHNAMES);
120 514238 : SSVAL(req->out.hdr,HDR_FLG2, 0);
121 :
122 : /* copy the pid, uid and mid to the request */
123 514238 : SSVAL(req->out.hdr, HDR_PID, 0);
124 514238 : SSVAL(req->out.hdr, HDR_UID, 0);
125 514238 : SSVAL(req->out.hdr, HDR_MID, 0);
126 514238 : SSVAL(req->out.hdr, HDR_TID,0);
127 514238 : SSVAL(req->out.hdr, HDR_PIDHIGH,0);
128 514238 : SIVAL(req->out.hdr, HDR_RCLS, 0);
129 514238 : memset(req->out.hdr+HDR_SS_FIELD, 0, 10);
130 :
131 514238 : return req;
132 : }
133 :
134 : /*
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.
139 : */
140 514231 : struct smbcli_request *smbcli_request_setup_session(struct smbcli_session *session,
141 : uint8_t command, unsigned int wct, size_t buflen)
142 : {
143 7718 : struct smbcli_request *req;
144 :
145 514231 : req = smbcli_request_setup_transport(session->transport, command, wct, buflen);
146 :
147 514231 : if (!req) return NULL;
148 :
149 514231 : smb1cli_session_set_id(session->smbXcli, session->vuid);
150 :
151 514231 : req->session = session;
152 :
153 514231 : SSVAL(req->out.hdr, HDR_FLG2, session->flags2);
154 514231 : SSVAL(req->out.hdr, HDR_PID, session->pid & 0xFFFF);
155 514231 : SSVAL(req->out.hdr, HDR_PIDHIGH, session->pid >> 16);
156 514231 : SSVAL(req->out.hdr, HDR_UID, session->vuid);
157 :
158 514231 : return req;
159 : }
160 :
161 : /*
162 : setup a request for tree based commands
163 : */
164 505124 : struct smbcli_request *smbcli_request_setup(struct smbcli_tree *tree,
165 : uint8_t command,
166 : unsigned int wct, unsigned int buflen)
167 : {
168 7456 : struct smbcli_request *req;
169 :
170 505124 : req = smbcli_request_setup_session(tree->session, command, wct, buflen);
171 505124 : if (req) {
172 505124 : smb1cli_tcon_set_id(tree->smbXcli, tree->tid);
173 :
174 505124 : req->tree = tree;
175 505124 : SSVAL(req->out.hdr,HDR_TID,tree->tid);
176 : }
177 505124 : return req;
178 : }
179 :
180 :
181 : /*
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.
185 :
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
188 : */
189 893400 : static void smbcli_req_grow_allocation(struct smbcli_request *req, unsigned int new_size)
190 : {
191 39392 : int delta;
192 39392 : uint8_t *buf2;
193 :
194 893400 : delta = new_size - req->out.data_size;
195 893400 : if (delta + req->out.size <= req->out.allocated) {
196 : /* it fits in the preallocation */
197 457376 : return;
198 : }
199 :
200 : /* we need to realloc */
201 411792 : req->out.allocated = req->out.size + delta + REQ_OVER_ALLOCATION;
202 411792 : buf2 = talloc_realloc(req, req->out.buffer, uint8_t, req->out.allocated);
203 411792 : if (buf2 == NULL) {
204 0 : smb_panic("out of memory in req_grow_allocation");
205 : }
206 :
207 411792 : if (buf2 == req->out.buffer) {
208 : /* the malloc library gave us the same pointer */
209 183100 : return;
210 : }
211 :
212 : /* update the pointers into the packet */
213 219090 : req->out.data = buf2 + PTR_DIFF(req->out.data, req->out.buffer);
214 219090 : req->out.ptr = buf2 + PTR_DIFF(req->out.ptr, req->out.buffer);
215 219090 : req->out.vwv = buf2 + PTR_DIFF(req->out.vwv, req->out.buffer);
216 219090 : req->out.hdr = buf2 + PTR_DIFF(req->out.hdr, req->out.buffer);
217 :
218 219090 : req->out.buffer = buf2;
219 : }
220 :
221 :
222 : /*
223 : grow the data buffer portion of a reply packet. Note that as this
224 : can reallocate the packet buffer this invalidates any local pointers
225 : into the packet.
226 :
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
229 : */
230 446700 : static void smbcli_req_grow_data(struct smbcli_request *req, unsigned int new_size)
231 : {
232 19696 : int delta;
233 :
234 446700 : smbcli_req_grow_allocation(req, new_size);
235 :
236 446700 : delta = new_size - req->out.data_size;
237 :
238 446700 : req->out.size += delta;
239 446700 : req->out.data_size += delta;
240 :
241 : /* set the BCC to the new data size */
242 446700 : SSVAL(req->out.vwv, VWV(req->out.wct), new_size);
243 446700 : }
244 :
245 :
246 : /*
247 : setup a chained reply in req->out with the given word count and
248 : initial data buffer size.
249 : */
250 18 : NTSTATUS smbcli_chained_request_setup(struct smbcli_request *req,
251 : uint8_t command,
252 : unsigned int wct, size_t buflen)
253 : {
254 3 : size_t wct_ofs;
255 3 : size_t size;
256 :
257 : /*
258 : * here we only support one chained command
259 : * If someone needs longer chains, the low
260 : * level code should be used directly.
261 : */
262 18 : if (req->subreqs[0] != NULL) {
263 0 : return NT_STATUS_INVALID_PARAMETER_MIX;
264 : }
265 18 : if (req->subreqs[1] != NULL) {
266 0 : return NT_STATUS_INVALID_PARAMETER_MIX;
267 : }
268 :
269 18 : req->subreqs[0] = smbcli_transport_setup_subreq(req);
270 18 : if (req->subreqs[0] == NULL) {
271 0 : return NT_STATUS_NO_MEMORY;
272 : }
273 :
274 18 : wct_ofs = smb1cli_req_wct_ofs(req->subreqs, 1);
275 :
276 18 : size = NBT_HDR_SIZE + wct_ofs + 1 + VWV(wct) + 2 + buflen;
277 :
278 18 : req->out.size = size;
279 :
280 : /* over allocate by a small amount */
281 18 : req->out.allocated = req->out.size + REQ_OVER_ALLOCATION;
282 :
283 18 : req->out.buffer = talloc_zero_array(req, uint8_t, req->out.allocated);
284 18 : if (!req->out.buffer) {
285 0 : return NT_STATUS_NO_MEMORY;
286 : }
287 :
288 18 : req->out.hdr = req->out.buffer + NBT_HDR_SIZE;
289 18 : req->out.vwv = req->out.hdr + wct_ofs;
290 18 : req->out.wct = wct;
291 18 : req->out.data = req->out.vwv + VWV(wct) + 2;
292 18 : req->out.data_size = buflen;
293 18 : req->out.ptr = req->out.data;
294 :
295 18 : SCVAL(req->out.hdr, HDR_WCT, wct);
296 18 : SSVAL(req->out.vwv, VWV(wct), buflen);
297 :
298 18 : memcpy(req->out.hdr, "\377SMB", 4);
299 18 : SCVAL(req->out.hdr,HDR_COM,command);
300 :
301 18 : SCVAL(req->out.hdr,HDR_FLG, FLAG_CASELESS_PATHNAMES);
302 18 : SSVAL(req->out.hdr,HDR_FLG2, 0);
303 :
304 : /* copy the pid, uid and mid to the request */
305 18 : SSVAL(req->out.hdr, HDR_PID, 0);
306 18 : SSVAL(req->out.hdr, HDR_UID, 0);
307 18 : SSVAL(req->out.hdr, HDR_MID, 0);
308 18 : SSVAL(req->out.hdr, HDR_TID,0);
309 18 : SSVAL(req->out.hdr, HDR_PIDHIGH,0);
310 18 : SIVAL(req->out.hdr, HDR_RCLS, 0);
311 18 : memset(req->out.hdr+HDR_SS_FIELD, 0, 10);
312 :
313 18 : if (req->session != NULL) {
314 18 : SSVAL(req->out.hdr, HDR_FLG2, req->session->flags2);
315 18 : SSVAL(req->out.hdr, HDR_PID, req->session->pid & 0xFFFF);
316 18 : SSVAL(req->out.hdr, HDR_PIDHIGH, req->session->pid >> 16);
317 18 : SSVAL(req->out.hdr, HDR_UID, req->session->vuid);
318 : }
319 :
320 18 : if (req->tree != NULL) {
321 18 : SSVAL(req->out.hdr, HDR_TID, req->tree->tid);
322 : }
323 :
324 18 : return NT_STATUS_OK;
325 : }
326 :
327 : /*
328 : advance to the next chained reply in a request
329 : */
330 12 : NTSTATUS smbcli_chained_advance(struct smbcli_request *req)
331 : {
332 12 : struct smbcli_transport *transport = req->transport;
333 12 : uint8_t *hdr = NULL;
334 12 : uint8_t wct = 0;
335 12 : uint16_t *vwv = NULL;
336 12 : uint32_t num_bytes = 0;
337 12 : uint8_t *bytes = NULL;
338 12 : struct iovec *recv_iov = NULL;
339 12 : uint8_t *inbuf = NULL;
340 :
341 12 : if (req->subreqs[0] != NULL) {
342 0 : return NT_STATUS_INVALID_PARAMETER_MIX;
343 : }
344 12 : if (req->subreqs[1] == NULL) {
345 0 : return NT_STATUS_INVALID_PARAMETER_MIX;
346 : }
347 :
348 12 : req->status = smb1cli_req_recv(req->subreqs[1], req,
349 : &recv_iov,
350 : &hdr,
351 : &wct,
352 : &vwv,
353 : NULL, /* pvwv_offset */
354 : &num_bytes,
355 : &bytes,
356 : NULL, /* pbytes_offset */
357 : &inbuf,
358 : NULL, 0); /* expected */
359 12 : TALLOC_FREE(req->subreqs[1]);
360 12 : if (!NT_STATUS_IS_OK(req->status)) {
361 0 : if (recv_iov == NULL) {
362 0 : req->state = SMBCLI_REQUEST_ERROR;
363 0 : return req->status;
364 : }
365 : }
366 :
367 : /* fill in the 'in' portion of the matching request */
368 12 : req->in.buffer = inbuf;
369 12 : req->in.size = NBT_HDR_SIZE + PTR_DIFF(bytes, hdr) + num_bytes;
370 12 : req->in.allocated = req->in.size;
371 :
372 12 : req->in.hdr = hdr;
373 12 : req->in.vwv = (uint8_t *)vwv;
374 12 : req->in.wct = wct;
375 12 : req->in.data = bytes;
376 12 : req->in.data_size = num_bytes;
377 12 : req->in.ptr = req->in.data;
378 12 : req->flags2 = SVAL(req->in.hdr, HDR_FLG2);
379 :
380 12 : smb_setup_bufinfo(req);
381 :
382 12 : transport->error.e.nt_status = req->status;
383 12 : if (NT_STATUS_IS_OK(req->status)) {
384 12 : transport->error.etype = ETYPE_NONE;
385 : } else {
386 0 : transport->error.etype = ETYPE_SMB;
387 : }
388 :
389 12 : req->state = SMBCLI_REQUEST_DONE;
390 :
391 12 : return NT_STATUS_OK;
392 : }
393 :
394 :
395 : /*
396 : send a message
397 : */
398 441610 : bool smbcli_request_send(struct smbcli_request *req)
399 : {
400 441610 : smbcli_transport_send(req);
401 441610 : return true;
402 : }
403 :
404 :
405 : /*
406 : receive a response to a packet
407 : */
408 514447 : bool smbcli_request_receive(struct smbcli_request *req)
409 : {
410 : /* req can be NULL when a send has failed. This eliminates lots of NULL
411 : checks in each module */
412 514447 : if (!req) return false;
413 :
414 : /* keep receiving packets until this one is replied to */
415 1932992 : while (req->state <= SMBCLI_REQUEST_RECV) {
416 1418549 : if (tevent_loop_once(req->transport->ev) != 0) {
417 0 : return false;
418 : }
419 : }
420 :
421 514443 : return req->state == SMBCLI_REQUEST_DONE;
422 : }
423 :
424 : /*
425 : wait for a reply to be received for a packet that just returns an error
426 : code and nothing more
427 : */
428 246881 : _PUBLIC_ NTSTATUS smbcli_request_simple_recv(struct smbcli_request *req)
429 : {
430 246881 : (void) smbcli_request_receive(req);
431 246881 : return smbcli_request_destroy(req);
432 : }
433 :
434 :
435 : /* Return true if the last packet was in error */
436 198761 : bool smbcli_request_is_error(struct smbcli_request *req)
437 : {
438 198761 : return NT_STATUS_IS_ERR(req->status);
439 : }
440 :
441 : /*
442 : append a string into the data portion of the request packet
443 :
444 : return the number of bytes added to the packet
445 : */
446 288500 : size_t smbcli_req_append_string(struct smbcli_request *req, const char *str, unsigned int flags)
447 : {
448 10427 : size_t len;
449 :
450 : /* determine string type to use */
451 288500 : if (!(flags & (STR_ASCII|STR_UNICODE))) {
452 204851 : flags |= (req->transport->negotiate.capabilities & CAP_UNICODE) ? STR_UNICODE : STR_ASCII;
453 : }
454 :
455 288500 : len = (strlen(str)+2) * MAX_BYTES_PER_CHAR;
456 :
457 288500 : smbcli_req_grow_allocation(req, len + req->out.data_size);
458 :
459 288500 : len = push_string(req->out.data + req->out.data_size, str, len, flags);
460 :
461 288500 : smbcli_req_grow_data(req, len + req->out.data_size);
462 :
463 288500 : return len;
464 : }
465 :
466 :
467 : /*
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:
471 :
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
474 :
475 : this is used in places where the non-terminated string byte length is
476 : placed in the packet as a separate field
477 : */
478 80714 : size_t smbcli_req_append_string_len(struct smbcli_request *req, const char *str, unsigned int flags, int *len)
479 : {
480 80714 : int diff = 0;
481 511 : size_t ret;
482 :
483 : /* determine string type to use */
484 80714 : if (!(flags & (STR_ASCII|STR_UNICODE))) {
485 80714 : flags |= (req->transport->negotiate.capabilities & CAP_UNICODE) ? STR_UNICODE : STR_ASCII;
486 : }
487 :
488 : /* see if an alignment byte will be used */
489 80714 : if ((flags & STR_UNICODE) && !(flags & STR_NOALIGN)) {
490 80714 : diff = ucs2_align(NULL, req->out.data + req->out.data_size, flags);
491 : }
492 :
493 : /* do the hard work */
494 80714 : ret = smbcli_req_append_string(req, str, flags);
495 :
496 : /* see if we need to subtract the termination */
497 80714 : if (flags & STR_TERMINATE) {
498 80714 : diff += (flags & STR_UNICODE) ? 2 : 1;
499 : }
500 :
501 80714 : if (ret >= diff) {
502 80714 : (*len) = ret - diff;
503 : } else {
504 0 : (*len) = ret;
505 : }
506 :
507 80714 : return ret;
508 : }
509 :
510 :
511 : /*
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
514 :
515 : if dest is NULL, then put the string at the end of the data portion of the packet
516 :
517 : if dest_len is -1 then no limit applies
518 : */
519 150896 : size_t smbcli_req_append_ascii4(struct smbcli_request *req, const char *str, unsigned int flags)
520 : {
521 9136 : size_t size;
522 150896 : smbcli_req_append_bytes(req, (const uint8_t *)"\4", 1);
523 150896 : size = smbcli_req_append_string(req, str, flags);
524 150896 : return size + 1;
525 : }
526 :
527 :
528 : /*
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
531 :
532 : if dest is NULL, then put the blob at the end of the data portion of the packet
533 : */
534 9625 : size_t smbcli_req_append_blob(struct smbcli_request *req, const DATA_BLOB *blob)
535 : {
536 9625 : if (blob->length > 0) {
537 6688 : smbcli_req_grow_allocation(req,
538 6688 : req->out.data_size + blob->length);
539 6688 : memcpy(req->out.data + req->out.data_size,
540 6688 : blob->data,
541 6688 : blob->length);
542 6688 : smbcli_req_grow_data(req, req->out.data_size + blob->length);
543 : }
544 9625 : return blob->length;
545 : }
546 :
547 : /*
548 : append raw bytes into the data portion of the request packet
549 : return the number of bytes added
550 : */
551 150896 : size_t smbcli_req_append_bytes(struct smbcli_request *req, const uint8_t *bytes, size_t byte_len)
552 : {
553 150896 : if (byte_len > 0) {
554 150896 : smbcli_req_grow_allocation(req, byte_len + req->out.data_size);
555 150896 : memcpy(req->out.data + req->out.data_size, bytes, byte_len);
556 150896 : smbcli_req_grow_data(req, byte_len + req->out.data_size);
557 : }
558 150896 : return byte_len;
559 : }
560 :
561 : /*
562 : append variable block (type 5 buffer) into the data portion of the request packet
563 : return the number of bytes added
564 : */
565 616 : size_t smbcli_req_append_var_block(struct smbcli_request *req, const uint8_t *bytes, uint16_t byte_len)
566 : {
567 616 : smbcli_req_grow_allocation(req, byte_len + 3 + req->out.data_size);
568 616 : SCVAL(req->out.data + req->out.data_size, 0, 5);
569 616 : SSVAL(req->out.data + req->out.data_size, 1, byte_len); /* add field length */
570 616 : if (byte_len > 0) {
571 406 : memcpy(req->out.data + req->out.data_size + 3, bytes, byte_len);
572 : }
573 616 : smbcli_req_grow_data(req, byte_len + 3 + req->out.data_size);
574 616 : return byte_len + 3;
575 : }
576 :
577 :
578 : /*
579 : pull a UCS2 string from a request packet, returning a talloced unix string
580 :
581 : the string length is limited by the 3 things:
582 : - the data size in the request (end of packet)
583 : - the passed 'byte_len' if it is not -1
584 : - the end of string (null termination)
585 :
586 : Note that 'byte_len' is the number of bytes in the packet
587 :
588 : on failure zero is returned and *dest is set to NULL, otherwise the number
589 : of bytes consumed in the packet is returned
590 : */
591 19098 : static size_t smbcli_req_pull_ucs2(struct request_bufinfo *bufinfo, TALLOC_CTX *mem_ctx,
592 : char **dest, const uint8_t *src, int byte_len, unsigned int flags)
593 : {
594 19098 : int src_len, src_len2, alignment=0;
595 537 : bool ret;
596 537 : size_t ret_size;
597 :
598 19098 : if (!(flags & STR_NOALIGN) && ucs2_align(bufinfo->align_base, src, flags)) {
599 1616 : src++;
600 1616 : alignment=1;
601 1616 : if (byte_len != -1) {
602 0 : byte_len--;
603 : }
604 : }
605 :
606 19098 : src_len = bufinfo->data_size - PTR_DIFF(src, bufinfo->data);
607 19098 : if (src_len < 0) {
608 0 : *dest = NULL;
609 0 : return 0;
610 : }
611 19098 : if (byte_len != -1 && src_len > byte_len) {
612 0 : src_len = byte_len;
613 : }
614 :
615 19098 : src_len2 = utf16_null_terminated_len_n(src, src_len);
616 :
617 : /* ucs2 strings must be at least 2 bytes long */
618 19098 : if (src_len2 < 2) {
619 0 : *dest = NULL;
620 0 : return 0;
621 : }
622 :
623 19098 : ret = convert_string_talloc(mem_ctx, CH_UTF16, CH_UNIX, src, src_len2, (void **)dest, &ret_size);
624 19098 : if (!ret) {
625 0 : *dest = NULL;
626 0 : return 0;
627 : }
628 :
629 19098 : return src_len2 + alignment;
630 : }
631 :
632 : /*
633 : pull a ascii string from a request packet, returning a talloced string
634 :
635 : the string length is limited by the 3 things:
636 : - the data size in the request (end of packet)
637 : - the passed 'byte_len' if it is not -1
638 : - the end of string (null termination)
639 :
640 : Note that 'byte_len' is the number of bytes in the packet
641 :
642 : on failure zero is returned and *dest is set to NULL, otherwise the number
643 : of bytes consumed in the packet is returned
644 : */
645 36269 : size_t smbcli_req_pull_ascii(struct request_bufinfo *bufinfo, TALLOC_CTX *mem_ctx,
646 : char **dest, const uint8_t *src, int byte_len, unsigned int flags)
647 : {
648 140 : int src_len, src_len2;
649 140 : bool ret;
650 140 : size_t ret_size;
651 :
652 36269 : src_len = bufinfo->data_size - PTR_DIFF(src, bufinfo->data);
653 36269 : if (src_len < 0) {
654 0 : *dest = NULL;
655 0 : return 0;
656 : }
657 36269 : if (byte_len != -1 && src_len > byte_len) {
658 32809 : src_len = byte_len;
659 : }
660 36269 : src_len2 = strnlen((const char *)src, src_len);
661 36269 : if (src_len2 < src_len - 1) {
662 : /* include the termination if we didn't reach the end of the packet */
663 32034 : src_len2++;
664 : }
665 :
666 36269 : ret = convert_string_talloc(mem_ctx, CH_DOS, CH_UNIX, src, src_len2, (void **)dest, &ret_size);
667 :
668 36269 : if (!ret) {
669 0 : *dest = NULL;
670 0 : return 0;
671 : }
672 :
673 36269 : return ret_size;
674 : }
675 :
676 : /**
677 : pull a string from a request packet, returning a talloced string
678 :
679 : the string length is limited by the 3 things:
680 : - the data size in the request (end of packet)
681 : - the passed 'byte_len' if it is not -1
682 : - the end of string (null termination)
683 :
684 : Note that 'byte_len' is the number of bytes in the packet
685 :
686 : on failure zero is returned and *dest is set to NULL, otherwise the number
687 : of bytes consumed in the packet is returned
688 : */
689 21998 : size_t smbcli_req_pull_string(struct request_bufinfo *bufinfo, TALLOC_CTX *mem_ctx,
690 : char **dest, const uint8_t *src, int byte_len, unsigned int flags)
691 : {
692 21998 : if (!(flags & STR_ASCII) &&
693 19098 : (((flags & STR_UNICODE) || (bufinfo->flags & BUFINFO_FLAG_UNICODE)))) {
694 19098 : return smbcli_req_pull_ucs2(bufinfo, mem_ctx, dest, src, byte_len, flags);
695 : }
696 :
697 2900 : return smbcli_req_pull_ascii(bufinfo, mem_ctx, dest, src, byte_len, flags);
698 : }
699 :
700 :
701 : /**
702 : pull a DATA_BLOB from a reply packet, returning a talloced blob
703 : make sure we don't go past end of packet
704 :
705 : if byte_len is -1 then limit the blob only by packet size
706 : */
707 5389 : DATA_BLOB smbcli_req_pull_blob(struct request_bufinfo *bufinfo, TALLOC_CTX *mem_ctx, const uint8_t *src, int byte_len)
708 : {
709 133 : int src_len;
710 :
711 5389 : src_len = bufinfo->data_size - PTR_DIFF(src, bufinfo->data);
712 :
713 5389 : if (src_len < 0) {
714 0 : return data_blob(NULL, 0);
715 : }
716 :
717 5389 : if (byte_len != -1 && src_len > byte_len) {
718 5389 : src_len = byte_len;
719 : }
720 :
721 5389 : return data_blob_talloc(mem_ctx, src, src_len);
722 : }
723 :
724 : /* check that a lump of data in a request is within the bounds of the data section of
725 : the packet */
726 18148 : static bool smbcli_req_data_oob(struct request_bufinfo *bufinfo, const uint8_t *ptr, uint32_t count)
727 : {
728 : /* be careful with wraparound! */
729 18193 : if ((uintptr_t)ptr < (uintptr_t)bufinfo->data ||
730 18148 : (uintptr_t)ptr >= (uintptr_t)bufinfo->data + bufinfo->data_size ||
731 18148 : count > bufinfo->data_size ||
732 18148 : (uintptr_t)ptr + count > (uintptr_t)bufinfo->data + bufinfo->data_size) {
733 0 : return true;
734 : }
735 18103 : return false;
736 : }
737 :
738 : /*
739 : pull a lump of data from a request packet
740 :
741 : return false if any part is outside the data portion of the packet
742 : */
743 34947 : bool smbcli_raw_pull_data(struct request_bufinfo *bufinfo, const uint8_t *src, int len, uint8_t *dest)
744 : {
745 34947 : if (len == 0) return true;
746 :
747 18148 : if (smbcli_req_data_oob(bufinfo, src, len)) {
748 0 : return false;
749 : }
750 :
751 18148 : memcpy(dest, src, len);
752 18148 : return true;
753 : }
754 :
755 :
756 : /*
757 : put a NTTIME into a packet
758 : */
759 9542 : void smbcli_push_nttime(void *base, uint16_t offset, NTTIME t)
760 : {
761 9542 : SBVAL(base, offset, t);
762 9542 : }
763 :
764 : /*
765 : pull a NTTIME from a packet
766 : */
767 6213306 : NTTIME smbcli_pull_nttime(void *base, uint16_t offset)
768 : {
769 6213306 : NTTIME ret = BVAL(base, offset);
770 6213306 : return ret;
771 : }
772 :
773 : /**
774 : pull a UCS2 string from a blob, returning a talloced unix string
775 :
776 : the string length is limited by the 3 things:
777 : - the data size in the blob
778 : - the passed 'byte_len' if it is not -1
779 : - the end of string (null termination)
780 :
781 : Note that 'byte_len' is the number of bytes in the packet
782 :
783 : on failure zero is returned and *dest is set to NULL, otherwise the number
784 : of bytes consumed in the blob is returned
785 : */
786 1013496 : size_t smbcli_blob_pull_ucs2(TALLOC_CTX* mem_ctx,
787 : const DATA_BLOB *blob, const char **dest,
788 : const uint8_t *src, int byte_len, unsigned int flags)
789 : {
790 1013496 : int src_len, src_len2, alignment=0;
791 614 : size_t ret_size;
792 614 : bool ret;
793 614 : char *dest2;
794 :
795 1013496 : if (src < blob->data ||
796 1013496 : src >= (blob->data + blob->length)) {
797 5 : *dest = NULL;
798 5 : return 0;
799 : }
800 :
801 1013491 : src_len = blob->length - PTR_DIFF(src, blob->data);
802 :
803 1013491 : if (byte_len != -1 && src_len > byte_len) {
804 1004659 : src_len = byte_len;
805 : }
806 :
807 1013491 : if (!(flags & STR_NOALIGN) && ucs2_align(blob->data, src, flags)) {
808 0 : src++;
809 0 : alignment=1;
810 0 : src_len--;
811 : }
812 :
813 1013491 : if (src_len < 2) {
814 67051 : *dest = NULL;
815 67051 : return 0;
816 : }
817 :
818 946440 : src_len2 = utf16_null_terminated_len_n(src, src_len);
819 :
820 946440 : ret = convert_string_talloc(mem_ctx, CH_UTF16, CH_UNIX, src, src_len2, (void **)&dest2, &ret_size);
821 946440 : if (!ret) {
822 0 : *dest = NULL;
823 0 : return 0;
824 : }
825 946440 : *dest = dest2;
826 :
827 946440 : return src_len2 + alignment;
828 : }
829 :
830 : /**
831 : pull a ascii string from a blob, returning a talloced string
832 :
833 : the string length is limited by the 3 things:
834 : - the data size in the blob
835 : - the passed 'byte_len' if it is not -1
836 : - the end of string (null termination)
837 :
838 : Note that 'byte_len' is the number of bytes in the blob
839 :
840 : on failure zero is returned and *dest is set to NULL, otherwise the number
841 : of bytes consumed in the blob is returned
842 : */
843 0 : static size_t smbcli_blob_pull_ascii(TALLOC_CTX *mem_ctx,
844 : const DATA_BLOB *blob, const char **dest,
845 : const uint8_t *src, int byte_len, unsigned int flags)
846 : {
847 0 : int src_len, src_len2;
848 0 : size_t ret_size;
849 0 : bool ret;
850 0 : char *dest2;
851 :
852 0 : src_len = blob->length - PTR_DIFF(src, blob->data);
853 0 : if (src_len < 0) {
854 0 : *dest = NULL;
855 0 : return 0;
856 : }
857 0 : if (byte_len != -1 && src_len > byte_len) {
858 0 : src_len = byte_len;
859 : }
860 0 : src_len2 = strnlen((const char *)src, src_len);
861 :
862 0 : if (src_len2 < src_len - 1) {
863 : /* include the termination if we didn't reach the end of the packet */
864 0 : src_len2++;
865 : }
866 :
867 0 : ret = convert_string_talloc(mem_ctx, CH_DOS, CH_UNIX, src, src_len2, (void **)&dest2, &ret_size);
868 :
869 0 : if (!ret) {
870 0 : *dest = NULL;
871 0 : return 0;
872 : }
873 0 : *dest = dest2;
874 :
875 0 : return ret_size;
876 : }
877 :
878 : /**
879 : pull a string from a blob, returning a talloced struct smb_wire_string
880 :
881 : the string length is limited by the 3 things:
882 : - the data size in the blob
883 : - length field on the wire
884 : - the end of string (null termination)
885 :
886 : if STR_LEN8BIT is set in the flags then assume the length field is
887 : 8 bits, instead of 32
888 :
889 : on failure zero is returned and dest->s is set to NULL, otherwise the number
890 : of bytes consumed in the blob is returned
891 : */
892 1013490 : size_t smbcli_blob_pull_string(struct smbcli_session *session,
893 : TALLOC_CTX *mem_ctx,
894 : const DATA_BLOB *blob,
895 : struct smb_wire_string *dest,
896 : uint16_t len_offset, uint16_t str_offset,
897 : unsigned int flags)
898 : {
899 614 : int extra;
900 1013490 : dest->s = NULL;
901 :
902 1013490 : if (!(flags & STR_ASCII)) {
903 : /* this is here to cope with SMB2 calls using the SMB
904 : parsers. SMB2 will pass smbcli_session==NULL, which forces
905 : unicode on (as used by SMB2) */
906 1013490 : if (session == NULL) {
907 877450 : flags |= STR_UNICODE;
908 136040 : } else if (session->transport->negotiate.capabilities & CAP_UNICODE) {
909 136040 : flags |= STR_UNICODE;
910 : }
911 : }
912 :
913 1013490 : if (flags & STR_LEN8BIT) {
914 238954 : if (len_offset > blob->length-1) {
915 0 : return 0;
916 : }
917 238954 : dest->private_length = CVAL(blob->data, len_offset);
918 : } else {
919 774536 : if (len_offset > blob->length-4) {
920 0 : return 0;
921 : }
922 774536 : dest->private_length = IVAL(blob->data, len_offset);
923 : }
924 1013490 : extra = 0;
925 1013490 : dest->s = NULL;
926 1013490 : if (!(flags & STR_ASCII) && (flags & STR_UNICODE)) {
927 1013490 : int align = 0;
928 1013490 : if ((str_offset&1) && !(flags & STR_NOALIGN)) {
929 10508 : align = 1;
930 : }
931 1013490 : if (flags & STR_LEN_NOTERM) {
932 10508 : extra = 2;
933 : }
934 1013490 : return align + extra + smbcli_blob_pull_ucs2(mem_ctx, blob, &dest->s,
935 1013490 : blob->data+str_offset+align,
936 1013490 : dest->private_length, flags);
937 : }
938 :
939 0 : if (flags & STR_LEN_NOTERM) {
940 0 : extra = 1;
941 : }
942 :
943 0 : return extra + smbcli_blob_pull_ascii(mem_ctx, blob, &dest->s,
944 0 : blob->data+str_offset, dest->private_length, flags);
945 : }
946 :
947 : /**
948 : pull a string from a blob, returning a talloced char *
949 :
950 : Currently only used by the UNIX search info level.
951 :
952 : the string length is limited by 2 things:
953 : - the data size in the blob
954 : - the end of string (null termination)
955 :
956 : on failure zero is returned and dest->s is set to NULL, otherwise the number
957 : of bytes consumed in the blob is returned
958 : */
959 6 : size_t smbcli_blob_pull_unix_string(struct smbcli_session *session,
960 : TALLOC_CTX *mem_ctx,
961 : DATA_BLOB *blob,
962 : const char **dest,
963 : uint16_t str_offset,
964 : unsigned int flags)
965 : {
966 6 : int extra = 0;
967 6 : *dest = NULL;
968 :
969 6 : if (!(flags & STR_ASCII) &&
970 6 : ((flags & STR_UNICODE) ||
971 6 : (session->transport->negotiate.capabilities & CAP_UNICODE))) {
972 6 : int align = 0;
973 6 : if ((str_offset&1) && !(flags & STR_NOALIGN)) {
974 0 : align = 1;
975 : }
976 6 : if (flags & STR_LEN_NOTERM) {
977 0 : extra = 2;
978 : }
979 6 : return align + extra + smbcli_blob_pull_ucs2(mem_ctx, blob, dest,
980 6 : blob->data+str_offset+align,
981 : -1, flags);
982 : }
983 :
984 0 : if (flags & STR_LEN_NOTERM) {
985 0 : extra = 1;
986 : }
987 :
988 0 : return extra + smbcli_blob_pull_ascii(mem_ctx, blob, dest,
989 0 : blob->data+str_offset, -1, flags);
990 : }
991 :
992 :
993 : /*
994 : append a string into a blob
995 : */
996 23275 : size_t smbcli_blob_append_string(struct smbcli_session *session,
997 : TALLOC_CTX *mem_ctx, DATA_BLOB *blob,
998 : const char *str, unsigned int flags)
999 : {
1000 619 : size_t max_len;
1001 619 : int len;
1002 :
1003 23275 : if (!str) return 0;
1004 :
1005 : /* determine string type to use */
1006 23275 : if (!(flags & (STR_ASCII|STR_UNICODE))) {
1007 22409 : flags |= (session->transport->negotiate.capabilities & CAP_UNICODE) ? STR_UNICODE : STR_ASCII;
1008 : }
1009 :
1010 23275 : max_len = (strlen(str)+2) * MAX_BYTES_PER_CHAR;
1011 :
1012 23275 : blob->data = talloc_realloc(mem_ctx, blob->data, uint8_t, blob->length + max_len);
1013 23275 : if (!blob->data) {
1014 0 : return 0;
1015 : }
1016 :
1017 23275 : len = push_string(blob->data + blob->length, str, max_len, flags);
1018 :
1019 23275 : blob->length += len;
1020 :
1021 23275 : return len;
1022 : }
1023 :
1024 : /*
1025 : pull a GUID structure from the wire. The buffer must be at least 16
1026 : bytes long
1027 : */
1028 1611 : NTSTATUS smbcli_pull_guid(void *base, uint16_t offset,
1029 : struct GUID *guid)
1030 : {
1031 0 : DATA_BLOB blob;
1032 :
1033 1611 : ZERO_STRUCTP(guid);
1034 :
1035 1611 : blob.data = offset + (uint8_t *)base;
1036 1611 : blob.length = 16;
1037 :
1038 1611 : return GUID_from_ndr_blob(&blob, guid);
1039 : }
1040 :
1041 : /*
1042 : push a guid onto the wire. The buffer must hold 16 bytes
1043 : */
1044 1611 : NTSTATUS smbcli_push_guid(void *base, uint16_t offset, const struct GUID *guid)
1045 : {
1046 1611 : struct GUID_ndr_buf buf = { .buf = {0}, };
1047 :
1048 1611 : GUID_to_ndr_buf(guid, &buf);
1049 1611 : memcpy(offset + (uint8_t *)base, buf.buf, sizeof(buf.buf));
1050 1611 : return NT_STATUS_OK;
1051 : }
|