s4-libcli: use new GUID functions in libcli
[ira/wip.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 "librpc/ndr/libndr.h"
31 #include "librpc/gen_ndr/ndr_misc.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 void smb_setup_bufinfo(struct smbcli_request *req)
41 {
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;
46         }
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;
50 }
51
52
53 /* destroy a request structure and return final status */
54 _PUBLIC_ NTSTATUS smbcli_request_destroy(struct smbcli_request *req)
55 {
56         NTSTATUS status;
57
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;
61
62         if (req->transport) {
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);
66         }
67
68         if (req->state == SMBCLI_REQUEST_ERROR &&
69             NT_STATUS_IS_OK(req->status)) {
70                 req->status = NT_STATUS_INTERNAL_ERROR;
71         }
72
73         status = req->status;
74
75         if (!req->do_not_free) {
76                 talloc_free(req);
77         }
78
79         return status;
80 }
81
82
83 /*
84   low-level function to setup a request buffer for a non-SMB packet 
85   at the transport level
86 */
87 struct smbcli_request *smbcli_request_setup_nonsmb(struct smbcli_transport *transport, size_t size)
88 {
89         struct smbcli_request *req;
90
91         req = talloc(transport, struct smbcli_request);
92         if (!req) {
93                 return NULL;
94         }
95         ZERO_STRUCTP(req);
96
97         /* setup the request context */
98         req->state = SMBCLI_REQUEST_INIT;
99         req->transport = transport;
100         req->session = NULL;
101         req->tree = NULL;
102         req->out.size = size;
103
104         /* over allocate by a small amount */
105         req->out.allocated = req->out.size + REQ_OVER_ALLOCATION; 
106
107         req->out.buffer = talloc_array(req, uint8_t, req->out.allocated);
108         if (!req->out.buffer) {
109                 return NULL;
110         }
111
112         SIVAL(req->out.buffer, 0, 0);
113
114         return req;
115 }
116
117
118 /*
119   setup a SMB packet at transport level
120 */
121 struct smbcli_request *smbcli_request_setup_transport(struct smbcli_transport *transport,
122                                                       uint8_t command, uint_t wct, uint_t buflen)
123 {
124         struct smbcli_request *req;
125
126         req = smbcli_request_setup_nonsmb(transport, NBT_HDR_SIZE + MIN_SMB_SIZE + wct*2 + buflen);
127
128         if (!req) return NULL;
129         
130         req->out.hdr = req->out.buffer + NBT_HDR_SIZE;
131         req->out.vwv = req->out.hdr + HDR_VWV;
132         req->out.wct = wct;
133         req->out.data = req->out.vwv + VWV(wct) + 2;
134         req->out.data_size = buflen;
135         req->out.ptr = req->out.data;
136
137         SCVAL(req->out.hdr, HDR_WCT, wct);
138         SSVAL(req->out.vwv, VWV(wct), buflen);
139
140         memcpy(req->out.hdr, "\377SMB", 4);
141         SCVAL(req->out.hdr,HDR_COM,command);
142
143         SCVAL(req->out.hdr,HDR_FLG, FLAG_CASELESS_PATHNAMES);
144         SSVAL(req->out.hdr,HDR_FLG2, 0);
145
146         if (command != SMBtranss && command != SMBtranss2) {
147                 /* assign a mid */
148                 req->mid = smbcli_transport_next_mid(transport);
149         }
150
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);
159         
160         return req;
161 }
162
163 /*
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.
168 */
169 struct smbcli_request *smbcli_request_setup_session(struct smbcli_session *session,
170                                                     uint8_t command, uint_t wct, size_t buflen)
171 {
172         struct smbcli_request *req;
173
174         req = smbcli_request_setup_transport(session->transport, command, wct, buflen);
175
176         if (!req) return NULL;
177
178         req->session = session;
179
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);
184         
185         return req;
186 }
187
188 /*
189   setup a request for tree based commands
190 */
191 struct smbcli_request *smbcli_request_setup(struct smbcli_tree *tree,
192                                             uint8_t command, 
193                                             uint_t wct, uint_t buflen)
194 {
195         struct smbcli_request *req;
196
197         req = smbcli_request_setup_session(tree->session, command, wct, buflen);
198         if (req) {
199                 req->tree = tree;
200                 SSVAL(req->out.hdr,HDR_TID,tree->tid);
201         }
202         return req;
203 }
204
205
206 /*
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.
210
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
213 */
214 static void smbcli_req_grow_allocation(struct smbcli_request *req, uint_t new_size)
215 {
216         int delta;
217         uint8_t *buf2;
218
219         delta = new_size - req->out.data_size;
220         if (delta + req->out.size <= req->out.allocated) {
221                 /* it fits in the preallocation */
222                 return;
223         }
224
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);
228         if (buf2 == NULL) {
229                 smb_panic("out of memory in req_grow_allocation");
230         }
231
232         if (buf2 == req->out.buffer) {
233                 /* the malloc library gave us the same pointer */
234                 return;
235         }
236         
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);
242
243         req->out.buffer = buf2;
244 }
245
246
247 /*
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
250   into the packet. 
251
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
254 */
255 static void smbcli_req_grow_data(struct smbcli_request *req, uint_t new_size)
256 {
257         int delta;
258
259         smbcli_req_grow_allocation(req, new_size);
260
261         delta = new_size - req->out.data_size;
262
263         req->out.size += delta;
264         req->out.data_size += delta;
265
266         /* set the BCC to the new data size */
267         SSVAL(req->out.vwv, VWV(req->out.wct), new_size);
268 }
269
270
271 /*
272   setup a chained reply in req->out with the given word count and
273   initial data buffer size.
274 */
275 NTSTATUS smbcli_chained_request_setup(struct smbcli_request *req,
276                                       uint8_t command, 
277                                       uint_t wct, size_t buflen)
278 {
279         uint_t new_size = 1 + (wct*2) + 2 + buflen;
280
281         SSVAL(req->out.vwv, VWV(0), command);
282         SSVAL(req->out.vwv, VWV(1), req->out.size - NBT_HDR_SIZE);
283
284         smbcli_req_grow_allocation(req, req->out.data_size + new_size);
285
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);
289
290         req->out.size += new_size;
291         req->out.data_size += new_size;
292
293         return NT_STATUS_OK;
294 }
295
296 /*
297   aadvance to the next chained reply in a request
298 */
299 NTSTATUS smbcli_chained_advance(struct smbcli_request *req)
300 {
301         uint8_t *buffer;
302
303         if (CVAL(req->in.vwv, VWV(0)) == SMB_CHAIN_NONE) {
304                 return NT_STATUS_NOT_FOUND;
305         }
306
307         buffer = req->in.hdr + SVAL(req->in.vwv, VWV(1));
308
309         if (buffer + 3 > req->in.buffer + req->in.size) {
310                 return NT_STATUS_BUFFER_TOO_SMALL;
311         }
312
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;
317         }
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));
320
321         /* fix the bufinfo */
322         smb_setup_bufinfo(req);
323
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;
327         }
328
329         return NT_STATUS_OK;
330 }
331
332
333 /*
334   send a message
335 */
336 bool smbcli_request_send(struct smbcli_request *req)
337 {
338         if (IVAL(req->out.buffer, 0) == 0) {
339                 _smb_setlen(req->out.buffer, req->out.size - NBT_HDR_SIZE);
340         }
341
342         smbcli_request_calculate_sign_mac(req);
343
344         smbcli_transport_send(req);
345
346         return true;
347 }
348
349
350 /*
351   receive a response to a packet
352 */
353 bool smbcli_request_receive(struct smbcli_request *req)
354 {
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;
358
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) {
362                         return false;
363                 }
364         }
365
366         return req->state == SMBCLI_REQUEST_DONE;
367 }
368
369
370 /*
371   handle oplock break requests from the server - return true if the request was
372   an oplock break
373 */
374 bool smbcli_handle_oplock_break(struct smbcli_transport *transport, uint_t len, const uint8_t *hdr, const uint8_t *vwv)
375 {
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) {
384                 return false;
385         }
386
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);
392         }
393
394         return true;
395 }
396
397 /*
398   wait for a reply to be received for a packet that just returns an error
399   code and nothing more
400 */
401 _PUBLIC_ NTSTATUS smbcli_request_simple_recv(struct smbcli_request *req)
402 {
403         (void) smbcli_request_receive(req);
404         return smbcli_request_destroy(req);
405 }
406
407
408 /* Return true if the last packet was in error */
409 bool smbcli_request_is_error(struct smbcli_request *req)
410 {
411         return NT_STATUS_IS_ERR(req->status);
412 }
413
414 /*
415   append a string into the data portion of the request packet
416
417   return the number of bytes added to the packet
418 */
419 size_t smbcli_req_append_string(struct smbcli_request *req, const char *str, uint_t flags)
420 {
421         size_t len;
422
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;
426         }
427
428         len = (strlen(str)+2) * MAX_BYTES_PER_CHAR;             
429
430         smbcli_req_grow_allocation(req, len + req->out.data_size);
431
432         len = push_string(req->out.data + req->out.data_size, str, len, flags);
433
434         smbcli_req_grow_data(req, len + req->out.data_size);
435
436         return len;
437 }
438
439
440 /*
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:
444
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
447
448  this is used in places where the non-terminated string byte length is
449  placed in the packet as a separate field  
450 */
451 size_t smbcli_req_append_string_len(struct smbcli_request *req, const char *str, uint_t flags, int *len)
452 {
453         int diff = 0;
454         size_t ret;
455
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;
459         }
460
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);
464         }
465
466         /* do the hard work */
467         ret = smbcli_req_append_string(req, str, flags);
468
469         /* see if we need to subtract the termination */
470         if (flags & STR_TERMINATE) {
471                 diff += (flags & STR_UNICODE) ? 2 : 1;
472         }
473
474         if (ret >= diff) {
475                 (*len) = ret - diff;
476         } else {
477                 (*len) = ret;
478         }
479
480         return ret;
481 }
482
483
484 /*
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
487
488   if dest is NULL, then put the string at the end of the data portion of the packet
489
490   if dest_len is -1 then no limit applies
491 */
492 size_t smbcli_req_append_ascii4(struct smbcli_request *req, const char *str, uint_t flags)
493 {
494         size_t size;
495         smbcli_req_append_bytes(req, (const uint8_t *)"\4", 1);
496         size = smbcli_req_append_string(req, str, flags);
497         return size + 1;
498 }
499
500
501 /*
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
504
505   if dest is NULL, then put the blob at the end of the data portion of the packet
506 */
507 size_t smbcli_req_append_blob(struct smbcli_request *req, const DATA_BLOB *blob)
508 {
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);
512         return blob->length;
513 }
514
515 /*
516   append raw bytes into the data portion of the request packet
517   return the number of bytes added
518 */
519 size_t smbcli_req_append_bytes(struct smbcli_request *req, const uint8_t *bytes, size_t byte_len)
520 {
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);
524         return byte_len;
525 }
526
527 /*
528   append variable block (type 5 buffer) into the data portion of the request packet
529   return the number of bytes added
530 */
531 size_t smbcli_req_append_var_block(struct smbcli_request *req, const uint8_t *bytes, uint16_t byte_len)
532 {
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 */
536         if (byte_len > 0) {
537                 memcpy(req->out.data + req->out.data_size + 3, bytes, byte_len);
538         }
539         smbcli_req_grow_data(req, byte_len + 3 + req->out.data_size);
540         return byte_len + 3;
541 }
542
543
544 /*
545   pull a UCS2 string from a request packet, returning a talloced unix string
546
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)
551
552   Note that 'byte_len' is the number of bytes in the packet
553
554   on failure zero is returned and *dest is set to NULL, otherwise the number
555   of bytes consumed in the packet is returned
556 */
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)
559 {
560         int src_len, src_len2, alignment=0;
561         bool ret;
562         size_t ret_size;
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, CH_UTF16, CH_UNIX, src, src_len2, (void **)dest, &ret_size, false);
590         if (!ret) {
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         bool ret;
616         size_t ret_size;
617
618         src_len = bufinfo->data_size - PTR_DIFF(src, bufinfo->data);
619         if (src_len < 0) {
620                 *dest = NULL;
621                 return 0;
622         }
623         if (byte_len != -1 && src_len > byte_len) {
624                 src_len = byte_len;
625         }
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 */
629                 src_len2++;
630         }
631
632         ret = convert_string_talloc(mem_ctx, CH_DOS, CH_UNIX, src, src_len2, (void **)dest, &ret_size, false);
633
634         if (!ret) {
635                 *dest = NULL;
636                 return 0;
637         }
638
639         return ret_size;
640 }
641
642 /**
643   pull a string from a request packet, returning a talloced string
644
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)
649
650   Note that 'byte_len' is the number of bytes in the packet
651
652   on failure zero is returned and *dest is set to NULL, otherwise the number
653   of bytes consumed in the packet is returned
654 */
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)
657 {
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);
661         }
662
663         return smbcli_req_pull_ascii(bufinfo, mem_ctx, dest, src, byte_len, flags);
664 }
665
666
667 /**
668   pull a DATA_BLOB from a reply packet, returning a talloced blob
669   make sure we don't go past end of packet
670
671   if byte_len is -1 then limit the blob only by packet size
672 */
673 DATA_BLOB smbcli_req_pull_blob(struct request_bufinfo *bufinfo, TALLOC_CTX *mem_ctx, const uint8_t *src, int byte_len)
674 {
675         int src_len;
676
677         src_len = bufinfo->data_size - PTR_DIFF(src, bufinfo->data);
678
679         if (src_len < 0) {
680                 return data_blob(NULL, 0);
681         }
682
683         if (byte_len != -1 && src_len > byte_len) {
684                 src_len = byte_len;
685         }
686
687         return data_blob_talloc(mem_ctx, src, src_len);
688 }
689
690 /* check that a lump of data in a request is within the bounds of the data section of
691    the packet */
692 static bool smbcli_req_data_oob(struct request_bufinfo *bufinfo, const uint8_t *ptr, uint32_t count)
693 {
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) {
699                 return true;
700         }
701         return false;
702 }
703
704 /*
705   pull a lump of data from a request packet
706
707   return false if any part is outside the data portion of the packet
708 */
709 bool smbcli_raw_pull_data(struct request_bufinfo *bufinfo, const uint8_t *src, int len, uint8_t *dest)
710 {
711         if (len == 0) return true;
712
713         if (smbcli_req_data_oob(bufinfo, src, len)) {
714                 return false;
715         }
716
717         memcpy(dest, src, len);
718         return true;
719 }
720
721
722 /*
723   put a NTTIME into a packet
724 */
725 void smbcli_push_nttime(void *base, uint16_t offset, NTTIME t)
726 {
727         SBVAL(base, offset, t);
728 }
729
730 /*
731   pull a NTTIME from a packet
732 */
733 NTTIME smbcli_pull_nttime(void *base, uint16_t offset)
734 {
735         NTTIME ret = BVAL(base, offset);
736         return ret;
737 }
738
739 /**
740   pull a UCS2 string from a blob, returning a talloced unix string
741
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)
746
747   Note that 'byte_len' is the number of bytes in the packet
748
749   on failure zero is returned and *dest is set to NULL, otherwise the number
750   of bytes consumed in the blob is returned
751 */
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)
755 {
756         int src_len, src_len2, alignment=0;
757         size_t ret_size;
758         bool ret;
759         char *dest2;
760
761         if (src < blob->data ||
762             src >= (blob->data + blob->length)) {
763                 *dest = NULL;
764                 return 0;
765         }
766
767         src_len = blob->length - PTR_DIFF(src, blob->data);
768
769         if (byte_len != -1 && src_len > byte_len) {
770                 src_len = byte_len;
771         }
772
773         if (!(flags & STR_NOALIGN) && ucs2_align(blob->data, src, flags)) {
774                 src++;
775                 alignment=1;
776                 src_len--;
777         }
778
779         if (src_len < 2) {
780                 *dest = NULL;
781                 return 0;
782         }
783
784         src_len2 = utf16_len_n(src, src_len);
785
786         ret = convert_string_talloc(mem_ctx, CH_UTF16, CH_UNIX, src, src_len2, (void **)&dest2, &ret_size, false);
787         if (!ret) {
788                 *dest = NULL;
789                 return 0;
790         }
791         *dest = dest2;
792
793         return src_len2 + alignment;
794 }
795
796 /**
797   pull a ascii string from a blob, returning a talloced string
798
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)
803
804   Note that 'byte_len' is the number of bytes in the blob
805
806   on failure zero is returned and *dest is set to NULL, otherwise the number
807   of bytes consumed in the blob is returned
808 */
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)
812 {
813         int src_len, src_len2;
814         size_t ret_size;
815         bool ret;
816         char *dest2;
817
818         src_len = blob->length - PTR_DIFF(src, blob->data);
819         if (src_len < 0) {
820                 *dest = NULL;
821                 return 0;
822         }
823         if (byte_len != -1 && src_len > byte_len) {
824                 src_len = byte_len;
825         }
826         src_len2 = strnlen((const char *)src, src_len);
827
828         if (src_len2 < src_len - 1) {
829                 /* include the termination if we didn't reach the end of the packet */
830                 src_len2++;
831         }
832
833         ret = convert_string_talloc(mem_ctx, CH_DOS, CH_UNIX, src, src_len2, (void **)&dest2, &ret_size, false);
834
835         if (!ret) {
836                 *dest = NULL;
837                 return 0;
838         }
839         *dest = dest2;
840
841         return ret_size;
842 }
843
844 /**
845   pull a string from a blob, returning a talloced struct smb_wire_string
846
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)
851
852    if STR_LEN8BIT is set in the flags then assume the length field is
853    8 bits, instead of 32
854
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
857 */
858 size_t smbcli_blob_pull_string(struct smbcli_session *session,
859                                TALLOC_CTX *mem_ctx,
860                                const DATA_BLOB *blob, 
861                                struct smb_wire_string *dest, 
862                                uint16_t len_offset, uint16_t str_offset, 
863                                uint_t flags)
864 {
865         int extra;
866         dest->s = NULL;
867
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;
876                 }
877         }
878
879         if (flags & STR_LEN8BIT) {
880                 if (len_offset > blob->length-1) {
881                         return 0;
882                 }
883                 dest->private_length = CVAL(blob->data, len_offset);
884         } else {
885                 if (len_offset > blob->length-4) {
886                         return 0;
887                 }
888                 dest->private_length = IVAL(blob->data, len_offset);
889         }
890         extra = 0;
891         dest->s = NULL;
892         if (!(flags & STR_ASCII) && (flags & STR_UNICODE)) {
893                 int align = 0;
894                 if ((str_offset&1) && !(flags & STR_NOALIGN)) {
895                         align = 1;
896                 }
897                 if (flags & STR_LEN_NOTERM) {
898                         extra = 2;
899                 }
900                 return align + extra + smbcli_blob_pull_ucs2(mem_ctx, blob, &dest->s, 
901                                                           blob->data+str_offset+align, 
902                                                           dest->private_length, flags);
903         }
904
905         if (flags & STR_LEN_NOTERM) {
906                 extra = 1;
907         }
908
909         return extra + smbcli_blob_pull_ascii(mem_ctx, blob, &dest->s, 
910                                            blob->data+str_offset, dest->private_length, flags);
911 }
912
913 /**
914   pull a string from a blob, returning a talloced char *
915
916   Currently only used by the UNIX search info level.
917
918   the string length is limited by 2 things:
919    - the data size in the blob
920    - the end of string (null termination)
921
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
924 */
925 size_t smbcli_blob_pull_unix_string(struct smbcli_session *session,
926                             TALLOC_CTX *mem_ctx,
927                             DATA_BLOB *blob, 
928                             const char **dest, 
929                             uint16_t str_offset, 
930                             uint_t flags)
931 {
932         int extra = 0;
933         *dest = NULL;
934         
935         if (!(flags & STR_ASCII) && 
936             ((flags & STR_UNICODE) || 
937              (session->transport->negotiate.capabilities & CAP_UNICODE))) {
938                 int align = 0;
939                 if ((str_offset&1) && !(flags & STR_NOALIGN)) {
940                         align = 1;
941                 }
942                 if (flags & STR_LEN_NOTERM) {
943                         extra = 2;
944                 }
945                 return align + extra + smbcli_blob_pull_ucs2(mem_ctx, blob, dest, 
946                                                           blob->data+str_offset+align, 
947                                                           -1, flags);
948         }
949
950         if (flags & STR_LEN_NOTERM) {
951                 extra = 1;
952         }
953
954         return extra + smbcli_blob_pull_ascii(mem_ctx, blob, dest,
955                                            blob->data+str_offset, -1, flags);
956 }
957
958
959 /*
960   append a string into a blob
961 */
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)
965 {
966         size_t max_len;
967         int len;
968
969         if (!str) return 0;
970
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;
974         }
975
976         max_len = (strlen(str)+2) * MAX_BYTES_PER_CHAR;         
977
978         blob->data = talloc_realloc(mem_ctx, blob->data, uint8_t, blob->length + max_len);
979         if (!blob->data) {
980                 return 0;
981         }
982
983         len = push_string(blob->data + blob->length, str, max_len, flags);
984
985         blob->length += len;
986
987         return len;
988 }
989
990 /*
991   pull a GUID structure from the wire. The buffer must be at least 16
992   bytes long
993  */
994 NTSTATUS smbcli_pull_guid(void *base, uint16_t offset,
995                           struct GUID *guid)
996 {
997         DATA_BLOB blob;
998
999         ZERO_STRUCTP(guid);
1000
1001         blob.data       = offset + (uint8_t *)base;
1002         blob.length     = 16;
1003
1004         return GUID_from_ndr_blob(&blob, guid);
1005 }
1006
1007 /*
1008   push a guid onto the wire. The buffer must hold 16 bytes
1009  */
1010 enum ndr_err_code smbcli_push_guid(void *base, uint16_t offset, 
1011                                    const struct GUID *guid)
1012 {
1013         TALLOC_CTX *tmp_ctx = talloc_new(NULL);
1014         enum ndr_err_code ndr_err;
1015         DATA_BLOB blob;
1016         ndr_err = ndr_push_struct_blob(&blob, tmp_ctx, NULL,
1017                                        guid, (ndr_push_flags_fn_t)ndr_push_GUID);
1018         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err) || blob.length != 16) {
1019                 talloc_free(tmp_ctx);
1020                 return ndr_err;
1021         }
1022         memcpy(offset + (uint8_t *)base, blob.data, blob.length);
1023         talloc_free(tmp_ctx);
1024         return ndr_err;
1025 }