#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)) {
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));
int n =
0;
sstr_t s = tk[
0];
if(!sstrcmp(s, sstr(
"user"))) {
s = tk[
1];
n++;
ace->who = sstrdup_a(mp, s);
}
else if(!sstrcmp(s, sstr(
"group"))) {
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 {
ace->who = sstrdup_a(mp, s);
}
n++;
if(n >= tkn) {
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++;
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 {
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;
}
}
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;
}