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