LCOV - code coverage report
Current view: top level - source4/rpc_server - service_rpc.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 46 56 82.1 %
Date: 2024-06-13 04:01:37 Functions: 6 6 100.0 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    smbd-specific dcerpc server code
       5             : 
       6             :    Copyright (C) Andrew Tridgell 2003-2005
       7             :    Copyright (C) Stefan (metze) Metzmacher 2004-2005
       8             :    Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2004,2007
       9             :    
      10             :    This program is free software; you can redistribute it and/or modify
      11             :    it under the terms of the GNU General Public License as published by
      12             :    the Free Software Foundation; either version 3 of the License, or
      13             :    (at your option) any later version.
      14             :    
      15             :    This program is distributed in the hope that it will be useful,
      16             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      17             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      18             :    GNU General Public License for more details.
      19             :    
      20             :    You should have received a copy of the GNU General Public License
      21             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      22             : */
      23             : 
      24             : #include "includes.h"
      25             : #include "librpc/gen_ndr/ndr_dcerpc.h"
      26             : #include "auth/auth.h"
      27             : #include "../lib/util/dlinklist.h"
      28             : #include "rpc_server/dcerpc_server.h"
      29             : #include "rpc_server/dcerpc_server_proto.h"
      30             : #include "librpc/rpc/dcerpc.h"
      31             : #include "system/filesys.h"
      32             : #include "lib/messaging/irpc.h"
      33             : #include "system/network.h"
      34             : #include "lib/socket/netif.h"
      35             : #include "param/param.h"
      36             : #include "../lib/tsocket/tsocket.h"
      37             : #include "librpc/rpc/dcerpc_proto.h"
      38             : #include "../lib/util/tevent_ntstatus.h"
      39             : #include "libcli/raw/smb.h"
      40             : #include "../libcli/named_pipe_auth/npa_tstream.h"
      41             : #include "samba/process_model.h"
      42             : 
      43       37693 : static void skip_become_root(void)
      44             : {
      45       37693 : }
      46             : 
      47       37693 : static void skip_unbecome_root(void)
      48             : {
      49       37693 : }
      50             : 
      51             : static struct dcesrv_context_callbacks srv_callbacks = {
      52             :         .log.successful_authz = log_successful_dcesrv_authz_event,
      53             :         .auth.gensec_prepare = dcesrv_gensec_prepare,
      54             :         .auth.become_root = skip_become_root,
      55             :         .auth.unbecome_root = skip_unbecome_root,
      56             :         .assoc_group.find = dcesrv_assoc_group_find_s4,
      57             : };
      58             : 
      59             : /*
      60             :  * Need to run the majority of the RPC endpoints in a single process to allow
      61             :  * for shared handles, and the sharing of ldb contexts.
      62             :  *
      63             :  * However other endpoints are capable of being run in multiple processes
      64             :  * e.g. NETLOGON.
      65             :  *
      66             :  * To support this the process model is manipulated to force those end points
      67             :  * not supporting multiple processes into the single process model. The code
      68             :  * responsible for this is in dcesrv_init_endpoints
      69             :  *
      70             :  */
      71             : NTSTATUS server_service_rpc_init(TALLOC_CTX *);
      72             : 
      73             : /*
      74             :  * Initialise the rpc endpoints.
      75             :  */
      76         110 : static NTSTATUS dcesrv_init_endpoints(struct task_server *task,
      77             :                                       struct dcesrv_context *dce_ctx,
      78             :                                       bool use_single_process)
      79             : {
      80             : 
      81             :         struct dcesrv_endpoint *e;
      82         110 :         const struct model_ops *model_ops = NULL;
      83             : 
      84             :         /*
      85             :          * For those RPC services that run with shared context we need to
      86             :          * ensure that they don't fork a new process on accept (standard_model).
      87             :          * And as there is only one process handling these requests we need
      88             :          * to handle accept errors in a similar manner to the single process
      89             :          * model.
      90             :          *
      91             :          * To do this we override the process model operations with the single
      92             :          * process operations. This is not the most elegant solution, but it is
      93             :          * the least ugly, and is confined to the next block of code.
      94             :          */
      95         110 :         if (use_single_process) {
      96          56 :                 model_ops = process_model_startup("single");
      97          56 :                 if (model_ops == NULL) {
      98           0 :                         DBG_ERR("Unable to load single process model");
      99           0 :                         return NT_STATUS_INTERNAL_ERROR;
     100             :                 }
     101             :         } else {
     102          54 :                 model_ops = task->model_ops;
     103             :         }
     104             : 
     105        2076 :         for (e = dce_ctx->endpoint_list; e; e = e->next) {
     106             : 
     107        1436 :                 enum dcerpc_transport_t transport =
     108        1966 :                     dcerpc_binding_get_transport(e->ep_description);
     109             : 
     110        1966 :                 if (transport == NCACN_HTTP) {
     111             :                         /*
     112             :                          * We don't support ncacn_http yet
     113             :                          */
     114         110 :                         continue;
     115             :                 }
     116        1856 :                 if (e->use_single_process == use_single_process) {
     117             :                         NTSTATUS status;
     118         940 :                         status = dcesrv_add_ep(dce_ctx,
     119             :                                                task->lp_ctx,
     120             :                                                e,
     121             :                                                task->event_ctx,
     122             :                                                model_ops,
     123             :                                                task->process_context);
     124         940 :                         if (!NT_STATUS_IS_OK(status)) {
     125           0 :                                 return status;
     126             :                         }
     127             :                 }
     128             :         }
     129         110 :         return NT_STATUS_OK;
     130             : }
     131             : 
     132             : /*
     133             :  * Initialise the RPC service.
     134             :  * And those end points that can be serviced by multiple processes.
     135             :  * The endpoints that need to be run in a single process are setup in the
     136             :  * post_fork hook.
     137             : */
     138          54 : static NTSTATUS dcesrv_task_init(struct task_server *task)
     139             : {
     140          54 :         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
     141             :         struct dcesrv_context *dce_ctx;
     142          54 :         const char **ep_servers = NULL;
     143             : 
     144          54 :         dcerpc_server_init(task->lp_ctx);
     145             : 
     146          54 :         task_server_set_title(task, "task[dcesrv]");
     147             : 
     148          54 :         status = dcesrv_init_context(task->event_ctx,
     149             :                                      task->lp_ctx,
     150             :                                      &srv_callbacks,
     151             :                                      &dce_ctx);
     152          54 :         if (!NT_STATUS_IS_OK(status)) {
     153           0 :                 return status;
     154             :         }
     155             : 
     156          54 :         ep_servers = lpcfg_dcerpc_endpoint_servers(task->lp_ctx);
     157          54 :         status = dcesrv_init_ep_servers(dce_ctx, ep_servers);
     158          54 :         if (!NT_STATUS_IS_OK(status)) {
     159           0 :                 return status;
     160             :         }
     161             : 
     162             :         /* Make sure the directory for NCALRPC exists */
     163          54 :         if (!directory_exist(lpcfg_ncalrpc_dir(task->lp_ctx))) {
     164          53 :                 mkdir(lpcfg_ncalrpc_dir(task->lp_ctx), 0755);
     165             :         }
     166          54 :         status = dcesrv_init_endpoints(task, dce_ctx, false);
     167          54 :         if (!NT_STATUS_IS_OK(status)) {
     168           0 :                 return status;
     169             :         }
     170             : 
     171          54 :         task->private_data = dce_ctx;
     172          54 :         return NT_STATUS_OK;
     173             : }
     174             : 
     175             : /*
     176             :  * Initialise the endpoints that need to run in a single process fork.
     177             :  * The endpoint registration is only done for the first process instance.
     178             :  *
     179             :  */
     180         110 : static void dcesrv_post_fork(struct task_server *task,
     181             :                              struct process_details *pd)
     182             : {
     183             : 
     184         110 :         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
     185             :         struct dcesrv_context *dce_ctx;
     186             : 
     187         110 :         if (task->private_data == NULL) {
     188           0 :                 task_server_terminate(task, "dcerpc: No dcesrv_context", true);
     189           0 :                 return;
     190             :         }
     191          83 :         dce_ctx =
     192         110 :             talloc_get_type_abort(task->private_data, struct dcesrv_context);
     193             : 
     194             :         /*
     195             :          * Ensure the single process endpoints are only available to the
     196             :          * first instance.
     197             :          */
     198         110 :         if (pd->instances == 0) {
     199          56 :                 status = dcesrv_init_endpoints(task, dce_ctx, true);
     200          56 :                 if (!NT_STATUS_IS_OK(status)) {
     201           0 :                         task_server_terminate(
     202             :                             task,
     203             :                             "dcerpc: Failed to initialise end points",
     204             :                             true);
     205           0 :                         return;
     206             :                 }
     207             :         }
     208             : 
     209         110 :         irpc_add_name(task->msg_ctx, "rpc_server");
     210             : }
     211             : 
     212          53 : NTSTATUS server_service_rpc_init(TALLOC_CTX *ctx)
     213             : {
     214             :         static const struct service_details details = {
     215             :             .inhibit_fork_on_accept = false,
     216             :             .inhibit_pre_fork = false,
     217             :             .task_init = dcesrv_task_init,
     218             :             .post_fork = dcesrv_post_fork};
     219          53 :         return register_server_service(ctx, "rpc", &details);
     220             : }

Generated by: LCOV version 1.13