src/server/daemon/vfs.c

changeset 63
66442f81f823
parent 59
ab25c0a231d0
child 66
74babc0082b7
--- a/src/server/daemon/vfs.c	Thu May 09 19:41:11 2013 +0200
+++ b/src/server/daemon/vfs.c	Sat May 11 13:28:26 2013 +0200
@@ -33,6 +33,7 @@
 
 #include "../util/pool.h"
 #include "../ucx/map.h"
+#include "acl.h"
 #include "vfs.h"
 
 static UcxMap *vfs_map;
@@ -107,12 +108,18 @@
     }
     
     // check ACLs
-    uid_t uid; // uid and gid will be initialized by sys_acl_check
-    gid_t gid;
-    if(sys_acl_check(ctx, access_mask, &uid, &gid)) {
+    SysACL sysacl;
+    if(sys_acl_check(ctx, access_mask, &sysacl)) {
         return NULL;
     }
     
+    if(sysacl.acl) {
+        if(!fs_acl_check(&sysacl, ctx->user, path, access_mask)) {
+            acl_set_error_status(ctx->sn, ctx->rq, sysacl.acl, ctx->user);
+            return NULL;
+        }
+    }
+    
     // open file
     mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
     int fd = open(path, oflags, mode);
@@ -124,6 +131,16 @@
         return NULL;
     }
     
+    // if a file system acl is active, we set the owner for newly created files
+    if(((oflags & O_CREAT) == O_CREAT) && sysacl.user_uid != -1) {
+        if(fchown(fd, sysacl.user_uid, sysacl.user_gid)) {
+            perror("vfs_open: fchown");
+            close(fd);
+            return NULL;
+        }
+    }
+    
+    
     VFSFile *file = pool ?
             pool_malloc(pool, sizeof(VFSFile)) : malloc(sizeof(VFSFile));
     if(!file) {
@@ -176,12 +193,18 @@
     }
     
     // check ACLs
