LCOV - code coverage report
Current view: top level - librpc/rpc - dcesrv_handles.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 124 139 89.2 %
Date: 2024-06-13 04:01:37 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       22588 : static int dcesrv_handle_destructor(struct dcesrv_handle *h)
      32             : {
      33       22588 :         DLIST_REMOVE(h->assoc_group->handles, h);
      34       22588 :         return 0;
      35             : }
      36             : 
      37             : 
      38             : /*
      39             :   allocate a new rpc handle
      40             : */
      41             : _PUBLIC_
      42       20779 : struct dcesrv_handle *dcesrv_handle_create(struct dcesrv_call_state *call,
      43             :                                            uint8_t handle_type)
      44             : {
      45       20779 :         struct dcesrv_connection_context *context = call->context;
      46       16588 :         struct auth_session_info *session_info =
      47        4191 :                 dcesrv_call_session_info(call);
      48             :         struct dcesrv_handle *h;
      49             :         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       20779 :         SMB_ASSERT((context->iface->flags & DCESRV_INTERFACE_FLAGS_HANDLES_NOT_USED) == 0);
      56             : 
      57       20779 :         sid = &session_info->security_token->sids[PRIMARY_USER_SID_INDEX];
      58             : 
      59       20779 :         h = talloc_zero(context->conn->assoc_group, struct dcesrv_handle);
      60       20779 :         if (!h) {
      61           0 :                 return NULL;
      62             :         }
      63       20779 :         h->data = NULL;
      64       20779 :         sid_copy(&h->sid, sid);
      65       20779 :         h->min_auth_level = call->auth_state->auth_level;
      66       20779 :         h->assoc_group = context->conn->assoc_group;
      67       20779 :         h->iface = context->iface;
      68       20779 :         h->wire_handle.handle_type = handle_type;
      69       20779 :         h->wire_handle.uuid = GUID_random();
      70             : 
      71       20779 :         DLIST_ADD(context->conn->assoc_group->handles, h);
      72             : 
      73       20779 :         talloc_set_destructor(h, dcesrv_handle_destructor);
      74             : 
      75       20779 :         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       94248 : struct dcesrv_handle *dcesrv_handle_lookup(struct dcesrv_call_state *call,
      85             :                                            const struct policy_handle *p,
      86             :                                            uint8_t handle_type)
      87             : {
      88       94248 :         struct dcesrv_connection_context *context = call->context;
      89       72205 :         struct auth_session_info *session_info =
      90       22043 :                 dcesrv_call_session_info(call);
      91             :         struct dcesrv_handle *h;
      92             :         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       94248 :         SMB_ASSERT((context->iface->flags & DCESRV_INTERFACE_FLAGS_HANDLES_NOT_USED) == 0);
      99             : 
     100       94248 :         sid = &session_info->security_token->sids[PRIMARY_USER_SID_INDEX];
     101             : 
     102       94248 :         if (ndr_policy_handle_empty(p)) {
     103             :                 /* TODO: we should probably return a NULL handle here */
     104          12 :                 return dcesrv_handle_create(call, handle_type);
     105             :         }
     106             : 
     107      107083 :         if (handle_type != DCESRV_HANDLE_ANY &&
     108       25647 :             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      417993 :         for (h=context->conn->assoc_group->handles; h; h=h->next) {
     117      643104 :                 if (h->wire_handle.handle_type == p->handle_type &&
     118      225204 :                     GUID_equal(&p->uuid, &h->wire_handle.uuid)) {
     119       94143 :                         break;
     120             :                 }
     121             :         }
     122             : 
     123       94236 :         if (h == NULL) {
     124             :                 /* not found */
     125          93 :                 return NULL;
     126             :         }
     127             : 
     128       94143 :         if (!dom_sid_equal(&h->sid, sid)) {
     129             :                 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       94143 :         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       94143 :         if (h->iface != context->iface) {
     144           3 :                 DBG_ERR("Attempt to use invalid iface\n");
     145           3 :                 return NULL;
     146             :         }
     147             : 
     148       94140 :         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        7420 : static int dcesrv_iface_state_destructor(struct dcesrv_iface_state *istate)
     165             : {
     166        7420 :         DLIST_REMOVE(istate->assoc->iface_states, istate);
     167        7420 :         return 0;
     168             : }
     169             : 
     170       31103 : 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       31103 :         struct dcesrv_iface_state *cur = NULL;
     180             : 
     181       42748 :         for (cur = assoc->iface_states; cur != NULL; cur = cur->next) {
     182             :                 bool match;
     183             : 
     184       31862 :                 SMB_ASSERT(cur->assoc == assoc);
     185             : 
     186       31862 :                 if (cur->ptr == ptr) {
     187           0 :                         return cur->ptr;
     188             :                 }
     189             : 
     190       31862 :                 if (cur->iface != iface) {
     191           0 :                         continue;
     192             :                 }
     193             : 
     194       31862 :                 match = dom_sid_equal(&cur->owner, owner);
     195       31862 :                 if (!match) {
     196        9797 :                         continue;
     197             :                 }
     198             : 
     199       22065 :                 if (cur->conn != conn) {
     200        1074 :                         continue;
     201             :                 }
     202             : 
     203       20991 :                 if (cur->auth != auth) {
     204           0 :                         continue;
     205             :                 }
     206             : 
     207       20991 :                 if (cur->pres != pres) {
     208           0 :                         continue;
     209             :                 }
     210             : 
     211       20991 :                 if (cur->magic != magic) {
     212         774 :                         continue;
     213             :                 }
     214             : 
     215       20217 :                 return cur->ptr;
     216             :         }
     217             : 
     218       10886 :         return NULL;
     219             : }
     220             : 
     221        7404 : 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        7404 :         struct dcesrv_iface_state *istate = NULL;
     233        7404 :         void *optr = NULL;
     234             : 
     235        7404 :         optr = dcesrv_iface_state_find(assoc,
     236             :                                        iface,
     237             :                                        owner,
     238             :                                        conn,
     239             :                                        auth,
     240             :                                        pres,
     241             :                                        magic,
     242             :                                        ptr);
     243        7404 :         if (optr != NULL) {
     244           0 :                 return NT_STATUS_OBJECTID_EXISTS;
     245             :         }
     246             : 
     247        7404 :         istate = talloc_zero(ptr, struct dcesrv_iface_state);
     248        7404 :         if (istate == NULL) {
     249           0 :                 return NT_STATUS_NO_MEMORY;
     250             :         }
     251             : 
     252        7404 :         *istate = (struct dcesrv_iface_state) {
     253             :                 .assoc = assoc,
     254             :                 .iface = iface,
     255        7404 :                 .owner = *owner,
     256             :                 .conn  = conn,
     257             :                 .auth  = auth,
     258             :                 .pres  = pres,
     259             :                 .magic = magic,
     260             :                 .location = location,
     261             :         };
     262             : 
     263        7404 :         istate->ptr = talloc_steal(mem_ctx, ptr);
     264             : 
     265        7404 :         talloc_set_destructor(istate, dcesrv_iface_state_destructor);
     266             : 
     267        7404 :         DLIST_ADD_END(assoc->iface_states, istate);
     268             : 
     269        7404 :         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           1 :         struct auth_session_info *session_info =
     278           1 :                 dcesrv_call_session_info(call);
     279           2 :         const struct dom_sid *owner =
     280           2 :                 &session_info->security_token->sids[0];
     281             :         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           2 :         struct auth_session_info *session_info =
     303           2 :                 dcesrv_call_session_info(call);
     304           4 :         const struct dom_sid *owner =
     305           4 :                 &session_info->security_token->sids[0];
     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        7402 : NTSTATUS _dcesrv_iface_state_store_conn(struct dcesrv_call_state *call,
     324             :                                         uint64_t magic,
     325             :                                         void *ptr,
     326             :                                         const char *location)
     327             : {
     328        7088 :         struct auth_session_info *session_info =
     329         314 :                 dcesrv_call_session_info(call);
     330        7402 :         const struct dom_sid *owner =
     331        7402 :                 &session_info->security_token->sids[0];
     332             :         NTSTATUS status;
     333             : 
     334        7402 :         status = dcesrv_iface_state_store(call->conn->assoc_group,
     335        7402 :                                           call->context->iface,
     336             :                                           owner,
     337        7402 :                                           call->conn,
     338        7402 :                                           call->auth_state,
     339        7402 :                                           call->context,
     340             :                                           magic,
     341        7402 :                                           call->conn, /* mem_ctx */
     342             :                                           ptr,
     343             :                                           location);
     344        7402 :         if (!NT_STATUS_IS_OK(status)) {
     345           0 :                 return status;
     346             :         }
     347             : 
     348        7402 :         return NT_STATUS_OK;
     349             : }
     350             : 
     351       23695 : void *_dcesrv_iface_state_find_conn(struct dcesrv_call_state *call, uint64_t magic)
     352             : {
     353       21707 :         struct auth_session_info *session_info =
     354        1988 :                 dcesrv_call_session_info(call);
     355       23695 :         const struct dom_sid *owner =
     356       23695 :                 &session_info->security_token->sids[0];
     357       23695 :         void *ptr = NULL;
     358             : 
     359       23695 :         ptr = dcesrv_iface_state_find(call->conn->assoc_group,
     360       23695 :                                       call->context->iface,
     361             :                                       owner,
     362       23695 :                                       call->conn,
     363       23695 :                                       call->auth_state,
     364       23695 :                                       call->context,
     365             :                                       magic,
     366             :                                       NULL); /* ptr */
     367       23695 :         if (ptr == NULL) {
     368        3480 :                 return NULL;
     369             :         }
     370             : 
     371       20215 :         return ptr;
     372             : }

Generated by: LCOV version 1.13