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

Generated by: LCOV version 1.14