LCOV - code coverage report
Current view: top level - librpc/ndr - ndr_sec_helper.c (source / functions) Hit Total Coverage
Test: coverage report for support-claim-type-attributes 6b5c566e Lines: 144 160 90.0 %
Date: 2023-11-21 12:31:41 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   592985699 : static size_t ndr_size_security_ace_core(const struct security_ace *ace, libndr_flags flags)
      36             : {
      37    22212597 :         size_t ret;
      38             : 
      39   592985699 :         if (!ace) return 0;
      40             : 
      41   592985699 :         ret = 8 + ndr_size_dom_sid(&ace->trustee, flags);
      42   592985699 :         if (sec_ace_object(ace->type)) {
      43   373111208 :                 ret += 4; /* uint32 bitmap ace->object.object.flags */
      44   373111208 :                 if (ace->object.object.flags & SEC_ACE_OBJECT_TYPE_PRESENT) {
      45   342867845 :                         ret += 16; /* GUID ace->object.object.type.type */
      46             :                 }
      47   373111208 :                 if (ace->object.object.flags & SEC_ACE_INHERITED_OBJECT_TYPE_PRESENT) {
      48   214040743 :                         ret += 16; /* GUID ace->object.object.inherited_type.inherited_type */
      49             :                 }
      50             :         }
      51             : 
      52   570773102 :         return ret;
      53             : }
      54             : 
      55             : /*
      56             :   return the wire size of a security_ace
      57             : */
      58   159340329 : size_t ndr_size_security_ace(const struct security_ace *ace, libndr_flags flags)
      59             : {
      60   159340329 :         size_t base = ndr_size_security_ace_core(ace, flags);
      61   159340329 :         size_t ret = base;
      62   159340329 :         if (sec_ace_callback(ace->type)) {
      63        4160 :                 ret += ace->coda.conditions.length;
      64   159336169 :         } else if (ace->type == SEC_ACE_TYPE_SYSTEM_RESOURCE_ATTRIBUTE) {
      65         264 :                 ret += ndr_size_security_ace_coda(&ace->coda, ace->type, flags);
      66             :         } else {
      67   159335905 :                 ret += ace->coda.ignored.length;
      68             :         }
      69             :         /* round up to a multiple of 4  (MS-DTYP 2.4.4.1) */
      70   159340329 :         ret = (ret + 3ULL) & ~3ULL;
      71   159340329 :         if (unlikely(ret < base)) {
      72             :                 /* overflow, and there's not much we can do anyway */
      73           0 :                 return 0;
      74             :         }
      75   153152826 :         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   433645370 : size_t ndr_subcontext_size_of_ace_coda(const struct security_ace *ace,
      89             :                                        size_t ace_size,
      90             :                                        libndr_flags flags)
      91             : {
      92    16025094 :         size_t core_size;
      93   433645370 :         if (ace_size == 0) {
      94           0 :                 return 0;
      95             :         }
      96   433645370 :         core_size = ndr_size_security_ace_core(ace, flags);
      97   433645370 :         if (ace_size < core_size) {
      98           0 :                 return 0;
      99             :         }
     100   433645370 :         return ace_size - core_size;
     101             : }
     102             : 
     103             : /*
     104             :   return the wire size of a security_acl
     105             : */
     106     8012758 : size_t ndr_size_security_acl(const struct security_acl *theacl, libndr_flags flags)
     107             : {
     108      315659 :         size_t ret;
     109      315659 :         int i;
     110     8012758 :         if (!theacl) return 0;
     111     6323752 :         ret = 8;
     112    50377212 :         for (i=0;i<theacl->num_aces;i++) {
     113    43742634 :                 ret += ndr_size_security_ace(&theacl->aces[i], flags);
     114             :         }
     115     6323752 :         return ret;
     116             : }
     117             : 
     118             : /*
     119             :   return the wire size of a security descriptor
     120             : */
     121     1378463 : size_t ndr_size_security_descriptor(const struct security_descriptor *sd, libndr_flags flags)
     122             : {
     123        4813 :         size_t ret;
     124     1378463 :         if (!sd) return 0;
     125             : 
     126     1377705 :         ret = 20;
     127     1377705 :         ret += ndr_size_dom_sid(sd->owner_sid, flags);
     128     1377705 :         ret += ndr_size_dom_sid(sd->group_sid, flags);
     129     1377705 :         ret += ndr_size_security_acl(sd->dacl, flags);
     130     1377705 :         ret += ndr_size_security_acl(sd->sacl, flags);
     131     1377705 :         return ret;
     132             : }
     133             : 
     134             : /*
     135             :   return the wire size of a dom_sid
     136             : */
     137   615953601 : size_t ndr_size_dom_sid(const struct dom_sid *sid, libndr_flags flags)
     138             : {
     139   615953601 :         if (!sid) return 0;
     140   615609838 :         return 8 + 4*sid->num_auths;
     141             : }
     142             : 
     143     3138296 : size_t ndr_size_dom_sid28(const struct dom_sid *sid, libndr_flags flags)
     144             : {
     145     3138296 :         if (all_zero((const uint8_t *)sid, sizeof(struct dom_sid))) {
     146     2802676 :                 return 0;
     147             :         }
     148      335614 :         return ndr_size_dom_sid(sid, flags);
     149             : }
     150             : 
     151         572 : size_t ndr_size_dom_sid0(const struct dom_sid *sid, libndr_flags flags)
     152             : {
     153         572 :         return ndr_size_dom_sid28(sid, flags);
     154             : }
     155             : 
     156             : /*
     157             :   print a dom_sid
     158             : */
     159       45642 : void ndr_print_dom_sid(struct ndr_print *ndr, const char *name, const struct dom_sid *sid)
     160             : {
     161        4005 :         struct dom_sid_buf buf;
     162       45642 :         ndr->print(ndr, "%-25s: %s", name, dom_sid_str_buf(sid, &buf));
     163       45642 : }
     164             : 
     165       23612 : void ndr_print_dom_sid2(struct ndr_print *ndr, const char *name, const struct dom_sid *sid)
     166             : {
     167       23612 :         ndr_print_dom_sid(ndr, name, sid);
     168       23612 : }
     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      581891 : 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      581891 :         if (!(ndr_flags & NDR_SCALARS)) {
     188           0 :                 return NDR_ERR_SUCCESS;
     189             :         }
     190      581891 :         NDR_CHECK(ndr_pull_uint3264(ndr, NDR_SCALARS, &num_auths));
     191      581891 :         NDR_CHECK(ndr_pull_dom_sid(ndr, ndr_flags, sid));
     192      581891 :         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      557748 :         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      428983 : enum ndr_err_code ndr_push_dom_sid2(struct ndr_push *ndr, ndr_flags_type ndr_flags, const struct dom_sid *sid)
     204             : {
     205      428983 :         if (!(ndr_flags & NDR_SCALARS)) {
     206           0 :                 return NDR_ERR_SUCCESS;
     207             :         }
     208      428983 :         NDR_CHECK(ndr_push_uint3264(ndr, NDR_SCALARS, sid->num_auths));
     209      428983 :         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     2753222 : 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     2753222 :         if (!(ndr_flags & NDR_SCALARS)) {
     221     1376599 :                 return NDR_ERR_SUCCESS;
     222             :         }
     223             : 
     224     1376611 :         subndr = talloc_zero(ndr, struct ndr_pull);
     225     1376611 :         NDR_ERR_HAVE_NO_MEMORY(subndr);
     226     1376611 :         subndr->flags                = ndr->flags;
     227     1376611 :         subndr->current_mem_ctx      = ndr->current_mem_ctx;
     228             : 
     229     1376611 :         subndr->data         = ndr->data + ndr->offset;
     230     1376611 :         subndr->data_size    = 28;
     231     1376611 :         subndr->offset               = 0;
     232             : 
     233     1376611 :         status = ndr_pull_advance(ndr, 28);
     234     1376611 :         if (!NDR_ERR_CODE_IS_SUCCESS(status)) {
     235           0 :                 talloc_free(subndr);
     236           0 :                 return status;
     237             :         }
     238             : 
     239     1376611 :         status = ndr_pull_dom_sid(subndr, ndr_flags, sid);
     240     1376611 :         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     1376610 :         } else if (sid->num_auths == 0) {
     244     1243236 :                 ZERO_STRUCT(sid->sub_auths);
     245             :         }
     246             : 
     247     1376611 :         talloc_free(subndr);
     248     1376611 :         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     6275636 : 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     6275636 :         if (!(ndr_flags & NDR_SCALARS)) {
     260     3137806 :                 return NDR_ERR_SUCCESS;
     261             :         }
     262             : 
     263     3137818 :         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     3137818 :         old_offset = ndr->offset;
     270     3137818 :         NDR_CHECK(ndr_push_dom_sid(ndr, ndr_flags, sid));
     271             : 
     272     3137818 :         padding = 28 - (ndr->offset - old_offset);
     273             : 
     274     3137818 :         if (padding > 0) {
     275     2868900 :                 NDR_CHECK(ndr_push_zero(ndr, padding));
     276             :         }
     277             : 
     278     3137806 :         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   115238319 : _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     2494579 :         uint32_t cntr_sub_auths_0;
     321   115238319 :         if (ndr_flags & NDR_SCALARS) {
     322   115238319 :                 NDR_CHECK(ndr_push_align(ndr, 4));
     323   115238319 :                 NDR_CHECK(ndr_push_uint8(ndr, NDR_SCALARS, r->sid_rev_num));
     324   115238319 :                 NDR_CHECK(ndr_push_int8(ndr, NDR_SCALARS, r->num_auths));
     325   115238319 :                 NDR_CHECK(ndr_push_array_uint8(ndr, NDR_SCALARS, r->id_auth, 6));
     326   115238319 :                 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   424627020 :                 for (cntr_sub_auths_0 = 0; cntr_sub_auths_0 < r->num_auths; cntr_sub_auths_0++) {
     330   309388701 :                         NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->sub_auths[cntr_sub_auths_0]));
     331             :                 }
     332             :         }
     333   112743740 :         return NDR_ERR_SUCCESS;
     334             : }
     335             : 
     336   267706859 : _PUBLIC_ enum ndr_err_code ndr_pull_dom_sid(struct ndr_pull *ndr, ndr_flags_type ndr_flags, struct dom_sid *r)
     337             : {
     338     8084203 :         uint32_t cntr_sub_auths_0;
     339   267706859 :         if (ndr_flags & NDR_SCALARS) {
     340   267706859 :                 NDR_CHECK(ndr_pull_align(ndr, 4));
     341   267706859 :                 NDR_CHECK(ndr_pull_uint8(ndr, NDR_SCALARS, &r->sid_rev_num));
     342   267706474 :                 NDR_CHECK(ndr_pull_int8(ndr, NDR_SCALARS, &r->num_auths));
     343   267706424 :                 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   267706416 :                 NDR_CHECK(ndr_pull_array_uint8(ndr, NDR_SCALARS, r->id_auth, 6));
     347   267706416 :                 ZERO_STRUCT(r->sub_auths);
     348   960908687 :                 for (cntr_sub_auths_0 = 0; cntr_sub_auths_0 < r->num_auths; cntr_sub_auths_0++) {
     349   685118073 :                         NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->sub_auths[cntr_sub_auths_0]));
     350             :                 }
     351             :         }
     352   259622218 :         return NDR_ERR_SUCCESS;
     353             : }

Generated by: LCOV version 1.14