LCOV - code coverage report
Current view: top level - librpc/rpc - binding.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 474 720 65.8 %
Date: 2024-06-13 04:01:37 Functions: 27 30 90.0 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    dcerpc utility functions
       5             : 
       6             :    Copyright (C) Andrew Tridgell 2003
       7             :    Copyright (C) Jelmer Vernooij 2004
       8             :    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005
       9             :    Copyright (C) Rafal Szczesniak 2006
      10             :    Copyright (C) Stefan Metzmacher 2014
      11             : 
      12             :    This program is free software; you can redistribute it and/or modify
      13             :    it under the terms of the GNU General Public License as published by
      14             :    the Free Software Foundation; either version 3 of the License, or
      15             :    (at your option) any later version.
      16             : 
      17             :    This program is distributed in the hope that it will be useful,
      18             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      19             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      20             :    GNU General Public License for more details.
      21             : 
      22             :    You should have received a copy of the GNU General Public License
      23             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      24             : */
      25             : 
      26             : #include "includes.h"
      27             : #include "../../lib/util/util_net.h"
      28             : #include "librpc/gen_ndr/ndr_epmapper.h"
      29             : #include "librpc/gen_ndr/ndr_misc.h"
      30             : #include "librpc/rpc/dcerpc.h"
      31             : #include "rpc_common.h"
      32             : 
      33             : #undef strcasecmp
      34             : #undef strncasecmp
      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             : };
      51             : 
      52             : static const struct {
      53             :         const char *name;
      54             :         enum dcerpc_transport_t transport;
      55             :         int num_protocols;
      56             :         enum epm_protocol protseq[MAX_PROTSEQ];
      57             : } transports[] = {
      58             :         { "ncacn_np",     NCACN_NP, 3, 
      59             :                 { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_SMB, EPM_PROTOCOL_NETBIOS }},
      60             :         { "ncacn_ip_tcp", NCACN_IP_TCP, 3, 
      61             :                 { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_TCP, EPM_PROTOCOL_IP } }, 
      62             :         { "ncacn_http", NCACN_HTTP, 3, 
      63             :                 { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_HTTP, EPM_PROTOCOL_IP } }, 
      64             :         { "ncadg_ip_udp", NCACN_IP_UDP, 3, 
      65             :                 { EPM_PROTOCOL_NCADG, EPM_PROTOCOL_UDP, EPM_PROTOCOL_IP } },
      66             :         { "ncalrpc", NCALRPC, 2, 
      67             :                 { EPM_PROTOCOL_NCALRPC, EPM_PROTOCOL_NAMED_PIPE } },
      68             :         { "ncacn_unix_stream", NCACN_UNIX_STREAM, 2, 
      69             :                 { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_UNIX_DS } },
      70             :         { "ncadg_unix_dgram", NCADG_UNIX_DGRAM, 2, 
      71             :                 { EPM_PROTOCOL_NCADG, EPM_PROTOCOL_UNIX_DS } },
      72             :         { "ncacn_at_dsp", NCACN_AT_DSP, 3, 
      73             :                 { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_APPLETALK, EPM_PROTOCOL_DSP } },
      74             :         { "ncadg_at_ddp", NCADG_AT_DDP, 3, 
      75             :                 { EPM_PROTOCOL_NCADG, EPM_PROTOCOL_APPLETALK, EPM_PROTOCOL_DDP } },
      76             :         { "ncacn_vns_ssp", NCACN_VNS_SPP, 3, 
      77             :                 { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_STREETTALK, EPM_PROTOCOL_VINES_SPP } },
      78             :         { "ncacn_vns_ipc", NCACN_VNS_IPC, 3, 
      79             :                 { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_STREETTALK, EPM_PROTOCOL_VINES_IPC }, },
      80             :         { "ncadg_ipx", NCADG_IPX, 2,
      81             :                 { EPM_PROTOCOL_NCADG, EPM_PROTOCOL_IPX },
      82             :         },
      83             :         { "ncacn_spx", NCACN_SPX, 3,
      84             :                 /* I guess some MS programmer confused the identifier for 
      85             :                  * EPM_PROTOCOL_UUID (0x0D or 13) with the one for 
      86             :                  * EPM_PROTOCOL_SPX (0x13) here. -- jelmer*/
      87             :                 { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_NCALRPC, EPM_PROTOCOL_UUID },
      88             :         },
      89             : };
      90             : 
      91             : static const struct ncacn_option {
      92             :         const char *name;
      93             :         uint32_t flag;
      94             : } ncacn_options[] = {
      95             :         {"sign", DCERPC_SIGN},
      96             :         {"seal", DCERPC_SEAL},
      97             :         {"connect", DCERPC_CONNECT},
      98             :         {"spnego", DCERPC_AUTH_SPNEGO},
      99             :         {"ntlm", DCERPC_AUTH_NTLM},
     100             :         {"krb5", DCERPC_AUTH_KRB5},
     101             :         {"schannel", DCERPC_SCHANNEL | DCERPC_SCHANNEL_AUTO},
     102             :         {"validate", DCERPC_DEBUG_VALIDATE_BOTH},
     103             :         {"print", DCERPC_DEBUG_PRINT_BOTH},
     104             :         {"padcheck", DCERPC_DEBUG_PAD_CHECK},
     105             :         {"bigendian", DCERPC_PUSH_BIGENDIAN},
     106             :         {"smb1", DCERPC_SMB1},
     107             :         {"smb2", DCERPC_SMB2},
     108             :         {"ndr64", DCERPC_NDR64},
     109             :         {"packet", DCERPC_PACKET},
     110             : };
     111             : 
     112      877443 : static const struct ncacn_option *ncacn_option_by_name(const char *name)
     113             : {
     114             :         size_t i;
     115             : 
     116    26407759 :         for (i=0; i<ARRAY_SIZE(ncacn_options); i++) {
     117             :                 int ret;
     118             : 
     119    13014549 :                 ret = strcasecmp(ncacn_options[i].name, name);
     120    13014549 :                 if (ret != 0) {
     121    13001247 :                         continue;
     122             :                 }
     123             : 
     124       13302 :                 return &ncacn_options[i];
     125             :         }
     126             : 
     127      864141 :         return NULL;
     128             : }
     129             : 
     130        3054 : const char *epm_floor_string(TALLOC_CTX *mem_ctx, struct epm_floor *epm_floor)
     131             : {
     132             :         struct ndr_syntax_id syntax;
     133             :         NTSTATUS status;
     134             : 
     135        3054 :         switch(epm_floor->lhs.protocol) {
     136        1236 :                 case EPM_PROTOCOL_UUID:
     137        1236 :                         status = dcerpc_floor_get_lhs_data(epm_floor, &syntax);
     138        1236 :                         if (NT_STATUS_IS_OK(status)) {
     139             :                                 /* lhs is used: UUID */
     140             :                                 struct GUID_txt_buf buf;
     141             : 
     142        1236 :                                 if (GUID_equal(&syntax.uuid, &ndr_transfer_syntax_ndr.uuid)) {
     143         621 :                                         return "NDR";
     144             :                                 } 
     145             : 
     146         615 :                                 if (GUID_equal(&syntax.uuid, &ndr_transfer_syntax_ndr64.uuid)) {
     147           0 :                                         return "NDR64";
     148             :                                 } 
     149             : 
     150         615 :                                 return talloc_asprintf(
     151             :                                         mem_ctx,
     152             :                                         " uuid %s/0x%02x",
     153             :                                         GUID_buf_string(&syntax.uuid, &buf),
     154             :                                         syntax.if_version);
     155             :                         } else { /* IPX */
     156           0 :                                 return talloc_asprintf(mem_ctx, "IPX:%s", 
     157           0 :                                                 data_blob_hex_string_upper(mem_ctx, &epm_floor->rhs.uuid.unknown));
     158             :                         }
     159             : 
     160         582 :                 case EPM_PROTOCOL_NCACN:
     161         582 :                         return "RPC-C";
     162             : 
     163           0 :                 case EPM_PROTOCOL_NCADG:
     164           0 :                         return "RPC";
     165             : 
     166          36 :                 case EPM_PROTOCOL_NCALRPC:
     167          36 :                         return "NCALRPC";
     168             : 
     169           0 :                 case EPM_PROTOCOL_DNET_NSP:
     170           0 :                         return "DNET/NSP";
     171             : 
     172         297 :                 case EPM_PROTOCOL_IP:
     173         297 :                         return talloc_asprintf(mem_ctx, "IP:%s", epm_floor->rhs.ip.ipaddr);
     174             : 
     175          36 :                 case EPM_PROTOCOL_NAMED_PIPE:
     176          36 :                         return talloc_asprintf(mem_ctx, "NAMED-PIPE:%s", epm_floor->rhs.named_pipe.path);
     177             : 
     178         285 :                 case EPM_PROTOCOL_SMB:
     179         285 :                         return talloc_asprintf(mem_ctx, "SMB:%s", epm_floor->rhs.smb.unc);
     180             : 
     181           0 :                 case EPM_PROTOCOL_UNIX_DS:
     182           0 :                         return talloc_asprintf(mem_ctx, "Unix:%s", epm_floor->rhs.unix_ds.path);
     183             : 
     184         285 :                 case EPM_PROTOCOL_NETBIOS:
     185         285 :                         return talloc_asprintf(mem_ctx, "NetBIOS:%s", epm_floor->rhs.netbios.name);
     186             : 
     187           0 :                 case EPM_PROTOCOL_NETBEUI:
     188           0 :                         return "NETBeui";
     189             : 
     190           0 :                 case EPM_PROTOCOL_SPX:
     191           0 :                         return "SPX";
     192             : 
     193           0 :                 case EPM_PROTOCOL_NB_IPX:
     194           0 :                         return "NB_IPX";
     195             : 
     196          66 :                 case EPM_PROTOCOL_HTTP:
     197          66 :                         return talloc_asprintf(mem_ctx, "HTTP:%d", epm_floor->rhs.http.port);
     198             : 
     199         231 :                 case EPM_PROTOCOL_TCP:
     200         231 :                         return talloc_asprintf(mem_ctx, "TCP:%d", epm_floor->rhs.tcp.port);
     201             : 
     202           0 :                 case EPM_PROTOCOL_UDP:
     203           0 :                         return talloc_asprintf(mem_ctx, "UDP:%d", epm_floor->rhs.udp.port);
     204             : 
     205           0 :                 default:
     206           0 :                         return talloc_asprintf(mem_ctx, "UNK(%02x):", epm_floor->lhs.protocol);
     207             :         }
     208             : }
     209             : 
     210             : 
     211             : /*
     212             :   form a binding string from a binding structure
     213             : */
     214        5569 : _PUBLIC_ char *dcerpc_binding_string(TALLOC_CTX *mem_ctx, const struct dcerpc_binding *b)
     215             : {
     216        5569 :         char *s = NULL;
     217             :         size_t i;
     218        5569 :         const char *t_name = NULL;
     219        5569 :         bool option_section = false;
     220        5569 :         const char *target_hostname = NULL;
     221             : 
     222        5569 :         if (b->transport != NCA_UNKNOWN) {
     223        5565 :                 t_name = derpc_transport_string_by_transport(b->transport);
     224        5565 :                 if (!t_name) {
     225           0 :                         return NULL;
     226             :                 }
     227             :         }
     228             : 
     229        5569 :         s = talloc_strdup(mem_ctx, "");
     230             : 
     231        5569 :         if (!GUID_all_zero(&b->object)) {
     232             :                 struct GUID_txt_buf buf;
     233           0 :                 talloc_asprintf_addbuf(
     234             :                         &s, "%s@", GUID_buf_string(&b->object, &buf));
     235             :         }
     236             : 
     237        5569 :         if (t_name != NULL) {
     238        5565 :                 talloc_asprintf_addbuf(&s, "%s:", t_name);
     239             :         }
     240             : 
     241        5569 :         if (b->host) {
     242         653 :                 talloc_asprintf_addbuf(&s, "%s", b->host);
     243             :         }
     244             : 
     245        5569 :         target_hostname = b->target_hostname;
     246        5569 :         if (target_hostname != NULL && b->host != NULL) {
     247         653 :                 if (strcmp(target_hostname, b->host) == 0) {
     248         640 :                         target_hostname = NULL;
     249             :                 }
     250             :         }
     251             : 
     252        5569 :         option_section =
     253        5889 :                 (b->endpoint != NULL) ||
     254        2038 :                 (target_hostname != NULL) ||
     255        3498 :                 (b->target_principal != NULL) ||
     256        3498 :                 (b->assoc_group_id != 0) ||
     257        9649 :                 (b->options != NULL) ||
     258        2038 :                 (b->flags != 0);
     259             : 
     260        5569 :         if (!option_section) {
     261        1846 :                 return s;
     262             :         }
     263             : 
     264        3723 :         talloc_asprintf_addbuf(&s, "[");
     265             : 
     266        3723 :         if (b->endpoint) {
     267        3523 :                 talloc_asprintf_addbuf(&s, "%s", b->endpoint);
     268             :         }
     269             : 
     270       59568 :         for (i=0;i<ARRAY_SIZE(ncacn_options);i++) {
     271       55845 :                 if (!(b->flags & ncacn_options[i].flag)) {
     272       55341 :                         continue;
     273             :                 }
     274             : 
     275         504 :                 talloc_asprintf_addbuf(&s, ",%s", ncacn_options[i].name);
     276             :         }
     277             : 
     278        3723 :         if (target_hostname) {
     279          13 :                 talloc_asprintf_addbuf(
     280           4 :                         &s, ",target_hostname=%s", b->target_hostname);
     281             :         }
     282             : 
     283        3723 :         if (b->target_principal) {
     284           5 :                 talloc_asprintf_addbuf(
     285           0 :                         &s, ",target_principal=%s", b->target_principal);
     286             :         }
     287             : 
     288        3723 :         if (b->assoc_group_id != 0) {
     289          18 :                 talloc_asprintf_addbuf(
     290           0 :                         &s, ",assoc_group_id=0x%08x", b->assoc_group_id);
     291             :         }
     292             : 
     293        4125 :         for (i=0;b->options && b->options[i];i++) {
     294         402 :                 talloc_asprintf_addbuf(&s, ",%s", b->options[i]);
     295             :         }
     296             : 
     297        3723 :         talloc_asprintf_addbuf(&s, "]");
     298             : 
     299        3723 :         return s;
     300             : }
     301             : 
     302             : /*
     303             :   parse a binding string into a dcerpc_binding structure
     304             : */
     305       77068 : _PUBLIC_ NTSTATUS dcerpc_parse_binding(TALLOC_CTX *mem_ctx, const char *_s, struct dcerpc_binding **b_out)
     306             : {
     307             :         char *_t;
     308             :         struct dcerpc_binding *b;
     309             :         char *s;
     310       77068 :         char *options = NULL;
     311             :         char *p;
     312             :         size_t i;
     313             :         NTSTATUS status;
     314             : 
     315       77068 :         b = talloc_zero(mem_ctx, struct dcerpc_binding);
     316       77068 :         if (!b) {
     317           0 :                 return NT_STATUS_NO_MEMORY;
     318             :         }
     319             : 
     320       77068 :         _t = talloc_strdup(b, _s);
     321       77068 :         if (_t == NULL) {
     322           0 :                 talloc_free(b);
     323           0 :                 return NT_STATUS_NO_MEMORY;
     324             :         }
     325             : 
     326       77068 :         s = _t;
     327             : 
     328       77068 :         p = strchr(s, '[');
     329       77068 :         if (p) {
     330       55197 :                 char *q = p + strlen(p) - 1;
     331       55197 :                 if (*q != ']') {
     332           0 :                         talloc_free(b);
     333           0 :                         return NT_STATUS_INVALID_PARAMETER_MIX;
     334             :                 }
     335       55197 :                 *p = '\0';
     336       55197 :                 *q = '\0';
     337       55197 :                 options = p + 1;
     338             :         }
     339             : 
     340       77068 :         p = strchr(s, '@');
     341             : 
     342       77068 :         if (p && PTR_DIFF(p, s) == 36) { /* 36 is the length of a UUID */
     343           0 :                 *p = '\0';
     344             : 
     345           0 :                 status = dcerpc_binding_set_string_option(b, "object", s);
     346           0 :                 if (!NT_STATUS_IS_OK(status)) {
     347           0 :                         talloc_free(b);
     348           0 :                         return status;
     349             :                 }
     350             : 
     351           0 :                 s = p + 1;
     352             :         }
     353             : 
     354       77068 :         p = strchr(s, ':');
     355             : 
     356       77068 :         if (p == NULL) {
     357         661 :                 b->transport = NCA_UNKNOWN;
     358       76407 :         } else if (is_ipaddress_v6(s)) {
     359           0 :                 b->transport = NCA_UNKNOWN;
     360             :         } else {
     361       76407 :                 *p = '\0';
     362             : 
     363       76407 :                 status = dcerpc_binding_set_string_option(b, "transport", s);
     364       76407 :                 if (!NT_STATUS_IS_OK(status)) {
     365           0 :                         talloc_free(b);
     366           0 :                         return status;
     367             :                 }
     368             : 
     369       76407 :                 s = p + 1;
     370             :         }
     371             : 
     372       77068 :         if (strlen(s) > 0) {
     373        8963 :                 status = dcerpc_binding_set_string_option(b, "host", s);
     374        8963 :                 if (!NT_STATUS_IS_OK(status)) {
     375           0 :                         talloc_free(b);
     376           0 :                         return status;
     377             :                 }
     378             : 
     379        8963 :                 b->target_hostname = talloc_strdup(b, b->host);
     380        8963 :                 if (b->target_hostname == NULL) {
     381           0 :                         talloc_free(b);
     382           0 :                         return NT_STATUS_NO_MEMORY;
     383             :                 }
     384             :         }
     385             : 
     386      134170 :         for (i=0; options != NULL; i++) {
     387       57102 :                 const char *name = options;
     388       57102 :                 const char *value = NULL;
     389             : 
     390       57102 :                 p = strchr(options, ',');
     391       57102 :                 if (p != NULL) {
     392        1905 :                         *p = '\0';
     393        1905 :                         options = p+1;
     394             :                 } else {
     395       55197 :                         options = NULL;
     396             :                 }
     397             : 
     398       57102 :                 p = strchr(name, '=');
     399       57102 :                 if (p != NULL) {
     400        1565 :                         *p = '\0';
     401        1565 :                         value = p + 1;
     402             :                 }
     403             : 
     404       57102 :                 if (value == NULL) {
     405             :                         /*
     406             :                          * If it's not a key=value pair
     407             :                          * it might be a ncacn_option
     408             :                          * or if it's the first option
     409             :                          * it's the endpoint.
     410             :                          */
     411       55537 :                         const struct ncacn_option *no = NULL;
     412             : 
     413       55537 :                         value = name;
     414             : 
     415       55537 :                         no = ncacn_option_by_name(name);
     416       55537 :                         if (no == NULL) {
     417       48898 :                                 if (i > 0) {
     418             :                                         /*
     419             :                                          * we don't allow unknown options
     420             :                                          */
     421           0 :                                         return NT_STATUS_INVALID_PARAMETER_MIX;
     422             :                                 }
     423             : 
     424             :                                 /*
     425             :                                  * This is the endpoint
     426             :                                  */
     427       48898 :                                 name = "endpoint";
     428       48898 :                                 if (strlen(value) == 0) {
     429        1812 :                                         value = NULL;
     430             :                                 }
     431             :                         }
     432             :                 }
     433             : 
     434       57102 :                 status = dcerpc_binding_set_string_option(b, name, value);
     435       57102 :                 if (!NT_STATUS_IS_OK(status)) {
     436           0 :                         talloc_free(b);
     437           0 :                         return status;
     438             :                 }
     439             :         }
     440             : 
     441       77068 :         talloc_free(_t);
     442       77068 :         *b_out = b;
     443       77068 :         return NT_STATUS_OK;
     444             : }
     445             : 
     446       38412 : _PUBLIC_ struct GUID dcerpc_binding_get_object(const struct dcerpc_binding *b)
     447             : {
     448       38412 :         return b->object;
     449             : }
     450             : 
     451       10069 : _PUBLIC_ NTSTATUS dcerpc_binding_set_object(struct dcerpc_binding *b,
     452             :                                             struct GUID object)
     453             : {
     454       10069 :         char *tmp = discard_const_p(char, b->object_string);
     455             : 
     456       10069 :         if (GUID_all_zero(&object)) {
     457       10069 :                 talloc_free(tmp);
     458       10069 :                 b->object_string = NULL;
     459       10069 :                 ZERO_STRUCT(b->object);
     460       10069 :                 return NT_STATUS_OK;
     461             :         }
     462             : 
     463           0 :         b->object_string = GUID_string(b, &object);
     464           0 :         if (b->object_string == NULL) {
     465           0 :                 b->object_string = tmp;
     466           0 :                 return NT_STATUS_NO_MEMORY;
     467             :         }
     468           0 :         talloc_free(tmp);
     469             : 
     470           0 :         b->object = object;
     471           0 :         return NT_STATUS_OK;
     472             : }
     473             : 
     474      568169 : _PUBLIC_ enum dcerpc_transport_t dcerpc_binding_get_transport(const struct dcerpc_binding *b)
     475             : {
     476      568169 :         return b->transport;
     477             : }
     478             : 
     479       77796 : _PUBLIC_ NTSTATUS dcerpc_binding_set_transport(struct dcerpc_binding *b,
     480             :                                                enum dcerpc_transport_t transport)
     481             : {
     482             :         NTSTATUS status;
     483             : 
     484             :         /*
     485             :          * TODO: we may want to check the transport value is
     486             :          * wellknown.
     487             :          */
     488       77796 :         if (b->transport == transport) {
     489         268 :                 return NT_STATUS_OK;
     490             :         }
     491             : 
     492             :         /*
     493             :          * This implicitly resets the endpoint
     494             :          * as the endpoint is transport specific.
     495             :          *
     496             :          * It also resets the assoc group as it's
     497             :          * also endpoint specific.
     498             :          *
     499             :          * TODO: in future we may reset more options
     500             :          * here.
     501             :          */
     502       77528 :         status = dcerpc_binding_set_string_option(b, "endpoint", NULL);
     503       77528 :         if (!NT_STATUS_IS_OK(status)) {
     504           0 :                 return status;
     505             :         }
     506             : 
     507       77528 :         b->assoc_group_id = 0;
     508             : 
     509       77528 :         b->transport = transport;
     510       77528 :         return NT_STATUS_OK;
     511             : }
     512             : 
     513           0 : _PUBLIC_ void dcerpc_binding_get_auth_info(const struct dcerpc_binding *b,
     514             :                                            enum dcerpc_AuthType *_auth_type,
     515             :                                            enum dcerpc_AuthLevel *_auth_level)
     516             : {
     517             :         enum dcerpc_AuthType auth_type;
     518             :         enum dcerpc_AuthLevel auth_level;
     519             : 
     520           0 :         if (b->flags & DCERPC_AUTH_SPNEGO) {
     521           0 :                 auth_type = DCERPC_AUTH_TYPE_SPNEGO;
     522           0 :         } else if (b->flags & DCERPC_AUTH_KRB5) {
     523           0 :                 auth_type = DCERPC_AUTH_TYPE_KRB5;
     524           0 :         } else if (b->flags & DCERPC_SCHANNEL) {
     525           0 :                 auth_type = DCERPC_AUTH_TYPE_SCHANNEL;
     526           0 :         } else if (b->flags & DCERPC_AUTH_NTLM) {
     527           0 :                 auth_type = DCERPC_AUTH_TYPE_NTLMSSP;
     528             :         } else {
     529           0 :                 auth_type = DCERPC_AUTH_TYPE_NONE;
     530             :         }
     531             : 
     532           0 :         if (b->flags & DCERPC_SEAL) {
     533           0 :                 auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
     534           0 :         } else if (b->flags & DCERPC_SIGN) {
     535           0 :                 auth_level = DCERPC_AUTH_LEVEL_INTEGRITY;
     536           0 :         } else if (b->flags & DCERPC_CONNECT) {
     537           0 :                 auth_level = DCERPC_AUTH_LEVEL_CONNECT;
     538           0 :         } else if (b->flags & DCERPC_PACKET) {
     539           0 :                 auth_level = DCERPC_AUTH_LEVEL_PACKET;
     540           0 :         } else if (auth_type != DCERPC_AUTH_TYPE_NONE) {
     541           0 :                 auth_level = DCERPC_AUTH_LEVEL_INTEGRITY;
     542             :         } else {
     543           0 :                 auth_level = DCERPC_AUTH_LEVEL_NONE;
     544             :         }
     545             : 
     546           0 :         if (_auth_type != NULL) {
     547           0 :                 *_auth_type = auth_type;
     548             :         }
     549             : 
     550           0 :         if (_auth_level != NULL) {
     551           0 :                 *_auth_level = auth_level;
     552             :         }
     553           0 : }
     554             : 
     555       19641 : _PUBLIC_ uint32_t dcerpc_binding_get_assoc_group_id(const struct dcerpc_binding *b)
     556             : {
     557       19641 :         return b->assoc_group_id;
     558             : }
     559             : 
     560       24884 : _PUBLIC_ NTSTATUS dcerpc_binding_set_assoc_group_id(struct dcerpc_binding *b,
     561             :                                                     uint32_t assoc_group_id)
     562             : {
     563       24884 :         b->assoc_group_id = assoc_group_id;
     564       24884 :         return NT_STATUS_OK;
     565             : }
     566             : 
     567      384960 : _PUBLIC_ struct ndr_syntax_id dcerpc_binding_get_abstract_syntax(const struct dcerpc_binding *b)
     568             : {
     569      384960 :         const char *s = dcerpc_binding_get_string_option(b, "abstract_syntax");
     570             :         bool ok;
     571             :         struct ndr_syntax_id id;
     572             : 
     573      384960 :         if (s == NULL) {
     574           0 :                 return ndr_syntax_id_null;
     575             :         }
     576             : 
     577      384960 :         ok = ndr_syntax_id_from_string(s, &id);
     578      384960 :         if (!ok) {
     579           0 :                 return ndr_syntax_id_null;
     580             :         }
     581             : 
     582      384960 :         return id;
     583             : }
     584             : 
     585      403627 : _PUBLIC_ NTSTATUS dcerpc_binding_set_abstract_syntax(struct dcerpc_binding *b,
     586             :                                                      const struct ndr_syntax_id *syntax)
     587             : {
     588             :         NTSTATUS status;
     589             :         struct ndr_syntax_id_buf buf;
     590             : 
     591      403627 :         if (syntax == NULL) {
     592           0 :                 status = dcerpc_binding_set_string_option(b, "abstract_syntax", NULL);
     593           0 :                 return status;
     594             :         }
     595             : 
     596      403627 :         if (ndr_syntax_id_equal(&ndr_syntax_id_null, syntax)) {
     597           3 :                 status = dcerpc_binding_set_string_option(b, "abstract_syntax", NULL);
     598           3 :                 return status;
     599             :         }
     600             : 
     601      403624 :         status = dcerpc_binding_set_string_option(
     602      403624 :                 b, "abstract_syntax", ndr_syntax_id_buf_string(syntax, &buf));
     603      403624 :         return status;
     604             : }
     605             : 
     606      716422 : _PUBLIC_ const char *dcerpc_binding_get_string_option(const struct dcerpc_binding *b,
     607             :                                                       const char *name)
     608             : {
     609             :         struct {
     610             :                 const char *name;
     611             :                 const char *value;
     612             : #define _SPECIAL(x) { .name = #x, .value = b->x, }
     613     3847317 :         } specials[] = {
     614      716422 :                 { .name = "object", .value = b->object_string, },
     615      716422 :                 _SPECIAL(host),
     616      716422 :                 _SPECIAL(endpoint),
     617      716422 :                 _SPECIAL(target_hostname),
     618      716422 :                 _SPECIAL(target_principal),
     619             : #undef _SPECIAL
     620             :         };
     621      716422 :         const struct ncacn_option *no = NULL;
     622      716422 :         size_t name_len = strlen(name);
     623             :         size_t i;
     624             :         int ret;
     625             : 
     626      716422 :         ret = strcmp(name, "transport");
     627      716422 :         if (ret == 0) {
     628           0 :                 return derpc_transport_string_by_transport(b->transport);
     629             :         }
     630             : 
     631      716422 :         ret = strcmp(name, "assoc_group_id");
     632      716422 :         if (ret == 0) {
     633           0 :                 char *tmp = discard_const_p(char, b->assoc_group_string);
     634             : 
     635           0 :                 if (b->assoc_group_id == 0) {
     636           0 :                         return NULL;
     637             :                 }
     638             : 
     639           0 :                 snprintf(tmp, sizeof(b->assoc_group_string),
     640           0 :                          "0x%08x", b->assoc_group_id);
     641           0 :                 return (const char *)b->assoc_group_string;
     642             :         }
     643             : 
     644     6232135 :         for (i=0; i < ARRAY_SIZE(specials); i++) {
     645     2908592 :                 ret = strcmp(specials[i].name, name);
     646     2908592 :                 if (ret != 0) {
     647     2592886 :                         continue;
     648             :                 }
     649             : 
     650      315706 :                 return specials[i].value;
     651             :         }
     652             : 
     653      400716 :         no = ncacn_option_by_name(name);
     654      400716 :         if (no != NULL) {
     655           0 :                 if (b->flags & no->flag) {
     656           0 :                         return no->name;
     657             :                 }
     658             : 
     659           0 :                 return NULL;
     660             :         }
     661             : 
     662      400716 :         if (b->options == NULL) {
     663           9 :                 return NULL;
     664             :         }
     665             : 
     666      417192 :         for (i=0; b->options[i]; i++) {
     667      402359 :                 const char *o = b->options[i];
     668      402359 :                 const char *vs = NULL;
     669             : 
     670      402359 :                 ret = strncmp(name, o, name_len);
     671      402359 :                 if (ret != 0) {
     672       16485 :                         continue;
     673             :                 }
     674             : 
     675      385874 :                 if (o[name_len] != '=') {
     676           0 :                         continue;
     677             :                 }
     678             : 
     679      385874 :                 vs = &o[name_len + 1];
     680             : 
     681      385874 :                 return vs;
     682             :         }
     683             : 
     684       14833 :         return NULL;
     685             : }
     686             : 
     687           0 : _PUBLIC_ char *dcerpc_binding_copy_string_option(TALLOC_CTX *mem_ctx,
     688             :                                                  const struct dcerpc_binding *b,
     689             :                                                  const char *name)
     690             : {
     691           0 :         const char *c = dcerpc_binding_get_string_option(b, name);
     692             :         char *v;
     693             : 
     694           0 :         if (c == NULL) {
     695           0 :                 errno = ENOENT;
     696           0 :                 return NULL;
     697             :         }
     698             : 
     699           0 :         v = talloc_strdup(mem_ctx, c);
     700           0 :         if (v == NULL) {
     701           0 :                 errno = ENOMEM;
     702           0 :                 return NULL;
     703             :         }
     704             : 
     705           0 :         return v;
     706             : }
     707             : 
     708      673453 : _PUBLIC_ NTSTATUS dcerpc_binding_set_string_option(struct dcerpc_binding *b,
     709             :                                                    const char *name,
     710             :                                                    const char *value)
     711             : {
     712             :         struct {
     713             :                 const char *name;
     714             :                 const char **ptr;
     715             : #define _SPECIAL(x) { .name = #x, .ptr = &b->x, }
     716     3085497 :         } specials[] = {
     717      673453 :                 _SPECIAL(host),
     718      673453 :                 _SPECIAL(endpoint),
     719      673453 :                 _SPECIAL(target_hostname),
     720      673453 :                 _SPECIAL(target_principal),
     721             : #undef _SPECIAL
     722             :         };
     723      673453 :         const struct ncacn_option *no = NULL;
     724      673453 :         size_t name_len = strlen(name);
     725      673453 :         const char *opt = NULL;
     726             :         char *tmp;
     727             :         size_t i;
     728             :         int ret;
     729             : 
     730             :         /*
     731             :          * Note: value == NULL, means delete it.
     732             :          * value != NULL means add or reset.
     733             :          */
     734             : 
     735      673453 :         ret = strcmp(name, "transport");
     736      673453 :         if (ret == 0) {
     737       76407 :                 enum dcerpc_transport_t t = dcerpc_transport_by_name(value);
     738             : 
     739       76407 :                 if (t == NCA_UNKNOWN && value != NULL) {
     740           0 :                         return NT_STATUS_INVALID_PARAMETER_MIX;
     741             :                 }
     742             : 
     743       76407 :                 return dcerpc_binding_set_transport(b, t);
     744             :         }
     745             : 
     746      597046 :         ret = strcmp(name, "object");
     747      597046 :         if (ret == 0) {
     748             :                 NTSTATUS status;
     749           0 :                 struct GUID uuid = GUID_zero();
     750             : 
     751           0 :                 if (value != NULL) {
     752             :                         DATA_BLOB blob;
     753           0 :                         blob = data_blob_string_const(value);
     754           0 :                         if (blob.length != 36) {
     755           0 :                                 return NT_STATUS_INVALID_PARAMETER_MIX;
     756             :                         }
     757             : 
     758           0 :                         status = GUID_from_data_blob(&blob, &uuid);
     759           0 :                         if (!NT_STATUS_IS_OK(status)) {
     760           0 :                                 return status;
     761             :                         }
     762             :                 }
     763             : 
     764           0 :                 return dcerpc_binding_set_object(b, uuid);
     765             :         }
     766             : 
     767      597046 :         ret = strcmp(name, "assoc_group_id");
     768      597046 :         if (ret == 0) {
     769           0 :                 uint32_t assoc_group_id = 0;
     770             : 
     771           0 :                 if (value != NULL) {
     772             :                         char c;
     773             : 
     774           0 :                         ret = sscanf(value, "0x%08x%c", &assoc_group_id, &c);
     775           0 :                         if (ret != 1) {
     776           0 :                                 return NT_STATUS_INVALID_PARAMETER_MIX;
     777             :                         }
     778             :                 }
     779             : 
     780           0 :                 return dcerpc_binding_set_assoc_group_id(b, assoc_group_id);
     781             :         }
     782             : 
     783     4639398 :         for (i=0; i < ARRAY_SIZE(specials); i++) {
     784     2020152 :                 ret = strcmp(specials[i].name, name);
     785     2020152 :                 if (ret != 0) {
     786     1844296 :                         continue;
     787             :                 }
     788             : 
     789      175856 :                 tmp = discard_const_p(char, *specials[i].ptr);
     790             : 
     791      175856 :                 if (value == NULL) {
     792       89706 :                         talloc_free(tmp);
     793       89706 :                         *specials[i].ptr = NULL;
     794       89706 :                         return NT_STATUS_OK;
     795             :                 }
     796             : 
     797       86150 :                 if (value[0] == '\0') {
     798           0 :                         return NT_STATUS_INVALID_PARAMETER_MIX;
     799             :                 }
     800             : 
     801       86150 :                 *specials[i].ptr = talloc_strdup(b, value);
     802       86150 :                 if (*specials[i].ptr == NULL) {
     803           0 :                         *specials[i].ptr = tmp;
     804           0 :                         return NT_STATUS_NO_MEMORY;
     805             :                 }
     806       86150 :                 talloc_free(tmp);
     807             : 
     808       86150 :                 return NT_STATUS_OK;
     809             :         }
     810             : 
     811      421190 :         no = ncacn_option_by_name(name);
     812      421190 :         if (no != NULL) {
     813        6663 :                 if (value == NULL) {
     814           0 :                         b->flags &= ~no->flag;
     815           0 :                         return NT_STATUS_OK;
     816             :                 }
     817             : 
     818        6663 :                 ret = strcasecmp(no->name, value);
     819        6663 :                 if (ret != 0) {
     820           0 :                         return NT_STATUS_INVALID_PARAMETER_MIX;
     821             :                 }
     822             : 
     823        6663 :                 b->flags |= no->flag;
     824        6663 :                 return NT_STATUS_OK;
     825             :         }
     826             : 
     827      425812 :         for (i=0; b->options && b->options[i]; i++) {
     828       23070 :                 const char *o = b->options[i];
     829             : 
     830       23070 :                 ret = strncmp(name, o, name_len);
     831       23070 :                 if (ret != 0) {
     832       11285 :                         continue;
     833             :                 }
     834             : 
     835       11785 :                 if (o[name_len] != '=') {
     836           0 :                         continue;
     837             :                 }
     838             : 
     839       11785 :                 opt = o;
     840       11785 :                 break;
     841             :         }
     842             : 
     843      414527 :         if (opt == NULL) {
     844             :                 const char **n;
     845             : 
     846      402742 :                 if (value == NULL) {
     847           0 :                         return NT_STATUS_OK;
     848             :                 }
     849             : 
     850      402742 :                 n = talloc_realloc(b, b->options, const char *, i + 2);
     851      402742 :                 if (n == NULL) {
     852           0 :                         return NT_STATUS_NO_MEMORY;
     853             :                 }
     854      402742 :                 n[i] = NULL;
     855      402742 :                 n[i + 1] = NULL;
     856      402742 :                 b->options = n;
     857             :         }
     858             : 
     859      414527 :         tmp = discard_const_p(char, opt);
     860             : 
     861      414527 :         if (value == NULL) {
     862           6 :                 for (;b->options[i];i++) {
     863           3 :                         b->options[i] = b->options[i+1];
     864             :                 }
     865           3 :                 talloc_free(tmp);
     866           3 :                 return NT_STATUS_OK;
     867             :         }
     868             : 
     869      414524 :         b->options[i] = talloc_asprintf(b->options, "%s=%s",
     870             :                                         name, value);
     871      414524 :         if (b->options[i] == NULL) {
     872           0 :                 b->options[i] = tmp;
     873           0 :                 return NT_STATUS_NO_MEMORY;
     874             :         }
     875             : 
     876      414524 :         return NT_STATUS_OK;
     877             : }
     878             : 
     879       52273 : _PUBLIC_ uint32_t dcerpc_binding_get_flags(const struct dcerpc_binding *b)
     880             : {
     881       52273 :         return b->flags;
     882             : }
     883             : 
     884       27653 : _PUBLIC_ NTSTATUS dcerpc_binding_set_flags(struct dcerpc_binding *b,
     885             :                                            uint32_t additional,
     886             :                                            uint32_t clear)
     887             : {
     888             :         /*
     889             :          * TODO: in future we may want to reject invalid combinations
     890             :          */
     891       27653 :         b->flags &= ~clear;
     892       27653 :         b->flags |= additional;
     893             : 
     894       27653 :         return NT_STATUS_OK;
     895             : }
     896             : 
     897        7648 : _PUBLIC_ NTSTATUS dcerpc_floor_get_lhs_data(const struct epm_floor *epm_floor,
     898             :                                             struct ndr_syntax_id *syntax)
     899             : {
     900        7648 :         TALLOC_CTX *mem_ctx = talloc_init("floor_get_lhs_data");
     901             :         struct ndr_pull *ndr;
     902             :         enum ndr_err_code ndr_err;
     903        7648 :         uint16_t if_version=0;
     904             : 
     905        7648 :         ndr = ndr_pull_init_blob(&epm_floor->lhs.lhs_data, mem_ctx);
     906        7648 :         if (ndr == NULL) {
     907           0 :                 talloc_free(mem_ctx);
     908           0 :                 return NT_STATUS_NO_MEMORY;
     909             :         }
     910        7648 :         ndr->flags |= LIBNDR_FLAG_NOALIGN;
     911             : 
     912        7648 :         ndr_err = ndr_pull_GUID(ndr, NDR_SCALARS | NDR_BUFFERS, &syntax->uuid);
     913        7648 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     914           0 :                 talloc_free(mem_ctx);
     915           0 :                 return ndr_map_error2ntstatus(ndr_err);
     916             :         }
     917             : 
     918        7648 :         ndr_err = ndr_pull_uint16(ndr, NDR_SCALARS, &if_version);
     919        7648 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     920           0 :                 talloc_free(mem_ctx);
     921           0 :                 return ndr_map_error2ntstatus(ndr_err);
     922             :         }
     923             : 
     924        7648 :         syntax->if_version = if_version;
     925             : 
     926        7648 :         talloc_free(mem_ctx);
     927             : 
     928        7648 :         return NT_STATUS_OK;
     929             : }
     930             : 
     931      769920 : static DATA_BLOB dcerpc_floor_pack_lhs_data(TALLOC_CTX *mem_ctx, const struct ndr_syntax_id *syntax)
     932             : {
     933             :         DATA_BLOB blob;
     934             :         enum ndr_err_code ndr_err;
     935             :         struct ndr_push *ndr;
     936             : 
     937      769920 :         ndr = ndr_push_init_ctx(mem_ctx);
     938      769920 :         if (ndr == NULL) {
     939           0 :                 return data_blob_null;
     940             :         }
     941             : 
     942      769920 :         ndr->flags |= LIBNDR_FLAG_NOALIGN;
     943             : 
     944      769920 :         ndr_err = ndr_push_GUID(ndr, NDR_SCALARS | NDR_BUFFERS, &syntax->uuid);
     945      769920 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     946           0 :                 return data_blob_null;
     947             :         }
     948      769920 :         ndr_err = ndr_push_uint16(ndr, NDR_SCALARS, syntax->if_version);
     949      769920 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     950           0 :                 return data_blob_null;
     951             :         }
     952             : 
     953      769920 :         blob = ndr_push_blob(ndr);
     954      769920 :         talloc_steal(mem_ctx, blob.data);
     955      769920 :         talloc_free(ndr);
     956      769920 :         return blob;
     957             : }
     958             : 
     959      384960 : static bool dcerpc_floor_pack_rhs_if_version_data(
     960             :         TALLOC_CTX *mem_ctx, const struct ndr_syntax_id *syntax,
     961             :         DATA_BLOB *pblob)
     962             : {
     963             :         DATA_BLOB blob;
     964      384960 :         struct ndr_push *ndr = ndr_push_init_ctx(mem_ctx);
     965             :         enum ndr_err_code ndr_err;
     966             : 
     967      384960 :         if (ndr == NULL) {
     968           0 :                 return false;
     969             :         }
     970             : 
     971      384960 :         ndr->flags |= LIBNDR_FLAG_NOALIGN;
     972             : 
     973      384960 :         ndr_err = ndr_push_uint16(ndr, NDR_SCALARS, syntax->if_version >> 16);
     974      384960 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     975           0 :                 return false;
     976             :         }
     977             : 
     978      384960 :         blob = ndr_push_blob(ndr);
     979      384960 :         talloc_steal(mem_ctx, blob.data);
     980      384960 :         talloc_free(ndr);
     981      384960 :         *pblob = blob;
     982      384960 :         return true;
     983             : }
     984             : 
     985        5280 : char *dcerpc_floor_get_rhs_data(TALLOC_CTX *mem_ctx, struct epm_floor *epm_floor)
     986             : {
     987        5280 :         switch (epm_floor->lhs.protocol) {
     988        4561 :         case EPM_PROTOCOL_TCP:
     989        4561 :                 if (epm_floor->rhs.tcp.port == 0) return NULL;
     990        4561 :                 return talloc_asprintf(mem_ctx, "%d", epm_floor->rhs.tcp.port);
     991             : 
     992           0 :         case EPM_PROTOCOL_UDP:
     993           0 :                 if (epm_floor->rhs.udp.port == 0) return NULL;
     994           0 :                 return talloc_asprintf(mem_ctx, "%d", epm_floor->rhs.udp.port);
     995             : 
     996           0 :         case EPM_PROTOCOL_HTTP:
     997           0 :                 if (epm_floor->rhs.http.port == 0) return NULL;
     998           0 :                 return talloc_asprintf(mem_ctx, "%d", epm_floor->rhs.http.port);
     999             : 
    1000           4 :         case EPM_PROTOCOL_IP:
    1001           4 :                 return talloc_strdup(mem_ctx, epm_floor->rhs.ip.ipaddr);
    1002             : 
    1003           0 :         case EPM_PROTOCOL_NCACN:
    1004           0 :                 return NULL;
    1005             : 
    1006           0 :         case EPM_PROTOCOL_NCADG:
    1007           0 :                 return NULL;
    1008             : 
    1009          16 :         case EPM_PROTOCOL_SMB:
    1010          16 :                 if (strlen(epm_floor->rhs.smb.unc) == 0) return NULL;
    1011          16 :                 return talloc_strdup(mem_ctx, epm_floor->rhs.smb.unc);
    1012             : 
    1013         683 :         case EPM_PROTOCOL_NAMED_PIPE:
    1014         683 :                 if (strlen(epm_floor->rhs.named_pipe.path) == 0) return NULL;
    1015         683 :                 return talloc_strdup(mem_ctx, epm_floor->rhs.named_pipe.path);
    1016             : 
    1017          16 :         case EPM_PROTOCOL_NETBIOS:
    1018          16 :                 if (strlen(epm_floor->rhs.netbios.name) == 0) return NULL;
    1019           0 :                 return talloc_strdup(mem_ctx, epm_floor->rhs.netbios.name);
    1020             : 
    1021           0 :         case EPM_PROTOCOL_NCALRPC:
    1022           0 :                 return NULL;
    1023             : 
    1024           0 :         case EPM_PROTOCOL_VINES_SPP:
    1025           0 :                 return talloc_asprintf(mem_ctx, "%d", epm_floor->rhs.vines_spp.port);
    1026             : 
    1027           0 :         case EPM_PROTOCOL_VINES_IPC:
    1028           0 :                 return talloc_asprintf(mem_ctx, "%d", epm_floor->rhs.vines_ipc.port);
    1029             : 
    1030           0 :         case EPM_PROTOCOL_STREETTALK:
    1031           0 :                 return talloc_strdup(mem_ctx, epm_floor->rhs.streettalk.streettalk);
    1032             : 
    1033           0 :         case EPM_PROTOCOL_UNIX_DS:
    1034           0 :                 if (strlen(epm_floor->rhs.unix_ds.path) == 0) return NULL;
    1035           0 :                 return talloc_strdup(mem_ctx, epm_floor->rhs.unix_ds.path);
    1036             : 
    1037           0 :         case EPM_PROTOCOL_NULL:
    1038           0 :                 return NULL;
    1039             : 
    1040           0 :         default:
    1041           0 :                 DEBUG(0,("Unsupported lhs protocol %d\n", epm_floor->lhs.protocol));
    1042           0 :                 break;
    1043             :         }
    1044             : 
    1045           0 :         return NULL;
    1046             : }
    1047             : 
    1048     1456439 : static NTSTATUS dcerpc_floor_set_rhs_data(TALLOC_CTX *mem_ctx, 
    1049             :                                           struct epm_floor *epm_floor,  
    1050             :                                           const char *data)
    1051             : {
    1052     1456439 :         if (data == NULL) {
    1053     1071925 :                 data = "";
    1054             :         }
    1055             : 
    1056     1456439 :         switch (epm_floor->lhs.protocol) {
    1057      218734 :         case EPM_PROTOCOL_TCP:
    1058      218734 :                 epm_floor->rhs.tcp.port = atoi(data);
    1059      337615 :                 return NT_STATUS_OK;
    1060             : 
    1061           0 :         case EPM_PROTOCOL_UDP:
    1062           0 :                 epm_floor->rhs.udp.port = atoi(data);
    1063           0 :                 return NT_STATUS_OK;
    1064             : 
    1065       24776 :         case EPM_PROTOCOL_HTTP:
    1066       24776 :                 epm_floor->rhs.http.port = atoi(data);
    1067       24776 :                 return NT_STATUS_OK;
    1068             : 
    1069      128541 :         case EPM_PROTOCOL_IP:
    1070      128541 :                 if (!is_ipaddress_v4(data)) {
    1071      127960 :                         data = "0.0.0.0";
    1072             :                 }
    1073      128541 :                 epm_floor->rhs.ip.ipaddr = talloc_strdup(mem_ctx, data);
    1074      128541 :                 NT_STATUS_HAVE_NO_MEMORY(epm_floor->rhs.ip.ipaddr);
    1075      128541 :                 return NT_STATUS_OK;
    1076             : 
    1077      302005 :         case EPM_PROTOCOL_NCACN:
    1078      302005 :                 epm_floor->rhs.ncacn.minor_version = 0;
    1079      302005 :                 return NT_STATUS_OK;
    1080             : 
    1081           0 :         case EPM_PROTOCOL_NCADG:
    1082           0 :                 epm_floor->rhs.ncadg.minor_version = 0;
    1083           0 :                 return NT_STATUS_OK;
    1084             : 
    1085      356042 :         case EPM_PROTOCOL_SMB:
    1086      356042 :                 epm_floor->rhs.smb.unc = talloc_strdup(mem_ctx, data);
    1087      356042 :                 NT_STATUS_HAVE_NO_MEMORY(epm_floor->rhs.smb.unc);
    1088      356042 :                 return NT_STATUS_OK;
    1089             : 
    1090      165333 :         case EPM_PROTOCOL_NAMED_PIPE:
    1091      165333 :                 epm_floor->rhs.named_pipe.path = talloc_strdup(mem_ctx, data);
    1092      165333 :                 NT_STATUS_HAVE_NO_MEMORY(epm_floor->rhs.named_pipe.path);
    1093      165333 :                 return NT_STATUS_OK;
    1094             : 
    1095      178053 :         case EPM_PROTOCOL_NETBIOS:
    1096      178053 :                 epm_floor->rhs.netbios.name = talloc_strdup(mem_ctx, data);
    1097      178053 :                 NT_STATUS_HAVE_NO_MEMORY(epm_floor->rhs.netbios.name);
    1098      178053 :                 return NT_STATUS_OK;
    1099             : 
    1100       82955 :         case EPM_PROTOCOL_NCALRPC:
    1101       82955 :                 return NT_STATUS_OK;
    1102             : 
    1103           0 :         case EPM_PROTOCOL_VINES_SPP:
    1104           0 :                 epm_floor->rhs.vines_spp.port = atoi(data);
    1105           0 :                 return NT_STATUS_OK;
    1106             : 
    1107           0 :         case EPM_PROTOCOL_VINES_IPC:
    1108           0 :                 epm_floor->rhs.vines_ipc.port = atoi(data);
    1109           0 :                 return NT_STATUS_OK;
    1110             : 
    1111           0 :         case EPM_PROTOCOL_STREETTALK:
    1112           0 :                 epm_floor->rhs.streettalk.streettalk = talloc_strdup(mem_ctx, data);
    1113           0 :                 NT_STATUS_HAVE_NO_MEMORY(epm_floor->rhs.streettalk.streettalk);
    1114           0 :                 return NT_STATUS_OK;
    1115             : 
    1116           0 :         case EPM_PROTOCOL_UNIX_DS:
    1117           0 :                 epm_floor->rhs.unix_ds.path = talloc_strdup(mem_ctx, data);
    1118           0 :                 NT_STATUS_HAVE_NO_MEMORY(epm_floor->rhs.unix_ds.path);
    1119           0 :                 return NT_STATUS_OK;
    1120             : 
    1121           0 :         case EPM_PROTOCOL_NULL:
    1122           0 :                 return NT_STATUS_OK;
    1123             : 
    1124           0 :         default:
    1125           0 :                 DEBUG(0,("Unsupported lhs protocol %d\n", epm_floor->lhs.protocol));
    1126           0 :                 break;
    1127             :         }
    1128             : 
    1129           0 :         return NT_STATUS_NOT_SUPPORTED;
    1130             : }
    1131             : 
    1132           0 : enum dcerpc_transport_t dcerpc_transport_by_endpoint_protocol(int prot)
    1133             : {
    1134             :         size_t i;
    1135             : 
    1136             :         /* Find a transport that has 'prot' as 4th protocol */
    1137           0 :         for (i=0;i<ARRAY_SIZE(transports);i++) {
    1138           0 :                 if (transports[i].num_protocols >= 2 && 
    1139           0 :                         transports[i].protseq[1] == prot) {
    1140           0 :                         return transports[i].transport;
    1141             :                 }
    1142             :         }
    1143             : 
    1144             :         /* Unknown transport */
    1145           0 :         return (unsigned int)-1;
    1146             : }
    1147             : 
    1148       24521 : _PUBLIC_ enum dcerpc_transport_t dcerpc_transport_by_tower(const struct epm_tower *tower)
    1149             : {
    1150             :         size_t i;
    1151             : 
    1152             :         /* Find a transport that matches this tower */
    1153       55381 :         for (i=0;i<ARRAY_SIZE(transports);i++) {
    1154             :                 int j;
    1155       55249 :                 if (transports[i].num_protocols != tower->num_floors - 2) {
    1156       18732 :                         continue; 
    1157             :                 }
    1158             : 
    1159      116997 :                 for (j = 0; j < transports[i].num_protocols && j < MAX_PROTSEQ; j++) {
    1160       92608 :                         if (transports[i].protseq[j] != tower->floors[j+2].lhs.protocol) {
    1161       12128 :                                 break;
    1162             :                         }
    1163             :                 }
    1164             : 
    1165       36517 :                 if (j == transports[i].num_protocols) {
    1166       24389 :                         return transports[i].transport;
    1167             :                 }
    1168             :         }
    1169             : 
    1170             :         /* Unknown transport */
    1171         132 :         return (unsigned int)-1;
    1172             : }
    1173             : 
    1174       16197 : _PUBLIC_ const char *derpc_transport_string_by_transport(enum dcerpc_transport_t t)
    1175             : {
    1176             :         size_t i;
    1177             : 
    1178       30516 :         for (i=0; i<ARRAY_SIZE(transports); i++) {
    1179       30516 :                 if (t == transports[i].transport) {
    1180       16197 :                         return transports[i].name;
    1181             :                 }
    1182             :         }
    1183           0 :         return NULL;
    1184             : }
    1185             : 
    1186       76407 : _PUBLIC_ enum dcerpc_transport_t dcerpc_transport_by_name(const char *name)
    1187             : {
    1188             :         size_t i;
    1189             : 
    1190       76407 :         if (name == NULL) {
    1191           0 :                 return NCA_UNKNOWN;
    1192             :         }
    1193             : 
    1194      148981 :         for (i=0; i<ARRAY_SIZE(transports);i++) {
    1195      148981 :                 if (strcasecmp(name, transports[i].name) == 0) {
    1196       76407 :                         return transports[i].transport;
    1197             :                 }
    1198             :         }
    1199             : 
    1200           0 :         return NCA_UNKNOWN;
    1201             : }
    1202             : 
    1203          20 : _PUBLIC_ NTSTATUS dcerpc_binding_from_tower(TALLOC_CTX *mem_ctx,
    1204             :                                             struct epm_tower *tower,
    1205             :                                             struct dcerpc_binding **b_out)
    1206             : {
    1207             :         NTSTATUS status;
    1208             :         struct dcerpc_binding *b;
    1209             :         enum dcerpc_transport_t transport;
    1210             :         struct ndr_syntax_id abstract_syntax;
    1211          20 :         char *endpoint = NULL;
    1212          20 :         char *host = NULL;
    1213             : 
    1214             :         /*
    1215             :          * A tower needs to have at least 4 floors to carry useful
    1216             :          * information. Floor 3 is the transport identifier which defines
    1217             :          * how many floors are required at least.
    1218             :          */
    1219          20 :         if (tower->num_floors < 4) {
    1220           0 :                 return NT_STATUS_INVALID_PARAMETER;
    1221             :         }
    1222             : 
    1223          20 :         status = dcerpc_parse_binding(mem_ctx, "", &b);
    1224          20 :         if (!NT_STATUS_IS_OK(status)) {
    1225           0 :                 return status;
    1226             :         }
    1227             : 
    1228          20 :         transport = dcerpc_transport_by_tower(tower);
    1229          20 :         if (transport == NCA_UNKNOWN) {
    1230           0 :                 talloc_free(b);
    1231           0 :                 return NT_STATUS_NOT_SUPPORTED;
    1232             :         }
    1233             : 
    1234          20 :         status = dcerpc_binding_set_transport(b, transport);
    1235          20 :         if (!NT_STATUS_IS_OK(status)) {
    1236           0 :                 talloc_free(b);
    1237           0 :                 return status;
    1238             :         }
    1239             : 
    1240             :         /* Set abstract syntax */
    1241          20 :         status = dcerpc_floor_get_lhs_data(&tower->floors[0], &abstract_syntax);
    1242          20 :         if (!NT_STATUS_IS_OK(status)) {
    1243           0 :                 talloc_free(b);
    1244           0 :                 return status;
    1245             :         }
    1246             : 
    1247          20 :         status = dcerpc_binding_set_abstract_syntax(b, &abstract_syntax);
    1248          20 :         if (!NT_STATUS_IS_OK(status)) {
    1249           0 :                 talloc_free(b);
    1250           0 :                 return status;
    1251             :         }
    1252             : 
    1253             :         /* Ignore floor 1, it contains the NDR version info */
    1254             : 
    1255             :         /* Set endpoint */
    1256          20 :         errno = 0;
    1257          20 :         if (tower->num_floors >= 4) {
    1258          20 :                 endpoint = dcerpc_floor_get_rhs_data(b, &tower->floors[3]);
    1259             :         }
    1260          20 :         if (errno != 0) {
    1261           0 :                 int saved_errno = errno;
    1262           0 :                 talloc_free(b);
    1263           0 :                 return map_nt_error_from_unix_common(saved_errno);
    1264             :         }
    1265             : 
    1266          20 :         status = dcerpc_binding_set_string_option(b, "endpoint", endpoint);
    1267          20 :         if (!NT_STATUS_IS_OK(status)) {
    1268           0 :                 talloc_free(b);
    1269           0 :                 return status;
    1270             :         }
    1271          20 :         TALLOC_FREE(endpoint);
    1272             : 
    1273             :         /* Set network address */
    1274          20 :         errno = 0;
    1275          20 :         if (tower->num_floors >= 5) {
    1276          20 :                 host = dcerpc_floor_get_rhs_data(b, &tower->floors[4]);
    1277             :         }
    1278          20 :         if (errno != 0) {
    1279           0 :                 int saved_errno = errno;
    1280           0 :                 talloc_free(b);
    1281           0 :                 return map_nt_error_from_unix_common(saved_errno);
    1282             :         }
    1283             : 
    1284          20 :         status = dcerpc_binding_set_string_option(b, "host", host);
    1285          20 :         if (!NT_STATUS_IS_OK(status)) {
    1286           0 :                 talloc_free(b);
    1287           0 :                 return status;
    1288             :         }
    1289          20 :         status = dcerpc_binding_set_string_option(b, "target_hostname", host);
    1290          20 :         if (!NT_STATUS_IS_OK(status)) {
    1291           0 :                 talloc_free(b);
    1292           0 :                 return status;
    1293             :         }
    1294          20 :         TALLOC_FREE(host);
    1295             : 
    1296          20 :         *b_out = b;
    1297          20 :         return NT_STATUS_OK;
    1298             : }
    1299             : 
    1300      431450 : _PUBLIC_ struct dcerpc_binding *dcerpc_binding_dup(TALLOC_CTX *mem_ctx,
    1301             :                                                    const struct dcerpc_binding *b)
    1302             : {
    1303             :         struct dcerpc_binding *n;
    1304             :         uint32_t count;
    1305             : 
    1306      431450 :         n = talloc_zero(mem_ctx, struct dcerpc_binding);
    1307      431450 :         if (n == NULL) {
    1308           0 :                 return NULL;
    1309             :         }
    1310             : 
    1311      431450 :         n->transport = b->transport;
    1312      431450 :         n->object = b->object;
    1313      431450 :         n->flags = b->flags;
    1314      431450 :         n->assoc_group_id = b->assoc_group_id;
    1315             : 
    1316      431450 :         if (b->object_string != NULL) {
    1317           0 :                 n->object_string = talloc_strdup(n, b->object_string);
    1318           0 :                 if (n->object_string == NULL) {
    1319           0 :                         goto nomem;
    1320             :                 }
    1321             :         }
    1322      431450 :         if (b->host != NULL) {
    1323       49416 :                 n->host = talloc_strdup(n, b->host);
    1324       49416 :                 if (n->host == NULL) {
    1325           0 :                         goto nomem;
    1326             :                 }
    1327             :         }
    1328             : 
    1329      431450 :         if (b->target_hostname != NULL) {
    1330       49416 :                 n->target_hostname = talloc_strdup(n, b->target_hostname);
    1331       49416 :                 if (n->target_hostname == NULL) {
    1332           0 :                         goto nomem;
    1333             :                 }
    1334             :         }
    1335             : 
    1336      431450 :         if (b->target_principal != NULL) {
    1337       15627 :                 n->target_principal = talloc_strdup(n, b->target_principal);
    1338       15627 :                 if (n->target_principal == NULL) {
    1339           0 :                         goto nomem;
    1340             :                 }
    1341             :         }
    1342             : 
    1343      431450 :         if (b->endpoint != NULL) {
    1344      398453 :                 n->endpoint = talloc_strdup(n, b->endpoint);
    1345      398453 :                 if (n->endpoint == NULL) {
    1346           0 :                         goto nomem;
    1347             :                 }
    1348             :         }
    1349             : 
    1350      436182 :         for (count = 0; b->options && b->options[count]; count++);
    1351             : 
    1352      431450 :         if (count > 0) {
    1353             :                 uint32_t i;
    1354             : 
    1355       37550 :                 n->options = talloc_array(n, const char *, count + 1);
    1356       37550 :                 if (n->options == NULL) {
    1357           0 :                         goto nomem;
    1358             :                 }
    1359             : 
    1360       87759 :                 for (i = 0; i < count; i++) {
    1361       50209 :                         n->options[i] = talloc_strdup(n->options, b->options[i]);
    1362       50209 :                         if (n->options[i] == NULL) {
    1363           0 :                                 goto nomem;
    1364             :                         }
    1365             :                 }
    1366       37550 :                 n->options[count] = NULL;
    1367             :         }
    1368             : 
    1369      431450 :         return n;
    1370           0 : nomem:
    1371           0 :         TALLOC_FREE(n);
    1372           0 :         return NULL;
    1373             : }
    1374             : 
    1375      384960 : _PUBLIC_ NTSTATUS dcerpc_binding_build_tower(TALLOC_CTX *mem_ctx,
    1376             :                                              const struct dcerpc_binding *binding,
    1377             :                                              struct epm_tower *tower)
    1378             : {
    1379      384960 :         const enum epm_protocol *protseq = NULL;
    1380      384960 :         size_t i, num_protocols = 0;
    1381             :         struct ndr_syntax_id abstract_syntax;
    1382             :         NTSTATUS status;
    1383             : 
    1384             :         /* Find transport */
    1385      853152 :         for (i=0;i<ARRAY_SIZE(transports);i++) {
    1386      853152 :                 if (transports[i].transport == binding->transport) {
    1387      384960 :                         protseq = transports[i].protseq;
    1388      384960 :                         num_protocols = transports[i].num_protocols;
    1389      384960 :                         break;
    1390             :                 }
    1391             :         }
    1392             : 
    1393      384960 :         if (i == ARRAY_SIZE(transports)) {
    1394           0 :                 DEBUG(0, ("Unable to find transport with id '%d'\n", binding->transport));
    1395           0 :                 return NT_STATUS_UNSUCCESSFUL;
    1396             :         }
    1397             : 
    1398      384960 :         tower->num_floors = 2 + num_protocols;
    1399      384960 :         tower->floors = talloc_array(mem_ctx, struct epm_floor, tower->num_floors);
    1400      384960 :         if (tower->floors == NULL) {
    1401           0 :                 return NT_STATUS_NO_MEMORY;
    1402             :         }
    1403             : 
    1404             :         /* Floor 0 */
    1405      384960 :         tower->floors[0].lhs.protocol = EPM_PROTOCOL_UUID;
    1406             : 
    1407      384960 :         abstract_syntax = dcerpc_binding_get_abstract_syntax(binding);
    1408      384960 :         tower->floors[0].lhs.lhs_data = dcerpc_floor_pack_lhs_data(tower->floors,
    1409             :                                                                    &abstract_syntax);
    1410             : 
    1411      732926 :         if (!dcerpc_floor_pack_rhs_if_version_data(
    1412      384960 :                     tower->floors, &abstract_syntax,
    1413      384960 :                     &tower->floors[0].rhs.uuid.unknown)) {
    1414           0 :                 return NT_STATUS_NO_MEMORY;
    1415             :         }
    1416             : 
    1417             :         /* Floor 1 */
    1418      384960 :         tower->floors[1].lhs.protocol = EPM_PROTOCOL_UUID;
    1419             : 
    1420      384960 :         tower->floors[1].lhs.lhs_data = dcerpc_floor_pack_lhs_data(tower->floors, 
    1421             :                                                                 &ndr_transfer_syntax_ndr);
    1422             : 
    1423      384960 :         tower->floors[1].rhs.uuid.unknown = data_blob_talloc_zero(tower->floors, 2);
    1424             : 
    1425             :         /* Floor 2 to num_protocols */
    1426     1456885 :         for (i = 0; i < num_protocols; i++) {
    1427     1071925 :                 tower->floors[2 + i].lhs.protocol = protseq[i];
    1428     1071925 :                 tower->floors[2 + i].lhs.lhs_data = data_blob_null;
    1429     1071925 :                 ZERO_STRUCT(tower->floors[2 + i].rhs);
    1430     1071925 :                 status = dcerpc_floor_set_rhs_data(tower->floors,
    1431     1071925 :                                                    &tower->floors[2 + i],
    1432             :                                                    NULL);
    1433     1071925 :                 if (!NT_STATUS_IS_OK(status)) {
    1434           0 :                         return status;
    1435             :                 }
    1436             :         }
    1437             : 
    1438             :         /* The 4th floor contains the endpoint */
    1439      384960 :         if (num_protocols >= 2 && binding->endpoint) {
    1440      723324 :                 status = dcerpc_floor_set_rhs_data(tower->floors,
    1441      379925 :                                                    &tower->floors[3],
    1442       36526 :                                                    binding->endpoint);
    1443      379925 :                 if (!NT_STATUS_IS_OK(status)) {
    1444           0 :                         return status;
    1445             :                 }
    1446             :         }
    1447             : 
    1448             :         /* The 5th contains the network address */
    1449      384960 :         if (num_protocols >= 3 && binding->host) {
    1450        8815 :                 status = dcerpc_floor_set_rhs_data(tower->floors,
    1451        4589 :                                                    &tower->floors[4],
    1452         363 :                                                    binding->host);
    1453        4589 :                 if (!NT_STATUS_IS_OK(status)) {
    1454           0 :                         return status;
    1455             :                 }
    1456             :         }
    1457             : 
    1458      384960 :         return NT_STATUS_OK;
    1459             : }

Generated by: LCOV version 1.13