source: vendor/current/source3/lib/charcnv.c

Last change on this file was 988, checked in by Silvan Scherrer, 9 years ago

Samba Server: update vendor to version 4.4.3

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