s3:rpc_server: Setup ncacn_ip_tcp sockets through endpoint init
authorSamuel Cabrero <scabrero@suse.de>
Wed, 27 Feb 2019 16:52:21 +0000 (17:52 +0100)
committerSamuel Cabrero <scabrero@sn-devel-184>
Fri, 20 Mar 2020 15:36:34 +0000 (15:36 +0000)
The listener is created in the endpoint memory context. If the endpoint
is freed, the listener will be freed too and the socket closed.

Signed-off-by: Samuel Cabrero <scabrero@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
source3/rpc_server/epmd.c
source3/rpc_server/rpc_server.c
source3/rpc_server/rpc_server.h
source3/rpc_server/rpc_service_setup.c
source3/rpc_server/rpc_sock_helper.c
source3/rpc_server/rpc_sock_helper.h

index 148a7e4655decafecaa05092ecd82527e3809f69..baf99db5f60268ca20c70af3d1edb29d5bc28cfd 100644 (file)
@@ -238,16 +238,6 @@ void start_epmd(struct tevent_context *ev_ctx,
                }
        }
 
-       status = dcesrv_setup_ncacn_ip_tcp_sockets(ev_ctx,
-                                                  msg_ctx,
-                                                  &ndr_table_epmapper,
-                                                  NULL,
-                                                  135);
-       if (!NT_STATUS_IS_OK(status)) {
-               DEBUG(0, ("Failed to open epmd tcpip sockets!\n"));
-               exit(1);
-       }
-
        status = dcesrv_setup_ncalrpc_socket(ev_ctx,
                                             msg_ctx,
                                             "EPMAPPER",
index ca6f61c332f5b2216a1d539b029c21a5b431a09b..2ba8cc0b53e46181f782bcd7f43f3f425781c63d 100644 (file)
@@ -93,6 +93,8 @@ struct dcerpc_ncacn_listen_state {
 
        struct tevent_context *ev_ctx;
        struct messaging_context *msg_ctx;
+       struct dcesrv_context *dce_ctx;
+       struct dcesrv_endpoint *endpoint;
        dcerpc_ncacn_termination_fn termination_fn;
        void *termination_data;
 };
@@ -308,32 +310,48 @@ NTSTATUS dcesrv_create_ncacn_ip_tcp_socket(const struct sockaddr_storage *ifss,
 
 NTSTATUS dcesrv_setup_ncacn_ip_tcp_socket(struct tevent_context *ev_ctx,
                                          struct messaging_context *msg_ctx,
+                                         struct dcesrv_context *dce_ctx,
+                                         struct dcesrv_endpoint *e,
                                          const struct sockaddr_storage *ifss,
-                                         uint16_t *port)
+                                         dcerpc_ncacn_termination_fn term_fn,
+                                         void *term_data)
 {
-       struct dcerpc_ncacn_listen_state *state;
-       struct tevent_fd *fde;
+       struct dcerpc_ncacn_listen_state *state = NULL;
+       struct tevent_fd *fde = NULL;
+       const char *endpoint = NULL;
+       uint16_t port = 0;
+       char port_str[6];
        int rc;
        NTSTATUS status;
 
-       state = talloc_zero(ev_ctx, struct dcerpc_ncacn_listen_state);
+       endpoint = dcerpc_binding_get_string_option(e->ep_description,
+                                                   "endpoint");
+       if (endpoint != NULL) {
+               port = atoi(endpoint);
+       }
+
+       /* Alloc in endpoint context. If the endpoint is freed (for example
+        * when forked daemons reinit the dcesrv_context, the tevent_fd
+        * listener will be stopped and the socket closed */
+       state = talloc_zero(e, struct dcerpc_ncacn_listen_state);
        if (state == NULL) {
                DBG_ERR("Out of memory\n");
                return NT_STATUS_NO_MEMORY;
        }
 
        state->fd = -1;
-       state->ep.port = *port;
+       state->ev_ctx = ev_ctx;
+       state->msg_ctx = msg_ctx;
+       state->endpoint = e;
+       state->dce_ctx = talloc_reference(state, dce_ctx);
+       state->termination_fn = term_fn;
+       state->termination_data = term_data;
 
-       status = dcesrv_create_ncacn_ip_tcp_socket(ifss, &state->ep.port,
-                                                  &state->fd);
+       status = dcesrv_create_ncacn_ip_tcp_socket(ifss, &port, &state->fd);
        if (!NT_STATUS_IS_OK(status)) {
                goto out;
        }
 
-       state->ev_ctx = ev_ctx;
-       state->msg_ctx = msg_ctx;
-
        /* ready to listen */
        set_socket_options(state->fd, "SO_KEEPALIVE");
        set_socket_options(state->fd, lp_socket_options());
@@ -350,7 +368,7 @@ NTSTATUS dcesrv_setup_ncacn_ip_tcp_socket(struct tevent_context *ev_ctx,
        }
 
        DBG_DEBUG("Opened socket fd %d for port %u\n",
-                 state->fd, state->ep.port);
+                 state->fd, port);
 
        errno = 0;
        fde = tevent_add_fd(state->ev_ctx,
@@ -371,7 +389,16 @@ NTSTATUS dcesrv_setup_ncacn_ip_tcp_socket(struct tevent_context *ev_ctx,
 
        tevent_fd_set_auto_close(fde);
 
-       *port = state->ep.port;
+       /* Set the port in the endpoint */
+       snprintf(port_str, sizeof(port_str), "%u", port);
+
+       status = dcerpc_binding_set_string_option(e->ep_description,
+                                                 "endpoint", port_str);
+       if (!NT_STATUS_IS_OK(status)) {
+               DBG_ERR("Failed to set binding endpoint '%s': %s\n",
+                       port_str, nt_errstr(status));
+               goto out;
+       }
 
        return NT_STATUS_OK;
 
index 8d96198067eb5c6f4532eaa9e87ff230b139065b..68fff9563a1b8c0dd3c4476cebc5d10c3a213fec 100644 (file)
@@ -87,8 +87,11 @@ NTSTATUS dcesrv_create_ncacn_ip_tcp_socket(const struct sockaddr_storage *ifss,
                                           int *out_fd);
 NTSTATUS dcesrv_setup_ncacn_ip_tcp_socket(struct tevent_context *ev_ctx,
                                          struct messaging_context *msg_ctx,
+                                         struct dcesrv_context *dce_ctx,
+                                         struct dcesrv_endpoint *e,
                                          const struct sockaddr_storage *ifss,
-                                         uint16_t *port);
+                                         dcerpc_ncacn_termination_fn term_fn,
+                                         void *term_data);
 
 NTSTATUS dcesrv_create_ncalrpc_socket(const char *name, int *out_fd);
 NTSTATUS dcesrv_setup_ncalrpc_socket(struct tevent_context *ev_ctx,
index 4eebb280eb21a319917053c824919ba97afbeedd..311654bf4cd55ce52c7ceb1f1fe570d2443bd193 100644 (file)
@@ -213,8 +213,13 @@ NTSTATUS dcesrv_setup_endpoint_sockets(struct tevent_context *ev_ctx,
                break;
 
        case NCACN_IP_TCP:
-               /* TODO */
-               status = NT_STATUS_OK;
+               status = dcesrv_setup_ncacn_ip_tcp_sockets(ev_ctx,
+                                                          msg_ctx,
+                                                          dce_ctx,
+                                                          e,
+                                                          bvec,
+                                                          term_fn,
+                                                          term_data);
                break;
 
        case NCACN_NP:
index 069d0959534d383caf0e75e3b247cc553a15520b..5ca154bf5adcda51fa57e68e3a99c7e841aab45f 100644 (file)
@@ -27,6 +27,7 @@
 #include "rpc_server/rpc_server.h"
 #include "rpc_server/rpc_sock_helper.h"
 #include "lib/server_prefork.h"
+#include "librpc/ndr/ndr_table.h"
 
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_RPC_SRV
@@ -158,16 +159,15 @@ done:
 }
 
 NTSTATUS dcesrv_setup_ncacn_ip_tcp_sockets(struct tevent_context *ev_ctx,
-                               struct messaging_context *msg_ctx,
-                               const struct ndr_interface_table *iface,
-                               struct dcerpc_binding_vector *bvec,
-                               uint16_t port)
+                                          struct messaging_context *msg_ctx,
+                                          struct dcesrv_context *dce_ctx,
+                                          struct dcesrv_endpoint *e,
+                                          struct dcerpc_binding_vector *bvec,
+                                          dcerpc_ncacn_termination_fn t_fn,
+                                          void *t_data)
 {
-       uint32_t num_ifs = iface_count();
-       uint32_t i;
-       uint16_t p = port;
        TALLOC_CTX *tmp_ctx;
-       NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
+       NTSTATUS status;
        int rc;
 
        tmp_ctx = talloc_stackframe();
@@ -176,6 +176,9 @@ NTSTATUS dcesrv_setup_ncacn_ip_tcp_sockets(struct tevent_context *ev_ctx,
        }
 
        if (lp_interfaces() && lp_bind_interfaces_only()) {
+               uint32_t num_ifs = iface_count();
+               uint32_t i;
+
                /*
                 * We have been given an interfaces line, and been told to only
                 * bind to those interfaces. Create a socket per interface and
@@ -188,16 +191,23 @@ NTSTATUS dcesrv_setup_ncacn_ip_tcp_sockets(struct tevent_context *ev_ctx,
                                        iface_n_sockaddr_storage(i);
                        struct tsocket_address *bind_addr;
                        const char *addr;
+                       const char *endpoint;
+                       uint16_t port = 0;
 
                        status = dcesrv_setup_ncacn_ip_tcp_socket(ev_ctx,
                                                                  msg_ctx,
+                                                                 dce_ctx,
+                                                                 e,
                                                                  ifss,
-                                                                 &p);
+                                                                 t_fn,
+                                                                 t_data);
                        if (!NT_STATUS_IS_OK(status)) {
                                goto done;
                        }
 
                        if (bvec != NULL) {
+                               struct dcesrv_if_list *if_list = NULL;
+
                                rc = tsocket_address_bsd_from_sockaddr(tmp_ctx,
                                                                       (const struct sockaddr*)ifss,
                                                                       sizeof(struct sockaddr_storage),
@@ -214,12 +224,24 @@ NTSTATUS dcesrv_setup_ncacn_ip_tcp_sockets(struct tevent_context *ev_ctx,
                                        goto done;
                                }
 
-                               status = dcerpc_binding_vector_add_port(iface,
-                                                                       bvec,
-                                                                       addr,
-                                                                       p);
-                               if (!NT_STATUS_IS_OK(status)) {
-                                       goto done;
+                               endpoint = dcerpc_binding_get_string_option(e->ep_description,
+                                                                           "endpoint");
+                               if (endpoint != NULL) {
+                                       port = atoi(endpoint);
+                               }
+
+                               for (if_list = e->interface_list; if_list; if_list = if_list->next) {
+                                       const struct ndr_interface_table *iface = NULL;
+                                       iface = ndr_table_by_syntax(&if_list->iface->syntax_id);
+                                       if (iface != NULL) {
+                                               status = dcerpc_binding_vector_add_port(iface,
+                                                                                       bvec,
+                                                                                       addr,
+                                                                                       port);
+                                               if (!NT_STATUS_IS_OK(status)) {
+                                                       goto done;
+                                               }
+                                       }
                                }
                        }
                }
@@ -248,19 +270,38 @@ NTSTATUS dcesrv_setup_ncacn_ip_tcp_sockets(struct tevent_context *ev_ctx,
 
                        status = dcesrv_setup_ncacn_ip_tcp_socket(ev_ctx,
                                                                  msg_ctx,
+                                                                 dce_ctx,
+                                                                 e,
                                                                  &ss,
-                                                                 &p);
+                                                                 t_fn,
+                                                                 t_data);
                        if (!NT_STATUS_IS_OK(status)) {
                                goto done;
                        }
 
                        if (bvec != NULL) {
-                               status = dcerpc_binding_vector_add_port(iface,
-                                                                       bvec,
-                                                                       sock_tok,
-                                                                       p);
-                               if (!NT_STATUS_IS_OK(status)) {
-                                       goto done;
+                               struct dcesrv_if_list *if_list = NULL;
+                               const char *endpoint;
+                               uint16_t port = 0;
+
+                               endpoint = dcerpc_binding_get_string_option(e->ep_description,
+                                                                           "endpoint");
+                               if (endpoint != NULL) {
+                                       port = atoi(endpoint);
+                               }
+
+                               for (if_list = e->interface_list; if_list; if_list = if_list->next) {
+                                       const struct ndr_interface_table *iface = NULL;
+                                       iface = ndr_table_by_syntax(&if_list->iface->syntax_id);
+                                       if (iface != NULL) {
+                                               status = dcerpc_binding_vector_add_port(iface,
+                                                                                       bvec,
+                                                                                       sock_tok,
+                                                                                       port);
+                                               if (!NT_STATUS_IS_OK(status)) {
+                                                       goto done;
+                                               }
+                                       }
                                }
                        }
                }
index 4aca3411de6ff14db3f01c1212f6d7e8e9f84c6c..1bf1be4c0e4b1855802ba9b3270482557c5bd5ad 100644 (file)
@@ -23,6 +23,8 @@
 #ifndef _RPC_SOCK_HELPER_H_
 #define _RPC_SOCK_HELPER_H_
 
+#include "rpc_server.h"
+
 struct pf_listen_fd;
 
 NTSTATUS dcesrv_create_ncacn_ip_tcp_sockets(
@@ -33,10 +35,12 @@ NTSTATUS dcesrv_create_ncacn_ip_tcp_sockets(
                                int *listen_fd_size);
 
 NTSTATUS dcesrv_setup_ncacn_ip_tcp_sockets(struct tevent_context *ev_ctx,
-                               struct messaging_context *msg_ctx,
-                               const struct ndr_interface_table *iface,
-                               struct dcerpc_binding_vector *bvec,
-                               uint16_t port);
+                                          struct messaging_context *msg_ctx,
+                                          struct dcesrv_context *dce_ctx,
+                                          struct dcesrv_endpoint *e,
+                                          struct dcerpc_binding_vector *bvec,
+                                          dcerpc_ncacn_termination_fn t_fn,
+                                          void *t_data);
 
 #endif /* _RPC_SOCK_HELPER_H_ */