acl_calc_mask.c revision 90781
174432Sjedgar/*
290781Sjedgar * Copyright (c) 2001-2002 Chris D. Faulhaber
374432Sjedgar * All rights reserved.
474432Sjedgar *
574432Sjedgar * Redistribution and use in source and binary forms, with or without
674432Sjedgar * modification, are permitted provided that the following conditions
774432Sjedgar * are met:
874432Sjedgar * 1. Redistributions of source code must retain the above copyright
974432Sjedgar *    notice, this list of conditions and the following disclaimer.
1074432Sjedgar * 2. Redistributions in binary form must reproduce the above copyright
1174432Sjedgar *    notice, this list of conditions and the following disclaimer in the
1274432Sjedgar *    documentation and/or other materials provided with the distribution.
1374432Sjedgar *
1474432Sjedgar * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1574432Sjedgar * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1674432Sjedgar * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1774432Sjedgar * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR THE VOICES IN HIS HEAD BE
1874432Sjedgar * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
1974432Sjedgar * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2074432Sjedgar * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2174432Sjedgar * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2274432Sjedgar * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2374432Sjedgar * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2474432Sjedgar * POSSIBILITY OF SUCH DAMAGE.
2574432Sjedgar *
2674432Sjedgar * $FreeBSD: head/lib/libc/posix1e/acl_calc_mask.c 90781 2002-02-17 20:05:20Z jedgar $
2774432Sjedgar */
2874432Sjedgar
2974432Sjedgar#include <sys/types.h>
3075185Stmm#include "namespace.h"
3174432Sjedgar#include <sys/acl.h>
3275185Stmm#include "un-namespace.h"
3374432Sjedgar
3474432Sjedgar#include <errno.h>
3575928Sjedgar#include <stdio.h>
3674432Sjedgar
3774432Sjedgar/*
3875928Sjedgar * acl_calc_mask() (23.4.2): calculate and set the permissions
3975928Sjedgar * associated with the ACL_MASK ACL entry.  If the ACL already
4075928Sjedgar * contains an ACL_MASK entry, its permissions shall be
4175928Sjedgar * overwritten; if not, one shall be added.
4274432Sjedgar */
4374432Sjedgarint
4474432Sjedgaracl_calc_mask(acl_t *acl_p)
4574432Sjedgar{
4675928Sjedgar	struct acl	*acl_int, *acl_int_new;
4775928Sjedgar	acl_t		acl_new;
4875928Sjedgar	int		i, mask_mode, mask_num;
4974432Sjedgar
5075928Sjedgar	/*
5175928Sjedgar	 * (23.4.2.4) requires acl_p to point to a pointer to a valid ACL.
5275928Sjedgar	 * Since one of the primary reasons to use this function would be
5375928Sjedgar	 * to calculate the appropriate mask to obtain a valid ACL, we only
5475928Sjedgar	 * perform sanity checks here and validate the ACL prior to
5575928Sjedgar	 * returning.
5675928Sjedgar	 */
5790781Sjedgar	if (acl_p == NULL || *acl_p == NULL) {
5874432Sjedgar		errno = EINVAL;
5990781Sjedgar		return (-1);
6074432Sjedgar	}
6175928Sjedgar	acl_int = &(*acl_p)->ats_acl;
6275928Sjedgar	if ((acl_int->acl_cnt < 3) || (acl_int->acl_cnt > ACL_MAX_ENTRIES)) {
6375928Sjedgar		errno = EINVAL;
6490781Sjedgar		return (-1);
6575928Sjedgar	}
6674432Sjedgar
6774432Sjedgar	acl_new = acl_dup(*acl_p);
6890781Sjedgar	if (acl_new == NULL)
6990781Sjedgar		return (-1);
7075928Sjedgar	acl_int_new = &acl_new->ats_acl;
7174432Sjedgar
7275928Sjedgar	mask_mode = 0;
7374432Sjedgar	mask_num = -1;
7474432Sjedgar
7574432Sjedgar	/* gather permissions and find a mask entry */
7675928Sjedgar	for (i = 0; i < acl_int_new->acl_cnt; i++) {
7775928Sjedgar		switch(acl_int_new->acl_entry[i].ae_tag) {
7875928Sjedgar		case ACL_USER:
7975928Sjedgar		case ACL_GROUP:
8074432Sjedgar		case ACL_GROUP_OBJ:
8174432Sjedgar			mask_mode |=
8275928Sjedgar			    acl_int_new->acl_entry[i].ae_perm & ACL_PERM_BITS;
8374432Sjedgar			break;
8474432Sjedgar		case ACL_MASK:
8574432Sjedgar			mask_num = i;
8674432Sjedgar			break;
8774432Sjedgar		}
8874432Sjedgar	}
8975928Sjedgar
9074432Sjedgar	/* if a mask entry already exists, overwrite the perms */
9175928Sjedgar	if (mask_num != -1)
9275928Sjedgar		acl_int_new->acl_entry[mask_num].ae_perm = mask_mode;
9375928Sjedgar	else {
9474432Sjedgar		/* if no mask exists, check acl_cnt... */
9575928Sjedgar		if (acl_int_new->acl_cnt == ACL_MAX_ENTRIES) {
9675928Sjedgar			errno = ENOMEM;
9790781Sjedgar			return (-1);
9874432Sjedgar		}
9974432Sjedgar		/* ...and add the mask entry */
10075928Sjedgar		acl_int_new->acl_entry[acl_int_new->acl_cnt].ae_tag = ACL_MASK;
10175928Sjedgar		acl_int_new->acl_entry[acl_int_new->acl_cnt].ae_id =
10275928Sjedgar		    ACL_UNDEFINED_ID;
10375928Sjedgar		acl_int_new->acl_entry[acl_int_new->acl_cnt].ae_perm =
10475928Sjedgar		    mask_mode;
10575928Sjedgar		acl_int_new->acl_cnt++;
10674432Sjedgar	}
10774432Sjedgar
10874432Sjedgar	if (acl_valid(acl_new) == -1) {
10974432Sjedgar		errno = EINVAL;
11074432Sjedgar		acl_free(acl_new);
11190781Sjedgar		return (-1);
11274432Sjedgar	}
11374432Sjedgar
11474432Sjedgar	**acl_p = *acl_new;
11574432Sjedgar	acl_free(acl_new);
11674432Sjedgar
11790781Sjedgar	return (0);
11874432Sjedgar}
119