# HG changeset patch # User Olaf Wintermann # Date 1362168952 -3600 # Node ID aced2245fb1c4d7c5df7489e5f99152f907cb6d5 # Parent b28cf69f42e8af09265c607055e6bc80e56deb68 new pathcheck saf and code cleanup diff -r b28cf69f42e8 -r aced2245fb1c src/server/config/acl.c --- a/src/server/config/acl.c Thu Feb 28 20:00:05 2013 +0100 +++ b/src/server/config/acl.c Fri Mar 01 21:15:52 2013 +0100 @@ -162,45 +162,7 @@ sstr_t *accessmask = sstrsplit(s, sstr(","), &maskn); for(int i=0;iaccess_mask = ace->access_mask | ACLCFG_READ; - } else if(!sstrcmp(access, sstr("write"))) { - ace->access_mask = ace->access_mask | ACLCFG_WRITE; - } else if(!sstrcmp(access, sstr("read_data"))) { - ace->access_mask = ace->access_mask | ACLCFG_READ_DATA; - } else if(!sstrcmp(access, sstr("write_data"))) { - ace->access_mask = ace->access_mask | ACLCFG_WRITE_DATA; - } else if(!sstrcmp(access, sstr("append"))) { - ace->access_mask = ace->access_mask | ACLCFG_APPEND; - } else if(!sstrcmp(access, sstr("add_file"))) { - ace->access_mask = ace->access_mask | ACLCFG_ADD_FILE; - } else if(!sstrcmp(access, sstr("add_subdirectory"))) { - ace->access_mask = ace->access_mask | ACLCFG_ADD_SUBDIRECTORY; - } else if(!sstrcmp(access, sstr("read_xattr"))) { - ace->access_mask = ace->access_mask | ACLCFG_READ_XATTR; - } else if(!sstrcmp(access, sstr("write_xattr"))) { - ace->access_mask = ace->access_mask | ACLCFG_WRITE_XATTR; - } else if(!sstrcmp(access, sstr("execute"))) { - ace->access_mask = ace->access_mask | ACLCFG_EXECUTE; - } else if(!sstrcmp(access, sstr("delete_child"))) { - ace->access_mask = ace->access_mask | ACLCFG_DELETE_CHILD; - } else if(!sstrcmp(access, sstr("delete"))) { - ace->access_mask = ace->access_mask | ACLCFG_DELETE; - } else if(!sstrcmp(access, sstr("read_attributes"))) { - ace->access_mask = ace->access_mask | ACLCFG_READ_ATTRIBUTES; - } else if(!sstrcmp(access, sstr("write_attributes"))) { - ace->access_mask = ace->access_mask | ACLCFG_WRITE_ATTRIBUTES; - } else if(!sstrcmp(access, sstr("list"))) { - ace->access_mask = ace->access_mask | ACLCFG_LIST; - } else if(!sstrcmp(access, sstr("read_acl"))) { - ace->access_mask = ace->access_mask | ACLCFG_READ_ACL; - } else if(!sstrcmp(access, sstr("write_acl"))) { - ace->access_mask = ace->access_mask | ACLCFG_WRITE_ACL; - } else if(!sstrcmp(access, sstr("write_owner"))) { - ace->access_mask = ace->access_mask | ACLCFG_WRITE_OWNER; - } else if(!sstrcmp(access, sstr("synchronize"))) { - ace->access_mask = ace->access_mask | ACLCFG_SYNCHRONIZE; - } + ace->access_mask = ace->access_mask | accstr2int(access); } free(accessmask); n++; // next token @@ -255,3 +217,47 @@ return 0; } + +uint32_t accstr2int(sstr_t access) { + uint32_t val = 0; + if(!sstrcmp(access, sstr("read"))) { + val = ACLCFG_READ; + } else if(!sstrcmp(access, sstr("write"))) { + val = ACLCFG_WRITE; + } else if(!sstrcmp(access, sstr("read_data"))) { + val = ACLCFG_READ_DATA; + } else if(!sstrcmp(access, sstr("write_data"))) { + val = ACLCFG_WRITE_DATA; + } else if(!sstrcmp(access, sstr("append"))) { + val = ACLCFG_APPEND; + } else if(!sstrcmp(access, sstr("add_file"))) { + val = ACLCFG_ADD_FILE; + } else if(!sstrcmp(access, sstr("add_subdirectory"))) { + val = ACLCFG_ADD_SUBDIRECTORY; + } else if(!sstrcmp(access, sstr("read_xattr"))) { + val = ACLCFG_READ_XATTR; + } else if(!sstrcmp(access, sstr("write_xattr"))) { + val = ACLCFG_WRITE_XATTR; + } else if(!sstrcmp(access, sstr("execute"))) { + val = ACLCFG_EXECUTE; + } else if(!sstrcmp(access, sstr("delete_child"))) { + val = ACLCFG_DELETE_CHILD; + } else if(!sstrcmp(access, sstr("delete"))) { + val = ACLCFG_DELETE; + } else if(!sstrcmp(access, sstr("read_attributes"))) { + val = ACLCFG_READ_ATTRIBUTES; + } else if(!sstrcmp(access, sstr("write_attributes"))) { + val = ACLCFG_WRITE_ATTRIBUTES; + } else if(!sstrcmp(access, sstr("list"))) { + val = ACLCFG_LIST; + } else if(!sstrcmp(access, sstr("read_acl"))) { + val = ACLCFG_READ_ACL; + } else if(!sstrcmp(access, sstr("write_acl"))) { + val = ACLCFG_WRITE_ACL; + } else if(!sstrcmp(access, sstr("write_owner"))) { + val = ACLCFG_WRITE_OWNER; + } else if(!sstrcmp(access, sstr("synchronize"))) { + val = ACLCFG_SYNCHRONIZE; + } + return val; +} diff -r b28cf69f42e8 -r aced2245fb1c src/server/config/acl.h --- a/src/server/config/acl.h Thu Feb 28 20:00:05 2013 +0100 +++ b/src/server/config/acl.h Fri Mar 01 21:15:52 2013 +0100 @@ -125,6 +125,11 @@ int acl_parse(void *p, ConfigLine *begin, ConfigLine *end, sstr_t line); int parse_ace(ACLFile *f, sstr_t line); +/* + * converts a access right string to an integer value + */ +uint32_t accstr2int(sstr_t access); + #ifdef __cplusplus } #endif diff -r b28cf69f42e8 -r aced2245fb1c src/server/daemon/acl.c --- a/src/server/daemon/acl.c Thu Feb 28 20:00:05 2013 +0100 +++ b/src/server/daemon/acl.c Fri Mar 01 21:15:52 2013 +0100 @@ -41,7 +41,10 @@ rq->acllist = handle; } -void acllist_append(Session *sn, Request *rq, ACLList *acl) { +/* + * append or prepend an ACL + */ +void acllist_add(Session *sn, Request *rq, ACLList *acl, int append) { if(!rq->acllist) { acllist_createhandle(sn, rq); } @@ -58,31 +61,22 @@ list->listhead = elm; list->listtail = elm; } else { - list->listtail->next = elm; - list->listtail = elm; + if(append) { + list->listtail->next = elm; + list->listtail = elm; + } else { + elm->next = list->listhead; + list->listhead = elm; + } } } +void acllist_append(Session *sn, Request *rq, ACLList *acl) { + acllist_add(sn, rq, acl, 1); +} + void acllist_prepend(Session *sn, Request *rq, ACLList *acl) { - if(!rq->acllist) { - acllist_createhandle(sn, rq); - } - ACLListHandle *list = rq->acllist; - - if(!list->defaultauthdb && acl->authdb) { - list->defaultauthdb = acl->authdb; - } - - ACLListElm *elm = pool_malloc(sn->pool, sizeof(ACLListElm)); - elm->acl = acl; - elm->next = NULL; - if(list->listhead == NULL) { - list->listhead = elm; - list->listtail = elm; - } else { - elm->next = list->listhead; - list->listhead = elm; - } + acllist_add(sn, rq, acl, 0); } @@ -92,6 +86,10 @@ return REQ_PROCEED; } + // we combine access_mask with the required access rights + access_mask = access_mask | rq->aclreqaccess; + + // get user User *user = NULL; if(list->defaultauthdb) { @@ -105,6 +103,7 @@ } if(!user->verify_password(user, pw)) { // wrong password + user->free(user); return REQ_ABORTED; } // ok - user is authenticated @@ -128,57 +127,62 @@ rq->srvhdrs); protocol_status(sn, rq, PROTOCOL_UNAUTHORIZED, NULL); } + user->free(user); return REQ_ABORTED; } elm = elm->next; } // ok - all acls allowed access + user->free(user); return REQ_PROCEED; } +int wsacl_affects_user(ACLEntry *ace, User *user) { + int check_access = 0; + + /* + * an ace can affect + * a named user or group (ace->who is set) + * the owner of the resource (ACL_OWNER is set) + * the owning group of the resource (ACL_GROUP is set) + * everyone (ACL_EVERYONE is set) + * + * Only one of this conditions should be true. The behavior on + * illegal flag combination is undefined. We assume that the acls + * are created correctly by the configuration loader. + */ + + if(ace->who && user) { + // this ace is defined for a named user or group + if((ace->flags & ACL_IDENTIFIER_GROUP) == ACL_IDENTIFIER_GROUP) { + if(user->check_group(user, ace->who)) { + // the user is in the group + check_access = 1; + } + } else { + if(!strcmp(user->name, ace->who)) { + check_access = 1; + } + } + } else if((ace->flags & ACL_OWNER) == ACL_OWNER) { + // TODO + } else if((ace->flags & ACL_GROUP) == ACL_GROUP) { + // TODO + } else if((ace->flags & ACL_EVERYONE) == ACL_EVERYONE) { + check_access = 1; + } + + return check_access; +} + int wsacl_check(ACLList *acl, User *user, int access_mask) { int allow = 0; uint32_t allowed_access = 0; // check each access control entry for(int i=0;iacenum;i++) { - ACLEntry *ace = acl->ace[i]; - int check_access = 0; - - /* - * an ace can affect - * a named user or group (ace->who is set) - * the owner of the resource (ACL_OWNER is set) - * the owning group of the resource (ACL_GROUP is set) - * everyone (ACL_EVERYONE is set) - * - * Only one of this conditions should be true. The behavior on - * illegal flag combination is undefined. We assume that the acls - * are created correctly by the configuration loader. - */ - - if(ace->who && user) { - // this ace is defined for a named user or group - if((ace->flags & ACL_IDENTIFIER_GROUP) == ACL_IDENTIFIER_GROUP) { - if(user->check_group(user, ace->who)) { - // the user is in the group - check_access = 1; - } - } else { - if(!strcmp(user->name, ace->who)) { - check_access = 1; - } - } - } else if((ace->flags & ACL_OWNER) == ACL_OWNER) { - // TODO - } else if((ace->flags & ACL_GROUP) == ACL_GROUP) { - // TODO - } else if((ace->flags & ACL_EVERYONE) == ACL_EVERYONE) { - check_access = 1; - } - - - if(check_access) { + ACLEntry *ace = acl->ace[i]; + if(wsacl_affects_user(ace, user)) { if(ace->type == ACL_TYPE_ALLOWED) { // add all new access rights allowed_access = allowed_access | diff -r b28cf69f42e8 -r aced2245fb1c src/server/daemon/acl.h --- a/src/server/daemon/acl.h Thu Feb 28 20:00:05 2013 +0100 +++ b/src/server/daemon/acl.h Fri Mar 01 21:15:52 2013 +0100 @@ -143,6 +143,7 @@ // private +int wsacl_affects_user(ACLEntry *ace, User *user); int wsacl_check(ACLList *acl, User *user, int access_mask); diff -r b28cf69f42e8 -r aced2245fb1c src/server/daemon/request.c --- a/src/server/daemon/request.c Thu Feb 28 20:00:05 2013 +0100 +++ b/src/server/daemon/request.c Fri Mar 01 21:15:52 2013 +0100 @@ -69,6 +69,7 @@ rq->aclname = NULL; rq->aclpb = NULL; rq->acllist = NULL; + rq->aclreqaccess = 0; rq->request_is_cacheable = 0; rq->directive_is_cacheable = 0; rq->cached_headers = NULL; diff -r b28cf69f42e8 -r aced2245fb1c src/server/daemon/ws-fn.c --- a/src/server/daemon/ws-fn.c Thu Feb 28 20:00:05 2013 +0100 +++ b/src/server/daemon/ws-fn.c Fri Mar 01 21:15:52 2013 +0100 @@ -55,6 +55,7 @@ { "auth-basic", auth_basic, NULL, 0 }, { "auth-db", auth_db, NULL, 0 }, { "require-auth", require_auth, NULL, 0}, + { "require-access", require_access, NULL, 0}, { "append-acl", append_acl, NULL, 0}, { "check-acl", check_acl, NULL, 0}, { "print-message", print_message, NULL, 0}, diff -r b28cf69f42e8 -r aced2245fb1c src/server/public/nsapi.h --- a/src/server/public/nsapi.h Thu Feb 28 20:00:05 2013 +0100 +++ b/src/server/public/nsapi.h Fri Mar 01 21:15:52 2013 +0100 @@ -991,6 +991,7 @@ pblock *aclpb; /* OBSOLETE */ /* 3.0 ACL list pointer */ ACLListHandle *acllist; + uint32_t aclreqaccess; /* new - required access rights */ int request_is_cacheable; /* */ int directive_is_cacheable; /* set by SAFs with no external side effects that make decisions based solely on URI and path */ diff -r b28cf69f42e8 -r aced2245fb1c src/server/safs/pathcheck.c --- a/src/server/safs/pathcheck.c Thu Feb 28 20:00:05 2013 +0100 +++ b/src/server/safs/pathcheck.c Fri Mar 01 21:15:52 2013 +0100 @@ -34,6 +34,9 @@ #include "../daemon/acldata.h" #include "../daemon/session.h" +#include "../ucx/string.h" +#include "../config/acl.h" + int require_auth(pblock *pb, Session *sn, Request *rq) { char *user = pblock_findkeyval(pb_key_auth_user, rq->vars); @@ -50,6 +53,23 @@ return REQ_PROCEED; } +int require_access(pblock *pb, Session *sn, Request *rq) { + char *mask_str = pblock_findval("mask", rq->vars); + if(!mask_str) { + // misconfig + // TODO: log + return REQ_ABORTED; + } + + uint32_t access_mask = 0; + size_t n = 0; + sstr_t *rights = sstrsplit(sstr(mask_str), sstrn(",", 1), &n); + for(int i=0;iinbuf) { buf->inbuf = (unsigned char *) malloc(sz); buf->maxsize = sz; diff -r b28cf69f42e8 -r aced2245fb1c src/server/util/object.c --- a/src/server/util/object.c Thu Feb 28 20:00:05 2013 +0100 +++ b/src/server/util/object.c Fri Mar 01 21:15:52 2013 +0100 @@ -97,7 +97,7 @@ - +// TODO: remove httpd_objset* create_test_objset() { httpd_objset *objset = malloc(sizeof(httpd_objset)); objset->obj = calloc(1, sizeof(httpd_object*));