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

Generated by: LCOV version 1.14