aclutils.c revision f48205be61a214698b763ff550ab9e657525104c
fa9e4066f08beec538e775443c5be79dd423fcabahrens * CDDL HEADER START
fa9e4066f08beec538e775443c5be79dd423fcabahrens * The contents of this file are subject to the terms of the
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks * Common Development and Distribution License (the "License").
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks * You may not use this file except in compliance with the License.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
fa9e4066f08beec538e775443c5be79dd423fcabahrens * See the License for the specific language governing permissions
fa9e4066f08beec538e775443c5be79dd423fcabahrens * and limitations under the License.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * When distributing Covered Code, include this CDDL HEADER in each
fa9e4066f08beec538e775443c5be79dd423fcabahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * If applicable, add the following below this CDDL HEADER, with the
fa9e4066f08beec538e775443c5be79dd423fcabahrens * fields enclosed by brackets "[]" replaced with your own identifying
fa9e4066f08beec538e775443c5be79dd423fcabahrens * information: Portions Copyright [yyyy] [name of copyright owner]
fa9e4066f08beec538e775443c5be79dd423fcabahrens * CDDL HEADER END
f48205be61a214698b763ff550ab9e657525104ccasper * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Use is subject to license terms.
fa9e4066f08beec538e775443c5be79dd423fcabahrens#pragma ident "%Z%%M% %I% %E% SMI"
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks ACE_NO_PROPAGATE_INHERIT_ACE | ACE_INHERIT_ONLY_ACE | \
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks ACE_SUCCESSFUL_ACCESS_ACE_FLAG | ACE_FAILED_ACCESS_ACE_FLAG | \
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks ACE_IDENTIFIER_GROUP | ACE_OWNER | ACE_GROUP | ACE_EVERYONE)
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks * ACL conversion helpers
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491markstypedef enum {
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491markstypedef struct acevals {
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491markstypedef struct ace_list {
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks int seen; /* bitmask of all aclent_t a_type values seen */
fa9e4066f08beec538e775443c5be79dd423fcabahrenstypedef union {
fa9e4066f08beec538e775443c5be79dd423fcabahrens const char *file;
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Free acl_t structure
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Determine whether a file has a trivial ACL
fa9e4066f08beec538e775443c5be79dd423fcabahrens * returns: 0 = trivial
fa9e4066f08beec538e775443c5be79dd423fcabahrens * 1 = nontrivial
fa9e4066f08beec538e775443c5be79dd423fcabahrens * <0 some other system failure, such as ENOENT or EPERM
d2443e765650e70b88cd0346e67d2aee6dd1ea3amarks return (-1);
d2443e765650e70b88cd0346e67d2aee6dd1ea3amarks return (-1);
fa9e4066f08beec538e775443c5be79dd423fcabahrensaccess_mask_set(int haswriteperm, int hasreadperm, int isowner, int isallow)
fa9e4066f08beec538e775443c5be79dd423fcabahrens * If the entity is not the owner and does not
fa9e4066f08beec538e775443c5be79dd423fcabahrens * have write permissions ACE_WRITE_ATTRIBUTES will
fa9e4066f08beec538e775443c5be79dd423fcabahrens * always go in the DENY ACE.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Given an mode_t, convert it into an access_mask as used
fa9e4066f08beec538e775443c5be79dd423fcabahrens * by nfsace, assuming aclent_t -> nfsace semantics.
fa9e4066f08beec538e775443c5be79dd423fcabahrensmode_to_ace_access(mode_t mode, int isdir, int isowner, int isallow)
fa9e4066f08beec538e775443c5be79dd423fcabahrens * The following call takes care of correctly setting the following
fa9e4066f08beec538e775443c5be79dd423fcabahrens * mask bits in the access_mask:
fa9e4066f08beec538e775443c5be79dd423fcabahrens * ACE_SYNCHRONIZE, ACE_WRITE_OWNER, ACE_DELETE,
fa9e4066f08beec538e775443c5be79dd423fcabahrens * ACE_WRITE_ATTRIBUTES, ACE_WRITE_NAMED_ATTRS, ACE_READ_NAMED_ATTRS
fa9e4066f08beec538e775443c5be79dd423fcabahrens access = access_mask_set(haswriteperm, hasreadperm, isowner, isallow);
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* write */
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Given an nfsace (presumably an ALLOW entry), make a
fa9e4066f08beec538e775443c5be79dd423fcabahrens * corresponding DENY entry at the address given.
fa9e4066f08beec538e775443c5be79dd423fcabahrensace_make_deny(ace_t *allow, ace_t *deny, int isdir, int isowner)
fa9e4066f08beec538e775443c5be79dd423fcabahrens deny->a_access_mask &= ~(ACE_SYNCHRONIZE | ACE_WRITE_OWNER |
fa9e4066f08beec538e775443c5be79dd423fcabahrens ACE_DELETE | ACE_WRITE_ATTRIBUTES | ACE_READ_NAMED_ATTRS |
fa9e4066f08beec538e775443c5be79dd423fcabahrens deny->a_access_mask |= access_mask_set((allow->a_access_mask &
fa9e4066f08beec538e775443c5be79dd423fcabahrens ACE_WRITE_DATA), (allow->a_access_mask & ACE_READ_DATA), isowner,
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Make an initial pass over an array of aclent_t's. Gather
fa9e4066f08beec538e775443c5be79dd423fcabahrens * information such as an ACL_MASK (if any), number of users,
fa9e4066f08beec538e775443c5be79dd423fcabahrens * number of groups, and whether the array needs to be sorted.
fa9e4066f08beec538e775443c5be79dd423fcabahrens for (i = 0; i < n; i++) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Convert an array of aclent_t into an array of nfsace entries,
fa9e4066f08beec538e775443c5be79dd423fcabahrens * following POSIX draft -> nfsv4 conversion semantics as outlined in
fa9e4066f08beec538e775443c5be79dd423fcabahrens * the IETF draft.
fa9e4066f08beec538e775443c5be79dd423fcabahrensln_aent_to_ace(aclent_t *aclent, int n, ace_t **acepp, int *rescount, int isdir)
fa9e4066f08beec538e775443c5be79dd423fcabahrens error = ln_aent_preprocess(aclent, n, &hasmask, &mask,
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* allow + deny for each aclent */
fa9e4066f08beec538e775443c5be79dd423fcabahrens * stick extra deny on the group_obj and on each
fa9e4066f08beec538e775443c5be79dd423fcabahrens * user|group for the mask (the group_obj was added
fa9e4066f08beec538e775443c5be79dd423fcabahrens * into the count for numgroup)
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* ... and don't count the mask itself */
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* sort the source if necessary */
fa9e4066f08beec538e775443c5be79dd423fcabahrens ksort((caddr_t)aclent, n, sizeof (aclent_t), cmp2acls);
fa9e4066f08beec538e775443c5be79dd423fcabahrens result = acep = calloc(1, resultsize * sizeof (ace_t));
fa9e4066f08beec538e775443c5be79dd423fcabahrens for (i = 0; i < n; i++) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens * don't process CLASS_OBJ (mask); mask was grabbed in
fa9e4066f08beec538e775443c5be79dd423fcabahrens * ln_aent_preprocess()
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* If we need an ACL_MASK emulator, prepend it now */
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Set the access mask for the prepended deny
fa9e4066f08beec538e775443c5be79dd423fcabahrens * ace. To do this, we invert the mask (found
fa9e4066f08beec538e775443c5be79dd423fcabahrens * in ln_aent_preprocess()) then convert it to an
fa9e4066f08beec538e775443c5be79dd423fcabahrens * DENY ace access_mask.
fa9e4066f08beec538e775443c5be79dd423fcabahrens acep->a_access_mask = mode_to_ace_access((mask ^ 07),
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* handle a_perm -> access_mask */
fa9e4066f08beec538e775443c5be79dd423fcabahrens acep->a_access_mask = mode_to_ace_access(aclent[i].a_perm,
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* emulate a default aclent */
fa9e4066f08beec538e775443c5be79dd423fcabahrens * handle a_perm and a_id
fa9e4066f08beec538e775443c5be79dd423fcabahrens * this must be done last, since it involves the
fa9e4066f08beec538e775443c5be79dd423fcabahrens * corresponding deny aces, which are handled
fa9e4066f08beec538e775443c5be79dd423fcabahrens * differently for each different a_type.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Set the corresponding deny for the group ace.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * The deny aces go after all of the groups, unlike
fa9e4066f08beec538e775443c5be79dd423fcabahrens * everything else, where they immediately follow
fa9e4066f08beec538e775443c5be79dd423fcabahrens * the allow ace.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * We calculate "skip", the number of slots to
fa9e4066f08beec538e775443c5be79dd423fcabahrens * skip ahead for the deny ace, here.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * The pattern is:
fa9e4066f08beec538e775443c5be79dd423fcabahrens * MD1 A1 MD2 A2 MD3 A3 D1 D2 D3
fa9e4066f08beec538e775443c5be79dd423fcabahrens * thus, skip is
fa9e4066f08beec538e775443c5be79dd423fcabahrens * (2 * numgroup) - 1 - groupi
fa9e4066f08beec538e775443c5be79dd423fcabahrens * (2 * numgroup) to account for MD + A
fa9e4066f08beec538e775443c5be79dd423fcabahrens * - 1 to account for the fact that we're on the
fa9e4066f08beec538e775443c5be79dd423fcabahrens * access (A), not the mask (MD)
fa9e4066f08beec538e775443c5be79dd423fcabahrens * - groupi to account for the fact that we have
fa9e4066f08beec538e775443c5be79dd423fcabahrens * passed up groupi number of MD's.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * If we just did the last group, skip acep past
fa9e4066f08beec538e775443c5be79dd423fcabahrens * all of the denies; else, just move ahead one.
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (error != 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrensconvert_aent_to_ace(aclent_t *aclentp, int aclcnt, int isdir,
fa9e4066f08beec538e775443c5be79dd423fcabahrens ksort((caddr_t)aclentp, aclcnt, sizeof (aclent_t), cmp2acls);
fa9e4066f08beec538e775443c5be79dd423fcabahrens for (i = 0, aclp = aclentp; i < aclcnt; aclp++, i++) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (-1);
fa9e4066f08beec538e775443c5be79dd423fcabahrens error = ln_aent_to_ace(aclentp, i, &acep, &acecnt, isdir);
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (-1);
fa9e4066f08beec538e775443c5be79dd423fcabahrens error = ln_aent_to_ace(&aclentp[dfaclstart], dfaclcnt,
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (-1);
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks acep = realloc(acep, sizeof (ace_t) * (acecnt + dfacecnt));
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks return (-1);
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks * Find or create an acevals holder for a given id and avl tree.
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks * Note that only one thread will ever touch these avl trees, so
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks * there is no need for locking.
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks /* this memory is freed by ln_ace_to_aent()->ace_list_free() */
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marksaccess_mask_check(ace_t *acep, int mask_bit, int isowner)
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks haswriteperm = (acep->a_access_mask & ACE_WRITE_DATA) ? 0 : 1;
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks hasreadperm = (acep->a_access_mask & ACE_READ_DATA) ? 0 : 1;
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks haswriteperm = (acep->a_access_mask & ACE_WRITE_DATA) ? 1 : 0;
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks hasreadperm = (acep->a_access_mask & ACE_READ_DATA) ? 1 : 0;
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks } else if (haswriteperm) {
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks return (0);
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks return (0);
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks return (0);
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks /* ACE_ACCESS_ALLOWED_ACE_TYPE */
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks return (0);
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks /* only ALLOW or DENY */
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks /* check for invalid flags */
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks /* some flags are illegal */
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks /* check for invalid masks */
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks error = access_mask_check(acep, ACE_SYNCHRONIZE, isowner);
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks error = access_mask_check(acep, ACE_WRITE_OWNER, isowner);
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks error = access_mask_check(acep, ACE_WRITE_ATTRIBUTES, isowner);
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks error = access_mask_check(acep, ACE_READ_NAMED_ATTRS, isowner);
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks error = access_mask_check(acep, ACE_WRITE_NAMED_ATTRS, isowner);
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks /* more detailed checking of masks */
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks /* ACL enforcement */
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marksace_mask_to_mode(uint32_t mask, o_mode_t *modep, int isdir)
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks /* write */
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks if (bits != 0) {
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marksace_allow_to_mode(uint32_t mask, o_mode_t *modep, int isdir)
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks /* ACE_READ_ACL and ACE_READ_ATTRIBUTES must both be set */
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marksacevals_to_aent(acevals_t *vals, aclent_t *dest, ace_list_t *list,
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks if ((list->hasmask) && (list->acl_mask != vals->mask) &&
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks error = ace_allow_to_mode(vals->allowed, &dest->a_perm, isdir);
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marksace_list_to_aent(ace_list_t *list, aclent_t **aclentp, int *aclcnt,
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks if ((list->seen & (USER_OBJ | GROUP_OBJ | OTHER_OBJ)) !=
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks if ((! list->hasmask) && (list->numusers + list->numgroups > 0)) {
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks * This must be the same condition as below, when we add the CLASS_OBJ
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks * (aka ACL mask)
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks result = aent = calloc(1, resultcount * sizeof (aclent_t));
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks /* USER_OBJ */
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks error = acevals_to_aent(&list->user_obj, aent, list, owner, group,
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks error = acevals_to_aent(vals, aent, list, owner, group,
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks /* GROUP_OBJ */
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks error = acevals_to_aent(&list->group_obj, aent, list, owner, group,
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks /* GROUP */
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks error = acevals_to_aent(vals, aent, list, owner, group,
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks * CLASS_OBJ (aka ACL_MASK)
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks * An ACL_MASK is not fabricated if the ACL is a default ACL.
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks * This is to follow UFS's behavior.
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks /* fabricate the ACL_MASK from the group permissions */
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks /* OTHER_OBJ */
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks error = acevals_to_aent(&list->other_obj, aent, list, owner, group,
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks if (error != 0) {
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks * free all data associated with an ace_list
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks while ((node = avl_destroy_nodes(&al->user, &cookie)) != NULL)
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks while ((node = avl_destroy_nodes(&al->group, &cookie)) != NULL)
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks /* free the container itself */
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks return (0);
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks return (1);
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks return (-1);
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks * Convert a list of ace_t entries to equivalent regular and default
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks * aclent_t lists. Return error (ENOTSUP) when conversion is not possible.
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marksln_ace_to_aent(ace_t *ace, int n, uid_t owner, gid_t group,
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks aclent_t **aclentp, int *aclcnt, aclent_t **dfaclentp, int *dfaclcnt,
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks /* we need at least user_obj, group_obj, and other_obj */
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks if (n < 6) {
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks avl_create(&normacl->user, acevals_compare, sizeof (acevals_t),
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks avl_create(&normacl->group, acevals_compare, sizeof (acevals_t),
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks avl_create(&dfacl->user, acevals_compare, sizeof (acevals_t),
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks avl_create(&dfacl->group, acevals_compare, sizeof (acevals_t),
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks /* process every ace_t... */
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks for (i = 0; i < n; i++) {
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks /* rule out certain cases quickly */
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks * Turn off these bits in order to not have to worry about
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks * them when doing the checks for compliments.
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks acep->a_access_mask &= ~(ACE_WRITE_OWNER | ACE_DELETE |
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks /* see if this should be a regular or default acl */
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks if (bits != 0) {
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks /* all or nothing on these inherit bits */
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks /* no more than one allowed per aclent_t */
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks * it's a DENY; if there was a previous DENY, it
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks * must have been an ACL_MASK.
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks /* ACL_MASK is for USER and GROUP only */
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks /* check for mismatched ACL_MASK emulations */
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks /* done collating; produce the aclent_t lists */
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks if (error != 0) {
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks if (error != 0) {
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marksconvert_ace_to_aent(ace_t *acebufp, int acecnt, int isdir,
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks uid_t owner, gid_t group, aclent_t **retaclentp, int *retaclcnt)
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks * Slap aclentp and dfaclentp into a single array.
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks aclentp = realloc(aclentp, (sizeof (aclent_t) * aclcnt) +
fa9e4066f08beec538e775443c5be79dd423fcabahrenscacl_get(acl_inp inp, int get_flag, int type, acl_t **aclp)
fa9e4066f08beec538e775443c5be79dd423fcabahrens const char *fname;
fa9e4066f08beec538e775443c5be79dd423fcabahrens * if acl's aren't supported then
fa9e4066f08beec538e775443c5be79dd423fcabahrens * send it through the old GETACL interface
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (-1);
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (-1);
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens malloc(acl_info->acl_cnt * acl_info->acl_entry_size);
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (-1);
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (-1);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (ace_trivial(acl_info->acl_aclp, acl_info->acl_cnt) == 0)
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (-1);
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens * return -1 on failure, otherwise the number of acl
fa9e4066f08beec538e775443c5be79dd423fcabahrens * entries is returned
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (cacl_get(acl_inp, get_flag, ACL_PATH, aclp));
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marksacl_translate(acl_t *aclp, int target_flavor, int isdir, uid_t owner,
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks * See if we need to translate
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks if ((target_flavor == _ACL_ACE_ENABLED && aclp->acl_type == ACE_T) ||
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks return (0);
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks return (-1);
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks return (-1);
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks error = convert_ace_to_aent(aclp->acl_aclp, aclp->acl_cnt,
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks return (-1);
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks return (-1);
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks * replace old acl with newly translated acl
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks aclp->acl_type = (target_flavor == _ACL_ACE_ENABLED) ? ACE_T : ACLENT_T;
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Set an ACL, translates acl to ace_t when appropriate.
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (-1);
fa9e4066f08beec538e775443c5be79dd423fcabahrens acl_flavor_target = pathconf(acl_inp->file, _PC_ACL_ENABLED);
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (-1);
fa9e4066f08beec538e775443c5be79dd423fcabahrens acl_flavor_target = fpathconf(acl_inp->fd, _PC_ACL_ENABLED);
a222db82aa8aaee84f3cba02cf799fe851fa7ac3marks * If target returns an error or 0 from pathconf call then
a222db82aa8aaee84f3cba02cf799fe851fa7ac3marks * fall back to UFS/POSIX Draft interface.
a222db82aa8aaee84f3cba02cf799fe851fa7ac3marks * In the case of 0 we will then fail in either acl(2) or
a222db82aa8aaee84f3cba02cf799fe851fa7ac3marks * acl_translate(). We could erroneously get 0 back from
a222db82aa8aaee84f3cba02cf799fe851fa7ac3marks * a file system that is using fs_pathconf() and not answering
a222db82aa8aaee84f3cba02cf799fe851fa7ac3marks * the _PC_ACL_ENABLED question itself.
a222db82aa8aaee84f3cba02cf799fe851fa7ac3marks if (acl_flavor_target == 0 || acl_flavor_target == -1)
3eb3c57322eccc9d4c2880c26f57ceb5a85c2491marks if ((error = acl_translate(aclp, acl_flavor_target, isdir,
fa9e4066f08beec538e775443c5be79dd423fcabahrens newaclp->acl_aclp = malloc(aclp->acl_entry_size * aclp->acl_cnt);
fa9e4066f08beec538e775443c5be79dd423fcabahrens aclp->acl_aclp, aclp->acl_entry_size * aclp->acl_cnt);
49f0e51890161901ae4f49c7a47602d97b52b934marks * Take an acl array and build an acl_t.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Remove an ACL from a file and create a trivial ACL based
fa9e4066f08beec538e775443c5be79dd423fcabahrens * off of the mode argument. After acl has been set owner/group
fa9e4066f08beec538e775443c5be79dd423fcabahrens * are updated to match owner,group arguments
fa9e4066f08beec538e775443c5be79dd423fcabahrensacl_strip(const char *file, uid_t owner, gid_t group, mode_t mode)
fa9e4066f08beec538e775443c5be79dd423fcabahrens ace_t min_ace_acl[6]; /* owner, group, everyone + complement denies */
fa9e4066f08beec538e775443c5be79dd423fcabahrens * force it through aclent flavor when file system doesn't
fa9e4066f08beec538e775443c5be79dd423fcabahrens * understand question
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) memcpy(min_ace_acl, trivial_acl, sizeof (ace_t) * 6);
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Make aces match request mode
fa9e4066f08beec538e775443c5be79dd423fcabahrens adjust_ace_pair(&min_ace_acl[0], (mode & 0700) >> 6);
fa9e4066f08beec538e775443c5be79dd423fcabahrens adjust_ace_pair(&min_ace_acl[2], (mode & 0070) >> 3);
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Need to fixup who field for abstrations for
fa9e4066f08beec538e775443c5be79dd423fcabahrens * accurate comparison, since field is undefined.
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (ace1.a_flags & (ACE_OWNER|ACE_GROUP|ACE_EVERYONE))
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (ace2.a_flags & (ACE_OWNER|ACE_GROUP|ACE_EVERYONE))
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (memcmp(aclent1, aclent2, sizeof (aclent_t)));
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Find acl entries in acl that correspond to removeacl. Search
fa9e4066f08beec538e775443c5be79dd423fcabahrens * is started from slot. The flag argument indicates whether to
fa9e4066f08beec538e775443c5be79dd423fcabahrens * remove all matches or just the first match.
fa9e4066f08beec538e775443c5be79dd423fcabahrensacl_removeentries(acl_t *acl, acl_t *removeacl, int start_slot, int flag)
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (flag != ACL_REMOVE_ALL && flag != ACL_REMOVE_FIRST)
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (match == 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens * List has changed, restart search from
fa9e4066f08beec538e775443c5be79dd423fcabahrens * beginning.
fa9e4066f08beec538e775443c5be79dd423fcabahrens acl_entry = ((char *)acl_entry + acl->acl_entry_size);
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Replace entires entries in acl1 with the corresponding entries
fa9e4066f08beec538e775443c5be79dd423fcabahrens * in newentries. The where argument specifies where to begin
fa9e4066f08beec538e775443c5be79dd423fcabahrens * the replacement. If the where argument is 1 greater than the
fa9e4066f08beec538e775443c5be79dd423fcabahrens * number of acl entries in acl1 then they are appended. If the
fa9e4066f08beec538e775443c5be79dd423fcabahrens * where argument is 2+ greater than the number of acl entries then
fa9e4066f08beec538e775443c5be79dd423fcabahrens * EACL_INVALID_SLOT is returned.
fa9e4066f08beec538e775443c5be79dd423fcabahrensacl_modifyentries(acl_t *acl1, acl_t *newentries, int where)
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (-1);
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) memcpy((char *)acl1->acl_aclp + (acl1->acl_entry_size * slot),
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Did ACL grow?
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Add acl2 entries into acl1. The where argument specifies where
fa9e4066f08beec538e775443c5be79dd423fcabahrens * to add the entries.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * allow where to specify 1 past last slot for an append operation
fa9e4066f08beec538e775443c5be79dd423fcabahrens * but anything greater is an error.
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (-1);
fa9e4066f08beec538e775443c5be79dd423fcabahrens * first push down entries where new ones will be inserted
fa9e4066f08beec538e775443c5be79dd423fcabahrens len = (acl1->acl_cnt - where) * acl1->acl_entry_size;
fa9e4066f08beec538e775443c5be79dd423fcabahrens * now stick in new entries.
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens * return text for an ACL error.
5a5eeccada4b11bc692e9a5015d5f4a4f188226cmarks "There is more than one group or default group entry"));
5a5eeccada4b11bc692e9a5015d5f4a4f188226cmarks "There is more than one user or default user entry"));
fa9e4066f08beec538e775443c5be79dd423fcabahrens "There is more than one other entry"));
fa9e4066f08beec538e775443c5be79dd423fcabahrens "There is more than one mask entry"));
fa9e4066f08beec538e775443c5be79dd423fcabahrens "Duplicate user or group entries"));
fa9e4066f08beec538e775443c5be79dd423fcabahrens "Missing user/group owner, other, mask entry"));
fa9e4066f08beec538e775443c5be79dd423fcabahrens "Memory error"));
fa9e4066f08beec538e775443c5be79dd423fcabahrens "Unrecognized entry type"));
fa9e4066f08beec538e775443c5be79dd423fcabahrens "Invalid inheritance flags"));
fa9e4066f08beec538e775443c5be79dd423fcabahrens "Unrecognized entry flags"));
fa9e4066f08beec538e775443c5be79dd423fcabahrens "Invalid ACL permissions"));
fa9e4066f08beec538e775443c5be79dd423fcabahrens "Invalid ACL count"));
fa9e4066f08beec538e775443c5be79dd423fcabahrens "Invalid ACL entry number specified"));
fa9e4066f08beec538e775443c5be79dd423fcabahrens "ACL entry doesn't exist"));
fa9e4066f08beec538e775443c5be79dd423fcabahrens "ACL type's are different"));
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (dgettext(TEXT_DOMAIN, "Invalid user or group"));
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (dgettext(TEXT_DOMAIN, "ACL string is invalid"));
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (dgettext(TEXT_DOMAIN, "Field expected to be blank"));
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (dgettext(TEXT_DOMAIN, "Invalid access type"));
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (dgettext(TEXT_DOMAIN, "Unrecognized entry"));
fa9e4066f08beec538e775443c5be79dd423fcabahrens "ACL specification missing required fields"));
fa9e4066f08beec538e775443c5be79dd423fcabahrens "Inheritance flags are only allowed on directories"));
5a5eeccada4b11bc692e9a5015d5f4a4f188226cmarks/* PRINTFLIKE1 */