root/maint/gnulib/lib/acl-internal.c

/* [previous][next][first][last][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-2021 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)
     /* [previous][next][first][last][top][bottom][index][help] */
  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)
     /* [previous][next][first][last][top][bottom][index][help] */
  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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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 }

/* [previous][next][first][last][top][bottom][index][help] */