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