s3: smbd - fix processing of packets with invalid DOS charset conversions.
[samba.git] / source3 / lib / charcnv.c
1 /*
2    Unix SMB/CIFS implementation.
3    Character set conversion Extensions
4    Copyright (C) Igor Vergeichik <iverg@mail.ru> 2001
5    Copyright (C) Andrew Tridgell 2001
6    Copyright (C) Simo Sorce 2001
7    Copyright (C) Martin Pool 2003
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21
22 */
23 #include "includes.h"
24
25 /* We can parameterize this if someone complains.... JRA. */
26
27 char lp_failed_convert_char(void)
28 {
29         return '_';
30 }
31
32 /**
33  * @file
34  *
35  * @brief Character-set conversion routines built on our iconv.
36  *
37  * @note Samba's internal character set (at least in the 3.0 series)
38  * is always the same as the one for the Unix filesystem.  It is
39  * <b>not</b> necessarily UTF-8 and may be different on machines that
40  * need i18n filenames to be compatible with Unix software.  It does
41  * have to be a superset of ASCII.  All multibyte sequences must start
42  * with a byte with the high bit set.
43  *
44  * @sa lib/iconv.c
45  */
46
47
48 static bool conv_silent; /* Should we do a debug if the conversion fails ? */
49 static bool initialized;
50
51 void lazy_initialize_conv(void)
52 {
53         if (!initialized) {
54                 load_case_tables_library();
55                 init_iconv();
56                 initialized = true;
57         }
58 }
59
60 /**
61  * Destroy global objects allocated by init_iconv()
62  **/
63 void gfree_charcnv(void)
64 {
65         TALLOC_FREE(global_iconv_convenience);
66         initialized = false;
67 }
68
69 /**
70  * Initialize iconv conversion descriptors.
71  *
72  * This is called the first time it is needed, and also called again
73  * every time the configuration is reloaded, because the charset or
74  * codepage might have changed.
75  **/
76 void init_iconv(void)
77 {
78         global_iconv_convenience = smb_iconv_convenience_reinit(NULL, lp_dos_charset(),
79                                                                 lp_unix_charset(), lp_display_charset(),
80                                                                 true, global_iconv_convenience);
81 }
82
83 /**
84  * Convert string from one encoding to another, making error checking etc
85  * Slow path version - uses (slow) iconv.
86  *
87  * @param src pointer to source string (multibyte or singlebyte)
88  * @param srclen length of the source string in bytes
89  * @param dest pointer to destination string (multibyte or singlebyte)
90  * @param destlen maximal length allowed for string
91  * @param allow_bad_conv determines if a "best effort" conversion is acceptable (never returns errors)
92  * @returns the number of bytes occupied in the destination
93  *
94  * Ensure the srclen contains the terminating zero.
95  *
96  **/
97
98 static size_t convert_string_internal(charset_t from, charset_t to,
99                       void const *src, size_t srclen, 
100                       void *dest, size_t destlen, bool allow_bad_conv)
101 {
102         size_t i_len, o_len;
103         size_t retval;
104         const char* inbuf = (const char*)src;
105         char* outbuf = (char*)dest;
106         smb_iconv_t descriptor;
107         struct smb_iconv_convenience *ic;
108
109         lazy_initialize_conv();
110         ic = get_iconv_convenience();
111         descriptor = get_conv_handle(ic, from, to);
112
113         if (srclen == (size_t)-1) {
114                 if (from == CH_UTF16LE || from == CH_UTF16BE) {
115                         srclen = (strlen_w((const smb_ucs2_t *)src)+1) * 2;
116                 } else {
117                         srclen = strlen((const char *)src)+1;
118                 }
119         }
120
121
122         if (descriptor == (smb_iconv_t)-1 || descriptor == (smb_iconv_t)0) {
123                 if (!conv_silent)
124                         DEBUG(0,("convert_string_internal: Conversion not supported.\n"));
125                 return (size_t)-1;
126         }
127
128         i_len=srclen;
129         o_len=destlen;
130
131  again:
132
133         retval = smb_iconv(descriptor, &inbuf, &i_len, &outbuf, &o_len);
134         if(retval==(size_t)-1) {
135                 const char *reason="unknown error";
136                 switch(errno) {
137                         case EINVAL:
138                                 reason="Incomplete multibyte sequence";
139                                 if (!conv_silent)
140                                         DEBUG(3,("convert_string_internal: Conversion error: %s(%s)\n",reason,inbuf));
141                                 if (allow_bad_conv)
142                                         goto use_as_is;
143                                 return (size_t)-1;
144                         case E2BIG:
145                                 reason="No more room"; 
146                                 if (!conv_silent) {
147                                         if (from == CH_UNIX) {
148                                                 DEBUG(3,("E2BIG: convert_string(%s,%s): srclen=%u destlen=%u - '%s'\n",
149                                                          charset_name(ic, from), charset_name(ic, to),
150                                                         (unsigned int)srclen, (unsigned int)destlen, (const char *)src));
151                                         } else {
152                                                 DEBUG(3,("E2BIG: convert_string(%s,%s): srclen=%u destlen=%u\n",
153                                                          charset_name(ic, from), charset_name(ic, to),
154                                                         (unsigned int)srclen, (unsigned int)destlen));
155                                         }
156                                 }
157                                 break;
158                         case EILSEQ:
159                                 reason="Illegal multibyte sequence";
160                                 if (!conv_silent)
161                                         DEBUG(3,("convert_string_internal: Conversion error: %s(%s)\n",reason,inbuf));
162                                 if (allow_bad_conv)
163                                         goto use_as_is;
164                                 
165                                 return (size_t)-1;
166                         default:
167                                 if (!conv_silent)
168                                         DEBUG(0,("convert_string_internal: Conversion error: %s(%s)\n",reason,inbuf));
169                                 return (size_t)-1;
170                 }
171                 /* smb_panic(reason); */
172         }
173         return destlen-o_len;
174
175  use_as_is:
176
177         /* 
178          * Conversion not supported. This is actually an error, but there are so
179          * many misconfigured iconv systems and smb.conf's out there we can't just
180          * fail. Do a very bad conversion instead.... JRA.
181          */
182
183         {
184                 if (o_len == 0 || i_len == 0)
185                         return destlen - o_len;
186
187                 if (((from == CH_UTF16LE)||(from == CH_UTF16BE)) &&
188                                 ((to != CH_UTF16LE)||(to != CH_UTF16BE))) {
189                         /* Can't convert from utf16 any endian to multibyte.
190                            Replace with the default fail char.
191                         */
192                         if (i_len < 2)
193                                 return destlen - o_len;
194                         if (i_len >= 2) {
195                                 *outbuf = lp_failed_convert_char();
196
197                                 outbuf++;
198                                 o_len--;
199
200                                 inbuf += 2;
201                                 i_len -= 2;
202                         }
203
204                         if (o_len == 0 || i_len == 0)
205                                 return destlen - o_len;
206
207                         /* Keep trying with the next char... */
208                         goto again;
209
210                 } else if (from != CH_UTF16LE && from != CH_UTF16BE && to == CH_UTF16LE) {
211                         /* Can't convert to UTF16LE - just widen by adding the
212                            default fail char then zero.
213                         */
214                         if (o_len < 2)
215                                 return destlen - o_len;
216
217                         outbuf[0] = lp_failed_convert_char();
218                         outbuf[1] = '\0';
219
220                         inbuf++;
221                         i_len--;
222
223                         outbuf += 2;
224                         o_len -= 2;
225
226                         if (o_len == 0 || i_len == 0)
227                                 return destlen - o_len;
228
229                         /* Keep trying with the next char... */
230                         goto again;
231
232                 } else if (from != CH_UTF16LE && from != CH_UTF16BE &&
233                                 to != CH_UTF16LE && to != CH_UTF16BE) {
234                         /* Failed multibyte to multibyte. Just copy the default fail char and
235                                 try again. */
236                         outbuf[0] = lp_failed_convert_char();
237
238                         inbuf++;
239                         i_len--;
240
241                         outbuf++;
242                         o_len--;
243
244                         if (o_len == 0 || i_len == 0)
245                                 return destlen - o_len;
246
247                         /* Keep trying with the next char... */
248                         goto again;
249
250                 } else {
251                         /* Keep compiler happy.... */
252                         return destlen - o_len;
253                 }
254         }
255 }
256
257 /**
258  * Convert string from one encoding to another, making error checking etc
259  * Fast path version - handles ASCII first.
260  *
261  * @param src pointer to source string (multibyte or singlebyte)
262  * @param srclen length of the source string in bytes, or -1 for nul terminated.
263  * @param dest pointer to destination string (multibyte or singlebyte)
264  * @param destlen maximal length allowed for string - *NEVER* -1.
265  * @param allow_bad_conv determines if a "best effort" conversion is acceptable (never returns errors)
266  * @returns the number of bytes occupied in the destination
267  *
268  * Ensure the srclen contains the terminating zero.
269  *
270  * This function has been hand-tuned to provide a fast path.
271  * Don't change unless you really know what you are doing. JRA.
272  **/
273
274 size_t convert_string(charset_t from, charset_t to,
275                       void const *src, size_t srclen, 
276                       void *dest, size_t destlen, bool allow_bad_conv)
277 {
278         /*
279          * NB. We deliberately don't do a strlen here if srclen == -1.
280          * This is very expensive over millions of calls and is taken
281          * care of in the slow path in convert_string_internal. JRA.
282          */
283
284 #ifdef DEVELOPER
285         SMB_ASSERT(destlen != (size_t)-1);
286 #endif
287
288         if (srclen == 0)
289                 return 0;
290
291         if (from != CH_UTF16LE && from != CH_UTF16BE && to != CH_UTF16LE && to != CH_UTF16BE) {
292                 const unsigned char *p = (const unsigned char *)src;
293                 unsigned char *q = (unsigned char *)dest;
294                 size_t slen = srclen;
295                 size_t dlen = destlen;
296                 unsigned char lastp = '\0';
297                 size_t retval = 0;
298
299                 /* If all characters are ascii, fast path here. */
300                 while (slen && dlen) {
301                         if ((lastp = *p) <= 0x7f) {
302                                 *q++ = *p++;
303                                 if (slen != (size_t)-1) {
304                                         slen--;
305                                 }
306                                 dlen--;
307                                 retval++;
308                                 if (!lastp)
309                                         break;
310                         } else {
311 #ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS
312                                 goto general_case;
313 #else
314                                 size_t ret = convert_string_internal(from, to, p, slen, q, dlen, allow_bad_conv);
315                                 if (ret == (size_t)-1) {
316                                         return ret;
317                                 }
318                                 return retval + ret;
319 #endif
320                         }
321                 }
322                 if (!dlen) {
323                         /* Even if we fast path we should note if we ran out of room. */
324                         if (((slen != (size_t)-1) && slen) ||
325                                         ((slen == (size_t)-1) && lastp)) {
326                                 errno = E2BIG;
327                         }
328                 }
329                 return retval;
330         } else if (from == CH_UTF16LE && to != CH_UTF16LE) {
331                 const unsigned char *p = (const unsigned char *)src;
332                 unsigned char *q = (unsigned char *)dest;
333                 size_t retval = 0;
334                 size_t slen = srclen;
335                 size_t dlen = destlen;
336                 unsigned char lastp = '\0';
337
338                 /* If all characters are ascii, fast path here. */
339                 while (((slen == (size_t)-1) || (slen >= 2)) && dlen) {
340                         if (((lastp = *p) <= 0x7f) && (p[1] == 0)) {
341                                 *q++ = *p;
342                                 if (slen != (size_t)-1) {
343                                         slen -= 2;
344                                 }
345                                 p += 2;
346                                 dlen--;
347                                 retval++;
348                                 if (!lastp)
349                                         break;
350                         } else {
351 #ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS
352                                 goto general_case;
353 #else
354                                 size_t ret = convert_string_internal(from, to, p, slen, q, dlen, allow_bad_conv);
355                                 if (ret == (size_t)-1) {
356                                         return ret;
357                                 }
358                                 return retval + ret;
359 #endif
360                         }
361                 }
362                 if (!dlen) {
363                         /* Even if we fast path we should note if we ran out of room. */
364                         if (((slen != (size_t)-1) && slen) ||
365                                         ((slen == (size_t)-1) && lastp)) {
366                                 errno = E2BIG;
367                         }
368                 }
369                 return retval;
370         } else if (from != CH_UTF16LE && from != CH_UTF16BE && to == CH_UTF16LE) {
371                 const unsigned char *p = (const unsigned char *)src;
372                 unsigned char *q = (unsigned char *)dest;
373                 size_t retval = 0;
374                 size_t slen = srclen;
375                 size_t dlen = destlen;
376                 unsigned char lastp = '\0';
377
378                 /* If all characters are ascii, fast path here. */
379                 while (slen && (dlen >= 2)) {
380                         if ((lastp = *p) <= 0x7F) {
381                                 *q++ = *p++;
382                                 *q++ = '\0';
383                                 if (slen != (size_t)-1) {
384                                         slen--;
385                                 }
386                                 dlen -= 2;
387                                 retval += 2;
388                                 if (!lastp)
389                                         break;
390                         } else {
391 #ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS
392                                 goto general_case;
393 #else
394                                 size_t ret = convert_string_internal(from, to, p, slen, q, dlen, allow_bad_conv);
395                                 if (ret == (size_t)-1) {
396                                         return ret;
397                                 }
398                                 return retval + ret;
399 #endif
400                         }
401                 }
402                 if (!dlen) {
403                         /* Even if we fast path we should note if we ran out of room. */
404                         if (((slen != (size_t)-1) && slen) ||
405                                         ((slen == (size_t)-1) && lastp)) {
406                                 errno = E2BIG;
407                         }
408                 }
409                 return retval;
410         }
411
412 #ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS
413   general_case:
414 #endif
415         return convert_string_internal(from, to, src, srclen, dest, destlen, allow_bad_conv);
416 }
417
418 /**
419  * Convert between character sets, allocating a new buffer using talloc for the result.
420  *
421  * @param srclen length of source buffer.
422  * @param dest always set at least to NULL
423  * @parm converted_size set to the number of bytes occupied by the string in
424  * the destination on success.
425  * @note -1 is not accepted for srclen.
426  *
427  * @return true if new buffer was correctly allocated, and string was
428  * converted.
429  *
430  * Ensure the srclen contains the terminating zero.
431  *
432  * I hate the goto's in this function. It's embarressing.....
433  * There has to be a cleaner way to do this. JRA.
434  */
435 bool convert_string_talloc(TALLOC_CTX *ctx, charset_t from, charset_t to,
436                            void const *src, size_t srclen, void *dst,
437                            size_t *converted_size, bool allow_bad_conv)
438
439 {
440         size_t i_len, o_len, destlen = (srclen * 3) / 2;
441         size_t retval;
442         const char *inbuf = (const char *)src;
443         char *outbuf = NULL, *ob = NULL;
444         smb_iconv_t descriptor;
445         void **dest = (void **)dst;
446         struct smb_iconv_convenience *ic;
447
448         *dest = NULL;
449
450         if (!converted_size) {
451                 errno = EINVAL;
452                 return false;
453         }
454
455         if (src == NULL || srclen == (size_t)-1) {
456                 errno = EINVAL;
457                 return false;
458         }
459
460         if (srclen == 0) {
461                 /* We really should treat this as an error, but
462                    there are too many callers that need this to
463                    return a NULL terminated string in the correct
464                    character set. */
465                 if (to == CH_UTF16LE|| to == CH_UTF16BE || to == CH_UTF16MUNGED) {
466                         destlen = 2;
467                 } else {
468                         destlen = 1;
469                 }
470                 ob = talloc_zero_array(ctx, char, destlen);
471                 if (ob == NULL) {
472                         errno = ENOMEM;
473                         return false;
474                 }
475                 *converted_size = destlen;
476                 *dest = ob;
477                 return true;
478         }
479
480         lazy_initialize_conv();
481         ic = get_iconv_convenience();
482         descriptor = get_conv_handle(ic, from, to);
483
484         if (descriptor == (smb_iconv_t)-1 || descriptor == (smb_iconv_t)0) {
485                 if (!conv_silent)
486                         DEBUG(0,("convert_string_talloc: Conversion not supported.\n"));
487                 errno = EOPNOTSUPP;
488                 return false;
489         }
490
491   convert:
492
493         /* +2 is for ucs2 null termination. */
494         if ((destlen*2)+2 < destlen) {
495                 /* wrapped ! abort. */
496                 if (!conv_silent)
497                         DEBUG(0, ("convert_string_talloc: destlen wrapped !\n"));
498                 TALLOC_FREE(outbuf);
499                 errno = EOPNOTSUPP;
500                 return false;
501         } else {
502                 destlen = destlen * 2;
503         }
504
505         /* +2 is for ucs2 null termination. */
506         ob = (char *)TALLOC_REALLOC(ctx, ob, destlen + 2);
507
508         if (!ob) {
509                 DEBUG(0, ("convert_string_talloc: realloc failed!\n"));
510                 errno = ENOMEM;
511                 return false;
512         }
513         outbuf = ob;
514         i_len = srclen;
515         o_len = destlen;
516
517  again:
518
519         retval = smb_iconv(descriptor,
520                            &inbuf, &i_len,
521                            &outbuf, &o_len);
522         if(retval == (size_t)-1)                {
523                 const char *reason="unknown error";
524                 switch(errno) {
525                         case EINVAL:
526                                 reason="Incomplete multibyte sequence";
527                                 if (!conv_silent)
528                                         DEBUG(3,("convert_string_talloc: Conversion error: %s(%s)\n",reason,inbuf));
529                                 if (allow_bad_conv)
530                                         goto use_as_is;
531                                 break;
532                         case E2BIG:
533                                 goto convert;
534                         case EILSEQ:
535                                 reason="Illegal multibyte sequence";
536                                 if (!conv_silent)
537                                         DEBUG(3,("convert_string_talloc: Conversion error: %s(%s)\n",reason,inbuf));
538                                 if (allow_bad_conv)
539                                         goto use_as_is;
540                                 break;
541                 }
542                 if (!conv_silent)
543                         DEBUG(0,("Conversion error: %s(%s)\n",reason,inbuf));
544                 /* smb_panic(reason); */
545                 TALLOC_FREE(ob);
546                 return false;
547         }
548
549   out:
550
551         destlen = destlen - o_len;
552         /* Don't shrink unless we're reclaiming a lot of
553          * space. This is in the hot codepath and these
554          * reallocs *cost*. JRA.
555          */
556         if (o_len > 1024) {
557                 /* We're shrinking here so we know the +2 is safe from wrap. */
558                 ob = (char *)TALLOC_REALLOC(ctx,ob,destlen + 2);
559         }
560
561         if (destlen && !ob) {
562                 DEBUG(0, ("convert_string_talloc: out of memory!\n"));
563                 errno = ENOMEM;
564                 return false;
565         }
566
567         *dest = ob;
568
569         /* Must ucs2 null terminate in the extra space we allocated. */
570         ob[destlen] = '\0';
571         ob[destlen+1] = '\0';
572
573         /* Ensure we can never return a *converted_size of zero. */
574         if (destlen == 0) {
575                 /* This can happen from a bad iconv "use_as_is:" call. */
576                 if (to == CH_UTF16LE|| to == CH_UTF16BE || to == CH_UTF16MUNGED) {
577                         destlen = 2;
578                 } else {
579                         destlen = 1;
580                 }
581         }
582
583         *converted_size = destlen;
584         return true;
585
586  use_as_is:
587
588         /* 
589          * Conversion not supported. This is actually an error, but there are so
590          * many misconfigured iconv systems and smb.conf's out there we can't just
591          * fail. Do a very bad conversion instead.... JRA.
592          */
593
594         {
595                 if (o_len == 0 || i_len == 0)
596                         goto out;
597
598                 if (((from == CH_UTF16LE)||(from == CH_UTF16BE)) &&
599                                 ((to != CH_UTF16LE)||(to != CH_UTF16BE))) {
600                         /* Can't convert from utf16 any endian to multibyte.
601                            Replace with the default fail char.
602                         */
603
604                         if (i_len < 2)
605                                 goto out;
606
607                         if (i_len >= 2) {
608                                 *outbuf = lp_failed_convert_char();
609
610                                 outbuf++;
611                                 o_len--;
612
613                                 inbuf += 2;
614                                 i_len -= 2;
615                         }
616
617                         if (o_len == 0 || i_len == 0)
618                                 goto out;
619
620                         /* Keep trying with the next char... */
621                         goto again;
622
623                 } else if (from != CH_UTF16LE && from != CH_UTF16BE && to == CH_UTF16LE) {
624                         /* Can't convert to UTF16LE - just widen by adding the
625                            default fail char then zero.
626                         */
627                         if (o_len < 2)
628                                 goto out;
629
630                         outbuf[0] = lp_failed_convert_char();
631                         outbuf[1] = '\0';
632
633                         inbuf++;
634                         i_len--;
635
636                         outbuf += 2;
637                         o_len -= 2;
638
639                         if (o_len == 0 || i_len == 0)
640                                 goto out;
641
642                         /* Keep trying with the next char... */
643                         goto again;
644
645                 } else if (from != CH_UTF16LE && from != CH_UTF16BE &&
646                                 to != CH_UTF16LE && to != CH_UTF16BE) {
647                         /* Failed multibyte to multibyte. Just copy the default fail char and
648                            try again. */
649                         outbuf[0] = lp_failed_convert_char();
650
651                         inbuf++;
652                         i_len--;
653
654                         outbuf++;
655                         o_len--;
656
657                         if (o_len == 0 || i_len == 0)
658                                 goto out;
659
660                         /* Keep trying with the next char... */
661                         goto again;
662
663                 } else {
664                         /* Keep compiler happy.... */
665                         goto out;
666                 }
667         }
668 }
669
670 size_t unix_strupper(const char *src, size_t srclen, char *dest, size_t destlen)
671 {
672         size_t size;
673         smb_ucs2_t *buffer;
674
675         if (!push_ucs2_talloc(talloc_tos(), &buffer, src, &size)) {
676                 return (size_t)-1;
677         }
678
679         if (!strupper_w(buffer) && (dest == src)) {
680                 TALLOC_FREE(buffer);
681                 return srclen;
682         }
683
684         size = convert_string(CH_UTF16LE, CH_UNIX, buffer, size, dest, destlen, True);
685         TALLOC_FREE(buffer);
686         return size;
687 }
688
689 /**
690  talloc_strdup() a unix string to upper case.
691 **/
692
693 char *talloc_strdup_upper(TALLOC_CTX *ctx, const char *s)
694 {
695         char *out_buffer = talloc_strdup(ctx,s);
696         const unsigned char *p = (const unsigned char *)s;
697         unsigned char *q = (unsigned char *)out_buffer;
698
699         if (!q) {
700                 return NULL;
701         }
702
703         /* this is quite a common operation, so we want it to be
704            fast. We optimise for the ascii case, knowing that all our
705            supported multi-byte character sets are ascii-compatible
706            (ie. they match for the first 128 chars) */
707
708         while (*p) {
709                 if (*p & 0x80)
710                         break;
711                 *q++ = toupper_ascii_fast(*p);
712                 p++;
713         }
714
715         if (*p) {
716                 /* MB case. */
717                 size_t converted_size, converted_size2;
718                 smb_ucs2_t *ubuf = NULL;
719
720                 /* We're not using the ascii buffer above. */
721                 TALLOC_FREE(out_buffer);
722
723                 if (!convert_string_talloc(ctx, CH_UNIX, CH_UTF16LE, s,
724                                            strlen(s)+1, (void *)&ubuf,
725                                            &converted_size, True))
726                 {
727                         return NULL;
728                 }
729
730                 strupper_w(ubuf);
731
732                 if (!convert_string_talloc(ctx, CH_UTF16LE, CH_UNIX, ubuf,
733                                            converted_size, (void *)&out_buffer,
734                                            &converted_size2, True))
735                 {
736                         TALLOC_FREE(ubuf);
737                         return NULL;
738                 }
739
740                 /* Don't need the intermediate buffer
741                  * anymore.
742                  */
743                 TALLOC_FREE(ubuf);
744         }
745
746         return out_buffer;
747 }
748
749 char *strupper_talloc(TALLOC_CTX *ctx, const char *s) {
750         return talloc_strdup_upper(ctx, s);
751 }
752
753
754 size_t unix_strlower(const char *src, size_t srclen, char *dest, size_t destlen)
755 {
756         size_t size;
757         smb_ucs2_t *buffer = NULL;
758
759         if (!convert_string_talloc(talloc_tos(), CH_UNIX, CH_UTF16LE, src, srclen,
760                                    (void **)(void *)&buffer, &size,
761                                    True))
762         {
763                 smb_panic("failed to create UCS2 buffer");
764         }
765         if (!strlower_w(buffer) && (dest == src)) {
766                 TALLOC_FREE(buffer);
767                 return srclen;
768         }
769         size = convert_string(CH_UTF16LE, CH_UNIX, buffer, size, dest, destlen, True);
770         TALLOC_FREE(buffer);
771         return size;
772 }
773
774
775 char *talloc_strdup_lower(TALLOC_CTX *ctx, const char *s)
776 {
777         size_t converted_size;
778         smb_ucs2_t *buffer = NULL;
779         char *out_buffer;
780
781         if (!push_ucs2_talloc(ctx, &buffer, s, &converted_size)) {
782                 return NULL;
783         }
784
785         strlower_w(buffer);
786
787         if (!pull_ucs2_talloc(ctx, &out_buffer, buffer, &converted_size)) {
788                 TALLOC_FREE(buffer);
789                 return NULL;
790         }
791
792         TALLOC_FREE(buffer);
793
794         return out_buffer;
795 }
796
797 char *strlower_talloc(TALLOC_CTX *ctx, const char *s) {
798         return talloc_strdup_lower(ctx, s);
799 }
800
801 size_t ucs2_align(const void *base_ptr, const void *p, int flags)
802 {
803         if (flags & (STR_NOALIGN|STR_ASCII))
804                 return 0;
805         return PTR_DIFF(p, base_ptr) & 1;
806 }
807
808
809 /**
810  * Copy a string from a char* unix src to a dos codepage string destination.
811  *
812  * @return the number of bytes occupied by the string in the destination.
813  *
814  * @param flags can include
815  * <dl>
816  * <dt>STR_TERMINATE</dt> <dd>means include the null termination</dd>
817  * <dt>STR_UPPER</dt> <dd>means uppercase in the destination</dd>
818  * </dl>
819  *
820  * @param dest_len the maximum length in bytes allowed in the
821  * destination.
822  **/
823 size_t push_ascii(void *dest, const char *src, size_t dest_len, int flags)
824 {
825         size_t src_len = 0;
826         char *tmpbuf = NULL;
827         size_t ret;
828
829         /* No longer allow a length of -1. */
830         if (dest_len == (size_t)-1) {
831                 smb_panic("push_ascii - dest_len == -1");
832         }
833
834         if (flags & STR_UPPER) {
835                 tmpbuf = SMB_STRDUP(src);
836                 if (!tmpbuf) {
837                         smb_panic("malloc fail");
838                 }
839                 strupper_m(tmpbuf);
840                 src = tmpbuf;
841         }
842
843         src_len = strlen(src);
844         if (flags & (STR_TERMINATE | STR_TERMINATE_ASCII)) {
845                 src_len++;
846         }
847
848         ret = convert_string(CH_UNIX, CH_DOS, src, src_len, dest, dest_len, True);
849
850         SAFE_FREE(tmpbuf);
851         if (ret == (size_t)-1) {
852                 if ((flags & (STR_TERMINATE | STR_TERMINATE_ASCII))
853                                 && dest_len > 0) {
854                         ((char *)dest)[0] = '\0';
855                 }
856                 return 0;
857         }
858         return ret;
859 }
860
861 size_t push_ascii_fstring(void *dest, const char *src)
862 {
863         return push_ascii(dest, src, sizeof(fstring), STR_TERMINATE);
864 }
865
866 /********************************************************************
867  Push an nstring - ensure null terminated. Written by
868  moriyama@miraclelinux.com (MORIYAMA Masayuki).
869 ********************************************************************/
870
871 size_t push_ascii_nstring(void *dest, const char *src)
872 {
873         size_t i, buffer_len, dest_len;
874         smb_ucs2_t *buffer;
875
876         conv_silent = True;
877         if (!push_ucs2_talloc(talloc_tos(), &buffer, src, &buffer_len)) {
878                 smb_panic("failed to create UCS2 buffer");
879         }
880
881         /* We're using buffer_len below to count ucs2 characters, not bytes. */
882         buffer_len /= sizeof(smb_ucs2_t);
883
884         dest_len = 0;
885         for (i = 0; buffer[i] != 0 && (i < buffer_len); i++) {
886                 unsigned char mb[10];
887                 /* Convert one smb_ucs2_t character at a time. */
888                 size_t mb_len = convert_string(CH_UTF16LE, CH_DOS, buffer+i, sizeof(smb_ucs2_t), mb, sizeof(mb), False);
889                 if ((mb_len != (size_t)-1) && (dest_len + mb_len <= MAX_NETBIOSNAME_LEN - 1)) {
890                         memcpy((char *)dest + dest_len, mb, mb_len);
891                         dest_len += mb_len;
892                 } else {
893                         errno = E2BIG;
894                         break;
895                 }
896         }
897         ((char *)dest)[dest_len] = '\0';
898
899         conv_silent = False;
900         TALLOC_FREE(buffer);
901         return dest_len;
902 }
903
904 /********************************************************************
905  Push and malloc an ascii string. src and dest null terminated.
906 ********************************************************************/
907
908 bool push_ascii_talloc(TALLOC_CTX *mem_ctx, char **dest, const char *src, size_t *converted_size)
909 {
910         size_t src_len = strlen(src)+1;
911
912         *dest = NULL;
913         return convert_string_talloc(mem_ctx, CH_UNIX, CH_DOS, src, src_len,
914                                      (void **)dest, converted_size, True);
915 }
916
917 /**
918  * Copy a string from a dos codepage source to a unix char* destination.
919  *
920  * The resulting string in "dest" is always null terminated.
921  *
922  * @param flags can have:
923  * <dl>
924  * <dt>STR_TERMINATE</dt>
925  * <dd>STR_TERMINATE means the string in @p src
926  * is null terminated, and src_len is ignored.</dd>
927  * </dl>
928  *
929  * @param src_len is the length of the source area in bytes.
930  * @returns the number of bytes occupied by the string in @p src.
931  **/
932 size_t pull_ascii(char *dest, const void *src, size_t dest_len, size_t src_len, int flags)
933 {
934         size_t ret;
935
936         if (dest_len == (size_t)-1) {
937                 /* No longer allow dest_len of -1. */
938                 smb_panic("pull_ascii - invalid dest_len of -1");
939         }
940
941         if (flags & STR_TERMINATE) {
942                 if (src_len == (size_t)-1) {
943                         src_len = strlen((const char *)src) + 1;
944                 } else {
945                         size_t len = strnlen((const char *)src, src_len);
946                         if (len < src_len)
947                                 len++;
948                         src_len = len;
949                 }
950         }
951
952         ret = convert_string(CH_DOS, CH_UNIX, src, src_len, dest, dest_len, True);
953         if (ret == (size_t)-1) {
954                 ret = 0;
955                 dest_len = 0;
956         }
957
958         if (dest_len && ret) {
959                 /* Did we already process the terminating zero ? */
960                 if (dest[MIN(ret-1, dest_len-1)] != 0) {
961                         dest[MIN(ret, dest_len-1)] = 0;
962                 }
963         } else  {
964                 dest[0] = 0;
965         }
966
967         return src_len;
968 }
969
970 /**
971  * Copy a string from a dos codepage source to a unix char* destination.
972  * Talloc version.
973  *
974  * The resulting string in "dest" is always null terminated.
975  *
976  * @param flags can have:
977  * <dl>
978  * <dt>STR_TERMINATE</dt>
979  * <dd>STR_TERMINATE means the string in @p src
980  * is null terminated, and src_len is ignored.</dd>
981  * </dl>
982  *
983  * @param src_len is the length of the source area in bytes.
984  * @returns the number of bytes occupied by the string in @p src.
985  **/
986
987 static size_t pull_ascii_base_talloc(TALLOC_CTX *ctx,
988                                      char **ppdest,
989                                      const void *src,
990                                      size_t src_len,
991                                      int flags)
992 {
993         char *dest = NULL;
994         size_t dest_len;
995
996         *ppdest = NULL;
997
998         if (!src_len) {
999                 return 0;
1000         }
1001
1002         if (flags & STR_TERMINATE) {
1003                 if (src_len == (size_t)-1) {
1004                         src_len = strlen((const char *)src) + 1;
1005                 } else {
1006                         size_t len = strnlen((const char *)src, src_len);
1007                         if (len < src_len)
1008                                 len++;
1009                         src_len = len;
1010                 }
1011                 /* Ensure we don't use an insane length from the client. */
1012                 if (src_len >= 1024*1024) {
1013                         char *msg = talloc_asprintf(ctx,
1014                                         "Bad src length (%u) in "
1015                                         "pull_ascii_base_talloc",
1016                                         (unsigned int)src_len);
1017                         smb_panic(msg);
1018                 }
1019         } else {
1020                 /* Can't have an unlimited length
1021                  * non STR_TERMINATE'd.
1022                  */
1023                 if (src_len == (size_t)-1) {
1024                         errno = EINVAL;
1025                         return 0;
1026                 }
1027         }
1028
1029         /* src_len != -1 here. */
1030
1031         if (!convert_string_talloc(ctx, CH_DOS, CH_UNIX, src, src_len, &dest,
1032                                      &dest_len, True)) {
1033                 dest_len = 0;
1034         }
1035
1036         if (dest_len && dest) {
1037                 /* Did we already process the terminating zero ? */
1038                 if (dest[dest_len-1] != 0) {
1039                         size_t size = talloc_get_size(dest);
1040                         /* Have we got space to append the '\0' ? */
1041                         if (size <= dest_len) {
1042                                 /* No, realloc. */
1043                                 dest = TALLOC_REALLOC_ARRAY(ctx, dest, char,
1044                                                 dest_len+1);
1045                                 if (!dest) {
1046                                         /* talloc fail. */
1047                                         dest_len = (size_t)-1;
1048                                         return 0;
1049                                 }
1050                         }
1051                         /* Yay - space ! */
1052                         dest[dest_len] = '\0';
1053                         dest_len++;
1054                 }
1055         } else if (dest) {
1056                 dest[0] = 0;
1057         }
1058
1059         *ppdest = dest;
1060         return src_len;
1061 }
1062
1063 size_t pull_ascii_fstring(char *dest, const void *src)
1064 {
1065         return pull_ascii(dest, src, sizeof(fstring), -1, STR_TERMINATE);
1066 }
1067
1068 /* When pulling an nstring it can expand into a larger size (dos cp -> utf8). Cope with this. */
1069
1070 size_t pull_ascii_nstring(char *dest, size_t dest_len, const void *src)
1071 {
1072         return pull_ascii(dest, src, dest_len, sizeof(nstring)-1, STR_TERMINATE);
1073 }
1074
1075 /**
1076  * Copy a string from a char* src to a unicode destination.
1077  *
1078  * @returns the number of bytes occupied by the string in the destination.
1079  *
1080  * @param flags can have:
1081  *
1082  * <dl>
1083  * <dt>STR_TERMINATE <dd>means include the null termination.
1084  * <dt>STR_UPPER     <dd>means uppercase in the destination.
1085  * <dt>STR_NOALIGN   <dd>means don't do alignment.
1086  * </dl>
1087  *
1088  * @param dest_len is the maximum length allowed in the
1089  * destination.
1090  **/
1091
1092 size_t push_ucs2(const void *base_ptr, void *dest, const char *src, size_t dest_len, int flags)
1093 {
1094         size_t len=0;
1095         size_t src_len;
1096         size_t ret;
1097
1098         if (dest_len == (size_t)-1) {
1099                 /* No longer allow dest_len of -1. */
1100                 smb_panic("push_ucs2 - invalid dest_len of -1");
1101         }
1102
1103         if (flags & STR_TERMINATE)
1104                 src_len = (size_t)-1;
1105         else
1106                 src_len = strlen(src);
1107
1108         if (ucs2_align(base_ptr, dest, flags)) {
1109                 *(char *)dest = 0;
1110                 dest = (void *)((char *)dest + 1);
1111                 if (dest_len)
1112                         dest_len--;
1113                 len++;
1114         }
1115
1116         /* ucs2 is always a multiple of 2 bytes */
1117         dest_len &= ~1;
1118
1119         ret =  convert_string(CH_UNIX, CH_UTF16LE, src, src_len, dest, dest_len, True);
1120         if (ret == (size_t)-1) {
1121                 if ((flags & STR_TERMINATE) &&
1122                                 dest &&
1123                                 dest_len) {
1124                         *(char *)dest = 0;
1125                 }
1126                 return len;
1127         }
1128
1129         len += ret;
1130
1131         if (flags & STR_UPPER) {
1132                 smb_ucs2_t *dest_ucs2 = (smb_ucs2_t *)dest;
1133                 size_t i;
1134
1135                 /* We check for i < (ret / 2) below as the dest string isn't null
1136                    terminated if STR_TERMINATE isn't set. */
1137
1138                 for (i = 0; i < (ret / 2) && i < (dest_len / 2) && dest_ucs2[i]; i++) {
1139                         smb_ucs2_t v = toupper_w(dest_ucs2[i]);
1140                         if (v != dest_ucs2[i]) {
1141                                 dest_ucs2[i] = v;
1142                         }
1143                 }
1144         }
1145
1146         return len;
1147 }
1148
1149
1150 /**
1151  * Copy a string from a unix char* src to a UCS2 destination,
1152  * allocating a buffer using talloc().
1153  *
1154  * @param dest always set at least to NULL 
1155  * @parm converted_size set to the number of bytes occupied by the string in
1156  * the destination on success.
1157  *
1158  * @return true if new buffer was correctly allocated, and string was
1159  * converted.
1160  **/
1161 bool push_ucs2_talloc(TALLOC_CTX *ctx, smb_ucs2_t **dest, const char *src,
1162                       size_t *converted_size)
1163 {
1164         size_t src_len = strlen(src)+1;
1165
1166         *dest = NULL;
1167         return convert_string_talloc(ctx, CH_UNIX, CH_UTF16LE, src, src_len,
1168                                      (void **)dest, converted_size, True);
1169 }
1170
1171
1172 /**
1173  Copy a string from a char* src to a UTF-8 destination.
1174  Return the number of bytes occupied by the string in the destination
1175  Flags can have:
1176   STR_TERMINATE means include the null termination
1177   STR_UPPER     means uppercase in the destination
1178  dest_len is the maximum length allowed in the destination. If dest_len
1179  is -1 then no maxiumum is used.
1180 **/
1181
1182 static size_t push_utf8(void *dest, const char *src, size_t dest_len, int flags)
1183 {
1184         size_t src_len = 0;
1185         size_t ret;
1186         char *tmpbuf = NULL;
1187
1188         if (dest_len == (size_t)-1) {
1189                 /* No longer allow dest_len of -1. */
1190                 smb_panic("push_utf8 - invalid dest_len of -1");
1191         }
1192
1193         if (flags & STR_UPPER) {
1194                 tmpbuf = strupper_talloc(talloc_tos(), src);
1195                 if (!tmpbuf) {
1196                         return (size_t)-1;
1197                 }
1198                 src = tmpbuf;
1199                 src_len = strlen(src);
1200         }
1201
1202         src_len = strlen(src);
1203         if (flags & STR_TERMINATE) {
1204                 src_len++;
1205         }
1206
1207         ret = convert_string(CH_UNIX, CH_UTF8, src, src_len, dest, dest_len, True);
1208         TALLOC_FREE(tmpbuf);
1209         return ret;
1210 }
1211
1212 size_t push_utf8_fstring(void *dest, const char *src)
1213 {
1214         return push_utf8(dest, src, sizeof(fstring), STR_TERMINATE);
1215 }
1216
1217 /**
1218  * Copy a string from a unix char* src to a UTF-8 destination, allocating a buffer using talloc
1219  *
1220  * @param dest always set at least to NULL 
1221  * @parm converted_size set to the number of bytes occupied by the string in
1222  * the destination on success.
1223  *
1224  * @return true if new buffer was correctly allocated, and string was
1225  * converted.
1226  **/
1227
1228 bool push_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src,
1229                       size_t *converted_size)
1230 {
1231         size_t src_len = strlen(src)+1;
1232
1233         *dest = NULL;
1234         return convert_string_talloc(ctx, CH_UNIX, CH_UTF8, src, src_len,
1235                                      (void**)dest, converted_size, True);
1236 }
1237
1238 /**
1239  Copy a string from a ucs2 source to a unix char* destination.
1240  Flags can have:
1241   STR_TERMINATE means the string in src is null terminated.
1242   STR_NOALIGN   means don't try to align.
1243  if STR_TERMINATE is set then src_len is ignored if it is -1.
1244  src_len is the length of the source area in bytes
1245  Return the number of bytes occupied by the string in src.
1246  The resulting string in "dest" is always null terminated.
1247 **/
1248
1249 size_t pull_ucs2(const void *base_ptr, char *dest, const void *src, size_t dest_len, size_t src_len, int flags)
1250 {
1251         size_t ret;
1252         size_t ucs2_align_len = 0;
1253
1254         if (dest_len == (size_t)-1) {
1255                 /* No longer allow dest_len of -1. */
1256                 smb_panic("pull_ucs2 - invalid dest_len of -1");
1257         }
1258
1259         if (!src_len) {
1260                 if (dest && dest_len > 0) {
1261                         dest[0] = '\0';
1262                 }
1263                 return 0;
1264         }
1265
1266         if (ucs2_align(base_ptr, src, flags)) {
1267                 src = (const void *)((const char *)src + 1);
1268                 if (src_len != (size_t)-1)
1269                         src_len--;
1270                 ucs2_align_len = 1;
1271         }
1272
1273         if (flags & STR_TERMINATE) {
1274                 /* src_len -1 is the default for null terminated strings. */
1275                 if (src_len != (size_t)-1) {
1276                         size_t len = strnlen_w((const smb_ucs2_t *)src,
1277                                                 src_len/2);
1278                         if (len < src_len/2)
1279                                 len++;
1280                         src_len = len*2;
1281                 }
1282         }
1283
1284         /* ucs2 is always a multiple of 2 bytes */
1285         if (src_len != (size_t)-1)
1286                 src_len &= ~1;
1287
1288         ret = convert_string(CH_UTF16LE, CH_UNIX, src, src_len, dest, dest_len, True);
1289         if (ret == (size_t)-1) {
1290                 ret = 0;
1291                 dest_len = 0;
1292         }
1293
1294         if (src_len == (size_t)-1)
1295                 src_len = ret*2;
1296
1297         if (dest_len && ret) {
1298                 /* Did we already process the terminating zero ? */
1299                 if (dest[MIN(ret-1, dest_len-1)] != 0) {
1300                         dest[MIN(ret, dest_len-1)] = 0;
1301                 }
1302         } else {
1303                 dest[0] = 0;
1304         }
1305
1306         return src_len + ucs2_align_len;
1307 }
1308
1309 /**
1310  Copy a string from a ucs2 source to a unix char* destination.
1311  Talloc version with a base pointer.
1312  Uses malloc if TALLOC_CTX is NULL (this is a bad interface and
1313  needs fixing. JRA).
1314  Flags can have:
1315   STR_TERMINATE means the string in src is null terminated.
1316   STR_NOALIGN   means don't try to align.
1317  if STR_TERMINATE is set then src_len is ignored if it is -1.
1318  src_len is the length of the source area in bytes
1319  Return the number of bytes occupied by the string in src.
1320  The resulting string in "dest" is always null terminated.
1321 **/
1322
1323 size_t pull_ucs2_base_talloc(TALLOC_CTX *ctx,
1324                         const void *base_ptr,
1325                         char **ppdest,
1326                         const void *src,
1327                         size_t src_len,
1328                         int flags)
1329 {
1330         char *dest;
1331         size_t dest_len;
1332         size_t ucs2_align_len = 0;
1333
1334         *ppdest = NULL;
1335
1336 #ifdef DEVELOPER
1337         /* Ensure we never use the braindead "malloc" varient. */
1338         if (ctx == NULL) {
1339                 smb_panic("NULL talloc CTX in pull_ucs2_base_talloc\n");
1340         }
1341 #endif
1342
1343         if (!src_len) {
1344                 return 0;
1345         }
1346
1347         if (ucs2_align(base_ptr, src, flags)) {
1348                 src = (const void *)((const char *)src + 1);
1349                 if (src_len != (size_t)-1)
1350                         src_len--;
1351                 ucs2_align_len = 1;
1352         }
1353
1354         if (flags & STR_TERMINATE) {
1355                 /* src_len -1 is the default for null terminated strings. */
1356                 if (src_len != (size_t)-1) {
1357                         size_t len = strnlen_w((const smb_ucs2_t *)src,
1358                                                 src_len/2);
1359                         if (len < src_len/2)
1360                                 len++;
1361                         src_len = len*2;
1362                 } else {
1363                         /*
1364                          * src_len == -1 - alloc interface won't take this
1365                          * so we must calculate.
1366                          */
1367                         src_len = (strlen_w((const smb_ucs2_t *)src)+1)*sizeof(smb_ucs2_t);
1368                 }
1369                 /* Ensure we don't use an insane length from the client. */
1370                 if (src_len >= 1024*1024) {
1371                         smb_panic("Bad src length in pull_ucs2_base_talloc\n");
1372                 }
1373         } else {
1374                 /* Can't have an unlimited length
1375                  * non STR_TERMINATE'd.
1376                  */
1377                 if (src_len == (size_t)-1) {
1378                         errno = EINVAL;
1379                         return 0;
1380                 }
1381         }
1382
1383         /* src_len != -1 here. */
1384
1385         /* ucs2 is always a multiple of 2 bytes */
1386         src_len &= ~1;
1387
1388         if (!convert_string_talloc(ctx, CH_UTF16LE, CH_UNIX, src, src_len,
1389                                    (void *)&dest, &dest_len, True)) {
1390                 dest_len = 0;
1391         }
1392
1393         if (dest_len) {
1394                 /* Did we already process the terminating zero ? */
1395                 if (dest[dest_len-1] != 0) {
1396                         size_t size = talloc_get_size(dest);
1397                         /* Have we got space to append the '\0' ? */
1398                         if (size <= dest_len) {
1399                                 /* No, realloc. */
1400                                 dest = TALLOC_REALLOC_ARRAY(ctx, dest, char,
1401                                                 dest_len+1);
1402                                 if (!dest) {
1403                                         /* talloc fail. */
1404                                         dest_len = (size_t)-1;
1405                                         return 0;
1406                                 }
1407                         }
1408                         /* Yay - space ! */
1409                         dest[dest_len] = '\0';
1410                         dest_len++;
1411                 }
1412         } else if (dest) {
1413                 dest[0] = 0;
1414         }
1415
1416         *ppdest = dest;
1417         return src_len + ucs2_align_len;
1418 }
1419
1420 size_t pull_ucs2_fstring(char *dest, const void *src)
1421 {
1422         return pull_ucs2(NULL, dest, src, sizeof(fstring), -1, STR_TERMINATE);
1423 }
1424
1425 /**
1426  * Copy a string from a UCS2 src to a unix char * destination, allocating a buffer using talloc
1427  *
1428  * @param dest always set at least to NULL 
1429  * @parm converted_size set to the number of bytes occupied by the string in
1430  * the destination on success.
1431  *
1432  * @return true if new buffer was correctly allocated, and string was
1433  * converted.
1434  **/
1435
1436 bool pull_ucs2_talloc(TALLOC_CTX *ctx, char **dest, const smb_ucs2_t *src,
1437                       size_t *converted_size)
1438 {
1439         size_t src_len = (strlen_w(src)+1) * sizeof(smb_ucs2_t);
1440
1441         *dest = NULL;
1442         return convert_string_talloc(ctx, CH_UTF16LE, CH_UNIX, src, src_len,
1443                                      (void **)dest, converted_size, True);
1444 }
1445
1446 /**
1447  * Copy a string from a UTF-8 src to a unix char * destination, allocating a buffer using talloc
1448  *
1449  * @param dest always set at least to NULL 
1450  * @parm converted_size set to the number of bytes occupied by the string in
1451  * the destination on success.
1452  *
1453  * @return true if new buffer was correctly allocated, and string was
1454  * converted.
1455  **/
1456
1457 bool pull_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src,
1458                       size_t *converted_size)
1459 {
1460         size_t src_len = strlen(src)+1;
1461
1462         *dest = NULL;
1463         return convert_string_talloc(ctx, CH_UTF8, CH_UNIX, src, src_len,
1464                                      (void **)dest, converted_size, True);
1465 }
1466
1467  
1468 /**
1469  * Copy a string from a DOS src to a unix char * destination, allocating a buffer using talloc
1470  *
1471  * @param dest always set at least to NULL 
1472  * @parm converted_size set to the number of bytes occupied by the string in
1473  * the destination on success.
1474  *
1475  * @return true if new buffer was correctly allocated, and string was
1476  * converted.
1477  **/
1478
1479 bool pull_ascii_talloc(TALLOC_CTX *ctx, char **dest, const char *src,
1480                        size_t *converted_size)
1481 {
1482         size_t src_len = strlen(src)+1;
1483
1484         *dest = NULL;
1485         return convert_string_talloc(ctx, CH_DOS, CH_UNIX, src, src_len,
1486                                      (void **)dest, converted_size, True);
1487 }
1488
1489 /**
1490  Copy a string from a char* src to a unicode or ascii
1491  dos codepage destination choosing unicode or ascii based on the 
1492  flags supplied
1493  Return the number of bytes occupied by the string in the destination.
1494  flags can have:
1495   STR_TERMINATE means include the null termination.
1496   STR_UPPER     means uppercase in the destination.
1497   STR_ASCII     use ascii even with unicode packet.
1498   STR_NOALIGN   means don't do alignment.
1499  dest_len is the maximum length allowed in the destination. If dest_len
1500  is -1 then no maxiumum is used.
1501 **/
1502
1503 size_t push_string_check_fn(const char *function, unsigned int line,
1504                             void *dest, const char *src,
1505                             size_t dest_len, int flags)
1506 {
1507 #ifdef DEVELOPER
1508         /* We really need to zero fill here, not clobber
1509          * region, as we want to ensure that valgrind thinks
1510          * all of the outgoing buffer has been written to
1511          * so a send() or write() won't trap an error.
1512          * JRA.
1513          */
1514 #if 0
1515         clobber_region(function, line, dest, dest_len);
1516 #else
1517         memset(dest, '\0', dest_len);
1518 #endif
1519 #endif
1520
1521         if (!(flags & STR_ASCII) && (flags & STR_UNICODE)) {
1522                 return push_ucs2(NULL, dest, src, dest_len, flags);
1523         }
1524         return push_ascii(dest, src, dest_len, flags);
1525 }
1526
1527
1528 /**
1529  Copy a string from a char* src to a unicode or ascii
1530  dos codepage destination choosing unicode or ascii based on the 
1531  flags in the SMB buffer starting at base_ptr.
1532  Return the number of bytes occupied by the string in the destination.
1533  flags can have:
1534   STR_TERMINATE means include the null termination.
1535   STR_UPPER     means uppercase in the destination.
1536   STR_ASCII     use ascii even with unicode packet.
1537   STR_NOALIGN   means don't do alignment.
1538  dest_len is the maximum length allowed in the destination. If dest_len
1539  is -1 then no maxiumum is used.
1540 **/
1541
1542 size_t push_string_base(const char *function, unsigned int line,
1543                         const char *base, uint16 flags2, 
1544                         void *dest, const char *src,
1545                         size_t dest_len, int flags)
1546 {
1547 #ifdef DEVELOPER
1548         /* We really need to zero fill here, not clobber
1549          * region, as we want to ensure that valgrind thinks
1550          * all of the outgoing buffer has been written to
1551          * so a send() or write() won't trap an error.
1552          * JRA.
1553          */
1554 #if 0
1555         clobber_region(function, line, dest, dest_len);
1556 #else
1557         memset(dest, '\0', dest_len);
1558 #endif
1559 #endif
1560
1561         if (!(flags & STR_ASCII) && \
1562             ((flags & STR_UNICODE || \
1563               (flags2 & FLAGS2_UNICODE_STRINGS)))) {
1564                 return push_ucs2(base, dest, src, dest_len, flags);
1565         }
1566         return push_ascii(dest, src, dest_len, flags);
1567 }
1568
1569 /**
1570  Copy a string from a char* src to a unicode or ascii
1571  dos codepage destination choosing unicode or ascii based on the 
1572  flags supplied
1573  Return the number of bytes occupied by the string in the destination.
1574  flags can have:
1575   STR_TERMINATE means include the null termination.
1576   STR_UPPER     means uppercase in the destination.
1577   STR_ASCII     use ascii even with unicode packet.
1578   STR_NOALIGN   means don't do alignment.
1579  dest_len is the maximum length allowed in the destination. If dest_len
1580  is -1 then no maxiumum is used.
1581 **/
1582
1583 ssize_t push_string(void *dest, const char *src, size_t dest_len, int flags)
1584 {
1585         size_t ret;
1586 #ifdef DEVELOPER
1587         /* We really need to zero fill here, not clobber
1588          * region, as we want to ensure that valgrind thinks
1589          * all of the outgoing buffer has been written to
1590          * so a send() or write() won't trap an error.
1591          * JRA.
1592          */
1593         memset(dest, '\0', dest_len);
1594 #endif
1595
1596         if (!(flags & STR_ASCII) && \
1597             (flags & STR_UNICODE)) {
1598                 ret = push_ucs2(NULL, dest, src, dest_len, flags);
1599         } else {
1600                 ret = push_ascii(dest, src, dest_len, flags);
1601         }
1602         if (ret == (size_t)-1) {
1603                 return -1;
1604         }
1605         return ret;
1606 }
1607
1608 /**
1609  Copy a string from a unicode or ascii source (depending on
1610  the packet flags) to a char* destination.
1611  Flags can have:
1612   STR_TERMINATE means the string in src is null terminated.
1613   STR_UNICODE   means to force as unicode.
1614   STR_ASCII     use ascii even with unicode packet.
1615   STR_NOALIGN   means don't do alignment.
1616  if STR_TERMINATE is set then src_len is ignored is it is -1
1617  src_len is the length of the source area in bytes.
1618  Return the number of bytes occupied by the string in src.
1619  The resulting string in "dest" is always null terminated.
1620 **/
1621
1622 size_t pull_string_fn(const char *function,
1623                         unsigned int line,
1624                         const void *base_ptr,
1625                         uint16 smb_flags2,
1626                         char *dest,
1627                         const void *src,
1628                         size_t dest_len,
1629                         size_t src_len,
1630                         int flags)
1631 {
1632 #ifdef DEVELOPER
1633         clobber_region(function, line, dest, dest_len);
1634 #endif
1635
1636         if ((base_ptr == NULL) && ((flags & (STR_ASCII|STR_UNICODE)) == 0)) {
1637                 smb_panic("No base ptr to get flg2 and neither ASCII nor "
1638                           "UNICODE defined");
1639         }
1640
1641         if (!(flags & STR_ASCII) && \
1642             ((flags & STR_UNICODE || \
1643               (smb_flags2 & FLAGS2_UNICODE_STRINGS)))) {
1644                 return pull_ucs2(base_ptr, dest, src, dest_len, src_len, flags);
1645         }
1646         return pull_ascii(dest, src, dest_len, src_len, flags);
1647 }
1648
1649 /**
1650  Copy a string from a unicode or ascii source (depending on
1651  the packet flags) to a char* destination.
1652  Variant that uses talloc.
1653  Flags can have:
1654   STR_TERMINATE means the string in src is null terminated.
1655   STR_UNICODE   means to force as unicode.
1656   STR_ASCII     use ascii even with unicode packet.
1657   STR_NOALIGN   means don't do alignment.
1658  if STR_TERMINATE is set then src_len is ignored is it is -1
1659  src_len is the length of the source area in bytes.
1660  Return the number of bytes occupied by the string in src.
1661  The resulting string in "dest" is always null terminated.
1662 **/
1663
1664 size_t pull_string_talloc_fn(const char *function,
1665                         unsigned int line,
1666                         TALLOC_CTX *ctx,
1667                         const void *base_ptr,
1668                         uint16 smb_flags2,
1669                         char **ppdest,
1670                         const void *src,
1671                         size_t src_len,
1672                         int flags)
1673 {
1674         if ((base_ptr == NULL) && ((flags & (STR_ASCII|STR_UNICODE)) == 0)) {
1675                 smb_panic("No base ptr to get flg2 and neither ASCII nor "
1676                           "UNICODE defined");
1677         }
1678
1679         if (!(flags & STR_ASCII) && \
1680             ((flags & STR_UNICODE || \
1681               (smb_flags2 & FLAGS2_UNICODE_STRINGS)))) {
1682                 return pull_ucs2_base_talloc(ctx,
1683                                         base_ptr,
1684                                         ppdest,
1685                                         src,
1686                                         src_len,
1687                                         flags);
1688         }
1689         return pull_ascii_base_talloc(ctx,
1690                                         ppdest,
1691                                         src,
1692                                         src_len,
1693                                         flags);
1694 }
1695
1696
1697 size_t align_string(const void *base_ptr, const char *p, int flags)
1698 {
1699         if (!(flags & STR_ASCII) && \
1700             ((flags & STR_UNICODE || \
1701               (SVAL(base_ptr, smb_flg2) & FLAGS2_UNICODE_STRINGS)))) {
1702                 return ucs2_align(base_ptr, p, flags);
1703         }
1704         return 0;
1705 }
1706