Fri, 01 Mar 2013 21:15:52 +0100
new pathcheck saf and code cleanup
/* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright 2013 Olaf Wintermann. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include <stdio.h> #include <stdlib.h> #include "../util/pool.h" #include "../safs/auth.h" #include "acl.h" void acllist_createhandle(Session *sn, Request *rq) { ACLListHandle *handle = pool_malloc(sn->pool, sizeof(ACLListHandle)); handle->defaultauthdb = NULL; handle->listhead = NULL; handle->listtail = NULL; rq->acllist = handle; } /* * append or prepend an ACL */ void acllist_add(Session *sn, Request *rq, ACLList *acl, int append) { 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 { 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) { acllist_add(sn, rq, acl, 0); } int acl_evaluate(Session *sn, Request *rq, int access_mask) { ACLListHandle *list = rq->acllist; if(!list) { 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) { char *usr; char *pw; if(!basicauth_getuser(sn, rq, &usr, &pw)) { user = list->defaultauthdb->get_user(list->defaultauthdb, usr); if(!user) { // wrong user name return REQ_ABORTED; } if(!user->verify_password(user, pw)) { // wrong password user->free(user); return REQ_ABORTED; } // ok - user is authenticated } } else { // TODO return REQ_ABORTED; } // evaluate each acl until one denies access ACLListElm *elm = list->listhead; while(elm) { ACLList *acl = elm->acl; if(!wsacl_check(acl, user, access_mask)) { // the acl denies access if(!user) { pblock_nvinsert( "www-authenticate", "Basic realm=\"Webserver\"", 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;i<acl->acenum;i++) { 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 | (access_mask & ace->access_mask); // check if we have all requested rights if((allowed_access & access_mask) == access_mask) { allow = 1; break; } } else { // ACL_TYPE_DENIED if((ace->access_mask & access_mask) != 0) { // access denied break; } } } } // TODO: events return allow; }