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 2 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 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
34 void SAFE_FREE(void *mem)
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.
45 The interfaces that each ACL implementation must support are as follows :
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_access_bits(SMB_ACL_ENTRY_T entry_d, uint32 *bits)
50 void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d)
51 SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
52 SMB_ACL_T sys_acl_get_fd(int fd)
53 SMB_ACL_T sys_acl_init( int count)
54 int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
55 int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
56 int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual)
57 int sys_acl_set_access_bits(SMB_ACL_ENTRY_T entry, uint32 bits)
58 int sys_acl_valid( SMB_ACL_T theacl )
59 int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
60 int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
61 int sys_acl_delete_def_file(const char *path)
63 The generic POSIX free is the following call. We split this into
64 several different free functions as we may need to add tag info
65 to structures when emulating the POSIX interface.
67 int sys_acl_free( void *obj_p)
69 The calls we actually use are :
71 int sys_acl_free_acl(SMB_ACL_T posix_acl)
72 int sys_acl_free_qualifier(void *qualifier, SMB_ACL_TAG_T tagtype)
76 #if defined(HAVE_POSIX_ACLS)
78 /* Identity mapping - easy. */
80 int sys_acl_get_entry( SMB_ACL_T the_acl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
82 return acl_get_entry( the_acl, entry_id, entry_p);
85 int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
87 return acl_get_tag_type( entry_d, tag_type_p);
90 void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d)
92 return acl_get_qualifier( entry_d);
95 SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
97 return acl_get_file( path_p, type);
101 SMB_ACL_T sys_acl_get_fd(int fd)
103 return acl_get_fd(fd);
107 #if defined(HAVE_ACL_GET_PERM_NP)
108 #define acl_get_perm(p, b) acl_get_perm_np(p, b)
111 int sys_acl_get_access_bits(SMB_ACL_ENTRY_T entry_d, uint32 *bits)
113 SMB_ACL_PERMSET_T permset;
115 if ((rc = acl_get_permset(entry_d, &permset)) != 0)
117 *bits = (acl_get_perm(permset, ACL_READ) ? 4 : 0)
118 | (acl_get_perm(permset, ACL_WRITE) ? 2 : 0)
119 | (acl_get_perm(permset, ACL_EXECUTE) ? 1 : 0);
123 SMB_ACL_T sys_acl_init( int count)
125 return acl_init(count);
128 int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
130 return acl_create_entry(pacl, pentry);
133 int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
135 return acl_set_tag_type(entry, tagtype);
138 int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual)
140 return acl_set_qualifier(entry, qual);
143 int sys_acl_set_access_bits(SMB_ACL_ENTRY_T entry, uint32 bits)
145 SMB_ACL_PERMSET_T permset;
147 if ((rc = acl_get_permset(entry, &permset)) != 0)
149 acl_clear_perms(permset);
151 acl_add_perm(permset, ACL_READ);
153 acl_add_perm(permset, ACL_WRITE);
155 acl_add_perm(permset, ACL_EXECUTE);
156 return acl_set_permset(entry, permset);
159 int sys_acl_valid( SMB_ACL_T theacl )
161 return acl_valid(theacl);
164 int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
166 return acl_set_file(name, acltype, theacl);
169 int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
171 return acl_set_fd(fd, theacl);
174 int sys_acl_delete_def_file(const char *name)
176 return acl_delete_def_file(name);
179 int sys_acl_free_acl(SMB_ACL_T the_acl)
181 return acl_free(the_acl);
184 int sys_acl_free_qualifier(void *qual, UNUSED(SMB_ACL_TAG_T tagtype))
186 return acl_free(qual);
189 #elif defined(HAVE_TRU64_ACLS)
191 * The interface to DEC/Compaq Tru64 UNIX ACLs
192 * is based on Draft 13 of the POSIX spec which is
193 * slightly different from the Draft 16 interface.
195 * Also, some of the permset manipulation functions
196 * such as acl_clear_perm() and acl_add_perm() appear
197 * to be broken on Tru64 so we have to manipulate
198 * the permission bits in the permset directly.
200 int sys_acl_get_entry( SMB_ACL_T the_acl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
202 SMB_ACL_ENTRY_T entry;
204 if (entry_id == SMB_ACL_FIRST_ENTRY && acl_first_entry(the_acl) != 0) {
209 if ((entry = acl_get_entry(the_acl)) != NULL) {
214 return errno ? -1 : 0;
217 int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
219 return acl_get_tag_type( entry_d, tag_type_p);
222 void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d)
224 return acl_get_qualifier( entry_d);
227 SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
229 return acl_get_file((char *)path_p, type);
233 SMB_ACL_T sys_acl_get_fd(int fd)
235 return acl_get_fd(fd, ACL_TYPE_ACCESS);
239 int sys_acl_get_access_bits(SMB_ACL_ENTRY_T entry_d, uint32 *bits)
241 SMB_ACL_PERMSET_T permset;
243 if ((rc = acl_get_permset(entry_d, &permset)) != 0)
245 *bits = *permset & 7; /* Tru64 doesn't have acl_get_perm() */
249 SMB_ACL_T sys_acl_init( int count)
251 return acl_init(count);
254 int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
256 SMB_ACL_ENTRY_T entry;
258 if ((entry = acl_create_entry(pacl)) == NULL) {
266 int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
268 return acl_set_tag_type(entry, tagtype);
271 int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual)
273 return acl_set_qualifier(entry, qual);
276 int sys_acl_set_access_bits(SMB_ACL_ENTRY_T entry, uint32 bits)
278 SMB_ACL_PERMSET_T permset;
280 if ((rc = acl_get_permset(entry, &permset)) != 0)
282 acl_clear_perms(permset);
284 return acl_set_permset(entry, permset);
287 int sys_acl_valid( SMB_ACL_T theacl )
291 return acl_valid(theacl, &entry);
294 int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
296 return acl_set_file((char *)name, acltype, theacl);
299 int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
301 return acl_set_fd(fd, ACL_TYPE_ACCESS, theacl);
304 int sys_acl_delete_def_file(const char *name)
306 return acl_delete_def_file((char *)name);
309 int sys_acl_free_acl(SMB_ACL_T the_acl)
311 return acl_free(the_acl);
314 int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype)
316 return acl_free_qualifier(qual, tagtype);
319 #elif defined(HAVE_UNIXWARE_ACLS) || defined(HAVE_SOLARIS_ACLS)
322 * Donated by Michael Davidson <md@sco.COM> for UnixWare / OpenUNIX.
323 * Modified by Toomas Soome <tsoome@ut.ee> for Solaris.
327 * Note that while this code implements sufficient functionality
328 * to support the sys_acl_* interfaces it does not provide all
329 * of the semantics of the POSIX ACL interfaces.
331 * In particular, an ACL entry descriptor (SMB_ACL_ENTRY_T) returned
332 * from a call to sys_acl_get_entry() should not be assumed to be
333 * valid after calling any of the following functions, which may
334 * reorder the entries in the ACL.
342 * The only difference between Solaris and UnixWare / OpenUNIX is
343 * that the #defines for the ACL operations have different names
345 #if defined(HAVE_UNIXWARE_ACLS)
347 #define SETACL ACL_SET
348 #define GETACL ACL_GET
349 #define GETACLCNT ACL_CNT
354 int sys_acl_get_entry(SMB_ACL_T acl_d, int entry_id, SMB_ACL_ENTRY_T *entry_p)
356 if (entry_id != SMB_ACL_FIRST_ENTRY && entry_id != SMB_ACL_NEXT_ENTRY) {
361 if (entry_p == NULL) {
366 if (entry_id == SMB_ACL_FIRST_ENTRY) {
370 if (acl_d->next < 0) {
375 if (acl_d->next >= acl_d->count) {
379 *entry_p = &acl_d->acl[acl_d->next++];
384 int sys_acl_get_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *type_p)
386 *type_p = entry_d->a_type;
391 void *sys_acl_get_qualifier(SMB_ACL_ENTRY_T entry_d)
393 if (entry_d->a_type != SMB_ACL_USER
394 && entry_d->a_type != SMB_ACL_GROUP) {
399 return &entry_d->a_id;
403 * There is no way of knowing what size the ACL returned by
404 * GETACL will be unless you first call GETACLCNT which means
405 * making an additional system call.
407 * In the hope of avoiding the cost of the additional system
408 * call in most cases, we initially allocate enough space for
409 * an ACL with INITIAL_ACL_SIZE entries. If this turns out to
410 * be too small then we use GETACLCNT to find out the actual
411 * size, reallocate the ACL buffer, and then call GETACL again.
414 #define INITIAL_ACL_SIZE 16
416 SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type)
419 int count; /* # of ACL entries allocated */
420 int naccess; /* # of access ACL entries */
421 int ndefault; /* # of default ACL entries */
423 if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) {
428 count = INITIAL_ACL_SIZE;
429 if ((acl_d = sys_acl_init(count)) == NULL) {
434 * If there isn't enough space for the ACL entries we use
435 * GETACLCNT to determine the actual number of ACL entries
436 * reallocate and try again. This is in a loop because it
437 * is possible that someone else could modify the ACL and
438 * increase the number of entries between the call to
439 * GETACLCNT and the call to GETACL.
441 while ((count = acl(path_p, GETACL, count, &acl_d->acl[0])) < 0
442 && errno == ENOSPC) {
444 sys_acl_free_acl(acl_d);
446 if ((count = acl(path_p, GETACLCNT, 0, NULL)) < 0) {
450 if ((acl_d = sys_acl_init(count)) == NULL) {
456 sys_acl_free_acl(acl_d);
461 * calculate the number of access and default ACL entries
463 * Note: we assume that the acl() system call returned a
464 * well formed ACL which is sorted so that all of the
465 * access ACL entries preceed any default ACL entries
467 for (naccess = 0; naccess < count; naccess++) {
468 if (acl_d->acl[naccess].a_type & ACL_DEFAULT)
471 ndefault = count - naccess;
474 * if the caller wants the default ACL we have to copy
475 * the entries down to the start of the acl[] buffer
476 * and mask out the ACL_DEFAULT flag from the type field
478 if (type == SMB_ACL_TYPE_DEFAULT) {
481 for (i = 0, j = naccess; i < ndefault; i++, j++) {
482 acl_d->acl[i] = acl_d->acl[j];
483 acl_d->acl[i].a_type &= ~ACL_DEFAULT;
486 acl_d->count = ndefault;
488 acl_d->count = naccess;
495 SMB_ACL_T sys_acl_get_fd(int fd)
498 int count; /* # of ACL entries allocated */
499 int naccess; /* # of access ACL entries */
501 count = INITIAL_ACL_SIZE;
502 if ((acl_d = sys_acl_init(count)) == NULL) {
506 while ((count = facl(fd, GETACL, count, &acl_d->acl[0])) < 0
507 && errno == ENOSPC) {
509 sys_acl_free_acl(acl_d);
511 if ((count = facl(fd, GETACLCNT, 0, NULL)) < 0) {
515 if ((acl_d = sys_acl_init(count)) == NULL) {
521 sys_acl_free_acl(acl_d);
526 * calculate the number of access ACL entries
528 for (naccess = 0; naccess < count; naccess++) {
529 if (acl_d->acl[naccess].a_type & ACL_DEFAULT)
533 acl_d->count = naccess;
539 int sys_acl_get_access_bits(SMB_ACL_ENTRY_T entry_d, uint32 *bits)
541 *bits = entry_d->a_perm;
545 SMB_ACL_T sys_acl_init(int count)
555 * note that since the definition of the structure pointed
556 * to by the SMB_ACL_T includes the first element of the
557 * acl[] array, this actually allocates an ACL with room
558 * for (count+1) entries
560 if ((a = (SMB_ACL_T)SMB_MALLOC(sizeof(struct SMB_ACL_T) + count * sizeof(struct acl))) == NULL) {
573 int sys_acl_create_entry(SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p)
576 SMB_ACL_ENTRY_T entry_d;
578 if (acl_p == NULL || entry_p == NULL || (acl_d = *acl_p) == NULL) {
583 if (acl_d->count >= acl_d->size) {
588 entry_d = &acl_d->acl[acl_d->count++];
597 int sys_acl_set_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T tag_type)
601 case SMB_ACL_USER_OBJ:
603 case SMB_ACL_GROUP_OBJ:
606 entry_d->a_type = tag_type;
616 int sys_acl_set_qualifier(SMB_ACL_ENTRY_T entry_d, void *qual_p)
618 if (entry_d->a_type != SMB_ACL_GROUP
619 && entry_d->a_type != SMB_ACL_USER) {
624 entry_d->a_id = *((id_t *)qual_p);
629 int sys_acl_set_access_bits(SMB_ACL_ENTRY_T entry_d, uint32 bits)
631 entry_d->a_perm = bits;
636 * sort the ACL and check it for validity
638 * if it's a minimal ACL with only 4 entries then we
639 * need to recalculate the mask permissions to make
640 * sure that they are the same as the GROUP_OBJ
641 * permissions as required by the UnixWare acl() system call.
643 * (note: since POSIX allows minimal ACLs which only contain
644 * 3 entries - ie there is no mask entry - we should, in theory,
645 * check for this and add a mask entry if necessary - however
646 * we "know" that the caller of this interface always specifies
647 * a mask so, in practice "this never happens" (tm) - if it *does*
648 * happen aclsort() will fail and return an error and someone will
649 * have to fix it ...)
652 static int acl_sort(SMB_ACL_T acl_d)
654 int fixmask = (acl_d->count <= 4);
656 if (aclsort(acl_d->count, fixmask, acl_d->acl) != 0) {
663 int sys_acl_valid(SMB_ACL_T acl_d)
665 return acl_sort(acl_d);
668 int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d)
673 struct acl *acl_buf = NULL;
676 if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) {
681 if (acl_sort(acl_d) != 0) {
685 acl_p = &acl_d->acl[0];
686 acl_count = acl_d->count;
689 * if it's a directory there is extra work to do
690 * since the acl() system call will replace both
691 * the access ACLs and the default ACLs (if any)
693 if (stat(name, &s) != 0) {
696 if (S_ISDIR(s.st_mode)) {
702 if (type == SMB_ACL_TYPE_ACCESS) {
704 def_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_DEFAULT);
708 acc_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_ACCESS);
711 if (tmp_acl == NULL) {
716 * allocate a temporary buffer for the complete ACL
718 acl_count = acc_acl->count + def_acl->count;
719 acl_p = acl_buf = SMB_MALLOC_ARRAY(struct acl, acl_count);
721 if (acl_buf == NULL) {
722 sys_acl_free_acl(tmp_acl);
728 * copy the access control and default entries into the buffer
730 memcpy(&acl_buf[0], &acc_acl->acl[0],
731 acc_acl->count * sizeof(acl_buf[0]));
733 memcpy(&acl_buf[acc_acl->count], &def_acl->acl[0],
734 def_acl->count * sizeof(acl_buf[0]));
737 * set the ACL_DEFAULT flag on the default entries
739 for (i = acc_acl->count; i < acl_count; i++) {
740 acl_buf[i].a_type |= ACL_DEFAULT;
743 sys_acl_free_acl(tmp_acl);
745 } else if (type != SMB_ACL_TYPE_ACCESS) {
750 ret = acl(name, SETACL, acl_count, acl_p);
757 int sys_acl_set_fd(int fd, SMB_ACL_T acl_d)
759 if (acl_sort(acl_d) != 0) {
763 return facl(fd, SETACL, acl_d->count, &acl_d->acl[0]);
766 int sys_acl_delete_def_file(const char *path)
772 * fetching the access ACL and rewriting it has
773 * the effect of deleting the default ACL
775 if ((acl_d = sys_acl_get_file(path, SMB_ACL_TYPE_ACCESS)) == NULL) {
779 ret = acl(path, SETACL, acl_d->count, acl_d->acl);
781 sys_acl_free_acl(acl_d);
786 int sys_acl_free_acl(SMB_ACL_T acl_d)
792 int sys_acl_free_qualifier(UNUSED(void *qual), UNUSED(SMB_ACL_TAG_T tagtype))
797 #elif defined(HAVE_HPUX_ACLS)
801 * Based on the Solaris/SCO code - with modifications.
805 * Note that while this code implements sufficient functionality
806 * to support the sys_acl_* interfaces it does not provide all
807 * of the semantics of the POSIX ACL interfaces.
809 * In particular, an ACL entry descriptor (SMB_ACL_ENTRY_T) returned
810 * from a call to sys_acl_get_entry() should not be assumed to be
811 * valid after calling any of the following functions, which may
812 * reorder the entries in the ACL.
819 /* This checks if the POSIX ACL system call is defined */
820 /* which basically corresponds to whether JFS 3.3 or */
821 /* higher is installed. If acl() was called when it */
822 /* isn't defined, it causes the process to core dump */
823 /* so it is important to check this and avoid acl() */
824 /* calls if it isn't there. */
826 static BOOL hpux_acl_call_presence(void)
832 static BOOL already_checked=0;
838 ret_val = shl_findsym(&handle, "acl", TYPE_PROCEDURE, &value);
841 DEBUG(5, ("hpux_acl_call_presence: shl_findsym() returned %d, errno = %d, error %s\n",
842 ret_val, errno, strerror(errno)));
843 DEBUG(5,("hpux_acl_call_presence: acl() system call is not present. Check if you have JFS 3.3 and above?\n"));
847 DEBUG(10,("hpux_acl_call_presence: acl() system call is present. We have JFS 3.3 or above \n"));
849 already_checked = True;
853 int sys_acl_get_entry(SMB_ACL_T acl_d, int entry_id, SMB_ACL_ENTRY_T *entry_p)
855 if (entry_id != SMB_ACL_FIRST_ENTRY && entry_id != SMB_ACL_NEXT_ENTRY) {
860 if (entry_p == NULL) {
865 if (entry_id == SMB_ACL_FIRST_ENTRY) {
869 if (acl_d->next < 0) {
874 if (acl_d->next >= acl_d->count) {
878 *entry_p = &acl_d->acl[acl_d->next++];
883 int sys_acl_get_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *type_p)
885 *type_p = entry_d->a_type;
890 void *sys_acl_get_qualifier(SMB_ACL_ENTRY_T entry_d)
892 if (entry_d->a_type != SMB_ACL_USER
893 && entry_d->a_type != SMB_ACL_GROUP) {
898 return &entry_d->a_id;
902 * There is no way of knowing what size the ACL returned by
903 * ACL_GET will be unless you first call ACL_CNT which means
904 * making an additional system call.
906 * In the hope of avoiding the cost of the additional system
907 * call in most cases, we initially allocate enough space for
908 * an ACL with INITIAL_ACL_SIZE entries. If this turns out to
909 * be too small then we use ACL_CNT to find out the actual
910 * size, reallocate the ACL buffer, and then call ACL_GET again.
913 #define INITIAL_ACL_SIZE 16
915 SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type)
918 int count; /* # of ACL entries allocated */
919 int naccess; /* # of access ACL entries */
920 int ndefault; /* # of default ACL entries */
922 if(hpux_acl_call_presence() == False) {
923 /* Looks like we don't have the acl() system call on HPUX.
924 * May be the system doesn't have the latest version of JFS.
929 if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) {
934 count = INITIAL_ACL_SIZE;
935 if ((acl_d = sys_acl_init(count)) == NULL) {
940 * If there isn't enough space for the ACL entries we use
941 * ACL_CNT to determine the actual number of ACL entries
942 * reallocate and try again. This is in a loop because it
943 * is possible that someone else could modify the ACL and
944 * increase the number of entries between the call to
945 * ACL_CNT and the call to ACL_GET.
947 while ((count = acl(path_p, ACL_GET, count, &acl_d->acl[0])) < 0 && errno == ENOSPC) {
949 sys_acl_free_acl(acl_d);
951 if ((count = acl(path_p, ACL_CNT, 0, NULL)) < 0) {
955 if ((acl_d = sys_acl_init(count)) == NULL) {
961 sys_acl_free_acl(acl_d);
966 * calculate the number of access and default ACL entries
968 * Note: we assume that the acl() system call returned a
969 * well formed ACL which is sorted so that all of the
970 * access ACL entries preceed any default ACL entries
972 for (naccess = 0; naccess < count; naccess++) {
973 if (acl_d->acl[naccess].a_type & ACL_DEFAULT)
976 ndefault = count - naccess;
979 * if the caller wants the default ACL we have to copy
980 * the entries down to the start of the acl[] buffer
981 * and mask out the ACL_DEFAULT flag from the type field
983 if (type == SMB_ACL_TYPE_DEFAULT) {
986 for (i = 0, j = naccess; i < ndefault; i++, j++) {
987 acl_d->acl[i] = acl_d->acl[j];
988 acl_d->acl[i].a_type &= ~ACL_DEFAULT;
991 acl_d->count = ndefault;
993 acl_d->count = naccess;
1000 SMB_ACL_T sys_acl_get_fd(int fd)
1003 * HPUX doesn't have the facl call. Fake it using the path.... JRA.
1006 files_struct *fsp = file_find_fd(fd);
1014 * We know we're in the same conn context. So we
1015 * can use the relative path.
1018 return sys_acl_get_file(fsp->fsp_name, SMB_ACL_TYPE_ACCESS);
1022 int sys_acl_get_access_bits(SMB_ACL_ENTRY_T entry_d, uint32 *bits)
1024 *bits = entry_d->a_perm;
1029 SMB_ACL_T sys_acl_init(int count)
1039 * note that since the definition of the structure pointed
1040 * to by the SMB_ACL_T includes the first element of the
1041 * acl[] array, this actually allocates an ACL with room
1042 * for (count+1) entries
1044 if ((a = SMB_MALLOC(sizeof(struct SMB_ACL_T) + count * sizeof(struct acl))) == NULL) {
1049 a->size = count + 1;
1057 int sys_acl_create_entry(SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p)
1060 SMB_ACL_ENTRY_T entry_d;
1062 if (acl_p == NULL || entry_p == NULL || (acl_d = *acl_p) == NULL) {
1067 if (acl_d->count >= acl_d->size) {
1072 entry_d = &acl_d->acl[acl_d->count++];
1073 entry_d->a_type = 0;
1075 entry_d->a_perm = 0;
1081 int sys_acl_set_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T tag_type)
1085 case SMB_ACL_USER_OBJ:
1087 case SMB_ACL_GROUP_OBJ:
1090 entry_d->a_type = tag_type;
1100 int sys_acl_set_qualifier(SMB_ACL_ENTRY_T entry_d, void *qual_p)
1102 if (entry_d->a_type != SMB_ACL_GROUP
1103 && entry_d->a_type != SMB_ACL_USER) {
1108 entry_d->a_id = *((id_t *)qual_p);
1113 int sys_acl_set_access_bits(SMB_ACL_ENTRY_T entry_d, uint32 bits)
1115 entry_d->a_perm = bits;
1120 /* Structure to capture the count for each type of ACE. */
1122 struct hpux_acl_types {
1131 int n_def_group_obj;
1135 int n_def_other_obj;
1138 int n_def_class_obj;
1144 * Counts the different number of objects in a given array of ACL
1148 * acl_count - Count of ACLs in the array of ACL strucutres.
1149 * aclp - Array of ACL structures.
1150 * acl_type_count - Pointer to acl_types structure. Should already be
1154 * acl_type_count - This structure is filled up with counts of various
1158 static int hpux_count_obj(int acl_count, struct acl *aclp, struct hpux_acl_types *acl_type_count)
1162 memset(acl_type_count, 0, sizeof(struct hpux_acl_types));
1164 for(i=0;i<acl_count;i++) {
1165 switch(aclp[i].a_type) {
1167 acl_type_count->n_user++;
1170 acl_type_count->n_user_obj++;
1173 acl_type_count->n_def_user_obj++;
1176 acl_type_count->n_group++;
1179 acl_type_count->n_group_obj++;
1182 acl_type_count->n_def_group_obj++;
1185 acl_type_count->n_other_obj++;
1188 acl_type_count->n_def_other_obj++;
1191 acl_type_count->n_class_obj++;
1194 acl_type_count->n_def_class_obj++;
1197 acl_type_count->n_def_user++;
1200 acl_type_count->n_def_group++;
1203 acl_type_count->n_illegal_obj++;
1209 /* swap_acl_entries: Swaps two ACL entries.
1211 * Inputs: aclp0, aclp1 - ACL entries to be swapped.
1214 static void hpux_swap_acl_entries(struct acl *aclp0, struct acl *aclp1)
1216 struct acl temp_acl;
1218 temp_acl.a_type = aclp0->a_type;
1219 temp_acl.a_id = aclp0->a_id;
1220 temp_acl.a_perm = aclp0->a_perm;
1222 aclp0->a_type = aclp1->a_type;
1223 aclp0->a_id = aclp1->a_id;
1224 aclp0->a_perm = aclp1->a_perm;
1226 aclp1->a_type = temp_acl.a_type;
1227 aclp1->a_id = temp_acl.a_id;
1228 aclp1->a_perm = temp_acl.a_perm;
1231 /* prohibited_duplicate_type
1232 * Identifies if given ACL type can have duplicate entries or
1235 * Inputs: acl_type - ACL Type.
1241 * True - If the ACL type matches any of the prohibited types.
1242 * False - If the ACL type doesn't match any of the prohibited types.
1245 static BOOL hpux_prohibited_duplicate_type(int acl_type)
1258 /* get_needed_class_perm
1259 * Returns the permissions of a ACL structure only if the ACL
1260 * type matches one of the pre-determined types for computing
1261 * CLASS_OBJ permissions.
1263 * Inputs: aclp - Pointer to ACL structure.
1266 static int hpux_get_needed_class_perm(struct acl *aclp)
1268 switch(aclp->a_type) {
1278 return aclp->a_perm;
1284 /* acl_sort for HPUX.
1285 * Sorts the array of ACL structures as per the description in
1286 * aclsort man page. Refer to aclsort man page for more details
1290 * acl_count - Count of ACLs in the array of ACL structures.
1291 * calclass - If this is not zero, then we compute the CLASS_OBJ
1293 * aclp - Array of ACL structures.
1297 * aclp - Sorted array of ACL structures.
1301 * Returns 0 for success -1 for failure. Prints a message to the Samba
1302 * debug log in case of failure.
1305 static int hpux_acl_sort(int acl_count, int calclass, struct acl *aclp)
1307 #if !defined(HAVE_HPUX_ACLSORT)
1309 * The aclsort() system call is availabe on the latest HPUX General
1310 * Patch Bundles. So for HPUX, we developed our version of acl_sort
1311 * function. Because, we don't want to update to a new
1312 * HPUX GR bundle just for aclsort() call.
1315 struct hpux_acl_types acl_obj_count;
1316 int n_class_obj_perm = 0;
1320 DEBUG(10,("Zero acl count passed. Returning Success\n"));
1325 DEBUG(0,("Null ACL pointer in hpux_acl_sort. Returning Failure. \n"));
1329 /* Count different types of ACLs in the ACLs array */
1331 hpux_count_obj(acl_count, aclp, &acl_obj_count);
1333 /* There should be only one entry each of type USER_OBJ, GROUP_OBJ,
1334 * CLASS_OBJ and OTHER_OBJ
1337 if( (acl_obj_count.n_user_obj != 1) ||
1338 (acl_obj_count.n_group_obj != 1) ||
1339 (acl_obj_count.n_class_obj != 1) ||
1340 (acl_obj_count.n_other_obj != 1)
1342 DEBUG(0,("hpux_acl_sort: More than one entry or no entries for \
1343 USER OBJ or GROUP_OBJ or OTHER_OBJ or CLASS_OBJ\n"));
1347 /* If any of the default objects are present, there should be only
1351 if( (acl_obj_count.n_def_user_obj > 1) || (acl_obj_count.n_def_group_obj > 1) ||
1352 (acl_obj_count.n_def_other_obj > 1) || (acl_obj_count.n_def_class_obj > 1) ) {
1353 DEBUG(0,("hpux_acl_sort: More than one entry for DEF_CLASS_OBJ \
1354 or DEF_USER_OBJ or DEF_GROUP_OBJ or DEF_OTHER_OBJ\n"));
1358 /* We now have proper number of OBJ and DEF_OBJ entries. Now sort the acl
1361 * Sorting crieteria - First sort by ACL type. If there are multiple entries of
1362 * same ACL type, sort by ACL id.
1364 * I am using the trival kind of sorting method here because, performance isn't
1365 * really effected by the ACLs feature. More over there aren't going to be more
1366 * than 17 entries on HPUX.
1369 for(i=0; i<acl_count;i++) {
1370 for (j=i+1; j<acl_count; j++) {
1371 if( aclp[i].a_type > aclp[j].a_type ) {
1372 /* ACL entries out of order, swap them */
1374 hpux_swap_acl_entries((aclp+i), (aclp+j));
1376 } else if ( aclp[i].a_type == aclp[j].a_type ) {
1378 /* ACL entries of same type, sort by id */
1380 if(aclp[i].a_id > aclp[j].a_id) {
1381 hpux_swap_acl_entries((aclp+i), (aclp+j));
1382 } else if (aclp[i].a_id == aclp[j].a_id) {
1383 /* We have a duplicate entry. */
1384 if(hpux_prohibited_duplicate_type(aclp[i].a_type)) {
1385 DEBUG(0, ("hpux_acl_sort: Duplicate entry: Type(hex): %x Id: %d\n",
1386 aclp[i].a_type, aclp[i].a_id));
1395 /* set the class obj permissions to the computed one. */
1397 int n_class_obj_index = -1;
1399 for(i=0;i<acl_count;i++) {
1400 n_class_obj_perm |= hpux_get_needed_class_perm((aclp+i));
1402 if(aclp[i].a_type == CLASS_OBJ)
1403 n_class_obj_index = i;
1405 aclp[n_class_obj_index].a_perm = n_class_obj_perm;
1410 return aclsort(acl_count, calclass, aclp);
1415 * sort the ACL and check it for validity
1417 * if it's a minimal ACL with only 4 entries then we
1418 * need to recalculate the mask permissions to make
1419 * sure that they are the same as the GROUP_OBJ
1420 * permissions as required by the UnixWare acl() system call.
1422 * (note: since POSIX allows minimal ACLs which only contain
1423 * 3 entries - ie there is no mask entry - we should, in theory,
1424 * check for this and add a mask entry if necessary - however
1425 * we "know" that the caller of this interface always specifies
1426 * a mask so, in practice "this never happens" (tm) - if it *does*
1427 * happen aclsort() will fail and return an error and someone will
1428 * have to fix it ...)
1431 static int acl_sort(SMB_ACL_T acl_d)
1433 int fixmask = (acl_d->count <= 4);
1435 if (hpux_acl_sort(acl_d->count, fixmask, acl_d->acl) != 0) {
1442 int sys_acl_valid(SMB_ACL_T acl_d)
1444 return acl_sort(acl_d);
1447 int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d)
1452 struct acl *acl_buf = NULL;
1455 if(hpux_acl_call_presence() == False) {
1456 /* Looks like we don't have the acl() system call on HPUX.
1457 * May be the system doesn't have the latest version of JFS.
1463 if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) {
1468 if (acl_sort(acl_d) != 0) {
1472 acl_p = &acl_d->acl[0];
1473 acl_count = acl_d->count;
1476 * if it's a directory there is extra work to do
1477 * since the acl() system call will replace both
1478 * the access ACLs and the default ACLs (if any)
1480 if (stat(name, &s) != 0) {
1483 if (S_ISDIR(s.st_mode)) {
1489 if (type == SMB_ACL_TYPE_ACCESS) {
1491 def_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_DEFAULT);
1495 acc_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_ACCESS);
1498 if (tmp_acl == NULL) {
1503 * allocate a temporary buffer for the complete ACL
1505 acl_count = acc_acl->count + def_acl->count;
1506 acl_p = acl_buf = SMB_MALLOC_ARRAY(struct acl, acl_count);
1508 if (acl_buf == NULL) {
1509 sys_acl_free_acl(tmp_acl);
1515 * copy the access control and default entries into the buffer
1517 memcpy(&acl_buf[0], &acc_acl->acl[0],
1518 acc_acl->count * sizeof(acl_buf[0]));
1520 memcpy(&acl_buf[acc_acl->count], &def_acl->acl[0],
1521 def_acl->count * sizeof(acl_buf[0]));
1524 * set the ACL_DEFAULT flag on the default entries
1526 for (i = acc_acl->count; i < acl_count; i++) {
1527 acl_buf[i].a_type |= ACL_DEFAULT;
1530 sys_acl_free_acl(tmp_acl);
1532 } else if (type != SMB_ACL_TYPE_ACCESS) {
1537 ret = acl(name, ACL_SET, acl_count, acl_p);
1547 int sys_acl_set_fd(int fd, SMB_ACL_T acl_d)
1550 * HPUX doesn't have the facl call. Fake it using the path.... JRA.
1553 files_struct *fsp = file_find_fd(fd);
1560 if (acl_sort(acl_d) != 0) {
1565 * We know we're in the same conn context. So we
1566 * can use the relative path.
1569 return sys_acl_set_file(fsp->fsp_name, SMB_ACL_TYPE_ACCESS, acl_d);
1573 int sys_acl_delete_def_file(const char *path)
1579 * fetching the access ACL and rewriting it has
1580 * the effect of deleting the default ACL
1582 if ((acl_d = sys_acl_get_file(path, SMB_ACL_TYPE_ACCESS)) == NULL) {
1586 ret = acl(path, ACL_SET, acl_d->count, acl_d->acl);
1588 sys_acl_free_acl(acl_d);
1593 int sys_acl_free_acl(SMB_ACL_T acl_d)
1599 int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype)
1604 #elif defined(HAVE_IRIX_ACLS)
1606 int sys_acl_get_entry(SMB_ACL_T acl_d, int entry_id, SMB_ACL_ENTRY_T *entry_p)
1608 if (entry_id != SMB_ACL_FIRST_ENTRY && entry_id != SMB_ACL_NEXT_ENTRY) {
1613 if (entry_p == NULL) {
1618 if (entry_id == SMB_ACL_FIRST_ENTRY) {
1622 if (acl_d->next < 0) {
1627 if (acl_d->next >= acl_d->aclp->acl_cnt) {
1631 *entry_p = &acl_d->aclp->acl_entry[acl_d->next++];
1636 int sys_acl_get_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *type_p)
1638 *type_p = entry_d->ae_tag;
1643 void *sys_acl_get_qualifier(SMB_ACL_ENTRY_T entry_d)
1645 if (entry_d->ae_tag != SMB_ACL_USER
1646 && entry_d->ae_tag != SMB_ACL_GROUP) {
1651 return &entry_d->ae_id;
1654 SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type)
1658 if ((a = SMB_MALLOC_P(struct SMB_ACL_T)) == NULL) {
1662 if ((a->aclp = acl_get_file(path_p, type)) == NULL) {
1672 SMB_ACL_T sys_acl_get_fd(int fd)
1676 if ((a = SMB_MALLOC_P(struct SMB_ACL_T)) == NULL) {
1680 if ((a->aclp = acl_get_fd(fd)) == NULL) {
1690 int sys_acl_get_access_bits(SMB_ACL_ENTRY_T entry_d, uint32 *bits)
1692 *bits = entry_d->ae_perm;
1697 SMB_ACL_T sys_acl_init(int count)
1706 if ((a = SMB_MALLOC(sizeof(struct SMB_ACL_T) + sizeof(struct acl))) == NULL) {
1712 a->freeaclp = False;
1713 a->aclp = (struct acl *)(&a->aclp + sizeof(struct acl *));
1714 a->aclp->acl_cnt = 0;
1720 int sys_acl_create_entry(SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p)
1723 SMB_ACL_ENTRY_T entry_d;
1725 if (acl_p == NULL || entry_p == NULL || (acl_d = *acl_p) == NULL) {
1730 if (acl_d->aclp->acl_cnt >= ACL_MAX_ENTRIES) {
1735 entry_d = &acl_d->aclp->acl_entry[acl_d->aclp->acl_cnt++];
1736 entry_d->ae_tag = 0;
1738 entry_d->ae_perm = 0;
1744 int sys_acl_set_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T tag_type)
1748 case SMB_ACL_USER_OBJ:
1750 case SMB_ACL_GROUP_OBJ:
1753 entry_d->ae_tag = tag_type;
1763 int sys_acl_set_qualifier(SMB_ACL_ENTRY_T entry_d, void *qual_p)
1765 if (entry_d->ae_tag != SMB_ACL_GROUP
1766 && entry_d->ae_tag != SMB_ACL_USER) {
1771 entry_d->ae_id = *((id_t *)qual_p);
1776 int sys_acl_set_access_bits(SMB_ACL_ENTRY_T entry_d, uint32 bits)
1778 entry_d->ae_perm = bits;
1783 int sys_acl_valid(SMB_ACL_T acl_d)
1785 return acl_valid(acl_d->aclp);
1788 int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d)
1790 return acl_set_file(name, type, acl_d->aclp);
1793 int sys_acl_set_fd(int fd, SMB_ACL_T acl_d)
1795 return acl_set_fd(fd, acl_d->aclp);
1798 int sys_acl_delete_def_file(const char *name)
1800 return acl_delete_def_file(name);
1803 int sys_acl_free_acl(SMB_ACL_T acl_d)
1805 if (acl_d->freeaclp) {
1806 acl_free(acl_d->aclp);
1812 int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype)
1817 #elif defined(HAVE_AIX_ACLS)
1819 /* Donated by Medha Date, mdate@austin.ibm.com, for IBM */
1821 int sys_acl_get_entry( SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
1823 struct acl_entry_link *link;
1824 struct new_acl_entry *entry;
1827 DEBUG(10,("This is the count: %d\n",theacl->count));
1829 /* Check if count was previously set to -1. *
1830 * If it was, that means we reached the end *
1831 * of the acl last time. */
1832 if(theacl->count == -1)
1836 /* To get to the next acl, traverse linked list until index *
1837 * of acl matches the count we are keeping. This count is *
1838 * incremented each time we return an acl entry. */
1840 for(keep_going = 0; keep_going < theacl->count; keep_going++)
1843 entry = *entry_p = link->entryp;
1845 DEBUG(10,("*entry_p is %d\n",entry_p));
1846 DEBUG(10,("*entry_p->ace_access is %d\n",entry->ace_access));
1848 /* Increment count */
1850 if(link->nextp == NULL)
1856 int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
1858 /* Initialize tag type */
1861 DEBUG(10,("the tagtype is %d\n",entry_d->ace_id->id_type));
1863 /* Depending on what type of entry we have, *
1864 * return tag type. */
1865 switch(entry_d->ace_id->id_type) {
1867 *tag_type_p = SMB_ACL_USER;
1870 *tag_type_p = SMB_ACL_GROUP;
1873 case SMB_ACL_USER_OBJ:
1874 case SMB_ACL_GROUP_OBJ:
1876 *tag_type_p = entry_d->ace_id->id_type;
1886 int sys_acl_get_access_bits(SMB_ACL_ENTRY_T entry_d, uint32 *bits)
1888 SMB_ACL_PERMSET_T permset;
1889 DEBUG(10,("Starting AIX sys_acl_get_access_bits\n"));
1890 permset = &entry_d->ace_access;
1891 DEBUG(10,("*permset is %d\n",*permset));
1892 *bits = (*permset & S_IRUSR ? 4 : 0)
1893 | (*permset & S_IWUSR ? 2 : 0)
1894 | (*permset & S_IXUSR ? 1 : 0);
1895 DEBUG(10,("Ending AIX sys_acl_get_access_bits\n"));
1899 void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d)
1901 return(entry_d->ace_id->id_data);
1904 SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
1906 struct acl *file_acl = (struct acl *)NULL;
1907 struct acl_entry *acl_entry;
1908 struct new_acl_entry *new_acl_entry;
1910 struct acl_entry_link *acl_entry_link;
1911 struct acl_entry_link *acl_entry_link_head;
1916 /* AIX has no DEFAULT */
1917 if ( type == SMB_ACL_TYPE_DEFAULT ) {
1922 /* Get the acl using statacl */
1924 DEBUG(10,("Entering sys_acl_get_file\n"));
1925 DEBUG(10,("path_p is %s\n",path_p));
1927 file_acl = (struct acl *)SMB_MALLOC(BUFSIZ);
1929 if(file_acl == NULL) {
1931 DEBUG(0,("Error in AIX sys_acl_get_file: %d\n",errno));
1935 memset(file_acl,0,BUFSIZ);
1937 rc = statacl((char *)path_p,0,file_acl,BUFSIZ);
1939 DEBUG(0,("statacl returned %d with errno %d\n",rc,errno));
1940 SAFE_FREE(file_acl);
1944 DEBUG(10,("Got facl and returned it\n"));
1946 /* Point to the first acl entry in the acl */
1947 acl_entry = file_acl->acl_ext;
1949 /* Begin setting up the head of the linked list *
1950 * that will be used for the storing the acl *
1951 * in a way that is useful for the posix_acls.c *
1954 acl_entry_link_head = acl_entry_link = sys_acl_init(0);
1955 if(acl_entry_link_head == NULL)
1958 acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
1959 if(acl_entry_link->entryp == NULL) {
1960 SAFE_FREE(file_acl);
1962 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
1966 DEBUG(10,("acl_entry is %d\n",acl_entry));
1967 DEBUG(10,("acl_last(file_acl) id %d\n",acl_last(file_acl)));
1969 /* Check if the extended acl bit is on. *
1970 * If it isn't, do not show the *
1971 * contents of the acl since AIX intends *
1972 * the extended info to remain unused */
1974 if(file_acl->acl_mode & S_IXACL){
1975 /* while we are not pointing to the very end */
1976 while(acl_entry < acl_last(file_acl)) {
1977 /* before we malloc anything, make sure this is */
1978 /* a valid acl entry and one that we want to map */
1979 idp = id_nxt(acl_entry->ace_id);
1980 if((acl_entry->ace_type == ACC_SPECIFY ||
1981 (acl_entry->ace_type == ACC_PERMIT)) && (idp != id_last(acl_entry))) {
1982 acl_entry = acl_nxt(acl_entry);
1986 idp = acl_entry->ace_id;
1988 /* Check if this is the first entry in the linked list. *
1989 * The first entry needs to keep prevp pointing to NULL *
1990 * and already has entryp allocated. */
1992 if(acl_entry_link_head->count != 0) {
1993 acl_entry_link->nextp = SMB_MALLOC_P(struct acl_entry_link);
1995 if(acl_entry_link->nextp == NULL) {
1996 SAFE_FREE(file_acl);
1998 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
2002 acl_entry_link->nextp->prevp = acl_entry_link;
2003 acl_entry_link = acl_entry_link->nextp;
2004 acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
2005 if(acl_entry_link->entryp == NULL) {
2006 SAFE_FREE(file_acl);
2008 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
2011 acl_entry_link->nextp = NULL;
2014 acl_entry_link->entryp->ace_len = acl_entry->ace_len;
2016 /* Don't really need this since all types are going *
2017 * to be specified but, it's better than leaving it 0 */
2019 acl_entry_link->entryp->ace_type = acl_entry->ace_type;
2021 acl_entry_link->entryp->ace_access = acl_entry->ace_access;
2023 memcpy(acl_entry_link->entryp->ace_id,idp,sizeof(struct ace_id));
2025 /* The access in the acl entries must be left shifted by *
2026 * three bites, because they will ultimately be compared *
2027 * to S_IRUSR, S_IWUSR, and S_IXUSR. */
2029 switch(acl_entry->ace_type){
2032 acl_entry_link->entryp->ace_access = acl_entry->ace_access;
2033 acl_entry_link->entryp->ace_access <<= 6;
2034 acl_entry_link_head->count++;
2037 /* Since there is no way to return a DENY acl entry *
2038 * change to PERMIT and then shift. */
2039 DEBUG(10,("acl_entry->ace_access is %d\n",acl_entry->ace_access));
2040 acl_entry_link->entryp->ace_access = ~acl_entry->ace_access & 7;
2041 DEBUG(10,("acl_entry_link->entryp->ace_access is %d\n",acl_entry_link->entryp->ace_access));
2042 acl_entry_link->entryp->ace_access <<= 6;
2043 acl_entry_link_head->count++;
2049 DEBUG(10,("acl_entry = %d\n",acl_entry));
2050 DEBUG(10,("The ace_type is %d\n",acl_entry->ace_type));
2052 acl_entry = acl_nxt(acl_entry);
2054 } /* end of if enabled */
2056 /* Since owner, group, other acl entries are not *
2057 * part of the acl entries in an acl, they must *
2058 * be dummied up to become part of the list. */
2060 for( i = 1; i < 4; i++) {
2061 DEBUG(10,("i is %d\n",i));
2062 if(acl_entry_link_head->count != 0) {
2063 acl_entry_link->nextp = SMB_MALLOC_P(struct acl_entry_link);
2064 if(acl_entry_link->nextp == NULL) {
2065 SAFE_FREE(file_acl);
2067 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
2071 acl_entry_link->nextp->prevp = acl_entry_link;
2072 acl_entry_link = acl_entry_link->nextp;
2073 acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
2074 if(acl_entry_link->entryp == NULL) {
2075 SAFE_FREE(file_acl);
2077 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
2082 acl_entry_link->nextp = NULL;
2084 new_acl_entry = acl_entry_link->entryp;
2085 idp = new_acl_entry->ace_id;
2087 new_acl_entry->ace_len = sizeof(struct acl_entry);
2088 new_acl_entry->ace_type = ACC_PERMIT;
2089 idp->id_len = sizeof(struct ace_id);
2090 DEBUG(10,("idp->id_len = %d\n",idp->id_len));
2091 memset(idp->id_data,0,sizeof(uid_t));
2095 new_acl_entry->ace_access = file_acl->g_access << 6;
2096 idp->id_type = SMB_ACL_GROUP_OBJ;
2100 new_acl_entry->ace_access = file_acl->o_access << 6;
2101 idp->id_type = SMB_ACL_OTHER;
2105 new_acl_entry->ace_access = file_acl->u_access << 6;
2106 idp->id_type = SMB_ACL_USER_OBJ;
2114 acl_entry_link_head->count++;
2115 DEBUG(10,("new_acl_entry->ace_access = %d\n",new_acl_entry->ace_access));
2118 acl_entry_link_head->count = 0;
2119 SAFE_FREE(file_acl);
2121 return(acl_entry_link_head);
2125 SMB_ACL_T sys_acl_get_fd(int fd)
2127 struct acl *file_acl = (struct acl *)NULL;
2128 struct acl_entry *acl_entry;
2129 struct new_acl_entry *new_acl_entry;
2131 struct acl_entry_link *acl_entry_link;
2132 struct acl_entry_link *acl_entry_link_head;
2137 /* Get the acl using fstatacl */
2139 DEBUG(10,("Entering sys_acl_get_fd\n"));
2140 DEBUG(10,("fd is %d\n",fd));
2141 file_acl = (struct acl *)SMB_MALLOC(BUFSIZ);
2143 if(file_acl == NULL) {
2145 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2149 memset(file_acl,0,BUFSIZ);
2151 rc = fstatacl(fd,0,file_acl,BUFSIZ);
2153 DEBUG(0,("The fstatacl call returned %d with errno %d\n",rc,errno));
2154 SAFE_FREE(file_acl);
2158 DEBUG(10,("Got facl and returned it\n"));
2160 /* Point to the first acl entry in the acl */
2162 acl_entry = file_acl->acl_ext;
2163 /* Begin setting up the head of the linked list *
2164 * that will be used for the storing the acl *
2165 * in a way that is useful for the posix_acls.c *
2168 acl_entry_link_head = acl_entry_link = sys_acl_init(0);
2169 if(acl_entry_link_head == NULL){
2170 SAFE_FREE(file_acl);
2174 acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
2176 if(acl_entry_link->entryp == NULL) {
2178 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2179 SAFE_FREE(file_acl);
2183 DEBUG(10,("acl_entry is %d\n",acl_entry));
2184 DEBUG(10,("acl_last(file_acl) id %d\n",acl_last(file_acl)));
2186 /* Check if the extended acl bit is on. *
2187 * If it isn't, do not show the *
2188 * contents of the acl since AIX intends *
2189 * the extended info to remain unused */
2191 if(file_acl->acl_mode & S_IXACL){
2192 /* while we are not pointing to the very end */
2193 while(acl_entry < acl_last(file_acl)) {
2194 /* before we malloc anything, make sure this is */
2195 /* a valid acl entry and one that we want to map */
2197 idp = id_nxt(acl_entry->ace_id);
2198 if((acl_entry->ace_type == ACC_SPECIFY ||
2199 (acl_entry->ace_type == ACC_PERMIT)) && (idp != id_last(acl_entry))) {
2200 acl_entry = acl_nxt(acl_entry);
2204 idp = acl_entry->ace_id;
2206 /* Check if this is the first entry in the linked list. *
2207 * The first entry needs to keep prevp pointing to NULL *
2208 * and already has entryp allocated. */
2210 if(acl_entry_link_head->count != 0) {
2211 acl_entry_link->nextp = SMB_MALLOC_P(struct acl_entry_link);
2212 if(acl_entry_link->nextp == NULL) {
2214 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2215 SAFE_FREE(file_acl);
2218 acl_entry_link->nextp->prevp = acl_entry_link;
2219 acl_entry_link = acl_entry_link->nextp;
2220 acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
2221 if(acl_entry_link->entryp == NULL) {
2223 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2224 SAFE_FREE(file_acl);
2228 acl_entry_link->nextp = NULL;
2231 acl_entry_link->entryp->ace_len = acl_entry->ace_len;
2233 /* Don't really need this since all types are going *
2234 * to be specified but, it's better than leaving it 0 */
2236 acl_entry_link->entryp->ace_type = acl_entry->ace_type;
2237 acl_entry_link->entryp->ace_access = acl_entry->ace_access;
2239 memcpy(acl_entry_link->entryp->ace_id, idp, sizeof(struct ace_id));
2241 /* The access in the acl entries must be left shifted by *
2242 * three bites, because they will ultimately be compared *
2243 * to S_IRUSR, S_IWUSR, and S_IXUSR. */
2245 switch(acl_entry->ace_type){
2248 acl_entry_link->entryp->ace_access = acl_entry->ace_access;
2249 acl_entry_link->entryp->ace_access <<= 6;
2250 acl_entry_link_head->count++;
2253 /* Since there is no way to return a DENY acl entry *
2254 * change to PERMIT and then shift. */
2255 DEBUG(10,("acl_entry->ace_access is %d\n",acl_entry->ace_access));
2256 acl_entry_link->entryp->ace_access = ~acl_entry->ace_access & 7;
2257 DEBUG(10,("acl_entry_link->entryp->ace_access is %d\n",acl_entry_link->entryp->ace_access));
2258 acl_entry_link->entryp->ace_access <<= 6;
2259 acl_entry_link_head->count++;
2265 DEBUG(10,("acl_entry = %d\n",acl_entry));
2266 DEBUG(10,("The ace_type is %d\n",acl_entry->ace_type));
2268 acl_entry = acl_nxt(acl_entry);
2270 } /* end of if enabled */
2272 /* Since owner, group, other acl entries are not *
2273 * part of the acl entries in an acl, they must *
2274 * be dummied up to become part of the list. */
2276 for( i = 1; i < 4; i++) {
2277 DEBUG(10,("i is %d\n",i));
2278 if(acl_entry_link_head->count != 0){
2279 acl_entry_link->nextp = SMB_MALLOC_P(struct acl_entry_link);
2280 if(acl_entry_link->nextp == NULL) {
2282 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2283 SAFE_FREE(file_acl);
2287 acl_entry_link->nextp->prevp = acl_entry_link;
2288 acl_entry_link = acl_entry_link->nextp;
2289 acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
2291 if(acl_entry_link->entryp == NULL) {
2292 SAFE_FREE(file_acl);
2294 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2299 acl_entry_link->nextp = NULL;
2301 new_acl_entry = acl_entry_link->entryp;
2302 idp = new_acl_entry->ace_id;
2304 new_acl_entry->ace_len = sizeof(struct acl_entry);
2305 new_acl_entry->ace_type = ACC_PERMIT;
2306 idp->id_len = sizeof(struct ace_id);
2307 DEBUG(10,("idp->id_len = %d\n",idp->id_len));
2308 memset(idp->id_data,0,sizeof(uid_t));
2312 new_acl_entry->ace_access = file_acl->g_access << 6;
2313 idp->id_type = SMB_ACL_GROUP_OBJ;
2317 new_acl_entry->ace_access = file_acl->o_access << 6;
2318 idp->id_type = SMB_ACL_OTHER;
2322 new_acl_entry->ace_access = file_acl->u_access << 6;
2323 idp->id_type = SMB_ACL_USER_OBJ;
2330 acl_entry_link_head->count++;
2331 DEBUG(10,("new_acl_entry->ace_access = %d\n",new_acl_entry->ace_access));
2334 acl_entry_link_head->count = 0;
2335 SAFE_FREE(file_acl);
2337 return(acl_entry_link_head);
2341 SMB_ACL_T sys_acl_init( int count)
2343 struct acl_entry_link *theacl = NULL;
2345 DEBUG(10,("Entering sys_acl_init\n"));
2347 theacl = SMB_MALLOC_P(struct acl_entry_link);
2348 if(theacl == NULL) {
2350 DEBUG(0,("Error in sys_acl_init is %d\n",errno));
2355 theacl->nextp = NULL;
2356 theacl->prevp = NULL;
2357 theacl->entryp = NULL;
2358 DEBUG(10,("Exiting sys_acl_init\n"));
2362 int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
2364 struct acl_entry_link *theacl;
2365 struct acl_entry_link *acl_entryp;
2366 struct acl_entry_link *temp_entry;
2369 DEBUG(10,("Entering the sys_acl_create_entry\n"));
2371 theacl = acl_entryp = *pacl;
2373 /* Get to the end of the acl before adding entry */
2375 for(counting=0; counting < theacl->count; counting++){
2376 DEBUG(10,("The acl_entryp is %d\n",acl_entryp));
2377 temp_entry = acl_entryp;
2378 acl_entryp = acl_entryp->nextp;
2381 if(theacl->count != 0){
2382 temp_entry->nextp = acl_entryp = SMB_MALLOC_P(struct acl_entry_link);
2383 if(acl_entryp == NULL) {
2385 DEBUG(0,("Error in sys_acl_create_entry is %d\n",errno));
2389 DEBUG(10,("The acl_entryp is %d\n",acl_entryp));
2390 acl_entryp->prevp = temp_entry;
2391 DEBUG(10,("The acl_entryp->prevp is %d\n",acl_entryp->prevp));
2394 *pentry = acl_entryp->entryp = SMB_MALLOC_P(struct new_acl_entry);
2395 if(*pentry == NULL) {
2397 DEBUG(0,("Error in sys_acl_create_entry is %d\n",errno));
2401 memset(*pentry,0,sizeof(struct new_acl_entry));
2402 acl_entryp->entryp->ace_len = sizeof(struct acl_entry);
2403 acl_entryp->entryp->ace_type = ACC_PERMIT;
2404 acl_entryp->entryp->ace_id->id_len = sizeof(struct ace_id);
2405 acl_entryp->nextp = NULL;
2407 DEBUG(10,("Exiting sys_acl_create_entry\n"));
2411 int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
2413 DEBUG(10,("Starting AIX sys_acl_set_tag_type\n"));
2414 entry->ace_id->id_type = tagtype;
2415 DEBUG(10,("The tag type is %d\n",entry->ace_id->id_type));
2416 DEBUG(10,("Ending AIX sys_acl_set_tag_type\n"));
2419 int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual)
2421 DEBUG(10,("Starting AIX sys_acl_set_qualifier\n"));
2422 memcpy(entry->ace_id->id_data,qual,sizeof(uid_t));
2423 DEBUG(10,("Ending AIX sys_acl_set_qualifier\n"));
2427 int sys_acl_set_access_bits(SMB_ACL_ENTRY_T entry, uint32 bits)
2429 DEBUG(10,("Starting AIX sys_acl_set_permset\n"));
2430 entry->ace_access = bits;
2431 DEBUG(10,("entry->ace_access = %d\n",entry->ace_access));
2432 DEBUG(10,("Ending AIX sys_acl_set_permset\n"));
2436 int sys_acl_valid( SMB_ACL_T theacl )
2441 struct acl_entry_link *acl_entry;
2443 for(acl_entry=theacl; acl_entry != NULL; acl_entry = acl_entry->nextp) {
2444 user_obj += (acl_entry->entryp->ace_id->id_type == SMB_ACL_USER_OBJ);
2445 group_obj += (acl_entry->entryp->ace_id->id_type == SMB_ACL_GROUP_OBJ);
2446 other_obj += (acl_entry->entryp->ace_id->id_type == SMB_ACL_OTHER);
2449 DEBUG(10,("user_obj=%d, group_obj=%d, other_obj=%d\n",user_obj,group_obj,other_obj));
2451 if(user_obj != 1 || group_obj != 1 || other_obj != 1)
2457 int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
2459 struct acl_entry_link *acl_entry_link = NULL;
2460 struct acl *file_acl = NULL;
2461 struct acl *file_acl_temp = NULL;
2462 struct acl_entry *acl_entry = NULL;
2463 struct ace_id *ace_id = NULL;
2470 DEBUG(10,("Entering sys_acl_set_file\n"));
2471 DEBUG(10,("File name is %s\n",name));
2473 /* AIX has no default ACL */
2474 if(acltype == SMB_ACL_TYPE_DEFAULT)
2477 acl_length = BUFSIZ;
2478 file_acl = (struct acl *)SMB_MALLOC(BUFSIZ);
2480 if(file_acl == NULL) {
2482 DEBUG(0,("Error in sys_acl_set_file is %d\n",errno));
2486 memset(file_acl,0,BUFSIZ);
2488 file_acl->acl_len = ACL_SIZ;
2489 file_acl->acl_mode = S_IXACL;
2491 for(acl_entry_link=theacl; acl_entry_link != NULL; acl_entry_link = acl_entry_link->nextp) {
2492 acl_entry_link->entryp->ace_access >>= 6;
2493 id_type = acl_entry_link->entryp->ace_id->id_type;
2496 case SMB_ACL_USER_OBJ:
2497 file_acl->u_access = acl_entry_link->entryp->ace_access;
2499 case SMB_ACL_GROUP_OBJ:
2500 file_acl->g_access = acl_entry_link->entryp->ace_access;
2503 file_acl->o_access = acl_entry_link->entryp->ace_access;
2509 if((file_acl->acl_len + sizeof(struct acl_entry)) > acl_length) {
2510 acl_length += sizeof(struct acl_entry);
2511 file_acl_temp = (struct acl *)SMB_MALLOC(acl_length);
2512 if(file_acl_temp == NULL) {
2513 SAFE_FREE(file_acl);
2515 DEBUG(0,("Error in sys_acl_set_file is %d\n",errno));
2519 memcpy(file_acl_temp,file_acl,file_acl->acl_len);
2520 SAFE_FREE(file_acl);
2521 file_acl = file_acl_temp;
2524 acl_entry = (struct acl_entry *)((char *)file_acl + file_acl->acl_len);
2525 file_acl->acl_len += sizeof(struct acl_entry);
2526 acl_entry->ace_len = acl_entry_link->entryp->ace_len;
2527 acl_entry->ace_access = acl_entry_link->entryp->ace_access;
2529 /* In order to use this, we'll need to wait until we can get denies */
2530 /* if(!acl_entry->ace_access && acl_entry->ace_type == ACC_PERMIT)
2531 acl_entry->ace_type = ACC_SPECIFY; */
2533 acl_entry->ace_type = ACC_SPECIFY;
2535 ace_id = acl_entry->ace_id;
2537 ace_id->id_type = acl_entry_link->entryp->ace_id->id_type;
2538 DEBUG(10,("The id type is %d\n",ace_id->id_type));
2539 ace_id->id_len = acl_entry_link->entryp->ace_id->id_len;
2540 memcpy(&user_id, acl_entry_link->entryp->ace_id->id_data, sizeof(uid_t));
2541 memcpy(acl_entry->ace_id->id_data, &user_id, sizeof(uid_t));
2544 rc = chacl(name,file_acl,file_acl->acl_len);
2545 DEBUG(10,("errno is %d\n",errno));
2546 DEBUG(10,("return code is %d\n",rc));
2547 SAFE_FREE(file_acl);
2548 DEBUG(10,("Exiting the sys_acl_set_file\n"));
2552 int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
2554 struct acl_entry_link *acl_entry_link = NULL;
2555 struct acl *file_acl = NULL;
2556 struct acl *file_acl_temp = NULL;
2557 struct acl_entry *acl_entry = NULL;
2558 struct ace_id *ace_id = NULL;
2564 DEBUG(10,("Entering sys_acl_set_fd\n"));
2565 acl_length = BUFSIZ;
2566 file_acl = (struct acl *)SMB_MALLOC(BUFSIZ);
2568 if(file_acl == NULL) {
2570 DEBUG(0,("Error in sys_acl_set_fd is %d\n",errno));
2574 memset(file_acl,0,BUFSIZ);
2576 file_acl->acl_len = ACL_SIZ;
2577 file_acl->acl_mode = S_IXACL;
2579 for(acl_entry_link=theacl; acl_entry_link != NULL; acl_entry_link = acl_entry_link->nextp) {
2580 acl_entry_link->entryp->ace_access >>= 6;
2581 id_type = acl_entry_link->entryp->ace_id->id_type;
2582 DEBUG(10,("The id_type is %d\n",id_type));
2585 case SMB_ACL_USER_OBJ:
2586 file_acl->u_access = acl_entry_link->entryp->ace_access;
2588 case SMB_ACL_GROUP_OBJ:
2589 file_acl->g_access = acl_entry_link->entryp->ace_access;
2592 file_acl->o_access = acl_entry_link->entryp->ace_access;
2598 if((file_acl->acl_len + sizeof(struct acl_entry)) > acl_length) {
2599 acl_length += sizeof(struct acl_entry);
2600 file_acl_temp = (struct acl *)SMB_MALLOC(acl_length);
2601 if(file_acl_temp == NULL) {
2602 SAFE_FREE(file_acl);
2604 DEBUG(0,("Error in sys_acl_set_fd is %d\n",errno));
2608 memcpy(file_acl_temp,file_acl,file_acl->acl_len);
2609 SAFE_FREE(file_acl);
2610 file_acl = file_acl_temp;
2613 acl_entry = (struct acl_entry *)((char *)file_acl + file_acl->acl_len);
2614 file_acl->acl_len += sizeof(struct acl_entry);
2615 acl_entry->ace_len = acl_entry_link->entryp->ace_len;
2616 acl_entry->ace_access = acl_entry_link->entryp->ace_access;
2618 /* In order to use this, we'll need to wait until we can get denies */
2619 /* if(!acl_entry->ace_access && acl_entry->ace_type == ACC_PERMIT)
2620 acl_entry->ace_type = ACC_SPECIFY; */
2622 acl_entry->ace_type = ACC_SPECIFY;
2624 ace_id = acl_entry->ace_id;
2626 ace_id->id_type = acl_entry_link->entryp->ace_id->id_type;
2627 DEBUG(10,("The id type is %d\n",ace_id->id_type));
2628 ace_id->id_len = acl_entry_link->entryp->ace_id->id_len;
2629 memcpy(&user_id, acl_entry_link->entryp->ace_id->id_data, sizeof(uid_t));
2630 memcpy(ace_id->id_data, &user_id, sizeof(uid_t));
2633 rc = fchacl(fd,file_acl,file_acl->acl_len);
2634 DEBUG(10,("errno is %d\n",errno));
2635 DEBUG(10,("return code is %d\n",rc));
2636 SAFE_FREE(file_acl);
2637 DEBUG(10,("Exiting sys_acl_set_fd\n"));
2641 int sys_acl_delete_def_file(const char *name)
2643 /* AIX has no default ACL */
2647 int sys_acl_free_acl(SMB_ACL_T posix_acl)
2649 struct acl_entry_link *acl_entry_link;
2651 for(acl_entry_link = posix_acl->nextp; acl_entry_link->nextp != NULL; acl_entry_link = acl_entry_link->nextp) {
2652 SAFE_FREE(acl_entry_link->prevp->entryp);
2653 SAFE_FREE(acl_entry_link->prevp);
2656 SAFE_FREE(acl_entry_link->prevp->entryp);
2657 SAFE_FREE(acl_entry_link->prevp);
2658 SAFE_FREE(acl_entry_link->entryp);
2659 SAFE_FREE(acl_entry_link);
2664 int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype)
2669 #else /* No ACLs. */
2671 #error No ACL functions defined for this platform!
2675 /************************************************************************
2676 Deliberately outside the ACL defines. Return 1 if this is a "no acls"
2678 ************************************************************************/
2680 int no_acl_syscall_error(int err)
2683 if (err == ENOSYS) {
2687 #if defined(ENOTSUP)
2688 if (err == ENOTSUP) {
2695 #endif /* SUPPORT_ACLS */