LCOV - code coverage report
Current view: top level - source4/rpc_server - dcerpc_server.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 198 284 69.7 %
Date: 2021-09-23 10:06:22 Functions: 15 19 78.9 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    server side dcerpc core code
       5             : 
       6             :    Copyright (C) Andrew Tridgell 2003-2005
       7             :    Copyright (C) Stefan (metze) Metzmacher 2004-2005
       8             :    
       9             :    This program is free software; you can redistribute it and/or modify
      10             :    it under the terms of the GNU General Public License as published by
      11             :    the Free Software Foundation; either version 3 of the License, or
      12             :    (at your option) any later version.
      13             :    
      14             :    This program is distributed in the hope that it will be useful,
      15             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17             :    GNU General Public License for more details.
      18             :    
      19             :    You should have received a copy of the GNU General Public License
      20             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      21             : */
      22             : 
      23             : #include "includes.h"
      24             : #include "auth/auth.h"
      25             : #include "auth/gensec/gensec.h"
      26             : #include "auth/credentials/credentials.h"
      27             : #include "rpc_server/dcerpc_server.h"
      28             : #include "rpc_server/dcerpc_server_proto.h"
      29             : #include "param/param.h"
      30             : #include "samba/service_stream.h"
      31             : #include "lib/tsocket/tsocket.h"
      32             : #include "lib/socket/socket.h"
      33             : #include "samba/process_model.h"
      34             : #include "lib/util/samba_modules.h"
      35             : #include "lib/util/tevent_ntstatus.h"
      36             : 
      37             : /*
      38             :   take a reference to an existing association group
      39             :  */
      40         679 : static struct dcesrv_assoc_group *dcesrv_assoc_group_reference(struct dcesrv_connection *conn,
      41             :                                                                uint32_t id)
      42             : {
      43         679 :         const struct dcesrv_endpoint *endpoint = conn->endpoint;
      44         568 :         enum dcerpc_transport_t transport =
      45         679 :                 dcerpc_binding_get_transport(endpoint->ep_description);
      46             :         struct dcesrv_assoc_group *assoc_group;
      47         679 :         void *id_ptr = NULL;
      48             : 
      49             :         /* find an association group given a assoc_group_id */
      50         679 :         id_ptr = idr_find(conn->dce_ctx->assoc_groups_idr, id);
      51         679 :         if (id_ptr == NULL) {
      52         257 :                 DBG_NOTICE("Failed to find assoc_group 0x%08x\n", id);
      53         230 :                 return NULL;
      54             :         }
      55         422 :         assoc_group = talloc_get_type_abort(id_ptr, struct dcesrv_assoc_group);
      56             : 
      57         422 :         if (assoc_group->transport != transport) {
      58           1 :                 const char *at =
      59           1 :                         derpc_transport_string_by_transport(
      60             :                                 assoc_group->transport);
      61           1 :                 const char *ct =
      62           0 :                         derpc_transport_string_by_transport(
      63             :                                 transport);
      64             : 
      65           1 :                 DBG_NOTICE("assoc_group 0x%08x (transport %s) "
      66             :                            "is not available on transport %s",
      67             :                            id, at, ct);
      68           1 :                 return NULL;
      69             :         }
      70             : 
      71         421 :         return talloc_reference(conn, assoc_group);
      72             : }
      73             : 
      74       18875 : static int dcesrv_assoc_group_destructor(struct dcesrv_assoc_group *assoc_group)
      75             : {
      76             :         int ret;
      77       18875 :         ret = idr_remove(assoc_group->dce_ctx->assoc_groups_idr, assoc_group->id);
      78       18875 :         if (ret != 0) {
      79           0 :                 DEBUG(0,(__location__ ": Failed to remove assoc_group 0x%08x\n",
      80             :                          assoc_group->id));
      81             :         }
      82       18875 :         return 0;
      83             : }
      84             : 
      85             : /*
      86             :   allocate a new association group
      87             :  */
      88       17365 : static struct dcesrv_assoc_group *dcesrv_assoc_group_new(struct dcesrv_connection *conn)
      89             : {
      90       17365 :         struct dcesrv_context *dce_ctx = conn->dce_ctx;
      91       17365 :         const struct dcesrv_endpoint *endpoint = conn->endpoint;
      92       13919 :         enum dcerpc_transport_t transport =
      93       17365 :                 dcerpc_binding_get_transport(endpoint->ep_description);
      94             :         struct dcesrv_assoc_group *assoc_group;
      95             :         int id;
      96             : 
      97       17365 :         assoc_group = talloc_zero(conn, struct dcesrv_assoc_group);
      98       17365 :         if (assoc_group == NULL) {
      99           0 :                 return NULL;
     100             :         }
     101             : 
     102       17365 :         id = idr_get_new_random(dce_ctx->assoc_groups_idr, assoc_group, UINT16_MAX);
     103       17365 :         if (id == -1) {
     104           0 :                 talloc_free(assoc_group);
     105           0 :                 DEBUG(0,(__location__ ": Out of association groups!\n"));
     106           0 :                 return NULL;
     107             :         }
     108             : 
     109       17365 :         assoc_group->transport = transport;
     110       17365 :         assoc_group->id = id;
     111       17365 :         assoc_group->dce_ctx = dce_ctx;
     112             : 
     113       17365 :         talloc_set_destructor(assoc_group, dcesrv_assoc_group_destructor);
     114             : 
     115       17365 :         return assoc_group;
     116             : }
     117             : 
     118       17885 : NTSTATUS dcesrv_assoc_group_find(
     119             :         struct dcesrv_call_state *call,
     120             :         void *private_data)
     121             : {
     122             :         /*
     123             :           if provided, check the assoc_group is valid
     124             :          */
     125       17885 :         if (call->pkt.u.bind.assoc_group_id != 0) {
     126        1169 :                 call->conn->assoc_group =
     127        1169 :                         dcesrv_assoc_group_reference(call->conn,
     128             :                                         call->pkt.u.bind.assoc_group_id);
     129             :         } else {
     130       17206 :                 call->conn->assoc_group = dcesrv_assoc_group_new(call->conn);
     131             :         }
     132             : 
     133             :         /*
     134             :          * The NETLOGON server does not use handles and so
     135             :          * there is no need to support association groups, but
     136             :          * we need to give back a number regardless.
     137             :          *
     138             :          * We have to do this when it is not run as a single process,
     139             :          * because then it can't see the other valid association
     140             :          * groups.  We handle this genericly for all endpoints not
     141             :          * running in single process mode.
     142             :          *
     143             :          * We know which endpoint we are on even before checking the
     144             :          * iface UUID, so for simplicity we enforce the same policy
     145             :          * for all interfaces on the endpoint.
     146             :          *
     147             :          * This means that where NETLOGON
     148             :          * shares an endpoint (such as ncalrpc or if 'lsa over
     149             :          * netlogon' is set) we will still check association groups.
     150             :          *
     151             :          */
     152             : 
     153       18074 :         if (call->conn->assoc_group == NULL &&
     154         258 :             !call->conn->endpoint->use_single_process) {
     155         156 :                 call->conn->assoc_group
     156         270 :                         = dcesrv_assoc_group_new(call->conn);
     157             :         }
     158             : 
     159       17885 :         if (call->conn->assoc_group == NULL) {
     160             :                 /* TODO Return correct status */
     161          99 :                 return NT_STATUS_UNSUCCESSFUL;
     162             :         }
     163             : 
     164       17786 :         return NT_STATUS_OK;
     165             : }
     166             : 
     167          64 : void dcerpc_server_init(struct loadparm_context *lp_ctx)
     168             : {
     169             :         static bool initialized;
     170             : #define _MODULE_PROTO(init) extern NTSTATUS init(TALLOC_CTX *);
     171             :         STATIC_dcerpc_server_MODULES_PROTO;
     172          64 :         init_module_fn static_init[] = { STATIC_dcerpc_server_MODULES };
     173             :         init_module_fn *shared_init;
     174             : 
     175          64 :         if (initialized) {
     176           0 :                 return;
     177             :         }
     178          64 :         initialized = true;
     179             : 
     180          64 :         shared_init = load_samba_modules(NULL, "dcerpc_server");
     181             : 
     182          64 :         run_init_functions(NULL, static_init);
     183          64 :         run_init_functions(NULL, shared_init);
     184             : 
     185          64 :         talloc_free(shared_init);
     186             : }
     187             : 
     188             : struct dcesrv_socket_context {
     189             :         const struct dcesrv_endpoint *endpoint;
     190             :         struct dcesrv_context *dcesrv_ctx;
     191             : };
     192             : 
     193       17911 : static void dcesrv_sock_accept(struct stream_connection *srv_conn)
     194             : {
     195             :         NTSTATUS status;
     196       14399 :         struct dcesrv_socket_context *dcesrv_sock = 
     197       17911 :                 talloc_get_type(srv_conn->private_data, struct dcesrv_socket_context);
     198       14399 :         enum dcerpc_transport_t transport =
     199       17911 :                 dcerpc_binding_get_transport(dcesrv_sock->endpoint->ep_description);
     200       17911 :         struct dcesrv_connection *dcesrv_conn = NULL;
     201             :         int ret;
     202       17911 :         struct loadparm_context *lp_ctx = dcesrv_sock->dcesrv_ctx->lp_ctx;
     203             : 
     204       17911 :         dcesrv_cleanup_broken_connections(dcesrv_sock->dcesrv_ctx);
     205             : 
     206       17911 :         if (!srv_conn->session_info) {
     207       10893 :                 status = auth_anonymous_session_info(srv_conn,
     208             :                                                      lp_ctx,
     209             :                                                      &srv_conn->session_info);
     210       10893 :                 if (!NT_STATUS_IS_OK(status)) {
     211           0 :                         DEBUG(0,("dcesrv_sock_accept: auth_anonymous_session_info failed: %s\n",
     212             :                                 nt_errstr(status)));
     213           0 :                         stream_terminate_connection(srv_conn, nt_errstr(status));
     214           0 :                         return;
     215             :                 }
     216             :         }
     217             : 
     218             :         /*
     219             :          * This fills in dcesrv_conn->endpoint with the endpoint
     220             :          * associated with the socket.  From this point on we know
     221             :          * which (group of) services we are handling, but not the
     222             :          * specific interface.
     223             :          */
     224             : 
     225       17911 :         status = dcesrv_endpoint_connect(dcesrv_sock->dcesrv_ctx,
     226             :                                          srv_conn,
     227             :                                          dcesrv_sock->endpoint,
     228             :                                          srv_conn->session_info,
     229             :                                          srv_conn->event.ctx,
     230             :                                          DCESRV_CALL_STATE_FLAG_MAY_ASYNC,
     231             :                                          &dcesrv_conn);
     232       17911 :         if (!NT_STATUS_IS_OK(status)) {
     233           0 :                 DEBUG(0,("dcesrv_sock_accept: dcesrv_endpoint_connect failed: %s\n", 
     234             :                         nt_errstr(status)));
     235           0 :                 stream_terminate_connection(srv_conn, nt_errstr(status));
     236           0 :                 return;
     237             :         }
     238             : 
     239       17911 :         dcesrv_conn->transport.private_data          = srv_conn;
     240       17911 :         dcesrv_conn->transport.report_output_data    = dcesrv_sock_report_output_data;
     241       17911 :         dcesrv_conn->transport.terminate_connection  = dcesrv_transport_terminate_connection;
     242             : 
     243       17911 :         TALLOC_FREE(srv_conn->event.fde);
     244             : 
     245       17911 :         dcesrv_conn->send_queue = tevent_queue_create(dcesrv_conn, "dcesrv send queue");
     246       17911 :         if (!dcesrv_conn->send_queue) {
     247           0 :                 status = NT_STATUS_NO_MEMORY;
     248           0 :                 DEBUG(0,("dcesrv_sock_accept: tevent_queue_create(%s)\n",
     249             :                         nt_errstr(status)));
     250           0 :                 stream_terminate_connection(srv_conn, nt_errstr(status));
     251           0 :                 return;
     252             :         }
     253             : 
     254       17911 :         if (transport == NCACN_NP) {
     255        7018 :                 dcesrv_conn->stream = talloc_move(dcesrv_conn,
     256             :                                                   &srv_conn->tstream);
     257             :         } else {
     258       10893 :                 ret = tstream_bsd_existing_socket(dcesrv_conn,
     259             :                                                   socket_get_fd(srv_conn->socket),
     260             :                                                   &dcesrv_conn->stream);
     261       10893 :                 if (ret == -1) {
     262           0 :                         status = map_nt_error_from_unix_common(errno);
     263           0 :                         DEBUG(0, ("dcesrv_sock_accept: "
     264             :                                   "failed to setup tstream: %s\n",
     265             :                                   nt_errstr(status)));
     266           0 :                         stream_terminate_connection(srv_conn, nt_errstr(status));
     267           0 :                         return;
     268             :                 }
     269       10893 :                 socket_set_flags(srv_conn->socket, SOCKET_FLAG_NOCLOSE);
     270             :         }
     271             : 
     272       17911 :         dcesrv_conn->local_address = srv_conn->local_address;
     273       17911 :         dcesrv_conn->remote_address = srv_conn->remote_address;
     274             : 
     275       17911 :         if (transport == NCALRPC) {
     276             :                 uid_t uid;
     277             :                 gid_t gid;
     278             :                 int sock_fd;
     279             : 
     280        1522 :                 sock_fd = socket_get_fd(srv_conn->socket);
     281        1522 :                 if (sock_fd == -1) {
     282           0 :                         stream_terminate_connection(
     283             :                                 srv_conn, "socket_get_fd failed\n");
     284           0 :                         return;
     285             :                 }
     286             : 
     287        1522 :                 ret = getpeereid(sock_fd, &uid, &gid);
     288        1522 :                 if (ret == -1) {
     289           0 :                         status = map_nt_error_from_unix_common(errno);
     290           0 :                         DEBUG(0, ("dcesrv_sock_accept: "
     291             :                                   "getpeereid() failed for NCALRPC: %s\n",
     292             :                                   nt_errstr(status)));
     293           0 :                         stream_terminate_connection(srv_conn, nt_errstr(status));
     294           0 :                         return;
     295             :                 }
     296        1522 :                 if (uid == dcesrv_conn->dce_ctx->initial_euid) {
     297        1522 :                         struct tsocket_address *r = NULL;
     298             : 
     299        1522 :                         ret = tsocket_address_unix_from_path(dcesrv_conn,
     300             :                                                              AS_SYSTEM_MAGIC_PATH_TOKEN,
     301             :                                                              &r);
     302        1522 :                         if (ret == -1) {
     303           0 :                                 status = map_nt_error_from_unix_common(errno);
     304           0 :                                 DEBUG(0, ("dcesrv_sock_accept: "
     305             :                                           "tsocket_address_unix_from_path() failed for NCALRPC: %s\n",
     306             :                                           nt_errstr(status)));
     307           0 :                                 stream_terminate_connection(srv_conn, nt_errstr(status));
     308           0 :                                 return;
     309             :                         }
     310        1522 :                         dcesrv_conn->remote_address = r;
     311             :                 }
     312             :         }
     313             : 
     314       17911 :         srv_conn->private_data = dcesrv_conn;
     315             : 
     316       17911 :         status = dcesrv_connection_loop_start(dcesrv_conn);
     317       17911 :         if (!NT_STATUS_IS_OK(status)) {
     318           0 :                 DEBUG(0,("dcesrv_sock_accept: dcerpc_read_fragment_buffer_send(%s)\n",
     319             :                         nt_errstr(status)));
     320           0 :                 stream_terminate_connection(srv_conn, nt_errstr(status));
     321           0 :                 return;
     322             :         }
     323             : 
     324       17031 :         return;
     325             : }
     326             : 
     327           0 : static void dcesrv_sock_recv(struct stream_connection *conn, uint16_t flags)
     328             : {
     329           0 :         struct dcesrv_connection *dce_conn = talloc_get_type(conn->private_data,
     330             :                                              struct dcesrv_connection);
     331           0 :         dcesrv_terminate_connection(dce_conn, "dcesrv_sock_recv triggered");
     332           0 : }
     333             : 
     334           0 : static void dcesrv_sock_send(struct stream_connection *conn, uint16_t flags)
     335             : {
     336           0 :         struct dcesrv_connection *dce_conn = talloc_get_type(conn->private_data,
     337             :                                              struct dcesrv_connection);
     338           0 :         dcesrv_terminate_connection(dce_conn, "dcesrv_sock_send triggered");
     339           0 : }
     340             : 
     341             : 
     342             : static const struct stream_server_ops dcesrv_stream_ops = {
     343             :         .name                   = "rpc",
     344             :         .accept_connection      = dcesrv_sock_accept,
     345             :         .recv_handler           = dcesrv_sock_recv,
     346             :         .send_handler           = dcesrv_sock_send,
     347             : };
     348             : 
     349           0 : static NTSTATUS dcesrv_add_ep_unix(struct dcesrv_context *dce_ctx, 
     350             :                                    struct loadparm_context *lp_ctx,
     351             :                                    struct dcesrv_endpoint *e,
     352             :                                    struct tevent_context *event_ctx,
     353             :                                    const struct model_ops *model_ops,
     354             :                                    void *process_context)
     355             : {
     356             :         struct dcesrv_socket_context *dcesrv_sock;
     357           0 :         uint16_t port = 1;
     358             :         NTSTATUS status;
     359             :         const char *endpoint;
     360             : 
     361           0 :         dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
     362           0 :         NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
     363             : 
     364             :         /* remember the endpoint of this socket */
     365           0 :         dcesrv_sock->endpoint                = e;
     366           0 :         dcesrv_sock->dcesrv_ctx              = talloc_reference(dcesrv_sock, dce_ctx);
     367             : 
     368           0 :         endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
     369             : 
     370           0 :         status = stream_setup_socket(dcesrv_sock, event_ctx, lp_ctx,
     371             :                                      model_ops, &dcesrv_stream_ops, 
     372             :                                      "unix", endpoint, &port,
     373             :                                      lpcfg_socket_options(lp_ctx),
     374             :                                      dcesrv_sock, process_context);
     375           0 :         if (!NT_STATUS_IS_OK(status)) {
     376           0 :                 DEBUG(0,("service_setup_stream_socket(path=%s) failed - %s\n",
     377             :                          endpoint, nt_errstr(status)));
     378             :         }
     379             : 
     380           0 :         return status;
     381             : }
     382             : 
     383         134 : static NTSTATUS dcesrv_add_ep_ncalrpc(struct dcesrv_context *dce_ctx, 
     384             :                                       struct loadparm_context *lp_ctx,
     385             :                                       struct dcesrv_endpoint *e,
     386             :                                       struct tevent_context *event_ctx,
     387             :                                       const struct model_ops *model_ops,
     388             :                                       void *process_context)
     389             : {
     390             :         struct dcesrv_socket_context *dcesrv_sock;
     391         134 :         uint16_t port = 1;
     392             :         char *full_path;
     393             :         NTSTATUS status;
     394             :         const char *endpoint;
     395             : 
     396         134 :         endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
     397             : 
     398         134 :         if (endpoint == NULL) {
     399             :                 /*
     400             :                  * No identifier specified: use DEFAULT.
     401             :                  *
     402             :                  * TODO: DO NOT hardcode this value anywhere else. Rather, specify
     403             :                  * no endpoint and let the epmapper worry about it.
     404             :                  */
     405          68 :                 endpoint = "DEFAULT";
     406          68 :                 status = dcerpc_binding_set_string_option(e->ep_description,
     407             :                                                           "endpoint",
     408             :                                                           endpoint);
     409          68 :                 if (!NT_STATUS_IS_OK(status)) {
     410           0 :                         DEBUG(0,("dcerpc_binding_set_string_option() failed - %s\n",
     411             :                                   nt_errstr(status)));
     412           0 :                         return status;
     413             :                 }
     414             :         }
     415             : 
     416         134 :         full_path = talloc_asprintf(dce_ctx, "%s/%s", lpcfg_ncalrpc_dir(lp_ctx),
     417             :                                     endpoint);
     418             : 
     419         134 :         dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
     420         134 :         NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
     421             : 
     422             :         /* remember the endpoint of this socket */
     423         134 :         dcesrv_sock->endpoint                = e;
     424         134 :         dcesrv_sock->dcesrv_ctx              = talloc_reference(dcesrv_sock, dce_ctx);
     425             : 
     426         134 :         status = stream_setup_socket(dcesrv_sock, event_ctx, lp_ctx,
     427             :                                      model_ops, &dcesrv_stream_ops, 
     428             :                                      "unix", full_path, &port, 
     429             :                                      lpcfg_socket_options(lp_ctx),
     430             :                                      dcesrv_sock, process_context);
     431         134 :         if (!NT_STATUS_IS_OK(status)) {
     432           0 :                 DEBUG(0,("service_setup_stream_socket(identifier=%s,path=%s) failed - %s\n",
     433             :                          endpoint, full_path, nt_errstr(status)));
     434             :         }
     435         134 :         return status;
     436             : }
     437             : 
     438         840 : static NTSTATUS dcesrv_add_ep_np(struct dcesrv_context *dce_ctx,
     439             :                                  struct loadparm_context *lp_ctx,
     440             :                                  struct dcesrv_endpoint *e,
     441             :                                  struct tevent_context *event_ctx,
     442             :                                  const struct model_ops *model_ops,
     443             :                                  void *process_context)
     444             : {
     445             :         struct dcesrv_socket_context *dcesrv_sock;
     446             :         NTSTATUS status;
     447             :         const char *endpoint;
     448             : 
     449         840 :         endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
     450         840 :         if (endpoint == NULL) {
     451           0 :                 DEBUG(0, ("Endpoint mandatory for named pipes\n"));
     452           0 :                 return NT_STATUS_INVALID_PARAMETER;
     453             :         }
     454             : 
     455         840 :         dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
     456         840 :         NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
     457             : 
     458             :         /* remember the endpoint of this socket */
     459         840 :         dcesrv_sock->endpoint                = e;
     460         840 :         dcesrv_sock->dcesrv_ctx              = talloc_reference(dcesrv_sock, dce_ctx);
     461             : 
     462         840 :         status = tstream_setup_named_pipe(dce_ctx, event_ctx, lp_ctx,
     463             :                                           model_ops, &dcesrv_stream_ops,
     464             :                                           endpoint,
     465             :                                           dcesrv_sock, process_context);
     466         840 :         if (!NT_STATUS_IS_OK(status)) {
     467           0 :                 DEBUG(0,("stream_setup_named_pipe(pipe=%s) failed - %s\n",
     468             :                          endpoint, nt_errstr(status)));
     469           0 :                 return status;
     470             :         }
     471             : 
     472         840 :         return NT_STATUS_OK;
     473             : }
     474             : 
     475             : /*
     476             :   add a socket address to the list of events, one event per dcerpc endpoint
     477             : */
     478         388 : static NTSTATUS add_socket_rpc_tcp_iface(struct dcesrv_context *dce_ctx,
     479             :                                          struct dcesrv_endpoint *e,
     480             :                                          struct tevent_context *event_ctx,
     481             :                                          const struct model_ops *model_ops,
     482             :                                          const char *address,
     483             :                                          void *process_context)
     484             : {
     485             :         struct dcesrv_socket_context *dcesrv_sock;
     486         388 :         uint16_t port = 0;
     487             :         NTSTATUS status;
     488             :         const char *endpoint;
     489             :         char port_str[6];
     490             : 
     491         388 :         endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
     492         388 :         if (endpoint != NULL) {
     493         322 :                 port = atoi(endpoint);
     494             :         }
     495             : 
     496         388 :         dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
     497         388 :         NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
     498             : 
     499             :         /* remember the endpoint of this socket */
     500         388 :         dcesrv_sock->endpoint                = e;
     501         388 :         dcesrv_sock->dcesrv_ctx              = talloc_reference(dcesrv_sock, dce_ctx);
     502             : 
     503         388 :         status = stream_setup_socket(dcesrv_sock, event_ctx, dce_ctx->lp_ctx,
     504             :                                      model_ops, &dcesrv_stream_ops, 
     505             :                                      "ip", address, &port,
     506             :                                      lpcfg_socket_options(dce_ctx->lp_ctx),
     507             :                                      dcesrv_sock, process_context);
     508         388 :         if (!NT_STATUS_IS_OK(status)) {
     509             :                 struct dcesrv_if_list *iface;
     510           0 :                 DEBUG(0,("service_setup_stream_socket(address=%s,port=%u) for ",
     511             :                          address, port));
     512           0 :                 for (iface = e->interface_list; iface; iface = iface->next) {
     513           0 :                         DEBUGADD(0, ("%s ", iface->iface->name));
     514             :                 }
     515           0 :                 DEBUGADD(0, ("failed - %s\n",
     516             :                              nt_errstr(status)));
     517           0 :                 return status;
     518             :         }
     519             : 
     520         400 :         snprintf(port_str, sizeof(port_str), "%u", port);
     521             : 
     522         388 :         status = dcerpc_binding_set_string_option(e->ep_description,
     523             :                                                   "endpoint", port_str);
     524         388 :         if (!NT_STATUS_IS_OK(status)) {
     525           0 :                 DEBUG(0,("dcerpc_binding_set_string_option(endpoint, %s) failed - %s\n",
     526             :                          port_str, nt_errstr(status)));
     527           0 :                 return status;
     528             :         } else {
     529             :                 struct dcesrv_if_list *iface;
     530         388 :                 DEBUG(4,("Successfully listening on ncacn_ip_tcp endpoint [%s]:[%s] for ",
     531             :                          address, port_str));
     532        2580 :                 for (iface = e->interface_list; iface; iface = iface->next) {
     533        2192 :                         DEBUGADD(4, ("%s ", iface->iface->name));
     534             :                 }
     535         388 :                 DEBUGADD(4, ("\n"));
     536             :         }
     537             : 
     538         388 :         return NT_STATUS_OK;
     539             : }
     540             : 
     541             : #include "lib/socket/netif.h" /* Included here to work around the fact that socket_wrapper redefines bind() */
     542             : 
     543         194 : static NTSTATUS dcesrv_add_ep_tcp(struct dcesrv_context *dce_ctx, 
     544             :                                   struct loadparm_context *lp_ctx,
     545             :                                   struct dcesrv_endpoint *e,
     546             :                                   struct tevent_context *event_ctx,
     547             :                                   const struct model_ops *model_ops,
     548             :                                   void *process_context)
     549             : {
     550             :         NTSTATUS status;
     551             : 
     552             :         /* Add TCP/IP sockets */
     553         194 :         if (lpcfg_interfaces(lp_ctx) && lpcfg_bind_interfaces_only(lp_ctx)) {
     554             :                 int num_interfaces;
     555             :                 int i;
     556             :                 struct interface *ifaces;
     557             : 
     558           0 :                 load_interface_list(dce_ctx, lp_ctx, &ifaces);
     559             : 
     560           0 :                 num_interfaces = iface_list_count(ifaces);
     561           0 :                 for(i = 0; i < num_interfaces; i++) {
     562           0 :                         const char *address = iface_list_n_ip(ifaces, i);
     563           0 :                         status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx,
     564             :                                                           model_ops, address,
     565             :                                                           process_context);
     566           0 :                         NT_STATUS_NOT_OK_RETURN(status);
     567             :                 }
     568             :         } else {
     569             :                 char **wcard;
     570             :                 size_t i;
     571         194 :                 size_t num_binds = 0;
     572         194 :                 wcard = iface_list_wildcard(dce_ctx);
     573         194 :                 NT_STATUS_HAVE_NO_MEMORY(wcard);
     574         576 :                 for (i=0; wcard[i]; i++) {
     575         388 :                         status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx,
     576         376 :                                                           model_ops, wcard[i],
     577             :                                                           process_context);
     578         388 :                         if (NT_STATUS_IS_OK(status)) {
     579         388 :                                 num_binds++;
     580             :                         }
     581             :                 }
     582         194 :                 talloc_free(wcard);
     583         194 :                 if (num_binds == 0) {
     584           0 :                         return NT_STATUS_INVALID_PARAMETER_MIX;
     585             :                 }
     586             :         }
     587             : 
     588         194 :         return NT_STATUS_OK;
     589             : }
     590             : 
     591        1168 : NTSTATUS dcesrv_add_ep(struct dcesrv_context *dce_ctx,
     592             :                        struct loadparm_context *lp_ctx,
     593             :                        struct dcesrv_endpoint *e,
     594             :                        struct tevent_context *event_ctx,
     595             :                        const struct model_ops *model_ops,
     596             :                        void *process_context)
     597             : {
     598         834 :         enum dcerpc_transport_t transport =
     599        1168 :                 dcerpc_binding_get_transport(e->ep_description);
     600             : 
     601        1168 :         switch (transport) {
     602           0 :         case NCACN_UNIX_STREAM:
     603           0 :                 return dcesrv_add_ep_unix(dce_ctx, lp_ctx, e, event_ctx,
     604             :                                           model_ops, process_context);
     605             : 
     606         134 :         case NCALRPC:
     607         134 :                 return dcesrv_add_ep_ncalrpc(dce_ctx, lp_ctx, e, event_ctx,
     608             :                                              model_ops, process_context);
     609             : 
     610         194 :         case NCACN_IP_TCP:
     611         194 :                 return dcesrv_add_ep_tcp(dce_ctx, lp_ctx, e, event_ctx,
     612             :                                          model_ops, process_context);
     613             : 
     614         840 :         case NCACN_NP:
     615         840 :                 return dcesrv_add_ep_np(dce_ctx, lp_ctx, e, event_ctx,
     616             :                                         model_ops, process_context);
     617             : 
     618           0 :         default:
     619           0 :                 return NT_STATUS_NOT_SUPPORTED;
     620             :         }
     621             : }
     622             : 
     623       53976 : _PUBLIC_ struct imessaging_context *dcesrv_imessaging_context(
     624             :                                         struct dcesrv_connection *conn)
     625             : {
     626       46439 :         struct stream_connection *srv_conn =
     627       53976 :                 talloc_get_type_abort(conn->transport.private_data,
     628             :                                       struct stream_connection);
     629       53976 :         return srv_conn->msg_ctx;
     630             : }
     631             : 
     632           0 : _PUBLIC_ struct server_id dcesrv_server_id(struct dcesrv_connection *conn)
     633             : {
     634           0 :         struct stream_connection *srv_conn =
     635           0 :                 talloc_get_type_abort(conn->transport.private_data,
     636             :                                 struct stream_connection);
     637           0 :         return srv_conn->server_id;
     638             : }
     639             : 
     640       10826 : void log_successful_dcesrv_authz_event(
     641             :         struct dcesrv_call_state *call,
     642             :         void *private_data)
     643             : {
     644       10826 :         struct dcesrv_auth *auth = call->auth_state;
     645        8361 :         enum dcerpc_transport_t transport =
     646       10826 :                 dcerpc_binding_get_transport(call->conn->endpoint->ep_description);
     647        8361 :         struct imessaging_context *imsg_ctx =
     648       10826 :                 dcesrv_imessaging_context(call->conn);
     649       10826 :         const char *auth_type = derpc_transport_string_by_transport(transport);
     650       10826 :         const char *transport_protection = AUTHZ_TRANSPORT_PROTECTION_NONE;
     651             : 
     652       10826 :         if (transport == NCACN_NP) {
     653        4954 :                 transport_protection = AUTHZ_TRANSPORT_PROTECTION_SMB;
     654             :         }
     655             : 
     656             :         /*
     657             :          * Log the authorization to this RPC interface.  This
     658             :          * covered ncacn_np pass-through auth, and anonymous
     659             :          * DCE/RPC (eg epmapper, netlogon etc)
     660             :          */
     661       35477 :         log_successful_authz_event(imsg_ctx,
     662       10826 :                                    call->conn->dce_ctx->lp_ctx,
     663       10394 :                                    call->conn->remote_address,
     664       10826 :                                    call->conn->local_address,
     665             :                                    "DCE/RPC",
     666             :                                    auth_type,
     667             :                                    transport_protection,
     668             :                                    auth->session_info);
     669             : 
     670       10826 :         auth->auth_audited = true;
     671       10826 : }
     672             : 
     673        7540 : NTSTATUS dcesrv_gensec_prepare(
     674             :         TALLOC_CTX *mem_ctx,
     675             :         struct dcesrv_call_state *call,
     676             :         struct gensec_security **out,
     677             :         void *private_data)
     678             : {
     679        7540 :         struct cli_credentials *server_creds = NULL;
     680        6246 :         struct imessaging_context *imsg_ctx =
     681        7540 :                 dcesrv_imessaging_context(call->conn);
     682             :         bool ok;
     683             : 
     684        7540 :         server_creds = cli_credentials_init_server(call->auth_state,
     685        7540 :                                                    call->conn->dce_ctx->lp_ctx);
     686        7540 :         if (server_creds == NULL) {
     687           0 :                 DEBUG(1, ("Failed to init server credentials\n"));
     688           0 :                 return NT_STATUS_NO_MEMORY;
     689             :         }
     690             :         /* This is required for ncalrpc_as_system. */
     691        7540 :         ok = cli_credentials_set_kerberos_state(server_creds,
     692             :                                                 CRED_USE_KERBEROS_DESIRED,
     693             :                                                 CRED_SPECIFIED);
     694        7540 :         if (!ok) {
     695           0 :                 DBG_WARNING("Failed to set kerberos state\n");
     696           0 :                 return NT_STATUS_INTERNAL_ERROR;
     697             :         }
     698             : 
     699        7540 :         return samba_server_gensec_start(mem_ctx,
     700             :                                          call->event_ctx,
     701             :                                          imsg_ctx,
     702        7540 :                                          call->conn->dce_ctx->lp_ctx,
     703             :                                          server_creds,
     704             :                                          NULL,
     705             :                                          out);
     706             : }
     707             : 
     708       17835 : void dcesrv_transport_terminate_connection(struct dcesrv_connection *dce_conn,
     709             :                                            const char *reason)
     710             : {
     711       14347 :         struct stream_connection *srv_conn =
     712       17835 :                 talloc_get_type_abort(dce_conn->transport.private_data,
     713             :                                       struct stream_connection);
     714       17835 :         stream_terminate_connection(srv_conn, reason);
     715       17518 : }

Generated by: LCOV version 1.13