acl_common.c revision 168404
1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License").  You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22/*
23 * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 */
26
27#pragma ident	"%Z%%M%	%I%	%E% SMI"
28
29#include <sys/types.h>
30#include <sys/acl.h>
31#include <sys/stat.h>
32#if defined(_KERNEL)
33#include <sys/systm.h>
34#include <sys/debug.h>
35#else
36#include <errno.h>
37#include <stdlib.h>
38#include <strings.h>
39#include <assert.h>
40#define	ASSERT	assert
41#endif
42
43
44ace_t trivial_acl[] = {
45	{-1, 0, ACE_OWNER, ACE_ACCESS_DENIED_ACE_TYPE},
46	{-1, ACE_WRITE_ACL|ACE_WRITE_OWNER|ACE_WRITE_ATTRIBUTES|
47	    ACE_WRITE_NAMED_ATTRS, ACE_OWNER, ACE_ACCESS_ALLOWED_ACE_TYPE},
48	{-1, 0, ACE_GROUP|ACE_IDENTIFIER_GROUP, ACE_ACCESS_DENIED_ACE_TYPE},
49	{-1, 0, ACE_GROUP|ACE_IDENTIFIER_GROUP, ACE_ACCESS_ALLOWED_ACE_TYPE},
50	{-1, ACE_WRITE_ACL|ACE_WRITE_OWNER| ACE_WRITE_ATTRIBUTES|
51	    ACE_WRITE_NAMED_ATTRS, ACE_EVERYONE, ACE_ACCESS_DENIED_ACE_TYPE},
52	{-1, ACE_READ_ACL|ACE_READ_ATTRIBUTES|ACE_READ_NAMED_ATTRS|
53	    ACE_SYNCHRONIZE, ACE_EVERYONE, ACE_ACCESS_ALLOWED_ACE_TYPE}
54};
55
56
57void
58adjust_ace_pair(ace_t *pair, mode_t mode)
59{
60	if (mode & S_IROTH)
61		pair[1].a_access_mask |= ACE_READ_DATA;
62	else
63		pair[0].a_access_mask |= ACE_READ_DATA;
64	if (mode & S_IWOTH)
65		pair[1].a_access_mask |=
66		    ACE_WRITE_DATA|ACE_APPEND_DATA;
67	else
68		pair[0].a_access_mask |=
69		    ACE_WRITE_DATA|ACE_APPEND_DATA;
70	if (mode & S_IXOTH)
71		pair[1].a_access_mask |= ACE_EXECUTE;
72	else
73		pair[0].a_access_mask |= ACE_EXECUTE;
74}
75
76/*
77 * ace_trivial:
78 * determine whether an ace_t acl is trivial
79 *
80 * Trivialness implys that the acl is composed of only
81 * owner, group, everyone entries.  ACL can't
82 * have read_acl denied, and write_owner/write_acl/write_attributes
83 * can only be owner@ entry.
84 */
85int
86ace_trivial(ace_t *acep, int aclcnt)
87{
88	int i;
89	int owner_seen = 0;
90	int group_seen = 0;
91	int everyone_seen = 0;
92
93	for (i = 0; i != aclcnt; i++) {
94		switch (acep[i].a_flags & 0xf040) {
95		case ACE_OWNER:
96			if (group_seen || everyone_seen)
97				return (1);
98			owner_seen++;
99			break;
100		case ACE_GROUP|ACE_IDENTIFIER_GROUP:
101			if (everyone_seen || owner_seen == 0)
102				return (1);
103			group_seen++;
104			break;
105
106		case ACE_EVERYONE:
107			if (owner_seen == 0 || group_seen == 0)
108				return (1);
109			everyone_seen++;
110			break;
111		default:
112			return (1);
113
114		}
115
116		if (acep[i].a_flags & (ACE_FILE_INHERIT_ACE|
117		    ACE_DIRECTORY_INHERIT_ACE|ACE_NO_PROPAGATE_INHERIT_ACE|
118		    ACE_INHERIT_ONLY_ACE))
119			return (1);
120
121		/*
122		 * Special check for some special bits
123		 *
124		 * Don't allow anybody to deny reading basic
125		 * attributes or a files ACL.
126		 */
127		if ((acep[i].a_access_mask &
128		    (ACE_READ_ACL|ACE_READ_ATTRIBUTES)) &&
129		    (acep[i].a_type == ACE_ACCESS_DENIED_ACE_TYPE))
130			return (1);
131
132		/*
133		 * Allow on owner@ to allow
134		 * write_acl/write_owner/write_attributes
135		 */
136		if (acep[i].a_type == ACE_ACCESS_ALLOWED_ACE_TYPE &&
137		    (!(acep[i].a_flags & ACE_OWNER) && (acep[i].a_access_mask &
138		    (ACE_WRITE_OWNER|ACE_WRITE_ACL|ACE_WRITE_ATTRIBUTES))))
139			return (1);
140	}
141
142	if ((owner_seen == 0) || (group_seen == 0) || (everyone_seen == 0))
143	    return (1);
144
145	return (0);
146}
147
148
149/*
150 * Generic shellsort, from K&R (1st ed, p 58.), somewhat modified.
151 * v = Ptr to array/vector of objs
152 * n = # objs in the array
153 * s = size of each obj (must be multiples of a word size)
154 * f = ptr to function to compare two objs
155 *	returns (-1 = less than, 0 = equal, 1 = greater than
156 */
157void
158ksort(caddr_t v, int n, int s, int (*f)())
159{
160	int g, i, j, ii;
161	unsigned int *p1, *p2;
162	unsigned int tmp;
163
164	/* No work to do */
165	if (v == NULL || n <= 1)
166		return;
167
168	/* Sanity check on arguments */
169	ASSERT(((uintptr_t)v & 0x3) == 0 && (s & 0x3) == 0);
170	ASSERT(s > 0);
171	for (g = n / 2; g > 0; g /= 2) {
172		for (i = g; i < n; i++) {
173			for (j = i - g; j >= 0 &&
174				(*f)(v + j * s, v + (j + g) * s) == 1;
175					j -= g) {
176				p1 = (void *)(v + j * s);
177				p2 = (void *)(v + (j + g) * s);
178				for (ii = 0; ii < s / 4; ii++) {
179					tmp = *p1;
180					*p1++ = *p2;
181					*p2++ = tmp;
182				}
183			}
184		}
185	}
186}
187
188/*
189 * Compare two acls, all fields.  Returns:
190 * -1 (less than)
191 *  0 (equal)
192 * +1 (greater than)
193 */
194int
195cmp2acls(void *a, void *b)
196{
197	aclent_t *x = (aclent_t *)a;
198	aclent_t *y = (aclent_t *)b;
199
200	/* Compare types */
201	if (x->a_type < y->a_type)
202		return (-1);
203	if (x->a_type > y->a_type)
204		return (1);
205	/* Equal types; compare id's */
206	if (x->a_id < y->a_id)
207		return (-1);
208	if (x->a_id > y->a_id)
209		return (1);
210	/* Equal ids; compare perms */
211	if (x->a_perm < y->a_perm)
212		return (-1);
213	if (x->a_perm > y->a_perm)
214		return (1);
215	/* Totally equal */
216	return (0);
217}
218