UNIXworkcode

1 /* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 * 4 * Copyright 2013 Olaf Wintermann. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include <stdio.h> 30 #include <stdlib.h> 31 #include <string.h> 32 33 #include "acl.h" 34 35 ACLFile* load_acl_file(char *file) { 36 FILE *in = fopen(file, "r"); 37 if(in == NULL) { 38 return NULL; 39 } 40 41 ACLFile *conf = malloc(sizeof(ACLFile)); 42 conf->parser.parse = acl_parse; 43 conf->namedACLs = NULL; 44 conf->uriACLs = NULL; 45 conf->pathACLs = NULL; 46 47 int r = cfg_parse_basic_file((ConfigParser*)conf, in); 48 if(r != 0) { 49 free_acl_file(conf); 50 return NULL; 51 } 52 53 fclose(in); 54 55 return conf; 56 } 57 58 void free_acl_file(ACLFile *conf) { 59 ucx_mempool_destroy(conf->parser.mp->pool); 60 free(conf); 61 } 62 63 int acl_parse(void *p, ConfigLine *begin, ConfigLine *end, sstr_t line) { 64 ACLFile *aclf = p; 65 UcxAllocator *mp = aclf->parser.mp; 66 67 if(sstrprefix(line, sstr("ACL "))) { 68 sstr_t param = sstrsubs(line, 4); 69 UcxList *plist = cfg_param_list(param, mp); 70 ACLConfig *acl = OBJ_NEW(mp, ACLConfig); 71 acl->type.ptr = NULL; 72 acl->authparam = NULL; 73 acl->entries = NULL; 74 aclf->cur = acl; 75 76 sstr_t type = cfg_param_get(plist, sstr("type")); 77 sstr_t name = cfg_param_get(plist, sstr("name")); 78 sstr_t path = cfg_param_get(plist, sstr("path")); 79 sstr_t uri = cfg_param_get(plist, sstr("uri")); 80 81 if(name.ptr) { 82 acl->id = name; 83 aclf->namedACLs = ucx_list_append_a(mp, aclf->namedACLs, acl); 84 } else if(path.ptr) { 85 acl->id = path; 86 aclf->pathACLs = ucx_list_append_a(mp, aclf->pathACLs, acl); 87 } else if(uri.ptr) { 88 acl->id = uri; 89 aclf->uriACLs = ucx_list_append_a(mp, aclf->uriACLs, acl); 90 } 91 92 if(type.ptr) { 93 acl->type = type; 94 } 95 } else if(sstrprefix(line, sstr("Authenticate "))) { 96 sstr_t param = sstrsubs(line, 13); 97 UcxList *plist = cfg_param_list(param, mp); 98 aclf->cur->authparam = plist; 99 } else { 100 if(parse_ace(aclf, line)) { 101 // TODO: error 102 return 1; 103 } 104 } 105 106 return 0; 107 } 108 109 int parse_ace(ACLFile *f, sstr_t line) { 110 ACLConfig *cur = f->cur; 111 UcxAllocator *mp = f->parser.mp; 112 113 ssize_t tkn = 0; 114 sstr_t *tk = sstrsplit(line, sstr(":"), &tkn); 115 if(!tk || tkn < 3) { 116 log_ereport(LOG_FAILURE, "parse_ace: to few tokens"); 117 return 1; 118 } 119 120 ACEConfig *ace = OBJ_NEW(mp, ACEConfig); 121 memset(ace, 0, sizeof(ACEConfig)); 122 123 /* 124 * first step: determine who is affected by this ace 125 */ 126 int n = 0; 127 sstr_t s = tk[0]; 128 129 if(!sstrcmp(s, sstr("user"))) { 130 // next token is the user name 131 s = tk[1]; 132 n++; 133 ace->who = sstrdup_a(mp, s); 134 } else if(!sstrcmp(s, sstr("group"))) { 135 // next token is the group name 136 s = tk[1]; 137 n++; 138 ace->who = sstrdup_a(mp, s); 139 ace->flags = ACLCFG_IDENTIFIER_GROUP; 140 } else if(!sstrcmp(s, sstr("owner@"))) { 141 ace->flags = ACLCFG_OWNER; 142 } else if(!sstrcmp(s, sstr("group@"))) { 143 ace->flags = ACLCFG_GROUP; 144 } else if(!sstrcmp(s, sstr("everyone@"))) { 145 ace->flags = ACLCFG_EVERYONE; 146 } else { 147 // you can specify only the user name in the ace 148 ace->who = sstrdup_a(mp, s); 149 } 150 151 n++; //next token 152 153 /* 154 * get the access mask 155 */ 156 157 if(n >= tkn) { 158 // to few tokens 159 log_ereport(LOG_FAILURE, "parse_ace: ace incomplete"); 160 return 1; 161 } 162 s = tk[n]; 163 164 ssize_t maskn = 0; 165 sstr_t *accessmask = sstrsplit(s, sstr(","), &maskn); 166 for(int i=0;i<maskn;i++) { 167 sstr_t access = accessmask[i]; 168 ace->access_mask = ace->access_mask | accstr2int(access); 169 } 170 free(accessmask); 171 n++; // next token 172 173 /* 174 * get flags (optional) and ace type 175 */ 176 177 int complete = 0; 178 while(n < tkn) { 179 s = tk[n]; 180 if(!sstrcmp(s, sstr("allow"))) { 181 ace->type = ACLCFG_TYPE_ALLOWED; 182 complete = 1; 183 break; 184 } else if(!sstrcmp(s, sstr("deny"))) { 185 ace->type = ACLCFG_TYPE_DENIED; 186 complete = 1; 187 break; 188 } else if(!sstrcmp(s, sstr("audit"))) { 189 ace->type = ACLCFG_TYPE_AUDIT; 190 complete = 1; 191 break; 192 } else if(!sstrcmp(s, sstr("alarm"))) { 193 ace->type = ACLCFG_TYPE_ALARM; 194 complete = 1; 195 break; 196 } else { 197 // set flags 198 ssize_t fln = 0; 199 sstr_t *flags = sstrsplit(s, sstr(","), &fln); 200 for(int i=0;i<fln;i++) { 201 sstr_t flag = flags[i]; 202 if(!sstrcmp(flag, sstr("successful_access_flag"))) { 203 ace->flags = ace->flags | ACLCFG_SUCCESSFUL_ACCESS_FLAG; 204 } else if(!sstrcmp(flag, sstr("failed_access_flag"))) { 205 ace->flags = ace->flags | ACLCFG_FAILED_ACCESS_ACE_FLAG; 206 } 207 // TODO: other flags 208 } 209 free(flags); 210 } 211 n++; 212 } 213 214 if(!complete) { 215 log_ereport(LOG_FAILURE, "parse_ace: ace incomplete"); 216 return 1; 217 } 218 219 cur->entries = ucx_list_append_a(mp, cur->entries, ace); 220 221 return 0; 222 } 223 224 uint32_t accstr2int(sstr_t access) { 225 uint32_t val = 0; 226 if(!sstrcmp(access, sstr("read"))) { 227 val = ACLCFG_READ; 228 } else if(!sstrcmp(access, sstr("write"))) { 229 val = ACLCFG_WRITE; 230 } else if(!sstrcmp(access, sstr("read_data"))) { 231 val = ACLCFG_READ_DATA; 232 } else if(!sstrcmp(access, sstr("write_data"))) { 233 val = ACLCFG_WRITE_DATA; 234 } else if(!sstrcmp(access, sstr("append"))) { 235 val = ACLCFG_APPEND; 236 } else if(!sstrcmp(access, sstr("add"))) { 237 val = ACLCFG_ADD_FILE; 238 } else if(!sstrcmp(access, sstr("add_file"))) { 239 val = ACLCFG_ADD_FILE; 240 } else if(!sstrcmp(access, sstr("add_subdirectory"))) { 241 val = ACLCFG_ADD_SUBDIRECTORY; 242 } else if(!sstrcmp(access, sstr("read_xattr"))) { 243 val = ACLCFG_READ_XATTR; 244 } else if(!sstrcmp(access, sstr("write_xattr"))) { 245 val = ACLCFG_WRITE_XATTR; 246 } else if(!sstrcmp(access, sstr("execute"))) { 247 val = ACLCFG_EXECUTE; 248 } else if(!sstrcmp(access, sstr("delete_child"))) { 249 val = ACLCFG_DELETE_CHILD; 250 } else if(!sstrcmp(access, sstr("delete"))) { 251 val = ACLCFG_DELETE; 252 } else if(!sstrcmp(access, sstr("read_attributes"))) { 253 val = ACLCFG_READ_ATTRIBUTES; 254 } else if(!sstrcmp(access, sstr("write_attributes"))) { 255 val = ACLCFG_WRITE_ATTRIBUTES; 256 } else if(!sstrcmp(access, sstr("list"))) { 257 val = ACLCFG_LIST; 258 } else if(!sstrcmp(access, sstr("read_acl"))) { 259 val = ACLCFG_READ_ACL; 260 } else if(!sstrcmp(access, sstr("write_acl"))) { 261 val = ACLCFG_WRITE_ACL; 262 } else if(!sstrcmp(access, sstr("write_owner"))) { 263 val = ACLCFG_WRITE_OWNER; 264 } else if(!sstrcmp(access, sstr("synchronize"))) { 265 val = ACLCFG_SYNCHRONIZE; 266 } 267 return val; 268 } 269