2 * Unix SMB/CIFS implementation.
3 * Based on the Samba ACL support code.
4 * Copyright (C) Jeremy Allison 2000.
6 * The permission functions have been changed to get/set all bits via
7 * one call. Some functions that rsync doesn't need were also removed.
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 3 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * with this program; if not, visit the http://fsf.org website.
33 void SAFE_FREE(void *mem)
40 This file wraps all differing system ACL interfaces into a consistent
41 one based on the POSIX interface. It also returns the correct errors
42 for older UNIX systems that don't support ACLs.
44 The interfaces that each ACL implementation must support are as follows :
46 int sys_acl_get_entry( SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
47 int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
48 int sys_acl_get_access_bits(SMB_ACL_ENTRY_T entry_d, uint32 *bits)
49 void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d)
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_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
55 int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual)
56 int sys_acl_set_access_bits(SMB_ACL_ENTRY_T entry, uint32 bits)
57 int sys_acl_valid( SMB_ACL_T theacl )
58 int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
59 int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
60 int sys_acl_delete_def_file(const char *path)
62 The generic POSIX free is the following call. We split this into
63 several different free functions as we may need to add tag info
64 to structures when emulating the POSIX interface.
66 int sys_acl_free( void *obj_p)
68 The calls we actually use are :
70 int sys_acl_free_acl(SMB_ACL_T posix_acl)
71 int sys_acl_free_qualifier(void *qualifier, SMB_ACL_TAG_T tagtype)
75 #if defined(HAVE_POSIX_ACLS)
77 /* Identity mapping - easy. */
79 int sys_acl_get_entry( SMB_ACL_T the_acl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
81 return acl_get_entry( the_acl, entry_id, entry_p);
84 int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
86 return acl_get_tag_type( entry_d, tag_type_p);
89 void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d)
91 return acl_get_qualifier( entry_d);
94 SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
96 return acl_get_file( path_p, type);
100 SMB_ACL_T sys_acl_get_fd(int fd)
102 return acl_get_fd(fd);
106 #if defined(HAVE_ACL_GET_PERM_NP)
107 #define acl_get_perm(p, b) acl_get_perm_np(p, b)
110 int sys_acl_get_access_bits(SMB_ACL_ENTRY_T entry_d, uint32 *bits)
112 SMB_ACL_PERMSET_T permset;
114 if ((rc = acl_get_permset(entry_d, &permset)) != 0)
116 *bits = (acl_get_perm(permset, ACL_READ) ? 4 : 0)
117 | (acl_get_perm(permset, ACL_WRITE) ? 2 : 0)
118 | (acl_get_perm(permset, ACL_EXECUTE) ? 1 : 0);
122 SMB_ACL_T sys_acl_init( int count)
124 return acl_init(count);
127 int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
129 return acl_create_entry(pacl, pentry);
132 int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
134 return acl_set_tag_type(entry, tagtype);
137 int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual)
139 return acl_set_qualifier(entry, qual);
142 int sys_acl_set_access_bits(SMB_ACL_ENTRY_T entry, uint32 bits)
144 SMB_ACL_PERMSET_T permset;
146 if ((rc = acl_get_permset(entry, &permset)) != 0)
148 acl_clear_perms(permset);
150 acl_add_perm(permset, ACL_READ);
152 acl_add_perm(permset, ACL_WRITE);
154 acl_add_perm(permset, ACL_EXECUTE);
155 return acl_set_permset(entry, permset);
158 int sys_acl_valid( SMB_ACL_T theacl )
160 return acl_valid(theacl);
163 int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
165 return acl_set_file(name, acltype, theacl);
168 int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
170 return acl_set_fd(fd, theacl);
173 int sys_acl_delete_def_file(const char *name)
175 return acl_delete_def_file(name);
178 int sys_acl_free_acl(SMB_ACL_T the_acl)
180 return acl_free(the_acl);
183 int sys_acl_free_qualifier(void *qual, UNUSED(SMB_ACL_TAG_T tagtype))
185 return acl_free(qual);
188 #elif defined(HAVE_TRU64_ACLS)
190 * The interface to DEC/Compaq Tru64 UNIX ACLs
191 * is based on Draft 13 of the POSIX spec which is
192 * slightly different from the Draft 16 interface.
194 * Also, some of the permset manipulation functions
195 * such as acl_clear_perm() and acl_add_perm() appear
196 * to be broken on Tru64 so we have to manipulate
197 * the permission bits in the permset directly.
199 int sys_acl_get_entry( SMB_ACL_T the_acl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
201 SMB_ACL_ENTRY_T entry;
203 if (entry_id == SMB_ACL_FIRST_ENTRY && acl_first_entry(the_acl) != 0) {
208 if ((entry = acl_get_entry(the_acl)) != NULL) {
213 return errno ? -1 : 0;
216 int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
218 return acl_get_tag_type( entry_d, tag_type_p);
221 void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d)
223 return acl_get_qualifier( entry_d);
226 SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
228 return acl_get_file((char *)path_p, type);
232 SMB_ACL_T sys_acl_get_fd(int fd)
234 return acl_get_fd(fd, ACL_TYPE_ACCESS);
238 int sys_acl_get_access_bits(SMB_ACL_ENTRY_T entry_d, uint32 *bits)
240 SMB_ACL_PERMSET_T permset;
242 if ((rc = acl_get_permset(entry_d, &permset)) != 0)
244 *bits = *permset & 7; /* Tru64 doesn't have acl_get_perm() */
248 SMB_ACL_T sys_acl_init( int count)
250 return acl_init(count);
253 int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
255 SMB_ACL_ENTRY_T entry;
257 if ((entry = acl_create_entry(pacl)) == NULL) {
265 int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
267 return acl_set_tag_type(entry, tagtype);
270 int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual)
272 return acl_set_qualifier(entry, qual);
275 int sys_acl_set_access_bits(SMB_ACL_ENTRY_T entry, uint32 bits)
277 SMB_ACL_PERMSET_T permset;
279 if ((rc = acl_get_permset(entry, &permset)) != 0)
282 return acl_set_permset(entry, permset);
285 int sys_acl_valid( SMB_ACL_T theacl )
289 return acl_valid(theacl, &entry);
292 int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
294 return acl_set_file((char *)name, acltype, theacl);
297 int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
299 return acl_set_fd(fd, ACL_TYPE_ACCESS, theacl);
302 int sys_acl_delete_def_file(const char *name)
304 return acl_delete_def_file((char *)name);
307 int sys_acl_free_acl(SMB_ACL_T the_acl)
309 return acl_free(the_acl);
312 int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype)
314 return acl_free_qualifier(qual, tagtype);
317 #elif defined(HAVE_UNIXWARE_ACLS) || defined(HAVE_SOLARIS_ACLS)
320 * Donated by Michael Davidson <md@sco.COM> for UnixWare / OpenUNIX.
321 * Modified by Toomas Soome <tsoome@ut.ee> for Solaris.
325 * Note that while this code implements sufficient functionality
326 * to support the sys_acl_* interfaces it does not provide all
327 * of the semantics of the POSIX ACL interfaces.
329 * In particular, an ACL entry descriptor (SMB_ACL_ENTRY_T) returned
330 * from a call to sys_acl_get_entry() should not be assumed to be
331 * valid after calling any of the following functions, which may
332 * reorder the entries in the ACL.
340 * The only difference between Solaris and UnixWare / OpenUNIX is
341 * that the #defines for the ACL operations have different names
343 #if defined(HAVE_UNIXWARE_ACLS)
345 #define SETACL ACL_SET
346 #define GETACL ACL_GET
347 #define GETACLCNT ACL_CNT
352 int sys_acl_get_entry(SMB_ACL_T acl_d, int entry_id, SMB_ACL_ENTRY_T *entry_p)
354 if (entry_id != SMB_ACL_FIRST_ENTRY && entry_id != SMB_ACL_NEXT_ENTRY) {
359 if (entry_p == NULL) {
364 if (entry_id == SMB_ACL_FIRST_ENTRY) {
368 if (acl_d->next < 0) {
373 if (acl_d->next >= acl_d->count) {
377 *entry_p = &acl_d->acl[acl_d->next++];
382 int sys_acl_get_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *type_p)
384 *type_p = entry_d->a_type;
389 void *sys_acl_get_qualifier(SMB_ACL_ENTRY_T entry_d)
391 if (entry_d->a_type != SMB_ACL_USER
392 && entry_d->a_type != SMB_ACL_GROUP) {
397 return &entry_d->a_id;
401 * There is no way of knowing what size the ACL returned by
402 * GETACL will be unless you first call GETACLCNT which means
403 * making an additional system call.
405 * In the hope of avoiding the cost of the additional system
406 * call in most cases, we initially allocate enough space for
407 * an ACL with INITIAL_ACL_SIZE entries. If this turns out to
408 * be too small then we use GETACLCNT to find out the actual
409 * size, reallocate the ACL buffer, and then call GETACL again.
412 #define INITIAL_ACL_SIZE 16
414 SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type)
417 int count; /* # of ACL entries allocated */
418 int naccess; /* # of access ACL entries */
419 int ndefault; /* # of default ACL entries */
421 if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) {
426 count = INITIAL_ACL_SIZE;
427 if ((acl_d = sys_acl_init(count)) == NULL) {
432 * If there isn't enough space for the ACL entries we use
433 * GETACLCNT to determine the actual number of ACL entries
434 * reallocate and try again. This is in a loop because it
435 * is possible that someone else could modify the ACL and
436 * increase the number of entries between the call to
437 * GETACLCNT and the call to GETACL.
439 while ((count = acl(path_p, GETACL, count, &acl_d->acl[0])) < 0
440 && errno == ENOSPC) {
442 sys_acl_free_acl(acl_d);
444 if ((count = acl(path_p, GETACLCNT, 0, NULL)) < 0) {
448 if ((acl_d = sys_acl_init(count)) == NULL) {
454 sys_acl_free_acl(acl_d);
459 * calculate the number of access and default ACL entries
461 * Note: we assume that the acl() system call returned a
462 * well formed ACL which is sorted so that all of the
463 * access ACL entries preceed any default ACL entries
465 for (naccess = 0; naccess < count; naccess++) {
466 if (acl_d->acl[naccess].a_type & ACL_DEFAULT)
469 ndefault = count - naccess;
472 * if the caller wants the default ACL we have to copy
473 * the entries down to the start of the acl[] buffer
474 * and mask out the ACL_DEFAULT flag from the type field
476 if (type == SMB_ACL_TYPE_DEFAULT) {
479 for (i = 0, j = naccess; i < ndefault; i++, j++) {
480 acl_d->acl[i] = acl_d->acl[j];
481 acl_d->acl[i].a_type &= ~ACL_DEFAULT;
484 acl_d->count = ndefault;
486 acl_d->count = naccess;
493 SMB_ACL_T sys_acl_get_fd(int fd)
496 int count; /* # of ACL entries allocated */
497 int naccess; /* # of access ACL entries */
499 count = INITIAL_ACL_SIZE;
500 if ((acl_d = sys_acl_init(count)) == NULL) {
504 while ((count = facl(fd, GETACL, count, &acl_d->acl[0])) < 0
505 && errno == ENOSPC) {
507 sys_acl_free_acl(acl_d);
509 if ((count = facl(fd, GETACLCNT, 0, NULL)) < 0) {
513 if ((acl_d = sys_acl_init(count)) == NULL) {
519 sys_acl_free_acl(acl_d);
524 * calculate the number of access ACL entries
526 for (naccess = 0; naccess < count; naccess++) {
527 if (acl_d->acl[naccess].a_type & ACL_DEFAULT)
531 acl_d->count = naccess;
537 int sys_acl_get_access_bits(SMB_ACL_ENTRY_T entry_d, uint32 *bits)
539 *bits = entry_d->a_perm;
543 SMB_ACL_T sys_acl_init(int count)
553 * note that since the definition of the structure pointed
554 * to by the SMB_ACL_T includes the first element of the
555 * acl[] array, this actually allocates an ACL with room
556 * for (count+1) entries
558 if ((a = (SMB_ACL_T)SMB_MALLOC(sizeof(struct SMB_ACL_T) + count * sizeof(struct acl))) == NULL) {
571 int sys_acl_create_entry(SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p)
574 SMB_ACL_ENTRY_T entry_d;
576 if (acl_p == NULL || entry_p == NULL || (acl_d = *acl_p) == NULL) {
581 if (acl_d->count >= acl_d->size) {
586 entry_d = &acl_d->acl[acl_d->count++];
595 int sys_acl_set_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T tag_type)
599 case SMB_ACL_USER_OBJ:
601 case SMB_ACL_GROUP_OBJ:
604 entry_d->a_type = tag_type;
614 int sys_acl_set_qualifier(SMB_ACL_ENTRY_T entry_d, void *qual_p)
616 if (entry_d->a_type != SMB_ACL_GROUP
617 && entry_d->a_type != SMB_ACL_USER) {
622 entry_d->a_id = *((id_t *)qual_p);
627 int sys_acl_set_access_bits(SMB_ACL_ENTRY_T entry_d, uint32 bits)
629 entry_d->a_perm = bits;
634 * sort the ACL and check it for validity
636 * if it's a minimal ACL with only 4 entries then we
637 * need to recalculate the mask permissions to make
638 * sure that they are the same as the GROUP_OBJ
639 * permissions as required by the UnixWare acl() system call.
641 * (note: since POSIX allows minimal ACLs which only contain
642 * 3 entries - ie there is no mask entry - we should, in theory,
643 * check for this and add a mask entry if necessary - however
644 * we "know" that the caller of this interface always specifies
645 * a mask so, in practice "this never happens" (tm) - if it *does*
646 * happen aclsort() will fail and return an error and someone will
647 * have to fix it ...)
650 static int acl_sort(SMB_ACL_T acl_d)
652 int fixmask = (acl_d->count <= 4);
654 if (aclsort(acl_d->count, fixmask, acl_d->acl) != 0) {
661 int sys_acl_valid(SMB_ACL_T acl_d)
663 return acl_sort(acl_d);
666 int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d)
671 struct acl *acl_buf = NULL;
674 if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) {
679 if (acl_sort(acl_d) != 0) {
683 acl_p = &acl_d->acl[0];
684 acl_count = acl_d->count;
687 * if it's a directory there is extra work to do
688 * since the acl() system call will replace both
689 * the access ACLs and the default ACLs (if any)
691 if (stat(name, &s) != 0) {
694 if (S_ISDIR(s.st_mode)) {
700 if (type == SMB_ACL_TYPE_ACCESS) {
702 def_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_DEFAULT);
706 acc_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_ACCESS);
709 if (tmp_acl == NULL) {
714 * allocate a temporary buffer for the complete ACL
716 acl_count = acc_acl->count + def_acl->count;
717 acl_p = acl_buf = SMB_MALLOC_ARRAY(struct acl, acl_count);
719 if (acl_buf == NULL) {
720 sys_acl_free_acl(tmp_acl);
726 * copy the access control and default entries into the buffer
728 memcpy(&acl_buf[0], &acc_acl->acl[0],
729 acc_acl->count * sizeof(acl_buf[0]));
731 memcpy(&acl_buf[acc_acl->count], &def_acl->acl[0],
732 def_acl->count * sizeof(acl_buf[0]));
735 * set the ACL_DEFAULT flag on the default entries
737 for (i = acc_acl->count; i < acl_count; i++) {
738 acl_buf[i].a_type |= ACL_DEFAULT;
741 sys_acl_free_acl(tmp_acl);
743 } else if (type != SMB_ACL_TYPE_ACCESS) {
748 ret = acl(name, SETACL, acl_count, acl_p);
755 int sys_acl_set_fd(int fd, SMB_ACL_T acl_d)
757 if (acl_sort(acl_d) != 0) {
761 return facl(fd, SETACL, acl_d->count, &acl_d->acl[0]);
764 int sys_acl_delete_def_file(const char *path)
770 * fetching the access ACL and rewriting it has
771 * the effect of deleting the default ACL
773 if ((acl_d = sys_acl_get_file(path, SMB_ACL_TYPE_ACCESS)) == NULL) {
777 ret = acl(path, SETACL, acl_d->count, acl_d->acl);
779 sys_acl_free_acl(acl_d);
784 int sys_acl_free_acl(SMB_ACL_T acl_d)
790 int sys_acl_free_qualifier(UNUSED(void *qual), UNUSED(SMB_ACL_TAG_T tagtype))
795 #elif defined(HAVE_HPUX_ACLS)
799 * Based on the Solaris/SCO code - with modifications.
803 * Note that while this code implements sufficient functionality
804 * to support the sys_acl_* interfaces it does not provide all
805 * of the semantics of the POSIX ACL interfaces.
807 * In particular, an ACL entry descriptor (SMB_ACL_ENTRY_T) returned
808 * from a call to sys_acl_get_entry() should not be assumed to be
809 * valid after calling any of the following functions, which may
810 * reorder the entries in the ACL.
817 /* This checks if the POSIX ACL system call is defined */
818 /* which basically corresponds to whether JFS 3.3 or */
819 /* higher is installed. If acl() was called when it */
820 /* isn't defined, it causes the process to core dump */
821 /* so it is important to check this and avoid acl() */
822 /* calls if it isn't there. */
824 static BOOL hpux_acl_call_presence(void)
830 static BOOL already_checked=0;
836 ret_val = shl_findsym(&handle, "acl", TYPE_PROCEDURE, &value);
839 DEBUG(5, ("hpux_acl_call_presence: shl_findsym() returned %d, errno = %d, error %s\n",
840 ret_val, errno, strerror(errno)));
841 DEBUG(5,("hpux_acl_call_presence: acl() system call is not present. Check if you have JFS 3.3 and above?\n"));
845 DEBUG(10,("hpux_acl_call_presence: acl() system call is present. We have JFS 3.3 or above \n"));
847 already_checked = True;
851 int sys_acl_get_entry(SMB_ACL_T acl_d, int entry_id, SMB_ACL_ENTRY_T *entry_p)
853 if (entry_id != SMB_ACL_FIRST_ENTRY && entry_id != SMB_ACL_NEXT_ENTRY) {
858 if (entry_p == NULL) {
863 if (entry_id == SMB_ACL_FIRST_ENTRY) {
867 if (acl_d->next < 0) {
872 if (acl_d->next >= acl_d->count) {
876 *entry_p = &acl_d->acl[acl_d->next++];
881 int sys_acl_get_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *type_p)
883 *type_p = entry_d->a_type;
888 void *sys_acl_get_qualifier(SMB_ACL_ENTRY_T entry_d)
890 if (entry_d->a_type != SMB_ACL_USER
891 && entry_d->a_type != SMB_ACL_GROUP) {
896 return &entry_d->a_id;
900 * There is no way of knowing what size the ACL returned by
901 * ACL_GET will be unless you first call ACL_CNT which means
902 * making an additional system call.
904 * In the hope of avoiding the cost of the additional system
905 * call in most cases, we initially allocate enough space for
906 * an ACL with INITIAL_ACL_SIZE entries. If this turns out to
907 * be too small then we use ACL_CNT to find out the actual
908 * size, reallocate the ACL buffer, and then call ACL_GET again.
911 #define INITIAL_ACL_SIZE 16
913 SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type)
916 int count; /* # of ACL entries allocated */
917 int naccess; /* # of access ACL entries */
918 int ndefault; /* # of default ACL entries */
920 if(hpux_acl_call_presence() == False) {
921 /* Looks like we don't have the acl() system call on HPUX.
922 * May be the system doesn't have the latest version of JFS.
927 if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) {
932 count = INITIAL_ACL_SIZE;
933 if ((acl_d = sys_acl_init(count)) == NULL) {
938 * If there isn't enough space for the ACL entries we use
939 * ACL_CNT to determine the actual number of ACL entries
940 * reallocate and try again. This is in a loop because it
941 * is possible that someone else could modify the ACL and
942 * increase the number of entries between the call to
943 * ACL_CNT and the call to ACL_GET.
945 while ((count = acl(path_p, ACL_GET, count, &acl_d->acl[0])) < 0 && errno == ENOSPC) {
947 sys_acl_free_acl(acl_d);
949 if ((count = acl(path_p, ACL_CNT, 0, NULL)) < 0) {
953 if ((acl_d = sys_acl_init(count)) == NULL) {
959 sys_acl_free_acl(acl_d);
964 * calculate the number of access and default ACL entries
966 * Note: we assume that the acl() system call returned a
967 * well formed ACL which is sorted so that all of the
968 * access ACL entries preceed any default ACL entries
970 for (naccess = 0; naccess < count; naccess++) {
971 if (acl_d->acl[naccess].a_type & ACL_DEFAULT)
974 ndefault = count - naccess;
977 * if the caller wants the default ACL we have to copy
978 * the entries down to the start of the acl[] buffer
979 * and mask out the ACL_DEFAULT flag from the type field
981 if (type == SMB_ACL_TYPE_DEFAULT) {
984 for (i = 0, j = naccess; i < ndefault; i++, j++) {
985 acl_d->acl[i] = acl_d->acl[j];
986 acl_d->acl[i].a_type &= ~ACL_DEFAULT;
989 acl_d->count = ndefault;
991 acl_d->count = naccess;
998 SMB_ACL_T sys_acl_get_fd(int fd)
1001 * HPUX doesn't have the facl call. Fake it using the path.... JRA.
1004 files_struct *fsp = file_find_fd(fd);
1012 * We know we're in the same conn context. So we
1013 * can use the relative path.
1016 return sys_acl_get_file(fsp->fsp_name, SMB_ACL_TYPE_ACCESS);
1020 int sys_acl_get_access_bits(SMB_ACL_ENTRY_T entry_d, uint32 *bits)
1022 *bits = entry_d->a_perm;
1027 SMB_ACL_T sys_acl_init(int count)
1037 * note that since the definition of the structure pointed
1038 * to by the SMB_ACL_T includes the first element of the
1039 * acl[] array, this actually allocates an ACL with room
1040 * for (count+1) entries
1042 if ((a = SMB_MALLOC(sizeof(struct SMB_ACL_T) + count * sizeof(struct acl))) == NULL) {
1047 a->size = count + 1;
1055 int sys_acl_create_entry(SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p)
1058 SMB_ACL_ENTRY_T entry_d;
1060 if (acl_p == NULL || entry_p == NULL || (acl_d = *acl_p) == NULL) {
1065 if (acl_d->count >= acl_d->size) {
1070 entry_d = &acl_d->acl[acl_d->count++];
1071 entry_d->a_type = 0;
1073 entry_d->a_perm = 0;
1079 int sys_acl_set_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T tag_type)
1083 case SMB_ACL_USER_OBJ:
1085 case SMB_ACL_GROUP_OBJ:
1088 entry_d->a_type = tag_type;
1098 int sys_acl_set_qualifier(SMB_ACL_ENTRY_T entry_d, void *qual_p)
1100 if (entry_d->a_type != SMB_ACL_GROUP
1101 && entry_d->a_type != SMB_ACL_USER) {
1106 entry_d->a_id = *((id_t *)qual_p);
1111 int sys_acl_set_access_bits(SMB_ACL_ENTRY_T entry_d, uint32 bits)
1113 entry_d->a_perm = bits;
1118 /* Structure to capture the count for each type of ACE. */
1120 struct hpux_acl_types {
1129 int n_def_group_obj;
1133 int n_def_other_obj;
1136 int n_def_class_obj;
1142 * Counts the different number of objects in a given array of ACL
1146 * acl_count - Count of ACLs in the array of ACL strucutres.
1147 * aclp - Array of ACL structures.
1148 * acl_type_count - Pointer to acl_types structure. Should already be
1152 * acl_type_count - This structure is filled up with counts of various
1156 static int hpux_count_obj(int acl_count, struct acl *aclp, struct hpux_acl_types *acl_type_count)
1160 memset(acl_type_count, 0, sizeof(struct hpux_acl_types));
1162 for(i=0;i<acl_count;i++) {
1163 switch(aclp[i].a_type) {
1165 acl_type_count->n_user++;
1168 acl_type_count->n_user_obj++;
1171 acl_type_count->n_def_user_obj++;
1174 acl_type_count->n_group++;
1177 acl_type_count->n_group_obj++;
1180 acl_type_count->n_def_group_obj++;
1183 acl_type_count->n_other_obj++;
1186 acl_type_count->n_def_other_obj++;
1189 acl_type_count->n_class_obj++;
1192 acl_type_count->n_def_class_obj++;
1195 acl_type_count->n_def_user++;
1198 acl_type_count->n_def_group++;
1201 acl_type_count->n_illegal_obj++;
1207 /* swap_acl_entries: Swaps two ACL entries.
1209 * Inputs: aclp0, aclp1 - ACL entries to be swapped.
1212 static void hpux_swap_acl_entries(struct acl *aclp0, struct acl *aclp1)
1214 struct acl temp_acl;
1216 temp_acl.a_type = aclp0->a_type;
1217 temp_acl.a_id = aclp0->a_id;
1218 temp_acl.a_perm = aclp0->a_perm;
1220 aclp0->a_type = aclp1->a_type;
1221 aclp0->a_id = aclp1->a_id;
1222 aclp0->a_perm = aclp1->a_perm;
1224 aclp1->a_type = temp_acl.a_type;
1225 aclp1->a_id = temp_acl.a_id;
1226 aclp1->a_perm = temp_acl.a_perm;
1229 /* prohibited_duplicate_type
1230 * Identifies if given ACL type can have duplicate entries or
1233 * Inputs: acl_type - ACL Type.
1239 * True - If the ACL type matches any of the prohibited types.
1240 * False - If the ACL type doesn't match any of the prohibited types.
1243 static BOOL hpux_prohibited_duplicate_type(int acl_type)
1256 /* get_needed_class_perm
1257 * Returns the permissions of a ACL structure only if the ACL
1258 * type matches one of the pre-determined types for computing
1259 * CLASS_OBJ permissions.
1261 * Inputs: aclp - Pointer to ACL structure.
1264 static int hpux_get_needed_class_perm(struct acl *aclp)
1266 switch(aclp->a_type) {
1276 return aclp->a_perm;
1282 /* acl_sort for HPUX.
1283 * Sorts the array of ACL structures as per the description in
1284 * aclsort man page. Refer to aclsort man page for more details
1288 * acl_count - Count of ACLs in the array of ACL structures.
1289 * calclass - If this is not zero, then we compute the CLASS_OBJ
1291 * aclp - Array of ACL structures.
1295 * aclp - Sorted array of ACL structures.
1299 * Returns 0 for success -1 for failure. Prints a message to the Samba
1300 * debug log in case of failure.
1303 static int hpux_acl_sort(int acl_count, int calclass, struct acl *aclp)
1305 #if !defined(HAVE_HPUX_ACLSORT)
1307 * The aclsort() system call is availabe on the latest HPUX General
1308 * Patch Bundles. So for HPUX, we developed our version of acl_sort
1309 * function. Because, we don't want to update to a new
1310 * HPUX GR bundle just for aclsort() call.
1313 struct hpux_acl_types acl_obj_count;
1314 int n_class_obj_perm = 0;
1318 DEBUG(10,("Zero acl count passed. Returning Success\n"));
1323 DEBUG(0,("Null ACL pointer in hpux_acl_sort. Returning Failure. \n"));
1327 /* Count different types of ACLs in the ACLs array */
1329 hpux_count_obj(acl_count, aclp, &acl_obj_count);
1331 /* There should be only one entry each of type USER_OBJ, GROUP_OBJ,
1332 * CLASS_OBJ and OTHER_OBJ
1335 if( (acl_obj_count.n_user_obj != 1) ||
1336 (acl_obj_count.n_group_obj != 1) ||
1337 (acl_obj_count.n_class_obj != 1) ||
1338 (acl_obj_count.n_other_obj != 1)
1340 DEBUG(0,("hpux_acl_sort: More than one entry or no entries for \
1341 USER OBJ or GROUP_OBJ or OTHER_OBJ or CLASS_OBJ\n"));
1345 /* If any of the default objects are present, there should be only
1349 if( (acl_obj_count.n_def_user_obj > 1) || (acl_obj_count.n_def_group_obj > 1) ||
1350 (acl_obj_count.n_def_other_obj > 1) || (acl_obj_count.n_def_class_obj > 1) ) {
1351 DEBUG(0,("hpux_acl_sort: More than one entry for DEF_CLASS_OBJ \
1352 or DEF_USER_OBJ or DEF_GROUP_OBJ or DEF_OTHER_OBJ\n"));
1356 /* We now have proper number of OBJ and DEF_OBJ entries. Now sort the acl
1359 * Sorting crieteria - First sort by ACL type. If there are multiple entries of
1360 * same ACL type, sort by ACL id.
1362 * I am using the trival kind of sorting method here because, performance isn't
1363 * really effected by the ACLs feature. More over there aren't going to be more
1364 * than 17 entries on HPUX.
1367 for(i=0; i<acl_count;i++) {
1368 for (j=i+1; j<acl_count; j++) {
1369 if( aclp[i].a_type > aclp[j].a_type ) {
1370 /* ACL entries out of order, swap them */
1372 hpux_swap_acl_entries((aclp+i), (aclp+j));
1374 } else if ( aclp[i].a_type == aclp[j].a_type ) {
1376 /* ACL entries of same type, sort by id */
1378 if(aclp[i].a_id > aclp[j].a_id) {
1379 hpux_swap_acl_entries((aclp+i), (aclp+j));
1380 } else if (aclp[i].a_id == aclp[j].a_id) {
1381 /* We have a duplicate entry. */
1382 if(hpux_prohibited_duplicate_type(aclp[i].a_type)) {
1383 DEBUG(0, ("hpux_acl_sort: Duplicate entry: Type(hex): %x Id: %d\n",
1384 aclp[i].a_type, aclp[i].a_id));
1393 /* set the class obj permissions to the computed one. */
1395 int n_class_obj_index = -1;
1397 for(i=0;i<acl_count;i++) {
1398 n_class_obj_perm |= hpux_get_needed_class_perm((aclp+i));
1400 if(aclp[i].a_type == CLASS_OBJ)
1401 n_class_obj_index = i;
1403 aclp[n_class_obj_index].a_perm = n_class_obj_perm;
1408 return aclsort(acl_count, calclass, aclp);
1413 * sort the ACL and check it for validity
1415 * if it's a minimal ACL with only 4 entries then we
1416 * need to recalculate the mask permissions to make
1417 * sure that they are the same as the GROUP_OBJ
1418 * permissions as required by the UnixWare acl() system call.
1420 * (note: since POSIX allows minimal ACLs which only contain
1421 * 3 entries - ie there is no mask entry - we should, in theory,
1422 * check for this and add a mask entry if necessary - however
1423 * we "know" that the caller of this interface always specifies
1424 * a mask so, in practice "this never happens" (tm) - if it *does*
1425 * happen aclsort() will fail and return an error and someone will
1426 * have to fix it ...)
1429 static int acl_sort(SMB_ACL_T acl_d)
1431 int fixmask = (acl_d->count <= 4);
1433 if (hpux_acl_sort(acl_d->count, fixmask, acl_d->acl) != 0) {
1440 int sys_acl_valid(SMB_ACL_T acl_d)
1442 return acl_sort(acl_d);
1445 int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d)
1450 struct acl *acl_buf = NULL;
1453 if(hpux_acl_call_presence() == False) {
1454 /* Looks like we don't have the acl() system call on HPUX.
1455 * May be the system doesn't have the latest version of JFS.
1461 if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) {
1466 if (acl_sort(acl_d) != 0) {
1470 acl_p = &acl_d->acl[0];
1471 acl_count = acl_d->count;
1474 * if it's a directory there is extra work to do
1475 * since the acl() system call will replace both
1476 * the access ACLs and the default ACLs (if any)
1478 if (stat(name, &s) != 0) {
1481 if (S_ISDIR(s.st_mode)) {
1487 if (type == SMB_ACL_TYPE_ACCESS) {
1489 def_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_DEFAULT);
1493 acc_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_ACCESS);
1496 if (tmp_acl == NULL) {
1501 * allocate a temporary buffer for the complete ACL
1503 acl_count = acc_acl->count + def_acl->count;
1504 acl_p = acl_buf = SMB_MALLOC_ARRAY(struct acl, acl_count);
1506 if (acl_buf == NULL) {
1507 sys_acl_free_acl(tmp_acl);
1513 * copy the access control and default entries into the buffer
1515 memcpy(&acl_buf[0], &acc_acl->acl[0],
1516 acc_acl->count * sizeof(acl_buf[0]));
1518 memcpy(&acl_buf[acc_acl->count], &def_acl->acl[0],
1519 def_acl->count * sizeof(acl_buf[0]));
1522 * set the ACL_DEFAULT flag on the default entries
1524 for (i = acc_acl->count; i < acl_count; i++) {
1525 acl_buf[i].a_type |= ACL_DEFAULT;
1528 sys_acl_free_acl(tmp_acl);
1530 } else if (type != SMB_ACL_TYPE_ACCESS) {
1535 ret = acl(name, ACL_SET, acl_count, acl_p);
1545 int sys_acl_set_fd(int fd, SMB_ACL_T acl_d)
1548 * HPUX doesn't have the facl call. Fake it using the path.... JRA.
1551 files_struct *fsp = file_find_fd(fd);
1558 if (acl_sort(acl_d) != 0) {
1563 * We know we're in the same conn context. So we
1564 * can use the relative path.
1567 return sys_acl_set_file(fsp->fsp_name, SMB_ACL_TYPE_ACCESS, acl_d);
1571 int sys_acl_delete_def_file(const char *path)
1577 * fetching the access ACL and rewriting it has
1578 * the effect of deleting the default ACL
1580 if ((acl_d = sys_acl_get_file(path, SMB_ACL_TYPE_ACCESS)) == NULL) {
1584 ret = acl(path, ACL_SET, acl_d->count, acl_d->acl);
1586 sys_acl_free_acl(acl_d);
1591 int sys_acl_free_acl(SMB_ACL_T acl_d)
1597 int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype)
1602 #elif defined(HAVE_IRIX_ACLS)
1604 int sys_acl_get_entry(SMB_ACL_T acl_d, int entry_id, SMB_ACL_ENTRY_T *entry_p)
1606 if (entry_id != SMB_ACL_FIRST_ENTRY && entry_id != SMB_ACL_NEXT_ENTRY) {
1611 if (entry_p == NULL) {
1616 if (entry_id == SMB_ACL_FIRST_ENTRY) {
1620 if (acl_d->next < 0) {
1625 if (acl_d->next >= acl_d->aclp->acl_cnt) {
1629 *entry_p = &acl_d->aclp->acl_entry[acl_d->next++];
1634 int sys_acl_get_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *type_p)
1636 *type_p = entry_d->ae_tag;
1641 void *sys_acl_get_qualifier(SMB_ACL_ENTRY_T entry_d)
1643 if (entry_d->ae_tag != SMB_ACL_USER
1644 && entry_d->ae_tag != SMB_ACL_GROUP) {
1649 return &entry_d->ae_id;
1652 SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type)
1656 if ((a = SMB_MALLOC_P(struct SMB_ACL_T)) == NULL) {
1660 if ((a->aclp = acl_get_file(path_p, type)) == NULL) {
1670 SMB_ACL_T sys_acl_get_fd(int fd)
1674 if ((a = SMB_MALLOC_P(struct SMB_ACL_T)) == NULL) {
1678 if ((a->aclp = acl_get_fd(fd)) == NULL) {
1688 int sys_acl_get_access_bits(SMB_ACL_ENTRY_T entry_d, uint32 *bits)
1690 *bits = entry_d->ae_perm;
1695 SMB_ACL_T sys_acl_init(int count)
1704 if ((a = SMB_MALLOC(sizeof(struct SMB_ACL_T) + sizeof(struct acl))) == NULL) {
1710 a->freeaclp = False;
1711 a->aclp = (struct acl *)(&a->aclp + sizeof(struct acl *));
1712 a->aclp->acl_cnt = 0;
1718 int sys_acl_create_entry(SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p)
1721 SMB_ACL_ENTRY_T entry_d;
1723 if (acl_p == NULL || entry_p == NULL || (acl_d = *acl_p) == NULL) {
1728 if (acl_d->aclp->acl_cnt >= ACL_MAX_ENTRIES) {
1733 entry_d = &acl_d->aclp->acl_entry[acl_d->aclp->acl_cnt++];
1734 entry_d->ae_tag = 0;
1736 entry_d->ae_perm = 0;
1742 int sys_acl_set_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T tag_type)
1746 case SMB_ACL_USER_OBJ:
1748 case SMB_ACL_GROUP_OBJ:
1751 entry_d->ae_tag = tag_type;
1761 int sys_acl_set_qualifier(SMB_ACL_ENTRY_T entry_d, void *qual_p)
1763 if (entry_d->ae_tag != SMB_ACL_GROUP
1764 && entry_d->ae_tag != SMB_ACL_USER) {
1769 entry_d->ae_id = *((id_t *)qual_p);
1774 int sys_acl_set_access_bits(SMB_ACL_ENTRY_T entry_d, uint32 bits)
1776 entry_d->ae_perm = bits;
1781 int sys_acl_valid(SMB_ACL_T acl_d)
1783 return acl_valid(acl_d->aclp);
1786 int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d)
1788 return acl_set_file(name, type, acl_d->aclp);
1791 int sys_acl_set_fd(int fd, SMB_ACL_T acl_d)
1793 return acl_set_fd(fd, acl_d->aclp);
1796 int sys_acl_delete_def_file(const char *name)
1798 return acl_delete_def_file(name);
1801 int sys_acl_free_acl(SMB_ACL_T acl_d)
1803 if (acl_d->freeaclp) {
1804 acl_free(acl_d->aclp);
1810 int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype)
1815 #elif defined(HAVE_AIX_ACLS)
1817 /* Donated by Medha Date, mdate@austin.ibm.com, for IBM */
1819 int sys_acl_get_entry( SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
1821 struct acl_entry_link *link;
1822 struct new_acl_entry *entry;
1825 DEBUG(10,("This is the count: %d\n",theacl->count));
1827 /* Check if count was previously set to -1. *
1828 * If it was, that means we reached the end *
1829 * of the acl last time. */
1830 if(theacl->count == -1)
1834 /* To get to the next acl, traverse linked list until index *
1835 * of acl matches the count we are keeping. This count is *
1836 * incremented each time we return an acl entry. */
1838 for(keep_going = 0; keep_going < theacl->count; keep_going++)
1841 entry = *entry_p = link->entryp;
1843 DEBUG(10,("*entry_p is %d\n",entry_p));
1844 DEBUG(10,("*entry_p->ace_access is %d\n",entry->ace_access));
1846 /* Increment count */
1848 if(link->nextp == NULL)
1854 int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
1856 /* Initialize tag type */
1859 DEBUG(10,("the tagtype is %d\n",entry_d->ace_id->id_type));
1861 /* Depending on what type of entry we have, *
1862 * return tag type. */
1863 switch(entry_d->ace_id->id_type) {
1865 *tag_type_p = SMB_ACL_USER;
1868 *tag_type_p = SMB_ACL_GROUP;
1871 case SMB_ACL_USER_OBJ:
1872 case SMB_ACL_GROUP_OBJ:
1874 *tag_type_p = entry_d->ace_id->id_type;
1884 int sys_acl_get_access_bits(SMB_ACL_ENTRY_T entry_d, uint32 *bits)
1886 SMB_ACL_PERMSET_T permset;
1887 DEBUG(10,("Starting AIX sys_acl_get_access_bits\n"));
1888 permset = &entry_d->ace_access;
1889 DEBUG(10,("*permset is %d\n",*permset));
1890 *bits = (*permset & S_IRUSR ? 4 : 0)
1891 | (*permset & S_IWUSR ? 2 : 0)
1892 | (*permset & S_IXUSR ? 1 : 0);
1893 DEBUG(10,("Ending AIX sys_acl_get_access_bits\n"));
1897 void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d)
1899 return(entry_d->ace_id->id_data);
1902 SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
1904 struct acl *file_acl = (struct acl *)NULL;
1905 struct acl_entry *acl_entry;
1906 struct new_acl_entry *new_acl_entry;
1908 struct acl_entry_link *acl_entry_link;
1909 struct acl_entry_link *acl_entry_link_head;
1914 /* AIX has no DEFAULT */
1915 if ( type == SMB_ACL_TYPE_DEFAULT ) {
1920 /* Get the acl using statacl */
1922 DEBUG(10,("Entering sys_acl_get_file\n"));
1923 DEBUG(10,("path_p is %s\n",path_p));
1925 file_acl = (struct acl *)SMB_MALLOC(BUFSIZ);
1927 if(file_acl == NULL) {
1929 DEBUG(0,("Error in AIX sys_acl_get_file: %d\n",errno));
1933 memset(file_acl,0,BUFSIZ);
1935 rc = statacl((char *)path_p,0,file_acl,BUFSIZ);
1937 DEBUG(0,("statacl returned %d with errno %d\n",rc,errno));
1938 SAFE_FREE(file_acl);
1942 DEBUG(10,("Got facl and returned it\n"));
1944 /* Point to the first acl entry in the acl */
1945 acl_entry = file_acl->acl_ext;
1947 /* Begin setting up the head of the linked list *
1948 * that will be used for the storing the acl *
1949 * in a way that is useful for the posix_acls.c *
1952 acl_entry_link_head = acl_entry_link = sys_acl_init(0);
1953 if(acl_entry_link_head == NULL)
1956 acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
1957 if(acl_entry_link->entryp == NULL) {
1958 SAFE_FREE(file_acl);
1960 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
1964 DEBUG(10,("acl_entry is %d\n",acl_entry));
1965 DEBUG(10,("acl_last(file_acl) id %d\n",acl_last(file_acl)));
1967 /* Check if the extended acl bit is on. *
1968 * If it isn't, do not show the *
1969 * contents of the acl since AIX intends *
1970 * the extended info to remain unused */
1972 if(file_acl->acl_mode & S_IXACL){
1973 /* while we are not pointing to the very end */
1974 while(acl_entry < acl_last(file_acl)) {
1975 /* before we malloc anything, make sure this is */
1976 /* a valid acl entry and one that we want to map */
1977 idp = id_nxt(acl_entry->ace_id);
1978 if((acl_entry->ace_type == ACC_SPECIFY ||
1979 (acl_entry->ace_type == ACC_PERMIT)) && (idp != id_last(acl_entry))) {
1980 acl_entry = acl_nxt(acl_entry);
1984 idp = acl_entry->ace_id;
1986 /* Check if this is the first entry in the linked list. *
1987 * The first entry needs to keep prevp pointing to NULL *
1988 * and already has entryp allocated. */
1990 if(acl_entry_link_head->count != 0) {
1991 acl_entry_link->nextp = SMB_MALLOC_P(struct acl_entry_link);
1993 if(acl_entry_link->nextp == NULL) {
1994 SAFE_FREE(file_acl);
1996 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
2000 acl_entry_link->nextp->prevp = acl_entry_link;
2001 acl_entry_link = acl_entry_link->nextp;
2002 acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
2003 if(acl_entry_link->entryp == NULL) {
2004 SAFE_FREE(file_acl);
2006 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
2009 acl_entry_link->nextp = NULL;
2012 acl_entry_link->entryp->ace_len = acl_entry->ace_len;
2014 /* Don't really need this since all types are going *
2015 * to be specified but, it's better than leaving it 0 */
2017 acl_entry_link->entryp->ace_type = acl_entry->ace_type;
2019 acl_entry_link->entryp->ace_access = acl_entry->ace_access;
2021 memcpy(acl_entry_link->entryp->ace_id,idp,sizeof(struct ace_id));
2023 /* The access in the acl entries must be left shifted by *
2024 * three bites, because they will ultimately be compared *
2025 * to S_IRUSR, S_IWUSR, and S_IXUSR. */
2027 switch(acl_entry->ace_type){
2030 acl_entry_link->entryp->ace_access = acl_entry->ace_access;
2031 acl_entry_link->entryp->ace_access <<= 6;
2032 acl_entry_link_head->count++;
2035 /* Since there is no way to return a DENY acl entry *
2036 * change to PERMIT and then shift. */
2037 DEBUG(10,("acl_entry->ace_access is %d\n",acl_entry->ace_access));
2038 acl_entry_link->entryp->ace_access = ~acl_entry->ace_access & 7;
2039 DEBUG(10,("acl_entry_link->entryp->ace_access is %d\n",acl_entry_link->entryp->ace_access));
2040 acl_entry_link->entryp->ace_access <<= 6;
2041 acl_entry_link_head->count++;
2047 DEBUG(10,("acl_entry = %d\n",acl_entry));
2048 DEBUG(10,("The ace_type is %d\n",acl_entry->ace_type));
2050 acl_entry = acl_nxt(acl_entry);
2052 } /* end of if enabled */
2054 /* Since owner, group, other acl entries are not *
2055 * part of the acl entries in an acl, they must *
2056 * be dummied up to become part of the list. */
2058 for( i = 1; i < 4; i++) {
2059 DEBUG(10,("i is %d\n",i));
2060 if(acl_entry_link_head->count != 0) {
2061 acl_entry_link->nextp = SMB_MALLOC_P(struct acl_entry_link);
2062 if(acl_entry_link->nextp == NULL) {
2063 SAFE_FREE(file_acl);
2065 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
2069 acl_entry_link->nextp->prevp = acl_entry_link;
2070 acl_entry_link = acl_entry_link->nextp;
2071 acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
2072 if(acl_entry_link->entryp == NULL) {
2073 SAFE_FREE(file_acl);
2075 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
2080 acl_entry_link->nextp = NULL;
2082 new_acl_entry = acl_entry_link->entryp;
2083 idp = new_acl_entry->ace_id;
2085 new_acl_entry->ace_len = sizeof(struct acl_entry);
2086 new_acl_entry->ace_type = ACC_PERMIT;
2087 idp->id_len = sizeof(struct ace_id);
2088 DEBUG(10,("idp->id_len = %d\n",idp->id_len));
2089 memset(idp->id_data,0,sizeof(uid_t));
2093 new_acl_entry->ace_access = file_acl->g_access << 6;
2094 idp->id_type = SMB_ACL_GROUP_OBJ;
2098 new_acl_entry->ace_access = file_acl->o_access << 6;
2099 idp->id_type = SMB_ACL_OTHER;
2103 new_acl_entry->ace_access = file_acl->u_access << 6;
2104 idp->id_type = SMB_ACL_USER_OBJ;
2112 acl_entry_link_head->count++;
2113 DEBUG(10,("new_acl_entry->ace_access = %d\n",new_acl_entry->ace_access));
2116 acl_entry_link_head->count = 0;
2117 SAFE_FREE(file_acl);
2119 return(acl_entry_link_head);
2123 SMB_ACL_T sys_acl_get_fd(int fd)
2125 struct acl *file_acl = (struct acl *)NULL;
2126 struct acl_entry *acl_entry;
2127 struct new_acl_entry *new_acl_entry;
2129 struct acl_entry_link *acl_entry_link;
2130 struct acl_entry_link *acl_entry_link_head;
2135 /* Get the acl using fstatacl */
2137 DEBUG(10,("Entering sys_acl_get_fd\n"));
2138 DEBUG(10,("fd is %d\n",fd));
2139 file_acl = (struct acl *)SMB_MALLOC(BUFSIZ);
2141 if(file_acl == NULL) {
2143 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2147 memset(file_acl,0,BUFSIZ);
2149 rc = fstatacl(fd,0,file_acl,BUFSIZ);
2151 DEBUG(0,("The fstatacl call returned %d with errno %d\n",rc,errno));
2152 SAFE_FREE(file_acl);
2156 DEBUG(10,("Got facl and returned it\n"));
2158 /* Point to the first acl entry in the acl */
2160 acl_entry = file_acl->acl_ext;
2161 /* Begin setting up the head of the linked list *
2162 * that will be used for the storing the acl *
2163 * in a way that is useful for the posix_acls.c *
2166 acl_entry_link_head = acl_entry_link = sys_acl_init(0);
2167 if(acl_entry_link_head == NULL){
2168 SAFE_FREE(file_acl);
2172 acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
2174 if(acl_entry_link->entryp == NULL) {
2176 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2177 SAFE_FREE(file_acl);
2181 DEBUG(10,("acl_entry is %d\n",acl_entry));
2182 DEBUG(10,("acl_last(file_acl) id %d\n",acl_last(file_acl)));
2184 /* Check if the extended acl bit is on. *
2185 * If it isn't, do not show the *
2186 * contents of the acl since AIX intends *
2187 * the extended info to remain unused */
2189 if(file_acl->acl_mode & S_IXACL){
2190 /* while we are not pointing to the very end */
2191 while(acl_entry < acl_last(file_acl)) {
2192 /* before we malloc anything, make sure this is */
2193 /* a valid acl entry and one that we want to map */
2195 idp = id_nxt(acl_entry->ace_id);
2196 if((acl_entry->ace_type == ACC_SPECIFY ||
2197 (acl_entry->ace_type == ACC_PERMIT)) && (idp != id_last(acl_entry))) {
2198 acl_entry = acl_nxt(acl_entry);
2202 idp = acl_entry->ace_id;
2204 /* Check if this is the first entry in the linked list. *
2205 * The first entry needs to keep prevp pointing to NULL *
2206 * and already has entryp allocated. */
2208 if(acl_entry_link_head->count != 0) {
2209 acl_entry_link->nextp = SMB_MALLOC_P(struct acl_entry_link);
2210 if(acl_entry_link->nextp == NULL) {
2212 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2213 SAFE_FREE(file_acl);
2216 acl_entry_link->nextp->prevp = acl_entry_link;
2217 acl_entry_link = acl_entry_link->nextp;
2218 acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
2219 if(acl_entry_link->entryp == NULL) {
2221 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2222 SAFE_FREE(file_acl);
2226 acl_entry_link->nextp = NULL;
2229 acl_entry_link->entryp->ace_len = acl_entry->ace_len;
2231 /* Don't really need this since all types are going *
2232 * to be specified but, it's better than leaving it 0 */
2234 acl_entry_link->entryp->ace_type = acl_entry->ace_type;
2235 acl_entry_link->entryp->ace_access = acl_entry->ace_access;
2237 memcpy(acl_entry_link->entryp->ace_id, idp, sizeof(struct ace_id));
2239 /* The access in the acl entries must be left shifted by *
2240 * three bites, because they will ultimately be compared *
2241 * to S_IRUSR, S_IWUSR, and S_IXUSR. */
2243 switch(acl_entry->ace_type){
2246 acl_entry_link->entryp->ace_access = acl_entry->ace_access;
2247 acl_entry_link->entryp->ace_access <<= 6;
2248 acl_entry_link_head->count++;
2251 /* Since there is no way to return a DENY acl entry *
2252 * change to PERMIT and then shift. */
2253 DEBUG(10,("acl_entry->ace_access is %d\n",acl_entry->ace_access));
2254 acl_entry_link->entryp->ace_access = ~acl_entry->ace_access & 7;
2255 DEBUG(10,("acl_entry_link->entryp->ace_access is %d\n",acl_entry_link->entryp->ace_access));
2256 acl_entry_link->entryp->ace_access <<= 6;
2257 acl_entry_link_head->count++;
2263 DEBUG(10,("acl_entry = %d\n",acl_entry));
2264 DEBUG(10,("The ace_type is %d\n",acl_entry->ace_type));
2266 acl_entry = acl_nxt(acl_entry);
2268 } /* end of if enabled */
2270 /* Since owner, group, other acl entries are not *
2271 * part of the acl entries in an acl, they must *
2272 * be dummied up to become part of the list. */
2274 for( i = 1; i < 4; i++) {
2275 DEBUG(10,("i is %d\n",i));
2276 if(acl_entry_link_head->count != 0){
2277 acl_entry_link->nextp = SMB_MALLOC_P(struct acl_entry_link);
2278 if(acl_entry_link->nextp == NULL) {
2280 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2281 SAFE_FREE(file_acl);
2285 acl_entry_link->nextp->prevp = acl_entry_link;
2286 acl_entry_link = acl_entry_link->nextp;
2287 acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
2289 if(acl_entry_link->entryp == NULL) {
2290 SAFE_FREE(file_acl);
2292 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2297 acl_entry_link->nextp = NULL;
2299 new_acl_entry = acl_entry_link->entryp;
2300 idp = new_acl_entry->ace_id;
2302 new_acl_entry->ace_len = sizeof(struct acl_entry);
2303 new_acl_entry->ace_type = ACC_PERMIT;
2304 idp->id_len = sizeof(struct ace_id);
2305 DEBUG(10,("idp->id_len = %d\n",idp->id_len));
2306 memset(idp->id_data,0,sizeof(uid_t));
2310 new_acl_entry->ace_access = file_acl->g_access << 6;
2311 idp->id_type = SMB_ACL_GROUP_OBJ;
2315 new_acl_entry->ace_access = file_acl->o_access << 6;
2316 idp->id_type = SMB_ACL_OTHER;
2320 new_acl_entry->ace_access = file_acl->u_access << 6;
2321 idp->id_type = SMB_ACL_USER_OBJ;
2328 acl_entry_link_head->count++;
2329 DEBUG(10,("new_acl_entry->ace_access = %d\n",new_acl_entry->ace_access));
2332 acl_entry_link_head->count = 0;
2333 SAFE_FREE(file_acl);
2335 return(acl_entry_link_head);
2339 SMB_ACL_T sys_acl_init( int count)
2341 struct acl_entry_link *theacl = NULL;
2343 DEBUG(10,("Entering sys_acl_init\n"));
2345 theacl = SMB_MALLOC_P(struct acl_entry_link);
2346 if(theacl == NULL) {
2348 DEBUG(0,("Error in sys_acl_init is %d\n",errno));
2353 theacl->nextp = NULL;
2354 theacl->prevp = NULL;
2355 theacl->entryp = NULL;
2356 DEBUG(10,("Exiting sys_acl_init\n"));
2360 int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
2362 struct acl_entry_link *theacl;
2363 struct acl_entry_link *acl_entryp;
2364 struct acl_entry_link *temp_entry;
2367 DEBUG(10,("Entering the sys_acl_create_entry\n"));
2369 theacl = acl_entryp = *pacl;
2371 /* Get to the end of the acl before adding entry */
2373 for(counting=0; counting < theacl->count; counting++){
2374 DEBUG(10,("The acl_entryp is %d\n",acl_entryp));
2375 temp_entry = acl_entryp;
2376 acl_entryp = acl_entryp->nextp;
2379 if(theacl->count != 0){
2380 temp_entry->nextp = acl_entryp = SMB_MALLOC_P(struct acl_entry_link);
2381 if(acl_entryp == NULL) {
2383 DEBUG(0,("Error in sys_acl_create_entry is %d\n",errno));
2387 DEBUG(10,("The acl_entryp is %d\n",acl_entryp));
2388 acl_entryp->prevp = temp_entry;
2389 DEBUG(10,("The acl_entryp->prevp is %d\n",acl_entryp->prevp));
2392 *pentry = acl_entryp->entryp = SMB_MALLOC_P(struct new_acl_entry);
2393 if(*pentry == NULL) {
2395 DEBUG(0,("Error in sys_acl_create_entry is %d\n",errno));
2399 memset(*pentry,0,sizeof(struct new_acl_entry));
2400 acl_entryp->entryp->ace_len = sizeof(struct acl_entry);
2401 acl_entryp->entryp->ace_type = ACC_PERMIT;
2402 acl_entryp->entryp->ace_id->id_len = sizeof(struct ace_id);
2403 acl_entryp->nextp = NULL;
2405 DEBUG(10,("Exiting sys_acl_create_entry\n"));
2409 int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
2411 DEBUG(10,("Starting AIX sys_acl_set_tag_type\n"));
2412 entry->ace_id->id_type = tagtype;
2413 DEBUG(10,("The tag type is %d\n",entry->ace_id->id_type));
2414 DEBUG(10,("Ending AIX sys_acl_set_tag_type\n"));
2417 int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual)
2419 DEBUG(10,("Starting AIX sys_acl_set_qualifier\n"));
2420 memcpy(entry->ace_id->id_data,qual,sizeof(uid_t));
2421 DEBUG(10,("Ending AIX sys_acl_set_qualifier\n"));
2425 int sys_acl_set_access_bits(SMB_ACL_ENTRY_T entry, uint32 bits)
2427 DEBUG(10,("Starting AIX sys_acl_set_permset\n"));
2428 entry->ace_access = bits;
2429 DEBUG(10,("entry->ace_access = %d\n",entry->ace_access));
2430 DEBUG(10,("Ending AIX sys_acl_set_permset\n"));
2434 int sys_acl_valid( SMB_ACL_T theacl )
2439 struct acl_entry_link *acl_entry;
2441 for(acl_entry=theacl; acl_entry != NULL; acl_entry = acl_entry->nextp) {
2442 user_obj += (acl_entry->entryp->ace_id->id_type == SMB_ACL_USER_OBJ);
2443 group_obj += (acl_entry->entryp->ace_id->id_type == SMB_ACL_GROUP_OBJ);
2444 other_obj += (acl_entry->entryp->ace_id->id_type == SMB_ACL_OTHER);
2447 DEBUG(10,("user_obj=%d, group_obj=%d, other_obj=%d\n",user_obj,group_obj,other_obj));
2449 if(user_obj != 1 || group_obj != 1 || other_obj != 1)
2455 int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
2457 struct acl_entry_link *acl_entry_link = NULL;
2458 struct acl *file_acl = NULL;
2459 struct acl *file_acl_temp = NULL;
2460 struct acl_entry *acl_entry = NULL;
2461 struct ace_id *ace_id = NULL;
2468 DEBUG(10,("Entering sys_acl_set_file\n"));
2469 DEBUG(10,("File name is %s\n",name));
2471 /* AIX has no default ACL */
2472 if(acltype == SMB_ACL_TYPE_DEFAULT)
2475 acl_length = BUFSIZ;
2476 file_acl = (struct acl *)SMB_MALLOC(BUFSIZ);
2478 if(file_acl == NULL) {
2480 DEBUG(0,("Error in sys_acl_set_file is %d\n",errno));
2484 memset(file_acl,0,BUFSIZ);
2486 file_acl->acl_len = ACL_SIZ;
2487 file_acl->acl_mode = S_IXACL;
2489 for(acl_entry_link=theacl; acl_entry_link != NULL; acl_entry_link = acl_entry_link->nextp) {
2490 acl_entry_link->entryp->ace_access >>= 6;
2491 id_type = acl_entry_link->entryp->ace_id->id_type;
2494 case SMB_ACL_USER_OBJ:
2495 file_acl->u_access = acl_entry_link->entryp->ace_access;
2497 case SMB_ACL_GROUP_OBJ:
2498 file_acl->g_access = acl_entry_link->entryp->ace_access;
2501 file_acl->o_access = acl_entry_link->entryp->ace_access;
2507 if((file_acl->acl_len + sizeof(struct acl_entry)) > acl_length) {
2508 acl_length += sizeof(struct acl_entry);
2509 file_acl_temp = (struct acl *)SMB_MALLOC(acl_length);
2510 if(file_acl_temp == NULL) {
2511 SAFE_FREE(file_acl);
2513 DEBUG(0,("Error in sys_acl_set_file is %d\n",errno));
2517 memcpy(file_acl_temp,file_acl,file_acl->acl_len);
2518 SAFE_FREE(file_acl);
2519 file_acl = file_acl_temp;
2522 acl_entry = (struct acl_entry *)((char *)file_acl + file_acl->acl_len);
2523 file_acl->acl_len += sizeof(struct acl_entry);
2524 acl_entry->ace_len = acl_entry_link->entryp->ace_len;
2525 acl_entry->ace_access = acl_entry_link->entryp->ace_access;
2527 /* In order to use this, we'll need to wait until we can get denies */
2528 /* if(!acl_entry->ace_access && acl_entry->ace_type == ACC_PERMIT)
2529 acl_entry->ace_type = ACC_SPECIFY; */
2531 acl_entry->ace_type = ACC_SPECIFY;
2533 ace_id = acl_entry->ace_id;
2535 ace_id->id_type = acl_entry_link->entryp->ace_id->id_type;
2536 DEBUG(10,("The id type is %d\n",ace_id->id_type));
2537 ace_id->id_len = acl_entry_link->entryp->ace_id->id_len;
2538 memcpy(&user_id, acl_entry_link->entryp->ace_id->id_data, sizeof(uid_t));
2539 memcpy(acl_entry->ace_id->id_data, &user_id, sizeof(uid_t));
2542 rc = chacl(name,file_acl,file_acl->acl_len);
2543 DEBUG(10,("errno is %d\n",errno));
2544 DEBUG(10,("return code is %d\n",rc));
2545 SAFE_FREE(file_acl);
2546 DEBUG(10,("Exiting the sys_acl_set_file\n"));
2550 int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
2552 struct acl_entry_link *acl_entry_link = NULL;
2553 struct acl *file_acl = NULL;
2554 struct acl *file_acl_temp = NULL;
2555 struct acl_entry *acl_entry = NULL;
2556 struct ace_id *ace_id = NULL;
2562 DEBUG(10,("Entering sys_acl_set_fd\n"));
2563 acl_length = BUFSIZ;
2564 file_acl = (struct acl *)SMB_MALLOC(BUFSIZ);
2566 if(file_acl == NULL) {
2568 DEBUG(0,("Error in sys_acl_set_fd is %d\n",errno));
2572 memset(file_acl,0,BUFSIZ);
2574 file_acl->acl_len = ACL_SIZ;
2575 file_acl->acl_mode = S_IXACL;
2577 for(acl_entry_link=theacl; acl_entry_link != NULL; acl_entry_link = acl_entry_link->nextp) {
2578 acl_entry_link->entryp->ace_access >>= 6;
2579 id_type = acl_entry_link->entryp->ace_id->id_type;
2580 DEBUG(10,("The id_type is %d\n",id_type));
2583 case SMB_ACL_USER_OBJ:
2584 file_acl->u_access = acl_entry_link->entryp->ace_access;
2586 case SMB_ACL_GROUP_OBJ:
2587 file_acl->g_access = acl_entry_link->entryp->ace_access;
2590 file_acl->o_access = acl_entry_link->entryp->ace_access;
2596 if((file_acl->acl_len + sizeof(struct acl_entry)) > acl_length) {
2597 acl_length += sizeof(struct acl_entry);
2598 file_acl_temp = (struct acl *)SMB_MALLOC(acl_length);
2599 if(file_acl_temp == NULL) {
2600 SAFE_FREE(file_acl);
2602 DEBUG(0,("Error in sys_acl_set_fd is %d\n",errno));
2606 memcpy(file_acl_temp,file_acl,file_acl->acl_len);
2607 SAFE_FREE(file_acl);
2608 file_acl = file_acl_temp;
2611 acl_entry = (struct acl_entry *)((char *)file_acl + file_acl->acl_len);
2612 file_acl->acl_len += sizeof(struct acl_entry);
2613 acl_entry->ace_len = acl_entry_link->entryp->ace_len;
2614 acl_entry->ace_access = acl_entry_link->entryp->ace_access;
2616 /* In order to use this, we'll need to wait until we can get denies */
2617 /* if(!acl_entry->ace_access && acl_entry->ace_type == ACC_PERMIT)
2618 acl_entry->ace_type = ACC_SPECIFY; */
2620 acl_entry->ace_type = ACC_SPECIFY;
2622 ace_id = acl_entry->ace_id;
2624 ace_id->id_type = acl_entry_link->entryp->ace_id->id_type;
2625 DEBUG(10,("The id type is %d\n",ace_id->id_type));
2626 ace_id->id_len = acl_entry_link->entryp->ace_id->id_len;
2627 memcpy(&user_id, acl_entry_link->entryp->ace_id->id_data, sizeof(uid_t));
2628 memcpy(ace_id->id_data, &user_id, sizeof(uid_t));
2631 rc = fchacl(fd,file_acl,file_acl->acl_len);
2632 DEBUG(10,("errno is %d\n",errno));
2633 DEBUG(10,("return code is %d\n",rc));
2634 SAFE_FREE(file_acl);
2635 DEBUG(10,("Exiting sys_acl_set_fd\n"));
2639 int sys_acl_delete_def_file(const char *name)
2641 /* AIX has no default ACL */
2645 int sys_acl_free_acl(SMB_ACL_T posix_acl)
2647 struct acl_entry_link *acl_entry_link;
2649 for(acl_entry_link = posix_acl->nextp; acl_entry_link->nextp != NULL; acl_entry_link = acl_entry_link->nextp) {
2650 SAFE_FREE(acl_entry_link->prevp->entryp);
2651 SAFE_FREE(acl_entry_link->prevp);
2654 SAFE_FREE(acl_entry_link->prevp->entryp);
2655 SAFE_FREE(acl_entry_link->prevp);
2656 SAFE_FREE(acl_entry_link->entryp);
2657 SAFE_FREE(acl_entry_link);
2662 int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype)
2667 #else /* No ACLs. */
2669 #error No ACL functions defined for this platform!
2673 /************************************************************************
2674 Deliberately outside the ACL defines. Return 1 if this is a "no acls"
2676 ************************************************************************/
2678 int no_acl_syscall_error(int err)
2681 if (err == ENOSYS) {
2685 #if defined(ENOTSUP)
2686 if (err == ENOTSUP) {
2693 #endif /* SUPPORT_ACLS */