This chapter discusses the following topics:
Tru64 UNIX access control lists (ACLs) are an optional extension to
the discretionary access control (DAC) traditionaly provided on a UNIX system.
Traditional UNIX DAC is the traditional UNIX permission bits; ACLs are an
extension of the UNIX permission bits.
A file or directory that has only the
permission bits may be considered an object with an ACL containing only the
three required or base entries that correspond to the
usr
,
group
, and
other
permission bits.
There are two types of ACLs:
An access ACL is associated with a file or directory, and is used to determine if a process may access the file or directory.
Default ACLs are associated with a directory. Default ACLs are used to determine the ACLs applied to new files and subdirectories created in the given directory. See Section 21.6 for more information.
The Tru64 UNIX ACL implementation is based on Draft 13 with some Draft 15 extensions of the POSIX P1003.6 standard.
ACLs can be applied to any file or directory on a file system that supports property lists. The file systems that support property lists are:
UFS
AdvFS
NFS (between Tru64 UNIX systems)
ACLs can be applied even if ACL processing is not enabled on the system; however, ACL access checks and default ACL inheritance do not take place.
See
Chapter 5
and
Chapter 11
for a
more detailed description of using and administering ACLs.
See the
acl
(4)
reference page for more information on using and programming with ACLs.
See
the
proplist
(4)
reference page for more information on property lists.
21.2 ACL Data Representations
An ACL has an internal and
an external representation.
The external representation consists of text
and is used to enter and display ACLs.
Library routines manipulate ACLs
in working storage in an internal representation that is only indirectly accessible
to the calling routine.
This internal representation can be interpreted with
the
acl.h
header file.
21.2.1 Internal Data Representation
The ACL routines manipulate the working storage representation, which is a set of opaque data structures for ACLs and ACL entries. Your program should operate on these data structures only through the defined routines. Because the working storage data structures are subject to change, the interface is the only reliable way to access the data.
The working storage representation is not contiguous in memory. Also, a program cannot determine the sizes of ACL entries and ACL descriptors. The working storage data structures contain internal pointer references and are therefore meaningless if passed between processes or stored in a file. A program can convert the working storage representation of an ACL to other representations of an ACL.
The two types most commonly used to access the opaque data are
acl_t
, a pointer to type
acl
(the ACL structure),
and
acl_entry_t
, a pointer to an ACL entry structure.
Note
The structures in the following sections are opaque internal data structures that are subject to change. Always use the defined types and the supplied library routines to access these structures.
The internal representation uses the following basic types and data
structures.
21.2.1.1 typedef struct acl *acl_t;
The
acl_t
type is used to specify an internal (working
storage) format ACL.
struct acl { int acl_magic; /* validation member */ int acl_num; /* number of actual acl entries */ int acl_alloc_size; /* size available in the acl */ acl_entry_t acl_current; /* pointer to current entry in */ acl_entry_t acl_first; /* pointer to ACL linked list */ attribute_t *attr_data; /* Pointer to the attr data */ };
21.2.1.2 typedef struct acl_entry *acl_entry_t;
The
acl_entry_t
type is used to specify an entry
within an ACL.
struct acl_entry{ acle_t *entry; void *head; struct acl_entry *next; struct acl_entry *prev; int acl_magic; int size; };
21.2.1.3 typedef uint_t acl_type_t;
The ACL types supported are as follows:
#define ACL_TYPE_ACC 0 #define ACL_TYPE_ACCESS ACL_TYPE_ACC /* The ACL is an access ACL. The property list entry name for an access ACL is "DEC_ACL_ACC" */ #define ACL_TYPE_DEF 1 #define ACL_TYPE_DEFAULT ACL_TYPE_DEF /* The ACL is a default access ACL. The property list entry name for a default access ACL is "DEC_ACL_ACC" */ #define ACL_TYPE_DEF_DIR 2 #define ACL_TYPE_DEFAULT_DIR ACL_TYPE_DEF_DIR /* The ACL is a default directory ACL. The property list entry name for a default directory ACL is "DEC_ACL_DEF_DIR" */
acl_type_t
is used to specify the ACL type.
21.2.1.4 typedef uint acl_tag_t;
The
acl_tag_t
type is used to specify the tag ( the
type) of an ACL entry.
ACL entries with a tag type of
ACL_USER
or
ACL_GROUP
also have an associated tag qualifier.
The
tag qualifier is the ID of the user or group.
The ACL entry tag types supported
are:
#define ACL_USER_OBJ 0 /* entry that equates to the owning user permission bits. */ #define ACL_GROUP_OBJ 1 /* entry that equates to the owning group permission bits. */ #define ACL_OTHER 2 #define ACL_OTHER_OBJ ACL_OTHER /* entry that equates to the other permission bits. */ #define ACL_USER 23 /* entry specifying permissions for a given user. */ #define ACL_GROUP 24 /* entry specifying permissions for a given group. */
21.2.1.5 typedef uint_t acl_perm_t;
The
acl_perm_t
permission bit definitions are as
follows:
#define ACL_EXECUTE 0X001 #define ACL_WRITE 0X002 #define ACL_READ 0X004
21.2.1.6 typedef acl_perm_t *acl_permset_t;
The
acl_permset_t
type is used to point to the permissions
assigned to an ACL entry.
21.2.1.7 Contiguous Internal Representation ACL
There is also a contiguous persistent data type for an ACL.
This representation
should be used only when the internal format ACL must persist between processes.
21.2.2 External Representation
The human-readable external representation of an ACL consists of a sequence of lines, each of which is terminated by a new-line character. The POSIX routines use the external representation when converting between the working storage representation and the text package.
The external representation is described in
Section 5.6.
Table 21-1
shows the structure of individual entries.
Table 21-1: ACL Entry External Representation
Entry Type | acl_tag_t
Value |
Entry |
base user | USER_OBJ |
user::perms |
base group | GROUP_OBJ |
group::perms |
base other | OTHER_OBJ |
other::perms |
user | USER |
user:user_name:perms |
group | GROUP |
group:group_name:perms |
The ACL routines are contained in the
libpacl.a
library.
The ACL library routines are based on Draft 13 of the POSIX P1003.6 standard.
See the reference page for each individual routine for detailed information.
The following routines are used to get, set, and validate ACLs:
acl_valid
()Checks the specified internal representation ACL for valid format.
acl_delete_def_fd
()Deletes the default access ACL from the designated directory using the file descriptor.
acl_delete_def_file
()Deletes the default access ACL from the designated directory.
acl_get_fd
()Retrieves the internal representation of the specified ACL type associated with the specific file or directory using the file descriptor.
acl_get_file
()Retrieves the internal representation of the specified ACL type associated with the specific file or directory.
acl_set_fd
()Sets the specified ACL type on the given file or directory to the specified ACL internal representation using the file descriptor.
acl_set_file
()Sets the specified ACL type on the given file or directory to the specified ACL internal representation.
The following routines retrieve and manipulate ACL entries:
acl_copy_entry
()Copies an ACL entry into the memory provided.
acl_create_entry
()Creates an empty ACL entry for the given ACL, allocating memory as necessary.
acl_delete_entry
()Deletes the designated ACL entry from an ACL.
acl_first_entry
()Resets the
current ACL entry so that the next call to
acl_get_entry
()
returns the first entry.
acl_get_entry
()Returns a pointer to the next ACL entry of the given ACL.
The following routines retrieve and manipulate fields in an ACL entry:
acl_add_perm
()Adds a permission to a set of permissions belonging to an ACL entry.
acl_clear_perm
()Clears a permission in a given ACL entry.
acl_delete_perm
()Removes permissions from a set of permissions belonging to an ACL entry.
acl_get_permset
()Copies the permissions from a given ACL entry to the location provided.
acl_get_qualifier
()Returns a pointer to the tag qualifier (ID) associated with a given ACL entry.
acl_get_tag_type
()Copies the tag (type) from the given ACL entry to the location provided.
acl_set_permset
()Sets the permissions in a given ACL entry to the given permissions.
acl_set_qualifier
()Sets the tag qualifier (ID) of the specified ACL entry to the given UID or GID.
acl_set_tag_type
()Sets the tag (type) of the specified ACL entry to the given type.
The following routines manage working storage for the ACL manipulation:
acl_free
()Releases all working storage associated with the given ACL.
acl_free_qualifier
()Releases working storage associated with the given tag qualifier.
acl_free_text
()Releases the buffer associated with the given external representation (text) ACL.
acl_init
()Allocates and initializes ACL internal representation working storage.
acl_copy_ext
()Copies the working storage internal format ACL data to the contiguous persistent ACL format.
acl_copy_int
()Copies contiguous persistent ACL data to working storage.
acl_dup
()Creates a copy of the designated ACL. The copy is independent of the original entry.
acl_size
()Calculates the size of the given ACL.
The following routines convert ACLs between external and internal representations:
acl_from_text
()Creates an internal representation ACL from the given external representation (text) ACL.
acl_to_text
()Creates an external representation (text) ACL from the given internal representation ACL.
Some interactions between the ACL and the UNIX permissions are subtle. Unless you understand the interaction between ACL routines and the system calls that manipulate UNIX DAC attributes, you might get different permissions than you intended.
The following sections describe rules for programs that handle ACLs.
21.4.1 Object Creation
If ACLs are enabled and are supported on the file system, the
open
(),
creat
(), and
mkdir
()
functions perform ACL inheritance when creating a file or directory.
See
Section 5.7
for a description of ACL inheritance.
When ACL inheritance is performed, the permissions on a created file
come from the mode you provide and the inherited ACL, not the
umask
.
Therefore, your program must set the mode when creating files
and directories.
The program must not depend on
umask
to
protect the files and directories.
When copying one file to another, it is a common practice for a program
to create a new file and propagate the owner, group, and mode.
If the source
file has an ACL, your program should propagate that ACL to the target file
in all cases where the mode is propagated.
21.4.2 ACL Replication
Programs that replicate permissions must preserve the ACL.
The
discretionary protection of a file or directory is no longer described by
the owner, group, and permissions; it includes the ACL which is a superset
of the permissions.
Neglecting to copy the ACL could allow unintended access
to the file or directory.
21.4.3 ACL Validity
Any ACL you create must be valid according to the following POSIX ACL rules:
It must have at least the three base entries
The user entries must have unique valid qualifiers
The group entries must have unique valid qualifiers
The user and group identifiers must be valid
You can use the
acl_valid
() routine to check your
ACLs.
21.5 ACL Creation Example
Assume that you want to set a file's access ACL to the following permissions:
user::rwx user:june:r-x user:sally:r-x group::rwx group:mktg:rwx other::r-x
The following code takes a tabular form of the ACL, creates a working storage representation of the ACL, and applies it to a file:
struct entries { acl_tag_t tag_type; char *qualifier; acl_permset_t perms; } table[] = { { USER_OBJ, NULL, ACL_PRDWREX }, { USER, "june", ACL_PRDEX }, { USER, "sally", ACL_PRDEX }, { GROUP_OBJ, NULL, ACL_PRDWREX }, { GROUP, "mktg", ACL_PRDWREX }, { OTHER_OBJ, NULL, ACL_PRDEX } }; #define TABLE_ENTRIES (sizeof(table)/sizeof(table[0])) acl_t acl_p; acl_entry_t entry_p; int i; uid_t uid; gid_t gid; /* allocate an ACL */ acl_init(&acl_p); [1] /* walk through the table and create entries */ for (i = 0; i < TABLE_ENTRIES; i++) { /* allocate the entry */ acl_create_entry(acl_p, &entry_p); [2] /* set the permissions */ acl_set_perm(entry_p, table[i].perms); /* setting the tag type and qualifier depends on the type */ switch (table[i].tag_type) { case USER: /* map user name to ID and specify as qualifier */ uid = pw_nametoid(table[i].qualifier); [3] acl_set_tag(entry_p, table[i].tag_type, (void *) uid); [4] break; case GROUP: /* map group name to ID and specify as qualifier */ gid = gr_nametoid(table[i].qualifier); [5] acl_set_tag(entry_p, table[i].tag_type, (void *) gid); break; default: /* qualifier is NULL for other types */ acl_set_tag(entry_p, table[i].tag_type, NULL); break; } } /* set the ACL on the file */ if (acl_set_file(filename, ACL_TYPE_ACCESS, acl_p) < 0) perror(filename); /* free storage allocated for the ACL */ acl_free(acl_p);
Notes:
This demonstrates the use of the initialization call for a working storage representation of the ACL. [Return to example]
A new ACL entry is allocated with this call. The tag type, qualifier, and permissions have an unspecified type. [Return to example]
The
pw_nametoid
() routine is an optimized
mapping from user name to ID.
It is described in the
pw_mapping
(3)
reference
page.
[Return to example]
The
acl_set_tag
() function takes a
void
argument for the qualifier, and casts it to the appropriate
data type depending on
obj_type.
[Return to example]
The
gr_nametoid
() routine is an optimized
mapping from group name to ID.
It is described in the
pw_mapping
(3)
reference
page.
[Return to example]
This section shows how a program can specify a default access ACL on a directory and then describes what happens when a file and a directory are created in that directory. There is another type of default ACL called a default directory ACL. ACLs are inherited differently if a directory has a default directory ACL in addition to or in place of a default access ACL. See Section 5.7 for a complete description of the ACL inheritance rules.
Assume that directory
/usr/john/acl_dir
has the
following access and default access ACLs:
#
getacl /usr/john/acl_dir
# file:/usr/john/acl_dir # owner:john # group:prog user::rwx user:june:r-x user:fred:r-x group::rwx group:mktg:rwx other::r-x#
getacl -d /usr/john/acl_dir
# file:/usr/john/acl_dir # owner:john # group:prog user::rwx user:june:r-x user:sally:r-x group::rwx group:mktg:rwx other::r-x
The following code updates the default access ACL to remove read and
write permission from the
mktg
group entry:
acl_permset_t perms; acl_id_type qualifier; acl_tag_t tag_type; acl_t acl; acl_entry_t acl_entry; char *filename; gid_t mktg_gid; /* map the "mktg" group name to an ID */ mktg_gid = gr_nametoid("mktg"); /* allocate an ACL entry */ acl_init(&acl); /* read the default ACL from the file */ acl=acl_get_file(filename, ACL_TYPE_DEFAULT); /* scan the ACL looking for the entry */ while (acl_get_entry(acl, &acl_entry) == 1) { /* retrieve the tag type and qualifier */ acl_get_tag(acl_entry, &tag_type, &qualifier); /* check for appropriate entry and remove 'r' and 'w' */ if (tag_type == GROUP && qualifier.acl_gid == mktg_gid) { acl_delete_perm(acl_entry, ACL_PRDWR); /* put the new default ACL on the file */ if (acl_set_file(filename, ACL_TYPE_DEFAULT, acl) < 0) { fprintf(stderr, "acl_set_file on "); psecerror(filename); } } }
The following code creates a file and a directory in the directory and demonstrates the ACL inheritance rules:
#define REGULAR_FILE "regular" #define DIRECTORY_FILE "dir" char pathname[100]; int fd; /* Create the regular file */ sprintf(pathname, "%s/%s", filename, REGULAR_FILE); fd = creat(pathname, 0644); /* Create the directory */ sprintf(pathname, "%s/%s", filename, DIRECTORY_FILE); mkdir(pathname, 0700);
When the preceding code is executed, the access ACL on the newly created file and the access and default access ACLs on the newly created directory are as follows:
#
getacl /usr/john/acl_dir/regular
# file:/usr/john/acl_dir/regular # owner:john # group:prog user::rw- user:june:r-x user:sally:r-x group::r-- group:mktg:--x other::r--
Note that the permissions for owning user, owning group, and other are
set to the logical AND of the default access ACL and the mode specified with
the
creat
() call.
The
umask
is not used
when ACL inheritance takes place.
The other entries are taken from the default
access ACL of the parent directory.
#
getacl /usr/john/acl_dir/dir
# file:/usr/john/acl_dir/dir # owner:john # group:prog user::rwx user:june:r-x user:sally:r-x group::--- group:mktg:--x other::---
Note that the inheritance rules for a subdirectory created in a directory that has a default access ACL are the same as those for a file. This is true only if there is not a default directory ACL on the parent directory in addition to the default access ACL.
#
getacl -d /usr/john/acl_dir/dir
# file:/usr/john/acl_dir/dir # owner:john # group:prog user::rwx user:june:r-x user:sally:r-x group::rwx group:mktg:--x other::r-x
Note that the default ACL is inherited from the directory's parent.