-    uid_t uid; // uid and gid will be initialized by sys_acl_check
-    gid_t gid;
-    if(sys_acl_check(ctx, access_mask, &uid, &gid)) {
+    SysACL sysacl;
+    if(sys_acl_check(ctx, access_mask, &sysacl)) {
         return -1;
     }
     
+    if(sysacl.acl) {
+        if(!fs_acl_check(&sysacl, ctx->user, path, access_mask)) {
+            acl_set_error_status(ctx->sn, ctx->rq, sysacl.acl, ctx->user);
+            return -1;
+        }
+    }
+    
     // stat
     if(stat(path, buf)) {
         if(ctx) {
@@ -256,12 +279,18 @@
     }
     
     // check ACLs
-    uid_t uid; // uid and gid will be initialized by sys_acl_check
-    gid_t gid;
-    if(sys_acl_check(ctx, access_mask, &uid, &gid)) {
+    SysACL sysacl;
+    if(sys_acl_check(ctx, access_mask, &sysacl)) {
         return NULL;
     }
     
+    if(sysacl.acl) {
+        if(!fs_acl_check(&sysacl, ctx->user, path, access_mask)) {
+            acl_set_error_status(ctx->sn, ctx->rq, sysacl.acl, ctx->user);
+            return NULL;
+        }
+    }
+    
     // open file
     int sys_fd = open(path, O_RDONLY);
     if(sys_fd == -1) {
@@ -315,7 +344,7 @@
     if(ctx && ctx->vfs) {
         return vfs_path_op(ctx, path, ctx->vfs->mkdir, ACL_ADD_FILE);
     } else {
-        return vfs_path_op(ctx, path, sys_mkdir, ACL_ADD_FILE);
+        return sys_path_op(ctx, path, sys_mkdir, ACL_ADD_FILE);
     }
 }
 
@@ -323,7 +352,7 @@
     if(ctx && ctx->vfs) {
         return vfs_path_op(ctx, path, ctx->vfs->unlink, ACL_DELETE);
     } else {
-        return vfs_path_op(ctx, path, sys_unlink, ACL_DELETE);
+        return sys_path_op(ctx, path, sys_unlink, ACL_DELETE);
     }
 }
 
@@ -332,38 +361,43 @@
 int vfs_path_op(VFSContext *ctx, char *path, vfs_op_f op, uint32_t access) {
     Session *sn;
     Request *rq;
-    uint32_t access_mask;
+    
+    uint32_t access_mask = ctx->aclreqaccess;
+    access_mask |= access;
+    if(!ctx->pool) {
+        // TODO: log warning
+        // broken VFSContext
+        return -1;
+    }
     
+    // ctx->aclreqaccess should be the complete access mask
+    uint32_t m = ctx->aclreqaccess; // save original access mask
+    ctx->aclreqaccess = access_mask; // set mask for vfs function call
+    int ret = op(ctx, path);
+    ctx->aclreqaccess = m; // restore original access mask
+    return ret;
+}
+
+int sys_path_op(VFSContext *ctx, char *path, sys_op_f op, uint32_t access) {
     if(ctx) {
-        access_mask = ctx->aclreqaccess;
-        access_mask |= access;
-        if(!ctx->pool) {
-            // TODO: log warning
-            // broken VFSContext
-        }
-        if(ctx->vfs) {
-            // ctx->aclreqaccess should be the complete access mask
-            uint32_t m = ctx->aclreqaccess; // save original access mask
-            ctx->aclreqaccess = access_mask; // set mask for vfs->fstat call
-            int ret = op(ctx, path);
-            ctx->aclreqaccess = m; // restore original access mask
-            return ret;
-        }
-    } else {
-        sn = NULL;
-        rq = NULL;
-        access_mask = access;
+        access |= ctx->aclreqaccess;
     }
     
     // check ACLs
-    uid_t uid; // uid and gid will be initialized by sys_acl_check
-    gid_t gid;
-    if(sys_acl_check(ctx, access_mask, &uid, &gid)) {
+    SysACL sysacl;
+    if(sys_acl_check(ctx, access, &sysacl)) {
         return -1;
     }
     
+    if(sysacl.acl) {
+        if(!fs_acl_check(&sysacl, ctx->user, path, access)) {
+            acl_set_error_status(ctx->sn, ctx->rq, sysacl.acl, ctx->user);
+            return -1;
+        }
+    }
+    
     // do path operation
-    if(op(ctx, path)) {
+    if(op(ctx, path, &sysacl)) {
         // error
         if(ctx) {
             ctx->vfs_errno = errno;
@@ -375,32 +409,25 @@
     return 0;
 }
 
-int sys_acl_check(VFSContext *ctx, uint32_t acm, uid_t *uid, gid_t *gid) {
-    /*
-     * we don't allow remote root access, so a uid of 0 means that
-     * no file system acl check is needed
-     */
-    *uid = 0;
-    *gid = 0;
+int sys_acl_check(VFSContext *ctx, uint32_t access_mask, SysACL *sysacl) {
     if(!ctx) {
+        if(sysacl) {
+            sysacl->acl = NULL;
+        }
         return 0;
     }
     
     ACLListHandle *acllist = ctx->acllist;
     if(acllist) {
-        ACLListElm *elm = acllist->listhead;
-        while(elm) {
-            ACLList *acl = elm->acl;
-            if(acl->isextern) {
-                // TODO
-            } else if(!acl->check(acl, ctx->user, acm)) {
-                // access denied
-                if(ctx->sn && ctx->rq) {
-                    acl_set_error_status(ctx->sn, ctx->rq, acl, ctx->user);
-                }
-                return 1;        
-            } 
-            elm = elm->next;
+        ACLList *acl = acl_evallist(
+                acllist,
+                ctx->user,
+                access_mask,
+                &sysacl->acl);
+        
+        if(acl) {
+            acl_set_error_status(ctx->sn, ctx->rq, acl, ctx->user);
+            return 1;
         }
     }
     
@@ -452,12 +479,20 @@
     closedir(dir->data);
 }
 
-int sys_mkdir(VFSContext *ctx, char *path) {
+int sys_mkdir(VFSContext *ctx, char *path, SysACL *sysacl) {
     mode_t mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
-    return mkdir(path, mode);
+    int ret = mkdir(path, mode);
+    if(ret == 0) {
+        if(sysacl->user_uid != -1) {
+            if(chown(path, sysacl->user_uid, sysacl->user_gid)) {
+                // TODO: error
+            }
+        }
+    }
+    return ret;
 }
 
-int sys_unlink(VFSContext *ctx, char *path) {
+int sys_unlink(VFSContext *ctx, char *path, SysACL *sysacl) {
     return unlink(path);
 }
 

mercurial