diff options
Diffstat (limited to 'source4')
-rw-r--r-- | source4/librpc/rpc/dcerpc.h | 1 | ||||
-rw-r--r-- | source4/librpc/rpc/dcerpc_util.c | 172 | ||||
-rw-r--r-- | source4/ntvfs/ipc/vfs_ipc.c | 4 | ||||
-rw-r--r-- | source4/rpc_server/dcerpc_server.c | 10 | ||||
-rw-r--r-- | source4/rpc_server/dcerpc_sock.c | 31 | ||||
-rw-r--r-- | source4/torture/local/binding_string.c | 4 | ||||
-rw-r--r-- | source4/torture/rpc/mgmt.c | 16 | ||||
-rw-r--r-- | source4/torture/rpc/scanner.c | 15 |
8 files changed, 158 insertions, 95 deletions
diff --git a/source4/librpc/rpc/dcerpc.h b/source4/librpc/rpc/dcerpc.h index 1a4b2fa34e..096ece7445 100644 --- a/source4/librpc/rpc/dcerpc.h +++ b/source4/librpc/rpc/dcerpc.h @@ -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; }; diff --git a/source4/librpc/rpc/dcerpc_util.c b/source4/librpc/rpc/dcerpc_util.c index 3dacfee5f6..88ef90cf95 100644 --- a/source4/librpc/rpc/dcerpc_util.c +++ b/source4/librpc/rpc/dcerpc_util.c @@ -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)); diff --git a/source4/ntvfs/ipc/vfs_ipc.c b/source4/ntvfs/ipc/vfs_ipc.c index 2109fb829e..dcbfdb948f 100644 --- a/source4/ntvfs/ipc/vfs_ipc.c +++ b/source4/ntvfs/ipc/vfs_ipc.c @@ -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) { diff --git a/source4/rpc_server/dcerpc_server.c b/source4/rpc_server/dcerpc_server.c index a174266518..9373b06643 100644 --- a/source4/rpc_server/dcerpc_server.c +++ b/source4/rpc_server/dcerpc_server.c @@ -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; diff --git a/source4/rpc_server/dcerpc_sock.c b/source4/rpc_server/dcerpc_sock.c index d5646a7c7a..8ba7464a79 100644 --- a/source4/rpc_server/dcerpc_sock.c +++ b/source4/rpc_server/dcerpc_sock.c @@ -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); diff --git a/source4/torture/local/binding_string.c b/source4/torture/local/binding_string.c index 289e8a3894..0fd1b4fb56 100644 --- a/source4/torture/local/binding_string.c +++ b/source4/torture/local/binding_string.c @@ -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; diff --git a/source4/torture/rpc/mgmt.c b/source4/torture/rpc/mgmt.c index 91d5ceb540..7cbee61708 100644 --- a/source4/torture/rpc/mgmt.c +++ b/source4/torture/rpc/mgmt.c @@ -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)); diff --git a/source4/torture/rpc/scanner.c b/source4/torture/rpc/scanner.c index 0c2f8dfbbe..5719b7f0b3 100644 --- a/source4/torture/rpc/scanner.c +++ b/source4/torture/rpc/scanner.c @@ -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)); |