Changeset 988 for vendor/current/librpc/rpc/binding.c
- Timestamp:
- Nov 24, 2016, 1:14:11 PM (9 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
vendor/current/librpc/rpc/binding.c
r740 r988 8 8 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005 9 9 Copyright (C) Rafal Szczesniak 2006 10 Copyright (C) Stefan Metzmacher 2014 10 11 11 12 This program is free software; you can redistribute it and/or modify … … 34 35 35 36 #define MAX_PROTSEQ 10 37 38 struct dcerpc_binding { 39 enum dcerpc_transport_t transport; 40 struct GUID object; 41 const char *object_string; 42 const char *host; 43 const char *target_hostname; 44 const char *target_principal; 45 const char *endpoint; 46 const char **options; 47 uint32_t flags; 48 uint32_t assoc_group_id; 49 char assoc_group_string[11]; /* 0x3456789a + '\0' */ 50 }; 36 51 37 52 static const struct { … … 74 89 }; 75 90 76 static const struct {91 static const struct ncacn_option { 77 92 const char *name; 78 93 uint32_t flag; … … 84 99 {"ntlm", DCERPC_AUTH_NTLM}, 85 100 {"krb5", DCERPC_AUTH_KRB5}, 101 {"schannel", DCERPC_SCHANNEL}, 86 102 {"validate", DCERPC_DEBUG_VALIDATE_BOTH}, 87 103 {"print", DCERPC_DEBUG_PRINT_BOTH}, … … 89 105 {"bigendian", DCERPC_PUSH_BIGENDIAN}, 90 106 {"smb2", DCERPC_SMB2}, 91 {"hdrsign", DCERPC_HEADER_SIGNING},92 107 {"ndr64", DCERPC_NDR64}, 93 {"localaddress", DCERPC_LOCALADDRESS}94 108 }; 109 110 static const struct ncacn_option *ncacn_option_by_name(const char *name) 111 { 112 size_t i; 113 114 for (i=0; i<ARRAY_SIZE(ncacn_options); i++) { 115 int ret; 116 117 ret = strcasecmp(ncacn_options[i].name, name); 118 if (ret != 0) { 119 continue; 120 } 121 122 return &ncacn_options[i]; 123 } 124 125 return NULL; 126 } 95 127 96 128 const char *epm_floor_string(TALLOC_CTX *mem_ctx, struct epm_floor *epm_floor) … … 106 138 char *uuidstr; 107 139 108 if (GUID_equal(&syntax.uuid, &ndr_transfer_syntax .uuid)) {140 if (GUID_equal(&syntax.uuid, &ndr_transfer_syntax_ndr.uuid)) { 109 141 return "NDR"; 110 142 } 111 143 112 if (GUID_equal(&syntax.uuid, &ndr 64_transfer_syntax.uuid)) {144 if (GUID_equal(&syntax.uuid, &ndr_transfer_syntax_ndr64.uuid)) { 113 145 return "NDR64"; 114 146 } … … 179 211 { 180 212 char *s = talloc_strdup(mem_ctx, ""); 213 char *o = s; 181 214 int i; 182 215 const char *t_name = NULL; 216 bool option_section = false; 217 const char *target_hostname = NULL; 183 218 184 219 if (b->transport != NCA_UNKNOWN) { 185 220 t_name = derpc_transport_string_by_transport(b->transport); 186 221 if (!t_name) { 187 return NULL; 188 } 189 } 190 191 if (!GUID_all_zero(&b->object.uuid)) { 192 s = talloc_asprintf(s, "%s@", 193 GUID_string(mem_ctx, &b->object.uuid)); 222 talloc_free(o); 223 return NULL; 224 } 225 } 226 227 if (!GUID_all_zero(&b->object)) { 228 o = s; 229 s = talloc_asprintf_append_buffer(s, "%s@", 230 GUID_string(mem_ctx, &b->object)); 231 if (s == NULL) { 232 talloc_free(o); 233 return NULL; 234 } 194 235 } 195 236 196 237 if (t_name != NULL) { 238 o = s; 197 239 s = talloc_asprintf_append_buffer(s, "%s:", t_name); 198 240 if (s == NULL) { 241 talloc_free(o); 199 242 return NULL; 200 243 } … … 202 245 203 246 if (b->host) { 247 o = s; 204 248 s = talloc_asprintf_append_buffer(s, "%s", b->host); 205 } 206 207 if (!b->endpoint && !b->options && !b->flags) { 249 if (s == NULL) { 250 talloc_free(o); 251 return NULL; 252 } 253 } 254 255 target_hostname = b->target_hostname; 256 if (target_hostname != NULL && b->host != NULL) { 257 if (strcmp(target_hostname, b->host) == 0) { 258 target_hostname = NULL; 259 } 260 } 261 262 if (b->endpoint) { 263 option_section = true; 264 } else if (target_hostname) { 265 option_section = true; 266 } else if (b->target_principal) { 267 option_section = true; 268 } else if (b->assoc_group_id != 0) { 269 option_section = true; 270 } else if (b->options) { 271 option_section = true; 272 } else if (b->flags) { 273 option_section = true; 274 } 275 276 if (!option_section) { 208 277 return s; 209 278 } 210 279 280 o = s; 211 281 s = talloc_asprintf_append_buffer(s, "["); 282 if (s == NULL) { 283 talloc_free(o); 284 return NULL; 285 } 212 286 213 287 if (b->endpoint) { 288 o = s; 214 289 s = talloc_asprintf_append_buffer(s, "%s", b->endpoint); 215 } 216 217 /* this is a *really* inefficent way of dealing with strings, 218 but this is rarely called and the strings are always short, 219 so I don't care */ 290 if (s == NULL) { 291 talloc_free(o); 292 return NULL; 293 } 294 } 295 296 for (i=0;i<ARRAY_SIZE(ncacn_options);i++) { 297 if (!(b->flags & ncacn_options[i].flag)) { 298 continue; 299 } 300 301 o = s; 302 s = talloc_asprintf_append_buffer(s, ",%s", ncacn_options[i].name); 303 if (s == NULL) { 304 talloc_free(o); 305 return NULL; 306 } 307 } 308 309 if (target_hostname) { 310 o = s; 311 s = talloc_asprintf_append_buffer(s, ",target_hostname=%s", 312 b->target_hostname); 313 if (s == NULL) { 314 talloc_free(o); 315 return NULL; 316 } 317 } 318 319 if (b->target_principal) { 320 o = s; 321 s = talloc_asprintf_append_buffer(s, ",target_principal=%s", 322 b->target_principal); 323 if (s == NULL) { 324 talloc_free(o); 325 return NULL; 326 } 327 } 328 329 if (b->assoc_group_id != 0) { 330 o = s; 331 s = talloc_asprintf_append_buffer(s, ",assoc_group_id=0x%08x", 332 b->assoc_group_id); 333 if (s == NULL) { 334 talloc_free(o); 335 return NULL; 336 } 337 } 338 220 339 for (i=0;b->options && b->options[i];i++) { 340 o = s; 221 341 s = talloc_asprintf_append_buffer(s, ",%s", b->options[i]); 222 if (!s) return NULL; 223 } 224 225 for (i=0;i<ARRAY_SIZE(ncacn_options);i++) { 226 if (b->flags & ncacn_options[i].flag) { 227 if (ncacn_options[i].flag == DCERPC_LOCALADDRESS && b->localaddress) { 228 s = talloc_asprintf_append_buffer(s, ",%s=%s", ncacn_options[i].name, 229 b->localaddress); 230 } else { 231 s = talloc_asprintf_append_buffer(s, ",%s", ncacn_options[i].name); 232 } 233 if (!s) return NULL; 234 } 235 } 236 342 if (s == NULL) { 343 talloc_free(o); 344 return NULL; 345 } 346 } 347 348 o = s; 237 349 s = talloc_asprintf_append_buffer(s, "]"); 350 if (s == NULL) { 351 talloc_free(o); 352 return NULL; 353 } 238 354 239 355 return s; … … 243 359 parse a binding string into a dcerpc_binding structure 244 360 */ 245 _PUBLIC_ NTSTATUS dcerpc_parse_binding(TALLOC_CTX *mem_ctx, const char *s, struct dcerpc_binding **b_out) 246 { 361 _PUBLIC_ NTSTATUS dcerpc_parse_binding(TALLOC_CTX *mem_ctx, const char *_s, struct dcerpc_binding **b_out) 362 { 363 char *_t; 247 364 struct dcerpc_binding *b; 248 char *options; 365 char *s; 366 char *options = NULL; 249 367 char *p; 250 int i, j, comma_count; 368 size_t i; 369 NTSTATUS status; 251 370 252 371 b = talloc_zero(mem_ctx, struct dcerpc_binding); … … 255 374 } 256 375 376 _t = talloc_strdup(b, _s); 377 if (_t == NULL) { 378 talloc_free(b); 379 return NT_STATUS_NO_MEMORY; 380 } 381 382 s = _t; 383 384 p = strchr(s, '['); 385 if (p) { 386 *p = '\0'; 387 options = p + 1; 388 if (options[strlen(options)-1] != ']') { 389 talloc_free(b); 390 return NT_STATUS_INVALID_PARAMETER_MIX; 391 } 392 options[strlen(options)-1] = 0; 393 } 394 257 395 p = strchr(s, '@'); 258 396 259 397 if (p && PTR_DIFF(p, s) == 36) { /* 36 is the length of a UUID */ 260 NTSTATUS status; 261 DATA_BLOB blob = data_blob(s, 36); 262 status = GUID_from_data_blob(&blob, &b->object.uuid); 263 264 if (NT_STATUS_IS_ERR(status)) { 265 DEBUG(0, ("Failed parsing UUID\n")); 398 *p = '\0'; 399 400 status = dcerpc_binding_set_string_option(b, "object", s); 401 if (!NT_STATUS_IS_OK(status)) { 402 talloc_free(b); 266 403 return status; 267 404 } 268 405 269 406 s = p + 1; 270 } else { 271 ZERO_STRUCT(b->object); 272 } 273 274 b->object.if_version = 0; 407 } 275 408 276 409 p = strchr(s, ':'); … … 278 411 if (p == NULL) { 279 412 b->transport = NCA_UNKNOWN; 413 } else if (is_ipaddress_v6(s)) { 414 b->transport = NCA_UNKNOWN; 280 415 } else { 281 char *type = talloc_strndup(mem_ctx, s, PTR_DIFF(p, s)); 282 if (!type) { 416 *p = '\0'; 417 418 status = dcerpc_binding_set_string_option(b, "transport", s); 419 if (!NT_STATUS_IS_OK(status)) { 420 talloc_free(b); 421 return status; 422 } 423 424 s = p + 1; 425 } 426 427 if (strlen(s) > 0) { 428 status = dcerpc_binding_set_string_option(b, "host", s); 429 if (!NT_STATUS_IS_OK(status)) { 430 talloc_free(b); 431 return status; 432 } 433 434 b->target_hostname = talloc_strdup(b, b->host); 435 if (b->target_hostname == NULL) { 436 talloc_free(b); 283 437 return NT_STATUS_NO_MEMORY; 284 438 } 285 286 for (i=0;i<ARRAY_SIZE(transports);i++) { 287 if (strcasecmp(type, transports[i].name) == 0) { 288 b->transport = transports[i].transport; 289 break; 439 } 440 441 for (i=0; options != NULL; i++) { 442 const char *name = options; 443 const char *value = NULL; 444 445 p = strchr(options, ','); 446 if (p != NULL) { 447 *p = '\0'; 448 options = p+1; 449 } else { 450 options = NULL; 451 } 452 453 p = strchr(name, '='); 454 if (p != NULL) { 455 *p = '\0'; 456 value = p + 1; 457 } 458 459 if (value == NULL) { 460 /* 461 * If it's not a key=value pair 462 * it might be a ncacn_option 463 * or if it's the first option 464 * it's the endpoint. 465 */ 466 const struct ncacn_option *no = NULL; 467 468 value = name; 469 470 no = ncacn_option_by_name(name); 471 if (no == NULL) { 472 if (i > 0) { 473 /* 474 * we don't allow unknown options 475 */ 476 return NT_STATUS_INVALID_PARAMETER_MIX; 477 } 478 479 /* 480 * This is the endpoint 481 */ 482 name = "endpoint"; 483 if (strlen(value) == 0) { 484 value = NULL; 485 } 290 486 } 291 487 } 292 488 293 if (i==ARRAY_SIZE(transports)) { 294 DEBUG(0,("Unknown dcerpc transport '%s'\n", type)); 295 return NT_STATUS_INVALID_PARAMETER; 296 } 297 298 talloc_free(type); 299 300 s = p+1; 301 } 302 303 p = strchr(s, '['); 304 if (p) { 305 b->host = talloc_strndup(b, s, PTR_DIFF(p, s)); 306 options = talloc_strdup(mem_ctx, p+1); 307 if (options[strlen(options)-1] != ']') { 308 return NT_STATUS_INVALID_PARAMETER; 309 } 310 options[strlen(options)-1] = 0; 489 status = dcerpc_binding_set_string_option(b, name, value); 490 if (!NT_STATUS_IS_OK(status)) { 491 talloc_free(b); 492 return status; 493 } 494 } 495 496 talloc_free(_t); 497 *b_out = b; 498 return NT_STATUS_OK; 499 } 500 501 _PUBLIC_ struct GUID dcerpc_binding_get_object(const struct dcerpc_binding *b) 502 { 503 return b->object; 504 } 505 506 _PUBLIC_ NTSTATUS dcerpc_binding_set_object(struct dcerpc_binding *b, 507 struct GUID object) 508 { 509 char *tmp = discard_const_p(char, b->object_string); 510 511 if (GUID_all_zero(&object)) { 512 talloc_free(tmp); 513 b->object_string = NULL; 514 ZERO_STRUCT(b->object); 515 return NT_STATUS_OK; 516 } 517 518 b->object_string = GUID_string(b, &object); 519 if (b->object_string == NULL) { 520 b->object_string = tmp; 521 return NT_STATUS_NO_MEMORY; 522 } 523 talloc_free(tmp); 524 525 b->object = object; 526 return NT_STATUS_OK; 527 } 528 529 _PUBLIC_ enum dcerpc_transport_t dcerpc_binding_get_transport(const struct dcerpc_binding *b) 530 { 531 return b->transport; 532 } 533 534 _PUBLIC_ NTSTATUS dcerpc_binding_set_transport(struct dcerpc_binding *b, 535 enum dcerpc_transport_t transport) 536 { 537 NTSTATUS status; 538 539 /* 540 * TODO: we may want to check the transport value is 541 * wellknown. 542 */ 543 if (b->transport == transport) { 544 return NT_STATUS_OK; 545 } 546 547 /* 548 * This implicitly resets the endpoint 549 * as the endpoint is transport specific. 550 * 551 * It also resets the assoc group as it's 552 * also endpoint specific. 553 * 554 * TODO: in future we may reset more options 555 * here. 556 */ 557 status = dcerpc_binding_set_string_option(b, "endpoint", NULL); 558 if (!NT_STATUS_IS_OK(status)) { 559 return status; 560 } 561 562 b->assoc_group_id = 0; 563 564 b->transport = transport; 565 return NT_STATUS_OK; 566 } 567 568 _PUBLIC_ void dcerpc_binding_get_auth_info(const struct dcerpc_binding *b, 569 enum dcerpc_AuthType *_auth_type, 570 enum dcerpc_AuthLevel *_auth_level) 571 { 572 enum dcerpc_AuthType auth_type; 573 enum dcerpc_AuthLevel auth_level; 574 575 if (b->flags & DCERPC_AUTH_SPNEGO) { 576 auth_type = DCERPC_AUTH_TYPE_SPNEGO; 577 } else if (b->flags & DCERPC_AUTH_KRB5) { 578 auth_type = DCERPC_AUTH_TYPE_KRB5; 579 } else if (b->flags & DCERPC_SCHANNEL) { 580 auth_type = DCERPC_AUTH_TYPE_SCHANNEL; 581 } else if (b->flags & DCERPC_AUTH_NTLM) { 582 auth_type = DCERPC_AUTH_TYPE_NTLMSSP; 311 583 } else { 312 b->host = talloc_strdup(b, s); 313 options = NULL; 314 } 315 if (!b->host) { 584 auth_type = DCERPC_AUTH_TYPE_NONE; 585 } 586 587 if (b->flags & DCERPC_SEAL) { 588 auth_level = DCERPC_AUTH_LEVEL_PRIVACY; 589 } else if (b->flags & DCERPC_SIGN) { 590 auth_level = DCERPC_AUTH_LEVEL_INTEGRITY; 591 } else if (b->flags & DCERPC_CONNECT) { 592 auth_level = DCERPC_AUTH_LEVEL_CONNECT; 593 } else if (auth_type != DCERPC_AUTH_TYPE_NONE) { 594 auth_level = DCERPC_AUTH_LEVEL_INTEGRITY; 595 } else { 596 auth_level = DCERPC_AUTH_LEVEL_NONE; 597 } 598 599 if (_auth_type != NULL) { 600 *_auth_type = auth_type; 601 } 602 603 if (_auth_level != NULL) { 604 *_auth_level = auth_level; 605 } 606 } 607 608 _PUBLIC_ uint32_t dcerpc_binding_get_assoc_group_id(const struct dcerpc_binding *b) 609 { 610 return b->assoc_group_id; 611 } 612 613 _PUBLIC_ NTSTATUS dcerpc_binding_set_assoc_group_id(struct dcerpc_binding *b, 614 uint32_t assoc_group_id) 615 { 616 b->assoc_group_id = assoc_group_id; 617 return NT_STATUS_OK; 618 } 619 620 _PUBLIC_ struct ndr_syntax_id dcerpc_binding_get_abstract_syntax(const struct dcerpc_binding *b) 621 { 622 const char *s = dcerpc_binding_get_string_option(b, "abstract_syntax"); 623 bool ok; 624 struct ndr_syntax_id id; 625 626 if (s == NULL) { 627 return ndr_syntax_id_null; 628 } 629 630 ok = ndr_syntax_id_from_string(s, &id); 631 if (!ok) { 632 return ndr_syntax_id_null; 633 } 634 635 return id; 636 } 637 638 _PUBLIC_ NTSTATUS dcerpc_binding_set_abstract_syntax(struct dcerpc_binding *b, 639 const struct ndr_syntax_id *syntax) 640 { 641 NTSTATUS status; 642 char *s = NULL; 643 644 if (syntax == NULL) { 645 status = dcerpc_binding_set_string_option(b, "abstract_syntax", NULL); 646 if (!NT_STATUS_IS_OK(status)) { 647 return status; 648 } 649 650 return NT_STATUS_OK; 651 } 652 653 if (ndr_syntax_id_equal(&ndr_syntax_id_null, syntax)) { 654 status = dcerpc_binding_set_string_option(b, "abstract_syntax", NULL); 655 if (!NT_STATUS_IS_OK(status)) { 656 return status; 657 } 658 659 return NT_STATUS_OK; 660 } 661 662 s = ndr_syntax_id_to_string(b, syntax); 663 if (s == NULL) { 316 664 return NT_STATUS_NO_MEMORY; 317 665 } 318 666 319 b->target_hostname = b->host; 320 321 b->options = NULL; 322 b->flags = 0; 323 b->assoc_group_id = 0; 324 b->endpoint = NULL; 325 b->localaddress = NULL; 326 327 if (!options) { 328 *b_out = b; 329 return NT_STATUS_OK; 330 } 331 332 comma_count = count_chars(options, ','); 333 334 b->options = talloc_array(b, const char *, comma_count+2); 335 if (!b->options) { 667 status = dcerpc_binding_set_string_option(b, "abstract_syntax", s); 668 TALLOC_FREE(s); 669 if (!NT_STATUS_IS_OK(status)) { 670 return status; 671 } 672 673 return NT_STATUS_OK; 674 } 675 676 _PUBLIC_ const char *dcerpc_binding_get_string_option(const struct dcerpc_binding *b, 677 const char *name) 678 { 679 struct { 680 const char *name; 681 const char *value; 682 #define _SPECIAL(x) { .name = #x, .value = b->x, } 683 } specials[] = { 684 { .name = "object", .value = b->object_string, }, 685 _SPECIAL(host), 686 _SPECIAL(endpoint), 687 _SPECIAL(target_hostname), 688 _SPECIAL(target_principal), 689 #undef _SPECIAL 690 }; 691 const struct ncacn_option *no = NULL; 692 size_t name_len = strlen(name); 693 size_t i; 694 int ret; 695 696 ret = strcmp(name, "transport"); 697 if (ret == 0) { 698 return derpc_transport_string_by_transport(b->transport); 699 } 700 701 ret = strcmp(name, "assoc_group_id"); 702 if (ret == 0) { 703 char *tmp = discard_const_p(char, b->assoc_group_string); 704 705 if (b->assoc_group_id == 0) { 706 return NULL; 707 } 708 709 snprintf(tmp, sizeof(b->assoc_group_string), 710 "0x%08x", b->assoc_group_id); 711 return (const char *)b->assoc_group_string; 712 } 713 714 for (i=0; i < ARRAY_SIZE(specials); i++) { 715 ret = strcmp(specials[i].name, name); 716 if (ret != 0) { 717 continue; 718 } 719 720 return specials[i].value; 721 } 722 723 no = ncacn_option_by_name(name); 724 if (no != NULL) { 725 if (b->flags & no->flag) { 726 return no->name; 727 } 728 729 return NULL; 730 } 731 732 if (b->options == NULL) { 733 return NULL; 734 } 735 736 for (i=0; b->options[i]; i++) { 737 const char *o = b->options[i]; 738 const char *vs = NULL; 739 740 ret = strncmp(name, o, name_len); 741 if (ret != 0) { 742 continue; 743 } 744 745 if (o[name_len] != '=') { 746 continue; 747 } 748 749 vs = &o[name_len + 1]; 750 751 return vs; 752 } 753 754 return NULL; 755 } 756 757 _PUBLIC_ char *dcerpc_binding_copy_string_option(TALLOC_CTX *mem_ctx, 758 const struct dcerpc_binding *b, 759 const char *name) 760 { 761 const char *c = dcerpc_binding_get_string_option(b, name); 762 char *v; 763 764 if (c == NULL) { 765 errno = ENOENT; 766 return NULL; 767 } 768 769 v = talloc_strdup(mem_ctx, c); 770 if (v == NULL) { 771 errno = ENOMEM; 772 return NULL; 773 } 774 775 return v; 776 } 777 778 _PUBLIC_ NTSTATUS dcerpc_binding_set_string_option(struct dcerpc_binding *b, 779 const char *name, 780 const char *value) 781 { 782 struct { 783 const char *name; 784 const char **ptr; 785 #define _SPECIAL(x) { .name = #x, .ptr = &b->x, } 786 } specials[] = { 787 _SPECIAL(host), 788 _SPECIAL(endpoint), 789 _SPECIAL(target_hostname), 790 _SPECIAL(target_principal), 791 #undef _SPECIAL 792 }; 793 const struct ncacn_option *no = NULL; 794 size_t name_len = strlen(name); 795 const char *opt = NULL; 796 char *tmp; 797 size_t i; 798 int ret; 799 800 /* 801 * Note: value == NULL, means delete it. 802 * value != NULL means add or reset. 803 */ 804 805 ret = strcmp(name, "transport"); 806 if (ret == 0) { 807 enum dcerpc_transport_t t = dcerpc_transport_by_name(value); 808 809 if (t == NCA_UNKNOWN && value != NULL) { 810 return NT_STATUS_INVALID_PARAMETER_MIX; 811 } 812 813 return dcerpc_binding_set_transport(b, t); 814 } 815 816 ret = strcmp(name, "object"); 817 if (ret == 0) { 818 NTSTATUS status; 819 struct GUID uuid = GUID_zero(); 820 821 if (value != NULL) { 822 DATA_BLOB blob; 823 blob = data_blob_string_const(value); 824 if (blob.length != 36) { 825 return NT_STATUS_INVALID_PARAMETER_MIX; 826 } 827 828 status = GUID_from_data_blob(&blob, &uuid); 829 if (!NT_STATUS_IS_OK(status)) { 830 return status; 831 } 832 } 833 834 return dcerpc_binding_set_object(b, uuid); 835 } 836 837 ret = strcmp(name, "assoc_group_id"); 838 if (ret == 0) { 839 uint32_t assoc_group_id = 0; 840 841 if (value != NULL) { 842 char c; 843 844 ret = sscanf(value, "0x%08x%c", &assoc_group_id, &c); 845 if (ret != 1) { 846 return NT_STATUS_INVALID_PARAMETER_MIX; 847 } 848 } 849 850 return dcerpc_binding_set_assoc_group_id(b, assoc_group_id); 851 } 852 853 for (i=0; i < ARRAY_SIZE(specials); i++) { 854 ret = strcmp(specials[i].name, name); 855 if (ret != 0) { 856 continue; 857 } 858 859 tmp = discard_const_p(char, *specials[i].ptr); 860 861 if (value == NULL) { 862 talloc_free(tmp); 863 *specials[i].ptr = NULL; 864 return NT_STATUS_OK; 865 } 866 867 if (value[0] == '\0') { 868 return NT_STATUS_INVALID_PARAMETER_MIX; 869 } 870 871 *specials[i].ptr = talloc_strdup(b, value); 872 if (*specials[i].ptr == NULL) { 873 *specials[i].ptr = tmp; 874 return NT_STATUS_NO_MEMORY; 875 } 876 talloc_free(tmp); 877 878 return NT_STATUS_OK; 879 } 880 881 no = ncacn_option_by_name(name); 882 if (no != NULL) { 883 if (value == NULL) { 884 b->flags &= ~no->flag; 885 return NT_STATUS_OK; 886 } 887 888 ret = strcasecmp(no->name, value); 889 if (ret != 0) { 890 return NT_STATUS_INVALID_PARAMETER_MIX; 891 } 892 893 b->flags |= no->flag; 894 return NT_STATUS_OK; 895 } 896 897 for (i=0; b->options && b->options[i]; i++) { 898 const char *o = b->options[i]; 899 900 ret = strncmp(name, o, name_len); 901 if (ret != 0) { 902 continue; 903 } 904 905 if (o[name_len] != '=') { 906 continue; 907 } 908 909 opt = o; 910 break; 911 } 912 913 if (opt == NULL) { 914 const char **n; 915 916 if (value == NULL) { 917 return NT_STATUS_OK; 918 } 919 920 n = talloc_realloc(b, b->options, const char *, i + 2); 921 if (n == NULL) { 922 return NT_STATUS_NO_MEMORY; 923 } 924 n[i] = NULL; 925 n[i + 1] = NULL; 926 b->options = n; 927 } 928 929 tmp = discard_const_p(char, opt); 930 931 if (value == NULL) { 932 for (;b->options[i];i++) { 933 b->options[i] = b->options[i+1]; 934 } 935 talloc_free(tmp); 936 return NT_STATUS_OK; 937 } 938 939 b->options[i] = talloc_asprintf(b->options, "%s=%s", 940 name, value); 941 if (b->options[i] == NULL) { 942 b->options[i] = tmp; 336 943 return NT_STATUS_NO_MEMORY; 337 944 } 338 945 339 for (i=0; (p = strchr(options, ',')); i++) { 340 b->options[i] = talloc_strndup(b, options, PTR_DIFF(p, options)); 341 if (!b->options[i]) { 342 return NT_STATUS_NO_MEMORY; 343 } 344 options = p+1; 345 } 346 b->options[i] = options; 347 b->options[i+1] = NULL; 348 349 /* some options are pre-parsed for convenience */ 350 for (i=0;b->options[i];i++) { 351 for (j=0;j<ARRAY_SIZE(ncacn_options);j++) { 352 size_t opt_len = strlen(ncacn_options[j].name); 353 if (strncasecmp(ncacn_options[j].name, b->options[i], opt_len) == 0) { 354 int k; 355 char c = b->options[i][opt_len]; 356 357 if (ncacn_options[j].flag == DCERPC_LOCALADDRESS && c == '=') { 358 b->localaddress = talloc_strdup(b, &b->options[i][opt_len+1]); 359 } else if (c != 0) { 360 continue; 361 } 362 363 b->flags |= ncacn_options[j].flag; 364 for (k=i;b->options[k];k++) { 365 b->options[k] = b->options[k+1]; 366 } 367 i--; 368 break; 369 } 370 } 371 } 372 373 if (b->options[0]) { 374 /* Endpoint is first option */ 375 b->endpoint = b->options[0]; 376 if (strlen(b->endpoint) == 0) b->endpoint = NULL; 377 378 for (i=0;b->options[i];i++) { 379 b->options[i] = b->options[i+1]; 380 } 381 } 382 383 if (b->options[0] == NULL) 384 b->options = NULL; 385 386 *b_out = b; 946 return NT_STATUS_OK; 947 } 948 949 _PUBLIC_ uint32_t dcerpc_binding_get_flags(const struct dcerpc_binding *b) 950 { 951 return b->flags; 952 } 953 954 _PUBLIC_ NTSTATUS dcerpc_binding_set_flags(struct dcerpc_binding *b, 955 uint32_t additional, 956 uint32_t clear) 957 { 958 /* 959 * TODO: in future we may want to reject invalid combinations 960 */ 961 b->flags &= ~clear; 962 b->flags |= additional; 963 387 964 return NT_STATUS_OK; 388 965 } … … 425 1002 { 426 1003 DATA_BLOB blob; 427 struct ndr_push *ndr = ndr_push_init_ctx(mem_ctx); 1004 enum ndr_err_code ndr_err; 1005 struct ndr_push *ndr; 1006 1007 ndr = ndr_push_init_ctx(mem_ctx); 1008 if (ndr == NULL) { 1009 return data_blob_null; 1010 } 428 1011 429 1012 ndr->flags |= LIBNDR_FLAG_NOALIGN; 430 1013 431 ndr_push_GUID(ndr, NDR_SCALARS | NDR_BUFFERS, &syntax->uuid); 432 ndr_push_uint16(ndr, NDR_SCALARS, syntax->if_version); 1014 ndr_err = ndr_push_GUID(ndr, NDR_SCALARS | NDR_BUFFERS, &syntax->uuid); 1015 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 1016 return data_blob_null; 1017 } 1018 ndr_err = ndr_push_uint16(ndr, NDR_SCALARS, syntax->if_version); 1019 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 1020 return data_blob_null; 1021 } 433 1022 434 1023 blob = ndr_push_blob(ndr); … … 464 1053 } 465 1054 466 c onst char *dcerpc_floor_get_rhs_data(TALLOC_CTX *mem_ctx, struct epm_floor *epm_floor)1055 char *dcerpc_floor_get_rhs_data(TALLOC_CTX *mem_ctx, struct epm_floor *epm_floor) 467 1056 { 468 1057 switch (epm_floor->lhs.protocol) { … … 531 1120 const char *data) 532 1121 { 1122 if (data == NULL) { 1123 data = ""; 1124 } 1125 533 1126 switch (epm_floor->lhs.protocol) { 534 1127 case EPM_PROTOCOL_TCP: … … 545 1138 546 1139 case EPM_PROTOCOL_IP: 1140 if (!is_ipaddress_v4(data)) { 1141 data = "0.0.0.0"; 1142 } 547 1143 epm_floor->rhs.ip.ipaddr = talloc_strdup(mem_ctx, data); 548 1144 NT_STATUS_HAVE_NO_MEMORY(epm_floor->rhs.ip.ipaddr); … … 631 1227 } 632 1228 633 for (j = 0; j < transports[i].num_protocols ; j++) {1229 for (j = 0; j < transports[i].num_protocols && j < MAX_PROTSEQ; j++) { 634 1230 if (transports[i].protseq[j] != tower->floors[j+2].lhs.protocol) { 635 1231 break; … … 658 1254 } 659 1255 1256 _PUBLIC_ enum dcerpc_transport_t dcerpc_transport_by_name(const char *name) 1257 { 1258 size_t i; 1259 1260 if (name == NULL) { 1261 return NCA_UNKNOWN; 1262 } 1263 1264 for (i=0; i<ARRAY_SIZE(transports);i++) { 1265 if (strcasecmp(name, transports[i].name) == 0) { 1266 return transports[i].transport; 1267 } 1268 } 1269 1270 return NCA_UNKNOWN; 1271 } 1272 660 1273 _PUBLIC_ NTSTATUS dcerpc_binding_from_tower(TALLOC_CTX *mem_ctx, 661 1274 struct epm_tower *tower, … … 663 1276 { 664 1277 NTSTATUS status; 665 struct dcerpc_binding *binding; 1278 struct dcerpc_binding *b; 1279 enum dcerpc_transport_t transport; 1280 struct ndr_syntax_id abstract_syntax; 1281 char *endpoint = NULL; 1282 char *host = NULL; 666 1283 667 1284 /* … … 674 1291 } 675 1292 676 binding = talloc_zero(mem_ctx, struct dcerpc_binding); 677 NT_STATUS_HAVE_NO_MEMORY(binding); 678 679 ZERO_STRUCT(binding->object); 680 binding->options = NULL; 681 binding->host = NULL; 682 binding->target_hostname = NULL; 683 binding->flags = 0; 684 binding->assoc_group_id = 0; 685 686 binding->transport = dcerpc_transport_by_tower(tower); 687 688 if (binding->transport == (unsigned int)-1) { 1293 status = dcerpc_parse_binding(mem_ctx, "", &b); 1294 if (!NT_STATUS_IS_OK(status)) { 1295 return status; 1296 } 1297 1298 transport = dcerpc_transport_by_tower(tower); 1299 if (transport == NCA_UNKNOWN) { 1300 talloc_free(b); 689 1301 return NT_STATUS_NOT_SUPPORTED; 690 1302 } 691 1303 692 /* Set object uuid */ 693 status = dcerpc_floor_get_lhs_data(&tower->floors[0], &binding->object); 694 1304 status = dcerpc_binding_set_transport(b, transport); 695 1305 if (!NT_STATUS_IS_OK(status)) { 696 DEBUG(1, ("Error pulling object uuid and version: %s", nt_errstr(status)));1306 talloc_free(b); 697 1307 return status; 698 1308 } 699 1309 1310 /* Set abstract syntax */ 1311 status = dcerpc_floor_get_lhs_data(&tower->floors[0], &abstract_syntax); 1312 if (!NT_STATUS_IS_OK(status)) { 1313 talloc_free(b); 1314 return status; 1315 } 1316 1317 status = dcerpc_binding_set_abstract_syntax(b, &abstract_syntax); 1318 if (!NT_STATUS_IS_OK(status)) { 1319 talloc_free(b); 1320 return status; 1321 } 1322 700 1323 /* Ignore floor 1, it contains the NDR version info */ 701 1324 702 binding->options = NULL;703 704 1325 /* Set endpoint */ 1326 errno = 0; 705 1327 if (tower->num_floors >= 4) { 706 binding->endpoint = dcerpc_floor_get_rhs_data(binding, &tower->floors[3]); 707 } else { 708 binding->endpoint = NULL; 709 } 1328 endpoint = dcerpc_floor_get_rhs_data(b, &tower->floors[3]); 1329 } 1330 if (errno != 0) { 1331 int saved_errno = errno; 1332 talloc_free(b); 1333 return map_nt_error_from_unix_common(saved_errno); 1334 } 1335 1336 status = dcerpc_binding_set_string_option(b, "endpoint", endpoint); 1337 if (!NT_STATUS_IS_OK(status)) { 1338 talloc_free(b); 1339 return status; 1340 } 1341 TALLOC_FREE(endpoint); 710 1342 711 1343 /* Set network address */ 1344 errno = 0; 712 1345 if (tower->num_floors >= 5) { 713 binding->host = dcerpc_floor_get_rhs_data(binding, &tower->floors[4]); 714 NT_STATUS_HAVE_NO_MEMORY(binding->host); 715 binding->target_hostname = binding->host; 716 } 717 *b_out = binding; 1346 host = dcerpc_floor_get_rhs_data(b, &tower->floors[4]); 1347 } 1348 if (errno != 0) { 1349 int saved_errno = errno; 1350 talloc_free(b); 1351 return map_nt_error_from_unix_common(saved_errno); 1352 } 1353 1354 status = dcerpc_binding_set_string_option(b, "host", host); 1355 if (!NT_STATUS_IS_OK(status)) { 1356 talloc_free(b); 1357 return status; 1358 } 1359 status = dcerpc_binding_set_string_option(b, "target_hostname", host); 1360 if (!NT_STATUS_IS_OK(status)) { 1361 talloc_free(b); 1362 return status; 1363 } 1364 TALLOC_FREE(host); 1365 1366 *b_out = b; 718 1367 return NT_STATUS_OK; 719 1368 } … … 735 1384 n->assoc_group_id = b->assoc_group_id; 736 1385 1386 if (b->object_string != NULL) { 1387 n->object_string = talloc_strdup(n, b->object_string); 1388 if (n->object_string == NULL) { 1389 talloc_free(n); 1390 return NULL; 1391 } 1392 } 737 1393 if (b->host != NULL) { 738 1394 n->host = talloc_strdup(n, b->host); … … 754 1410 n->target_principal = talloc_strdup(n, b->target_principal); 755 1411 if (n->target_principal == NULL) { 756 talloc_free(n);757 return NULL;758 }759 }760 761 if (b->localaddress != NULL) {762 n->localaddress = talloc_strdup(n, b->localaddress);763 if (n->localaddress == NULL) {764 1412 talloc_free(n); 765 1413 return NULL; … … 805 1453 const enum epm_protocol *protseq = NULL; 806 1454 int num_protocols = -1, i; 1455 struct ndr_syntax_id abstract_syntax; 807 1456 NTSTATUS status; 808 1457 … … 827 1476 tower->floors[0].lhs.protocol = EPM_PROTOCOL_UUID; 828 1477 829 tower->floors[0].lhs.lhs_data = dcerpc_floor_pack_lhs_data(tower->floors, &binding->object); 1478 abstract_syntax = dcerpc_binding_get_abstract_syntax(binding); 1479 tower->floors[0].lhs.lhs_data = dcerpc_floor_pack_lhs_data(tower->floors, 1480 &abstract_syntax); 830 1481 831 1482 if (!dcerpc_floor_pack_rhs_if_version_data( 832 tower->floors, & binding->object,1483 tower->floors, &abstract_syntax, 833 1484 &tower->floors[0].rhs.uuid.unknown)) { 834 1485 return NT_STATUS_NO_MEMORY; … … 839 1490 840 1491 tower->floors[1].lhs.lhs_data = dcerpc_floor_pack_lhs_data(tower->floors, 841 &ndr_transfer_syntax );1492 &ndr_transfer_syntax_ndr); 842 1493 843 1494 tower->floors[1].rhs.uuid.unknown = data_blob_talloc_zero(tower->floors, 2); … … 846 1497 for (i = 0; i < num_protocols; i++) { 847 1498 tower->floors[2 + i].lhs.protocol = protseq[i]; 848 tower->floors[2 + i].lhs.lhs_data = data_blob_ talloc(tower->floors, NULL, 0);1499 tower->floors[2 + i].lhs.lhs_data = data_blob_null; 849 1500 ZERO_STRUCT(tower->floors[2 + i].rhs); 850 dcerpc_floor_set_rhs_data(tower->floors, &tower->floors[2 + i], ""); 1501 status = dcerpc_floor_set_rhs_data(tower->floors, 1502 &tower->floors[2 + i], 1503 NULL); 1504 if (!NT_STATUS_IS_OK(status)) { 1505 return status; 1506 } 851 1507 } 852 1508 853 1509 /* The 4th floor contains the endpoint */ 854 1510 if (num_protocols >= 2 && binding->endpoint) { 855 status = dcerpc_floor_set_rhs_data(tower->floors, &tower->floors[3], binding->endpoint); 856 if (NT_STATUS_IS_ERR(status)) { 1511 status = dcerpc_floor_set_rhs_data(tower->floors, 1512 &tower->floors[3], 1513 binding->endpoint); 1514 if (!NT_STATUS_IS_OK(status)) { 857 1515 return status; 858 1516 } … … 861 1519 /* The 5th contains the network address */ 862 1520 if (num_protocols >= 3 && binding->host) { 863 if (is_ipaddress(binding->host) || 864 (binding->host[0] == '\\' && binding->host[1] == '\\')) { 865 status = dcerpc_floor_set_rhs_data(tower->floors, &tower->floors[4], 866 binding->host); 867 } else { 868 /* note that we don't attempt to resolve the 869 name here - when we get a hostname here we 870 are in the client code, and want to put in 871 a wildcard all-zeros IP for the server to 872 fill in */ 873 status = dcerpc_floor_set_rhs_data(tower->floors, &tower->floors[4], 874 "0.0.0.0"); 875 } 876 if (NT_STATUS_IS_ERR(status)) { 1521 status = dcerpc_floor_set_rhs_data(tower->floors, 1522 &tower->floors[4], 1523 binding->host); 1524 if (!NT_STATUS_IS_OK(status)) { 877 1525 return status; 878 1526 }
Note:
See TracChangeset
for help on using the changeset viewer.