X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?p=netatalk.git;a=blobdiff_plain;f=etc%2Fafpd%2Facls.c;h=fcc39995d952c9b684595ac6650c72a26a496442;hp=34a7e92cf9e4bff07ba171401214fba6c8b9ab3d;hb=14874ef66d68c5200a9a42a7408d022d58211898;hpb=bdc45d00129b791a92255a63b5b3934e350d40ce diff --git a/etc/afpd/acls.c b/etc/afpd/acls.c index 34a7e92c..fcc39995 100644 --- a/etc/afpd/acls.c +++ b/etc/afpd/acls.c @@ -1035,6 +1035,63 @@ EC_CLEANUP: #endif /* HAVE_SOLARIS_ACLS */ #ifdef HAVE_POSIX_ACLS +#ifndef HAVE_ACL_FROM_MODE +static acl_t acl_from_mode(mode_t mode) +{ + acl_t acl; + acl_entry_t entry; + acl_permset_t permset; + + if (!(acl = acl_init(3))) + return NULL; + + if (acl_create_entry(&acl, &entry) != 0) + goto error; + acl_set_tag_type(entry, ACL_USER_OBJ); + acl_get_permset(entry, &permset); + acl_clear_perms(permset); + if (mode & S_IRUSR) + acl_add_perm(permset, ACL_READ); + if (mode & S_IWUSR) + acl_add_perm(permset, ACL_WRITE); + if (mode & S_IXUSR) + acl_add_perm(permset, ACL_EXECUTE); + acl_set_permset(entry, permset); + + if (acl_create_entry(&acl, &entry) != 0) + goto error; + acl_set_tag_type(entry, ACL_GROUP_OBJ); + acl_get_permset(entry, &permset); + acl_clear_perms(permset); + if (mode & S_IRGRP) + acl_add_perm(permset, ACL_READ); + if (mode & S_IWGRP) + acl_add_perm(permset, ACL_WRITE); + if (mode & S_IXGRP) + acl_add_perm(permset, ACL_EXECUTE); + acl_set_permset(entry, permset); + + if (acl_create_entry(&acl, &entry) != 0) + goto error; + acl_set_tag_type(entry, ACL_OTHER); + acl_get_permset(entry, &permset); + acl_clear_perms(permset); + if (mode & S_IROTH) + acl_add_perm(permset, ACL_READ); + if (mode & S_IWOTH) + acl_add_perm(permset, ACL_WRITE); + if (mode & S_IXOTH) + acl_add_perm(permset, ACL_EXECUTE); + acl_set_permset(entry, permset); + + return acl; + +error: + acl_free(acl); + return NULL; +} +#endif + static int set_acl(const struct vol *vol, const char *name, int inherit _U_, @@ -1057,11 +1114,8 @@ static int set_acl(const struct vol *vol, /* for files def_acl will be NULL */ /* create access acl from mode */ -#ifdef HAVE_ACL_FROM_MODE EC_NULL_LOG_ERR(acc_acl = acl_from_mode(st.st_mode), AFPERR_MISC); -#else -#error "Missing acl_from_mode() replacement" -#endif + /* adds the clients aces */ EC_ZERO_ERR(map_aces_darwin_to_posix(daces, &def_acl, &acc_acl, ace_count), AFPERR_MISC); @@ -1114,18 +1168,20 @@ static int check_acl_access(const struct vol *vol, uuidtype_t uuidtype; struct stat st; bstring parent = NULL; + int is_dir; - LOG(log_maxdebug, logtype_afpd, "check_access: Request: 0x%08x", requested_rights); + LOG(log_maxdebug, logtype_afpd, "check_acl_access(dir: \"%s\", path: \"%s\", curdir: \"%s\", 0x%08x)", + cfrombstr(dir->d_fullpath), path, getcwdpath(), requested_rights); /* Get uid or gid from UUID */ - EC_ZERO_LOG_ERR(getnamefromuuid(uuid, &username, &uuidtype), AFPERR_PARAM); + EC_ZERO_ERR(getnamefromuuid(uuid, &username, &uuidtype), AFPERR_PARAM); EC_ZERO_LOG_ERR(lstat(path, &st), AFPERR_PARAM); switch (uuidtype) { case UUID_USER: break; case UUID_GROUP: - LOG(log_warning, logtype_afpd, "check_access: afp_access not supported for groups"); + LOG(log_warning, logtype_afpd, "check_acl_access: afp_access not supported for groups"); EC_STATUS(AFPERR_MISC); goto EC_CLEANUP; default: @@ -1133,10 +1189,12 @@ static int check_acl_access(const struct vol *vol, goto EC_CLEANUP; } - if ((strcmp(path, ".") == 0) && (dir->d_rights_cache != 0xffffffff)) { + is_dir = !strcmp(path, "."); + + if (is_dir && (curdir->d_rights_cache != 0xffffffff)) { /* its a dir and the cache value is valid */ - allowed_rights = dir->d_rights_cache; - LOG(log_debug, logtype_afpd, "allowed rights from dircache: 0x%08x", allowed_rights); + allowed_rights = curdir->d_rights_cache; + LOG(log_debug, logtype_afpd, "check_access: allowed rights from dircache: 0x%08x", allowed_rights); } else { #ifdef HAVE_SOLARIS_ACLS EC_ZERO_LOG(solaris_acl_rights(path, &st, &allowed_rights)); @@ -1156,12 +1214,12 @@ static int check_acl_access(const struct vol *vol, int i; uint32_t parent_rights = 0; - if (dir->d_did == DIRDID_ROOT_PARENT) { + if (curdir->d_did == DIRDID_ROOT_PARENT) { /* use volume path */ EC_NULL_LOG_ERR(parent = bfromcstr(vol->v_path), AFPERR_MISC); } else { /* build path for parent */ - EC_NULL_LOG_ERR(parent = bstrcpy(dir->d_fullpath), AFPERR_MISC); + EC_NULL_LOG_ERR(parent = bstrcpy(curdir->d_fullpath), AFPERR_MISC); EC_ZERO_LOG_ERR(bconchar(parent, '/'), AFPERR_MISC); EC_ZERO_LOG_ERR(bcatcstr(parent, path), AFPERR_MISC); EC_NEG1_LOG_ERR(i = bstrrchr(parent, '/'), AFPERR_MISC); @@ -1175,13 +1233,22 @@ static int check_acl_access(const struct vol *vol, EC_ZERO_LOG(solaris_acl_rights(cfrombstr(parent), &st, &parent_rights)); #endif #ifdef HAVE_POSIX_ACLS - EC_ZERO_LOG(posix_acl_rights(path, &st, &allowed_rights)); + EC_ZERO_LOG(posix_acl_rights(path, &st, &parent_rights)); #endif if (parent_rights & (DARWIN_ACE_WRITE_DATA | DARWIN_ACE_DELETE_CHILD)) allowed_rights |= DARWIN_ACE_DELETE; /* man, that was a lot of work! */ } + + if (is_dir) { + /* Without DARWIN_ACE_DELETE set OS X 10.6 refuses to rename subdirectories in a + * directory. + */ + if (allowed_rights & DARWIN_ACE_ADD_SUBDIRECTORY) + allowed_rights |= DARWIN_ACE_DELETE; + + dir->d_rights_cache = allowed_rights; + } LOG(log_debug, logtype_afpd, "allowed rights: 0x%08x", allowed_rights); - dir->d_rights_cache = allowed_rights; } if ((requested_rights & allowed_rights) != requested_rights) { @@ -1508,15 +1575,17 @@ EC_CLEANUP: */ int check_vol_acl_support(const struct vol *vol) { - int ret = 1; + int ret = 0; #ifdef HAVE_SOLARIS_ACLS ace_t *aces = NULL; + ret = 1; if (get_nfsv4_acl(vol->v_path, &aces) == -1) ret = 0; #endif #ifdef HAVE_POSIX_ACLS acl_t acl = NULL; + ret = 1; if ((acl = acl_get_file(vol->v_path, ACL_TYPE_ACCESS)) == NULL) ret = 0; #endif