xref: /illumos-gate/usr/src/common/acl/acl_common.c (revision ef9416a8)
1fa9e4066Sahrens /*
2fa9e4066Sahrens  * CDDL HEADER START
3fa9e4066Sahrens  *
4fa9e4066Sahrens  * The contents of this file are subject to the terms of the
5f48205beScasper  * Common Development and Distribution License (the "License").
6f48205beScasper  * 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 /*
2227dd1e87SMark Shellenbaum  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
231eb4e906SKevin Crowe  * Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
24fa9e4066Sahrens  */
25fa9e4066Sahrens 
26fa9e4066Sahrens #include <sys/types.h>
27fa9e4066Sahrens #include <sys/stat.h>
28b819cea2SGordon Ross #include <sys/errno.h>
29da6c28aaSamw #include <sys/avl.h>
30b819cea2SGordon Ross #if defined(_KERNEL) || defined(_FAKE_KERNEL)
31b819cea2SGordon Ross #include <sys/debug.h>
32b819cea2SGordon Ross #include <sys/kmem.h>
33fa9e4066Sahrens #include <sys/systm.h>
34da6c28aaSamw #include <sys/sysmacros.h>
35da6c28aaSamw #include <acl/acl_common.h>
36fa9e4066Sahrens #else
37fa9e4066Sahrens #include <errno.h>
38fa9e4066Sahrens #include <stdlib.h>
39da6c28aaSamw #include <stddef.h>
40fa9e4066Sahrens #include <strings.h>
41da6c28aaSamw #include <unistd.h>
42fa9e4066Sahrens #include <assert.h>
43da6c28aaSamw #include <grp.h>
44da6c28aaSamw #include <pwd.h>
45da6c28aaSamw #include <acl_common.h>
46fa9e4066Sahrens #define	ASSERT	assert
47fa9e4066Sahrens #endif
48fa9e4066Sahrens 
49da6c28aaSamw #define	ACE_POSIX_SUPPORTED_BITS (ACE_READ_DATA | \
50da6c28aaSamw     ACE_WRITE_DATA | ACE_APPEND_DATA | ACE_EXECUTE | \
51da6c28aaSamw     ACE_READ_ATTRIBUTES | ACE_READ_ACL | ACE_WRITE_ACL)
52da6c28aaSamw 
53da6c28aaSamw 
54da6c28aaSamw #define	ACL_SYNCHRONIZE_SET_DENY		0x0000001
55da6c28aaSamw #define	ACL_SYNCHRONIZE_SET_ALLOW		0x0000002
56da6c28aaSamw #define	ACL_SYNCHRONIZE_ERR_DENY		0x0000004
57da6c28aaSamw #define	ACL_SYNCHRONIZE_ERR_ALLOW		0x0000008
58da6c28aaSamw 
59da6c28aaSamw #define	ACL_WRITE_OWNER_SET_DENY		0x0000010
60da6c28aaSamw #define	ACL_WRITE_OWNER_SET_ALLOW		0x0000020
61da6c28aaSamw #define	ACL_WRITE_OWNER_ERR_DENY		0x0000040
62da6c28aaSamw #define	ACL_WRITE_OWNER_ERR_ALLOW		0x0000080
63da6c28aaSamw 
64da6c28aaSamw #define	ACL_DELETE_SET_DENY			0x0000100
65da6c28aaSamw #define	ACL_DELETE_SET_ALLOW			0x0000200
66da6c28aaSamw #define	ACL_DELETE_ERR_DENY			0x0000400
67da6c28aaSamw #define	ACL_DELETE_ERR_ALLOW			0x0000800
68da6c28aaSamw 
69da6c28aaSamw #define	ACL_WRITE_ATTRS_OWNER_SET_DENY		0x0001000
70da6c28aaSamw #define	ACL_WRITE_ATTRS_OWNER_SET_ALLOW		0x0002000
71da6c28aaSamw #define	ACL_WRITE_ATTRS_OWNER_ERR_DENY		0x0004000
72da6c28aaSamw #define	ACL_WRITE_ATTRS_OWNER_ERR_ALLOW		0x0008000
73da6c28aaSamw 
74da6c28aaSamw #define	ACL_WRITE_ATTRS_WRITER_SET_DENY		0x0010000
75da6c28aaSamw #define	ACL_WRITE_ATTRS_WRITER_SET_ALLOW	0x0020000
76da6c28aaSamw #define	ACL_WRITE_ATTRS_WRITER_ERR_DENY		0x0040000
77da6c28aaSamw #define	ACL_WRITE_ATTRS_WRITER_ERR_ALLOW	0x0080000
78da6c28aaSamw 
79da6c28aaSamw #define	ACL_WRITE_NAMED_WRITER_SET_DENY		0x0100000
80da6c28aaSamw #define	ACL_WRITE_NAMED_WRITER_SET_ALLOW	0x0200000
81da6c28aaSamw #define	ACL_WRITE_NAMED_WRITER_ERR_DENY		0x0400000
82da6c28aaSamw #define	ACL_WRITE_NAMED_WRITER_ERR_ALLOW	0x0800000
83da6c28aaSamw 
84da6c28aaSamw #define	ACL_READ_NAMED_READER_SET_DENY		0x1000000
85da6c28aaSamw #define	ACL_READ_NAMED_READER_SET_ALLOW		0x2000000
86da6c28aaSamw #define	ACL_READ_NAMED_READER_ERR_DENY		0x4000000
87da6c28aaSamw #define	ACL_READ_NAMED_READER_ERR_ALLOW		0x8000000
88da6c28aaSamw 
89da6c28aaSamw 
90da6c28aaSamw #define	ACE_VALID_MASK_BITS (\
91da6c28aaSamw     ACE_READ_DATA | \
92da6c28aaSamw     ACE_LIST_DIRECTORY | \
93da6c28aaSamw     ACE_WRITE_DATA | \
94da6c28aaSamw     ACE_ADD_FILE | \
95da6c28aaSamw     ACE_APPEND_DATA | \
96da6c28aaSamw     ACE_ADD_SUBDIRECTORY | \
97da6c28aaSamw     ACE_READ_NAMED_ATTRS | \
98da6c28aaSamw     ACE_WRITE_NAMED_ATTRS | \
99da6c28aaSamw     ACE_EXECUTE | \
100da6c28aaSamw     ACE_DELETE_CHILD | \
101da6c28aaSamw     ACE_READ_ATTRIBUTES | \
102da6c28aaSamw     ACE_WRITE_ATTRIBUTES | \
103da6c28aaSamw     ACE_DELETE | \
104da6c28aaSamw     ACE_READ_ACL | \
105da6c28aaSamw     ACE_WRITE_ACL | \
106da6c28aaSamw     ACE_WRITE_OWNER | \
107da6c28aaSamw     ACE_SYNCHRONIZE)
108da6c28aaSamw 
109da6c28aaSamw #define	ACE_MASK_UNDEFINED			0x80000000
110da6c28aaSamw 
111da6c28aaSamw #define	ACE_VALID_FLAG_BITS (ACE_FILE_INHERIT_ACE | \
112da6c28aaSamw     ACE_DIRECTORY_INHERIT_ACE | \
113da6c28aaSamw     ACE_NO_PROPAGATE_INHERIT_ACE | ACE_INHERIT_ONLY_ACE | \
114da6c28aaSamw     ACE_SUCCESSFUL_ACCESS_ACE_FLAG | ACE_FAILED_ACCESS_ACE_FLAG | \
115da6c28aaSamw     ACE_IDENTIFIER_GROUP | ACE_OWNER | ACE_GROUP | ACE_EVERYONE)
116da6c28aaSamw 
117da6c28aaSamw /*
118da6c28aaSamw  * ACL conversion helpers
119da6c28aaSamw  */
120da6c28aaSamw 
121da6c28aaSamw typedef enum {
122da6c28aaSamw 	ace_unused,
123da6c28aaSamw 	ace_user_obj,
124da6c28aaSamw 	ace_user,
125da6c28aaSamw 	ace_group, /* includes GROUP and GROUP_OBJ */
126da6c28aaSamw 	ace_other_obj
127da6c28aaSamw } ace_to_aent_state_t;
128da6c28aaSamw 
129da6c28aaSamw typedef struct acevals {
130da6c28aaSamw 	uid_t key;
131da6c28aaSamw 	avl_node_t avl;
132da6c28aaSamw 	uint32_t mask;
133da6c28aaSamw 	uint32_t allowed;
134da6c28aaSamw 	uint32_t denied;
135da6c28aaSamw 	int aent_type;
136da6c28aaSamw } acevals_t;
137da6c28aaSamw 
138da6c28aaSamw typedef struct ace_list {
139da6c28aaSamw 	acevals_t user_obj;
140da6c28aaSamw 	avl_tree_t user;
141da6c28aaSamw 	int numusers;
142da6c28aaSamw 	acevals_t group_obj;
143da6c28aaSamw 	avl_tree_t group;
144da6c28aaSamw 	int numgroups;
145da6c28aaSamw 	acevals_t other_obj;
146da6c28aaSamw 	uint32_t acl_mask;
147da6c28aaSamw 	int hasmask;
148da6c28aaSamw 	int dfacl_flag;
149da6c28aaSamw 	ace_to_aent_state_t state;
150da6c28aaSamw 	int seen; /* bitmask of all aclent_t a_type values seen */
151da6c28aaSamw } ace_list_t;
152fa9e4066Sahrens 
153fa9e4066Sahrens /*
154fa9e4066Sahrens  * Generic shellsort, from K&R (1st ed, p 58.), somewhat modified.
155fa9e4066Sahrens  * v = Ptr to array/vector of objs
156fa9e4066Sahrens  * n = # objs in the array
157fa9e4066Sahrens  * s = size of each obj (must be multiples of a word size)
158fa9e4066Sahrens  * f = ptr to function to compare two objs
159fa9e4066Sahrens  *	returns (-1 = less than, 0 = equal, 1 = greater than
160fa9e4066Sahrens  */
161fa9e4066Sahrens void
ksort(caddr_t v,int n,int s,int (* f)())162fa9e4066Sahrens ksort(caddr_t v, int n, int s, int (*f)())
163fa9e4066Sahrens {
164fa9e4066Sahrens 	int g, i, j, ii;
165fa9e4066Sahrens 	unsigned int *p1, *p2;
166fa9e4066Sahrens 	unsigned int tmp;
167fa9e4066Sahrens 
168fa9e4066Sahrens 	/* No work to do */
169fa9e4066Sahrens 	if (v == NULL || n <= 1)
170fa9e4066Sahrens 		return;
171fa9e4066Sahrens 
172fa9e4066Sahrens 	/* Sanity check on arguments */
173fa9e4066Sahrens 	ASSERT(((uintptr_t)v & 0x3) == 0 && (s & 0x3) == 0);
174fa9e4066Sahrens 	ASSERT(s > 0);
175fa9e4066Sahrens 	for (g = n / 2; g > 0; g /= 2) {
176fa9e4066Sahrens 		for (i = g; i < n; i++) {
177fa9e4066Sahrens 			for (j = i - g; j >= 0 &&
178da6c28aaSamw 			    (*f)(v + j * s, v + (j + g) * s) == 1;
179da6c28aaSamw 			    j -= g) {
180fa9e4066Sahrens 				p1 = (void *)(v + j * s);
181fa9e4066Sahrens 				p2 = (void *)(v + (j + g) * s);
182fa9e4066Sahrens 				for (ii = 0; ii < s / 4; ii++) {
183fa9e4066Sahrens 					tmp = *p1;
184fa9e4066Sahrens 					*p1++ = *p2;
185fa9e4066Sahrens 					*p2++ = tmp;
186fa9e4066Sahrens 				}
187fa9e4066Sahrens 			}
188fa9e4066Sahrens 		}
189fa9e4066Sahrens 	}
190fa9e4066Sahrens }
191fa9e4066Sahrens 
192fa9e4066Sahrens /*
193fa9e4066Sahrens  * Compare two acls, all fields.  Returns:
194fa9e4066Sahrens  * -1 (less than)
195fa9e4066Sahrens  *  0 (equal)
196fa9e4066Sahrens  * +1 (greater than)
197fa9e4066Sahrens  */
198fa9e4066Sahrens int
cmp2acls(void * a,void * b)199fa9e4066Sahrens cmp2acls(void *a, void *b)
200fa9e4066Sahrens {
201fa9e4066Sahrens 	aclent_t *x = (aclent_t *)a;
202fa9e4066Sahrens 	aclent_t *y = (aclent_t *)b;
203fa9e4066Sahrens 
204fa9e4066Sahrens 	/* Compare types */
205fa9e4066Sahrens 	if (x->a_type < y->a_type)
206fa9e4066Sahrens 		return (-1);
207fa9e4066Sahrens 	if (x->a_type > y->a_type)
208fa9e4066Sahrens 		return (1);
209fa9e4066Sahrens 	/* Equal types; compare id's */
210fa9e4066Sahrens 	if (x->a_id < y->a_id)
211fa9e4066Sahrens 		return (-1);
212fa9e4066Sahrens 	if (x->a_id > y->a_id)
213fa9e4066Sahrens 		return (1);
214fa9e4066Sahrens 	/* Equal ids; compare perms */
215fa9e4066Sahrens 	if (x->a_perm < y->a_perm)
216fa9e4066Sahrens 		return (-1);
217fa9e4066Sahrens 	if (x->a_perm > y->a_perm)
218fa9e4066Sahrens 		return (1);
219fa9e4066Sahrens 	/* Totally equal */
220fa9e4066Sahrens 	return (0);
221fa9e4066Sahrens }
222da6c28aaSamw 
223da6c28aaSamw /*ARGSUSED*/
224da6c28aaSamw static void *
cacl_realloc(void * ptr,size_t size,size_t new_size)225da6c28aaSamw cacl_realloc(void *ptr, size_t size, size_t new_size)
226da6c28aaSamw {
227b819cea2SGordon Ross #if defined(_KERNEL) || defined(_FAKE_KERNEL)
228da6c28aaSamw 	void *tmp;
229da6c28aaSamw 
230da6c28aaSamw 	tmp = kmem_alloc(new_size, KM_SLEEP);
231da6c28aaSamw 	(void) memcpy(tmp, ptr, (size < new_size) ? size : new_size);
232da6c28aaSamw 	kmem_free(ptr, size);
233da6c28aaSamw 	return (tmp);
234da6c28aaSamw #else
235da6c28aaSamw 	return (realloc(ptr, new_size));
236da6c28aaSamw #endif
237da6c28aaSamw }
238da6c28aaSamw 
239da6c28aaSamw static int
cacl_malloc(void ** ptr,size_t size)240da6c28aaSamw cacl_malloc(void **ptr, size_t size)
241da6c28aaSamw {
242b819cea2SGordon Ross #if defined(_KERNEL) || defined(_FAKE_KERNEL)
243da6c28aaSamw 	*ptr = kmem_zalloc(size, KM_SLEEP);
244