1/* 2 * Copyright (c) 1999 Apple Computer, 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/types.h> 25#include <sys/acl.h> 26#include <stdlib.h> 27#include <fcntl.h> 28#include <strings.h> 29#include <errno.h> 30#include <uuid/uuid.h> 31 32/* 33 * Versions of copy_int/copy_ext that retain native endianity. 34 */ 35extern ssize_t acl_copy_ext_native(void *buf_p, acl_t acl, ssize_t size); 36extern acl_t acl_copy_int_native(const void *buf_p); 37 38struct _filesec { 39 int fs_valid; 40#define FS_VALID_UID (1<<0) 41#define FS_VALID_GID (1<<1) 42#define FS_VALID_UUID (1<<2) 43#define FS_VALID_GRPUUID (1<<3) 44#define FS_VALID_MODE (1<<4) 45#define FS_VALID_ACL (1<<5) 46 uid_t fs_uid; 47 gid_t fs_gid; 48 uuid_t fs_uuid; 49 uuid_t fs_grpuuid; 50 mode_t fs_mode; 51 size_t fs_aclsize; 52 void *fs_aclbuf; 53}; 54 55#define FS_ISVALID(_fsec, _bit) ((_fsec)->fs_valid & (_bit)) 56#define FS_CLEAR(_fsec, _bit) ((_fsec)->fs_valid &= ~(_bit)) 57#define FS_SET(_fsec, _bit) ((_fsec)->fs_valid |= (_bit)) 58 59static void filesec_discard_aclbuf(struct _filesec *fsec); 60 61filesec_t 62filesec_init(void) 63{ 64 struct _filesec *fsp; 65 66 fsp = malloc(sizeof(*fsp)); 67 if (fsp != NULL) 68 fsp->fs_valid = 0; 69 return(fsp); 70} 71 72filesec_t 73filesec_dup(filesec_t fsec) 74{ 75 struct _filesec *fsp; 76 77 fsp = malloc(sizeof(*fsp)); 78 if (fsp != NULL) { 79 *fsp = *fsec; 80 if (FS_ISVALID(fsec, FS_VALID_ACL)) { 81 if (fsec->fs_aclbuf != _FILESEC_REMOVE_ACL) { 82 fsp->fs_aclbuf = malloc(fsec->fs_aclsize); 83 if (fsp->fs_aclbuf == NULL) { 84 free(fsp); 85 return(NULL); 86 } 87 bcopy(fsec->fs_aclbuf, fsp->fs_aclbuf, fsec->fs_aclsize); 88 } 89 } 90 } 91 return(fsp); 92} 93 94void 95filesec_free(filesec_t fsec) 96{ 97 filesec_discard_aclbuf(fsec); 98 free(fsec); 99} 100 101int 102filesec_get_property(filesec_t fsec, filesec_property_t property, void *propptr) 103{ 104 int error; 105 106 error = 0; 107 switch(property) { 108 case FILESEC_OWNER: 109 if (!FS_ISVALID(fsec, FS_VALID_UID)) { 110 error = ENOENT; 111 break; 112 } 113 if (propptr != NULL) 114 *(uid_t *)propptr = fsec->fs_uid; 115 break; 116 case FILESEC_GROUP: 117 if (!FS_ISVALID(fsec, FS_VALID_GID)) { 118 error = ENOENT; 119 break; 120 } 121 if (propptr != NULL) 122 *(gid_t *)propptr = fsec->fs_gid; 123 break; 124 case FILESEC_UUID: 125 if (!FS_ISVALID(fsec, FS_VALID_UUID)) { 126 error = ENOENT; 127 break; 128 } 129 if (propptr != NULL) 130 uuid_copy(*(uuid_t *)propptr, fsec->fs_uuid); 131 break; 132 case FILESEC_GRPUUID: 133 if (!FS_ISVALID(fsec, FS_VALID_GRPUUID)) { 134 error = ENOENT; 135 break; 136 } 137 if (propptr != NULL) 138 uuid_copy(*(uuid_t *)propptr, fsec->fs_grpuuid); 139 break; 140 case FILESEC_MODE: 141 if (!FS_ISVALID(fsec, FS_VALID_MODE)) { 142 error = ENOENT; 143 break; 144 } 145 if (propptr != NULL) 146 *(mode_t *)propptr = fsec->fs_mode; 147 break; 148 case FILESEC_ACL: 149 if (!FS_ISVALID(fsec, FS_VALID_ACL)) { 150 error = ENOENT; 151 break; 152 } 153 if (propptr != NULL) { 154 if (fsec->fs_aclbuf == _FILESEC_REMOVE_ACL) { 155 *(acl_t *)propptr = _FILESEC_REMOVE_ACL; 156 } else { 157 *(acl_t *)propptr = acl_copy_int_native(fsec->fs_aclbuf); 158 if (*(acl_t *)propptr == NULL) 159 error = errno; 160 } 161 } 162 break; 163 case FILESEC_ACL_RAW: 164 if (!FS_ISVALID(fsec, FS_VALID_ACL)) { 165 error = ENOENT; 166 break; 167 } 168 if (propptr != NULL) 169 *(void **)propptr = fsec->fs_aclbuf; 170 break; 171 case FILESEC_ACL_ALLOCSIZE: 172 if (!FS_ISVALID(fsec, FS_VALID_ACL)) { 173 error = ENOENT; 174 break; 175 } 176 if (propptr != NULL) 177 *(size_t *)propptr = fsec->fs_aclsize; 178 break; 179 default: 180 error = EINVAL; 181 break; 182 } 183 if (error) { 184 errno = error; 185 return(-1); 186 } 187 return(0); 188} 189 190int 191filesec_set_property(filesec_t fsec, filesec_property_t property, const void *propptr) 192{ 193 void *aclbuf; 194 ssize_t aclsize, copysize; 195 acl_t acl; 196 int error; 197 198 error = 0; 199 switch(property) { 200 case FILESEC_OWNER: 201 if (propptr == _FILESEC_UNSET_PROPERTY) { 202 FS_CLEAR(fsec, FS_VALID_UID); 203 } else { 204 fsec->fs_uid = *(uid_t *)propptr; 205 FS_SET(fsec, FS_VALID_UID); 206 } 207 break; 208 case FILESEC_GROUP: 209 if (propptr == _FILESEC_UNSET_PROPERTY) { 210 FS_CLEAR(fsec, FS_VALID_GID); 211 } else { 212 fsec->fs_gid = *(gid_t *)propptr; 213 FS_SET(fsec, FS_VALID_GID); 214 } 215 break; 216 case FILESEC_UUID: 217 if (propptr == _FILESEC_UNSET_PROPERTY) { 218 FS_CLEAR(fsec, FS_VALID_UUID); 219 } else { 220 uuid_copy(fsec->fs_uuid, *(uuid_t *)propptr); 221 FS_SET(fsec, FS_VALID_UUID); 222 } 223 break; 224 case FILESEC_GRPUUID: 225 if (propptr == _FILESEC_UNSET_PROPERTY) { 226 FS_CLEAR(fsec, FS_VALID_GRPUUID); 227 } else { 228 uuid_copy(fsec->fs_grpuuid, *(uuid_t *)propptr); 229 FS_SET(fsec, FS_VALID_GRPUUID); 230 } 231 break; 232 case FILESEC_MODE: 233 if (propptr == _FILESEC_UNSET_PROPERTY) { 234 FS_CLEAR(fsec, FS_VALID_MODE); 235 } else { 236 fsec->fs_mode = *(mode_t *)propptr; 237 FS_SET(fsec, FS_VALID_MODE); 238 } 239 break; 240 case FILESEC_ACL: 241 if (propptr == _FILESEC_UNSET_PROPERTY) { 242 filesec_discard_aclbuf(fsec); 243 FS_CLEAR(fsec, FS_VALID_ACL); 244 } else if (propptr == _FILESEC_REMOVE_ACL) { 245 filesec_discard_aclbuf(fsec); 246 fsec->fs_aclbuf = _FILESEC_REMOVE_ACL; 247 fsec->fs_aclsize = 0; 248 FS_SET(fsec, FS_VALID_ACL); 249 } else { 250 acl = *(acl_t *)propptr; 251 aclsize = acl_size(acl); 252 if (aclsize < 0) { 253 error = errno; 254 break; 255 } 256 if ((aclbuf = malloc(aclsize)) == NULL) { 257 error = errno; 258 break; 259 } 260 copysize = acl_copy_ext_native(aclbuf, acl, aclsize); 261 if (copysize < 0) { 262 free(aclbuf); 263 error = EINVAL; 264 break; 265 } 266 filesec_discard_aclbuf(fsec); 267 fsec->fs_aclbuf = aclbuf; 268 fsec->fs_aclsize = aclsize; 269 FS_SET(fsec, FS_VALID_ACL); 270 } 271 break; 272 case FILESEC_ACL_RAW: 273 filesec_discard_aclbuf(fsec); 274 if ((propptr != NULL) && (*(void **)propptr != NULL)) { 275 fsec->fs_aclbuf = *(void **)propptr; 276 FS_SET(fsec, FS_VALID_ACL); 277 } 278 break; 279 case FILESEC_ACL_ALLOCSIZE: 280 if (propptr != NULL) { 281 fsec->fs_aclsize = *(size_t *)propptr; 282 } else { 283 error = EINVAL; 284 } 285 break; 286 default: 287 error = EINVAL; 288 break; 289 } 290 if (error != 0) { 291 errno = error; 292 return (-1); 293 } 294 return (0); 295} 296 297int 298filesec_unset_property(filesec_t fsec, filesec_property_t property) 299{ 300 return filesec_set_property(fsec, property, _FILESEC_UNSET_PROPERTY); 301} 302 303int 304filesec_query_property(filesec_t fsec, filesec_property_t property, int *validptr) 305{ 306 int valid, error; 307 308 error = 0; 309 switch(property) { 310 case FILESEC_OWNER: 311 valid = FS_ISVALID(fsec, FS_VALID_UID); 312 break; 313 case FILESEC_GROUP: 314 valid = FS_ISVALID(fsec, FS_VALID_GID); 315 break; 316 case FILESEC_UUID: 317 valid = FS_ISVALID(fsec, FS_VALID_UUID); 318 break; 319 case FILESEC_GRPUUID: 320 valid = FS_ISVALID(fsec, FS_VALID_GRPUUID); 321 break; 322 case FILESEC_MODE: 323 valid = FS_ISVALID(fsec, FS_VALID_MODE); 324 break; 325 case FILESEC_ACL: 326 case FILESEC_ACL_RAW: 327 case FILESEC_ACL_ALLOCSIZE: 328 valid = FS_ISVALID(fsec, FS_VALID_ACL); 329 break; 330 default: 331 error = EINVAL; 332 break; 333 } 334 335 if (error != 0) { 336 errno = error; 337 return(-1); 338 } 339 *validptr = valid; 340 return(0); 341} 342 343static void 344filesec_discard_aclbuf(struct _filesec *fsec) 345{ 346 if (FS_ISVALID(fsec, FS_VALID_ACL)) { 347 if (fsec->fs_aclbuf != _FILESEC_REMOVE_ACL) 348 free(fsec->fs_aclbuf); 349 fsec->fs_aclbuf = NULL; 350 fsec->fs_aclsize = 0; 351 FS_CLEAR(fsec, FS_VALID_ACL); 352 } 353} 354