]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
rpc_client: Factor out rpccli_epm_map_interface() from rpc_pipe_get_tcp_port()
authorVolker Lendecke <vl@samba.org>
Mon, 8 Feb 2021 14:47:41 +0000 (15:47 +0100)
committerVolker Lendecke <vl@samba.org>
Fri, 19 Mar 2021 07:09:37 +0000 (07:09 +0000)
Make it usable for ncalrpc as well

Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
source3/rpc_client/cli_pipe.c

index e37884979b2379670ac5c90f4c1c827b5dfb5883..58d5001b4c3bdf601499d941f4ebbdd0b0febb4a 100644 (file)
@@ -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;
        }