Line data Source code
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 15450 : void gfree_charcnv(void)
29 : {
30 15450 : free_iconv_handle();
31 15450 : }
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 92046 : size_t push_ascii(void *dest, const char *src, size_t dest_len, int flags)
48 : {
49 92046 : size_t src_len = 0;
50 92046 : char *tmpbuf = NULL;
51 92046 : size_t size = 0;
52 771 : bool ret;
53 :
54 : /* No longer allow a length of -1. */
55 92046 : if (dest_len == (size_t)-1) {
56 0 : smb_panic("push_ascii - dest_len == -1");
57 : }
58 :
59 92046 : if (flags & STR_UPPER) {
60 237 : tmpbuf = SMB_STRDUP(src);
61 237 : if (!tmpbuf) {
62 0 : smb_panic("malloc fail");
63 : }
64 237 : if (!strupper_m(tmpbuf)) {
65 0 : if ((flags & (STR_TERMINATE|STR_TERMINATE_ASCII)) &&
66 0 : dest &&
67 0 : dest_len > 0) {
68 0 : *(char *)dest = 0;
69 : }
70 0 : SAFE_FREE(tmpbuf);
71 0 : return 0;
72 : }
73 237 : src = tmpbuf;
74 : }
75 :
76 92046 : src_len = strlen(src);
77 92046 : if (flags & (STR_TERMINATE | STR_TERMINATE_ASCII)) {
78 46018 : src_len++;
79 : }
80 :
81 92046 : ret = convert_string(CH_UNIX, CH_DOS, src, src_len, dest, dest_len, &size);
82 92046 : SAFE_FREE(tmpbuf);
83 92046 : if (ret == false) {
84 20 : if ((flags & (STR_TERMINATE | STR_TERMINATE_ASCII)) &&
85 : dest_len > 0) {
86 2 : ((char *)dest)[0] = '\0';
87 : }
88 20 : return 0;
89 : }
90 92026 : 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 : **/
112 46404 : size_t pull_ascii(char *dest, const void *src, size_t dest_len, size_t src_len, int flags)
113 : {
114 0 : bool ret;
115 46404 : size_t size = 0;
116 :
117 46404 : if (dest_len == (size_t)-1) {
118 : /* No longer allow dest_len of -1. */
119 0 : smb_panic("pull_ascii - invalid dest_len of -1");
120 : }
121 :
122 46404 : if (flags & STR_TERMINATE) {
123 46404 : if (src_len == (size_t)-1) {
124 19135 : src_len = strlen((const char *)src) + 1;
125 : } else {
126 27269 : size_t len = strnlen((const char *)src, src_len);
127 27269 : if (len < src_len)
128 19055 : len++;
129 27269 : src_len = len;
130 : }
131 : }
132 :
133 46404 : ret = convert_string(CH_DOS, CH_UNIX, src, src_len, dest, dest_len, &size);
134 46404 : if (ret == false) {
135 0 : size = 0;
136 0 : dest_len = 0;
137 : }
138 :
139 46404 : if (dest_len && size) {
140 : /* Did we already process the terminating zero ? */
141 46404 : if (dest[MIN(size-1, dest_len-1)] != 0) {
142 8214 : dest[MIN(size, dest_len-1)] = 0;
143 : }
144 : } else {
145 0 : dest[0] = 0;
146 : }
147 :
148 46404 : 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 :
168 16931 : static 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 16931 : char *dest = NULL;
175 144 : size_t dest_len;
176 :
177 16931 : *ppdest = NULL;
178 :
179 16931 : if (!src_len) {
180 0 : return 0;
181 : }
182 :
183 16931 : if (src_len == (size_t)-1) {
184 0 : smb_panic("src_len == -1 in pull_ascii_base_talloc");
185 : }
186 :
187 16931 : if (flags & STR_TERMINATE) {
188 7328 : size_t len = strnlen((const char *)src, src_len);
189 7328 : if (len < src_len)
190 7326 : len++;
191 7328 : src_len = len;
192 : /* Ensure we don't use an insane length from the client. */
193 7328 : if (src_len >= 1024*1024) {
194 0 : char *msg = talloc_asprintf(ctx,
195 : "Bad src length (%u) in "
196 : "pull_ascii_base_talloc",
197 : (unsigned int)src_len);
198 0 : smb_panic(msg);
199 : }
200 : }
201 :
202 : /* src_len != -1 here. */
203 :
204 16931 : if (!convert_string_talloc(ctx, CH_DOS, CH_UNIX, src, src_len, &dest,
205 : &dest_len)) {
206 0 : dest_len = 0;
207 : }
208 :
209 16931 : if (dest_len && dest) {
210 : /* Did we already process the terminating zero ? */
211 16931 : if (dest[dest_len-1] != 0) {
212 4 : size_t size = talloc_get_size(dest);
213 : /* Have we got space to append the '\0' ? */
214 4 : if (size <= dest_len) {
215 : /* No, realloc. */
216 0 : dest = talloc_realloc(ctx, dest, char,
217 : dest_len+1);
218 0 : if (!dest) {
219 : /* talloc fail. */
220 0 : dest_len = (size_t)-1;
221 0 : return 0;
222 : }
223 : }
224 : /* Yay - space ! */
225 4 : dest[dest_len] = '\0';
226 4 : dest_len++;
227 : }
228 0 : } else if (dest) {
229 0 : dest[0] = 0;
230 : }
231 :
232 16931 : *ppdest = dest;
233 16931 : 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 :
253 1028221 : static size_t push_ucs2(const void *base_ptr, void *dest, const char *src, size_t dest_len, int flags)
254 : {
255 1028221 : size_t len=0;
256 1042 : size_t src_len;
257 1028221 : size_t size = 0;
258 1042 : bool ret;
259 :
260 1028221 : if (dest_len == (size_t)-1) {
261 : /* No longer allow dest_len of -1. */
262 0 : smb_panic("push_ucs2 - invalid dest_len of -1");
263 : }
264 :
265 1028221 : if (flags & STR_TERMINATE)
266 192648 : src_len = (size_t)-1;
267 : else
268 835036 : src_len = strlen(src);
269 :
270 1028221 : if (ucs2_align(base_ptr, dest, flags)) {
271 4404 : *(char *)dest = 0;
272 4404 : dest = (void *)((char *)dest + 1);
273 4404 : if (dest_len)
274 4404 : dest_len--;
275 4268 : len++;
276 : }
277 :
278 : /* ucs2 is always a multiple of 2 bytes */
279 1028221 : dest_len &= ~1;
280 :
281 1028221 : ret = convert_string(CH_UNIX, CH_UTF16LE, src, src_len, dest, dest_len, &size);
282 1028221 : if (ret == false) {
283 80 : if ((flags & STR_TERMINATE) &&
284 40 : dest &&
285 : dest_len) {
286 40 : *(char *)dest = 0;
287 : }
288 80 : return len;
289 : }
290 :
291 1028141 : len += size;
292 :
293 1028141 : if (flags & STR_UPPER) {
294 42769 : 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 426052 : for (i = 0; i < (size / 2) && i < (dest_len / 2) && dest_ucs2[i]; i++) {
301 383258 : smb_ucs2_t v = toupper_w(dest_ucs2[i]);
302 383258 : if (v != dest_ucs2[i]) {
303 0 : dest_ucs2[i] = v;
304 : }
305 : }
306 : }
307 :
308 1027099 : 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 :
325 352126 : static 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 10719 : char *dest;
333 10719 : size_t dest_len;
334 352126 : size_t ucs2_align_len = 0;
335 :
336 352126 : *ppdest = NULL;
337 :
338 : #ifdef DEVELOPER
339 : /* Ensure we never use the braindead "malloc" variant. */
340 352126 : if (ctx == NULL) {
341 0 : smb_panic("NULL talloc CTX in pull_ucs2_base_talloc\n");
342 : }
343 : #endif
344 :
345 352126 : if (!src_len) {
346 37172 : return 0;
347 : }
348 :
349 314954 : if (src_len == (size_t)-1) {
350 : /* no longer used anywhere, but worth checking */
351 0 : smb_panic("sec_len == -1 in pull_ucs2_base_talloc");
352 : }
353 :
354 314954 : if (ucs2_align(base_ptr, src, flags)) {
355 83129 : src = (const void *)((const char *)src + 1);
356 83129 : src_len--;
357 83129 : ucs2_align_len = 1;
358 : }
359 :
360 314954 : if (flags & STR_TERMINATE) {
361 : /* src_len -1 is the default for null terminated strings. */
362 218005 : size_t len = strnlen_w((const smb_ucs2_t *)src,
363 : src_len/2);
364 218005 : if (len < src_len/2)
365 217180 : len++;
366 218005 : src_len = len*2;
367 :
368 : /* Ensure we don't use an insane length from the client. */
369 218005 : if (src_len >= 1024*1024) {
370 0 : smb_panic("Bad src length in pull_ucs2_base_talloc\n");
371 : }
372 : }
373 :
374 : /* ucs2 is always a multiple of 2 bytes */
375 314954 : src_len &= ~1;
376 :
377 314954 : if (!convert_string_talloc(ctx, CH_UTF16LE, CH_UNIX, src, src_len,
378 : (void *)&dest, &dest_len)) {
379 4 : dest_len = 0;
380 : }
381 :
382 314954 : if (dest_len) {
383 : /* Did we already process the terminating zero ? */
384 314950 : if (dest[dest_len-1] != 0) {
385 97770 : size_t size = talloc_get_size(dest);
386 : /* Have we got space to append the '\0' ? */
387 97770 : if (size <= dest_len) {
388 : /* No, realloc. */
389 0 : dest = talloc_realloc(ctx, dest, char,
390 : dest_len+1);
391 0 : if (!dest) {
392 : /* talloc fail. */
393 0 : dest_len = (size_t)-1;
394 0 : return 0;
395 : }
396 : }
397 : /* Yay - space ! */
398 97770 : dest[dest_len] = '\0';
399 97770 : dest_len++;
400 : }
401 4 : } else if (dest) {
402 0 : dest[0] = 0;
403 : }
404 :
405 314954 : *ppdest = dest;
406 314954 : 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 maximum is used.
421 : **/
422 :
423 827 : size_t push_string_check_fn(void *dest, const char *src,
424 : size_t dest_len, int flags)
425 : {
426 827 : if (!(flags & STR_ASCII) && (flags & STR_UNICODE)) {
427 0 : return push_ucs2(NULL, dest, src, dest_len, flags);
428 : }
429 827 : 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 maximum is used.
445 : **/
446 :
447 1037518 : size_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 1037518 : if (!(flags & STR_ASCII) && \
453 1028219 : ((flags & STR_UNICODE || \
454 : (flags2 & FLAGS2_UNICODE_STRINGS)))) {
455 1028213 : return push_ucs2(base, dest, src, dest_len, flags);
456 : }
457 9305 : 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 :
475 369057 : size_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 369057 : if ((base_ptr == NULL) && ((flags & (STR_ASCII|STR_UNICODE)) == 0)) {
484 0 : smb_panic("No base ptr to get flg2 and neither ASCII nor "
485 : "UNICODE defined");
486 : }
487 :
488 369057 : if (!(flags & STR_ASCII) && \
489 352182 : ((flags & STR_UNICODE || \
490 : (smb_flags2 & FLAGS2_UNICODE_STRINGS)))) {
491 352126 : return pull_ucs2_base_talloc(ctx,
492 : base_ptr,
493 : ppdest,
494 : src,
495 : src_len,
496 : flags);
497 : }
498 16931 : 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 :
516 8 : size_t dos_PutUniCode(char *dst,const char *src, size_t len, bool null_terminate)
517 : {
518 8 : int flags = null_terminate ? STR_UNICODE|STR_NOALIGN|STR_TERMINATE
519 8 : : STR_UNICODE|STR_NOALIGN;
520 8 : 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 :
528 0 : int rpcstr_push_talloc(TALLOC_CTX *ctx, smb_ucs2_t **dest, const char *src)
529 : {
530 0 : size_t size;
531 0 : if (push_ucs2_talloc(ctx, dest, src, &size))
532 0 : return size;
533 : else
534 0 : return -1;
535 : }
|