Ignore:
Timestamp:
Nov 24, 2016, 1:14:11 PM (9 years ago)
Author:
Silvan Scherrer
Message:

Samba Server: update vendor to version 4.4.3

File:
1 edited

Legend:

Unmodified
Added
Removed
  • vendor/current/librpc/rpc/binding.c

    r740 r988  
    88   Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005
    99   Copyright (C) Rafal Szczesniak 2006
     10   Copyright (C) Stefan Metzmacher 2014
    1011
    1112   This program is free software; you can redistribute it and/or modify
     
    3435
    3536#define MAX_PROTSEQ             10
     37
     38struct 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};
    3651
    3752static const struct {
     
    7489};
    7590
    76 static const struct {
     91static const struct ncacn_option {
    7792        const char *name;
    7893        uint32_t flag;
     
    8499        {"ntlm", DCERPC_AUTH_NTLM},
    85100        {"krb5", DCERPC_AUTH_KRB5},
     101        {"schannel", DCERPC_SCHANNEL},
    86102        {"validate", DCERPC_DEBUG_VALIDATE_BOTH},
    87103        {"print", DCERPC_DEBUG_PRINT_BOTH},
     
    89105        {"bigendian", DCERPC_PUSH_BIGENDIAN},
    90106        {"smb2", DCERPC_SMB2},
    91         {"hdrsign", DCERPC_HEADER_SIGNING},
    92107        {"ndr64", DCERPC_NDR64},
    93         {"localaddress", DCERPC_LOCALADDRESS}
    94108};
     109
     110static 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}
    95127
    96128const char *epm_floor_string(TALLOC_CTX *mem_ctx, struct epm_floor *epm_floor)
     
    106138                                char *uuidstr;
    107139
    108                                 if (GUID_equal(&syntax.uuid, &ndr_transfer_syntax.uuid)) {
     140                                if (GUID_equal(&syntax.uuid, &ndr_transfer_syntax_ndr.uuid)) {
    109141                                        return "NDR";
    110142                                }
    111143
    112                                 if (GUID_equal(&syntax.uuid, &ndr64_transfer_syntax.uuid)) {
     144                                if (GUID_equal(&syntax.uuid, &ndr_transfer_syntax_ndr64.uuid)) {
    113145                                        return "NDR64";
    114146                                }
     
    179211{
    180212        char *s = talloc_strdup(mem_ctx, "");
     213        char *o = s;
    181214        int i;
    182215        const char *t_name = NULL;
     216        bool option_section = false;
     217        const char *target_hostname = NULL;
    183218
    184219        if (b->transport != NCA_UNKNOWN) {
    185220                t_name = derpc_transport_string_by_transport(b->transport);
    186221                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                }
    194235        }
    195236
    196237        if (t_name != NULL) {
     238                o = s;
    197239                s = talloc_asprintf_append_buffer(s, "%s:", t_name);
    198240                if (s == NULL) {
     241                        talloc_free(o);
    199242                        return NULL;
    200243                }
     
    202245
    203246        if (b->host) {
     247                o = s;
    204248                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) {
    208277                return s;
    209278        }
    210279
     280        o = s;
    211281        s = talloc_asprintf_append_buffer(s, "[");
     282        if (s == NULL) {
     283                talloc_free(o);
     284                return NULL;
     285        }
    212286
    213287        if (b->endpoint) {
     288                o = s;
    214289                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
    220339        for (i=0;b->options && b->options[i];i++) {
     340                o = s;
    221341                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;
    237349        s = talloc_asprintf_append_buffer(s, "]");
     350        if (s == NULL) {
     351                talloc_free(o);
     352                return NULL;
     353        }
    238354
    239355        return s;
     
    243359  parse a binding string into a dcerpc_binding structure
    244360*/
    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;
    247364        struct dcerpc_binding *b;
    248         char *options;
     365        char *s;
     366        char *options = NULL;
    249367        char *p;
    250         int i, j, comma_count;
     368        size_t i;
     369        NTSTATUS status;
    251370
    252371        b = talloc_zero(mem_ctx, struct dcerpc_binding);
     
    255374        }
    256375
     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
    257395        p = strchr(s, '@');
    258396
    259397        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);
    266403                        return status;
    267404                }
    268405
    269406                s = p + 1;
    270         } else {
    271                 ZERO_STRUCT(b->object);
    272         }
    273 
    274         b->object.if_version = 0;
     407        }
    275408
    276409        p = strchr(s, ':');
     
    278411        if (p == NULL) {
    279412                b->transport = NCA_UNKNOWN;
     413        } else if (is_ipaddress_v6(s)) {
     414                b->transport = NCA_UNKNOWN;
    280415        } 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);
    283437                        return NT_STATUS_NO_MEMORY;
    284438                }
    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                                }
    290486                        }
    291487                }
    292488
    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;
    311583        } 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) {
    316664                return NT_STATUS_NO_MEMORY;
    317665        }
    318666
    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;
    336943                return NT_STATUS_NO_MEMORY;
    337944        }
    338945
    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
    387964        return NT_STATUS_OK;
    388965}
     
    4251002{
    4261003        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        }
    4281011
    4291012        ndr->flags |= LIBNDR_FLAG_NOALIGN;
    4301013
    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        }
    4331022
    4341023        blob = ndr_push_blob(ndr);
     
    4641053}
    4651054
    466 const char *dcerpc_floor_get_rhs_data(TALLOC_CTX *mem_ctx, struct epm_floor *epm_floor)
     1055char *dcerpc_floor_get_rhs_data(TALLOC_CTX *mem_ctx, struct epm_floor *epm_floor)
    4671056{
    4681057        switch (epm_floor->lhs.protocol) {
     
    5311120                                          const char *data)
    5321121{
     1122        if (data == NULL) {
     1123                data = "";
     1124        }
     1125
    5331126        switch (epm_floor->lhs.protocol) {
    5341127        case EPM_PROTOCOL_TCP:
     
    5451138
    5461139        case EPM_PROTOCOL_IP:
     1140                if (!is_ipaddress_v4(data)) {
     1141                        data = "0.0.0.0";
     1142                }
    5471143                epm_floor->rhs.ip.ipaddr = talloc_strdup(mem_ctx, data);
    5481144                NT_STATUS_HAVE_NO_MEMORY(epm_floor->rhs.ip.ipaddr);
     
    6311227                }
    6321228
    633                 for (j = 0; j < transports[i].num_protocols; j++) {
     1229                for (j = 0; j < transports[i].num_protocols && j < MAX_PROTSEQ; j++) {
    6341230                        if (transports[i].protseq[j] != tower->floors[j+2].lhs.protocol) {
    6351231                                break;
     
    6581254}
    6591255
     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
    6601273_PUBLIC_ NTSTATUS dcerpc_binding_from_tower(TALLOC_CTX *mem_ctx,
    6611274                                            struct epm_tower *tower,
     
    6631276{
    6641277        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;
    6661283
    6671284        /*
     
    6741291        }
    6751292
    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);
    6891301                return NT_STATUS_NOT_SUPPORTED;
    6901302        }
    6911303
    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);
    6951305        if (!NT_STATUS_IS_OK(status)) {
    696                 DEBUG(1, ("Error pulling object uuid and version: %s", nt_errstr(status)));
     1306                talloc_free(b);
    6971307                return status;
    6981308        }
    6991309
     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
    7001323        /* Ignore floor 1, it contains the NDR version info */
    7011324
    702         binding->options = NULL;
    703 
    7041325        /* Set endpoint */
     1326        errno = 0;
    7051327        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);
    7101342
    7111343        /* Set network address */
     1344        errno = 0;
    7121345        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;
    7181367        return NT_STATUS_OK;
    7191368}
     
    7351384        n->assoc_group_id = b->assoc_group_id;
    7361385
     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        }
    7371393        if (b->host != NULL) {
    7381394                n->host = talloc_strdup(n, b->host);
     
    7541410                n->target_principal = talloc_strdup(n, b->target_principal);
    7551411                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) {
    7641412                        talloc_free(n);
    7651413                        return NULL;
     
    8051453        const enum epm_protocol *protseq = NULL;
    8061454        int num_protocols = -1, i;
     1455        struct ndr_syntax_id abstract_syntax;
    8071456        NTSTATUS status;
    8081457
     
    8271476        tower->floors[0].lhs.protocol = EPM_PROTOCOL_UUID;
    8281477
    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);
    8301481
    8311482        if (!dcerpc_floor_pack_rhs_if_version_data(
    832                     tower->floors, &binding->object,
     1483                    tower->floors, &abstract_syntax,
    8331484                    &tower->floors[0].rhs.uuid.unknown)) {
    8341485                return NT_STATUS_NO_MEMORY;
     
    8391490
    8401491        tower->floors[1].lhs.lhs_data = dcerpc_floor_pack_lhs_data(tower->floors,
    841                                                                 &ndr_transfer_syntax);
     1492                                                                &ndr_transfer_syntax_ndr);
    8421493
    8431494        tower->floors[1].rhs.uuid.unknown = data_blob_talloc_zero(tower->floors, 2);
     
    8461497        for (i = 0; i < num_protocols; i++) {
    8471498                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;
    8491500                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                }
    8511507        }
    8521508
    8531509        /* The 4th floor contains the endpoint */
    8541510        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)) {
    8571515                        return status;
    8581516                }
     
    8611519        /* The 5th contains the network address */
    8621520        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)) {
    8771525                        return status;
    8781526                }
Note: See TracChangeset for help on using the changeset viewer.