r3123: Add dcerpc_binding_build_tower()
authorJelmer Vernooij <jelmer@samba.org>
Thu, 21 Oct 2004 19:54:38 +0000 (19:54 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:02:23 +0000 (13:02 -0500)
Add local test for testing the functions dcerpc_parse_binding(),
dcerpc_binding_string() and dcerpc_binding_build_tower()

source/librpc/idl/epmapper.idl
source/librpc/rpc/dcerpc_util.c
source/torture/config.mk
source/torture/local/binding_string.c [new file with mode: 0644]
source/torture/torture.c

index 81f9b0976c24447bac3ceb9aac3cf6703b578e88..e1e980b0fd8f12a65323b43460b3e0a995c6e486 100644 (file)
@@ -151,7 +151,7 @@ interface epmapper
        } epm_rhs_null;
 
        typedef struct {
-               astring identifier;
+               uint16 minor_version;
        } epm_rhs_ncalrpc;
 
        typedef struct {
index bded74c40708833b24270f4bbf133f9f3a03ffd8..3b4f7a7efb331379b69b6677b62d0ab2cb6ba60c 100644 (file)
@@ -247,8 +247,8 @@ static const struct {
                { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_IP, EPM_PROTOCOL_TCP } }, 
        { "ncadg_ip_udp", NCACN_IP_UDP, 3, 
                { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_IP, EPM_PROTOCOL_UDP } },
-       { "ncalrpc", NCALRPC, 1
-               { EPM_PROTOCOL_NCALRPC } },
+       { "ncalrpc", NCALRPC, 2
+               { EPM_PROTOCOL_NCALRPC, EPM_PROTOCOL_PIPE } },
        { "ncacn_unix_stream", NCACN_UNIX_STREAM, 2, 
                { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_UNIX_DS } },
        { "ncadg_unix_dgram", NCADG_UNIX_DGRAM, 2, 
@@ -276,6 +276,8 @@ static const struct {
        {"bigendian", DCERPC_PUSH_BIGENDIAN}
 };
 
+
+
 /*
   form a binding string from a binding structure
 */
@@ -298,26 +300,31 @@ const char *dcerpc_binding_string(TALLOC_CTX *mem_ctx, const struct dcerpc_bindi
                s = talloc_asprintf(mem_ctx, "%s@", GUID_string(mem_ctx, b->object));
        }
 
-       s = talloc_asprintf_append(s, "%s:%s[", t_name, b->host);
+       s = talloc_asprintf_append(s, "%s:%s", t_name, b->host);
        if (!s) return NULL;
 
+       if ((!b->options || !b->options[0]) && !b->flags) {
+               return s;
+       }
+
+       s = talloc_asprintf_append(s, "[");
+
        /* this is a *really* inefficent way of dealing with strings,
           but this is rarely called and the strings are always short,
           so I don't care */
        for (i=0;b->options && b->options[i];i++) {
-               s = talloc_asprintf(mem_ctx, "%s%s,", s, b->options[i]);
+               s = talloc_asprintf_append(s, "%s,", b->options[i]);
                if (!s) return NULL;
        }
        for (i=0;i<ARRAY_SIZE(ncacn_options);i++) {
                if (b->flags & ncacn_options[i].flag) {
-                       s = talloc_asprintf(mem_ctx, "%s%s,", s, ncacn_options[i].name);
+                       s = talloc_asprintf_append(s, "%s,", ncacn_options[i].name);
                        if (!s) return NULL;
                }
        }
-       if (s[strlen(s)-1] == ',') {
-               s[strlen(s)-1] = 0;
-       }
-       s = talloc_asprintf(mem_ctx, "%s]", s);
+
+       s[strlen(s)-1] = 0;
+       s = talloc_asprintf_append(s, "]");
 
        return s;
 }
@@ -431,6 +438,173 @@ NTSTATUS dcerpc_parse_binding(TALLOC_CTX *mem_ctx, const char *s, struct dcerpc_
        return NT_STATUS_OK;
 }
 
+static NTSTATUS floor_set_rhs_data(TALLOC_CTX *mem_ctx, struct epm_floor *floor,  const char *data)
+{
+       switch (floor->lhs.protocol) {
+       case EPM_PROTOCOL_TCP:
+               floor->rhs.tcp.port = atoi(data);
+               return NT_STATUS_OK;
+               
+       case EPM_PROTOCOL_UDP:
+               floor->rhs.udp.port = atoi(data);
+               return NT_STATUS_OK;
+
+       case EPM_PROTOCOL_HTTP:
+               floor->rhs.http.port = atoi(data);
+               return NT_STATUS_OK;
+
+       case EPM_PROTOCOL_IP:
+               floor->rhs.ip.address = 0;
+
+               /* Only try to put in a IPv4 address. Windows 2003 just returns 
+                * 0.0.0.0 for IPv6 addresses */
+               if (strlen(data) > 0) {
+                   struct addrinfo hints, *res;
+
+                       memset(&hints, 0, sizeof(struct addrinfo));
+
+                       hints.ai_family = AF_INET;
+
+                       if (getaddrinfo(data, NULL, &hints, &res) < 0) {
+                               return NT_STATUS_BAD_NETWORK_NAME;
+                       }
+
+                       floor->rhs.ip.address = ntohl(((struct in_addr *)res->ai_addr)->s_addr);
+
+                       freeaddrinfo(res);
+               }
+               return NT_STATUS_OK;
+
+       case EPM_PROTOCOL_NCACN:
+               floor->rhs.ncacn.minor_version = 0;
+               return NT_STATUS_OK;
+
+       case EPM_PROTOCOL_NCADG:
+               floor->rhs.ncadg.minor_version = 0;
+               return NT_STATUS_OK;
+
+       case EPM_PROTOCOL_SMB:
+               floor->rhs.smb.unc = talloc_strdup(mem_ctx, data);
+               if (!floor->rhs.smb.unc) {
+                       return NT_STATUS_NO_MEMORY;
+               }
+               return NT_STATUS_OK;
+
+       case EPM_PROTOCOL_PIPE:
+               floor->rhs.pipe.path = talloc_strdup(mem_ctx, data);
+               if (!floor->rhs.pipe.path) {
+                       return NT_STATUS_NO_MEMORY;
+               }
+               return NT_STATUS_OK;
+
+       case EPM_PROTOCOL_NETBIOS:
+               floor->rhs.netbios.name = talloc_strdup(mem_ctx, data);
+               if (!floor->rhs.netbios.name) {
+                       return NT_STATUS_NO_MEMORY;
+               }
+               return NT_STATUS_OK;
+
+       case EPM_PROTOCOL_NCALRPC:
+               return NT_STATUS_OK;
+               
+       case EPM_PROTOCOL_VINES_SPP:
+               floor->rhs.vines_spp.port = atoi(data);
+               return NT_STATUS_OK;
+               
+       case EPM_PROTOCOL_VINES_IPC:
+               floor->rhs.vines_ipc.port = atoi(data);
+               return NT_STATUS_OK;
+               
+       case EPM_PROTOCOL_STREETTALK:
+               floor->rhs.streettalk.streettalk = talloc_strdup(mem_ctx, data);
+               if (!floor->rhs.streettalk.streettalk) {
+                       return NT_STATUS_NO_MEMORY;
+               }
+               return NT_STATUS_OK;
+               
+       case EPM_PROTOCOL_UNIX_DS:
+               floor->rhs.unix_ds.path = talloc_strdup(mem_ctx, data);
+               if (!floor->rhs.unix_ds.path) {
+                       return NT_STATUS_NO_MEMORY;
+               }
+               return NT_STATUS_OK;
+               
+       case EPM_PROTOCOL_NULL:
+               return NT_STATUS_OK;
+       }
+
+       return NT_STATUS_NOT_SUPPORTED;
+}
+
+
+NTSTATUS dcerpc_binding_build_tower(TALLOC_CTX *mem_ctx, struct dcerpc_binding *binding, struct epm_tower **tower)
+{
+       const enum epm_protocols *protseq;
+       int num_protocols = -1, i;
+       NTSTATUS status;
+       
+       *tower = talloc_p(mem_ctx, struct epm_tower);
+
+       if (!(*tower)) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       /* Find transport */
+       for (i=0;i<ARRAY_SIZE(transports);i++) {
+               if (transports[i].transport == binding->transport) {
+                       protseq = transports[i].protseq;
+                       num_protocols = transports[i].num_protocols;
+                       break;
+               }
+       }
+
+       if (num_protocols == -1) {
+               DEBUG(0, ("Unable to find transport with id '%d'\n", binding->transport));
+               return NT_STATUS_UNSUCCESSFUL;
+       }
+
+       (*tower)->num_floors = 2 + num_protocols;
+       (*tower)->floors = talloc_array_p(mem_ctx, struct epm_floor, (*tower)->num_floors);
+
+       /* Floor 0 */
+       (*tower)->floors[0].lhs.protocol = EPM_PROTOCOL_UUID;
+       if (binding->object) {
+               (*tower)->floors[0].lhs.info.uuid.uuid = *binding->object;
+       }
+       (*tower)->floors[0].lhs.info.uuid.version = 0;
+       
+       /* Floor 1 */
+       (*tower)->floors[1].lhs.protocol = EPM_PROTOCOL_UUID;
+       (*tower)->floors[1].lhs.info.uuid.version = NDR_GUID_VERSION;
+       status = GUID_from_string(NDR_GUID, &(*tower)->floors[1].lhs.info.uuid.uuid);
+       if (NT_STATUS_IS_ERR(status)) {
+               return status;
+       }
+
+       /* Floor 2 to num_protocols */
+       for (i = 0; i < num_protocols; i++) {
+               (*tower)->floors[2 + i].lhs.protocol = protseq[i];
+       }
+
+       /* The top floor contains the endpoint */
+       if (num_protocols >= 1 && binding->options && binding->options[0]) {
+               status = floor_set_rhs_data(mem_ctx, &(*tower)->floors[2 + num_protocols - 1], binding->options[0]);
+               if (NT_STATUS_IS_ERR(status)) {
+                       return status;
+               }
+       }
+
+       /* The second-to-top floor contains the network address */
+       if (num_protocols >= 2 && binding->host) {
+               status = floor_set_rhs_data(mem_ctx, &(*tower)->floors[2 + num_protocols - 2], binding->host);
+               if (NT_STATUS_IS_ERR(status)) {
+                       return status;
+               }
+       }
+
+       return NT_STATUS_OK;
+}
+
 
 /* open a rpc connection to a rpc pipe on SMB using the binding
    structure to determine the endpoint and options */
@@ -722,7 +896,7 @@ NTSTATUS dcerpc_generic_session_key(struct dcerpc_pipe *p,
                                    DATA_BLOB *session_key)
 {
        /* this took quite a few CPU cycles to find ... */
-       session_key->data = discard_const_p(char, "SystemLibraryDTC");
+       session_key->data = discard_const_p(unsigned char, "SystemLibraryDTC");
        session_key->length = 16;
        return NT_STATUS_OK;
 }
index 9967696c24b8ad888d155b0cb75e44a52f67b5de..e64d041889383c4e3da41a15af23032a0f8f39a8 100644 (file)
@@ -103,7 +103,8 @@ REQUIRED_SUBSYSTEMS = \
 ADD_OBJ_FILES = \
                torture/local/iconv.o \
                torture/local/talloc.o \
-               torture/local/messaging.o
+               torture/local/messaging.o \
+               torture/local/binding_string.o
 REQUIRED_SUBSYSTEMS = \
                LIBSMB \
                MESSAGING
diff --git a/source/torture/local/binding_string.c b/source/torture/local/binding_string.c
new file mode 100644 (file)
index 0000000..26fe67d
--- /dev/null
@@ -0,0 +1,81 @@
+/* 
+   Unix SMB/CIFS implementation.
+
+   local testing of RPC binding string parsing 
+
+   Copyright (C) Jelmer Vernooij 2004
+   
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+
+static BOOL test_BindingString(const char *binding)
+{
+       TALLOC_CTX *mem_ctx = talloc_init("test_BindingString");
+       struct dcerpc_binding b;
+       const char *s;
+       struct epm_tower *tower;
+       NTSTATUS status;
+
+       /* Parse */
+       status = dcerpc_parse_binding(mem_ctx, binding, &b);
+       if (NT_STATUS_IS_ERR(status)) {
+               DEBUG(0, ("Error parsing binding string '%s': %s\n", binding, nt_errstr(status)));
+               return False;
+       }
+
+       s = dcerpc_binding_string(mem_ctx, &b);
+       if (!s) {
+               DEBUG(0, ("Error converting binding back to string for '%s'\n", binding)); 
+               return False;
+       }
+
+       if (strcasecmp(binding, s) != 0) {
+               DEBUG(0, ("Mismatch while comparing original and regenerated binding strings: '%s' <> '%s'\n", binding, s));
+               return False;
+       }
+
+       /* Generate protocol towers */
+       status = dcerpc_binding_build_tower(mem_ctx, &b, &tower);
+       if (NT_STATUS_IS_ERR(status)) {
+               DEBUG(0, ("Error generating protocol tower from '%s': %s\n", binding, nt_errstr(status)));
+               return False;
+       }
+
+       /* FIXME: Convert back to binding and then back to string and compare */
+
+       return True;
+}
+
+BOOL torture_local_binding_string(int dummy) 
+{
+       BOOL ret = True;
+
+       ret &= test_BindingString("ncacn_np:");
+       ret &= test_BindingString("ncalrpc:");
+       ret &= test_BindingString("ncalrpc:");
+       ret &= test_BindingString("ncacn_np:[rpcecho]");
+       ret &= test_BindingString("ncacn_np:127.0.0.1[rpcecho]");
+       ret &= test_BindingString("ncacn_np:localhost[rpcecho]");
+       ret &= test_BindingString("ncacn_np:[/pipe/rpcecho]");
+       ret &= test_BindingString("ncacn_np:localhost[/pipe/rpcecho,sign,seal]");
+       ret &= test_BindingString("ncacn_np:[,sign]");
+       ret &= test_BindingString("ncadg_ip_udp:");
+       ret &= test_BindingString("308FB580-1EB2-11CA-923B-08002B1075A7@ncacn_np:localhost");
+       ret &= test_BindingString("308FB580-1EB2-11CA-923B-08002B1075A7@ncacn_ip_tcp:localhost");
+
+       return ret;
+}
index 5992bfc6332091009caa420b0ac35212d6d36b79..cb639da653ed5238731af75783c1909add232a43 100644 (file)
@@ -3471,6 +3471,7 @@ static struct {
        {"LOCAL-ICONV", torture_local_iconv, 0},
        {"LOCAL-TALLOC", torture_local_talloc, 0},
        {"LOCAL-MESSAGING", torture_local_messaging, 0},
+       {"LOCAL-BINDINGSTRING", torture_local_binding_string, 0},
 
        /* ldap testers */
        {"LDAP-BASIC", torture_ldap_basic, 0},