supports file system ACLs on Solaris

Sat, 11 May 2013 13:28:26 +0200

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Sat, 11 May 2013 13:28:26 +0200
changeset 63
66442f81f823
parent 62
c47e081b6c0f
child 64
c7f5b062e622

supports file system ACLs on Solaris

src/server/daemon/acl.c file | annotate | diff | comparison | revisions
src/server/daemon/acl.h file | annotate | diff | comparison | revisions
src/server/daemon/config.c file | annotate | diff | comparison | revisions
src/server/daemon/keyfile_auth.c file | annotate | diff | comparison | revisions
src/server/daemon/ldap_auth.c file | annotate | diff | comparison | revisions
src/server/daemon/vfs.c file | annotate | diff | comparison | revisions
src/server/daemon/vfs.h file | annotate | diff | comparison | revisions
src/server/daemon/webserver.c file | annotate | diff | comparison | revisions
src/server/public/acl.h file | annotate | diff | comparison | revisions
src/server/public/auth.h file | annotate | diff | comparison | revisions
src/server/public/nsapi.h file | annotate | diff | comparison | revisions
src/server/util/util.c file | annotate | diff | comparison | revisions
src/server/util/util.h file | annotate | diff | comparison | revisions
--- a/src/server/daemon/acl.c	Thu May 09 19:41:11 2013 +0200
+++ b/src/server/daemon/acl.c	Sat May 11 13:28:26 2013 +0200
@@ -29,6 +29,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 
+#include "../util/util.h"
 #include "../util/pool.h"
 #include "../safs/auth.h"
 #include "acl.h"
