From f019fa98dbf39cc7ed718c39b4f996459d3e7d55 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 16 Sep 2024 22:04:49 +0200 Subject: [PATCH] s3:rpc_client: convert rpc_pipe_open_tcp_port() to rpc_client_{association,connection} Note that cli_rpc_pipe_open() calls rpc_client_association_create() without a need for NCACN_NP, but that will change in the next commits... Signed-off-by: Stefan Metzmacher Reviewed-by: Ralph Boehme (cherry picked from commit 637a8e5270fefaea5c61921d4b6ecfc4455a91aa) --- source3/rpc_client/cli_pipe.c | 281 ++++++++++++++++++++++------------ 1 file changed, 179 insertions(+), 102 deletions(-) diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index d89e2b2b11c..81661ddeae3 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -2843,75 +2843,55 @@ NTSTATUS rpccli_ncalrpc_bind_data(TALLOC_CTX *mem_ctx, /** * Create an rpc pipe client struct, connecting to a tcp port. */ -static NTSTATUS rpc_pipe_open_tcp_port(TALLOC_CTX *mem_ctx, const char *host, - const struct sockaddr_storage *ss_addr, - uint16_t port, - const struct ndr_interface_table *table, - struct rpc_pipe_client **presult) +static NTSTATUS rpc_pipe_open_tcp_port(TALLOC_CTX *mem_ctx, + const struct rpc_client_association *assoc, + struct rpc_client_connection **pconn) { - struct rpc_pipe_client *result; - struct sockaddr_storage addr; + struct rpc_client_connection *conn = NULL; + enum dcerpc_transport_t transport; + const char *endpoint = NULL; + uint16_t port; NTSTATUS status; int fd; - result = talloc_zero(mem_ctx, struct rpc_pipe_client); - if (result == NULL) { - return NT_STATUS_NO_MEMORY; + transport = dcerpc_binding_get_transport(assoc->binding); + if (transport != NCACN_IP_TCP) { + return NT_STATUS_RPC_WRONG_KIND_OF_BINDING; } - result->abstract_syntax = table->syntax_id; - result->transfer_syntax = ndr_transfer_syntax_ndr; - - result->desthost = talloc_strdup(result, host); - if (result->desthost == NULL) { - status = NT_STATUS_NO_MEMORY; - goto fail; + endpoint = dcerpc_binding_get_string_option(assoc->binding, + "endpoint"); + if (endpoint == NULL) { + return NT_STATUS_RPC_INVALID_ENDPOINT_FORMAT; } - - result->srv_name_slash = talloc_asprintf_strupper_m( - result, "\\\\%s", result->desthost); - if (result->srv_name_slash == NULL) { - status = NT_STATUS_NO_MEMORY; - goto fail; + port = (uint16_t)atoi(endpoint); + if (port == 0) { + return NT_STATUS_RPC_INVALID_ENDPOINT_FORMAT; } - result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN; - - if (ss_addr == NULL) { - if (!resolve_name(host, &addr, NBT_NAME_SERVER, false)) { - status = NT_STATUS_NOT_FOUND; - goto fail; - } - } else { - addr = *ss_addr; + status = rpc_client_connection_create(mem_ctx, &conn); + if (!NT_STATUS_IS_OK(status)) { + return status; } - status = open_socket_out(&addr, port, 60*1000, &fd); + status = open_socket_out(&assoc->addr.u.ss, port, 60*1000, &fd); if (!NT_STATUS_IS_OK(status)) { - goto fail; + TALLOC_FREE(conn); + return status; } set_socket_options(fd, lp_socket_options()); - status = rpc_transport_sock_init(result, fd, &result->transport); + status = rpc_transport_sock_init(conn, fd, &conn->transport); if (!NT_STATUS_IS_OK(status)) { close(fd); - goto fail; + TALLOC_FREE(conn); + return status; } - result->transport->transport = NCACN_IP_TCP; - - result->binding_handle = rpccli_bh_create(result, NULL, table); - if (result->binding_handle == NULL) { - TALLOC_FREE(result); - return NT_STATUS_NO_MEMORY; - } + conn->transport->transport = NCACN_IP_TCP; - *presult = result; + *pconn = conn; return NT_STATUS_OK; - - fail: - TALLOC_FREE(result); - return status; } static NTSTATUS rpccli_epm_map_binding( @@ -3080,88 +3060,98 @@ done: * target host. */ static NTSTATUS rpc_pipe_get_tcp_port(const char *host, - const struct sockaddr_storage *addr, + const struct samba_sockaddr *saddr, const struct ndr_interface_table *table, uint16_t *pport) { - NTSTATUS status; + TALLOC_CTX *frame = talloc_stackframe(); + const char *epm_ep = NULL; + struct rpc_client_association *epm_assoc = NULL; + struct rpc_client_connection *epm_conn = NULL; struct rpc_pipe_client *epm_pipe = NULL; - struct pipe_auth_data *auth = NULL; + struct pipe_auth_data *epm_auth = NULL; char *endpoint = NULL; - TALLOC_CTX *tmp_ctx = talloc_stackframe(); + uint16_t port = 0; + NTSTATUS status; - if (pport == NULL) { - status = NT_STATUS_INVALID_PARAMETER; - goto done; + endpoint = dcerpc_default_transport_endpoint(frame, + NCACN_IP_TCP, + table); + if (endpoint != NULL) { + port = (uint16_t)atoi(endpoint); } - if (ndr_syntax_id_equal(&table->syntax_id, - &ndr_table_epmapper.syntax_id)) { - *pport = 135; - status = NT_STATUS_OK; - goto done; + if (port != 0) { + *pport = port; + TALLOC_FREE(frame); + return NT_STATUS_OK; + } + + epm_ep = dcerpc_default_transport_endpoint(frame, + NCACN_IP_TCP, + &ndr_table_epmapper); + if (epm_ep == NULL) { + TALLOC_FREE(frame); + return NT_STATUS_RPC_INTERNAL_ERROR; + } + + status = rpc_client_association_create(frame, + host, + NCACN_IP_TCP, + saddr, + epm_ep, + &epm_assoc); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(frame); + return status; } /* open the connection to the endpoint mapper */ - status = rpc_pipe_open_tcp_port(tmp_ctx, host, addr, 135, - &ndr_table_epmapper, - &epm_pipe); + status = rpc_pipe_open_tcp_port(frame, epm_assoc, &epm_conn); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(frame); + return status; + } + status = rpccli_anon_bind_data(frame, &epm_auth); if (!NT_STATUS_IS_OK(status)) { - goto done; + TALLOC_FREE(frame); + return status; } - status = rpccli_anon_bind_data(tmp_ctx, &auth); + status = rpc_pipe_wrap_create(&ndr_table_epmapper, + NULL, + &epm_assoc, + &epm_conn, + frame, + &epm_pipe); if (!NT_STATUS_IS_OK(status)) { - goto done; + TALLOC_FREE(frame); + return status; } - status = rpc_pipe_bind(epm_pipe, auth); + status = rpc_pipe_bind(epm_pipe, epm_auth); if (!NT_STATUS_IS_OK(status)) { - goto done; + TALLOC_FREE(frame); + return status; } status = rpccli_epm_map_interface( epm_pipe->binding_handle, NCACN_IP_TCP, &table->syntax_id, - tmp_ctx, + frame, &endpoint); if (!NT_STATUS_IS_OK(status)) { DBG_DEBUG("rpccli_epm_map_interface failed: %s\n", nt_errstr(status)); - goto done; - } - - *pport = (uint16_t)atoi(endpoint); - -done: - TALLOC_FREE(tmp_ctx); - return status; -} - -/** - * Create a rpc pipe client struct, connecting to a host via tcp. - * The port is determined by asking the endpoint mapper on the given - * host. - */ -static NTSTATUS rpc_pipe_open_tcp( - TALLOC_CTX *mem_ctx, - const char *host, - const struct sockaddr_storage *addr, - const struct ndr_interface_table *table, - struct rpc_pipe_client **presult) -{ - NTSTATUS status; - uint16_t port = 0; - - status = rpc_pipe_get_tcp_port(host, addr, table, &port); - if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(frame); return status; } - return rpc_pipe_open_tcp_port(mem_ctx, host, addr, port, - table, presult); + *pport = (uint16_t)atoi(endpoint); + TALLOC_FREE(frame); + return NT_STATUS_OK; } static NTSTATUS rpc_pipe_get_ncalrpc_name( @@ -3648,17 +3638,104 @@ static NTSTATUS cli_rpc_pipe_open(struct cli_state *cli, const struct sockaddr_storage *remote_sockaddr, struct rpc_pipe_client **presult) { + TALLOC_CTX *frame = talloc_stackframe(); + struct samba_sockaddr saddr = { .sa_socklen = 0, }; + struct rpc_client_association *assoc = NULL; + struct rpc_client_connection *conn = NULL; + struct rpc_pipe_client *result = NULL; + char _tcp_endpoint[6] = { 0, }; + const char *endpoint = NULL; + NTSTATUS status; + + if (cli != NULL && remote_name == NULL) { + remote_name = smbXcli_conn_remote_name(cli->conn); + } + if (cli != NULL && remote_sockaddr == NULL) { + remote_sockaddr = smbXcli_conn_remote_sockaddr(cli->conn); + } + + if (remote_sockaddr != NULL) { + saddr.u.ss = *remote_sockaddr; + } else { + bool ok; + + ok = resolve_name(remote_name, + &saddr.u.ss, + NBT_NAME_SERVER, + false); + if (!ok) { + TALLOC_FREE(frame); + return NT_STATUS_NOT_FOUND; + } + } + + endpoint = dcerpc_default_transport_endpoint(frame, + transport, + table); + if (endpoint == NULL) { + uint16_t port = 0; + + if (transport != NCACN_IP_TCP) { + TALLOC_FREE(frame); + return NT_STATUS_RPC_NO_ENDPOINT_FOUND; + } + + status = rpc_pipe_get_tcp_port(remote_name, + &saddr, + table, + &port); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + snprintf(_tcp_endpoint, sizeof(_tcp_endpoint), "%u", port); + endpoint = _tcp_endpoint; + } + + status = rpc_client_association_create(NULL, + remote_name, + transport, + &saddr, + endpoint, + &assoc); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(frame); + return status; + } + talloc_steal(frame, assoc); + switch (transport) { case NCACN_IP_TCP: - return rpc_pipe_open_tcp(NULL, - remote_name, - remote_sockaddr, - table, presult); + status = rpc_pipe_open_tcp_port(NULL, + assoc, + &conn); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(frame); + return status; + } + talloc_steal(frame, conn); + break; case NCACN_NP: + TALLOC_FREE(frame); return rpc_pipe_open_np(cli, table, presult); default: + TALLOC_FREE(frame); return NT_STATUS_NOT_IMPLEMENTED; } + status = rpc_pipe_wrap_create(table, + cli, + &assoc, + &conn, + NULL, + &result); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(frame); + return status; + } + + *presult = result; + TALLOC_FREE(frame); + return NT_STATUS_OK; } /**************************************************************************** -- 2.47.2