LCOV - code coverage report
Current view: top level - libcli/security - sddl.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 248 281 88.3 %
Date: 2024-06-13 04:01:37 Functions: 12 12 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    40553579 : 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   266627321 :         while (map->name != NULL) {
      39   213442135 :                 size_t len = strlen(map->name);
      40   213442135 :                 int cmp = strncmp(map->name, str, len);
      41             : 
      42   213442135 :                 if (cmp == 0) {
      43    21740547 :                         *plen = len;
      44    21740547 :                         *pflag = map->flag;
      45    21740547 :                         return true;
      46             :                 }
      47   191701588 :                 map += 1;
      48             :         }
      49    18813032 :         return false;
      50             : }
      51             : 
      52             : /*
      53             :   map a series of letter codes into a uint32_t
      54             : */
      55     6650543 : static bool sddl_map_flags(const struct flag_map *map, const char *str, 
      56             :                            uint32_t *pflags, size_t *plen)
      57             : {
      58     6650543 :         const char *str0 = str;
      59     6650543 :         if (plen != NULL) {
      60     1029031 :                 *plen = 0;
      61             :         }
      62     6650543 :         *pflags = 0;
      63    15101301 :         while (str[0] && isupper(str[0])) {
      64             :                 size_t len;
      65             :                 uint32_t flags;
      66             :                 bool found;
      67             : 
      68     2927515 :                 found = sddl_map_flag(map, str, &len, &flags);
      69     2927515 :                 if (!found) {
      70           0 :                         DEBUG(1, ("Unknown flag - %s in %s\n", str, str0));
      71           0 :                         return false;
      72             :                 }
      73             : 
      74     2927515 :                 *pflags |= flags;
      75     2927515 :                 if (plen != NULL) {
      76       34835 :                         *plen += len;
      77             :                 }
      78     2927515 :                 str += len;
      79             :         }
      80     6650543 :         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             :         { .code = "OW", .sid = SID_OWNER_RIGHTS },
      96             : 
      97             :         { .code = "NU", .sid = SID_NT_NETWORK },
      98             :         { .code = "IU", .sid = SID_NT_INTERACTIVE },
      99             :         { .code = "SU", .sid = SID_NT_SERVICE },
     100             :         { .code = "AN", .sid = SID_NT_ANONYMOUS },
     101             :         { .code = "ED", .sid = SID_NT_ENTERPRISE_DCS },
     102             :         { .code = "PS", .sid = SID_NT_SELF },
     103             :         { .code = "AU", .sid = SID_NT_AUTHENTICATED_USERS },
     104             :         { .code = "RC", .sid = SID_NT_RESTRICTED },
     105             :         { .code = "SY", .sid = SID_NT_SYSTEM },
     106             :         { .code = "LS", .sid = SID_NT_LOCAL_SERVICE },
     107             :         { .code = "NS", .sid = SID_NT_NETWORK_SERVICE },
     108             :         { .code = "WR", .sid = SID_SECURITY_RESTRICTED_CODE },
     109             : 
     110             :         { .code = "BA", .sid = SID_BUILTIN_ADMINISTRATORS },
     111             :         { .code = "BU", .sid = SID_BUILTIN_USERS },
     112             :         { .code = "BG", .sid = SID_BUILTIN_GUESTS },
     113             :         { .code = "PU", .sid = SID_BUILTIN_POWER_USERS },
     114             :         { .code = "AO", .sid = SID_BUILTIN_ACCOUNT_OPERATORS },
     115             :         { .code = "SO", .sid = SID_BUILTIN_SERVER_OPERATORS },
     116             :         { .code = "PO", .sid = SID_BUILTIN_PRINT_OPERATORS },
     117             :         { .code = "BO", .sid = SID_BUILTIN_BACKUP_OPERATORS },
     118             :         { .code = "RE", .sid = SID_BUILTIN_REPLICATOR },
     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             : 
     123             :         { .code = "MU", .sid = SID_BUILTIN_PERFMON_USERS },
     124             :         { .code = "LU", .sid = SID_BUILTIN_PERFLOG_USERS },
     125             :         { .code = "IS", .sid = SID_BUILTIN_IUSERS },
     126             :         { .code = "CY", .sid = SID_BUILTIN_CRYPTO_OPERATORS },
     127             :         { .code = "ER", .sid = SID_BUILTIN_EVENT_LOG_READERS },
     128             :         { .code = "CD", .sid = SID_BUILTIN_CERT_SERV_DCOM_ACCESS },
     129             :         { .code = "RA", .sid = SID_BUILTIN_RDS_REMOTE_ACCESS_SERVERS },
     130             :         { .code = "ES", .sid = SID_BUILTIN_RDS_ENDPOINT_SERVERS },
     131             :         { .code = "MS", .sid = SID_BUILTIN_RDS_MANAGEMENT_SERVERS },
     132             :         { .code = "HA", .sid = SID_BUILTIN_HYPER_V_ADMINS },
     133             :         { .code = "AA", .sid = SID_BUILTIN_ACCESS_CONTROL_ASSISTANCE_OPS },
     134             :         { .code = "RM", .sid = SID_BUILTIN_REMOTE_MANAGEMENT_USERS },
     135             : 
     136             :         { .code = "UD", .sid = SID_USER_MODE_DRIVERS },
     137             : 
     138             :         { .code = "AC", .sid = SID_SECURITY_BUILTIN_PACKAGE_ANY_PACKAGE },
     139             : 
     140             :         { .code = "LW", .sid = SID_SECURITY_MANDATORY_LOW },
     141             :         { .code = "ME", .sid = SID_SECURITY_MANDATORY_MEDIUM },
     142             :         { .code = "MP", .sid = SID_SECURITY_MANDATORY_MEDIUM_PLUS },
     143             :         { .code = "HI", .sid = SID_SECURITY_MANDATORY_HIGH },
     144             :         { .code = "SI", .sid = SID_SECURITY_MANDATORY_SYSTEM },
     145             : 
     146             :         { .code = "AS", .sid = SID_AUTHENTICATION_AUTHORITY_ASSERTED_IDENTITY },
     147             :         { .code = "SS", .sid = SID_SERVICE_ASSERTED_IDENTITY },
     148             : 
     149             :         { .code = "RO", .sid = NULL, .rid = DOMAIN_RID_ENTERPRISE_READONLY_DCS },
     150             : 
     151             :         { .code = "LA", .sid = NULL, .rid = DOMAIN_RID_ADMINISTRATOR },
     152             :         { .code = "LG", .sid = NULL, .rid = DOMAIN_RID_GUEST },
     153             : 
     154             :         { .code = "DA", .sid = NULL, .rid = DOMAIN_RID_ADMINS },
     155             :         { .code = "DU", .sid = NULL, .rid = DOMAIN_RID_USERS },
     156             :         { .code = "DG", .sid = NULL, .rid = DOMAIN_RID_GUESTS },
     157             :         { .code = "DC", .sid = NULL, .rid = DOMAIN_RID_DOMAIN_MEMBERS },
     158             :         { .code = "DD", .sid = NULL, .rid = DOMAIN_RID_DCS },
     159             :         { .code = "CA", .sid = NULL, .rid = DOMAIN_RID_CERT_ADMINS },
     160             :         { .code = "SA", .sid = NULL, .rid = DOMAIN_RID_SCHEMA_ADMINS },
     161             :         { .code = "EA", .sid = NULL, .rid = DOMAIN_RID_ENTERPRISE_ADMINS },
     162             :         { .code = "PA", .sid = NULL, .rid = DOMAIN_RID_POLICY_ADMINS },
     163             : 
     164             :         { .code = "CN", .sid = NULL, .rid = DOMAIN_RID_CLONEABLE_CONTROLLERS },
     165             : 
     166             :         { .code = "AP", .sid = NULL, .rid = DOMAIN_RID_PROTECTED_USERS },
     167             :         { .code = "KA", .sid = NULL, .rid = DOMAIN_RID_KEY_ADMINS },
     168             :         { .code = "EK", .sid = NULL, .rid = DOMAIN_RID_ENTERPRISE_KEY_ADMINS },
     169             : 
     170             :         { .code = "RS", .sid = NULL, .rid = DOMAIN_RID_RAS_SERVERS }
     171             : };
     172             : 
     173             : /*
     174             :   decode a SID
     175             :   It can either be a special 2 letter code, or in S-* format
     176             : */
     177     2825052 : static struct dom_sid *sddl_decode_sid(TALLOC_CTX *mem_ctx, const char **sddlp,
     178             :                                        const struct dom_sid *domain_sid)
     179             : {
     180     2825052 :         const char *sddl = (*sddlp);
     181             :         size_t i;
     182             : 
     183             :         /* see if its in the numeric format */
     184     2825052 :         if (strncmp(sddl, "S-", 2) == 0) {
     185             :                 struct dom_sid *sid;
     186             :                 char *sid_str;
     187      122505 :                 size_t len = strspn(sddl+2, "-0123456789");
     188      122505 :                 sid_str = talloc_strndup(mem_ctx, sddl, len+2);
     189      122505 :                 if (!sid_str) {
     190           0 :                         return NULL;
     191             :                 }
     192      122505 :                 (*sddlp) += len+2;
     193      122505 :                 sid = dom_sid_parse_talloc(mem_ctx, sid_str);
     194      122505 :                 talloc_free(sid_str);
     195      122505 :                 return sid;
     196             :         }
     197             : 
     198             :         /* now check for one of the special codes */
     199    63527572 :         for (i=0;i<ARRAY_SIZE(sid_codes);i++) {
     200    63527572 :                 if (strncmp(sid_codes[i].code, sddl, 2) == 0) break;
     201             :         }
     202     2702547 :         if (i == ARRAY_SIZE(sid_codes)) {
     203           0 :                 DEBUG(1,("Unknown sddl sid code '%2.2s'\n", sddl));
     204           0 :                 return NULL;
     205             :         }
     206             : 
     207     2702547 :         (*sddlp) += 2;
     208             : 
     209     2702547 :         if (sid_codes[i].sid == NULL) {
     210      684146 :                 return dom_sid_add_rid(mem_ctx, domain_sid, sid_codes[i].rid);
     211             :         }
     212             : 
     213     2018401 :         return dom_sid_parse_talloc(mem_ctx, sid_codes[i].sid);
     214             : }
     215             : 
     216             : static const struct flag_map ace_types[] = {
     217             :         { "AU", SEC_ACE_TYPE_SYSTEM_AUDIT },
     218             :         { "AL", SEC_ACE_TYPE_SYSTEM_ALARM },
     219             :         { "OA", SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT },
     220             :         { "OD", SEC_ACE_TYPE_ACCESS_DENIED_OBJECT },
     221             :         { "OU", SEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT },
     222             :         { "OL", SEC_ACE_TYPE_SYSTEM_ALARM_OBJECT },
     223             :         { "A",  SEC_ACE_TYPE_ACCESS_ALLOWED },
     224             :         { "D",  SEC_ACE_TYPE_ACCESS_DENIED },
     225             :         { NULL, 0 }
     226             : };
     227             : 
     228             : static const struct flag_map ace_flags[] = {
     229             :         { "OI", SEC_ACE_FLAG_OBJECT_INHERIT },
     230             :         { "CI", SEC_ACE_FLAG_CONTAINER_INHERIT },
     231             :         { "NP", SEC_ACE_FLAG_NO_PROPAGATE_INHERIT },
     232             :         { "IO", SEC_ACE_FLAG_INHERIT_ONLY },
     233             :         { "ID", SEC_ACE_FLAG_INHERITED_ACE },
     234             :         { "SA", SEC_ACE_FLAG_SUCCESSFUL_ACCESS },
     235             :         { "FA", SEC_ACE_FLAG_FAILED_ACCESS },
     236             :         { NULL, 0 },
     237             : };
     238             : 
     239             : static const struct flag_map ace_access_mask[] = {
     240             :         { "RP", SEC_ADS_READ_PROP },
     241             :         { "WP", SEC_ADS_WRITE_PROP },
     242             :         { "CR", SEC_ADS_CONTROL_ACCESS },
     243             :         { "CC", SEC_ADS_CREATE_CHILD },
     244             :         { "DC", SEC_ADS_DELETE_CHILD },
     245             :         { "LC", SEC_ADS_LIST },
     246             :         { "LO", SEC_ADS_LIST_OBJECT },
     247             :         { "RC", SEC_STD_READ_CONTROL },
     248             :         { "WO", SEC_STD_WRITE_OWNER },
     249             :         { "WD", SEC_STD_WRITE_DAC },
     250             :         { "SD", SEC_STD_DELETE },
     251             :         { "DT", SEC_ADS_DELETE_TREE },
     252             :         { "SW", SEC_ADS_SELF_WRITE },
     253             :         { "GA", SEC_GENERIC_ALL },
     254             :         { "GR", SEC_GENERIC_READ },
     255             :         { "GW", SEC_GENERIC_WRITE },
     256             :         { "GX", SEC_GENERIC_EXECUTE },
     257             :         { NULL, 0 }
     258             : };
     259             : 
     260             : static const struct flag_map decode_ace_access_mask[] = {
     261             :         { "FA", FILE_ALL_ACCESS },
     262             :         { "FR", FILE_GENERIC_READ },
     263             :         { "FW", FILE_GENERIC_WRITE },
     264             :         { "FX", FILE_GENERIC_EXECUTE },
     265             :         { NULL, 0 },
     266             : };
     267             : 
     268     2810756 : static bool sddl_decode_access(const char *str, uint32_t *pmask)
     269             : {
     270     2810756 :         const char *str0 = str;
     271     2810756 :         uint32_t mask = 0;
     272             :         int cmp;
     273             : 
     274     2810756 :         cmp = strncmp(str, "0x", 2);
     275     2810756 :         if (cmp == 0) {
     276       36614 :                 *pmask = strtol(str, NULL, 16);
     277       36614 :                 return true;
     278             :         }
     279             : 
     280    23908310 :         while ((str[0] != '\0') && isupper(str[0])) {
     281    18813032 :                 uint32_t flags = 0;
     282    18813032 :                 size_t len = 0;
     283             :                 bool found;
     284             : 
     285    18813032 :                 found = sddl_map_flag(
     286             :                         ace_access_mask, str, &len, &flags);
     287    18813032 :                 found |= sddl_map_flag(
     288             :                         decode_ace_access_mask, str, &len, &flags);
     289    18813032 :                 if (!found) {
     290           0 :                         DEBUG(1, ("Unknown flag - %s in %s\n", str, str0));
     291           0 :                         return false;
     292             :                 }
     293    18813032 :                 mask |= flags;
     294    18813032 :                 str += len;
     295             :         }
     296             : 
     297     2774142 :         *pmask = mask;
     298     2774142 :         return true;
     299             : }
     300             : 
     301             : /*
     302             :   decode an ACE
     303             :   return true on success, false on failure
     304             :   note that this routine modifies the string
     305             : */
     306     2810756 : static bool sddl_decode_ace(TALLOC_CTX *mem_ctx, struct security_ace *ace, char *str,
     307             :                             const struct dom_sid *domain_sid)
     308             : {
     309             :         const char *tok[6];
     310             :         const char *s;
     311             :         int i;
     312             :         uint32_t v;
     313             :         struct dom_sid *sid;
     314             :         bool ok;
     315             : 
     316     2810756 :         ZERO_STRUCTP(ace);
     317             : 
     318             :         /* parse out the 6 tokens */
     319     2810756 :         tok[0] = str;
     320    16864536 :         for (i=0;i<5;i++) {
     321    14053780 :                 char *ptr = strchr(str, ';');
     322    14053780 :                 if (ptr == NULL) return false;
     323    14053780 :                 *ptr = 0;
     324    14053780 :                 str = ptr+1;
     325    14053780 :                 tok[i+1] = str;
     326             :         }
     327             : 
     328             :         /* parse ace type */
     329     2810756 :         if (!sddl_map_flags(ace_types, tok[0], &v, NULL)) {
     330           0 :                 return false;
     331             :         }
     332     2810756 :         ace->type = v;
     333             : 
     334             :         /* ace flags */
     335     2810756 :         if (!sddl_map_flags(ace_flags, tok[1], &v, NULL)) {
     336           0 :                 return false;
     337             :         }
     338     2810756 :         ace->flags = v;
     339             :         
     340             :         /* access mask */
     341     2810756 :         ok = sddl_decode_access(tok[2], &ace->access_mask);
     342     2810756 :         if (!ok) {
     343           0 :                 return false;
     344             :         }
     345             : 
     346             :         /* object */
     347     2810756 :         if (tok[3][0] != 0) {
     348      973955 :                 NTSTATUS status = GUID_from_string(tok[3], 
     349             :                                                    &ace->object.object.type.type);
     350      973955 :                 if (!NT_STATUS_IS_OK(status)) {
     351           0 :                         return false;
     352             :                 }
     353      973955 :                 ace->object.object.flags |= SEC_ACE_OBJECT_TYPE_PRESENT;
     354             :         }
     355             : 
     356             :         /* inherit object */
     357     2810756 :         if (tok[4][0] != 0) {
     358       30120 :                 NTSTATUS status = GUID_from_string(tok[4], 
     359             :                                                    &ace->object.object.inherited_type.inherited_type);
     360       30120 :                 if (!NT_STATUS_IS_OK(status)) {
     361           0 :                         return false;
     362             :                 }
     363       30120 :                 ace->object.object.flags |= SEC_ACE_INHERITED_OBJECT_TYPE_PRESENT;
     364             :         }
     365             : 
     366             :         /* trustee */
     367     2810756 :         s = tok[5];
     368     2810756 :         sid = sddl_decode_sid(mem_ctx, &s, domain_sid);
     369     2810756 :         if (sid == NULL) {
     370           0 :                 return false;
     371             :         }
     372     2810756 :         ace->trustee = *sid;
     373     2810756 :         talloc_free(sid);
     374             : 
     375     2810756 :         return true;
     376             : }
     377             : 
     378             : static const struct flag_map acl_flags[] = {
     379             :         { "P", SEC_DESC_DACL_PROTECTED },
     380             :         { "AR", SEC_DESC_DACL_AUTO_INHERIT_REQ },
     381             :         { "AI", SEC_DESC_DACL_AUTO_INHERITED },
     382             :         { NULL, 0 }
     383             : };
     384             : 
     385             : /*
     386             :   decode an ACL
     387             : */
     388     1506691 : static struct security_acl *sddl_decode_acl(struct security_descriptor *sd, 
     389             :                                             const char **sddlp, uint32_t *flags,
     390             :                                             const struct dom_sid *domain_sid)
     391             : {
     392     1506691 :         const char *sddl = *sddlp;
     393             :         struct security_acl *acl;
     394             :         size_t len;
     395             : 
     396     1506691 :         *flags = 0;
     397             : 
     398     1506691 :         acl = talloc_zero(sd, struct security_acl);
     399     1506691 :         if (acl == NULL) return NULL;
     400     1506691 :         acl->revision = SECURITY_ACL_REVISION_ADS;
     401             : 
     402     1506691 :         if (isupper(sddl[0]) && sddl[1] == ':') {
     403             :                 /* its an empty ACL */
     404      477660 :                 return acl;
     405             :         }
     406             : 
     407             :         /* work out the ACL flags */
     408     1029031 :         if (!sddl_map_flags(acl_flags, sddl, flags, &len)) {
     409           0 :                 talloc_free(acl);
     410           0 :                 return NULL;
     411             :         }
     412     1029031 :         sddl += len;
     413             : 
     414             :         /* now the ACEs */
     415     4669234 :         while (*sddl == '(') {
     416             :                 char *astr;
     417     2810756 :                 len = strcspn(sddl+1, ")");
     418     2810756 :                 astr = talloc_strndup(acl, sddl+1, len);
     419     2810756 :                 if (astr == NULL || sddl[len+1] != ')') {
     420           0 :                         talloc_free(acl);
     421           0 :                         return NULL;
     422             :                 }
     423     2810756 :                 acl->aces = talloc_realloc(acl, acl->aces, struct security_ace, 
     424             :                                            acl->num_aces+1);
     425     2810756 :                 if (acl->aces == NULL) {
     426           0 :                         talloc_free(acl);
     427           0 :                         return NULL;
     428             :                 }
     429     2810756 :                 if (!sddl_decode_ace(acl->aces, &acl->aces[acl->num_aces], 
     430             :                                      astr, domain_sid)) {
     431           0 :                         talloc_free(acl);
     432           0 :                         return NULL;
     433             :                 }
     434     2810756 :                 switch (acl->aces[acl->num_aces].type) {
     435      977069 :                 case SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT:
     436             :                 case SEC_ACE_TYPE_ACCESS_DENIED_OBJECT:
     437             :                 case SEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT:
     438             :                 case SEC_ACE_TYPE_SYSTEM_ALARM_OBJECT:
     439      977069 :                         acl->revision = SECURITY_ACL_REVISION_ADS;
     440      977069 :                         break;
     441     1833687 :                 default:
     442     1833687 :                         break;
     443             :                 }
     444     2810756 :                 talloc_free(astr);
     445     2810756 :                 sddl += len+2;
     446     2810756 :                 acl->num_aces++;
     447             :         }
     448             : 
     449     1029031 :         (*sddlp) = sddl;
     450     1029031 :         return acl;
     451             : }
     452             : 
     453             : /*
     454             :   decode a security descriptor in SDDL format
     455             : */
     456     1032794 : struct security_descriptor *sddl_decode(TALLOC_CTX *mem_ctx, const char *sddl,
     457             :                                         const struct dom_sid *domain_sid)
     458             : {
     459             :         struct security_descriptor *sd;
     460     1032794 :         sd = talloc_zero(mem_ctx, struct security_descriptor);
     461             : 
     462     1032794 :         sd->revision = SECURITY_DESCRIPTOR_REVISION_1;
     463     1032794 :         sd->type     = SEC_DESC_SELF_RELATIVE;
     464             :         
     465     3387563 :         while (*sddl) {
     466             :                 uint32_t flags;
     467     1520989 :                 char c = sddl[0];
     468     1520991 :                 if (sddl[1] != ':') goto failed;
     469             : 
     470     1520987 :                 sddl += 2;
     471     1520987 :                 switch (c) {
     472     1026086 :                 case 'D':
     473     1026086 :                         if (sd->dacl != NULL) goto failed;
     474     1026086 :                         sd->dacl = sddl_decode_acl(sd, &sddl, &flags, domain_sid);
     475     1026086 :                         if (sd->dacl == NULL) goto failed;
     476     1026086 :                         sd->type |= flags | SEC_DESC_DACL_PRESENT;
     477     1026086 :                         break;
     478      480605 :                 case 'S':
     479      480605 :                         if (sd->sacl != NULL) goto failed;
     480      480605 :                         sd->sacl = sddl_decode_acl(sd, &sddl, &flags, domain_sid);
     481      480605 :                         if (sd->sacl == NULL) goto failed;
     482             :                         /* this relies on the SEC_DESC_SACL_* flags being
     483             :                            1 bit shifted from the SEC_DESC_DACL_* flags */
     484      480605 :                         sd->type |= (flags<<1) | SEC_DESC_SACL_PRESENT;
     485      480605 :                         break;
     486        7146 :                 case 'O':
     487        7146 :                         if (sd->owner_sid != NULL) goto failed;
     488        7146 :                         sd->owner_sid = sddl_decode_sid(sd, &sddl, domain_sid);
     489        7146 :                         if (sd->owner_sid == NULL) goto failed;
     490        7146 :                         break;
     491        7150 :                 case 'G':
     492        7150 :                         if (sd->group_sid != NULL) goto failed;
     493        7150 :                         sd->group_sid = sddl_decode_sid(sd, &sddl, domain_sid);
     494        7150 :                         if (sd->group_sid == NULL) goto failed;
     495        7150 :                         break;
     496             :                 }
     497             :         }
     498             : 
     499     1032792 :         return sd;
     500             : 
     501           2 : failed:
     502           2 :         DEBUG(2,("Badly formatted SDDL '%s'\n", sddl));
     503           2 :         talloc_free(sd);
     504           2 :         return NULL;
     505             : }
     506             : 
     507             : /*
     508             :   turn a set of flags into a string
     509             : */
     510     1377439 : static char *sddl_flags_to_string(TALLOC_CTX *mem_ctx, const struct flag_map *map,
     511             :                                   uint32_t flags, bool check_all)
     512             : {
     513             :         int i;
     514             :         char *s;
     515             : 
     516             :         /* try to find an exact match */
     517    11724850 :         for (i=0;map[i].name;i++) {
     518    10908205 :                 if (map[i].flag == flags) {
     519      560794 :                         return talloc_strdup(mem_ctx, map[i].name);
     520             :                 }
     521             :         }
     522             : 
     523      816645 :         s = talloc_strdup(mem_ctx, "");
     524             : 
     525             :         /* now by bits */
     526     9124008 :         for (i=0;map[i].name;i++) {
     527     8307363 :                 if ((flags & map[i].flag) != 0) {
     528     3601294 :                         s = talloc_asprintf_append_buffer(s, "%s", map[i].name);
     529     3601294 :                         if (s == NULL) goto failed;
     530     3601294 :                         flags &= ~map[i].flag;
     531             :                 }
     532             :         }
     533             : 
     534      816645 :         if (check_all && flags != 0) {
     535        4619 :                 goto failed;
     536             :         }
     537             : 
     538      812026 :         return s;
     539             : 
     540        4619 : failed:
     541        4619 :         talloc_free(s);
     542        4619 :         return NULL;
     543             : }
     544             : 
     545             : /*
     546             :   encode a sid in SDDL format
     547             : */
     548      570617 : static char *sddl_encode_sid(TALLOC_CTX *mem_ctx, const struct dom_sid *sid,
     549             :                              const struct dom_sid *domain_sid)
     550             : {
     551             :         size_t i;
     552             :         char *sidstr;
     553             : 
     554      570617 :         sidstr = dom_sid_string(mem_ctx, sid);
     555      570617 :         if (sidstr == NULL) return NULL;
     556             : 
     557             :         /* seen if its a well known sid */ 
     558    17770504 :         for (i=0;sid_codes[i].sid;i++) {
     559    17498408 :                 if (strcmp(sidstr, sid_codes[i].sid) == 0) {
     560      298521 :                         talloc_free(sidstr);
     561      298521 :                         return talloc_strdup(mem_ctx, sid_codes[i].code);
     562             :                 }
     563             :         }
     564             : 
     565             :         /* or a well known rid in our domain */
     566      272096 :         if (dom_sid_in_domain(domain_sid, sid)) {
     567      269110 :                 uint32_t rid = sid->sub_auths[sid->num_auths-1];
     568     2208286 :                 for (;i<ARRAY_SIZE(sid_codes);i++) {
     569     2206393 :                         if (rid == sid_codes[i].rid) {
     570      267217 :                                 talloc_free(sidstr);
     571      267217 :                                 return talloc_strdup(mem_ctx, sid_codes[i].code);
     572             :                         }
     573             :                 }
     574             :         }
     575             :         
     576        4879 :         talloc_free(sidstr);
     577             : 
     578             :         /* TODO: encode well known sids as two letter codes */
     579        4879 :         return dom_sid_string(mem_ctx, sid);
     580             : }
     581             : 
     582             : 
     583             : /*
     584             :   encode an ACE in SDDL format
     585             : */
     586      426967 : static char *sddl_encode_ace(TALLOC_CTX *mem_ctx, const struct security_ace *ace,
     587             :                              const struct dom_sid *domain_sid)
     588             : {
     589      426967 :         char *sddl = NULL;
     590             :         TALLOC_CTX *tmp_ctx;
     591             :         struct GUID_txt_buf object_buf, iobject_buf;
     592      426967 :         const char *sddl_type="", *sddl_flags="", *sddl_mask="",
     593      426967 :                 *sddl_object="", *sddl_iobject="", *sddl_trustee="";
     594             : 
     595      426967 :         tmp_ctx = talloc_new(mem_ctx);
     596      426967 :         if (tmp_ctx == NULL) {
     597           0 :                 DEBUG(0, ("talloc_new failed\n"));
     598           0 :                 return NULL;
     599             :         }
     600             : 
     601      426967 :         sddl_type = sddl_flags_to_string(tmp_ctx, ace_types, ace->type, true);
     602      426967 :         if (sddl_type == NULL) {
     603           0 :                 goto failed;
     604             :         }
     605             : 
     606      426967 :         sddl_flags = sddl_flags_to_string(tmp_ctx, ace_flags, ace->flags,
     607             :                                           true);
     608      426967 :         if (sddl_flags == NULL) {
     609           0 :                 goto failed;
     610             :         }
     611             : 
     612      426967 :         sddl_mask = sddl_flags_to_string(tmp_ctx, ace_access_mask,
     613       12326 :                                          ace->access_mask, true);
     614      426967 :         if (sddl_mask == NULL) {
     615        4619 :                 sddl_mask = talloc_asprintf(tmp_ctx, "0x%08x",
     616         238 :                                              ace->access_mask);
     617        4619 :                 if (sddl_mask == NULL) {
     618           0 :                         goto failed;
     619             :                 }
     620             :         }
     621             : 
     622      736874 :         if (ace->type == SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT ||
     623      624880 :             ace->type == SEC_ACE_TYPE_ACCESS_DENIED_OBJECT ||
     624      613685 :             ace->type == SEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT ||
     625      303090 :             ace->type == SEC_ACE_TYPE_SYSTEM_ALARM_OBJECT) {
     626      123877 :                 const struct security_ace_object *object = &ace->object.object;
     627             : 
     628      123877 :                 if (ace->object.object.flags & SEC_ACE_OBJECT_TYPE_PRESENT) {
     629      108073 :                         sddl_object = GUID_buf_string(
     630             :                                 &object->type.type, &object_buf);
     631             :                 }
     632             : 
     633      123877 :                 if (ace->object.object.flags &
     634             :                     SEC_ACE_INHERITED_OBJECT_TYPE_PRESENT) {
     635       95305 :                         sddl_iobject = GUID_buf_string(
     636             :                                 &object->inherited_type.inherited_type,
     637             :                                 &iobject_buf);
     638             :                 }
     639             :         }
     640             : 
     641      426967 :         sddl_trustee = sddl_encode_sid(tmp_ctx, &ace->trustee, domain_sid);
     642      426967 :         if (sddl_trustee == NULL) {
     643           0 :                 goto failed;
     644             :         }
     645             : 
     646      426967 :         sddl = talloc_asprintf(mem_ctx, "%s;%s;%s;%s;%s;%s",
     647             :                                sddl_type, sddl_flags, sddl_mask, sddl_object,
     648             :                                sddl_iobject, sddl_trustee);
     649             : 
     650      426967 : failed:
     651      426967 :         talloc_free(tmp_ctx);
     652      426967 :         return sddl;
     653             : }
     654             : 
     655             : /*
     656             :   encode an ACL in SDDL format
     657             : */
     658       96538 : static char *sddl_encode_acl(TALLOC_CTX *mem_ctx, const struct security_acl *acl,
     659             :                              uint32_t flags, const struct dom_sid *domain_sid)
     660             : {
     661             :         char *sddl;
     662             :         uint32_t i;
     663             : 
     664             :         /* add any ACL flags */
     665       96538 :         sddl = sddl_flags_to_string(mem_ctx, acl_flags, flags, false);
     666       96538 :         if (sddl == NULL) goto failed;
     667             : 
     668             :         /* now the ACEs, encoded in braces */
     669      523505 :         for (i=0;i<acl->num_aces;i++) {
     670      426967 :                 char *ace = sddl_encode_ace(sddl, &acl->aces[i], domain_sid);
     671      426967 :                 if (ace == NULL) goto failed;
     672      426967 :                 sddl = talloc_asprintf_append_buffer(sddl, "(%s)", ace);
     673      426967 :                 if (sddl == NULL) goto failed;
     674      426967 :                 talloc_free(ace);
     675             :         }
     676             : 
     677       96538 :         return sddl;
     678             : 
     679           0 : failed:
     680           0 :         talloc_free(sddl);
     681           0 :         return NULL;
     682             : }
     683             : 
     684             : 
     685             : /*
     686             :   encode a security descriptor to SDDL format
     687             : */
     688       72052 : char *sddl_encode(TALLOC_CTX *mem_ctx, const struct security_descriptor *sd,
     689             :                   const struct dom_sid *domain_sid)
     690             : {
     691             :         char *sddl;
     692             :         TALLOC_CTX *tmp_ctx;
     693             : 
     694             :         /* start with a blank string */
     695       72052 :         sddl = talloc_strdup(mem_ctx, "");
     696       72052 :         if (sddl == NULL) goto failed;
     697             : 
     698       72052 :         tmp_ctx = talloc_new(mem_ctx);
     699             : 
     700       72052 :         if (sd->owner_sid != NULL) {
     701       71825 :                 char *sid = sddl_encode_sid(tmp_ctx, sd->owner_sid, domain_sid);
     702       71825 :                 if (sid == NULL) goto failed;
     703       71825 :                 sddl = talloc_asprintf_append_buffer(sddl, "O:%s", sid);
     704       71825 :                 if (sddl == NULL) goto failed;
     705             :         }
     706             : 
     707       72052 :         if (sd->group_sid != NULL) {
     708       71825 :                 char *sid = sddl_encode_sid(tmp_ctx, sd->group_sid, domain_sid);
     709       71825 :                 if (sid == NULL) goto failed;
     710       71825 :                 sddl = talloc_asprintf_append_buffer(sddl, "G:%s", sid);
     711       71825 :                 if (sddl == NULL) goto failed;
     712             :         }
     713             : 
     714       72052 :         if ((sd->type & SEC_DESC_DACL_PRESENT) && sd->dacl != NULL) {
     715       65741 :                 char *acl = sddl_encode_acl(tmp_ctx, sd->dacl, sd->type, domain_sid);
     716       65741 :                 if (acl == NULL) goto failed;
     717       65741 :                 sddl = talloc_asprintf_append_buffer(sddl, "D:%s", acl);
     718       65741 :                 if (sddl == NULL) goto failed;
     719             :         }
     720             : 
     721       72052 :         if ((sd->type & SEC_DESC_SACL_PRESENT) && sd->sacl != NULL) {
     722       30797 :                 char *acl = sddl_encode_acl(tmp_ctx, sd->sacl, sd->type>>1, domain_sid);
     723       30797 :                 if (acl == NULL) goto failed;
     724       30797 :                 sddl = talloc_asprintf_append_buffer(sddl, "S:%s", acl);
     725       30797 :                 if (sddl == NULL) goto failed;
     726             :         }
     727             : 
     728       72052 :         talloc_free(tmp_ctx);
     729       72052 :         return sddl;
     730             : 
     731           0 : failed:
     732           0 :         talloc_free(sddl);
     733           0 :         return NULL;
     734             : }
     735             : 
     736             : 

Generated by: LCOV version 1.13