acl-internal.h 8.75 KB
Newer Older
Paul Eggert's avatar
Paul Eggert committed
1
/* Internal implementation of access control lists.  -*- coding: utf-8 -*-
2

Paul Eggert's avatar
Paul Eggert committed
3
   Copyright (C) 2002-2003, 2005-2018 Free Software Foundation, Inc.
4 5 6 7 8 9 10 11 12 13 14 15

   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
Paul Eggert's avatar
Paul Eggert committed
16
   along with this program.  If not, see <https://www.gnu.org/licenses/>.
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62

   Written by Paul Eggert, Andreas Grünbacher, and Bruno Haible.  */

#include "acl.h"

#include <stdbool.h>
#include <stdlib.h>

/* All systems define the ACL related API in <sys/acl.h>.  */
#if HAVE_SYS_ACL_H
# include <sys/acl.h>
#endif
#if defined HAVE_FACL && ! defined GETACLCNT && defined ACL_CNT
# define GETACLCNT ACL_CNT
#endif

/* On Linux, additional ACL related API is available in <acl/libacl.h>.  */
#ifdef HAVE_ACL_LIBACL_H
# include <acl/libacl.h>
#endif

/* On HP-UX >= 11.11, additional ACL API is available in <aclv.h>.  */
#if HAVE_ACLV_H
# include <sys/types.h>
# include <aclv.h>
/* HP-UX 11.11 lacks these declarations.  */
extern int acl (char *, int, int, struct acl *);
extern int aclsort (int, int, struct acl *);
#endif

#include <errno.h>

#include <limits.h>
#ifndef MIN
# define MIN(a,b) ((a) < (b) ? (a) : (b))
#endif

#ifndef SIZE_MAX
# define SIZE_MAX ((size_t) -1)
#endif

#ifndef HAVE_FCHMOD
# define HAVE_FCHMOD false
# define fchmod(fd, mode) (-1)
#endif

Paul Eggert's avatar
Paul Eggert committed
63 64 65
#ifndef _GL_INLINE_HEADER_BEGIN
 #error "Please include config.h first."
#endif
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
_GL_INLINE_HEADER_BEGIN
#ifndef ACL_INTERNAL_INLINE
# define ACL_INTERNAL_INLINE _GL_INLINE
#endif

#if USE_ACL

# if HAVE_ACL_GET_FILE
/* POSIX 1003.1e (draft 17 -- abandoned) specific version.  */
/* Linux, FreeBSD, Mac OS X, IRIX, Tru64 */

#  ifndef MIN_ACL_ENTRIES
#   define MIN_ACL_ENTRIES 4
#  endif

/* POSIX 1003.1e (draft 17) */
#  ifdef HAVE_ACL_GET_FD
/* Most platforms have a 1-argument acl_get_fd, only OSF/1 has a 2-argument
   macro(!).  */
#   if HAVE_ACL_FREE_TEXT /* OSF/1 */
ACL_INTERNAL_INLINE acl_t
rpl_acl_get_fd (int fd)
{
  return acl_get_fd (fd, ACL_TYPE_ACCESS);
}
#    undef acl_get_fd
#    define acl_get_fd rpl_acl_get_fd
#   endif
#  else
#   define HAVE_ACL_GET_FD false
#   undef acl_get_fd
#   define acl_get_fd(fd) (NULL)
#  endif

/* POSIX 1003.1e (draft 17) */
#  ifdef HAVE_ACL_SET_FD
/* Most platforms have a 2-argument acl_set_fd, only OSF/1 has a 3-argument
   macro(!).  */
#   if HAVE_ACL_FREE_TEXT /* OSF/1 */
ACL_INTERNAL_INLINE int
rpl_acl_set_fd (int fd, acl_t acl)
{
  return acl_set_fd (fd, ACL_TYPE_ACCESS, acl);
}
#    undef acl_set_fd
#    define acl_set_fd rpl_acl_set_fd
#   endif
#  else
#   define HAVE_ACL_SET_FD false
#   undef acl_set_fd
#   define acl_set_fd(fd, acl) (-1)
#  endif

/* POSIX 1003.1e (draft 13) */
#  if ! HAVE_ACL_FREE_TEXT
#   define acl_free_text(buf) acl_free (buf)
#  endif

