LCOV - code coverage report
Current view: top level - librpc/rpc - dcesrv_handles.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 128 147 87.1 %
Date: 2024-04-21 15:09:00 Functions: 10 10 100.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    server side dcerpc handle code
       5             : 
       6             :    Copyright (C) Andrew Tridgell 2003
       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 "lib/util/dlinklist.h"
      24             : #include "rpc_server/dcerpc_server.h"
      25             : #include "libcli/security/security.h"
      26             : #include "librpc/gen_ndr/auth.h"
      27             : 
      28             : /*
      29             :   destroy a rpc handle
      30             : */
      31      124712 : static int dcesrv_handle_destructor(struct dcesrv_handle *h)
      32             : {
      33      124712 :         DLIST_REMOVE(h->assoc_group->handles, h);
      34      124712 :         return 0;
      35             : }
      36             : 
      37             : 
      38             : /*
      39             :   allocate a new rpc handle
      40             : */
      41             : _PUBLIC_
      42      122609 : struct dcesrv_handle *dcesrv_handle_create(struct dcesrv_call_state *call,
      43             :                                            uint8_t handle_type)
      44             : {
      45      122609 :         struct dcesrv_connection_context *context = call->context;
      46         591 :         struct auth_session_info *session_info =
      47      122609 :                 dcesrv_call_session_info(call);
      48         591 :         struct dcesrv_handle *h;
      49         591 :         struct dom_sid *sid;
      50             : 
      51             :         /*
      52             :          * For simplicity, ensure we abort here for an interface that
      53             :          * has no handles (programmer error)
      54             :          */
      55      122609 :         SMB_ASSERT((context->iface->flags & DCESRV_INTERFACE_FLAGS_HANDLES_NOT_USED) == 0);
      56             : 
      57      122609 :         sid = &session_info->security_token->sids[PRIMARY_USER_SID_INDEX];
      58             : 
      59      122609 :         h = talloc_zero(context->conn->assoc_group, struct dcesrv_handle);
      60      122609 :         if (!h) {
      61           0 :                 return NULL;
      62             :         }
      63      122609 :         h->data = NULL;
      64      122609 :         sid_copy(&h->sid, sid);
      65      122609 :         h->min_auth_level = call->auth_state->auth_level;
      66      122609 :         h->assoc_group = context->conn->assoc_group;
      67      122609 :         h->iface = context->iface;
      68      122609 :         h->wire_handle.handle_type = handle_type;
      69      122609 :         h->wire_handle.uuid = GUID_random();
      70             : 
      71      122609 :         DLIST_ADD(context->conn->assoc_group->handles, h);
      72             : 
      73      122609 :         talloc_set_destructor(h, dcesrv_handle_destructor);
      74             : 
      75      122609 :         return h;
      76             : }
      77             : 
      78             : /**
      79             :   find an internal handle given a wire handle. If the wire handle is NULL then
      80             :   allocate a new handle
      81             : */
      82             : 
      83             : _PUBLIC_
      84      762129 : struct dcesrv_handle *dcesrv_handle_lookup(struct dcesrv_call_state *call,
      85             :                                            const struct policy_handle *p,
      86             :                                            uint8_t handle_type)
      87             : {
      88      762129 :         struct dcesrv_connection_context *context = call->context;
      89         977 :         struct auth_session_info *session_info =
      90      762129 :                 dcesrv_call_session_info(call);
      91         977 :         struct dcesrv_handle *h;
      92         977 :         struct dom_sid *sid;
      93             : 
      94             :         /*
      95             :          * For simplicity, ensure we abort here for an interface that
      96             :          * has no handles (programmer error)
      97             :          */
      98      762129 :         SMB_ASSERT((context->iface->flags & DCESRV_INTERFACE_FLAGS_HANDLES_NOT_USED) == 0);
      99             : 
     100      762129 :         sid = &session_info->security_token->sids[PRIMARY_USER_SID_INDEX];
     101             : 
     102      762129 :         if (ndr_policy_handle_empty(p)) {
     103             :                 /* TODO: we should probably return a NULL handle here */
     104          14 :                 return dcesrv_handle_create(call, handle_type);
     105             :         }
     106             : 
     107      762115 :         if (handle_type != DCESRV_HANDLE_ANY &&
     108       29973 :             p->handle_type != handle_type) {
     109           0 :                 DBG_WARNING("client gave us the wrong handle type "
     110             :                             "(%"PRIu32" should be %"PRIu8")\n",
     111             :                             p->handle_type,
     112             :                             handle_type);
     113           0 :                 return NULL;
     114             :         }
     115             : 
     116     1279912 :         for (h=context->conn->assoc_group->handles; h; h=h->next) {
     117     2266612 :                 if (h->wire_handle.handle_type == p->handle_type &&
     118      986916 :                     GUID_equal(&p->uuid, &h->wire_handle.uuid)) {
     119      760951 :                         break;
     120             :                 }
     121             :         }
     122             : 
     123      762115 :         if (h == NULL) {
     124             :                 /* not found */
     125         187 :                 return NULL;
     126             :         }
     127             : 
     128      761899 :         if (!dom_sid_equal(&h->sid, sid)) {
     129           0 :                 struct dom_sid_buf buf1, buf2;
     130           0 :                 DBG_ERR("Attempt to use invalid sid %s - %s\n",
     131             :                         dom_sid_str_buf(&h->sid, &buf1),
     132             :                         dom_sid_str_buf(sid, &buf2));
     133           0 :                 return NULL;
     134             :         }
     135             : 
     136      761899 :         if (call->auth_state->auth_level < h->min_auth_level) {
     137           0 :                 DBG_ERR("Attempt to use invalid auth_level %u < %u\n",
     138             :                         call->auth_state->auth_level,
     139             :                         h->min_auth_level);
     140           0 :                 return NULL;
     141             :         }
     142             : 
     143      761899 :         if (h->iface != context->iface) {
     144          12 :                 DBG_ERR("Attempt to use invalid iface\n");
     145          12 :                 return NULL;
     146             :         }
     147             : 
     148      760942 :         return h;
     149             : }
     150             : 
     151             : struct dcesrv_iface_state {
     152             :         struct dcesrv_iface_state *prev, *next;
     153             :         struct dcesrv_assoc_group *assoc;
     154             :         const struct dcesrv_interface *iface;
     155             :         struct dom_sid owner;
     156             :         const struct dcesrv_connection *conn;
     157             :         const struct dcesrv_auth *auth;
     158             :         const struct dcesrv_connection_context *pres;
     159             :         uint64_t magic;
     160             :         void *ptr;
     161             :         const char *location;
     162             : };
     163             : 
     164       15092 : static int dcesrv_iface_state_destructor(struct dcesrv_iface_state *istate)
     165             : {
     166       15092 :         DLIST_REMOVE(istate->assoc->iface_states, istate);
     167       15092 :         return 0;
     168             : }
     169             : 
     170       55101 : static void *dcesrv_iface_state_find(struct dcesrv_assoc_group *assoc,
     171             :                         const struct dcesrv_interface *iface,
     172             :                         const struct dom_sid *owner,
     173             :                         const struct dcesrv_connection *conn,
     174             :                         const struct dcesrv_auth *auth,
     175             :                         const struct dcesrv_connection_context *pres,
     176             :                         uint64_t magic,
     177             :                         const void *ptr)
     178             : {
     179       55101 :         struct dcesrv_iface_state *cur = NULL;
     180             : 
     181       74073 :         for (cur = assoc->iface_states; cur != NULL; cur = cur->next) {
     182        4165 :                 bool match;
     183             : 
     184       53251 :                 SMB_ASSERT(cur->assoc == assoc);
     185             : 
     186       53251 :                 if (cur->ptr == ptr) {
     187           0 :                         return cur->ptr;
     188             :                 }
     189             : 
     190       53251 :                 if (cur->iface != iface) {
     191           0 :                         continue;
     192             :                 }
     193             : 
     194       53251 :                 match = dom_sid_equal(&cur->owner, owner);
     195       53251 :                 if (!match) {
     196       16024 :                         continue;
     197             :                 }
     198             : 
     199       37227 :                 if (cur->conn != conn) {
     200        1385 :                         continue;
     201             :                 }
     202             : 
     203       35842 :                 if (cur->auth != auth) {
     204           0 :                         continue;
     205             :                 }
     206             : 
     207       35842 :                 if (cur->pres != pres) {
     208           0 :                         continue;
     209             :                 }
     210             : 
     211       35842 :                 if (cur->magic != magic) {
     212        1563 :                         continue;
     213             :                 }
     214             : 
     215       34279 :                 return cur->ptr;
     216             :         }
     217             : 
     218       19447 :         return NULL;
     219             : }
     220             : 
     221       15074 : static NTSTATUS dcesrv_iface_state_store(struct dcesrv_assoc_group *assoc,
     222             :                                 const struct dcesrv_interface *iface,
     223             :                                 const struct dom_sid *owner,
     224             :                                 const struct dcesrv_connection *conn,
     225             :                                 const struct dcesrv_auth *auth,
     226             :                                 const struct dcesrv_connection_context *pres,
     227             :                                 uint64_t magic,
     228             :                                 TALLOC_CTX *mem_ctx,
     229             :                                 void *ptr,
     230             :                                 const char *location)
     231             : {
     232       15074 :         struct dcesrv_iface_state *istate = NULL;
     233       15074 :         void *optr = NULL;
     234             : 
     235       15074 :         optr = dcesrv_iface_state_find(assoc,
     236             :                                        iface,
     237             :                                        owner,
     238             :                                        conn,
     239             :                                        auth,
     240             :                                        pres,
     241             :                                        magic,
     242             :                                        ptr);
     243       15074 :         if (optr != NULL) {
     244           0 :                 return NT_STATUS_OBJECTID_EXISTS;
     245             :         }
     246             : 
     247       15074 :         istate = talloc_zero(ptr, struct dcesrv_iface_state);
     248       15074 :         if (istate == NULL) {
     249           0 :                 return NT_STATUS_NO_MEMORY;
     250             :         }
     251             : 
     252       15074 :         *istate = (struct dcesrv_iface_state) {
     253             :                 .assoc = assoc,
     254             :                 .iface = iface,
     255       15074 :                 .owner = *owner,
     256             :                 .conn  = conn,
     257             :                 .auth  = auth,
     258             :                 .pres  = pres,
     259             :                 .magic = magic,
     260             :                 .location = location,
     261             :         };
     262             : 
     263       15074 :         istate->ptr = talloc_steal(mem_ctx, ptr);
     264             : 
     265       15074 :         talloc_set_destructor(istate, dcesrv_iface_state_destructor);
     266             : 
     267       15074 :         DLIST_ADD_END(assoc->iface_states, istate);
     268             : 
     269       15074 :         return NT_STATUS_OK;
     270             : }
     271             : 
     272           2 : NTSTATUS _dcesrv_iface_state_store_assoc(struct dcesrv_call_state *call,
     273             :                                 uint64_t magic,
     274             :                                 void *ptr,
     275             :                                 const char *location)
     276             : {
     277           0 :         struct auth_session_info *session_info =
     278           2 :                 dcesrv_call_session_info(call);
     279           2 :         const struct dom_sid *owner =
     280           2 :                 &session_info->security_token->sids[PRIMARY_USER_SID_INDEX];
     281           0 :         NTSTATUS status;
     282             : 
     283           2 :         status = dcesrv_iface_state_store(call->conn->assoc_group,
     284           2 :                                           call->context->iface,
     285             :                                           owner,
     286             :                                           NULL, /* conn */
     287             :                                           NULL, /* auth */
     288             :                                           NULL, /* pres */
     289             :                                           magic,
     290           2 :                                           call->conn->assoc_group, /* mem_ctx */
     291             :                                           ptr,
     292             :                                           location);
     293           2 :         if (!NT_STATUS_IS_OK(status)) {
     294           0 :                 return status;
     295             :         }
     296             : 
     297           2 :         return NT_STATUS_OK;
     298             : }
     299             : 
     300           4 : void *_dcesrv_iface_state_find_assoc(struct dcesrv_call_state *call, uint64_t magic)
     301             : {
     302           0 :         struct auth_session_info *session_info =
     303           4 :                 dcesrv_call_session_info(call);
     304           4 :         const struct dom_sid *owner =
     305           4 :                 &session_info->security_token->sids[PRIMARY_USER_SID_INDEX];
     306           4 :         void *ptr = NULL;
     307             : 
     308           4 :         ptr = dcesrv_iface_state_find(call->conn->assoc_group,
     309           4 :                                       call->context->iface,
     310             :                                       owner,
     311             :                                       NULL, /* conn */
     312             :                                       NULL, /* auth */
     313             :                                       NULL, /* pres */
     314             :                                       magic,
     315             :                                       NULL); /* ptr */
     316           4 :         if (ptr == NULL) {
     317           2 :                 return NULL;
     318             :         }
     319             : 
     320           2 :         return ptr;
     321             : }
     322             : 
     323       15072 : NTSTATUS _dcesrv_iface_state_store_conn(struct dcesrv_call_state *call,
     324             :                                         uint64_t magic,
     325             :                                         void *ptr,
     326             :                                         const char *location)
     327             : {
     328         974 :         struct auth_session_info *session_info =
     329       15072 :                 dcesrv_call_session_info(call);
     330       15072 :         const struct dom_sid *owner =
     331       15072 :                 &session_info->security_token->sids[PRIMARY_USER_SID_INDEX];
     332         974 :         NTSTATUS status;
     333             : 
     334       15072 :         status = dcesrv_iface_state_store(call->conn->assoc_group,
     335       14098 :                                           call->context->iface,
     336             :                                           owner,
     337       14098 :                                           call->conn,
     338       15072 :                                           call->auth_state,
     339       15072 :                                           call->context,
     340             :                                           magic,
     341       15072 :                                           call->conn, /* mem_ctx */
     342             :                                           ptr,
     343             :                                           location);
     344       15072 :         if (!NT_STATUS_IS_OK(status)) {
     345           0 :                 return status;
     346             :         }
     347             : 
     348       15072 :         return NT_STATUS_OK;
     349             : }
     350             : 
     351       40023 : void *_dcesrv_iface_state_find_conn(struct dcesrv_call_state *call, uint64_t magic)
     352             : {
     353        2566 :         struct auth_session_info *session_info =
     354       40023 :                 dcesrv_call_session_info(call);
     355       40023 :         const struct dom_sid *owner =
     356       40023 :                 &session_info->security_token->sids[PRIMARY_USER_SID_INDEX];
     357       40023 :         void *ptr = NULL;
     358             : 
     359       42589 :         ptr = dcesrv_iface_state_find(call->conn->assoc_group,
     360       37457 :                                       call->context->iface,
     361             :                                       owner,
     362       40023 :                                       call->conn,
     363       40023 :                                       call->auth_state,
     364       40023 :                                       call->context,
     365             :                                       magic,
     366             :                                       NULL); /* ptr */
     367       40023 :         if (ptr == NULL) {
     368        5746 :                 return NULL;
     369             :         }
     370             : 
     371       32112 :         return ptr;
     372             : }

Generated by: LCOV version 1.14