r3124: Add dcerpc_binding_from_tower()
authorJelmer Vernooij <jelmer@samba.org>
Thu, 21 Oct 2004 21:02:51 +0000 (21:02 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:02:23 +0000 (13:02 -0500)
Add tests for dcerpc_binding_from_tower()

source/librpc/rpc/dcerpc_util.c
source/torture/local/binding_string.c

index 3b4f7a7efb331379b69b6677b62d0ab2cb6ba60c..f1b120894ed0a13fc37eb9080e2f6dd816746c58 100644 (file)
@@ -300,9 +300,13 @@ 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:", t_name);
        if (!s) return NULL;
 
+       if (b->host) {
+               s = talloc_asprintf_append(s, "%s", b->host);
+       }
+
        if ((!b->options || !b->options[0]) && !b->flags) {
                return s;
        }
@@ -438,6 +442,69 @@ NTSTATUS dcerpc_parse_binding(TALLOC_CTX *mem_ctx, const char *s, struct dcerpc_
        return NT_STATUS_OK;
 }
 
+static const char *floor_get_rhs_data(TALLOC_CTX *mem_ctx, struct epm_floor *floor)
+{
+       switch (floor->lhs.protocol) {
+       case EPM_PROTOCOL_TCP:
+               if (floor->rhs.tcp.port == 0) return NULL;
+               return talloc_asprintf(mem_ctx, "%d", floor->rhs.tcp.port);
+               
+       case EPM_PROTOCOL_UDP:
+               if (floor->rhs.udp.port == 0) return NULL;
+               return talloc_asprintf(mem_ctx, "%d", floor->rhs.udp.port);
+
+       case EPM_PROTOCOL_HTTP:
+               if (floor->rhs.http.port == 0) return NULL;
+               return talloc_asprintf(mem_ctx, "%d", floor->rhs.http.port);
+
+       case EPM_PROTOCOL_IP:
+               if (floor->rhs.ip.address == 0) {
+                       return NULL; 
+               }
+
+               {
+               struct in_addr in;
+                       in.s_addr = htonl(floor->rhs.ip.address);
+            return talloc_strdup(mem_ctx, inet_ntoa(in));
+               }
+
+       case EPM_PROTOCOL_NCACN:
+               return NULL;
+
+       case EPM_PROTOCOL_NCADG:
+               return NULL;
+
+       case EPM_PROTOCOL_SMB:
+               return talloc_strdup(mem_ctx, floor->rhs.smb.unc);
+
+       case EPM_PROTOCOL_PIPE:
+               return talloc_strdup(mem_ctx, floor->rhs.pipe.path);
+
+       case EPM_PROTOCOL_NETBIOS:
+               return talloc_strdup(mem_ctx, floor->rhs.netbios.name);
+
+       case EPM_PROTOCOL_NCALRPC:
+               return NULL;
+               
+       case EPM_PROTOCOL_VINES_SPP:
+               return talloc_asprintf(mem_ctx, "%d", floor->rhs.vines_spp.port);
+               
+       case EPM_PROTOCOL_VINES_IPC:
+               return talloc_asprintf(mem_ctx, "%d", floor->rhs.vines_ipc.port);
+               
+       case EPM_PROTOCOL_STREETTALK:
+               return talloc_strdup(mem_ctx, floor->rhs.streettalk.streettalk);
+               
+       case EPM_PROTOCOL_UNIX_DS:
+               return talloc_strdup(mem_ctx, floor->rhs.unix_ds.path);
+               
+       case EPM_PROTOCOL_NULL:
+               return NULL;
+       }
+
+       return NULL;
+}
+
 static NTSTATUS floor_set_rhs_data(TALLOC_CTX *mem_ctx, struct epm_floor *floor,  const char *data)
 {
        switch (floor->lhs.protocol) {
@@ -464,12 +531,13 @@ static NTSTATUS floor_set_rhs_data(TALLOC_CTX *mem_ctx, struct epm_floor *floor,
                        memset(&hints, 0, sizeof(struct addrinfo));
 
                        hints.ai_family = AF_INET;
+                       hints.ai_protocol = PF_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);
+                       floor->rhs.ip.address = ntohl(((struct sockaddr_in *)res->ai_addr)->sin_addr.s_addr);
 
                        freeaddrinfo(res);
                }
@@ -536,6 +604,67 @@ static NTSTATUS floor_set_rhs_data(TALLOC_CTX *mem_ctx, struct epm_floor *floor,
        return NT_STATUS_NOT_SUPPORTED;
 }
 
+NTSTATUS dcerpc_binding_from_tower(TALLOC_CTX *mem_ctx, struct epm_tower *tower, struct dcerpc_binding *binding)
+{
+       int i;
+
+       binding->transport = -1;
+       binding->object = NULL;
+       binding->options = NULL;
+       binding->host = NULL;
+       binding->flags = 0;
+
+       /* Find a transport that matches this tower */
+       for (i=0;i<ARRAY_SIZE(transports);i++) {
+               int j;
+               if (transports[i].num_protocols != tower->num_floors - 2) {
+                       continue; 
+               }
+               
+               for (j = 0; j < transports[i].num_protocols; j++) {
+                       if (transports[i].protseq[j] != tower->floors[j+2].lhs.protocol) {
+                               break;
+                       }
+               }
+
+               if (j == transports[i].num_protocols) {
+                       binding->transport = transports[i].transport;
+                       break;
+               }
+       }
+
+       if (binding->transport == -1) {
+               return NT_STATUS_NOT_SUPPORTED;
+       }
+
+       if (tower->num_floors < 1) {
+               return NT_STATUS_OK;
+       }
+
+       /* Set object uuid */
+       if (!uuid_all_zero(&tower->floors[0].lhs.info.uuid.uuid)) {
+               binding->object = talloc_p(mem_ctx, struct GUID);
+               *binding->object = tower->floors[0].lhs.info.uuid.uuid;
+       }
+
+       /* Ignore floor 1, it contains the NDR version info */
+       
+       binding->options = talloc_array_p(mem_ctx, const char *, 2);
+
+       /* Set endpoint */
+       if (tower->num_floors >= 3) {
+               binding->options[0] = floor_get_rhs_data(mem_ctx, &tower->floors[tower->num_floors-1]);
+       } else {
+               binding->options[0] = NULL;
+       }
+       binding->options[1] = NULL;
+
+       /* Set network address */
+       if (tower->num_floors >= 4) {
+               binding->host = floor_get_rhs_data(mem_ctx, &tower->floors[tower->num_floors-2]);
+       }
+       return NT_STATUS_OK;
+}
 
 NTSTATUS dcerpc_binding_build_tower(TALLOC_CTX *mem_ctx, struct dcerpc_binding *binding, struct epm_tower **tower)
 {
@@ -570,6 +699,8 @@ NTSTATUS dcerpc_binding_build_tower(TALLOC_CTX *mem_ctx, struct dcerpc_binding *
        (*tower)->floors[0].lhs.protocol = EPM_PROTOCOL_UUID;
        if (binding->object) {
                (*tower)->floors[0].lhs.info.uuid.uuid = *binding->object;
+       } else {
+               ZERO_STRUCT((*tower)->floors[0].lhs.info.uuid.uuid);
        }
        (*tower)->floors[0].lhs.info.uuid.version = 0;
        
@@ -584,6 +715,7 @@ NTSTATUS dcerpc_binding_build_tower(TALLOC_CTX *mem_ctx, struct dcerpc_binding *
        /* Floor 2 to num_protocols */
        for (i = 0; i < num_protocols; i++) {
                (*tower)->floors[2 + i].lhs.protocol = protseq[i];
+               ZERO_STRUCT((*tower)->floors[2 + i].rhs);
        }
 
        /* The top floor contains the endpoint */
index 26fe67dd5c1325a2d77737c121019c126418267e..7ec9a30d249e4e06c1978091a9020fb9508c9b0f 100644 (file)
 
 #include "includes.h"
 
-static BOOL test_BindingString(const char *binding)
+static BOOL test_BindingString(TALLOC_CTX *mem_ctx, const char *binding)
 {
-       TALLOC_CTX *mem_ctx = talloc_init("test_BindingString");
-       struct dcerpc_binding b;
-       const char *s;
+       struct dcerpc_binding b, b2;
+       const char *s, *s2;
        struct epm_tower *tower;
        NTSTATUS status;
 
@@ -55,27 +54,70 @@ static BOOL test_BindingString(const char *binding)
                return False;
        }
 
-       /* FIXME: Convert back to binding and then back to string and compare */
+       /* Convert back to binding and then back to string and compare */
+
+       status = dcerpc_binding_from_tower(mem_ctx, tower, &b2);
+       if (NT_STATUS_IS_ERR(status)) {
+               DEBUG(0, ("Error generating binding from tower for original binding '%s': %s\n", binding, nt_errstr(status)));
+               return False;
+       }
+
+       /* Compare to a stripped down version of the binding string because 
+        * the protocol tower doesn't contain the extra option data */
+       if (b.options && b.options[0]) {
+               b.options[1] = NULL; 
+       }
+
+       b.flags = 0;
+       
+       s = dcerpc_binding_string(mem_ctx, &b);
+       if (!s) {
+               DEBUG(0, ("Error converting binding back to string for (stripped down) '%s'\n", binding)); 
+               return False;
+       }
+
+
+       s2 = dcerpc_binding_string(mem_ctx, &b2);
+       if (!s) {
+               DEBUG(0, ("Error converting binding back to string for '%s'\n", binding)); 
+               return False;
+       }
+
+       if (strcasecmp(s, s2) != 0) {
+               DEBUG(0, ("Mismatch while comparing original and from protocol tower generated binding strings: '%s' <> '%s'\n", s, s2));
+               return False;
+       }
 
        return True;
 }
 
+static const char *test_strings[] = {
+       "ncacn_np:", 
+       "ncalrpc:", 
+       "ncalrpc:[Security=Sane]", 
+       "ncacn_np:[rpcecho]",
+       "ncacn_np:127.0.0.1[rpcecho]",
+       "ncacn_ip_tcp:127.0.0.1",
+       "ncacn_np:localhost[rpcecho]",
+       "ncacn_np:[/pipe/rpcecho]",
+       "ncacn_np:localhost[/pipe/rpcecho,sign,seal]",
+       "ncacn_np:[,sign]",
+       "ncadg_ip_udp:",
+       "308FB580-1EB2-11CA-923B-08002B1075A7@ncacn_np:localhost",
+       "308FB580-1EB2-11CA-923B-08002B1075A7@ncacn_ip_tcp:127.0.0.1",
+};
+
 BOOL torture_local_binding_string(int dummy) 
 {
        BOOL ret = True;
+       TALLOC_CTX *mem_ctx = talloc_init("test_BindingString");
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(test_strings); i++) {
+               ret &= test_BindingString(mem_ctx, test_strings[i]);
+       }
 
-       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");
+       talloc_destroy(mem_ctx);
 
        return ret;
 }