diff options
-rw-r--r-- | source3/Makefile.in | 36 | ||||
-rw-r--r-- | source3/configure.in | 16 | ||||
-rw-r--r-- | source3/include/smb_acls.h | 250 | ||||
-rw-r--r-- | source3/lib/sysacls.c | 2921 | ||||
-rw-r--r-- | source3/modules/vfs_aixacl.c | 215 | ||||
-rw-r--r-- | source3/modules/vfs_aixacl_util.c | 297 | ||||
-rw-r--r-- | source3/modules/vfs_default.c | 10 | ||||
-rw-r--r-- | source3/modules/vfs_hpuxacl.c | 104 | ||||
-rw-r--r-- | source3/modules/vfs_irixacl.c | 104 | ||||
-rw-r--r-- | source3/modules/vfs_posixacl.c | 391 | ||||
-rw-r--r-- | source3/modules/vfs_solarisacl.c | 788 | ||||
-rw-r--r-- | source3/modules/vfs_tru64acl.c | 504 | ||||
-rw-r--r-- | source3/smbd/posix_acls.c | 14 |
13 files changed, 2636 insertions, 3014 deletions
diff --git a/source3/Makefile.in b/source3/Makefile.in index 72e5fd3fe5..c90ad0af3d 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -381,6 +381,12 @@ VFS_CAP_OBJ = modules/vfs_cap.o VFS_EXPAND_MSDFS_OBJ = modules/vfs_expand_msdfs.o VFS_SHADOW_COPY_OBJ = modules/vfs_shadow_copy.o VFS_AFSACL_OBJ = modules/vfs_afsacl.o +VFS_POSIXACL_OBJ = modules/vfs_posixacl.o +VFS_AIXACL_OBJ = modules/vfs_aixacl.o modules/vfs_aixacl_util.o +VFS_SOLARISACL_OBJ = modules/vfs_solarisacl.o +VFS_HPUXACL_OBJ = modules/vfs_hpuxacl.o +VFS_IRIXACL_OBJ = modules/vfs_irixacl.o +VFS_TRU64ACL_OBJ = modules/vfs_tru64acl.o VFS_CATIA_OBJ = modules/vfs_catia.o VFS_CACHEPRIME_OBJ = modules/vfs_cacheprime.o VFS_PREALLOC_OBJ = modules/vfs_prealloc.o @@ -1352,6 +1358,36 @@ bin/afsacl.@SHLIBEXT@: $(VFS_AFSACL_OBJ:.o=.po) @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_AFSACL_OBJ:.o=.po) \ @SONAMEFLAG@`basename $@` +bin/posixacl.@SHLIBEXT@: $(VFS_POSIXACL_OBJ:.o=.@PICSUFFIX@) + @echo "Building plugin $@" + @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_POSIXACL_OBJ:.o=.@PICSUFFIX@) \ + @SONAMEFLAG@`basename $@` + +bin/aixacl.@SHLIBEXT@: $(VFS_AIXACL_OBJ:.o=.@PICSUFFIX@) + @echo "Building plugin $@" + @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_AIXACL_OBJ:.o=.@PICSUFFIX@) \ + @SONAMEFLAG@`basename $@` + +bin/solarisacl.@SHLIBEXT@: $(VFS_SOLARISACL_OBJ:.o=.@PICSUFFIX@) + @echo "Building plugin $@" + @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_SOLARISACL_OBJ:.o=.@PICSUFFIX@) \ + @SONAMEFLAG@`basename $@` + +bin/irixacl.@SHLIBEXT@: $(VFS_IRIXACL_OBJ:.o=.@PICSUFFIX@) + @echo "Building plugin $@" + @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_IRIXACL_OBJ:.o=.@PICSUFFIX@) \ + @SONAMEFLAG@`basename $@` + +bin/hpuxacl.@SHLIBEXT@: $(VFS_HPUXACL_OBJ:.o=.@PICSUFFIX@) + @echo "Building plugin $@" + @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_HPUXACL_OBJ:.o=.@PICSUFFIX@) \ + @SONAMEFLAG@`basename $@` + +bin/tru64acl.@SHLIBEXT@: $(VFS_TRU64ACL_OBJ:.o=.@PICSUFFIX@) + @echo "Building plugin $@" + @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_TRU64ACL_OBJ:.o=.@PICSUFFIX@) \ + @SONAMEFLAG@`basename $@` + bin/catia.@SHLIBEXT@: $(VFS_CATIA_OBJ:.o=.@PICSUFFIX@) @echo "Building plugin $@" @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_CATIA_OBJ:.o=.@PICSUFFIX@) \ diff --git a/source3/configure.in b/source3/configure.in index 7d5b91c989..f28a7a8eb5 100644 --- a/source3/configure.in +++ b/source3/configure.in @@ -4761,28 +4761,34 @@ AC_ARG_WITH(acl-support, *sysv5*) AC_MSG_RESULT(Using UnixWare ACLs) AC_DEFINE(HAVE_UNIXWARE_ACLS,1,[Whether UnixWare ACLs are available]) + default_static_modules="$default_static_modules vfs_solarisacl" ;; *solaris*) AC_MSG_RESULT(Using solaris ACLs) AC_DEFINE(HAVE_SOLARIS_ACLS,1,[Whether solaris ACLs are available]) ACL_LIBS="$ACL_LIBS -lsec" + default_static_modules="$default_static_modules vfs_solarisacl" ;; *hpux*) AC_MSG_RESULT(Using HPUX ACLs) AC_DEFINE(HAVE_HPUX_ACLS,1,[Whether HPUX ACLs are available]) + default_static_modules="$default_static_modules vfs_hpuxacl" ;; *irix*) AC_MSG_RESULT(Using IRIX ACLs) AC_DEFINE(HAVE_IRIX_ACLS,1,[Whether IRIX ACLs are available]) + default_static_modules="$default_static_modules vfs_irixacl" ;; *aix*) AC_MSG_RESULT(Using AIX ACLs) AC_DEFINE(HAVE_AIX_ACLS,1,[Whether AIX ACLs are available]) + default_static_modules="$default_static_modules vfs_aixacl" ;; *osf*) AC_MSG_RESULT(Using Tru64 ACLs) AC_DEFINE(HAVE_TRU64_ACLS,1,[Whether Tru64 ACLs are available]) ACL_LIBS="$ACL_LIBS -lpacl" + default_static_modules="$default_static_modules vfs_tru64acl" ;; *freebsd[[5-9]]*) AC_MSG_RESULT(Using FreeBSD posix ACLs) @@ -4853,6 +4859,10 @@ samba_cv_HAVE_ACL_GET_PERM_NP=yes,samba_cv_HAVE_ACL_GET_PERM_NP=no) AC_MSG_RESULT(no) ) +if test x"$samba_cv_HAVE_POSIX_ACLS" = x"yes"; then + default_static_modules="$default_static_modules vfs_posixacl" +fi + ################################################# # check for AIO support @@ -5579,6 +5589,12 @@ SMB_MODULE(vfs_cap, \$(VFS_CAP_OBJ), "bin/cap.$SHLIBEXT", VFS) SMB_MODULE(vfs_expand_msdfs, \$(VFS_EXPAND_MSDFS_OBJ), "bin/expand_msdfs.$SHLIBEXT", VFS) SMB_MODULE(vfs_shadow_copy, \$(VFS_SHADOW_COPY_OBJ), "bin/shadow_copy.$SHLIBEXT", VFS) SMB_MODULE(vfs_afsacl, \$(VFS_AFSACL_OBJ), "bin/afsacl.$SHLIBEXT", VFS) +SMB_MODULE(vfs_posixacl, \$(VFS_POSIXACL_OBJ), "bin/posixacl.$SHLIBEXT", VFS) +SMB_MODULE(vfs_aixacl, \$(VFS_AIXACL_OBJ), "bin/aixacl.$SHLIBEXT", VFS) +SMB_MODULE(vfs_solarisacl, \$(VFS_SOLARISACL_OBJ), "bin/solarisacl.$SHLIBEXT", VFS) +SMB_MODULE(vfs_irixacl, \$(VFS_IRIXACL_OBJ), "bin/irixacl.$SHLIBEXT", VFS) +SMB_MODULE(vfs_hpuxacl, \$(VFS_HPUXACL_OBJ), "bin/hpuxacl.$SHLIBEXT", VFS) +SMB_MODULE(vfs_tru64acl, \$(VFS_TRU64ACL_OBJ), "bin/tru64acl.$SHLIBEXT", VFS) SMB_MODULE(vfs_catia, \$(VFS_CATIA_OBJ), "bin/catia.$SHLIBEXT", VFS) SMB_MODULE(vfs_cacheprime, \$(VFS_CACHEPRIME_OBJ), "bin/cacheprime.$SHLIBEXT", VFS) SMB_MODULE(vfs_prealloc, \$(VFS_PREALLOC_OBJ), "bin/prealloc.$SHLIBEXT", VFS) diff --git a/source3/include/smb_acls.h b/source3/include/smb_acls.h index ec1316e466..01ab268a05 100644 --- a/source3/include/smb_acls.h +++ b/source3/include/smb_acls.h @@ -20,250 +20,41 @@ #ifndef _SMB_ACLS_H #define _SMB_ACLS_H -#if defined(HAVE_POSIX_ACLS) -/* This is an identity mapping (just remove the SMB_). */ - -#define SMB_ACL_TAG_T acl_tag_t -#define SMB_ACL_TYPE_T acl_type_t -#define SMB_ACL_PERMSET_T acl_permset_t -#define SMB_ACL_PERM_T acl_perm_t -#define SMB_ACL_READ ACL_READ -#define SMB_ACL_WRITE ACL_WRITE -#define SMB_ACL_EXECUTE ACL_EXECUTE - -/* Types of ACLs. */ -#define SMB_ACL_USER ACL_USER -#define SMB_ACL_USER_OBJ ACL_USER_OBJ -#define SMB_ACL_GROUP ACL_GROUP -#define SMB_ACL_GROUP_OBJ ACL_GROUP_OBJ -#define SMB_ACL_OTHER ACL_OTHER -#define SMB_ACL_MASK ACL_MASK - -#define SMB_ACL_T acl_t - -#define SMB_ACL_ENTRY_T acl_entry_t - -#define SMB_ACL_FIRST_ENTRY ACL_FIRST_ENTRY -#define SMB_ACL_NEXT_ENTRY ACL_NEXT_ENTRY - -#define SMB_ACL_TYPE_ACCESS ACL_TYPE_ACCESS -#define SMB_ACL_TYPE_DEFAULT ACL_TYPE_DEFAULT - -#elif defined(HAVE_TRU64_ACLS) - -/* This is for DEC/Compaq Tru64 UNIX */ - -#define SMB_ACL_TAG_T acl_tag_t -#define SMB_ACL_TYPE_T acl_type_t -#define SMB_ACL_PERMSET_T acl_permset_t -#define SMB_ACL_PERM_T acl_perm_t -#define SMB_ACL_READ ACL_READ -#define SMB_ACL_WRITE ACL_WRITE -#define SMB_ACL_EXECUTE ACL_EXECUTE - -/* Types of ACLs. */ -#define SMB_ACL_USER ACL_USER -#define SMB_ACL_USER_OBJ ACL_USER_OBJ -#define SMB_ACL_GROUP ACL_GROUP -#define SMB_ACL_GROUP_OBJ ACL_GROUP_OBJ -#define SMB_ACL_OTHER ACL_OTHER -#define SMB_ACL_MASK ACL_MASK - -#define SMB_ACL_T acl_t - -#define SMB_ACL_ENTRY_T acl_entry_t - -#define SMB_ACL_FIRST_ENTRY 0 -#define SMB_ACL_NEXT_ENTRY 1 - -#define SMB_ACL_TYPE_ACCESS ACL_TYPE_ACCESS -#define SMB_ACL_TYPE_DEFAULT ACL_TYPE_DEFAULT - -#elif defined(HAVE_UNIXWARE_ACLS) || defined(HAVE_SOLARIS_ACLS) -/* - * Donated by Michael Davidson <md@sco.COM> for UnixWare / OpenUNIX. - * Modified by Toomas Soome <tsoome@ut.ee> for Solaris. - */ - -/* SVR4.2 ES/MP ACLs */ -typedef int SMB_ACL_TAG_T; typedef int SMB_ACL_TYPE_T; -typedef ushort *SMB_ACL_PERMSET_T; -typedef ushort SMB_ACL_PERM_T; +typedef mode_t *SMB_ACL_PERMSET_T; +typedef mode_t SMB_ACL_PERM_T; #define SMB_ACL_READ 4 #define SMB_ACL_WRITE 2 #define SMB_ACL_EXECUTE 1 /* Types of ACLs. */ -#define SMB_ACL_USER USER -#define SMB_ACL_USER_OBJ USER_OBJ -#define SMB_ACL_GROUP GROUP -#define SMB_ACL_GROUP_OBJ GROUP_OBJ -#define SMB_ACL_OTHER OTHER_OBJ -#define SMB_ACL_MASK CLASS_OBJ - -typedef struct SMB_ACL_T { - int size; - int count; - int next; - struct acl acl[1]; -} *SMB_ACL_T; - -typedef struct acl *SMB_ACL_ENTRY_T; - -#define SMB_ACL_FIRST_ENTRY 0 -#define SMB_ACL_NEXT_ENTRY 1 - -#define SMB_ACL_TYPE_ACCESS 0 -#define SMB_ACL_TYPE_DEFAULT 1 - -#elif defined(HAVE_HPUX_ACLS) - -/* - * Based on the Solaris & UnixWare code. - */ - -#undef GROUP -#include <sys/aclv.h> +enum smb_acl_tag_t { + SMB_ACL_USER=1, + SMB_ACL_USER_OBJ, + SMB_ACL_GROUP, + SMB_ACL_GROUP_OBJ, + SMB_ACL_OTHER, + SMB_ACL_MASK +}; -/* SVR4.2 ES/MP ACLs */ -typedef int SMB_ACL_TAG_T; -typedef int SMB_ACL_TYPE_T; -typedef ushort *SMB_ACL_PERMSET_T; -typedef ushort SMB_ACL_PERM_T; -#define SMB_ACL_READ 4 -#define SMB_ACL_WRITE 2 -#define SMB_ACL_EXECUTE 1 +typedef enum smb_acl_tag_t SMB_ACL_TAG_T; -/* Types of ACLs. */ -#define SMB_ACL_USER USER -#define SMB_ACL_USER_OBJ USER_OBJ -#define SMB_ACL_GROUP GROUP -#define SMB_ACL_GROUP_OBJ GROUP_OBJ -#define SMB_ACL_OTHER OTHER_OBJ -#define SMB_ACL_MASK CLASS_OBJ +struct smb_acl_entry { + enum smb_acl_tag_t a_type; + SMB_ACL_PERM_T a_perm; + uid_t uid; + gid_t gid; +}; -typedef struct SMB_ACL_T { +typedef struct smb_acl_t { int size; int count; int next; - struct acl acl[1]; -} *SMB_ACL_T; - -typedef struct acl *SMB_ACL_ENTRY_T; - -#define SMB_ACL_FIRST_ENTRY 0 -#define SMB_ACL_NEXT_ENTRY 1 - -#define SMB_ACL_TYPE_ACCESS 0 -#define SMB_ACL_TYPE_DEFAULT 1 - -#elif defined(HAVE_IRIX_ACLS) - -#define SMB_ACL_TAG_T acl_tag_t -#define SMB_ACL_TYPE_T acl_type_t -#define SMB_ACL_PERMSET_T acl_permset_t -#define SMB_ACL_PERM_T acl_perm_t -#define SMB_ACL_READ ACL_READ -#define SMB_ACL_WRITE ACL_WRITE -#define SMB_ACL_EXECUTE ACL_EXECUTE - -/* Types of ACLs. */ -#define SMB_ACL_USER ACL_USER -#define SMB_ACL_USER_OBJ ACL_USER_OBJ -#define SMB_ACL_GROUP ACL_GROUP -#define SMB_ACL_GROUP_OBJ ACL_GROUP_OBJ -#define SMB_ACL_OTHER ACL_OTHER_OBJ -#define SMB_ACL_MASK ACL_MASK - -typedef struct SMB_ACL_T { - int next; - BOOL freeaclp; - struct acl *aclp; -} *SMB_ACL_T; - -#define SMB_ACL_ENTRY_T acl_entry_t - -#define SMB_ACL_FIRST_ENTRY 0 -#define SMB_ACL_NEXT_ENTRY 1 - -#define SMB_ACL_TYPE_ACCESS ACL_TYPE_ACCESS -#define SMB_ACL_TYPE_DEFAULT ACL_TYPE_DEFAULT - -#elif defined(HAVE_AIX_ACLS) - -/* Donated by Medha Date, mdate@austin.ibm.com, for IBM */ - -#include <acl.h> - -typedef uint *SMB_ACL_PERMSET_T; - -struct acl_entry_link{ - struct acl_entry_link *prevp; - struct new_acl_entry *entryp; - struct acl_entry_link *nextp; - int count; -}; - -struct new_acl_entry{ - unsigned short ace_len; - unsigned short ace_type; - unsigned int ace_access; - struct ace_id ace_id[1]; -}; - -#define SMB_ACL_ENTRY_T struct new_acl_entry* -#define SMB_ACL_T struct acl_entry_link* - -#define SMB_ACL_TAG_T unsigned short -#define SMB_ACL_TYPE_T int -#define SMB_ACL_PERM_T uint -#define SMB_ACL_READ S_IRUSR -#define SMB_ACL_WRITE S_IWUSR -#define SMB_ACL_EXECUTE S_IXUSR - -/* Types of ACLs. */ -#define SMB_ACL_USER ACEID_USER -#define SMB_ACL_USER_OBJ 3 -#define SMB_ACL_GROUP ACEID_GROUP -#define SMB_ACL_GROUP_OBJ 4 -#define SMB_ACL_OTHER 5 -#define SMB_ACL_MASK 6 - - -#define SMB_ACL_FIRST_ENTRY 1 -#define SMB_ACL_NEXT_ENTRY 2 - -#define SMB_ACL_TYPE_ACCESS 0 -#define SMB_ACL_TYPE_DEFAULT 1 - -#else /* No ACLs. */ - -/* No ACLS - fake it. */ -#define SMB_ACL_TAG_T int -#define SMB_ACL_TYPE_T int -#define SMB_ACL_PERMSET_T mode_t -#define SMB_ACL_PERM_T mode_t -#define SMB_ACL_READ S_IRUSR -#define SMB_ACL_WRITE S_IWUSR -#define SMB_ACL_EXECUTE S_IXUSR - -/* Types of ACLs. */ -#define SMB_ACL_USER 0 -#define SMB_ACL_USER_OBJ 1 -#define SMB_ACL_GROUP 2 -#define SMB_ACL_GROUP_OBJ 3 -#define SMB_ACL_OTHER 4 -#define SMB_ACL_MASK 5 - -typedef struct SMB_ACL_T_ { - int dummy; + struct smb_acl_entry acl[1]; } *SMB_ACL_T; -typedef struct SMB_ACL_ENTRY_T_ { - int dummy; -} *SMB_ACL_ENTRY_T; +typedef struct smb_acl_entry *SMB_ACL_ENTRY_T; #define SMB_ACL_FIRST_ENTRY 0 #define SMB_ACL_NEXT_ENTRY 1 @@ -271,5 +62,4 @@ typedef struct SMB_ACL_ENTRY_T_ { #define SMB_ACL_TYPE_ACCESS 0 #define SMB_ACL_TYPE_DEFAULT 1 -#endif /* No ACLs. */ #endif /* _SMB_ACLS_H */ diff --git a/source3/lib/sysacls.c b/source3/lib/sysacls.c index 36baf96016..e8c33c2c95 100644 --- a/source3/lib/sysacls.c +++ b/source3/lib/sysacls.c @@ -2,6 +2,8 @@ Unix SMB/CIFS implementation. Samba system utilities for ACL support. Copyright (C) Jeremy Allison 2000. + Copyright (C) Volker Lendecke 2006 + Copyright (C) Michael Adam 2006 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -24,337 +26,6 @@ #define DBGC_CLASS DBGC_ACLS /* - This file wraps all differing system ACL interfaces into a consistent - one based on the POSIX interface. It also returns the correct errors - for older UNIX systems that don't support ACLs. - - The interfaces that each ACL implementation must support are as follows : - - int sys_acl_get_entry( SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p) - int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p) - int sys_acl_get_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p - void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d) - SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type) - SMB_ACL_T sys_acl_get_fd(int fd) - int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset); - int sys_acl_add_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm); - char *sys_acl_to_text( SMB_ACL_T theacl, ssize_t *plen) - SMB_ACL_T sys_acl_init( int count) - int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry) - int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype) - int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual) - int sys_acl_set_permset( SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset) - int sys_acl_valid( SMB_ACL_T theacl ) - int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl) - int sys_acl_set_fd( int fd, SMB_ACL_T theacl) - int sys_acl_delete_def_file(const char *path) - - This next one is not POSIX complient - but we *have* to have it ! - More POSIX braindamage. - - int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm) - - The generic POSIX free is the following call. We split this into - several different free functions as we may need to add tag info - to structures when emulating the POSIX interface. - - int sys_acl_free( void *obj_p) - - The calls we actually use are : - - int sys_acl_free_text(char *text) - free acl_to_text - int sys_acl_free_acl(SMB_ACL_T posix_acl) - int sys_acl_free_qualifier(void *qualifier, SMB_ACL_TAG_T tagtype) - -*/ - -#if defined(HAVE_POSIX_ACLS) - -/* Identity mapping - easy. */ - -int sys_acl_get_entry( SMB_ACL_T the_acl, int entry_id, SMB_ACL_ENTRY_T *entry_p) -{ - return acl_get_entry( the_acl, entry_id, entry_p); -} - -int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p) -{ - return acl_get_tag_type( entry_d, tag_type_p); -} - -int sys_acl_get_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p) -{ - return acl_get_permset( entry_d, permset_p); -} - -void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d) -{ - return acl_get_qualifier( entry_d); -} - -SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type) -{ - return acl_get_file( path_p, type); -} - -SMB_ACL_T sys_acl_get_fd(int fd) -{ - return acl_get_fd(fd); -} - -int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset) -{ - return acl_clear_perms(permset); -} - -int sys_acl_add_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm) -{ - return acl_add_perm(permset, perm); -} - -int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm) -{ -#if defined(HAVE_ACL_GET_PERM_NP) - /* - * Required for TrustedBSD-based ACL implementations where - * non-POSIX.1e functions are denoted by a _np (non-portable) - * suffix. - */ - return acl_get_perm_np(permset, perm); -#else - return acl_get_perm(permset, perm); -#endif -} - -char *sys_acl_to_text( SMB_ACL_T the_acl, ssize_t *plen) -{ - return acl_to_text( the_acl, plen); -} - -SMB_ACL_T sys_acl_init( int count) -{ - return acl_init(count); -} - -int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry) -{ - return acl_create_entry(pacl, pentry); -} - -int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype) -{ - return acl_set_tag_type(entry, tagtype); -} - -int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual) -{ - return acl_set_qualifier(entry, qual); -} - -int sys_acl_set_permset( SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset) -{ - return acl_set_permset(entry, permset); -} - -int sys_acl_valid( SMB_ACL_T theacl ) -{ - return acl_valid(theacl); -} - -int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl) -{ - return acl_set_file(name, acltype, theacl); -} - -int sys_acl_set_fd( int fd, SMB_ACL_T theacl) -{ - return acl_set_fd(fd, theacl); -} - -int sys_acl_delete_def_file(const char *name) -{ - return acl_delete_def_file(name); -} - -int sys_acl_free_text(char *text) -{ - return acl_free(text); -} - -int sys_acl_free_acl(SMB_ACL_T the_acl) -{ - return acl_free(the_acl); -} - -int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype) -{ - return acl_free(qual); -} - -#elif defined(HAVE_TRU64_ACLS) -/* - * The interface to DEC/Compaq Tru64 UNIX ACLs - * is based on Draft 13 of the POSIX spec which is - * slightly different from the Draft 16 interface. - * - * Also, some of the permset manipulation functions - * such as acl_clear_perm() and acl_add_perm() appear - * to be broken on Tru64 so we have to manipulate - * the permission bits in the permset directly. - */ -int sys_acl_get_entry( SMB_ACL_T the_acl, int entry_id, SMB_ACL_ENTRY_T *entry_p) -{ - SMB_ACL_ENTRY_T entry; - - if (entry_id == SMB_ACL_FIRST_ENTRY && acl_first_entry(the_acl) != 0) { - return -1; - } - - errno = 0; - if ((entry = acl_get_entry(the_acl)) != NULL) { - *entry_p = entry; - return 1; - } - - return errno ? -1 : 0; -} - -int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p) -{ - return acl_get_tag_type( entry_d, tag_type_p); -} - -int sys_acl_get_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p) -{ - return acl_get_permset( entry_d, permset_p); -} - -void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d) -{ - return acl_get_qualifier( entry_d); -} - -SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type) -{ - return acl_get_file((char *)path_p, type); -} - -SMB_ACL_T sys_acl_get_fd(int fd) -{ - return acl_get_fd(fd, ACL_TYPE_ACCESS); -} - -int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset) -{ - *permset = 0; /* acl_clear_perm() is broken on Tru64 */ - - return 0; -} - -int sys_acl_add_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm) -{ - if (perm & ~(SMB_ACL_READ | SMB_ACL_WRITE | SMB_ACL_EXECUTE)) { - errno = EINVAL; - return -1; - } - - *permset |= perm; /* acl_add_perm() is broken on Tru64 */ - - return 0; -} - -int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm) -{ - return *permset & perm; /* Tru64 doesn't have acl_get_perm() */ -} - -char *sys_acl_to_text( SMB_ACL_T the_acl, ssize_t *plen) -{ - return acl_to_text( the_acl, plen); -} - -SMB_ACL_T sys_acl_init( int count) -{ - return acl_init(count); -} - -int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry) -{ - SMB_ACL_ENTRY_T entry; - - if ((entry = acl_create_entry(pacl)) == NULL) { - return -1; - } - - *pentry = entry; - return 0; -} - -int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype) -{ - return acl_set_tag_type(entry, tagtype); -} - -int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual) -{ - return acl_set_qualifier(entry, qual); -} - -int sys_acl_set_permset( SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset) -{ - return acl_set_permset(entry, permset); -} - -int sys_acl_valid( SMB_ACL_T theacl ) -{ - acl_entry_t entry; - - return acl_valid(theacl, &entry); -} - -int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl) -{ - return acl_set_file((char *)name, acltype, theacl); -} - -int sys_acl_set_fd( int fd, SMB_ACL_T theacl) -{ - return acl_set_fd(fd, ACL_TYPE_ACCESS, theacl); -} - -int sys_acl_delete_def_file(const char *name) -{ - return acl_delete_def_file((char *)name); -} - -int sys_acl_free_text(char *text) -{ - /* - * (void) cast and explicit return 0 are for DEC UNIX - * which just #defines acl_free_text() to be free() - */ - (void) acl_free_text(text); - return 0; -} - -int sys_acl_free_acl(SMB_ACL_T the_acl) -{ - return acl_free(the_acl); -} - -int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype) -{ - return acl_free_qualifier(qual, tagtype); -} - -#elif defined(HAVE_UNIXWARE_ACLS) || defined(HAVE_SOLARIS_ACLS) - -/* - * Donated by Michael Davidson <md@sco.COM> for UnixWare / OpenUNIX. - * Modified by Toomas Soome <tsoome@ut.ee> for Solaris. - */ - -/* * Note that while this code implements sufficient functionality * to support the sys_acl_* interfaces it does not provide all * of the semantics of the POSIX ACL interfaces. @@ -369,19 +40,6 @@ int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype) * sys_acl_set_fd() */ -/* - * The only difference between Solaris and UnixWare / OpenUNIX is - * that the #defines for the ACL operations have different names - */ -#if defined(HAVE_UNIXWARE_ACLS) - -#define SETACL ACL_SET -#define GETACL ACL_GET -#define GETACLCNT ACL_CNT - -#endif - - int sys_acl_get_entry(SMB_ACL_T acl_d, int entry_id, SMB_ACL_ENTRY_T *entry_p) { if (entry_id != SMB_ACL_FIRST_ENTRY && entry_id != SMB_ACL_NEXT_ENTRY) { @@ -428,148 +86,16 @@ int sys_acl_get_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p) void *sys_acl_get_qualifier(SMB_ACL_ENTRY_T entry_d) { - if (entry_d->a_type != SMB_ACL_USER - && entry_d->a_type != SMB_ACL_GROUP) { - errno = EINVAL; - return NULL; - } - - return &entry_d->a_id; -} - -/* - * There is no way of knowing what size the ACL returned by - * GETACL will be unless you first call GETACLCNT which means - * making an additional system call. - * - * In the hope of avoiding the cost of the additional system - * call in most cases, we initially allocate enough space for - * an ACL with INITIAL_ACL_SIZE entries. If this turns out to - * be too small then we use GETACLCNT to find out the actual - * size, reallocate the ACL buffer, and then call GETACL again. - */ - -#define INITIAL_ACL_SIZE 16 - -SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type) -{ - SMB_ACL_T acl_d; - int count; /* # of ACL entries allocated */ - int naccess; /* # of access ACL entries */ - int ndefault; /* # of default ACL entries */ - - if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) { - errno = EINVAL; - return NULL; - } - - count = INITIAL_ACL_SIZE; - if ((acl_d = sys_acl_init(count)) == NULL) { - return NULL; - } - - /* - * If there isn't enough space for the ACL entries we use - * GETACLCNT to determine the actual number of ACL entries - * reallocate and try again. This is in a loop because it - * is possible that someone else could modify the ACL and - * increase the number of entries between the call to - * GETACLCNT and the call to GETACL. - */ - while ((count = acl(path_p, GETACL, count, &acl_d->acl[0])) < 0 - && errno == ENOSPC) { - - sys_acl_free_acl(acl_d); - - if ((count = acl(path_p, GETACLCNT, 0, NULL)) < 0) { - return NULL; - } - - if ((acl_d = sys_acl_init(count)) == NULL) { - return NULL; - } - } - - if (count < 0) { - sys_acl_free_acl(acl_d); - return NULL; - } - - /* - * calculate the number of access and default ACL entries - * - * Note: we assume that the acl() system call returned a - * well formed ACL which is sorted so that all of the - * access ACL entries preceed any default ACL entries - */ - for (naccess = 0; naccess < count; naccess++) { - if (acl_d->acl[naccess].a_type & ACL_DEFAULT) - break; - } - ndefault = count - naccess; - - /* - * if the caller wants the default ACL we have to copy - * the entries down to the start of the acl[] buffer - * and mask out the ACL_DEFAULT flag from the type field - */ - if (type == SMB_ACL_TYPE_DEFAULT) { - int i, j; - - for (i = 0, j = naccess; i < ndefault; i++, j++) { - acl_d->acl[i] = acl_d->acl[j]; - acl_d->acl[i].a_type &= ~ACL_DEFAULT; - } - - acl_d->count = ndefault; - } else { - acl_d->count = naccess; - } - - return acl_d; -} - -SMB_ACL_T sys_acl_get_fd(int fd) -{ - SMB_ACL_T acl_d; - int count; /* # of ACL entries allocated */ - int naccess; /* # of access ACL entries */ - - count = INITIAL_ACL_SIZE; - if ((acl_d = sys_acl_init(count)) == NULL) { - return NULL; - } - - while ((count = facl(fd, GETACL, count, &acl_d->acl[0])) < 0 - && errno == ENOSPC) { - - sys_acl_free_acl(acl_d); - - if ((count = facl(fd, GETACLCNT, 0, NULL)) < 0) { - return NULL; + if (entry_d->a_type == SMB_ACL_USER) { + return &entry_d->uid; } - if ((acl_d = sys_acl_init(count)) == NULL) { - return NULL; - } + if (entry_d->a_type == SMB_ACL_GROUP) { + return &entry_d->gid; } - if (count < 0) { - sys_acl_free_acl(acl_d); + errno = EINVAL; return NULL; - } - - /* - * calculate the number of access ACL entries - */ - for (naccess = 0; naccess < count; naccess++) { - if (acl_d->acl[naccess].a_type & ACL_DEFAULT) - break; - } - - acl_d->count = naccess; - - return acl_d; } int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset_d) @@ -585,15 +111,15 @@ int sys_acl_add_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm) && perm != SMB_ACL_EXECUTE) { errno = EINVAL; return -1; - } - + } + if (permset_d == NULL) { errno = EINVAL; return -1; } *permset_d |= perm; - + return 0; } @@ -621,13 +147,12 @@ char *sys_acl_to_text(SMB_ACL_T acl_d, ssize_t *len_p) } for (i = 0; i < acl_d->count; i++) { - struct acl *ap = &acl_d->acl[i]; - struct passwd *pw; + struct smb_acl_entry *ap = &acl_d->acl[i]; struct group *gr; char tagbuf[12]; char idbuf[12]; - char *tag; - char *id = ""; + const char *tag; + const char *id = ""; char perms[4]; int nbytes; @@ -639,27 +164,24 @@ char *sys_acl_to_text(SMB_ACL_T acl_d, ssize_t *len_p) */ default: slprintf(tagbuf, sizeof(tagbuf)-1, "0x%x", - ap->a_type); + ap->a_type); tag = tagbuf; - slprintf(idbuf, sizeof(idbuf)-1, "%ld", - (long)ap->a_id); - id = idbuf; break; - + case SMB_ACL_USER: - id = uidtoname(ap->a_id); + id = uidtoname(ap->uid); case SMB_ACL_USER_OBJ: tag = "user"; break; case SMB_ACL_GROUP: - if ((gr = getgrgid(ap->a_id)) == NULL) { + if ((gr = getgrgid(ap->gid)) == NULL) { slprintf(idbuf, sizeof(idbuf)-1, "%ld", - (long)ap->a_id); + (long)ap->gid); id = idbuf; } else { id = gr->gr_name; - } + } case SMB_ACL_GROUP_OBJ: tag = "group"; break; @@ -691,10 +213,10 @@ char *sys_acl_to_text(SMB_ACL_T acl_d, ssize_t *len_p) if ((len + nbytes) > maxlen) { maxlen += nbytes + 20 * (acl_d->count - i); if ((text = SMB_REALLOC(text, maxlen)) == NULL) { - errno = ENOMEM; + errno = ENOMEM; return NULL; - } } + } slprintf(&text[len], nbytes-1, "%s:%s:%s\n", tag, id, perms); len += nbytes - 1; @@ -721,11 +243,12 @@ SMB_ACL_T sys_acl_init(int count) * acl[] array, this actually allocates an ACL with room * for (count+1) entries */ - if ((a = SMB_MALLOC(sizeof(struct SMB_ACL_T) + count * sizeof(struct acl))) == NULL) { + if ((a = SMB_MALLOC(sizeof(struct smb_acl_t) + + count * sizeof(struct smb_acl_entry))) == NULL) { errno = ENOMEM; return NULL; } - + a->size = count + 1; a->count = 0; a->next = -1; @@ -733,7 +256,6 @@ SMB_ACL_T sys_acl_init(int count) return a; } - int sys_acl_create_entry(SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p) { SMB_ACL_T acl_d; @@ -751,7 +273,8 @@ int sys_acl_create_entry(SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p) entry_d = &acl_d->acl[acl_d->count++]; entry_d->a_type = 0; - entry_d->a_id = -1; + entry_d->uid = -1; + entry_d->gid = -1; entry_d->a_perm = 0; *entry_p = entry_d; @@ -772,184 +295,36 @@ int sys_acl_set_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T tag_type) default: errno = EINVAL; return -1; - } + } return 0; } int sys_acl_set_qualifier(SMB_ACL_ENTRY_T entry_d, void *qual_p) { - if (entry_d->a_type != SMB_ACL_GROUP - && entry_d->a_type != SMB_ACL_USER) { - errno = EINVAL; - return -1; + if (entry_d->a_type == SMB_ACL_USER) { + entry_d->uid = *((uid_t *)qual_p); + return 0; + } + if (entry_d->a_type == SMB_ACL_GROUP) { + entry_d->gid = *((gid_t *)qual_p); + return 0; } - entry_d->a_id = *((id_t *)qual_p); - - return 0; + errno = EINVAL; + return -1; } int sys_acl_set_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T permset_d) { if (*permset_d & ~(SMB_ACL_READ|SMB_ACL_WRITE|SMB_ACL_EXECUTE)) { - return EINVAL; - } - - entry_d->a_perm = *permset_d; - - return 0; -} - -/* - * sort the ACL and check it for validity - * - * if it's a minimal ACL with only 4 entries then we - * need to recalculate the mask permissions to make - * sure that they are the same as the GROUP_OBJ - * permissions as required by the UnixWare acl() system call. - * - * (note: since POSIX allows minimal ACLs which only contain - * 3 entries - ie there is no mask entry - we should, in theory, - * check for this and add a mask entry if necessary - however - * we "know" that the caller of this interface always specifies - * a mask so, in practice "this never happens" (tm) - if it *does* - * happen aclsort() will fail and return an error and someone will - * have to fix it ...) - */ - -static int acl_sort(SMB_ACL_T acl_d) -{ - int fixmask = (acl_d->count <= 4); - - if (aclsort(acl_d->count, fixmask, acl_d->acl) != 0) { errno = EINVAL; return -1; } - return 0; -} - -int sys_acl_valid(SMB_ACL_T acl_d) -{ - return acl_sort(acl_d); -} - -int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d) -{ - struct stat s; - struct acl *acl_p; - int acl_count; - struct acl *acl_buf = NULL; - int ret; - - if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) { - errno = EINVAL; - return -1; - } - - if (acl_sort(acl_d) != 0) { - return -1; - } - - acl_p = &acl_d->acl[0]; - acl_count = acl_d->count; - - /* - * if it's a directory there is extra work to do - * since the acl() system call will replace both - * the access ACLs and the default ACLs (if any) - */ - if (stat(name, &s) != 0) { - return -1; - } - if (S_ISDIR(s.st_mode)) { - SMB_ACL_T acc_acl; - SMB_ACL_T def_acl; - SMB_ACL_T tmp_acl; - int i; - - if (type == SMB_ACL_TYPE_ACCESS) { - acc_acl = acl_d; - def_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_DEFAULT); - - } else { - def_acl = acl_d; - acc_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_ACCESS); - } - - if (tmp_acl == NULL) { - return -1; - } - - /* - * allocate a temporary buffer for the complete ACL - */ - acl_count = acc_acl->count + def_acl->count; - acl_p = acl_buf = SMB_MALLOC_ARRAY(struct acl, acl_count); - - if (acl_buf == NULL) { - sys_acl_free_acl(tmp_acl); - errno = ENOMEM; - return -1; - } - - /* - * copy the access control and default entries into the buffer - */ - memcpy(&acl_buf[0], &acc_acl->acl[0], - acc_acl->count * sizeof(acl_buf[0])); - - memcpy(&acl_buf[acc_acl->count], &def_acl->acl[0], - def_acl->count * sizeof(acl_buf[0])); - - /* - * set the ACL_DEFAULT flag on the default entries - */ - for (i = acc_acl->count; i < acl_count; i++) { - acl_buf[i].a_type |= ACL_DEFAULT; - } - - sys_acl_free_acl(tmp_acl); - - } else if (type != SMB_ACL_TYPE_ACCESS) { - errno = EINVAL; - return -1; - } - - ret = acl(name, SETACL, acl_count, acl_p); - - SAFE_FREE(acl_buf); - - return ret; -} - -int sys_acl_set_fd(int fd, SMB_ACL_T acl_d) -{ - if (acl_sort(acl_d) != 0) { - return -1; - } - - return facl(fd, SETACL, acl_d->count, &acl_d->acl[0]); -} -int sys_acl_delete_def_file(const char *path) -{ - SMB_ACL_T acl_d; - int ret; - - /* - * fetching the access ACL and rewriting it has - * the effect of deleting the default ACL - */ - if ((acl_d = sys_acl_get_file(path, SMB_ACL_TYPE_ACCESS)) == NULL) { - return -1; - } - - ret = acl(path, SETACL, acl_d->count, acl_d->acl); - - sys_acl_free_acl(acl_d); - - return ret; + entry_d->a_perm = *permset_d; + + return 0; } int sys_acl_free_text(char *text) @@ -969,2231 +344,241 @@ int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype) return 0; } -#elif defined(HAVE_HPUX_ACLS) -#include <dl.h> - -/* - * Based on the Solaris/SCO code - with modifications. - */ - -/* - * Note that while this code implements sufficient functionality - * to support the sys_acl_* interfaces it does not provide all - * of the semantics of the POSIX ACL interfaces. - * - * In particular, an ACL entry descriptor (SMB_ACL_ENTRY_T) returned - * from a call to sys_acl_get_entry() should not be assumed to be - * valid after calling any of the following functions, which may - * reorder the entries in the ACL. - * - * sys_acl_valid() - * sys_acl_set_file() - * sys_acl_set_fd() - */ - -/* This checks if the POSIX ACL system call is defined */ -/* which basically corresponds to whether JFS 3.3 or */ -/* higher is installed. If acl() was called when it */ -/* isn't defined, it causes the process to core dump */ -/* so it is important to check this and avoid acl() */ -/* calls if it isn't there. */ - -static BOOL hpux_acl_call_presence(void) -{ - - shl_t handle = NULL; - void *value; - int ret_val=0; - static BOOL already_checked=0; - - if(already_checked) - return True; - - - ret_val = shl_findsym(&handle, "acl", TYPE_PROCEDURE, &value); - - if(ret_val != 0) { - DEBUG(5, ("hpux_acl_call_presence: shl_findsym() returned %d, errno = %d, error %s\n", - ret_val, errno, strerror(errno))); - DEBUG(5,("hpux_acl_call_presence: acl() system call is not present. Check if you have JFS 3.3 and above?\n")); - return False; - } - - DEBUG(10,("hpux_acl_call_presence: acl() system call is present. We have JFS 3.3 or above \n")); - - already_checked = True; - return True; -} - -int sys_acl_get_entry(SMB_ACL_T acl_d, int entry_id, SMB_ACL_ENTRY_T *entry_p) -{ - if (entry_id != SMB_ACL_FIRST_ENTRY && entry_id != SMB_ACL_NEXT_ENTRY) { - errno = EINVAL; - return -1; - } - - if (entry_p == NULL) { - errno = EINVAL; - return -1; - } - - if (entry_id == SMB_ACL_FIRST_ENTRY) { - acl_d->next = 0; - } - - if (acl_d->next < 0) { - errno = EINVAL; - return -1; - } - - if (acl_d->next >= acl_d->count) { - return 0; - } - - *entry_p = &acl_d->acl[acl_d->next++]; - - return 1; -} - -int sys_acl_get_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *type_p) -{ - *type_p = entry_d->a_type; - - return 0; -} - -int sys_acl_get_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p) -{ - *permset_p = &entry_d->a_perm; - - return 0; -} - -void *sys_acl_get_qualifier(SMB_ACL_ENTRY_T entry_d) +int sys_acl_valid(SMB_ACL_T acl_d) { - if (entry_d->a_type != SMB_ACL_USER - && entry_d->a_type != SMB_ACL_GROUP) { - errno = EINVAL; - return NULL; - } - - return &entry_d->a_id; + errno = EINVAL; + return -1; } /* - * There is no way of knowing what size the ACL returned by - * ACL_GET will be unless you first call ACL_CNT which means - * making an additional system call. - * - * In the hope of avoiding the cost of the additional system - * call in most cases, we initially allocate enough space for - * an ACL with INITIAL_ACL_SIZE entries. If this turns out to - * be too small then we use ACL_CNT to find out the actual - * size, reallocate the ACL buffer, and then call ACL_GET again. - */ - -#define INITIAL_ACL_SIZE 16 - -SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type) -{ - SMB_ACL_T acl_d; - int count; /* # of ACL entries allocated */ - int naccess; /* # of access ACL entries */ - int ndefault; /* # of default ACL entries */ - - if(hpux_acl_call_presence() == False) { - /* Looks like we don't have the acl() system call on HPUX. - * May be the system doesn't have the latest version of JFS. - */ - return NULL; - } - - if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) { - errno = EINVAL; - return NULL; - } - - count = INITIAL_ACL_SIZE; - if ((acl_d = sys_acl_init(count)) == NULL) { - return NULL; - } - - /* - * If there isn't enough space for the ACL entries we use - * ACL_CNT to determine the actual number of ACL entries - * reallocate and try again. This is in a loop because it - * is possible that someone else could modify the ACL and - * increase the number of entries between the call to - * ACL_CNT and the call to ACL_GET. - */ - while ((count = acl(path_p, ACL_GET, count, &acl_d->acl[0])) < 0 && errno == ENOSPC) { - - sys_acl_free_acl(acl_d); - - if ((count = acl(path_p, ACL_CNT, 0, NULL)) < 0) { - return NULL; - } - - if ((acl_d = sys_acl_init(count)) == NULL) { - return NULL; - } - } - - if (count < 0) { - sys_acl_free_acl(acl_d); - return NULL; - } - - /* - * calculate the number of access and default ACL entries - * - * Note: we assume that the acl() system call returned a - * well formed ACL which is sorted so that all of the - * access ACL entries preceed any default ACL entries - */ - for (naccess = 0; naccess < count; naccess++) { - if (acl_d->acl[naccess].a_type & ACL_DEFAULT) - break; - } - ndefault = count - naccess; - - /* - * if the caller wants the default ACL we have to copy - * the entries down to the start of the acl[] buffer - * and mask out the ACL_DEFAULT flag from the type field - */ - if (type == SMB_ACL_TYPE_DEFAULT) { - int i, j; - - for (i = 0, j = naccess; i < ndefault; i++, j++) { - acl_d->acl[i] = acl_d->acl[j]; - acl_d->acl[i].a_type &= ~ACL_DEFAULT; - } - - acl_d->count = ndefault; - } else { - acl_d->count = naccess; - } - - return acl_d; -} - -SMB_ACL_T sys_acl_get_fd(int fd) -{ - /* - * HPUX doesn't have the facl call. Fake it using the path.... JRA. - */ - - files_struct *fsp = file_find_fd(fd); - - if (fsp == NULL) { - errno = EBADF; - return NULL; - } - - /* - * We know we're in the same conn context. So we - * can use the relative path. - */ - - return sys_acl_get_file(fsp->fsp_name, SMB_ACL_TYPE_ACCESS); -} - -int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset_d) -{ - *permset_d = 0; - - return 0; -} - -int sys_acl_add_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm) -{ - if (perm != SMB_ACL_READ && perm != SMB_ACL_WRITE - && perm != SMB_ACL_EXECUTE) { - errno = EINVAL; - return -1; - } - - if (permset_d == NULL) { - errno = EINVAL; - return -1; - } - - *permset_d |= perm; - - return 0; -} - -int sys_acl_get_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm) -{ - return *permset_d & perm; -} - -char *sys_acl_to_text(SMB_ACL_T acl_d, ssize_t *len_p) -{ - int i; - int len, maxlen; - char *text; - - /* - * use an initial estimate of 20 bytes per ACL entry - * when allocating memory for the text representation - * of the ACL - */ - len = 0; - maxlen = 20 * acl_d->count; - if ((text = SMB_MALLOC(maxlen)) == NULL) { - errno = ENOMEM; - return NULL; - } - - for (i = 0; i < acl_d->count; i++) { - struct acl *ap = &acl_d->acl[i]; - struct passwd *pw; - struct group *gr; - char tagbuf[12]; - char idbuf[12]; - char *tag; - char *id = ""; - char perms[4]; - int nbytes; - - switch (ap->a_type) { - /* - * for debugging purposes it's probably more - * useful to dump unknown tag types rather - * than just returning an error - */ - default: - slprintf(tagbuf, sizeof(tagbuf)-1, "0x%x", - ap->a_type); - tag = tagbuf; - slprintf(idbuf, sizeof(idbuf)-1, "%ld", - (long)ap->a_id); - id = idbuf; - break; - - case SMB_ACL_USER: - id = uidtoname(ap->a_id); - case SMB_ACL_USER_OBJ: - tag = "user"; - break; - - case SMB_ACL_GROUP: - if ((gr = getgrgid(ap->a_id)) == NULL) { - slprintf(idbuf, sizeof(idbuf)-1, "%ld", - (long)ap->a_id); - id = idbuf; - } else { - id = gr->gr_name; - } - case SMB_ACL_GROUP_OBJ: - tag = "group"; - break; - - case SMB_ACL_OTHER: - tag = "other"; - break; - - case SMB_ACL_MASK: - tag = "mask"; - break; - - } - - perms[0] = (ap->a_perm & SMB_ACL_READ) ? 'r' : '-'; - perms[1] = (ap->a_perm & SMB_ACL_WRITE) ? 'w' : '-'; - perms[2] = (ap->a_perm & SMB_ACL_EXECUTE) ? 'x' : '-'; - perms[3] = '\0'; - - /* <tag> : <qualifier> : rwx \n \0 */ - nbytes = strlen(tag) + 1 + strlen(id) + 1 + 3 + 1 + 1; - - /* - * If this entry would overflow the buffer - * allocate enough additional memory for this - * entry and an estimate of another 20 bytes - * for each entry still to be processed - */ - if ((len + nbytes) > maxlen) { - maxlen += nbytes + 20 * (acl_d->count - i); - if ((text = SMB_REALLOC(text, maxlen)) == NULL) { - errno = ENOMEM; - return NULL; - } - } - - slprintf(&text[len], nbytes-1, "%s:%s:%s\n", tag, id, perms); - len += nbytes - 1; - } - - if (len_p) - *len_p = len; - - return text; -} - -SMB_ACL_T sys_acl_init(int count) -{ - SMB_ACL_T a; - - if (count < 0) { - errno = EINVAL; - return NULL; - } - - /* - * note that since the definition of the structure pointed - * to by the SMB_ACL_T includes the first element of the - * acl[] array, this actually allocates an ACL with room - * for (count+1) entries - */ - if ((a = SMB_MALLOC(sizeof(struct SMB_ACL_T) + count * sizeof(struct acl))) == NULL) { - errno = ENOMEM; - return NULL; - } - - a->size = count + 1; - a->count = 0; - a->next = -1; - - return a; -} - - -int sys_acl_create_entry(SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p) -{ - SMB_ACL_T acl_d; - SMB_ACL_ENTRY_T entry_d; - - if (acl_p == NULL || entry_p == NULL || (acl_d = *acl_p) == NULL) { - errno = EINVAL; - return -1; - } - - if (acl_d->count >= acl_d->size) { - errno = ENOSPC; - return -1; - } - - entry_d = &acl_d->acl[acl_d->count++]; - entry_d->a_type = 0; - entry_d->a_id = -1; - entry_d->a_perm = 0; - *entry_p = entry_d; - - return 0; -} - -int sys_acl_set_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T tag_type) -{ - switch (tag_type) { - case SMB_ACL_USER: - case SMB_ACL_USER_OBJ: - case SMB_ACL_GROUP: - case SMB_ACL_GROUP_OBJ: - case SMB_ACL_OTHER: - case SMB_ACL_MASK: - entry_d->a_type = tag_type; - break; - default: - errno = EINVAL; - return -1; - } - - return 0; -} - -int sys_acl_set_qualifier(SMB_ACL_ENTRY_T entry_d, void *qual_p) -{ - if (entry_d->a_type != SMB_ACL_GROUP - && entry_d->a_type != SMB_ACL_USER) { - errno = EINVAL; - return -1; - } - - entry_d->a_id = *((id_t *)qual_p); - - return 0; -} - -int sys_acl_set_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T permset_d) -{ - if (*permset_d & ~(SMB_ACL_READ|SMB_ACL_WRITE|SMB_ACL_EXECUTE)) { - return EINVAL; - } - - entry_d->a_perm = *permset_d; - - return 0; -} - -/* Structure to capture the count for each type of ACE. */ - -struct hpux_acl_types { - int n_user; - int n_def_user; - int n_user_obj; - int n_def_user_obj; - - int n_group; - int n_def_group; - int n_group_obj; - int n_def_group_obj; - - int n_other; - int n_other_obj; - int n_def_other_obj; - - int n_class_obj; - int n_def_class_obj; - - int n_illegal_obj; -}; - -/* count_obj: - * Counts the different number of objects in a given array of ACL - * structures. - * Inputs: - * - * acl_count - Count of ACLs in the array of ACL strucutres. - * aclp - Array of ACL structures. - * acl_type_count - Pointer to acl_types structure. Should already be - * allocated. - * Output: - * - * acl_type_count - This structure is filled up with counts of various - * acl types. - */ - -static int hpux_count_obj(int acl_count, struct acl *aclp, struct hpux_acl_types *acl_type_count) -{ - int i; - - memset(acl_type_count, 0, sizeof(struct hpux_acl_types)); - - for(i=0;i<acl_count;i++) { - switch(aclp[i].a_type) { - case USER: - acl_type_count->n_user++; - break; - case USER_OBJ: - acl_type_count->n_user_obj++; - break; - case DEF_USER_OBJ: - acl_type_count->n_def_user_obj++; - break; - case GROUP: - acl_type_count->n_group++; - break; - case GROUP_OBJ: - acl_type_count->n_group_obj++; - break; - case DEF_GROUP_OBJ: - acl_type_count->n_def_group_obj++; - break; - case OTHER_OBJ: - acl_type_count->n_other_obj++; - break; - case DEF_OTHER_OBJ: - acl_type_count->n_def_other_obj++; - break; - case CLASS_OBJ: - acl_type_count->n_class_obj++; - break; - case DEF_CLASS_OBJ: - acl_type_count->n_def_class_obj++; - break; - case DEF_USER: - acl_type_count->n_def_user++; - break; - case DEF_GROUP: - acl_type_count->n_def_group++; - break; - default: - acl_type_count->n_illegal_obj++; - break; - } - } -} - -/* swap_acl_entries: Swaps two ACL entries. - * - * Inputs: aclp0, aclp1 - ACL entries to be swapped. - */ - -static void hpux_swap_acl_entries(struct acl *aclp0, struct acl *aclp1) -{ - struct acl temp_acl; - - temp_acl.a_type = aclp0->a_type; - temp_acl.a_id = aclp0->a_id; - temp_acl.a_perm = aclp0->a_perm; - - aclp0->a_type = aclp1->a_type; - aclp0->a_id = aclp1->a_id; - aclp0->a_perm = aclp1->a_perm; - - aclp1->a_type = temp_acl.a_type; - aclp1->a_id = temp_acl.a_id; - aclp1->a_perm = temp_acl.a_perm; -} - -/* prohibited_duplicate_type - * Identifies if given ACL type can have duplicate entries or - * not. - * - * Inputs: acl_type - ACL Type. - * - * Outputs: - * - * Return.. - * - * True - If the ACL type matches any of the prohibited types. - * False - If the ACL type doesn't match any of the prohibited types. - */ - -static BOOL hpux_prohibited_duplicate_type(int acl_type) -{ - switch(acl_type) { - case USER: - case GROUP: - case DEF_USER: - case DEF_GROUP: - return True; - default: - return False; - } -} - -/* get_needed_class_perm - * Returns the permissions of a ACL structure only if the ACL - * type matches one of the pre-determined types for computing - * CLASS_OBJ permissions. - * - * Inputs: aclp - Pointer to ACL structure. - */ - -static int hpux_get_needed_class_perm(struct acl *aclp) -{ - switch(aclp->a_type) { - case USER: - case GROUP_OBJ: - case GROUP: - case DEF_USER_OBJ: - case DEF_USER: - case DEF_GROUP_OBJ: - case DEF_GROUP: - case DEF_CLASS_OBJ: - case DEF_OTHER_OBJ: - return aclp->a_perm; - default: - return 0; - } -} - -/* acl_sort for HPUX. - * Sorts the array of ACL structures as per the description in - * aclsort man page. Refer to aclsort man page for more details - * - * Inputs: - * - * acl_count - Count of ACLs in the array of ACL structures. - * calclass - If this is not zero, then we compute the CLASS_OBJ - * permissions. - * aclp - Array of ACL structures. - * - * Outputs: - * - * aclp - Sorted array of ACL structures. - * - * Outputs: - * - * Returns 0 for success -1 for failure. Prints a message to the Samba - * debug log in case of failure. + * acl_get_file, acl_get_fd, acl_set_file, acl_set_fd and + * sys_acl_delete_def_file are to be redirected to the default + * statically-bound acl vfs module, but they are replacable. */ - -static int hpux_acl_sort(int acl_count, int calclass, struct acl *aclp) -{ -#if !defined(HAVE_HPUX_ACLSORT) - /* - * The aclsort() system call is availabe on the latest HPUX General - * Patch Bundles. So for HPUX, we developed our version of acl_sort - * function. Because, we don't want to update to a new - * HPUX GR bundle just for aclsort() call. - */ - - struct hpux_acl_types acl_obj_count; - int n_class_obj_perm = 0; - int i, j; - if(!acl_count) { - DEBUG(10,("Zero acl count passed. Returning Success\n")); - return 0; - } - - if(aclp == NULL) { - DEBUG(0,("Null ACL pointer in hpux_acl_sort. Returning Failure. \n")); - return -1; - } - - /* Count different types of ACLs in the ACLs array */ - - hpux_count_obj(acl_count, aclp, &acl_obj_count); - - /* There should be only one entry each of type USER_OBJ, GROUP_OBJ, - * CLASS_OBJ and OTHER_OBJ - */ - - if( (acl_obj_count.n_user_obj != 1) || - (acl_obj_count.n_group_obj != 1) || - (acl_obj_count.n_class_obj != 1) || - (acl_obj_count.n_other_obj != 1) - ) { - DEBUG(0,("hpux_acl_sort: More than one entry or no entries for \ -USER OBJ or GROUP_OBJ or OTHER_OBJ or CLASS_OBJ\n")); - return -1; - } - - /* If any of the default objects are present, there should be only - * one of them each. - */ - - if( (acl_obj_count.n_def_user_obj > 1) || (acl_obj_count.n_def_group_obj > 1) || - (acl_obj_count.n_def_other_obj > 1) || (acl_obj_count.n_def_class_obj > 1) ) { - DEBUG(0,("hpux_acl_sort: More than one entry for DEF_CLASS_OBJ \ -or DEF_USER_OBJ or DEF_GROUP_OBJ or DEF_OTHER_OBJ\n")); - return -1; - } - - /* We now have proper number of OBJ and DEF_OBJ entries. Now sort the acl - * structures. - * - * Sorting crieteria - First sort by ACL type. If there are multiple entries of - * same ACL type, sort by ACL id. - * - * I am using the trival kind of sorting method here because, performance isn't - * really effected by the ACLs feature. More over there aren't going to be more - * than 17 entries on HPUX. - */ - - for(i=0; i<acl_count;i++) { - for (j=i+1; j<acl_count; j++) { - if( aclp[i].a_type > aclp[j].a_type ) { - /* ACL entries out of order, swap them */ - - hpux_swap_acl_entries((aclp+i), (aclp+j)); - - } else if ( aclp[i].a_type == aclp[j].a_type ) { - - /* ACL entries of same type, sort by id */ - - if(aclp[i].a_id > aclp[j].a_id) { - hpux_swap_acl_entries((aclp+i), (aclp+j)); - } else if (aclp[i].a_id == aclp[j].a_id) { - /* We have a duplicate entry. */ - if(hpux_prohibited_duplicate_type(aclp[i].a_type)) { - DEBUG(0, ("hpux_acl_sort: Duplicate entry: Type(hex): %x Id: %d\n", - aclp[i].a_type, aclp[i].a_id)); - return -1; - } - } - - } - } - } - - /* set the class obj permissions to the computed one. */ - if(calclass) { - int n_class_obj_index = -1; - - for(i=0;i<acl_count;i++) { - n_class_obj_perm |= hpux_get_needed_class_perm((aclp+i)); - - if(aclp[i].a_type == CLASS_OBJ) - n_class_obj_index = i; - } - aclp[n_class_obj_index].a_perm = n_class_obj_perm; - } - - return 0; -#else - return aclsort(acl_count, calclass, aclp); -#endif -} - -/* - * sort the ACL and check it for validity - * - * if it's a minimal ACL with only 4 entries then we - * need to recalculate the mask permissions to make - * sure that they are the same as the GROUP_OBJ - * permissions as required by the UnixWare acl() system call. - * - * (note: since POSIX allows minimal ACLs which only contain - * 3 entries - ie there is no mask entry - we should, in theory, - * check for this and add a mask entry if necessary - however - * we "know" that the caller of this interface always specifies - * a mask so, in practice "this never happens" (tm) - if it *does* - * happen aclsort() will fail and return an error and someone will - * have to fix it ...) - */ - -static int acl_sort(SMB_ACL_T acl_d) -{ - int fixmask = (acl_d->count <= 4); - - if (hpux_acl_sort(acl_d->count, fixmask, acl_d->acl) != 0) { - errno = EINVAL; - return -1; - } - return 0; -} +#if defined(HAVE_POSIX_ACLS) -int sys_acl_valid(SMB_ACL_T acl_d) -{ - return acl_sort(acl_d); -} - -int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d) -{ - struct stat s; - struct acl *acl_p; - int acl_count; - struct acl *acl_buf = NULL; - int ret; - - if(hpux_acl_call_presence() == False) { - /* Looks like we don't have the acl() system call on HPUX. - * May be the system doesn't have the latest version of JFS. - */ - errno=ENOSYS; - return -1; - } - - if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) { - errno = EINVAL; - return -1; - } - - if (acl_sort(acl_d) != 0) { - return -1; - } - - acl_p = &acl_d->acl[0]; - acl_count = acl_d->count; - - /* - * if it's a directory there is extra work to do - * since the acl() system call will replace both - * the access ACLs and the default ACLs (if any) - */ - if (stat(name, &s) != 0) { - return -1; - } - if (S_ISDIR(s.st_mode)) { - SMB_ACL_T acc_acl; - SMB_ACL_T def_acl; - SMB_ACL_T tmp_acl; - int i; - - if (type == SMB_ACL_TYPE_ACCESS) { - acc_acl = acl_d; - def_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_DEFAULT); - - } else { - def_acl = acl_d; - acc_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_ACCESS); - } - - if (tmp_acl == NULL) { - return -1; - } - - /* - * allocate a temporary buffer for the complete ACL - */ - acl_count = acc_acl->count + def_acl->count; - acl_p = acl_buf = SMB_MALLOC_ARRAY(struct acl, acl_count); - - if (acl_buf == NULL) { - sys_acl_free_acl(tmp_acl); - errno = ENOMEM; - return -1; - } - - /* - * copy the access control and default entries into the buffer - */ - memcpy(&acl_buf[0], &acc_acl->acl[0], - acc_acl->count * sizeof(acl_buf[0])); - - memcpy(&acl_buf[acc_acl->count], &def_acl->acl[0], - def_acl->count * sizeof(acl_buf[0])); - - /* - * set the ACL_DEFAULT flag on the default entries - */ - for (i = acc_acl->count; i < acl_count; i++) { - acl_buf[i].a_type |= ACL_DEFAULT; - } - - sys_acl_free_acl(tmp_acl); - - } else if (type != SMB_ACL_TYPE_ACCESS) { - errno = EINVAL; - return -1; - } - - ret = acl(name, ACL_SET, acl_count, acl_p); - - if (acl_buf) { - free(acl_buf); - } - - return ret; -} - -int sys_acl_set_fd(int fd, SMB_ACL_T acl_d) -{ - /* - * HPUX doesn't have the facl call. Fake it using the path.... JRA. - */ - - files_struct *fsp = file_find_fd(fd); - - if (fsp == NULL) { - errno = EBADF; - return NULL; - } - - if (acl_sort(acl_d) != 0) { - return -1; - } - - /* - * We know we're in the same conn context. So we - * can use the relative path. - */ - - return sys_acl_set_file(fsp->fsp_name, SMB_ACL_TYPE_ACCESS, acl_d); -} - -int sys_acl_delete_def_file(const char *path) -{ - SMB_ACL_T acl_d; - int ret; - - /* - * fetching the access ACL and rewriting it has - * the effect of deleting the default ACL - */ - if ((acl_d = sys_acl_get_file(path, SMB_ACL_TYPE_ACCESS)) == NULL) { - return -1; - } - - ret = acl(path, ACL_SET, acl_d->count, acl_d->acl); - - sys_acl_free_acl(acl_d); - - return ret; -} - -int sys_acl_free_text(char *text) -{ - free(text); - return 0; -} - -int sys_acl_free_acl(SMB_ACL_T acl_d) -{ - free(acl_d); - return 0; -} - -int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype) -{ - return 0; -} - -#elif defined(HAVE_IRIX_ACLS) - -int sys_acl_get_entry(SMB_ACL_T acl_d, int entry_id, SMB_ACL_ENTRY_T *entry_p) -{ - if (entry_id != SMB_ACL_FIRST_ENTRY && entry_id != SMB_ACL_NEXT_ENTRY) { - errno = EINVAL; - return -1; - } - - if (entry_p == NULL) { - errno = EINVAL; - return -1; - } - - if (entry_id == SMB_ACL_FIRST_ENTRY) { - acl_d->next = 0; - } - - if (acl_d->next < 0) { - errno = EINVAL; - return -1; - } - - if (acl_d->next >= acl_d->aclp->acl_cnt) { - return 0; - } - - *entry_p = &acl_d->aclp->acl_entry[acl_d->next++]; - - return 1; -} - -int sys_acl_get_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *type_p) -{ - *type_p = entry_d->ae_tag; - - return 0; -} - -int sys_acl_get_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p) -{ - *permset_p = entry_d; - - return 0; -} - -void *sys_acl_get_qualifier(SMB_ACL_ENTRY_T entry_d) -{ - if (entry_d->ae_tag != SMB_ACL_USER - && entry_d->ae_tag != SMB_ACL_GROUP) { - errno = EINVAL; - return NULL; - } - - return &entry_d->ae_id; -} - -SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type) -{ - SMB_ACL_T a; - - if ((a = SMB_MALLOC_P(struct SMB_ACL_T)) == NULL) { - errno = ENOMEM; - return NULL; - } - if ((a->aclp = acl_get_file(path_p, type)) == NULL) { - SAFE_FREE(a); - return NULL; - } - a->next = -1; - a->freeaclp = True; - return a; -} - -SMB_ACL_T sys_acl_get_fd(int fd) -{ - SMB_ACL_T a; - - if ((a = SMB_MALLOC_P(struct SMB_ACL_T)) == NULL) { - errno = ENOMEM; - return NULL; - } - if ((a->aclp = acl_get_fd(fd)) == NULL) { - SAFE_FREE(a); - return NULL; - } - a->next = -1; - a->freeaclp = True; - return a; -} - -int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset_d) -{ - permset_d->ae_perm = 0; - - return 0; -} - -int sys_acl_add_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm) -{ - if (perm != SMB_ACL_READ && perm != SMB_ACL_WRITE - && perm != SMB_ACL_EXECUTE) { - errno = EINVAL; - return -1; - } - - if (permset_d == NULL) { - errno = EINVAL; - return -1; - } - - permset_d->ae_perm |= perm; - - return 0; -} - -int sys_acl_get_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm) -{ - return permset_d->ae_perm & perm; -} - -char *sys_acl_to_text(SMB_ACL_T acl_d, ssize_t *len_p) -{ - return acl_to_text(acl_d->aclp, len_p); -} - -SMB_ACL_T sys_acl_init(int count) -{ - SMB_ACL_T a; - - if (count < 0) { - errno = EINVAL; - return NULL; - } - - if ((a = SMB_MALLOC(sizeof(struct SMB_ACL_T) + sizeof(struct acl))) == NULL) { - errno = ENOMEM; - return NULL; - } - - a->next = -1; - a->freeaclp = False; - a->aclp = (struct acl *)(&a->aclp + sizeof(struct acl *)); - a->aclp->acl_cnt = 0; - - return a; -} - - -int sys_acl_create_entry(SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p) -{ - SMB_ACL_T acl_d; - SMB_ACL_ENTRY_T entry_d; - - if (acl_p == NULL || entry_p == NULL || (acl_d = *acl_p) == NULL) { - errno = EINVAL; - return -1; - } - - if (acl_d->aclp->acl_cnt >= ACL_MAX_ENTRIES) { - errno = ENOSPC; - return -1; - } - - entry_d = &acl_d->aclp->acl_entry[acl_d->aclp->acl_cnt++]; - entry_d->ae_tag = 0; - entry_d->ae_id = 0; - entry_d->ae_perm = 0; - *entry_p = entry_d; - - return 0; -} - -int sys_acl_set_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T tag_type) -{ - switch (tag_type) { - case SMB_ACL_USER: - case SMB_ACL_USER_OBJ: - case SMB_ACL_GROUP: - case SMB_ACL_GROUP_OBJ: - case SMB_ACL_OTHER: - case SMB_ACL_MASK: - entry_d->ae_tag = tag_type; - break; - default: - errno = EINVAL; - return -1; - } - - return 0; -} - -int sys_acl_set_qualifier(SMB_ACL_ENTRY_T entry_d, void *qual_p) -{ - if (entry_d->ae_tag != SMB_ACL_GROUP - && entry_d->ae_tag != SMB_ACL_USER) { - errno = EINVAL; - return -1; - } - - entry_d->ae_id = *((id_t *)qual_p); - - return 0; -} - -int sys_acl_set_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T permset_d) -{ - if (permset_d->ae_perm & ~(SMB_ACL_READ|SMB_ACL_WRITE|SMB_ACL_EXECUTE)) { - return EINVAL; - } - - entry_d->ae_perm = permset_d->ae_perm; - - return 0; -} - -int sys_acl_valid(SMB_ACL_T acl_d) -{ - return acl_valid(acl_d->aclp); -} - -int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d) +SMB_ACL_T sys_acl_get_file(vfs_handle_struct *handle, + const char *path_p, SMB_ACL_TYPE_T type) { - return acl_set_file(name, type, acl_d->aclp); + return posixacl_sys_acl_get_file(handle, path_p, type); } - -int sys_acl_set_fd(int fd, SMB_ACL_T acl_d) -{ - return acl_set_fd(fd, acl_d->aclp); -} - -int sys_acl_delete_def_file(const char *name) + +SMB_ACL_T sys_acl_get_fd(vfs_handle_struct *handle, files_struct *fsp, int fd) { - return acl_delete_def_file(name); + return posixacl_sys_acl_get_fd(handle, fsp, fd); } - -int sys_acl_free_text(char *text) + +int sys_acl_set_file(vfs_handle_struct *handle, + const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d) { - return acl_free(text); + return posixacl_sys_acl_set_file(handle, name, type, acl_d); } - -int sys_acl_free_acl(SMB_ACL_T acl_d) + +int sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, + int fd, SMB_ACL_T acl_d) { - if (acl_d->freeaclp) { - acl_free(acl_d->aclp); - } - acl_free(acl_d); - return 0; + return posixacl_sys_acl_set_fd(handle, fsp, fd, acl_d); } -int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype) +int sys_acl_delete_def_file(vfs_handle_struct *handle, + const char *path) { - return 0; + return posixacl_sys_acl_delete_def_file(handle, path); } #elif defined(HAVE_AIX_ACLS) -/* Donated by Medha Date, mdate@austin.ibm.com, for IBM */ - -int sys_acl_get_entry( SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p) +SMB_ACL_T sys_acl_get_file(vfs_handle_struct *handle, + const char *path_p, SMB_ACL_TYPE_T type) { - struct acl_entry_link *link; - struct new_acl_entry *entry; - int keep_going; - - DEBUG(10,("This is the count: %d\n",theacl->count)); - - /* Check if count was previously set to -1. * - * If it was, that means we reached the end * - * of the acl last time. */ - if(theacl->count == -1) - return(0); - - link = theacl; - /* To get to the next acl, traverse linked list until index * - * of acl matches the count we are keeping. This count is * - * incremented each time we return an acl entry. */ - - for(keep_going = 0; keep_going < theacl->count; keep_going++) - link = link->nextp; - - entry = *entry_p = link->entryp; - - DEBUG(10,("*entry_p is %d\n",entry_p)); - DEBUG(10,("*entry_p->ace_access is %d\n",entry->ace_access)); - - /* Increment count */ - theacl->count++; - if(link->nextp == NULL) - theacl->count = -1; - - return(1); + return aixacl_sys_acl_get_file(handle, path_p, type); } -int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p) +SMB_ACL_T sys_acl_get_fd(vfs_handle_struct *handle, files_struct *fsp, int fd) { - /* Initialize tag type */ - - *tag_type_p = -1; - DEBUG(10,("the tagtype is %d\n",entry_d->ace_id->id_type)); - - /* Depending on what type of entry we have, * - * return tag type. */ - switch(entry_d->ace_id->id_type) { - case ACEID_USER: - *tag_type_p = SMB_ACL_USER; - break; - case ACEID_GROUP: - *tag_type_p = SMB_ACL_GROUP; - break; - - case SMB_ACL_USER_OBJ: - case SMB_ACL_GROUP_OBJ: - case SMB_ACL_OTHER: - *tag_type_p = entry_d->ace_id->id_type; - break; - - default: - return(-1); - } - - return(0); + return aixacl_sys_acl_get_fd(handle, fsp, fd); } -int sys_acl_get_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p) +int sys_acl_set_file(vfs_handle_struct *handle, + const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d) { - DEBUG(10,("Starting AIX sys_acl_get_permset\n")); - *permset_p = &entry_d->ace_access; - DEBUG(10,("**permset_p is %d\n",**permset_p)); - if(!(**permset_p & S_IXUSR) && - !(**permset_p & S_IWUSR) && - !(**permset_p & S_IRUSR) && - (**permset_p != 0)) - return(-1); - - DEBUG(10,("Ending AIX sys_acl_get_permset\n")); - return(0); + return aixacl_sys_acl_set_file(handle, name, type, acl_d); } -void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d) +int sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, + int fd, SMB_ACL_T acl_d) { - return(entry_d->ace_id->id_data); + return aixacl_sys_acl_set_fd(handle, fsp, fd, acl_d); } -SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type) +int sys_acl_delete_def_file(vfs_handle_struct *handle, + const char *path) { - struct acl *file_acl = (struct acl *)NULL; - struct acl_entry *acl_entry; - struct new_acl_entry *new_acl_entry; - struct ace_id *idp; - struct acl_entry_link *acl_entry_link; - struct acl_entry_link *acl_entry_link_head; - int i; - int rc = 0; - uid_t user_id; - - /* AIX has no DEFAULT */ - if ( type == SMB_ACL_TYPE_DEFAULT ) - return NULL; - - /* Get the acl using statacl */ - - DEBUG(10,("Entering sys_acl_get_file\n")); - DEBUG(10,("path_p is %s\n",path_p)); - - file_acl = (struct acl *)SMB_MALLOC(BUFSIZ); - - if(file_acl == NULL) { - errno=ENOMEM; - DEBUG(0,("Error in AIX sys_acl_get_file: %d\n",errno)); - return(NULL); - } - - memset(file_acl,0,BUFSIZ); - - rc = statacl((char *)path_p,0,file_acl,BUFSIZ); - if(rc == -1) { - DEBUG(0,("statacl returned %d with errno %d\n",rc,errno)); - SAFE_FREE(file_acl); - return(NULL); - } - - DEBUG(10,("Got facl and returned it\n")); - - /* Point to the first acl entry in the acl */ - acl_entry = file_acl->acl_ext; - - /* Begin setting up the head of the linked list * - * that will be used for the storing the acl * - * in a way that is useful for the posix_acls.c * - * code. */ - - acl_entry_link_head = acl_entry_link = sys_acl_init(0); - if(acl_entry_link_head == NULL) - return(NULL); - - acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry); - if(acl_entry_link->entryp == NULL) { - SAFE_FREE(file_acl); - errno = ENOMEM; - DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno)); - return(NULL); - } - - DEBUG(10,("acl_entry is %d\n",acl_entry)); - DEBUG(10,("acl_last(file_acl) id %d\n",acl_last(file_acl))); - - /* Check if the extended acl bit is on. * - * If it isn't, do not show the * - * contents of the acl since AIX intends * - * the extended info to remain unused */ - - if(file_acl->acl_mode & S_IXACL){ - /* while we are not pointing to the very end */ - while(acl_entry < acl_last(file_acl)) { - /* before we malloc anything, make sure this is */ - /* a valid acl entry and one that we want to map */ - idp = id_nxt(acl_entry->ace_id); - if((acl_entry->ace_type == ACC_SPECIFY || - (acl_entry->ace_type == ACC_PERMIT)) && (idp != id_last(acl_entry))) { - acl_entry = acl_nxt(acl_entry); - continue; - } - - idp = acl_entry->ace_id; - - /* Check if this is the first entry in the linked list. * - * The first entry needs to keep prevp pointing to NULL * - * and already has entryp allocated. */ - - if(acl_entry_link_head->count != 0) { - acl_entry_link->nextp = SMB_MALLOC_P(struct acl_entry_link); - - if(acl_entry_link->nextp == NULL) { - SAFE_FREE(file_acl); - errno = ENOMEM; - DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno)); - return(NULL); - } - - acl_entry_link->nextp->prevp = acl_entry_link; - acl_entry_link = acl_entry_link->nextp; - acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry); - if(acl_entry_link->entryp == NULL) { - SAFE_FREE(file_acl); - errno = ENOMEM; - DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno)); - return(NULL); - } - acl_entry_link->nextp = NULL; - } - - acl_entry_link->entryp->ace_len = acl_entry->ace_len; - - /* Don't really need this since all types are going * - * to be specified but, it's better than leaving it 0 */ - - acl_entry_link->entryp->ace_type = acl_entry->ace_type; - - acl_entry_link->entryp->ace_access = acl_entry->ace_access; - - memcpy(acl_entry_link->entryp->ace_id,idp,sizeof(struct ace_id)); - - /* The access in the acl entries must be left shifted by * - * three bites, because they will ultimately be compared * - * to S_IRUSR, S_IWUSR, and S_IXUSR. */ - - switch(acl_entry->ace_type){ - case ACC_PERMIT: - case ACC_SPECIFY: - acl_entry_link->entryp->ace_access = acl_entry->ace_access; - acl_entry_link->entryp->ace_access <<= 6; - acl_entry_link_head->count++; - break; - case ACC_DENY: - /* Since there is no way to return a DENY acl entry * - * change to PERMIT and then shift. */ - DEBUG(10,("acl_entry->ace_access is %d\n",acl_entry->ace_access)); - acl_entry_link->entryp->ace_access = ~acl_entry->ace_access & 7; - DEBUG(10,("acl_entry_link->entryp->ace_access is %d\n",acl_entry_link->entryp->ace_access)); - acl_entry_link->entryp->ace_access <<= 6; - acl_entry_link_head->count++; - break; - default: - return(0); - } - - DEBUG(10,("acl_entry = %d\n",acl_entry)); - DEBUG(10,("The ace_type is %d\n",acl_entry->ace_type)); - - acl_entry = acl_nxt(acl_entry); - } - } /* end of if enabled */ - - /* Since owner, group, other acl entries are not * - * part of the acl entries in an acl, they must * - * be dummied up to become part of the list. */ - - for( i = 1; i < 4; i++) { - DEBUG(10,("i is %d\n",i)); - if(acl_entry_link_head->count != 0) { - acl_entry_link->nextp = SMB_MALLOC_P(struct acl_entry_link); - if(acl_entry_link->nextp == NULL) { - SAFE_FREE(file_acl); - errno = ENOMEM; - DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno)); - return(NULL); - } - - acl_entry_link->nextp->prevp = acl_entry_link; - acl_entry_link = acl_entry_link->nextp; - acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry); - if(acl_entry_link->entryp == NULL) { - SAFE_FREE(file_acl); - errno = ENOMEM; - DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno)); - return(NULL); - } - } - - acl_entry_link->nextp = NULL; - - new_acl_entry = acl_entry_link->entryp; - idp = new_acl_entry->ace_id; - - new_acl_entry->ace_len = sizeof(struct acl_entry); - new_acl_entry->ace_type = ACC_PERMIT; - idp->id_len = sizeof(struct ace_id); - DEBUG(10,("idp->id_len = %d\n",idp->id_len)); - memset(idp->id_data,0,sizeof(uid_t)); - - switch(i) { - case 2: - new_acl_entry->ace_access = file_acl->g_access << 6; - idp->id_type = SMB_ACL_GROUP_OBJ; - break; - - case 3: - new_acl_entry->ace_access = file_acl->o_access << 6; - idp->id_type = SMB_ACL_OTHER; - break; - - case 1: - new_acl_entry->ace_access = file_acl->u_access << 6; - idp->id_type = SMB_ACL_USER_OBJ; - break; - - default: - return(NULL); - - } - - acl_entry_link_head->count++; - DEBUG(10,("new_acl_entry->ace_access = %d\n",new_acl_entry->ace_access)); - } - - acl_entry_link_head->count = 0; - SAFE_FREE(file_acl); - - return(acl_entry_link_head); + return aixacl_sys_acl_delete_def_file(handle, path); } -SMB_ACL_T sys_acl_get_fd(int fd) -{ - struct acl *file_acl = (struct acl *)NULL; - struct acl_entry *acl_entry; - struct new_acl_entry *new_acl_entry; - struct ace_id *idp; - struct acl_entry_link *acl_entry_link; - struct acl_entry_link *acl_entry_link_head; - int i; - int rc = 0; - uid_t user_id; - - /* Get the acl using fstatacl */ - - DEBUG(10,("Entering sys_acl_get_fd\n")); - DEBUG(10,("fd is %d\n",fd)); - file_acl = (struct acl *)SMB_MALLOC(BUFSIZ); - - if(file_acl == NULL) { - errno=ENOMEM; - DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno)); - return(NULL); - } - - memset(file_acl,0,BUFSIZ); - - rc = fstatacl(fd,0,file_acl,BUFSIZ); - if(rc == -1) { - DEBUG(0,("The fstatacl call returned %d with errno %d\n",rc,errno)); - SAFE_FREE(file_acl); - return(NULL); - } - - DEBUG(10,("Got facl and returned it\n")); - - /* Point to the first acl entry in the acl */ - - acl_entry = file_acl->acl_ext; - /* Begin setting up the head of the linked list * - * that will be used for the storing the acl * - * in a way that is useful for the posix_acls.c * - * code. */ - - acl_entry_link_head = acl_entry_link = sys_acl_init(0); - if(acl_entry_link_head == NULL){ - SAFE_FREE(file_acl); - return(NULL); - } - - acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry); - - if(acl_entry_link->entryp == NULL) { - errno = ENOMEM; - DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno)); - SAFE_FREE(file_acl); - return(NULL); - } - - DEBUG(10,("acl_entry is %d\n",acl_entry)); - DEBUG(10,("acl_last(file_acl) id %d\n",acl_last(file_acl))); - - /* Check if the extended acl bit is on. * - * If it isn't, do not show the * - * contents of the acl since AIX intends * - * the extended info to remain unused */ - - if(file_acl->acl_mode & S_IXACL){ - /* while we are not pointing to the very end */ - while(acl_entry < acl_last(file_acl)) { - /* before we malloc anything, make sure this is */ - /* a valid acl entry and one that we want to map */ - - idp = id_nxt(acl_entry->ace_id); - if((acl_entry->ace_type == ACC_SPECIFY || - (acl_entry->ace_type == ACC_PERMIT)) && (idp != id_last(acl_entry))) { - acl_entry = acl_nxt(acl_entry); - continue; - } - - idp = acl_entry->ace_id; - - /* Check if this is the first entry in the linked list. * - * The first entry needs to keep prevp pointing to NULL * - * and already has entryp allocated. */ - - if(acl_entry_link_head->count != 0) { - acl_entry_link->nextp = SMB_MALLOC_P(struct acl_entry_link); - if(acl_entry_link->nextp == NULL) { - errno = ENOMEM; - DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno)); - SAFE_FREE(file_acl); - return(NULL); - } - acl_entry_link->nextp->prevp = acl_entry_link; - acl_entry_link = acl_entry_link->nextp; - acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry); - if(acl_entry_link->entryp == NULL) { - errno = ENOMEM; - DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno)); - SAFE_FREE(file_acl); - return(NULL); - } - - acl_entry_link->nextp = NULL; - } - - acl_entry_link->entryp->ace_len = acl_entry->ace_len; - - /* Don't really need this since all types are going * - * to be specified but, it's better than leaving it 0 */ - - acl_entry_link->entryp->ace_type = acl_entry->ace_type; - acl_entry_link->entryp->ace_access = acl_entry->ace_access; - - memcpy(acl_entry_link->entryp->ace_id, idp, sizeof(struct ace_id)); - - /* The access in the acl entries must be left shifted by * - * three bites, because they will ultimately be compared * - * to S_IRUSR, S_IWUSR, and S_IXUSR. */ - - switch(acl_entry->ace_type){ - case ACC_PERMIT: - case ACC_SPECIFY: - acl_entry_link->entryp->ace_access = acl_entry->ace_access; - acl_entry_link->entryp->ace_access <<= 6; - acl_entry_link_head->count++; - break; - case ACC_DENY: - /* Since there is no way to return a DENY acl entry * - * change to PERMIT and then shift. */ - DEBUG(10,("acl_entry->ace_access is %d\n",acl_entry->ace_access)); - acl_entry_link->entryp->ace_access = ~acl_entry->ace_access & 7; - DEBUG(10,("acl_entry_link->entryp->ace_access is %d\n",acl_entry_link->entryp->ace_access)); - acl_entry_link->entryp->ace_access <<= 6; - acl_entry_link_head->count++; - break; - default: - return(0); - } - - DEBUG(10,("acl_entry = %d\n",acl_entry)); - DEBUG(10,("The ace_type is %d\n",acl_entry->ace_type)); - - acl_entry = acl_nxt(acl_entry); - } - } /* end of if enabled */ - - /* Since owner, group, other acl entries are not * - * part of the acl entries in an acl, they must * - * be dummied up to become part of the list. */ - - for( i = 1; i < 4; i++) { - DEBUG(10,("i is %d\n",i)); - if(acl_entry_link_head->count != 0){ - acl_entry_link->nextp = SMB_MALLOC_P(struct acl_entry_link); - if(acl_entry_link->nextp == NULL) { - errno = ENOMEM; - DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno)); - SAFE_FREE(file_acl); - return(NULL); - } - - acl_entry_link->nextp->prevp = acl_entry_link; - acl_entry_link = acl_entry_link->nextp; - acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry); - - if(acl_entry_link->entryp == NULL) { - SAFE_FREE(file_acl); - errno = ENOMEM; - DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno)); - return(NULL); - } - } - - acl_entry_link->nextp = NULL; - - new_acl_entry = acl_entry_link->entryp; - idp = new_acl_entry->ace_id; - - new_acl_entry->ace_len = sizeof(struct acl_entry); - new_acl_entry->ace_type = ACC_PERMIT; - idp->id_len = sizeof(struct ace_id); - DEBUG(10,("idp->id_len = %d\n",idp->id_len)); - memset(idp->id_data,0,sizeof(uid_t)); - - switch(i) { - case 2: - new_acl_entry->ace_access = file_acl->g_access << 6; - idp->id_type = SMB_ACL_GROUP_OBJ; - break; - - case 3: - new_acl_entry->ace_access = file_acl->o_access << 6; - idp->id_type = SMB_ACL_OTHER; - break; - - case 1: - new_acl_entry->ace_access = file_acl->u_access << 6; - idp->id_type = SMB_ACL_USER_OBJ; - break; - - default: - return(NULL); - } - - acl_entry_link_head->count++; - DEBUG(10,("new_acl_entry->ace_access = %d\n",new_acl_entry->ace_access)); - } - - acl_entry_link_head->count = 0; - SAFE_FREE(file_acl); +#elif defined(HAVE_TRU64_ACLS) - return(acl_entry_link_head); -} - -int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset) +SMB_ACL_T sys_acl_get_file(vfs_handle_struct *handle, + const char *path_p, SMB_ACL_TYPE_T type) { - *permset = *permset & ~0777; - return(0); + return tru64acl_sys_acl_get_file(handle, path_p, type); } -int sys_acl_add_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm) +SMB_ACL_T sys_acl_get_fd(vfs_handle_struct *handle, files_struct *fsp, int fd) { - if((perm != 0) && - (perm & (S_IXUSR | S_IWUSR | S_IRUSR)) == 0) - return(-1); - - *permset |= perm; - DEBUG(10,("This is the permset now: %d\n",*permset)); - return(0); + return tru64acl_sys_acl_get_fd(handle, fsp, fd); } -char *sys_acl_to_text( SMB_ACL_T theacl, ssize_t *plen) +int sys_acl_set_file(vfs_handle_struct *handle, + const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d) { - return(NULL); + return tru64acl_sys_acl_set_file(handle, name, type, acl_d); } -SMB_ACL_T sys_acl_init( int count) +int sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, + int fd, SMB_ACL_T acl_d) { - struct acl_entry_link *theacl = NULL; - - DEBUG(10,("Entering sys_acl_init\n")); - - theacl = SMB_MALLOC_P(struct acl_entry_link); - if(theacl == NULL) { - errno = ENOMEM; - DEBUG(0,("Error in sys_acl_init is %d\n",errno)); - return(NULL); - } - - theacl->count = 0; - theacl->nextp = NULL; - theacl->prevp = NULL; - theacl->entryp = NULL; - DEBUG(10,("Exiting sys_acl_init\n")); - return(theacl); + return tru64acl_sys_acl_set_fd(handle, fsp, fd, acl_d); } -int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry) +int sys_acl_delete_def_file(vfs_handle_struct *handle, + const char *path) { - struct acl_entry_link *theacl; - struct acl_entry_link *acl_entryp; - struct acl_entry_link *temp_entry; - int counting; - - DEBUG(10,("Entering the sys_acl_create_entry\n")); - - theacl = acl_entryp = *pacl; - - /* Get to the end of the acl before adding entry */ - - for(counting=0; counting < theacl->count; counting++){ - DEBUG(10,("The acl_entryp is %d\n",acl_entryp)); - temp_entry = acl_entryp; - acl_entryp = acl_entryp->nextp; - } - - if(theacl->count != 0){ - temp_entry->nextp = acl_entryp = SMB_MALLOC_P(struct acl_entry_link); - if(acl_entryp == NULL) { - errno = ENOMEM; - DEBUG(0,("Error in sys_acl_create_entry is %d\n",errno)); - return(-1); - } - - DEBUG(10,("The acl_entryp is %d\n",acl_entryp)); - acl_entryp->prevp = temp_entry; - DEBUG(10,("The acl_entryp->prevp is %d\n",acl_entryp->prevp)); - } - - *pentry = acl_entryp->entryp = SMB_MALLOC_P(struct new_acl_entry); - if(*pentry == NULL) { - errno = ENOMEM; - DEBUG(0,("Error in sys_acl_create_entry is %d\n",errno)); - return(-1); - } - - memset(*pentry,0,sizeof(struct new_acl_entry)); - acl_entryp->entryp->ace_len = sizeof(struct acl_entry); - acl_entryp->entryp->ace_type = ACC_PERMIT; - acl_entryp->entryp->ace_id->id_len = sizeof(struct ace_id); - acl_entryp->nextp = NULL; - theacl->count++; - DEBUG(10,("Exiting sys_acl_create_entry\n")); - return(0); + return tru64acl_sys_acl_delete_def_file(handle, path); } -int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype) -{ - DEBUG(10,("Starting AIX sys_acl_set_tag_type\n")); - entry->ace_id->id_type = tagtype; - DEBUG(10,("The tag type is %d\n",entry->ace_id->id_type)); - DEBUG(10,("Ending AIX sys_acl_set_tag_type\n")); -} +#elif defined(HAVE_SOLARIS_ACLS) || defined(HAVE_UNIXWARE_ACLS) -int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual) +SMB_ACL_T sys_acl_get_file(vfs_handle_struct *handle, + const char *path_p, SMB_ACL_TYPE_T type) { - DEBUG(10,("Starting AIX sys_acl_set_qualifier\n")); - memcpy(entry->ace_id->id_data,qual,sizeof(uid_t)); - DEBUG(10,("Ending AIX sys_acl_set_qualifier\n")); - return(0); + return solarisacl_sys_acl_get_file(handle, path_p, type); } -int sys_acl_set_permset( SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset) +SMB_ACL_T sys_acl_get_fd(vfs_handle_struct *handle, files_struct *fsp, int fd) { - DEBUG(10,("Starting AIX sys_acl_set_permset\n")); - if(!(*permset & S_IXUSR) && - !(*permset & S_IWUSR) && - !(*permset & S_IRUSR) && - (*permset != 0)) - return(-1); - - entry->ace_access = *permset; - DEBUG(10,("entry->ace_access = %d\n",entry->ace_access)); - DEBUG(10,("Ending AIX sys_acl_set_permset\n")); - return(0); + return solarisacl_sys_acl_get_fd(handle, fsp, fd); } -int sys_acl_valid( SMB_ACL_T theacl ) +int sys_acl_set_file(vfs_handle_struct *handle, + const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d) { - int user_obj = 0; - int group_obj = 0; - int other_obj = 0; - struct acl_entry_link *acl_entry; - - for(acl_entry=theacl; acl_entry != NULL; acl_entry = acl_entry->nextp) { - user_obj += (acl_entry->entryp->ace_id->id_type == SMB_ACL_USER_OBJ); - group_obj += (acl_entry->entryp->ace_id->id_type == SMB_ACL_GROUP_OBJ); - other_obj += (acl_entry->entryp->ace_id->id_type == SMB_ACL_OTHER); - } - - DEBUG(10,("user_obj=%d, group_obj=%d, other_obj=%d\n",user_obj,group_obj,other_obj)); - - if(user_obj != 1 || group_obj != 1 || other_obj != 1) - return(-1); - - return(0); + return solarisacl_sys_acl_set_file(handle, name, type, acl_d); } -int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl) +int sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, + int fd, SMB_ACL_T acl_d) { - struct acl_entry_link *acl_entry_link = NULL; - struct acl *file_acl = NULL; - struct acl *file_acl_temp = NULL; - struct acl_entry *acl_entry = NULL; - struct ace_id *ace_id = NULL; - uint id_type; - uint ace_access; - uint user_id; - uint acl_length; - uint rc; - - DEBUG(10,("Entering sys_acl_set_file\n")); - DEBUG(10,("File name is %s\n",name)); - - /* AIX has no default ACL */ - if(acltype == SMB_ACL_TYPE_DEFAULT) - return(0); - - acl_length = BUFSIZ; - file_acl = (struct acl *)SMB_MALLOC(BUFSIZ); - - if(file_acl == NULL) { - errno = ENOMEM; - DEBUG(0,("Error in sys_acl_set_file is %d\n",errno)); - return(-1); - } - - memset(file_acl,0,BUFSIZ); - - file_acl->acl_len = ACL_SIZ; - file_acl->acl_mode = S_IXACL; - - for(acl_entry_link=theacl; acl_entry_link != NULL; acl_entry_link = acl_entry_link->nextp) { - acl_entry_link->entryp->ace_access >>= 6; - id_type = acl_entry_link->entryp->ace_id->id_type; - - switch(id_type) { - case SMB_ACL_USER_OBJ: - file_acl->u_access = acl_entry_link->entryp->ace_access; - continue; - case SMB_ACL_GROUP_OBJ: - file_acl->g_access = acl_entry_link->entryp->ace_access; - continue; - case SMB_ACL_OTHER: - file_acl->o_access = acl_entry_link->entryp->ace_access; - continue; - case SMB_ACL_MASK: - continue; - } - - if((file_acl->acl_len + sizeof(struct acl_entry)) > acl_length) { - acl_length += sizeof(struct acl_entry); - file_acl_temp = (struct acl *)SMB_MALLOC(acl_length); - if(file_acl_temp == NULL) { - SAFE_FREE(file_acl); - errno = ENOMEM; - DEBUG(0,("Error in sys_acl_set_file is %d\n",errno)); - return(-1); - } - - memcpy(file_acl_temp,file_acl,file_acl->acl_len); - SAFE_FREE(file_acl); - file_acl = file_acl_temp; - } - - acl_entry = (struct acl_entry *)((char *)file_acl + file_acl->acl_len); - file_acl->acl_len += sizeof(struct acl_entry); - acl_entry->ace_len = acl_entry_link->entryp->ace_len; - acl_entry->ace_access = acl_entry_link->entryp->ace_access; - - /* In order to use this, we'll need to wait until we can get denies */ - /* if(!acl_entry->ace_access && acl_entry->ace_type == ACC_PERMIT) - acl_entry->ace_type = ACC_SPECIFY; */ - - acl_entry->ace_type = ACC_SPECIFY; - - ace_id = acl_entry->ace_id; - - ace_id->id_type = acl_entry_link->entryp->ace_id->id_type; - DEBUG(10,("The id type is %d\n",ace_id->id_type)); - ace_id->id_len = acl_entry_link->entryp->ace_id->id_len; - memcpy(&user_id, acl_entry_link->entryp->ace_id->id_data, sizeof(uid_t)); - memcpy(acl_entry->ace_id->id_data, &user_id, sizeof(uid_t)); - } - - rc = chacl(name,file_acl,file_acl->acl_len); - DEBUG(10,("errno is %d\n",errno)); - DEBUG(10,("return code is %d\n",rc)); - SAFE_FREE(file_acl); - DEBUG(10,("Exiting the sys_acl_set_file\n")); - return(rc); + return solarisacl_sys_acl_set_fd(handle, fsp, fd, acl_d); } -int sys_acl_set_fd( int fd, SMB_ACL_T theacl) +int sys_acl_delete_def_file(vfs_handle_struct *handle, + const char *path) { - struct acl_entry_link *acl_entry_link = NULL; - struct acl *file_acl = NULL; - struct acl *file_acl_temp = NULL; - struct acl_entry *acl_entry = NULL; - struct ace_id *ace_id = NULL; - uint id_type; - uint user_id; - uint acl_length; - uint rc; - - DEBUG(10,("Entering sys_acl_set_fd\n")); - acl_length = BUFSIZ; - file_acl = (struct acl *)SMB_MALLOC(BUFSIZ); - - if(file_acl == NULL) { - errno = ENOMEM; - DEBUG(0,("Error in sys_acl_set_fd is %d\n",errno)); - return(-1); - } - - memset(file_acl,0,BUFSIZ); - - file_acl->acl_len = ACL_SIZ; - file_acl->acl_mode = S_IXACL; - - for(acl_entry_link=theacl; acl_entry_link != NULL; acl_entry_link = acl_entry_link->nextp) { - acl_entry_link->entryp->ace_access >>= 6; - id_type = acl_entry_link->entryp->ace_id->id_type; - DEBUG(10,("The id_type is %d\n",id_type)); - - switch(id_type) { - case SMB_ACL_USER_OBJ: - file_acl->u_access = acl_entry_link->entryp->ace_access; - continue; - case SMB_ACL_GROUP_OBJ: - file_acl->g_access = acl_entry_link->entryp->ace_access; - continue; - case SMB_ACL_OTHER: - file_acl->o_access = acl_entry_link->entryp->ace_access; - continue; - case SMB_ACL_MASK: - continue; - } - - if((file_acl->acl_len + sizeof(struct acl_entry)) > acl_length) { - acl_length += sizeof(struct acl_entry); - file_acl_temp = (struct acl *)SMB_MALLOC(acl_length); - if(file_acl_temp == NULL) { - SAFE_FREE(file_acl); - errno = ENOMEM; - DEBUG(0,("Error in sys_acl_set_fd is %d\n",errno)); - return(-1); - } - - memcpy(file_acl_temp,file_acl,file_acl->acl_len); - SAFE_FREE(file_acl); - file_acl = file_acl_temp; - } - - acl_entry = (struct acl_entry *)((char *)file_acl + file_acl->acl_len); - file_acl->acl_len += sizeof(struct acl_entry); - acl_entry->ace_len = acl_entry_link->entryp->ace_len; - acl_entry->ace_access = acl_entry_link->entryp->ace_access; - - /* In order to use this, we'll need to wait until we can get denies */ - /* if(!acl_entry->ace_access && acl_entry->ace_type == ACC_PERMIT) - acl_entry->ace_type = ACC_SPECIFY; */ - - acl_entry->ace_type = ACC_SPECIFY; - - ace_id = acl_entry->ace_id; - - ace_id->id_type = acl_entry_link->entryp->ace_id->id_type; - DEBUG(10,("The id type is %d\n",ace_id->id_type)); - ace_id->id_len = acl_entry_link->entryp->ace_id->id_len; - memcpy(&user_id, acl_entry_link->entryp->ace_id->id_data, sizeof(uid_t)); - memcpy(ace_id->id_data, &user_id, sizeof(uid_t)); - } - - rc = fchacl(fd,file_acl,file_acl->acl_len); - DEBUG(10,("errno is %d\n",errno)); - DEBUG(10,("return code is %d\n",rc)); - SAFE_FREE(file_acl); - DEBUG(10,("Exiting sys_acl_set_fd\n")); - return(rc); + return solarisacl_sys_acl_delete_def_file(handle, path); } -int sys_acl_delete_def_file(const char *name) -{ - /* AIX has no default ACL */ - return 0; -} +#elif defined(HAVE_HPUX_ACLS) -int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm) +SMB_ACL_T sys_acl_get_file(vfs_handle_struct *handle, + const char *path_p, SMB_ACL_TYPE_T type) { - return(*permset & perm); + return hpuxacl_sys_acl_get_file(handle, path_p, type); } -int sys_acl_free_text(char *text) +SMB_ACL_T sys_acl_get_fd(vfs_handle_struct *handle, files_struct *fsp, int fd) { - return(0); + return hpuxacl_sys_acl_get_fd(handle, fsp, fd); } -int sys_acl_free_acl(SMB_ACL_T posix_acl) +int sys_acl_set_file(vfs_handle_struct *handle, + const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d) { - struct acl_entry_link *acl_entry_link; - - for(acl_entry_link = posix_acl->nextp; acl_entry_link->nextp != NULL; acl_entry_link = acl_entry_link->nextp) { - SAFE_FREE(acl_entry_link->prevp->entryp); - SAFE_FREE(acl_entry_link->prevp); - } - - SAFE_FREE(acl_entry_link->prevp->entryp); - SAFE_FREE(acl_entry_link->prevp); - SAFE_FREE(acl_entry_link->entryp); - SAFE_FREE(acl_entry_link); - - return(0); + return hpuxacl_sys_acl_set_file(handle, name, type, acl_d); } -int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype) +int sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, + int fd, SMB_ACL_T acl_d) { - return(0); + return hpuxacl_sys_acl_set_fd(handle, fsp, fd, acl_d); } -#else /* No ACLs. */ - -int sys_acl_get_entry( SMB_ACL_T the_acl, int entry_id, SMB_ACL_ENTRY_T *entry_p) +int sys_acl_delete_def_file(vfs_handle_struct *handle, + const char *path) { - errno = ENOSYS; - return -1; + return hpuxacl_sys_acl_delete_def_file(handle, path); } -int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p) -{ - errno = ENOSYS; - return -1; -} +#elif defined(HAVE_IRIX_ACLS) -int sys_acl_get_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p) +SMB_ACL_T sys_acl_get_file(vfs_handle_struct *handle, + const char *path_p, SMB_ACL_TYPE_T type) { - errno = ENOSYS; - return -1; + return irixacl_sys_acl_get_file(handle, path_p, type); } -void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d) +SMB_ACL_T sys_acl_get_fd(vfs_handle_struct *handle, files_struct *fsp, int fd) { - errno = ENOSYS; - return NULL; + return irixacl_sys_acl_get_fd(handle, fsp, fd); } -SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type) +int sys_acl_set_file(vfs_handle_struct *handle, + const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d) { - errno = ENOSYS; - return (SMB_ACL_T)NULL; + return irixacl_sys_acl_set_file(handle, name, type, acl_d); } -SMB_ACL_T sys_acl_get_fd(int fd) +int sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, + int fd, SMB_ACL_T acl_d) { - errno = ENOSYS; - return (SMB_ACL_T)NULL; + return irixacl_sys_acl_set_fd(handle, fsp, fd, acl_d); } -int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset) +int sys_acl_delete_def_file(vfs_handle_struct *handle, + const char *path) { - errno = ENOSYS; - return -1; + return irixacl_sys_acl_delete_def_file(handle, path); } -int sys_acl_add_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm) -{ - errno = ENOSYS; - return -1; -} - -int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm) -{ - errno = ENOSYS; - return (permset & perm) ? 1 : 0; -} +#else /* No ACLs. */ -char *sys_acl_to_text( SMB_ACL_T the_acl, ssize_t *plen) +SMB_ACL_T sys_acl_get_file(vfs_handle_struct *handle, + const char *path_p, SMB_ACL_TYPE_T type) { - errno = ENOSYS; + errno = ENOTSUP; return NULL; } -int sys_acl_free_text(char *text) -{ - errno = ENOSYS; - return -1; -} - -SMB_ACL_T sys_acl_init( int count) +SMB_ACL_T sys_acl_get_fd(vfs_handle_struct *handle, files_struct *fsp, int fd) { - errno = ENOSYS; + errno = ENOTSUP; return NULL; } -int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry) +int sys_acl_set_file(vfs_handle_struct *handle, + const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d) { - errno = ENOSYS; + errno = ENOTSUP; return -1; } -int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype) +int sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, + int fd, SMB_ACL_T acl_d) { - errno = ENOSYS; + errno = ENOTSUP; return -1; } -int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual) +int sys_acl_delete_def_file(vfs_handle_struct *handle, + const char *path) { - errno = ENOSYS; + errno = ENOTSUP; return -1; } -int sys_acl_set_permset( SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset) -{ - errno = ENOSYS; - return -1; -} - -int sys_acl_valid( SMB_ACL_T theacl ) -{ - errno = ENOSYS; - return -1; -} - -int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl) -{ - errno = ENOSYS; - return -1; -} - -int sys_acl_set_fd( int fd, SMB_ACL_T theacl) -{ - errno = ENOSYS; - return -1; -} - -int sys_acl_delete_def_file(const char *name) -{ - errno = ENOSYS; - return -1; -} - -int sys_acl_free_acl(SMB_ACL_T the_acl) -{ - errno = ENOSYS; - return -1; -} - -int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype) -{ - errno = ENOSYS; - return -1; -} - -#endif /* No ACLs. */ +#endif /************************************************************************ Deliberately outside the ACL defines. Return 1 if this is a "no acls" diff --git a/source3/modules/vfs_aixacl.c b/source3/modules/vfs_aixacl.c new file mode 100644 index 0000000000..4a1fcc59a3 --- /dev/null +++ b/source3/modules/vfs_aixacl.c @@ -0,0 +1,215 @@ +/* + Unix SMB/Netbios implementation. + VFS module to get and set posix acls + Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2006 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +extern SMB_ACL_T aixacl_to_smbacl( struct acl *file_acl); +extern struct acl *aixacl_smb_to_aixacl(SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl); + +SMB_ACL_T aixacl_sys_acl_get_file(vfs_handle_struct *handle, + const char *path_p, + SMB_ACL_TYPE_T type) +{ + struct acl *file_acl = (struct acl *)NULL; + struct smb_acl_t *result = (struct smb_acl_t *)NULL; + + int rc = 0; + uid_t user_id; + + /* AIX has no DEFAULT */ + if ( type == SMB_ACL_TYPE_DEFAULT ) + return NULL; + + /* Get the acl using statacl */ + + DEBUG(10,("Entering AIX sys_acl_get_file\n")); + DEBUG(10,("path_p is %s\n",path_p)); + + file_acl = (struct acl *)SMB_MALLOC(BUFSIZ); + + if(file_acl == NULL) { + errno=ENOMEM; + DEBUG(0,("Error in AIX sys_acl_get_file: %d\n",errno)); + return(NULL); + } + + memset(file_acl,0,BUFSIZ); + + rc = statacl((char *)path_p,0,file_acl,BUFSIZ); + if( (rc == -1) && (errno == ENOSPC)) { + struct acl *new_acl = SMB_MALLOC(file_acl->acl_len + sizeof(struct acl)); + if( new_acl == NULL) { + SAFE_FREE(file_acl); + errno = ENOMEM; + return NULL; + } + file_acl = new_acl; + rc = statacl((char *)path_p,0,file_acl,file_acl->acl_len+sizeof(struct acl)); + if( rc == -1) { + DEBUG(0,("statacl returned %d with errno %d\n",rc,errno)); + SAFE_FREE(file_acl); + return(NULL); + } + } + + DEBUG(10,("Got facl and returned it\n")); + + + result = aixacl_to_smbacl(file_acl); + SAFE_FREE(file_acl); + return result; + + /*errno = ENOTSUP; + return NULL;*/ +} + +SMB_ACL_T aixacl_sys_acl_get_fd(vfs_handle_struct *handle, + files_struct *fsp, + int fd) +{ + + struct acl *file_acl = (struct acl *)NULL; + struct smb_acl_t *result = (struct smb_acl_t *)NULL; + + int rc = 0; + uid_t user_id; + + /* Get the acl using fstatacl */ + + DEBUG(10,("Entering AIX sys_acl_get_fd\n")); + DEBUG(10,("fd is %d\n",fd)); + file_acl = (struct acl *)SMB_MALLOC(BUFSIZ); + + if(file_acl == NULL) { + errno=ENOMEM; + DEBUG(0,("Error in AIX sys_acl_get_fd is %d\n",errno)); + return(NULL); + } + + memset(file_acl,0,BUFSIZ); + + rc = fstatacl(fd,0,file_acl,BUFSIZ); + if( (rc == -1) && (errno == ENOSPC)) { + struct acl *new_acl = SMB_MALLOC(file_acl->acl_len + sizeof(struct acl)); + if( new_acl == NULL) { + SAFE_FREE(file_acl); + errno = ENOMEM; + return NULL; + } + file_acl = new_acl; + rc = fstatacl(fd,0,file_acl,file_acl->acl_len + sizeof(struct acl)); + if( rc == -1) { + DEBUG(0,("fstatacl returned %d with errno %d\n",rc,errno)); + SAFE_FREE(file_acl); + return(NULL); + } + } + + DEBUG(10,("Got facl and returned it\n")); + + result = aixacl_to_smbacl(file_acl); + SAFE_FREE(file_acl); + return result; + + /*errno = ENOTSUP; + return NULL;*/ +} + +int aixacl_sys_acl_set_file(vfs_handle_struct *handle, + const char *name, + SMB_ACL_TYPE_T type, + SMB_ACL_T theacl) +{ + struct acl *file_acl = NULL; + uint rc; + + file_acl = aixacl_smb_to_aixacl(type, theacl); + if (!file_acl) + return -1; + + rc = chacl((char *)name,file_acl,file_acl->acl_len); + DEBUG(10,("errno is %d\n",errno)); + DEBUG(10,("return code is %d\n",rc)); + SAFE_FREE(file_acl); + DEBUG(10,("Exiting the aixacl_sys_acl_set_file\n")); + + return rc; +} + +int aixacl_sys_acl_set_fd(vfs_handle_struct *handle, + files_struct *fsp, + int fd, SMB_ACL_T theacl) +{ + struct acl *file_acl = NULL; + uint rc; + + file_acl = aixacl_smb_to_aixacl(SMB_ACL_TYPE_ACCESS, theacl); + if (!file_acl) + return -1; + + rc = fchacl(fd,file_acl,file_acl->acl_len); + DEBUG(10,("errno is %d\n",errno)); + DEBUG(10,("return code is %d\n",rc)); + SAFE_FREE(file_acl); + DEBUG(10,("Exiting aixacl_sys_acl_set_fd\n")); + + return rc; +} + +int aixacl_sys_acl_delete_def_file(vfs_handle_struct *handle, + const char *path) +{ + return 0; /* otherwise you can't set acl at upper level */ +} + +/* VFS operations structure */ + +static vfs_op_tuple aixacl_op_tuples[] = { + /* Disk operations */ + {SMB_VFS_OP(aixacl_sys_acl_get_file), + SMB_VFS_OP_SYS_ACL_GET_FILE, + SMB_VFS_LAYER_TRANSPARENT}, + + {SMB_VFS_OP(aixacl_sys_acl_get_fd), + SMB_VFS_OP_SYS_ACL_GET_FD, + SMB_VFS_LAYER_TRANSPARENT}, + + {SMB_VFS_OP(aixacl_sys_acl_set_file), + SMB_VFS_OP_SYS_ACL_SET_FILE, + SMB_VFS_LAYER_TRANSPARENT}, + + {SMB_VFS_OP(aixacl_sys_acl_set_fd), + SMB_VFS_OP_SYS_ACL_SET_FD, + SMB_VFS_LAYER_TRANSPARENT}, + + {SMB_VFS_OP(aixacl_sys_acl_delete_def_file), + SMB_VFS_OP_SYS_ACL_DELETE_DEF_FILE, + SMB_VFS_LAYER_TRANSPARENT}, + + {SMB_VFS_OP(NULL), + SMB_VFS_OP_NOOP, + SMB_VFS_LAYER_NOOP} +}; + +NTSTATUS vfs_aixacl_init(void) +{ + return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "aixacl", + aixacl_op_tuples); +} diff --git a/source3/modules/vfs_aixacl_util.c b/source3/modules/vfs_aixacl_util.c new file mode 100644 index 0000000000..fd7481af3e --- /dev/null +++ b/source3/modules/vfs_aixacl_util.c @@ -0,0 +1,297 @@ +/* + Unix SMB/Netbios implementation. + VFS module to get and set posix acls + Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2006 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +SMB_ACL_T aixacl_to_smbacl(struct acl *file_acl) +{ + struct acl_entry *acl_entry; + struct ace_id *idp; + + struct smb_acl_t *result = SMB_MALLOC_P(struct smb_acl_t); + struct smb_acl_entry *ace; + int i; + + if (result == NULL) { + return NULL; + } + ZERO_STRUCTP(result); + + /* Point to the first acl entry in the acl */ + acl_entry = file_acl->acl_ext; + + + + DEBUG(10,("acl_entry is %d\n",acl_entry)); + DEBUG(10,("acl_last(file_acl) id %d\n",acl_last(file_acl))); + + /* Check if the extended acl bit is on. * + * If it isn't, do not show the * + * contents of the acl since AIX intends * + * the extended info to remain unused */ + + if(file_acl->acl_mode & S_IXACL){ + /* while we are not pointing to the very end */ + while(acl_entry < acl_last(file_acl)) { + /* before we malloc anything, make sure this is */ + /* a valid acl entry and one that we want to map */ + idp = id_nxt(acl_entry->ace_id); + if((acl_entry->ace_type == ACC_SPECIFY || + (acl_entry->ace_type == ACC_PERMIT)) && (idp != id_last(acl_entry))) { + acl_entry = acl_nxt(acl_entry); + continue; + } + + idp = acl_entry->ace_id; + DEBUG(10,("idp->id_data is %d\n",idp->id_data[0])); + + result = SMB_REALLOC(result, sizeof(struct smb_acl_t) + + (sizeof(struct smb_acl_entry) * + (result->count+1))); + if (result == NULL) { + DEBUG(0, ("SMB_REALLOC failed\n")); + errno = ENOMEM; + return NULL; + } + + + DEBUG(10,("idp->id_type is %d\n",idp->id_type)); + ace = &result->acl[result->count]; + + ace->a_type = idp->id_type; + + switch(ace->a_type) { + case ACEID_USER: { + ace->uid = idp->id_data[0]; + DEBUG(10,("case ACEID_USER ace->uid is %d\n",ace->uid)); + ace->a_type = SMB_ACL_USER; + break; + } + + case ACEID_GROUP: { + ace->gid = idp->id_data[0]; + DEBUG(10,("case ACEID_GROUP ace->gid is %d\n",ace->gid)); + ace->a_type = SMB_ACL_GROUP; + break; + } + default: + break; + } + /* The access in the acl entries must be left shifted by * + * three bites, because they will ultimately be compared * + * to S_IRUSR, S_IWUSR, and S_IXUSR. */ + + switch(acl_entry->ace_type){ + case ACC_PERMIT: + case ACC_SPECIFY: + ace->a_perm = acl_entry->ace_access; + ace->a_perm <<= 6; + DEBUG(10,("ace->a_perm is %d\n",ace->a_perm)); + break; + case ACC_DENY: + /* Since there is no way to return a DENY acl entry * + * change to PERMIT and then shift. */ + DEBUG(10,("acl_entry->ace_access is %d\n",acl_entry->ace_access)); + ace->a_perm = ~acl_entry->ace_access & 7; + DEBUG(10,("ace->a_perm is %d\n",ace->a_perm)); + ace->a_perm <<= 6; + break; + default: + DEBUG(0, ("unknown ace->type\n")); + SAFE_FREE(result); + return(0); + } + + result->count++; + ace->a_perm |= (ace->a_perm & S_IRUSR) ? SMB_ACL_READ : 0; + ace->a_perm |= (ace->a_perm & S_IWUSR) ? SMB_ACL_WRITE : 0; + ace->a_perm |= (ace->a_perm & S_IXUSR) ? SMB_ACL_EXECUTE : 0; + DEBUG(10,("ace->a_perm is %d\n",ace->a_perm)); + + DEBUG(10,("acl_entry = %d\n",acl_entry)); + DEBUG(10,("The ace_type is %d\n",acl_entry->ace_type)); + + acl_entry = acl_nxt(acl_entry); + } + } /* end of if enabled */ + + /* Since owner, group, other acl entries are not * + * part of the acl entries in an acl, they must * + * be dummied up to become part of the list. */ + + for( i = 1; i < 4; i++) { + DEBUG(10,("i is %d\n",i)); + + result = SMB_REALLOC(result, sizeof(struct smb_acl_t) + + (sizeof(struct smb_acl_entry) * + (result->count+1))); + if (result == NULL) { + DEBUG(0, ("SMB_REALLOC failed\n")); + errno = ENOMEM; + DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno)); + return NULL; + } + + ace = &result->acl[result->count]; + + ace->uid = 0; + ace->gid = 0; + DEBUG(10,("ace->uid = %d\n",ace->uid)); + + switch(i) { + case 2: + ace->a_perm = file_acl->g_access << 6; + ace->a_type = SMB_ACL_GROUP_OBJ; + break; + + case 3: + ace->a_perm = file_acl->o_access << 6; + ace->a_type = SMB_ACL_OTHER; + break; + + case 1: + ace->a_perm = file_acl->u_access << 6; + ace->a_type = SMB_ACL_USER_OBJ; + break; + + default: + return(NULL); + + } + ace->a_perm |= ((ace->a_perm & S_IRUSR) ? SMB_ACL_READ : 0); + ace->a_perm |= ((ace->a_perm & S_IWUSR) ? SMB_ACL_WRITE : 0); + ace->a_perm |= ((ace->a_perm & S_IXUSR) ? SMB_ACL_EXECUTE : 0); + + memcpy(&result->acl[result->count],ace,sizeof(struct smb_acl_entry)); + result->count++; + DEBUG(10,("ace->a_perm = %d\n",ace->a_perm)); + DEBUG(10,("ace->a_type = %d\n",ace->a_type)); + } + + + return result; + + +} + +static ushort aixacl_smb_to_aixperm(SMB_ACL_PERM_T a_perm) +{ + ushort ret = (ushort)0; + if (a_perm & SMB_ACL_READ) + ret |= R_ACC; + if (a_perm & SMB_ACL_WRITE) + ret |= W_ACC; + if (a_perm & SMB_ACL_EXECUTE) + ret |= X_ACC; + return ret; +} + +struct acl *aixacl_smb_to_aixacl(SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl) +{ + struct smb_acl_entry *smb_entry = NULL; + struct acl *file_acl = NULL; + struct acl *file_acl_temp = NULL; + struct acl_entry *acl_entry = NULL; + struct ace_id *ace_id = NULL; + uint id_type; + uint user_id; + uint acl_length; + int i; + + DEBUG(10,("Entering aixacl_smb_to_aixacl\n")); + /* AIX has no default ACL */ + if(acltype == SMB_ACL_TYPE_DEFAULT) + return NULL; + + acl_length = BUFSIZ; + file_acl = (struct acl *)SMB_MALLOC(BUFSIZ); + if(file_acl == NULL) { + errno = ENOMEM; + DEBUG(0,("Error in aixacl_smb_to_aixacl is %d\n",errno)); + return NULL; + } + + memset(file_acl,0,BUFSIZ); + + file_acl->acl_len = ACL_SIZ; + file_acl->acl_mode = S_IXACL; + + for(i=0; i<theacl->count; i++ ) { + smb_entry = &(theacl->acl[i]); + id_type = smb_entry->a_type; + DEBUG(10,("The id_type is %d\n",id_type)); + + switch(id_type) { + case SMB_ACL_USER_OBJ: + file_acl->u_access = aixacl_smb_to_aixperm(smb_entry->a_perm); + continue; + case SMB_ACL_GROUP_OBJ: + file_acl->g_access = aixacl_smb_to_aixperm(smb_entry->a_perm); + continue; + case SMB_ACL_OTHER: + file_acl->o_access = aixacl_smb_to_aixperm(smb_entry->a_perm); + continue; + case SMB_ACL_MASK: + continue; + case SMB_ACL_GROUP: + break; /* process this */ + case SMB_ACL_USER: + break; /* process this */ + default: /* abnormal case */ + DEBUG(10,("The id_type is unknown !\n")); + continue; + } + + if((file_acl->acl_len + sizeof(struct acl_entry)) > acl_length) { + acl_length += sizeof(struct acl_entry); + file_acl_temp = (struct acl *)SMB_MALLOC(acl_length); + if(file_acl_temp == NULL) { + SAFE_FREE(file_acl); + errno = ENOMEM; + DEBUG(0,("Error in aixacl_smb_to_aixacl is %d\n",errno)); + return NULL; + } + + memcpy(file_acl_temp,file_acl,file_acl->acl_len); + SAFE_FREE(file_acl); + file_acl = file_acl_temp; + } + + acl_entry = (struct acl_entry *)((char *)file_acl + file_acl->acl_len); + file_acl->acl_len += sizeof(struct acl_entry); + acl_entry->ace_len = sizeof(struct acl_entry); /* contains 1 ace_id */ + acl_entry->ace_access = aixacl_smb_to_aixperm(smb_entry->a_perm); + + /* In order to use this, we'll need to wait until we can get denies */ + /* if(!acl_entry->ace_access && acl_entry->ace_type == ACC_PERMIT) + acl_entry->ace_type = ACC_SPECIFY; */ + + acl_entry->ace_type = ACC_SPECIFY; + + ace_id = acl_entry->ace_id; + + ace_id->id_type = (smb_entry->a_type==SMB_ACL_GROUP) ? ACEID_GROUP : ACEID_USER; + DEBUG(10,("The id type is %d\n",ace_id->id_type)); + ace_id->id_len = sizeof(struct ace_id); /* contains 1 id_data */ + ace_id->id_data[0] = (smb_entry->a_type==SMB_ACL_GROUP) ? smb_entry->gid : smb_entry->uid; + } + + return file_acl; +} diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c index 82eec46d37..ae565ae980 100644 --- a/source3/modules/vfs_default.c +++ b/source3/modules/vfs_default.c @@ -916,12 +916,12 @@ static void * vfswrap_sys_acl_get_qualifier(vfs_handle_struct *handle, SMB_ACL_ static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle, const char *path_p, SMB_ACL_TYPE_T type) { - return sys_acl_get_file(path_p, type); + return sys_acl_get_file(handle, path_p, type); } static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle, files_struct *fsp, int fd) { - return sys_acl_get_fd(fd); + return sys_acl_get_fd(handle, fsp, fd); } static int vfswrap_sys_acl_clear_perms(vfs_handle_struct *handle, SMB_ACL_PERMSET_T permset) @@ -971,17 +971,17 @@ static int vfswrap_sys_acl_valid(vfs_handle_struct *handle, SMB_ACL_T theacl ) static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle, const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl) { - return sys_acl_set_file(name, acltype, theacl); + return sys_acl_set_file(handle, name, acltype, theacl); } static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_ACL_T theacl) { - return sys_acl_set_fd(fd, theacl); + return sys_acl_set_fd(handle, fsp, fd, theacl); } static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle, const char *path) { - return sys_acl_delete_def_file(path); + return sys_acl_delete_def_file(handle, path); } static int vfswrap_sys_acl_get_perm(vfs_handle_struct *handle, SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm) diff --git a/source3/modules/vfs_hpuxacl.c b/source3/modules/vfs_hpuxacl.c new file mode 100644 index 0000000000..43cc45cbf1 --- /dev/null +++ b/source3/modules/vfs_hpuxacl.c @@ -0,0 +1,104 @@ +/* + Unix SMB/Netbios implementation. + VFS module to get and set hpux acls + Copyright (C) Michael Adam 2006 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +/* prototypes for private functions first - for clarity */ + +/* public functions - the api */ + +SMB_ACL_T hpuxacl_sys_acl_get_file(vfs_handle_struct *handle, + const char *path_p, + SMB_ACL_TYPE_T type) +{ + errno = ENOTSUP; + return NULL; +} + +SMB_ACL_T hpuxacl_sys_acl_get_fd(vfs_handle_struct *handle, + files_struct *fsp, + int fd) +{ + errno = ENOTSUP; + return NULL; +} + +int hpuxacl_sys_acl_set_file(vfs_handle_struct *handle, + const char *name, + SMB_ACL_TYPE_T type, + SMB_ACL_T theacl) +{ + errno = ENOTSUP; + return -1; +} + +int hpuxacl_sys_acl_set_fd(vfs_handle_struct *handle, + files_struct *fsp, + int fd, SMB_ACL_T theacl) +{ + errno = ENOTSUP; + return -1; +} + +int hpuxacl_sys_acl_delete_def_file(vfs_handle_struct *handle, + const char *path) +{ + errno = ENOTSUP; + return -1; +} + +/* private functions */ + +/* VFS operations structure */ + +static vfs_op_tuple hpuxacl_op_tuples[] = { + /* Disk operations */ + {SMB_VFS_OP(hpuxacl_sys_acl_get_file), + SMB_VFS_OP_SYS_ACL_GET_FILE, + SMB_VFS_LAYER_TRANSPARENT}, + + {SMB_VFS_OP(hpuxacl_sys_acl_get_fd), + SMB_VFS_OP_SYS_ACL_GET_FD, + SMB_VFS_LAYER_TRANSPARENT}, + + {SMB_VFS_OP(hpuxacl_sys_acl_set_file), + SMB_VFS_OP_SYS_ACL_SET_FILE, + SMB_VFS_LAYER_TRANSPARENT}, + + {SMB_VFS_OP(hpuxacl_sys_acl_set_fd), + SMB_VFS_OP_SYS_ACL_SET_FD, + SMB_VFS_LAYER_TRANSPARENT}, + + {SMB_VFS_OP(hpuxacl_sys_acl_delete_def_file), + SMB_VFS_OP_SYS_ACL_DELETE_DEF_FILE, + SMB_VFS_LAYER_TRANSPARENT}, + + {SMB_VFS_OP(NULL), + SMB_VFS_OP_NOOP, + SMB_VFS_LAYER_NOOP} +}; + +NTSTATUS vfs_hpuxacl_init(void) +{ + return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "hpuxacl", + hpuxacl_op_tuples); +} + +/* ENTE */ diff --git a/source3/modules/vfs_irixacl.c b/source3/modules/vfs_irixacl.c new file mode 100644 index 0000000000..8acb24b385 --- /dev/null +++ b/source3/modules/vfs_irixacl.c @@ -0,0 +1,104 @@ +/* + Unix SMB/Netbios implementation. + VFS module to get and set irix acls + Copyright (C) Michael Adam 2006 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +/* prototypes for private functions first - for clarity */ + +/* public functions - the api */ + +SMB_ACL_T irixacl_sys_acl_get_file(vfs_handle_struct *handle, + const char *path_p, + SMB_ACL_TYPE_T type) +{ + errno = ENOTSUP; + return NULL; +} + +SMB_ACL_T irixacl_sys_acl_get_fd(vfs_handle_struct *handle, + files_struct *fsp, + int fd) +{ + errno = ENOTSUP; + return NULL; +} + +int irixacl_sys_acl_set_file(vfs_handle_struct *handle, + const char *name, + SMB_ACL_TYPE_T type, + SMB_ACL_T theacl) +{ + errno = ENOTSUP; + return -1; +} + +int irixacl_sys_acl_set_fd(vfs_handle_struct *handle, + files_struct *fsp, + int fd, SMB_ACL_T theacl) +{ + errno = ENOTSUP; + return -1; +} + +int irixacl_sys_acl_delete_def_file(vfs_handle_struct *handle, + const char *path) +{ + errno = ENOTSUP; + return -1; +} + +/* private functions */ + +/* VFS operations structure */ + +static vfs_op_tuple irixacl_op_tuples[] = { + /* Disk operations */ + {SMB_VFS_OP(irixacl_sys_acl_get_file), + SMB_VFS_OP_SYS_ACL_GET_FILE, + SMB_VFS_LAYER_TRANSPARENT}, + + {SMB_VFS_OP(irixacl_sys_acl_get_fd), + SMB_VFS_OP_SYS_ACL_GET_FD, + SMB_VFS_LAYER_TRANSPARENT}, + + {SMB_VFS_OP(irixacl_sys_acl_set_file), + SMB_VFS_OP_SYS_ACL_SET_FILE, + SMB_VFS_LAYER_TRANSPARENT}, + + {SMB_VFS_OP(irixacl_sys_acl_set_fd), + SMB_VFS_OP_SYS_ACL_SET_FD, + SMB_VFS_LAYER_TRANSPARENT}, + + {SMB_VFS_OP(irixacl_sys_acl_delete_def_file), + SMB_VFS_OP_SYS_ACL_DELETE_DEF_FILE, + SMB_VFS_LAYER_TRANSPARENT}, + + {SMB_VFS_OP(NULL), + SMB_VFS_OP_NOOP, + SMB_VFS_LAYER_NOOP} +}; + +NTSTATUS vfs_irixacl_init(void) +{ + return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "irixacl", + irixacl_op_tuples); +} + +/* ENTE */ diff --git a/source3/modules/vfs_posixacl.c b/source3/modules/vfs_posixacl.c new file mode 100644 index 0000000000..6d7c2b3c00 --- /dev/null +++ b/source3/modules/vfs_posixacl.c @@ -0,0 +1,391 @@ +/* + Unix SMB/Netbios implementation. + VFS module to get and set posix acls + Copyright (C) Volker Lendecke 2006 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + + +/* prototypes for static functions first - for clarity */ + +static BOOL smb_ace_to_internal(acl_entry_t posix_ace, + struct smb_acl_entry *ace); +static struct smb_acl_t *smb_acl_to_internal(acl_t acl); +static int smb_acl_set_mode(acl_entry_t entry, SMB_ACL_PERM_T perm); +static acl_t smb_acl_to_posix(const struct smb_acl_t *acl); + + +/* public functions - the api */ + +SMB_ACL_T posixacl_sys_acl_get_file(vfs_handle_struct *handle, + const char *path_p, + SMB_ACL_TYPE_T type) +{ + struct smb_acl_t *result; + acl_type_t acl_type; + acl_t acl; + + switch(type) { + case SMB_ACL_TYPE_ACCESS: + acl_type = ACL_TYPE_ACCESS; + break; + case SMB_ACL_TYPE_DEFAULT: + acl_type = ACL_TYPE_DEFAULT; + break; + default: + errno = EINVAL; + return NULL; + } + + acl = acl_get_file(path_p, acl_type); + + if (acl == NULL) { + return NULL; + } + + result = smb_acl_to_internal(acl); + acl_free(acl); + return result; +} + +SMB_ACL_T posixacl_sys_acl_get_fd(vfs_handle_struct *handle, + files_struct *fsp, + int fd) +{ + struct smb_acl_t *result; + acl_t acl = acl_get_fd(fd); + + if (acl == NULL) { + return NULL; + } + + result = smb_acl_to_internal(acl); + acl_free(acl); + return result; +} + +int posixacl_sys_acl_set_file(vfs_handle_struct *handle, + const char *name, + SMB_ACL_TYPE_T type, + SMB_ACL_T theacl) +{ + int res; + acl_type_t acl_type; + acl_t acl; + + DEBUG(10, ("Calling acl_set_file: %s, %d\n", name, type)); + + switch(type) { + case SMB_ACL_TYPE_ACCESS: + acl_type = ACL_TYPE_ACCESS; + break; + case SMB_ACL_TYPE_DEFAULT: + acl_type = ACL_TYPE_DEFAULT; + break; + default: + errno = EINVAL; + return -1; + } + + if ((acl = smb_acl_to_posix(theacl)) == NULL) { + return -1; + } + res = acl_set_file(name, acl_type, acl); + if (res != 0) { + DEBUG(10, ("acl_set_file failed: %s\n", strerror(errno))); + } + acl_free(acl); + return res; +} + +int posixacl_sys_acl_set_fd(vfs_handle_struct *handle, + files_struct *fsp, + int fd, SMB_ACL_T theacl) +{ + int res; + acl_t acl = smb_acl_to_posix(theacl); + if (acl == NULL) { + return -1; + } + res = acl_set_fd(fd, acl); + acl_free(acl); + return res; +} + +int posixacl_sys_acl_delete_def_file(vfs_handle_struct *handle, + const char *path) +{ + return acl_delete_def_file(path); +} + + +/* private functions */ + +static BOOL smb_ace_to_internal(acl_entry_t posix_ace, + struct smb_acl_entry *ace) +{ + acl_tag_t tag; + acl_permset_t permset; + + if (acl_get_tag_type(posix_ace, &tag) != 0) { + DEBUG(0, ("smb_acl_get_tag_type failed\n")); + return False; + } + + switch(tag) { + case ACL_USER: + ace->a_type = SMB_ACL_USER; + break; + case ACL_USER_OBJ: + ace->a_type = SMB_ACL_USER_OBJ; + break; + case ACL_GROUP: + ace->a_type = SMB_ACL_GROUP; + break; + case ACL_GROUP_OBJ: + ace->a_type = SMB_ACL_GROUP_OBJ; + break; + case ACL_OTHER: + ace->a_type = SMB_ACL_OTHER; + break; + case ACL_MASK: + ace->a_type = SMB_ACL_MASK; + break; + default: + DEBUG(0, ("unknown tag type %d\n", (unsigned int)tag)); + return False; + } + switch(ace->a_type) { + case SMB_ACL_USER: { + uid_t *puid = acl_get_qualifier(posix_ace); + if (puid == NULL) { + DEBUG(0, ("smb_acl_get_qualifier failed\n")); + return False; + } + ace->uid = *puid; + acl_free(puid); + break; + } + + case SMB_ACL_GROUP: { + gid_t *pgid = acl_get_qualifier(posix_ace); + if (pgid == NULL) { + DEBUG(0, ("smb_acl_get_qualifier failed\n")); + return False; + } + ace->gid = *pgid; + acl_free(pgid); + break; + } + default: + break; + } + if (acl_get_permset(posix_ace, &permset) != 0) { + DEBUG(0, ("smb_acl_get_mode failed\n")); + return False; + } + ace->a_perm = 0; + ace->a_perm |= (acl_get_perm(permset, ACL_READ) ? SMB_ACL_READ : 0); + ace->a_perm |= (acl_get_perm(permset, ACL_WRITE) ? SMB_ACL_WRITE : 0); + ace->a_perm |= (acl_get_perm(permset, ACL_EXECUTE) ? SMB_ACL_EXECUTE : 0); + return True; +} + +static struct smb_acl_t *smb_acl_to_internal(acl_t acl) +{ + struct smb_acl_t *result = SMB_MALLOC_P(struct smb_acl_t); + int entry_id = ACL_FIRST_ENTRY; + acl_entry_t e; + if (result == NULL) { + return NULL; + } + ZERO_STRUCTP(result); + while (acl_get_entry(acl, entry_id, &e) == 1) { + + entry_id = ACL_NEXT_ENTRY; + + result = SMB_REALLOC(result, sizeof(struct smb_acl_t) + + (sizeof(struct smb_acl_entry) * + (result->count+1))); + if (result == NULL) { + DEBUG(0, ("SMB_REALLOC failed\n")); + errno = ENOMEM; + return NULL; + } + + if (!smb_ace_to_internal(e, &result->acl[result->count])) { + SAFE_FREE(result); + return NULL; + } + + result->count += 1; + } + return result; +} + +static int smb_acl_set_mode(acl_entry_t entry, SMB_ACL_PERM_T perm) +{ + int ret; + acl_permset_t permset; + + if ((ret = acl_get_permset(entry, &permset)) != 0) { + return ret; + } + if ((ret = acl_clear_perms(permset)) != 0) { + return ret; + } + if ((perm & SMB_ACL_READ) && + ((ret = acl_add_perm(permset, ACL_READ)) != 0)) { + return ret; + } + if ((perm & SMB_ACL_WRITE) && + ((ret = acl_add_perm(permset, ACL_WRITE)) != 0)) { + return ret; + } + if ((perm & SMB_ACL_EXECUTE) && + ((ret = acl_add_perm(permset, ACL_EXECUTE)) != 0)) { + return ret; + } + return acl_set_permset(entry, permset); +} + +static acl_t smb_acl_to_posix(const struct smb_acl_t *acl) +{ + acl_t result; + int i; + + result = acl_init(acl->count); + if (result == NULL) { + DEBUG(10, ("acl_init failed\n")); + return NULL; + } + + for (i=0; i<acl->count; i++) { + const struct smb_acl_entry *entry = &acl->acl[i]; + acl_entry_t e; + acl_tag_t tag; + + if (acl_create_entry(&result, &e) != 0) { + DEBUG(1, ("acl_create_entry failed: %s\n", + strerror(errno))); + goto fail; + } + + switch (entry->a_type) { + case SMB_ACL_USER: + tag = ACL_USER; + break; + case SMB_ACL_USER_OBJ: + tag = ACL_USER_OBJ; + break; + case SMB_ACL_GROUP: + tag = ACL_GROUP; + break; + case SMB_ACL_GROUP_OBJ: + tag = ACL_GROUP_OBJ; + break; + case SMB_ACL_OTHER: + tag = ACL_OTHER; + break; + case SMB_ACL_MASK: + tag = ACL_MASK; + break; + default: + DEBUG(1, ("Unknown tag value %d\n", entry->a_type)); + goto fail; + } + + if (acl_set_tag_type(e, tag) != 0) { + DEBUG(10, ("acl_set_tag_type(%d) failed: %s\n", + tag, strerror(errno))); + goto fail; + } + + switch (entry->a_type) { + case SMB_ACL_USER: + if (acl_set_qualifier(e, &entry->uid) != 0) { + DEBUG(1, ("acl_set_qualifiier failed: %s\n", + strerror(errno))); + goto fail; + } + break; + case SMB_ACL_GROUP: + if (acl_set_qualifier(e, &entry->gid) != 0) { + DEBUG(1, ("acl_set_qualifiier failed: %s\n", + strerror(errno))); + goto fail; + } + break; + default: /* Shut up, compiler! :-) */ + break; + } + + if (smb_acl_set_mode(e, entry->a_perm) != 0) { + goto fail; + } + } + + if (acl_valid(result) != 0) { + DEBUG(0, ("smb_acl_to_posix: ACL is invalid for set (%s)\n", + strerror(errno))); + goto fail; + } + + return result; + + fail: + if (result != NULL) { + acl_free(result); + } + return NULL; +} + +/* VFS operations structure */ + +static vfs_op_tuple posixacl_op_tuples[] = { + /* Disk operations */ + {SMB_VFS_OP(posixacl_sys_acl_get_file), + SMB_VFS_OP_SYS_ACL_GET_FILE, + SMB_VFS_LAYER_TRANSPARENT}, + + {SMB_VFS_OP(posixacl_sys_acl_get_fd), + SMB_VFS_OP_SYS_ACL_GET_FD, + SMB_VFS_LAYER_TRANSPARENT}, + + {SMB_VFS_OP(posixacl_sys_acl_set_file), + SMB_VFS_OP_SYS_ACL_SET_FILE, + SMB_VFS_LAYER_TRANSPARENT}, + + {SMB_VFS_OP(posixacl_sys_acl_set_fd), + SMB_VFS_OP_SYS_ACL_SET_FD, + SMB_VFS_LAYER_TRANSPARENT}, + + {SMB_VFS_OP(posixacl_sys_acl_delete_def_file), + SMB_VFS_OP_SYS_ACL_DELETE_DEF_FILE, + SMB_VFS_LAYER_TRANSPARENT}, + + {SMB_VFS_OP(NULL), + SMB_VFS_OP_NOOP, + SMB_VFS_LAYER_NOOP} +}; + +NTSTATUS vfs_posixacl_init(void) +{ + return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "posixacl", + posixacl_op_tuples); +} diff --git a/source3/modules/vfs_solarisacl.c b/source3/modules/vfs_solarisacl.c new file mode 100644 index 0000000000..5e5e5978f2 --- /dev/null +++ b/source3/modules/vfs_solarisacl.c @@ -0,0 +1,788 @@ +/* + Unix SMB/Netbios implementation. + VFS module to get and set Solaris ACLs + Copyright (C) Michael Adam 2006 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + + +#include "includes.h" + + +/* typedef struct acl SOLARIS_ACE_T; */ +typedef aclent_t SOLARIS_ACE_T; +typedef aclent_t *SOLARIS_ACL_T; +typedef int SOLARIS_ACL_TAG_T; /* the type of an ACL entry */ +typedef o_mode_t SOLARIS_PERM_T; + +/* for convenience: check if solaris acl entry is a default entry? */ +#define _IS_DEFAULT(ace) ((ace).a_type & ACL_DEFAULT) +#define _IS_OF_TYPE(ace, type) ( \ + (((type) == SMB_ACL_TYPE_ACCESS) && !_IS_DEFAULT(ace)) \ + || \ + (((type) == SMB_ACL_TYPE_DEFAULT) && _IS_DEFAULT(ace)) \ +) + + +/* prototypes for private functions */ + +static SOLARIS_ACL_T solaris_acl_init(int count); +static BOOL smb_acl_to_solaris_acl(SMB_ACL_T smb_acl, + SOLARIS_ACL_T *solariacl, int *count, + SMB_ACL_TYPE_T type); +static SMB_ACL_T solaris_acl_to_smb_acl(SOLARIS_ACL_T solarisacl, int count, + SMB_ACL_TYPE_T type); +static SOLARIS_ACL_TAG_T smb_tag_to_solaris_tag(SMB_ACL_TAG_T smb_tag); +static SMB_ACL_TAG_T solaris_tag_to_smb_tag(SOLARIS_ACL_TAG_T solaris_tag); +static BOOL solaris_add_to_acl(SOLARIS_ACL_T *solaris_acl, int *count, + SOLARIS_ACL_T add_acl, int add_count, SMB_ACL_TYPE_T type); +static BOOL solaris_acl_get_file(const char *name, SOLARIS_ACL_T *solarisacl, + int *count); +static BOOL solaris_acl_get_fd(int fd, SOLARIS_ACL_T *solarisacl, int *count); +static BOOL solaris_acl_sort(SOLARIS_ACL_T acl, int count); +static SMB_ACL_PERM_T solaris_perm_to_smb_perm(const SOLARIS_PERM_T perm); +static SOLARIS_PERM_T smb_perm_to_solaris_perm(const SMB_ACL_PERM_T perm); +static BOOL solaris_acl_check(SOLARIS_ACL_T solaris_acl, int count); + + +/* public functions - the api */ + +SMB_ACL_T solarisacl_sys_acl_get_file(vfs_handle_struct *handle, + const char *path_p, + SMB_ACL_TYPE_T type) +{ + SMB_ACL_T result = NULL; + int count; + SOLARIS_ACL_T solaris_acl; + + DEBUG(10, ("solarisacl_sys_acl_get_file called for file '%s'.\n", + path_p)); + + if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) { + DEBUG(10, ("invalid SMB_ACL_TYPE given (%d)\n", type)); + errno = EINVAL; + goto done; + } + + DEBUGADD(10, ("getting %s acl\n", + ((type == SMB_ACL_TYPE_ACCESS) ? "access" : "default"))); + + if (!solaris_acl_get_file(path_p, &solaris_acl, &count)) { + goto done; + } + result = solaris_acl_to_smb_acl(solaris_acl, count, type); + if (result == NULL) { + DEBUG(10, ("conversion solaris_acl -> smb_acl failed (%s).\n", + strerror(errno))); + } + + done: + DEBUG(10, ("solarisacl_sys_acl_get_file %s.\n", + ((result == NULL) ? "failed" : "succeeded" ))); + SAFE_FREE(solaris_acl); + return result; +} + + +/* + * get the access ACL of a file referred to by a fd + */ +SMB_ACL_T solarisacl_sys_acl_get_fd(vfs_handle_struct *handle, + files_struct *fsp, + int fd) +{ + SMB_ACL_T result = NULL; + int count; + SOLARIS_ACL_T solaris_acl; + + DEBUG(10, ("entering solarisacl_sys_acl_get_fd.\n")); + + if (!solaris_acl_get_fd(fd, &solaris_acl, &count)) { + goto done; + } + /* + * The facl call returns both ACCESS and DEFAULT acls (as present). + * The posix acl_get_fd function returns only the + * access acl. So we need to filter this out here. + */ + result = solaris_acl_to_smb_acl(solaris_acl, count, + SMB_ACL_TYPE_ACCESS); + if (result == NULL) { + DEBUG(10, ("conversion solaris_acl -> smb_acl failed (%s).\n", + strerror(errno))); + } + + done: + DEBUG(10, ("solarisacl_sys_acl_get_fd %s.\n", + ((result == NULL) ? "failed" : "succeeded"))); + SAFE_FREE(solaris_acl); + return NULL; +} + +int solarisacl_sys_acl_set_file(vfs_handle_struct *handle, + const char *name, + SMB_ACL_TYPE_T type, + SMB_ACL_T theacl) +{ + int ret = -1; + struct stat s; + SOLARIS_ACL_T solaris_acl; + int count; + + DEBUG(10, ("solarisacl_sys_acl_set_file called for file '%s'\n", + name)); + + if ((type != SMB_ACL_TYPE_ACCESS) && (type != SMB_ACL_TYPE_DEFAULT)) { + errno = EINVAL; + DEBUG(10, ("invalid smb acl type given (%d).\n", type)); + goto done; + } + DEBUGADD(10, ("setting %s acl\n", + ((type == SMB_ACL_TYPE_ACCESS) ? "access" : "default"))); + + if(!smb_acl_to_solaris_acl(theacl, &solaris_acl, &count, type)) { + DEBUG(10, ("conversion smb_acl -> solaris_acl failed (%s).\n", + strerror(errno))); + goto done; + } + + /* + * if the file is a directory, there is extra work to do: + * since the solaris acl call stores both the access acl and + * the default acl as provided, we have to get the acl part + * that has not been specified in "type" from the file first + * and concatenate it with the acl provided. + */ + if (SMB_VFS_STAT(handle->conn, name, &s) != 0) { + DEBUG(10, ("Error in stat call: %s\n", strerror(errno))); + goto done; + } + if (S_ISDIR(s.st_mode)) { + SOLARIS_ACL_T other_acl; + int other_count; + SMB_ACL_TYPE_T other_type; + + other_type = (type == SMB_ACL_TYPE_ACCESS) + ? SMB_ACL_TYPE_DEFAULT + : SMB_ACL_TYPE_ACCESS; + DEBUGADD(10, ("getting acl from filesystem\n")); + if (!solaris_acl_get_file(name, &other_acl, &other_count)) { + DEBUG(10, ("error getting acl from directory\n")); + goto done; + } + DEBUG(10, ("adding %s part of fs acl to given acl\n", + ((other_type == SMB_ACL_TYPE_ACCESS) + ? "access" + : "default"))); + if (!solaris_add_to_acl(&solaris_acl, &count, other_acl, + other_count, other_type)) + { + DEBUG(10, ("error adding other acl.\n")); + SAFE_FREE(other_acl); + goto done; + } + SAFE_FREE(other_acl); + } + else if (type != SMB_ACL_TYPE_ACCESS) { + errno = EINVAL; + goto done; + } + + if (!solaris_acl_sort(solaris_acl, count)) { + DEBUG(10, ("resulting acl is not valid!\n")); + goto done; + } + + ret = acl(name, SETACL, count, solaris_acl); + + done: + DEBUG(10, ("solarisacl_sys_acl_set_file %s.\n", + ((ret != 0) ? "failed" : "succeeded"))); + SAFE_FREE(solaris_acl); + return ret; +} + +/* + * set the access ACL on the file referred to by a fd + */ +int solarisacl_sys_acl_set_fd(vfs_handle_struct *handle, + files_struct *fsp, + int fd, SMB_ACL_T theacl) +{ + SOLARIS_ACL_T solaris_acl; + SOLARIS_ACL_T default_acl; + int count, default_count; + int ret = -1; + + DEBUG(10, ("entering solarisacl_sys_acl_set_fd\n")); + + /* + * the posix acl_set_fd call sets the access acl of the + * file referred to by fd. the solaris facl-SETACL call + * sets the access and default acl as provided, so we + * have to retrieve the default acl of the file and + * concatenate it with the access acl provided. + */ + if (!smb_acl_to_solaris_acl(theacl, &solaris_acl, &count, + SMB_ACL_TYPE_ACCESS)) + { + DEBUG(10, ("conversion smb_acl -> solaris_acl failed (%s).\n", + strerror(errno))); + goto done; + } + if (!solaris_acl_get_fd(fd, &default_acl, &default_count)) { + DEBUG(10, ("error getting (default) acl from fd\n")); + goto done; + } + if (!solaris_add_to_acl(&solaris_acl, &count, + default_acl, default_count, + SMB_ACL_TYPE_DEFAULT)) + { + DEBUG(10, ("error adding default acl to solaris acl\n")); + goto done; + } + if (!solaris_acl_sort(solaris_acl, count)) { + DEBUG(10, ("resulting acl is not valid!\n")); + goto done; + } + + ret = facl(fd, SETACL, count, solaris_acl); + if (ret != 0) { + DEBUG(10, ("call of facl failed (%s).\n", strerror(errno))); + } + + done: + DEBUG(10, ("solarisacl_sys_acl_st_fd %s.\n", + ((ret == 0) ? "succeded" : "failed" ))); + SAFE_FREE(solaris_acl); + SAFE_FREE(default_acl); + return ret; +} + +/* + * delete the default ACL of a directory + * + * This is achieved by fetching the access ACL and rewriting it + * directly, via the solaris system call: the SETACL call on + * directories writes both the access and the default ACL as provided. + * + * XXX: posix acl_delete_def_file returns an error if + * the file referred to by path is not a directory. + * this function does not complain but the actions + * have no effect on a file other than a directory. + * But sys_acl_delete_default_file is only called in + * smbd/posixacls.c after having checked that the file + * is a directory, anyways. So implementing the extra + * check is considered unnecessary. --- Agreed? XXX + */ +int solarisacl_sys_acl_delete_def_file(vfs_handle_struct *handle, + const char *path) +{ + SMB_ACL_T smb_acl; + int ret = -1; + SOLARIS_ACL_T solaris_acl; + int count; + + DEBUG(10, ("entering solarisacl_sys_acl_delete_def_file.\n")); + + smb_acl = solarisacl_sys_acl_get_file(handle, path, + SMB_ACL_TYPE_ACCESS); + if (smb_acl == NULL) { + DEBUG(10, ("getting file acl failed!\n")); + goto done; + } + if (!smb_acl_to_solaris_acl(smb_acl, &solaris_acl, &count, + SMB_ACL_TYPE_ACCESS)) + { + DEBUG(10, ("conversion smb_acl -> solaris_acl failed.\n")); + goto done; + } + if (!solaris_acl_sort(solaris_acl, count)) { + DEBUG(10, ("resulting acl is not valid!\n")); + goto done; + } + ret = acl(path, SETACL, count, solaris_acl); + if (ret != 0) { + DEBUG(10, ("settinge file acl failed!\n")); + } + + done: + DEBUG(10, ("solarisacl_sys_acl_delete_def_file %s.\n", + ((ret != 0) ? "failed" : "succeeded" ))); + SAFE_FREE(smb_acl); + return ret; +} + + +/* private functions */ + +static SOLARIS_ACL_T solaris_acl_init(int count) +{ + SOLARIS_ACL_T solaris_acl = + (SOLARIS_ACL_T)SMB_MALLOC(sizeof(aclent_t) * count); + if (solaris_acl == NULL) { + errno = ENOMEM; + } + return solaris_acl; +} + +/* + * Convert the SMB acl to the ACCESS or DEFAULT part of a + * solaris ACL, as desired. + */ +static BOOL smb_acl_to_solaris_acl(SMB_ACL_T smb_acl, + SOLARIS_ACL_T *solaris_acl, int *count, + SMB_ACL_TYPE_T type) +{ + BOOL ret = False; + int i; + int check_which, check_rc; + + DEBUG(10, ("entering smb_acl_to_solaris_acl\n")); + + *solaris_acl = NULL; + *count = 0; + + for (i = 0; i < smb_acl->count; i++) { + const struct smb_acl_entry *smb_entry = &(smb_acl->acl[i]); + SOLARIS_ACE_T solaris_entry; + + ZERO_STRUCT(solaris_entry); + + solaris_entry.a_type = smb_tag_to_solaris_tag(smb_entry->a_type); + if (solaris_entry.a_type == 0) { + DEBUG(10, ("smb_tag to solaris_tag failed\n")); + goto fail; + } + switch(solaris_entry.a_type) { + case USER: + DEBUG(10, ("got tag type USER with uid %d\n", + smb_entry->uid)); + solaris_entry.a_id = (uid_t)smb_entry->uid; + break; + case GROUP: + DEBUG(10, ("got tag type GROUP with gid %d\n", + smb_entry->gid)); + solaris_entry.a_id = (uid_t)smb_entry->gid; + break; + default: + break; + } + if (type == SMB_ACL_TYPE_DEFAULT) { + DEBUG(10, ("adding default bit to solaris ace\n")); + solaris_entry.a_type |= ACL_DEFAULT; + } + + solaris_entry.a_perm = + smb_perm_to_solaris_perm(smb_entry->a_perm); + DEBUG(10, ("assembled the following solaris ace:\n")); + DEBUGADD(10, (" - type: 0x%04x\n", solaris_entry.a_type)); + DEBUGADD(10, (" - id: %d\n", solaris_entry.a_id)); + DEBUGADD(10, (" - perm: o%o\n", solaris_entry.a_perm)); + if (!solaris_add_to_acl(solaris_acl, count, &solaris_entry, + 1, type)) + { + DEBUG(10, ("error adding acl entry\n")); + goto fail; + } + DEBUG(10, ("count after adding: %d (i: %d)\n", *count, i)); + DEBUG(10, ("test, if entry has been copied into acl:\n")); + DEBUGADD(10, (" - type: 0x%04x\n", + (*solaris_acl)[(*count)-1].a_type)); + DEBUGADD(10, (" - id: %d\n", + (*solaris_acl)[(*count)-1].a_id)); + DEBUGADD(10, (" - perm: o%o\n", + (*solaris_acl)[(*count)-1].a_perm)); + } + + ret = True; + goto done; + + fail: + SAFE_FREE(*solaris_acl); + done: + DEBUG(10, ("smb_acl_to_solaris_acl %s\n", + ((ret == True) ? "succeeded" : "failed"))); + return ret; +} + +/* + * convert either the access or the default part of a + * soaris acl to the SMB_ACL format. + */ +static SMB_ACL_T solaris_acl_to_smb_acl(SOLARIS_ACL_T solaris_acl, int count, + SMB_ACL_TYPE_T type) +{ + SMB_ACL_T result; + int i; + + if ((result = sys_acl_init(0)) == NULL) { + DEBUG(10, ("error allocating memory for SMB_ACL\n")); + goto fail; + } + for (i = 0; i < count; i++) { + SMB_ACL_ENTRY_T smb_entry; + SMB_ACL_PERM_T smb_perm; + + if (!_IS_OF_TYPE(solaris_acl[i], type)) { + continue; + } + result = SMB_REALLOC(result, + sizeof(struct smb_acl_t) + + (sizeof(struct smb_acl_entry) * + (result->count + 1))); + if (result == NULL) { + DEBUG(10, ("error reallocating memory for SMB_ACL\n")); + goto fail; + } + smb_entry = &result->acl[result->count]; + if (sys_acl_set_tag_type(smb_entry, + solaris_tag_to_smb_tag(solaris_acl[i].a_type)) != 0) + { + DEBUG(10, ("invalid tag type given: 0x%04x\n", + solaris_acl[i].a_type)); + goto fail; + } + /* intentionally not checking return code here: */ + sys_acl_set_qualifier(smb_entry, (void *)&solaris_acl[i].a_id); + smb_perm = solaris_perm_to_smb_perm(solaris_acl[i].a_perm); + if (sys_acl_set_permset(smb_entry, &smb_perm) != 0) { + DEBUG(10, ("invalid permset given: %d\n", + solaris_acl[i].a_perm)); + goto fail; + } + result->count += 1; + } + goto done; + + fail: + SAFE_FREE(result); + done: + DEBUG(10, ("solaris_acl_to_smb_acl %s\n", + ((result == NULL) ? "failed" : "succeeded"))); + return result; +} + + + +static SOLARIS_ACL_TAG_T smb_tag_to_solaris_tag(SMB_ACL_TAG_T smb_tag) +{ + SOLARIS_ACL_TAG_T solaris_tag = 0; + + DEBUG(10, ("smb_tag_to_solaris_tag\n")); + DEBUGADD(10, (" --> got smb tag 0x%04x\n", smb_tag)); + + switch (smb_tag) { + case SMB_ACL_USER: + solaris_tag = USER; + break; + case SMB_ACL_USER_OBJ: + solaris_tag = USER_OBJ; + break; + case SMB_ACL_GROUP: + solaris_tag = GROUP; + break; + case SMB_ACL_GROUP_OBJ: + solaris_tag = GROUP_OBJ; + break; + case SMB_ACL_OTHER: + solaris_tag = OTHER_OBJ; + break; + case SMB_ACL_MASK: + solaris_tag = CLASS_OBJ; + break; + default: + DEBUGADD(10, (" !!! unknown smb tag type 0x%04x\n", smb_tag)); + break; + } + + DEBUGADD(10, (" --> determined solaris tag 0x%04x\n", solaris_tag)); + + return solaris_tag; +} + +static SMB_ACL_TAG_T solaris_tag_to_smb_tag(SOLARIS_ACL_TAG_T solaris_tag) +{ + SMB_ACL_TAG_T smb_tag = 0; + + DEBUG(10, ("solaris_tag_to_smb_tag:\n")); + DEBUGADD(10, (" --> got solaris tag 0x%04x\n", solaris_tag)); + + solaris_tag &= ~ACL_DEFAULT; + + switch (solaris_tag) { + case USER: + smb_tag = SMB_ACL_USER; + break; + case USER_OBJ: + smb_tag = SMB_ACL_USER_OBJ; + break; + case GROUP: + smb_tag = SMB_ACL_GROUP; + break; + case GROUP_OBJ: + smb_tag = SMB_ACL_GROUP_OBJ; + break; + case OTHER_OBJ: + smb_tag = SMB_ACL_OTHER; + break; + case CLASS_OBJ: + smb_tag = SMB_ACL_MASK; + break; + default: + DEBUGADD(10, (" !!! unknown solaris tag type: 0x%04x\n", + solaris_tag)); + break; + } + + DEBUGADD(10, (" --> determined smb tag 0x%04x\n", smb_tag)); + + return smb_tag; +} + + +static SMB_ACL_PERM_T solaris_perm_to_smb_perm(const SOLARIS_PERM_T perm) +{ + SMB_ACL_PERM_T smb_perm = 0; + smb_perm |= ((perm & SMB_ACL_READ) ? SMB_ACL_READ : 0); + smb_perm |= ((perm & SMB_ACL_WRITE) ? SMB_ACL_WRITE : 0); + smb_perm |= ((perm & SMB_ACL_EXECUTE) ? SMB_ACL_EXECUTE : 0); + return smb_perm; +} + + +static SOLARIS_PERM_T smb_perm_to_solaris_perm(const SMB_ACL_PERM_T perm) +{ + SOLARIS_PERM_T solaris_perm = 0; + solaris_perm |= ((perm & SMB_ACL_READ) ? SMB_ACL_READ : 0); + solaris_perm |= ((perm & SMB_ACL_WRITE) ? SMB_ACL_WRITE : 0); + solaris_perm |= ((perm & SMB_ACL_EXECUTE) ? SMB_ACL_EXECUTE : 0); + return solaris_perm; +} + + +static BOOL solaris_acl_get_file(const char *name, SOLARIS_ACL_T *solaris_acl, + int *count) +{ + BOOL result = False; + + DEBUG(10, ("solaris_acl_get_file called for file '%s'\n", name)); + + /* + * The original code tries some INITIAL_ACL_SIZE + * and only did the GETACLCNT call upon failure + * (for performance reasons). + * For the sake of simplicity, I skip this for now. + */ + *count = acl(name, GETACLCNT, 0, NULL); + if (*count < 0) { + DEBUG(10, ("acl GETACLCNT failed: %s\n", strerror(errno))); + goto done; + } + *solaris_acl = solaris_acl_init(*count); + if (*solaris_acl == NULL) { + DEBUG(10, ("error allocating memory for solaris acl...\n")); + goto done; + } + *count = acl(name, GETACL, *count, *solaris_acl); + if (*count < 0) { + DEBUG(10, ("acl GETACL failed: %s\n", strerror(errno))); + goto done; + } + result = True; + + done: + DEBUG(10, ("solaris_acl_get_file %s.\n", + ((result == True) ? "succeeded" : "failed" ))); + return result; +} + + +static BOOL solaris_acl_get_fd(int fd, SOLARIS_ACL_T *solaris_acl, int *count) +{ + BOOL ret = False; + + DEBUG(10, ("entering solaris_acl_get_fd\n")); + + /* + * see solaris_acl_get_file for comment about omission + * of INITIAL_ACL_SIZE... + */ + *count = facl(fd, GETACLCNT, 0, NULL); + if (*count < 0) { + DEBUG(10, ("facl GETACLCNT failed: %s\n", strerror(errno))); + goto done; + } + *solaris_acl = solaris_acl_init(*count); + if (*solaris_acl == NULL) { + DEBUG(10, ("error allocating memory for solaris acl...\n")); + goto done; + } + *count = facl(fd, GETACL, *count, *solaris_acl); + if (*count < 0) { + DEBUG(10, ("facl GETACL failed: %s\n", strerror(errno))); + goto done; + } + ret = True; + + done: + DEBUG(10, ("solaris_acl_get_fd %s\n", + ((ret == True) ? "succeeded" : "failed"))); + return ret; +} + + + +/* + * Add entries to a solaris ACL. + * + * Entries are directly added to the solarisacl parameter. + * if memory allocation fails, this may result in solarisacl + * being NULL. if the resulting acl is to be checked and is + * not valid, it is kept in solarisacl but False is returned. + * + * The type of ACEs (access/default) to be added to the ACL can + * be selected via the type parameter. + * I use the SMB_ACL_TYPE_T type here. Since SMB_ACL_TYPE_ACCESS + * is defined as "0", this means that one can only add either + * access or default ACEs, not both at the same time. If it + * should become necessary to add all of an ACL, one would have + * to replace this parameter by another type. + */ +static BOOL solaris_add_to_acl(SOLARIS_ACL_T *solaris_acl, int *count, + SOLARIS_ACL_T add_acl, int add_count, + SMB_ACL_TYPE_T type) +{ + int i; + + if ((type != SMB_ACL_TYPE_ACCESS) && (type != SMB_ACL_TYPE_DEFAULT)) + { + DEBUG(10, ("invalid acl type given: %d\n", type)); + errno = EINVAL; + return False; + } + for (i = 0; i < add_count; i++) { + if (!_IS_OF_TYPE(add_acl[i], type)) { + continue; + } + ADD_TO_ARRAY(NULL, SOLARIS_ACE_T, add_acl[i], + solaris_acl, count); + if (solaris_acl == NULL) { + DEBUG(10, ("error enlarging acl.\n")); + errno = ENOMEM; + return False; + } + } + return True; +} + + +/* + * sort the ACL and check it for validity + * + * [original comment from lib/sysacls.c:] + * + * if it's a minimal ACL with only 4 entries then we + * need to recalculate the mask permissions to make + * sure that they are the same as the GROUP_OBJ + * permissions as required by the UnixWare acl() system call. + * + * (note: since POSIX allows minimal ACLs which only contain + * 3 entries - ie there is no mask entry - we should, in theory, + * check for this and add a mask entry if necessary - however + * we "know" that the caller of this interface always specifies + * a mask, so in practice "this never happens" (tm) - if it *does* + * happen aclsort() will fail and return an error and someone will + * have to fix it...) + */ +static BOOL solaris_acl_sort(SOLARIS_ACL_T solaris_acl, int count) +{ + int fixmask = (count <= 4); + + if (aclsort(count, fixmask, solaris_acl) != 0) { + errno = EINVAL; + return False; + } + return True; +} + +/* + * acl check function: + * unused at the moment but could be used to get more + * concrete error messages for debugging... + * (acl sort just says that the acl is invalid...) + */ +static BOOL solaris_acl_check(SOLARIS_ACL_T solaris_acl, int count) +{ + int check_rc; + int check_which; + + check_rc = aclcheck(solaris_acl, count, &check_which); + if (check_rc != 0) { + DEBUG(10, ("acl is not valid:\n")); + DEBUGADD(10, (" - return code: %d\n", check_rc)); + DEBUGADD(10, (" - which: %d\n", check_which)); + if (check_which != -1) { + DEBUGADD(10, (" - invalid entry:\n")); + DEBUGADD(10, (" * type: %d:\n", + solaris_acl[check_which].a_type)); + DEBUGADD(10, (" * id: %d\n", + solaris_acl[check_which].a_id)); + DEBUGADD(10, (" * perm: 0o%o\n", + solaris_acl[check_which].a_perm)); + } + return False; + } + return True; +} + + +/* VFS operations structure */ + +static vfs_op_tuple solarisacl_op_tuples[] = { + /* Disk operations */ + {SMB_VFS_OP(solarisacl_sys_acl_get_file), + SMB_VFS_OP_SYS_ACL_GET_FILE, + SMB_VFS_LAYER_TRANSPARENT}, + + {SMB_VFS_OP(solarisacl_sys_acl_get_fd), + SMB_VFS_OP_SYS_ACL_GET_FD, + SMB_VFS_LAYER_TRANSPARENT}, + + {SMB_VFS_OP(solarisacl_sys_acl_set_file), + SMB_VFS_OP_SYS_ACL_SET_FILE, + SMB_VFS_LAYER_TRANSPARENT}, + + {SMB_VFS_OP(solarisacl_sys_acl_set_fd), + SMB_VFS_OP_SYS_ACL_SET_FD, + SMB_VFS_LAYER_TRANSPARENT}, + + {SMB_VFS_OP(solarisacl_sys_acl_delete_def_file), + SMB_VFS_OP_SYS_ACL_DELETE_DEF_FILE, + SMB_VFS_LAYER_TRANSPARENT}, + + {SMB_VFS_OP(NULL), + SMB_VFS_OP_NOOP, + SMB_VFS_LAYER_NOOP} +}; + +NTSTATUS vfs_solarisacl_init(void) +{ + return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "solarisacl", + solarisacl_op_tuples); +} + +/* ENTE */ diff --git a/source3/modules/vfs_tru64acl.c b/source3/modules/vfs_tru64acl.c new file mode 100644 index 0000000000..774fadf4b9 --- /dev/null +++ b/source3/modules/vfs_tru64acl.c @@ -0,0 +1,504 @@ +/* + Unix SMB/Netbios implementation. + VFS module to get and set Tru64 acls + Copyright (C) Michael Adam 2006 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +/* prototypes for private functions first - for clarity */ + +static struct smb_acl_t *tru64_acl_to_smb_acl(const struct acl *tru64_acl); +static BOOL tru64_ace_to_smb_ace(acl_entry_t tru64_ace, + struct smb_acl_entry *smb_ace); +static acl_t smb_acl_to_tru64_acl(const SMB_ACL_T smb_acl); +static acl_tag_t smb_tag_to_tru64(SMB_ACL_TAG_T smb_tag); +static SMB_ACL_TAG_T tru64_tag_to_smb(acl_tag_t tru64_tag); +static acl_perm_t smb_permset_to_tru64(smb_acl_permset_t smb_permset); +static smb_acl_permset_t tru64_permset_to_smb(const acl_perm_t tru64_permset); + + +/* public functions - the api */ + +SMB_ACL_T tru64acl_sys_acl_get_file(vfs_handle_struct *handle, + const char *path_p, + SMB_ACL_TYPE_T type) +{ + struct smb_acl_t *result; + acl_type_t the_acl_type; + acl_t tru64_acl; + + DEBUG(10, ("Hi! This is tru64acl_sys_acl_get_file.\n")); + + switch(type) { + case SMB_ACL_TYPE_ACCESS: + the_acl_type = ACL_TYPE_ACCESS; + break; + case SMB_ACL_TYPE_DEFAULT: + the_acl_type = ACL_TYPE_DEFAULT; + break; + default: + errno = EINVAL; + return NULL; + } + + tru64_acl = acl_get_file((char *)path_p, the_acl_type); + + if (tru64_acl == NULL) { + return NULL; + } + + result = tru64_acl_to_smb_acl(tru64_acl); + acl_free(tru64_acl); + return result; +} + +SMB_ACL_T tru64acl_sys_acl_get_fd(vfs_handle_struct *handle, + files_struct *fsp, + int fd) +{ + struct smb_acl_t *result; + acl_t tru64_acl = acl_get_fd(fd, ACL_TYPE_ACCESS); + + if (tru64_acl == NULL) { + return NULL; + } + + result = tru64_acl_to_smb_acl(tru64_acl); + acl_free(tru64_acl); + return result; +} + +int tru64acl_sys_acl_set_file(vfs_handle_struct *handle, + const char *name, + SMB_ACL_TYPE_T type, + SMB_ACL_T theacl) +{ + int res; + acl_type_t the_acl_type; + acl_t tru64_acl; + + DEBUG(10, ("tru64acl_sys_acl_set_file called with name %s, type %d\n", + name, type)); + + switch(type) { + case SMB_ACL_TYPE_ACCESS: + DEBUGADD(10, ("got acl type ACL_TYPE_ACCESS\n")); + the_acl_type = ACL_TYPE_ACCESS; + break; + case SMB_ACL_TYPE_DEFAULT: + DEBUGADD(10, ("got acl type ACL_TYPE_DEFAULT\n")); + the_acl_type = ACL_TYPE_DEFAULT; + break; + default: + DEBUGADD(10, ("invalid acl type\n")); + errno = EINVAL; + goto fail; + } + + tru64_acl = smb_acl_to_tru64_acl(theacl); + if (tru64_acl == NULL) { + DEBUG(10, ("smb_acl_to_tru64_acl failed!\n")); + goto fail; + } + DEBUG(10, ("got tru64 acl...\n")); + res = acl_set_file((char *)name, the_acl_type, tru64_acl); + acl_free(tru64_acl); + if (res != 0) { + DEBUG(10, ("acl_set_file failed: %s\n", strerror(errno))); + goto fail; + } + return res; +fail: + DEBUG(1, ("tru64acl_sys_acl_set_file failed!\n")); + return -1; +} + +int tru64acl_sys_acl_set_fd(vfs_handle_struct *handle, + files_struct *fsp, + int fd, SMB_ACL_T theacl) +{ + int res; + acl_t tru64_acl = smb_acl_to_tru64_acl(theacl); + if (tru64_acl == NULL) { + return -1; + } + res = acl_set_fd(fd, ACL_TYPE_ACCESS, tru64_acl); + acl_free(tru64_acl); + return res; + +} + +int tru64acl_sys_acl_delete_def_file(vfs_handle_struct *handle, + const char *path) +{ + return acl_delete_def_file((char *)path); +} + + +/* private functions */ + +static struct smb_acl_t *tru64_acl_to_smb_acl(const struct acl *tru64_acl) +{ + struct smb_acl_t *result; + acl_entry_t entry; + + DEBUG(10, ("Hi! This is tru64_acl_to_smb_acl.\n")); + + if ((result = SMB_MALLOC_P(struct smb_acl_t)) == NULL) { + DEBUG(0, ("SMB_MALLOC_P failed in tru64_acl_to_smb_acl\n")); + errno = ENOMEM; + goto fail; + } + ZERO_STRUCTP(result); + if (acl_first_entry((struct acl *)tru64_acl) != 0) { + DEBUG(10, ("acl_first_entry failed: %s\n", strerror(errno))); + goto fail; + } + while ((entry = acl_get_entry((struct acl *)tru64_acl)) != NULL) { + result = SMB_REALLOC(result, sizeof(struct smb_acl_t) + + (sizeof(struct smb_acl_entry) * + (result->count + 1))); + if (result == NULL) { + DEBUG(0, ("SMB_REALLOC failed in tru64_acl_to_smb_acl\n")); + errno = ENOMEM; + goto fail; + } + /* XYZ */ + if (!tru64_ace_to_smb_ace(entry, &result->acl[result->count])) { + SAFE_FREE(result); + goto fail; + } + result->count += 1; + } + return result; + +fail: + if (result != NULL) { + SAFE_FREE(result); + } + DEBUG(1, ("tru64_acl_to_smb_acl failed!\n")); + return NULL; +} + +static BOOL tru64_ace_to_smb_ace(acl_entry_t tru64_ace, + struct smb_acl_entry *smb_ace) +{ + acl_tag_t tru64_tag; + acl_permset_t permset; + SMB_ACL_TAG_T smb_tag_type; + smb_acl_permset_t smb_permset; + void *qualifier; + + if (acl_get_tag_type(tru64_ace, &tru64_tag) != 0) { + DEBUG(0, ("acl_get_tag_type failed: %s\n", strerror(errno))); + return False; + } + + /* On could set the tag type directly to save a function call, + * but I like this better... */ + smb_tag_type = tru64_tag_to_smb(tru64_tag); + if (smb_tag_type == 0) { + DEBUG(3, ("invalid tag type given: %d\n", tru64_tag)); + return False; + } + if (sys_acl_set_tag_type(smb_ace, smb_tag_type) != 0) { + DEBUG(3, ("sys_acl_set_tag_type failed: %s\n", + strerror(errno))); + return False; + } + qualifier = acl_get_qualifier(tru64_ace); + if (qualifier != NULL) { + if (sys_acl_set_qualifier(smb_ace, qualifier) != 0) { + DEBUG(3, ("sys_acl_set_qualifier failed\n")); + return False; + } + } + if (acl_get_permset(tru64_ace, &permset) != 0) { + DEBUG(3, ("acl_get_permset failed: %s\n", strerror(errno))); + return False; + } + smb_permset = tru64_permset_to_smb(*permset); + if (sys_acl_set_permset(smb_ace, &smb_permset) != 0) { + DEBUG(3, ("sys_acl_set_permset failed: %s\n", strerror(errno))); + return False; + } + return True; +} + +static acl_t smb_acl_to_tru64_acl(const SMB_ACL_T smb_acl) +{ + acl_t result; + acl_entry_t tru64_entry; + int i; + char *acl_text; + ssize_t acl_text_len; + + /* The tru64 acl_init function takes a size_t value + * instead of a count of entries (as with posix). + * the size parameter "Specifies the size of the working + * storage in bytes" (according to the man page). + * But it is unclear to me, how this size is to be + * calculated. + * + * It should not matter, since acl_create_entry enlarges + * the working storage at need. ... */ + + DEBUG(10, ("Hi! This is smb_acl_to_tru64_acl.\n")); + + result = acl_init(1); + + if (result == NULL) { + DEBUG(3, ("acl_init failed!\n")); + goto fail; + } + + DEBUGADD(10, ("parsing acl entries...\n")); + for (i = 0; i < smb_acl->count; i++) { + /* XYZ - maybe eliminate this direct access? */ + const struct smb_acl_entry *smb_entry = &smb_acl->acl[i]; + acl_tag_t tru64_tag; + acl_perm_t tru64_permset; + + tru64_tag = smb_tag_to_tru64(smb_entry->a_type); + if (tru64_tag == -1) { + DEBUG(3, ("smb_tag_to_tru64 failed!\n")); + goto fail; + } + + if (tru64_tag == ACL_MASK) { + DEBUGADD(10, (" - acl type ACL_MASK: not implemented on Tru64 ==> skipping\n")); + continue; + } + + tru64_entry = acl_create_entry(&result); + if (tru64_entry == NULL) { + DEBUG(3, ("acl_create_entry failed: %s\n", + strerror(errno))); + goto fail; + } + + if (acl_set_tag_type(tru64_entry, tru64_tag) != 0) { + DEBUG(3, ("acl_set_tag_type(%d) failed: %s\n", + strerror(errno))); + goto fail; + } + + switch (smb_entry->a_type) { + case SMB_ACL_USER: + if (acl_set_qualifier(tru64_entry, + (int *)&smb_entry->uid) != 0) + { + DEBUG(3, ("acl_set_qualifier failed: %s\n", + strerror(errno))); + goto fail; + } + DEBUGADD(10, (" - setting uid to %d\n", smb_entry->uid)); + break; + case SMB_ACL_GROUP: + if (acl_set_qualifier(tru64_entry, + (int *)&smb_entry->gid) != 0) + { + DEBUG(3, ("acl_set_qualifier failed: %s\n", + strerror(errno))); + goto fail; + } + DEBUGADD(10, (" - setting gid to %d\n", smb_entry->gid)); + break; + default: + break; + } + + tru64_permset = smb_permset_to_tru64(smb_entry->a_perm); + if (tru64_permset == -1) { + DEBUG(3, ("smb_permset_to_tru64 failed!\n")); + goto fail; + } + DEBUGADD(10, (" - setting perms to %0d\n", tru64_permset)); + if (acl_set_permset(tru64_entry, &tru64_permset) != 0) + { + DEBUG(3, ("acl_set_permset failed: %s\n", strerror(errno))); + goto fail; + } + } /* for */ + DEBUGADD(10, ("done parsing acl entries\n")); + + tru64_entry = NULL; + if (acl_valid(result, &tru64_entry) != 0) { + DEBUG(1, ("smb_acl_to_tru64_acl: ACL is invalid (%s)\n", + strerror(errno))); + if (tru64_entry != NULL) { + DEBUGADD(1, ("the acl contains duplicate entries\n")); + } + goto fail; + } + DEBUGADD(10, ("acl is valid\n")); + + acl_text = acl_to_text(result, &acl_text_len); + if (acl_text == NULL) { + DEBUG(3, ("acl_to_text failed: %s\n", strerror(errno))); + goto fail; + } + DEBUG(1, ("acl_text: %s\n", acl_text)); + free(acl_text); + + return result; + +fail: + if (result != NULL) { + acl_free(result); + } + DEBUG(1, ("smb_acl_to_tru64_acl failed!\n")); + return NULL; +} + +static acl_tag_t smb_tag_to_tru64(SMB_ACL_TAG_T smb_tag) +{ + acl_tag_t result; + switch (smb_tag) { + case SMB_ACL_USER: + result = ACL_USER; + DEBUGADD(10, ("got acl type ACL_USER\n")); + break; + case SMB_ACL_USER_OBJ: + result = ACL_USER_OBJ; + DEBUGADD(10, ("got acl type ACL_USER_OBJ\n")); + break; + case SMB_ACL_GROUP: + result = ACL_GROUP; + DEBUGADD(10, ("got acl type ACL_GROUP\n")); + break; + case SMB_ACL_GROUP_OBJ: + result = ACL_GROUP_OBJ; + DEBUGADD(10, ("got acl type ACL_GROUP_OBJ\n")); + break; + case SMB_ACL_OTHER: + result = ACL_OTHER; + DEBUGADD(10, ("got acl type ACL_OTHER\n")); + break; + case SMB_ACL_MASK: + result = ACL_MASK; + DEBUGADD(10, ("got acl type ACL_MASK\n")); + break; + default: + DEBUG(1, ("Unknown tag type %d\n", smb_tag)); + result = -1; + } + return result; +} + + +static SMB_ACL_TAG_T tru64_tag_to_smb(acl_tag_t tru64_tag) +{ + SMB_ACL_TAG_T smb_tag_type; + switch(tru64_tag) { + case ACL_USER: + smb_tag_type = SMB_ACL_USER; + DEBUGADD(10, ("got smb acl tag type SMB_ACL_USER\n")); + break; + case ACL_USER_OBJ: + smb_tag_type = SMB_ACL_USER_OBJ; + DEBUGADD(10, ("got smb acl tag type SMB_ACL_USER_OBJ\n")); + break; + case ACL_GROUP: + smb_tag_type = SMB_ACL_GROUP; + DEBUGADD(10, ("got smb acl tag type SMB_ACL_GROUP\n")); + break; + case ACL_GROUP_OBJ: + smb_tag_type = SMB_ACL_GROUP_OBJ; + DEBUGADD(10, ("got smb acl tag type SMB_ACL_GROUP_OBJ\n")); + break; + case ACL_OTHER: + smb_tag_type = SMB_ACL_OTHER; + DEBUGADD(10, ("got smb acl tag type SMB_ACL_OTHER\n")); + break; + case ACL_MASK: + smb_tag_type = SMB_ACL_MASK; + DEBUGADD(10, ("got smb acl tag type SMB_ACL_MASK\n")); + break; + default: + DEBUG(0, ("Unknown tag type %d\n", (unsigned int)tru64_tag)); + smb_tag_type = 0; + } + return smb_tag_type; +} + +static acl_perm_t smb_permset_to_tru64(smb_acl_permset_t smb_permset) +{ + /* originally, I thought that acl_clear_perm was the + * proper way to reset the permset to 0. but without + * initializing it to 0, acl_clear_perm fails. + * so probably, acl_clear_perm is not necessary here... ?! */ + acl_perm_t tru64_permset = 0; + if (acl_clear_perm(&tru64_permset) != 0) { + DEBUG(5, ("acl_clear_perm failed: %s\n", strerror(errno))); + return -1; + } + /* according to original lib/sysacls.c, acl_add_perm is + * broken on tru64 ... */ + tru64_permset |= ((smb_permset & SMB_ACL_READ) ? ACL_READ : 0); + tru64_permset |= ((smb_permset & SMB_ACL_WRITE) ? ACL_WRITE : 0); + tru64_permset |= ((smb_permset & SMB_ACL_EXECUTE) ? ACL_EXECUTE : 0); + return tru64_permset; +} + +static smb_acl_permset_t tru64_permset_to_smb(const acl_perm_t tru64_permset) +{ + smb_acl_permset_t smb_permset = 0; + smb_permset |= ((tru64_permset & ACL_READ) ? SMB_ACL_READ : 0); + smb_permset |= ((tru64_permset & ACL_WRITE) ? SMB_ACL_WRITE : 0); + smb_permset |= ((tru64_permset & ACL_EXECUTE) ? SMB_ACL_EXECUTE : 0); + return smb_permset; +} + + +/* VFS operations structure */ + +static vfs_op_tuple tru64acl_op_tuples[] = { + /* Disk operations */ + {SMB_VFS_OP(tru64acl_sys_acl_get_file), + SMB_VFS_OP_SYS_ACL_GET_FILE, + SMB_VFS_LAYER_TRANSPARENT}, + + {SMB_VFS_OP(tru64acl_sys_acl_get_fd), + SMB_VFS_OP_SYS_ACL_GET_FD, + SMB_VFS_LAYER_TRANSPARENT}, + + {SMB_VFS_OP(tru64acl_sys_acl_set_file), + SMB_VFS_OP_SYS_ACL_SET_FILE, + SMB_VFS_LAYER_TRANSPARENT}, + + {SMB_VFS_OP(tru64acl_sys_acl_set_fd), + SMB_VFS_OP_SYS_ACL_SET_FD, + SMB_VFS_LAYER_TRANSPARENT}, + + {SMB_VFS_OP(tru64acl_sys_acl_delete_def_file), + SMB_VFS_OP_SYS_ACL_DELETE_DEF_FILE, + SMB_VFS_LAYER_TRANSPARENT}, + + {SMB_VFS_OP(NULL), + SMB_VFS_OP_NOOP, + SMB_VFS_LAYER_NOOP} +}; + +NTSTATUS vfs_tru64acl_init(void) +{ + return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "tru64acl", + tru64acl_op_tuples); +} + +/* ENTE */ diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index d265057ac0..3ea442f818 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -575,6 +575,9 @@ static void print_canon_ace(canon_ace *pace, int num) case SMB_ACL_OTHER: dbgtext( "SMB_ACL_OTHER "); break; + default: + dbgtext( "MASK " ); + break; } if (pace->inherited) dbgtext( "(inherited) "); @@ -2436,17 +2439,6 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau } /* - * Check if the ACL is valid. - */ - - if (SMB_VFS_SYS_ACL_VALID(conn, the_acl) == -1) { - DEBUG(0,("set_canon_ace_list: ACL type (%s) is invalid for set (%s).\n", - the_acl_type == SMB_ACL_TYPE_DEFAULT ? "directory default" : "file", - strerror(errno) )); - goto fail; - } - - /* * Finally apply it to the file or directory. */ |