LCOV - code coverage report
Current view: top level - librpc/ndr - ndr_sec_helper.c (source / functions) Hit Total Coverage
Test: coverage report for master 70ed9daf Lines: 144 160 90.0 %
Date: 2024-01-11 09:59:51 Functions: 20 20 100.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    fast routines for getting the wire size of security objects
       5             : 
       6             :    Copyright (C) Andrew Tridgell 2003
       7             :    Copyright (C) Stefan Metzmacher 2006-2008
       8             : 
       9             :    This program is free software; you can redistribute it and/or modify
      10             :    it under the terms of the GNU General Public License as published by
      11             :    the Free Software Foundation; either version 3 of the License, or
      12             :    (at your option) any later version.
      13             : 
      14             :    This program is distributed in the hope that it will be useful,
      15             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17             :    GNU General Public License for more details.
      18             : 
      19             :    You should have received a copy of the GNU General Public License
      20             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      21             : */
      22             : 
      23             : 
      24             : #include "includes.h"
      25             : #include "librpc/gen_ndr/ndr_security.h"
      26             : #include "../libcli/security/security.h"
      27             : 
      28             : 
      29             : /*
      30             :  * Find the wire size of a security_ace that has no trailing coda.
      31             :  * This is used in ndr_pull_security_ace() generated from security.idl
      32             :  * to work out where the coda starts (and in ndr_size_security_ace()
      33             :  * just below).
      34             :  */
      35   592366639 : static size_t ndr_size_security_ace_core(const struct security_ace *ace, libndr_flags flags)
      36             : {
      37    22213039 :         size_t ret;
      38             : 
      39   592366639 :         if (!ace) return 0;
      40             : 
      41   592366639 :         ret = 8 + ndr_size_dom_sid(&ace->trustee, flags);
      42   592366639 :         if (sec_ace_object(ace->type)) {
      43   371867514 :                 ret += 4; /* uint32 bitmap ace->object.object.flags */
      44   371867514 :                 if (ace->object.object.flags & SEC_ACE_OBJECT_TYPE_PRESENT) {
      45   341739273 :                         ret += 16; /* GUID ace->object.object.type.type */
      46             :                 }
      47   371867514 :                 if (ace->object.object.flags & SEC_ACE_INHERITED_OBJECT_TYPE_PRESENT) {
      48   213203079 :                         ret += 16; /* GUID ace->object.object.inherited_type.inherited_type */
      49             :                 }
      50             :         }
      51             : 
      52   570153600 :         return ret;
      53             : }
      54             : 
      55             : /*
      56             :   return the wire size of a security_ace
      57             : */
      58   158661195 : size_t ndr_size_security_ace(const struct security_ace *ace, libndr_flags flags)
      59             : {
      60   158661195 :         size_t base = ndr_size_security_ace_core(ace, flags);
      61   158661195 :         size_t ret = base;
      62   158661195 :         if (sec_ace_callback(ace->type)) {
      63        4292 :                 ret += ace->coda.conditions.length;
      64   158656903 :         } else if (ace->type == SEC_ACE_TYPE_SYSTEM_RESOURCE_ATTRIBUTE) {
      65         308 :                 ret += ndr_size_security_ace_coda(&ace->coda, ace->type, flags);
      66             :         } else {
      67   158656595 :                 ret += ace->coda.ignored.length;
      68             :         }
      69             :         /* round up to a multiple of 4  (MS-DTYP 2.4.4.1) */
      70   158661195 :         ret = (ret + 3ULL) & ~3ULL;
      71   158661195 :         if (unlikely(ret < base)) {
      72             :                 /* overflow, and there's not much we can do anyway */
      73           0 :                 return 0;
      74             :         }
      75   152473480 :         return ret;
      76             : }
      77             : 
      78             : /*
      79             :  * An ACE coda can't be bigger than the space allowed for by
      80             :  * ace->size, so we need to check this from the context of the ACE.
      81             :  *
      82             :  * Usually the coda also can't be any smaller than the remaining
      83             :  * space, because it is defined as a blob consuming everything it can.
      84             :  *
      85             :  * This is only used to find the size for the coda subcontext in
      86             :  * security.idl.
      87             :  */
      88   433705444 : size_t ndr_subcontext_size_of_ace_coda(const struct security_ace *ace,
      89             :                                        size_t ace_size,
      90             :                                        libndr_flags flags)
      91             : {
      92    16025324 :         size_t core_size;
      93   433705444 :         if (ace_size == 0) {
      94           0 :                 return 0;
      95             :         }
      96   433705444 :         core_size = ndr_size_security_ace_core(ace, flags);
      97   433705444 :         if (ace_size < core_size) {
      98           0 :                 return 0;
      99             :         }
     100   433705444 :         return ace_size - core_size;
     101             : }
     102             : 
     103             : /*
     104             :   return the wire size of a security_acl
     105             : */
     106     8261743 : size_t ndr_size_security_acl(const struct security_acl *theacl, libndr_flags flags)
     107             : {
     108      315757 :         size_t ret;
     109      315757 :         int i;
     110     8261743 :         if (!theacl) return 0;
     111     6436846 :         ret = 8;
     112    50630742 :         for (i=0;i<theacl->num_aces;i++) {
     113    43883010 :                 ret += ndr_size_security_ace(&theacl->aces[i], flags);
     114             :         }
     115     6436846 :         return ret;
     116             : }
     117             : 
     118             : /*
     119             :   return the wire size of a security descriptor
     120             : */
     121     1514289 : size_t ndr_size_security_descriptor(const struct security_descriptor *sd, libndr_flags flags)
     122             : {
     123        4851 :         size_t ret;
     124     1514289 :         if (!sd) return 0;
     125             : 
     126     1513531 :         ret = 20;
     127     1513531 :         ret += ndr_size_dom_sid(sd->owner_sid, flags);
     128     1513531 :         ret += ndr_size_dom_sid(sd->group_sid, flags);
     129     1513531 :         ret += ndr_size_security_acl(sd->dacl, flags);
     130     1513531 :         ret += ndr_size_security_acl(sd->sacl, flags);
     131     1513531 :         return ret;
     132             : }
     133             : 
     134             : /*
     135             :   return the wire size of a dom_sid
     136             : */
     137   615705579 : size_t ndr_size_dom_sid(const struct dom_sid *sid, libndr_flags flags)
     138             : {
     139   615705579 :         if (!sid) return 0;
     140   615362358 :         return 8 + 4*sid->num_auths;
     141             : }
     142             : 
     143     3119878 : size_t ndr_size_dom_sid28(const struct dom_sid *sid, libndr_flags flags)
     144             : {
     145     3119878 :         if (all_zero((const uint8_t *)sid, sizeof(struct dom_sid))) {
     146     2786274 :                 return 0;
     147             :         }
     148      333598 :         return ndr_size_dom_sid(sid, flags);
     149             : }
     150             : 
     151         574 : size_t ndr_size_dom_sid0(const struct dom_sid *sid, libndr_flags flags)
     152             : {
     153         574 :         return ndr_size_dom_sid28(sid, flags);
     154             : }
     155             : 
     156             : /*
     157             :   print a dom_sid
     158             : */
     159       45594 : void ndr_print_dom_sid(struct ndr_print *ndr, const char *name, const struct dom_sid *sid)
     160             : {
     161        3961 :         struct dom_sid_buf buf;
     162       45594 :         ndr->print(ndr, "%-25s: %s", name, dom_sid_str_buf(sid, &buf));
     163       45594 : }
     164             : 
     165       23608 : void ndr_print_dom_sid2(struct ndr_print *ndr, const char *name, const struct dom_sid *sid)
     166             : {
     167       23608 :         ndr_print_dom_sid(ndr, name, sid);
     168       23608 : }
     169             : 
     170       13970 : void ndr_print_dom_sid28(struct ndr_print *ndr, const char *name, const struct dom_sid *sid)
     171             : {
     172       13970 :         ndr_print_dom_sid(ndr, name, sid);
     173       13970 : }
     174             : 
     175           2 : void ndr_print_dom_sid0(struct ndr_print *ndr, const char *name, const struct dom_sid *sid)
     176             : {
     177           2 :         ndr_print_dom_sid(ndr, name, sid);
     178           2 : }
     179             : 
     180             : 
     181             : /*
     182             :   parse a dom_sid2 - this is a dom_sid but with an extra copy of the num_auths field
     183             : */
     184      586123 : enum ndr_err_code ndr_pull_dom_sid2(struct ndr_pull *ndr, ndr_flags_type ndr_flags, struct dom_sid *sid)
     185             : {
     186       24143 :         uint32_t num_auths;
     187      586123 :         if (!(ndr_flags & NDR_SCALARS)) {
     188           0 :                 return NDR_ERR_SUCCESS;
     189             :         }
     190      586123 :         NDR_CHECK(ndr_pull_uint3264(ndr, NDR_SCALARS, &num_auths));
     191      586123 :         NDR_CHECK(ndr_pull_dom_sid(ndr, ndr_flags, sid));
     192      586123 :         if (sid->num_auths != num_auths) {
     193           0 :                 return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE,
     194             :                                       "Bad num_auths %"PRIu32"; should equal %"PRId8,
     195             :                                       num_auths, sid->num_auths);
     196             :         }
     197      561980 :         return NDR_ERR_SUCCESS;
     198             : }
     199             : 
     200             : /*
     201             :   parse a dom_sid2 - this is a dom_sid but with an extra copy of the num_auths field
     202             : */
     203      430639 : enum ndr_err_code ndr_push_dom_sid2(struct ndr_push *ndr, ndr_flags_type ndr_flags, const struct dom_sid *sid)
     204             : {
     205      430639 :         if (!(ndr_flags & NDR_SCALARS)) {
     206           0 :                 return NDR_ERR_SUCCESS;
     207             :         }
     208      430639 :         NDR_CHECK(ndr_push_uint3264(ndr, NDR_SCALARS, sid->num_auths));
     209      430639 :         return ndr_push_dom_sid(ndr, ndr_flags, sid);
     210             : }
     211             : 
     212             : /*
     213             :   parse a dom_sid28 - this is a dom_sid in a fixed 28 byte buffer, so we need to ensure there are only up to 5 sub_auth
     214             : */
     215     2738242 : enum ndr_err_code ndr_pull_dom_sid28(struct ndr_pull *ndr, ndr_flags_type ndr_flags, struct dom_sid *sid)
     216             : {
     217          24 :         enum ndr_err_code status;
     218          24 :         struct ndr_pull *subndr;
     219             : 
     220     2738242 :         if (!(ndr_flags & NDR_SCALARS)) {
     221     1369109 :                 return NDR_ERR_SUCCESS;
     222             :         }
     223             : 
     224     1369121 :         subndr = talloc_zero(ndr, struct ndr_pull);
     225     1369121 :         NDR_ERR_HAVE_NO_MEMORY(subndr);
     226     1369121 :         subndr->flags                = ndr->flags;
     227     1369121 :         subndr->current_mem_ctx      = ndr->current_mem_ctx;
     228             : 
     229     1369121 :         subndr->data         = ndr->data + ndr->offset;
     230     1369121 :         subndr->data_size    = 28;
     231     1369121 :         subndr->offset               = 0;
     232             : 
     233     1369121 :         status = ndr_pull_advance(ndr, 28);
     234     1369121 :         if (!NDR_ERR_CODE_IS_SUCCESS(status)) {
     235           0 :                 talloc_free(subndr);
     236           0 :                 return status;
     237             :         }
     238             : 
     239     1369121 :         status = ndr_pull_dom_sid(subndr, ndr_flags, sid);
     240     1369121 :         if (!NDR_ERR_CODE_IS_SUCCESS(status)) {
     241             :                 /* handle a w2k bug which send random data in the buffer */
     242           1 :                 ZERO_STRUCTP(sid);
     243     1369120 :         } else if (sid->num_auths == 0) {
     244     1236412 :                 ZERO_STRUCT(sid->sub_auths);
     245             :         }
     246             : 
     247     1369121 :         talloc_free(subndr);
     248     1369121 :         return NDR_ERR_SUCCESS;
     249             : }
     250             : 
     251             : /*
     252             :   push a dom_sid28 - this is a dom_sid in a 28 byte fixed buffer
     253             : */
     254     6238796 : enum ndr_err_code ndr_push_dom_sid28(struct ndr_push *ndr, ndr_flags_type ndr_flags, const struct dom_sid *sid)
     255             : {
     256          24 :         uint32_t old_offset;
     257          24 :         uint32_t padding;
     258             : 
     259     6238796 :         if (!(ndr_flags & NDR_SCALARS)) {
     260     3119386 :                 return NDR_ERR_SUCCESS;
     261             :         }
     262             : 
     263     3119398 :         if (sid->num_auths > 5) {
     264           0 :                 return ndr_push_error(ndr, NDR_ERR_RANGE,
     265             :                                       "dom_sid28 allows only up to 5 sub auths [%"PRId8"]",
     266             :                                       sid->num_auths);
     267             :         }
     268             : 
     269     3119398 :         old_offset = ndr->offset;
     270     3119398 :         NDR_CHECK(ndr_push_dom_sid(ndr, ndr_flags, sid));
     271             : 
     272     3119398 :         padding = 28 - (ndr->offset - old_offset);
     273             : 
     274     3119398 :         if (padding > 0) {
     275     2851452 :                 NDR_CHECK(ndr_push_zero(ndr, padding));
     276             :         }
     277             : 
     278     3119386 :         return NDR_ERR_SUCCESS;
     279             : }
     280             : 
     281             : /*
     282             :   parse a dom_sid0 - this is a dom_sid in a variable byte buffer, which is maybe empty
     283             : */
     284          23 : enum ndr_err_code ndr_pull_dom_sid0(struct ndr_pull *ndr, ndr_flags_type ndr_flags, struct dom_sid *sid)
     285             : {
     286          23 :         if (!(ndr_flags & NDR_SCALARS)) {
     287           0 :                 return NDR_ERR_SUCCESS;
     288             :         }
     289             : 
     290          23 :         if (ndr->data_size == ndr->offset) {
     291           0 :                 ZERO_STRUCTP(sid);
     292           0 :                 return NDR_ERR_SUCCESS;
     293             :         }
     294             : 
     295          23 :         return ndr_pull_dom_sid(ndr, ndr_flags, sid);
     296             : }
     297             : 
     298             : /*
     299             :   push a dom_sid0 - this is a dom_sid in a variable byte buffer, which is maybe empty
     300             : */
     301          16 : enum ndr_err_code ndr_push_dom_sid0(struct ndr_push *ndr, ndr_flags_type ndr_flags, const struct dom_sid *sid)
     302             : {
     303          16 :         if (!(ndr_flags & NDR_SCALARS)) {
     304           0 :                 return NDR_ERR_SUCCESS;
     305             :         }
     306             : 
     307          16 :         if (!sid) {
     308           0 :                 return NDR_ERR_SUCCESS;
     309             :         }
     310             : 
     311          16 :         if (all_zero((const uint8_t *)sid, sizeof(struct dom_sid))) {
     312           0 :                 return NDR_ERR_SUCCESS;
     313             :         }
     314             : 
     315          16 :         return ndr_push_dom_sid(ndr, ndr_flags, sid);
     316             : }
     317             : 
     318   112756988 : _PUBLIC_ enum ndr_err_code ndr_push_dom_sid(struct ndr_push *ndr, ndr_flags_type ndr_flags, const struct dom_sid *r)
     319             : {
     320     2495139 :         uint32_t cntr_sub_auths_0;
     321   112756988 :         if (ndr_flags & NDR_SCALARS) {
     322   112756988 :                 NDR_CHECK(ndr_push_align(ndr, 4));
     323   112756988 :                 NDR_CHECK(ndr_push_uint8(ndr, NDR_SCALARS, r->sid_rev_num));
     324   112756988 :                 NDR_CHECK(ndr_push_int8(ndr, NDR_SCALARS, r->num_auths));
     325   112756988 :                 NDR_CHECK(ndr_push_array_uint8(ndr, NDR_SCALARS, r->id_auth, 6));
     326   112756988 :                 if (r->num_auths < 0 || r->num_auths > ARRAY_SIZE(r->sub_auths)) {
     327           0 :                         return ndr_push_error(ndr, NDR_ERR_RANGE, "value (%"PRId8") out of range (0 - %zu)", r->num_auths, ARRAY_SIZE(r->sub_auths));
     328             :                 }
     329   418427000 :                 for (cntr_sub_auths_0 = 0; cntr_sub_auths_0 < r->num_auths; cntr_sub_auths_0++) {
     330   305670012 :                         NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->sub_auths[cntr_sub_auths_0]));
     331             :                 }
     332             :         }
     333   110261849 :         return NDR_ERR_SUCCESS;
     334             : }
     335             : 
     336   266117342 : _PUBLIC_ enum ndr_err_code ndr_pull_dom_sid(struct ndr_pull *ndr, ndr_flags_type ndr_flags, struct dom_sid *r)
     337             : {
     338     8084924 :         uint32_t cntr_sub_auths_0;
     339   266117342 :         if (ndr_flags & NDR_SCALARS) {
     340   266117342 :                 NDR_CHECK(ndr_pull_align(ndr, 4));
     341   266117342 :                 NDR_CHECK(ndr_pull_uint8(ndr, NDR_SCALARS, &r->sid_rev_num));
     342   266116957 :                 NDR_CHECK(ndr_pull_int8(ndr, NDR_SCALARS, &r->num_auths));
     343   266116907 :                 if (r->num_auths < 0 || r->num_auths > ARRAY_SIZE(r->sub_auths)) {
     344           8 :                         return ndr_pull_error(ndr, NDR_ERR_RANGE, "value (%"PRId8") out of range (0 - %zu)", r->num_auths, ARRAY_SIZE(r->sub_auths));
     345             :                 }
     346   266116899 :                 NDR_CHECK(ndr_pull_array_uint8(ndr, NDR_SCALARS, r->id_auth, 6));
     347   266116899 :                 ZERO_STRUCT(r->sub_auths);
     348   958438097 :                 for (cntr_sub_auths_0 = 0; cntr_sub_auths_0 < r->num_auths; cntr_sub_auths_0++) {
     349   684236279 :                         NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->sub_auths[cntr_sub_auths_0]));
     350             :                 }
     351             :         }
     352   258031980 :         return NDR_ERR_SUCCESS;
     353             : }

Generated by: LCOV version 1.14