1/* 2 * Copyright (c) 2004, 2011 Apple Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24#include <sys/appleapiopts.h> 25#include <sys/types.h> 26#include <sys/acl.h> 27#include <errno.h> 28#include <stdlib.h> 29#include <string.h> 30 31#include "aclvar.h" 32 33#if __DARWIN_ACL_EXTENDED_ALLOW != KAUTH_ACE_PERMIT 34# error __DARWIN_ACL_EXTENDED_ALLOW != KAUTH_ACE_PERMIT 35#endif 36#if __DARWIN_ACL_EXTENDED_DENY != KAUTH_ACE_DENY 37# error __DARWIN_ACL_EXTENDED_DENY != KAUTH_ACE_DENY 38#endif 39 40int 41acl_copy_entry(acl_entry_t dest, acl_entry_t src) 42{ 43 /* validate arguments */ 44 _ACL_VALIDATE_ENTRY(dest); 45 _ACL_VALIDATE_ENTRY(src); 46 if (dest == src) { 47 errno = EINVAL; 48 return(-1); 49 } 50 bcopy(src, dest, sizeof(*src)); 51 return(0); 52} 53 54int 55acl_create_entry_np(acl_t *acl_p, acl_entry_t *entry_p, int index) 56{ 57 struct _acl *ap = *acl_p; 58 int i; 59 60 /* validate arguments */ 61 _ACL_VALIDATE_ACL(ap); 62 if (ap->a_entries >= ACL_MAX_ENTRIES) { 63 errno = ENOMEM; 64 return(-1); 65 } 66 if (index == ACL_LAST_ENTRY) 67 index = ap->a_entries; 68 if (index > ap->a_entries) { 69 errno = ERANGE; 70 return(-1); 71 } 72 73 /* move following entries out of the way */ 74 for (i = ap->a_entries; i > index; i--) 75 ap->a_ace[i] = ap->a_ace[i - 1]; 76 ap->a_entries++; 77 78 /* initialise new entry */ 79 memset(&ap->a_ace[index], 0, sizeof(ap->a_ace[index])); 80 ap->a_ace[index].ae_magic = _ACL_ENTRY_MAGIC; 81 ap->a_ace[index].ae_tag = ACL_UNDEFINED_TAG; 82 83 *entry_p = &ap->a_ace[index]; 84 return(0); 85} 86 87int 88acl_create_entry(acl_t *acl_p, acl_entry_t *entry_p) 89{ 90 return(acl_create_entry_np(acl_p, entry_p, ACL_LAST_ENTRY)); 91} 92 93int 94acl_delete_entry(acl_t acl, acl_entry_t entry) 95{ 96 int i; 97 98 _ACL_VALIDATE_ACL(acl); 99 _ACL_VALIDATE_ENTRY(entry); 100 _ACL_VALIDATE_ENTRY_CONTAINED(acl, entry); 101 102 /* copy following entries down & invalidate last slot */ 103 acl->a_entries--; 104 for (i = entry - &acl->a_ace[0]; i < acl->a_entries; i++) 105 acl->a_ace[i] = acl->a_ace[i + 1]; 106 acl->a_ace[acl->a_entries].ae_magic = 0; 107 /* Sync up the iterator's position if necessary */ 108 if (acl->a_last_get >= (entry - &acl->a_ace[0])) 109 acl->a_last_get--; 110 111 return(0); 112} 113 114int 115acl_get_entry(acl_t acl, int entry_id, acl_entry_t *entry_p) 116{ 117 118 _ACL_VALIDATE_ACL(acl); 119 if ((entry_id != ACL_FIRST_ENTRY) && 120 (entry_id != ACL_NEXT_ENTRY) && 121 (entry_id != ACL_LAST_ENTRY) && 122 ((entry_id < 0) || (entry_id >= acl->a_entries))) { 123 errno = EINVAL; 124 return(-1); 125 } 126 if (entry_id == ACL_FIRST_ENTRY) 127 entry_id = 0; 128 else 129 if (entry_id == ACL_NEXT_ENTRY) { 130 entry_id = acl->a_last_get + 1; 131 } 132 else 133 if (entry_id == ACL_LAST_ENTRY) 134 entry_id = acl->a_entries - 1; 135 136 if (entry_id >= acl->a_entries) { 137 errno = EINVAL; 138 return (-1); 139 } 140 141 *entry_p = &acl->a_ace[entry_id]; 142 acl->a_last_get = entry_id; 143 144 return(0); 145} 146 147void * 148acl_get_qualifier(acl_entry_t entry) 149{ 150 acl_tag_t tag_type; 151 void *result; 152 int error; 153 154 result = NULL; 155 if (!_ACL_VALID_ENTRY(entry)) { 156 errno = EINVAL; 157 } else if ((error = acl_get_tag_type(entry, &tag_type)) != 0) { 158 /* errno is set by acl_get_tag_type */ 159 } else { 160 switch(tag_type) { 161 case ACL_EXTENDED_ALLOW: 162 case ACL_EXTENDED_DENY: 163 if ((result = malloc(sizeof(guid_t))) != NULL) 164 bcopy(&entry->ae_applicable, result, sizeof(guid_t)); 165 break; 166 default: 167 errno = EINVAL; 168 break; 169 } 170 } 171 return(result); 172} 173 174int 175acl_get_tag_type(acl_entry_t entry, acl_tag_t *tag_type_p) 176{ 177 _ACL_VALIDATE_ENTRY(entry); 178 179 *tag_type_p = entry->ae_tag; 180 return(0); 181} 182 183int 184acl_set_qualifier(acl_entry_t entry, const void *tag_qualifier_p) 185{ 186 acl_tag_t tag_type; 187 188 _ACL_VALIDATE_ENTRY(entry); 189 if (acl_get_tag_type(entry, &tag_type) != 0) 190 return(-1); 191 192 switch(tag_type) { 193 case ACL_EXTENDED_ALLOW: 194 case ACL_EXTENDED_DENY: 195 bcopy(tag_qualifier_p, &entry->ae_applicable, sizeof(guid_t)); 196 break; 197 default: 198 errno = EINVAL; 199 return(-1); 200 } 201 return(0); 202} 203 204int 205acl_set_tag_type(acl_entry_t entry, acl_tag_t tag_type) 206{ 207 _ACL_VALIDATE_ENTRY(entry); 208 209 switch(tag_type) { 210 case ACL_EXTENDED_ALLOW: 211 case ACL_EXTENDED_DENY: 212 entry->ae_tag = tag_type; 213 break; 214 default: 215 errno = EINVAL; 216 return(-1); 217 } 218 return(0); 219} 220