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