00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "includes.h"
00024
00025
00026
00027
00028 NTSTATUS ndr_pull_string(struct ndr_pull *ndr, int ndr_flags, const char **s)
00029 {
00030 char *as=NULL;
00031 uint32_t len1, ofs, len2;
00032 uint16_t len3;
00033 int ret;
00034 charset_t chset = CH_UTF16LE;
00035 unsigned byte_mul = 2;
00036 unsigned flags = ndr->flags;
00037 unsigned c_len_term = 0;
00038
00039 if (!(ndr_flags & NDR_SCALARS)) {
00040 return NT_STATUS_OK;
00041 }
00042
00043 if (NDR_BE(ndr)) {
00044 chset = CH_UTF16BE;
00045 }
00046
00047 if (flags & LIBNDR_FLAG_STR_ASCII) {
00048 chset = CH_DOS;
00049 byte_mul = 1;
00050 flags &= ~LIBNDR_FLAG_STR_ASCII;
00051 }
00052
00053 if (flags & LIBNDR_FLAG_STR_UTF8) {
00054 chset = CH_UTF8;
00055 byte_mul = 1;
00056 flags &= ~LIBNDR_FLAG_STR_UTF8;
00057 }
00058
00059 flags &= ~LIBNDR_FLAG_STR_CONFORMANT;
00060 if (flags & LIBNDR_FLAG_STR_CHARLEN) {
00061 c_len_term = 1;
00062 flags &= ~LIBNDR_FLAG_STR_CHARLEN;
00063 }
00064
00065 switch (flags & LIBNDR_STRING_FLAGS) {
00066 case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4:
00067 case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4|LIBNDR_FLAG_STR_NOTERM:
00068 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &len1));
00069 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &ofs));
00070 if (ofs != 0) {
00071 return ndr_pull_error(ndr, NDR_ERR_STRING, "non-zero array offset with string flags 0x%x\n",
00072 ndr->flags & LIBNDR_STRING_FLAGS);
00073 }
00074 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &len2));
00075 if (len2 > len1) {
00076 return ndr_pull_error(ndr, NDR_ERR_STRING,
00077 "Bad string lengths len1=%u ofs=%u len2=%u\n",
00078 len1, ofs, len2);
00079 }
00080 NDR_PULL_NEED_BYTES(ndr, (len2 + c_len_term)*byte_mul);
00081 if (len2 == 0) {
00082 as = talloc_strdup(ndr->current_mem_ctx, "");
00083 } else {
00084 ret = convert_string_talloc(ndr->current_mem_ctx,
00085 chset, CH_UNIX,
00086 ndr->data+ndr->offset,
00087 (len2 + c_len_term)*byte_mul,
00088 &as, True);
00089 if (ret == -1) {
00090 return ndr_pull_error(ndr, NDR_ERR_CHARCNV,
00091 "Bad character conversion");
00092 }
00093 }
00094 NDR_CHECK(ndr_pull_advance(ndr, (len2 + c_len_term)*byte_mul));
00095
00096 if (len1 != len2) {
00097 DEBUG(6,("len1[%u] != len2[%u] '%s'\n", len1, len2, as));
00098 }
00099
00100
00101
00102 if (ndr->flags & LIBNDR_FLAG_STR_NOTERM) {
00103 if (strlen(as) < (len2 + c_len_term)) {
00104 DEBUG(6,("short string '%s'\n", as));
00105 }
00106 } else {
00107 if (strlen(as) == (len2 + c_len_term)) {
00108 DEBUG(6,("long string '%s'\n", as));
00109 }
00110 }
00111 *s = as;
00112 break;
00113
00114 case LIBNDR_FLAG_STR_SIZE4:
00115 case LIBNDR_FLAG_STR_SIZE4|LIBNDR_FLAG_STR_NOTERM:
00116 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &len1));
00117 NDR_PULL_NEED_BYTES(ndr, (len1 + c_len_term)*byte_mul);
00118 if (len1 == 0) {
00119 as = talloc_strdup(ndr->current_mem_ctx, "");
00120 } else {
00121 ret = convert_string_talloc(ndr->current_mem_ctx,
00122 chset, CH_UNIX,
00123 ndr->data+ndr->offset,
00124 (len1 + c_len_term)*byte_mul,
00125 &as, False);
00126 if (ret == -1) {
00127 return ndr_pull_error(ndr, NDR_ERR_CHARCNV,
00128 "Bad character conversion");
00129 }
00130 }
00131 NDR_CHECK(ndr_pull_advance(ndr, (len1 + c_len_term)*byte_mul));
00132
00133
00134
00135 if (ndr->flags & LIBNDR_FLAG_STR_NOTERM) {
00136 if (strlen(as) < (len1 + c_len_term)) {
00137 DEBUG(6,("short string '%s'\n", as));
00138 }
00139 } else {
00140 if (strlen(as) == (len1 + c_len_term)) {
00141 DEBUG(6,("long string '%s'\n", as));
00142 }
00143 }
00144 *s = as;
00145 break;
00146
00147 case LIBNDR_FLAG_STR_LEN4:
00148 case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_NOTERM:
00149 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &ofs));
00150 if (ofs != 0) {
00151 return ndr_pull_error(ndr, NDR_ERR_STRING, "non-zero array offset with string flags 0x%x\n",
00152 ndr->flags & LIBNDR_STRING_FLAGS);
00153 }
00154 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &len1));
00155 NDR_PULL_NEED_BYTES(ndr, (len1 + c_len_term)*byte_mul);
00156 if (len1 == 0) {
00157 as = talloc_strdup(ndr->current_mem_ctx, "");
00158 } else {
00159 ret = convert_string_talloc(ndr->current_mem_ctx,
00160 chset, CH_UNIX,
00161 ndr->data+ndr->offset,
00162 (len1 + c_len_term)*byte_mul,
00163 &as, False);
00164 if (ret == -1) {
00165 return ndr_pull_error(ndr, NDR_ERR_CHARCNV,
00166 "Bad character conversion");
00167 }
00168 }
00169 NDR_CHECK(ndr_pull_advance(ndr, (len1 + c_len_term)*byte_mul));
00170
00171
00172
00173 if (ndr->flags & LIBNDR_FLAG_STR_NOTERM) {
00174 if (strlen(as) < (len1 + c_len_term)) {
00175 DEBUG(6,("short string '%s'\n", as));
00176 }
00177 } else {
00178 if (strlen(as) == (len1 + c_len_term)) {
00179 DEBUG(6,("long string '%s'\n", as));
00180 }
00181 }
00182 *s = as;
00183 break;
00184
00185
00186 case LIBNDR_FLAG_STR_SIZE2:
00187 case LIBNDR_FLAG_STR_SIZE2|LIBNDR_FLAG_STR_NOTERM:
00188 NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &len3));
00189 NDR_PULL_NEED_BYTES(ndr, (len3 + c_len_term)*byte_mul);
00190 if (len3 == 0) {
00191 as = talloc_strdup(ndr->current_mem_ctx, "");
00192 } else {
00193 ret = convert_string_talloc(ndr->current_mem_ctx,
00194 chset, CH_UNIX,
00195 ndr->data+ndr->offset,
00196 (len3 + c_len_term)*byte_mul,
00197 &as, False);
00198 if (ret == -1) {
00199 return ndr_pull_error(ndr, NDR_ERR_CHARCNV,
00200 "Bad character conversion");
00201 }
00202 }
00203 NDR_CHECK(ndr_pull_advance(ndr, (len3 + c_len_term)*byte_mul));
00204
00205
00206
00207 if (ndr->flags & LIBNDR_FLAG_STR_NOTERM) {
00208 if (strlen(as) < (len3 + c_len_term)) {
00209 DEBUG(6,("short string '%s'\n", as));
00210 }
00211 } else {
00212 if (strlen(as) == (len3 + c_len_term)) {
00213 DEBUG(6,("long string '%s'\n", as));
00214 }
00215 }
00216 *s = as;
00217 break;
00218
00219 case LIBNDR_FLAG_STR_SIZE2|LIBNDR_FLAG_STR_NOTERM|LIBNDR_FLAG_STR_BYTESIZE:
00220 NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &len3));
00221 NDR_PULL_NEED_BYTES(ndr, len3);
00222 if (len3 == 0) {
00223 as = talloc_strdup(ndr->current_mem_ctx, "");
00224 } else {
00225 ret = convert_string_talloc(ndr->current_mem_ctx,
00226 chset, CH_UNIX,
00227 ndr->data+ndr->offset,
00228 len3, &as, False);
00229 if (ret == -1) {
00230 return ndr_pull_error(ndr, NDR_ERR_CHARCNV,
00231 "Bad character conversion");
00232 }
00233 }
00234 NDR_CHECK(ndr_pull_advance(ndr, len3));
00235 *s = as;
00236 break;
00237
00238 case LIBNDR_FLAG_STR_NULLTERM:
00239 if (byte_mul == 1) {
00240 len1 = ascii_len_n((const char *)(ndr->data+ndr->offset), ndr->data_size - ndr->offset);
00241 } else {
00242 len1 = utf16_len_n(ndr->data+ndr->offset, ndr->data_size - ndr->offset);
00243 }
00244 ret = convert_string_talloc(ndr->current_mem_ctx,
00245 chset, CH_UNIX,
00246 ndr->data+ndr->offset,
00247 len1, &as, False);
00248 if (ret == -1) {
00249 return ndr_pull_error(ndr, NDR_ERR_CHARCNV,
00250 "Bad character conversion");
00251 }
00252 NDR_CHECK(ndr_pull_advance(ndr, len1));
00253 *s = as;
00254 break;
00255
00256 case LIBNDR_FLAG_STR_FIXLEN15:
00257 case LIBNDR_FLAG_STR_FIXLEN32:
00258 len1 = (flags & LIBNDR_FLAG_STR_FIXLEN32)?32:15;
00259 NDR_PULL_NEED_BYTES(ndr, len1*byte_mul);
00260 ret = convert_string_talloc(ndr->current_mem_ctx,
00261 chset, CH_UNIX,
00262 ndr->data+ndr->offset,
00263 len1*byte_mul, &as, False);
00264 if (ret == -1) {
00265 return ndr_pull_error(ndr, NDR_ERR_CHARCNV,
00266 "Bad character conversion");
00267 }
00268 NDR_CHECK(ndr_pull_advance(ndr, len1*byte_mul));
00269 *s = as;
00270 break;
00271
00272 default:
00273 return ndr_pull_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%x\n",
00274 ndr->flags & LIBNDR_STRING_FLAGS);
00275 }
00276
00277 return NT_STATUS_OK;
00278 }
00279
00280
00281
00282
00283
00284 NTSTATUS ndr_push_string(struct ndr_push *ndr, int ndr_flags, const char *s)
00285 {
00286 ssize_t s_len, c_len, d_len;
00287 charset_t chset = CH_UTF16LE;
00288 unsigned flags = ndr->flags;
00289 unsigned byte_mul = 2;
00290 uint8_t *dest = NULL;
00291
00292 if (!(ndr_flags & NDR_SCALARS)) {
00293 return NT_STATUS_OK;
00294 }
00295
00296 if (NDR_BE(ndr)) {
00297 chset = CH_UTF16BE;
00298 }
00299
00300 s_len = s?strlen(s):0;
00301
00302 if (flags & LIBNDR_FLAG_STR_ASCII) {
00303 chset = CH_DOS;
00304 byte_mul = 1;
00305 flags &= ~LIBNDR_FLAG_STR_ASCII;
00306 }
00307
00308 if (flags & LIBNDR_FLAG_STR_UTF8) {
00309 chset = CH_UTF8;
00310 byte_mul = 1;
00311 flags &= ~LIBNDR_FLAG_STR_UTF8;
00312 }
00313
00314 flags &= ~LIBNDR_FLAG_STR_CONFORMANT;
00315
00316 if (!(flags &
00317 (LIBNDR_FLAG_STR_NOTERM |
00318 LIBNDR_FLAG_STR_FIXLEN15 |
00319 LIBNDR_FLAG_STR_FIXLEN32))) {
00320 s_len++;
00321 }
00322 d_len = convert_string_talloc(ndr, CH_UNIX, chset, s, s_len, &dest,
00323 False);
00324 if (d_len == -1) {
00325 return ndr_push_error(ndr, NDR_ERR_CHARCNV,
00326 "Bad character conversion");
00327 }
00328
00329 if (flags & LIBNDR_FLAG_STR_BYTESIZE) {
00330 c_len = d_len;
00331 flags &= ~LIBNDR_FLAG_STR_BYTESIZE;
00332 } else if (flags & LIBNDR_FLAG_STR_CHARLEN) {
00333 c_len = (d_len / byte_mul)-1;
00334 flags &= ~LIBNDR_FLAG_STR_CHARLEN;
00335 } else {
00336 c_len = d_len / byte_mul;
00337 }
00338
00339 switch ((flags & LIBNDR_STRING_FLAGS) & ~LIBNDR_FLAG_STR_NOTERM) {
00340 case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4:
00341 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, c_len));
00342 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
00343 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, c_len));
00344 NDR_CHECK(ndr_push_bytes(ndr, dest, d_len));
00345 break;
00346
00347 case LIBNDR_FLAG_STR_LEN4:
00348 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
00349 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, c_len));
00350 NDR_CHECK(ndr_push_bytes(ndr, dest, d_len));
00351 break;
00352
00353 case LIBNDR_FLAG_STR_SIZE4:
00354 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, c_len));
00355 NDR_CHECK(ndr_push_bytes(ndr, dest, d_len));
00356 break;
00357
00358 case LIBNDR_FLAG_STR_SIZE2:
00359 NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, c_len));
00360 NDR_CHECK(ndr_push_bytes(ndr, dest, d_len));
00361 break;
00362
00363 case LIBNDR_FLAG_STR_NULLTERM:
00364 NDR_CHECK(ndr_push_bytes(ndr, dest, d_len));
00365 break;
00366
00367 case LIBNDR_FLAG_STR_FIXLEN15:
00368 case LIBNDR_FLAG_STR_FIXLEN32: {
00369 ssize_t fix_len = (flags & LIBNDR_FLAG_STR_FIXLEN32)?32:15;
00370 uint32_t pad_len = fix_len - d_len;
00371 if (d_len > fix_len) {
00372 return ndr_push_error(ndr, NDR_ERR_CHARCNV,
00373 "Bad character conversion");
00374 }
00375 NDR_CHECK(ndr_push_bytes(ndr, dest, d_len));
00376 if (pad_len != 0) {
00377 NDR_CHECK(ndr_push_zero(ndr, pad_len));
00378 }
00379 break;
00380 }
00381
00382 default:
00383 return ndr_push_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%x\n",
00384 ndr->flags & LIBNDR_STRING_FLAGS);
00385 }
00386
00387 talloc_free(dest);
00388
00389 return NT_STATUS_OK;
00390 }
00391
00392
00393
00394
00395 size_t ndr_string_array_size(struct ndr_push *ndr, const char *s)
00396 {
00397 size_t c_len;
00398 unsigned flags = ndr->flags;
00399 unsigned byte_mul = 2;
00400 unsigned c_len_term = 1;
00401
00402 if (flags & LIBNDR_FLAG_STR_FIXLEN32) {
00403 return 32;
00404 }
00405 if (flags & LIBNDR_FLAG_STR_FIXLEN15) {
00406 return 15;
00407 }
00408
00409 c_len = s?strlen(s):0;
00410
00411 if (flags & (LIBNDR_FLAG_STR_ASCII|LIBNDR_FLAG_STR_UTF8)) {
00412 byte_mul = 1;
00413 }
00414
00415 if (flags & LIBNDR_FLAG_STR_NOTERM) {
00416 c_len_term = 0;
00417 }
00418
00419 c_len = c_len + c_len_term;
00420
00421 if (flags & LIBNDR_FLAG_STR_BYTESIZE) {
00422 c_len = c_len * byte_mul;
00423 }
00424
00425 return c_len;
00426 }
00427
00428 void ndr_print_string(struct ndr_print *ndr, const char *name, const char *s)
00429 {
00430 if (s) {
00431 ndr->print(ndr, "%-25s: '%s'", name, s);
00432 } else {
00433 ndr->print(ndr, "%-25s: NULL", name);
00434 }
00435 }
00436
00437 uint32_t ndr_size_string(int ret, const char * const* string, int flags)
00438 {
00439
00440 if(!(*string)) return ret;
00441 return ret+strlen(*string)+1;
00442 }
00443
00444
00445
00446
00447 NTSTATUS ndr_pull_string_array(struct ndr_pull *ndr, int ndr_flags, const char ***_a)
00448 {
00449 const char **a = *_a;
00450 uint32_t count;
00451
00452 if (!(ndr_flags & NDR_SCALARS)) {
00453 return NT_STATUS_OK;
00454 }
00455
00456 for (count = 0;; count++) {
00457 TALLOC_CTX *tmp_ctx;
00458 const char *s = NULL;
00459 a = talloc_realloc(ndr->current_mem_ctx, a, const char *, count + 2);
00460 NT_STATUS_HAVE_NO_MEMORY(a);
00461 a[count] = NULL;
00462 a[count+1] = NULL;
00463
00464 tmp_ctx = ndr->current_mem_ctx;
00465 ndr->current_mem_ctx = a;
00466 NDR_CHECK(ndr_pull_string(ndr, ndr_flags, &s));
00467 ndr->current_mem_ctx = tmp_ctx;
00468 if (strcmp("", s)==0) {
00469 a[count] = NULL;
00470 break;
00471 } else {
00472 a[count] = s;
00473 }
00474 }
00475
00476 *_a =a;
00477 return NT_STATUS_OK;
00478 }
00479
00480
00481
00482
00483 NTSTATUS ndr_push_string_array(struct ndr_push *ndr, int ndr_flags, const char **a)
00484 {
00485 uint32_t count;
00486
00487 if (!(ndr_flags & NDR_SCALARS)) {
00488 return NT_STATUS_OK;
00489 }
00490
00491 for (count = 0; a && a[count]; count++) {
00492 NDR_CHECK(ndr_push_string(ndr, ndr_flags, a[count]));
00493 }
00494
00495 NDR_CHECK(ndr_push_string(ndr, ndr_flags, ""));
00496
00497 return NT_STATUS_OK;
00498 }
00499
00500 void ndr_print_string_array(struct ndr_print *ndr, const char *name, const char **a)
00501 {
00502 uint32_t count;
00503 uint32_t i;
00504
00505 for (count = 0; a && a[count]; count++) {}
00506
00507 ndr->print(ndr, "%s: ARRAY(%d)", name, count);
00508 ndr->depth++;
00509 for (i=0;i<count;i++) {
00510 char *idx=NULL;
00511 asprintf(&idx, "[%d]", i);
00512 if (idx) {
00513 ndr_print_string(ndr, idx, a[i]);
00514 free(idx);
00515 }
00516 }
00517 ndr->depth--;
00518 }
00519
00520
00521
00522
00523 uint32_t ndr_string_length(const void *_var, uint32_t element_size)
00524 {
00525 uint32_t i;
00526 uint8_t zero[4] = {0,0,0,0};
00527 const char *var = (const char *)_var;
00528
00529 for (i = 0; memcmp(var+i*element_size,zero,element_size) != 0; i++);
00530
00531 return i+1;
00532 }
00533
00534 NTSTATUS ndr_check_string_terminator(struct ndr_pull *ndr, uint32_t count, uint32_t element_size)
00535 {
00536 uint32_t i;
00537 struct ndr_pull_save save_offset;
00538
00539 ndr_pull_save(ndr, &save_offset);
00540 ndr_pull_advance(ndr, (count - 1) * element_size);
00541 NDR_PULL_NEED_BYTES(ndr, element_size);
00542
00543 for (i = 0; i < element_size; i++) {
00544 if (ndr->data[ndr->offset+i] != 0) {
00545 ndr_pull_restore(ndr, &save_offset);
00546
00547 return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "String terminator not present or outside string boundaries");
00548 }
00549 }
00550
00551 ndr_pull_restore(ndr, &save_offset);
00552
00553 return NT_STATUS_OK;
00554 }
00555
00556 NTSTATUS ndr_pull_charset(struct ndr_pull *ndr, int ndr_flags, const char **var, uint32_t length, uint8_t byte_mul, charset_t chset)
00557 {
00558 int ret;
00559 if (length == 0) {
00560 *var = talloc_strdup(ndr->current_mem_ctx, "");
00561 return NT_STATUS_OK;
00562 }
00563
00564 if (NDR_BE(ndr) && chset == CH_UTF16) {
00565 chset = CH_UTF16BE;
00566 }
00567
00568 NDR_PULL_NEED_BYTES(ndr, length*byte_mul);
00569
00570 ret = convert_string_talloc(ndr->current_mem_ctx,
00571 chset, CH_UNIX,
00572 ndr->data+ndr->offset,
00573 length*byte_mul,
00574 var, False);
00575 if (ret == -1) {
00576 return ndr_pull_error(ndr, NDR_ERR_CHARCNV,
00577 "Bad character conversion");
00578 }
00579 NDR_CHECK(ndr_pull_advance(ndr, length*byte_mul));
00580
00581 return NT_STATUS_OK;
00582 }
00583
00584 NTSTATUS ndr_push_charset(struct ndr_push *ndr, int ndr_flags, const char *var,
00585 uint32_t length, uint8_t byte_mul, charset_t chset)
00586 {
00587 ssize_t ret, required;
00588
00589 if (NDR_BE(ndr) && chset == CH_UTF16) {
00590 chset = CH_UTF16BE;
00591 }
00592
00593 required = byte_mul * length;
00594
00595 NDR_PUSH_NEED_BYTES(ndr, required);
00596 ret = convert_string(CH_UNIX, chset,
00597 var, strlen(var),
00598 ndr->data+ndr->offset, required, False);
00599 if (ret == -1) {
00600 return ndr_push_error(ndr, NDR_ERR_CHARCNV,
00601 "Bad character conversion");
00602 }
00603
00604
00605 if (ret < required) {
00606 memset(ndr->data+ndr->offset+ret, 0, required-ret);
00607 }
00608
00609 ndr->offset += required;
00610
00611 return NT_STATUS_OK;
00612 }
00613
00614
00615 uint32_t ndr_charset_length(const void *var, int chset)
00616 {
00617
00618
00619 return strlen((const char *)var)+1;
00620 }