root/librpc/rpc/binding.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. epm_floor_string
  2. dcerpc_binding_string
  3. dcerpc_parse_binding
  4. dcerpc_floor_get_lhs_data
  5. dcerpc_floor_pack_lhs_data
  6. dcerpc_floor_get_rhs_data
  7. dcerpc_floor_set_rhs_data
  8. dcerpc_transport_by_endpoint_protocol
  9. dcerpc_transport_by_tower
  10. derpc_transport_string_by_transport
  11. dcerpc_binding_from_tower
  12. dcerpc_binding_build_tower

   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 
  11    This program is free software; you can redistribute it and/or modify
  12    it under the terms of the GNU General Public License as published by
  13    the Free Software Foundation; either version 3 of the License, or
  14    (at your option) any later version.
  15 
  16    This program is distributed in the hope that it will be useful,
  17    but WITHOUT ANY WARRANTY; without even the implied warranty of
  18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19    GNU General Public License for more details.
  20 
  21    You should have received a copy of the GNU General Public License
  22    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  23 */
  24 
  25 #include "includes.h"
  26 #include "librpc/gen_ndr/ndr_epmapper.h"
  27 #include "librpc/gen_ndr/ndr_misc.h"
  28 #include "librpc/rpc/dcerpc.h"
  29 #undef strcasecmp
  30 
  31 #define MAX_PROTSEQ             10
  32 
  33 static const struct {
  34         const char *name;
  35         enum dcerpc_transport_t transport;
  36         int num_protocols;
  37         enum epm_protocol protseq[MAX_PROTSEQ];
  38 } transports[] = {
  39         { "ncacn_np",     NCACN_NP, 3, 
  40                 { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_SMB, EPM_PROTOCOL_NETBIOS }},
  41         { "ncacn_ip_tcp", NCACN_IP_TCP, 3, 
  42                 { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_TCP, EPM_PROTOCOL_IP } }, 
  43         { "ncacn_http", NCACN_HTTP, 3, 
  44                 { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_HTTP, EPM_PROTOCOL_IP } }, 
  45         { "ncadg_ip_udp", NCACN_IP_UDP, 3, 
  46                 { EPM_PROTOCOL_NCADG, EPM_PROTOCOL_UDP, EPM_PROTOCOL_IP } },
  47         { "ncalrpc", NCALRPC, 2, 
  48                 { EPM_PROTOCOL_NCALRPC, EPM_PROTOCOL_PIPE } },
  49         { "ncacn_unix_stream", NCACN_UNIX_STREAM, 2, 
  50                 { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_UNIX_DS } },
  51         { "ncadg_unix_dgram", NCADG_UNIX_DGRAM, 2, 
  52                 { EPM_PROTOCOL_NCADG, EPM_PROTOCOL_UNIX_DS } },
  53         { "ncacn_at_dsp", NCACN_AT_DSP, 3, 
  54                 { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_APPLETALK, EPM_PROTOCOL_DSP } },
  55         { "ncadg_at_ddp", NCADG_AT_DDP, 3, 
  56                 { EPM_PROTOCOL_NCADG, EPM_PROTOCOL_APPLETALK, EPM_PROTOCOL_DDP } },
  57         { "ncacn_vns_ssp", NCACN_VNS_SPP, 3, 
  58                 { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_STREETTALK, EPM_PROTOCOL_VINES_SPP } },
  59         { "ncacn_vns_ipc", NCACN_VNS_IPC, 3, 
  60                 { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_STREETTALK, EPM_PROTOCOL_VINES_IPC }, },
  61         { "ncadg_ipx", NCADG_IPX, 2,
  62                 { EPM_PROTOCOL_NCADG, EPM_PROTOCOL_IPX },
  63         },
  64         { "ncacn_spx", NCACN_SPX, 3,
  65                 /* I guess some MS programmer confused the identifier for 
  66                  * EPM_PROTOCOL_UUID (0x0D or 13) with the one for 
  67                  * EPM_PROTOCOL_SPX (0x13) here. -- jelmer*/
  68                 { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_NCALRPC, EPM_PROTOCOL_UUID },
  69         },
  70 };
  71 
  72 static const struct {
  73         const char *name;
  74         uint32_t flag;
  75 } ncacn_options[] = {
  76         {"sign", DCERPC_SIGN},
  77         {"seal", DCERPC_SEAL},
  78         {"connect", DCERPC_CONNECT},
  79         {"spnego", DCERPC_AUTH_SPNEGO},
  80         {"ntlm", DCERPC_AUTH_NTLM},
  81         {"krb5", DCERPC_AUTH_KRB5},
  82         {"validate", DCERPC_DEBUG_VALIDATE_BOTH},
  83         {"print", DCERPC_DEBUG_PRINT_BOTH},
  84         {"padcheck", DCERPC_DEBUG_PAD_CHECK},
  85         {"bigendian", DCERPC_PUSH_BIGENDIAN},
  86         {"smb2", DCERPC_SMB2},
  87         {"hdrsign", DCERPC_HEADER_SIGNING}
  88 };
  89 
  90 const char *epm_floor_string(TALLOC_CTX *mem_ctx, struct epm_floor *epm_floor)
     /* [<][>][^][v][top][bottom][index][help] */
  91 {
  92         struct ndr_syntax_id syntax;
  93         NTSTATUS status;
  94 
  95         switch(epm_floor->lhs.protocol) {
  96                 case EPM_PROTOCOL_UUID:
  97                         status = dcerpc_floor_get_lhs_data(epm_floor, &syntax);
  98                         if (NT_STATUS_IS_OK(status)) {
  99                                 /* lhs is used: UUID */
 100                                 char *uuidstr;
 101 
 102                                 if (GUID_equal(&syntax.uuid, &ndr_transfer_syntax.uuid)) {
 103                                         return "NDR";
 104                                 } 
 105 
 106                                 if (GUID_equal(&syntax.uuid, &ndr64_transfer_syntax.uuid)) {
 107                                         return "NDR64";
 108                                 } 
 109 
 110                                 uuidstr = GUID_string(mem_ctx, &syntax.uuid);
 111 
 112                                 return talloc_asprintf(mem_ctx, " uuid %s/0x%02x", uuidstr, syntax.if_version);
 113                         } else { /* IPX */
 114                                 return talloc_asprintf(mem_ctx, "IPX:%s", 
 115                                                 data_blob_hex_string(mem_ctx, &epm_floor->rhs.uuid.unknown));
 116                         }
 117 
 118                 case EPM_PROTOCOL_NCACN:
 119                         return "RPC-C";
 120 
 121                 case EPM_PROTOCOL_NCADG:
 122                         return "RPC";
 123 
 124                 case EPM_PROTOCOL_NCALRPC:
 125                         return "NCALRPC";
 126 
 127                 case EPM_PROTOCOL_DNET_NSP:
 128                         return "DNET/NSP";
 129 
 130                 case EPM_PROTOCOL_IP:
 131                         return talloc_asprintf(mem_ctx, "IP:%s", epm_floor->rhs.ip.ipaddr);
 132 
 133                 case EPM_PROTOCOL_PIPE:
 134                         return talloc_asprintf(mem_ctx, "PIPE:%s", epm_floor->rhs.pipe.path);
 135 
 136                 case EPM_PROTOCOL_SMB:
 137                         return talloc_asprintf(mem_ctx, "SMB:%s", epm_floor->rhs.smb.unc);
 138 
 139                 case EPM_PROTOCOL_UNIX_DS:
 140                         return talloc_asprintf(mem_ctx, "Unix:%s", epm_floor->rhs.unix_ds.path);
 141 
 142                 case EPM_PROTOCOL_NETBIOS:
 143                         return talloc_asprintf(mem_ctx, "NetBIOS:%s", epm_floor->rhs.netbios.name);
 144 
 145                 case EPM_PROTOCOL_NETBEUI:
 146                         return "NETBeui";
 147 
 148                 case EPM_PROTOCOL_SPX:
 149                         return "SPX";
 150 
 151                 case EPM_PROTOCOL_NB_IPX:
 152                         return "NB_IPX";
 153 
 154                 case EPM_PROTOCOL_HTTP:
 155                         return talloc_asprintf(mem_ctx, "HTTP:%d", epm_floor->rhs.http.port);
 156 
 157                 case EPM_PROTOCOL_TCP:
 158                         return talloc_asprintf(mem_ctx, "TCP:%d", epm_floor->rhs.tcp.port);
 159 
 160                 case EPM_PROTOCOL_UDP:
 161                         return talloc_asprintf(mem_ctx, "UDP:%d", epm_floor->rhs.udp.port);
 162 
 163                 default:
 164                         return talloc_asprintf(mem_ctx, "UNK(%02x):", epm_floor->lhs.protocol);
 165         }
 166 }
 167 
 168 
 169 /*
 170   form a binding string from a binding structure
 171 */
 172 _PUBLIC_ char *dcerpc_binding_string(TALLOC_CTX *mem_ctx, const struct dcerpc_binding *b)
     /* [<][>][^][v][top][bottom][index][help] */
 173 {
 174         char *s = talloc_strdup(mem_ctx, "");
 175         int i;
 176         const char *t_name = NULL;
 177 
 178         if (b->transport != NCA_UNKNOWN) {
 179                 t_name = derpc_transport_string_by_transport(b->transport);
 180                 if (!t_name) {
 181                         return NULL;
 182                 }
 183         }
 184 
 185         if (!GUID_all_zero(&b->object.uuid)) { 
 186                 s = talloc_asprintf(s, "%s@",
 187                                     GUID_string(mem_ctx, &b->object.uuid));
 188         }
 189 
 190         if (t_name != NULL) {
 191                 s = talloc_asprintf_append_buffer(s, "%s:", t_name);
 192                 if (s == NULL) {
 193                         return NULL;
 194                 }
 195         }
 196 
 197         if (b->host) {
 198                 s = talloc_asprintf_append_buffer(s, "%s", b->host);
 199         }
 200 
 201         if (!b->endpoint && !b->options && !b->flags) {
 202                 return s;
 203         }
 204 
 205         s = talloc_asprintf_append_buffer(s, "[");
 206 
 207         if (b->endpoint) {
 208                 s = talloc_asprintf_append_buffer(s, "%s", b->endpoint);
 209         }
 210 
 211         /* this is a *really* inefficent way of dealing with strings,
 212            but this is rarely called and the strings are always short,
 213            so I don't care */
 214         for (i=0;b->options && b->options[i];i++) {
 215                 s = talloc_asprintf_append_buffer(s, ",%s", b->options[i]);
 216                 if (!s) return NULL;
 217         }
 218 
 219         for (i=0;i<ARRAY_SIZE(ncacn_options);i++) {
 220                 if (b->flags & ncacn_options[i].flag) {
 221                         s = talloc_asprintf_append_buffer(s, ",%s", ncacn_options[i].name);
 222                         if (!s) return NULL;
 223                 }
 224         }
 225 
 226         s = talloc_asprintf_append_buffer(s, "]");
 227 
 228         return s;
 229 }
 230 
 231 /*
 232   parse a binding string into a dcerpc_binding structure
 233 */
 234 _PUBLIC_ NTSTATUS dcerpc_parse_binding(TALLOC_CTX *mem_ctx, const char *s, struct dcerpc_binding **b_out)
     /* [<][>][^][v][top][bottom][index][help] */
 235 {
 236         struct dcerpc_binding *b;
 237         char *options;
 238         char *p;
 239         int i, j, comma_count;
 240 
 241         b = talloc(mem_ctx, struct dcerpc_binding);
 242         if (!b) {
 243                 return NT_STATUS_NO_MEMORY;
 244         }
 245 
 246         p = strchr(s, '@');
 247 
 248         if (p && PTR_DIFF(p, s) == 36) { /* 36 is the length of a UUID */
 249                 NTSTATUS status;
 250                 DATA_BLOB blob = data_blob(s, 36);
 251                 status = GUID_from_data_blob(&blob, &b->object.uuid);
 252 
 253                 if (NT_STATUS_IS_ERR(status)) {
 254                         DEBUG(0, ("Failed parsing UUID\n"));
 255                         return status;
 256                 }
 257 
 258                 s = p + 1;
 259         } else {
 260                 ZERO_STRUCT(b->object);
 261         }
 262 
 263         b->object.if_version = 0;
 264 
 265         p = strchr(s, ':');
 266 
 267         if (p == NULL) {
 268                 b->transport = NCA_UNKNOWN;
 269         } else {
 270                 char *type = talloc_strndup(mem_ctx, s, PTR_DIFF(p, s));
 271                 if (!type) {
 272                         return NT_STATUS_NO_MEMORY;
 273                 }
 274 
 275                 for (i=0;i<ARRAY_SIZE(transports);i++) {
 276                         if (strcasecmp(type, transports[i].name) == 0) {
 277                                 b->transport = transports[i].transport;
 278                                 break;
 279                         }
 280                 }
 281 
 282                 if (i==ARRAY_SIZE(transports)) {
 283                         DEBUG(0,("Unknown dcerpc transport '%s'\n", type));
 284                         return NT_STATUS_INVALID_PARAMETER;
 285                 }
 286 
 287                 talloc_free(type);
 288 
 289                 s = p+1;
 290         }
 291 
 292         p = strchr(s, '[');
 293         if (p) {
 294                 b->host = talloc_strndup(b, s, PTR_DIFF(p, s));
 295                 options = talloc_strdup(mem_ctx, p+1);
 296                 if (options[strlen(options)-1] != ']') {
 297                         return NT_STATUS_INVALID_PARAMETER;
 298                 }
 299                 options[strlen(options)-1] = 0;
 300         } else {
 301                 b->host = talloc_strdup(b, s);
 302                 options = NULL;
 303         }
 304         if (!b->host) {
 305                 return NT_STATUS_NO_MEMORY;
 306         }
 307 
 308         b->target_hostname = b->host;
 309 
 310         b->options = NULL;
 311         b->flags = 0;
 312         b->assoc_group_id = 0;
 313         b->endpoint = NULL;
 314 
 315         if (!options) {
 316                 *b_out = b;
 317                 return NT_STATUS_OK;
 318         }
 319 
 320         comma_count = count_chars(options, ',');
 321 
 322         b->options = talloc_array(b, const char *, comma_count+2);
 323         if (!b->options) {
 324                 return NT_STATUS_NO_MEMORY;
 325         }
 326 
 327         for (i=0; (p = strchr(options, ',')); i++) {
 328                 b->options[i] = talloc_strndup(b, options, PTR_DIFF(p, options));
 329                 if (!b->options[i]) {
 330                         return NT_STATUS_NO_MEMORY;
 331                 }
 332                 options = p+1;
 333         }
 334         b->options[i] = options;
 335         b->options[i+1] = NULL;
 336 
 337         /* some options are pre-parsed for convenience */
 338         for (i=0;b->options[i];i++) {
 339                 for (j=0;j<ARRAY_SIZE(ncacn_options);j++) {
 340                         if (strcasecmp(ncacn_options[j].name, b->options[i]) == 0) {
 341                                 int k;
 342                                 b->flags |= ncacn_options[j].flag;
 343                                 for (k=i;b->options[k];k++) {
 344                                         b->options[k] = b->options[k+1];
 345                                 }
 346                                 i--;
 347                                 break;
 348                         }
 349                 }
 350         }
 351 
 352         if (b->options[0]) {
 353                 /* Endpoint is first option */
 354                 b->endpoint = b->options[0];
 355                 if (strlen(b->endpoint) == 0) b->endpoint = NULL;
 356 
 357                 for (i=0;b->options[i];i++) {
 358                         b->options[i] = b->options[i+1];
 359                 }
 360         }
 361 
 362         if (b->options[0] == NULL)
 363                 b->options = NULL;
 364 
 365         *b_out = b;
 366         return NT_STATUS_OK;
 367 }
 368 
 369 _PUBLIC_ NTSTATUS dcerpc_floor_get_lhs_data(const struct epm_floor *epm_floor,
     /* [<][>][^][v][top][bottom][index][help] */
 370                                             struct ndr_syntax_id *syntax)
 371 {
 372         TALLOC_CTX *mem_ctx = talloc_init("floor_get_lhs_data");
 373         struct ndr_pull *ndr;
 374         enum ndr_err_code ndr_err;
 375         uint16_t if_version=0;
 376 
 377         ndr = ndr_pull_init_blob(&epm_floor->lhs.lhs_data, mem_ctx, NULL);
 378         if (ndr == NULL) {
 379                 talloc_free(mem_ctx);
 380                 return NT_STATUS_NO_MEMORY;
 381         }
 382         ndr->flags |= LIBNDR_FLAG_NOALIGN;
 383 
 384         ndr_err = ndr_pull_GUID(ndr, NDR_SCALARS | NDR_BUFFERS, &syntax->uuid);
 385         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
 386                 talloc_free(mem_ctx);
 387                 return ndr_map_error2ntstatus(ndr_err);
 388         }
 389 
 390         ndr_err = ndr_pull_uint16(ndr, NDR_SCALARS, &if_version);
 391         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
 392                 talloc_free(mem_ctx);
 393                 return ndr_map_error2ntstatus(ndr_err);
 394         }
 395 
 396         syntax->if_version = if_version;
 397 
 398         talloc_free(mem_ctx);
 399 
 400         return NT_STATUS_OK;
 401 }
 402 
 403 static DATA_BLOB dcerpc_floor_pack_lhs_data(TALLOC_CTX *mem_ctx, const struct ndr_syntax_id *syntax)
     /* [<][>][^][v][top][bottom][index][help] */
 404 {
 405         struct ndr_push *ndr = ndr_push_init_ctx(mem_ctx, NULL);
 406 
 407         ndr->flags |= LIBNDR_FLAG_NOALIGN;
 408 
 409         ndr_push_GUID(ndr, NDR_SCALARS | NDR_BUFFERS, &syntax->uuid);
 410         ndr_push_uint16(ndr, NDR_SCALARS, syntax->if_version);
 411 
 412         return ndr_push_blob(ndr);
 413 }
 414 
 415 const char *dcerpc_floor_get_rhs_data(TALLOC_CTX *mem_ctx, struct epm_floor *epm_floor)
     /* [<][>][^][v][top][bottom][index][help] */
 416 {
 417         switch (epm_floor->lhs.protocol) {
 418         case EPM_PROTOCOL_TCP:
 419                 if (epm_floor->rhs.tcp.port == 0) return NULL;
 420                 return talloc_asprintf(mem_ctx, "%d", epm_floor->rhs.tcp.port);
 421 
 422         case EPM_PROTOCOL_UDP:
 423                 if (epm_floor->rhs.udp.port == 0) return NULL;
 424                 return talloc_asprintf(mem_ctx, "%d", epm_floor->rhs.udp.port);
 425 
 426         case EPM_PROTOCOL_HTTP:
 427                 if (epm_floor->rhs.http.port == 0) return NULL;
 428                 return talloc_asprintf(mem_ctx, "%d", epm_floor->rhs.http.port);
 429 
 430         case EPM_PROTOCOL_IP:
 431                 return talloc_strdup(mem_ctx, epm_floor->rhs.ip.ipaddr);
 432 
 433         case EPM_PROTOCOL_NCACN:
 434                 return NULL;
 435 
 436         case EPM_PROTOCOL_NCADG:
 437                 return NULL;
 438 
 439         case EPM_PROTOCOL_SMB:
 440                 if (strlen(epm_floor->rhs.smb.unc) == 0) return NULL;
 441                 return talloc_strdup(mem_ctx, epm_floor->rhs.smb.unc);
 442 
 443         case EPM_PROTOCOL_PIPE:
 444                 if (strlen(epm_floor->rhs.pipe.path) == 0) return NULL;
 445                 return talloc_strdup(mem_ctx, epm_floor->rhs.pipe.path);
 446 
 447         case EPM_PROTOCOL_NETBIOS:
 448                 if (strlen(epm_floor->rhs.netbios.name) == 0) return NULL;
 449                 return talloc_strdup(mem_ctx, epm_floor->rhs.netbios.name);
 450 
 451         case EPM_PROTOCOL_NCALRPC:
 452                 return NULL;
 453 
 454         case EPM_PROTOCOL_VINES_SPP:
 455                 return talloc_asprintf(mem_ctx, "%d", epm_floor->rhs.vines_spp.port);
 456 
 457         case EPM_PROTOCOL_VINES_IPC:
 458                 return talloc_asprintf(mem_ctx, "%d", epm_floor->rhs.vines_ipc.port);
 459 
 460         case EPM_PROTOCOL_STREETTALK:
 461                 return talloc_strdup(mem_ctx, epm_floor->rhs.streettalk.streettalk);
 462 
 463         case EPM_PROTOCOL_UNIX_DS:
 464                 if (strlen(epm_floor->rhs.unix_ds.path) == 0) return NULL;
 465                 return talloc_strdup(mem_ctx, epm_floor->rhs.unix_ds.path);
 466 
 467         case EPM_PROTOCOL_NULL:
 468                 return NULL;
 469 
 470         default:
 471                 DEBUG(0,("Unsupported lhs protocol %d\n", epm_floor->lhs.protocol));
 472                 break;
 473         }
 474 
 475         return NULL;
 476 }
 477 
 478 static NTSTATUS dcerpc_floor_set_rhs_data(TALLOC_CTX *mem_ctx, 
     /* [<][>][^][v][top][bottom][index][help] */
 479                                           struct epm_floor *epm_floor,  
 480                                           const char *data)
 481 {
 482         switch (epm_floor->lhs.protocol) {
 483         case EPM_PROTOCOL_TCP:
 484                 epm_floor->rhs.tcp.port = atoi(data);
 485                 return NT_STATUS_OK;
 486 
 487         case EPM_PROTOCOL_UDP:
 488                 epm_floor->rhs.udp.port = atoi(data);
 489                 return NT_STATUS_OK;
 490 
 491         case EPM_PROTOCOL_HTTP:
 492                 epm_floor->rhs.http.port = atoi(data);
 493                 return NT_STATUS_OK;
 494 
 495         case EPM_PROTOCOL_IP:
 496                 epm_floor->rhs.ip.ipaddr = talloc_strdup(mem_ctx, data);
 497                 NT_STATUS_HAVE_NO_MEMORY(epm_floor->rhs.ip.ipaddr);
 498                 return NT_STATUS_OK;
 499 
 500         case EPM_PROTOCOL_NCACN:
 501                 epm_floor->rhs.ncacn.minor_version = 0;
 502                 return NT_STATUS_OK;
 503 
 504         case EPM_PROTOCOL_NCADG:
 505                 epm_floor->rhs.ncadg.minor_version = 0;
 506                 return NT_STATUS_OK;
 507 
 508         case EPM_PROTOCOL_SMB:
 509                 epm_floor->rhs.smb.unc = talloc_strdup(mem_ctx, data);
 510                 NT_STATUS_HAVE_NO_MEMORY(epm_floor->rhs.smb.unc);
 511                 return NT_STATUS_OK;
 512 
 513         case EPM_PROTOCOL_PIPE:
 514                 epm_floor->rhs.pipe.path = talloc_strdup(mem_ctx, data);
 515                 NT_STATUS_HAVE_NO_MEMORY(epm_floor->rhs.pipe.path);
 516                 return NT_STATUS_OK;
 517 
 518         case EPM_PROTOCOL_NETBIOS:
 519                 epm_floor->rhs.netbios.name = talloc_strdup(mem_ctx, data);
 520                 NT_STATUS_HAVE_NO_MEMORY(epm_floor->rhs.netbios.name);
 521                 return NT_STATUS_OK;
 522 
 523         case EPM_PROTOCOL_NCALRPC:
 524                 return NT_STATUS_OK;
 525 
 526         case EPM_PROTOCOL_VINES_SPP:
 527                 epm_floor->rhs.vines_spp.port = atoi(data);
 528                 return NT_STATUS_OK;
 529 
 530         case EPM_PROTOCOL_VINES_IPC:
 531                 epm_floor->rhs.vines_ipc.port = atoi(data);
 532                 return NT_STATUS_OK;
 533 
 534         case EPM_PROTOCOL_STREETTALK:
 535                 epm_floor->rhs.streettalk.streettalk = talloc_strdup(mem_ctx, data);
 536                 NT_STATUS_HAVE_NO_MEMORY(epm_floor->rhs.streettalk.streettalk);
 537                 return NT_STATUS_OK;
 538 
 539         case EPM_PROTOCOL_UNIX_DS:
 540                 epm_floor->rhs.unix_ds.path = talloc_strdup(mem_ctx, data);
 541                 NT_STATUS_HAVE_NO_MEMORY(epm_floor->rhs.unix_ds.path);
 542                 return NT_STATUS_OK;
 543 
 544         case EPM_PROTOCOL_NULL:
 545                 return NT_STATUS_OK;
 546 
 547         default:
 548                 DEBUG(0,("Unsupported lhs protocol %d\n", epm_floor->lhs.protocol));
 549                 break;
 550         }
 551 
 552         return NT_STATUS_NOT_SUPPORTED;
 553 }
 554 
 555 enum dcerpc_transport_t dcerpc_transport_by_endpoint_protocol(int prot)
     /* [<][>][^][v][top][bottom][index][help] */
 556 {
 557         int i;
 558 
 559         /* Find a transport that has 'prot' as 4th protocol */
 560         for (i=0;i<ARRAY_SIZE(transports);i++) {
 561                 if (transports[i].num_protocols >= 2 && 
 562                         transports[i].protseq[1] == prot) {
 563                         return transports[i].transport;
 564                 }
 565         }
 566 
 567         /* Unknown transport */
 568         return (unsigned int)-1;
 569 }
 570 
 571 _PUBLIC_ enum dcerpc_transport_t dcerpc_transport_by_tower(const struct epm_tower *tower)
     /* [<][>][^][v][top][bottom][index][help] */
 572 {
 573         int i;
 574 
 575         /* Find a transport that matches this tower */
 576         for (i=0;i<ARRAY_SIZE(transports);i++) {
 577                 int j;
 578                 if (transports[i].num_protocols != tower->num_floors - 2) {
 579                         continue; 
 580                 }
 581 
 582                 for (j = 0; j < transports[i].num_protocols; j++) {
 583                         if (transports[i].protseq[j] != tower->floors[j+2].lhs.protocol) {
 584                                 break;
 585                         }
 586                 }
 587 
 588                 if (j == transports[i].num_protocols) {
 589                         return transports[i].transport;
 590                 }
 591         }
 592 
 593         /* Unknown transport */
 594         return (unsigned int)-1;
 595 }
 596 
 597 _PUBLIC_ const char *derpc_transport_string_by_transport(enum dcerpc_transport_t t)
     /* [<][>][^][v][top][bottom][index][help] */
 598 {
 599         int i;
 600 
 601         for (i=0; i<ARRAY_SIZE(transports); i++) {
 602                 if (t == transports[i].transport) {
 603                         return transports[i].name;
 604                 }
 605         }
 606         return NULL;
 607 }
 608 
 609 _PUBLIC_ NTSTATUS dcerpc_binding_from_tower(TALLOC_CTX *mem_ctx, 
     /* [<][>][^][v][top][bottom][index][help] */
 610                                    struct epm_tower *tower, 
 611                                    struct dcerpc_binding **b_out)
 612 {
 613         NTSTATUS status;
 614         struct dcerpc_binding *binding;
 615 
 616         binding = talloc(mem_ctx, struct dcerpc_binding);
 617         NT_STATUS_HAVE_NO_MEMORY(binding);
 618 
 619         ZERO_STRUCT(binding->object);
 620         binding->options = NULL;
 621         binding->host = NULL;
 622         binding->target_hostname = NULL;
 623         binding->flags = 0;
 624         binding->assoc_group_id = 0;
 625 
 626         binding->transport = dcerpc_transport_by_tower(tower);
 627 
 628         if (binding->transport == (unsigned int)-1) {
 629                 return NT_STATUS_NOT_SUPPORTED;
 630         }
 631 
 632         if (tower->num_floors < 1) {
 633                 return NT_STATUS_OK;
 634         }
 635 
 636         /* Set object uuid */
 637         status = dcerpc_floor_get_lhs_data(&tower->floors[0], &binding->object);
 638 
 639         if (!NT_STATUS_IS_OK(status)) {
 640                 DEBUG(1, ("Error pulling object uuid and version: %s", nt_errstr(status)));     
 641                 return status;
 642         }
 643 
 644         /* Ignore floor 1, it contains the NDR version info */
 645 
 646         binding->options = NULL;
 647 
 648         /* Set endpoint */
 649         if (tower->num_floors >= 4) {
 650                 binding->endpoint = dcerpc_floor_get_rhs_data(mem_ctx, &tower->floors[3]);
 651         } else {
 652                 binding->endpoint = NULL;
 653         }
 654 
 655         /* Set network address */
 656         if (tower->num_floors >= 5) {
 657                 binding->host = dcerpc_floor_get_rhs_data(mem_ctx, &tower->floors[4]);
 658                 NT_STATUS_HAVE_NO_MEMORY(binding->host);
 659                 binding->target_hostname = binding->host;
 660         }
 661         *b_out = binding;
 662         return NT_STATUS_OK;
 663 }
 664 
 665 _PUBLIC_ NTSTATUS dcerpc_binding_build_tower(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 666                                              const struct dcerpc_binding *binding,
 667                                              struct epm_tower *tower)
 668 {
 669         const enum epm_protocol *protseq = NULL;
 670         int num_protocols = -1, i;
 671         NTSTATUS status;
 672 
 673         /* Find transport */
 674         for (i=0;i<ARRAY_SIZE(transports);i++) {
 675                 if (transports[i].transport == binding->transport) {
 676                         protseq = transports[i].protseq;
 677                         num_protocols = transports[i].num_protocols;
 678                         break;
 679                 }
 680         }
 681 
 682         if (num_protocols == -1) {
 683                 DEBUG(0, ("Unable to find transport with id '%d'\n", binding->transport));
 684                 return NT_STATUS_UNSUCCESSFUL;
 685         }
 686 
 687         tower->num_floors = 2 + num_protocols;
 688         tower->floors = talloc_array(mem_ctx, struct epm_floor, tower->num_floors);
 689 
 690         /* Floor 0 */
 691         tower->floors[0].lhs.protocol = EPM_PROTOCOL_UUID;
 692 
 693         tower->floors[0].lhs.lhs_data = dcerpc_floor_pack_lhs_data(mem_ctx, &binding->object);
 694 
 695         tower->floors[0].rhs.uuid.unknown = data_blob_talloc_zero(mem_ctx, 2);
 696 
 697         /* Floor 1 */
 698         tower->floors[1].lhs.protocol = EPM_PROTOCOL_UUID;
 699 
 700         tower->floors[1].lhs.lhs_data = dcerpc_floor_pack_lhs_data(mem_ctx, 
 701                                                                 &ndr_transfer_syntax);
 702 
 703         tower->floors[1].rhs.uuid.unknown = data_blob_talloc_zero(mem_ctx, 2);
 704 
 705         /* Floor 2 to num_protocols */
 706         for (i = 0; i < num_protocols; i++) {
 707                 tower->floors[2 + i].lhs.protocol = protseq[i];
 708                 tower->floors[2 + i].lhs.lhs_data = data_blob_talloc(mem_ctx, NULL, 0);
 709                 ZERO_STRUCT(tower->floors[2 + i].rhs);
 710                 dcerpc_floor_set_rhs_data(mem_ctx, &tower->floors[2 + i], "");
 711         }
 712 
 713         /* The 4th floor contains the endpoint */
 714         if (num_protocols >= 2 && binding->endpoint) {
 715                 status = dcerpc_floor_set_rhs_data(mem_ctx, &tower->floors[3], binding->endpoint);
 716                 if (NT_STATUS_IS_ERR(status)) {
 717                         return status;
 718                 }
 719         }
 720 
 721         /* The 5th contains the network address */
 722         if (num_protocols >= 3 && binding->host) {
 723                 if (is_ipaddress(binding->host)) {
 724                         status = dcerpc_floor_set_rhs_data(mem_ctx, &tower->floors[4], 
 725                                                            binding->host);
 726                 } else {
 727                         /* note that we don't attempt to resolve the
 728                            name here - when we get a hostname here we
 729                            are in the client code, and want to put in
 730                            a wildcard all-zeros IP for the server to
 731                            fill in */
 732                         status = dcerpc_floor_set_rhs_data(mem_ctx, &tower->floors[4], 
 733                                                            "0.0.0.0");
 734                 }
 735                 if (NT_STATUS_IS_ERR(status)) {
 736                         return status;
 737                 }
 738         }
 739 
 740         return NT_STATUS_OK;
 741 }

/* [<][>][^][v][top][bottom][index][help] */