4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #pragma ident "%Z%%M% %I% %E% SMI"
30 * aclcheck(): check validity of an ACL
31 * A valid ACL is defined as follows:
32 * There must be exactly one USER_OBJ, GROUP_OBJ, and OTHER_OBJ entry.
33 * If there are any USER entries, then the user id must be unique.
34 * If there are any GROUP entries, then the group id must be unique.
35 * If there are any GROUP or USER entries, there must be exactly one
37 * The same rules apply to default ACL entries.
43 #include <sys/types.h>
53 struct entry user_obj
;
55 struct entry group_obj
;
57 struct entry other_obj
;
58 struct entry class_obj
;
59 struct entry def_user_obj
;
60 struct entry def_user
;
61 struct entry def_group_obj
;
62 struct entry def_group
;
63 struct entry def_other_obj
;
64 struct entry def_class_obj
;
67 static void free_mem(struct entry_stat
*);
68 static int check_dup(int, uid_t
*, uid_t
, struct entry_stat
*);
71 aclent_aclcheck(aclent_t
*aclbufp
, int nentries
, int *which
, int isdir
)
73 struct entry_stat tally
;
79 memset(&tally
, '\0', sizeof (tally
));
81 for (aclentp
= aclbufp
; nentries
> 0; nentries
--, aclentp
++) {
82 switch (aclentp
->a_type
) {
84 /* check uniqueness */
85 if (tally
.user_obj
.count
> 0) {
86 *which
= (int)(aclentp
- aclbufp
);
87 (void) free_mem(&tally
);
89 return (EACL_USER_ERROR
);
91 tally
.user_obj
.count
= 1;
95 /* check uniqueness */
96 if (tally
.group_obj
.count
> 0) {
97 *which
= (int)(aclentp
- aclbufp
);
98 (void) free_mem(&tally
);
100 return (EACL_GRP_ERROR
);
102 tally
.group_obj
.count
= 1;
106 /* check uniqueness */
107 if (tally
.other_obj
.count
> 0) {
108 *which
= (int)(aclentp
- aclbufp
);
109 (void) free_mem(&tally
);
111 return (EACL_OTHER_ERROR
);
113 tally
.other_obj
.count
= 1;
117 /* check uniqueness */
118 if (tally
.class_obj
.count
> 0) {
119 *which
= (int)(aclentp
- aclbufp
);
120 (void) free_mem(&tally
);
122 return (EACL_CLASS_ERROR
);
124 tally
.class_obj
.count
= 1;
131 /* check duplicate */
132 if (aclentp
->a_type
== DEF_USER
) {
133 cnt
= (tally
.def_user
.count
)++;
134 idp
= &(tally
.def_user
.id
);
135 } else if (aclentp
->a_type
== DEF_GROUP
) {
136 cnt
= (tally
.def_group
.count
)++;
137 idp
= &(tally
.def_group
.id
);
138 } else if (aclentp
->a_type
== USER
) {
139 cnt
= (tally
.user
.count
)++;
140 idp
= &(tally
.user
.id
);
142 cnt
= (tally
.group
.count
)++;
143 idp
= &(tally
.group
.id
);
147 *idp
= calloc(nentries
, sizeof (uid_t
));
149 return (EACL_MEM_ERROR
);
151 if (check_dup(cnt
, *idp
, aclentp
->a_id
,
153 *which
= (int)(aclentp
- aclbufp
);
154 return (EACL_DUPLICATE_ERROR
);
157 (*idp
)[cnt
] = aclentp
->a_id
;
161 /* check uniqueness */
162 if (tally
.def_user_obj
.count
> 0) {
163 *which
= (int)(aclentp
- aclbufp
);
164 (void) free_mem(&tally
);
166 return (EACL_USER_ERROR
);
168 tally
.def_user_obj
.count
= 1;
172 /* check uniqueness */
173 if (tally
.def_group_obj
.count
> 0) {
174 *which
= (int)(aclentp
- aclbufp
);
175 (void) free_mem(&tally
);
177 return (EACL_GRP_ERROR
);
179 tally
.def_group_obj
.count
= 1;
183 /* check uniqueness */
184 if (tally
.def_other_obj
.count
> 0) {
185 *which
= (int)(aclentp
- aclbufp
);
186 (void) free_mem(&tally
);
188 return (EACL_OTHER_ERROR
);
190 tally
.def_other_obj
.count
= 1;
194 /* check uniqueness */
195 if (tally
.def_class_obj
.count
> 0) {
196 *which
= (int)(aclentp
- aclbufp
);
197 (void) free_mem(&tally
);
199 return (EACL_CLASS_ERROR
);
201 tally
.def_class_obj
.count
= 1;
205 (void) free_mem(&tally
);
207 *which
= (int)(aclentp
- aclbufp
);
208 return (EACL_ENTRY_ERROR
);
211 /* If there are group or user entries, there must be one class entry */
212 if (tally
.user
.count
> 0 || tally
.group
.count
> 0)
213 if (tally
.class_obj
.count
!= 1) {
214 (void) free_mem(&tally
);
216 return (EACL_MISS_ERROR
);
218 /* same is true for default entries */
219 if (tally
.def_user
.count
> 0 || tally
.def_group
.count
> 0)
220 if (tally
.def_class_obj
.count
!= 1) {
221 (void) free_mem(&tally
);
223 return (EACL_MISS_ERROR
);
226 /* there must be exactly one user_obj, group_obj, and other_obj entry */
227 if (tally
.user_obj
.count
!= 1 ||
228 tally
.group_obj
.count
!= 1 ||
229 tally
.other_obj
.count
!= 1) {
230 (void) free_mem(&tally
);
232 return (EACL_MISS_ERROR
);
235 /* has default? same rules apply to default entries */
236 if (tally
.def_user
.count
> 0 || tally
.def_user_obj
.count
> 0 ||
237 tally
.def_group
.count
> 0 || tally
.def_group_obj
.count
> 0 ||
238 tally
.def_class_obj
.count
> 0 || tally
.def_other_obj
.count
> 0) {
241 * Can't have default ACL's on non-directories
244 (void) free_mem(&tally
);
246 return (EACL_INHERIT_NOTDIR
);
249 if (tally
.def_user_obj
.count
!= 1 ||
250 tally
.def_group_obj
.count
!= 1 ||
251 tally
.def_other_obj
.count
!= 1) {
252 (void) free_mem(&tally
);
254 return (EACL_MISS_ERROR
);
258 (void) free_mem(&tally
);
263 aclcheck(aclent_t
*aclbufp
, int nentries
, int *which
)
265 return (aclent_aclcheck(aclbufp
, nentries
, which
, 1));
270 free_mem(struct entry_stat
*tallyp
)
272 if ((tallyp
->user
).count
> 0)
273 free((tallyp
->user
).id
);
274 if ((tallyp
->group
).count
> 0)
275 free((tallyp
->group
).id
);
276 if ((tallyp
->def_user
).count
> 0)
277 free((tallyp
->def_user
).id
);
278 if ((tallyp
->def_group
).count
> 0)
279 free((tallyp
->def_group
).id
);
283 check_dup(int count
, uid_t
*ids
, uid_t newid
, struct entry_stat
*tallyp
)
287 for (i
= 0; i
< count
; i
++) {
288 if (ids
[i
] == newid
) {
290 (void) free_mem(tallyp
);
297 #define IFLAGS (ACE_FILE_INHERIT_ACE|ACE_DIRECTORY_INHERIT_ACE| \
298 ACE_NO_PROPAGATE_INHERIT_ACE|ACE_INHERIT_ONLY_ACE)
301 ace_aclcheck(acl_t
*aclp
, int isdir
)
308 * step through all valid flags.
311 if (aclp
->acl_cnt
<= 0 || aclp
->acl_cnt
> MAX_ACL_ENTRIES
)
312 return (EACL_COUNT_ERROR
);
314 for (i
= 0, acep
= aclp
->acl_aclp
;
315 i
!= aclp
->acl_cnt
&& error
== 0; i
++, acep
++) {
316 switch (acep
->a_flags
& 0xf040) {
320 case ACE_IDENTIFIER_GROUP
:
321 case ACE_GROUP
|ACE_IDENTIFIER_GROUP
:
325 return (EACL_FLAGS_ERROR
);
329 * INHERIT_ONLY/NO_PROPAGATE need a to INHERIT_FILE
330 * or INHERIT_DIR also
333 (ACE_INHERIT_ONLY_ACE
|ACE_NO_PROPAGATE_INHERIT_ACE
)) {
334 if ((acep
->a_flags
& (ACE_FILE_INHERIT_ACE
|
335 ACE_DIRECTORY_INHERIT_ACE
)) == 0) {
337 return (EACL_INHERIT_ERROR
);
342 switch (acep
->a_type
) {
343 case ACE_ACCESS_ALLOWED_ACE_TYPE
:
344 case ACE_ACCESS_DENIED_ACE_TYPE
:
345 case ACE_SYSTEM_AUDIT_ACE_TYPE
:
346 case ACE_SYSTEM_ALARM_ACE_TYPE
:
350 return (EACL_ENTRY_ERROR
);
352 if (acep
->a_access_mask
> ACE_ALL_PERMS
) {
354 return (EACL_PERM_MASK_ERROR
);
362 acl_check(acl_t
*aclp
, int flag
)
367 switch (aclp
->acl_type
) {
369 error
= aclent_aclcheck(aclp
->acl_aclp
, aclp
->acl_cnt
,
373 error
= ace_aclcheck(aclp
, flag
);
377 error
= EACL_ENTRY_ERROR
;