#endif
#ifdef HAVE_POSIX_ACLS
#include <sys/acl.h>
+#endif
+#ifdef HAVE_ACL_LIBACL_H
#include <acl/libacl.h>
#endif
#include "unix.h"
#include "acls.h"
#include "acl_mappings.h"
+#include "auth.h"
/* for map_acl() */
#define SOLARIS_2_DARWIN 1
*
* @param path (r) path to filesystem object
* @param sb (r) struct stat of path
- * @param pwd (r) struct passwd of user
* @param result (w) resulting Darwin allow ACE
*
* @returns 0 or -1 on error
*/
static int solaris_acl_rights(const char *path,
const struct stat *sb,
- const struct passwd *pwd,
uint32_t *result)
{
EC_INIT;
/* Get ACL from file/dir */
EC_NEG1_LOG(ace_count = get_nfsv4_acl(path, &aces));
- if (ace_count == 0) {
- LOG(log_warning, logtype_afpd, "Zero ACEs from get_nfsv4_acl");
- EC_FAIL;
- }
+ if (ace_count == 0)
+ goto EC_CLEANUP;
/* Now check requested rights */
i = 0;
if its a trivial ACE_EVERYONE ACE
THEN
process ACE */
- if (((who == pwd->pw_uid) && !(flags & (ACE_TRIVIAL|ACE_IDENTIFIER_GROUP)))
+ if (((who == uuid) && !(flags & (ACE_TRIVIAL|ACE_IDENTIFIER_GROUP)))
||
((flags & ACE_IDENTIFIER_GROUP) && !(flags & ACE_GROUP) && gmem(who))
||
- ((flags & ACE_OWNER) && (pwd->pw_uid == sb->st_uid))
+ ((flags & ACE_OWNER) && (uuid == sb->st_uid))
||
- ((flags & ACE_GROUP) && gmem(sb->st_gid))
+ ((flags & ACE_GROUP) && !(uuid == sb->st_uid) && gmem(sb->st_gid))
||
- (flags & ACE_EVERYONE)
+ (flags & ACE_EVERYONE && !(uuid == sb->st_uid) && !gmem(sb->st_gid))
) {
/* Found an applicable ACE */
if (type == ACE_ACCESS_ALLOWED_ACE_TYPE)
/* uid/gid first */
EC_ZERO(getnamefromuuid(darwin_aces->darwin_ace_uuid, &name, &uuidtype));
switch (uuidtype) {
- case UUID_LOCAL:
- free(name);
- name = NULL;
- darwin_aces++;
- continue;
case UUID_USER:
EC_NULL_LOG(pwd = getpwnam(name));
nfsv4_aces->a_who = pwd->pw_uid;
nfsv4_aces->a_who = (uid_t)(grp->gr_gid);
nfsv4_ace_flags |= ACE_IDENTIFIER_GROUP;
break;
+ default:
+ LOG(log_error, logtype_afpd, "map_aces_darwin_to_solaris: unkown uuidtype");
+ EC_FAIL;
}
free(name);
name = NULL;
nfsv4_ace_rights |= darwin_to_nfsv4_rights[i].to;
}
- LOG(log_debug9, logtype_afpd, "map_aces_darwin_to_solaris: ACE flags: Darwin:%08x -> NFSv4:%04x", darwin_ace_flags, nfsv4_ace_flags);
- LOG(log_debug9, logtype_afpd, "map_aces_darwin_to_solaris: ACE rights: Darwin:%08x -> NFSv4:%08x", darwin_ace_rights, nfsv4_ace_rights);
+ LOG(log_debug9, logtype_afpd,
+ "map_aces_darwin_to_solaris: ACE flags: Darwin:%08x -> NFSv4:%04x",
+ darwin_ace_flags, nfsv4_ace_flags);
+ LOG(log_debug9, logtype_afpd,
+ "map_aces_darwin_to_solaris: ACE rights: Darwin:%08x -> NFSv4:%08x",
+ darwin_ace_rights, nfsv4_ace_rights);
nfsv4_aces->a_flags = nfsv4_ace_flags;
nfsv4_aces->a_access_mask = nfsv4_ace_rights;
#ifdef HAVE_POSIX_ACLS
+static uint32_t posix_permset_to_darwin_rights(acl_entry_t e, int is_dir)
+{
+ EC_INIT;
+ uint32_t rights = 0;
+ acl_permset_t permset;
+
+ EC_ZERO_LOG(acl_get_permset(e, &permset));
+
+#ifdef HAVE_ACL_GET_PERM_NP
+ if (acl_get_perm_np(permset, ACL_READ))
+#else
+ if (acl_get_perm(permset, ACL_READ))
+#endif
+ rights = DARWIN_ACE_READ_DATA
+ | DARWIN_ACE_READ_EXTATTRIBUTES
+ | DARWIN_ACE_READ_ATTRIBUTES
+ | DARWIN_ACE_READ_SECURITY;
+#ifdef HAVE_ACL_GET_PERM_NP
+ if (acl_get_perm_np(permset, ACL_WRITE)) {
+#else
+ if (acl_get_perm(permset, ACL_WRITE)) {
+#endif
+ rights |= DARWIN_ACE_WRITE_DATA
+ | DARWIN_ACE_APPEND_DATA
+ | DARWIN_ACE_WRITE_EXTATTRIBUTES
+ | DARWIN_ACE_WRITE_ATTRIBUTES;
+ if (is_dir)
+ rights |= DARWIN_ACE_DELETE_CHILD;
+ }
+#ifdef HAVE_ACL_GET_PERM_NP
+ if (acl_get_perm_np(permset, ACL_EXECUTE))
+#else
+ if (acl_get_perm(permset, ACL_EXECUTE))
+#endif
+ rights |= DARWIN_ACE_EXECUTE;
+
+EC_CLEANUP:
+ LOG(log_maxdebug, logtype_afpd, "mapped rights: 0x%08x", rights);
+ return rights;
+}
+
+/*!
+ * Compile access rights for a user to one file-system object
+ *
+ * This combines combines all access rights for a user to one fs-object and
+ * returns the result as a Darwin allowed rights ACE.
+ * This must honor trivial ACEs which are a mode_t mapping.
+ *
+ * @param path (r) path to filesystem object
+ * @param sb (r) struct stat of path
+ * @param result (rw) resulting Darwin allow ACE
+ *
+ * @returns 0 or -1 on error
+ */
+static int posix_acl_rights(const char *path,
+ const struct stat *sb,
+ uint32_t *result)
+{
+ EC_INIT;
+ int havemask = 0;
+ int entry_id = ACL_FIRST_ENTRY;
+ uint32_t rights = 0, maskrights = 0;
+ uid_t *uid = NULL;
+ gid_t *gid = NULL;
+ acl_t acl = NULL;
+ acl_entry_t e;
+ acl_tag_t tag;
+
+ EC_NULL_LOG(acl = acl_get_file(path, ACL_TYPE_ACCESS));
+
+ /* itereate through all ACEs to get the mask */
+ while (!havemask && acl_get_entry(acl, entry_id, &e) == 1) {
+ entry_id = ACL_NEXT_ENTRY;
+ EC_ZERO_LOG(acl_get_tag_type(e, &tag));
+ switch (tag) {
+ case ACL_MASK:
+ maskrights = posix_permset_to_darwin_rights(e, S_ISDIR(sb->st_mode));
+ LOG(log_maxdebug, logtype_afpd, "maskrights: 0x%08x", maskrights);
+ havemask = 1;
+ break;
+ default:
+ continue;
+ }
+ }
+
+ /* itereate through all ACEs */
+ entry_id = ACL_FIRST_ENTRY;
+ while (acl_get_entry(acl, entry_id, &e) == 1) {
+ entry_id = ACL_NEXT_ENTRY;
+ EC_ZERO_LOG(acl_get_tag_type(e, &tag));
+ switch (tag) {
+ case ACL_USER:
+ EC_NULL_LOG(uid = (uid_t *)acl_get_qualifier(e));
+ if (*uid == uuid) {
+ LOG(log_maxdebug, logtype_afpd, "ACL_USER: %u", *uid);
+ rights |= posix_permset_to_darwin_rights(e, S_ISDIR(sb->st_mode));
+ }
+ acl_free(uid);
+ uid = NULL;
+ break;
+ case ACL_USER_OBJ:
+ if (sb->st_uid == uuid) {
+ LOG(log_maxdebug, logtype_afpd, "ACL_USER_OBJ: %u", sb->st_uid);
+ rights |= posix_permset_to_darwin_rights(e, S_ISDIR(sb->st_mode));
+ }
+ break;
+ case ACL_GROUP:
+ EC_NULL_LOG(gid = (gid_t *)acl_get_qualifier(e));
+ if (gmem(*gid)) {
+ LOG(log_maxdebug, logtype_afpd, "ACL_GROUP: %u", *gid);
+ rights |= (posix_permset_to_darwin_rights(e, S_ISDIR(sb->st_mode)) & maskrights);
+ }
+ acl_free(gid);
+ gid = NULL;
+ break;
+ case ACL_GROUP_OBJ:
+ if (!(sb->st_uid == uuid) && gmem(sb->st_gid)) {
+ LOG(log_maxdebug, logtype_afpd, "ACL_GROUP_OBJ: %u", sb->st_gid);
+ rights |= posix_permset_to_darwin_rights(e, S_ISDIR(sb->st_mode));
+ }
+ break;
+ case ACL_OTHER:
+ if (!(sb->st_uid == uuid) && !gmem(sb->st_gid)) {
+ LOG(log_maxdebug, logtype_afpd, "ACL_OTHER");
+ rights |= posix_permset_to_darwin_rights(e, S_ISDIR(sb->st_mode));
+ }
+ break;
+ default:
+ continue;
+ }
+ } /* while */
+
+ *result |= rights;
+
+EC_CLEANUP:
+ if (acl) acl_free(acl);
+ if (uid) acl_free(uid);
+ if (gid) acl_free(gid);
+ EC_EXIT;
+}
+
/*!
* Add entries of one acl to another acl
*
/* uid/gid */
EC_ZERO_LOG(getnamefromuuid(darwin_aces->darwin_ace_uuid, &name, &uuidtype));
switch (uuidtype) {
- case UUID_LOCAL:
- free(name);
- name = NULL;
- continue;
case UUID_USER:
EC_NULL_LOG(pwd = getpwnam(name));
tag = ACL_USER;
id = (uid_t)(grp->gr_gid);
LOG(log_debug, logtype_afpd, "map_ace: name: %s, gid: %u", name, id);
break;
+ default:
+ continue;
}
free(name);
name = NULL;
{
EC_INIT;
int mapped_aces = 0;
- int havemask = 0;
int entry_id = ACL_FIRST_ENTRY;
acl_entry_t e;
acl_tag_t tag;
- acl_permset_t permset, mask;
uid_t *uid = NULL;
gid_t *gid = NULL;
struct passwd *pwd = NULL;
struct group *grp = NULL;
uint32_t flags;
- uint32_t rights;
+ uint32_t rights, maskrights = 0;
darwin_ace_t *saved_darwin_aces = darwin_aces;
LOG(log_maxdebug, logtype_afpd, "map_aces_posix_to_darwin(%s)",
gid = NULL;
break;
- /* store mask so we can apply it later in a second loop */
case ACL_MASK:
- EC_ZERO_LOG(acl_get_permset(e, &mask));
- havemask = 1;
+ maskrights = posix_permset_to_darwin_rights(e, type & IS_DIR);
continue;
default:
darwin_aces->darwin_ace_flags = htonl(flags);
/* rights */
- EC_ZERO_LOG(acl_get_permset(e, &permset));
-
- rights = 0;
- if (acl_get_perm(permset, ACL_READ))
- rights = DARWIN_ACE_READ_DATA
- | DARWIN_ACE_READ_EXTATTRIBUTES
- | DARWIN_ACE_READ_ATTRIBUTES
- | DARWIN_ACE_READ_SECURITY;
- if (acl_get_perm(permset, ACL_WRITE)) {
- rights |= DARWIN_ACE_WRITE_DATA
- | DARWIN_ACE_APPEND_DATA
- | DARWIN_ACE_WRITE_EXTATTRIBUTES
- | DARWIN_ACE_WRITE_ATTRIBUTES;
- if ((type & ~MAP_MASK) == IS_DIR)
- rights |= DARWIN_ACE_DELETE;
- }
- if (acl_get_perm(permset, ACL_EXECUTE))
- rights |= DARWIN_ACE_EXECUTE;
-
+ rights = posix_permset_to_darwin_rights(e, type & IS_DIR);
darwin_aces->darwin_ace_rights = htonl(rights);
darwin_aces++;
mapped_aces++;
} /* while */
- if (havemask) {
- /* Loop through the mapped ACE buffer once again, applying the mask */
- /* Map the mask to Darwin ACE rights first */
- rights = 0;
- if (acl_get_perm(mask, ACL_READ))
- rights = DARWIN_ACE_READ_DATA
- | DARWIN_ACE_READ_EXTATTRIBUTES
- | DARWIN_ACE_READ_ATTRIBUTES
- | DARWIN_ACE_READ_SECURITY;
- if (acl_get_perm(mask, ACL_WRITE)) {
- rights |= DARWIN_ACE_WRITE_DATA
- | DARWIN_ACE_APPEND_DATA
- | DARWIN_ACE_WRITE_EXTATTRIBUTES
- | DARWIN_ACE_WRITE_ATTRIBUTES;
- if ((type & ~MAP_MASK) == IS_DIR)
- rights |= DARWIN_ACE_DELETE;
- }
- if (acl_get_perm(mask, ACL_EXECUTE))
- rights |= DARWIN_ACE_EXECUTE;
- for (int i = mapped_aces; i > 0; i--) {
- saved_darwin_aces->darwin_ace_rights &= htonl(rights);
- saved_darwin_aces++;
- }
+ /* Loop through the mapped ACE buffer once again, applying the mask */
+ for (int i = mapped_aces; i > 0; i--) {
+ saved_darwin_aces->darwin_ace_rights &= htonl(maskrights);
+ saved_darwin_aces++;
}
+
EC_STATUS(mapped_aces);
EC_CLEANUP:
acl_t defacl = NULL , accacl = NULL;
/* stat to check if its a dir */
- EC_ZERO_LOG(stat(name, &st));
+ EC_ZERO_LOG(lstat(name, &st));
/* if its a dir, check for default acl too */
dirflag = 0;
LOG(log_maxdebug, logtype_afpd, "set_acl: BEGIN");
struct stat st;
- EC_ZERO_LOG_ERR(stat(name, &st), AFPERR_NOOBJ);
+ EC_ZERO_LOG_ERR(lstat(name, &st), AFPERR_NOOBJ);
/* seed default ACL with access ACL */
if (S_ISDIR(st.st_mode))
/* 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);
* Note: this gets called frequently and is a good place for optimizations !
*
* @param vol (r) volume
- * @param dir (r) directory
+ * @param dir (rw) directory
* @param path (r) path to filesystem object
* @param uuid (r) UUID of user
* @param requested_rights (r) requested Darwin ACE
* @returns AFP result code
*/
static int check_acl_access(const struct vol *vol,
- const struct dir *dir,
+ struct dir *dir,
const char *path,
const uuidp_t uuid,
uint32_t requested_rights)
uint32_t allowed_rights = 0;
char *username = NULL;
uuidtype_t uuidtype;
- struct passwd *pwd;
struct stat st;
bstring parent = NULL;
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");
EC_STATUS(AFPERR_MISC);
goto EC_CLEANUP;
-
- case UUID_LOCAL:
- LOG(log_warning, logtype_afpd, "check_access: local UUID");
+ default:
EC_STATUS(AFPERR_MISC);
goto EC_CLEANUP;
}
- EC_NULL_LOG_ERR(pwd = getpwnam(username), AFPERR_MISC);
-
+ if ((strcmp(path, ".") == 0) && (dir->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);
+ } else {
#ifdef HAVE_SOLARIS_ACLS
- EC_ZERO_LOG(solaris_acl_rights(path, &st, pwd, &allowed_rights));
+ EC_ZERO_LOG(solaris_acl_rights(path, &st, &allowed_rights));
#endif
#ifdef HAVE_POSIX_ACLS
+ EC_ZERO_LOG(posix_acl_rights(path, &st, &allowed_rights));
#endif
+ /*
+ * The DARWIN_ACE_DELETE right might implicitly result from write acces to the parent
+ * directory. As it seems the 10.6 AFP client is puzzled when this right is not
+ * allowed where a delete would succeed because the parent dir gives write perms.
+ * So we check the parent dir for write access and set the right accordingly.
+ * Currentyl acl2ownermode calls us with dir = NULL, because it doesn't make sense
+ * there to do this extra check -- afaict.
+ */
+ if (vol && dir && (requested_rights & DARWIN_ACE_DELETE)) {
+ int i;
+ uint32_t parent_rights = 0;
+
+ if (dir->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_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);
+ EC_ZERO_LOG_ERR(binsertch(parent, i, 1, 0), AFPERR_MISC);
+ }
- LOG(log_debug, logtype_afpd, "allowed rights: 0x%08x", allowed_rights);
-
- /*
- * The DARWIN_ACE_DELETE right might implicitly result from write acces to the parent
- * directory. As it seems the 10.6 AFP client is puzzled when this right is not
- * allowed where a delete would succeed because the parent dir gives write perms.
- * So we check the parent dir for write access and set the right accordingly.
- * Currentyl acl2ownermode calls us with dir = NULL, because it doesn't make sense
- * there to do this extra check -- afaict.
- */
- if (vol && dir && (requested_rights & DARWIN_ACE_DELETE)) {
- int i;
- uint32_t parent_rights = 0;
-
- if (dir->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_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);
- EC_ZERO_LOG_ERR(binsertch(parent, i, 1, 0), AFPERR_MISC);
- }
-
- LOG(log_debug, logtype_afpd,"parent: %s", cfrombstr(parent));
- EC_ZERO_LOG_ERR(lstat(cfrombstr(parent), &st), AFPERR_MISC);
+ LOG(log_debug, logtype_afpd,"parent: %s", cfrombstr(parent));
+ EC_ZERO_LOG_ERR(lstat(cfrombstr(parent), &st), AFPERR_MISC);
#ifdef HAVE_SOLARIS_ACLS
- EC_ZERO_LOG(solaris_acl_rights(cfrombstr(parent), &st, pwd, &parent_rights));
+ 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));
#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 (parent_rights & (DARWIN_ACE_WRITE_DATA | DARWIN_ACE_DELETE_CHILD))
+ allowed_rights |= DARWIN_ACE_DELETE; /* man, that was a lot of work! */
+ }
+ LOG(log_debug, logtype_afpd, "allowed rights: 0x%08x", allowed_rights);
+ dir->d_rights_cache = allowed_rights;
}
if ((requested_rights & allowed_rights) != requested_rights) {
/* Shall we return owner UUID ? */
if (bitmap & kFileSec_UUID) {
LOG(log_debug, logtype_afpd, "afp_getacl: client requested files owner user UUID");
- if (NULL == (pw = getpwuid(s_path->st.st_uid)))
- return AFPERR_MISC;
- LOG(log_debug, logtype_afpd, "afp_getacl: got uid: %d, name: %s", s_path->st.st_uid, pw->pw_name);
- if ((ret = getuuidfromname(pw->pw_name, UUID_USER, rbuf)) != 0)
- return AFPERR_MISC;
+ if (NULL == (pw = getpwuid(s_path->st.st_uid))) {
+ LOG(log_debug, logtype_afpd, "afp_getacl: local uid: %u", s_path->st.st_uid);
+ localuuid_from_id(rbuf, UUID_USER, s_path->st.st_uid);
+ } else {
+ LOG(log_debug, logtype_afpd, "afp_getacl: got uid: %d, name: %s", s_path->st.st_uid, pw->pw_name);
+ if ((ret = getuuidfromname(pw->pw_name, UUID_USER, rbuf)) != 0)
+ return AFPERR_MISC;
+ }
rbuf += UUID_BINSIZE;
*rbuflen += UUID_BINSIZE;
}
/* Shall we return group UUID ? */
if (bitmap & kFileSec_GRPUUID) {
LOG(log_debug, logtype_afpd, "afp_getacl: client requested files owner group UUID");
- if (NULL == (gr = getgrgid(s_path->st.st_gid)))
- return AFPERR_MISC;
- LOG(log_debug, logtype_afpd, "afp_getacl: got gid: %d, name: %s", s_path->st.st_gid, gr->gr_name);
- if ((ret = getuuidfromname(gr->gr_name, UUID_GROUP, rbuf)) != 0)
- return AFPERR_MISC;
+ if (NULL == (gr = getgrgid(s_path->st.st_gid))) {
+ LOG(log_debug, logtype_afpd, "afp_getacl: local gid: %u", s_path->st.st_gid);
+ localuuid_from_id(rbuf, UUID_GROUP, s_path->st.st_gid);
+ } else {
+ LOG(log_debug, logtype_afpd, "afp_getacl: got gid: %d, name: %s", s_path->st.st_gid, gr->gr_name);
+ if ((ret = getuuidfromname(gr->gr_name, UUID_GROUP, rbuf)) != 0)
+ return AFPERR_MISC;
+ }
rbuf += UUID_BINSIZE;
*rbuflen += UUID_BINSIZE;
}
/* Shall we return ACL ? */
if (bitmap & kFileSec_ACL) {
LOG(log_debug, logtype_afpd, "afp_getacl: client requested files ACL");
- get_and_map_acl(s_path->u_name, rbuf, rbuflen);
+ if (get_and_map_acl(s_path->u_name, rbuf, rbuflen) != 0) {
+ LOG(log_error, logtype_afpd, "afp_getacl(\"%s/%s\"): mapping error",
+ getcwdpath(), s_path->u_name);
+ return AFPERR_MISC;
+ }
}
LOG(log_debug9, logtype_afpd, "afp_getacl: END");
return ret;
}
-/*
- unix.c/accessmode calls this: map ACL to OS 9 mode
-*/
-int acltoownermode(char *path, struct stat *st, uid_t uid, struct maccess *ma)
+/********************************************************************
+ * ACL funcs interfacing with other parts
+ ********************************************************************/
+
+/*!
+ * map ACL to user maccess
+ *
+ * This is the magic function that makes ACLs usable by calculating
+ * the access granted by ACEs to the logged in user.
+ */
+int acltoownermode(char *path, struct stat *st, struct maccess *ma)
{
EC_INIT;
- struct passwd *pw;
uint32_t rights = 0;
- if ( ! (AFPobj->options.flags & OPTION_UUID)
- ||
- ! (AFPobj->options.flags & OPTION_ACL2MACCESS))
- return 0;
-
- LOG(log_maxdebug, logtype_afpd, "acltoownermode('%s')", path);
+ if ( ! (AFPobj->options.flags & OPTION_ACL2MACCESS)
+ || (current_vol == NULL)
+ || ! (current_vol->v_flags & AFPVOL_ACLS))
+ return 0;
- EC_NULL_LOG(pw = getpwuid(uid));
+ LOG(log_maxdebug, logtype_afpd, "acltoownermode(\"%s/%s\", 0x%02x)",
+ getcwdpath(), path, ma->ma_user);
#ifdef HAVE_SOLARIS_ACLS
- EC_ZERO_LOG(solaris_acl_rights(path, st, pw, &rights));
+ EC_ZERO_LOG(solaris_acl_rights(path, st, &rights));
#endif
#ifdef HAVE_POSIX_ACLS
+ EC_ZERO_LOG(posix_acl_rights(path, st, &rights));
#endif
- LOG(log_debug, logtype_afpd, "rights: 0x%08x", rights);
+ LOG(log_maxdebug, logtype_afpd, "rights: 0x%08x", rights);
- LOG(log_maxdebug, logtype_afpd, "acltoownermode: ma_user before: %04o",ma->ma_user);
if (rights & DARWIN_ACE_READ_DATA)
ma->ma_user |= AR_UREAD;
if (rights & DARWIN_ACE_WRITE_DATA)
ma->ma_user |= AR_UWRITE;
if (rights & (DARWIN_ACE_EXECUTE | DARWIN_ACE_SEARCH))
ma->ma_user |= AR_USEARCH;
- LOG(log_maxdebug, logtype_afpd, "acltoownermode: ma_user after: %04o", ma->ma_user);
+
+ LOG(log_maxdebug, logtype_afpd, "resulting user maccess: 0x%02x", ma->ma_user);
EC_CLEANUP:
EC_EXIT;
}
-/*
- We're being called at the end of afp_createdir. We're (hopefully) inside dir
- and ".AppleDouble" and ".AppleDouble/.Parent" should have already been created.
- We then inherit any explicit ACE from "." to ".AppleDouble" and ".AppleDouble/.Parent".
- FIXME: add to VFS layer ?
-*/
-#ifdef HAVE_SOLARIS_ACLS
-void addir_inherit_acl(const struct vol *vol)
+/*!
+ * Check whether a volume supports ACLs
+ *
+ * @param vol (r) volume
+ *
+ * @returns 0 if not, 1 if yes
+ */
+int check_vol_acl_support(const struct vol *vol)
{
- ace_t *diraces = NULL, *adaces = NULL, *combinedaces = NULL;
- int diracecount, adacecount;
-
- LOG(log_debug9, logtype_afpd, "addir_inherit_acl: BEGIN");
-
- /* Check if ACLs are enabled for the volume */
- if (vol->v_flags & AFPVOL_ACLS) {
-
- if ((diracecount = get_nfsv4_acl(".", &diraces)) <= 0)
- goto cleanup;
- /* Remove any trivial ACE from "." */
- if ((diracecount = strip_trivial_aces(&diraces, diracecount)) <= 0)
- goto cleanup;
-
- /*
- Inherit to ".AppleDouble"
- */
-
- if ((adacecount = get_nfsv4_acl(".AppleDouble", &adaces)) <= 0)
- goto cleanup;
- /* Remove any non-trivial ACE from ".AppleDouble" */
- if ((adacecount = strip_nontrivial_aces(&adaces, adacecount)) <= 0)
- goto cleanup;
-
- /* Combine ACEs */
- if ((combinedaces = concat_aces(diraces, diracecount, adaces, adacecount)) == NULL)
- goto cleanup;
-
- /* Now set new acl */
- if ((acl(".AppleDouble", ACE_SETACL, diracecount + adacecount, combinedaces)) != 0)
- LOG(log_error, logtype_afpd, "addir_inherit_acl: acl: %s", strerror(errno));
-
- free(adaces);
- adaces = NULL;
- free(combinedaces);
- combinedaces = NULL;
-
- /*
- Inherit to ".AppleDouble/.Parent"
- */
-
- if ((adacecount = get_nfsv4_acl(".AppleDouble/.Parent", &adaces)) <= 0)
- goto cleanup;
- if ((adacecount = strip_nontrivial_aces(&adaces, adacecount)) <= 0)
- goto cleanup;
+ int ret = 1;
- /* Combine ACEs */
- if ((combinedaces = concat_aces(diraces, diracecount, adaces, adacecount)) == NULL)
- goto cleanup;
-
- /* Now set new acl */
- if ((acl(".AppleDouble/.Parent", ACE_SETACL, diracecount + adacecount, combinedaces)) != 0)
- LOG(log_error, logtype_afpd, "addir_inherit_acl: acl: %s", strerror(errno));
-
-
- }
-
-cleanup:
- LOG(log_debug9, logtype_afpd, "addir_inherit_acl: END");
-
- free(diraces);
- free(adaces);
- free(combinedaces);
-}
-#endif /* HAVE_SOLARIS_ACLS */
+#ifdef HAVE_SOLARIS_ACLS
+ ace_t *aces = NULL;
+ if (get_nfsv4_acl(vol->v_path, &aces) == -1)
+ ret = 0;
+#endif
+#ifdef HAVE_POSIX_ACLS
+ acl_t acl = NULL;
+ if ((acl = acl_get_file(vol->v_path, ACL_TYPE_ACCESS)) == NULL)
+ ret = 0;
+#endif
+#ifdef HAVE_SOLARIS_ACLS
+ if (aces) free(aces);
+#endif
#ifdef HAVE_POSIX_ACLS
-void addir_inherit_acl(const struct vol *vol)
-{
- return;
-}
+ if (acl) acl_free(acl);
#endif /* HAVE_POSIX_ACLS */
+
+ LOG(log_debug, logtype_afpd, "Volume \"%s\" ACL support: %s",
+ vol->v_path, ret ? "yes" : "no");
+ return ret;
+}