From b398a96b09af5268e71bd3108f6c1e97568736f8 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Tue, 20 May 2008 18:08:41 +0200 Subject: rpc_client: use endpoint mapper to get the port for rpc_pipe_open_tcp(). Michael (This used to be commit f7db445c828c0eef2c08b538bd07d485dc248689) --- source3/Makefile.in | 7 +- source3/client/client_proto.h | 1 - source3/include/proto.h | 8 +- source3/rpc_client/cli_pipe.c | 167 ++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 171 insertions(+), 12 deletions(-) diff --git a/source3/Makefile.in b/source3/Makefile.in index 6899faf91e..faf4ccf4f6 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -750,7 +750,7 @@ SMBCONTROL_OBJ = utils/smbcontrol.o $(LOCKING_OBJ) $(PARAM_OBJ) \ SMBTREE_OBJ = utils/smbtree.o $(PARAM_OBJ) \ $(PROFILE_OBJ) $(LIB_NONSMBD_OBJ) $(LIBSMB_OBJ) \ $(KRBCLIENT_OBJ) $(POPT_LIB_OBJ) \ - rpc_client/cli_pipe.o $(RPC_PARSE_OBJ2) \ + rpc_client/cli_pipe.o librpc/rpc/binding.o $(RPC_PARSE_OBJ2) \ $(RPC_CLIENT_OBJ1) \ $(PASSDB_OBJ) @LIBWBCLIENT_STATIC@ $(SMBLDAP_OBJ) $(LDB_OBJ) $(GROUPDB_OBJ) \ $(LIBMSRPC_GEN_OBJ) @@ -829,6 +829,7 @@ LIBBIGBALLOFMUD_OBJ = $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) \ $(GROUPDB_OBJ) $(KRBCLIENT_OBJ) $(SMBLDAP_OBJ) $(LDB_OBJ) CLIENT_OBJ1 = client/client.o client/clitar.o rpc_client/cli_pipe.o \ + librpc/rpc/binding.o \ client/dnsbrowse.o \ $(RPC_CLIENT_OBJ1) \ $(RPC_PARSE_OBJ2) @@ -837,7 +838,7 @@ CLIENT_OBJ = $(CLIENT_OBJ1) $(PARAM_OBJ) $(LIBSMB_OBJ) \ $(LIB_NONSMBD_OBJ) $(KRBCLIENT_OBJ) $(LIBMSRPC_GEN_OBJ) \ $(READLINE_OBJ) $(POPT_LIB_OBJ) \ $(PASSDB_OBJ) @LIBWBCLIENT_STATIC@ $(SMBLDAP_OBJ) $(GROUPDB_OBJ) $(LDB_OBJ) \ - $(DISPLAY_SEC_OBJ) + $(DISPLAY_SEC_OBJ) LIBNETAPI_OBJ1 = lib/netapi/netapi.o \ lib/netapi/cm.o \ @@ -1144,7 +1145,7 @@ NTLM_AUTH_OBJ = ${NTLM_AUTH_OBJ1} $(LIBSAMBA_OBJ) $(POPT_LIB_OBJ) \ librpc/gen_ndr/ndr_netlogon.o -VLP_OBJ1 = ../testsuite/printing/vlp.o $(RPC_CLIENT_OBJ1) $(RPC_PARSE_OBJ2) $(RPC_CLIENT_OBJ) +VLP_OBJ1 = ../testsuite/printing/vlp.o $(RPC_CLIENT_OBJ1) $(RPC_PARSE_OBJ2) $(RPC_CLIENT_OBJ) librpc/rpc/binding.o VLP_OBJ = $(VLP_OBJ1) $(PARAM_OBJ) $(LIBSMB_OBJ) \ $(LIB_NONSMBD_OBJ) $(KRBCLIENT_OBJ) $(LIBMSRPC_GEN_OBJ) \ diff --git a/source3/client/client_proto.h b/source3/client/client_proto.h index d88805a097..7adc086186 100644 --- a/source3/client/client_proto.h +++ b/source3/client/client_proto.h @@ -123,7 +123,6 @@ NTSTATUS rpccli_kerberos_bind_data(TALLOC_CTX *mem_ctx, const char *password, struct cli_pipe_auth_data **presult); NTSTATUS rpc_pipe_open_tcp(TALLOC_CTX *mem_ctx, const char *host, - uint16_t port, const struct ndr_syntax_id *abstract_syntax, struct rpc_pipe_client **presult); struct rpc_pipe_client *cli_rpc_pipe_open_noauth(struct cli_state *cli, int pipe_idx, NTSTATUS *perr); diff --git a/source3/include/proto.h b/source3/include/proto.h index f76e43ac64..03a7f918c0 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -7061,8 +7061,14 @@ NTSTATUS rpccli_kerberos_bind_data(TALLOC_CTX *mem_ctx, const char *username, const char *password, struct cli_pipe_auth_data **presult); +NTSTATUS rpc_pipe_open_tcp_port(TALLOC_CTX *mem_ctx, const char *host, + uint16_t port, + const struct ndr_syntax_id *abstract_syntax, + struct rpc_pipe_client **presult); +NTSTATUS rpc_pipe_get_tcp_port(const char *host, + const struct ndr_syntax_id *abstract_syntax, + uint16_t *pport); NTSTATUS rpc_pipe_open_tcp(TALLOC_CTX *mem_ctx, const char *host, - uint16_t port, const struct ndr_syntax_id *abstract_syntax, struct rpc_pipe_client **presult); NTSTATUS rpc_pipe_open_ncalrpc(TALLOC_CTX *mem_ctx, const char *socket_path, diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index 9908c69674..7a5a62f2d9 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -18,6 +18,7 @@ */ #include "includes.h" +#include "librpc/gen_ndr/cli_epmapper.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_RPC_CLI @@ -2509,13 +2510,13 @@ static int rpc_pipe_sock_destructor(struct rpc_pipe_client *p) return 0; } -/******************************************************************** - Create a rpc pipe client struct, connecting to a tcp port - ********************************************************************/ -NTSTATUS rpc_pipe_open_tcp(TALLOC_CTX *mem_ctx, const char *host, - uint16_t port, - const struct ndr_syntax_id *abstract_syntax, - struct rpc_pipe_client **presult) +/** + * Create an rpc pipe client struct, connecting to a tcp port. + */ +NTSTATUS rpc_pipe_open_tcp_port(TALLOC_CTX *mem_ctx, const char *host, + uint16_t port, + const struct ndr_syntax_id *abstract_syntax, + struct rpc_pipe_client **presult) { struct rpc_pipe_client *result; struct sockaddr_storage addr; @@ -2563,6 +2564,158 @@ NTSTATUS rpc_pipe_open_tcp(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. + */ +NTSTATUS rpc_pipe_get_tcp_port(const char *host, + const struct ndr_syntax_id *abstract_syntax, + uint16_t *pport) +{ + NTSTATUS status; + struct rpc_pipe_client *epm_pipe = NULL; + struct cli_pipe_auth_data *auth = NULL; + struct dcerpc_binding *map_binding = NULL; + struct dcerpc_binding *res_binding = NULL; + struct epm_twr_t *map_tower = NULL; + struct epm_twr_t *res_towers = 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(); + + if (pport == NULL) { + status = NT_STATUS_INVALID_PARAMETER; + goto done; + } + + /* open the connection to the endpoint mapper */ + status = rpc_pipe_open_tcp_port(tmp_ctx, host, 135, + &ndr_table_epmapper.syntax_id, + &epm_pipe); + + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + + status = rpccli_anon_bind_data(tmp_ctx, &auth); + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + + status = rpc_pipe_bind(epm_pipe, auth); + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + + /* create tower for asking the epmapper */ + + map_binding = TALLOC_ZERO_P(tmp_ctx, struct dcerpc_binding); + if (map_binding == NULL) { + status = NT_STATUS_NO_MEMORY; + goto done; + } + + map_binding->transport = NCACN_IP_TCP; + map_binding->object = *abstract_syntax; + map_binding->host = host; /* needed? */ + map_binding->endpoint = "0"; /* correct? needed? */ + + map_tower = TALLOC_ZERO_P(tmp_ctx, struct epm_twr_t); + if (map_tower == NULL) { + status = NT_STATUS_NO_MEMORY; + goto done; + } + + status = dcerpc_binding_build_tower(tmp_ctx, map_binding, + &(map_tower->tower)); + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + + /* allocate further parameters for the epm_Map call */ + + res_towers = TALLOC_ARRAY(tmp_ctx, struct epm_twr_t, max_towers); + if (res_towers == NULL) { + status = NT_STATUS_NO_MEMORY; + goto done; + } + towers.twr = res_towers; + + entry_handle = TALLOC_ZERO_P(tmp_ctx, struct policy_handle); + if (entry_handle == NULL) { + status = NT_STATUS_NO_MEMORY; + goto done; + } + + /* ask the endpoint mapper for the port */ + + status = rpccli_epm_Map(epm_pipe, + tmp_ctx, + &(abstract_syntax->uuid), + map_tower, + entry_handle, + max_towers, + &num_towers, + &towers); + + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + + if (num_towers != 1) { + status = NT_STATUS_UNSUCCESSFUL; + goto done; + } + + /* extract the port from the answer */ + + status = dcerpc_binding_from_tower(tmp_ctx, + &(towers.twr->tower), + &res_binding); + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + + /* are further checks here necessary? */ + if (res_binding->transport != NCACN_IP_TCP) { + status = NT_STATUS_UNSUCCESSFUL; + goto done; + } + + *pport = (uint16_t)atoi(res_binding->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. + */ +NTSTATUS rpc_pipe_open_tcp(TALLOC_CTX *mem_ctx, const char *host, + const struct ndr_syntax_id *abstract_syntax, + struct rpc_pipe_client **presult) +{ + NTSTATUS status; + uint16_t port; + + status = rpc_pipe_get_tcp_port(host, abstract_syntax, &port); + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + + status = rpc_pipe_open_tcp_port(mem_ctx, host, port, + abstract_syntax, presult); + +done: + return status; +} + /******************************************************************** Create a rpc pipe client struct, connecting to a unix domain socket ********************************************************************/ -- cgit