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