source: vendor/current/source4/libcli/smb2/request.c

Last change on this file was 988, checked in by Silvan Scherrer, 9 years ago

Samba Server: update vendor to version 4.4.3

File size: 18.0 KB
Line 
1/*
2 Unix SMB/CIFS implementation.
3
4 SMB2 client request handling
5
6 Copyright (C) Andrew Tridgell 2005
7 Copyright (C) Stefan Metzmacher 2005
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
21*/
22
23#include "includes.h"
24#include "libcli/raw/libcliraw.h"
25#include "libcli/smb2/smb2.h"
26#include "../lib/util/dlinklist.h"
27#include "lib/events/events.h"
28#include "libcli/smb2/smb2_calls.h"
29
30/* fill in the bufinfo */
31void smb2_setup_bufinfo(struct smb2_request *req)
32{
33 req->in.bufinfo.mem_ctx = req;
34 req->in.bufinfo.flags = BUFINFO_FLAG_UNICODE | BUFINFO_FLAG_SMB2;
35 req->in.bufinfo.align_base = req->in.buffer;
36 if (req->in.dynamic) {
37 req->in.bufinfo.data = req->in.dynamic;
38 req->in.bufinfo.data_size = req->in.body_size - req->in.body_fixed;
39 } else {
40 req->in.bufinfo.data = NULL;
41 req->in.bufinfo.data_size = 0;
42 }
43}
44
45/*
46 initialise a smb2 request
47*/
48struct smb2_request *smb2_request_init(struct smb2_transport *transport, uint16_t opcode,
49 uint16_t body_fixed_size, bool body_dynamic_present,
50 uint32_t body_dynamic_size)
51{
52 struct smb2_request *req;
53 uint32_t hdr_offset;
54 bool compound = false;
55
56 if (body_dynamic_present) {
57 if (body_dynamic_size == 0) {
58 body_dynamic_size = 1;
59 }
60 } else {
61 body_dynamic_size = 0;
62 }
63
64 req = talloc_zero(transport, struct smb2_request);
65 if (req == NULL) return NULL;
66
67 req->state = SMB2_REQUEST_INIT;
68 req->transport = transport;
69
70 hdr_offset = NBT_HDR_SIZE;
71
72 req->out.size = hdr_offset + SMB2_HDR_BODY + body_fixed_size;
73 req->out.allocated = req->out.size + body_dynamic_size;
74
75 req->out.buffer = talloc_realloc(req, req->out.buffer,
76 uint8_t, req->out.allocated);
77 if (req->out.buffer == NULL) {
78 talloc_free(req);
79 return NULL;
80 }
81
82 req->out.hdr = req->out.buffer + hdr_offset;
83 req->out.body = req->out.hdr + SMB2_HDR_BODY;
84 req->out.body_fixed= body_fixed_size;
85 req->out.body_size = body_fixed_size;
86 req->out.dynamic = (body_dynamic_size ? req->out.body + body_fixed_size : NULL);
87
88 SIVAL(req->out.hdr, 0, SMB2_MAGIC);
89 SSVAL(req->out.hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
90 SSVAL(req->out.hdr, SMB2_HDR_CREDIT_CHARGE, 0);
91 SIVAL(req->out.hdr, SMB2_HDR_STATUS, 0);
92 SSVAL(req->out.hdr, SMB2_HDR_OPCODE, opcode);
93 SSVAL(req->out.hdr, SMB2_HDR_CREDIT, 0);
94 SIVAL(req->out.hdr, SMB2_HDR_FLAGS, 0);
95 SIVAL(req->out.hdr, SMB2_HDR_NEXT_COMMAND, 0);
96 SBVAL(req->out.hdr, SMB2_HDR_MESSAGE_ID, 0);
97 SIVAL(req->out.hdr, SMB2_HDR_PID, 0);
98 SIVAL(req->out.hdr, SMB2_HDR_TID, 0);
99 SBVAL(req->out.hdr, SMB2_HDR_SESSION_ID, 0);
100 memset(req->out.hdr+SMB2_HDR_SIGNATURE, 0, 16);
101
102 /* set the length of the fixed body part and +1 if there's a dynamic part also */
103 SSVAL(req->out.body, 0, body_fixed_size + (body_dynamic_size?1:0));
104
105 /*
106 * if we have a dynamic part, make sure the first byte
107 * which is always be part of the packet is initialized
108 */
109 if (body_dynamic_size && !compound) {
110 req->out.size += 1;
111 SCVAL(req->out.dynamic, 0, 0);
112 }
113
114 return req;
115}
116
117/*
118 initialise a smb2 request for tree operations
119*/
120struct smb2_request *smb2_request_init_tree(struct smb2_tree *tree, uint16_t opcode,
121 uint16_t body_fixed_size, bool body_dynamic_present,
122 uint32_t body_dynamic_size)
123{
124 struct smb2_request *req = smb2_request_init(tree->session->transport, opcode,
125 body_fixed_size, body_dynamic_present,
126 body_dynamic_size);
127 if (req == NULL) return NULL;
128
129 req->session = tree->session;
130 req->tree = tree;
131
132 return req;
133}
134
135/* destroy a request structure and return final status */
136NTSTATUS smb2_request_destroy(struct smb2_request *req)
137{
138 NTSTATUS status;
139
140 /* this is the error code we give the application for when a
141 _send() call fails completely */
142 if (!req) return NT_STATUS_UNSUCCESSFUL;
143
144 if (req->state == SMB2_REQUEST_ERROR &&
145 NT_STATUS_IS_OK(req->status)) {
146 status = NT_STATUS_INTERNAL_ERROR;
147 } else {
148 status = req->status;
149 }
150
151 talloc_free(req);
152 return status;
153}
154
155/*
156 receive a response to a packet
157*/
158bool smb2_request_receive(struct smb2_request *req)
159{
160 /* req can be NULL when a send has failed. This eliminates lots of NULL
161 checks in each module */
162 if (!req) return false;
163
164 /* keep receiving packets until this one is replied to */
165 while (req->state <= SMB2_REQUEST_RECV) {
166 if (tevent_loop_once(req->transport->ev) != 0) {
167 return false;
168 }
169 }
170
171 return req->state == SMB2_REQUEST_DONE;
172}
173
174/* Return true if the last packet was in error */
175bool smb2_request_is_error(struct smb2_request *req)
176{
177 return NT_STATUS_IS_ERR(req->status);
178}
179
180/* Return true if the last packet was OK */
181bool smb2_request_is_ok(struct smb2_request *req)
182{
183 return NT_STATUS_IS_OK(req->status);
184}
185
186/*
187 check if a range in the reply body is out of bounds
188*/
189bool smb2_oob(struct smb2_request_buffer *buf, const uint8_t *ptr, size_t size)
190{
191 if (size == 0) {
192 /* zero bytes is never out of range */
193 return false;
194 }
195 /* be careful with wraparound! */
196 if ((uintptr_t)ptr < (uintptr_t)buf->body ||
197 (uintptr_t)ptr >= (uintptr_t)buf->body + buf->body_size ||
198 size > buf->body_size ||
199 (uintptr_t)ptr + size > (uintptr_t)buf->body + buf->body_size) {
200 return true;
201 }
202 return false;
203}
204
205size_t smb2_padding_size(uint32_t offset, size_t n)
206{
207 if ((offset & (n-1)) == 0) return 0;
208 return n - (offset & (n-1));
209}
210
211static size_t smb2_padding_fix(struct smb2_request_buffer *buf)
212{
213 if (buf->dynamic == (buf->body + buf->body_fixed)) {
214 if (buf->dynamic != (buf->buffer + buf->size)) {
215 return 1;
216 }
217 }
218 return 0;
219}
220
221/*
222 grow a SMB2 buffer by the specified amount
223*/
224NTSTATUS smb2_grow_buffer(struct smb2_request_buffer *buf, size_t increase)
225{
226 size_t hdr_ofs;
227 size_t dynamic_ofs;
228 uint8_t *buffer_ptr;
229 uint32_t newsize = buf->size + increase;
230
231 /* a packet size should be limited a bit */
232 if (newsize >= 0x00FFFFFF) return NT_STATUS_MARSHALL_OVERFLOW;
233
234 if (newsize <= buf->allocated) return NT_STATUS_OK;
235
236 hdr_ofs = buf->hdr - buf->buffer;
237 dynamic_ofs = buf->dynamic - buf->buffer;
238
239 buffer_ptr = talloc_realloc(buf, buf->buffer, uint8_t, newsize);
240 NT_STATUS_HAVE_NO_MEMORY(buffer_ptr);
241
242 buf->buffer = buffer_ptr;
243 buf->hdr = buf->buffer + hdr_ofs;
244 buf->body = buf->hdr + SMB2_HDR_BODY;
245 buf->dynamic = buf->buffer + dynamic_ofs;
246 buf->allocated = newsize;
247
248 return NT_STATUS_OK;
249}
250
251/*
252 pull a uint16_t ofs/ uint16_t length/blob triple from a data blob
253 the ptr points to the start of the offset/length pair
254*/
255NTSTATUS smb2_pull_o16s16_blob(struct smb2_request_buffer *buf, TALLOC_CTX *mem_ctx, uint8_t *ptr, DATA_BLOB *blob)
256{
257 uint16_t ofs, size;
258 if (smb2_oob(buf, ptr, 4)) {
259 return NT_STATUS_INVALID_PARAMETER;
260 }
261 ofs = SVAL(ptr, 0);
262 size = SVAL(ptr, 2);
263 if (ofs == 0) {
264 *blob = data_blob(NULL, 0);
265 return NT_STATUS_OK;
266 }
267 if (smb2_oob(buf, buf->hdr + ofs, size)) {
268 return NT_STATUS_INVALID_PARAMETER;
269 }
270 *blob = data_blob_talloc(mem_ctx, buf->hdr + ofs, size);
271 NT_STATUS_HAVE_NO_MEMORY(blob->data);
272 return NT_STATUS_OK;
273}
274
275/*
276 push a uint16_t ofs/ uint16_t length/blob triple into a data blob
277 the ofs points to the start of the offset/length pair, and is relative
278 to the body start
279*/
280NTSTATUS smb2_push_o16s16_blob(struct smb2_request_buffer *buf,
281 uint16_t ofs, DATA_BLOB blob)
282{
283 NTSTATUS status;
284 size_t offset;
285 size_t padding_length;
286 size_t padding_fix;
287 uint8_t *ptr = buf->body+ofs;
288
289 if (buf->dynamic == NULL) {
290 return NT_STATUS_INVALID_PARAMETER;
291 }
292
293 /* we have only 16 bit for the size */
294 if (blob.length > 0xFFFF) {
295 return NT_STATUS_INVALID_PARAMETER;
296 }
297
298 /* check if there're enough room for ofs and size */
299 if (smb2_oob(buf, ptr, 4)) {
300 return NT_STATUS_INVALID_PARAMETER;
301 }
302
303 if (blob.data == NULL) {
304 if (blob.length != 0) {
305 return NT_STATUS_INTERNAL_ERROR;
306 }
307 SSVAL(ptr, 0, 0);
308 SSVAL(ptr, 2, 0);
309 return NT_STATUS_OK;
310 }
311
312 offset = buf->dynamic - buf->hdr;
313 padding_length = smb2_padding_size(offset, 2);
314 offset += padding_length;
315 padding_fix = smb2_padding_fix(buf);
316
317 SSVAL(ptr, 0, offset);
318 SSVAL(ptr, 2, blob.length);
319
320 status = smb2_grow_buffer(buf, blob.length + padding_length - padding_fix);
321 NT_STATUS_NOT_OK_RETURN(status);
322
323 memset(buf->dynamic, 0, padding_length);
324 buf->dynamic += padding_length;
325
326 memcpy(buf->dynamic, blob.data, blob.length);
327 buf->dynamic += blob.length;
328
329 buf->size += blob.length + padding_length - padding_fix;
330 buf->body_size += blob.length + padding_length;
331
332 return NT_STATUS_OK;
333}
334
335
336/*
337 push a uint16_t ofs/ uint32_t length/blob triple into a data blob
338 the ofs points to the start of the offset/length pair, and is relative
339 to the body start
340*/
341NTSTATUS smb2_push_o16s32_blob(struct smb2_request_buffer *buf,
342 uint16_t ofs, DATA_BLOB blob)
343{
344 NTSTATUS status;
345 size_t offset;
346 size_t padding_length;
347 size_t padding_fix;
348 uint8_t *ptr = buf->body+ofs;
349
350 if (buf->dynamic == NULL) {
351 return NT_STATUS_INVALID_PARAMETER;
352 }
353
354 /* check if there're enough room for ofs and size */
355 if (smb2_oob(buf, ptr, 6)) {
356 return NT_STATUS_INVALID_PARAMETER;
357 }
358
359 if (blob.data == NULL) {
360 if (blob.length != 0) {
361 return NT_STATUS_INTERNAL_ERROR;
362 }
363 SSVAL(ptr, 0, 0);
364 SIVAL(ptr, 2, 0);
365 return NT_STATUS_OK;
366 }
367
368 offset = buf->dynamic - buf->hdr;
369 padding_length = smb2_padding_size(offset, 2);
370 offset += padding_length;
371 padding_fix = smb2_padding_fix(buf);
372
373 SSVAL(ptr, 0, offset);
374 SIVAL(ptr, 2, blob.length);
375
376 status = smb2_grow_buffer(buf, blob.length + padding_length - padding_fix);
377 NT_STATUS_NOT_OK_RETURN(status);
378
379 memset(buf->dynamic, 0, padding_length);
380 buf->dynamic += padding_length;
381
382 memcpy(buf->dynamic, blob.data, blob.length);
383 buf->dynamic += blob.length;
384
385 buf->size += blob.length + padding_length - padding_fix;
386 buf->body_size += blob.length + padding_length;
387
388 return NT_STATUS_OK;
389}
390
391
392/*
393 push a uint32_t ofs/ uint32_t length/blob triple into a data blob
394 the ofs points to the start of the offset/length pair, and is relative
395 to the body start
396*/
397NTSTATUS smb2_push_o32s32_blob(struct smb2_request_buffer *buf,
398 uint32_t ofs, DATA_BLOB blob)
399{
400 NTSTATUS status;
401 size_t offset;
402 size_t padding_length;
403 size_t padding_fix;
404 uint8_t *ptr = buf->body+ofs;
405
406 if (buf->dynamic == NULL) {
407 return NT_STATUS_INVALID_PARAMETER;
408 }
409
410 /* check if there're enough room for ofs and size */
411 if (smb2_oob(buf, ptr, 8)) {
412 return NT_STATUS_INVALID_PARAMETER;
413 }
414
415 if (blob.data == NULL) {
416 if (blob.length != 0) {
417 return NT_STATUS_INTERNAL_ERROR;
418 }
419 SIVAL(ptr, 0, 0);
420 SIVAL(ptr, 4, 0);
421 return NT_STATUS_OK;
422 }
423
424 offset = buf->dynamic - buf->hdr;
425 padding_length = smb2_padding_size(offset, 8);
426 offset += padding_length;
427 padding_fix = smb2_padding_fix(buf);
428
429 SIVAL(ptr, 0, offset);
430 SIVAL(ptr, 4, blob.length);
431
432 status = smb2_grow_buffer(buf, blob.length + padding_length - padding_fix);
433 NT_STATUS_NOT_OK_RETURN(status);
434
435 memset(buf->dynamic, 0, padding_length);
436 buf->dynamic += padding_length;
437
438 memcpy(buf->dynamic, blob.data, blob.length);
439 buf->dynamic += blob.length;
440
441 buf->size += blob.length + padding_length - padding_fix;
442 buf->body_size += blob.length + padding_length;
443
444 return NT_STATUS_OK;
445}
446
447
448/*
449 push a uint32_t length/ uint32_t ofs/blob triple into a data blob
450 the ofs points to the start of the length/offset pair, and is relative
451 to the body start
452*/
453NTSTATUS smb2_push_s32o32_blob(struct smb2_request_buffer *buf,
454 uint32_t ofs, DATA_BLOB blob)
455{
456 NTSTATUS status;
457 size_t offset;
458 size_t padding_length;
459 size_t padding_fix;
460 uint8_t *ptr = buf->body+ofs;
461
462 if (buf->dynamic == NULL) {
463 return NT_STATUS_INVALID_PARAMETER;
464 }
465
466 /* check if there're enough room for ofs and size */
467 if (smb2_oob(buf, ptr, 8)) {
468 return NT_STATUS_INVALID_PARAMETER;
469 }
470
471 if (blob.data == NULL) {
472 if (blob.length != 0) {
473 return NT_STATUS_INTERNAL_ERROR;
474 }
475 SIVAL(ptr, 0, 0);
476 SIVAL(ptr, 4, 0);
477 return NT_STATUS_OK;
478 }
479
480 offset = buf->dynamic - buf->hdr;
481 padding_length = smb2_padding_size(offset, 8);
482 offset += padding_length;
483 padding_fix = smb2_padding_fix(buf);
484
485 SIVAL(ptr, 0, blob.length);
486 SIVAL(ptr, 4, offset);
487
488 status = smb2_grow_buffer(buf, blob.length + padding_length - padding_fix);
489 NT_STATUS_NOT_OK_RETURN(status);
490
491 memset(buf->dynamic, 0, padding_length);
492 buf->dynamic += padding_length;
493
494 memcpy(buf->dynamic, blob.data, blob.length);
495 buf->dynamic += blob.length;
496
497 buf->size += blob.length + padding_length - padding_fix;
498 buf->body_size += blob.length + padding_length;
499
500 return NT_STATUS_OK;
501}
502
503/*
504 pull a uint16_t ofs/ uint32_t length/blob triple from a data blob
505 the ptr points to the start of the offset/length pair
506*/
507NTSTATUS smb2_pull_o16s32_blob(struct smb2_request_buffer *buf, TALLOC_CTX *mem_ctx, uint8_t *ptr, DATA_BLOB *blob)
508{
509 uint16_t ofs;
510 uint32_t size;
511
512 if (smb2_oob(buf, ptr, 6)) {
513 return NT_STATUS_INVALID_PARAMETER;
514 }
515 ofs = SVAL(ptr, 0);
516 size = IVAL(ptr, 2);
517 if (ofs == 0) {
518 *blob = data_blob(NULL, 0);
519 return NT_STATUS_OK;
520 }
521 if (smb2_oob(buf, buf->hdr + ofs, size)) {
522 return NT_STATUS_INVALID_PARAMETER;
523 }
524 *blob = data_blob_talloc(mem_ctx, buf->hdr + ofs, size);
525 NT_STATUS_HAVE_NO_MEMORY(blob->data);
526 return NT_STATUS_OK;
527}
528
529/*
530 pull a uint32_t ofs/ uint32_t length/blob triple from a data blob
531 the ptr points to the start of the offset/length pair
532*/
533NTSTATUS smb2_pull_o32s32_blob(struct smb2_request_buffer *buf, TALLOC_CTX *mem_ctx, uint8_t *ptr, DATA_BLOB *blob)
534{
535 uint32_t ofs, size;
536 if (smb2_oob(buf, ptr, 8)) {
537 return NT_STATUS_INVALID_PARAMETER;
538 }
539 ofs = IVAL(ptr, 0);
540 size = IVAL(ptr, 4);
541 if (ofs == 0) {
542 *blob = data_blob(NULL, 0);
543 return NT_STATUS_OK;
544 }
545 if (smb2_oob(buf, buf->hdr + ofs, size)) {
546 return NT_STATUS_INVALID_PARAMETER;
547 }
548 *blob = data_blob_talloc(mem_ctx, buf->hdr + ofs, size);
549 NT_STATUS_HAVE_NO_MEMORY(blob->data);
550 return NT_STATUS_OK;
551}
552
553/*
554 pull a uint16_t ofs/ uint32_t length/blob triple from a data blob
555 the ptr points to the start of the offset/length pair
556
557 In this varient the uint16_t is padded by an extra 2 bytes, making
558 the size aligned on 4 byte boundary
559*/
560NTSTATUS smb2_pull_o16As32_blob(struct smb2_request_buffer *buf, TALLOC_CTX *mem_ctx, uint8_t *ptr, DATA_BLOB *blob)
561{
562 uint32_t ofs, size;
563 if (smb2_oob(buf, ptr, 8)) {
564 return NT_STATUS_INVALID_PARAMETER;
565 }
566 ofs = SVAL(ptr, 0);
567 size = IVAL(ptr, 4);
568 if (ofs == 0) {
569 *blob = data_blob(NULL, 0);
570 return NT_STATUS_OK;
571 }
572 if (smb2_oob(buf, buf->hdr + ofs, size)) {
573 return NT_STATUS_INVALID_PARAMETER;
574 }
575 *blob = data_blob_talloc(mem_ctx, buf->hdr + ofs, size);
576 NT_STATUS_HAVE_NO_MEMORY(blob->data);
577 return NT_STATUS_OK;
578}
579
580/*
581 pull a uint32_t length/ uint32_t ofs/blob triple from a data blob
582 the ptr points to the start of the offset/length pair
583*/
584NTSTATUS smb2_pull_s32o32_blob(struct smb2_request_buffer *buf, TALLOC_CTX *mem_ctx, uint8_t *ptr, DATA_BLOB *blob)
585{
586 uint32_t ofs, size;
587 if (smb2_oob(buf, ptr, 8)) {
588 return NT_STATUS_INVALID_PARAMETER;
589 }
590 size = IVAL(ptr, 0);
591 ofs = IVAL(ptr, 4);
592 if (ofs == 0) {
593 *blob = data_blob(NULL, 0);
594 return NT_STATUS_OK;
595 }
596 if (smb2_oob(buf, buf->hdr + ofs, size)) {
597 return NT_STATUS_INVALID_PARAMETER;
598 }
599 *blob = data_blob_talloc(mem_ctx, buf->hdr + ofs, size);
600 NT_STATUS_HAVE_NO_MEMORY(blob->data);
601 return NT_STATUS_OK;
602}
603
604/*
605 pull a uint32_t length/ uint16_t ofs/blob triple from a data blob
606 the ptr points to the start of the offset/length pair
607*/
608NTSTATUS smb2_pull_s32o16_blob(struct smb2_request_buffer *buf, TALLOC_CTX *mem_ctx, uint8_t *ptr, DATA_BLOB *blob)
609{
610 uint32_t ofs, size;
611 if (smb2_oob(buf, ptr, 8)) {
612 return NT_STATUS_INVALID_PARAMETER;
613 }
614 size = IVAL(ptr, 0);
615 ofs = SVAL(ptr, 4);
616 if (ofs == 0) {
617 *blob = data_blob(NULL, 0);
618 return NT_STATUS_OK;
619 }
620 if (smb2_oob(buf, buf->hdr + ofs, size)) {
621 return NT_STATUS_INVALID_PARAMETER;
622 }
623 *blob = data_blob_talloc(mem_ctx, buf->hdr + ofs, size);
624 NT_STATUS_HAVE_NO_MEMORY(blob->data);
625 return NT_STATUS_OK;
626}
627
628/*
629 pull a string in a uint16_t ofs/ uint16_t length/blob format
630 UTF-16 without termination
631*/
632NTSTATUS smb2_pull_o16s16_string(struct smb2_request_buffer *buf, TALLOC_CTX *mem_ctx,
633 uint8_t *ptr, const char **str)
634{
635 DATA_BLOB blob;
636 NTSTATUS status;
637 void *vstr;
638 size_t converted_size = 0;
639 bool ret;
640
641 status = smb2_pull_o16s16_blob(buf, mem_ctx, ptr, &blob);
642 NT_STATUS_NOT_OK_RETURN(status);
643
644 if (blob.data == NULL) {
645 *str = NULL;
646 return NT_STATUS_OK;
647 }
648
649 if (blob.length == 0) {
650 char *s;
651 s = talloc_strdup(mem_ctx, "");
652 NT_STATUS_HAVE_NO_MEMORY(s);
653 *str = s;
654 return NT_STATUS_OK;
655 }
656
657 ret = convert_string_talloc(mem_ctx, CH_UTF16, CH_UNIX,
658 blob.data, blob.length, &vstr, &converted_size);
659 data_blob_free(&blob);
660 (*str) = (char *)vstr;
661 if (!ret) {
662 return NT_STATUS_ILLEGAL_CHARACTER;
663 }
664 return NT_STATUS_OK;
665}
666
667/*
668 push a string in a uint16_t ofs/ uint16_t length/blob format
669 UTF-16 without termination
670*/
671NTSTATUS smb2_push_o16s16_string(struct smb2_request_buffer *buf,
672 uint16_t ofs, const char *str)
673{
674 DATA_BLOB blob;
675 NTSTATUS status;
676 bool ret;
677 void *ptr = NULL;
678
679 if (str == NULL) {
680 return smb2_push_o16s16_blob(buf, ofs, data_blob(NULL, 0));
681 }
682
683 if (*str == 0) {
684 blob.data = discard_const_p(uint8_t, str);
685 blob.length = 0;
686 return smb2_push_o16s16_blob(buf, ofs, blob);
687 }
688
689 ret = convert_string_talloc(buf->buffer, CH_UNIX, CH_UTF16,
690 str, strlen(str), &ptr, &blob.length);
691 if (!ret) {
692 return NT_STATUS_ILLEGAL_CHARACTER;
693 }
694 blob.data = (uint8_t *)ptr;
695
696 status = smb2_push_o16s16_blob(buf, ofs, blob);
697 data_blob_free(&blob);
698 return status;
699}
700
701/*
702 push a file handle into a buffer
703*/
704void smb2_push_handle(uint8_t *data, struct smb2_handle *h)
705{
706 SBVAL(data, 0, h->data[0]);
707 SBVAL(data, 8, h->data[1]);
708}
709
710/*
711 pull a file handle from a buffer
712*/
713void smb2_pull_handle(uint8_t *ptr, struct smb2_handle *h)
714{
715 h->data[0] = BVAL(ptr, 0);
716 h->data[1] = BVAL(ptr, 8);
717}
Note: See TracBrowser for help on using the repository browser.