LCOV - code coverage report
Current view: top level - source3/lib - util_sd.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 224 331 67.7 %
Date: 2024-04-21 15:09:00 Functions: 10 10 100.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    Security Descriptor (SD) helper functions
       4             : 
       5             :    Copyright (C) Andrew Tridgell 2000
       6             :    Copyright (C) Tim Potter      2000
       7             :    Copyright (C) Jeremy Allison  2000
       8             :    Copyright (C) Jelmer Vernooij 2003
       9             : 
      10             :    This program is free software; you can redistribute it and/or modify
      11             :    it under the terms of the GNU General Public License as published by
      12             :    the Free Software Foundation; either version 3 of the License, or
      13             :    (at your option) any later version.
      14             : 
      15             :    This program is distributed in the hope that it will be useful,
      16             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      17             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      18             :    GNU General Public License for more details.
      19             : 
      20             :    You should have received a copy of the GNU General Public License
      21             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      22             : */
      23             : 
      24             : #include "includes.h"
      25             : #include "libsmb/libsmb.h"
      26             : #include "util_sd.h"
      27             : #include "librpc/gen_ndr/ndr_lsa.h"
      28             : #include "../libcli/security/security.h"
      29             : #include "rpc_client/cli_pipe.h"
      30             : #include "rpc_client/cli_lsarpc.h"
      31             : #include "lib/util/string_wrappers.h"
      32             : 
      33             : /* These values discovered by inspection */
      34             : 
      35             : struct perm_value {
      36             :         const char *perm;
      37             :         uint32_t mask;
      38             : };
      39             : 
      40             : static const struct perm_value special_values[] = {
      41             :         { "R", SEC_RIGHTS_FILE_READ },
      42             :         { "W", SEC_RIGHTS_FILE_WRITE },
      43             :         { "X", SEC_RIGHTS_FILE_EXECUTE },
      44             :         { "D", SEC_STD_DELETE },
      45             :         { "P", SEC_STD_WRITE_DAC },
      46             :         { "O", SEC_STD_WRITE_OWNER },
      47             :         { NULL, 0 },
      48             : };
      49             : 
      50             : static const struct perm_value standard_values[] = {
      51             :         { "READ",   SEC_RIGHTS_DIR_READ|SEC_DIR_TRAVERSE },
      52             :         { "CHANGE", SEC_RIGHTS_DIR_READ|SEC_STD_DELETE|\
      53             :           SEC_DIR_DELETE_CHILD|\
      54             :           SEC_RIGHTS_DIR_WRITE|SEC_DIR_TRAVERSE },
      55             :         { "FULL",   SEC_RIGHTS_DIR_ALL },
      56             :         { NULL, 0 },
      57             : };
      58             : 
      59             : static const struct {
      60             :         uint16_t mask;
      61             :         const char *str;
      62             :         const char *desc;
      63             : } sec_desc_ctrl_bits[] = {
      64             :         {SEC_DESC_OWNER_DEFAULTED,       "OD", "Owner Defaulted"},
      65             :         {SEC_DESC_GROUP_DEFAULTED,       "GD", "Group Defaulted"},
      66             :         {SEC_DESC_DACL_PRESENT,          "DP", "DACL Present"},
      67             :         {SEC_DESC_DACL_DEFAULTED,        "DD", "DACL Defaulted"},
      68             :         {SEC_DESC_SACL_PRESENT,          "SP", "SACL Present"},
      69             :         {SEC_DESC_SACL_DEFAULTED,        "SD", "SACL Defaulted"},
      70             :         {SEC_DESC_DACL_TRUSTED,          "DT", "DACL Trusted"},
      71             :         {SEC_DESC_SERVER_SECURITY,       "SS", "Server Security"},
      72             :         {SEC_DESC_DACL_AUTO_INHERIT_REQ, "DR", "DACL Inheritance Required"},
      73             :         {SEC_DESC_SACL_AUTO_INHERIT_REQ, "SR", "SACL Inheritance Required"},
      74             :         {SEC_DESC_DACL_AUTO_INHERITED,   "DI", "DACL Auto Inherited"},
      75             :         {SEC_DESC_SACL_AUTO_INHERITED,   "SI", "SACL Auto Inherited"},
      76             :         {SEC_DESC_DACL_PROTECTED,        "PD", "DACL Protected"},
      77             :         {SEC_DESC_SACL_PROTECTED,        "PS", "SACL Protected"},
      78             :         {SEC_DESC_RM_CONTROL_VALID,      "RM", "RM Control Valid"},
      79             :         {SEC_DESC_SELF_RELATIVE ,        "SR", "Self Relative"},
      80             : };
      81             : 
      82             : /* Open cli connection and policy handle */
      83        5742 : static NTSTATUS cli_lsa_lookup_sid(struct cli_state *cli,
      84             :                                    const struct dom_sid *sid,
      85             :                                    TALLOC_CTX *mem_ctx,
      86             :                                    enum lsa_SidType *type,
      87             :                                    char **domain, char **name)
      88             : {
      89        5742 :         struct smbXcli_tcon *orig_tcon = NULL;
      90        5742 :         char *orig_share = NULL;
      91        5742 :         struct rpc_pipe_client *p = NULL;
      92           0 :         struct policy_handle handle;
      93           0 :         NTSTATUS status;
      94        5742 :         TALLOC_CTX *frame = talloc_stackframe();
      95           0 :         enum lsa_SidType *types;
      96           0 :         char **domains;
      97           0 :         char **names;
      98             : 
      99        5742 :         if (cli_state_has_tcon(cli)) {
     100        5742 :                 cli_state_save_tcon_share(cli, &orig_tcon, &orig_share);
     101             :         }
     102             : 
     103        5742 :         status = cli_tree_connect(cli, "IPC$", "?????", NULL);
     104        5742 :         if (!NT_STATUS_IS_OK(status)) {
     105           0 :                 goto tcon_fail;
     106             :         }
     107             : 
     108        5742 :         status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc,
     109             :                                           &p);
     110        5742 :         if (!NT_STATUS_IS_OK(status)) {
     111           0 :                 goto fail;
     112             :         }
     113             : 
     114        5742 :         status = rpccli_lsa_open_policy(p, talloc_tos(), True,
     115             :                                         GENERIC_EXECUTE_ACCESS, &handle);
     116        5742 :         if (!NT_STATUS_IS_OK(status)) {
     117           0 :                 goto fail;
     118             :         }
     119             : 
     120        5742 :         status = rpccli_lsa_lookup_sids(p, talloc_tos(), &handle, 1, sid,
     121             :                                         &domains, &names, &types);
     122        5742 :         if (!NT_STATUS_IS_OK(status)) {
     123           0 :                 goto fail;
     124             :         }
     125             : 
     126        5742 :         *type = types[0];
     127        5742 :         *domain = talloc_move(mem_ctx, &domains[0]);
     128        5742 :         *name = talloc_move(mem_ctx, &names[0]);
     129             : 
     130        5742 :         status = NT_STATUS_OK;
     131        5742 :  fail:
     132        5742 :         TALLOC_FREE(p);
     133        5742 :         cli_tdis(cli);
     134        5742 :  tcon_fail:
     135        5742 :         cli_state_restore_tcon_share(cli, orig_tcon, orig_share);
     136        5742 :         TALLOC_FREE(frame);
     137        5742 :         return status;
     138             : }
     139             : 
     140             : /* convert a SID to a string, either numeric or username/group */
     141        5864 : void SidToString(struct cli_state *cli, fstring str, const struct dom_sid *sid,
     142             :                  bool numeric)
     143             : {
     144        5864 :         char *domain = NULL;
     145        5864 :         char *name = NULL;
     146           0 :         enum lsa_SidType type;
     147           0 :         NTSTATUS status;
     148             : 
     149        5864 :         sid_to_fstring(str, sid);
     150             : 
     151        5864 :         if (numeric || cli == NULL) {
     152         122 :                 return;
     153             :         }
     154             : 
     155        5742 :         status = cli_lsa_lookup_sid(cli, sid, talloc_tos(), &type,
     156             :                                     &domain, &name);
     157             : 
     158        5742 :         if (!NT_STATUS_IS_OK(status)) {
     159           0 :                 return;
     160             :         }
     161             : 
     162        5742 :         if (*domain) {
     163        2600 :                 slprintf(str, sizeof(fstring) - 1, "%s%s%s",
     164             :                         domain, lp_winbind_separator(), name);
     165             :         } else {
     166        3142 :                 fstrcpy(str, name);
     167             :         }
     168             : }
     169             : 
     170        1434 : static NTSTATUS cli_lsa_lookup_name(struct cli_state *cli,
     171             :                                     const char *name,
     172             :                                     enum lsa_SidType *type,
     173             :                                     struct dom_sid *sid)
     174             : {
     175        1434 :         struct smbXcli_tcon *orig_tcon = NULL;
     176        1434 :         char *orig_share = NULL;
     177        1434 :         struct rpc_pipe_client *p = NULL;
     178           0 :         struct policy_handle handle;
     179           0 :         NTSTATUS status;
     180        1434 :         TALLOC_CTX *frame = talloc_stackframe();
     181           0 :         struct dom_sid *sids;
     182           0 :         enum lsa_SidType *types;
     183             : 
     184        1434 :         if (cli_state_has_tcon(cli)) {
     185        1434 :                 cli_state_save_tcon_share(cli, &orig_tcon, &orig_share);
     186             :         }
     187             : 
     188        1434 :         status = cli_tree_connect(cli, "IPC$", "?????", NULL);
     189        1434 :         if (!NT_STATUS_IS_OK(status)) {
     190           0 :                 goto tcon_fail;
     191             :         }
     192             : 
     193        1434 :         status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc,
     194             :                                           &p);
     195        1434 :         if (!NT_STATUS_IS_OK(status)) {
     196           0 :                 goto fail;
     197             :         }
     198             : 
     199        1434 :         status = rpccli_lsa_open_policy(p, talloc_tos(), True,
     200             :                                         GENERIC_EXECUTE_ACCESS, &handle);
     201        1434 :         if (!NT_STATUS_IS_OK(status)) {
     202           0 :                 goto fail;
     203             :         }
     204             : 
     205        1434 :         status = rpccli_lsa_lookup_names(p, talloc_tos(), &handle, 1, &name,
     206             :                                          NULL, 1, &sids, &types);
     207        1434 :         if (!NT_STATUS_IS_OK(status)) {
     208           0 :                 goto fail;
     209             :         }
     210             : 
     211        1434 :         *type = types[0];
     212        1434 :         *sid = sids[0];
     213             : 
     214        1434 :         status = NT_STATUS_OK;
     215        1434 :  fail:
     216        1434 :         TALLOC_FREE(p);
     217        1434 :         cli_tdis(cli);
     218        1434 :  tcon_fail:
     219        1434 :         cli_state_restore_tcon_share(cli, orig_tcon, orig_share);
     220        1434 :         TALLOC_FREE(frame);
     221        1434 :         return status;
     222             : }
     223             : 
     224             : /* convert a string to a SID, either numeric or username/group */
     225        1458 : bool StringToSid(struct cli_state *cli, struct dom_sid *sid, const char *str)
     226             : {
     227           0 :         enum lsa_SidType type;
     228             : 
     229        1458 :         if (string_to_sid(sid, str)) {
     230          24 :                 return true;
     231             :         }
     232             : 
     233        1434 :         if (cli == NULL) {
     234           0 :                 return false;
     235             :         }
     236             : 
     237        1434 :         return NT_STATUS_IS_OK(cli_lsa_lookup_name(cli, str, &type, sid));
     238             : }
     239             : 
     240        4588 : static void print_ace_flags(FILE *f, uint8_t flags)
     241             : {
     242        4588 :         char *str = talloc_strdup(NULL, "");
     243           0 :         size_t len;
     244             : 
     245        4588 :         if (flags & SEC_ACE_FLAG_OBJECT_INHERIT) {
     246        1824 :                 talloc_asprintf_addbuf(&str, "OI|");
     247             :         }
     248        4588 :         if (flags & SEC_ACE_FLAG_CONTAINER_INHERIT) {
     249        1848 :                 talloc_asprintf_addbuf(&str, "CI|");
     250             :         }
     251        4588 :         if (flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) {
     252          18 :                 talloc_asprintf_addbuf(&str, "NP|");
     253             :         }
     254        4588 :         if (flags & SEC_ACE_FLAG_INHERIT_ONLY) {
     255        1044 :                 talloc_asprintf_addbuf(&str, "IO|");
     256             :         }
     257        4588 :         if (flags & SEC_ACE_FLAG_INHERITED_ACE) {
     258        2562 :                 talloc_asprintf_addbuf(&str, "I|");
     259             :         }
     260        4588 :         if (str == NULL) {
     261           0 :                 goto out;
     262             :         }
     263             : 
     264             :         /* Ignore define SEC_ACE_FLAG_SUCCESSFUL_ACCESS ( 0x40 )
     265             :            and SEC_ACE_FLAG_FAILED_ACCESS ( 0x80 ) as they're
     266             :            audit ace flags. */
     267             : 
     268        4588 :         len = strlen(str);
     269        4588 :         if (len > 0) {
     270        3498 :                 fprintf(f, "/%.*s/", (int)len-1, str);
     271             :         } else {
     272        1090 :                 fprintf(f, "/0x%x/", flags);
     273             :         }
     274        4588 :         TALLOC_FREE(str);
     275        4588 :         return;
     276             : 
     277           0 :   out:
     278           0 :         fprintf(f, "/0x%x/", flags);
     279             : }
     280             : 
     281             : /* print an ACE on a FILE, using either numeric or ascii representation */
     282        4588 : void print_ace(struct cli_state *cli, FILE *f, struct security_ace *ace,
     283             :                bool numeric)
     284             : {
     285           0 :         const struct perm_value *v;
     286           0 :         fstring sidstr;
     287        4588 :         int do_print = 0;
     288           0 :         uint32_t got_mask;
     289             : 
     290        4588 :         SidToString(cli, sidstr, &ace->trustee, numeric);
     291             : 
     292        4588 :         fprintf(f, "%s:", sidstr);
     293             : 
     294        4588 :         if (numeric) {
     295           0 :                 fprintf(f, "%d/0x%x/0x%08x",
     296           0 :                         ace->type, ace->flags, ace->access_mask);
     297        4480 :                 return;
     298             :         }
     299             : 
     300             :         /* Ace type */
     301             : 
     302        4588 :         if (ace->type == SEC_ACE_TYPE_ACCESS_ALLOWED) {
     303        4556 :                 fprintf(f, "ALLOWED");
     304          32 :         } else if (ace->type == SEC_ACE_TYPE_ACCESS_DENIED) {
     305          32 :                 fprintf(f, "DENIED");
     306             :         } else {
     307           0 :                 fprintf(f, "%d", ace->type);
     308             :         }
     309             : 
     310        4588 :         print_ace_flags(f, ace->flags);
     311             : 
     312             :         /* Standard permissions */
     313             : 
     314        8042 :         for (v = standard_values; v->perm; v++) {
     315        7934 :                 if (ace->access_mask == v->mask) {
     316        4480 :                         fprintf(f, "%s", v->perm);
     317        4480 :                         return;
     318             :                 }
     319             :         }
     320             : 
     321             :         /* Special permissions.  Print out a hex value if we have
     322             :            leftover bits in the mask. */
     323             : 
     324         108 :         got_mask = ace->access_mask;
     325             : 
     326         212 :  again:
     327        1484 :         for (v = special_values; v->perm; v++) {
     328        1272 :                 if ((ace->access_mask & v->mask) == v->mask) {
     329         652 :                         if (do_print) {
     330         324 :                                 fprintf(f, "%s", v->perm);
     331             :                         }
     332         652 :                         got_mask &= ~v->mask;
     333             :                 }
     334             :         }
     335             : 
     336         212 :         if (!do_print) {
     337         108 :                 if (got_mask != 0) {
     338           4 :                         fprintf(f, "0x%08x", ace->access_mask);
     339             :                 } else {
     340         104 :                         do_print = 1;
     341         104 :                         goto again;
     342             :                 }
     343             :         }
     344             : }
     345             : 
     346        1230 : static bool parse_ace_flags(const char *str, unsigned int *pflags)
     347             : {
     348        1230 :         const char *p = str;
     349        1230 :         *pflags = 0;
     350             : 
     351        3582 :         while (*p) {
     352        2352 :                 if (strnequal(p, "OI", 2)) {
     353         666 :                         *pflags |= SEC_ACE_FLAG_OBJECT_INHERIT;
     354         666 :                         p += 2;
     355        1686 :                 } else if (strnequal(p, "CI", 2)) {
     356         690 :                         *pflags |= SEC_ACE_FLAG_CONTAINER_INHERIT;
     357         690 :                         p += 2;
     358         996 :                 } else if (strnequal(p, "NP", 2)) {
     359          54 :                         *pflags |= SEC_ACE_FLAG_NO_PROPAGATE_INHERIT;
     360          54 :                         p += 2;
     361         942 :                 } else if (strnequal(p, "IO", 2)) {
     362          12 :                         *pflags |= SEC_ACE_FLAG_INHERIT_ONLY;
     363          12 :                         p += 2;
     364         930 :                 } else if (*p == 'I') {
     365         930 :                         *pflags |= SEC_ACE_FLAG_INHERITED_ACE;
     366         930 :                         p += 1;
     367           0 :                 } else if (*p) {
     368           0 :                         return false;
     369             :                 }
     370             : 
     371        2352 :                 switch (*p) {
     372        1122 :                 case '|':
     373        1122 :                         p++;
     374             : 
     375           0 :                         FALL_THROUGH;
     376        2352 :                 case '\0':
     377        2352 :                         continue;
     378           0 :                 default:
     379           0 :                         return false;
     380             :                 }
     381             :         }
     382        1230 :         return true;
     383             : }
     384             : 
     385             : /* parse an ACE in the same format as print_ace() */
     386        1394 : bool parse_ace(struct cli_state *cli, struct security_ace *ace,
     387             :                const char *orig_str)
     388             : {
     389           0 :         char *p;
     390           0 :         const char *cp;
     391           0 :         char *tok;
     392        1394 :         unsigned int atype = 0;
     393        1394 :         unsigned int aflags = 0;
     394        1394 :         unsigned int amask = 0;
     395           0 :         struct dom_sid sid;
     396           0 :         uint32_t mask;
     397           0 :         const struct perm_value *v;
     398        1394 :         char *str = SMB_STRDUP(orig_str);
     399        1394 :         TALLOC_CTX *frame = talloc_stackframe();
     400             : 
     401        1394 :         if (!str) {
     402           0 :                 TALLOC_FREE(frame);
     403           0 :                 return False;
     404             :         }
     405             : 
     406        1394 :         ZERO_STRUCTP(ace);
     407        1394 :         p = strchr_m(str,':');
     408        1394 :         if (!p) {
     409           0 :                 printf("ACE '%s': missing ':'.\n", orig_str);
     410           0 :                 SAFE_FREE(str);
     411           0 :                 TALLOC_FREE(frame);
     412           0 :                 return False;
     413             :         }
     414        1394 :         *p = '\0';
     415        1394 :         p++;
     416             : 
     417        1394 :         if (!StringToSid(cli, &sid, str)) {
     418           0 :                 printf("ACE '%s': failed to convert '%s' to SID\n",
     419             :                         orig_str, str);
     420           0 :                 SAFE_FREE(str);
     421           0 :                 TALLOC_FREE(frame);
     422           0 :                 return False;
     423             :         }
     424             : 
     425        1394 :         cp = p;
     426        1394 :         if (!next_token_talloc(frame, &cp, &tok, "/")) {
     427           0 :                 printf("ACE '%s': failed to find '/' character.\n",
     428             :                         orig_str);
     429           0 :                 SAFE_FREE(str);
     430           0 :                 TALLOC_FREE(frame);
     431           0 :                 return False;
     432             :         }
     433             : 
     434        1394 :         if (strncmp(tok, "ALLOWED", strlen("ALLOWED")) == 0) {
     435        1380 :                 atype = SEC_ACE_TYPE_ACCESS_ALLOWED;
     436          14 :         } else if (strncmp(tok, "DENIED", strlen("DENIED")) == 0) {
     437          10 :                 atype = SEC_ACE_TYPE_ACCESS_DENIED;
     438             : 
     439           4 :         } else if (strnequal(tok, "0x", 2)) {
     440           0 :                 int result;
     441             : 
     442           2 :                 result = sscanf(tok, "%x", &atype);
     443           2 :                 if (result == 0 ||
     444           2 :                     (atype != SEC_ACE_TYPE_ACCESS_ALLOWED &&
     445           2 :                      atype != SEC_ACE_TYPE_ACCESS_DENIED)) {
     446           0 :                         printf("ACE '%s': bad hex value for type at '%s'\n",
     447             :                                orig_str, tok);
     448           0 :                         SAFE_FREE(str);
     449           0 :                         TALLOC_FREE(frame);
     450           0 :                         return false;
     451             :                 }
     452           4 :         } else if(tok[0] >= '0' && tok[0] <= '9') {
     453           0 :                 int result;
     454             : 
     455           2 :                 result = sscanf(tok, "%u", &atype);
     456           2 :                 if (result == 0 ||
     457           2 :                     (atype != SEC_ACE_TYPE_ACCESS_ALLOWED &&
     458           2 :                      atype != SEC_ACE_TYPE_ACCESS_DENIED)) {
     459           0 :                         printf("ACE '%s': bad integer value for type at '%s'\n",
     460             :                                orig_str, tok);
     461           0 :                         SAFE_FREE(str);
     462           0 :                         TALLOC_FREE(frame);
     463           0 :                         return false;
     464             :                 }
     465             :         } else {
     466           0 :                 printf("ACE '%s': missing 'ALLOWED' or 'DENIED' entry at '%s'\n",
     467             :                         orig_str, tok);
     468           0 :                 SAFE_FREE(str);
     469           0 :                 TALLOC_FREE(frame);
     470           0 :                 return False;
     471             :         }
     472             : 
     473        1394 :         if (!next_token_talloc(frame, &cp, &tok, "/")) {
     474           0 :                 printf("ACE '%s': bad flags entry at '%s'\n",
     475             :                         orig_str, tok);
     476           0 :                 SAFE_FREE(str);
     477           0 :                 TALLOC_FREE(frame);
     478           0 :                 return False;
     479             :         }
     480             : 
     481        1394 :         if (tok[0] < '0' || tok[0] > '9') {
     482        1230 :                 if (!parse_ace_flags(tok, &aflags)) {
     483           0 :                         printf("ACE '%s': bad named flags entry at '%s'\n",
     484             :                                 orig_str, tok);
     485           0 :                         SAFE_FREE(str);
     486           0 :                         TALLOC_FREE(frame);
     487           0 :                         return False;
     488             :                 }
     489         164 :         } else if (strnequal(tok, "0x", 2)) {
     490         162 :                 if (!sscanf(tok, "%x", &aflags)) {
     491           0 :                         printf("ACE '%s': bad hex flags entry at '%s'\n",
     492             :                                 orig_str, tok);
     493           0 :                         SAFE_FREE(str);
     494           0 :                         TALLOC_FREE(frame);
     495           0 :                         return False;
     496             :                 }
     497             :         } else {
     498           2 :                 if (!sscanf(tok, "%u", &aflags)) {
     499           0 :                         printf("ACE '%s': bad integer flags entry at '%s'\n",
     500             :                                 orig_str, tok);
     501           0 :                         SAFE_FREE(str);
     502           0 :                         TALLOC_FREE(frame);
     503           0 :                         return False;
     504             :                 }
     505             :         }
     506             : 
     507        1394 :         if (!next_token_talloc(frame, &cp, &tok, "/")) {
     508           0 :                 printf("ACE '%s': missing / at '%s'\n",
     509             :                         orig_str, tok);
     510           0 :                 SAFE_FREE(str);
     511           0 :                 TALLOC_FREE(frame);
     512           0 :                 return False;
     513             :         }
     514             : 
     515        1394 :         if (strncmp(tok, "0x", 2) == 0) {
     516          12 :                 if (sscanf(tok, "%x", &amask) != 1) {
     517           0 :                         printf("ACE '%s': bad hex number at '%s'\n",
     518             :                                 orig_str, tok);
     519           0 :                         SAFE_FREE(str);
     520           0 :                         TALLOC_FREE(frame);
     521           0 :                         return False;
     522             :                 }
     523          12 :                 goto done;
     524             :         }
     525             : 
     526        3814 :         for (v = standard_values; v->perm; v++) {
     527        3684 :                 if (strcmp(tok, v->perm) == 0) {
     528        1252 :                         amask = v->mask;
     529        1252 :                         goto done;
     530             :                 }
     531             :         }
     532             : 
     533         130 :         p = tok;
     534             : 
     535         444 :         while(*p) {
     536         314 :                 bool found = False;
     537             : 
     538        2198 :                 for (v = special_values; v->perm; v++) {
     539        1884 :                         if (v->perm[0] == *p) {
     540         314 :                                 amask |= v->mask;
     541         314 :                                 found = True;
     542             :                         }
     543             :                 }
     544             : 
     545         314 :                 if (!found) {
     546           0 :                         printf("ACE '%s': bad permission value at '%s'\n",
     547             :                                 orig_str, p);
     548           0 :                         SAFE_FREE(str);
     549           0 :                         TALLOC_FREE(frame);
     550           0 :                         return False;
     551             :                 }
     552         314 :                 p++;
     553             :         }
     554             : 
     555         130 :         if (*p) {
     556           0 :                 TALLOC_FREE(frame);
     557           0 :                 SAFE_FREE(str);
     558           0 :                 return False;
     559             :         }
     560             : 
     561         130 :  done:
     562        1394 :         mask = amask;
     563        1394 :         init_sec_ace(ace, &sid, atype, mask, aflags);
     564        1394 :         TALLOC_FREE(frame);
     565        1394 :         SAFE_FREE(str);
     566        1394 :         return True;
     567             : }
     568             : 
     569         692 : static void print_acl_ctrl(FILE *file, uint16_t ctrl, bool numeric)
     570             : {
     571           0 :         int i;
     572         692 :         const char* separator = "";
     573             : 
     574         692 :         fprintf(file, "CONTROL:");
     575         692 :         if (numeric) {
     576           0 :                 fprintf(file, "0x%x\n", ctrl);
     577           0 :                 return;
     578             :         }
     579             : 
     580       11764 :         for (i = ARRAY_SIZE(sec_desc_ctrl_bits) - 1; i >= 0; i--) {
     581       11072 :                 if (ctrl & sec_desc_ctrl_bits[i].mask) {
     582        1390 :                         fprintf(file, "%s%s",
     583        1390 :                                 separator, sec_desc_ctrl_bits[i].str);
     584        1390 :                         separator = "|";
     585             :                 }
     586             :         }
     587         692 :         fputc('\n', file);
     588             : }
     589             : 
     590             : /* print a ascii version of a security descriptor on a FILE handle */
     591         692 : void sec_desc_print(struct cli_state *cli, FILE *f,
     592             :                     struct security_descriptor *sd, bool numeric)
     593             : {
     594           0 :         fstring sidstr;
     595           0 :         uint32_t i;
     596             : 
     597         692 :         fprintf(f, "REVISION:%d\n", sd->revision);
     598         692 :         print_acl_ctrl(f, sd->type, numeric);
     599             : 
     600             :         /* Print owner and group sid */
     601             : 
     602         692 :         if (sd->owner_sid) {
     603         638 :                 SidToString(cli, sidstr, sd->owner_sid, numeric);
     604             :         } else {
     605          54 :                 fstrcpy(sidstr, "");
     606             :         }
     607             : 
     608         692 :         fprintf(f, "OWNER:%s\n", sidstr);
     609             : 
     610         692 :         if (sd->group_sid) {
     611         638 :                 SidToString(cli, sidstr, sd->group_sid, numeric);
     612             :         } else {
     613          54 :                 fstrcpy(sidstr, "");
     614             :         }
     615             : 
     616         692 :         fprintf(f, "GROUP:%s\n", sidstr);
     617             : 
     618             :         /* Print aces */
     619        5254 :         for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
     620        4562 :                 struct security_ace *ace = &sd->dacl->aces[i];
     621        4562 :                 fprintf(f, "ACL:");
     622        4562 :                 print_ace(cli, f, ace, numeric);
     623        4562 :                 fprintf(f, "\n");
     624             :         }
     625             : 
     626         692 : }

Generated by: LCOV version 1.14