/* Linux-specific */
#  ifndef HAVE_ACL_EXTENDED_FILE
#   define HAVE_ACL_EXTENDED_FILE false
#   define acl_extended_file(name) (-1)
#  endif

Paul Eggert's avatar
Paul Eggert committed
130 131
#  if ! defined HAVE_ACL_FROM_MODE && ! defined HAVE_ACL_FROM_TEXT
#   define acl_from_mode (NULL)
132 133
#  endif

Paul Eggert's avatar
Paul Eggert committed
134
/* Set to 0 if a file's mode is stored independently from the ACL.  */
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
#  if (HAVE_ACL_COPY_EXT_NATIVE && HAVE_ACL_CREATE_ENTRY_NP) || defined __sgi /* Mac OS X, IRIX */
#   define MODE_INSIDE_ACL 0
#  endif

/* Return the number of entries in ACL.
   Return -1 and set errno upon failure to determine it.  */
/* Define a replacement for acl_entries if needed. (Only Linux has it.)  */
#  if !HAVE_ACL_ENTRIES
#   define acl_entries rpl_acl_entries
extern int acl_entries (acl_t);
#  endif

#  if HAVE_ACL_TYPE_EXTENDED /* Mac OS X */
/* ACL is an ACL, from a file, stored as type ACL_TYPE_EXTENDED.
   Return 1 if the given ACL is non-trivial.
   Return 0 if it is trivial.  */
extern int acl_extended_nontrivial (acl_t);
#  else
/* ACL is an ACL, from a file, stored as type ACL_TYPE_ACCESS.
   Return 1 if the given ACL is non-trivial.
   Return 0 if it is trivial, i.e. equivalent to a simple stat() mode.
   Return -1 and set errno upon failure to determine it.  */
extern int acl_access_nontrivial (acl_t);
Paul Eggert's avatar
Paul Eggert committed
158 159 160 161 162 163

/* ACL is an ACL, from a file, stored as type ACL_TYPE_DEFAULT.
   Return 1 if the given ACL is non-trivial.
   Return 0 if it is trivial, i.e. equivalent to a simple stat() mode.
   Return -1 and set errno upon failure to determine it.  */
extern int acl_default_nontrivial (acl_t);
164 165 166 167
#  endif

# elif HAVE_FACL && defined GETACL /* Solaris, Cygwin, not HP-UX */

Paul Eggert's avatar
Paul Eggert committed
168
/* Set to 0 if a file's mode is stored independently from the ACL.  */
169 170 171 172 173 174
#  if defined __CYGWIN__ /* Cygwin */
#   define MODE_INSIDE_ACL 0
#  endif

/* Return 1 if the given ACL is non-trivial.
   Return 0 if it is trivial, i.e. equivalent to a simple stat() mode.  */
Paul Eggert's avatar
Paul Eggert committed
175
extern int acl_nontrivial (int count, aclent_t *entries) _GL_ATTRIBUTE_PURE;
176 177 178 179 180 181

#  ifdef ACE_GETACL /* Solaris 10 */

/* Test an ACL retrieved with ACE_GETACL.
   Return 1 if the given ACL, consisting of COUNT entries, is non-trivial.
   Return 0 if it is trivial, i.e. equivalent to a simple stat() mode.  */
Paul Eggert's avatar
Paul Eggert committed
182
extern int acl_ace_nontrivial (int count, ace_t *entries) _GL_ATTRIBUTE_PURE;
183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220

/* Definitions for when the built executable is executed on Solaris 10
   (newer version) or Solaris 11.  */
