#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;
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))
||
*
* @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
+ * @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,
- const struct passwd *pwd,
uint32_t *result)
{
EC_INIT;
+ int havemask = 0;
int entry_id = ACL_FIRST_ENTRY;
uint32_t rights = 0, maskrights = 0;
uid_t *uid = NULL;
EC_NULL_LOG(acl = acl_get_file(path, ACL_TYPE_ACCESS));
/* itereate through all ACEs to get the mask */
- while (acl_get_entry(acl, entry_id, &e) == 1) {
+ 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));
- continue;
+ LOG(log_maxdebug, logtype_afpd, "maskrights: 0x%08x", maskrights);
+ havemask = 1;
+ break;
default:
continue;
}
switch (tag) {
case ACL_USER:
EC_NULL_LOG(uid = (uid_t *)acl_get_qualifier(e));
- if (*uid == pwd->pw_uid)
+ 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 == pwd->pw_uid)
+ 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))
+ 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 (gmem(sb->st_gid))
+ if (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:
+ LOG(log_maxdebug, logtype_afpd, "ACL_OTHER");
rights |= posix_permset_to_darwin_rights(e, S_ISDIR(sb->st_mode));
break;
-
default:
continue;
}
uint32_t allowed_rights = 0;
char *username = NULL;
uuidtype_t uuidtype;
- struct passwd *pwd;
struct stat st;
bstring parent = NULL;
goto EC_CLEANUP;
}
- EC_NULL_LOG_ERR(pwd = getpwnam(username), AFPERR_MISC);
-
#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, pwd, &allowed_rights));
+ EC_ZERO_LOG(posix_acl_rights(path, &st, &allowed_rights));
#endif
LOG(log_debug, logtype_afpd, "allowed rights: 0x%08x", allowed_rights);
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, pwd, &allowed_rights));
+ 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! */
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;
}
+
+/*!
+ * 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)
+{
+ int ret = 1;
+
+#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
+ 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;
+}