Annotation of embedaddon/rsync/lib/sysacls.c, revision 1.1
1.1 ! misho 1: /*
! 2: * Unix SMB/CIFS implementation.
! 3: * Based on the Samba ACL support code.
! 4: * Copyright (C) Jeremy Allison 2000.
! 5: * Copyright (C) 2007-2008 Wayne Davison
! 6: *
! 7: * The permission functions have been changed to get/set all bits via
! 8: * one call. Some functions that rsync doesn't need were also removed.
! 9: *
! 10: * This program is free software; you can redistribute it and/or modify
! 11: * it under the terms of the GNU General Public License as published by
! 12: * the Free Software Foundation; either version 3 of the License, or
! 13: * (at your option) any later version.
! 14: *
! 15: * This program is distributed in the hope that it will be useful,
! 16: * but WITHOUT ANY WARRANTY; without even the implied warranty of
! 17: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
! 18: * GNU General Public License for more details.
! 19: *
! 20: * You should have received a copy of the GNU General Public License
! 21: * with this program; if not, visit the http://fsf.org website.
! 22: */
! 23:
! 24: #include "rsync.h"
! 25: #include "sysacls.h"
! 26:
! 27: #ifdef SUPPORT_ACLS
! 28:
! 29: #ifdef DEBUG
! 30: #undef DEBUG
! 31: #endif
! 32: #define DEBUG(x,y)
! 33:
! 34: void SAFE_FREE(void *mem)
! 35: {
! 36: if (mem)
! 37: free(mem);
! 38: }
! 39:
! 40: /*
! 41: This file wraps all differing system ACL interfaces into a consistent
! 42: one based on the POSIX interface. It also returns the correct errors
! 43: for older UNIX systems that don't support ACLs.
! 44:
! 45: The interfaces that each ACL implementation must support are as follows :
! 46:
! 47: int sys_acl_get_entry( SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
! 48: int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
! 49: int sys_acl_get_info(SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T *tag_type_p, uint32 *bits_p, id_t *u_g_id_p)
! 50: SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
! 51: SMB_ACL_T sys_acl_get_fd(int fd)
! 52: SMB_ACL_T sys_acl_init( int count)
! 53: int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
! 54: int sys_acl_set_info(SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tag_type, uint32 bits, id_t u_g_id)
! 55: int sys_acl_set_access_bits(SMB_ACL_ENTRY_T entry, uint32 bits)
! 56: int sys_acl_valid( SMB_ACL_T theacl )
! 57: int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
! 58: int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
! 59: int sys_acl_delete_def_file(const char *path)
! 60: int sys_acl_free_acl(SMB_ACL_T posix_acl)
! 61:
! 62: */
! 63:
! 64: #if defined(HAVE_POSIX_ACLS) /*--------------------------------------------*/
! 65:
! 66: /* Identity mapping - easy. */
! 67:
! 68: int sys_acl_get_entry( SMB_ACL_T the_acl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
! 69: {
! 70: return acl_get_entry( the_acl, entry_id, entry_p);
! 71: }
! 72:
! 73: int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
! 74: {
! 75: return acl_get_tag_type( entry_d, tag_type_p);
! 76: }
! 77:
! 78: SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
! 79: {
! 80: return acl_get_file( path_p, type);
! 81: }
! 82:
! 83: #if 0
! 84: SMB_ACL_T sys_acl_get_fd(int fd)
! 85: {
! 86: return acl_get_fd(fd);
! 87: }
! 88: #endif
! 89:
! 90: #if defined(HAVE_ACL_GET_PERM_NP)
! 91: #define acl_get_perm(p, b) acl_get_perm_np(p, b)
! 92: #endif
! 93:
! 94: int sys_acl_get_info(SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T *tag_type_p, uint32 *bits_p, id_t *u_g_id_p)
! 95: {
! 96: acl_permset_t permset;
! 97:
! 98: if (acl_get_tag_type(entry, tag_type_p) != 0
! 99: || acl_get_permset(entry, &permset) != 0)
! 100: return -1;
! 101:
! 102: *bits_p = (acl_get_perm(permset, ACL_READ) ? 4 : 0)
! 103: | (acl_get_perm(permset, ACL_WRITE) ? 2 : 0)
! 104: | (acl_get_perm(permset, ACL_EXECUTE) ? 1 : 0);
! 105:
! 106: if (*tag_type_p == SMB_ACL_USER || *tag_type_p == SMB_ACL_GROUP) {
! 107: void *qual;
! 108: if ((qual = acl_get_qualifier(entry)) == NULL)
! 109: return -1;
! 110: *u_g_id_p = *(id_t*)qual;
! 111: acl_free(qual);
! 112: }
! 113:
! 114: return 0;
! 115: }
! 116:
! 117: SMB_ACL_T sys_acl_init( int count)
! 118: {
! 119: return acl_init(count);
! 120: }
! 121:
! 122: int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
! 123: {
! 124: return acl_create_entry(pacl, pentry);
! 125: }
! 126:
! 127: int sys_acl_set_info(SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tag_type, uint32 bits, id_t u_g_id)
! 128: {
! 129: if (acl_set_tag_type(entry, tag_type) != 0)
! 130: return -1;
! 131:
! 132: if (tag_type == SMB_ACL_USER || tag_type == SMB_ACL_GROUP) {
! 133: if (acl_set_qualifier(entry, (void*)&u_g_id) != 0)
! 134: return -1;
! 135: }
! 136:
! 137: return sys_acl_set_access_bits(entry, bits);
! 138: }
! 139:
! 140: int sys_acl_set_access_bits(SMB_ACL_ENTRY_T entry, uint32 bits)
! 141: {
! 142: acl_permset_t permset;
! 143: int rc;
! 144: if ((rc = acl_get_permset(entry, &permset)) != 0)
! 145: return rc;
! 146: acl_clear_perms(permset);
! 147: if (bits & 4)
! 148: acl_add_perm(permset, ACL_READ);
! 149: if (bits & 2)
! 150: acl_add_perm(permset, ACL_WRITE);
! 151: if (bits & 1)
! 152: acl_add_perm(permset, ACL_EXECUTE);
! 153: return acl_set_permset(entry, permset);
! 154: }
! 155:
! 156: int sys_acl_valid( SMB_ACL_T theacl )
! 157: {
! 158: return acl_valid(theacl);
! 159: }
! 160:
! 161: int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
! 162: {
! 163: return acl_set_file(name, acltype, theacl);
! 164: }
! 165:
! 166: #if 0
! 167: int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
! 168: {
! 169: return acl_set_fd(fd, theacl);
! 170: }
! 171: #endif
! 172:
! 173: int sys_acl_delete_def_file(const char *name)
! 174: {
! 175: return acl_delete_def_file(name);
! 176: }
! 177:
! 178: int sys_acl_free_acl(SMB_ACL_T the_acl)
! 179: {
! 180: return acl_free(the_acl);
! 181: }
! 182:
! 183: #elif defined(HAVE_TRU64_ACLS) /*--------------------------------------------*/
! 184: /*
! 185: * The interface to DEC/Compaq Tru64 UNIX ACLs
! 186: * is based on Draft 13 of the POSIX spec which is
! 187: * slightly different from the Draft 16 interface.
! 188: *
! 189: * Also, some of the permset manipulation functions
! 190: * such as acl_clear_perm() and acl_add_perm() appear
! 191: * to be broken on Tru64 so we have to manipulate
! 192: * the permission bits in the permset directly.
! 193: */
! 194: int sys_acl_get_entry( SMB_ACL_T the_acl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
! 195: {
! 196: SMB_ACL_ENTRY_T entry;
! 197:
! 198: if (entry_id == SMB_ACL_FIRST_ENTRY && acl_first_entry(the_acl) != 0) {
! 199: return -1;
! 200: }
! 201:
! 202: errno = 0;
! 203: if ((entry = acl_get_entry(the_acl)) != NULL) {
! 204: *entry_p = entry;
! 205: return 1;
! 206: }
! 207:
! 208: return errno ? -1 : 0;
! 209: }
! 210:
! 211: int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
! 212: {
! 213: return acl_get_tag_type( entry_d, tag_type_p);
! 214: }
! 215:
! 216: SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
! 217: {
! 218: return acl_get_file((char *)path_p, type);
! 219: }
! 220:
! 221: #if 0
! 222: SMB_ACL_T sys_acl_get_fd(int fd)
! 223: {
! 224: return acl_get_fd(fd, ACL_TYPE_ACCESS);
! 225: }
! 226: #endif
! 227:
! 228: int sys_acl_get_info(SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T *tag_type_p, uint32 *bits_p, id_t *u_g_id_p)
! 229: {
! 230: acl_permset_t permset;
! 231:
! 232: if (acl_get_tag_type(entry, tag_type_p) != 0
! 233: || acl_get_permset(entry, &permset) != 0)
! 234: return -1;
! 235:
! 236: *bits_p = *permset & 7; /* Tru64 doesn't have acl_get_perm() */
! 237:
! 238: if (*tag_type_p == SMB_ACL_USER || *tag_type_p == SMB_ACL_GROUP) {
! 239: void *qual;
! 240: if ((qual = acl_get_qualifier(entry)) == NULL)
! 241: return -1;
! 242: *u_g_id_p = *(id_t*)qual;
! 243: acl_free_qualifier(qual, *tag_type_p);
! 244: }
! 245:
! 246: return 0;
! 247: }
! 248:
! 249: SMB_ACL_T sys_acl_init( int count)
! 250: {
! 251: return acl_init(count);
! 252: }
! 253:
! 254: int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
! 255: {
! 256: SMB_ACL_ENTRY_T entry;
! 257:
! 258: if ((entry = acl_create_entry(pacl)) == NULL) {
! 259: return -1;
! 260: }
! 261:
! 262: *pentry = entry;
! 263: return 0;
! 264: }
! 265:
! 266: int sys_acl_set_info(SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tag_type, uint32 bits, id_t u_g_id)
! 267: {
! 268: if (acl_set_tag_type(entry, tag_type) != 0)
! 269: return -1;
! 270:
! 271: if (tag_type == SMB_ACL_USER || tag_type == SMB_ACL_GROUP) {
! 272: if (acl_set_qualifier(entry, (void*)&u_g_id) != 0)
! 273: return -1;
! 274: }
! 275:
! 276: return sys_acl_set_access_bits(entry, bits);
! 277: }
! 278:
! 279: int sys_acl_set_access_bits(SMB_ACL_ENTRY_T entry, uint32 bits)
! 280: {
! 281: acl_permset_t permset;
! 282: int rc;
! 283: if ((rc = acl_get_permset(entry, &permset)) != 0)
! 284: return rc;
! 285: *permset = bits & 7;
! 286: return acl_set_permset(entry, permset);
! 287: }
! 288:
! 289: int sys_acl_valid( SMB_ACL_T theacl )
! 290: {
! 291: acl_entry_t entry;
! 292:
! 293: return acl_valid(theacl, &entry);
! 294: }
! 295:
! 296: int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
! 297: {
! 298: return acl_set_file((char *)name, acltype, theacl);
! 299: }
! 300:
! 301: #if 0
! 302: int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
! 303: {
! 304: return acl_set_fd(fd, ACL_TYPE_ACCESS, theacl);
! 305: }
! 306: #endif
! 307:
! 308: int sys_acl_delete_def_file(const char *name)
! 309: {
! 310: return acl_delete_def_file((char *)name);
! 311: }
! 312:
! 313: int sys_acl_free_acl(SMB_ACL_T the_acl)
! 314: {
! 315: return acl_free(the_acl);
! 316: }
! 317:
! 318: #elif defined(HAVE_UNIXWARE_ACLS) || defined(HAVE_SOLARIS_ACLS) /*-----------*/
! 319:
! 320: /*
! 321: * Donated by Michael Davidson <md@sco.COM> for UnixWare / OpenUNIX.
! 322: * Modified by Toomas Soome <tsoome@ut.ee> for Solaris.
! 323: */
! 324:
! 325: /*
! 326: * Note that while this code implements sufficient functionality
! 327: * to support the sys_acl_* interfaces it does not provide all
! 328: * of the semantics of the POSIX ACL interfaces.
! 329: *
! 330: * In particular, an ACL entry descriptor (SMB_ACL_ENTRY_T) returned
! 331: * from a call to sys_acl_get_entry() should not be assumed to be
! 332: * valid after calling any of the following functions, which may
! 333: * reorder the entries in the ACL.
! 334: *
! 335: * sys_acl_valid()
! 336: * sys_acl_set_file()
! 337: * sys_acl_set_fd()
! 338: */
! 339:
! 340: /*
! 341: * The only difference between Solaris and UnixWare / OpenUNIX is
! 342: * that the #defines for the ACL operations have different names
! 343: */
! 344: #if defined(HAVE_UNIXWARE_ACLS)
! 345:
! 346: #define SETACL ACL_SET
! 347: #define GETACL ACL_GET
! 348: #define GETACLCNT ACL_CNT
! 349:
! 350: #endif
! 351:
! 352:
! 353: int sys_acl_get_entry(SMB_ACL_T acl_d, int entry_id, SMB_ACL_ENTRY_T *entry_p)
! 354: {
! 355: if (entry_id != SMB_ACL_FIRST_ENTRY && entry_id != SMB_ACL_NEXT_ENTRY) {
! 356: errno = EINVAL;
! 357: return -1;
! 358: }
! 359:
! 360: if (entry_p == NULL) {
! 361: errno = EINVAL;
! 362: return -1;
! 363: }
! 364:
! 365: if (entry_id == SMB_ACL_FIRST_ENTRY) {
! 366: acl_d->next = 0;
! 367: }
! 368:
! 369: if (acl_d->next < 0) {
! 370: errno = EINVAL;
! 371: return -1;
! 372: }
! 373:
! 374: if (acl_d->next >= acl_d->count) {
! 375: return 0;
! 376: }
! 377:
! 378: *entry_p = &acl_d->acl[acl_d->next++];
! 379:
! 380: return 1;
! 381: }
! 382:
! 383: int sys_acl_get_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *type_p)
! 384: {
! 385: *type_p = entry_d->a_type;
! 386:
! 387: return 0;
! 388: }
! 389:
! 390: /*
! 391: * There is no way of knowing what size the ACL returned by
! 392: * GETACL will be unless you first call GETACLCNT which means
! 393: * making an additional system call.
! 394: *
! 395: * In the hope of avoiding the cost of the additional system
! 396: * call in most cases, we initially allocate enough space for
! 397: * an ACL with INITIAL_ACL_SIZE entries. If this turns out to
! 398: * be too small then we use GETACLCNT to find out the actual
! 399: * size, reallocate the ACL buffer, and then call GETACL again.
! 400: */
! 401:
! 402: #define INITIAL_ACL_SIZE 16
! 403:
! 404: SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type)
! 405: {
! 406: SMB_ACL_T acl_d;
! 407: int count; /* # of ACL entries allocated */
! 408: int naccess; /* # of access ACL entries */
! 409: int ndefault; /* # of default ACL entries */
! 410:
! 411: if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) {
! 412: errno = EINVAL;
! 413: return NULL;
! 414: }
! 415:
! 416: count = INITIAL_ACL_SIZE;
! 417: if ((acl_d = sys_acl_init(count)) == NULL) {
! 418: return NULL;
! 419: }
! 420:
! 421: /*
! 422: * If there isn't enough space for the ACL entries we use
! 423: * GETACLCNT to determine the actual number of ACL entries
! 424: * reallocate and try again. This is in a loop because it
! 425: * is possible that someone else could modify the ACL and
! 426: * increase the number of entries between the call to
! 427: * GETACLCNT and the call to GETACL.
! 428: */
! 429: while ((count = acl(path_p, GETACL, count, &acl_d->acl[0])) < 0
! 430: && errno == ENOSPC) {
! 431:
! 432: sys_acl_free_acl(acl_d);
! 433:
! 434: if ((count = acl(path_p, GETACLCNT, 0, NULL)) < 0) {
! 435: return NULL;
! 436: }
! 437:
! 438: if ((acl_d = sys_acl_init(count)) == NULL) {
! 439: return NULL;
! 440: }
! 441: }
! 442:
! 443: if (count < 0) {
! 444: sys_acl_free_acl(acl_d);
! 445: return NULL;
! 446: }
! 447:
! 448: /*
! 449: * calculate the number of access and default ACL entries
! 450: *
! 451: * Note: we assume that the acl() system call returned a
! 452: * well formed ACL which is sorted so that all of the
! 453: * access ACL entries preceed any default ACL entries
! 454: */
! 455: for (naccess = 0; naccess < count; naccess++) {
! 456: if (acl_d->acl[naccess].a_type & ACL_DEFAULT)
! 457: break;
! 458: }
! 459: ndefault = count - naccess;
! 460:
! 461: /*
! 462: * if the caller wants the default ACL we have to copy
! 463: * the entries down to the start of the acl[] buffer
! 464: * and mask out the ACL_DEFAULT flag from the type field
! 465: */
! 466: if (type == SMB_ACL_TYPE_DEFAULT) {
! 467: int i, j;
! 468:
! 469: for (i = 0, j = naccess; i < ndefault; i++, j++) {
! 470: acl_d->acl[i] = acl_d->acl[j];
! 471: acl_d->acl[i].a_type &= ~ACL_DEFAULT;
! 472: }
! 473:
! 474: acl_d->count = ndefault;
! 475: } else {
! 476: acl_d->count = naccess;
! 477: }
! 478:
! 479: return acl_d;
! 480: }
! 481:
! 482: #if 0
! 483: SMB_ACL_T sys_acl_get_fd(int fd)
! 484: {
! 485: SMB_ACL_T acl_d;
! 486: int count; /* # of ACL entries allocated */
! 487: int naccess; /* # of access ACL entries */
! 488:
! 489: count = INITIAL_ACL_SIZE;
! 490: if ((acl_d = sys_acl_init(count)) == NULL) {
! 491: return NULL;
! 492: }
! 493:
! 494: while ((count = facl(fd, GETACL, count, &acl_d->acl[0])) < 0
! 495: && errno == ENOSPC) {
! 496:
! 497: sys_acl_free_acl(acl_d);
! 498:
! 499: if ((count = facl(fd, GETACLCNT, 0, NULL)) < 0) {
! 500: return NULL;
! 501: }
! 502:
! 503: if ((acl_d = sys_acl_init(count)) == NULL) {
! 504: return NULL;
! 505: }
! 506: }
! 507:
! 508: if (count < 0) {
! 509: sys_acl_free_acl(acl_d);
! 510: return NULL;
! 511: }
! 512:
! 513: /*
! 514: * calculate the number of access ACL entries
! 515: */
! 516: for (naccess = 0; naccess < count; naccess++) {
! 517: if (acl_d->acl[naccess].a_type & ACL_DEFAULT)
! 518: break;
! 519: }
! 520:
! 521: acl_d->count = naccess;
! 522:
! 523: return acl_d;
! 524: }
! 525: #endif
! 526:
! 527: int sys_acl_get_info(SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T *tag_type_p, uint32 *bits_p, id_t *u_g_id_p)
! 528: {
! 529: *tag_type_p = entry->a_type;
! 530:
! 531: *bits_p = entry->a_perm;
! 532:
! 533: if (*tag_type_p == SMB_ACL_USER || *tag_type_p == SMB_ACL_GROUP)
! 534: *u_g_id_p = entry->a_id;
! 535:
! 536: return 0;
! 537: }
! 538:
! 539: SMB_ACL_T sys_acl_init(int count)
! 540: {
! 541: SMB_ACL_T a;
! 542:
! 543: if (count < 0) {
! 544: errno = EINVAL;
! 545: return NULL;
! 546: }
! 547:
! 548: /*
! 549: * note that since the definition of the structure pointed
! 550: * to by the SMB_ACL_T includes the first element of the
! 551: * acl[] array, this actually allocates an ACL with room
! 552: * for (count+1) entries
! 553: */
! 554: if ((a = (SMB_ACL_T)SMB_MALLOC(sizeof a[0] + count * sizeof (struct acl))) == NULL) {
! 555: errno = ENOMEM;
! 556: return NULL;
! 557: }
! 558:
! 559: a->size = count + 1;
! 560: a->count = 0;
! 561: a->next = -1;
! 562:
! 563: return a;
! 564: }
! 565:
! 566:
! 567: int sys_acl_create_entry(SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p)
! 568: {
! 569: SMB_ACL_T acl_d;
! 570: SMB_ACL_ENTRY_T entry_d;
! 571:
! 572: if (acl_p == NULL || entry_p == NULL || (acl_d = *acl_p) == NULL) {
! 573: errno = EINVAL;
! 574: return -1;
! 575: }
! 576:
! 577: if (acl_d->count >= acl_d->size) {
! 578: errno = ENOSPC;
! 579: return -1;
! 580: }
! 581:
! 582: entry_d = &acl_d->acl[acl_d->count++];
! 583: entry_d->a_type = 0;
! 584: entry_d->a_id = -1;
! 585: entry_d->a_perm = 0;
! 586: *entry_p = entry_d;
! 587:
! 588: return 0;
! 589: }
! 590:
! 591: int sys_acl_set_info(SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tag_type, uint32 bits, id_t u_g_id)
! 592: {
! 593: entry->a_type = tag_type;
! 594:
! 595: if (tag_type == SMB_ACL_USER || tag_type == SMB_ACL_GROUP)
! 596: entry->a_id = u_g_id;
! 597:
! 598: entry->a_perm = bits;
! 599:
! 600: return 0;
! 601: }
! 602:
! 603: int sys_acl_set_access_bits(SMB_ACL_ENTRY_T entry_d, uint32 bits)
! 604: {
! 605: entry_d->a_perm = bits;
! 606: return 0;
! 607: }
! 608:
! 609: /*
! 610: * sort the ACL and check it for validity
! 611: *
! 612: * if it's a minimal ACL with only 4 entries then we
! 613: * need to recalculate the mask permissions to make
! 614: * sure that they are the same as the GROUP_OBJ
! 615: * permissions as required by the UnixWare acl() system call.
! 616: *
! 617: * (note: since POSIX allows minimal ACLs which only contain
! 618: * 3 entries - ie there is no mask entry - we should, in theory,
! 619: * check for this and add a mask entry if necessary - however
! 620: * we "know" that the caller of this interface always specifies
! 621: * a mask so, in practice "this never happens" (tm) - if it *does*
! 622: * happen aclsort() will fail and return an error and someone will
! 623: * have to fix it ...)
! 624: */
! 625:
! 626: static int acl_sort(SMB_ACL_T acl_d)
! 627: {
! 628: int fixmask = (acl_d->count <= 4);
! 629:
! 630: if (aclsort(acl_d->count, fixmask, acl_d->acl) != 0) {
! 631: errno = EINVAL;
! 632: return -1;
! 633: }
! 634: return 0;
! 635: }
! 636:
! 637: int sys_acl_valid(SMB_ACL_T acl_d)
! 638: {
! 639: return acl_sort(acl_d);
! 640: }
! 641:
! 642: int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d)
! 643: {
! 644: struct stat s;
! 645: struct acl *acl_p;
! 646: int acl_count;
! 647: struct acl *acl_buf = NULL;
! 648: int ret;
! 649:
! 650: if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) {
! 651: errno = EINVAL;
! 652: return -1;
! 653: }
! 654:
! 655: if (acl_sort(acl_d) != 0) {
! 656: return -1;
! 657: }
! 658:
! 659: acl_p = &acl_d->acl[0];
! 660: acl_count = acl_d->count;
! 661:
! 662: /*
! 663: * if it's a directory there is extra work to do
! 664: * since the acl() system call will replace both
! 665: * the access ACLs and the default ACLs (if any)
! 666: */
! 667: if (stat(name, &s) != 0) {
! 668: return -1;
! 669: }
! 670: if (S_ISDIR(s.st_mode)) {
! 671: SMB_ACL_T acc_acl;
! 672: SMB_ACL_T def_acl;
! 673: SMB_ACL_T tmp_acl;
! 674: int i;
! 675:
! 676: if (type == SMB_ACL_TYPE_ACCESS) {
! 677: acc_acl = acl_d;
! 678: def_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_DEFAULT);
! 679:
! 680: } else {
! 681: def_acl = acl_d;
! 682: acc_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_ACCESS);
! 683: }
! 684:
! 685: if (tmp_acl == NULL) {
! 686: return -1;
! 687: }
! 688:
! 689: /*
! 690: * allocate a temporary buffer for the complete ACL
! 691: */
! 692: acl_count = acc_acl->count + def_acl->count;
! 693: acl_p = acl_buf = SMB_MALLOC_ARRAY(struct acl, acl_count);
! 694:
! 695: if (acl_buf == NULL) {
! 696: sys_acl_free_acl(tmp_acl);
! 697: errno = ENOMEM;
! 698: return -1;
! 699: }
! 700:
! 701: /*
! 702: * copy the access control and default entries into the buffer
! 703: */
! 704: memcpy(&acl_buf[0], &acc_acl->acl[0],
! 705: acc_acl->count * sizeof(acl_buf[0]));
! 706:
! 707: memcpy(&acl_buf[acc_acl->count], &def_acl->acl[0],
! 708: def_acl->count * sizeof(acl_buf[0]));
! 709:
! 710: /*
! 711: * set the ACL_DEFAULT flag on the default entries
! 712: */
! 713: for (i = acc_acl->count; i < acl_count; i++) {
! 714: acl_buf[i].a_type |= ACL_DEFAULT;
! 715: }
! 716:
! 717: sys_acl_free_acl(tmp_acl);
! 718:
! 719: } else if (type != SMB_ACL_TYPE_ACCESS) {
! 720: errno = EINVAL;
! 721: return -1;
! 722: }
! 723:
! 724: ret = acl(name, SETACL, acl_count, acl_p);
! 725:
! 726: SAFE_FREE(acl_buf);
! 727:
! 728: return ret;
! 729: }
! 730:
! 731: #if 0
! 732: int sys_acl_set_fd(int fd, SMB_ACL_T acl_d)
! 733: {
! 734: if (acl_sort(acl_d) != 0) {
! 735: return -1;
! 736: }
! 737:
! 738: return facl(fd, SETACL, acl_d->count, &acl_d->acl[0]);
! 739: }
! 740: #endif
! 741:
! 742: int sys_acl_delete_def_file(const char *path)
! 743: {
! 744: SMB_ACL_T acl_d;
! 745: int ret;
! 746:
! 747: /*
! 748: * fetching the access ACL and rewriting it has
! 749: * the effect of deleting the default ACL
! 750: */
! 751: if ((acl_d = sys_acl_get_file(path, SMB_ACL_TYPE_ACCESS)) == NULL) {
! 752: return -1;
! 753: }
! 754:
! 755: ret = acl(path, SETACL, acl_d->count, acl_d->acl);
! 756:
! 757: sys_acl_free_acl(acl_d);
! 758:
! 759: return ret;
! 760: }
! 761:
! 762: int sys_acl_free_acl(SMB_ACL_T acl_d)
! 763: {
! 764: SAFE_FREE(acl_d);
! 765: return 0;
! 766: }
! 767:
! 768: #elif defined(HAVE_HPUX_ACLS) /*---------------------------------------------*/
! 769:
! 770: #include <dl.h>
! 771:
! 772: /*
! 773: * Based on the Solaris/SCO code - with modifications.
! 774: */
! 775:
! 776: /*
! 777: * Note that while this code implements sufficient functionality
! 778: * to support the sys_acl_* interfaces it does not provide all
! 779: * of the semantics of the POSIX ACL interfaces.
! 780: *
! 781: * In particular, an ACL entry descriptor (SMB_ACL_ENTRY_T) returned
! 782: * from a call to sys_acl_get_entry() should not be assumed to be
! 783: * valid after calling any of the following functions, which may
! 784: * reorder the entries in the ACL.
! 785: *
! 786: * sys_acl_valid()
! 787: * sys_acl_set_file()
! 788: * sys_acl_set_fd()
! 789: */
! 790:
! 791: /* This checks if the POSIX ACL system call is defined */
! 792: /* which basically corresponds to whether JFS 3.3 or */
! 793: /* higher is installed. If acl() was called when it */
! 794: /* isn't defined, it causes the process to core dump */
! 795: /* so it is important to check this and avoid acl() */
! 796: /* calls if it isn't there. */
! 797:
! 798: static BOOL hpux_acl_call_presence(void)
! 799: {
! 800:
! 801: shl_t handle = NULL;
! 802: void *value;
! 803: int ret_val=0;
! 804: static BOOL already_checked=0;
! 805:
! 806: if(already_checked)
! 807: return True;
! 808:
! 809:
! 810: ret_val = shl_findsym(&handle, "acl", TYPE_PROCEDURE, &value);
! 811:
! 812: if(ret_val != 0) {
! 813: DEBUG(5, ("hpux_acl_call_presence: shl_findsym() returned %d, errno = %d, error %s\n",
! 814: ret_val, errno, strerror(errno)));
! 815: DEBUG(5,("hpux_acl_call_presence: acl() system call is not present. Check if you have JFS 3.3 and above?\n"));
! 816: return False;
! 817: }
! 818:
! 819: DEBUG(10,("hpux_acl_call_presence: acl() system call is present. We have JFS 3.3 or above \n"));
! 820:
! 821: already_checked = True;
! 822: return True;
! 823: }
! 824:
! 825: int sys_acl_get_entry(SMB_ACL_T acl_d, int entry_id, SMB_ACL_ENTRY_T *entry_p)
! 826: {
! 827: if (entry_id != SMB_ACL_FIRST_ENTRY && entry_id != SMB_ACL_NEXT_ENTRY) {
! 828: errno = EINVAL;
! 829: return -1;
! 830: }
! 831:
! 832: if (entry_p == NULL) {
! 833: errno = EINVAL;
! 834: return -1;
! 835: }
! 836:
! 837: if (entry_id == SMB_ACL_FIRST_ENTRY) {
! 838: acl_d->next = 0;
! 839: }
! 840:
! 841: if (acl_d->next < 0) {
! 842: errno = EINVAL;
! 843: return -1;
! 844: }
! 845:
! 846: if (acl_d->next >= acl_d->count) {
! 847: return 0;
! 848: }
! 849:
! 850: *entry_p = &acl_d->acl[acl_d->next++];
! 851:
! 852: return 1;
! 853: }
! 854:
! 855: int sys_acl_get_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *type_p)
! 856: {
! 857: *type_p = entry_d->a_type;
! 858:
! 859: return 0;
! 860: }
! 861:
! 862: /*
! 863: * There is no way of knowing what size the ACL returned by
! 864: * ACL_GET will be unless you first call ACL_CNT which means
! 865: * making an additional system call.
! 866: *
! 867: * In the hope of avoiding the cost of the additional system
! 868: * call in most cases, we initially allocate enough space for
! 869: * an ACL with INITIAL_ACL_SIZE entries. If this turns out to
! 870: * be too small then we use ACL_CNT to find out the actual
! 871: * size, reallocate the ACL buffer, and then call ACL_GET again.
! 872: */
! 873:
! 874: #define INITIAL_ACL_SIZE 16
! 875:
! 876: SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type)
! 877: {
! 878: SMB_ACL_T acl_d;
! 879: int count; /* # of ACL entries allocated */
! 880: int naccess; /* # of access ACL entries */
! 881: int ndefault; /* # of default ACL entries */
! 882:
! 883: if(hpux_acl_call_presence() == False) {
! 884: /* Looks like we don't have the acl() system call on HPUX.
! 885: * May be the system doesn't have the latest version of JFS.
! 886: */
! 887: return NULL;
! 888: }
! 889:
! 890: if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) {
! 891: errno = EINVAL;
! 892: return NULL;
! 893: }
! 894:
! 895: count = INITIAL_ACL_SIZE;
! 896: if ((acl_d = sys_acl_init(count)) == NULL) {
! 897: return NULL;
! 898: }
! 899:
! 900: /*
! 901: * If there isn't enough space for the ACL entries we use
! 902: * ACL_CNT to determine the actual number of ACL entries
! 903: * reallocate and try again. This is in a loop because it
! 904: * is possible that someone else could modify the ACL and
! 905: * increase the number of entries between the call to
! 906: * ACL_CNT and the call to ACL_GET.
! 907: */
! 908: while ((count = acl(path_p, ACL_GET, count, &acl_d->acl[0])) < 0 && errno == ENOSPC) {
! 909:
! 910: sys_acl_free_acl(acl_d);
! 911:
! 912: if ((count = acl(path_p, ACL_CNT, 0, NULL)) < 0) {
! 913: return NULL;
! 914: }
! 915:
! 916: if ((acl_d = sys_acl_init(count)) == NULL) {
! 917: return NULL;
! 918: }
! 919: }
! 920:
! 921: if (count < 0) {
! 922: sys_acl_free_acl(acl_d);
! 923: return NULL;
! 924: }
! 925:
! 926: /*
! 927: * calculate the number of access and default ACL entries
! 928: *
! 929: * Note: we assume that the acl() system call returned a
! 930: * well formed ACL which is sorted so that all of the
! 931: * access ACL entries preceed any default ACL entries
! 932: */
! 933: for (naccess = 0; naccess < count; naccess++) {
! 934: if (acl_d->acl[naccess].a_type & ACL_DEFAULT)
! 935: break;
! 936: }
! 937: ndefault = count - naccess;
! 938:
! 939: /*
! 940: * if the caller wants the default ACL we have to copy
! 941: * the entries down to the start of the acl[] buffer
! 942: * and mask out the ACL_DEFAULT flag from the type field
! 943: */
! 944: if (type == SMB_ACL_TYPE_DEFAULT) {
! 945: int i, j;
! 946:
! 947: for (i = 0, j = naccess; i < ndefault; i++, j++) {
! 948: acl_d->acl[i] = acl_d->acl[j];
! 949: acl_d->acl[i].a_type &= ~ACL_DEFAULT;
! 950: }
! 951:
! 952: acl_d->count = ndefault;
! 953: } else {
! 954: acl_d->count = naccess;
! 955: }
! 956:
! 957: return acl_d;
! 958: }
! 959:
! 960: #if 0
! 961: SMB_ACL_T sys_acl_get_fd(int fd)
! 962: {
! 963: /*
! 964: * HPUX doesn't have the facl call. Fake it using the path.... JRA.
! 965: */
! 966:
! 967: files_struct *fsp = file_find_fd(fd);
! 968:
! 969: if (fsp == NULL) {
! 970: errno = EBADF;
! 971: return NULL;
! 972: }
! 973:
! 974: /*
! 975: * We know we're in the same conn context. So we
! 976: * can use the relative path.
! 977: */
! 978:
! 979: return sys_acl_get_file(fsp->fsp_name, SMB_ACL_TYPE_ACCESS);
! 980: }
! 981: #endif
! 982:
! 983: int sys_acl_get_info(SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T *tag_type_p, uint32 *bits_p, id_t *u_g_id_p)
! 984: {
! 985: *tag_type_p = entry->a_type;
! 986:
! 987: *bits_p = entry->a_perm;
! 988:
! 989: if (*tag_type_p == SMB_ACL_USER || *tag_type_p == SMB_ACL_GROUP)
! 990: *u_g_id_p = entry->a_id;
! 991:
! 992: return 0;
! 993: }
! 994:
! 995: SMB_ACL_T sys_acl_init(int count)
! 996: {
! 997: SMB_ACL_T a;
! 998:
! 999: if (count < 0) {
! 1000: errno = EINVAL;
! 1001: return NULL;
! 1002: }
! 1003:
! 1004: /*
! 1005: * note that since the definition of the structure pointed
! 1006: * to by the SMB_ACL_T includes the first element of the
! 1007: * acl[] array, this actually allocates an ACL with room
! 1008: * for (count+1) entries
! 1009: */
! 1010: if ((a = (SMB_ACL_T)SMB_MALLOC(sizeof a[0] + count * sizeof(struct acl))) == NULL) {
! 1011: errno = ENOMEM;
! 1012: return NULL;
! 1013: }
! 1014:
! 1015: a->size = count + 1;
! 1016: a->count = 0;
! 1017: a->next = -1;
! 1018:
! 1019: return a;
! 1020: }
! 1021:
! 1022:
! 1023: int sys_acl_create_entry(SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p)
! 1024: {
! 1025: SMB_ACL_T acl_d;
! 1026: SMB_ACL_ENTRY_T entry_d;
! 1027:
! 1028: if (acl_p == NULL || entry_p == NULL || (acl_d = *acl_p) == NULL) {
! 1029: errno = EINVAL;
! 1030: return -1;
! 1031: }
! 1032:
! 1033: if (acl_d->count >= acl_d->size) {
! 1034: errno = ENOSPC;
! 1035: return -1;
! 1036: }
! 1037:
! 1038: entry_d = &acl_d->acl[acl_d->count++];
! 1039: entry_d->a_type = 0;
! 1040: entry_d->a_id = -1;
! 1041: entry_d->a_perm = 0;
! 1042: *entry_p = entry_d;
! 1043:
! 1044: return 0;
! 1045: }
! 1046:
! 1047: int sys_acl_set_info(SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tag_type, uint32 bits, id_t u_g_id)
! 1048: {
! 1049: entry->a_type = tag_type;
! 1050:
! 1051: if (tag_type == SMB_ACL_USER || tag_type == SMB_ACL_GROUP)
! 1052: entry->a_id = u_g_id;
! 1053:
! 1054: entry->a_perm = bits;
! 1055:
! 1056: return 0;
! 1057: }
! 1058:
! 1059: int sys_acl_set_access_bits(SMB_ACL_ENTRY_T entry_d, uint32 bits)
! 1060: {
! 1061: entry_d->a_perm = bits;
! 1062:
! 1063: return 0;
! 1064: }
! 1065:
! 1066: /* Structure to capture the count for each type of ACE. */
! 1067:
! 1068: struct hpux_acl_types {
! 1069: int n_user;
! 1070: int n_def_user;
! 1071: int n_user_obj;
! 1072: int n_def_user_obj;
! 1073:
! 1074: int n_group;
! 1075: int n_def_group;
! 1076: int n_group_obj;
! 1077: int n_def_group_obj;
! 1078:
! 1079: int n_other;
! 1080: int n_other_obj;
! 1081: int n_def_other_obj;
! 1082:
! 1083: int n_class_obj;
! 1084: int n_def_class_obj;
! 1085:
! 1086: int n_illegal_obj;
! 1087: };
! 1088:
! 1089: /* count_obj:
! 1090: * Counts the different number of objects in a given array of ACL
! 1091: * structures.
! 1092: * Inputs:
! 1093: *
! 1094: * acl_count - Count of ACLs in the array of ACL strucutres.
! 1095: * aclp - Array of ACL structures.
! 1096: * acl_type_count - Pointer to acl_types structure. Should already be
! 1097: * allocated.
! 1098: * Output:
! 1099: *
! 1100: * acl_type_count - This structure is filled up with counts of various
! 1101: * acl types.
! 1102: */
! 1103:
! 1104: static void hpux_count_obj(int acl_count, struct acl *aclp, struct hpux_acl_types *acl_type_count)
! 1105: {
! 1106: int i;
! 1107:
! 1108: memset(acl_type_count, 0, sizeof(struct hpux_acl_types));
! 1109:
! 1110: for(i=0;i<acl_count;i++) {
! 1111: switch(aclp[i].a_type) {
! 1112: case USER:
! 1113: acl_type_count->n_user++;
! 1114: break;
! 1115: case USER_OBJ:
! 1116: acl_type_count->n_user_obj++;
! 1117: break;
! 1118: case DEF_USER_OBJ:
! 1119: acl_type_count->n_def_user_obj++;
! 1120: break;
! 1121: case GROUP:
! 1122: acl_type_count->n_group++;
! 1123: break;
! 1124: case GROUP_OBJ:
! 1125: acl_type_count->n_group_obj++;
! 1126: break;
! 1127: case DEF_GROUP_OBJ:
! 1128: acl_type_count->n_def_group_obj++;
! 1129: break;
! 1130: case OTHER_OBJ:
! 1131: acl_type_count->n_other_obj++;
! 1132: break;
! 1133: case DEF_OTHER_OBJ:
! 1134: acl_type_count->n_def_other_obj++;
! 1135: break;
! 1136: case CLASS_OBJ:
! 1137: acl_type_count->n_class_obj++;
! 1138: break;
! 1139: case DEF_CLASS_OBJ:
! 1140: acl_type_count->n_def_class_obj++;
! 1141: break;
! 1142: case DEF_USER:
! 1143: acl_type_count->n_def_user++;
! 1144: break;
! 1145: case DEF_GROUP:
! 1146: acl_type_count->n_def_group++;
! 1147: break;
! 1148: default:
! 1149: acl_type_count->n_illegal_obj++;
! 1150: break;
! 1151: }
! 1152: }
! 1153: }
! 1154:
! 1155: /* swap_acl_entries: Swaps two ACL entries.
! 1156: *
! 1157: * Inputs: aclp0, aclp1 - ACL entries to be swapped.
! 1158: */
! 1159:
! 1160: static void hpux_swap_acl_entries(struct acl *aclp0, struct acl *aclp1)
! 1161: {
! 1162: struct acl temp_acl;
! 1163:
! 1164: temp_acl.a_type = aclp0->a_type;
! 1165: temp_acl.a_id = aclp0->a_id;
! 1166: temp_acl.a_perm = aclp0->a_perm;
! 1167:
! 1168: aclp0->a_type = aclp1->a_type;
! 1169: aclp0->a_id = aclp1->a_id;
! 1170: aclp0->a_perm = aclp1->a_perm;
! 1171:
! 1172: aclp1->a_type = temp_acl.a_type;
! 1173: aclp1->a_id = temp_acl.a_id;
! 1174: aclp1->a_perm = temp_acl.a_perm;
! 1175: }
! 1176:
! 1177: /* prohibited_duplicate_type
! 1178: * Identifies if given ACL type can have duplicate entries or
! 1179: * not.
! 1180: *
! 1181: * Inputs: acl_type - ACL Type.
! 1182: *
! 1183: * Outputs:
! 1184: *
! 1185: * Return..
! 1186: *
! 1187: * True - If the ACL type matches any of the prohibited types.
! 1188: * False - If the ACL type doesn't match any of the prohibited types.
! 1189: */
! 1190:
! 1191: static BOOL hpux_prohibited_duplicate_type(int acl_type)
! 1192: {
! 1193: switch(acl_type) {
! 1194: case USER:
! 1195: case GROUP:
! 1196: case DEF_USER:
! 1197: case DEF_GROUP:
! 1198: return True;
! 1199: default:
! 1200: return False;
! 1201: }
! 1202: }
! 1203:
! 1204: /* get_needed_class_perm
! 1205: * Returns the permissions of a ACL structure only if the ACL
! 1206: * type matches one of the pre-determined types for computing
! 1207: * CLASS_OBJ permissions.
! 1208: *
! 1209: * Inputs: aclp - Pointer to ACL structure.
! 1210: */
! 1211:
! 1212: static int hpux_get_needed_class_perm(struct acl *aclp)
! 1213: {
! 1214: switch(aclp->a_type) {
! 1215: case USER:
! 1216: case GROUP_OBJ:
! 1217: case GROUP:
! 1218: case DEF_USER_OBJ:
! 1219: case DEF_USER:
! 1220: case DEF_GROUP_OBJ:
! 1221: case DEF_GROUP:
! 1222: case DEF_CLASS_OBJ:
! 1223: case DEF_OTHER_OBJ:
! 1224: return aclp->a_perm;
! 1225: default:
! 1226: return 0;
! 1227: }
! 1228: }
! 1229:
! 1230: /* acl_sort for HPUX.
! 1231: * Sorts the array of ACL structures as per the description in
! 1232: * aclsort man page. Refer to aclsort man page for more details
! 1233: *
! 1234: * Inputs:
! 1235: *
! 1236: * acl_count - Count of ACLs in the array of ACL structures.
! 1237: * calclass - If this is not zero, then we compute the CLASS_OBJ
! 1238: * permissions.
! 1239: * aclp - Array of ACL structures.
! 1240: *
! 1241: * Outputs:
! 1242: *
! 1243: * aclp - Sorted array of ACL structures.
! 1244: *
! 1245: * Outputs:
! 1246: *
! 1247: * Returns 0 for success -1 for failure. Prints a message to the Samba
! 1248: * debug log in case of failure.
! 1249: */
! 1250:
! 1251: static int hpux_acl_sort(int acl_count, int calclass, struct acl *aclp)
! 1252: {
! 1253: #if !defined(HAVE_HPUX_ACLSORT)
! 1254: /*
! 1255: * The aclsort() system call is availabe on the latest HPUX General
! 1256: * Patch Bundles. So for HPUX, we developed our version of acl_sort
! 1257: * function. Because, we don't want to update to a new
! 1258: * HPUX GR bundle just for aclsort() call.
! 1259: */
! 1260:
! 1261: struct hpux_acl_types acl_obj_count;
! 1262: int n_class_obj_perm = 0;
! 1263: int i, j;
! 1264:
! 1265: if(!acl_count) {
! 1266: DEBUG(10,("Zero acl count passed. Returning Success\n"));
! 1267: return 0;
! 1268: }
! 1269:
! 1270: if(aclp == NULL) {
! 1271: DEBUG(0,("Null ACL pointer in hpux_acl_sort. Returning Failure. \n"));
! 1272: return -1;
! 1273: }
! 1274:
! 1275: /* Count different types of ACLs in the ACLs array */
! 1276:
! 1277: hpux_count_obj(acl_count, aclp, &acl_obj_count);
! 1278:
! 1279: /* There should be only one entry each of type USER_OBJ, GROUP_OBJ,
! 1280: * CLASS_OBJ and OTHER_OBJ
! 1281: */
! 1282:
! 1283: if( (acl_obj_count.n_user_obj != 1) ||
! 1284: (acl_obj_count.n_group_obj != 1) ||
! 1285: (acl_obj_count.n_class_obj != 1) ||
! 1286: (acl_obj_count.n_other_obj != 1)
! 1287: ) {
! 1288: DEBUG(0,("hpux_acl_sort: More than one entry or no entries for \
! 1289: USER OBJ or GROUP_OBJ or OTHER_OBJ or CLASS_OBJ\n"));
! 1290: return -1;
! 1291: }
! 1292:
! 1293: /* If any of the default objects are present, there should be only
! 1294: * one of them each.
! 1295: */
! 1296:
! 1297: if( (acl_obj_count.n_def_user_obj > 1) || (acl_obj_count.n_def_group_obj > 1) ||
! 1298: (acl_obj_count.n_def_other_obj > 1) || (acl_obj_count.n_def_class_obj > 1) ) {
! 1299: DEBUG(0,("hpux_acl_sort: More than one entry for DEF_CLASS_OBJ \
! 1300: or DEF_USER_OBJ or DEF_GROUP_OBJ or DEF_OTHER_OBJ\n"));
! 1301: return -1;
! 1302: }
! 1303:
! 1304: /* We now have proper number of OBJ and DEF_OBJ entries. Now sort the acl
! 1305: * structures.
! 1306: *
! 1307: * Sorting crieteria - First sort by ACL type. If there are multiple entries of
! 1308: * same ACL type, sort by ACL id.
! 1309: *
! 1310: * I am using the trival kind of sorting method here because, performance isn't
! 1311: * really effected by the ACLs feature. More over there aren't going to be more
! 1312: * than 17 entries on HPUX.
! 1313: */
! 1314:
! 1315: for(i=0; i<acl_count;i++) {
! 1316: for (j=i+1; j<acl_count; j++) {
! 1317: if( aclp[i].a_type > aclp[j].a_type ) {
! 1318: /* ACL entries out of order, swap them */
! 1319:
! 1320: hpux_swap_acl_entries((aclp+i), (aclp+j));
! 1321:
! 1322: } else if ( aclp[i].a_type == aclp[j].a_type ) {
! 1323:
! 1324: /* ACL entries of same type, sort by id */
! 1325:
! 1326: if(aclp[i].a_id > aclp[j].a_id) {
! 1327: hpux_swap_acl_entries((aclp+i), (aclp+j));
! 1328: } else if (aclp[i].a_id == aclp[j].a_id) {
! 1329: /* We have a duplicate entry. */
! 1330: if(hpux_prohibited_duplicate_type(aclp[i].a_type)) {
! 1331: DEBUG(0, ("hpux_acl_sort: Duplicate entry: Type(hex): %x Id: %d\n",
! 1332: aclp[i].a_type, aclp[i].a_id));
! 1333: return -1;
! 1334: }
! 1335: }
! 1336:
! 1337: }
! 1338: }
! 1339: }
! 1340:
! 1341: /* set the class obj permissions to the computed one. */
! 1342: if(calclass) {
! 1343: int n_class_obj_index = -1;
! 1344:
! 1345: for(i=0;i<acl_count;i++) {
! 1346: n_class_obj_perm |= hpux_get_needed_class_perm((aclp+i));
! 1347:
! 1348: if(aclp[i].a_type == CLASS_OBJ)
! 1349: n_class_obj_index = i;
! 1350: }
! 1351: aclp[n_class_obj_index].a_perm = n_class_obj_perm;
! 1352: }
! 1353:
! 1354: return 0;
! 1355: #else
! 1356: return aclsort(acl_count, calclass, aclp);
! 1357: #endif
! 1358: }
! 1359:
! 1360: /*
! 1361: * sort the ACL and check it for validity
! 1362: *
! 1363: * if it's a minimal ACL with only 4 entries then we
! 1364: * need to recalculate the mask permissions to make
! 1365: * sure that they are the same as the GROUP_OBJ
! 1366: * permissions as required by the UnixWare acl() system call.
! 1367: *
! 1368: * (note: since POSIX allows minimal ACLs which only contain
! 1369: * 3 entries - ie there is no mask entry - we should, in theory,
! 1370: * check for this and add a mask entry if necessary - however
! 1371: * we "know" that the caller of this interface always specifies
! 1372: * a mask so, in practice "this never happens" (tm) - if it *does*
! 1373: * happen aclsort() will fail and return an error and someone will
! 1374: * have to fix it ...)
! 1375: */
! 1376:
! 1377: static int acl_sort(SMB_ACL_T acl_d)
! 1378: {
! 1379: int fixmask = (acl_d->count <= 4);
! 1380:
! 1381: if (hpux_acl_sort(acl_d->count, fixmask, acl_d->acl) != 0) {
! 1382: errno = EINVAL;
! 1383: return -1;
! 1384: }
! 1385: return 0;
! 1386: }
! 1387:
! 1388: int sys_acl_valid(SMB_ACL_T acl_d)
! 1389: {
! 1390: return acl_sort(acl_d);
! 1391: }
! 1392:
! 1393: int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d)
! 1394: {
! 1395: struct stat s;
! 1396: struct acl *acl_p;
! 1397: int acl_count;
! 1398: struct acl *acl_buf = NULL;
! 1399: int ret;
! 1400:
! 1401: if(hpux_acl_call_presence() == False) {
! 1402: /* Looks like we don't have the acl() system call on HPUX.
! 1403: * May be the system doesn't have the latest version of JFS.
! 1404: */
! 1405: errno=ENOSYS;
! 1406: return -1;
! 1407: }
! 1408:
! 1409: if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) {
! 1410: errno = EINVAL;
! 1411: return -1;
! 1412: }
! 1413:
! 1414: if (acl_sort(acl_d) != 0) {
! 1415: return -1;
! 1416: }
! 1417:
! 1418: acl_p = &acl_d->acl[0];
! 1419: acl_count = acl_d->count;
! 1420:
! 1421: /*
! 1422: * if it's a directory there is extra work to do
! 1423: * since the acl() system call will replace both
! 1424: * the access ACLs and the default ACLs (if any)
! 1425: */
! 1426: if (stat(name, &s) != 0) {
! 1427: return -1;
! 1428: }
! 1429: if (S_ISDIR(s.st_mode)) {
! 1430: SMB_ACL_T acc_acl;
! 1431: SMB_ACL_T def_acl;
! 1432: SMB_ACL_T tmp_acl;
! 1433: int i;
! 1434:
! 1435: if (type == SMB_ACL_TYPE_ACCESS) {
! 1436: acc_acl = acl_d;
! 1437: def_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_DEFAULT);
! 1438:
! 1439: } else {
! 1440: def_acl = acl_d;
! 1441: acc_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_ACCESS);
! 1442: }
! 1443:
! 1444: if (tmp_acl == NULL) {
! 1445: return -1;
! 1446: }
! 1447:
! 1448: /*
! 1449: * allocate a temporary buffer for the complete ACL
! 1450: */
! 1451: acl_count = acc_acl->count + def_acl->count;
! 1452: acl_p = acl_buf = SMB_MALLOC_ARRAY(struct acl, acl_count);
! 1453:
! 1454: if (acl_buf == NULL) {
! 1455: sys_acl_free_acl(tmp_acl);
! 1456: errno = ENOMEM;
! 1457: return -1;
! 1458: }
! 1459:
! 1460: /*
! 1461: * copy the access control and default entries into the buffer
! 1462: */
! 1463: memcpy(&acl_buf[0], &acc_acl->acl[0],
! 1464: acc_acl->count * sizeof(acl_buf[0]));
! 1465:
! 1466: memcpy(&acl_buf[acc_acl->count], &def_acl->acl[0],
! 1467: def_acl->count * sizeof(acl_buf[0]));
! 1468:
! 1469: /*
! 1470: * set the ACL_DEFAULT flag on the default entries
! 1471: */
! 1472: for (i = acc_acl->count; i < acl_count; i++) {
! 1473: acl_buf[i].a_type |= ACL_DEFAULT;
! 1474: }
! 1475:
! 1476: sys_acl_free_acl(tmp_acl);
! 1477:
! 1478: } else if (type != SMB_ACL_TYPE_ACCESS) {
! 1479: errno = EINVAL;
! 1480: return -1;
! 1481: }
! 1482:
! 1483: ret = acl(name, ACL_SET, acl_count, acl_p);
! 1484:
! 1485: if (acl_buf) {
! 1486: free(acl_buf);
! 1487: }
! 1488:
! 1489: return ret;
! 1490: }
! 1491:
! 1492: #if 0
! 1493: int sys_acl_set_fd(int fd, SMB_ACL_T acl_d)
! 1494: {
! 1495: /*
! 1496: * HPUX doesn't have the facl call. Fake it using the path.... JRA.
! 1497: */
! 1498:
! 1499: files_struct *fsp = file_find_fd(fd);
! 1500:
! 1501: if (fsp == NULL) {
! 1502: errno = EBADF;
! 1503: return NULL;
! 1504: }
! 1505:
! 1506: if (acl_sort(acl_d) != 0) {
! 1507: return -1;
! 1508: }
! 1509:
! 1510: /*
! 1511: * We know we're in the same conn context. So we
! 1512: * can use the relative path.
! 1513: */
! 1514:
! 1515: return sys_acl_set_file(fsp->fsp_name, SMB_ACL_TYPE_ACCESS, acl_d);
! 1516: }
! 1517: #endif
! 1518:
! 1519: int sys_acl_delete_def_file(const char *path)
! 1520: {
! 1521: SMB_ACL_T acl_d;
! 1522: int ret;
! 1523:
! 1524: /*
! 1525: * fetching the access ACL and rewriting it has
! 1526: * the effect of deleting the default ACL
! 1527: */
! 1528: if ((acl_d = sys_acl_get_file(path, SMB_ACL_TYPE_ACCESS)) == NULL) {
! 1529: return -1;
! 1530: }
! 1531:
! 1532: ret = acl(path, ACL_SET, acl_d->count, acl_d->acl);
! 1533:
! 1534: sys_acl_free_acl(acl_d);
! 1535:
! 1536: return ret;
! 1537: }
! 1538:
! 1539: int sys_acl_free_acl(SMB_ACL_T acl_d)
! 1540: {
! 1541: free(acl_d);
! 1542: return 0;
! 1543: }
! 1544:
! 1545: #elif defined(HAVE_IRIX_ACLS) /*---------------------------------------------*/
! 1546:
! 1547: int sys_acl_get_entry(SMB_ACL_T acl_d, int entry_id, SMB_ACL_ENTRY_T *entry_p)
! 1548: {
! 1549: if (entry_id != SMB_ACL_FIRST_ENTRY && entry_id != SMB_ACL_NEXT_ENTRY) {
! 1550: errno = EINVAL;
! 1551: return -1;
! 1552: }
! 1553:
! 1554: if (entry_p == NULL) {
! 1555: errno = EINVAL;
! 1556: return -1;
! 1557: }
! 1558:
! 1559: if (entry_id == SMB_ACL_FIRST_ENTRY) {
! 1560: acl_d->next = 0;
! 1561: }
! 1562:
! 1563: if (acl_d->next < 0) {
! 1564: errno = EINVAL;
! 1565: return -1;
! 1566: }
! 1567:
! 1568: if (acl_d->next >= acl_d->aclp->acl_cnt) {
! 1569: return 0;
! 1570: }
! 1571:
! 1572: *entry_p = &acl_d->aclp->acl_entry[acl_d->next++];
! 1573:
! 1574: return 1;
! 1575: }
! 1576:
! 1577: int sys_acl_get_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *type_p)
! 1578: {
! 1579: *type_p = entry_d->ae_tag;
! 1580:
! 1581: return 0;
! 1582: }
! 1583:
! 1584: SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type)
! 1585: {
! 1586: SMB_ACL_T a;
! 1587:
! 1588: if ((a = SMB_MALLOC_P(struct SMB_ACL_T)) == NULL) {
! 1589: errno = ENOMEM;
! 1590: return NULL;
! 1591: }
! 1592: if ((a->aclp = acl_get_file(path_p, type)) == NULL) {
! 1593: SAFE_FREE(a);
! 1594: return NULL;
! 1595: }
! 1596: a->next = -1;
! 1597: a->freeaclp = True;
! 1598: return a;
! 1599: }
! 1600:
! 1601: #if 0
! 1602: SMB_ACL_T sys_acl_get_fd(int fd)
! 1603: {
! 1604: SMB_ACL_T a;
! 1605:
! 1606: if ((a = SMB_MALLOC_P(struct SMB_ACL_T)) == NULL) {
! 1607: errno = ENOMEM;
! 1608: return NULL;
! 1609: }
! 1610: if ((a->aclp = acl_get_fd(fd)) == NULL) {
! 1611: SAFE_FREE(a);
! 1612: return NULL;
! 1613: }
! 1614: a->next = -1;
! 1615: a->freeaclp = True;
! 1616: return a;
! 1617: }
! 1618: #endif
! 1619:
! 1620: int sys_acl_get_info(SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T *tag_type_p, uint32 *bits_p, id_t *u_g_id_p)
! 1621: {
! 1622: *tag_type_p = entry->ae_tag;
! 1623:
! 1624: *bits_p = entry->ae_perm;
! 1625:
! 1626: if (*tag_type_p == SMB_ACL_USER || *tag_type_p == SMB_ACL_GROUP)
! 1627: *u_g_id_p = entry->ae_id;
! 1628:
! 1629: return 0;
! 1630: }
! 1631:
! 1632: SMB_ACL_T sys_acl_init(int count)
! 1633: {
! 1634: SMB_ACL_T a;
! 1635:
! 1636: if (count < 0) {
! 1637: errno = EINVAL;
! 1638: return NULL;
! 1639: }
! 1640:
! 1641: if ((a = (SMB_ACL_T)SMB_MALLOC(sizeof a[0] + sizeof (struct acl))) == NULL) {
! 1642: errno = ENOMEM;
! 1643: return NULL;
! 1644: }
! 1645:
! 1646: a->next = -1;
! 1647: a->freeaclp = False;
! 1648: a->aclp = (struct acl *)((char *)a + sizeof a[0]);
! 1649: a->aclp->acl_cnt = 0;
! 1650:
! 1651: return a;
! 1652: }
! 1653:
! 1654:
! 1655: int sys_acl_create_entry(SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p)
! 1656: {
! 1657: SMB_ACL_T acl_d;
! 1658: SMB_ACL_ENTRY_T entry_d;
! 1659:
! 1660: if (acl_p == NULL || entry_p == NULL || (acl_d = *acl_p) == NULL) {
! 1661: errno = EINVAL;
! 1662: return -1;
! 1663: }
! 1664:
! 1665: if (acl_d->aclp->acl_cnt >= ACL_MAX_ENTRIES) {
! 1666: errno = ENOSPC;
! 1667: return -1;
! 1668: }
! 1669:
! 1670: entry_d = &acl_d->aclp->acl_entry[acl_d->aclp->acl_cnt++];
! 1671: entry_d->ae_tag = 0;
! 1672: entry_d->ae_id = 0;
! 1673: entry_d->ae_perm = 0;
! 1674: *entry_p = entry_d;
! 1675:
! 1676: return 0;
! 1677: }
! 1678:
! 1679: int sys_acl_set_info(SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tag_type, uint32 bits, id_t u_g_id)
! 1680: {
! 1681: entry->ae_tag = tag_type;
! 1682:
! 1683: if (tag_type == SMB_ACL_USER || tag_type == SMB_ACL_GROUP)
! 1684: entry->ae_id = u_g_id;
! 1685:
! 1686: entry->ae_perm = bits;
! 1687:
! 1688: return 0;
! 1689: }
! 1690:
! 1691: int sys_acl_set_access_bits(SMB_ACL_ENTRY_T entry_d, uint32 bits)
! 1692: {
! 1693: entry_d->ae_perm = bits;
! 1694:
! 1695: return 0;
! 1696: }
! 1697:
! 1698: int sys_acl_valid(SMB_ACL_T acl_d)
! 1699: {
! 1700: return acl_valid(acl_d->aclp);
! 1701: }
! 1702:
! 1703: int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d)
! 1704: {
! 1705: return acl_set_file(name, type, acl_d->aclp);
! 1706: }
! 1707:
! 1708: #if 0
! 1709: int sys_acl_set_fd(int fd, SMB_ACL_T acl_d)
! 1710: {
! 1711: return acl_set_fd(fd, acl_d->aclp);
! 1712: }
! 1713: #endif
! 1714:
! 1715: int sys_acl_delete_def_file(const char *name)
! 1716: {
! 1717: return acl_delete_def_file(name);
! 1718: }
! 1719:
! 1720: int sys_acl_free_acl(SMB_ACL_T acl_d)
! 1721: {
! 1722: if (acl_d->freeaclp) {
! 1723: acl_free(acl_d->aclp);
! 1724: }
! 1725: acl_free(acl_d);
! 1726: return 0;
! 1727: }
! 1728:
! 1729: #elif defined(HAVE_AIX_ACLS) /*----------------------------------------------*/
! 1730:
! 1731: /* Donated by Medha Date, mdate@austin.ibm.com, for IBM */
! 1732:
! 1733: int sys_acl_get_entry( SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
! 1734: {
! 1735: struct acl_entry_link *link;
! 1736: struct new_acl_entry *entry;
! 1737: int keep_going;
! 1738:
! 1739: if (entry_id == SMB_ACL_FIRST_ENTRY)
! 1740: theacl->count = 0;
! 1741: else if (entry_id != SMB_ACL_NEXT_ENTRY) {
! 1742: errno = EINVAL;
! 1743: return -1;
! 1744: }
! 1745:
! 1746: DEBUG(10,("This is the count: %d\n",theacl->count));
! 1747:
! 1748: /* Check if count was previously set to -1. *
! 1749: * If it was, that means we reached the end *
! 1750: * of the acl last time. */
! 1751: if(theacl->count == -1)
! 1752: return(0);
! 1753:
! 1754: link = theacl;
! 1755: /* To get to the next acl, traverse linked list until index *
! 1756: * of acl matches the count we are keeping. This count is *
! 1757: * incremented each time we return an acl entry. */
! 1758:
! 1759: for(keep_going = 0; keep_going < theacl->count; keep_going++)
! 1760: link = link->nextp;
! 1761:
! 1762: entry = *entry_p = link->entryp;
! 1763:
! 1764: DEBUG(10,("*entry_p is %d\n",entry_p));
! 1765: DEBUG(10,("*entry_p->ace_access is %d\n",entry->ace_access));
! 1766:
! 1767: /* Increment count */
! 1768: theacl->count++;
! 1769: if(link->nextp == NULL)
! 1770: theacl->count = -1;
! 1771:
! 1772: return(1);
! 1773: }
! 1774:
! 1775: int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
! 1776: {
! 1777: /* Initialize tag type */
! 1778:
! 1779: *tag_type_p = -1;
! 1780: DEBUG(10,("the tagtype is %d\n",entry_d->ace_id->id_type));
! 1781:
! 1782: /* Depending on what type of entry we have, *
! 1783: * return tag type. */
! 1784: switch(entry_d->ace_id->id_type) {
! 1785: case ACEID_USER:
! 1786: *tag_type_p = SMB_ACL_USER;
! 1787: break;
! 1788: case ACEID_GROUP:
! 1789: *tag_type_p = SMB_ACL_GROUP;
! 1790: break;
! 1791:
! 1792: case SMB_ACL_USER_OBJ:
! 1793: case SMB_ACL_GROUP_OBJ:
! 1794: case SMB_ACL_OTHER:
! 1795: *tag_type_p = entry_d->ace_id->id_type;
! 1796: break;
! 1797:
! 1798: default:
! 1799: return(-1);
! 1800: }
! 1801:
! 1802: return(0);
! 1803: }
! 1804:
! 1805: SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
! 1806: {
! 1807: struct acl *file_acl = (struct acl *)NULL;
! 1808: struct acl_entry *acl_entry;
! 1809: struct new_acl_entry *new_acl_entry;
! 1810: struct ace_id *idp;
! 1811: struct acl_entry_link *acl_entry_link;
! 1812: struct acl_entry_link *acl_entry_link_head;
! 1813: int i;
! 1814: int rc = 0;
! 1815:
! 1816: /* AIX has no DEFAULT */
! 1817: if ( type == SMB_ACL_TYPE_DEFAULT ) {
! 1818: #ifdef ENOTSUP
! 1819: errno = ENOTSUP;
! 1820: #else
! 1821: errno = ENOSYS;
! 1822: #endif
! 1823: return NULL;
! 1824: }
! 1825:
! 1826: /* Get the acl using statacl */
! 1827:
! 1828: DEBUG(10,("Entering sys_acl_get_file\n"));
! 1829: DEBUG(10,("path_p is %s\n",path_p));
! 1830:
! 1831: file_acl = (struct acl *)SMB_MALLOC(BUFSIZ);
! 1832:
! 1833: if(file_acl == NULL) {
! 1834: errno=ENOMEM;
! 1835: DEBUG(0,("Error in AIX sys_acl_get_file: %d\n",errno));
! 1836: return(NULL);
! 1837: }
! 1838:
! 1839: memset(file_acl,0,BUFSIZ);
! 1840:
! 1841: rc = statacl((char *)path_p,0,file_acl,BUFSIZ);
! 1842: if(rc == -1) {
! 1843: DEBUG(0,("statacl returned %d with errno %d\n",rc,errno));
! 1844: SAFE_FREE(file_acl);
! 1845: return(NULL);
! 1846: }
! 1847:
! 1848: DEBUG(10,("Got facl and returned it\n"));
! 1849:
! 1850: /* Point to the first acl entry in the acl */
! 1851: acl_entry = file_acl->acl_ext;
! 1852:
! 1853: /* Begin setting up the head of the linked list *
! 1854: * that will be used for the storing the acl *
! 1855: * in a way that is useful for the posix_acls.c *
! 1856: * code. */
! 1857:
! 1858: acl_entry_link_head = acl_entry_link = sys_acl_init(0);
! 1859: if(acl_entry_link_head == NULL)
! 1860: return(NULL);
! 1861:
! 1862: acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
! 1863: if(acl_entry_link->entryp == NULL) {
! 1864: SAFE_FREE(file_acl);
! 1865: errno = ENOMEM;
! 1866: DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
! 1867: return(NULL);
! 1868: }
! 1869:
! 1870: DEBUG(10,("acl_entry is %d\n",acl_entry));
! 1871: DEBUG(10,("acl_last(file_acl) id %d\n",acl_last(file_acl)));
! 1872:
! 1873: /* Check if the extended acl bit is on. *
! 1874: * If it isn't, do not show the *
! 1875: * contents of the acl since AIX intends *
! 1876: * the extended info to remain unused */
! 1877:
! 1878: if(file_acl->acl_mode & S_IXACL){
! 1879: /* while we are not pointing to the very end */
! 1880: while(acl_entry < acl_last(file_acl)) {
! 1881: /* before we malloc anything, make sure this is */
! 1882: /* a valid acl entry and one that we want to map */
! 1883: idp = id_nxt(acl_entry->ace_id);
! 1884: if((acl_entry->ace_type == ACC_SPECIFY ||
! 1885: (acl_entry->ace_type == ACC_PERMIT)) && (idp != id_last(acl_entry))) {
! 1886: acl_entry = acl_nxt(acl_entry);
! 1887: continue;
! 1888: }
! 1889:
! 1890: idp = acl_entry->ace_id;
! 1891:
! 1892: /* Check if this is the first entry in the linked list. *
! 1893: * The first entry needs to keep prevp pointing to NULL *
! 1894: * and already has entryp allocated. */
! 1895:
! 1896: if(acl_entry_link_head->count != 0) {
! 1897: acl_entry_link->nextp = SMB_MALLOC_P(struct acl_entry_link);
! 1898:
! 1899: if(acl_entry_link->nextp == NULL) {
! 1900: SAFE_FREE(file_acl);
! 1901: errno = ENOMEM;
! 1902: DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
! 1903: return(NULL);
! 1904: }
! 1905:
! 1906: acl_entry_link->nextp->prevp = acl_entry_link;
! 1907: acl_entry_link = acl_entry_link->nextp;
! 1908: acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
! 1909: if(acl_entry_link->entryp == NULL) {
! 1910: SAFE_FREE(file_acl);
! 1911: errno = ENOMEM;
! 1912: DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
! 1913: return(NULL);
! 1914: }
! 1915: acl_entry_link->nextp = NULL;
! 1916: }
! 1917:
! 1918: acl_entry_link->entryp->ace_len = acl_entry->ace_len;
! 1919:
! 1920: /* Don't really need this since all types are going *
! 1921: * to be specified but, it's better than leaving it 0 */
! 1922:
! 1923: acl_entry_link->entryp->ace_type = acl_entry->ace_type;
! 1924:
! 1925: acl_entry_link->entryp->ace_access = acl_entry->ace_access;
! 1926:
! 1927: memcpy(acl_entry_link->entryp->ace_id,idp,sizeof(struct ace_id));
! 1928:
! 1929: /* The access in the acl entries must be left shifted by *
! 1930: * three bites, because they will ultimately be compared *
! 1931: * to S_IRUSR, S_IWUSR, and S_IXUSR. */
! 1932:
! 1933: switch(acl_entry->ace_type){
! 1934: case ACC_PERMIT:
! 1935: case ACC_SPECIFY:
! 1936: acl_entry_link->entryp->ace_access = acl_entry->ace_access;
! 1937: acl_entry_link->entryp->ace_access <<= 6;
! 1938: acl_entry_link_head->count++;
! 1939: break;
! 1940: case ACC_DENY:
! 1941: /* Since there is no way to return a DENY acl entry *
! 1942: * change to PERMIT and then shift. */
! 1943: DEBUG(10,("acl_entry->ace_access is %d\n",acl_entry->ace_access));
! 1944: acl_entry_link->entryp->ace_access = ~acl_entry->ace_access & 7;
! 1945: DEBUG(10,("acl_entry_link->entryp->ace_access is %d\n",acl_entry_link->entryp->ace_access));
! 1946: acl_entry_link->entryp->ace_access <<= 6;
! 1947: acl_entry_link_head->count++;
! 1948: break;
! 1949: default:
! 1950: return(0);
! 1951: }
! 1952:
! 1953: DEBUG(10,("acl_entry = %d\n",acl_entry));
! 1954: DEBUG(10,("The ace_type is %d\n",acl_entry->ace_type));
! 1955:
! 1956: acl_entry = acl_nxt(acl_entry);
! 1957: }
! 1958: } /* end of if enabled */
! 1959:
! 1960: /* Since owner, group, other acl entries are not *
! 1961: * part of the acl entries in an acl, they must *
! 1962: * be dummied up to become part of the list. */
! 1963:
! 1964: for( i = 1; i < 4; i++) {
! 1965: DEBUG(10,("i is %d\n",i));
! 1966: if(acl_entry_link_head->count != 0) {
! 1967: acl_entry_link->nextp = SMB_MALLOC_P(struct acl_entry_link);
! 1968: if(acl_entry_link->nextp == NULL) {
! 1969: SAFE_FREE(file_acl);
! 1970: errno = ENOMEM;
! 1971: DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
! 1972: return(NULL);
! 1973: }
! 1974:
! 1975: acl_entry_link->nextp->prevp = acl_entry_link;
! 1976: acl_entry_link = acl_entry_link->nextp;
! 1977: acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
! 1978: if(acl_entry_link->entryp == NULL) {
! 1979: SAFE_FREE(file_acl);
! 1980: errno = ENOMEM;
! 1981: DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
! 1982: return(NULL);
! 1983: }
! 1984: }
! 1985:
! 1986: acl_entry_link->nextp = NULL;
! 1987:
! 1988: new_acl_entry = acl_entry_link->entryp;
! 1989: idp = new_acl_entry->ace_id;
! 1990:
! 1991: new_acl_entry->ace_len = sizeof(struct acl_entry);
! 1992: new_acl_entry->ace_type = ACC_PERMIT;
! 1993: idp->id_len = sizeof(struct ace_id);
! 1994: DEBUG(10,("idp->id_len = %d\n",idp->id_len));
! 1995: memset(idp->id_data,0,sizeof(uid_t));
! 1996:
! 1997: switch(i) {
! 1998: case 2:
! 1999: new_acl_entry->ace_access = file_acl->g_access << 6;
! 2000: idp->id_type = SMB_ACL_GROUP_OBJ;
! 2001: break;
! 2002:
! 2003: case 3:
! 2004: new_acl_entry->ace_access = file_acl->o_access << 6;
! 2005: idp->id_type = SMB_ACL_OTHER;
! 2006: break;
! 2007:
! 2008: case 1:
! 2009: new_acl_entry->ace_access = file_acl->u_access << 6;
! 2010: idp->id_type = SMB_ACL_USER_OBJ;
! 2011: break;
! 2012:
! 2013: default:
! 2014: return(NULL);
! 2015:
! 2016: }
! 2017:
! 2018: acl_entry_link_head->count++;
! 2019: DEBUG(10,("new_acl_entry->ace_access = %d\n",new_acl_entry->ace_access));
! 2020: }
! 2021:
! 2022: acl_entry_link_head->count = 0;
! 2023: SAFE_FREE(file_acl);
! 2024:
! 2025: return(acl_entry_link_head);
! 2026: }
! 2027:
! 2028: #if 0
! 2029: SMB_ACL_T sys_acl_get_fd(int fd)
! 2030: {
! 2031: struct acl *file_acl = (struct acl *)NULL;
! 2032: struct acl_entry *acl_entry;
! 2033: struct new_acl_entry *new_acl_entry;
! 2034: struct ace_id *idp;
! 2035: struct acl_entry_link *acl_entry_link;
! 2036: struct acl_entry_link *acl_entry_link_head;
! 2037: int i;
! 2038: int rc = 0;
! 2039:
! 2040: /* Get the acl using fstatacl */
! 2041:
! 2042: DEBUG(10,("Entering sys_acl_get_fd\n"));
! 2043: DEBUG(10,("fd is %d\n",fd));
! 2044: file_acl = (struct acl *)SMB_MALLOC(BUFSIZ);
! 2045:
! 2046: if(file_acl == NULL) {
! 2047: errno=ENOMEM;
! 2048: DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
! 2049: return(NULL);
! 2050: }
! 2051:
! 2052: memset(file_acl,0,BUFSIZ);
! 2053:
! 2054: rc = fstatacl(fd,0,file_acl,BUFSIZ);
! 2055: if(rc == -1) {
! 2056: DEBUG(0,("The fstatacl call returned %d with errno %d\n",rc,errno));
! 2057: SAFE_FREE(file_acl);
! 2058: return(NULL);
! 2059: }
! 2060:
! 2061: DEBUG(10,("Got facl and returned it\n"));
! 2062:
! 2063: /* Point to the first acl entry in the acl */
! 2064:
! 2065: acl_entry = file_acl->acl_ext;
! 2066: /* Begin setting up the head of the linked list *
! 2067: * that will be used for the storing the acl *
! 2068: * in a way that is useful for the posix_acls.c *
! 2069: * code. */
! 2070:
! 2071: acl_entry_link_head = acl_entry_link = sys_acl_init(0);
! 2072: if(acl_entry_link_head == NULL){
! 2073: SAFE_FREE(file_acl);
! 2074: return(NULL);
! 2075: }
! 2076:
! 2077: acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
! 2078:
! 2079: if(acl_entry_link->entryp == NULL) {
! 2080: errno = ENOMEM;
! 2081: DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
! 2082: SAFE_FREE(file_acl);
! 2083: return(NULL);
! 2084: }
! 2085:
! 2086: DEBUG(10,("acl_entry is %d\n",acl_entry));
! 2087: DEBUG(10,("acl_last(file_acl) id %d\n",acl_last(file_acl)));
! 2088:
! 2089: /* Check if the extended acl bit is on. *
! 2090: * If it isn't, do not show the *
! 2091: * contents of the acl since AIX intends *
! 2092: * the extended info to remain unused */
! 2093:
! 2094: if(file_acl->acl_mode & S_IXACL){
! 2095: /* while we are not pointing to the very end */
! 2096: while(acl_entry < acl_last(file_acl)) {
! 2097: /* before we malloc anything, make sure this is */
! 2098: /* a valid acl entry and one that we want to map */
! 2099:
! 2100: idp = id_nxt(acl_entry->ace_id);
! 2101: if((acl_entry->ace_type == ACC_SPECIFY ||
! 2102: (acl_entry->ace_type == ACC_PERMIT)) && (idp != id_last(acl_entry))) {
! 2103: acl_entry = acl_nxt(acl_entry);
! 2104: continue;
! 2105: }
! 2106:
! 2107: idp = acl_entry->ace_id;
! 2108:
! 2109: /* Check if this is the first entry in the linked list. *
! 2110: * The first entry needs to keep prevp pointing to NULL *
! 2111: * and already has entryp allocated. */
! 2112:
! 2113: if(acl_entry_link_head->count != 0) {
! 2114: acl_entry_link->nextp = SMB_MALLOC_P(struct acl_entry_link);
! 2115: if(acl_entry_link->nextp == NULL) {
! 2116: errno = ENOMEM;
! 2117: DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
! 2118: SAFE_FREE(file_acl);
! 2119: return(NULL);
! 2120: }
! 2121: acl_entry_link->nextp->prevp = acl_entry_link;
! 2122: acl_entry_link = acl_entry_link->nextp;
! 2123: acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
! 2124: if(acl_entry_link->entryp == NULL) {
! 2125: errno = ENOMEM;
! 2126: DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
! 2127: SAFE_FREE(file_acl);
! 2128: return(NULL);
! 2129: }
! 2130:
! 2131: acl_entry_link->nextp = NULL;
! 2132: }
! 2133:
! 2134: acl_entry_link->entryp->ace_len = acl_entry->ace_len;
! 2135:
! 2136: /* Don't really need this since all types are going *
! 2137: * to be specified but, it's better than leaving it 0 */
! 2138:
! 2139: acl_entry_link->entryp->ace_type = acl_entry->ace_type;
! 2140: acl_entry_link->entryp->ace_access = acl_entry->ace_access;
! 2141:
! 2142: memcpy(acl_entry_link->entryp->ace_id, idp, sizeof(struct ace_id));
! 2143:
! 2144: /* The access in the acl entries must be left shifted by *
! 2145: * three bites, because they will ultimately be compared *
! 2146: * to S_IRUSR, S_IWUSR, and S_IXUSR. */
! 2147:
! 2148: switch(acl_entry->ace_type){
! 2149: case ACC_PERMIT:
! 2150: case ACC_SPECIFY:
! 2151: acl_entry_link->entryp->ace_access = acl_entry->ace_access;
! 2152: acl_entry_link->entryp->ace_access <<= 6;
! 2153: acl_entry_link_head->count++;
! 2154: break;
! 2155: case ACC_DENY:
! 2156: /* Since there is no way to return a DENY acl entry *
! 2157: * change to PERMIT and then shift. */
! 2158: DEBUG(10,("acl_entry->ace_access is %d\n",acl_entry->ace_access));
! 2159: acl_entry_link->entryp->ace_access = ~acl_entry->ace_access & 7;
! 2160: DEBUG(10,("acl_entry_link->entryp->ace_access is %d\n",acl_entry_link->entryp->ace_access));
! 2161: acl_entry_link->entryp->ace_access <<= 6;
! 2162: acl_entry_link_head->count++;
! 2163: break;
! 2164: default:
! 2165: return(0);
! 2166: }
! 2167:
! 2168: DEBUG(10,("acl_entry = %d\n",acl_entry));
! 2169: DEBUG(10,("The ace_type is %d\n",acl_entry->ace_type));
! 2170:
! 2171: acl_entry = acl_nxt(acl_entry);
! 2172: }
! 2173: } /* end of if enabled */
! 2174:
! 2175: /* Since owner, group, other acl entries are not *
! 2176: * part of the acl entries in an acl, they must *
! 2177: * be dummied up to become part of the list. */
! 2178:
! 2179: for( i = 1; i < 4; i++) {
! 2180: DEBUG(10,("i is %d\n",i));
! 2181: if(acl_entry_link_head->count != 0){
! 2182: acl_entry_link->nextp = SMB_MALLOC_P(struct acl_entry_link);
! 2183: if(acl_entry_link->nextp == NULL) {
! 2184: errno = ENOMEM;
! 2185: DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
! 2186: SAFE_FREE(file_acl);
! 2187: return(NULL);
! 2188: }
! 2189:
! 2190: acl_entry_link->nextp->prevp = acl_entry_link;
! 2191: acl_entry_link = acl_entry_link->nextp;
! 2192: acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
! 2193:
! 2194: if(acl_entry_link->entryp == NULL) {
! 2195: SAFE_FREE(file_acl);
! 2196: errno = ENOMEM;
! 2197: DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
! 2198: return(NULL);
! 2199: }
! 2200: }
! 2201:
! 2202: acl_entry_link->nextp = NULL;
! 2203:
! 2204: new_acl_entry = acl_entry_link->entryp;
! 2205: idp = new_acl_entry->ace_id;
! 2206:
! 2207: new_acl_entry->ace_len = sizeof(struct acl_entry);
! 2208: new_acl_entry->ace_type = ACC_PERMIT;
! 2209: idp->id_len = sizeof(struct ace_id);
! 2210: DEBUG(10,("idp->id_len = %d\n",idp->id_len));
! 2211: memset(idp->id_data,0,sizeof(uid_t));
! 2212:
! 2213: switch(i) {
! 2214: case 2:
! 2215: new_acl_entry->ace_access = file_acl->g_access << 6;
! 2216: idp->id_type = SMB_ACL_GROUP_OBJ;
! 2217: break;
! 2218:
! 2219: case 3:
! 2220: new_acl_entry->ace_access = file_acl->o_access << 6;
! 2221: idp->id_type = SMB_ACL_OTHER;
! 2222: break;
! 2223:
! 2224: case 1:
! 2225: new_acl_entry->ace_access = file_acl->u_access << 6;
! 2226: idp->id_type = SMB_ACL_USER_OBJ;
! 2227: break;
! 2228:
! 2229: default:
! 2230: return(NULL);
! 2231: }
! 2232:
! 2233: acl_entry_link_head->count++;
! 2234: DEBUG(10,("new_acl_entry->ace_access = %d\n",new_acl_entry->ace_access));
! 2235: }
! 2236:
! 2237: acl_entry_link_head->count = 0;
! 2238: SAFE_FREE(file_acl);
! 2239:
! 2240: return(acl_entry_link_head);
! 2241: }
! 2242: #endif
! 2243:
! 2244: int sys_acl_get_info(SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T *tag_type_p, uint32 *bits_p, id_t *u_g_id_p)
! 2245: {
! 2246: uint *permset;
! 2247:
! 2248: if (sys_acl_get_tag_type(entry, tag_type_p) != 0)
! 2249: return -1;
! 2250:
! 2251: if (*tag_type_p == SMB_ACL_USER || *tag_type_p == SMB_ACL_GROUP)
! 2252: memcpy(u_g_id_p, entry->ace_id->id_data, sizeof (id_t));
! 2253:
! 2254: permset = &entry->ace_access;
! 2255:
! 2256: DEBUG(10,("*permset is %d\n",*permset));
! 2257: *bits_p = (*permset & S_IRUSR ? 4 : 0)
! 2258: | (*permset & S_IWUSR ? 2 : 0)
! 2259: | (*permset & S_IXUSR ? 1 : 0);
! 2260:
! 2261: return 0;
! 2262: }
! 2263:
! 2264: SMB_ACL_T sys_acl_init( int count)
! 2265: {
! 2266: struct acl_entry_link *theacl = NULL;
! 2267:
! 2268: if (count < 0) {
! 2269: errno = EINVAL;
! 2270: return NULL;
! 2271: }
! 2272:
! 2273: DEBUG(10,("Entering sys_acl_init\n"));
! 2274:
! 2275: theacl = SMB_MALLOC_P(struct acl_entry_link);
! 2276: if(theacl == NULL) {
! 2277: errno = ENOMEM;
! 2278: DEBUG(0,("Error in sys_acl_init is %d\n",errno));
! 2279: return(NULL);
! 2280: }
! 2281:
! 2282: theacl->count = 0;
! 2283: theacl->nextp = NULL;
! 2284: theacl->prevp = NULL;
! 2285: theacl->entryp = NULL;
! 2286: DEBUG(10,("Exiting sys_acl_init\n"));
! 2287: return(theacl);
! 2288: }
! 2289:
! 2290: int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
! 2291: {
! 2292: struct acl_entry_link *theacl;
! 2293: struct acl_entry_link *acl_entryp;
! 2294: struct acl_entry_link *temp_entry;
! 2295: int counting;
! 2296:
! 2297: DEBUG(10,("Entering the sys_acl_create_entry\n"));
! 2298:
! 2299: theacl = acl_entryp = *pacl;
! 2300:
! 2301: /* Get to the end of the acl before adding entry */
! 2302:
! 2303: for(counting=0; counting < theacl->count; counting++){
! 2304: DEBUG(10,("The acl_entryp is %d\n",acl_entryp));
! 2305: temp_entry = acl_entryp;
! 2306: acl_entryp = acl_entryp->nextp;
! 2307: }
! 2308:
! 2309: if(theacl->count != 0){
! 2310: temp_entry->nextp = acl_entryp = SMB_MALLOC_P(struct acl_entry_link);
! 2311: if(acl_entryp == NULL) {
! 2312: errno = ENOMEM;
! 2313: DEBUG(0,("Error in sys_acl_create_entry is %d\n",errno));
! 2314: return(-1);
! 2315: }
! 2316:
! 2317: DEBUG(10,("The acl_entryp is %d\n",acl_entryp));
! 2318: acl_entryp->prevp = temp_entry;
! 2319: DEBUG(10,("The acl_entryp->prevp is %d\n",acl_entryp->prevp));
! 2320: }
! 2321:
! 2322: *pentry = acl_entryp->entryp = SMB_MALLOC_P(struct new_acl_entry);
! 2323: if(*pentry == NULL) {
! 2324: errno = ENOMEM;
! 2325: DEBUG(0,("Error in sys_acl_create_entry is %d\n",errno));
! 2326: return(-1);
! 2327: }
! 2328:
! 2329: memset(*pentry,0,sizeof(struct new_acl_entry));
! 2330: acl_entryp->entryp->ace_len = sizeof(struct acl_entry);
! 2331: acl_entryp->entryp->ace_type = ACC_PERMIT;
! 2332: acl_entryp->entryp->ace_id->id_len = sizeof(struct ace_id);
! 2333: acl_entryp->nextp = NULL;
! 2334: theacl->count++;
! 2335: DEBUG(10,("Exiting sys_acl_create_entry\n"));
! 2336: return(0);
! 2337: }
! 2338:
! 2339: int sys_acl_set_info(SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tag_type, uint32 bits, id_t u_g_id)
! 2340: {
! 2341: entry->ace_id->id_type = tag_type;
! 2342: DEBUG(10,("The tag type is %d\n",entry->ace_id->id_type));
! 2343:
! 2344: if (tag_type == SMB_ACL_USER || tag_type == SMB_ACL_GROUP)
! 2345: memcpy(entry->ace_id->id_data, &u_g_id, sizeof (id_t));
! 2346:
! 2347: entry->ace_access = bits;
! 2348: DEBUG(10,("entry->ace_access = %d\n",entry->ace_access));
! 2349:
! 2350: return 0;
! 2351: }
! 2352:
! 2353: int sys_acl_set_access_bits(SMB_ACL_ENTRY_T entry, uint32 bits)
! 2354: {
! 2355: DEBUG(10,("Starting AIX sys_acl_set_permset\n"));
! 2356: entry->ace_access = bits;
! 2357: DEBUG(10,("entry->ace_access = %d\n",entry->ace_access));
! 2358: DEBUG(10,("Ending AIX sys_acl_set_permset\n"));
! 2359: return(0);
! 2360: }
! 2361:
! 2362: int sys_acl_valid( SMB_ACL_T theacl )
! 2363: {
! 2364: int user_obj = 0;
! 2365: int group_obj = 0;
! 2366: int other_obj = 0;
! 2367: struct acl_entry_link *acl_entry;
! 2368:
! 2369: for(acl_entry=theacl; acl_entry != NULL; acl_entry = acl_entry->nextp) {
! 2370: user_obj += (acl_entry->entryp->ace_id->id_type == SMB_ACL_USER_OBJ);
! 2371: group_obj += (acl_entry->entryp->ace_id->id_type == SMB_ACL_GROUP_OBJ);
! 2372: other_obj += (acl_entry->entryp->ace_id->id_type == SMB_ACL_OTHER);
! 2373: }
! 2374:
! 2375: DEBUG(10,("user_obj=%d, group_obj=%d, other_obj=%d\n",user_obj,group_obj,other_obj));
! 2376:
! 2377: if(user_obj != 1 || group_obj != 1 || other_obj != 1)
! 2378: return(-1);
! 2379:
! 2380: return(0);
! 2381: }
! 2382:
! 2383: int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
! 2384: {
! 2385: struct acl_entry_link *acl_entry_link = NULL;
! 2386: struct acl *file_acl = NULL;
! 2387: struct acl *file_acl_temp = NULL;
! 2388: struct acl_entry *acl_entry = NULL;
! 2389: struct ace_id *ace_id = NULL;
! 2390: uint id_type;
! 2391: uint user_id;
! 2392: uint acl_length;
! 2393: uint rc;
! 2394:
! 2395: DEBUG(10,("Entering sys_acl_set_file\n"));
! 2396: DEBUG(10,("File name is %s\n",name));
! 2397:
! 2398: /* AIX has no default ACL */
! 2399: if(acltype == SMB_ACL_TYPE_DEFAULT)
! 2400: return(0);
! 2401:
! 2402: acl_length = BUFSIZ;
! 2403: file_acl = (struct acl *)SMB_MALLOC(BUFSIZ);
! 2404:
! 2405: if(file_acl == NULL) {
! 2406: errno = ENOMEM;
! 2407: DEBUG(0,("Error in sys_acl_set_file is %d\n",errno));
! 2408: return(-1);
! 2409: }
! 2410:
! 2411: memset(file_acl,0,BUFSIZ);
! 2412:
! 2413: file_acl->acl_len = ACL_SIZ;
! 2414: file_acl->acl_mode = S_IXACL;
! 2415:
! 2416: for(acl_entry_link=theacl; acl_entry_link != NULL; acl_entry_link = acl_entry_link->nextp) {
! 2417: acl_entry_link->entryp->ace_access >>= 6;
! 2418: id_type = acl_entry_link->entryp->ace_id->id_type;
! 2419:
! 2420: switch(id_type) {
! 2421: case SMB_ACL_USER_OBJ:
! 2422: file_acl->u_access = acl_entry_link->entryp->ace_access;
! 2423: continue;
! 2424: case SMB_ACL_GROUP_OBJ:
! 2425: file_acl->g_access = acl_entry_link->entryp->ace_access;
! 2426: continue;
! 2427: case SMB_ACL_OTHER:
! 2428: file_acl->o_access = acl_entry_link->entryp->ace_access;
! 2429: continue;
! 2430: case SMB_ACL_MASK:
! 2431: continue;
! 2432: }
! 2433:
! 2434: if((file_acl->acl_len + sizeof(struct acl_entry)) > acl_length) {
! 2435: acl_length += sizeof(struct acl_entry);
! 2436: file_acl_temp = (struct acl *)SMB_MALLOC(acl_length);
! 2437: if(file_acl_temp == NULL) {
! 2438: SAFE_FREE(file_acl);
! 2439: errno = ENOMEM;
! 2440: DEBUG(0,("Error in sys_acl_set_file is %d\n",errno));
! 2441: return(-1);
! 2442: }
! 2443:
! 2444: memcpy(file_acl_temp,file_acl,file_acl->acl_len);
! 2445: SAFE_FREE(file_acl);
! 2446: file_acl = file_acl_temp;
! 2447: }
! 2448:
! 2449: acl_entry = (struct acl_entry *)((char *)file_acl + file_acl->acl_len);
! 2450: file_acl->acl_len += sizeof(struct acl_entry);
! 2451: acl_entry->ace_len = acl_entry_link->entryp->ace_len;
! 2452: acl_entry->ace_access = acl_entry_link->entryp->ace_access;
! 2453:
! 2454: /* In order to use this, we'll need to wait until we can get denies */
! 2455: /* if(!acl_entry->ace_access && acl_entry->ace_type == ACC_PERMIT)
! 2456: acl_entry->ace_type = ACC_SPECIFY; */
! 2457:
! 2458: acl_entry->ace_type = ACC_SPECIFY;
! 2459:
! 2460: ace_id = acl_entry->ace_id;
! 2461:
! 2462: ace_id->id_type = acl_entry_link->entryp->ace_id->id_type;
! 2463: DEBUG(10,("The id type is %d\n",ace_id->id_type));
! 2464: ace_id->id_len = acl_entry_link->entryp->ace_id->id_len;
! 2465: memcpy(&user_id, acl_entry_link->entryp->ace_id->id_data, sizeof(uid_t));
! 2466: memcpy(acl_entry->ace_id->id_data, &user_id, sizeof(uid_t));
! 2467: }
! 2468:
! 2469: rc = chacl((char*)name,file_acl,file_acl->acl_len);
! 2470: DEBUG(10,("errno is %d\n",errno));
! 2471: DEBUG(10,("return code is %d\n",rc));
! 2472: SAFE_FREE(file_acl);
! 2473: DEBUG(10,("Exiting the sys_acl_set_file\n"));
! 2474: return(rc);
! 2475: }
! 2476:
! 2477: #if 0
! 2478: int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
! 2479: {
! 2480: struct acl_entry_link *acl_entry_link = NULL;
! 2481: struct acl *file_acl = NULL;
! 2482: struct acl *file_acl_temp = NULL;
! 2483: struct acl_entry *acl_entry = NULL;
! 2484: struct ace_id *ace_id = NULL;
! 2485: uint id_type;
! 2486: uint user_id;
! 2487: uint acl_length;
! 2488: uint rc;
! 2489:
! 2490: DEBUG(10,("Entering sys_acl_set_fd\n"));
! 2491: acl_length = BUFSIZ;
! 2492: file_acl = (struct acl *)SMB_MALLOC(BUFSIZ);
! 2493:
! 2494: if(file_acl == NULL) {
! 2495: errno = ENOMEM;
! 2496: DEBUG(0,("Error in sys_acl_set_fd is %d\n",errno));
! 2497: return(-1);
! 2498: }
! 2499:
! 2500: memset(file_acl,0,BUFSIZ);
! 2501:
! 2502: file_acl->acl_len = ACL_SIZ;
! 2503: file_acl->acl_mode = S_IXACL;
! 2504:
! 2505: for(acl_entry_link=theacl; acl_entry_link != NULL; acl_entry_link = acl_entry_link->nextp) {
! 2506: acl_entry_link->entryp->ace_access >>= 6;
! 2507: id_type = acl_entry_link->entryp->ace_id->id_type;
! 2508: DEBUG(10,("The id_type is %d\n",id_type));
! 2509:
! 2510: switch(id_type) {
! 2511: case SMB_ACL_USER_OBJ:
! 2512: file_acl->u_access = acl_entry_link->entryp->ace_access;
! 2513: continue;
! 2514: case SMB_ACL_GROUP_OBJ:
! 2515: file_acl->g_access = acl_entry_link->entryp->ace_access;
! 2516: continue;
! 2517: case SMB_ACL_OTHER:
! 2518: file_acl->o_access = acl_entry_link->entryp->ace_access;
! 2519: continue;
! 2520: case SMB_ACL_MASK:
! 2521: continue;
! 2522: }
! 2523:
! 2524: if((file_acl->acl_len + sizeof(struct acl_entry)) > acl_length) {
! 2525: acl_length += sizeof(struct acl_entry);
! 2526: file_acl_temp = (struct acl *)SMB_MALLOC(acl_length);
! 2527: if(file_acl_temp == NULL) {
! 2528: SAFE_FREE(file_acl);
! 2529: errno = ENOMEM;
! 2530: DEBUG(0,("Error in sys_acl_set_fd is %d\n",errno));
! 2531: return(-1);
! 2532: }
! 2533:
! 2534: memcpy(file_acl_temp,file_acl,file_acl->acl_len);
! 2535: SAFE_FREE(file_acl);
! 2536: file_acl = file_acl_temp;
! 2537: }
! 2538:
! 2539: acl_entry = (struct acl_entry *)((char *)file_acl + file_acl->acl_len);
! 2540: file_acl->acl_len += sizeof(struct acl_entry);
! 2541: acl_entry->ace_len = acl_entry_link->entryp->ace_len;
! 2542: acl_entry->ace_access = acl_entry_link->entryp->ace_access;
! 2543:
! 2544: /* In order to use this, we'll need to wait until we can get denies */
! 2545: /* if(!acl_entry->ace_access && acl_entry->ace_type == ACC_PERMIT)
! 2546: acl_entry->ace_type = ACC_SPECIFY; */
! 2547:
! 2548: acl_entry->ace_type = ACC_SPECIFY;
! 2549:
! 2550: ace_id = acl_entry->ace_id;
! 2551:
! 2552: ace_id->id_type = acl_entry_link->entryp->ace_id->id_type;
! 2553: DEBUG(10,("The id type is %d\n",ace_id->id_type));
! 2554: ace_id->id_len = acl_entry_link->entryp->ace_id->id_len;
! 2555: memcpy(&user_id, acl_entry_link->entryp->ace_id->id_data, sizeof(uid_t));
! 2556: memcpy(ace_id->id_data, &user_id, sizeof(uid_t));
! 2557: }
! 2558:
! 2559: rc = fchacl(fd,file_acl,file_acl->acl_len);
! 2560: DEBUG(10,("errno is %d\n",errno));
! 2561: DEBUG(10,("return code is %d\n",rc));
! 2562: SAFE_FREE(file_acl);
! 2563: DEBUG(10,("Exiting sys_acl_set_fd\n"));
! 2564: return(rc);
! 2565: }
! 2566: #endif
! 2567:
! 2568: int sys_acl_delete_def_file(UNUSED(const char *name))
! 2569: {
! 2570: /* AIX has no default ACL */
! 2571: return 0;
! 2572: }
! 2573:
! 2574: int sys_acl_free_acl(SMB_ACL_T posix_acl)
! 2575: {
! 2576: struct acl_entry_link *acl_entry_link;
! 2577:
! 2578: for(acl_entry_link = posix_acl->nextp; acl_entry_link->nextp != NULL; acl_entry_link = acl_entry_link->nextp) {
! 2579: SAFE_FREE(acl_entry_link->prevp->entryp);
! 2580: SAFE_FREE(acl_entry_link->prevp);
! 2581: }
! 2582:
! 2583: SAFE_FREE(acl_entry_link->prevp->entryp);
! 2584: SAFE_FREE(acl_entry_link->prevp);
! 2585: SAFE_FREE(acl_entry_link->entryp);
! 2586: SAFE_FREE(acl_entry_link);
! 2587:
! 2588: return(0);
! 2589: }
! 2590:
! 2591: #elif defined(HAVE_OSX_ACLS) /*----------------------------------------------*/
! 2592:
! 2593: #define OSX_BROKEN_GETENTRY /* returns 0 instead of 1 */
! 2594:
! 2595: #include <membership.h>
! 2596:
! 2597: int sys_acl_get_entry(SMB_ACL_T the_acl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
! 2598: {
! 2599: int ret = acl_get_entry(the_acl, entry_id, entry_p);
! 2600: #ifdef OSX_BROKEN_GETENTRY
! 2601: if (ret == 0)
! 2602: ret = 1;
! 2603: else if (ret == -1 && errno == 22)
! 2604: ret = 0;
! 2605: #endif
! 2606: return ret;
! 2607: }
! 2608:
! 2609: SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type)
! 2610: {
! 2611: if (type == ACL_TYPE_DEFAULT) {
! 2612: errno = ENOTSUP;
! 2613: return NULL;
! 2614: }
! 2615: errno = 0;
! 2616: return acl_get_file(path_p, type);
! 2617: }
! 2618:
! 2619: #if 0
! 2620: SMB_ACL_T sys_acl_get_fd(int fd)
! 2621: {
! 2622: return acl_get_fd(fd);
! 2623: }
! 2624: #endif
! 2625:
! 2626: int sys_acl_get_info(SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T *tag_type_p, uint32 *bits_p, id_t *u_g_id_p)
! 2627: {
! 2628: uuid_t *uup;
! 2629: acl_tag_t tag;
! 2630: acl_flagset_t flagset;
! 2631: acl_permset_t permset;
! 2632: uint32 bits, fb, bb, pb;
! 2633: int id_type = -1;
! 2634: int rc;
! 2635:
! 2636: if (acl_get_tag_type(entry, &tag) != 0
! 2637: || acl_get_flagset_np(entry, &flagset) != 0
! 2638: || acl_get_permset(entry, &permset) != 0
! 2639: || (uup = acl_get_qualifier(entry)) == NULL)
! 2640: return -1;
! 2641:
! 2642: rc = mbr_uuid_to_id(*uup, u_g_id_p, &id_type);
! 2643: acl_free(uup);
! 2644: if (rc != 0)
! 2645: return rc;
! 2646:
! 2647: if (id_type == ID_TYPE_UID)
! 2648: *tag_type_p = SMB_ACL_USER;
! 2649: else
! 2650: *tag_type_p = SMB_ACL_GROUP;
! 2651:
! 2652: bits = tag == ACL_EXTENDED_ALLOW ? 1 : 0;
! 2653:
! 2654: for (fb = (1u<<4), bb = (1u<<1); bb < (1u<<12); fb *= 2, bb *= 2) {
! 2655: if (acl_get_flag_np(flagset, fb) == 1)
! 2656: bits |= bb;
! 2657: }
! 2658:
! 2659: for (pb = (1u<<1), bb = (1u<<12); bb < (1u<<25); pb *= 2, bb *= 2) {
! 2660: if (acl_get_perm_np(permset, pb) == 1)
! 2661: bits |= bb;
! 2662: }
! 2663:
! 2664: *bits_p = bits;
! 2665:
! 2666: return 0;
! 2667: }
! 2668:
! 2669: SMB_ACL_T sys_acl_init(int count)
! 2670: {
! 2671: return acl_init(count);
! 2672: }
! 2673:
! 2674: int sys_acl_create_entry(SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
! 2675: {
! 2676: return acl_create_entry(pacl, pentry);
! 2677: }
! 2678:
! 2679: int sys_acl_set_info(SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tag_type, uint32 bits, id_t u_g_id)
! 2680: {
! 2681: acl_flagset_t flagset;
! 2682: acl_permset_t permset;
! 2683: uint32 fb, bb, pb;
! 2684: int is_user = tag_type == SMB_ACL_USER;
! 2685: uuid_t uu;
! 2686: int rc;
! 2687:
! 2688: tag_type = bits & 1 ? ACL_EXTENDED_ALLOW : ACL_EXTENDED_DENY;
! 2689:
! 2690: if (acl_get_flagset_np(entry, &flagset) != 0
! 2691: || acl_get_permset(entry, &permset) != 0)
! 2692: return -1;
! 2693:
! 2694: acl_clear_flags_np(flagset);
! 2695: acl_clear_perms(permset);
! 2696:
! 2697: for (fb = (1u<<4), bb = (1u<<1); bb < (1u<<12); fb *= 2, bb *= 2) {
! 2698: if (bits & bb)
! 2699: acl_add_flag_np(flagset, fb);
! 2700: }
! 2701:
! 2702: for (pb = (1u<<1), bb = (1u<<12); bb < (1u<<25); pb *= 2, bb *= 2) {
! 2703: if (bits & bb)
! 2704: acl_add_perm(permset, pb);
! 2705: }
! 2706:
! 2707: if (is_user)
! 2708: rc = mbr_uid_to_uuid(u_g_id, uu);
! 2709: else
! 2710: rc = mbr_gid_to_uuid(u_g_id, uu);
! 2711: if (rc != 0)
! 2712: return rc;
! 2713:
! 2714: if (acl_set_tag_type(entry, tag_type) != 0
! 2715: || acl_set_qualifier(entry, &uu) != 0
! 2716: || acl_set_permset(entry, permset) != 0
! 2717: || acl_set_flagset_np(entry, flagset) != 0)
! 2718: return -1;
! 2719:
! 2720: return 0;
! 2721: }
! 2722:
! 2723: #if 0
! 2724: int sys_acl_set_access_bits(SMB_ACL_ENTRY_T entry, uint32 bits)
! 2725: {
! 2726: return -1; /* Not needed for OS X. */
! 2727: }
! 2728: #endif
! 2729:
! 2730: int sys_acl_valid(SMB_ACL_T theacl)
! 2731: {
! 2732: return acl_valid(theacl);
! 2733: }
! 2734:
! 2735: int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
! 2736: {
! 2737: return acl_set_file(name, acltype, theacl);
! 2738: }
! 2739:
! 2740: #if 0
! 2741: int sys_acl_set_fd(int fd, SMB_ACL_T theacl)
! 2742: {
! 2743: return acl_set_fd(fd, theacl);
! 2744: }
! 2745: #endif
! 2746:
! 2747: int sys_acl_delete_def_file(const char *name)
! 2748: {
! 2749: return acl_delete_def_file(name);
! 2750: }
! 2751:
! 2752: int sys_acl_free_acl(SMB_ACL_T the_acl)
! 2753: {
! 2754: return acl_free(the_acl);
! 2755: }
! 2756:
! 2757: #else /* No ACLs. */
! 2758:
! 2759: #error No ACL functions defined for this platform!
! 2760:
! 2761: #endif
! 2762:
! 2763: /************************************************************************
! 2764: Deliberately outside the ACL defines. Return 1 if this is a "no acls"
! 2765: errno, 0 if not.
! 2766: ************************************************************************/
! 2767:
! 2768: int no_acl_syscall_error(int err)
! 2769: {
! 2770: #ifdef HAVE_OSX_ACLS
! 2771: if (err == ENOENT)
! 2772: return 1; /* Weird problem with directory ACLs. */
! 2773: #endif
! 2774: #if defined(ENOSYS)
! 2775: if (err == ENOSYS) {
! 2776: return 1;
! 2777: }
! 2778: #endif
! 2779: #if defined(ENOTSUP)
! 2780: if (err == ENOTSUP) {
! 2781: return 1;
! 2782: }
! 2783: #endif
! 2784: if (err == EINVAL) {
! 2785: /* If the type of SMB_ACL_TYPE_ACCESS or SMB_ACL_TYPE_DEFAULT
! 2786: * isn't valid, then the ACLs must be non-POSIX. */
! 2787: return 1;
! 2788: }
! 2789: return 0;
! 2790: }
! 2791:
! 2792: #endif /* SUPPORT_ACLS */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>