(root)/
tar-1.35/
gnu/
acl-internal.c
       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  }