LCOV - code coverage report
Current view: top level - source3/lib - util_sd.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 226 317 71.3 %
Date: 2021-09-23 10:06:22 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_RIGHTS_DIR_WRITE|SEC_DIR_TRAVERSE },
      54             :         { "FULL",   SEC_RIGHTS_DIR_ALL },
      55             :         { NULL, 0 },
      56             : };
      57             : 
      58             : static const struct {
      59             :         uint16_t mask;
      60             :         const char *str;
      61             :         const char *desc;
      62             : } sec_desc_ctrl_bits[] = {
      63             :         {SEC_DESC_OWNER_DEFAULTED,       "OD", "Owner Defaulted"},
      64             :         {SEC_DESC_GROUP_DEFAULTED,       "GD", "Group Defaulted"},
      65             :         {SEC_DESC_DACL_PRESENT,          "DP", "DACL Present"},
      66             :         {SEC_DESC_DACL_DEFAULTED,        "DD", "DACL Defaulted"},
      67             :         {SEC_DESC_SACL_PRESENT,          "SP", "SACL Present"},
      68             :         {SEC_DESC_SACL_DEFAULTED,        "SD", "SACL Defaulted"},
      69             :         {SEC_DESC_DACL_TRUSTED,          "DT", "DACL Trusted"},
      70             :         {SEC_DESC_SERVER_SECURITY,       "SS", "Server Security"},
      71             :         {SEC_DESC_DACL_AUTO_INHERIT_REQ, "DR", "DACL Inheritance Required"},
      72             :         {SEC_DESC_SACL_AUTO_INHERIT_REQ, "SR", "SACL Inheritance Required"},
      73             :         {SEC_DESC_DACL_AUTO_INHERITED,   "DI", "DACL Auto Inherited"},
      74             :         {SEC_DESC_SACL_AUTO_INHERITED,   "SI", "SACL Auto Inherited"},
      75             :         {SEC_DESC_DACL_PROTECTED,        "PD", "DACL Protected"},
      76             :         {SEC_DESC_SACL_PROTECTED,        "PS", "SACL Protected"},
      77             :         {SEC_DESC_RM_CONTROL_VALID,      "RM", "RM Control Valid"},
      78             :         {SEC_DESC_SELF_RELATIVE ,        "SR", "Self Relative"},
      79             : };
      80             : 
      81             : /* Open cli connection and policy handle */
      82        5714 : static NTSTATUS cli_lsa_lookup_sid(struct cli_state *cli,
      83             :                                    const struct dom_sid *sid,
      84             :                                    TALLOC_CTX *mem_ctx,
      85             :                                    enum lsa_SidType *type,
      86             :                                    char **domain, char **name)
      87             : {
      88        5714 :         struct smbXcli_tcon *orig_tcon = NULL;
      89        5714 :         struct rpc_pipe_client *p = NULL;
      90             :         struct policy_handle handle;
      91             :         NTSTATUS status;
      92        5714 :         TALLOC_CTX *frame = talloc_stackframe();
      93             :         enum lsa_SidType *types;
      94             :         char **domains;
      95             :         char **names;
      96             : 
      97        5714 :         if (cli_state_has_tcon(cli)) {
      98        5714 :                 orig_tcon = cli_state_save_tcon(cli);
      99        5714 :                 if (orig_tcon == NULL) {
     100           0 :                         status = NT_STATUS_NO_MEMORY;
     101           0 :                         goto tcon_fail;
     102             :                 }
     103             :         }
     104             : 
     105        5714 :         status = cli_tree_connect(cli, "IPC$", "?????", NULL);
     106        5714 :         if (!NT_STATUS_IS_OK(status)) {
     107           0 :                 goto tcon_fail;
     108             :         }
     109             : 
     110        5714 :         status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc,
     111             :                                           &p);
     112        5714 :         if (!NT_STATUS_IS_OK(status)) {
     113           0 :                 goto fail;
     114             :         }
     115             : 
     116        5714 :         status = rpccli_lsa_open_policy(p, talloc_tos(), True,
     117             :                                         GENERIC_EXECUTE_ACCESS, &handle);
     118        5714 :         if (!NT_STATUS_IS_OK(status)) {
     119           0 :                 goto fail;
     120             :         }
     121             : 
     122        5714 :         status = rpccli_lsa_lookup_sids(p, talloc_tos(), &handle, 1, sid,
     123             :                                         &domains, &names, &types);
     124        5714 :         if (!NT_STATUS_IS_OK(status)) {
     125           0 :                 goto fail;
     126             :         }
     127             : 
     128        5714 :         *type = types[0];
     129        5714 :         *domain = talloc_move(mem_ctx, &domains[0]);
     130        5714 :         *name = talloc_move(mem_ctx, &names[0]);
     131             : 
     132        5714 :         status = NT_STATUS_OK;
     133        5714 :  fail:
     134        5714 :         TALLOC_FREE(p);
     135        5714 :         cli_tdis(cli);
     136        5714 :  tcon_fail:
     137        5714 :         cli_state_restore_tcon(cli, orig_tcon);
     138        5714 :         TALLOC_FREE(frame);
     139        5714 :         return status;
     140             : }
     141             : 
     142             : /* convert a SID to a string, either numeric or username/group */
     143        5836 : void SidToString(struct cli_state *cli, fstring str, const struct dom_sid *sid,
     144             :                  bool numeric)
     145             : {
     146        5836 :         char *domain = NULL;
     147        5836 :         char *name = NULL;
     148             :         enum lsa_SidType type;
     149             :         NTSTATUS status;
     150             : 
     151        5836 :         sid_to_fstring(str, sid);
     152             : 
     153        5836 :         if (numeric || cli == NULL) {
     154         244 :                 return;
     155             :         }
     156             : 
     157        5714 :         status = cli_lsa_lookup_sid(cli, sid, talloc_tos(), &type,
     158             :                                     &domain, &name);
     159             : 
     160        5714 :         if (!NT_STATUS_IS_OK(status)) {
     161           0 :                 return;
     162             :         }
     163             : 
     164        5714 :         if (*domain) {
     165        2580 :                 slprintf(str, sizeof(fstring) - 1, "%s%s%s",
     166             :                         domain, lp_winbind_separator(), name);
     167             :         } else {
     168        3134 :                 fstrcpy(str, name);
     169             :         }
     170             : }
     171             : 
     172        1304 : static NTSTATUS cli_lsa_lookup_name(struct cli_state *cli,
     173             :                                     const char *name,
     174             :                                     enum lsa_SidType *type,
     175             :                                     struct dom_sid *sid)
     176             : {
     177        1304 :         struct smbXcli_tcon *orig_tcon = NULL;
     178        1304 :         struct rpc_pipe_client *p = NULL;
     179             :         struct policy_handle handle;
     180             :         NTSTATUS status;
     181        1304 :         TALLOC_CTX *frame = talloc_stackframe();
     182             :         struct dom_sid *sids;
     183             :         enum lsa_SidType *types;
     184             : 
     185        1304 :         if (cli_state_has_tcon(cli)) {
     186        1304 :                 orig_tcon = cli_state_save_tcon(cli);
     187        1304 :                 if (orig_tcon == NULL) {
     188           0 :                         status = NT_STATUS_NO_MEMORY;
     189           0 :                         goto tcon_fail;
     190             :                 }
     191             :         }
     192             : 
     193        1304 :         status = cli_tree_connect(cli, "IPC$", "?????", NULL);
     194        1304 :         if (!NT_STATUS_IS_OK(status)) {
     195           0 :                 goto tcon_fail;
     196             :         }
     197             : 
     198        1304 :         status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc,
     199             :                                           &p);
     200        1304 :         if (!NT_STATUS_IS_OK(status)) {
     201           0 :                 goto fail;
     202             :         }
     203             : 
     204        1304 :         status = rpccli_lsa_open_policy(p, talloc_tos(), True,
     205             :                                         GENERIC_EXECUTE_ACCESS, &handle);
     206        1304 :         if (!NT_STATUS_IS_OK(status)) {
     207           0 :                 goto fail;
     208             :         }
     209             : 
     210        1304 :         status = rpccli_lsa_lookup_names(p, talloc_tos(), &handle, 1, &name,
     211             :                                          NULL, 1, &sids, &types);
     212        1304 :         if (!NT_STATUS_IS_OK(status)) {
     213           0 :                 goto fail;
     214             :         }
     215             : 
     216        1304 :         *type = types[0];
     217        1304 :         *sid = sids[0];
     218             : 
     219        1304 :         status = NT_STATUS_OK;
     220        1304 :  fail:
     221        1304 :         TALLOC_FREE(p);
     222        1304 :         cli_tdis(cli);
     223        1304 :  tcon_fail:
     224        1304 :         cli_state_restore_tcon(cli, orig_tcon);
     225        1304 :         TALLOC_FREE(frame);
     226        1304 :         return status;
     227             : }
     228             : 
     229             : /* convert a string to a SID, either numeric or username/group */
     230        1328 : bool StringToSid(struct cli_state *cli, struct dom_sid *sid, const char *str)
     231             : {
     232             :         enum lsa_SidType type;
     233             : 
     234        1328 :         if (string_to_sid(sid, str)) {
     235          24 :                 return true;
     236             :         }
     237             : 
     238        1304 :         if (cli == NULL) {
     239           0 :                 return false;
     240             :         }
     241             : 
     242        1304 :         return NT_STATUS_IS_OK(cli_lsa_lookup_name(cli, str, &type, sid));
     243             : }
     244             : 
     245        4568 : static void print_ace_flags(FILE *f, uint8_t flags)
     246             : {
     247        4568 :         char *str = talloc_strdup(NULL, "");
     248             : 
     249        4568 :         if (!str) {
     250           0 :                 goto out;
     251             :         }
     252             : 
     253        4568 :         if (flags & SEC_ACE_FLAG_OBJECT_INHERIT) {
     254        1824 :                 str = talloc_asprintf(str, "%s%s",
     255             :                                 str, "OI|");
     256        1824 :                 if (!str) {
     257           0 :                         goto out;
     258             :                 }
     259             :         }
     260        4568 :         if (flags & SEC_ACE_FLAG_CONTAINER_INHERIT) {
     261        1848 :                 str = talloc_asprintf(str, "%s%s",
     262             :                                 str, "CI|");
     263        1848 :                 if (!str) {
     264           0 :                         goto out;
     265             :                 }
     266             :         }
     267        4568 :         if (flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) {
     268          18 :                 str = talloc_asprintf(str, "%s%s",
     269             :                                 str, "NP|");
     270          18 :                 if (!str) {
     271           0 :                         goto out;
     272             :                 }
     273             :         }
     274        4568 :         if (flags & SEC_ACE_FLAG_INHERIT_ONLY) {
     275        1044 :                 str = talloc_asprintf(str, "%s%s",
     276             :                                 str, "IO|");
     277        1044 :                 if (!str) {
     278           0 :                         goto out;
     279             :                 }
     280             :         }
     281        4568 :         if (flags & SEC_ACE_FLAG_INHERITED_ACE) {
     282        2562 :                 str = talloc_asprintf(str, "%s%s",
     283             :                                 str, "I|");
     284        2562 :                 if (!str) {
     285           0 :                         goto out;
     286             :                 }
     287             :         }
     288             :         /* Ignore define SEC_ACE_FLAG_SUCCESSFUL_ACCESS ( 0x40 )
     289             :            and SEC_ACE_FLAG_FAILED_ACCESS ( 0x80 ) as they're
     290             :            audit ace flags. */
     291             : 
     292        4568 :         if (str[strlen(str)-1] == '|') {
     293        3498 :                 str[strlen(str)-1] = '\0';
     294        3498 :                 fprintf(f, "/%s/", str);
     295             :         } else {
     296        1070 :                 fprintf(f, "/0x%x/", flags);
     297             :         }
     298        4568 :         TALLOC_FREE(str);
     299        4568 :         return;
     300             : 
     301           0 :   out:
     302           0 :         fprintf(f, "/0x%x/", flags);
     303             : }
     304             : 
     305             : /* print an ACE on a FILE, using either numeric or ascii representation */
     306        4568 : void print_ace(struct cli_state *cli, FILE *f, struct security_ace *ace,
     307             :                bool numeric)
     308             : {
     309             :         const struct perm_value *v;
     310             :         fstring sidstr;
     311        4568 :         int do_print = 0;
     312             :         uint32_t got_mask;
     313             : 
     314        4568 :         SidToString(cli, sidstr, &ace->trustee, numeric);
     315             : 
     316        4568 :         fprintf(f, "%s:", sidstr);
     317             : 
     318        4568 :         if (numeric) {
     319           0 :                 fprintf(f, "%d/0x%x/0x%08x",
     320           0 :                         ace->type, ace->flags, ace->access_mask);
     321           0 :                 return;
     322             :         }
     323             : 
     324             :         /* Ace type */
     325             : 
     326        4568 :         if (ace->type == SEC_ACE_TYPE_ACCESS_ALLOWED) {
     327        4536 :                 fprintf(f, "ALLOWED");
     328          32 :         } else if (ace->type == SEC_ACE_TYPE_ACCESS_DENIED) {
     329          32 :                 fprintf(f, "DENIED");
     330             :         } else {
     331           0 :                 fprintf(f, "%d", ace->type);
     332             :         }
     333             : 
     334        4568 :         print_ace_flags(f, ace->flags);
     335             : 
     336             :         /* Standard permissions */
     337             : 
     338        7970 :         for (v = standard_values; v->perm; v++) {
     339        7874 :                 if (ace->access_mask == v->mask) {
     340        4472 :                         fprintf(f, "%s", v->perm);
     341        4472 :                         return;
     342             :                 }
     343             :         }
     344             : 
     345             :         /* Special permissions.  Print out a hex value if we have
     346             :            leftover bits in the mask. */
     347             : 
     348          96 :         got_mask = ace->access_mask;
     349             : 
     350         192 :  again:
     351        1344 :         for (v = special_values; v->perm; v++) {
     352        1152 :                 if ((ace->access_mask & v->mask) == v->mask) {
     353         600 :                         if (do_print) {
     354         300 :                                 fprintf(f, "%s", v->perm);
     355             :                         }
     356         600 :                         got_mask &= ~v->mask;
     357             :                 }
     358             :         }
     359             : 
     360         192 :         if (!do_print) {
     361          96 :                 if (got_mask != 0) {
     362           0 :                         fprintf(f, "0x%08x", ace->access_mask);
     363             :                 } else {
     364          96 :                         do_print = 1;
     365          96 :                         goto again;
     366             :                 }
     367             :         }
     368             : }
     369             : 
     370        1110 : static bool parse_ace_flags(const char *str, unsigned int *pflags)
     371             : {
     372        1110 :         const char *p = str;
     373        1110 :         *pflags = 0;
     374             : 
     375        4332 :         while (*p) {
     376        2112 :                 if (strnequal(p, "OI", 2)) {
     377         594 :                         *pflags |= SEC_ACE_FLAG_OBJECT_INHERIT;
     378         594 :                         p += 2;
     379        1518 :                 } else if (strnequal(p, "CI", 2)) {
     380         618 :                         *pflags |= SEC_ACE_FLAG_CONTAINER_INHERIT;
     381         618 :                         p += 2;
     382         900 :                 } else if (strnequal(p, "NP", 2)) {
     383          54 :                         *pflags |= SEC_ACE_FLAG_NO_PROPAGATE_INHERIT;
     384          54 :                         p += 2;
     385         846 :                 } else if (strnequal(p, "IO", 2)) {
     386          12 :                         *pflags |= SEC_ACE_FLAG_INHERIT_ONLY;
     387          12 :                         p += 2;
     388         834 :                 } else if (*p == 'I') {
     389         834 :                         *pflags |= SEC_ACE_FLAG_INHERITED_ACE;
     390         834 :                         p += 1;
     391           0 :                 } else if (*p) {
     392           0 :                         return false;
     393             :                 }
     394             : 
     395        2112 :                 switch (*p) {
     396        1002 :                 case '|':
     397        1002 :                         p++;
     398             : 
     399             :                         FALL_THROUGH;
     400        2112 :                 case '\0':
     401        2112 :                         continue;
     402           0 :                 default:
     403           0 :                         return false;
     404             :                 }
     405             :         }
     406        1110 :         return true;
     407             : }
     408             : 
     409             : /* parse an ACE in the same format as print_ace() */
     410        1266 : bool parse_ace(struct cli_state *cli, struct security_ace *ace,
     411             :                const char *orig_str)
     412             : {
     413             :         char *p;
     414             :         const char *cp;
     415             :         char *tok;
     416        1266 :         unsigned int atype = 0;
     417        1266 :         unsigned int aflags = 0;
     418        1266 :         unsigned int amask = 0;
     419             :         struct dom_sid sid;
     420             :         uint32_t mask;
     421             :         const struct perm_value *v;
     422        1266 :         char *str = SMB_STRDUP(orig_str);
     423        1266 :         TALLOC_CTX *frame = talloc_stackframe();
     424             : 
     425        1266 :         if (!str) {
     426           0 :                 TALLOC_FREE(frame);
     427           0 :                 return False;
     428             :         }
     429             : 
     430        1266 :         ZERO_STRUCTP(ace);
     431        1266 :         p = strchr_m(str,':');
     432        1266 :         if (!p) {
     433           0 :                 printf("ACE '%s': missing ':'.\n", orig_str);
     434           0 :                 SAFE_FREE(str);
     435           0 :                 TALLOC_FREE(frame);
     436           0 :                 return False;
     437             :         }
     438        1266 :         *p = '\0';
     439        1266 :         p++;
     440             : 
     441        1266 :         if (!StringToSid(cli, &sid, str)) {
     442           0 :                 printf("ACE '%s': failed to convert '%s' to SID\n",
     443             :                         orig_str, str);
     444           0 :                 SAFE_FREE(str);
     445           0 :                 TALLOC_FREE(frame);
     446           0 :                 return False;
     447             :         }
     448             : 
     449        1266 :         cp = p;
     450        1266 :         if (!next_token_talloc(frame, &cp, &tok, "/")) {
     451           0 :                 printf("ACE '%s': failed to find '/' character.\n",
     452             :                         orig_str);
     453           0 :                 SAFE_FREE(str);
     454           0 :                 TALLOC_FREE(frame);
     455           0 :                 return False;
     456             :         }
     457             : 
     458        1266 :         if (strncmp(tok, "ALLOWED", strlen("ALLOWED")) == 0) {
     459        1252 :                 atype = SEC_ACE_TYPE_ACCESS_ALLOWED;
     460          14 :         } else if (strncmp(tok, "DENIED", strlen("DENIED")) == 0) {
     461          10 :                 atype = SEC_ACE_TYPE_ACCESS_DENIED;
     462             : 
     463           4 :         } else if (strnequal(tok, "0x", 2)) {
     464             :                 int result;
     465             : 
     466           2 :                 result = sscanf(tok, "%x", &atype);
     467           4 :                 if (result == 0 ||
     468           4 :                     (atype != SEC_ACE_TYPE_ACCESS_ALLOWED &&
     469           2 :                      atype != SEC_ACE_TYPE_ACCESS_DENIED)) {
     470           0 :                         printf("ACE '%s': bad hex value for type at '%s'\n",
     471             :                                orig_str, tok);
     472           0 :                         SAFE_FREE(str);
     473           0 :                         TALLOC_FREE(frame);
     474           0 :                         return false;
     475             :                 }
     476           4 :         } else if(tok[0] >= '0' && tok[0] <= '9') {
     477             :                 int result;
     478             : 
     479           2 :                 result = sscanf(tok, "%u", &atype);
     480           4 :                 if (result == 0 ||
     481           4 :                     (atype != SEC_ACE_TYPE_ACCESS_ALLOWED &&
     482           2 :                      atype != SEC_ACE_TYPE_ACCESS_DENIED)) {
     483           0 :                         printf("ACE '%s': bad integer value for type at '%s'\n",
     484             :                                orig_str, tok);
     485           0 :                         SAFE_FREE(str);
     486           0 :                         TALLOC_FREE(frame);
     487           0 :                         return false;
     488             :                 }
     489             :         } else {
     490           0 :                 printf("ACE '%s': missing 'ALLOWED' or 'DENIED' entry at '%s'\n",
     491             :                         orig_str, tok);
     492           0 :                 SAFE_FREE(str);
     493           0 :                 TALLOC_FREE(frame);
     494           0 :                 return False;
     495             :         }
     496             : 
     497        1266 :         if (!next_token_talloc(frame, &cp, &tok, "/")) {
     498           0 :                 printf("ACE '%s': bad flags entry at '%s'\n",
     499             :                         orig_str, tok);
     500           0 :                 SAFE_FREE(str);
     501           0 :                 TALLOC_FREE(frame);
     502           0 :                 return False;
     503             :         }
     504             : 
     505        1266 :         if (tok[0] < '0' || tok[0] > '9') {
     506        2220 :                 if (!parse_ace_flags(tok, &aflags)) {
     507           0 :                         printf("ACE '%s': bad named flags entry at '%s'\n",
     508             :                                 orig_str, tok);
     509           0 :                         SAFE_FREE(str);
     510           0 :                         TALLOC_FREE(frame);
     511           0 :                         return False;
     512             :                 }
     513         156 :         } else if (strnequal(tok, "0x", 2)) {
     514         154 :                 if (!sscanf(tok, "%x", &aflags)) {
     515           0 :                         printf("ACE '%s': bad hex flags entry at '%s'\n",
     516             :                                 orig_str, tok);
     517           0 :                         SAFE_FREE(str);
     518           0 :                         TALLOC_FREE(frame);
     519           0 :                         return False;
     520             :                 }
     521             :         } else {
     522           2 :                 if (!sscanf(tok, "%u", &aflags)) {
     523           0 :                         printf("ACE '%s': bad integer flags entry at '%s'\n",
     524             :                                 orig_str, tok);
     525           0 :                         SAFE_FREE(str);
     526           0 :                         TALLOC_FREE(frame);
     527           0 :                         return False;
     528             :                 }
     529             :         }
     530             : 
     531        1266 :         if (!next_token_talloc(frame, &cp, &tok, "/")) {
     532           0 :                 printf("ACE '%s': missing / at '%s'\n",
     533             :                         orig_str, tok);
     534           0 :                 SAFE_FREE(str);
     535           0 :                 TALLOC_FREE(frame);
     536           0 :                 return False;
     537             :         }
     538             : 
     539        1266 :         if (strncmp(tok, "0x", 2) == 0) {
     540           4 :                 if (sscanf(tok, "%x", &amask) != 1) {
     541           0 :                         printf("ACE '%s': bad hex number at '%s'\n",
     542             :                                 orig_str, tok);
     543           0 :                         SAFE_FREE(str);
     544           0 :                         TALLOC_FREE(frame);
     545           0 :                         return False;
     546             :                 }
     547           4 :                 goto done;
     548             :         }
     549             : 
     550        3470 :         for (v = standard_values; v->perm; v++) {
     551        3340 :                 if (strcmp(tok, v->perm) == 0) {
     552        1132 :                         amask = v->mask;
     553        1132 :                         goto done;
     554             :                 }
     555             :         }
     556             : 
     557         130 :         p = tok;
     558             : 
     559         574 :         while(*p) {
     560         314 :                 bool found = False;
     561             : 
     562        2198 :                 for (v = special_values; v->perm; v++) {
     563        1884 :                         if (v->perm[0] == *p) {
     564         314 :                                 amask |= v->mask;
     565         314 :                                 found = True;
     566             :                         }
     567             :                 }
     568             : 
     569         314 :                 if (!found) {
     570           0 :                         printf("ACE '%s': bad permission value at '%s'\n",
     571             :                                 orig_str, p);
     572           0 :                         SAFE_FREE(str);
     573           0 :                         TALLOC_FREE(frame);
     574           0 :                         return False;
     575             :                 }
     576         314 :                 p++;
     577             :         }
     578             : 
     579         130 :         if (*p) {
     580           0 :                 TALLOC_FREE(frame);
     581           0 :                 SAFE_FREE(str);
     582           0 :                 return False;
     583             :         }
     584             : 
     585         130 :  done:
     586        1266 :         mask = amask;
     587        1266 :         init_sec_ace(ace, &sid, atype, mask, aflags);
     588        1266 :         TALLOC_FREE(frame);
     589        1266 :         SAFE_FREE(str);
     590        1266 :         return True;
     591             : }
     592             : 
     593         688 : static void print_acl_ctrl(FILE *file, uint16_t ctrl, bool numeric)
     594             : {
     595             :         int i;
     596         688 :         const char* separator = "";
     597             : 
     598         688 :         fprintf(file, "CONTROL:");
     599         688 :         if (numeric) {
     600           0 :                 fprintf(file, "0x%x\n", ctrl);
     601           0 :                 return;
     602             :         }
     603             : 
     604       11696 :         for (i = ARRAY_SIZE(sec_desc_ctrl_bits) - 1; i >= 0; i--) {
     605       11008 :                 if (ctrl & sec_desc_ctrl_bits[i].mask) {
     606        1382 :                         fprintf(file, "%s%s",
     607           0 :                                 separator, sec_desc_ctrl_bits[i].str);
     608        1382 :                         separator = "|";
     609             :                 }
     610             :         }
     611         688 :         fputc('\n', file);
     612             : }
     613             : 
     614             : /* print a ascii version of a security descriptor on a FILE handle */
     615         688 : void sec_desc_print(struct cli_state *cli, FILE *f,
     616             :                     struct security_descriptor *sd, bool numeric)
     617             : {
     618             :         fstring sidstr;
     619             :         uint32_t i;
     620             : 
     621         688 :         fprintf(f, "REVISION:%d\n", sd->revision);
     622         688 :         print_acl_ctrl(f, sd->type, numeric);
     623             : 
     624             :         /* Print owner and group sid */
     625             : 
     626         688 :         if (sd->owner_sid) {
     627         634 :                 SidToString(cli, sidstr, sd->owner_sid, numeric);
     628             :         } else {
     629          54 :                 fstrcpy(sidstr, "");
     630             :         }
     631             : 
     632         688 :         fprintf(f, "OWNER:%s\n", sidstr);
     633             : 
     634         688 :         if (sd->group_sid) {
     635         634 :                 SidToString(cli, sidstr, sd->group_sid, numeric);
     636             :         } else {
     637          54 :                 fstrcpy(sidstr, "");
     638             :         }
     639             : 
     640         688 :         fprintf(f, "GROUP:%s\n", sidstr);
     641             : 
     642             :         /* Print aces */
     643        5230 :         for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
     644        4542 :                 struct security_ace *ace = &sd->dacl->aces[i];
     645        4542 :                 fprintf(f, "ACL:");
     646        4542 :                 print_ace(cli, f, ace, numeric);
     647        4542 :                 fprintf(f, "\n");
     648             :         }
     649             : 
     650         688 : }

Generated by: LCOV version 1.13