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