@@ -122,6 +123,10 @@
 }
 
 void acl_set_error_status(Session *sn, Request *rq, ACLList *acl, User *user) {
+    if(sn == NULL || rq == NULL) {
+        return;
+    }
+    
     if(!user) {
         char *value = NULL;
         if(acl->authprompt) {
@@ -159,7 +164,7 @@
     User *user = acllist_getuser(sn, rq, list);
     
     // evalutate all ACLs
-    ACLList *acl = acl_evallist(list, user, access_mask);
+    ACLList *acl = acl_evallist(list, user, access_mask, NULL);
     if(acl) {
         acl_set_error_status(sn, rq, acl, user);
         // TODO: don't free the user here
@@ -177,16 +182,29 @@
     return REQ_PROCEED;
 }
 
-ACLList* acl_evallist(ACLListHandle *list, User *user, int access_mask) {
+ACLList* acl_evallist(
+        ACLListHandle *list,
+        User *user,
+        int access_mask,
+        ACLList **externacl)
+{
     if(!list) {
         return NULL;
     }
+    if(externacl) {
+        *externacl = NULL;
+    }
     
     // evaluate each acl until one denies access
     ACLListElm *elm = list->listhead;
     while(elm) {
         ACLList *acl = elm->acl;
-        if(!acl->check(acl, user, access_mask)) {
+        if(acl->isextern) {
+            // set externacl to the first external acl
+            if(externacl && *externacl == NULL) {
+                *externacl = acl;
+            }
+        } else if(!acl->check(acl, user, access_mask)) {
             // the acl denies access
             return acl;
         } 
@@ -266,3 +284,269 @@
     
     return allow; // allow is 0, if no ace set it to 1
 }
+
+
+/* filesystem acl functions */
+
+#if defined (__SVR4) && defined (__sun)
+
+#include <sys/acl.h>
+
+int solaris_acl_check(
+        char *path,
+        struct stat *s,
+        uint32_t mask,
+        uid_t uid,
+        gid_t gid);
+int solaris_acl_affects_user(
+        ace_t *ace,
+        uid_t uid,
+        gid_t gid,
+        uid_t owner,
+        gid_t owninggroup);
+
+int fs_acl_check(SysACL *acl, User *user, char *path, uint32_t access_mask) {
+    sstr_t p;
+    if(path[0] != '/') {
+        size_t n = 128;
+        char *cwd = malloc(n);
+        while(!getcwd(cwd, n)) {
+            if(errno == ERANGE) {
+                n *= 2;
+                cwd = realloc(cwd, n);
+            } else {
+                free(cwd);
+                return 0;
+            }
+        }
+        sstr_t wd = sstr(cwd);
+        sstr_t pp = sstr(path);
+        p.length = wd.length + pp.length + 1;
+        p.ptr = malloc(p.length + 1);
+        p = sstrncat(3, p, wd, sstrn("/", 1), pp);
+        p.ptr[p.length] = '\0';
+    } else {
+        p = sstrdup(sstr(path));
+    }
+    if(p.ptr[p.length-1] == '/') {
+        p.ptr[p.length-1] = 0;
+        p.length--;
+    }
+    
+    // get uid/gid
+    struct passwd pw;
+    if(user) {
+        char *pwbuf = malloc(DEF_PWBUF);
+        if(pwbuf == NULL) {
+            free(p.ptr);
+            return 0;
+        }
+        if(!util_getpwnam(user->name, &pw, pwbuf, DEF_PWBUF)) {
+            free(pwbuf);
+            free(p.ptr);
+            return 0;
+        }
+        free(pwbuf);
+        acl->user_uid = pw.pw_uid;
+        acl->user_gid = pw.pw_gid;
+    } else {
+        acl->user_uid = -1;
+        acl->user_gid = -1;
+    }
+    
+    // translate access_mask
+    uint32_t mask = 0;
+    if((access_mask & ACL_READ_DATA) == ACL_READ_DATA) {
+        mask |= ACE_READ_DATA;
+    }
+    if((access_mask & ACL_WRITE_DATA) == ACL_WRITE_DATA) {
+        mask |= ACE_WRITE_DATA;
+    }
+    if((access_mask & ACL_ADD_FILE) == ACL_ADD_FILE) {
+        mask |= ACE_ADD_FILE;
+    }
+    if((access_mask & ACL_READ_XATTR) == ACL_READ_XATTR) {
+        mask |= ACE_READ_NAMED_ATTRS;
+    }
+    if((access_mask & ACL_WRITE_XATTR) == ACL_WRITE_XATTR) {
+        mask |= ACE_WRITE_NAMED_ATTRS;
+    }
+    if((access_mask & ACL_EXECUTE) == ACL_EXECUTE) {
+        mask |= ACE_EXECUTE;
+    }
+    if((access_mask & ACL_DELETE) == ACL_DELETE) {
+        mask |= ACE_DELETE_CHILD;
+    }
+    if((access_mask & ACL_READ_ATTRIBUTES) == ACL_READ_ATTRIBUTES) {
+        mask |= ACE_READ_ATTRIBUTES;
+    }
+    if((access_mask & ACL_WRITE_ATTRIBUTES) == ACL_WRITE_ATTRIBUTES) {
+        mask |= ACE_WRITE_ATTRIBUTES;
+    }
+    if((access_mask & ACL_LIST) == ACL_LIST) {
+        mask |= ACE_LIST_DIRECTORY;
+    }
+    if((access_mask & ACL_READ_ACL) == ACL_READ_ACL) {
+        mask |= ACE_READ_ACL;
+    }
+    if((access_mask & ACL_WRITE_ACL) == ACL_WRITE_ACL) {
+        mask |= ACE_WRITE_ACL;
+    }
+    if((access_mask & ACL_WRITE_OWNER) == ACL_WRITE_OWNER) {
+        mask |= ACE_WRITE_OWNER;
+    }
+    if((access_mask & ACL_SYNCHRONIZE) == ACL_SYNCHRONIZE) {
+        mask |= ACE_SYNCHRONIZE;
+    }
+    
+    /*
+     * If the vfs wants to create new files, path does not name an existing
+     * file. In this case, we check if the user has the ACE_ADD_FILE
+     * permission for the parent directory
+     */
+    struct stat s;
+    if(stat(p.ptr, &s)) {
+        if(errno != ENOENT) {
+            perror("fs_acl_check: stat");
+            free(p.ptr);
+            return 0;
+        } else {
+            mask = ACE_ADD_FILE;
+            p = util_path_remove_last(p);
+            if(stat(p.ptr, &s)) {
+                free(p.ptr);
+                return 0;
+            }
+        }
+    }
+    
+    /*
+     * perform a acl check for the path and each parent directory
+     * we don't check the file system root
+     * 
+     * after the first check, we check only search permission for the
+     * directories
+     */
+    if(!solaris_acl_check(p.ptr, &s, mask, pw.pw_uid, pw.pw_gid)) {
+        free(p.ptr);
+        return 0;
+    }
+    
+    p = util_path_remove_last(p);
+    mask = ACE_LIST_DIRECTORY;
+    while(p.length > 1) {
+        if(stat(p.ptr, &s)) {
+            free(p.ptr);
+            return 0;
+        }
+        if(!solaris_acl_check(p.ptr, &s, mask, pw.pw_uid, pw.pw_gid)) {
+            free(p.ptr);
+            return 0;
+        }
+        
+        // cut the last file name from the path
+        p = util_path_remove_last(p);
+    }
+    
+    
+    return 1;
+}
+
+int solaris_acl_check(
+        char *path,
+        struct stat *s,
+        uint32_t mask,
+        uid_t uid,
+        gid_t gid)
+{
+    //printf("solaris_acl_check %s\n", path);
+    
+    int nace = acl(path, ACE_GETACLCNT, 0, NULL);
+    if(nace == -1) {
+        perror("acl: ACE_GETACLCNT");
+        // TODO: log error
+        return 0;
+    }
+    ace_t *aces = calloc(nace, sizeof(ace_t));
+    if(acl(path, ACE_GETACL, nace, aces) == 1) {
+        perror("acl: ACE_GETACL");
+        // TODO: log error
+        free(aces);
+        return 0;
+    }
+    
+    int allow = 0;
+    uint32_t allowed_access = 0;
+    for(int i=0;i<nace;i++) {
+        ace_t ace = aces[i];
+        if(solaris_acl_affects_user(&ace, uid, gid, s->st_uid, s->st_gid)) {
+            if(ace.a_type == ACE_ACCESS_ALLOWED_ACE_TYPE) {
+                // add all new access rights 
+                allowed_access |= (mask & ace.a_access_mask);
+                // check if we have all requested rights
+                if((allowed_access & mask) == mask) {
+                    allow = 1;
+                    break;
+                }
+            } else if(ace.a_type == ACE_ACCESS_DENIED_ACE_TYPE) {
+                // ACL_TYPE_DENIED
+                
+                if((ace.a_access_mask & mask) != 0) {
+                    // access denied
+                    break;
+                }
+            }
+        }
+    }
+    
+    free(aces);
+    
+    //printf("return %d\n", allow);
+    return allow;
+}
+
+int solaris_acl_affects_user(
+        ace_t *ace,
+        uid_t uid,
+        gid_t gid,
+        uid_t owner,
+        gid_t owninggroup)
+{
+    /*
+     * mostly the same as wsacl_affects_user
+     */
+    
+    int check_access = 0;
+    
+    if((ace->a_flags & ACE_OWNER) == ACE_OWNER) {
+        if(uid == owner) {
+            check_access = 1;
+        }
+    } else if((ace->a_flags & ACE_GROUP) == ACE_GROUP) {
+        if(gid == owninggroup) {
+            check_access = 1;
+        }
+    } else if((ace->a_flags & ACE_EVERYONE) == ACE_EVERYONE) {
+       check_access = 1;
+    } else if(ace->a_who != -1 && uid != 0) {
+        // this ace is defined for a named user or group
+        if((ace->a_flags & ACE_IDENTIFIER_GROUP) == ACE_IDENTIFIER_GROUP) {
+            // TODO: check all groups
+            if(ace->a_who == gid) {
+                // the user is in the group
+                check_access = 1;
+            }
+        } else {
+            if(ace->a_who == uid) {
+                check_access = 1;
+            }
+        }
+    }
+    
+    return check_access;
+}
+
+
+
+#endif
+
--- a/src/server/daemon/acl.h	Thu May 09 19:41:11 2013 +0200
+++ b/src/server/daemon/acl.h	Sat May 11 13:28:26 2013 +0200
@@ -35,11 +35,21 @@
 extern "C" {
 #endif
 
+typedef struct SysACL {
+    ACLList *acl;
+    uid_t   user_uid;
+    gid_t   user_gid;
+} SysACL;
+    
 // private
 int wsacl_affects_user(WSAce *ace, User *user);
 int wsacl_check(WSAcl *acl, User *user, int access_mask);
 
 
+// file system acl functions
+
+int fs_acl_check(SysACL *acl, User *user, char *path, uint32_t access_mask);
+
 #ifdef	__cplusplus
 }
 #endif
--- a/src/server/daemon/config.c	Thu May 09 19:41:11 2013 +0200
+++ b/src/server/daemon/config.c	Sat May 11 13:28:26 2013 +0200
@@ -786,6 +786,7 @@
     UCX_FOREACH(UcxList*, aclfile->namedACLs, elm) {
         ACLConfig *ac = elm->data;
         ACLList *acl = acl_config_convert(cfg, ac);
+        printf("put acl: %s\n", ac->id.ptr);
         ucx_map_sstr_put(acldata->namedACLs, ac->id, acl);
     }
     free_acl_file(aclfile);
@@ -808,6 +809,11 @@
     acllist->ace = NULL;
     acllist->ece = NULL;
     
+    if(acl->type.ptr && !sstrcmp(acl->type, sstr("fs"))) {
+        printf("set acl to extern\n");
+        acllist->acl.isextern = 1;
+    }
+    
     size_t s = ucx_list_size(acl->entries);
     WSAce **aces = calloc(s, sizeof(WSAce*));
     WSAce **eces = calloc(s, sizeof(WSAce*));
--- a/src/server/daemon/keyfile_auth.c	Thu May 09 19:41:11 2013 +0200
+++ b/src/server/daemon/keyfile_auth.c	Sat May 11 13:28:26 2013 +0200
@@ -84,6 +84,8 @@
     
     KeyfileUser *user = malloc(sizeof(KeyfileUser));
     user->user.name = sstrdup(name).ptr;
+    user->user.uid = -1;
+    user->user.gid = -1;
     user->user.verify_password = keyfile_user_verify_password;
     user->user.check_group = keyfile_user_check_group;
     user->user.free = keyfile_user_free;
@@ -151,8 +153,11 @@
     SHA1((const unsigned char*)saltpw, saltpwlen, pwhash);
     
     if(!memcmp(user->hash, pwhash, 20)) {
+        free(pwhash);
         return 1;
     }
     
+    free(pwhash);
+    
     return 0;
 }
--- a/src/server/daemon/ldap_auth.c	Thu May 09 19:41:11 2013 +0200
+++ b/src/server/daemon/ldap_auth.c	Sat May 11 13:28:26 2013 +0200
@@ -91,12 +91,16 @@
 
     LDAPMessage *msg = ldap_first_entry(ld, result);
     if (msg) {
-        LDAPUser *user = malloc(sizeof (LDAPUser));
+        LDAPUser *user = malloc(sizeof(LDAPUser));
         if (user != NULL) {
             user->user.verify_password = ldap_user_verify_password;
             user->user.check_group = ldap_user_check_group;
             user->user.free = ldap_user_free;
             user->user.name = username; // must not be freed
+            
+            // TODO: get uid/gid from ldap
+            user->user.uid = -1;
+            user->user.gid = -1;
 
             user->ldap = ld;
             user->userdn = ldap_get_dn(ld, msg);
--- 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);
 }
 
--- a/src/server/daemon/vfs.h	Thu May 09 19:41:11 2013 +0200
+++ b/src/server/daemon/vfs.h	Sat May 11 13:28:26 2013 +0200
@@ -30,26 +30,28 @@
 #define	VFS_H
 
 #include "../public/vfs.h"
+#include "acl.h"
 
 #ifdef	__cplusplus
 extern "C" {
 #endif
-
-// private
+    
 int vfs_init();
 
 typedef int(*vfs_op_f)(VFSContext *, char *);
+typedef int(*sys_op_f)(VFSContext *, char *, SysACL *);
 int vfs_path_op(VFSContext *ctx, char *path, vfs_op_f op, uint32_t access);
+int sys_path_op(VFSContext *ctx, char *path, sys_op_f op, uint32_t access);
 
-int sys_acl_check(VFSContext *ctx, uint32_t acm, uid_t *uid, gid_t *gid);
+int sys_acl_check(VFSContext *ctx, uint32_t access_mask, SysACL *externacl);
 void sys_set_error_status(VFSContext *ctx);
 ssize_t sys_file_read(SYS_FILE fd, void *buf, size_t nbyte);
 ssize_t sys_file_write(SYS_FILE fd, const void *buf, size_t nbyte);
 void sys_file_close(SYS_FILE fd);
 int sys_dir_read(VFS_DIR dir, VFS_ENTRY *entry, int getstat);
 void sys_dir_close(VFS_DIR dir);
-int sys_mkdir(VFSContext *ctx, char *path);
-int sys_unlink(VFSContext *ctx, char *path);
+int sys_mkdir(VFSContext *ctx, char *path, SysACL *sysacl);
+int sys_unlink(VFSContext *ctx, char *path, SysACL *sysacl);
 
 #ifdef	__cplusplus
 }
--- a/src/server/daemon/webserver.c	Thu May 09 19:41:11 2013 +0200
+++ b/src/server/daemon/webserver.c	Sat May 11 13:28:26 2013 +0200
@@ -93,11 +93,12 @@
     // set global vars
     conf_global_vars_s *vars = conf_getglobals();
     
+    setpwent();
     if(cfg->user.ptr) {
         char *pwbuf = malloc(DEF_PWBUF);
         vars->Vuserpw = malloc(sizeof(struct passwd));
         // open user database
-        setpwent();
+        //setpwent();
         if(!util_getpwnam(cfg->user.ptr, vars->Vuserpw, pwbuf, DEF_PWBUF)) {
             log_ereport(
                     LOG_MISCONFIG,
@@ -107,7 +108,7 @@
             vars->Vuserpw = NULL;
         }
         free(pwbuf);
-        endpwent();
+        //endpwent(); // TODO: close or not?
     }
 
     // change uid
--- a/src/server/public/acl.h	Thu May 09 19:41:11 2013 +0200
+++ b/src/server/public/acl.h	Sat May 11 13:28:26 2013 +0200
@@ -181,10 +181,16 @@
  * 
  * evalutes all ACLs in acllist
  * 
+ * externacl is set if an acl is extern, otherwise it is set to NULL
+ * 
  * returns NULL if access is allowed or a pointer to the ACLList which
  * denied access
  */
-ACLList* acl_evallist(ACLListHandle *acllist, User *user, int access_mask);
+ACLList* acl_evallist(
+        ACLListHandle *acllist,
+        User *user,
+        int access_mask,
+        ACLList **externacl);
 
 #ifdef	__cplusplus
 }
--- a/src/server/public/auth.h	Thu May 09 19:41:11 2013 +0200
+++ b/src/server/public/auth.h	Sat May 11 13:28:26 2013 +0200
@@ -29,6 +29,8 @@
 #ifndef WS_AUTH_H
 #define	WS_AUTH_H
 
+#include <sys/types.h>
+
 #ifdef	__cplusplus
 extern "C" {
 #endif
@@ -74,6 +76,8 @@
 
 struct user {
     char                   *name;
+    uid_t                  uid;
+    gid_t                  gid;
     /* int verify_password(User *user, char *password) */
     user_verify_passwd_f   verify_password;
     /* int check_group(User *user, char *group) */
--- a/src/server/public/nsapi.h	Thu May 09 19:41:11 2013 +0200
+++ b/src/server/public/nsapi.h	Sat May 11 13:28:26 2013 +0200
@@ -1370,7 +1370,7 @@
 NSAPI_PUBLIC int system_fwrite(SYS_FILE fd, const void *buf, int nbyte);
 NSAPI_PUBLIC int system_fclose(SYS_FILE fd);
 
-NSAPI_PUBLIC int util_errno2status(int errno_value);
+NSAPI_PUBLIC int util_errno2status(int errno_value); // new
 #define util_errno2status util_errno2status
 
 
--- a/src/server/util/util.c	Thu May 09 19:41:11 2013 +0200
+++ b/src/server/util/util.c	Sat May 11 13:28:26 2013 +0200
@@ -301,3 +301,20 @@
     
     return newstr;
 }
+
+sstr_t util_path_remove_last(sstr_t path) {
+    int i;
+    for(i=path.length-1;i>=0;i--) {
+        char c = path.ptr[i];
+        if(c == '/') {
+            path.ptr[i] = 0;
+            path.length = i;
+            break;
+        }
+    }
+    if(i < 0) {
+        path.ptr = NULL;
+        path.length = 0;
+    }
+    return path;
+}
--- a/src/server/util/util.h	Thu May 09 19:41:11 2013 +0200
+++ b/src/server/util/util.h	Sat May 11 13:28:26 2013 +0200
@@ -228,6 +228,8 @@
 /* path utils */
 NSAPI_PUBLIC
 sstr_t util_path_append(pool_handle_t *pool, char *path, char *child);
+NSAPI_PUBLIC
+sstr_t util_path_remove_last(sstr_t path);
 
 /* --- End common function prototypes --- */
 

mercurial