/* For a_type.  */
#   define OLD_ALLOW 0
#   define OLD_DENY  1
#   define NEW_ACE_ACCESS_ALLOWED_ACE_TYPE 0 /* replaces ALLOW */
#   define NEW_ACE_ACCESS_DENIED_ACE_TYPE  1 /* replaces DENY */
/* For a_flags.  */
#   define OLD_ACE_OWNER            0x0100
#   define OLD_ACE_GROUP            0x0200
#   define OLD_ACE_OTHER            0x0400
#   define NEW_ACE_OWNER            0x1000
#   define NEW_ACE_GROUP            0x2000
#   define NEW_ACE_IDENTIFIER_GROUP 0x0040
#   define NEW_ACE_EVERYONE         0x4000
/* For a_access_mask.  */
#   define NEW_ACE_READ_DATA         0x001 /* corresponds to 'r' */
#   define NEW_ACE_WRITE_DATA        0x002 /* corresponds to 'w' */
#   define NEW_ACE_APPEND_DATA       0x004
#   define NEW_ACE_READ_NAMED_ATTRS  0x008
#   define NEW_ACE_WRITE_NAMED_ATTRS 0x010
#   define NEW_ACE_EXECUTE           0x020
#   define NEW_ACE_DELETE_CHILD      0x040
#   define NEW_ACE_READ_ATTRIBUTES   0x080
#   define NEW_ACE_WRITE_ATTRIBUTES  0x100
#   define NEW_ACE_DELETE          0x10000
#   define NEW_ACE_READ_ACL        0x20000
#   define NEW_ACE_WRITE_ACL       0x40000
#   define NEW_ACE_WRITE_OWNER     0x80000
#   define NEW_ACE_SYNCHRONIZE    0x100000

#  endif

# elif HAVE_GETACL /* HP-UX */

/* Return 1 if the given ACL is non-trivial.
   Return 0 if it is trivial, i.e. equivalent to a simple stat() mode.  */
Paul Eggert's avatar
Paul Eggert committed
221
extern int acl_nontrivial (int count, struct acl_entry *entries);
222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248

#  if HAVE_ACLV_H /* HP-UX >= 11.11 */

/* Return 1 if the given ACL is non-trivial.
   Return 0 if it is trivial, i.e. equivalent to a simple stat() mode.  */
extern int aclv_nontrivial (int count, struct acl *entries);

#  endif

# elif HAVE_ACLX_GET && 0 /* AIX */

/* TODO */

# elif HAVE_STATACL /* older AIX */

/* Return 1 if the given ACL is non-trivial.
   Return 0 if it is trivial, i.e. equivalent to a simple stat() mode.  */
extern int acl_nontrivial (struct acl *a);

# elif HAVE_ACLSORT /* NonStop Kernel */

/* Return 1 if the given ACL is non-trivial.
   Return 0 if it is trivial, i.e. equivalent to a simple stat() mode.  */
extern int acl_nontrivial (int count, struct acl *entries);

# endif

Paul Eggert's avatar
Paul Eggert committed
249 250 251 252 253
/* Set to 1 if a file's mode is implicit by the ACL.  */
# ifndef MODE_INSIDE_ACL
#  define MODE_INSIDE_ACL 1
# endif

254 255
#endif

Paul Eggert's avatar
Paul Eggert committed
256 257
struct permission_context {
  mode_t mode;
Paul Eggert's avatar
Paul Eggert committed
258
#if USE_ACL
Paul Eggert's avatar
Paul Eggert committed
259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295
# if HAVE_ACL_GET_FILE /* Linux, FreeBSD, Mac OS X, IRIX, Tru64 */
  acl_t acl;
#  if !HAVE_ACL_TYPE_EXTENDED
  acl_t default_acl;
#  endif
  bool acls_not_supported;

# elif defined GETACL /* Solaris, Cygwin */
  int count;
  aclent_t *entries;
#  ifdef ACE_GETACL
  int ace_count;
  ace_t *ace_entries;
#  endif

# elif HAVE_GETACL /* HP-UX */
  struct acl_entry entries[NACLENTRIES];
  int count;
#  if HAVE_ACLV_H
  struct acl aclv_entries[NACLVENTRIES];
  int aclv_count;
#  endif

# elif HAVE_STATACL /* older AIX */
  union { struct acl a; char room[4096]; } u;
  bool have_u;

# elif HAVE_ACLSORT /* NonStop Kernel */
  struct acl entries[NACLENTRIES];
  int count;

# endif
#endif
};

int get_permissions (const char *, int, mode_t, struct permission_context *);
int set_permissions (struct permission_context *, const char *, int);
Paul Eggert's avatar
Paul Eggert committed
296 297 298 299 300
void free_permission_context (struct permission_context *)
#if ! (defined USE_ACL && (HAVE_ACL_GET_FILE || defined GETACL))
    _GL_ATTRIBUTE_CONST
#endif
  ;
Paul Eggert's avatar
Paul Eggert committed
301

302
_GL_INLINE_HEADER_END