diff options
Diffstat (limited to 'source/lib/sysacls.c')
-rw-r--r-- | source/lib/sysacls.c | 329 |
1 files changed, 85 insertions, 244 deletions
diff --git a/source/lib/sysacls.c b/source/lib/sysacls.c index d1b6e58b409..0770a8856a2 100644 --- a/source/lib/sysacls.c +++ b/source/lib/sysacls.c @@ -45,8 +45,9 @@ extern int DEBUGLEVEL; 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( char *name, SMB_ACL_TYPE_T acltype, 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. @@ -160,7 +161,7 @@ int sys_acl_valid( SMB_ACL_T theacl ) return acl_valid(theacl); } -int sys_acl_set_file( char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T 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); } @@ -170,6 +171,11 @@ 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); @@ -649,17 +655,40 @@ int sys_acl_set_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T permset_d) return 0; } -int sys_acl_valid(SMB_ACL_T acl_d) +/* + * 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) { - if (aclsort(acl_d->count, 1, acl_d->acl) != 0) { + 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(char *name, SMB_ACL_TYPE_T type, SMB_ACL_T 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; @@ -672,7 +701,7 @@ int sys_acl_set_file(char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d) return -1; } - if (stat(name, &s) != 0) { + if (acl_sort(acl_d) != 0) { return -1; } @@ -684,6 +713,9 @@ int sys_acl_set_file(char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d) * 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; @@ -692,13 +724,11 @@ int sys_acl_set_file(char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d) if (type == SMB_ACL_TYPE_ACCESS) { acc_acl = acl_d; - def_acl = - tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_DEFAULT); + 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); + acc_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_ACCESS); } if (tmp_acl == NULL) { @@ -708,9 +738,8 @@ int sys_acl_set_file(char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d) /* * allocate a temporary buffer for the complete ACL */ - acl_count = acc_acl->count + def_acl->count; - acl_p = - acl_buf = malloc(acl_count * sizeof(acl_buf[0])); + acl_count = acc_acl->count + def_acl->count; + acl_p = acl_buf = malloc(acl_count * sizeof(acl_buf[0])); if (acl_buf == NULL) { sys_acl_free_acl(tmp_acl); @@ -741,12 +770,7 @@ int sys_acl_set_file(char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d) return -1; } - if (aclsort(acl_count, 1, acl_p) != 0) { - errno = EINVAL; - ret = -1; - } else { - ret = acl(name, SETACL, acl_count, acl_p); - } + ret = acl(name, SETACL, acl_count, acl_p); if (acl_buf) { free(acl_buf); @@ -757,14 +781,33 @@ int sys_acl_set_file(char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d) int sys_acl_set_fd(int fd, SMB_ACL_T acl_d) { - if (aclsort(acl_d->count, 1, acl_d->acl) != 0) { - errno = EINVAL; + 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; +} + int sys_acl_free_text(char *text) { free(text); @@ -1003,7 +1046,7 @@ int sys_acl_valid(SMB_ACL_T acl_d) return acl_valid(acl_d->aclp); } -int sys_acl_set_file(char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d) +int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d) { return acl_set_file(name, type, acl_d->aclp); } @@ -1013,6 +1056,11 @@ 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) +{ + return acl_delete_def_file(name); +} + int sys_acl_free_text(char *text) { return acl_free(text); @@ -1032,225 +1080,6 @@ int sys_acl_free_qualifier(void *qual) return 0; } -#elif defined(HAVE_XFS_ACLS) -/* For Linux SGI/XFS Filesystems - * contributed by J Trostel, Connex - * */ - -/* based on the implementation for Solaris by Toomas Soome.. which is - * based on the implementation by Micheal Davidson for Unixware... - * - * Linux XFS is a 'work-in-progress' - * This interface may change... - * You've been warned ;-> */ - -/* First, do the identity mapping */ - -int sys_acl_get_entry( SMB_ACL_T the_acl, int entry_id, SMB_ACL_ENTRY_T *entry_p) -{ - if( acl_get_entry( the_acl, entry_id, entry_p) >= 0) { - return 1; - } - else { - return -1; - } -} - -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); -} - -char *sys_acl_to_text( SMB_ACL_T the_acl, ssize_t *plen) -{ - return acl_to_text( the_acl, plen); -} - -int sys_acl_valid( SMB_ACL_T theacl ) -{ - return acl_valid(theacl); -} - -int sys_acl_set_file( 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); -} - -/* Now the functions I need to define for XFS */ - -int sys_acl_create_entry( SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p) -{ - acl_t acl, newacl; - acl_entry_t ace; - int cnt; - - acl = *acl_p; - ace = *entry_p; - - if((*acl_p == NULL) || (ace == NULL)){ - errno = EINVAL; - return -1; - } - - cnt = acl->acl_cnt; - if( (cnt + 1) > ACL_MAX_ENTRIES ){ - errno = ENOSPC; - return -1; - } - - newacl = (acl_t)malloc(sizeof(struct acl)); - if(newacl == NULL){ - errno = ENOMEM; - return -1; - } - - *newacl = *acl; - newacl->acl_entry[cnt] = *ace; - newacl->acl_cnt = cnt + 1; - - acl_free(*acl_p); - *acl_p = newacl; - *entry_p = &newacl->acl_entry[cnt]; - return 0; -} - - -int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p) -{ - *tag_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->ae_perm; - 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; -} - -int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset) -{ - *permset = 0; - return 0; -} - -int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm) -{ - return (*permset & 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!! */ - - if (perm != SMB_ACL_READ && perm != SMB_ACL_WRITE && perm != SMB_ACL_EXECUTE) { - errno = EINVAL; - return -1; - } - - if(permset == NULL) { - errno = EINVAL; - return -1; - } - - *permset |= perm; - - return 0; -} - -SMB_ACL_T sys_acl_init( int count) -{ - SMB_ACL_T a; - if((count > ACL_MAX_ENTRIES) || (count < 0)) { - errno = EINVAL; - return NULL; - } - else { - a = (struct acl *)malloc(sizeof(struct acl)); /* where is this memory freed? */ - a->acl_cnt = 0; - return a; - } -} - -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 = *((uid_t *)qual_p); - - return 0; -} - -int sys_acl_set_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T permset_d) -{ - /* TO DO: expand to extended permissions eventually! */ - - if(*permset_d & ~(SMB_ACL_READ|SMB_ACL_WRITE|SMB_ACL_EXECUTE)) { - return EINVAL; - } - - return 0; -} - -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) -{ - return 0; -} - #elif defined(HAVE_AIX_ACLS) /* Donated by Medha Date, mdate@austin.ibm.com, for IBM */ @@ -1914,7 +1743,7 @@ int sys_acl_valid( SMB_ACL_T theacl ) return(0); } -int sys_acl_set_file( char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl) +int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl) { struct acl_entry_link *acl_entry_link = NULL; struct acl *file_acl = NULL; @@ -2098,6 +1927,12 @@ int sys_acl_set_fd( int fd, SMB_ACL_T theacl) return(rc); } +int sys_acl_delete_def_file(const char *name) +{ + /* AIX has no default ACL */ + return 0; +} + int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm) { return(*permset & perm); @@ -2234,7 +2069,7 @@ int sys_acl_valid( SMB_ACL_T theacl ) return -1; } -int sys_acl_set_file( char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl) +int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl) { errno = ENOSYS; return -1; @@ -2246,6 +2081,12 @@ int sys_acl_set_fd( int fd, SMB_ACL_T theacl) 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; |