rpc_client: use endpoint mapper to get the port for rpc_pipe_open_tcp().
authorMichael Adam <obnox@samba.org>
Tue, 20 May 2008 16:08:41 +0000 (18:08 +0200)
committerMichael Adam <obnox@samba.org>
Thu, 22 May 2008 09:29:57 +0000 (11:29 +0200)
Michael

source/Makefile.in
source/client/client_proto.h
source/include/proto.h
source/rpc_client/cli_pipe.c

index 6899faf91e372818f3632ba64fc90757a70296e1..faf4ccf4f613a200ad08c9b6d9fb2fafb1eb563d 100644 (file)
@@ -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) \
index d88805a097364c35155759ae3b9b194cca541211..7adc086186c716b9d7f4cf97fbc60b295fccdfba 100644 (file)
@@ -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);
index f76e43ac64d6f857e4dd825184d2226912aa4f5d..03a7f918c0ad402ac39b9681bacea76fa5c7406e 100644 (file)
@@ -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,
index 9908c69674e9c11c3f89a4fd5295ce4bd2f1da66..7a5a62f2d9ffb01ed116e8a8771c1f2920f4e974 100644 (file)
@@ -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
  ********************************************************************/