LCOV - code coverage report
Current view: top level - source3/rpc_server - rpc_server.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 42 121 34.7 %
Date: 2024-06-13 04:01:37 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             : 
      37             : #undef DBGC_CLASS
      38             : #define DBGC_CLASS DBGC_RPC_SRV
      39             : 
      40             : /* Start listening on the appropriate unix socket and setup all is needed to
      41             :  * dispatch requests to the pipes rpc implementation */
      42             : 
      43             : struct dcerpc_ncacn_listen_state {
      44             :         int fd;
      45             : 
      46             :         struct tevent_context *ev_ctx;
      47             :         struct messaging_context *msg_ctx;
      48             :         struct dcesrv_context *dce_ctx;
      49             :         struct dcesrv_endpoint *endpoint;
      50             :         dcerpc_ncacn_termination_fn termination_fn;
      51             :         void *termination_data;
      52             : };
      53             : 
      54             : static void ncacn_terminate_connection(struct dcerpc_ncacn_conn *conn,
      55             :                                        const char *reason);
      56             : 
      57         252 : NTSTATUS dcesrv_auth_gensec_prepare(
      58             :         TALLOC_CTX *mem_ctx,
      59             :         struct dcesrv_call_state *call,
      60             :         struct gensec_security **out,
      61             :         void *private_data)
      62             : {
      63         252 :         struct gensec_security *gensec = NULL;
      64             :         NTSTATUS status;
      65             : 
      66         252 :         if (out == NULL) {
      67           0 :                 return NT_STATUS_INVALID_PARAMETER;
      68             :         }
      69             : 
      70         379 :         status = auth_generic_prepare(mem_ctx,
      71         252 :                                       call->conn->remote_address,
      72         252 :                                       call->conn->local_address,
      73             :                                       "DCE/RPC",
      74             :                                       &gensec);
      75         252 :         if (!NT_STATUS_IS_OK(status)) {
      76           0 :                 DBG_ERR("Failed to prepare gensec: %s\n", nt_errstr(status));
      77           0 :                 return status;
      78             :         }
      79             : 
      80         252 :         *out = gensec;
      81             : 
      82         252 :         return NT_STATUS_OK;
      83             : }
      84             : 
      85         499 : void dcesrv_log_successful_authz(
      86             :         struct dcesrv_call_state *call,
      87             :         void *private_data)
      88             : {
      89         499 :         TALLOC_CTX *frame = talloc_stackframe();
      90         499 :         struct auth4_context *auth4_context = NULL;
      91         499 :         struct dcesrv_auth *auth = call->auth_state;
      92         499 :         enum dcerpc_transport_t transport = dcerpc_binding_get_transport(
      93         499 :                         call->conn->endpoint->ep_description);
      94         499 :         const char *auth_type = derpc_transport_string_by_transport(transport);
      95         499 :         const char *transport_protection = AUTHZ_TRANSPORT_PROTECTION_NONE;
      96             :         NTSTATUS status;
      97             : 
      98         499 :         if (frame == NULL) {
      99           0 :                 DBG_ERR("No memory");
     100           0 :                 return;
     101             :         }
     102             : 
     103         499 :         if (transport == NCACN_NP) {
     104         263 :                 transport_protection = AUTHZ_TRANSPORT_PROTECTION_SMB;
     105             :         }
     106             : 
     107         499 :         become_root();
     108         499 :         status = make_auth4_context(frame, &auth4_context);
     109         499 :         unbecome_root();
     110         499 :         if (!NT_STATUS_IS_OK(status)) {
     111           0 :                 DBG_ERR("Unable to make auth context for authz log.\n");
     112           0 :                 TALLOC_FREE(frame);
     113           0 :                 return;
     114             :         }
     115             : 
     116             :         /*
     117             :          * Log the authorization to this RPC interface.  This
     118             :          * covered ncacn_np pass-through auth, and anonymous
     119             :          * DCE/RPC (eg epmapper, netlogon etc)
     120             :          */
     121        1345 :         log_successful_authz_event(auth4_context->msg_ctx,
     122         499 :                                    auth4_context->lp_ctx,
     123         499 :                                    call->conn->remote_address,
     124         499 :                                    call->conn->local_address,
     125             :                                    "DCE/RPC",
     126             :                                    auth_type,
     127             :                                    transport_protection,
     128             :                                    auth->session_info);
     129             : 
     130         499 :         auth->auth_audited = true;
     131             : 
     132         499 :         TALLOC_FREE(frame);
     133             : }
     134             : 
     135           0 : static int dcesrv_assoc_group_destructor(struct dcesrv_assoc_group *assoc_group)
     136             : {
     137             :         int ret;
     138           0 :         ret = idr_remove(assoc_group->dce_ctx->assoc_groups_idr,
     139           0 :                          assoc_group->id);
     140           0 :         if (ret != 0) {
     141           0 :                 DBG_ERR("Failed to remove assoc_group 0x%08x\n",
     142             :                         assoc_group->id);
     143             :         }
     144           0 :         return 0;
     145             : }
     146             : 
     147           0 : static NTSTATUS dcesrv_assoc_group_new(struct dcesrv_call_state *call)
     148             : {
     149           0 :         struct dcesrv_connection *conn = call->conn;
     150           0 :         struct dcesrv_context *dce_ctx = conn->dce_ctx;
     151           0 :         const struct dcesrv_endpoint *endpoint = conn->endpoint;
     152           0 :         enum dcerpc_transport_t transport =
     153           0 :                 dcerpc_binding_get_transport(endpoint->ep_description);
     154           0 :         struct dcesrv_assoc_group *assoc_group = NULL;
     155             :         int id;
     156             : 
     157           0 :         assoc_group = talloc_zero(conn, struct dcesrv_assoc_group);
     158           0 :         if (assoc_group == NULL) {
     159           0 :                 return NT_STATUS_NO_MEMORY;
     160             :         }
     161             : 
     162           0 :         id = idr_get_new_random(dce_ctx->assoc_groups_idr,
     163             :                                 assoc_group,
     164             :                                 UINT16_MAX);
     165           0 :         if (id == -1) {
     166           0 :                 TALLOC_FREE(assoc_group);
     167           0 :                 DBG_ERR("Out of association groups!\n");
     168           0 :                 return NT_STATUS_RPC_OUT_OF_RESOURCES;
     169             :         }
     170             : 
     171           0 :         assoc_group->transport = transport;
     172           0 :         assoc_group->id = id;
     173           0 :         assoc_group->dce_ctx = dce_ctx;
     174             : 
     175           0 :         call->conn->assoc_group = assoc_group;
     176             : 
     177           0 :         talloc_set_destructor(assoc_group, dcesrv_assoc_group_destructor);
     178             : 
     179           0 :         return NT_STATUS_OK;
     180             : }
     181             : 
     182           0 : static NTSTATUS dcesrv_assoc_group_reference(struct dcesrv_call_state *call,
     183             :                                              uint32_t assoc_group_id)
     184             : {
     185           0 :         struct dcesrv_connection *conn = call->conn;
     186           0 :         const struct dcesrv_endpoint *endpoint = conn->endpoint;
     187           0 :         enum dcerpc_transport_t transport =
     188           0 :                 dcerpc_binding_get_transport(endpoint->ep_description);
     189           0 :         struct dcesrv_assoc_group *assoc_group = NULL;
     190           0 :         void *id_ptr = NULL;
     191             : 
     192             :         /* find an association group given a assoc_group_id */
     193           0 :         id_ptr = idr_find(conn->dce_ctx->assoc_groups_idr, assoc_group_id);
     194           0 :         if (id_ptr == NULL) {
     195             :                 /*
     196             :                  * FIXME If the association group is not found it has
     197             :                  * been created in other process (preforking daemons).
     198             :                  * Until this is properly fixed we just create a new
     199             :                  * association group in this process
     200             :                  */
     201           0 :                 DBG_NOTICE("Failed to find assoc_group 0x%08x in this "
     202             :                            "server process, creating a new one\n",
     203             :                            assoc_group_id);
     204           0 :                 return dcesrv_assoc_group_new(call);
     205             :         }
     206           0 :         assoc_group = talloc_get_type_abort(id_ptr, struct dcesrv_assoc_group);
     207             : 
     208           0 :         if (assoc_group->transport != transport) {
     209           0 :                 const char *at =
     210           0 :                         derpc_transport_string_by_transport(
     211             :                                 assoc_group->transport);
     212           0 :                 const char *ct =
     213           0 :                         derpc_transport_string_by_transport(
     214             :                                 transport);
     215             : 
     216           0 :                 DBG_NOTICE("assoc_group 0x%08x (transport %s) "
     217             :                            "is not available on transport %s",
     218             :                            assoc_group_id, at, ct);
     219           0 :                 return NT_STATUS_UNSUCCESSFUL;
     220             :         }
     221             : 
     222           0 :         conn->assoc_group = talloc_reference(conn, assoc_group);
     223           0 :         return NT_STATUS_OK;
     224             : }
     225             : 
     226           0 : NTSTATUS dcesrv_assoc_group_find(
     227             :         struct dcesrv_call_state *call,
     228             :         void *private_data)
     229             : {
     230           0 :         uint32_t assoc_group_id = call->pkt.u.bind.assoc_group_id;
     231             : 
     232           0 :         if (assoc_group_id != 0) {
     233           0 :                 return dcesrv_assoc_group_reference(call, assoc_group_id);
     234             :         }
     235             : 
     236             :         /* If not requested by client create a new association group */
     237           0 :         return dcesrv_assoc_group_new(call);
     238             : }
     239             : 
     240         674 : void dcesrv_transport_terminate_connection(struct dcesrv_connection *dce_conn,
     241             :                                            const char *reason)
     242             : {
     243         674 :        struct dcerpc_ncacn_conn *ncacn_conn = talloc_get_type_abort(
     244             :                        dce_conn->transport.private_data,
     245             :                        struct dcerpc_ncacn_conn);
     246             : 
     247         674 :        ncacn_terminate_connection(ncacn_conn, reason);
     248         674 : }
     249             : 
     250         674 : static void ncacn_terminate_connection(struct dcerpc_ncacn_conn *conn,
     251             :                                        const char *reason)
     252             : {
     253         674 :        if (reason == NULL) {
     254           0 :                reason = "Unknown reason";
     255             :        }
     256             : 
     257         674 :        DBG_NOTICE("Terminating connection - '%s'\n", reason);
     258             : 
     259         674 :        talloc_free(conn);
     260         674 : }
     261             : 
     262           0 : NTSTATUS dcesrv_endpoint_by_ncacn_np_name(struct dcesrv_context *dce_ctx,
     263             :                                           const char *pipe_name,
     264             :                                           struct dcesrv_endpoint **out)
     265             : {
     266           0 :         struct dcesrv_endpoint *e = NULL;
     267             : 
     268           0 :         for (e = dce_ctx->endpoint_list; e; e = e->next) {
     269           0 :                 enum dcerpc_transport_t transport =
     270           0 :                         dcerpc_binding_get_transport(e->ep_description);
     271           0 :                 const char *endpoint = NULL;
     272             : 
     273           0 :                 if (transport != NCACN_NP) {
     274           0 :                         continue;
     275             :                 }
     276             : 
     277           0 :                 endpoint = dcerpc_binding_get_string_option(e->ep_description,
     278             :                                                             "endpoint");
     279           0 :                 if (endpoint == NULL) {
     280           0 :                         continue;
     281             :                 }
     282             : 
     283           0 :                 if (strncmp(endpoint, "\\pipe\\", 6) == 0) {
     284           0 :                         endpoint += 6;
     285             :                 }
     286             : 
     287           0 :                 if (strequal(endpoint, pipe_name)) {
     288           0 :                         *out = e;
     289           0 :                         return NT_STATUS_OK;
     290             :                 }
     291             :         }
     292             : 
     293           0 :         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
     294             : }
     295             : 
     296        9543 : struct pipes_struct *dcesrv_get_pipes_struct(struct dcesrv_connection *conn)
     297             : {
     298        9543 :         struct dcerpc_ncacn_conn *ncacn_conn = talloc_get_type_abort(
     299             :                         conn->transport.private_data,
     300             :                         struct dcerpc_ncacn_conn);
     301             : 
     302        9543 :         return &ncacn_conn->p;
     303             : }
     304             : 
     305             : /* vim: set ts=8 sw=8 noet cindent syntax=c.doxygen: */

Generated by: LCOV version 1.13