[Return to Library] [Contents] [Previous Chapter] [Next Section] [Next Chapter] [Index] [Help]


21    Programming With ACLs

This chapter discusses the following topics:

Note

The ACL library routines (-lpacl) are not thread safe.

The Digital UNIX ACLs are based on the POSIX P1003.6 Draft 13 standard. The ACL library routines may change in the final version of the standard.


[Return to Library] [Contents] [Previous Chapter] [Next Section] [Next Chapter] [Index] [Help]


21.1    Introduction to ACLs

Aaccess control lists (ACLs) are the method used to implement discretionary access control (DAC). ACLs provide a more granular discretionary access control mechanism than traditional UNIX permission bits. All objects are considered to be protected by an ACL. An object protected by traditional UNIX DAC has a base entry ACL. If additional entries are added to the ACL, they are evaluated according to entry type by rules defined by the POSIX specification.

The POSIX ACL policy has been defined by the POSIX P1003.6 DAC security specification and features the following:

In addition to the POSIX ACLs, Digital UNIX provides enhanced library interfaces.

You can apply ACLs to any traditional UNIX file system object that has permission bits that are used for access control, such as files and directories. Symbolic links have permission bits that are initialized according to the usual rules but are never used for access control; ACLs on this file type are not supported. The guidelines in this chapter apply to all objects that may be protected by ACLs.

Refer to the acl(4) reference page for a description of POSIX ACL support.


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


21.2    Library Routines

Table 21-1 lists the ACL library routines:

Table 21-1: ACL Library Routines

Routine Description
acl_add_perm() Add a set of permissions
acl_clear_perm() Clear the permissions
acl_convert_posix() Remove non-POSIX entries from an ACL
acl_copy_entry() Copy an ACL entry
acl_copy_ext() Copies an ACL from system to user space
acl_copy_int() Copies an ACL from user to system space
acl_create_entry() Create a new ACL entry
acl_delete_def_fd() Delete the default ACL from a directory
acl_delete_def_file() Delete the default ACL from a file
acl_delete_entry() Delete an entry
acl_delete_perm() Delete a set of permissions
acl_dup() Create a duplicate ACL
acl_first_entry() Move current entry to first entry
acl_free() Free the ACL working storage memory
acl_free_qualifier() Free the acl_id entry in an ACL
acl_free_text() Free the ACL text working storage memory
acl_from_text() Convert the text ACL to the internal representation
acl_get_entry() Get the descriptor to an ACL
acl_get_fd() Get ACL using the file descriptor
acl_get_file() Retrieve an ACL
acl_get_permset() Retrieve the permissions for an ACL
acl_get_qualifier() Retrieve the ID from the current ACL
acl_get_tag_type() Retrieve the entry type identifier
acl_init() Allocate and initialize ACL working storage
acl_locate_entry() Locate an entry in an ACL
acl_set_fd() Set the ACL by the file descriptor
acl_set_file() Set the ACL by the pathname
acl_set_permset() Set permissions in a ACL entry
acl_set_qualifier() Set the ACL entry type
acl_set_tag_type() Set the ACL entry type
acl_size() Determine the size of an ACL
acl_to_text() Convert an IR to an ASCII string
acl_validate_and_sort() Check ACL for validity and sort for decision order


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


21.3    Discretionary Access Terms

Table 21-2 describes the terms used with discretionary access to objects:

Table 21-2: Discretionary Access Terms

Term Definition
Read access Either the subject is granted read permission by the object's mode and ACL, or the subject is root.
Write access Either the subject is granted write permission by the object's mode and ACL, or the subject is root.
Execute access Either the subject is granted execute permission by the object's mode and ACL, or the subject is root.
Search access Either the subject is granted search permission by the directory's mode or the subject is root.
Owner access Either the subject's EUID is the same as the object's UID, or the subject is root.


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


21.4    ACL Data Representations

Two internal ACL data structures are defined by the POSIX specification. In addition, there is a textual representation for ACLs that is presented to the user. You must be careful not to mix data structures when using the ACL system calls and library routines.

All data representations use the following basic types, most of which are required by the POSIX ACL specification:

typedef unsigned short  acl_tag_t;
typedef unsigned short  acl_permset_t;

 
/* acl_tag_t values */
 
#define BOGUS_OBJ 0 #define USER_OBJ 1 #define USER 3 #define GROUP_OBJ 4 #define GROUP 5 #define OTHER_OBJ 6
 
/* acl_permset_t values */
 
#define ACL_NOPERM 0x0 #define ACL_PEXECUTE 0x1 #define ACL_PWRITE 0x2 #define ACL_PREAD 0x4
 
/* tag qualifier type */
 
typedef union { uid_t _acl_uid; gid_t _acl_gid; } acl_id;


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


21.4.1    Working Storage Representation

Many of the ACL routines operate on 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, your 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. The working storage representation of an ACL can be converted to other representations of an ACL, as described in Section 21.4.2.


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


21.4.2    Data Package Representation

The data package represents an ACL in a contiguous section of memory that is independent of the process address space in which it resides. The data package can be passed between processes or stored in a file because it is contiguous and does not have internal pointer references.

The data structure associated with the data package is visible at the programmer interface. It contains a header that includes the number of entries in the ACL and a magic number to identify the data structure type, followed by an array of ACL entries that contain the tag type, permissions, and qualifier.

The following structure describes the header:

/*
 *      Header for data package type.
 */

 
typedef struct { ushort acl_num; ushort acl_magic; } aclh_t;

In addition to including the header, the data structure for the data package includes an array of ACL entries of the following format:

/*
 *      Descriptor for a specific ACL entry
 *      in internal representation.
 */
