LCOV - code coverage report
Current view: top level - source3/rpc_server - rpc_server.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 42 125 33.6 %
Date: 2024-04-21 15:09:00 Functions: 5 10 50.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/Netbios implementation.
       3             :    Generic infrstructure for RPC Daemons
       4             :    Copyright (C) Simo Sorce 2010
       5             :    Copyright (C) Andrew Bartlett 2011
       6             :    Copyright (C) Andreas Schneider 2011
       7             : 
       8             :    This program is free software; you can redistribute it and/or modify
       9             :    it under the terms of the GNU General Public License as published by
      10             :    the Free Software Foundation; either version 3 of the License, or
      11             :    (at your option) any later version.
      12             : 
      13             :    This program is distributed in the hope that it will be useful,
      14             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :    GNU General Public License for more details.
      17             : 
      18             :    You should have received a copy of the GNU General Public License
      19             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      20             : */
      21             : 
      22             : #include "includes.h"
      23             : #include "librpc/rpc/dcesrv_core.h"
      24             : #include "rpc_server/rpc_pipes.h"
      25             : #include "rpc_server/rpc_server.h"
      26             : #include "rpc_server/rpc_config.h"
      27             : #include "rpc_dce.h"
      28             : #include "librpc/gen_ndr/netlogon.h"
      29             : #include "librpc/gen_ndr/auth.h"
      30             : #include "lib/tsocket/tsocket.h"
      31             : #include "libcli/named_pipe_auth/npa_tstream.h"
      32             : #include "../auth/auth_sam_reply.h"
      33             : #include "auth.h"
      34             : #include "rpc_server/rpc_ncacn_np.h"
      35             : #include "rpc_server/srv_pipe_hnd.h"
      36             : #include "lib/util/idtree_random.h"
      37             : 
      38             : #undef DBGC_CLASS
      39             : #define DBGC_CLASS DBGC_RPC_SRV
      40             : 
      41             : /* Start listening on the appropriate unix socket and setup all is needed to
      42             :  * dispatch requests to the pipes rpc implementation */
      43             : 
      44             : struct dcerpc_ncacn_listen_state {
      45             :         int fd;
      46             : 
      47             :         struct tevent_context *ev_ctx;
      48             :         struct messaging_context *msg_ctx;
      49             :         struct dcesrv_context *dce_ctx;
      50             :         struct dcesrv_endpoint *endpoint;
      51             :         dcerpc_ncacn_termination_fn termination_fn;
      52             :         void *termination_data;
      53             : };
      54             : 
      55             : static void ncacn_terminate_connection(struct dcerpc_ncacn_conn *conn,
      56             :                                        const char *reason);
      57             : 
      58         779 : NTSTATUS dcesrv_auth_gensec_prepare(
      59             :         TALLOC_CTX *mem_ctx,
      60             :         struct dcesrv_call_state *call,
      61             :         struct gensec_security **out,
      62             :         void *private_data)
      63             : {
      64         779 :         struct gensec_security *gensec = NULL;
      65           0 :         NTSTATUS status;
      66             : 
      67         779 :         if (out == NULL) {
      68           0 :                 return NT_STATUS_INVALID_PARAMETER;
      69             :         }
      70             : 
      71         779 :         status = auth_generic_prepare(mem_ctx,
      72         779 :                                       call->conn->remote_address,
      73         779 :                                       call->conn->local_address,
      74             :                                       "DCE/RPC",
      75             :                                       &gensec);
      76         779 :         if (!NT_STATUS_IS_OK(status)) {
      77           0 :                 DBG_ERR("Failed to prepare gensec: %s\n", nt_errstr(status));
      78           0 :                 return status;
      79             :         }
      80             : 
      81         779 :         *out = gensec;
      82             : 
      83         779 :         return NT_STATUS_OK;
      84             : }
      85             : 
      86       34045 : void dcesrv_log_successful_authz(
      87             :         struct dcesrv_call_state *call,
      88             :         void *private_data)
      89             : {
      90       34045 :         TALLOC_CTX *frame = talloc_stackframe();
      91       34045 :         struct auth4_context *auth4_context = NULL;
      92       34045 :         struct dcesrv_auth *auth = call->auth_state;
      93       34045 :         enum dcerpc_transport_t transport = dcerpc_binding_get_transport(
      94       34045 :                         call->conn->endpoint->ep_description);
      95       34045 :         const char *auth_type = derpc_transport_string_by_transport(transport);
      96       34045 :         const char *transport_protection = AUTHZ_TRANSPORT_PROTECTION_NONE;
      97           0 :         NTSTATUS status;
      98             : 
      99       34045 :         if (frame == NULL) {
     100           0 :                 DBG_ERR("No memory\n");
     101           0 :                 return;
     102             :         }
     103             : 
     104       34045 :         if (transport == NCACN_NP) {
     105       33651 :                 transport_protection = AUTHZ_TRANSPORT_PROTECTION_SMB;
     106             :         }
     107             : 
     108       34045 :         become_root();
     109       34045 :         status = make_auth4_context(frame, &auth4_context);
     110       34045 :         unbecome_root();
     111       34045 :         if (!NT_STATUS_IS_OK(status)) {
     112           0 :                 DBG_ERR("Unable to make auth context for authz log.\n");
     113           0 :                 TALLOC_FREE(frame);
     114           0 :                 return;
     115             :         }
     116             : 
     117             :         /*
     118             :          * Log the authorization to this RPC interface.  This
     119             :          * covered ncacn_np pass-through auth, and anonymous
     120             :          * DCE/RPC (eg epmapper, netlogon etc)
     121             :          */
     122       34045 :         log_successful_authz_event(auth4_context->msg_ctx,
     123       34045 :                                    auth4_context->lp_ctx,
     124       34045 :                                    call->conn->remote_address,
     125       34045 :                                    call->conn->local_address,
     126             :                                    "DCE/RPC",
     127             :                                    auth_type,
     128             :                                    transport_protection,
     129             :                                    auth->session_info,
     130             :                                    NULL /* client_audit_info */,
     131             :                                    NULL /* server_audit_info */);
     132             : 
     133       34045 :         auth->auth_audited = true;
     134             : 
     135       34045 :         TALLOC_FREE(frame);
     136             : }
     137             : 
     138           0 : static int dcesrv_assoc_group_destructor(struct dcesrv_assoc_group *assoc_group)
     139             : {
     140           0 :         int ret;
     141           0 :         ret = idr_remove(assoc_group->dce_ctx->assoc_groups_idr,
     142           0 :                          assoc_group->id);
     143           0 :         if (ret != 0) {
     144           0 :                 DBG_ERR("Failed to remove assoc_group 0x%08x\n",
     145             :                         assoc_group->id);
     146             :         }
     147           0 :         return 0;
     148             : }
     149             : 
     150           0 : static NTSTATUS dcesrv_assoc_group_new(struct dcesrv_call_state *call)
     151             : {
     152           0 :         struct dcesrv_connection *conn = call->conn;
     153           0 :         struct dcesrv_context *dce_ctx = conn->dce_ctx;
     154           0 :         const struct dcesrv_endpoint *endpoint = conn->endpoint;
     155           0 :         enum dcerpc_transport_t transport =
     156           0 :                 dcerpc_binding_get_transport(endpoint->ep_description);
     157           0 :         struct dcesrv_assoc_group *assoc_group = NULL;
     158           0 :         int id;
     159             : 
     160           0 :         assoc_group = talloc_zero(conn, struct dcesrv_assoc_group);
     161           0 :         if (assoc_group == NULL) {
     162           0 :                 return NT_STATUS_NO_MEMORY;
     163             :         }
     164             : 
     165           0 :         id = idr_get_new_random(dce_ctx->assoc_groups_idr,
     166             :                                 assoc_group,
     167             :                                 1,
     168             :                                 UINT16_MAX);
     169           0 :         if (id == -1) {
     170           0 :                 TALLOC_FREE(assoc_group);
     171           0 :                 DBG_ERR("Out of association groups!\n");
     172           0 :                 return NT_STATUS_RPC_OUT_OF_RESOURCES;
     173             :         }
     174             : 
     175           0 :         assoc_group->transport = transport;
     176           0 :         assoc_group->id = id;
     177           0 :         assoc_group->dce_ctx = dce_ctx;
     178             : 
     179           0 :         call->conn->assoc_group = assoc_group;
     180             : 
     181           0 :         talloc_set_destructor(assoc_group, dcesrv_assoc_group_destructor);
     182             : 
     183           0 :         return NT_STATUS_OK;
     184             : }
     185             : 
     186           0 : static NTSTATUS dcesrv_assoc_group_reference(struct dcesrv_call_state *call,
     187             :                                              uint32_t assoc_group_id)
     188             : {
     189           0 :         struct dcesrv_connection *conn = call->conn;
     190           0 :         const struct dcesrv_endpoint *endpoint = conn->endpoint;
     191           0 :         enum dcerpc_transport_t transport =
     192           0 :                 dcerpc_binding_get_transport(endpoint->ep_description);
     193           0 :         struct dcesrv_assoc_group *assoc_group = NULL;
     194           0 :         void *id_ptr = NULL;
     195             : 
     196             :         /* find an association group given a assoc_group_id */
     197           0 :         id_ptr = idr_find(conn->dce_ctx->assoc_groups_idr, assoc_group_id);
     198           0 :         if (id_ptr == NULL) {
     199             :                 /*
     200             :                  * FIXME If the association group is not found it has
     201             :                  * been created in other process (preforking daemons).
     202             :                  * Until this is properly fixed we just create a new
     203             :                  * association group in this process
     204             :                  */
     205           0 :                 DBG_NOTICE("Failed to find assoc_group 0x%08x in this "
     206             :                            "server process, creating a new one\n",
     207             :                            assoc_group_id);
     208           0 :                 return dcesrv_assoc_group_new(call);
     209             :         }
     210           0 :         assoc_group = talloc_get_type_abort(id_ptr, struct dcesrv_assoc_group);
     211             : 
     212           0 :         if (assoc_group->transport != transport) {
     213           0 :                 const char *at =
     214           0 :                         derpc_transport_string_by_transport(
     215             :                                 assoc_group->transport);
     216           0 :                 const char *ct =
     217           0 :                         derpc_transport_string_by_transport(
     218             :                                 transport);
     219             : 
     220           0 :                 DBG_NOTICE("assoc_group 0x%08x (transport %s) "
     221             :                            "is not available on transport %s\n",
     222             :                            assoc_group_id, at, ct);
     223           0 :                 return NT_STATUS_UNSUCCESSFUL;
     224             :         }
     225             : 
     226           0 :         conn->assoc_group = talloc_reference(conn, assoc_group);
     227           0 :         return NT_STATUS_OK;
     228             : }
     229             : 
     230           0 : NTSTATUS dcesrv_assoc_group_find(
     231             :         struct dcesrv_call_state *call,
     232             :         void *private_data)
     233             : {
     234           0 :         uint32_t assoc_group_id = call->pkt.u.bind.assoc_group_id;
     235             : 
     236           0 :         if (assoc_group_id != 0) {
     237           0 :                 return dcesrv_assoc_group_reference(call, assoc_group_id);
     238             :         }
     239             : 
     240             :         /* If not requested by client create a new association group */
     241           0 :         return dcesrv_assoc_group_new(call);
     242             : }
     243             : 
     244       34750 : void dcesrv_transport_terminate_connection(struct dcesrv_connection *dce_conn,
     245             :                                            const char *reason)
     246             : {
     247       34750 :        struct dcerpc_ncacn_conn *ncacn_conn = talloc_get_type_abort(
     248             :                        dce_conn->transport.private_data,
     249             :                        struct dcerpc_ncacn_conn);
     250             : 
     251       34750 :        ncacn_terminate_connection(ncacn_conn, reason);
     252       34750 : }
     253             : 
     254       34750 : static void ncacn_terminate_connection(struct dcerpc_ncacn_conn *conn,
     255             :                                        const char *reason)
     256             : {
     257       34750 :        if (reason == NULL) {
     258           0 :                reason = "Unknown reason";
     259             :        }
     260             : 
     261       34750 :        DBG_NOTICE("Terminating connection - '%s'\n", reason);
     262             : 
     263       34750 :        talloc_free(conn);
     264       34750 : }
     265             : 
     266           0 : NTSTATUS dcesrv_endpoint_by_ncacn_np_name(struct dcesrv_context *dce_ctx,
     267             :                                           const char *pipe_name,
     268             :                                           struct dcesrv_endpoint **out)
     269             : {
     270           0 :         struct dcesrv_endpoint *e = NULL;
     271             : 
     272           0 :         for (e = dce_ctx->endpoint_list; e; e = e->next) {
     273           0 :                 enum dcerpc_transport_t transport =
     274           0 :                         dcerpc_binding_get_transport(e->ep_description);
     275           0 :                 const char *endpoint = NULL;
     276             : 
     277           0 :                 if (transport != NCACN_NP) {
     278           0 :                         continue;
     279             :                 }
     280             : 
     281           0 :                 endpoint = dcerpc_binding_get_string_option(e->ep_description,
     282             :                                                             "endpoint");
     283           0 :                 if (endpoint == NULL) {
     284           0 :                         continue;
     285             :                 }
     286             : 
     287           0 :                 if (strncmp(endpoint, "\\pipe\\", 6) == 0) {
     288           0 :                         endpoint += 6;
     289             :                 }
     290             : 
     291           0 :                 if (strequal(endpoint, pipe_name)) {
     292           0 :                         *out = e;
     293           0 :                         return NT_STATUS_OK;
     294             :                 }
     295             :         }
     296             : 
     297           0 :         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
     298             : }
     299             : 
     300      604898 : struct pipes_struct *dcesrv_get_pipes_struct(struct dcesrv_connection *conn)
     301             : {
     302      604898 :         struct dcerpc_ncacn_conn *ncacn_conn = talloc_get_type_abort(
     303             :                         conn->transport.private_data,
     304             :                         struct dcerpc_ncacn_conn);
     305             : 
     306      604898 :         return &ncacn_conn->p;
     307             : }
     308             : 
     309             : /* vim: set ts=8 sw=8 noet cindent syntax=c.doxygen: */

Generated by: LCOV version 1.14