r3167: Add a member 'endpoint' to the dcerpc_binding struct to use instead of
authorJelmer Vernooij <jelmer@samba.org>
Sun, 24 Oct 2004 22:46:47 +0000 (22:46 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:02:28 +0000 (13:02 -0500)
options[0].

source/librpc/rpc/dcerpc.h
source/librpc/rpc/dcerpc_util.c
source/ntvfs/ipc/vfs_ipc.c
source/rpc_server/dcerpc_server.c
source/rpc_server/dcerpc_sock.c
source/torture/local/binding_string.c
source/torture/rpc/mgmt.c
source/torture/rpc/scanner.c

index 1a4b2fa34eb7a324591d40898830ea8e9a6daf0d..096ece7445452357a43b747dc60ac8cb6ea3d545 100644 (file)
@@ -148,6 +148,7 @@ struct dcerpc_binding {
        struct GUID object;
        int object_version;
        const char *host;
+       const char *endpoint;
        const char **options;
        uint32_t flags;
 };
index 3dacfee5f62326db72f850187f00a06884d2c096..88ef90cf955f1d6d4bd896f1a1b0603ba62d5ec2 100644 (file)
@@ -403,27 +403,30 @@ const char *dcerpc_binding_string(TALLOC_CTX *mem_ctx, const struct dcerpc_bindi
                s = talloc_asprintf_append(s, "%s", b->host);
        }
 
-       if ((!b->options || !b->options[0]) && !b->flags) {
+       if (!b->endpoint && !b->options && !b->flags) {
                return s;
        }
 
        s = talloc_asprintf_append(s, "[");
 
+       if (b->endpoint) {
+               s = talloc_asprintf_append(s, "%s", b->endpoint);
+       }
+
        /* 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_append(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_append(s, "%s,", ncacn_options[i].name);
+                       s = talloc_asprintf_append(s, ",%s", ncacn_options[i].name);
                        if (!s) return NULL;
                }
        }
 
-       s[strlen(s)-1] = 0;
        s = talloc_asprintf_append(s, "]");
 
        return s;
@@ -499,12 +502,14 @@ NTSTATUS dcerpc_parse_binding(TALLOC_CTX *mem_ctx, const char *s, struct dcerpc_
 
        b->options = NULL;
        b->flags = 0;
+       b->endpoint = NULL;
 
        if (!options) {
                return NT_STATUS_OK;
        }
 
        comma_count = count_chars(options, ',');
+
        b->options = talloc_array_p(mem_ctx, const char *, comma_count+2);
        if (!b->options) {
                return NT_STATUS_NO_MEMORY;
@@ -520,6 +525,14 @@ NTSTATUS dcerpc_parse_binding(TALLOC_CTX *mem_ctx, const char *s, struct dcerpc_
        b->options[i] = options;
        b->options[i+1] = NULL;
 
+       /* Endpoint is first option */
+       b->endpoint = b->options[0];
+       if (strlen(b->endpoint) == 0) b->endpoint = NULL;
+
+       for (i=0;b->options[i];i++) {
+               b->options[i] = b->options[i+1];
+       }
+
        /* some options are pre-parsed for convenience */
        for (i=0;b->options[i];i++) {
                for (j=0;j<ARRAY_SIZE(ncacn_options);j++) {
@@ -534,6 +547,9 @@ NTSTATUS dcerpc_parse_binding(TALLOC_CTX *mem_ctx, const char *s, struct dcerpc_
                        }
                }
        }
+
+       if (b->options[0] == NULL)
+               b->options = NULL;
        
        return NT_STATUS_OK;
 }
@@ -571,12 +587,15 @@ static const char *floor_get_rhs_data(TALLOC_CTX *mem_ctx, struct epm_floor *flo
                return NULL;
 
        case EPM_PROTOCOL_SMB:
+               if (strlen(floor->rhs.smb.unc) == 0) return NULL;
                return talloc_strdup(mem_ctx, floor->rhs.smb.unc);
 
        case EPM_PROTOCOL_PIPE:
+               if (strlen(floor->rhs.pipe.path) == 0) return NULL;
                return talloc_strdup(mem_ctx, floor->rhs.pipe.path);
 
        case EPM_PROTOCOL_NETBIOS:
+               if (strlen(floor->rhs.netbios.name) == 0) return NULL;
                return talloc_strdup(mem_ctx, floor->rhs.netbios.name);
 
        case EPM_PROTOCOL_NCALRPC:
@@ -592,6 +611,7 @@ static const char *floor_get_rhs_data(TALLOC_CTX *mem_ctx, struct epm_floor *flo
                return talloc_strdup(mem_ctx, floor->rhs.streettalk.streettalk);
                
        case EPM_PROTOCOL_UNIX_DS:
+               if (strlen(floor->rhs.unix_ds.path) == 0) return NULL;
                return talloc_strdup(mem_ctx, floor->rhs.unix_ds.path);
                
        case EPM_PROTOCOL_NULL:
@@ -749,15 +769,14 @@ NTSTATUS dcerpc_binding_from_tower(TALLOC_CTX *mem_ctx, struct epm_tower *tower,
 
        /* Ignore floor 1, it contains the NDR version info */
        
-       binding->options = talloc_array_p(mem_ctx, const char *, 2);
+       binding->options = NULL;
 
        /* Set endpoint */
        if (tower->num_floors >= 4) {
-               binding->options[0] = floor_get_rhs_data(mem_ctx, &tower->floors[3]);
+               binding->endpoint = floor_get_rhs_data(mem_ctx, &tower->floors[3]);
        } else {
-               binding->options[0] = NULL;
+               binding->endpoint = NULL;
        }
-       binding->options[1] = NULL;
 
        /* Set network address */
        if (tower->num_floors >= 5) {
@@ -813,8 +832,8 @@ NTSTATUS dcerpc_binding_build_tower(TALLOC_CTX *mem_ctx, struct dcerpc_binding *
        }
 
        /* The 4th floor contains the endpoint */
-       if (num_protocols >= 2 && binding->options && binding->options[0]) {
-               status = floor_set_rhs_data(mem_ctx, &tower->floors[3], binding->options[0]);
+       if (num_protocols >= 2 && binding->endpoint) {
+               status = floor_set_rhs_data(mem_ctx, &tower->floors[3], binding->endpoint);
                if (NT_STATUS_IS_ERR(status)) {
                        return status;
                }
@@ -831,6 +850,95 @@ NTSTATUS dcerpc_binding_build_tower(TALLOC_CTX *mem_ctx, struct dcerpc_binding *
        return NT_STATUS_OK;
 }
 
+NTSTATUS dcerpc_epm_map(TALLOC_CTX *mem_ctx, struct dcerpc_binding *binding,
+                                const char *uuid, uint_t version)
+{
+       struct dcerpc_pipe *p;
+       NTSTATUS status;
+       struct epm_Map r;
+       struct policy_handle handle;
+       struct GUID guid;
+       struct epm_twr_t twr, *twr_r;
+       struct dcerpc_binding epmapper_binding;
+
+
+       if (!strcmp(uuid, DCERPC_EPMAPPER_UUID)) {
+               switch(binding->transport) {
+                       case NCACN_IP_TCP: binding->endpoint = "135"/*FIXME*/; return NT_STATUS_OK;
+                       case NCALRPC: binding->endpoint = EPMAPPER_IDENTIFIER; return NT_STATUS_OK;
+                       default: return NT_STATUS_NOT_SUPPORTED;
+               }
+       }
+       
+
+       ZERO_STRUCT(epmapper_binding);
+       epmapper_binding.transport = binding->transport;
+       epmapper_binding.host = binding->host;
+       epmapper_binding.options = NULL;
+       epmapper_binding.flags = 0;
+       epmapper_binding.endpoint = NULL;
+       
+       status = dcerpc_pipe_connect_b(&p,
+                                       &epmapper_binding,
+                                  DCERPC_EPMAPPER_UUID,
+                                  DCERPC_EPMAPPER_VERSION,
+                                  NULL, NULL, NULL);
+
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+       ZERO_STRUCT(handle);
+       ZERO_STRUCT(guid);
+
+       status = GUID_from_string(uuid, &binding->object);
+       if (NT_STATUS_IS_ERR(status)) {
+               return status;
+       }
+
+       binding->object_version = version;
+
+       status = dcerpc_binding_build_tower(p, binding, &twr.tower);
+       if (NT_STATUS_IS_ERR(status)) {
+               return status;
+       }
+
+       /* with some nice pretty paper around it of course */
+       r.in.object = &guid;
+       r.in.map_tower = &twr;
+       r.in.entry_handle = &handle;
+       r.in.max_towers = 1;
+       r.out.entry_handle = &handle;
+
+       status = dcerpc_epm_Map(p, p, &r);
+       if (!NT_STATUS_IS_OK(status)) {
+               dcerpc_pipe_close(p);
+               return status;
+       }
+       if (r.out.result != 0 || r.out.num_towers != 1) {
+               dcerpc_pipe_close(p);
+               return NT_STATUS_PORT_UNREACHABLE;
+       }
+
+       twr_r = r.out.towers[0].twr;
+       if (!twr_r) {
+               dcerpc_pipe_close(p);
+               return NT_STATUS_PORT_UNREACHABLE;
+       }
+
+       if (twr_r->tower.num_floors != twr.tower.num_floors ||
+           twr_r->tower.floors[3].lhs.protocol != twr.tower.floors[3].lhs.protocol) {
+               dcerpc_pipe_close(p);
+               return NT_STATUS_PORT_UNREACHABLE;
+       }
+
+       binding->endpoint = floor_get_rhs_data(mem_ctx, &twr_r->tower.floors[3]);
+
+       dcerpc_pipe_close(p);
+
+       return NT_STATUS_OK;
+}
+
 
 /* open a rpc connection to a rpc pipe on SMB using the binding
    structure to determine the endpoint and options */
@@ -848,7 +956,7 @@ static NTSTATUS dcerpc_pipe_connect_ncacn_np(struct dcerpc_pipe **p,
        const char *pipe_name;
        TALLOC_CTX *mem_ctx = talloc_init("dcerpc_pipe_connect_ncacn_np");
        
-       if (!binding->options || !binding->options[0] || !strlen(binding->options[0])) {
+       if (!binding->endpoint) {
                const struct dcerpc_interface_table *table = idl_iface_by_uuid(pipe_uuid);
                struct dcerpc_binding default_binding;
                int i;
@@ -864,13 +972,13 @@ static NTSTATUS dcerpc_pipe_connect_ncacn_np(struct dcerpc_pipe **p,
                        status = dcerpc_parse_binding(mem_ctx, table->endpoints->names[i], &default_binding);
 
                        if (NT_STATUS_IS_OK(status) && default_binding.transport == NCACN_NP) {
-                               pipe_name = default_binding.options[0]; 
+                               pipe_name = default_binding.endpoint;   
                                break;
                                
                        }
                }
        } else {
-               pipe_name = binding->options[0];
+               pipe_name = binding->endpoint;
        }
 
        if (!strncasecmp(pipe_name, "/pipe/", 6) || 
@@ -952,30 +1060,24 @@ static NTSTATUS dcerpc_pipe_connect_ncalrpc(struct dcerpc_pipe **p,
                                                 const char *password)
 {
        NTSTATUS status;
-       const char *identifier = NULL;
        TALLOC_CTX *mem_ctx = talloc_init("dcerpc_pipe_connect_ncalrpc");
 
-       if (binding->options) {
-               identifier = binding->options[0];
-       }
-
        /* Look up identifier using the epmapper */
-       if (!identifier) {
-               status = dcerpc_epm_map_ncalrpc(mem_ctx, pipe_uuid, pipe_version,
-                                                &identifier);
+       if (!binding->endpoint) {
+               status = dcerpc_epm_map(mem_ctx, binding, pipe_uuid, pipe_version);
                if (!NT_STATUS_IS_OK(status)) {
                        DEBUG(0,("Failed to map DCERPC/TCP NCALRPC identifier for '%s' - %s\n", 
                                 pipe_uuid, nt_errstr(status)));
                        talloc_destroy(mem_ctx);
                        return status;
                }
-               DEBUG(1,("Mapped to DCERPC/TCP identifier %s\n", identifier));
+               DEBUG(1,("Mapped to DCERPC/TCP identifier %s\n", binding->endpoint));
        }
 
-       status = dcerpc_pipe_open_pipe(p, identifier);
+       status = dcerpc_pipe_open_pipe(p, binding->endpoint);
 
        if (!NT_STATUS_IS_OK(status)) {
-               DEBUG(0,("Failed to open ncalrpc pipe '%s'\n", identifier));
+               DEBUG(0,("Failed to open ncalrpc pipe '%s'\n", binding->endpoint));
                talloc_destroy(mem_ctx);
                return status;
     }
@@ -1021,14 +1123,14 @@ static NTSTATUS dcerpc_pipe_connect_ncacn_unix_stream(struct dcerpc_pipe **p,
 {
        NTSTATUS status;
 
-       if (!binding->options || !binding->options[0]) {
+       if (!binding->endpoint) {
                DEBUG(0, ("Path to unix socket not specified\n"));
                return NT_STATUS_INVALID_PARAMETER;
        }
 
-       status = dcerpc_pipe_open_unix_stream(p, binding->options[0]);
+       status = dcerpc_pipe_open_unix_stream(p, binding->endpoint);
        if (!NT_STATUS_IS_OK(status)) {
-               DEBUG(0,("Failed to open unix socket %s\n", binding->options[0]));
+               DEBUG(0,("Failed to open unix socket %s\n", binding->endpoint));
                 return status;
     }
 
@@ -1069,23 +1171,21 @@ static NTSTATUS dcerpc_pipe_connect_ncacn_ip_tcp(struct dcerpc_pipe **p,
 {
        NTSTATUS status;
        uint32_t port = 0;
+       TALLOC_CTX *mem_ctx = talloc_init("connect_ncacn_ip_tcp");
 
-       if (binding->options && binding->options[0] && strlen(binding->options[0])) {
-               port = atoi(binding->options[0]);
-       }
-
-       if (port == 0) {
-               status = dcerpc_epm_map_tcp_port(binding->host, 
-                                                pipe_uuid, pipe_version,
-                                                &port);
+       if (!binding->endpoint) {
+               status = dcerpc_epm_map(mem_ctx, binding, 
+                                                pipe_uuid, pipe_version);
                if (!NT_STATUS_IS_OK(status)) {
                        DEBUG(0,("Failed to map DCERPC/TCP port for '%s' - %s\n", 
                                 pipe_uuid, nt_errstr(status)));
                        return status;
                }
-               DEBUG(1,("Mapped to DCERPC/TCP port %u\n", port));
+               DEBUG(1,("Mapped to DCERPC/TCP port %s\n", binding->endpoint));
        }
 
+       port = atoi(binding->endpoint);
+
        status = dcerpc_pipe_open_tcp(p, binding->host, port, AF_UNSPEC);
        if (!NT_STATUS_IS_OK(status)) {
                DEBUG(0,("Failed to connect to %s:%d\n", binding->host, port));
index 2109fb829e7248aae0e01c435f974145bd09be86..dcbfdb948f37ffd5cf6c6999f4952af5db5a5bae 100644 (file)
@@ -212,9 +212,7 @@ static NTSTATUS ipc_open_generic(struct ntvfs_module_context *ntvfs,
          finalised for Samba4
        */
        ep_description.transport = NCACN_NP;
-       ep_description.options = talloc_array_p(req, const char *, 2);
-       ep_description.options[0] = p->pipe_name;
-       ep_description.options[1] = NULL;
+       ep_description.endpoint = p->pipe_name;
 
        /* tell the RPC layer the session_info */
        if (req->session) {
index a17426651818b47d66c8943a597fbd8be1335a07..9373b066431c21f6afcc5b317d26609192646690 100644 (file)
@@ -33,15 +33,11 @@ static BOOL endpoints_match(const struct dcerpc_binding *ep1,
                return False;
        }
 
-       if (!ep1->options || !ep2->options) {
-               return ep1->options == ep2->options;
+       if (!ep1->endpoint || !ep2->endpoint) {
+               return ep1->endpoint == ep2->endpoint;
        }
 
-       if (!ep1->options[0] || !ep2->options[0]) {
-               return ep1->options[0] == ep2->options[0];
-       }
-
-       if (strcasecmp(ep1->options[0], ep2->options[0]) != 0) 
+       if (strcasecmp(ep1->endpoint, ep2->endpoint) != 0) 
                return False;
 
        return True;
index d5646a7c7aa2fcd4b8aa513a5d6a505455beaa81..8ba7464a79dba90e267c5181678f68a852759b43 100644 (file)
@@ -60,9 +60,9 @@ static void add_socket_rpc_unix(struct server_service *service,
        struct dcesrv_socket_context *dcesrv_sock;
        uint16_t port = 1;
 
-       sock = service_setup_socket(service,model_ops, "unix", e->ep_description.options[0], &port);
+       sock = service_setup_socket(service,model_ops, "unix", e->ep_description.endpoint, &port);
        if (!sock) {
-               DEBUG(0,("service_setup_socket(path=%s) failed\n",e->ep_description.options[0]));
+               DEBUG(0,("service_setup_socket(path=%s) failed\n",e->ep_description.endpoint));
                return;
        }
 
@@ -89,22 +89,16 @@ static void add_socket_rpc_ncalrpc(struct server_service *service,
        uint16_t port = 1;
        char *full_path;
 
-       if (!e->ep_description.options) {
-               e->ep_description.options = talloc_array_p(dce_ctx, const char *, 2);
-               e->ep_description.options[0] = NULL; 
-       }
-
-       if (!e->ep_description.options[0]) {
+       if (!e->ep_description.endpoint) {
                /* No identifier specified: generate one */
-               e->ep_description.options[0] = generate_random_str(dce_ctx, 10);
-               e->ep_description.options[1] = NULL;
+               e->ep_description.endpoint = generate_random_str(dce_ctx, 10);
        }
 
-       full_path = talloc_asprintf(dce_ctx, "%s/%s", lp_ncalrpc_dir(), e->ep_description.options[0]);
+       full_path = talloc_asprintf(dce_ctx, "%s/%s", lp_ncalrpc_dir(), e->ep_description.endpoint);
 
        sock = service_setup_socket(service,model_ops, "unix", full_path, &port);
        if (!sock) {
-               DEBUG(0,("service_setup_socket(identifier=%s,path=%s) failed\n",e->ep_description.options[0], full_path));
+               DEBUG(0,("service_setup_socket(identifier=%s,path=%s) failed\n",e->ep_description.endpoint, full_path));
                return;
        }
 
@@ -137,8 +131,8 @@ static void add_socket_rpc_tcp_iface(struct server_service *service,
        uint16_t port = 0;
        const char *ip_str = talloc_strdup(service, inet_ntoa(*ifip));
                        
-       if (e->ep_description.options && e->ep_description.options[0]
-               port = atoi(e->ep_description.options[0]);
+       if (e->ep_description.endpoint
+               port = atoi(e->ep_description.endpoint);
 
        sock = service_setup_socket(service,model_ops, "ipv4", ip_str, &port);
        if (!sock) {
@@ -146,13 +140,8 @@ static void add_socket_rpc_tcp_iface(struct server_service *service,
                return;
        }
 
-       /* And put the settings back into the binding. This will 
-        * go away once we store the 'encoded' endpoint instead of a 
-        * string describing it */
-       if (e->ep_description.options == NULL) {
-               e->ep_description.options = talloc_array_p(dce_ctx, const char *, 2);
-               e->ep_description.options[0] = talloc_asprintf(dce_ctx, "%d", port);
-               e->ep_description.options[1] = NULL;
+       if (e->ep_description.endpoint == NULL) {
+               e->ep_description.endpoint = talloc_asprintf(dce_ctx, "%d", port);
        }
 
        dcesrv_sock = talloc_p(sock, struct dcesrv_socket_context);
index 289e8a3894bdda5c7a26c03d75328b2a85155fbd..0fd1b4fb56b04897be10ada5206b719e16099d2f 100644 (file)
@@ -64,9 +64,7 @@ static BOOL test_BindingString(TALLOC_CTX *mem_ctx, const char *binding)
 
        /* 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.options = NULL;
 
        b.flags = 0;
        
index 91d5ceb5409d33b7b3717181e2ea532642d09b45..7cbee6170880f386cd26d2421da9a19d721a5a52 100644 (file)
@@ -195,12 +195,6 @@ BOOL torture_rpc_mgmt(int dummy)
                return False;
        }
 
-       b.options = talloc_array_p(mem_ctx, const char *, 2);
-       if (!b.options) {
-               return False;
-       }
-
-
        for (i=0;dcerpc_pipes[i];i++) {         
                /* some interfaces are not mappable */
                if (dcerpc_pipes[i]->num_calls == 0 ||
@@ -211,20 +205,16 @@ BOOL torture_rpc_mgmt(int dummy)
                printf("\nTesting pipe '%s'\n", dcerpc_pipes[i]->name);
 
                if (b.transport == NCACN_IP_TCP) {
-                       uint32_t port;
-                       status = dcerpc_epm_map_tcp_port(b.host, 
+                       status = dcerpc_epm_map(mem_ctx, &b, 
                                                         dcerpc_pipes[i]->uuid,
-                                                        dcerpc_pipes[i]->if_version,
-                                                        &port);
+                                                        dcerpc_pipes[i]->if_version);
                        if (!NT_STATUS_IS_OK(status)) {
                                printf("Failed to map port for uuid %s\n", dcerpc_pipes[i]->uuid);
                                continue;
                        }
-                       b.options[0] = talloc_asprintf(mem_ctx, "%u", port);
                } else {
-                       b.options[0] = dcerpc_pipes[i]->name;
+                       b.endpoint = dcerpc_pipes[i]->name;
                }
-               b.options[1] = NULL;
 
                lp_set_cmdline("torture:binding", dcerpc_binding_string(mem_ctx, &b));
 
index 0c2f8dfbbe4decf310b4224e0e84ce3ee16cffda..5719b7f0b313d506e492e90a46e5535ea7327f34 100644 (file)
@@ -150,11 +150,6 @@ BOOL torture_rpc_scanner(int dummy)
                return False;
        }
 
-       b.options = talloc_array_p(mem_ctx, const char *, 2);
-       if (!b.options) {
-               return False;
-       }
-
        for (i=0;dcerpc_pipes[i];i++) {         
                /* some interfaces are not mappable */
                if (dcerpc_pipes[i]->num_calls == 0 ||
@@ -165,20 +160,16 @@ BOOL torture_rpc_scanner(int dummy)
                printf("\nTesting pipe '%s'\n", dcerpc_pipes[i]->name);
 
                if (b.transport == NCACN_IP_TCP) {
-                       uint32_t port;
-                       status = dcerpc_epm_map_tcp_port(b.host, 
+                       status = dcerpc_epm_map(mem_ctx, &b, 
                                                         dcerpc_pipes[i]->uuid,
-                                                        dcerpc_pipes[i]->if_version,
-                                                        &port);
+                                                        dcerpc_pipes[i]->if_version);
                        if (!NT_STATUS_IS_OK(status)) {
                                printf("Failed to map port for uuid %s\n", dcerpc_pipes[i]->uuid);
                                continue;
                        }
-                       b.options[0] = talloc_asprintf(mem_ctx, "%u", port);
                } else {
-                       b.options[0] = dcerpc_pipes[i]->name;
+                       b.endpoint = dcerpc_pipes[i]->name;
                }
-               b.options[1] = NULL;
 
                lp_set_cmdline("torture:binding", dcerpc_binding_string(mem_ctx, &b));