Fix bug 8040 - smbclient segfaults when a Cyrillic netbios name or workgroup is confi...
[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 /**
26  * @file
27  *
28  * @brief Character-set conversion routines built on our iconv.
29  *
30  * @note Samba's internal character set (at least in the 3.0 series)
31  * is always the same as the one for the Unix filesystem.  It is
32  * <b>not</b> necessarily UTF-8 and may be different on machines that
33  * need i18n filenames to be compatible with Unix software.  It does
34  * have to be a superset of ASCII.  All multibyte sequences must start
35  * with a byte with the high bit set.
36  *
37  * @sa lib/iconv.c
38  */
39
40
41 static bool initialized;
42
43 void lazy_initialize_conv(void)
44 {
45         if (!initialized) {
46                 load_case_tables_library();
47                 init_iconv();
48                 initialized = true;
49         }
50 }
51
52 /**
53  * Destroy global objects allocated by init_iconv()
54  **/
55 void gfree_charcnv(void)
56 {
57         TALLOC_FREE(global_iconv_handle);
58         initialized = false;
59 }
60
61 /**
62  * Initialize iconv conversion descriptors.
63  *
64  * This is called the first time it is needed, and also called again
65  * every time the configuration is reloaded, because the charset or
66  * codepage might have changed.
67  **/
68 void init_iconv(void)
69 {
70         global_iconv_handle = smb_iconv_handle_reinit(NULL, lp_dos_charset(),
71                                                                 lp_unix_charset(), lp_display_charset(),
72                                                                 true, global_iconv_handle);
73 }
74
75 /**
76  * Convert string from one encoding to another, making error checking etc
77  * Slow path version - uses (slow) iconv.
78  *
79  * @param src pointer to source string (multibyte or singlebyte)
80  * @param srclen length of the source string in bytes
81  * @param dest pointer to destination string (multibyte or singlebyte)
82  * @param destlen maximal length allowed for string
83  * @returns the number of bytes occupied in the destination
84  *
85  * Ensure the srclen contains the terminating zero.
86  *
87  **/
88
89 static size_t convert_string_internal(charset_t from, charset_t to,
90                       void const *src, size_t srclen, 
91                       void *dest, size_t destlen, size_t *converted_size)
92 {
93         size_t i_len, o_len;
94         size_t retval;
95         const char* inbuf = (const char*)src;
96         char* outbuf = (char*)dest;
97         smb_iconv_t descriptor;
98         struct smb_iconv_handle *ic;
99
100         lazy_initialize_conv();
101         ic = get_iconv_handle();
102         descriptor = get_conv_handle(ic, from, to);
103
104         if (srclen == (size_t)-1) {
105                 if (from == CH_UTF16LE || from == CH_UTF16BE) {
106                         srclen = (strlen_w((const smb_ucs2_t *)src)+1) * 2;
107                 } else {
108                         srclen = strlen((const char *)src)+1;
109                 }
110         }
111
112
113         if (descriptor == (smb_iconv_t)-1 || descriptor == (smb_iconv_t)0) {
114                 errno = EINVAL;
115                 return (size_t)-1;
116         }
117
118         i_len=srclen;
119         o_len=destlen;
120
121         retval = smb_iconv(descriptor, &inbuf, &i_len, &outbuf, &o_len);
122         if (converted_size != NULL)
123                 *converted_size = destlen-o_len;
124         return retval;
125 }
126
127 /**
128  * Convert string from one encoding to another, making error checking etc
129  * Fast path version - handles ASCII first.
130  *
131  * @param src pointer to source string (multibyte or singlebyte)
132  * @param srclen length of the source string in bytes, or -1 for nul terminated.
133  * @param dest pointer to destination string (multibyte or singlebyte)
134  * @param destlen maximal length allowed for string - *NEVER* -1.
135  * @returns the number of bytes occupied in the destination
136  *
137  * Ensure the srclen contains the terminating zero.
138  *
139  * This function has been hand-tuned to provide a fast path.
140  * Don't change unless you really know what you are doing. JRA.
141  **/
142
143 size_t convert_string_error(charset_t from, charset_t to,
144                             void const *src, size_t srclen,
145                             void *dest, size_t destlen,
146                             size_t *converted_size)
147 {
148         /*
149          * NB. We deliberately don't do a strlen here if srclen == -1.
150          * This is very expensive over millions of calls and is taken
151          * care of in the slow path in convert_string_internal. JRA.
152          */
153
154 #ifdef DEVELOPER
155         SMB_ASSERT(destlen != (size_t)-1);
156 #endif
157
158         if (converted_size) {
159                 *converted_size = 0;
160         }
161
162         if (srclen == 0)
163                 return 0;
164
165         if (from != CH_UTF16LE && from != CH_UTF16BE && to != CH_UTF16LE && to != CH_UTF16BE) {
166                 const unsigned char *p = (const unsigned char *)src;
167                 unsigned char *q = (unsigned char *)dest;
168                 size_t slen = srclen;
169                 size_t dlen = destlen;
170                 unsigned char lastp = '\0';
171                 size_t retval = 0;
172
173                 /* If all characters are ascii, fast path here. */
174                 while (slen && dlen) {
175                         if ((lastp = *p) <= 0x7f) {
176                                 *q++ = *p++;
177                                 if (slen != (size_t)-1) {
178                                         slen--;
179                                 }
180                                 dlen--;
181                                 retval++;
182                                 if (!lastp)
183                                         break;
184                         } else {
185 #ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS
186                                 goto general_case;
187 #else
188                                 size_t ret = convert_string_internal(from, to, p, slen, q, dlen, converted_size);
189                                 if (converted_size) {
190                                         *converted_size = ret + retval;
191                                 }
192                                 return ret;
193 #endif
194                         }
195                 }
196                 if (converted_size) {
197                         *converted_size = retval;
198                 }
199                 if (!dlen) {
200                         /* Even if we fast path we should note if we ran out of room. */
201                         if (((slen != (size_t)-1) && slen) ||
202                                         ((slen == (size_t)-1) && lastp)) {
203                                 errno = E2BIG;
204                                 return (size_t)-1;
205                         }
206                 }
207                 return retval;
208         } else if (from == CH_UTF16LE && to != CH_UTF16LE) {
209                 const unsigned char *p = (const unsigned char *)src;
210                 unsigned char *q = (unsigned char *)dest;
211                 size_t retval = 0;
212                 size_t slen = srclen;
213                 size_t dlen = destlen;
214                 unsigned char lastp = '\0';
215
216                 /* If all characters are ascii, fast path here. */
217                 while (((slen == (size_t)-1) || (slen >= 2)) && dlen) {
218                         if (((lastp = *p) <= 0x7f) && (p[1] == 0)) {
219                                 *q++ = *p;
220                                 if (slen != (size_t)-1) {
221                                         slen -= 2;
222                                 }
223                                 p += 2;
224                                 dlen--;
225                                 retval++;
226                                 if (!lastp)
227                                         break;
228                         } else {
229 #ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS
230                                 goto general_case;
231 #else
232                                 size_t ret = convert_string_internal(from, to, p, slen, q, dlen, converted_size);
233                                 if (converted_size) {
234                                         *converted_size = ret + retval;
235                                 }
236                                 return ret;
237 #endif
238                         }
239                 }
240                 if (converted_size) {
241                         *converted_size = retval;
242                 }
243                 if (!dlen) {
244                         /* Even if we fast path we should note if we ran out of room. */
245                         if (((slen != (size_t)-1) && slen) ||
246                                         ((slen == (size_t)-1) && lastp)) {
247                                 errno = E2BIG;
248                                 return (size_t)-1;
249                         }
250                 }
251                 return retval;
252         } else if (from != CH_UTF16LE && from != CH_UTF16BE && to == CH_UTF16LE) {
253                 const unsigned char *p = (const unsigned char *)src;
254                 unsigned char *q = (unsigned char *)dest;
255                 size_t retval = 0;
256                 size_t slen = srclen;
257                 size_t dlen = destlen;
258                 unsigned char lastp = '\0';
259
260                 /* If all characters are ascii, fast path here. */
261                 while (slen && (dlen >= 2)) {
262                         if ((lastp = *p) <= 0x7F) {
263                                 *q++ = *p++;
264                                 *q++ = '\0';
265                                 if (slen != (size_t)-1) {
266                                         slen--;
267                                 }
268                                 dlen -= 2;
269                                 retval += 2;
270                                 if (!lastp)
271                                         break;
272                         } else {
273 #ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS
274                                 goto general_case;
275 #else
276                                 size_t ret = convert_string_internal(from, to, p, slen, q, dlen, converted_size);
277                                 if (converted_size) {
278                                         *converted_size = ret + retval;
279                                 }
280                                 return ret;
281 #endif
282                         }
283                 }
284                 if (converted_size) {
285                         *converted_size = retval;
286                 }
287                 if (!dlen) {
288                         /* Even if we fast path we should note if we ran out of room. */
289                         if (((slen != (size_t)-1) && slen) ||
290                                         ((slen == (size_t)-1) && lastp)) {
291                                 errno = E2BIG;
292                                 return (size_t)-1;
293                         }
294                 }
295                 return retval;
296         }
297
298 #ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS
299   general_case:
300 #endif
301         return convert_string_internal(from, to, src, srclen, dest, destlen, converted_size);
302 }
303
304 size_t convert_string(charset_t from, charset_t to,
305                       void const *src, size_t srclen,
306                       void *dest, size_t destlen) {
307         size_t converted_size;
308         size_t retval = convert_string_error(from, to, src, srclen, dest, destlen, &converted_size);
309         if(retval==(size_t)-1) {
310                 const char *reason="unknown error";
311                 switch(errno) {
312                         case EINVAL:
313                                 reason="Incomplete multibyte sequence";
314                                 DEBUG(3,("convert_string_internal: Conversion error: %s(%s)\n",
315                                          reason, (const char *)src));
316                                 return (size_t)-1;
317                         case E2BIG:
318                         {
319                                 struct smb_iconv_handle *ic;
320                                 lazy_initialize_conv();
321                                 ic = get_iconv_handle();
322
323                                 reason="No more room";
324                                 if (from == CH_UNIX) {
325                                         DEBUG(3,("E2BIG: convert_string(%s,%s): srclen=%u destlen=%u - '%s'\n",
326                                                  charset_name(ic, from), charset_name(ic, to),
327                                                  (unsigned int)srclen, (unsigned int)destlen, (const char *)src));
328                                 } else {
329                                         DEBUG(3,("E2BIG: convert_string(%s,%s): srclen=%u destlen=%u\n",
330                                                  charset_name(ic, from), charset_name(ic, to),
331                                                  (unsigned int)srclen, (unsigned int)destlen));
332                                 }
333                                 break;
334                         }
335                         case EILSEQ:
336                                 reason="Illegal multibyte sequence";
337                                 DEBUG(3,("convert_string_internal: Conversion error: %s(%s)\n",
338                                          reason, (const char *)src));
339                                 return (size_t)-1;
340                         default:
341                                 DEBUG(0,("convert_string_internal: Conversion error: %s(%s)\n",
342                                          reason, (const char *)src));
343                                 return (size_t)-1;
344                 }
345                 /* smb_panic(reason); */
346         }
347         return converted_size;
348 }
349
350
351 /**
352  * Convert between character sets, allocating a new buffer using talloc for the result.
353  *
354  * @param srclen length of source buffer.
355  * @param dest always set at least to NULL
356  * @parm converted_size set to the number of bytes occupied by the string in
357  * the destination on success.
358  * @note -1 is not accepted for srclen.
359  *
360  * @return true if new buffer was correctly allocated, and string was
361  * converted.
362  *
363  * Ensure the srclen contains the terminating zero.
364  *
365  * I hate the goto's in this function. It's embarressing.....
366  * There has to be a cleaner way to do this. JRA.
367  */
368 bool convert_string_talloc(TALLOC_CTX *ctx, charset_t from, charset_t to,
369                            void const *src, size_t srclen, void *dst,
370                            size_t *converted_size)
371
372 {
373         size_t i_len, o_len, destlen = (srclen * 3) / 2;
374         size_t retval;
375         const char *inbuf = (const char *)src;
376         char *outbuf = NULL, *ob = NULL;
377         smb_iconv_t descriptor;
378         void **dest = (void **)dst;
379         struct smb_iconv_handle *ic;
380
381         *dest = NULL;
382
383         if (!converted_size) {
384                 errno = EINVAL;
385                 return false;
386         }
387
388         if (src == NULL || srclen == (size_t)-1) {
389                 errno = EINVAL;
390                 return false;
391         }
392
393         if (srclen == 0) {
394                 /* We really should treat this as an error, but
395                    there are too many callers that need this to
396                    return a NULL terminated string in the correct
397                    character set. */
398                 if (to == CH_UTF16LE|| to == CH_UTF16BE || to == CH_UTF16MUNGED) {
399                         destlen = 2;
400                 } else {
401                         destlen = 1;
402                 }
403                 ob = talloc_zero_array(ctx, char, destlen);
404                 if (ob == NULL) {
405                         errno = ENOMEM;
406                         return false;
407                 }
408                 *converted_size = destlen;
409                 *dest = ob;
410                 return true;
411         }
412
413         lazy_initialize_conv();
414         ic = get_iconv_handle();
415         descriptor = get_conv_handle(ic, from, to);
416
417         if (descriptor == (smb_iconv_t)-1 || descriptor == (smb_iconv_t)0) {
418                 DEBUG(0,("convert_string_talloc: Conversion not supported.\n"));
419                 errno = EOPNOTSUPP;
420                 return false;
421         }
422
423   convert:
424
425         /* +2 is for ucs2 null termination. */
426         if ((destlen*2)+2 < destlen) {
427                 /* wrapped ! abort. */
428                 DEBUG(0, ("convert_string_talloc: destlen wrapped !\n"));
429                 TALLOC_FREE(outbuf);
430                 errno = EOPNOTSUPP;
431                 return false;
432         } else {
433                 destlen = destlen * 2;
434         }
435
436         /* +2 is for ucs2 null termination. */
437         ob = (char *)TALLOC_REALLOC(ctx, ob, destlen + 2);
438
439         if (!ob) {
440                 DEBUG(0, ("convert_string_talloc: realloc failed!\n"));
441                 errno = ENOMEM;
442                 return false;
443         }
444         outbuf = ob;
445         i_len = srclen;
446         o_len = destlen;
447
448         retval = smb_iconv(descriptor,
449                            &inbuf, &i_len,
450                            &outbuf, &o_len);
451         if(retval == (size_t)-1)                {
452                 const char *reason="unknown error";
453                 switch(errno) {
454                         case EINVAL:
455                                 reason="Incomplete multibyte sequence";
456                                 DEBUG(3,("convert_string_talloc: Conversion error: %s(%s)\n",reason,inbuf));
457                                 break;
458                         case E2BIG:
459                                 goto convert;
460                         case EILSEQ:
461                                 reason="Illegal multibyte sequence";
462                                 DEBUG(3,("convert_string_talloc: Conversion error: %s(%s)\n",reason,inbuf));
463                                 break;
464                 }
465                 DEBUG(0,("Conversion error: %s(%s)\n",reason,inbuf));
466                 /* smb_panic(reason); */
467                 TALLOC_FREE(ob);
468                 return false;
469         }
470
471         destlen = destlen - o_len;
472         /* Don't shrink unless we're reclaiming a lot of
473          * space. This is in the hot codepath and these
474          * reallocs *cost*. JRA.
475          */
476         if (o_len > 1024) {
477                 /* We're shrinking here so we know the +2 is safe from wrap. */
478                 ob = (char *)TALLOC_REALLOC(ctx,ob,destlen + 2);
479         }
480
481         if (destlen && !ob) {
482                 DEBUG(0, ("convert_string_talloc: out of memory!\n"));
483                 errno = ENOMEM;
484                 return false;
485         }
486
487         *dest = ob;
488
489         /* Must ucs2 null terminate in the extra space we allocated. */
490         ob[destlen] = '\0';
491         ob[destlen+1] = '\0';
492
493         /* Ensure we can never return a *converted_size of zero. */
494         if (destlen == 0) {
495                 /* As we're now returning false on a bad smb_iconv call,
496                    this should never happen. But be safe anyway. */
497                 if (to == CH_UTF16LE|| to == CH_UTF16BE || to == CH_UTF16MUNGED) {
498                         destlen = 2;
499                 } else {
500                         destlen = 1;
501                 }
502         }
503
504         *converted_size = destlen;
505         return true;
506 }
507
508 size_t unix_strupper(const char *src, size_t srclen, char *dest, size_t destlen)
509 {
510         size_t size;
511         smb_ucs2_t *buffer;
512
513         if (!push_ucs2_talloc(talloc_tos(), &buffer, src, &size)) {
514                 return (size_t)-1;
515         }
516
517         if (!strupper_w(buffer) && (dest == src)) {
518                 TALLOC_FREE(buffer);
519                 return srclen;
520         }
521
522         size = convert_string(CH_UTF16LE, CH_UNIX, buffer, size, dest, destlen);
523         TALLOC_FREE(buffer);
524         return size;
525 }
526
527 /**
528  talloc_strdup() a unix string to upper case.
529 **/
530
531 char *talloc_strdup_upper(TALLOC_CTX *ctx, const char *s)
532 {
533         char *out_buffer = talloc_strdup(ctx,s);
534         const unsigned char *p = (const unsigned char *)s;
535         unsigned char *q = (unsigned char *)out_buffer;
536
537         if (!q) {
538                 return NULL;
539         }
540
541         /* this is quite a common operation, so we want it to be
542            fast. We optimise for the ascii case, knowing that all our
543            supported multi-byte character sets are ascii-compatible
544            (ie. they match for the first 128 chars) */
545
546         while (*p) {
547                 if (*p & 0x80)
548                         break;
549                 *q++ = toupper_ascii_fast(*p);
550                 p++;
551         }
552
553         if (*p) {
554                 /* MB case. */
555                 size_t converted_size, converted_size2;
556                 smb_ucs2_t *ubuf = NULL;
557
558                 /* We're not using the ascii buffer above. */
559                 TALLOC_FREE(out_buffer);
560
561                 if (!convert_string_talloc(ctx, CH_UNIX, CH_UTF16LE, s,
562                                            strlen(s)+1, (void *)&ubuf,
563                                            &converted_size))
564                 {
565                         return NULL;
566                 }
567
568                 strupper_w(ubuf);
569
570                 if (!convert_string_talloc(ctx, CH_UTF16LE, CH_UNIX, ubuf,
571                                            converted_size, (void *)&out_buffer,
572                                            &converted_size2))
573                 {
574                         TALLOC_FREE(ubuf);
575                         return NULL;
576                 }
577
578                 /* Don't need the intermediate buffer
579                  * anymore.
580                  */
581                 TALLOC_FREE(ubuf);
582         }
583
584         return out_buffer;
585 }
586
587 char *strupper_talloc(TALLOC_CTX *ctx, const char *s) {
588         return talloc_strdup_upper(ctx, s);
589 }
590
591
592 size_t unix_strlower(const char *src, size_t srclen, char *dest, size_t destlen)
593 {
594         size_t size;
595         smb_ucs2_t *buffer = NULL;
596
597         if (!convert_string_talloc(talloc_tos(), CH_UNIX, CH_UTF16LE, src, srclen,
598                                    (void **)(void *)&buffer, &size))
599         {
600                 smb_panic("failed to create UCS2 buffer");
601         }
602         if (!strlower_w(buffer) && (dest == src)) {
603                 TALLOC_FREE(buffer);
604                 return srclen;
605         }
606         size = convert_string(CH_UTF16LE, CH_UNIX, buffer, size, dest, destlen);
607         TALLOC_FREE(buffer);
608         return size;
609 }
610
611
612 char *talloc_strdup_lower(TALLOC_CTX *ctx, const char *s)
613 {
614         size_t converted_size;
615         smb_ucs2_t *buffer = NULL;
616         char *out_buffer;
617
618         if (!push_ucs2_talloc(ctx, &buffer, s, &converted_size)) {
619                 return NULL;
620         }
621
622         strlower_w(buffer);
623
624         if (!pull_ucs2_talloc(ctx, &out_buffer, buffer, &converted_size)) {
625                 TALLOC_FREE(buffer);
626                 return NULL;
627         }
628
629         TALLOC_FREE(buffer);
630
631         return out_buffer;
632 }
633
634 char *strlower_talloc(TALLOC_CTX *ctx, const char *s) {
635         return talloc_strdup_lower(ctx, s);
636 }
637
638 size_t ucs2_align(const void *base_ptr, const void *p, int flags)
639 {
640         if (flags & (STR_NOALIGN|STR_ASCII))
641                 return 0;
642         return PTR_DIFF(p, base_ptr) & 1;
643 }
644
645
646 /**
647  * Copy a string from a char* unix src to a dos codepage string destination.
648  *
649  * @return the number of bytes occupied by the string in the destination.
650  *
651  * @param flags can include
652  * <dl>
653  * <dt>STR_TERMINATE</dt> <dd>means include the null termination</dd>
654  * <dt>STR_UPPER</dt> <dd>means uppercase in the destination</dd>
655  * </dl>
656  *
657  * @param dest_len the maximum length in bytes allowed in the
658  * destination.
659  **/
660 size_t push_ascii(void *dest, const char *src, size_t dest_len, int flags)
661 {
662         size_t src_len = strlen(src);
663         char *tmpbuf = NULL;
664         size_t ret;
665
666         /* No longer allow a length of -1. */
667         if (dest_len == (size_t)-1) {
668                 smb_panic("push_ascii - dest_len == -1");
669         }
670
671         if (flags & STR_UPPER) {
672                 tmpbuf = SMB_STRDUP(src);
673                 if (!tmpbuf) {
674                         smb_panic("malloc fail");
675                 }
676                 strupper_m(tmpbuf);
677                 src = tmpbuf;
678         }
679
680         if (flags & (STR_TERMINATE | STR_TERMINATE_ASCII)) {
681                 src_len++;
682         }
683
684         ret = convert_string(CH_UNIX, CH_DOS, src, src_len, dest, dest_len);
685         if (ret == (size_t)-1 &&
686                         (flags & (STR_TERMINATE | STR_TERMINATE_ASCII))
687                         && dest_len > 0) {
688                 ((char *)dest)[0] = '\0';
689         }
690         SAFE_FREE(tmpbuf);
691         return ret;
692 }
693
694 /********************************************************************
695  Push and malloc an ascii string. src and dest null terminated.
696 ********************************************************************/
697
698 bool push_ascii_talloc(TALLOC_CTX *mem_ctx, char **dest, const char *src, size_t *converted_size)
699 {
700         size_t src_len = strlen(src)+1;
701
702         *dest = NULL;
703         return convert_string_talloc(mem_ctx, CH_UNIX, CH_DOS, src, src_len,
704                                      (void **)dest, converted_size);
705 }
706
707 /**
708  * Copy a string from a dos codepage source to a unix char* destination.
709  *
710  * The resulting string in "dest" is always null terminated.
711  *
712  * @param flags can have:
713  * <dl>
714  * <dt>STR_TERMINATE</dt>
715  * <dd>STR_TERMINATE means the string in @p src
716  * is null terminated, and src_len is ignored.</dd>
717  * </dl>
718  *
719  * @param src_len is the length of the source area in bytes.
720  * @returns the number of bytes occupied by the string in @p src.
721  **/
722 size_t pull_ascii(char *dest, const void *src, size_t dest_len, size_t src_len, int flags)
723 {
724         size_t ret;
725
726         if (dest_len == (size_t)-1) {
727                 /* No longer allow dest_len of -1. */
728                 smb_panic("pull_ascii - invalid dest_len of -1");
729         }
730
731         if (flags & STR_TERMINATE) {
732                 if (src_len == (size_t)-1) {
733                         src_len = strlen((const char *)src) + 1;
734                 } else {
735                         size_t len = strnlen((const char *)src, src_len);
736                         if (len < src_len)
737                                 len++;
738                         src_len = len;
739                 }
740         }
741
742         ret = convert_string(CH_DOS, CH_UNIX, src, src_len, dest, dest_len);
743         if (ret == (size_t)-1) {
744                 ret = 0;
745                 dest_len = 0;
746         }
747
748         if (dest_len && ret) {
749                 /* Did we already process the terminating zero ? */
750                 if (dest[MIN(ret-1, dest_len-1)] != 0) {
751                         dest[MIN(ret, dest_len-1)] = 0;
752                 }
753         } else  {
754                 dest[0] = 0;
755         }
756
757         return src_len;
758 }
759
760 /**
761  * Copy a string from a dos codepage source to a unix char* destination.
762  * Talloc version.
763  *
764  * The resulting string in "dest" is always null terminated.
765  *
766  * @param flags can have:
767  * <dl>
768  * <dt>STR_TERMINATE</dt>
769  * <dd>STR_TERMINATE means the string in @p src
770  * is null terminated, and src_len is ignored.</dd>
771  * </dl>
772  *
773  * @param src_len is the length of the source area in bytes.
774  * @returns the number of bytes occupied by the string in @p src.
775  **/
776
777 static size_t pull_ascii_base_talloc(TALLOC_CTX *ctx,
778                                      char **ppdest,
779                                      const void *src,
780                                      size_t src_len,
781                                      int flags)
782 {
783         char *dest = NULL;
784         size_t dest_len;
785
786         *ppdest = NULL;
787
788         if (!src_len) {
789                 return 0;
790         }
791
792         if (src_len == (size_t)-1) {
793                 smb_panic("sec_len == -1 in pull_ascii_base_talloc");
794         }
795
796         if (flags & STR_TERMINATE) {
797                 size_t len = strnlen((const char *)src, src_len);
798                 if (len < src_len)
799                         len++;
800                 src_len = len;
801                 /* Ensure we don't use an insane length from the client. */
802                 if (src_len >= 1024*1024) {
803                         char *msg = talloc_asprintf(ctx,
804                                         "Bad src length (%u) in "
805                                         "pull_ascii_base_talloc",
806                                         (unsigned int)src_len);
807                         smb_panic(msg);
808                 }
809         }
810
811         /* src_len != -1 here. */
812
813         if (!convert_string_talloc(ctx, CH_DOS, CH_UNIX, src, src_len, &dest,
814                                      &dest_len)) {
815                 dest_len = 0;
816         }
817
818         if (dest_len && dest) {
819                 /* Did we already process the terminating zero ? */
820                 if (dest[dest_len-1] != 0) {
821                         size_t size = talloc_get_size(dest);
822                         /* Have we got space to append the '\0' ? */
823                         if (size <= dest_len) {
824                                 /* No, realloc. */
825                                 dest = TALLOC_REALLOC_ARRAY(ctx, dest, char,
826                                                 dest_len+1);
827                                 if (!dest) {
828                                         /* talloc fail. */
829                                         dest_len = (size_t)-1;
830                                         return 0;
831                                 }
832                         }
833                         /* Yay - space ! */
834                         dest[dest_len] = '\0';
835                         dest_len++;
836                 }
837         } else if (dest) {
838                 dest[0] = 0;
839         }
840
841         *ppdest = dest;
842         return src_len;
843 }
844
845 /**
846  * Copy a string from a char* src to a unicode destination.
847  *
848  * @returns the number of bytes occupied by the string in the destination.
849  *
850  * @param flags can have:
851  *
852  * <dl>
853  * <dt>STR_TERMINATE <dd>means include the null termination.
854  * <dt>STR_UPPER     <dd>means uppercase in the destination.
855  * <dt>STR_NOALIGN   <dd>means don't do alignment.
856  * </dl>
857  *
858  * @param dest_len is the maximum length allowed in the
859  * destination.
860  **/
861
862 size_t push_ucs2(const void *base_ptr, void *dest, const char *src, size_t dest_len, int flags)
863 {
864         size_t len=0;
865         size_t src_len;
866         size_t ret;
867
868         if (dest_len == (size_t)-1) {
869                 /* No longer allow dest_len of -1. */
870                 smb_panic("push_ucs2 - invalid dest_len of -1");
871         }
872
873         if (flags & STR_TERMINATE)
874                 src_len = (size_t)-1;
875         else
876                 src_len = strlen(src);
877
878         if (ucs2_align(base_ptr, dest, flags)) {
879                 *(char *)dest = 0;
880                 dest = (void *)((char *)dest + 1);
881                 if (dest_len)
882                         dest_len--;
883                 len++;
884         }
885
886         /* ucs2 is always a multiple of 2 bytes */
887         dest_len &= ~1;
888
889         ret =  convert_string(CH_UNIX, CH_UTF16LE, src, src_len, dest, dest_len);
890         if (ret == (size_t)-1) {
891                 if ((flags & STR_TERMINATE) &&
892                                 dest &&
893                                 dest_len) {
894                         *(char *)dest = 0;
895                 }
896                 return len;
897         }
898
899         len += ret;
900
901         if (flags & STR_UPPER) {
902                 smb_ucs2_t *dest_ucs2 = (smb_ucs2_t *)dest;
903                 size_t i;
904
905                 /* We check for i < (ret / 2) below as the dest string isn't null
906                    terminated if STR_TERMINATE isn't set. */
907
908                 for (i = 0; i < (ret / 2) && i < (dest_len / 2) && dest_ucs2[i]; i++) {
909                         smb_ucs2_t v = toupper_m(dest_ucs2[i]);
910                         if (v != dest_ucs2[i]) {
911                                 dest_ucs2[i] = v;
912                         }
913                 }
914         }
915
916         return len;
917 }
918
919
920 /**
921  * Copy a string from a unix char* src to a UCS2 destination,
922  * allocating a buffer using talloc().
923  *
924  * @param dest always set at least to NULL 
925  * @parm converted_size set to the number of bytes occupied by the string in
926  * the destination on success.
927  *
928  * @return true if new buffer was correctly allocated, and string was
929  * converted.
930  **/
931 bool push_ucs2_talloc(TALLOC_CTX *ctx, smb_ucs2_t **dest, const char *src,
932                       size_t *converted_size)
933 {
934         size_t src_len = strlen(src)+1;
935
936         *dest = NULL;
937         return convert_string_talloc(ctx, CH_UNIX, CH_UTF16LE, src, src_len,
938                                      (void **)dest, converted_size);
939 }
940
941
942 /**
943  * Copy a string from a unix char* src to a UTF-8 destination, allocating a buffer using talloc
944  *
945  * @param dest always set at least to NULL 
946  * @parm converted_size set to the number of bytes occupied by the string in
947  * the destination on success.
948  *
949  * @return true if new buffer was correctly allocated, and string was
950  * converted.
951  **/
952
953 bool push_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src,
954                       size_t *converted_size)
955 {
956         size_t src_len = strlen(src)+1;
957
958         *dest = NULL;
959         return convert_string_talloc(ctx, CH_UNIX, CH_UTF8, src, src_len,
960                                      (void**)dest, converted_size);
961 }
962
963 /**
964  Copy a string from a ucs2 source to a unix char* destination.
965  Flags can have:
966   STR_TERMINATE means the string in src is null terminated.
967   STR_NOALIGN   means don't try to align.
968  if STR_TERMINATE is set then src_len is ignored if it is -1.
969  src_len is the length of the source area in bytes
970  Return the number of bytes occupied by the string in src.
971  The resulting string in "dest" is always null terminated.
972 **/
973
974 size_t pull_ucs2(const void *base_ptr, char *dest, const void *src, size_t dest_len, size_t src_len, int flags)
975 {
976         size_t ret;
977         size_t ucs2_align_len = 0;
978
979         if (dest_len == (size_t)-1) {
980                 /* No longer allow dest_len of -1. */
981                 smb_panic("pull_ucs2 - invalid dest_len of -1");
982         }
983
984         if (!src_len) {
985                 if (dest && dest_len > 0) {
986                         dest[0] = '\0';
987                 }
988                 return 0;
989         }
990
991         if (ucs2_align(base_ptr, src, flags)) {
992                 src = (const void *)((const char *)src + 1);
993                 if (src_len != (size_t)-1)
994                         src_len--;
995                 ucs2_align_len = 1;
996         }
997
998         if (flags & STR_TERMINATE) {
999                 /* src_len -1 is the default for null terminated strings. */
1000                 if (src_len != (size_t)-1) {
1001                         size_t len = strnlen_w((const smb_ucs2_t *)src,
1002                                                 src_len/2);
1003                         if (len < src_len/2)
1004                                 len++;
1005                         src_len = len*2;
1006                 }
1007         }
1008
1009         /* ucs2 is always a multiple of 2 bytes */
1010         if (src_len != (size_t)-1)
1011                 src_len &= ~1;
1012
1013         ret = convert_string(CH_UTF16LE, CH_UNIX, src, src_len, dest, dest_len);
1014         if (ret == (size_t)-1) {
1015                 ret = 0;
1016                 dest_len = 0;
1017         }
1018
1019         if (src_len == (size_t)-1)
1020                 src_len = ret*2;
1021
1022         if (dest_len && ret) {
1023                 /* Did we already process the terminating zero ? */
1024                 if (dest[MIN(ret-1, dest_len-1)] != 0) {
1025                         dest[MIN(ret, dest_len-1)] = 0;
1026                 }
1027         } else {
1028                 dest[0] = 0;
1029         }
1030
1031         return src_len + ucs2_align_len;
1032 }
1033
1034 /**
1035  Copy a string from a ucs2 source to a unix char* destination.
1036  Talloc version with a base pointer.
1037  Uses malloc if TALLOC_CTX is NULL (this is a bad interface and
1038  needs fixing. JRA).
1039  Flags can have:
1040   STR_TERMINATE means the string in src is null terminated.
1041   STR_NOALIGN   means don't try to align.
1042  if STR_TERMINATE is set then src_len is ignored if it is -1.
1043  src_len is the length of the source area in bytes
1044  Return the number of bytes occupied by the string in src.
1045  The resulting string in "dest" is always null terminated.
1046 **/
1047
1048 static size_t pull_ucs2_base_talloc(TALLOC_CTX *ctx,
1049                                     const void *base_ptr,
1050                                     char **ppdest,
1051                                     const void *src,
1052                                     size_t src_len,
1053                                     int flags)
1054 {
1055         char *dest;
1056         size_t dest_len;
1057         size_t ucs2_align_len = 0;
1058
1059         *ppdest = NULL;
1060
1061 #ifdef DEVELOPER
1062         /* Ensure we never use the braindead "malloc" varient. */
1063         if (ctx == NULL) {
1064                 smb_panic("NULL talloc CTX in pull_ucs2_base_talloc\n");
1065         }
1066 #endif
1067
1068         if (!src_len) {
1069                 return 0;
1070         }
1071
1072         if (src_len == (size_t)-1) {
1073                 /* no longer used anywhere, but worth checking */
1074                 smb_panic("sec_len == -1 in pull_ucs2_base_talloc");
1075         }
1076
1077         if (ucs2_align(base_ptr, src, flags)) {
1078                 src = (const void *)((const char *)src + 1);
1079                 src_len--;
1080                 ucs2_align_len = 1;
1081         }
1082
1083         if (flags & STR_TERMINATE) {
1084                 /* src_len -1 is the default for null terminated strings. */
1085                 size_t len = strnlen_w((const smb_ucs2_t *)src,
1086                                        src_len/2);
1087                 if (len < src_len/2)
1088                         len++;
1089                 src_len = len*2;
1090
1091                 /* Ensure we don't use an insane length from the client. */
1092                 if (src_len >= 1024*1024) {
1093                         smb_panic("Bad src length in pull_ucs2_base_talloc\n");
1094                 }
1095         }
1096
1097         /* ucs2 is always a multiple of 2 bytes */
1098         src_len &= ~1;
1099
1100         if (!convert_string_talloc(ctx, CH_UTF16LE, CH_UNIX, src, src_len,
1101                                    (void *)&dest, &dest_len)) {
1102                 dest_len = 0;
1103         }
1104
1105         if (dest_len) {
1106                 /* Did we already process the terminating zero ? */
1107                 if (dest[dest_len-1] != 0) {
1108                         size_t size = talloc_get_size(dest);
1109                         /* Have we got space to append the '\0' ? */
1110                         if (size <= dest_len) {
1111                                 /* No, realloc. */
1112                                 dest = TALLOC_REALLOC_ARRAY(ctx, dest, char,
1113                                                 dest_len+1);
1114                                 if (!dest) {
1115                                         /* talloc fail. */
1116                                         dest_len = (size_t)-1;
1117                                         return 0;
1118                                 }
1119                         }
1120                         /* Yay - space ! */
1121                         dest[dest_len] = '\0';
1122                         dest_len++;
1123                 }
1124         } else if (dest) {
1125                 dest[0] = 0;
1126         }
1127
1128         *ppdest = dest;
1129         return src_len + ucs2_align_len;
1130 }
1131
1132 /**
1133  * Copy a string from a UCS2 src to a unix char * destination, allocating a buffer using talloc
1134  *
1135  * @param dest always set at least to NULL 
1136  * @parm converted_size set to the number of bytes occupied by the string in
1137  * the destination on success.
1138  *
1139  * @return true if new buffer was correctly allocated, and string was
1140  * converted.
1141  **/
1142
1143 bool pull_ucs2_talloc(TALLOC_CTX *ctx, char **dest, const smb_ucs2_t *src,
1144                       size_t *converted_size)
1145 {
1146         size_t src_len = (strlen_w(src)+1) * sizeof(smb_ucs2_t);
1147
1148         *dest = NULL;
1149         return convert_string_talloc(ctx, CH_UTF16LE, CH_UNIX, src, src_len,
1150                                      (void **)dest, converted_size);
1151 }
1152
1153 /**
1154  * Copy a string from a UTF-8 src to a unix char * destination, allocating a buffer using talloc
1155  *
1156  * @param dest always set at least to NULL 
1157  * @parm converted_size set to the number of bytes occupied by the string in
1158  * the destination on success.
1159  *
1160  * @return true if new buffer was correctly allocated, and string was
1161  * converted.
1162  **/
1163
1164 bool pull_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src,
1165                       size_t *converted_size)
1166 {
1167         size_t src_len = strlen(src)+1;
1168
1169         *dest = NULL;
1170         return convert_string_talloc(ctx, CH_UTF8, CH_UNIX, src, src_len,
1171                                      (void **)dest, converted_size);
1172 }
1173
1174  
1175 /**
1176  * Copy a string from a DOS src to a unix char * destination, allocating a buffer using talloc
1177  *
1178  * @param dest always set at least to NULL 
1179  * @parm converted_size set to the number of bytes occupied by the string in
1180  * the destination on success.
1181  *
1182  * @return true if new buffer was correctly allocated, and string was
1183  * converted.
1184  **/
1185
1186 bool pull_ascii_talloc(TALLOC_CTX *ctx, char **dest, const char *src,
1187                        size_t *converted_size)
1188 {
1189         size_t src_len = strlen(src)+1;
1190
1191         *dest = NULL;
1192         return convert_string_talloc(ctx, CH_DOS, CH_UNIX, src, src_len,
1193                                      (void **)dest, converted_size);
1194 }
1195
1196 /**
1197  Copy a string from a char* src to a unicode or ascii
1198  dos codepage destination choosing unicode or ascii based on the 
1199  flags supplied
1200  Return the number of bytes occupied by the string in the destination.
1201  flags can have:
1202   STR_TERMINATE means include the null termination.
1203   STR_UPPER     means uppercase in the destination.
1204   STR_ASCII     use ascii even with unicode packet.
1205   STR_NOALIGN   means don't do alignment.
1206  dest_len is the maximum length allowed in the destination. If dest_len
1207  is -1 then no maxiumum is used.
1208 **/
1209
1210 size_t push_string_check_fn(void *dest, const char *src,
1211                          size_t dest_len, int flags)
1212 {
1213         if (!(flags & STR_ASCII) && (flags & STR_UNICODE)) {
1214                 return push_ucs2(NULL, dest, src, dest_len, flags);
1215         }
1216         return push_ascii(dest, src, dest_len, flags);
1217 }
1218
1219
1220 /**
1221  Copy a string from a char* src to a unicode or ascii
1222  dos codepage destination choosing unicode or ascii based on the 
1223  flags in the SMB buffer starting at base_ptr.
1224  Return the number of bytes occupied by the string in the destination.
1225  flags can have:
1226   STR_TERMINATE means include the null termination.
1227   STR_UPPER     means uppercase in the destination.
1228   STR_ASCII     use ascii even with unicode packet.
1229   STR_NOALIGN   means don't do alignment.
1230  dest_len is the maximum length allowed in the destination. If dest_len
1231  is -1 then no maxiumum is used.
1232 **/
1233
1234 size_t push_string_base(const char *base, uint16 flags2,
1235                         void *dest, const char *src,
1236                         size_t dest_len, int flags)
1237 {
1238
1239         if (!(flags & STR_ASCII) && \
1240             ((flags & STR_UNICODE || \
1241               (flags2 & FLAGS2_UNICODE_STRINGS)))) {
1242                 return push_ucs2(base, dest, src, dest_len, flags);
1243         }
1244         return push_ascii(dest, src, dest_len, flags);
1245 }
1246
1247 /**
1248  Copy a string from a char* src to a unicode or ascii
1249  dos codepage destination choosing unicode or ascii based on the 
1250  flags supplied
1251  Return the number of bytes occupied by the string in the destination.
1252  flags can have:
1253   STR_TERMINATE means include the null termination.
1254   STR_UPPER     means uppercase in the destination.
1255   STR_ASCII     use ascii even with unicode packet.
1256   STR_NOALIGN   means don't do alignment.
1257  dest_len is the maximum length allowed in the destination. If dest_len
1258  is -1 then no maxiumum is used.
1259 **/
1260
1261 ssize_t push_string(void *dest, const char *src, size_t dest_len, int flags)
1262 {
1263         size_t ret;
1264
1265         if (!(flags & STR_ASCII) && \
1266             (flags & STR_UNICODE)) {
1267                 ret = push_ucs2(NULL, dest, src, dest_len, flags);
1268         } else {
1269                 ret = push_ascii(dest, src, dest_len, flags);
1270         }
1271         if (ret == (size_t)-1) {
1272                 return -1;
1273         }
1274         return ret;
1275 }
1276
1277 /**
1278  Copy a string from a unicode or ascii source (depending on
1279  the packet flags) to a char* destination.
1280  Flags can have:
1281   STR_TERMINATE means the string in src is null terminated.
1282   STR_UNICODE   means to force as unicode.
1283   STR_ASCII     use ascii even with unicode packet.
1284   STR_NOALIGN   means don't do alignment.
1285  if STR_TERMINATE is set then src_len is ignored is it is -1
1286  src_len is the length of the source area in bytes.
1287  Return the number of bytes occupied by the string in src.
1288  The resulting string in "dest" is always null terminated.
1289 **/
1290
1291 size_t pull_string_fn(const void *base_ptr,
1292                    uint16 smb_flags2,
1293                    char *dest,
1294                    const void *src,
1295                    size_t dest_len,
1296                    size_t src_len,
1297                    int flags)
1298 {
1299         if ((base_ptr == NULL) && ((flags & (STR_ASCII|STR_UNICODE)) == 0)) {
1300                 smb_panic("No base ptr to get flg2 and neither ASCII nor "
1301                           "UNICODE defined");
1302         }
1303
1304         if (!(flags & STR_ASCII) && \
1305             ((flags & STR_UNICODE || \
1306               (smb_flags2 & FLAGS2_UNICODE_STRINGS)))) {
1307                 return pull_ucs2(base_ptr, dest, src, dest_len, src_len, flags);
1308         }
1309         return pull_ascii(dest, src, dest_len, src_len, flags);
1310 }
1311
1312 /**
1313  Copy a string from a unicode or ascii source (depending on
1314  the packet flags) to a char* destination.
1315  Variant that uses talloc.
1316  Flags can have:
1317   STR_TERMINATE means the string in src is null terminated.
1318   STR_UNICODE   means to force as unicode.
1319   STR_ASCII     use ascii even with unicode packet.
1320   STR_NOALIGN   means don't do alignment.
1321  if STR_TERMINATE is set then src_len is ignored is it is -1
1322  src_len is the length of the source area in bytes.
1323  Return the number of bytes occupied by the string in src.
1324  The resulting string in "dest" is always null terminated.
1325 **/
1326
1327 size_t pull_string_talloc(TALLOC_CTX *ctx,
1328                           const void *base_ptr,
1329                           uint16 smb_flags2,
1330                           char **ppdest,
1331                           const void *src,
1332                           size_t src_len,
1333                           int flags)
1334 {
1335         if ((base_ptr == NULL) && ((flags & (STR_ASCII|STR_UNICODE)) == 0)) {
1336                 smb_panic("No base ptr to get flg2 and neither ASCII nor "
1337                           "UNICODE defined");
1338         }
1339
1340         if (!(flags & STR_ASCII) && \
1341             ((flags & STR_UNICODE || \
1342               (smb_flags2 & FLAGS2_UNICODE_STRINGS)))) {
1343                 return pull_ucs2_base_talloc(ctx,
1344                                         base_ptr,
1345                                         ppdest,
1346                                         src,
1347                                         src_len,
1348                                         flags);
1349         }
1350         return pull_ascii_base_talloc(ctx,
1351                                         ppdest,
1352                                         src,
1353                                         src_len,
1354                                         flags);
1355 }
1356
1357
1358 size_t align_string(const void *base_ptr, const char *p, int flags)
1359 {
1360         if (!(flags & STR_ASCII) && \
1361             ((flags & STR_UNICODE || \
1362               (SVAL(base_ptr, smb_flg2) & FLAGS2_UNICODE_STRINGS)))) {
1363                 return ucs2_align(base_ptr, p, flags);
1364         }
1365         return 0;
1366 }
1367