root/lib/acl-internal.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. acl_extended_nontrivial
  2. acl_access_nontrivial
  3. acl_default_nontrivial
  4. acl_nontrivial
  5. acl_ace_nontrivial
  6. acl_nontrivial
  7. aclv_nontrivial
  8. acl_nontrivial
  9. acl_nfs4_nontrivial
  10. acl_nontrivial
  11. free_permission_context

     1 /* Test whether a file has a nontrivial ACL.  -*- coding: utf-8 -*-
     2 
     3    Copyright (C) 2002-2003, 2005-2023 Free Software Foundation, Inc.
     4 
     5    This program is free software: you can redistribute it and/or modify
     6    it under the terms of the GNU General Public License as published by
     7    the Free Software Foundation, either version 3 of the License, or
     8    (at your option) any later version.
     9 
    10    This program is distributed in the hope that it will be useful,
    11    but WITHOUT ANY WARRANTY; without even the implied warranty of
    12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13    GNU General Public License for more details.
    14 
    15    You should have received a copy of the GNU General Public License
    16    along with this program.  If not, see <https://www.gnu.org/licenses/>.
    17 
    18    Written by Paul Eggert, Andreas Grünbacher, and Bruno Haible.  */
    19 
    20 #include <config.h>
    21 
    22 #include "acl.h"
    23 
    24 #include "acl-internal.h"
    25 
    26 #if USE_ACL && HAVE_ACL_GET_FILE /* Linux, FreeBSD, Mac OS X, IRIX, Tru64, Cygwin >= 2.5 */
    27 
    28 # if HAVE_ACL_TYPE_EXTENDED /* Mac OS X */
    29 
    30 /* ACL is an ACL, from a file, stored as type ACL_TYPE_EXTENDED.
    31    Return 1 if the given ACL is non-trivial.
    32    Return 0 if it is trivial.  */
    33 int
    34 acl_extended_nontrivial (acl_t acl)
    35 {
    36   /* acl is non-trivial if it is non-empty.  */
    37   return (acl_entries (acl) > 0);
    38 }
    39 
    40 # else /* Linux, FreeBSD, IRIX, Tru64, Cygwin >= 2.5 */
    41 
    42 /* ACL is an ACL, from a file, stored as type ACL_TYPE_ACCESS.
    43    Return 1 if the given ACL is non-trivial.
    44    Return 0 if it is trivial, i.e. equivalent to a simple stat() mode.
    45    Return -1 and set errno upon failure to determine it.  */
    46 int
    47 acl_access_nontrivial (acl_t acl)
    48 {
    49   /* acl is non-trivial if it has some entries other than for "user::",
    50      "group::", and "other::".  Normally these three should be present
    51      at least, allowing us to write
    52         return (3 < acl_entries (acl));
    53      but the following code is more robust.  */
    54 #  if HAVE_ACL_FIRST_ENTRY /* Linux, FreeBSD, Cygwin >= 2.5 */
    55 
    56   acl_entry_t ace;
    57   int got_one;
    58 
    59   for (got_one = acl_get_entry (acl, ACL_FIRST_ENTRY, &ace);
    60        got_one > 0;
    61        got_one = acl_get_entry (acl, ACL_NEXT_ENTRY, &ace))
    62     {
    63       acl_tag_t tag;
    64       if (acl_get_tag_type (ace, &tag) < 0)
    65         return -1;
    66       if (!(tag == ACL_USER_OBJ || tag == ACL_GROUP_OBJ || tag == ACL_OTHER))
    67         return 1;
    68     }
    69   return got_one;
    70 
    71 #  elif HAVE_ACL_TO_SHORT_TEXT /* IRIX */
    72   /* Don't use acl_get_entry: it is undocumented.  */
    73 
    74   int count = acl->acl_cnt;
    75   int i;
    76 
    77   for (i = 0; i < count; i++)
    78     {
    79       acl_entry_t ace = &acl->acl_entry[i];
    80       acl_tag_t tag = ace->ae_tag;
    81 
    82       if (!(tag == ACL_USER_OBJ || tag == ACL_GROUP_OBJ
    83             || tag == ACL_OTHER_OBJ))
    84         return 1;
    85     }
    86   return 0;
    87 
    88 #  elif HAVE_ACL_FREE_TEXT /* Tru64 */
    89   /* Don't use acl_get_entry: it takes only one argument and does not work.  */
    90 
    91   int count = acl->acl_num;
    92   acl_entry_t ace;
    93 
    94   for (ace = acl->acl_first; count > 0; ace = ace->next, count--)
    95     {
    96       acl_tag_t tag;
    97       acl_perm_t perm;
    98 
    99       tag = ace->entry->acl_type;
   100       if (!(tag == ACL_USER_OBJ || tag == ACL_GROUP_OBJ || tag == ACL_OTHER))
   101         return 1;
   102 
   103       perm = ace->entry->acl_perm;
   104       /* On Tru64, perm can also contain non-standard bits such as
   105          PERM_INSERT, PERM_DELETE, PERM_MODIFY, PERM_LOOKUP, ... */
   106       if ((perm & ~(ACL_READ | ACL_WRITE | ACL_EXECUTE)) != 0)
   107         return 1;
   108     }
   109   return 0;
   110 
   111 #  else
   112 
   113   errno = ENOSYS;
   114   return -1;
   115 #  endif
   116 }
   117 
   118 int
   119 acl_default_nontrivial (acl_t acl)
   120 {
   121   /* acl is non-trivial if it is non-empty.  */
   122   return (acl_entries (acl) > 0);
   123 }
   124 
   125 # endif
   126 
   127 #elif USE_ACL && HAVE_FACL && defined GETACL /* Solaris, Cygwin < 2.5, not HP-UX */
   128 
   129 /* Test an ACL retrieved with GETACL.
   130    Return 1 if the given ACL, consisting of COUNT entries, is non-trivial.
   131    Return 0 if it is trivial, i.e. equivalent to a simple stat() mode.  */
   132 int
   133 acl_nontrivial (int count, aclent_t *entries)
   134 {
   135   int i;
   136 
   137   for (i = 0; i < count; i++)
   138     {
   139       aclent_t *ace = &entries[i];
   140 
   141       /* Note: If ace->a_type = USER_OBJ, ace->a_id is the st_uid from stat().
   142          If ace->a_type = GROUP_OBJ, ace->a_id is the st_gid from stat().
   143          We don't need to check ace->a_id in these cases.  */
   144       if (!(ace->a_type == USER_OBJ
   145             || ace->a_type == GROUP_OBJ
   146             || ace->a_type == OTHER_OBJ
   147             /* Note: Cygwin does not return a CLASS_OBJ ("mask:") entry
   148                sometimes.  */
   149             || ace->a_type == CLASS_OBJ))
   150         return 1;
   151     }
   152   return 0;
   153 }
   154 
   155 # ifdef ACE_GETACL
   156 
   157 /* A shortcut for a bitmask.  */
   158 #  define NEW_ACE_WRITEA_DATA (NEW_ACE_WRITE_DATA | NEW_ACE_APPEND_DATA)
   159 
   160 /* Test an ACL retrieved with ACE_GETACL.
   161    Return 1 if the given ACL, consisting of COUNT entries, is non-trivial.
   162    Return 0 if it is trivial, i.e. equivalent to a simple stat() mode.  */
   163 int
   164 acl_ace_nontrivial (int count, ace_t *entries)
   165 {
   166   int i;
   167 
   168   /* The flags in the ace_t structure changed in a binary incompatible way
   169      when ACL_NO_TRIVIAL etc. were introduced in <sys/acl.h> version 1.15.
   170      How to distinguish the two conventions at runtime?
   171      In the old convention, usually three ACEs have a_flags = ACE_OWNER /
   172      ACE_GROUP / ACE_OTHER, in the range 0x0100..0x0400.  In the new
   173      convention, these values are not used.  */
   174   int old_convention = 0;
   175 
   176   for (i = 0; i < count; i++)
   177     if (entries[i].a_flags & (OLD_ACE_OWNER | OLD_ACE_GROUP | OLD_ACE_OTHER))
   178       {
   179         old_convention = 1;
   180         break;
   181       }
   182 
   183   if (old_convention)
   184     /* Running on Solaris 10.  */
   185     for (i = 0; i < count; i++)
   186       {
   187         ace_t *ace = &entries[i];
   188 
   189         /* Note:
   190            If ace->a_flags = ACE_OWNER, ace->a_who is the st_uid from stat().
   191            If ace->a_flags = ACE_GROUP, ace->a_who is the st_gid from stat().
   192            We don't need to check ace->a_who in these cases.  */
   193         if (!(ace->a_type == OLD_ALLOW
   194               && (ace->a_flags == OLD_ACE_OWNER
   195                   || ace->a_flags == OLD_ACE_GROUP
   196                   || ace->a_flags == OLD_ACE_OTHER)))
   197           return 1;
   198       }
   199   else
   200     {
   201       /* Running on Solaris 10 (newer version) or Solaris 11.  */
   202       unsigned int access_masks[6] =
   203         {
   204           0, /* owner@ deny */
   205           0, /* owner@ allow */
   206           0, /* group@ deny */
   207           0, /* group@ allow */
   208           0, /* everyone@ deny */
   209           0  /* everyone@ allow */
   210         };
   211 
   212       for (i = 0; i < count; i++)
   213         {
   214           ace_t *ace = &entries[i];
   215           unsigned int index1;
   216           unsigned int index2;
   217 
   218           if (ace->a_type == NEW_ACE_ACCESS_ALLOWED_ACE_TYPE)
   219             index1 = 1;
   220           else if (ace->a_type == NEW_ACE_ACCESS_DENIED_ACE_TYPE)
   221             index1 = 0;
   222           else
   223             return 1;
   224 
   225           if (ace->a_flags == NEW_ACE_OWNER)
   226             index2 = 0;
   227           else if (ace->a_flags == (NEW_ACE_GROUP | NEW_ACE_IDENTIFIER_GROUP))
   228             index2 = 2;
   229           else if (ace->a_flags == NEW_ACE_EVERYONE)
   230             index2 = 4;
   231           else
   232             return 1;
   233 
   234           access_masks[index1 + index2] |= ace->a_access_mask;
   235         }
   236 
   237       /* The same bit shouldn't be both allowed and denied.  */
   238       if (access_masks[0] & access_masks[1])
   239         return 1;
   240       if (access_masks[2] & access_masks[3])
   241         return 1;
   242       if (access_masks[4] & access_masks[5])
   243         return 1;
   244 
   245       /* Check minimum masks.  */
   246       if ((NEW_ACE_WRITE_NAMED_ATTRS
   247            | NEW_ACE_WRITE_ATTRIBUTES
   248            | NEW_ACE_WRITE_ACL
   249            | NEW_ACE_WRITE_OWNER)
   250           & ~ access_masks[1])
   251         return 1;
   252       access_masks[1] &= ~(NEW_ACE_WRITE_NAMED_ATTRS
   253                            | NEW_ACE_WRITE_ATTRIBUTES
   254                            | NEW_ACE_WRITE_ACL
   255                            | NEW_ACE_WRITE_OWNER);
   256       if ((NEW_ACE_READ_NAMED_ATTRS
   257            | NEW_ACE_READ_ATTRIBUTES
   258            | NEW_ACE_READ_ACL
   259            | NEW_ACE_SYNCHRONIZE)
   260           & ~ access_masks[5])
   261         return 1;
   262       access_masks[5] &= ~(NEW_ACE_READ_NAMED_ATTRS
   263                            | NEW_ACE_READ_ATTRIBUTES
   264                            | NEW_ACE_READ_ACL
   265                            | NEW_ACE_SYNCHRONIZE);
   266 
   267       /* Check the allowed or denied bits.  */
   268       switch ((access_masks[0] | access_masks[1])
   269               & ~(NEW_ACE_READ_NAMED_ATTRS
   270                   | NEW_ACE_READ_ATTRIBUTES
   271                   | NEW_ACE_READ_ACL
   272                   | NEW_ACE_SYNCHRONIZE))
   273         {
   274         case 0:
   275         case NEW_ACE_READ_DATA:
   276         case                     NEW_ACE_WRITEA_DATA:
   277         case NEW_ACE_READ_DATA | NEW_ACE_WRITEA_DATA:
   278         case                                           NEW_ACE_EXECUTE:
   279         case NEW_ACE_READ_DATA |                       NEW_ACE_EXECUTE:
   280         case                     NEW_ACE_WRITEA_DATA | NEW_ACE_EXECUTE:
   281         case NEW_ACE_READ_DATA | NEW_ACE_WRITEA_DATA | NEW_ACE_EXECUTE:
   282           break;
   283         default:
   284           return 1;
   285         }
   286       switch ((access_masks[2] | access_masks[3])
   287               & ~(NEW_ACE_READ_NAMED_ATTRS
   288                   | NEW_ACE_READ_ATTRIBUTES
   289                   | NEW_ACE_READ_ACL
   290                   | NEW_ACE_SYNCHRONIZE))
   291         {
   292         case 0:
   293         case NEW_ACE_READ_DATA:
   294         case                     NEW_ACE_WRITEA_DATA:
   295         case NEW_ACE_READ_DATA | NEW_ACE_WRITEA_DATA:
   296         case                                           NEW_ACE_EXECUTE:
   297         case NEW_ACE_READ_DATA |                       NEW_ACE_EXECUTE:
   298         case                     NEW_ACE_WRITEA_DATA | NEW_ACE_EXECUTE:
   299         case NEW_ACE_READ_DATA | NEW_ACE_WRITEA_DATA | NEW_ACE_EXECUTE:
   300           break;
   301         default:
   302           return 1;
   303         }
   304       switch ((access_masks[4] | access_masks[5])
   305               & ~(NEW_ACE_WRITE_NAMED_ATTRS
   306                   | NEW_ACE_WRITE_ATTRIBUTES
   307                   | NEW_ACE_WRITE_ACL
   308                   | NEW_ACE_WRITE_OWNER))
   309         {
   310         case 0:
   311         case NEW_ACE_READ_DATA:
   312         case                     NEW_ACE_WRITEA_DATA:
   313         case NEW_ACE_READ_DATA | NEW_ACE_WRITEA_DATA:
   314         case                                           NEW_ACE_EXECUTE:
   315         case NEW_ACE_READ_DATA |                       NEW_ACE_EXECUTE:
   316         case                     NEW_ACE_WRITEA_DATA | NEW_ACE_EXECUTE:
   317         case NEW_ACE_READ_DATA | NEW_ACE_WRITEA_DATA | NEW_ACE_EXECUTE:
   318           break;
   319         default:
   320           return 1;
   321         }
   322 
   323       /* Check that the NEW_ACE_WRITE_DATA and NEW_ACE_APPEND_DATA bits are
   324          either both allowed or both denied.  */
   325       if (((access_masks[0] & NEW_ACE_WRITE_DATA) != 0)
   326           != ((access_masks[0] & NEW_ACE_APPEND_DATA) != 0))
   327         return 1;
   328       if (((access_masks[2] & NEW_ACE_WRITE_DATA) != 0)
   329           != ((access_masks[2] & NEW_ACE_APPEND_DATA) != 0))
   330         return 1;
   331       if (((access_masks[4] & NEW_ACE_WRITE_DATA) != 0)
   332           != ((access_masks[4] & NEW_ACE_APPEND_DATA) != 0))
   333         return 1;
   334     }
   335 
   336   return 0;
   337 }
   338 
   339 # endif
   340 
   341 #elif USE_ACL && HAVE_GETACL /* HP-UX */
   342 
   343 /* Return 1 if the given ACL is non-trivial.
   344    Return 0 if it is trivial, i.e. equivalent to a simple stat() mode.  */
   345 int
   346 acl_nontrivial (int count, struct acl_entry *entries)
   347 {
   348   int i;
   349 
   350   if (count > 3)
   351     return 1;
   352 
   353   for (i = 0; i < count; i++)
   354     {
   355       struct acl_entry *ace = &entries[i];
   356 
   357       if (ace->uid != ACL_NSUSER && ace->gid != ACL_NSGROUP)
   358         return 1;
   359     }
   360   return 0;
   361 }
   362 
   363 # if HAVE_ACLV_H /* HP-UX >= 11.11 */
   364 
   365 /* Return 1 if the given ACL is non-trivial.
   366    Return 0 if it is trivial, i.e. equivalent to a simple stat() mode.  */
   367 int
   368 aclv_nontrivial (int count, struct acl *entries)
   369 {
   370   int i;
   371 
   372   for (i = 0; i < count; i++)
   373     {
   374       struct acl *ace = &entries[i];
   375 
   376       /* Note: If ace->a_type = USER_OBJ, ace->a_id is the st_uid from stat().
   377          If ace->a_type = GROUP_OBJ, ace->a_id is the st_gid from stat().
   378          We don't need to check ace->a_id in these cases.  */
   379       if (!(ace->a_type == USER_OBJ /* no need to check ace->a_id here */
   380             || ace->a_type == GROUP_OBJ /* no need to check ace->a_id here */
   381             || ace->a_type == CLASS_OBJ
   382             || ace->a_type == OTHER_OBJ))
   383         return 1;
   384     }
   385   return 0;
   386 }
   387 
   388 # endif
   389 
   390 #elif USE_ACL && (HAVE_ACLX_GET || HAVE_STATACL) /* AIX */
   391 
   392 /* Return 1 if the given ACL is non-trivial.
   393    Return 0 if it is trivial, i.e. equivalent to a simple stat() mode.  */
   394 int
   395 acl_nontrivial (struct acl *a)
   396 {
   397   /* The normal way to iterate through an ACL is like this:
   398        struct acl_entry *ace;
   399        for (ace = a->acl_ext; ace != acl_last (a); ace = acl_nxt (ace))
   400          {
   401            struct ace_id *aei;
   402            switch (ace->ace_type)
   403              {
   404              case ACC_PERMIT:
   405              case ACC_DENY:
   406              case ACC_SPECIFY:
   407                ...;
   408              }
   409            for (aei = ace->ace_id; aei != id_last (ace); aei = id_nxt (aei))
   410              ...
   411          }
   412    */
   413   return (acl_last (a) != a->acl_ext ? 1 : 0);
   414 }
   415 
   416 # if HAVE_ACLX_GET && defined ACL_AIX_WIP /* newer AIX */
   417 
   418 /* Return 1 if the given ACL is non-trivial.
   419    Return 0 if it is trivial, i.e. equivalent to a simple stat() mode.  */
   420 int
   421 acl_nfs4_nontrivial (nfs4_acl_int_t *a)
   422 {
   423 #  if 1 /* let's try this first */
   424   return (a->aclEntryN > 0 ? 1 : 0);
   425 #  else
   426   int count = a->aclEntryN;
   427   int i;
   428 
   429   for (i = 0; i < count; i++)
   430     {
   431       nfs4_ace_int_t *ace = &a->aclEntry[i];
   432 
   433       if (!((ace->flags & ACE4_ID_SPECIAL) != 0
   434             && (ace->aceWho.special_whoid == ACE4_WHO_OWNER
   435                 || ace->aceWho.special_whoid == ACE4_WHO_GROUP
   436                 || ace->aceWho.special_whoid == ACE4_WHO_EVERYONE)
   437             && ace->aceType == ACE4_ACCESS_ALLOWED_ACE_TYPE
   438             && ace->aceFlags == 0
   439             && (ace->aceMask & ~(ACE4_READ_DATA | ACE4_LIST_DIRECTORY
   440                                  | ACE4_WRITE_DATA | ACE4_ADD_FILE
   441                                  | ACE4_EXECUTE)) == 0))
   442         return 1;
   443     }
   444   return 0;
   445 #  endif
   446 }
   447 
   448 # endif
   449 
   450 #elif USE_ACL && HAVE_ACLSORT /* NonStop Kernel */
   451 
   452 /* Test an ACL retrieved with ACL_GET.
   453    Return 1 if the given ACL, consisting of COUNT entries, is non-trivial.
   454    Return 0 if it is trivial, i.e. equivalent to a simple stat() mode.  */
   455 int
   456 acl_nontrivial (int count, struct acl *entries)
   457 {
   458   int i;
   459 
   460   for (i = 0; i < count; i++)
   461     {
   462       struct acl *ace = &entries[i];
   463 
   464       /* Note: If ace->a_type = USER_OBJ, ace->a_id is the st_uid from stat().
   465          If ace->a_type = GROUP_OBJ, ace->a_id is the st_gid from stat().
   466          We don't need to check ace->a_id in these cases.  */
   467       if (!(ace->a_type == USER_OBJ /* no need to check ace->a_id here */
   468             || ace->a_type == GROUP_OBJ /* no need to check ace->a_id here */
   469             || ace->a_type == CLASS_OBJ
   470             || ace->a_type == OTHER_OBJ))
   471         return 1;
   472     }
   473   return 0;
   474 }
   475 
   476 #endif
   477 
   478 void
   479 free_permission_context (struct permission_context *ctx)
   480 {
   481 #if USE_ACL
   482 # if HAVE_ACL_GET_FILE /* Linux, FreeBSD, Mac OS X, IRIX, Tru64, Cygwin >= 2.5 */
   483   if (ctx->acl)
   484     acl_free (ctx->acl);
   485 #  if !HAVE_ACL_TYPE_EXTENDED
   486   if (ctx->default_acl)
   487     acl_free (ctx->default_acl);
   488 #  endif
   489 
   490 # elif defined GETACL /* Solaris, Cygwin < 2.5 */
   491   free (ctx->entries);
   492 #  ifdef ACE_GETACL
   493   free (ctx->ace_entries);
   494 #  endif
   495 
   496 # elif HAVE_GETACL /* HP-UX */
   497 
   498 #  if HAVE_ACLV_H
   499 #  endif
   500 
   501 # elif HAVE_STATACL /* older AIX */
   502 
   503 # elif HAVE_ACLSORT /* NonStop Kernel */
   504 
   505 # endif
   506 #endif
   507 }

/* [<][>][^][v][top][bottom][index][help] */