1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32
33 #include "acl.h"
34 #include "logging.h"
35
36 ACLFile* load_acl_file(
const char *file) {
37 FILE *in = fopen(file,
"r");
38 if(in ==
NULL) {
39 return NULL;
40 }
41
42 ACLFile *conf = malloc(
sizeof(ACLFile));
43 conf->parser.parse = acl_parse;
44 conf->namedACLs = cxLinkedListCreate(cxDefaultAllocator,
NULL,
CX_STORE_POINTERS);
45 conf->uriACLs = cxLinkedListCreate(cxDefaultAllocator,
NULL,
CX_STORE_POINTERS);
46 conf->pathACLs = cxLinkedListCreate(cxDefaultAllocator,
NULL,
CX_STORE_POINTERS);
47
48 int r = cfg_parse_basic_file((ConfigParser*)conf, in);
49 if(r !=
0) {
50 free_acl_file(conf);
51 return NULL;
52 }
53
54 fclose(in);
55
56 return conf;
57 }
58
59 void free_acl_file(ACLFile *conf) {
60 cxListDestroy(conf->namedACLs);
61 cxListDestroy(conf->uriACLs);
62 cxListDestroy(conf->pathACLs);
63 cxMempoolDestroy(conf->parser.mp->data);
64 free(conf);
65 }
66
67 int acl_parse(
void *p, ConfigLine *begin, ConfigLine *end, cxmutstr line) {
68 ACLFile *aclf = p;
69 CxAllocator *mp = aclf->parser.mp;
70
71 if(cx_strprefix(cx_strcast(line), cx_str(
"ACL "))) {
72 cxmutstr param = cx_strsubs_m(line,
4);
73 ConfigParam *plist = cfg_param_list(param, mp);
74 ACLConfig *acl =
OBJ_NEW(mp, ACLConfig);
75 acl->type.ptr =
NULL;
76 acl->authparam =
NULL;
77 acl->entries =
NULL;
78 aclf->cur = acl;
79
80 cxmutstr type = cfg_param_get(plist, cx_str(
"type"));
81 cxmutstr name = cfg_param_get(plist, cx_str(
"name"));
82 cxmutstr path = cfg_param_get(plist, cx_str(
"path"));
83 cxmutstr uri = cfg_param_get(plist, cx_str(
"uri"));
84
85 if(name.ptr) {
86 acl->id = name;
87 cxListAdd(aclf->namedACLs, acl);
88 }
else if(path.ptr) {
89 acl->id = path;
90 cxListAdd(aclf->pathACLs, acl);
91 }
else if(uri.ptr) {
92 acl->id = uri;
93 cxListAdd(aclf->uriACLs, acl);
94 }
95
96 if(type.ptr) {
97 acl->type = type;
98 }
99 }
else if(cx_strprefix(cx_strcast(line), cx_str(
"Authenticate "))) {
100 cxmutstr param = cx_strsubs_m(line,
13);
101 ConfigParam *plist = cfg_param_list(param, mp);
102 aclf->cur->authparam = plist;
103 }
else {
104 if(parse_ace(aclf, line)) {
105
106 return 1;
107 }
108 }
109
110 return 0;
111 }
112
113 #define ACE_MAX_TOKENS 2048
114
115 int parse_ace(ACLFile *f, cxmutstr line) {
116 ACLConfig *cur = f->cur;
117 CxAllocator *mp = f->parser.mp;
118
119 cxstring *tk =
NULL;
120 ssize_t tkn = cx_strsplit_a(mp, cx_strcast(line), cx_str(
":"),
ACE_MAX_TOKENS, &tk);
121 if(!tk || tkn <
3) {
122 ws_cfg_log(
LOG_FAILURE,
"parse_ace: to few tokens: %.*s", (
int)line.length, line.ptr);
123 return 1;
124 }
125
126 ACEConfig *ace =
OBJ_NEW(mp, ACEConfig);
127 memset(ace,
0,
sizeof(ACEConfig));
128
129
130
131
132 int n =
0;
133 cxstring s = tk[
0];
134
135 if(!cx_strcmp(s, cx_str(
"user"))) {
136
137 s = tk[
1];
138 n++;
139 ace->who = cx_strdup_a(mp, s);
140 }
else if(!cx_strcmp(s, cx_str(
"group"))) {
141
142 s = tk[
1];
143 n++;
144 ace->who = cx_strdup_a(mp, s);
145 ace->flags =
ACLCFG_IDENTIFIER_GROUP;
146 }
else if(!cx_strcmp(s, cx_str(
"owner@"))) {
147 ace->flags =
ACLCFG_OWNER;
148 }
else if(!cx_strcmp(s, cx_str(
"group@"))) {
149 ace->flags =
ACLCFG_GROUP;
150 }
else if(!cx_strcmp(s, cx_str(
"everyone@"))) {
151 ace->flags =
ACLCFG_EVERYONE;
152 }
else {
153
154 ace->who = cx_strdup_a(mp, s);
155 }
156
157 n++;
158
159
160
161
162
163 if(n >= tkn) {
164
165 ws_cfg_log(
LOG_FAILURE,
"parse_ace: ace incomplete");
166 return 1;
167 }
168 s = tk[n];
169
170 cxstring *accessmask =
NULL;
171 ssize_t maskn = cx_strsplit_a(mp, s, cx_str(
","),
ACE_MAX_TOKENS, &accessmask);
172 for(
int i=
0;i<maskn;i++) {
173 cxstring access = accessmask[i];
174 ace->access_mask = ace->access_mask | accstr2int(access);
175 }
176 cxFree(mp, accessmask);
177 n++;
178
179
180
181
182
183 int complete =
0;
184 while(n < tkn) {
185 s = tk[n];
186 if(!cx_strcmp(s, cx_str(
"allow"))) {
187 ace->type =
ACLCFG_TYPE_ALLOWED;
188 complete =
1;
189 break;
190 }
else if(!cx_strcmp(s, cx_str(
"deny"))) {
191 ace->type =
ACLCFG_TYPE_DENIED;
192 complete =
1;
193 break;
194 }
else if(!cx_strcmp(s, cx_str(
"audit"))) {
195 ace->type =
ACLCFG_TYPE_AUDIT;
196 complete =
1;
197 break;
198 }
else if(!cx_strcmp(s, cx_str(
"alarm"))) {
199 ace->type =
ACLCFG_TYPE_ALARM;
200 complete =
1;
201 break;
202 }
else {
203
204 cxstring *flags =
NULL;
205 ssize_t fln = cx_strsplit_a(mp, s, cx_str(
","),
ACE_MAX_TOKENS, &flags);
206 for(
int i=
0;i<fln;i++) {
207 cxstring flag = flags[i];
208 if(!cx_strcmp(flag, cx_str(
"successful_access_flag"))) {
209 ace->flags = ace->flags |
ACLCFG_SUCCESSFUL_ACCESS_FLAG;
210 }
else if(!cx_strcmp(flag, cx_str(
"failed_access_flag"))) {
211 ace->flags = ace->flags |
ACLCFG_FAILED_ACCESS_ACE_FLAG;
212 }
213
214 }
215 free(flags);
216 }
217 n++;
218 }
219
220 if(!complete) {
221 ws_cfg_log(
LOG_FAILURE,
"parse_ace: ace incomplete");
222 return 1;
223 }
224
225 CFG_ACE_ADD(&cur->entries, ace);
226
227 return 0;
228 }
229
230 uint32_t accstr2int(cxstring access) {
231 uint32_t val =
0;
232 if(!cx_strcmp(access, cx_str(
"read"))) {
233 val =
ACLCFG_READ;
234 }
else if(!cx_strcmp(access, cx_str(
"write"))) {
235 val =
ACLCFG_WRITE;
236 }
else if(!cx_strcmp(access, cx_str(
"read_data"))) {
237 val =
ACLCFG_READ_DATA;
238 }
else if(!cx_strcmp(access, cx_str(
"write_data"))) {
239 val =
ACLCFG_WRITE_DATA;
240 }
else if(!cx_strcmp(access, cx_str(
"append"))) {
241 val =
ACLCFG_APPEND;
242 }
else if(!cx_strcmp(access, cx_str(
"add"))) {
243 val =
ACLCFG_ADD_FILE;
244 }
else if(!cx_strcmp(access, cx_str(
"add_file"))) {
245 val =
ACLCFG_ADD_FILE;
246 }
else if(!cx_strcmp(access, cx_str(
"add_subdirectory"))) {
247 val =
ACLCFG_ADD_SUBDIRECTORY;
248 }
else if(!cx_strcmp(access, cx_str(
"read_xattr"))) {
249 val =
ACLCFG_READ_XATTR;
250 }
else if(!cx_strcmp(access, cx_str(
"write_xattr"))) {
251 val =
ACLCFG_WRITE_XATTR;
252 }
else if(!cx_strcmp(access, cx_str(
"execute"))) {
253 val =
ACLCFG_EXECUTE;
254 }
else if(!cx_strcmp(access, cx_str(
"delete_child"))) {
255 val =
ACLCFG_DELETE_CHILD;
256 }
else if(!cx_strcmp(access, cx_str(
"delete"))) {
257 val =
ACLCFG_DELETE;
258 }
else if(!cx_strcmp(access, cx_str(
"read_attributes"))) {
259 val =
ACLCFG_READ_ATTRIBUTES;
260 }
else if(!cx_strcmp(access, cx_str(
"write_attributes"))) {
261 val =
ACLCFG_WRITE_ATTRIBUTES;
262 }
else if(!cx_strcmp(access, cx_str(
"list"))) {
263 val =
ACLCFG_LIST;
264 }
else if(!cx_strcmp(access, cx_str(
"read_acl"))) {
265 val =
ACLCFG_READ_ACL;
266 }
else if(!cx_strcmp(access, cx_str(
"write_acl"))) {
267 val =
ACLCFG_WRITE_ACL;
268 }
else if(!cx_strcmp(access, cx_str(
"write_owner"))) {
269 val =
ACLCFG_WRITE_OWNER;
270 }
else if(!cx_strcmp(access, cx_str(
"synchronize"))) {
271 val =
ACLCFG_SYNCHRONIZE;
272 }
273 return val;
274 }
275