]> arthur.barton.de Git - netatalk.git/blobdiff - etc/afpd/acls.c
Merge from branch-2-1
[netatalk.git] / etc / afpd / acls.c
index 0c67c9475c72233efbff3082905510ef35e7a11e..76d87c12645e60e618e28256df65b5faaa6acc97 100644 (file)
@@ -50,6 +50,7 @@
 #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;
@@ -125,11 +124,11 @@ static int solaris_acl_rights(const char *path,
            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))
             ||
@@ -375,17 +374,16 @@ EC_CLEANUP:
  *
  * @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;
@@ -397,12 +395,15 @@ static int posix_acl_rights(const char *path,
     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;
         }
@@ -416,29 +417,38 @@ static int posix_acl_rights(const char *path,
         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;
         }
@@ -1085,7 +1095,6 @@ static int check_acl_access(const struct vol *vol,
     uint32_t       allowed_rights = 0;
     char           *username = NULL;
     uuidtype_t     uuidtype;
-    struct passwd  *pwd;
     struct stat    st;
     bstring        parent = NULL;
 
@@ -1109,13 +1118,11 @@ static int check_acl_access(const struct vol *vol,
         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);
@@ -1148,10 +1155,10 @@ static int check_acl_access(const struct vol *vol,
         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! */
@@ -1421,16 +1428,19 @@ int afp_setacl(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size
     return ret;
 }
 
+/********************************************************************
+ * 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, uid_t uid, struct maccess *ma)
+int acltoownermode(char *path, struct stat *st, struct maccess *ma)
 {
     EC_INIT;
-    struct passwd *pw;
     uint32_t rights = 0;
 
     if ( ! (AFPobj->options.flags & OPTION_ACL2MACCESS)
@@ -1441,13 +1451,11 @@ int acltoownermode(char *path, struct stat *st, uid_t uid, struct maccess *ma)
     LOG(log_maxdebug, logtype_afpd, "acltoownermode(\"%s/%s\", 0x%02x)",
         getcwdpath(), path, ma->ma_user);
 
-    EC_NULL_LOG(pw = getpwuid(uid));
-
 #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, pw, &rights));
+    EC_ZERO_LOG(posix_acl_rights(path, st, &rights));
 #endif
 
     LOG(log_maxdebug, logtype_afpd, "rights: 0x%08x", rights);
@@ -1464,3 +1472,37 @@ int acltoownermode(char *path, struct stat *st, uid_t uid, struct maccess *ma)
 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;
+}