diff options
Diffstat (limited to 'source3')
-rw-r--r-- | source3/acconfig.h | 1 | ||||
-rwxr-xr-x | source3/configure | 35 | ||||
-rw-r--r-- | source3/configure.in | 4 | ||||
-rw-r--r-- | source3/include/config.h.in | 1 | ||||
-rw-r--r-- | source3/include/smb_acls.h | 47 | ||||
-rw-r--r-- | source3/lib/ms_fnmatch.c | 105 | ||||
-rw-r--r-- | source3/lib/sysacls.c | 887 |
7 files changed, 1062 insertions, 18 deletions
diff --git a/source3/acconfig.h b/source3/acconfig.h index 63af9f78c17..c6f324deae8 100644 --- a/source3/acconfig.h +++ b/source3/acconfig.h @@ -144,4 +144,5 @@ #undef HAVE_SOLARIS_ACLS #undef HAVE_IRIX_ACLS #undef HAVE_XFS_ACLS +#undef HAVE_AIX_ACLS #undef HAVE_NO_ACLS diff --git a/source3/configure b/source3/configure index 55be2c5474a..13d45b93807 100755 --- a/source3/configure +++ b/source3/configure @@ -12061,9 +12061,16 @@ EOF EOF ;; + *aix*) + echo "$ac_t""Using AIX ACLs" 1>&6 + cat >> confdefs.h <<\EOF +#define HAVE_AIX_ACLS 1 +EOF + + ;; *) echo $ac_n "checking for acl_get_file in -lacl""... $ac_c" 1>&6 -echo "configure:12067: checking for acl_get_file in -lacl" >&5 +echo "configure:12074: checking for acl_get_file in -lacl" >&5 ac_lib_var=`echo acl'_'acl_get_file | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -12071,7 +12078,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lacl $LIBS" cat > conftest.$ac_ext <<EOF -#line 12075 "configure" +#line 12082 "configure" #include "confdefs.h" /* Override any gcc2 internal prototype to avoid an error. */ /* We use char because int might match the return type of a gcc2 @@ -12082,7 +12089,7 @@ int main() { acl_get_file() ; return 0; } EOF -if { (eval echo configure:12086: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:12093: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -12110,13 +12117,13 @@ else fi echo $ac_n "checking for ACL support""... $ac_c" 1>&6 -echo "configure:12114: checking for ACL support" >&5 +echo "configure:12121: checking for ACL support" >&5 if eval "test \"`echo '$''{'samba_cv_HAVE_POSIX_ACLS'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 12120 "configure" +#line 12127 "configure" #include "confdefs.h" #include <sys/types.h> #include <sys/acl.h> @@ -12124,7 +12131,7 @@ int main() { acl_t acl; int entry_id; acl_entry_t *entry_p; return acl_get_entry( acl, entry_id, entry_p); ; return 0; } EOF -if { (eval echo configure:12128: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:12135: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* samba_cv_HAVE_POSIX_ACLS=yes else @@ -12144,13 +12151,13 @@ echo "$ac_t""$samba_cv_HAVE_POSIX_ACLS" 1>&6 EOF echo $ac_n "checking for acl_get_perm_np""... $ac_c" 1>&6 -echo "configure:12148: checking for acl_get_perm_np" >&5 +echo "configure:12155: checking for acl_get_perm_np" >&5 if eval "test \"`echo '$''{'samba_cv_HAVE_ACL_GET_PERM_NP'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 12154 "configure" +#line 12161 "configure" #include "confdefs.h" #include <sys/types.h> #include <sys/acl.h> @@ -12158,7 +12165,7 @@ int main() { acl_permset_t permset_d; acl_perm_t perm; return acl_get_perm_np( permset_d, perm); ; return 0; } EOF -if { (eval echo configure:12162: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:12169: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* samba_cv_HAVE_ACL_GET_PERM_NP=yes else @@ -12179,13 +12186,13 @@ EOF fi fi echo $ac_n "checking for XFS ACL support""... $ac_c" 1>&6 -echo "configure:12183: checking for XFS ACL support" >&5 +echo "configure:12190: checking for XFS ACL support" >&5 if eval "test \"`echo '$''{'samba_cv_HAVE_XFS_ACLS'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 12189 "configure" +#line 12196 "configure" #include "confdefs.h" #include <sys/types.h> #include <acl/acl.h> @@ -12193,7 +12200,7 @@ int main() { char test_str[13] = SGI_ACL_FILE; ; return 0; } EOF -if { (eval echo configure:12197: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:12204: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* samba_cv_HAVE_XFS_ACLS=yes else @@ -12238,11 +12245,11 @@ if test "$cross_compiling" = yes; then : else cat > conftest.$ac_ext <<EOF -#line 12242 "configure" +#line 12249 "configure" #include "confdefs.h" #include "${srcdir-.}/tests/summary.c" EOF -if { (eval echo configure:12246: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:12253: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then echo "configure OK"; else diff --git a/source3/configure.in b/source3/configure.in index 97562056303..8fbcf69a9fb 100644 --- a/source3/configure.in +++ b/source3/configure.in @@ -2090,6 +2090,10 @@ AC_ARG_WITH(acl-support, AC_MSG_RESULT(Using IRIX ACLs) AC_DEFINE(HAVE_IRIX_ACLS) ;; + *aix*) + AC_MSG_RESULT(Using AIX ACLs) + AC_DEFINE(HAVE_AIX_ACLS) + ;; *) AC_CHECK_LIB(acl,acl_get_file) AC_CACHE_CHECK([for ACL support],samba_cv_HAVE_POSIX_ACLS,[ diff --git a/source3/include/config.h.in b/source3/include/config.h.in index 6a6c8567665..b2ed622f880 100644 --- a/source3/include/config.h.in +++ b/source3/include/config.h.in @@ -207,6 +207,7 @@ #undef HAVE_SOLARIS_ACLS #undef HAVE_IRIX_ACLS #undef HAVE_XFS_ACLS +#undef HAVE_AIX_ACLS #undef HAVE_NO_ACLS /* The number of bytes in a int. */ diff --git a/source3/include/smb_acls.h b/source3/include/smb_acls.h index 570b8eab8c9..613f6db3e32 100644 --- a/source3/include/smb_acls.h +++ b/source3/include/smb_acls.h @@ -166,6 +166,53 @@ typedef ushort *SMB_ACL_PERMSET_T; #define EXTENDED_PERM_BITS (ACL_CHOWN|ACL_CHMOD|ACL_DELETE) #endif /* CONFIG_EXTENDED_PERMISSION */ +#elif defined(HAVE_AIX_ACLS) + +/* Donated by Medha Date, mdate@austin.ibm.com, for IBM */ + +#include "/usr/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. */ diff --git a/source3/lib/ms_fnmatch.c b/source3/lib/ms_fnmatch.c index 364fd6f347a..c4ebaf6aa27 100644 --- a/source3/lib/ms_fnmatch.c +++ b/source3/lib/ms_fnmatch.c @@ -31,6 +31,106 @@ #include "includes.h" #endif + + +/* + bugger. we need a separate wildcard routine for older versions + of the protocol. This is not yet perfect, but its a lot + better thaan what we had */ +static int ms_fnmatch_lanman_core(char *pattern, char *string) +{ + char *p = pattern, *n = string; + char c; + + if (strcmp(p,"?")==0 && strcmp(n,".")==0) goto match; + + while ((c = *p++)) { + switch (c) { + case '.': + /* if (! *n && ! *p) goto match; */ + if (*n != '.') goto nomatch; + n++; + break; + + case '?': + if ((*n == '.' && n[1] != '.') || ! *n) goto next; + n++; + break; + + case '>': + if (n[0] == '.') { + if (! n[1] && ms_fnmatch_lanman_core(p, n+1) == 0) goto match; + if (ms_fnmatch_lanman_core(p, n) == 0) goto match; + goto nomatch; + } + if (! *n) goto next; + n++; + break; + + case '*': + if (! *p) goto match; + for (; *n; n++) { + if (ms_fnmatch_lanman_core(p, n) == 0) goto match; + } + break; + + case '<': + for (; *n; n++) { + if (ms_fnmatch_lanman_core(p, n) == 0) goto match; + if (*n == '.' && !strchr(n+1,'.')) { + n++; + break; + } + } + break; + + case '"': + if (*n == 0 && ms_fnmatch_lanman_core(p, n) == 0) goto match; + if (*n != '.') goto nomatch; + n++; + break; + + default: + if (c != *n) goto nomatch; + n++; + } + } + + if (! *n) goto match; + + nomatch: + /* + if (verbose) printf("NOMATCH pattern=[%s] string=[%s]\n", pattern, string); + */ + return -1; + +next: + if (ms_fnmatch_lanman_core(p, n) == 0) goto match; + goto nomatch; + + match: + /* + if (verbose) printf("MATCH pattern=[%s] string=[%s]\n", pattern, string); + */ + return 0; +} + +static int ms_fnmatch_lanman1(char *pattern, char *string) +{ + if (!strpbrk(pattern, "?*<>\"")) { + if (strcmp(string,"..") == 0) string = "."; + return strcmp(pattern, string); + } + + if (strcmp(string,"..") == 0 || strcmp(string,".") == 0) { + return ms_fnmatch_lanman_core(pattern, "..") && + ms_fnmatch_lanman_core(pattern, "."); + } + + return ms_fnmatch_lanman_core(pattern, string); +} + + /* the following function was derived using the masktest utility - after years of effort we finally have a perfect MS wildcard matching routine! @@ -43,6 +143,11 @@ int ms_fnmatch(char *pattern, char *string) { char *p = pattern, *n = string; char c; + extern int Protocol; + + if (Protocol <= PROTOCOL_LANMAN2) { + return ms_fnmatch_lanman1(pattern, string); + } while ((c = *p++)) { switch (c) { diff --git a/source3/lib/sysacls.c b/source3/lib/sysacls.c index ba015e8f8d1..d1b6e58b409 100644 --- a/source3/lib/sysacls.c +++ b/source3/lib/sysacls.c @@ -1161,8 +1161,8 @@ int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm) int sys_acl_add_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm) { -// TO DO: Add in ALL possible permissions here -// TO DO: Include extended ones!! + /* TO DO: Add in ALL possible permissions here */ + /* TO DO: Include extended ones!! */ if (perm != SMB_ACL_READ && perm != SMB_ACL_WRITE && perm != SMB_ACL_EXECUTE) { errno = EINVAL; @@ -1187,7 +1187,7 @@ SMB_ACL_T sys_acl_init( int count) return NULL; } else { - a = (struct acl *)malloc(sizeof(struct acl)); // where is this memory freed? + a = (struct acl *)malloc(sizeof(struct acl)); /* where is this memory freed? */ a->acl_cnt = 0; return a; } @@ -1227,7 +1227,7 @@ int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry_d, void *qual_p) int sys_acl_set_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T permset_d) { -// TO DO: expand to extended permissions eventually! + /* TO DO: expand to extended permissions eventually! */ if(*permset_d & ~(SMB_ACL_READ|SMB_ACL_WRITE|SMB_ACL_EXECUTE)) { return EINVAL; @@ -1251,6 +1251,885 @@ int sys_acl_free_qualifier(void *qual) return 0; } +#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) +{ + 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); +} + +int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p) +{ + /* 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); +} + +int sys_acl_get_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p) +{ + 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); +} + +void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d) +{ + return(entry_d->ace_id->id_data); +} + +SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type) +{ + 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 statacl */ + + DEBUG(10,("Entering sys_acl_get_file\n")); + DEBUG(10,("path_p is %s\n",path_p)); + + file_acl = (struct acl *)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)); + 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 = (struct new_acl_entry *)malloc(sizeof(struct new_acl_entry)); + if(acl_entry_link->entryp == NULL) { + 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 = (struct acl_entry_link *) + malloc(sizeof(struct acl_entry_link)); + + if(acl_entry_link->nextp == NULL) { + 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 = (struct new_acl_entry *)malloc(sizeof(struct new_acl_entry)); + if(acl_entry_link->entryp == NULL) { + 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 = (struct acl_entry_link *)malloc(sizeof(struct acl_entry_link)); + if(acl_entry_link->nextp == NULL) { + 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 = (struct new_acl_entry *)malloc(sizeof(struct new_acl_entry)); + if(acl_entry_link->entryp == NULL) { + 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; + free(file_acl); + + return(acl_entry_link_head); +} + +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 *)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)); + 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){ + free(file_acl); + return(NULL); + } + + acl_entry_link->entryp = (struct new_acl_entry *)malloc(sizeof(struct new_acl_entry)); + + if(acl_entry_link->entryp == NULL) { + errno = ENOMEM; + DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno)); + 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 = (struct acl_entry_link *)malloc(sizeof(struct acl_entry_link)); + if(acl_entry_link->nextp == NULL) { + errno = ENOMEM; + DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno)); + free(file_acl); + return(NULL); + } + acl_entry_link->nextp->prevp = acl_entry_link; + acl_entry_link = acl_entry_link->nextp; + acl_entry_link->entryp = (struct new_acl_entry *)malloc(sizeof(struct new_acl_entry)); + if(acl_entry_link->entryp == NULL) { + errno = ENOMEM; + DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno)); + 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 = (struct acl_entry_link *)malloc(sizeof(struct acl_entry_link)); + if(acl_entry_link->nextp == NULL) { + errno = ENOMEM; + DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno)); + free(file_acl); + return(NULL); + } + + acl_entry_link->nextp->prevp = acl_entry_link; + acl_entry_link = acl_entry_link->nextp; + acl_entry_link->entryp = (struct new_acl_entry *)malloc(sizeof(struct new_acl_entry)); + + if(acl_entry_link->entryp == NULL) { + 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; + free(file_acl); + + return(acl_entry_link_head); +} + +int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset) +{ + *permset = *permset & ~0777; + return(0); +} + +int sys_acl_add_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm) +{ + 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); +} + +char *sys_acl_to_text( SMB_ACL_T theacl, ssize_t *plen) +{ + return(NULL); +} + +SMB_ACL_T sys_acl_init( int count) +{ + struct acl_entry_link *theacl = NULL; + + DEBUG(10,("Entering sys_acl_init\n")); + + theacl = (struct acl_entry_link *)malloc(sizeof(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); +} + +int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry) +{ + 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 = (struct acl_entry_link *)malloc(sizeof(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 = (struct new_acl_entry *)malloc(sizeof(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); +} + +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")); +} + +int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual) +{ + 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); +} + +int sys_acl_set_permset( SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset) +{ + 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); +} + +int sys_acl_valid( SMB_ACL_T theacl ) +{ + 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); +} + +int sys_acl_set_file( char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl) +{ + 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 *)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 *)malloc(acl_length); + if(file_acl_temp == NULL) { + 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); + 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)); + free(file_acl); + DEBUG(10,("Exiting the sys_acl_set_file\n")); + return(rc); +} + +int sys_acl_set_fd( int fd, SMB_ACL_T theacl) +{ + 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 *)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 *)malloc(acl_length); + if(file_acl_temp == NULL) { + 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); + 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)); + free(file_acl); + DEBUG(10,("Exiting sys_acl_set_fd\n")); + return(rc); +} + +int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm) +{ + return(*permset & perm); +} + +int sys_acl_free_text(char *text) +{ + return(0); +} + +int sys_acl_free_acl(SMB_ACL_T posix_acl) +{ + 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) { + free(acl_entry_link->prevp->entryp); + free(acl_entry_link->prevp); + } + + free(acl_entry_link->prevp->entryp); + free(acl_entry_link->prevp); + free(acl_entry_link->entryp); + free(acl_entry_link); + + return(0); +} + +int sys_acl_free_qualifier(void *qual) +{ + return(0); +} + #else /* No ACLs. */ int sys_acl_get_entry( SMB_ACL_T the_acl, int entry_id, SMB_ACL_ENTRY_T *entry_p) |