s3-talloc Change TALLOC_REALLOC_ARRAY() to talloc_realloc()
[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  * Destroy global objects allocated by init_iconv()
27  **/
28 void gfree_charcnv(void)
29 {
30         TALLOC_FREE(global_iconv_handle);
31 }
32
33 /**
34  * Copy a string from a char* unix src to a dos codepage string destination.
35  *
36  * @return the number of bytes occupied by the string in the destination.
37  *
38  * @param flags can include
39  * <dl>
40  * <dt>STR_TERMINATE</dt> <dd>means include the null termination</dd>
41  * <dt>STR_UPPER</dt> <dd>means uppercase in the destination</dd>
42  * </dl>
43  *
44  * @param dest_len the maximum length in bytes allowed in the
45  * destination.
46  **/
47 size_t push_ascii(void *dest, const char *src, size_t dest_len, int flags)
48 {
49         size_t src_len = strlen(src);
50         char *tmpbuf = NULL;
51         size_t size;
52         bool ret;
53
54         /* No longer allow a length of -1. */
55         if (dest_len == (size_t)-1) {
56                 smb_panic("push_ascii - dest_len == -1");
57         }
58
59         if (flags & STR_UPPER) {
60                 tmpbuf = SMB_STRDUP(src);
61                 if (!tmpbuf) {
62                         smb_panic("malloc fail");
63                 }
64                 strupper_m(tmpbuf);
65                 src = tmpbuf;
66         }
67
68         if (flags & (STR_TERMINATE | STR_TERMINATE_ASCII)) {
69                 src_len++;
70         }
71
72         ret = convert_string(CH_UNIX, CH_DOS, src, src_len, dest, dest_len, &size);
73         if (ret == false &&
74                         (flags & (STR_TERMINATE | STR_TERMINATE_ASCII))
75                         && dest_len > 0) {
76                 ((char *)dest)[0] = '\0';
77         }
78         SAFE_FREE(tmpbuf);
79         return ret ? size : (size_t)-1;
80 }
81
82 /********************************************************************
83  Push and malloc an ascii string. src and dest null terminated.
84 ********************************************************************/
85
86 /**
87  * Copy a string from a dos codepage source to a unix char* destination.
88  *
89  * The resulting string in "dest" is always null terminated.
90  *
91  * @param flags can have:
92  * <dl>
93  * <dt>STR_TERMINATE</dt>
94  * <dd>STR_TERMINATE means the string in @p src
95  * is null terminated, and src_len is ignored.</dd>
96  * </dl>
97  *
98  * @param src_len is the length of the source area in bytes.
99  * @returns the number of bytes occupied by the string in @p src.
100  **/
101 size_t pull_ascii(char *dest, const void *src, size_t dest_len, size_t src_len, int flags)
102 {
103         bool ret;
104         size_t size = 0;
105
106         if (dest_len == (size_t)-1) {
107                 /* No longer allow dest_len of -1. */
108                 smb_panic("pull_ascii - invalid dest_len of -1");
109         }
110
111         if (flags & STR_TERMINATE) {
112                 if (src_len == (size_t)-1) {
113                         src_len = strlen((const char *)src) + 1;
114                 } else {
115                         size_t len = strnlen((const char *)src, src_len);
116                         if (len < src_len)
117                                 len++;
118                         src_len = len;
119                 }
120         }
121
122         ret = convert_string(CH_DOS, CH_UNIX, src, src_len, dest, dest_len, &size);
123         if (ret == false) {
124                 size = 0;
125                 dest_len = 0;
126         }
127
128         if (dest_len && size) {
129                 /* Did we already process the terminating zero ? */
130                 if (dest[MIN(size-1, dest_len-1)] != 0) {
131                         dest[MIN(size, dest_len-1)] = 0;
132                 }
133         } else  {
134                 dest[0] = 0;
135         }
136
137         return src_len;
138 }
139
140 /**
141  * Copy a string from a dos codepage source to a unix char* destination.
142  * Talloc version.
143  *
144  * The resulting string in "dest" is always null terminated.
145  *
146  * @param flags can have:
147  * <dl>
148  * <dt>STR_TERMINATE</dt>
149  * <dd>STR_TERMINATE means the string in @p src
150  * is null terminated, and src_len is ignored.</dd>
151  * </dl>
152  *
153  * @param src_len is the length of the source area in bytes.
154  * @returns the number of bytes occupied by the string in @p src.
155  **/
156
157 static size_t pull_ascii_base_talloc(TALLOC_CTX *ctx,
158                                      char **ppdest,
159                                      const void *src,
160                                      size_t src_len,
161                                      int flags)
162 {
163         char *dest = NULL;
164         size_t dest_len;
165
166         *ppdest = NULL;
167
168         if (!src_len) {
169                 return 0;
170         }
171
172         if (src_len == (size_t)-1) {
173                 smb_panic("sec_len == -1 in pull_ascii_base_talloc");
174         }
175
176         if (flags & STR_TERMINATE) {
177                 size_t len = strnlen((const char *)src, src_len);
178                 if (len < src_len)
179                         len++;
180                 src_len = len;
181                 /* Ensure we don't use an insane length from the client. */
182                 if (src_len >= 1024*1024) {
183                         char *msg = talloc_asprintf(ctx,
184                                         "Bad src length (%u) in "
185                                         "pull_ascii_base_talloc",
186                                         (unsigned int)src_len);
187                         smb_panic(msg);
188                 }
189         }
190
191         /* src_len != -1 here. */
192
193         if (!convert_string_talloc(ctx, CH_DOS, CH_UNIX, src, src_len, &dest,
194                                      &dest_len)) {
195                 dest_len = 0;
196         }
197
198         if (dest_len && dest) {
199                 /* Did we already process the terminating zero ? */
200                 if (dest[dest_len-1] != 0) {
201                         size_t size = talloc_get_size(dest);
202                         /* Have we got space to append the '\0' ? */
203                         if (size <= dest_len) {
204                                 /* No, realloc. */
205                                 dest = talloc_realloc(ctx, dest, char,
206                                                 dest_len+1);
207                                 if (!dest) {
208                                         /* talloc fail. */
209                                         dest_len = (size_t)-1;
210                                         return 0;
211                                 }
212                         }
213                         /* Yay - space ! */
214                         dest[dest_len] = '\0';
215                         dest_len++;
216                 }
217         } else if (dest) {
218                 dest[0] = 0;
219         }
220
221         *ppdest = dest;
222         return src_len;
223 }
224
225 /**
226  * Copy a string from a char* src to a unicode destination.
227  *
228  * @returns the number of bytes occupied by the string in the destination.
229  *
230  * @param flags can have:
231  *
232  * <dl>
233  * <dt>STR_TERMINATE <dd>means include the null termination.
234  * <dt>STR_UPPER     <dd>means uppercase in the destination.
235  * <dt>STR_NOALIGN   <dd>means don't do alignment.
236  * </dl>
237  *
238  * @param dest_len is the maximum length allowed in the
239  * destination.
240  **/
241
242 static size_t push_ucs2(const void *base_ptr, void *dest, const char *src, size_t dest_len, int flags)
243 {
244         size_t len=0;
245         size_t src_len;
246         size_t size = 0;
247         bool ret;
248
249         if (dest_len == (size_t)-1) {
250                 /* No longer allow dest_len of -1. */
251                 smb_panic("push_ucs2 - invalid dest_len of -1");
252         }
253
254         if (flags & STR_TERMINATE)
255                 src_len = (size_t)-1;
256         else
257                 src_len = strlen(src);
258
259         if (ucs2_align(base_ptr, dest, flags)) {
260                 *(char *)dest = 0;
261                 dest = (void *)((char *)dest + 1);
262                 if (dest_len)
263                         dest_len--;
264                 len++;
265         }
266
267         /* ucs2 is always a multiple of 2 bytes */
268         dest_len &= ~1;
269
270         ret = convert_string(CH_UNIX, CH_UTF16LE, src, src_len, dest, dest_len, &size);
271         if (ret == false) {
272                 if ((flags & STR_TERMINATE) &&
273                                 dest &&
274                                 dest_len) {
275                         *(char *)dest = 0;
276                 }
277                 return len;
278         }
279
280         len += size;
281
282         if (flags & STR_UPPER) {
283                 smb_ucs2_t *dest_ucs2 = (smb_ucs2_t *)dest;
284                 size_t i;
285
286                 /* We check for i < (ret / 2) below as the dest string isn't null
287                    terminated if STR_TERMINATE isn't set. */
288
289                 for (i = 0; i < (ret / 2) && i < (dest_len / 2) && dest_ucs2[i]; i++) {
290                         smb_ucs2_t v = toupper_m(dest_ucs2[i]);
291                         if (v != dest_ucs2[i]) {
292                                 dest_ucs2[i] = v;
293                         }
294                 }
295         }
296
297         return len;
298 }
299
300
301
302 /**
303  Copy a string from a ucs2 source to a unix char* destination.
304  Flags can have:
305   STR_TERMINATE means the string in src is null terminated.
306   STR_NOALIGN   means don't try to align.
307  if STR_TERMINATE is set then src_len is ignored if it is -1.
308  src_len is the length of the source area in bytes
309  Return the number of bytes occupied by the string in src.
310  The resulting string in "dest" is always null terminated.
311 **/
312
313 static size_t pull_ucs2(const void *base_ptr, char *dest, const void *src, size_t dest_len, size_t src_len, int flags)
314 {
315         size_t size = 0;
316         size_t ucs2_align_len = 0;
317         bool ret;
318
319         if (dest_len == (size_t)-1) {
320                 /* No longer allow dest_len of -1. */
321                 smb_panic("pull_ucs2 - invalid dest_len of -1");
322         }
323
324         if (!src_len) {
325                 if (dest && dest_len > 0) {
326                         dest[0] = '\0';
327                 }
328                 return 0;
329         }
330
331         if (ucs2_align(base_ptr, src, flags)) {
332                 src = (const void *)((const char *)src + 1);
333                 if (src_len != (size_t)-1)
334                         src_len--;
335                 ucs2_align_len = 1;
336         }
337
338         if (flags & STR_TERMINATE) {
339                 /* src_len -1 is the default for null terminated strings. */
340                 if (src_len != (size_t)-1) {
341                         size_t len = strnlen_w((const smb_ucs2_t *)src,
342                                                 src_len/2);
343                         if (len < src_len/2)
344                                 len++;
345                         src_len = len*2;
346                 }
347         }
348
349         /* ucs2 is always a multiple of 2 bytes */
350         if (src_len != (size_t)-1)
351                 src_len &= ~1;
352
353         ret = convert_string(CH_UTF16LE, CH_UNIX, src, src_len, dest, dest_len, &size);
354         if (ret == false) {
355                 size = 0;
356                 dest_len = 0;
357         }
358
359         if (src_len == (size_t)-1)
360                 src_len = size*2;
361
362         if (dest_len && size) {
363                 /* Did we already process the terminating zero ? */
364                 if (dest[MIN(size-1, dest_len-1)] != 0) {
365                         dest[MIN(size, dest_len-1)] = 0;
366                 }
367         } else {
368                 dest[0] = 0;
369         }
370
371         return src_len + ucs2_align_len;
372 }
373
374 /**
375  Copy a string from a ucs2 source to a unix char* destination.
376  Talloc version with a base pointer.
377  Uses malloc if TALLOC_CTX is NULL (this is a bad interface and
378  needs fixing. JRA).
379  Flags can have:
380   STR_TERMINATE means the string in src is null terminated.
381   STR_NOALIGN   means don't try to align.
382  if STR_TERMINATE is set then src_len is ignored if it is -1.
383  src_len is the length of the source area in bytes
384  Return the number of bytes occupied by the string in src.
385  The resulting string in "dest" is always null terminated.
386 **/
387
388 static size_t pull_ucs2_base_talloc(TALLOC_CTX *ctx,
389                                     const void *base_ptr,
390                                     char **ppdest,
391                                     const void *src,
392                                     size_t src_len,
393                                     int flags)
394 {
395         char *dest;
396         size_t dest_len;
397         size_t ucs2_align_len = 0;
398
399         *ppdest = NULL;
400
401 #ifdef DEVELOPER
402         /* Ensure we never use the braindead "malloc" varient. */
403         if (ctx == NULL) {
404                 smb_panic("NULL talloc CTX in pull_ucs2_base_talloc\n");
405         }
406 #endif
407
408         if (!src_len) {
409                 return 0;
410         }
411
412         if (src_len == (size_t)-1) {
413                 /* no longer used anywhere, but worth checking */
414                 smb_panic("sec_len == -1 in pull_ucs2_base_talloc");
415         }
416
417         if (ucs2_align(base_ptr, src, flags)) {
418                 src = (const void *)((const char *)src + 1);
419                 src_len--;
420                 ucs2_align_len = 1;
421         }
422
423         if (flags & STR_TERMINATE) {
424                 /* src_len -1 is the default for null terminated strings. */
425                 size_t len = strnlen_w((const smb_ucs2_t *)src,
426                                        src_len/2);
427                 if (len < src_len/2)
428                         len++;
429                 src_len = len*2;
430
431                 /* Ensure we don't use an insane length from the client. */
432                 if (src_len >= 1024*1024) {
433                         smb_panic("Bad src length in pull_ucs2_base_talloc\n");
434                 }
435         }
436
437         /* ucs2 is always a multiple of 2 bytes */
438         src_len &= ~1;
439
440         if (!convert_string_talloc(ctx, CH_UTF16LE, CH_UNIX, src, src_len,
441                                    (void *)&dest, &dest_len)) {
442                 dest_len = 0;
443         }
444
445         if (dest_len) {
446                 /* Did we already process the terminating zero ? */
447                 if (dest[dest_len-1] != 0) {
448                         size_t size = talloc_get_size(dest);
449                         /* Have we got space to append the '\0' ? */
450                         if (size <= dest_len) {
451                                 /* No, realloc. */
452                                 dest = talloc_realloc(ctx, dest, char,
453                                                 dest_len+1);
454                                 if (!dest) {
455                                         /* talloc fail. */
456                                         dest_len = (size_t)-1;
457                                         return 0;
458                                 }
459                         }
460                         /* Yay - space ! */
461                         dest[dest_len] = '\0';
462                         dest_len++;
463                 }
464         } else if (dest) {
465                 dest[0] = 0;
466         }
467
468         *ppdest = dest;
469         return src_len + ucs2_align_len;
470 }
471
472 /**
473  Copy a string from a char* src to a unicode or ascii
474  dos codepage destination choosing unicode or ascii based on the 
475  flags supplied
476  Return the number of bytes occupied by the string in the destination.
477  flags can have:
478   STR_TERMINATE means include the null termination.
479   STR_UPPER     means uppercase in the destination.
480   STR_ASCII     use ascii even with unicode packet.
481   STR_NOALIGN   means don't do alignment.
482  dest_len is the maximum length allowed in the destination. If dest_len
483  is -1 then no maxiumum is used.
484 **/
485
486 size_t push_string_check_fn(void *dest, const char *src,
487                          size_t dest_len, int flags)
488 {
489         if (!(flags & STR_ASCII) && (flags & STR_UNICODE)) {
490                 return push_ucs2(NULL, dest, src, dest_len, flags);
491         }
492         return push_ascii(dest, src, dest_len, flags);
493 }
494
495
496 /**
497  Copy a string from a char* src to a unicode or ascii
498  dos codepage destination choosing unicode or ascii based on the 
499  flags in the SMB buffer starting at base_ptr.
500  Return the number of bytes occupied by the string in the destination.
501  flags can have:
502   STR_TERMINATE means include the null termination.
503   STR_UPPER     means uppercase in the destination.
504   STR_ASCII     use ascii even with unicode packet.
505   STR_NOALIGN   means don't do alignment.
506  dest_len is the maximum length allowed in the destination. If dest_len
507  is -1 then no maxiumum is used.
508 **/
509
510 size_t push_string_base(const char *base, uint16 flags2,
511                         void *dest, const char *src,
512                         size_t dest_len, int flags)
513 {
514
515         if (!(flags & STR_ASCII) && \
516             ((flags & STR_UNICODE || \
517               (flags2 & FLAGS2_UNICODE_STRINGS)))) {
518                 return push_ucs2(base, dest, src, dest_len, flags);
519         }
520         return push_ascii(dest, src, dest_len, flags);
521 }
522
523 /**
524  Copy a string from a unicode or ascii source (depending on
525  the packet flags) to a char* destination.
526  Flags can have:
527   STR_TERMINATE means the string in src is null terminated.
528   STR_UNICODE   means to force as unicode.
529   STR_ASCII     use ascii even with unicode packet.
530   STR_NOALIGN   means don't do alignment.
531  if STR_TERMINATE is set then src_len is ignored is it is -1
532  src_len is the length of the source area in bytes.
533  Return the number of bytes occupied by the string in src.
534  The resulting string in "dest" is always null terminated.
535 **/
536
537 size_t pull_string_fn(const void *base_ptr,
538                    uint16 smb_flags2,
539                    char *dest,
540                    const void *src,
541                    size_t dest_len,
542                    size_t src_len,
543                    int flags)
544 {
545         if ((base_ptr == NULL) && ((flags & (STR_ASCII|STR_UNICODE)) == 0)) {
546                 smb_panic("No base ptr to get flg2 and neither ASCII nor "
547                           "UNICODE defined");
548         }
549
550         if (!(flags & STR_ASCII) && \
551             ((flags & STR_UNICODE || \
552               (smb_flags2 & FLAGS2_UNICODE_STRINGS)))) {
553                 return pull_ucs2(base_ptr, dest, src, dest_len, src_len, flags);
554         }
555         return pull_ascii(dest, src, dest_len, src_len, flags);
556 }
557
558 /**
559  Copy a string from a unicode or ascii source (depending on
560  the packet flags) to a char* destination.
561  Variant that uses talloc.
562  Flags can have:
563   STR_TERMINATE means the string in src is null terminated.
564   STR_UNICODE   means to force as unicode.
565   STR_ASCII     use ascii even with unicode packet.
566   STR_NOALIGN   means don't do alignment.
567  if STR_TERMINATE is set then src_len is ignored is it is -1
568  src_len is the length of the source area in bytes.
569  Return the number of bytes occupied by the string in src.
570  The resulting string in "dest" is always null terminated.
571 **/
572
573 size_t pull_string_talloc(TALLOC_CTX *ctx,
574                           const void *base_ptr,
575                           uint16 smb_flags2,
576                           char **ppdest,
577                           const void *src,
578                           size_t src_len,
579                           int flags)
580 {
581         if ((base_ptr == NULL) && ((flags & (STR_ASCII|STR_UNICODE)) == 0)) {
582                 smb_panic("No base ptr to get flg2 and neither ASCII nor "
583                           "UNICODE defined");
584         }
585
586         if (!(flags & STR_ASCII) && \
587             ((flags & STR_UNICODE || \
588               (smb_flags2 & FLAGS2_UNICODE_STRINGS)))) {
589                 return pull_ucs2_base_talloc(ctx,
590                                         base_ptr,
591                                         ppdest,
592                                         src,
593                                         src_len,
594                                         flags);
595         }
596         return pull_ascii_base_talloc(ctx,
597                                         ppdest,
598                                         src,
599                                         src_len,
600                                         flags);
601 }
602
603
604 size_t align_string(const void *base_ptr, const char *p, int flags)
605 {
606         if (!(flags & STR_ASCII) && \
607             ((flags & STR_UNICODE || \
608               (SVAL(base_ptr, smb_flg2) & FLAGS2_UNICODE_STRINGS)))) {
609                 return ucs2_align(base_ptr, p, flags);
610         }
611         return 0;
612 }
613
614 /*******************************************************************
615  Write a string in (little-endian) unicode format. src is in
616  the current DOS codepage. len is the length in bytes of the
617  string pointed to by dst.
618
619  if null_terminate is True then null terminate the packet (adds 2 bytes)
620
621  the return value is the length in bytes consumed by the string, including the
622  null termination if applied
623 ********************************************************************/
624
625 size_t dos_PutUniCode(char *dst,const char *src, size_t len, bool null_terminate)
626 {
627         int flags = null_terminate ? STR_UNICODE|STR_NOALIGN|STR_TERMINATE
628                                    : STR_UNICODE|STR_NOALIGN;
629         return push_ucs2(NULL, dst, src, len, flags);
630 }
631
632
633 /* Converts a string from internal samba format to unicode
634  */
635
636 int rpcstr_push(void *dest, const char *src, size_t dest_len, int flags)
637 {
638         return push_ucs2(NULL, dest, src, dest_len, flags|STR_UNICODE|STR_NOALIGN);
639 }
640
641 /* Converts a string from internal samba format to unicode. Always terminates.
642  * Actually just a wrapper round push_ucs2_talloc().
643  */
644
645 int rpcstr_push_talloc(TALLOC_CTX *ctx, smb_ucs2_t **dest, const char *src)
646 {
647         size_t size;
648         if (push_ucs2_talloc(ctx, dest, src, &size))
649                 return size;
650         else
651                 return -1;
652 }