/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright (c) 1995 Sun Microsystems, Inc. All Rights Reserved * * module: * acls.c * * purpose: * routines to manipulate access control lists, mapping between * the data structures required by the filesystem ACL system calls * and the representation used in our fileinfo structure. * */ #ident "%W% %E% SMI" #include #include #include "filesync.h" #include "database.h" #ifdef NO_ACLS /* * Solaris 2.4 libc.so does not contain this entry point, so if we * want to build a 2.4 version of filesync, we need to provide a * dummy entry point that will fail when-ever it is called. */ #define acl bogus_acl static int acl(const char *name, int opcode, int count, aclent_t *acls) { return (-1); } #endif /* * routine: * get_acls * * purpose: * to read the ACL (if any) from a file into a fileinfo structure * * parameters: * name of file * pointer to fileinfo structure * * returns: * number of ACL entries */ int get_acls(const char *name, struct fileinfo *ip) { int count; int i; static aclent_t acls[MAX_ACL_ENTRIES]; aclent_t *list; count = acl(name, GETACL, MAX_ACL_ENTRIES, acls); if (count <= 0) return (0); /* with a count of 3 or 4 there may not be any real ones */ if (count > 4) goto gotsome; /* look for anything beyond the normal unix protection */ for (i = 0; i < count; i++) switch (acls[i].a_type) { default: /* weird types are real */ goto gotsome; case USER_OBJ: case GROUP_OBJ: case OTHER_OBJ: case CLASS_OBJ: continue; /* all file have these */ } return (0); /* nothing interesting */ gotsome: /* allocate an array to hold the acls */ list = (aclent_t *) malloc(count * sizeof (*list)); if (list == 0) nomem("Access Control List"); /* copy the acls into the new list */ for (i = 0; i < count; i++) { list[i].a_type = acls[i].a_type; list[i].a_id = acls[i].a_id; list[i].a_perm = acls[i].a_perm; } ip->f_acls = list; ip->f_numacls = count; return (ip->f_numacls); } /* * routine: * cmp_acls * * purpose: * determine whether or not two ACLs are the same * * parameters: * pointer to first fileinfo * pointer to second fileinfo * * returns: * true equal * false different */ int cmp_acls(struct fileinfo *f1, struct fileinfo *f2) { int i; if (f1->f_numacls != f2->f_numacls) return (0); if (f1->f_numacls == 0) return (1); for (i = 0; i < f1->f_numacls; i++) { if (f1->f_acls[i].a_type != f2->f_acls[i].a_type) return (0); if (f1->f_acls[i].a_id != f2->f_acls[i].a_id) return (0); if (f1->f_acls[i].a_perm != f2->f_acls[i].a_perm) return (0); } return (1); } /* * routine: * set_acls * * purpose: * to write the ACL of a file * * parameters: * name of file * fileinfo pointer (which contains an acl pointer) * * returns: * retcode and errno */ int set_acls(const char *name, struct fileinfo *fp) { int rc; int nacl; aclent_t acls[4], *list; if (fp->f_numacls == 0) { /* fabricate a standard set of bogus ACLs */ acls[0].a_type = USER_OBJ; acls[0].a_id = fp->f_uid; acls[0].a_perm = (fp->f_mode >> 6) & 7; acls[1].a_type = GROUP_OBJ; acls[1].a_id = fp->f_gid; acls[1].a_perm = (fp->f_mode >> 3) & 7; acls[2].a_type = CLASS_OBJ; acls[2].a_id = 0; acls[2].a_perm = (fp->f_mode >> 6) & 7; acls[3].a_type = OTHER_OBJ; acls[3].a_id = 0; acls[3].a_perm = fp->f_mode & 7; nacl = 4; list = acls; } else { nacl = fp->f_numacls; list = fp->f_acls; } rc = acl(name, SETACL, nacl, list); /* non-negative number mean success */ if (rc < 0) return (rc); else return (0); } /* * routine: * show_acls * * purpose: * to map an acl into arguments for a setfacl command * * paramters: * number of elements in list * pointer to list * * returns: * pointer to character buffer containing arguments */ char *show_acls(int numacl, aclent_t *list) { int i, j; int type, perm, id; char *s; static char buf[ MAX_LINE ]; s = buf; if (numacl > 0) { *s++ = '-'; *s++ = 's'; *s++ = ' '; } else { *s++ = '-'; *s++ = 'd'; } for (i = 0; i < numacl; i++) { type = list[i].a_type; id = list[i].a_id; perm = list[i].a_perm; if (i > 0) *s++ = ','; /* note whether this is per-file or default */ if (type & ACL_DEFAULT) { *s++ = 'd'; *s++ = ':'; } /* print out the entry type */ if (type & (USER_OBJ|USER)) { *s++ = 'u'; *s++ = ':'; } else if (type & (GROUP_OBJ|GROUP)) { *s++ = 'g'; *s++ = ':'; } else if (type & OTHER_OBJ) { *s++ = 'o'; *s++ = ':'; } else if (type & CLASS_OBJ) { *s++ = 'm'; *s++ = ':'; } /* print out the ID for this ACL */ if (type & (USER_OBJ|GROUP_OBJ)) *s++ = ':'; else if (type & (USER|GROUP)) { for (j = 1; id/j > 10; j *= 10); while (j > 0) { *s++ = '0' + (id/j); id %= j*10; j /= 10; } *s++ = ':'; } /* print out the permissions for this ACL */ *s++ = (perm & 04) ? 'r' : '-'; *s++ = (perm & 02) ? 'w' : '-'; *s++ = (perm & 01) ? 'x' : '-'; } *s = 0; return (buf); }