xref: /netbsd-src/lib/libc/posix1e/acl_support.c (revision 9aa2a9c323eb12a08584c70d6ea91d316703d3fe)
1*9aa2a9c3Schristos /*-
2*9aa2a9c3Schristos  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3*9aa2a9c3Schristos  *
4*9aa2a9c3Schristos  * Copyright (c) 1999-2001, 2008 Robert N. M. Watson
5*9aa2a9c3Schristos  * All rights reserved.
6*9aa2a9c3Schristos  *
7*9aa2a9c3Schristos  * Redistribution and use in source and binary forms, with or without
8*9aa2a9c3Schristos  * modification, are permitted provided that the following conditions
9*9aa2a9c3Schristos  * are met:
10*9aa2a9c3Schristos  * 1. Redistributions of source code must retain the above copyright
11*9aa2a9c3Schristos  *    notice, this list of conditions and the following disclaimer.
12*9aa2a9c3Schristos  * 2. Redistributions in binary form must reproduce the above copyright
13*9aa2a9c3Schristos  *    notice, this list of conditions and the following disclaimer in the
14*9aa2a9c3Schristos  *    documentation and/or other materials provided with the distribution.
15*9aa2a9c3Schristos  *
16*9aa2a9c3Schristos  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17*9aa2a9c3Schristos  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18*9aa2a9c3Schristos  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19*9aa2a9c3Schristos  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20*9aa2a9c3Schristos  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21*9aa2a9c3Schristos  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22*9aa2a9c3Schristos  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23*9aa2a9c3Schristos  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24*9aa2a9c3Schristos  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25*9aa2a9c3Schristos  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26*9aa2a9c3Schristos  * SUCH DAMAGE.
27*9aa2a9c3Schristos  */
28*9aa2a9c3Schristos /*
29*9aa2a9c3Schristos  * Support functionality for the POSIX.1e ACL interface
30*9aa2a9c3Schristos  * These calls are intended only to be called within the library.
31*9aa2a9c3Schristos  */
32*9aa2a9c3Schristos 
33*9aa2a9c3Schristos #include <sys/cdefs.h>
34*9aa2a9c3Schristos #if 0
35*9aa2a9c3Schristos __FBSDID("$FreeBSD: head/lib/libc/posix1e/acl_support.c 326193 2017-11-25 17:12:48Z pfg $");
36*9aa2a9c3Schristos #else
37*9aa2a9c3Schristos __RCSID("$NetBSD: acl_support.c,v 1.1 2020/05/16 18:31:47 christos Exp $");
38*9aa2a9c3Schristos #endif
39*9aa2a9c3Schristos 
40*9aa2a9c3Schristos #include "namespace.h"
41*9aa2a9c3Schristos #include <sys/types.h>
42*9aa2a9c3Schristos #include <sys/acl.h>
43*9aa2a9c3Schristos #include <errno.h>
44*9aa2a9c3Schristos #include <grp.h>
45*9aa2a9c3Schristos #include <pwd.h>
46*9aa2a9c3Schristos #include <stdio.h>
47*9aa2a9c3Schristos #include <stdlib.h>
48*9aa2a9c3Schristos #include <string.h>
49*9aa2a9c3Schristos #include <assert.h>
50*9aa2a9c3Schristos 
51*9aa2a9c3Schristos #include "acl_support.h"
52*9aa2a9c3Schristos 
53*9aa2a9c3Schristos #define ACL_STRING_PERM_WRITE   'w'
54*9aa2a9c3Schristos #define ACL_STRING_PERM_READ    'r'
55*9aa2a9c3Schristos #define ACL_STRING_PERM_EXEC    'x'
56*9aa2a9c3Schristos #define ACL_STRING_PERM_NONE    '-'
57*9aa2a9c3Schristos 
58*9aa2a9c3Schristos /*
59*9aa2a9c3Schristos  * Return 0, if both ACLs are identical.
60*9aa2a9c3Schristos  */
61*9aa2a9c3Schristos int
_acl_differs(const acl_t a,const acl_t b)62*9aa2a9c3Schristos _acl_differs(const acl_t a, const acl_t b)
63*9aa2a9c3Schristos {
64*9aa2a9c3Schristos 	size_t i;
65*9aa2a9c3Schristos 	struct acl_entry *entrya, *entryb;
66*9aa2a9c3Schristos 
67*9aa2a9c3Schristos 	assert(_acl_brand(a) == _acl_brand(b));
68*9aa2a9c3Schristos 	assert(_acl_brand(a) != ACL_BRAND_UNKNOWN);
69*9aa2a9c3Schristos 	assert(_acl_brand(b) != ACL_BRAND_UNKNOWN);
70*9aa2a9c3Schristos 
71*9aa2a9c3Schristos 	if (a->ats_acl.acl_cnt != b->ats_acl.acl_cnt)
72*9aa2a9c3Schristos 		return (1);
73*9aa2a9c3Schristos 
74*9aa2a9c3Schristos 	for (i = 0; i < b->ats_acl.acl_cnt; i++) {
75*9aa2a9c3Schristos 		entrya = &(a->ats_acl.acl_entry[i]);
76*9aa2a9c3Schristos 		entryb = &(b->ats_acl.acl_entry[i]);
77*9aa2a9c3Schristos 
78*9aa2a9c3Schristos 		if (entrya->ae_tag != entryb->ae_tag ||
79*9aa2a9c3Schristos 		    entrya->ae_id != entryb->ae_id ||
80*9aa2a9c3Schristos 		    entrya->ae_perm != entryb->ae_perm ||
81*9aa2a9c3Schristos 		    entrya->ae_entry_type != entryb->ae_entry_type ||
82*9aa2a9c3Schristos 		    entrya->ae_flags != entryb->ae_flags)
83*9aa2a9c3Schristos 			return (1);
84*9aa2a9c3Schristos 	}
85*9aa2a9c3Schristos 
86*9aa2a9c3Schristos 	return (0);
87*9aa2a9c3Schristos }
88*9aa2a9c3Schristos 
89*9aa2a9c3Schristos /*
90*9aa2a9c3Schristos  * _posix1e_acl_entry_compare -- compare two acl_entry structures to
91*9aa2a9c3Schristos  * determine the order they should appear in.  Used by _posix1e_acl_sort to
92*9aa2a9c3Schristos  * sort ACL entries into the kernel-desired order -- i.e., the order useful
93*9aa2a9c3Schristos  * for evaluation and O(n) validity checking.  Beter to have an O(nlogn) sort
94*9aa2a9c3Schristos  * in userland and an O(n) in kernel than to have both in kernel.
95*9aa2a9c3Schristos  */
96*9aa2a9c3Schristos typedef int (*compare)(const void *, const void *);
97*9aa2a9c3Schristos static int
_posix1e_acl_entry_compare(struct acl_entry * a,struct acl_entry * b)98*9aa2a9c3Schristos _posix1e_acl_entry_compare(struct acl_entry *a, struct acl_entry *b)
99*9aa2a9c3Schristos {
100*9aa2a9c3Schristos 
101*9aa2a9c3Schristos 	assert(_entry_brand(a) == ACL_BRAND_POSIX);
102*9aa2a9c3Schristos 	assert(_entry_brand(b) == ACL_BRAND_POSIX);
103*9aa2a9c3Schristos 
104*9aa2a9c3Schristos 	/*
105*9aa2a9c3Schristos 	 * First, sort between tags -- conveniently defined in the correct
106*9aa2a9c3Schristos 	 * order for verification.
107*9aa2a9c3Schristos 	 */
108*9aa2a9c3Schristos 	if (a->ae_tag < b->ae_tag)
109*9aa2a9c3Schristos 		return (-1);
110*9aa2a9c3Schristos 	if (a->ae_tag > b->ae_tag)
111*9aa2a9c3Schristos 		return (1);
112*9aa2a9c3Schristos 
113*9aa2a9c3Schristos 	/*
114*9aa2a9c3Schristos 	 * Next compare uids/gids on appropriate types.
115*9aa2a9c3Schristos 	 */
116*9aa2a9c3Schristos 
117*9aa2a9c3Schristos 	if (a->ae_tag == ACL_USER || a->ae_tag == ACL_GROUP) {
118*9aa2a9c3Schristos 		if (a->ae_id < b->ae_id)
119*9aa2a9c3Schristos 			return (-1);
120*9aa2a9c3Schristos 		if (a->ae_id > b->ae_id)
121*9aa2a9c3Schristos 			return (1);
122*9aa2a9c3Schristos 
123*9aa2a9c3Schristos 		/* shouldn't be equal, fall through to the invalid case */
124*9aa2a9c3Schristos 	}
125*9aa2a9c3Schristos 
126*9aa2a9c3Schristos 	/*
127*9aa2a9c3Schristos 	 * Don't know how to sort multiple entries of the rest--either it's
128*9aa2a9c3Schristos 	 * a bad entry, or there shouldn't be more than one.  Ignore and the
129*9aa2a9c3Schristos 	 * validity checker can get it later.
130*9aa2a9c3Schristos 	 */
131*9aa2a9c3Schristos 	return (0);
132*9aa2a9c3Schristos }
133*9aa2a9c3Schristos 
134*9aa2a9c3Schristos /*
135*9aa2a9c3Schristos  * _posix1e_acl_sort -- sort ACL entries in POSIX.1e-formatted ACLs.
136*9aa2a9c3Schristos  */
137*9aa2a9c3Schristos void
_posix1e_acl_sort(acl_t acl)138*9aa2a9c3Schristos _posix1e_acl_sort(acl_t acl)
139*9aa2a9c3Schristos {
140*9aa2a9c3Schristos 	struct acl *acl_int;
141*9aa2a9c3Schristos 
142*9aa2a9c3Schristos 	acl_int = &acl->ats_acl;
143*9aa2a9c3Schristos 
144*9aa2a9c3Schristos 	qsort(&acl_int->acl_entry[0], acl_int->acl_cnt,
145*9aa2a9c3Schristos 	    sizeof(struct acl_entry), (compare) _posix1e_acl_entry_compare);
146*9aa2a9c3Schristos }
147*9aa2a9c3Schristos 
148*9aa2a9c3Schristos /*
149*9aa2a9c3Schristos  * acl_posix1e -- in what situations should we acl_sort before submission?
150*9aa2a9c3Schristos  * We apply posix1e ACL semantics for any ACL of type ACL_TYPE_ACCESS or
151*9aa2a9c3Schristos  * ACL_TYPE_DEFAULT
152*9aa2a9c3Schristos  */
153*9aa2a9c3Schristos int
_posix1e_acl(acl_t acl,acl_type_t type)154*9aa2a9c3Schristos _posix1e_acl(acl_t acl, acl_type_t type)
155*9aa2a9c3Schristos {
156*9aa2a9c3Schristos 
157*9aa2a9c3Schristos 	if (_acl_brand(acl) != ACL_BRAND_POSIX)
158*9aa2a9c3Schristos 		return (0);
159*9aa2a9c3Schristos 
160*9aa2a9c3Schristos 	return ((type == ACL_TYPE_ACCESS) || (type == ACL_TYPE_DEFAULT));
161*9aa2a9c3Schristos }
162*9aa2a9c3Schristos 
163*9aa2a9c3Schristos /*
164*9aa2a9c3Schristos  * _posix1e_acl_check -- given an ACL, check its validity.  This is mirrored
165*9aa2a9c3Schristos  * from code in sys/kern/kern_acl.c, and if changes are made in one, they
166*9aa2a9c3Schristos  * should be made in the other also.  This copy of acl_check is made
167*9aa2a9c3Schristos  * available * in userland for the benefit of processes wanting to check ACLs
168*9aa2a9c3Schristos  * for validity before submitting them to the kernel, or for performing
169*9aa2a9c3Schristos  * in userland file system checking.  Needless to say, the kernel makes
170*9aa2a9c3Schristos  * the real checks on calls to get/setacl.
171*9aa2a9c3Schristos  *
172*9aa2a9c3Schristos  * See the comments in kernel for explanation -- just briefly, it assumes
173*9aa2a9c3Schristos  * an already sorted ACL, and checks based on that assumption.  The
174*9aa2a9c3Schristos  * POSIX.1e interface, acl_valid(), will perform the sort before calling
175*9aa2a9c3Schristos  * this.  Returns 0 on success, EINVAL on failure.
176*9aa2a9c3Schristos  */
177*9aa2a9c3Schristos int
_posix1e_acl_check(acl_t acl)178*9aa2a9c3Schristos _posix1e_acl_check(acl_t acl)
179*9aa2a9c3Schristos {
180*9aa2a9c3Schristos 	struct acl *acl_int;
181*9aa2a9c3Schristos 	struct acl_entry	*entry; 	/* current entry */
182*9aa2a9c3Schristos 	uid_t	highest_uid=0, highest_gid=0;
183*9aa2a9c3Schristos 	int	stage = ACL_USER_OBJ;
184*9aa2a9c3Schristos 	size_t	i = 0;
185*9aa2a9c3Schristos 	int	count_user_obj=0, count_user=0, count_group_obj=0,
186*9aa2a9c3Schristos 		count_group=0, count_mask=0, count_other=0;
187*9aa2a9c3Schristos 
188*9aa2a9c3Schristos 	acl_int = &acl->ats_acl;
189*9aa2a9c3Schristos 
190*9aa2a9c3Schristos 	/* printf("_posix1e_acl_check: checking acl with %d entries\n",
191*9aa2a9c3Schristos 	    acl->acl_cnt); */
192*9aa2a9c3Schristos 	while (i < acl_int->acl_cnt) {
193*9aa2a9c3Schristos 		entry = &acl_int->acl_entry[i];
194*9aa2a9c3Schristos 
195*9aa2a9c3Schristos 		if ((entry->ae_perm | ACL_PERM_BITS) != ACL_PERM_BITS)
196*9aa2a9c3Schristos 			return (EINVAL);
197*9aa2a9c3Schristos 
198*9aa2a9c3Schristos 		switch(entry->ae_tag) {
199*9aa2a9c3Schristos 		case ACL_USER_OBJ:
200*9aa2a9c3Schristos 			/* printf("_posix1e_acl_check: %d: ACL_USER_OBJ\n",
201*9aa2a9c3Schristos 			    i); */
202*9aa2a9c3Schristos 			if (stage > ACL_USER_OBJ)
203*9aa2a9c3Schristos 				return (EINVAL);
204*9aa2a9c3Schristos 			stage = ACL_USER;
205*9aa2a9c3Schristos 			count_user_obj++;
206*9aa2a9c3Schristos 			break;
207*9aa2a9c3Schristos 
208*9aa2a9c3Schristos 		case ACL_USER:
209*9aa2a9c3Schristos 			/* printf("_posix1e_acl_check: %d: ACL_USER\n", i); */
210*9aa2a9c3Schristos 			if (stage > ACL_USER)
211*9aa2a9c3Schristos 				return (EINVAL);
212*9aa2a9c3Schristos 			stage = ACL_USER;
213*9aa2a9c3Schristos 			if (count_user && (entry->ae_id <= highest_uid))
214*9aa2a9c3Schristos 				return (EINVAL);
215*9aa2a9c3Schristos 			highest_uid = entry->ae_id;
216*9aa2a9c3Schristos 			count_user++;
217*9aa2a9c3Schristos 			break;
218*9aa2a9c3Schristos 
219*9aa2a9c3Schristos 		case ACL_GROUP_OBJ:
220*9aa2a9c3Schristos 			/* printf("_posix1e_acl_check: %d: ACL_GROUP_OBJ\n",
221*9aa2a9c3Schristos 			    i); */
222*9aa2a9c3Schristos 			if (stage > ACL_GROUP_OBJ)
223*9aa2a9c3Schristos 				return (EINVAL);
224*9aa2a9c3Schristos 			stage = ACL_GROUP;
225*9aa2a9c3Schristos 			count_group_obj++;
226*9aa2a9c3Schristos 			break;
227*9aa2a9c3Schristos 
228*9aa2a9c3Schristos 		case ACL_GROUP:
229*9aa2a9c3Schristos 			/* printf("_posix1e_acl_check: %d: ACL_GROUP\n", i); */
230*9aa2a9c3Schristos 			if (stage > ACL_GROUP)
231*9aa2a9c3Schristos 				return (EINVAL);
232*9aa2a9c3Schristos 			stage = ACL_GROUP;
233*9aa2a9c3Schristos 			if (count_group && (entry->ae_id <= highest_gid))
234*9aa2a9c3Schristos 				return (EINVAL);
235*9aa2a9c3Schristos 			highest_gid = entry->ae_id;
236*9aa2a9c3Schristos 			count_group++;
237*9aa2a9c3Schristos 			break;
238*9aa2a9c3Schristos 
239*9aa2a9c3Schristos 		case ACL_MASK:
240*9aa2a9c3Schristos 			/* printf("_posix1e_acl_check: %d: ACL_MASK\n", i); */
241*9aa2a9c3Schristos 			if (stage > ACL_MASK)
242*9aa2a9c3Schristos 				return (EINVAL);
243*9aa2a9c3Schristos 			stage = ACL_MASK;
244*9aa2a9c3Schristos 			count_mask++;
245*9aa2a9c3Schristos 			break;
246*9aa2a9c3Schristos 
247*9aa2a9c3Schristos 		case ACL_OTHER:
248*9aa2a9c3Schristos 			/* printf("_posix1e_acl_check: %d: ACL_OTHER\n", i); */
249*9aa2a9c3Schristos 			if (stage > ACL_OTHER)
250*9aa2a9c3Schristos 				return (EINVAL);
251*9aa2a9c3Schristos 			stage = ACL_OTHER;
252*9aa2a9c3Schristos 			count_other++;
253*9aa2a9c3Schristos 			break;
254*9aa2a9c3Schristos 
255*9aa2a9c3Schristos 		default:
256*9aa2a9c3Schristos 			/* printf("_posix1e_acl_check: %d: INVALID\n", i); */
257*9aa2a9c3Schristos 			return (EINVAL);
258*9aa2a9c3Schristos 		}
259*9aa2a9c3Schristos 		i++;
260*9aa2a9c3Schristos 	}
261*9aa2a9c3Schristos 
262*9aa2a9c3Schristos 	if (count_user_obj != 1)
263*9aa2a9c3Schristos 		return (EINVAL);
264*9aa2a9c3Schristos 
265*9aa2a9c3Schristos 	if (count_group_obj != 1)
266*9aa2a9c3Schristos 		return (EINVAL);
267*9aa2a9c3Schristos 
268*9aa2a9c3Schristos 	if (count_mask != 0 && count_mask != 1)
269*9aa2a9c3Schristos 		return (EINVAL);
270*9aa2a9c3Schristos 
271*9aa2a9c3Schristos 	if (count_other != 1)
272*9aa2a9c3Schristos 		return (EINVAL);
273*9aa2a9c3Schristos 
274*9aa2a9c3Schristos 	return (0);
275*9aa2a9c3Schristos }
276*9aa2a9c3Schristos 
277*9aa2a9c3Schristos /*
278*9aa2a9c3Schristos  * Given a right-shifted permission (i.e., direct ACL_PERM_* mask), fill
279*9aa2a9c3Schristos  * in a string describing the permissions.
280*9aa2a9c3Schristos  */
281*9aa2a9c3Schristos int
_posix1e_acl_perm_to_string(acl_perm_t perm,ssize_t buf_len,char * buf)282*9aa2a9c3Schristos _posix1e_acl_perm_to_string(acl_perm_t perm, ssize_t buf_len, char *buf)
283*9aa2a9c3Schristos {
284*9aa2a9c3Schristos 
285*9aa2a9c3Schristos 	if (buf_len < _POSIX1E_ACL_STRING_PERM_MAXSIZE + 1) {
286*9aa2a9c3Schristos 		errno = ENOMEM;
287*9aa2a9c3Schristos 		return (-1);
288*9aa2a9c3Schristos 	}
289*9aa2a9c3Schristos 
290*9aa2a9c3Schristos 	if ((perm | ACL_PERM_BITS) != ACL_PERM_BITS) {
291*9aa2a9c3Schristos 		errno = EINVAL;
292*9aa2a9c3Schristos 		return (-1);
293*9aa2a9c3Schristos 	}
294*9aa2a9c3Schristos 
295*9aa2a9c3Schristos 	buf[3] = 0;	/* null terminate */
296*9aa2a9c3Schristos 
297*9aa2a9c3Schristos 	if (perm & ACL_READ)
298*9aa2a9c3Schristos 		buf[0] = ACL_STRING_PERM_READ;
299*9aa2a9c3Schristos 	else
300*9aa2a9c3Schristos 		buf[0] = ACL_STRING_PERM_NONE;
301*9aa2a9c3Schristos 
302*9aa2a9c3Schristos 	if (perm & ACL_WRITE)
303*9aa2a9c3Schristos 		buf[1] = ACL_STRING_PERM_WRITE;
304*9aa2a9c3Schristos 	else
305*9aa2a9c3Schristos 		buf[1] = ACL_STRING_PERM_NONE;
306*9aa2a9c3Schristos 
307*9aa2a9c3Schristos 	if (perm & ACL_EXECUTE)
308*9aa2a9c3Schristos 		buf[2] = ACL_STRING_PERM_EXEC;
309*9aa2a9c3Schristos 	else
310*9aa2a9c3Schristos 		buf[2] = ACL_STRING_PERM_NONE;
311*9aa2a9c3Schristos 
312*9aa2a9c3Schristos 	return (0);
313*9aa2a9c3Schristos }
314*9aa2a9c3Schristos 
315*9aa2a9c3Schristos /*
316*9aa2a9c3Schristos  * given a string, return a permission describing it
317*9aa2a9c3Schristos  */
318*9aa2a9c3Schristos int
_posix1e_acl_string_to_perm(char * string,acl_perm_t * perm)319*9aa2a9c3Schristos _posix1e_acl_string_to_perm(char *string, acl_perm_t *perm)
320*9aa2a9c3Schristos {
321*9aa2a9c3Schristos 	acl_perm_t	myperm = ACL_PERM_NONE;
322*9aa2a9c3Schristos 	char	*ch;
323*9aa2a9c3Schristos 
324*9aa2a9c3Schristos 	ch = string;
325*9aa2a9c3Schristos 	while (*ch) {
326*9aa2a9c3Schristos 		switch(*ch) {
327*9aa2a9c3Schristos 		case ACL_STRING_PERM_READ:
328*9aa2a9c3Schristos 			myperm |= ACL_READ;
329*9aa2a9c3Schristos 			break;
330*9aa2a9c3Schristos 		case ACL_STRING_PERM_WRITE:
331*9aa2a9c3Schristos 			myperm |= ACL_WRITE;
332*9aa2a9c3Schristos 			break;
333*9aa2a9c3Schristos 		case ACL_STRING_PERM_EXEC:
334*9aa2a9c3Schristos 			myperm |= ACL_EXECUTE;
335*9aa2a9c3Schristos 			break;
336*9aa2a9c3Schristos 		case ACL_STRING_PERM_NONE:
337*9aa2a9c3Schristos 			break;
338*9aa2a9c3Schristos 		default:
339*9aa2a9c3Schristos 			return (EINVAL);
340*9aa2a9c3Schristos 		}
341*9aa2a9c3Schristos 		ch++;
342*9aa2a9c3Schristos 	}
343*9aa2a9c3Schristos 
344*9aa2a9c3Schristos 	*perm = myperm;
345*9aa2a9c3Schristos 	return (0);
346*9aa2a9c3Schristos }
347*9aa2a9c3Schristos 
348*9aa2a9c3Schristos /*
349*9aa2a9c3Schristos  * Add an ACL entry without doing much checking, et al
350*9aa2a9c3Schristos  */
351*9aa2a9c3Schristos int
_posix1e_acl_add_entry(acl_t acl,acl_tag_t tag,uid_t id,acl_perm_t perm)352*9aa2a9c3Schristos _posix1e_acl_add_entry(acl_t acl, acl_tag_t tag, uid_t id, acl_perm_t perm)
353*9aa2a9c3Schristos {
354*9aa2a9c3Schristos 	struct acl		*acl_int;
355*9aa2a9c3Schristos 	struct acl_entry	*e;
356*9aa2a9c3Schristos 
357*9aa2a9c3Schristos 	acl_int = &acl->ats_acl;
358*9aa2a9c3Schristos 
359*9aa2a9c3Schristos 	if (acl_int->acl_cnt >= ACL_MAX_ENTRIES) {
360*9aa2a9c3Schristos 		errno = ENOMEM;
361*9aa2a9c3Schristos 		return (-1);
362*9aa2a9c3Schristos 	}
363*9aa2a9c3Schristos 
364*9aa2a9c3Schristos 	e = &(acl_int->acl_entry[acl_int->acl_cnt]);
365*9aa2a9c3Schristos 	e->ae_perm = perm;
366*9aa2a9c3Schristos 	e->ae_tag = tag;
367*9aa2a9c3Schristos 	e->ae_id = id;
368*9aa2a9c3Schristos 	acl_int->acl_cnt++;
369*9aa2a9c3Schristos 
370*9aa2a9c3Schristos 	return (0);
371*9aa2a9c3Schristos }
372*9aa2a9c3Schristos 
373*9aa2a9c3Schristos /*
374*9aa2a9c3Schristos  * Convert "old" type - ACL_TYPE_{ACCESS,DEFAULT}_OLD - into its "new"
375*9aa2a9c3Schristos  * counterpart.  It's necessary for the old (pre-NFSv4 ACLs) binaries
376*9aa2a9c3Schristos  * to work with new libc and kernel.  Fixing 'type' for old binaries with
377*9aa2a9c3Schristos  * old libc and new kernel is being done by kern/vfs_acl.c:type_unold().
378*9aa2a9c3Schristos  */
379*9aa2a9c3Schristos int
_acl_type_unold(acl_type_t type)380*9aa2a9c3Schristos _acl_type_unold(acl_type_t type)
381*9aa2a9c3Schristos {
382*9aa2a9c3Schristos 
383*9aa2a9c3Schristos 	switch (type) {
384*9aa2a9c3Schristos 	case ACL_TYPE_ACCESS_OLD:
385*9aa2a9c3Schristos 		return (ACL_TYPE_ACCESS);
386*9aa2a9c3Schristos 	case ACL_TYPE_DEFAULT_OLD:
387*9aa2a9c3Schristos 		return (ACL_TYPE_DEFAULT);
388*9aa2a9c3Schristos 	default:
389*9aa2a9c3Schristos 		return (type);
390*9aa2a9c3Schristos 	}
391*9aa2a9c3Schristos }
392*9aa2a9c3Schristos 
393*9aa2a9c3Schristos char *
string_skip_whitespace(char * string)394*9aa2a9c3Schristos string_skip_whitespace(char *string)
395*9aa2a9c3Schristos {
396*9aa2a9c3Schristos 
397*9aa2a9c3Schristos 	while (*string && ((*string == ' ') || (*string == '\t')))
398*9aa2a9c3Schristos 		string++;
399*9aa2a9c3Schristos 
400*9aa2a9c3Schristos 	return (string);
401*9aa2a9c3Schristos }
402*9aa2a9c3Schristos 
403*9aa2a9c3Schristos void
string_trim_trailing_whitespace(char * string)404*9aa2a9c3Schristos string_trim_trailing_whitespace(char *string)
405*9aa2a9c3Schristos {
406*9aa2a9c3Schristos 	char	*end;
407*9aa2a9c3Schristos 
408*9aa2a9c3Schristos 	if (*string == '\0')
409*9aa2a9c3Schristos 		return;
410*9aa2a9c3Schristos 
411*9aa2a9c3Schristos 	end = string + strlen(string) - 1;
412*9aa2a9c3Schristos 
413*9aa2a9c3Schristos 	while (end != string) {
414*9aa2a9c3Schristos 		if ((*end == ' ') || (*end == '\t')) {
415*9aa2a9c3Schristos 			*end = '\0';
416*9aa2a9c3Schristos 			end--;
417*9aa2a9c3Schristos 		} else {
418*9aa2a9c3Schristos 			return;
419*9aa2a9c3Schristos 		}
420*9aa2a9c3Schristos 	}
421*9aa2a9c3Schristos 
422*9aa2a9c3Schristos 	return;
423*9aa2a9c3Schristos }
424