1/* 2 Unix SMB/CIFS implementation. 3 4 routines for marshalling/unmarshalling string types 5 6 Copyright (C) Andrew Tridgell 2003 7 8 This program is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 3 of the License, or 11 (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program. If not, see <http://www.gnu.org/licenses/>. 20*/ 21 22#include "includes.h" 23#include "librpc/ndr/libndr.h" 24 25/** 26 pull a general string from the wire 27*/ 28_PUBLIC_ enum ndr_err_code ndr_pull_string(struct ndr_pull *ndr, int ndr_flags, const char **s) 29{ 30 char *as=NULL; 31 uint32_t len1, ofs, len2; 32 uint16_t len3; 33 size_t converted_size; 34 int chset = CH_UTF16; 35 unsigned byte_mul = 2; 36 unsigned flags = ndr->flags; 37 unsigned c_len_term = 0; 38 39 if (!(ndr_flags & NDR_SCALARS)) { 40 return NDR_ERR_SUCCESS; 41 } 42 43 if (NDR_BE(ndr)) { 44 chset = CH_UTF16BE; 45 } 46 47 if (flags & LIBNDR_FLAG_STR_ASCII) { 48 chset = CH_DOS; 49 byte_mul = 1; 50 flags &= ~LIBNDR_FLAG_STR_ASCII; 51 } 52 53 if (flags & LIBNDR_FLAG_STR_UTF8) { 54 chset = CH_UTF8; 55 byte_mul = 1; 56 flags &= ~LIBNDR_FLAG_STR_UTF8; 57 } 58 59 flags &= ~LIBNDR_FLAG_STR_CONFORMANT; 60 if (flags & LIBNDR_FLAG_STR_CHARLEN) { 61 c_len_term = 1; 62 flags &= ~LIBNDR_FLAG_STR_CHARLEN; 63 } 64 65 switch (flags & LIBNDR_STRING_FLAGS) { 66 case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4: 67 case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4|LIBNDR_FLAG_STR_NOTERM: 68 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &len1)); 69 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &ofs)); 70 if (ofs != 0) { 71 return ndr_pull_error(ndr, NDR_ERR_STRING, "non-zero array offset with string flags 0x%x\n", 72 ndr->flags & LIBNDR_STRING_FLAGS); 73 } 74 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &len2)); 75 if (len2 > len1) { 76 return ndr_pull_error(ndr, NDR_ERR_STRING, 77 "Bad string lengths len1=%u ofs=%u len2=%u\n", 78 len1, ofs, len2); 79 } 80 NDR_PULL_NEED_BYTES(ndr, (len2 + c_len_term)*byte_mul); 81 if (len2 == 0) { 82 as = talloc_strdup(ndr->current_mem_ctx, ""); 83 } else { 84 if (!convert_string_talloc(ndr->current_mem_ctx, chset, 85 CH_UNIX, 86 ndr->data+ndr->offset, 87 (len2 + c_len_term)*byte_mul, 88 (void **)(void *)&as, 89 &converted_size, false)) 90 { 91 return ndr_pull_error(ndr, NDR_ERR_CHARCNV, 92 "Bad character conversion"); 93 } 94 } 95 NDR_CHECK(ndr_pull_advance(ndr, (len2 + c_len_term)*byte_mul)); 96 97 if (len1 != len2) { 98 DEBUG(6,("len1[%u] != len2[%u] '%s'\n", len1, len2, as)); 99 } 100 101 /* this is a way of detecting if a string is sent with the wrong 102 termination */ 103 if (ndr->flags & LIBNDR_FLAG_STR_NOTERM) { 104 if (strlen(as) < (len2 + c_len_term)) { 105 DEBUG(6,("short string '%s'\n", as)); 106 } 107 } else { 108 if (strlen(as) == (len2 + c_len_term)) { 109 DEBUG(6,("long string '%s'\n", as)); 110 } 111 } 112 *s = as; 113 break; 114 115 case LIBNDR_FLAG_STR_SIZE4: 116 case LIBNDR_FLAG_STR_SIZE4|LIBNDR_FLAG_STR_NOTERM: 117 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &len1)); 118 NDR_PULL_NEED_BYTES(ndr, (len1 + c_len_term)*byte_mul); 119 if (len1 == 0) { 120 as = talloc_strdup(ndr->current_mem_ctx, ""); 121 } else { 122 if (!convert_string_talloc(ndr->current_mem_ctx, chset, 123 CH_UNIX, 124 ndr->data+ndr->offset, 125 (len1 + c_len_term)*byte_mul, 126 (void **)(void *)&as, 127 &converted_size, false)) 128 { 129 return ndr_pull_error(ndr, NDR_ERR_CHARCNV, 130 "Bad character conversion"); 131 } 132 } 133 NDR_CHECK(ndr_pull_advance(ndr, (len1 + c_len_term)*byte_mul)); 134 135 /* this is a way of detecting if a string is sent with the wrong 136 termination */ 137 if (ndr->flags & LIBNDR_FLAG_STR_NOTERM) { 138 if (strlen(as) < (len1 + c_len_term)) { 139 DEBUG(6,("short string '%s'\n", as)); 140 } 141 } else { 142 if (strlen(as) == (len1 + c_len_term)) { 143 DEBUG(6,("long string '%s'\n", as)); 144 } 145 } 146 *s = as; 147 break; 148 149 case LIBNDR_FLAG_STR_LEN4: 150 case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_NOTERM: 151 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &ofs)); 152 if (ofs != 0) { 153 return ndr_pull_error(ndr, NDR_ERR_STRING, "non-zero array offset with string flags 0x%x\n", 154 ndr->flags & LIBNDR_STRING_FLAGS); 155 } 156 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &len1)); 157 NDR_PULL_NEED_BYTES(ndr, (len1 + c_len_term)*byte_mul); 158 if (len1 == 0) { 159 as = talloc_strdup(ndr->current_mem_ctx, ""); 160 } else { 161 if (!convert_string_talloc(ndr->current_mem_ctx, chset, 162 CH_UNIX, 163 ndr->data+ndr->offset, 164 (len1 + c_len_term)*byte_mul, 165 (void **)(void *)&as, 166 &converted_size, false)) 167 { 168 return ndr_pull_error(ndr, NDR_ERR_CHARCNV, 169 "Bad character conversion"); 170 } 171 } 172 NDR_CHECK(ndr_pull_advance(ndr, (len1 + c_len_term)*byte_mul)); 173 174 /* this is a way of detecting if a string is sent with the wrong 175 termination */ 176 if (ndr->flags & LIBNDR_FLAG_STR_NOTERM) { 177 if (strlen(as) < (len1 + c_len_term)) { 178 DEBUG(6,("short string '%s'\n", as)); 179 } 180 } else { 181 if (strlen(as) == (len1 + c_len_term)) { 182 DEBUG(6,("long string '%s'\n", as)); 183 } 184 } 185 *s = as; 186 break; 187 188 189 case LIBNDR_FLAG_STR_SIZE2: 190 case LIBNDR_FLAG_STR_SIZE2|LIBNDR_FLAG_STR_NOTERM: 191 NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &len3)); 192 NDR_PULL_NEED_BYTES(ndr, (len3 + c_len_term)*byte_mul); 193 if (len3 == 0) { 194 as = talloc_strdup(ndr->current_mem_ctx, ""); 195 } else { 196 if (!convert_string_talloc(ndr->current_mem_ctx, chset, 197 CH_UNIX, 198 ndr->data+ndr->offset, 199 (len3 + c_len_term)*byte_mul, 200 (void **)(void *)&as, 201 &converted_size, false)) 202 { 203 return ndr_pull_error(ndr, NDR_ERR_CHARCNV, 204 "Bad character conversion"); 205 } 206 } 207 NDR_CHECK(ndr_pull_advance(ndr, (len3 + c_len_term)*byte_mul)); 208 209 /* this is a way of detecting if a string is sent with the wrong 210 termination */ 211 if (ndr->flags & LIBNDR_FLAG_STR_NOTERM) { 212 if (strlen(as) < (len3 + c_len_term)) { 213 DEBUG(6,("short string '%s'\n", as)); 214 } 215 } else { 216 if (strlen(as) == (len3 + c_len_term)) { 217 DEBUG(6,("long string '%s'\n", as)); 218 } 219 } 220 *s = as; 221 break; 222 223 case LIBNDR_FLAG_STR_SIZE2|LIBNDR_FLAG_STR_NOTERM|LIBNDR_FLAG_STR_BYTESIZE: 224 NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &len3)); 225 NDR_PULL_NEED_BYTES(ndr, len3); 226 if (len3 == 0) { 227 as = talloc_strdup(ndr->current_mem_ctx, ""); 228 } else { 229 if (!convert_string_talloc(ndr->current_mem_ctx, chset, 230 CH_UNIX, 231 ndr->data+ndr->offset, len3, 232 (void **)(void *)&as, 233 &converted_size, false)) 234 { 235 return ndr_pull_error(ndr, NDR_ERR_CHARCNV, 236 "Bad character conversion"); 237 } 238 } 239 NDR_CHECK(ndr_pull_advance(ndr, len3)); 240 *s = as; 241 break; 242 243 case LIBNDR_FLAG_STR_NULLTERM: 244 if (byte_mul == 1) { 245 len1 = ascii_len_n((const char *)(ndr->data+ndr->offset), ndr->data_size - ndr->offset); 246 } else { 247 len1 = utf16_len_n(ndr->data+ndr->offset, ndr->data_size - ndr->offset); 248 } 249 if (!convert_string_talloc(ndr->current_mem_ctx, chset, CH_UNIX, 250 ndr->data+ndr->offset, len1, 251 (void **)(void *)&as, 252 &converted_size, false)) 253 { 254 return ndr_pull_error(ndr, NDR_ERR_CHARCNV, 255 "Bad character conversion"); 256 } 257 NDR_CHECK(ndr_pull_advance(ndr, len1)); 258 *s = as; 259 break; 260 261 case LIBNDR_FLAG_STR_NOTERM: 262 if (!(ndr->flags & LIBNDR_FLAG_REMAINING)) { 263 return ndr_pull_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%x (missing NDR_REMAINING)\n", 264 ndr->flags & LIBNDR_STRING_FLAGS); 265 } 266 267 len1 = ndr->data_size - ndr->offset; 268 269 NDR_PULL_NEED_BYTES(ndr, len1); 270 if (len1 == 0) { 271 as = talloc_strdup(ndr->current_mem_ctx, ""); 272 } else { 273 if (!convert_string_talloc(ndr->current_mem_ctx, chset, 274 CH_UNIX, 275 ndr->data+ndr->offset, len1, 276 (void **)(void *)&as, 277 &converted_size, false)) 278 { 279 return ndr_pull_error(ndr, NDR_ERR_CHARCNV, 280 "Bad character conversion"); 281 } 282 } 283 NDR_CHECK(ndr_pull_advance(ndr, len1)); 284 285 *s = as; 286 break; 287 288 default: 289 return ndr_pull_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%x\n", 290 ndr->flags & LIBNDR_STRING_FLAGS); 291 } 292 293 return NDR_ERR_SUCCESS; 294} 295 296 297/** 298 push a general string onto the wire 299*/ 300_PUBLIC_ enum ndr_err_code ndr_push_string(struct ndr_push *ndr, int ndr_flags, const char *s) 301{ 302 ssize_t s_len, c_len; 303 size_t d_len; 304 int chset = CH_UTF16; 305 unsigned flags = ndr->flags; 306 unsigned byte_mul = 2; 307 uint8_t *dest = NULL; 308 309 if (!(ndr_flags & NDR_SCALARS)) { 310 return NDR_ERR_SUCCESS; 311 } 312 313 if (NDR_BE(ndr)) { 314 chset = CH_UTF16BE; 315 } 316 317 s_len = s?strlen(s):0; 318 319 if (flags & LIBNDR_FLAG_STR_ASCII) { 320 chset = CH_DOS; 321 byte_mul = 1; 322 flags &= ~LIBNDR_FLAG_STR_ASCII; 323 } 324 325 if (flags & LIBNDR_FLAG_STR_UTF8) { 326 chset = CH_UTF8; 327 byte_mul = 1; 328 flags &= ~LIBNDR_FLAG_STR_UTF8; 329 } 330 331 flags &= ~LIBNDR_FLAG_STR_CONFORMANT; 332 333 if (!(flags & LIBNDR_FLAG_STR_NOTERM)) { 334 s_len++; 335 } 336 if (!convert_string_talloc(ndr, CH_UNIX, chset, s, s_len, 337 (void **)(void *)&dest, &d_len, false)) 338 { 339 return ndr_push_error(ndr, NDR_ERR_CHARCNV, 340 "Bad character conversion"); 341 } 342 343 if (flags & LIBNDR_FLAG_STR_BYTESIZE) { 344 c_len = d_len; 345 flags &= ~LIBNDR_FLAG_STR_BYTESIZE; 346 } else if (flags & LIBNDR_FLAG_STR_CHARLEN) { 347 c_len = (d_len / byte_mul)-1; 348 flags &= ~LIBNDR_FLAG_STR_CHARLEN; 349 } else { 350 c_len = d_len / byte_mul; 351 } 352 353 switch ((flags & LIBNDR_STRING_FLAGS) & ~LIBNDR_FLAG_STR_NOTERM) { 354 case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4: 355 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, c_len)); 356 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0)); 357 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, c_len)); 358 NDR_CHECK(ndr_push_bytes(ndr, dest, d_len)); 359 break; 360 361 case LIBNDR_FLAG_STR_LEN4: 362 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0)); 363 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, c_len)); 364 NDR_CHECK(ndr_push_bytes(ndr, dest, d_len)); 365 break; 366 367 case LIBNDR_FLAG_STR_SIZE4: 368 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, c_len)); 369 NDR_CHECK(ndr_push_bytes(ndr, dest, d_len)); 370 break; 371 372 case LIBNDR_FLAG_STR_SIZE2: 373 NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, c_len)); 374 NDR_CHECK(ndr_push_bytes(ndr, dest, d_len)); 375 break; 376 377 case LIBNDR_FLAG_STR_NULLTERM: 378 NDR_CHECK(ndr_push_bytes(ndr, dest, d_len)); 379 break; 380 381 default: 382 if (ndr->flags & LIBNDR_FLAG_REMAINING) { 383 NDR_CHECK(ndr_push_bytes(ndr, dest, d_len)); 384 break; 385 } 386 387 return ndr_push_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%x\n", 388 ndr->flags & LIBNDR_STRING_FLAGS); 389 } 390 391 talloc_free(dest); 392 393 return NDR_ERR_SUCCESS; 394} 395 396/** 397 push a general string onto the wire 398*/ 399_PUBLIC_ size_t ndr_string_array_size(struct ndr_push *ndr, const char *s) 400{ 401 size_t c_len; 402 unsigned flags = ndr->flags; 403 unsigned byte_mul = 2; 404 unsigned c_len_term = 1; 405 406 c_len = s?strlen_m(s):0; 407 408 if (flags & (LIBNDR_FLAG_STR_ASCII|LIBNDR_FLAG_STR_UTF8)) { 409 byte_mul = 1; 410 } 411 412 if (flags & LIBNDR_FLAG_STR_NOTERM) { 413 c_len_term = 0; 414 } 415 416 c_len = c_len + c_len_term; 417 418 if (flags & LIBNDR_FLAG_STR_BYTESIZE) { 419 c_len = c_len * byte_mul; 420 } 421 422 return c_len; 423} 424 425_PUBLIC_ void ndr_print_string(struct ndr_print *ndr, const char *name, const char *s) 426{ 427 if (s) { 428 ndr->print(ndr, "%-25s: '%s'", name, s); 429 } else { 430 ndr->print(ndr, "%-25s: NULL", name); 431 } 432} 433 434_PUBLIC_ uint32_t ndr_size_string(int ret, const char * const* string, int flags) 435{ 436 /* FIXME: Is this correct for all strings ? */ 437 if(!(*string)) return ret; 438 return ret+strlen(*string)+1; 439} 440 441/** 442 pull a general string array from the wire 443*/ 444_PUBLIC_ enum ndr_err_code ndr_pull_string_array(struct ndr_pull *ndr, int ndr_flags, const char ***_a) 445{ 446 const char **a = NULL; 447 uint32_t count; 448 unsigned flags = ndr->flags; 449 unsigned saved_flags = ndr->flags; 450 451 if (!(ndr_flags & NDR_SCALARS)) { 452 return NDR_ERR_SUCCESS; 453 } 454 455 switch (flags & LIBNDR_STRING_FLAGS) { 456 case LIBNDR_FLAG_STR_NULLTERM: 457 /* 458 * here the strings are null terminated 459 * but also the array is null terminated 460 */ 461 for (count = 0;; count++) { 462 TALLOC_CTX *tmp_ctx; 463 const char *s = NULL; 464 a = talloc_realloc(ndr->current_mem_ctx, a, const char *, count + 2); 465 NDR_ERR_HAVE_NO_MEMORY(a); 466 a[count] = NULL; 467 a[count+1] = NULL; 468 469 tmp_ctx = ndr->current_mem_ctx; 470 ndr->current_mem_ctx = a; 471 NDR_CHECK(ndr_pull_string(ndr, ndr_flags, &s)); 472 ndr->current_mem_ctx = tmp_ctx; 473 if (strcmp("", s)==0) { 474 a[count] = NULL; 475 break; 476 } else { 477 a[count] = s; 478 } 479 } 480 481 *_a =a; 482 break; 483 484 case LIBNDR_FLAG_STR_NOTERM: 485 if (!(ndr->flags & LIBNDR_FLAG_REMAINING)) { 486 return ndr_pull_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%x (missing NDR_REMAINING)\n", 487 ndr->flags & LIBNDR_STRING_FLAGS); 488 } 489 /* 490 * here the strings are not null terminated 491 * but serarated by a null terminator 492 * 493 * which means the same as: 494 * very string is null terminated exept the last 495 * string is terminated by the end of the buffer 496 * 497 * as LIBNDR_FLAG_STR_NULLTERM also end at the end 498 * of the buffer, we can pull each string with this flag 499 */ 500 ndr->flags &= ~(LIBNDR_FLAG_STR_NOTERM|LIBNDR_FLAG_REMAINING); 501 ndr->flags |= LIBNDR_FLAG_STR_NULLTERM; 502 503 for (count = 0; ((ndr->data_size - ndr->offset) > 0); count++) { 504 TALLOC_CTX *tmp_ctx; 505 const char *s = NULL; 506 a = talloc_realloc(ndr->current_mem_ctx, a, const char *, count + 2); 507 NDR_ERR_HAVE_NO_MEMORY(a); 508 a[count] = NULL; 509 a[count+1] = NULL; 510 511 tmp_ctx = ndr->current_mem_ctx; 512 ndr->current_mem_ctx = a; 513 NDR_CHECK(ndr_pull_string(ndr, ndr_flags, &s)); 514 ndr->current_mem_ctx = tmp_ctx; 515 a[count] = s; 516 } 517 518 *_a =a; 519 break; 520 521 default: 522 return ndr_pull_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%x\n", 523 ndr->flags & LIBNDR_STRING_FLAGS); 524 } 525 526 ndr->flags = saved_flags; 527 return NDR_ERR_SUCCESS; 528} 529 530/** 531 push a general string array onto the wire 532*/ 533_PUBLIC_ enum ndr_err_code ndr_push_string_array(struct ndr_push *ndr, int ndr_flags, const char **a) 534{ 535 uint32_t count; 536 unsigned flags = ndr->flags; 537 unsigned saved_flags = ndr->flags; 538 539 if (!(ndr_flags & NDR_SCALARS)) { 540 return NDR_ERR_SUCCESS; 541 } 542 543 switch (flags & LIBNDR_STRING_FLAGS) { 544 case LIBNDR_FLAG_STR_NULLTERM: 545 for (count = 0; a && a[count]; count++) { 546 NDR_CHECK(ndr_push_string(ndr, ndr_flags, a[count])); 547 } 548 549 NDR_CHECK(ndr_push_string(ndr, ndr_flags, "")); 550 break; 551 552 case LIBNDR_FLAG_STR_NOTERM: 553 if (!(ndr->flags & LIBNDR_FLAG_REMAINING)) { 554 return ndr_push_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%x (missing NDR_REMAINING)\n", 555 ndr->flags & LIBNDR_STRING_FLAGS); 556 } 557 558 for (count = 0; a && a[count]; count++) { 559 if (count > 0) { 560 ndr->flags &= ~(LIBNDR_FLAG_STR_NOTERM|LIBNDR_FLAG_REMAINING); 561 ndr->flags |= LIBNDR_FLAG_STR_NULLTERM; 562 NDR_CHECK(ndr_push_string(ndr, ndr_flags, "")); 563 ndr->flags = saved_flags; 564 } 565 NDR_CHECK(ndr_push_string(ndr, ndr_flags, a[count])); 566 } 567 568 break; 569 570 default: 571 return ndr_push_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%x\n", 572 ndr->flags & LIBNDR_STRING_FLAGS); 573 } 574 575 ndr->flags = saved_flags; 576 return NDR_ERR_SUCCESS; 577} 578 579_PUBLIC_ void ndr_print_string_array(struct ndr_print *ndr, const char *name, const char **a) 580{ 581 uint32_t count; 582 uint32_t i; 583 584 for (count = 0; a && a[count]; count++) {} 585 586 ndr->print(ndr, "%s: ARRAY(%d)", name, count); 587 ndr->depth++; 588 for (i=0;i<count;i++) { 589 char *idx=NULL; 590 if (asprintf(&idx, "[%d]", i) != -1) { 591 ndr_print_string(ndr, idx, a[i]); 592 free(idx); 593 } 594 } 595 ndr->depth--; 596} 597 598_PUBLIC_ size_t ndr_size_string_array(const char **a, uint32_t count, int flags) 599{ 600 uint32_t i; 601 size_t size = 0; 602 603 switch (flags & LIBNDR_STRING_FLAGS) { 604 case LIBNDR_FLAG_STR_NULLTERM: 605 for (i = 0; i < count; i++) { 606 size += strlen_m_term(a[i]); 607 } 608 break; 609 case LIBNDR_FLAG_STR_NOTERM: 610 for (i = 0; i < count; i++) { 611 size += strlen_m(a[i]); 612 } 613 break; 614 default: 615 return 0; 616 } 617 618 return size; 619} 620 621/** 622 * Return number of elements in a string including the last (zeroed) element 623 */ 624_PUBLIC_ uint32_t ndr_string_length(const void *_var, uint32_t element_size) 625{ 626 uint32_t i; 627 uint8_t zero[4] = {0,0,0,0}; 628 const char *var = (const char *)_var; 629 630 for (i = 0; memcmp(var+i*element_size,zero,element_size) != 0; i++); 631 632 return i+1; 633} 634 635_PUBLIC_ enum ndr_err_code ndr_check_string_terminator(struct ndr_pull *ndr, uint32_t count, uint32_t element_size) 636{ 637 uint32_t i; 638 uint32_t save_offset; 639 640 save_offset = ndr->offset; 641 ndr_pull_advance(ndr, (count - 1) * element_size); 642 NDR_PULL_NEED_BYTES(ndr, element_size); 643 644 for (i = 0; i < element_size; i++) { 645 if (ndr->data[ndr->offset+i] != 0) { 646 ndr->offset = save_offset; 647 648 return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "String terminator not present or outside string boundaries"); 649 } 650 } 651 652 ndr->offset = save_offset; 653 654 return NDR_ERR_SUCCESS; 655} 656 657_PUBLIC_ enum ndr_err_code ndr_pull_charset(struct ndr_pull *ndr, int ndr_flags, const char **var, uint32_t length, uint8_t byte_mul, charset_t chset) 658{ 659 size_t converted_size; 660 661 if (length == 0) { 662 *var = talloc_strdup(ndr->current_mem_ctx, ""); 663 return NDR_ERR_SUCCESS; 664 } 665 666 if (NDR_BE(ndr) && chset == CH_UTF16) { 667 chset = CH_UTF16BE; 668 } 669 670 NDR_PULL_NEED_BYTES(ndr, length*byte_mul); 671 672 if (!convert_string_talloc(ndr->current_mem_ctx, chset, CH_UNIX, 673 ndr->data+ndr->offset, length*byte_mul, 674 discard_const_p(void *, var), 675 &converted_size, false)) 676 { 677 return ndr_pull_error(ndr, NDR_ERR_CHARCNV, 678 "Bad character conversion"); 679 } 680 NDR_CHECK(ndr_pull_advance(ndr, length*byte_mul)); 681 682 return NDR_ERR_SUCCESS; 683} 684 685_PUBLIC_ enum ndr_err_code ndr_push_charset(struct ndr_push *ndr, int ndr_flags, const char *var, uint32_t length, uint8_t byte_mul, charset_t chset) 686{ 687 ssize_t ret, required; 688 689 if (NDR_BE(ndr) && chset == CH_UTF16) { 690 chset = CH_UTF16BE; 691 } 692 693 required = byte_mul * length; 694 695 NDR_PUSH_NEED_BYTES(ndr, required); 696 ret = convert_string(CH_UNIX, chset, 697 var, strlen(var), 698 ndr->data+ndr->offset, required, false); 699 if (ret == -1) { 700 return ndr_push_error(ndr, NDR_ERR_CHARCNV, 701 "Bad character conversion"); 702 } 703 704 /* Make sure the remaining part of the string is filled with zeroes */ 705 if (ret < required) { 706 memset(ndr->data+ndr->offset+ret, 0, required-ret); 707 } 708 709 ndr->offset += required; 710 711 return NDR_ERR_SUCCESS; 712} 713 714/* Return number of elements in a string in the specified charset */ 715_PUBLIC_ uint32_t ndr_charset_length(const void *var, charset_t chset) 716{ 717 switch (chset) { 718 /* case CH_UTF16: this has the same value as CH_UTF16LE */ 719 case CH_UTF16LE: 720 case CH_UTF16BE: 721 case CH_UTF16MUNGED: 722 case CH_UTF8: 723 return strlen_m_ext_term((const char *)var, chset); 724 case CH_DISPLAY: 725 case CH_DOS: 726 case CH_UNIX: 727 return strlen((const char *)var)+1; 728 } 729 730 /* Fallback, this should never happen */ 731 return strlen((const char *)var)+1; 732} 733