xref: /titanic_52/usr/src/lib/libsec/common/aclcheck.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright (c) 1993-1997 by Sun Microsystems, Inc.
24*7c478bd9Sstevel@tonic-gate  */
25*7c478bd9Sstevel@tonic-gate 
26*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
27*7c478bd9Sstevel@tonic-gate /*LINTLIBRARY*/
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate /*
30*7c478bd9Sstevel@tonic-gate  * aclcheck(): check validity of an ACL
31*7c478bd9Sstevel@tonic-gate  *	A valid ACL is defined as follows:
32*7c478bd9Sstevel@tonic-gate  *	There must be exactly one USER_OBJ, GROUP_OBJ, and OTHER_OBJ entry.
33*7c478bd9Sstevel@tonic-gate  *	If there are any USER entries, then the user id must be unique.
34*7c478bd9Sstevel@tonic-gate  *	If there are any GROUP entries, then the group id must be unique.
35*7c478bd9Sstevel@tonic-gate  *	If there are any GROUP or USER entries, there must be exactly one
36*7c478bd9Sstevel@tonic-gate  *	CLASS_OBJ entry.
37*7c478bd9Sstevel@tonic-gate  *	The same rules apply to default ACL entries.
38*7c478bd9Sstevel@tonic-gate  */
39*7c478bd9Sstevel@tonic-gate 
40*7c478bd9Sstevel@tonic-gate #include <errno.h>
41*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
42*7c478bd9Sstevel@tonic-gate #include <string.h>
43*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
44*7c478bd9Sstevel@tonic-gate #include <sys/acl.h>
45*7c478bd9Sstevel@tonic-gate 
46*7c478bd9Sstevel@tonic-gate struct entry {
47*7c478bd9Sstevel@tonic-gate 	int	count;
48*7c478bd9Sstevel@tonic-gate 	uid_t	*id;
49*7c478bd9Sstevel@tonic-gate };
50*7c478bd9Sstevel@tonic-gate 
51*7c478bd9Sstevel@tonic-gate struct entry_stat {
52*7c478bd9Sstevel@tonic-gate 	struct entry	user_obj;
53*7c478bd9Sstevel@tonic-gate 	struct entry	user;
54*7c478bd9Sstevel@tonic-gate 	struct entry	group_obj;
55*7c478bd9Sstevel@tonic-gate 	struct entry	group;
56*7c478bd9Sstevel@tonic-gate 	struct entry	other_obj;
57*7c478bd9Sstevel@tonic-gate 	struct entry	class_obj;
58*7c478bd9Sstevel@tonic-gate 	struct entry	def_user_obj;
59*7c478bd9Sstevel@tonic-gate 	struct entry	def_user;
60*7c478bd9Sstevel@tonic-gate 	struct entry	def_group_obj;
61*7c478bd9Sstevel@tonic-gate 	struct entry	def_group;
62*7c478bd9Sstevel@tonic-gate 	struct entry	def_other_obj;
63*7c478bd9Sstevel@tonic-gate 	struct entry	def_class_obj;
64*7c478bd9Sstevel@tonic-gate };
65*7c478bd9Sstevel@tonic-gate 
66*7c478bd9Sstevel@tonic-gate static void free_mem(struct entry_stat *);
67*7c478bd9Sstevel@tonic-gate static int check_dup(int, uid_t *, uid_t, struct entry_stat *);
68*7c478bd9Sstevel@tonic-gate 
69*7c478bd9Sstevel@tonic-gate int
70*7c478bd9Sstevel@tonic-gate aclcheck(aclent_t *aclbufp, int nentries, int *which)
71*7c478bd9Sstevel@tonic-gate {
72*7c478bd9Sstevel@tonic-gate 	struct entry_stat	tally;
73*7c478bd9Sstevel@tonic-gate 	aclent_t		*aclentp;
74*7c478bd9Sstevel@tonic-gate 	uid_t			**idp;
75*7c478bd9Sstevel@tonic-gate 	int			cnt;
76*7c478bd9Sstevel@tonic-gate 
77*7c478bd9Sstevel@tonic-gate 	*which = -1;
78*7c478bd9Sstevel@tonic-gate 	memset(&tally, '\0', sizeof (tally));
79*7c478bd9Sstevel@tonic-gate 
80*7c478bd9Sstevel@tonic-gate 	for (aclentp = aclbufp; nentries > 0; nentries--, aclentp++) {
81*7c478bd9Sstevel@tonic-gate 		switch (aclentp->a_type) {
82*7c478bd9Sstevel@tonic-gate 		case USER_OBJ:
83*7c478bd9Sstevel@tonic-gate 			/* check uniqueness */
84*7c478bd9Sstevel@tonic-gate 			if (tally.user_obj.count > 0) {
85*7c478bd9Sstevel@tonic-gate 				*which = (int) (aclentp - aclbufp);
86*7c478bd9Sstevel@tonic-gate 				(void) free_mem(&tally);
87*7c478bd9Sstevel@tonic-gate 				errno = EINVAL;
88*7c478bd9Sstevel@tonic-gate 				return (USER_ERROR);
89*7c478bd9Sstevel@tonic-gate 			}
90*7c478bd9Sstevel@tonic-gate 			tally.user_obj.count = 1;
91*7c478bd9Sstevel@tonic-gate 			break;
92*7c478bd9Sstevel@tonic-gate 
93*7c478bd9Sstevel@tonic-gate 		case GROUP_OBJ:
94*7c478bd9Sstevel@tonic-gate 			/* check uniqueness */
95*7c478bd9Sstevel@tonic-gate 			if (tally.group_obj.count > 0) {
96*7c478bd9Sstevel@tonic-gate 				*which = (int) (aclentp - aclbufp);
97*7c478bd9Sstevel@tonic-gate 				(void) free_mem(&tally);
98*7c478bd9Sstevel@tonic-gate 				errno = EINVAL;
99*7c478bd9Sstevel@tonic-gate 				return (GRP_ERROR);
100*7c478bd9Sstevel@tonic-gate 			}
101*7c478bd9Sstevel@tonic-gate 			tally.group_obj.count = 1;
102*7c478bd9Sstevel@tonic-gate 			break;
103*7c478bd9Sstevel@tonic-gate 
104*7c478bd9Sstevel@tonic-gate 		case OTHER_OBJ:
105*7c478bd9Sstevel@tonic-gate 			/* check uniqueness */
106*7c478bd9Sstevel@tonic-gate 			if (tally.other_obj.count > 0) {
107*7c478bd9Sstevel@tonic-gate 				*which = (int) (aclentp - aclbufp);
108*7c478bd9Sstevel@tonic-gate 				(void) free_mem(&tally);
109*7c478bd9Sstevel@tonic-gate 				errno = EINVAL;
110*7c478bd9Sstevel@tonic-gate 				return (OTHER_ERROR);
111*7c478bd9Sstevel@tonic-gate 			}
112*7c478bd9Sstevel@tonic-gate 			tally.other_obj.count = 1;
113*7c478bd9Sstevel@tonic-gate 			break;
114*7c478bd9Sstevel@tonic-gate 
115*7c478bd9Sstevel@tonic-gate 		case CLASS_OBJ:
116*7c478bd9Sstevel@tonic-gate 			/* check uniqueness */
117*7c478bd9Sstevel@tonic-gate 			if (tally.class_obj.count > 0) {
118*7c478bd9Sstevel@tonic-gate 				*which = (int) (aclentp - aclbufp);
119*7c478bd9Sstevel@tonic-gate 				(void) free_mem(&tally);
120*7c478bd9Sstevel@tonic-gate 				errno = EINVAL;
121*7c478bd9Sstevel@tonic-gate 				return (CLASS_ERROR);
122*7c478bd9Sstevel@tonic-gate 			}
123*7c478bd9Sstevel@tonic-gate 			tally.class_obj.count = 1;
124*7c478bd9Sstevel@tonic-gate 			break;
125*7c478bd9Sstevel@tonic-gate 
126*7c478bd9Sstevel@tonic-gate 		case USER:
127*7c478bd9Sstevel@tonic-gate 		case GROUP:
128*7c478bd9Sstevel@tonic-gate 		case DEF_USER:
129*7c478bd9Sstevel@tonic-gate 		case DEF_GROUP:
130*7c478bd9Sstevel@tonic-gate 			/* check duplicate */
131*7c478bd9Sstevel@tonic-gate 			if (aclentp->a_type == DEF_USER) {
132*7c478bd9Sstevel@tonic-gate 				cnt = (tally.def_user.count)++;
133*7c478bd9Sstevel@tonic-gate 				idp = &(tally.def_user.id);
134*7c478bd9Sstevel@tonic-gate 			} else if (aclentp->a_type == DEF_GROUP) {
135*7c478bd9Sstevel@tonic-gate 				cnt = (tally.def_group.count)++;
136*7c478bd9Sstevel@tonic-gate 				idp = &(tally.def_group.id);
137*7c478bd9Sstevel@tonic-gate 			} else if (aclentp->a_type == USER) {
138*7c478bd9Sstevel@tonic-gate 				cnt = (tally.user.count)++;
139*7c478bd9Sstevel@tonic-gate 				idp = &(tally.user.id);
140*7c478bd9Sstevel@tonic-gate 			} else {
141*7c478bd9Sstevel@tonic-gate 				cnt = (tally.group.count)++;
142*7c478bd9Sstevel@tonic-gate 				idp = &(tally.group.id);
143*7c478bd9Sstevel@tonic-gate 			}
144*7c478bd9Sstevel@tonic-gate 
145*7c478bd9Sstevel@tonic-gate 			if (cnt == 0) {
146*7c478bd9Sstevel@tonic-gate 				*idp = calloc(nentries, sizeof (uid_t));
147*7c478bd9Sstevel@tonic-gate 				if (*idp == NULL)
148*7c478bd9Sstevel@tonic-gate 					return (MEM_ERROR);
149*7c478bd9Sstevel@tonic-gate 			} else {
150*7c478bd9Sstevel@tonic-gate 				if (check_dup(cnt, *idp, aclentp->a_id,
151*7c478bd9Sstevel@tonic-gate 				    &tally) == -1) {
152*7c478bd9Sstevel@tonic-gate 					*which = (int) (aclentp - aclbufp);
153*7c478bd9Sstevel@tonic-gate 					return (DUPLICATE_ERROR);
154*7c478bd9Sstevel@tonic-gate 				}
155*7c478bd9Sstevel@tonic-gate 			}
156*7c478bd9Sstevel@tonic-gate 			(*idp)[cnt] = aclentp->a_id;
157*7c478bd9Sstevel@tonic-gate 			break;
158*7c478bd9Sstevel@tonic-gate 
159*7c478bd9Sstevel@tonic-gate 		case DEF_USER_OBJ:
160*7c478bd9Sstevel@tonic-gate 			/* check uniqueness */
161*7c478bd9Sstevel@tonic-gate 			if (tally.def_user_obj.count > 0) {
162*7c478bd9Sstevel@tonic-gate 				*which = (int) (aclentp - aclbufp);
163*7c478bd9Sstevel@tonic-gate 				(void) free_mem(&tally);
164*7c478bd9Sstevel@tonic-gate 				errno = EINVAL;
165*7c478bd9Sstevel@tonic-gate 				return (USER_ERROR);
166*7c478bd9Sstevel@tonic-gate 			}
167*7c478bd9Sstevel@tonic-gate 			tally.def_user_obj.count = 1;
168*7c478bd9Sstevel@tonic-gate 			break;
169*7c478bd9Sstevel@tonic-gate 
170*7c478bd9Sstevel@tonic-gate 		case DEF_GROUP_OBJ:
171*7c478bd9Sstevel@tonic-gate 			/* check uniqueness */
172*7c478bd9Sstevel@tonic-gate 			if (tally.def_group_obj.count > 0) {
173*7c478bd9Sstevel@tonic-gate 				*which = (int) (aclentp - aclbufp);
174*7c478bd9Sstevel@tonic-gate 				(void) free_mem(&tally);
175*7c478bd9Sstevel@tonic-gate 				errno = EINVAL;
176*7c478bd9Sstevel@tonic-gate 				return (GRP_ERROR);
177*7c478bd9Sstevel@tonic-gate 			}
178*7c478bd9Sstevel@tonic-gate 			tally.def_group_obj.count = 1;
179*7c478bd9Sstevel@tonic-gate 			break;
180*7c478bd9Sstevel@tonic-gate 
181*7c478bd9Sstevel@tonic-gate 		case DEF_OTHER_OBJ:
182*7c478bd9Sstevel@tonic-gate 			/* check uniqueness */
183*7c478bd9Sstevel@tonic-gate 			if (tally.def_other_obj.count > 0) {
184*7c478bd9Sstevel@tonic-gate 				*which = (int) (aclentp - aclbufp);
185*7c478bd9Sstevel@tonic-gate 				(void) free_mem(&tally);
186*7c478bd9Sstevel@tonic-gate 				errno = EINVAL;
187*7c478bd9Sstevel@tonic-gate 				return (OTHER_ERROR);
188*7c478bd9Sstevel@tonic-gate 			}
189*7c478bd9Sstevel@tonic-gate 			tally.def_other_obj.count = 1;
190*7c478bd9Sstevel@tonic-gate 			break;
191*7c478bd9Sstevel@tonic-gate 
192*7c478bd9Sstevel@tonic-gate 		case DEF_CLASS_OBJ:
193*7c478bd9Sstevel@tonic-gate 			/* check uniqueness */
194*7c478bd9Sstevel@tonic-gate 			if (tally.def_class_obj.count > 0) {
195*7c478bd9Sstevel@tonic-gate 				*which = (int) (aclentp - aclbufp);
196*7c478bd9Sstevel@tonic-gate 				(void) free_mem(&tally);
197*7c478bd9Sstevel@tonic-gate 				errno = EINVAL;
198*7c478bd9Sstevel@tonic-gate 				return (CLASS_ERROR);
199*7c478bd9Sstevel@tonic-gate 			}
200*7c478bd9Sstevel@tonic-gate 			tally.def_class_obj.count = 1;
201*7c478bd9Sstevel@tonic-gate 			break;
202*7c478bd9Sstevel@tonic-gate 
203*7c478bd9Sstevel@tonic-gate 		default:
204*7c478bd9Sstevel@tonic-gate 			(void) free_mem(&tally);
205*7c478bd9Sstevel@tonic-gate 			errno = EINVAL;
206*7c478bd9Sstevel@tonic-gate 			*which = (int) (aclentp - aclbufp);
207*7c478bd9Sstevel@tonic-gate 			return (ENTRY_ERROR);
208*7c478bd9Sstevel@tonic-gate 		}
209*7c478bd9Sstevel@tonic-gate 	}
210*7c478bd9Sstevel@tonic-gate 	/* If there are group or user entries, there must be one class entry */
211*7c478bd9Sstevel@tonic-gate 	if (tally.user.count > 0 || tally.group.count > 0)
212*7c478bd9Sstevel@tonic-gate 		if (tally.class_obj.count != 1) {
213*7c478bd9Sstevel@tonic-gate 			(void) free_mem(&tally);
214*7c478bd9Sstevel@tonic-gate 			errno = EINVAL;
215*7c478bd9Sstevel@tonic-gate 			return (MISS_ERROR);
216*7c478bd9Sstevel@tonic-gate 		}
217*7c478bd9Sstevel@tonic-gate 	/* same is true for default entries */
218*7c478bd9Sstevel@tonic-gate 	if (tally.def_user.count > 0 || tally.def_group.count > 0)
219*7c478bd9Sstevel@tonic-gate 		if (tally.def_class_obj.count != 1) {
220*7c478bd9Sstevel@tonic-gate 			(void) free_mem(&tally);
221*7c478bd9Sstevel@tonic-gate 			errno = EINVAL;
222*7c478bd9Sstevel@tonic-gate 			return (MISS_ERROR);
223*7c478bd9Sstevel@tonic-gate 		}
224*7c478bd9Sstevel@tonic-gate 
225*7c478bd9Sstevel@tonic-gate 	/* there must be exactly one user_obj, group_obj, and other_obj entry */
226*7c478bd9Sstevel@tonic-gate 	if (tally.user_obj.count != 1 ||
227*7c478bd9Sstevel@tonic-gate 	    tally.group_obj.count != 1 ||
228*7c478bd9Sstevel@tonic-gate 		tally.other_obj.count != 1) {
229*7c478bd9Sstevel@tonic-gate 		(void) free_mem(&tally);
230*7c478bd9Sstevel@tonic-gate 		errno = EINVAL;
231*7c478bd9Sstevel@tonic-gate 		return (MISS_ERROR);
232*7c478bd9Sstevel@tonic-gate 	}
233*7c478bd9Sstevel@tonic-gate 
234*7c478bd9Sstevel@tonic-gate 	/* has default? same rules apply to default entries */
235*7c478bd9Sstevel@tonic-gate 	if (tally.def_user.count > 0 ||
236*7c478bd9Sstevel@tonic-gate 	    tally.def_user_obj.count > 0 ||
237*7c478bd9Sstevel@tonic-gate 	    tally.def_group.count > 0 ||
238*7c478bd9Sstevel@tonic-gate 	    tally.def_group_obj.count > 0 ||
239*7c478bd9Sstevel@tonic-gate 	    tally.def_class_obj.count > 0 ||
240*7c478bd9Sstevel@tonic-gate 	    tally.def_other_obj.count > 0)
241*7c478bd9Sstevel@tonic-gate 		if (tally.def_user_obj.count != 1 ||
242*7c478bd9Sstevel@tonic-gate 		    tally.def_group_obj.count != 1 ||
243*7c478bd9Sstevel@tonic-gate 		    tally.def_other_obj.count != 1) {
244*7c478bd9Sstevel@tonic-gate 			(void) free_mem(&tally);
245*7c478bd9Sstevel@tonic-gate 			errno = EINVAL;
246*7c478bd9Sstevel@tonic-gate 			return (MISS_ERROR);
247*7c478bd9Sstevel@tonic-gate 		}
248*7c478bd9Sstevel@tonic-gate 	(void) free_mem(&tally);
249*7c478bd9Sstevel@tonic-gate 	return (0);
250*7c478bd9Sstevel@tonic-gate }
251*7c478bd9Sstevel@tonic-gate 
252*7c478bd9Sstevel@tonic-gate static void
253*7c478bd9Sstevel@tonic-gate free_mem(struct entry_stat *tallyp)
254*7c478bd9Sstevel@tonic-gate {
255*7c478bd9Sstevel@tonic-gate 	if ((tallyp->user).count > 0)
256*7c478bd9Sstevel@tonic-gate 		free((tallyp->user).id);
257*7c478bd9Sstevel@tonic-gate 	if ((tallyp->group).count > 0)
258*7c478bd9Sstevel@tonic-gate 		free((tallyp->group).id);
259*7c478bd9Sstevel@tonic-gate 	if ((tallyp->def_user).count > 0)
260*7c478bd9Sstevel@tonic-gate 		free((tallyp->def_user).id);
261*7c478bd9Sstevel@tonic-gate 	if ((tallyp->def_group).count > 0)
262*7c478bd9Sstevel@tonic-gate 		free((tallyp->def_group).id);
263*7c478bd9Sstevel@tonic-gate }
264*7c478bd9Sstevel@tonic-gate 
265*7c478bd9Sstevel@tonic-gate static int
266*7c478bd9Sstevel@tonic-gate check_dup(int count, uid_t *ids, uid_t newid, struct entry_stat *tallyp)
267*7c478bd9Sstevel@tonic-gate {
268*7c478bd9Sstevel@tonic-gate 	int	i;
269*7c478bd9Sstevel@tonic-gate 
270*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < count; i++) {
271*7c478bd9Sstevel@tonic-gate 		if (ids[i] == newid) {
272*7c478bd9Sstevel@tonic-gate 			errno = EINVAL;
273*7c478bd9Sstevel@tonic-gate 			(void) free_mem(tallyp);
274*7c478bd9Sstevel@tonic-gate 			return (-1);
275*7c478bd9Sstevel@tonic-gate 		}
276*7c478bd9Sstevel@tonic-gate 	}
277*7c478bd9Sstevel@tonic-gate 	return (0);
278*7c478bd9Sstevel@tonic-gate }
279