typedef struct {
        acl_tag_t       acl_tag;
        acl_permset_t   acl_perm;
        acl_id          acl_id;
} acle_t;
/*
 *      Descriptor for specific ACL entry
 *      in (data package format).
 */
struct acl_data {
       aclh_t       acl_hdr;
/*     acle_t       *acl_entry;  comment; acl entries follow */
};
typedef struct acl_data         *acl_data_t;

The following code fragment operates on all entries in a data package ACL representation:

        acl_data_t     data_p;
        acle_t         *entry_p;
        int            i;

 
entry_p = (acle_t *) (data_p + 1); /* The pointer arithmetic addresses the first acl entry.*/ for (i = 0; i < data_p->acl_num; i++, entry_p++) { /* reference the ACL entries through entry_p */ }


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


21.4.3    External Representation

The external representation is a textual, human readable version of the ACL that corresponds to the text package described in the POSIX specification and the acl(4) reference page. The external representation is composed of a sequence of lines, each of which is terminated by a newline character. Table 21-3 shows how the individual entries are structured.

Table 21-3: 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 external representation is used by the POSIX routines that convert between the working storage representation and the text package.


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


21.5    Default ACLs

The POSIX specification allows a default access ACL to be associated with directories. When a directory has a default access ACL, files and directories created in the directory are protected with DAC attributes that are derived from the default ACL and the mode that is specified on the object creation system call. You can set a default access ACL on a directory by using the acl_write() call with a second argument of ACL_TYPE_DEFAULT. You can retrieve a default ACL by using the acl_read() call with a second argument of ACL_TYPE_DEFAULT.

Note that, although the system consults the owner and group of the directory when it is checking for access against the access ACL, the owner and group are not inherited from the default access ACL when a file is created in a directory that has a default access ACL. The default access ACL does not include an owner and group ID. Rather, the base user and group entries include permissions that are used when computing the access ACL for a file; the file owner is set from the process and the group is inherited from the parent directory.

The Digital UNIX system provides an extension of the POSIX ACLs in the form of an added default directory ACL type that can be used by other ACL implementations (for example, the Distributed Computing Environment (DCE)). This ACL is ACL_TYPE_DEFAULT_DIR and is used for directories only. If a parent directory has ACL_TYPE_DEFAULT_DIR, then new directories are set to the parents ACL_TYPE_DEFAULT_DIR.

The inheritance rules are described in detail in the acl(4) reference page and Section 5.9 of this manual.


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


21.6    ACL Rules

Some interactions between the ACL and the UNIX permissions are subtle, and you may end up with different permissions than you intended because of the way that ACL system calls interact with the system calls that manipulate the UNIX DAC attributes.

The following sections describe rules for programs that handle ACLs.


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


21.6.1    Object Creation

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. The program must now handle the possibility that the file may also be protected by an ACL. Your program should propagate the ACL in all cases where the UNIX DAC attributes would be propagated.

When the parent directory of the file to be created has a default ACL, the owner of the created file is inherited from the process and the group is inherited from the parent directory. In addition, the specified mode is used instead of the process umask. Therefore, your program must specify a proper mode on the object creation system call and must not depend on the umask to properly protect objects.


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


21.6.2    ACL Replication

ACLs are preserved automatically in programs that replicate permissions.


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


21.6.3    ACL Validity

The ACL must be valid according to the following POSIX ACL rules:


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


21.7    ACL Creation Example

Assume that you want to set up a file's access ACL as follows:

user::rwx
user:june:r-x
user:sally:r-x

 
group::rwx group:mktg:rwx
 
other::r-x

The following code takes the 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_alloc(&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_write(filename, ACL_TYPE_ACCESS, acl_p) < 0) perror(filename);
 
/* free storage allocated for the ACL */
 
acl_free(acl_p);

Notes:

  1. This demonstrates the use of the allocation call for a working storage representation of the ACL. [Return to example]

  2. A new ACL entry is allocated with this call. The tag type, qualifier, and permissions have an unspecified type. [Return to example]

  3. The pw_nametoid() routine is an optimized mapping from user name to ID. It is described in the map_ids() reference page. [Return to example]

  4. 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]

  5. The gr_nametoid() routine is an optimized mapping from group name to ID. It is described in the map_ids() reference page. [Return to example]


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


21.8    Imported and Exported Data

When imported and exported objects with ACLs are accessed, several issues arise that vary depending on the scenario.


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


21.8.1    Digital UNIX System to Same Digital UNIX System

From a Digital UNIX system to the same Digital UNIX system, the ACL does not have to be converted from the internal to the external format. It can be saved in its compacted data format. This saves the effort of having to convert the ACL from the external to internal format and back.


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


21.8.2    Digital UNIX System to Another Digital UNIX System

If the two Digital UNIX systems have the exact same password and group files (that is, these files are distributed using NIS or some other means), then saving the ACL is done the same as from a Digital UNIX system to the same Digital UNIX system. If the systems do not share the same password and group files, then the ACLs must be converted to the external format when backing up. If this is not done, unintended access may be granted to the files being restored. Also, this ensures that all the UIDs and GIDs are known.


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


21.8.3    Digital UNIX System to Other

If you are exporting data to another machine, the remote system's ACL policy needs to be based on Draft 13 of POSIX P1003.6 (or something compatible).


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Chapter] [Index] [Help]


21.8.4    Other to Digital UNIX System

When importing data containing ACLs from another vendor's machine, the ACL format must be based on Draft 13 of POSIX P1003.6. The ACL is validated and then set on the object if valid. If the ACL cannot be set on the object being restored, 0700 is added to the standard UNIX permissions.