From: Volker Lendecke Date: Mon, 8 Feb 2021 14:47:41 +0000 (+0100) Subject: rpc_client: Factor out rpccli_epm_map_interface() from rpc_pipe_get_tcp_port() X-Git-Tag: tevent-0.11.0~1448 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=a8ab5ab5bc2b127bdd4c1c0ba779d57d3a3e4135;p=thirdparty%2Fsamba.git rpc_client: Factor out rpccli_epm_map_interface() from rpc_pipe_get_tcp_port() Make it usable for ncalrpc as well Signed-off-by: Volker Lendecke Reviewed-by: Jeremy Allison --- diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index e37884979b2..58d5001b4c3 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -2734,152 +2734,222 @@ static NTSTATUS rpc_pipe_open_tcp_port(TALLOC_CTX *mem_ctx, const char *host, return status; } -/** - * Determine the tcp port on which a dcerpc interface is listening - * for the ncacn_ip_tcp transport via the endpoint mapper of the - * target host. - */ -static NTSTATUS rpc_pipe_get_tcp_port(const char *host, - const struct sockaddr_storage *addr, - const struct ndr_interface_table *table, - uint16_t *pport) +static NTSTATUS rpccli_epm_map_binding( + struct dcerpc_binding_handle *epm_connection, + struct dcerpc_binding *binding, + TALLOC_CTX *mem_ctx, + char **pendpoint) { - NTSTATUS status; - struct rpc_pipe_client *epm_pipe = NULL; - struct dcerpc_binding_handle *epm_handle = NULL; - struct pipe_auth_data *auth = NULL; - struct dcerpc_binding *map_binding = NULL; + TALLOC_CTX *frame = talloc_stackframe(); + enum dcerpc_transport_t transport = + dcerpc_binding_get_transport(binding); + enum dcerpc_transport_t res_transport; struct dcerpc_binding *res_binding = NULL; - enum dcerpc_transport_t transport; - const char *endpoint = NULL; struct epm_twr_t *map_tower = NULL; - struct epm_twr_t *res_towers = NULL; + struct epm_twr_p_t res_towers = { .twr = NULL }; struct policy_handle *entry_handle = NULL; uint32_t num_towers = 0; - uint32_t max_towers = 1; - struct epm_twr_p_t towers; - TALLOC_CTX *tmp_ctx = talloc_stackframe(); - uint32_t result = 0; + const uint32_t max_towers = 1; + const char *endpoint = NULL; + char *tmp = NULL; + uint32_t result; + NTSTATUS status; - if (pport == NULL) { - status = NT_STATUS_INVALID_PARAMETER; - goto done; + map_tower = talloc_zero(frame, struct epm_twr_t); + if (map_tower == NULL) { + goto nomem; } - if (ndr_syntax_id_equal(&table->syntax_id, - &ndr_table_epmapper.syntax_id)) { - *pport = 135; - status = NT_STATUS_OK; + status = dcerpc_binding_build_tower( + frame, binding, &(map_tower->tower)); + if (!NT_STATUS_IS_OK(status)) { + DBG_DEBUG("dcerpc_binding_build_tower failed: %s\n", + nt_errstr(status)); goto done; } - /* open the connection to the endpoint mapper */ - status = rpc_pipe_open_tcp_port(tmp_ctx, host, addr, 135, - &ndr_table_epmapper, - &epm_pipe); + res_towers.twr = talloc_array(frame, struct epm_twr_t, max_towers); + if (res_towers.twr == NULL) { + goto nomem; + } - if (!NT_STATUS_IS_OK(status)) { - goto done; + entry_handle = talloc_zero(frame, struct policy_handle); + if (entry_handle == NULL) { + goto nomem; } - epm_handle = epm_pipe->binding_handle; - status = rpccli_anon_bind_data(tmp_ctx, &auth); + status = dcerpc_epm_Map( + epm_connection, + frame, + NULL, + map_tower, + entry_handle, + max_towers, + &num_towers, + &res_towers, + &result); + if (!NT_STATUS_IS_OK(status)) { + DBG_DEBUG("dcerpc_epm_Map failed: %s\n", nt_errstr(status)); goto done; } - status = rpc_pipe_bind(epm_pipe, auth); - if (!NT_STATUS_IS_OK(status)) { + if (result != EPMAPPER_STATUS_OK) { + DBG_DEBUG("dcerpc_epm_Map returned %"PRIu32"\n", result); + status = NT_STATUS_NOT_FOUND; goto done; } - /* create tower for asking the epmapper */ - - status = dcerpc_parse_binding(tmp_ctx, "ncacn_ip_tcp:", - &map_binding); - if (!NT_STATUS_IS_OK(status)) { + if (num_towers != 1) { + DBG_DEBUG("dcerpc_epm_Map returned %"PRIu32" towers\n", + num_towers); + status = NT_STATUS_INVALID_NETWORK_RESPONSE; goto done; } - status = dcerpc_binding_set_abstract_syntax(map_binding, - &table->syntax_id); + status = dcerpc_binding_from_tower( + frame, &(res_towers.twr->tower), &res_binding); if (!NT_STATUS_IS_OK(status)) { + DBG_DEBUG("dcerpc_binding_from_tower failed: %s\n", + nt_errstr(status)); goto done; } - map_tower = talloc_zero(tmp_ctx, struct epm_twr_t); - if (map_tower == NULL) { - status = NT_STATUS_NO_MEMORY; + res_transport = dcerpc_binding_get_transport(res_binding); + if (res_transport != transport) { + DBG_DEBUG("dcerpc_epm_Map returned transport %d, " + "expected %d\n", + (int)res_transport, + (int)transport); + status = NT_STATUS_INVALID_NETWORK_RESPONSE; goto done; } - status = dcerpc_binding_build_tower(tmp_ctx, map_binding, - &(map_tower->tower)); - if (!NT_STATUS_IS_OK(status)) { + endpoint = dcerpc_binding_get_string_option(res_binding, "endpoint"); + if (endpoint == NULL) { + DBG_DEBUG("dcerpc_epm_Map returned no endpoint\n"); + status = NT_STATUS_INVALID_NETWORK_RESPONSE; goto done; } - /* allocate further parameters for the epm_Map call */ + tmp = talloc_strdup(mem_ctx, endpoint); + if (tmp == NULL) { + goto nomem; + } + *pendpoint = tmp; - res_towers = talloc_array(tmp_ctx, struct epm_twr_t, max_towers); - if (res_towers == NULL) { - status = NT_STATUS_NO_MEMORY; + status = NT_STATUS_OK; + goto done; + +nomem: + status = NT_STATUS_NO_MEMORY; +done: + TALLOC_FREE(frame); + return status; +} + +static NTSTATUS rpccli_epm_map_interface( + struct dcerpc_binding_handle *epm_connection, + enum dcerpc_transport_t transport, + const struct ndr_syntax_id *iface, + TALLOC_CTX *mem_ctx, + char **pendpoint) +{ + struct dcerpc_binding *binding = NULL; + char *endpoint = NULL; + NTSTATUS status; + + status = dcerpc_parse_binding(mem_ctx, "", &binding); + if (!NT_STATUS_IS_OK(status)) { + DBG_DEBUG("dcerpc_parse_binding failed: %s\n", + nt_errstr(status)); goto done; } - towers.twr = res_towers; - entry_handle = talloc_zero(tmp_ctx, struct policy_handle); - if (entry_handle == NULL) { - status = NT_STATUS_NO_MEMORY; + status = dcerpc_binding_set_transport(binding, transport); + if (!NT_STATUS_IS_OK(status)) { + DBG_DEBUG("dcerpc_binding_set_transport failed: %s\n", + nt_errstr(status)); goto done; } - /* ask the endpoint mapper for the port */ - - status = dcerpc_epm_Map(epm_handle, - tmp_ctx, - NULL, - map_tower, - entry_handle, - max_towers, - &num_towers, - &towers, - &result); + status = dcerpc_binding_set_abstract_syntax(binding, iface); + if (!NT_STATUS_IS_OK(status)) { + DBG_DEBUG("dcerpc_binding_set_abstract_syntax failed: %s\n", + nt_errstr(status)); + goto done; + } + status = rpccli_epm_map_binding( + epm_connection, binding, mem_ctx, &endpoint); if (!NT_STATUS_IS_OK(status)) { + DBG_DEBUG("rpccli_epm_map_binding failed: %s\n", + nt_errstr(status)); goto done; } + *pendpoint = endpoint; - if (result != EPMAPPER_STATUS_OK) { - status = NT_STATUS_UNSUCCESSFUL; +done: + TALLOC_FREE(binding); + return status; +} + +/** + * Determine the tcp port on which a dcerpc interface is listening + * for the ncacn_ip_tcp transport via the endpoint mapper of the + * target host. + */ +static NTSTATUS rpc_pipe_get_tcp_port(const char *host, + const struct sockaddr_storage *addr, + const struct ndr_interface_table *table, + uint16_t *pport) +{ + NTSTATUS status; + struct rpc_pipe_client *epm_pipe = NULL; + struct pipe_auth_data *auth = NULL; + char *endpoint = NULL; + TALLOC_CTX *tmp_ctx = talloc_stackframe(); + + if (pport == NULL) { + status = NT_STATUS_INVALID_PARAMETER; goto done; } - if (num_towers != 1) { - status = NT_STATUS_UNSUCCESSFUL; + if (ndr_syntax_id_equal(&table->syntax_id, + &ndr_table_epmapper.syntax_id)) { + *pport = 135; + status = NT_STATUS_OK; goto done; } - /* extract the port from the answer */ + /* open the connection to the endpoint mapper */ + status = rpc_pipe_open_tcp_port(tmp_ctx, host, addr, 135, + &ndr_table_epmapper, + &epm_pipe); - status = dcerpc_binding_from_tower(tmp_ctx, - &(towers.twr->tower), - &res_binding); if (!NT_STATUS_IS_OK(status)) { goto done; } - transport = dcerpc_binding_get_transport(res_binding); - endpoint = dcerpc_binding_get_string_option(res_binding, "endpoint"); + status = rpccli_anon_bind_data(tmp_ctx, &auth); + if (!NT_STATUS_IS_OK(status)) { + goto done; + } - /* are further checks here necessary? */ - if (transport != NCACN_IP_TCP) { - status = NT_STATUS_INVALID_NETWORK_RESPONSE; + status = rpc_pipe_bind(epm_pipe, auth); + if (!NT_STATUS_IS_OK(status)) { goto done; } - if (endpoint == NULL) { - status = NT_STATUS_INVALID_NETWORK_RESPONSE; + status = rpccli_epm_map_interface( + epm_pipe->binding_handle, + NCACN_IP_TCP, + &table->syntax_id, + tmp_ctx, + &endpoint); + if (!NT_STATUS_IS_OK(status)) { + DBG_DEBUG("rpccli_epm_map_interface failed: %s\n", + nt_errstr(status)); goto done; }