--- 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); }