LCOV - code coverage report
Current view: top level - libcli/security - sddl.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 248 281 88.3 %
Date: 2021-09-23 10:06:22 Functions: 13 13 100.0 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    security descriptor description language functions
       5             : 
       6             :    Copyright (C) Andrew Tridgell                2005
       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 "libcli/security/security.h"
      24             : #include "librpc/gen_ndr/ndr_misc.h"
      25             : #include "system/locale.h"
      26             : 
      27             : struct flag_map {
      28             :         const char *name;
      29             :         uint32_t flag;
      30             : };
      31             : 
      32    58472019 : static bool sddl_map_flag(
      33             :         const struct flag_map *map,
      34             :         const char *str,
      35             :         size_t *plen,
      36             :         uint32_t *pflag)
      37             : {
      38   385849618 :         while (map->name != NULL) {
      39   310374066 :                 size_t len = strlen(map->name);
      40   310374066 :                 int cmp = strncmp(map->name, str, len);
      41             : 
      42   310374066 :                 if (cmp == 0) {
      43    31229687 :                         *plen = len;
      44    31229687 :                         *pflag = map->flag;
      45    31229687 :                         return true;
      46             :                 }
      47   279144379 :                 map += 1;
      48             :         }
      49    24983703 :         return false;
      50             : }
      51             : 
      52             : /*
      53             :   map a series of letter codes into a uint32_t
      54             : */
      55     8840395 : static bool sddl_map_flags(const struct flag_map *map, const char *str, 
      56             :                            uint32_t *pflags, size_t *plen)
      57             : {
      58     8840395 :         const char *str0 = str;
      59     8840395 :         if (plen != NULL) {
      60     1299219 :                 *plen = 0;
      61             :         }
      62     8840395 :         *pflags = 0;
      63    19988747 :         while (str[0] && isupper(str[0])) {
      64             :                 size_t len;
      65             :                 uint32_t flags;
      66             :                 bool found;
      67             : 
      68     3987355 :                 found = sddl_map_flag(map, str, &len, &flags);
      69     3987355 :                 if (!found) {
      70           0 :                         DEBUG(1, ("Unknown flag - %s in %s\n", str, str0));
      71           0 :                         return false;
      72             :                 }
      73             : 
      74     3987355 :                 *pflags |= flags;
      75     3987355 :                 if (plen != NULL) {
      76       39900 :                         *plen += len;
      77             :                 }
      78     3987355 :                 str += len;
      79             :         }
      80     8231121 :         return true;
      81             : }
      82             : 
      83             : /*
      84             :   a mapping between the 2 letter SID codes and sid strings
      85             : */
      86             : static const struct {
      87             :         const char *code;
      88             :         const char *sid;
      89             :         uint32_t rid;
      90             : } sid_codes[] = {
      91             :         { .code = "WD", .sid = SID_WORLD },
      92             : 
      93             :         { .code = "CO", .sid = SID_CREATOR_OWNER },
      94             :         { .code = "CG", .sid = SID_CREATOR_GROUP },
      95             : 
      96             :         { .code = "NU", .sid = SID_NT_NETWORK },
      97             :         { .code = "IU", .sid = SID_NT_INTERACTIVE },
      98             :         { .code = "SU", .sid = SID_NT_SERVICE },
      99             :         { .code = "AN", .sid = SID_NT_ANONYMOUS },
     100             :         { .code = "ED", .sid = SID_NT_ENTERPRISE_DCS },
     101             :         { .code = "PS", .sid = SID_NT_SELF },
     102             :         { .code = "AU", .sid = SID_NT_AUTHENTICATED_USERS },
     103             :         { .code = "RC", .sid = SID_NT_RESTRICTED },
     104             :         { .code = "SY", .sid = SID_NT_SYSTEM },
     105             :         { .code = "LS", .sid = SID_NT_LOCAL_SERVICE },
     106             :         { .code = "NS", .sid = SID_NT_NETWORK_SERVICE },
     107             :         { .code = "IS", .sid = SID_NT_IUSR },
     108             : 
     109             :         { .code = "BA", .sid = SID_BUILTIN_ADMINISTRATORS },
     110             :         { .code = "BU", .sid = SID_BUILTIN_USERS },
     111             :         { .code = "BG", .sid = SID_BUILTIN_GUESTS },
     112             :         { .code = "PU", .sid = SID_BUILTIN_POWER_USERS },
     113             :         { .code = "AO", .sid = SID_BUILTIN_ACCOUNT_OPERATORS },
     114             :         { .code = "SO", .sid = SID_BUILTIN_SERVER_OPERATORS },
     115             :         { .code = "PO", .sid = SID_BUILTIN_PRINT_OPERATORS },
     116             :         { .code = "BO", .sid = SID_BUILTIN_BACKUP_OPERATORS },
     117             :         { .code = "RE", .sid = SID_BUILTIN_REPLICATOR },
     118             :         { .code = "BR", .sid = SID_BUILTIN_RAS_SERVERS },
     119             :         { .code = "RU", .sid = SID_BUILTIN_PREW2K },
     120             :         { .code = "RD", .sid = SID_BUILTIN_REMOTE_DESKTOP_USERS },
     121             :         { .code = "NO", .sid = SID_BUILTIN_NETWORK_CONF_OPERATORS },
     122             :         { .code = "IF", .sid = SID_BUILTIN_INCOMING_FOREST_TRUST },
     123             : 
     124             :         { .code = "LA", .sid = NULL, .rid = DOMAIN_RID_ADMINISTRATOR },
     125             :         { .code = "LG", .sid = NULL, .rid = DOMAIN_RID_GUEST },
     126             :         { .code = "LK", .sid = NULL, .rid = DOMAIN_RID_KRBTGT },
     127             : 
     128             :         { .code = "ER", .sid = NULL, .rid = DOMAIN_RID_ENTERPRISE_READONLY_DCS },
     129             :         { .code = "DA", .sid = NULL, .rid = DOMAIN_RID_ADMINS },
     130             :         { .code = "DU", .sid = NULL, .rid = DOMAIN_RID_USERS },
     131             :         { .code = "DG", .sid = NULL, .rid = DOMAIN_RID_GUESTS },
     132             :         { .code = "DC", .sid = NULL, .rid = DOMAIN_RID_DOMAIN_MEMBERS },
     133             :         { .code = "DD", .sid = NULL, .rid = DOMAIN_RID_DCS },
     134             :         { .code = "CA", .sid = NULL, .rid = DOMAIN_RID_CERT_ADMINS },
     135             :         { .code = "SA", .sid = NULL, .rid = DOMAIN_RID_SCHEMA_ADMINS },
     136             :         { .code = "EA", .sid = NULL, .rid = DOMAIN_RID_ENTERPRISE_ADMINS },
     137             :         { .code = "PA", .sid = NULL, .rid = DOMAIN_RID_POLICY_ADMINS },
     138             :         { .code = "RO", .sid = NULL, .rid = DOMAIN_RID_READONLY_DCS },
     139             :         { .code = "RS", .sid = NULL, .rid = DOMAIN_RID_RAS_SERVERS }
     140             : };
     141             : 
     142             : /*
     143             :   decode a SID
     144             :   It can either be a special 2 letter code, or in S-* format
     145             : */
     146     3791416 : static struct dom_sid *sddl_decode_sid(TALLOC_CTX *mem_ctx, const char **sddlp,
     147             :                                        const struct dom_sid *domain_sid)
     148             : {
     149     3791416 :         const char *sddl = (*sddlp);
     150             :         size_t i;
     151             : 
     152             :         /* see if its in the numeric format */
     153     3791416 :         if (strncmp(sddl, "S-", 2) == 0) {
     154             :                 struct dom_sid *sid;
     155             :                 char *sid_str;
     156      132387 :                 size_t len = strspn(sddl+2, "-0123456789");
     157      132387 :                 sid_str = talloc_strndup(mem_ctx, sddl, len+2);
     158      132387 :                 if (!sid_str) {
     159           0 :                         return NULL;
     160             :                 }
     161      132387 :                 (*sddlp) += len+2;
     162      132387 :                 sid = dom_sid_parse_talloc(mem_ctx, sid_str);
     163      132387 :                 talloc_free(sid_str);
     164      132387 :                 return sid;
     165             :         }
     166             : 
     167             :         /* now check for one of the special codes */
     168    65334101 :         for (i=0;i<ARRAY_SIZE(sid_codes);i++) {
     169    65582548 :                 if (strncmp(sid_codes[i].code, sddl, 2) == 0) break;
     170             :         }
     171     3659029 :         if (i == ARRAY_SIZE(sid_codes)) {
     172           0 :                 DEBUG(1,("Unknown sddl sid code '%2.2s'\n", sddl));
     173           0 :                 return NULL;
     174             :         }
     175             : 
     176     3659029 :         (*sddlp) += 2;
     177             : 
     178     3659029 :         if (sid_codes[i].sid == NULL) {
     179      963586 :                 return dom_sid_add_rid(mem_ctx, domain_sid, sid_codes[i].rid);
     180             :         }
     181             : 
     182     2695443 :         return dom_sid_parse_talloc(mem_ctx, sid_codes[i].sid);
     183             : }
     184             : 
     185             : static const struct flag_map ace_types[] = {
     186             :         { "AU", SEC_ACE_TYPE_SYSTEM_AUDIT },
     187             :         { "AL", SEC_ACE_TYPE_SYSTEM_ALARM },
     188             :         { "OA", SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT },
     189             :         { "OD", SEC_ACE_TYPE_ACCESS_DENIED_OBJECT },
     190             :         { "OU", SEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT },
     191             :         { "OL", SEC_ACE_TYPE_SYSTEM_ALARM_OBJECT },
     192             :         { "A",  SEC_ACE_TYPE_ACCESS_ALLOWED },
     193             :         { "D",  SEC_ACE_TYPE_ACCESS_DENIED },
     194             :         { NULL, 0 }
     195             : };
     196             : 
     197             : static const struct flag_map ace_flags[] = {
     198             :         { "OI", SEC_ACE_FLAG_OBJECT_INHERIT },
     199             :         { "CI", SEC_ACE_FLAG_CONTAINER_INHERIT },
     200             :         { "NP", SEC_ACE_FLAG_NO_PROPAGATE_INHERIT },
     201             :         { "IO", SEC_ACE_FLAG_INHERIT_ONLY },
     202             :         { "ID", SEC_ACE_FLAG_INHERITED_ACE },
     203             :         { "SA", SEC_ACE_FLAG_SUCCESSFUL_ACCESS },
     204             :         { "FA", SEC_ACE_FLAG_FAILED_ACCESS },
     205             :         { NULL, 0 },
     206             : };
     207             : 
     208             : static const struct flag_map ace_access_mask[] = {
     209             :         { "RP", SEC_ADS_READ_PROP },
     210             :         { "WP", SEC_ADS_WRITE_PROP },
     211             :         { "CR", SEC_ADS_CONTROL_ACCESS },
     212             :         { "CC", SEC_ADS_CREATE_CHILD },
     213             :         { "DC", SEC_ADS_DELETE_CHILD },
     214             :         { "LC", SEC_ADS_LIST },
     215             :         { "LO", SEC_ADS_LIST_OBJECT },
     216             :         { "RC", SEC_STD_READ_CONTROL },
     217             :         { "WO", SEC_STD_WRITE_OWNER },
     218             :         { "WD", SEC_STD_WRITE_DAC },
     219             :         { "SD", SEC_STD_DELETE },
     220             :         { "DT", SEC_ADS_DELETE_TREE },
     221             :         { "SW", SEC_ADS_SELF_WRITE },
     222             :         { "GA", SEC_GENERIC_ALL },
     223             :         { "GR", SEC_GENERIC_READ },
     224             :         { "GW", SEC_GENERIC_WRITE },
     225             :         { "GX", SEC_GENERIC_EXECUTE },
     226             :         { NULL, 0 }
     227             : };
     228             : 
     229             : static const struct flag_map decode_ace_access_mask[] = {
     230             :         { "FA", FILE_ALL_ACCESS },
     231             :         { "FR", FILE_GENERIC_READ },
     232             :         { "FW", FILE_GENERIC_WRITE },
     233             :         { "FX", FILE_GENERIC_EXECUTE },
     234             :         { NULL, 0 },
     235             : };
     236             : 
     237     3770588 : static bool sddl_decode_access(const char *str, uint32_t *pmask)
     238             : {
     239     3770588 :         const char *str0 = str;
     240     3770588 :         uint32_t mask = 0;
     241             :         int cmp;
     242             : 
     243     3770588 :         cmp = strncmp(str, "0x", 2);
     244     3770588 :         if (cmp == 0) {
     245       38613 :                 *pmask = strtol(str, NULL, 16);
     246       38613 :                 return true;
     247             :         }
     248             : 
     249    33756578 :         while ((str[0] != '\0') && isupper(str[0])) {
     250    27242332 :                 uint32_t flags = 0;
     251    27242332 :                 size_t len = 0;
     252             :                 bool found;
     253             : 
     254    27242332 :                 found = sddl_map_flag(
     255             :                         ace_access_mask, str, &len, &flags);
     256    27242332 :                 found |= sddl_map_flag(
     257             :                         decode_ace_access_mask, str, &len, &flags);
     258    27242332 :                 if (!found) {
     259           0 :                         DEBUG(1, ("Unknown flag - %s in %s\n", str, str0));
     260           0 :                         return false;
     261             :                 }
     262    27242332 :                 mask |= flags;
     263    27242332 :                 str += len;
     264             :         }
     265             : 
     266     3731975 :         *pmask = mask;
     267     3731975 :         return true;
     268             : }
     269             : 
     270             : /*
     271             :   decode an ACE
     272             :   return true on success, false on failure
     273             :   note that this routine modifies the string
     274             : */
     275     3770588 : static bool sddl_decode_ace(TALLOC_CTX *mem_ctx, struct security_ace *ace, char *str,
     276             :                             const struct dom_sid *domain_sid)
     277             : {
     278             :         const char *tok[6];
     279             :         const char *s;
     280             :         int i;
     281             :         uint32_t v;
     282             :         struct dom_sid *sid;
     283             :         bool ok;
     284             : 
     285     3770588 :         ZERO_STRUCTP(ace);
     286             : 
     287             :         /* parse out the 6 tokens */
     288     3770588 :         tok[0] = str;
     289    22623528 :         for (i=0;i<5;i++) {
     290    18852940 :                 char *ptr = strchr(str, ';');
     291    18852940 :                 if (ptr == NULL) return false;
     292    18852940 :                 *ptr = 0;
     293    18852940 :                 str = ptr+1;
     294    18852940 :                 tok[i+1] = str;
     295             :         }
     296             : 
     297             :         /* parse ace type */
     298     3770588 :         if (!sddl_map_flags(ace_types, tok[0], &v, NULL)) {
     299           0 :                 return false;
     300             :         }
     301     3770588 :         ace->type = v;
     302             : 
     303             :         /* ace flags */
     304     3770588 :         if (!sddl_map_flags(ace_flags, tok[1], &v, NULL)) {
     305           0 :                 return false;
     306             :         }
     307     3770588 :         ace->flags = v;
     308             :         
     309             :         /* access mask */
     310     3770588 :         ok = sddl_decode_access(tok[2], &ace->access_mask);
     311     3770588 :         if (!ok) {
     312           0 :                 return false;
     313             :         }
     314             : 
     315             :         /* object */
     316     3770588 :         if (tok[3][0] != 0) {
     317     1088131 :                 NTSTATUS status = GUID_from_string(tok[3], 
     318             :                                                    &ace->object.object.type.type);
     319     1088131 :                 if (!NT_STATUS_IS_OK(status)) {
     320           0 :                         return false;
     321             :                 }
     322     1088131 :                 ace->object.object.flags |= SEC_ACE_OBJECT_TYPE_PRESENT;
     323             :         }
     324             : 
     325             :         /* inherit object */
     326     3770588 :         if (tok[4][0] != 0) {
     327       50622 :                 NTSTATUS status = GUID_from_string(tok[4], 
     328             :                                                    &ace->object.object.inherited_type.inherited_type);
     329       50622 :                 if (!NT_STATUS_IS_OK(status)) {
     330           0 :                         return false;
     331             :                 }
     332       50622 :                 ace->object.object.flags |= SEC_ACE_INHERITED_OBJECT_TYPE_PRESENT;
     333             :         }
     334             : 
     335             :         /* trustee */
     336     3770588 :         s = tok[5];
     337     3770588 :         sid = sddl_decode_sid(mem_ctx, &s, domain_sid);
     338     3770588 :         if (sid == NULL) {
     339           0 :                 return false;
     340             :         }
     341     3770588 :         ace->trustee = *sid;
     342     3770588 :         talloc_free(sid);
     343             : 
     344     3770588 :         return true;
     345             : }
     346             : 
     347             : static const struct flag_map acl_flags[] = {
     348             :         { "P", SEC_DESC_DACL_PROTECTED },
     349             :         { "AR", SEC_DESC_DACL_AUTO_INHERIT_REQ },
     350             :         { "AI", SEC_DESC_DACL_AUTO_INHERITED },
     351             :         { NULL, 0 }
     352             : };
     353             : 
     354             : /*
     355             :   decode an ACL
     356             : */
     357     1780399 : static struct security_acl *sddl_decode_acl(struct security_descriptor *sd, 
     358             :                                             const char **sddlp, uint32_t *flags,
     359             :                                             const struct dom_sid *domain_sid)
     360             : {
     361     1780399 :         const char *sddl = *sddlp;
     362             :         struct security_acl *acl;
     363             :         size_t len;
     364             : 
     365     1780399 :         *flags = 0;
     366             : 
     367     1780399 :         acl = talloc_zero(sd, struct security_acl);
     368     1780399 :         if (acl == NULL) return NULL;
     369     1780399 :         acl->revision = SECURITY_ACL_REVISION_ADS;
     370             : 
     371     1780399 :         if (isupper(sddl[0]) && sddl[1] == ':') {
     372             :                 /* its an empty ACL */
     373      443131 :                 return acl;
     374             :         }
     375             : 
     376             :         /* work out the ACL flags */
     377     1299219 :         if (!sddl_map_flags(acl_flags, sddl, flags, &len)) {
     378           0 :                 talloc_free(acl);
     379           0 :                 return NULL;
     380             :         }
     381     1299219 :         sddl += len;
     382             : 
     383             :         /* now the ACEs */
     384     6120654 :         while (*sddl == '(') {
     385             :                 char *astr;
     386     3770588 :                 len = strcspn(sddl+1, ")");
     387     3770588 :                 astr = talloc_strndup(acl, sddl+1, len);
     388     3770588 :                 if (astr == NULL || sddl[len+1] != ')') {
     389           0 :                         talloc_free(acl);
     390           0 :                         return NULL;
     391             :                 }
     392     3770588 :                 acl->aces = talloc_realloc(acl, acl->aces, struct security_ace, 
     393             :                                            acl->num_aces+1);
     394     3770588 :                 if (acl->aces == NULL) {
     395           0 :                         talloc_free(acl);
     396           0 :                         return NULL;
     397             :                 }
     398     3770588 :                 if (!sddl_decode_ace(acl->aces, &acl->aces[acl->num_aces], 
     399             :                                      astr, domain_sid)) {
     400           0 :                         talloc_free(acl);
     401           0 :                         return NULL;
     402             :                 }
     403     3770588 :                 switch (acl->aces[acl->num_aces].type) {
     404     1094564 :                 case SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT:
     405             :                 case SEC_ACE_TYPE_ACCESS_DENIED_OBJECT:
     406             :                 case SEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT:
     407             :                 case SEC_ACE_TYPE_SYSTEM_ALARM_OBJECT:
     408     1094564 :                         acl->revision = SECURITY_ACL_REVISION_ADS;
     409     1094564 :                         break;
     410     2448066 :                 default:
     411     2448066 :                         break;
     412             :                 }
     413     3770588 :                 talloc_free(astr);
     414     3770588 :                 sddl += len+2;
     415     3770588 :                 acl->num_aces++;
     416             :         }
     417             : 
     418     1299219 :         (*sddlp) = sddl;
     419     1299219 :         return acl;
     420             : }
     421             : 
     422             : /*
     423             :   decode a security descriptor in SDDL format
     424             : */
     425     1300696 : struct security_descriptor *sddl_decode(TALLOC_CTX *mem_ctx, const char *sddl,
     426             :                                         const struct dom_sid *domain_sid)
     427             : {
     428             :         struct security_descriptor *sd;
     429     1300696 :         sd = talloc_zero(mem_ctx, struct security_descriptor);
     430             : 
     431     1300696 :         sd->revision = SECURITY_DESCRIPTOR_REVISION_1;
     432     1300696 :         sd->type     = SEC_DESC_SELF_RELATIVE;
     433             :         
     434     4155484 :         while (*sddl) {
     435             :                 uint32_t flags;
     436     1801230 :                 char c = sddl[0];
     437     1801232 :                 if (sddl[1] != ':') goto failed;
     438             : 
     439     1801227 :                 sddl += 2;
     440     1801227 :                 switch (c) {
     441     1293953 :                 case 'D':
     442     1293953 :                         if (sd->dacl != NULL) goto failed;
     443     1293953 :                         sd->dacl = sddl_decode_acl(sd, &sddl, &flags, domain_sid);
     444     1293953 :                         if (sd->dacl == NULL) goto failed;
     445     1293953 :                         sd->type |= flags | SEC_DESC_DACL_PRESENT;
     446     1293953 :                         break;
     447      486446 :                 case 'S':
     448      486446 :                         if (sd->sacl != NULL) goto failed;
     449      486446 :                         sd->sacl = sddl_decode_acl(sd, &sddl, &flags, domain_sid);
     450      486446 :                         if (sd->sacl == NULL) goto failed;
     451             :                         /* this relies on the SEC_DESC_SACL_* flags being
     452             :                            1 bit shifted from the SEC_DESC_DACL_* flags */
     453      486446 :                         sd->type |= (flags<<1) | SEC_DESC_SACL_PRESENT;
     454      486446 :                         break;
     455       10410 :                 case 'O':
     456       10410 :                         if (sd->owner_sid != NULL) goto failed;
     457       10410 :                         sd->owner_sid = sddl_decode_sid(sd, &sddl, domain_sid);
     458       10410 :                         if (sd->owner_sid == NULL) goto failed;
     459        9576 :                         break;
     460       10418 :                 case 'G':
     461       10418 :                         if (sd->group_sid != NULL) goto failed;
     462       10418 :                         sd->group_sid = sddl_decode_sid(sd, &sddl, domain_sid);
     463       10418 :                         if (sd->group_sid == NULL) goto failed;
     464        9584 :                         break;
     465             :                 }
     466             :         }
     467             : 
     468     1189450 :         return sd;
     469             : 
     470           3 : failed:
     471           3 :         DEBUG(2,("Badly formatted SDDL '%s'\n", sddl));
     472           3 :         talloc_free(sd);
     473           3 :         return NULL;
     474             : }
     475             : 
     476             : /*
     477             :   turn a set of flags into a string
     478             : */
     479     1849186 : static char *sddl_flags_to_string(TALLOC_CTX *mem_ctx, const struct flag_map *map,
     480             :                                   uint32_t flags, bool check_all)
     481             : {
     482             :         int i;
     483             :         char *s;
     484             : 
     485             :         /* try to find an exact match */
     486    15499621 :         for (i=0;map[i].name;i++) {
     487    14420570 :                 if (map[i].flag == flags) {
     488      770135 :                         return talloc_strdup(mem_ctx, map[i].name);
     489             :                 }
     490             :         }
     491             : 
     492     1079051 :         s = talloc_strdup(mem_ctx, "");
     493             : 
     494             :         /* now by bits */
     495    12030286 :         for (i=0;map[i].name;i++) {
     496    10951235 :                 if ((flags & map[i].flag) != 0) {
     497     4684663 :                         s = talloc_asprintf_append_buffer(s, "%s", map[i].name);
     498     4684663 :                         if (s == NULL) goto failed;
     499     4684663 :                         flags &= ~map[i].flag;
     500             :                 }
     501             :         }
     502             : 
     503     1079051 :         if (check_all && flags != 0) {
     504        9477 :                 goto failed;
     505             :         }
     506             : 
     507      882168 :         return s;
     508             : 
     509        9748 : failed:
     510        9748 :         talloc_free(s);
     511        9748 :         return NULL;
     512             : }
     513             : 
     514             : /*
     515             :   encode a sid in SDDL format
     516             : */
     517      752302 : static char *sddl_encode_sid(TALLOC_CTX *mem_ctx, const struct dom_sid *sid,
     518             :                              const struct dom_sid *domain_sid)
     519             : {
     520             :         size_t i;
     521             :         char *sidstr;
     522             : 
     523      752302 :         sidstr = dom_sid_string(mem_ctx, sid);
     524      752302 :         if (sidstr == NULL) return NULL;
     525             : 
     526             :         /* seen if its a well known sid */ 
     527    15764453 :         for (i=0;sid_codes[i].sid;i++) {
     528    15546096 :                 if (strcmp(sidstr, sid_codes[i].sid) == 0) {
     529      406679 :                         talloc_free(sidstr);
     530      406679 :                         return talloc_strdup(mem_ctx, sid_codes[i].code);
     531             :                 }
     532             :         }
     533             : 
     534             :         /* or a well known rid in our domain */
     535      345623 :         if (dom_sid_in_domain(domain_sid, sid)) {
     536      280582 :                 uint32_t rid = sid->sub_auths[sid->num_auths-1];
     537     2555703 :                 for (;i<ARRAY_SIZE(sid_codes);i++) {
     538     2554440 :                         if (rid == sid_codes[i].rid) {
     539      279319 :                                 talloc_free(sidstr);
     540      279319 :                                 return talloc_strdup(mem_ctx, sid_codes[i].code);
     541             :                         }
     542             :                 }
     543             :         }
     544             :         
     545       66304 :         talloc_free(sidstr);
     546             : 
     547             :         /* TODO: encode well known sids as two letter codes */
     548       66304 :         return dom_sid_string(mem_ctx, sid);
     549             : }
     550             : 
     551             : 
     552             : /*
     553             :   encode an ACE in SDDL format
     554             : */
     555      575366 : static char *sddl_encode_ace(TALLOC_CTX *mem_ctx, const struct security_ace *ace,
     556             :                              const struct dom_sid *domain_sid)
     557             : {
     558      575366 :         char *sddl = NULL;
     559             :         TALLOC_CTX *tmp_ctx;
     560             :         struct GUID_txt_buf object_buf, iobject_buf;
     561      575366 :         const char *sddl_type="", *sddl_flags="", *sddl_mask="",
     562      575366 :                 *sddl_object="", *sddl_iobject="", *sddl_trustee="";
     563             : 
     564      575366 :         tmp_ctx = talloc_new(mem_ctx);
     565      575366 :         if (tmp_ctx == NULL) {
     566           0 :                 DEBUG(0, ("talloc_new failed\n"));
     567           0 :                 return NULL;
     568             :         }
     569             : 
     570      575366 :         sddl_type = sddl_flags_to_string(tmp_ctx, ace_types, ace->type, true);
     571      575366 :         if (sddl_type == NULL) {
     572           0 :                 goto failed;
     573             :         }
     574             : 
     575      575366 :         sddl_flags = sddl_flags_to_string(tmp_ctx, ace_flags, ace->flags,
     576             :                                           true);
     577      575366 :         if (sddl_flags == NULL) {
     578           0 :                 goto failed;
     579             :         }
     580             : 
     581      575366 :         sddl_mask = sddl_flags_to_string(tmp_ctx, ace_access_mask,
     582       29014 :                                          ace->access_mask, true);
     583      575366 :         if (sddl_mask == NULL) {
     584        9748 :                 sddl_mask = talloc_asprintf(tmp_ctx, "0x%08x",
     585        2252 :                                              ace->access_mask);
     586        9748 :                 if (sddl_mask == NULL) {
     587           0 :                         goto failed;
     588             :                 }
     589             :         }
     590             : 
     591      994614 :         if (ace->type == SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT ||
     592      655378 :             ace->type == SEC_ACE_TYPE_ACCESS_DENIED_OBJECT ||
     593      739985 :             ace->type == SEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT ||
     594      319203 :             ace->type == SEC_ACE_TYPE_SYSTEM_ALARM_OBJECT) {
     595      185384 :                 const struct security_ace_object *object = &ace->object.object;
     596             : 
     597      185384 :                 if (ace->object.object.flags & SEC_ACE_OBJECT_TYPE_PRESENT) {
     598      162706 :                         sddl_object = GUID_buf_string(
     599             :                                 &object->type.type, &object_buf);
     600             :                 }
     601             : 
     602      185384 :                 if (ace->object.object.flags &
     603             :                     SEC_ACE_INHERITED_OBJECT_TYPE_PRESENT) {
     604      137093 :                         sddl_iobject = GUID_buf_string(
     605             :                                 &object->inherited_type.inherited_type,
     606             :                                 &iobject_buf);
     607             :                 }
     608             :         }
     609             : 
     610      575366 :         sddl_trustee = sddl_encode_sid(tmp_ctx, &ace->trustee, domain_sid);
     611      575366 :         if (sddl_trustee == NULL) {
     612           0 :                 goto failed;
     613             :         }
     614             : 
     615      575366 :         sddl = talloc_asprintf(mem_ctx, "%s;%s;%s;%s;%s;%s",
     616             :                                sddl_type, sddl_flags, sddl_mask, sddl_object,
     617             :                                sddl_iobject, sddl_trustee);
     618             : 
     619      575366 : failed:
     620      575366 :         talloc_free(tmp_ctx);
     621      575366 :         return sddl;
     622             : }
     623             : 
     624             : /*
     625             :   encode an ACL in SDDL format
     626             : */
     627      123088 : static char *sddl_encode_acl(TALLOC_CTX *mem_ctx, const struct security_acl *acl,
     628             :                              uint32_t flags, const struct dom_sid *domain_sid)
     629             : {
     630             :         char *sddl;
     631             :         uint32_t i;
     632             : 
     633             :         /* add any ACL flags */
     634      123088 :         sddl = sddl_flags_to_string(mem_ctx, acl_flags, flags, false);
     635      123088 :         if (sddl == NULL) goto failed;
     636             : 
     637             :         /* now the ACEs, encoded in braces */
     638      675226 :         for (i=0;i<acl->num_aces;i++) {
     639      575366 :                 char *ace = sddl_encode_ace(sddl, &acl->aces[i], domain_sid);
     640      575366 :                 if (ace == NULL) goto failed;
     641      575366 :                 sddl = talloc_asprintf_append_buffer(sddl, "(%s)", ace);
     642      575366 :                 if (sddl == NULL) goto failed;
     643      575366 :                 talloc_free(ace);
     644             :         }
     645             : 
     646       99860 :         return sddl;
     647             : 
     648           0 : failed:
     649           0 :         talloc_free(sddl);
     650           0 :         return NULL;
     651             : }
     652             : 
     653             : 
     654             : /*
     655             :   encode a security descriptor to SDDL format
     656             : */
     657       88854 : char *sddl_encode(TALLOC_CTX *mem_ctx, const struct security_descriptor *sd,
     658             :                   const struct dom_sid *domain_sid)
     659             : {
     660             :         char *sddl;
     661             :         TALLOC_CTX *tmp_ctx;
     662             : 
     663             :         /* start with a blank string */
     664       88854 :         sddl = talloc_strdup(mem_ctx, "");
     665       88854 :         if (sddl == NULL) goto failed;
     666             : 
     667       88854 :         tmp_ctx = talloc_new(mem_ctx);
     668             : 
     669       88854 :         if (sd->owner_sid != NULL) {
     670       88468 :                 char *sid = sddl_encode_sid(tmp_ctx, sd->owner_sid, domain_sid);
     671       88468 :                 if (sid == NULL) goto failed;
     672       88468 :                 sddl = talloc_asprintf_append_buffer(sddl, "O:%s", sid);
     673       88468 :                 if (sddl == NULL) goto failed;
     674             :         }
     675             : 
     676       88854 :         if (sd->group_sid != NULL) {
     677       88468 :                 char *sid = sddl_encode_sid(tmp_ctx, sd->group_sid, domain_sid);
     678       88468 :                 if (sid == NULL) goto failed;
     679       88468 :                 sddl = talloc_asprintf_append_buffer(sddl, "G:%s", sid);
     680       88468 :                 if (sddl == NULL) goto failed;
     681             :         }
     682             : 
     683       88854 :         if ((sd->type & SEC_DESC_DACL_PRESENT) && sd->dacl != NULL) {
     684       82543 :                 char *acl = sddl_encode_acl(tmp_ctx, sd->dacl, sd->type, domain_sid);
     685       82543 :                 if (acl == NULL) goto failed;
     686       82543 :                 sddl = talloc_asprintf_append_buffer(sddl, "D:%s", acl);
     687       82543 :                 if (sddl == NULL) goto failed;
     688             :         }
     689             : 
     690       88854 :         if ((sd->type & SEC_DESC_SACL_PRESENT) && sd->sacl != NULL) {
     691       40545 :                 char *acl = sddl_encode_acl(tmp_ctx, sd->sacl, sd->type>>1, domain_sid);
     692       40545 :                 if (acl == NULL) goto failed;
     693       40545 :                 sddl = talloc_asprintf_append_buffer(sddl, "S:%s", acl);
     694       40545 :                 if (sddl == NULL) goto failed;
     695             :         }
     696             : 
     697       88854 :         talloc_free(tmp_ctx);
     698       88854 :         return sddl;
     699             : 
     700           0 : failed:
     701           0 :         talloc_free(sddl);
     702           0 :         return NULL;
     703             : }
     704             : 
     705             : 

Generated by: LCOV version 1.13