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) 1995 Sun Microsystems, Inc. All Rights Reserved 24 * 25 * module: 26 * acls.c 27 * 28 * purpose: 29 * routines to manipulate access control lists, mapping between 30 * the data structures required by the filesystem ACL system calls 31 * and the representation used in our fileinfo structure. 32 * 33 */ 34 #ident "%W% %E% SMI" 35 36 #include <stdio.h> 37 #include <stdlib.h> 38 39 #include "filesync.h" 40 #include "database.h" 41 42 #ifdef NO_ACLS 43 /* 44 * Solaris 2.4 libc.so does not contain this entry point, so if we 45 * want to build a 2.4 version of filesync, we need to provide a 46 * dummy entry point that will fail when-ever it is called. 47 */ 48 #define acl bogus_acl 49 50 static int acl(const char *name, int opcode, int count, aclent_t *acls) 51 { 52 return (-1); 53 } 54 #endif 55 56 /* 57 * routine: 58 * get_acls 59 * 60 * purpose: 61 * to read the ACL (if any) from a file into a fileinfo structure 62 * 63 * parameters: 64 * name of file 65 * pointer to fileinfo structure 66 * 67 * returns: 68 * number of ACL entries 69 */ 70 int 71 get_acls(const char *name, struct fileinfo *ip) 72 { int count; 73 int i; 74 static aclent_t acls[MAX_ACL_ENTRIES]; 75 aclent_t *list; 76 77 count = acl(name, GETACL, MAX_ACL_ENTRIES, acls); 78 if (count <= 0) 79 return (0); 80 81 /* with a count of 3 or 4 there may not be any real ones */ 82 if (count > 4) 83 goto gotsome; 84 85 /* look for anything beyond the normal unix protection */ 86 for (i = 0; i < count; i++) 87 switch (acls[i].a_type) { 88 default: /* weird types are real */ 89 goto gotsome; 90 91 case USER_OBJ: 92 case GROUP_OBJ: 93 case OTHER_OBJ: 94 case CLASS_OBJ: 95 continue; /* all file have these */ 96 } 97 98 return (0); /* nothing interesting */ 99 100 gotsome: 101 /* allocate an array to hold the acls */ 102 list = (aclent_t *) malloc(count * sizeof (*list)); 103 if (list == 0) 104 nomem("Access Control List"); 105 106 /* copy the acls into the new list */ 107 for (i = 0; i < count; i++) { 108 list[i].a_type = acls[i].a_type; 109 list[i].a_id = acls[i].a_id; 110 list[i].a_perm = acls[i].a_perm; 111 } 112 113 ip->f_acls = list; 114 ip->f_numacls = count; 115 return (ip->f_numacls); 116 } 117 118 /* 119 * routine: 120 * cmp_acls 121 * 122 * purpose: 123 * determine whether or not two ACLs are the same 124 * 125 * parameters: 126 * pointer to first fileinfo 127 * pointer to second fileinfo 128 * 129 * returns: 130 * true equal 131 * false different 132 */ 133 int 134 cmp_acls(struct fileinfo *f1, struct fileinfo *f2) 135 { int i; 136 137 if (f1->f_numacls != f2->f_numacls) 138 return (0); 139 140 if (f1->f_numacls == 0) 141 return (1); 142 143 for (i = 0; i < f1->f_numacls; i++) { 144 if (f1->f_acls[i].a_type != f2->f_acls[i].a_type) 145 return (0); 146 if (f1->f_acls[i].a_id != f2->f_acls[i].a_id) 147 return (0); 148 if (f1->f_acls[i].a_perm != f2->f_acls[i].a_perm) 149 return (0); 150 } 151 152 return (1); 153 } 154 155 /* 156 * routine: 157 * set_acls 158 * 159 * purpose: 160 * to write the ACL of a file 161 * 162 * parameters: 163 * name of file 164 * fileinfo pointer (which contains an acl pointer) 165 * 166 * returns: 167 * retcode and errno 168 */ 169 int 170 set_acls(const char *name, struct fileinfo *fp) 171 { int rc; 172 int nacl; 173 aclent_t acls[4], *list; 174 175 if (fp->f_numacls == 0) { 176 /* fabricate a standard set of bogus ACLs */ 177 acls[0].a_type = USER_OBJ; 178 acls[0].a_id = fp->f_uid; 179 acls[0].a_perm = (fp->f_mode >> 6) & 7; 180 181 acls[1].a_type = GROUP_OBJ; 182 acls[1].a_id = fp->f_gid; 183 acls[1].a_perm = (fp->f_mode >> 3) & 7; 184 185 acls[2].a_type = CLASS_OBJ; 186 acls[2].a_id = 0; 187 acls[2].a_perm = (fp->f_mode >> 6) & 7; 188 189 acls[3].a_type = OTHER_OBJ; 190 acls[3].a_id = 0; 191 acls[3].a_perm = fp->f_mode & 7; 192 193 nacl = 4; 194 list = acls; 195 } else { 196 nacl = fp->f_numacls; 197 list = fp->f_acls; 198 } 199 200 rc = acl(name, SETACL, nacl, list); 201 202 /* non-negative number mean success */ 203 if (rc < 0) 204 return (rc); 205 else 206 return (0); 207 } 208 209 /* 210 * routine: 211 * show_acls 212 * 213 * purpose: 214 * to map an acl into arguments for a setfacl command 215 * 216 * paramters: 217 * number of elements in list 218 * pointer to list 219 * 220 * returns: 221 * pointer to character buffer containing arguments 222 */ 223 char 224 *show_acls(int numacl, aclent_t *list) 225 { int i, j; 226 int type, perm, id; 227 char *s; 228 static char buf[ MAX_LINE ]; 229 230 s = buf; 231 232 if (numacl > 0) { 233 *s++ = '-'; 234 *s++ = 's'; 235 *s++ = ' '; 236 } else { 237 *s++ = '-'; 238 *s++ = 'd'; 239 } 240 241 for (i = 0; i < numacl; i++) { 242 type = list[i].a_type; 243 id = list[i].a_id; 244 perm = list[i].a_perm; 245 246 if (i > 0) 247 *s++ = ','; 248 249 /* note whether this is per-file or default */ 250 if (type & ACL_DEFAULT) { 251 *s++ = 'd'; 252 *s++ = ':'; 253 } 254 255 /* print out the entry type */ 256 if (type & (USER_OBJ|USER)) { 257 *s++ = 'u'; 258 *s++ = ':'; 259 } else if (type & (GROUP_OBJ|GROUP)) { 260 *s++ = 'g'; 261 *s++ = ':'; 262 } else if (type & OTHER_OBJ) { 263 *s++ = 'o'; 264 *s++ = ':'; 265 } else if (type & CLASS_OBJ) { 266 *s++ = 'm'; 267 *s++ = ':'; 268 } 269 270 /* print out the ID for this ACL */ 271 if (type & (USER_OBJ|GROUP_OBJ)) 272 *s++ = ':'; 273 else if (type & (USER|GROUP)) { 274 for (j = 1; id/j > 10; j *= 10); 275 276 while (j > 0) { 277 *s++ = '0' + (id/j); 278 id %= j*10; 279 j /= 10; 280 } 281 282 *s++ = ':'; 283 } 284 285 /* print out the permissions for this ACL */ 286 *s++ = (perm & 04) ? 'r' : '-'; 287 *s++ = (perm & 02) ? 'w' : '-'; 288 *s++ = (perm & 01) ? 'x' : '-'; 289 } 290 291 *s = 0; 292 return (buf); 293 } 294