Mon, 06 Mar 2017 17:32:26 +0100
merge srvctrl into default branch
/* * 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 <string.h> #include "acl.h" ACLFile* load_acl_file(char *file) { FILE *in = fopen(file, "r"); if(in == NULL) { return NULL; } ACLFile *conf = malloc(sizeof(ACLFile)); conf->parser.parse = acl_parse; conf->namedACLs = NULL; conf->uriACLs = NULL; conf->pathACLs = NULL; int r = cfg_parse_basic_file((ConfigParser*)conf, in); if(r != 0) { free_acl_file(conf); return NULL; } fclose(in); return conf; } void free_acl_file(ACLFile *conf) { ucx_mempool_destroy(conf->parser.mp->pool); free(conf); } int acl_parse(void *p, ConfigLine *begin, ConfigLine *end, sstr_t line) { ACLFile *aclf = p; UcxAllocator *mp = aclf->parser.mp; if(sstrprefix(line, sstr("ACL "))) { sstr_t param = sstrsubs(line, 4); UcxList *plist = cfg_param_list(param, mp); ACLConfig *acl = OBJ_NEW(mp, ACLConfig); acl->type.ptr = NULL; acl->authparam = NULL; acl->entries = NULL; aclf->cur = acl; sstr_t type = cfg_param_get(plist, sstr("type")); sstr_t name = cfg_param_get(plist, sstr("name")); sstr_t path = cfg_param_get(plist, sstr("path")); sstr_t uri = cfg_param_get(plist, sstr("uri")); if(name.ptr) { acl->id = name; aclf->namedACLs = ucx_list_append_a(mp, aclf->namedACLs, acl); } else if(path.ptr) { acl->id = path; aclf->pathACLs = ucx_list_append_a(mp, aclf->pathACLs, acl); } else if(uri.ptr) { acl->id = uri; aclf->uriACLs = ucx_list_append_a(mp, aclf->uriACLs, acl); } if(type.ptr) { acl->type = type; } } else if(sstrprefix(line, sstr("Authenticate "))) { sstr_t param = sstrsubs(line, 13); UcxList *plist = cfg_param_list(param, mp); aclf->cur->authparam = plist; } else { if(parse_ace(aclf, line)) { // TODO: error return 1; } } return 0; } int parse_ace(ACLFile *f, sstr_t line) { ACLConfig *cur = f->cur; UcxAllocator *mp = f->parser.mp; ssize_t tkn = 0; sstr_t *tk = sstrsplit(line, sstr(":"), &tkn); if(!tk || tkn < 3) { log_ereport(LOG_FAILURE, "parse_ace: to few tokens"); return 1; } ACEConfig *ace = OBJ_NEW(mp, ACEConfig); memset(ace, 0, sizeof(ACEConfig)); /* * first step: determine who is affected by this ace */ int n = 0; sstr_t s = tk[0]; if(!sstrcmp(s, sstr("user"))) { // next token is the user name s = tk[1]; n++; ace->who = sstrdup_a(mp, s); } else if(!sstrcmp(s, sstr("group"))) { // next token is the group name s = tk[1]; n++; ace->who = sstrdup_a(mp, s); ace->flags = ACLCFG_IDENTIFIER_GROUP; } else if(!sstrcmp(s, sstr("owner@"))) { ace->flags = ACLCFG_OWNER; } else if(!sstrcmp(s, sstr("group@"))) { ace->flags = ACLCFG_GROUP; } else if(!sstrcmp(s, sstr("everyone@"))) { ace->flags = ACLCFG_EVERYONE; } else { // you can specify only the user name in the ace ace->who = sstrdup_a(mp, s); } n++; //next token /* * get the access mask */ if(n >= tkn) { // to few tokens log_ereport(LOG_FAILURE, "parse_ace: ace incomplete"); return 1; } s = tk[n]; ssize_t maskn = 0; sstr_t *accessmask = sstrsplit(s, sstr(","), &maskn); for(int i=0;i<maskn;i++) { sstr_t access = accessmask[i]; ace->access_mask = ace->access_mask | accstr2int(access); } free(accessmask); n++; // next token /* * get flags (optional) and ace type */ int complete = 0; while(n < tkn) { s = tk[n]; if(!sstrcmp(s, sstr("allow"))) { ace->type = ACLCFG_TYPE_ALLOWED; complete = 1; break; } else if(!sstrcmp(s, sstr("deny"))) { ace->type = ACLCFG_TYPE_DENIED; complete = 1; break; } else if(!sstrcmp(s, sstr("audit"))) { ace->type = ACLCFG_TYPE_AUDIT; complete = 1; break; } else if(!sstrcmp(s, sstr("alarm"))) { ace->type = ACLCFG_TYPE_ALARM; complete = 1; break; } else { // set flags ssize_t fln = 0; sstr_t *flags = sstrsplit(s, sstr(","), &fln); for(int i=0;i<fln;i++) { sstr_t flag = flags[i]; if(!sstrcmp(flag, sstr("successful_access_flag"))) { ace->flags = ace->flags | ACLCFG_SUCCESSFUL_ACCESS_FLAG; } else if(!sstrcmp(flag, sstr("failed_access_flag"))) { ace->flags = ace->flags | ACLCFG_FAILED_ACCESS_ACE_FLAG; } // TODO: other flags } free(flags); } n++; } if(!complete) { log_ereport(LOG_FAILURE, "parse_ace: ace incomplete"); return 1; } cur->entries = ucx_list_append_a(mp, cur->entries, ace); 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"))) { val = ACLCFG_ADD_FILE; } 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; }