53 void acllist_add(Session *sn, Request *rq, ACLList *acl, int append) { |
53 void acllist_add(Session *sn, Request *rq, ACLList *acl, int append) { |
54 if(!rq->acllist) { |
54 if(!rq->acllist) { |
55 acllist_createhandle(sn, rq); |
55 acllist_createhandle(sn, rq); |
56 } |
56 } |
57 ACLListHandle *list = rq->acllist; |
57 ACLListHandle *list = rq->acllist; |
58 |
58 |
59 if(!list->defaultauthdb && acl->authdb) { |
59 if(!list->defaultauthdb && acl->authdb) { |
60 list->defaultauthdb = acl->authdb; |
60 list->defaultauthdb = acl->authdb; |
61 } |
61 } |
62 |
62 |
63 ACLListElm *elm = pool_malloc(sn->pool, sizeof(ACLListElm)); |
63 ACLListElm *elm = pool_malloc(sn->pool, sizeof(ACLListElm)); |
64 elm->acl = acl; |
64 elm->acl = acl; |
65 elm->next = NULL; |
65 elm->next = NULL; |
66 if(list->listhead == NULL) { |
66 if(list->listhead == NULL) { |
67 list->listhead = elm; |
67 list->listhead = elm; |
127 AUTH_TYPE_BASIC, |
127 AUTH_TYPE_BASIC, |
128 sizeof(AUTH_TYPE_BASIC)-1, |
128 sizeof(AUTH_TYPE_BASIC)-1, |
129 rq->vars); |
129 rq->vars); |
130 } |
130 } |
131 } |
131 } |
132 |
132 |
133 return user; |
133 return user; |
134 } |
134 } |
135 |
135 |
136 void acl_set_error_status(Session *sn, Request *rq, ACLList *acl, User *user) { |
136 void acl_set_error_status(Session *sn, Request *rq, ACLList *acl, User *user) { |
137 if(sn == NULL || rq == NULL) { |
137 if(sn == NULL || rq == NULL) { |
138 return; |
138 return; |
139 } |
139 } |
140 |
140 |
141 if(!user) { |
141 if(!user) { |
142 char *value = NULL; |
142 char *value = NULL; |
143 if(acl->authprompt) { |
143 if(acl->authprompt) { |
144 size_t realmlen = strlen(acl->authprompt); |
144 size_t realmlen = strlen(acl->authprompt); |
145 size_t len = realmlen + 16; |
145 size_t len = realmlen + 16; |
165 int acl_evaluate(Session *sn, Request *rq, int access_mask) { |
165 int acl_evaluate(Session *sn, Request *rq, int access_mask) { |
166 ACLListHandle *list = rq->acllist; |
166 ACLListHandle *list = rq->acllist; |
167 if(!list) { |
167 if(!list) { |
168 return REQ_PROCEED; |
168 return REQ_PROCEED; |
169 } |
169 } |
170 |
170 |
171 // we combine access_mask with the required access rights |
171 // we combine access_mask with the required access rights |
172 access_mask |= rq->aclreqaccess; |
172 access_mask |= rq->aclreqaccess; |
173 |
173 |
174 // get user |
174 // get user |
175 User *user = acllist_getuser(sn, rq, list); |
175 User *user = acllist_getuser(sn, rq, list); |
176 |
176 |
177 // evalutate all ACLs |
177 // evalutate all ACLs |
178 ACLList *acl = acl_evallist(list, user, access_mask, NULL); |
178 ACLList *acl = acl_evallist(list, user, access_mask, NULL); |
179 if(acl) { |
179 if(acl) { |
180 acl_set_error_status(sn, rq, acl, user); |
180 acl_set_error_status(sn, rq, acl, user); |
181 // TODO: don't free the user here |
181 // TODO: don't free the user here |
182 if(user) { |
182 if(user) { |
183 user->free(user); |
183 user->free(user); |
184 } |
184 } |
185 return REQ_ABORTED; |
185 return REQ_ABORTED; |
186 } |
186 } |
187 |
187 |
188 // access allowed, we can free the user |
188 // access allowed, we can free the user |
189 if(user) { |
189 if(user) { |
190 user->free(user); |
190 user->free(user); |
191 } |
191 } |
192 |
192 |
193 return REQ_PROCEED; |
193 return REQ_PROCEED; |
194 } |
194 } |
195 |
195 |
196 ACLList* acl_evallist( |
196 ACLList* acl_evallist( |
197 ACLListHandle *list, |
197 ACLListHandle *list, |
216 *externacl = acl; |
216 *externacl = acl; |
217 } |
217 } |
218 } else if(!acl->check(acl, user, access_mask)) { |
218 } else if(!acl->check(acl, user, access_mask)) { |
219 // the acl denies access |
219 // the acl denies access |
220 return acl; |
220 return acl; |
221 } |
221 } |
222 elm = elm->next; |
222 elm = elm->next; |
223 } |
223 } |
224 |
224 |
225 // ok - all acls allowed access |
225 // ok - all acls allowed access |
226 |
226 |
227 return NULL; |
227 return NULL; |
228 } |
228 } |
229 |
229 |
230 int wsacl_affects_user(WSAce *ace, User *user) { |
230 int wsacl_affects_user(WSAce *ace, User *user) { |
231 int check_access = 0; |
231 int check_access = 0; |
232 |
232 |
233 /* |
233 /* |
234 * an ace can affect |
234 * an ace can affect |
235 * a named user or group (ace->who is set) |
235 * a named user or group (ace->who is set) |
236 * the owner of the resource (ACL_OWNER is set) |
236 * the owner of the resource (ACL_OWNER is set) |
237 * the owning group of the resource (ACL_GROUP is set) |
237 * the owning group of the resource (ACL_GROUP is set) |
238 * everyone (ACL_EVERYONE is set) |
238 * everyone (ACL_EVERYONE is set) |
239 * |
239 * |
240 * Only one of this conditions should be true. The behavior on |
240 * Only one of this conditions should be true. The behavior on |
241 * illegal flag combination is undefined. We assume that the acls |
241 * illegal flag combination is undefined. We assume that the acls |
242 * are created correctly by the configuration loader. |
242 * are created correctly by the configuration loader. |
243 */ |
243 */ |
244 |
244 |
245 if(ace->who && user) { |
245 if(ace->who && user) { |
246 // this ace is defined for a named user or group |
246 // this ace is defined for a named user or group |
247 if((ace->flags & ACL_IDENTIFIER_GROUP) == ACL_IDENTIFIER_GROUP) { |
247 if((ace->flags & ACL_IDENTIFIER_GROUP) == ACL_IDENTIFIER_GROUP) { |
248 if(user->check_group(user, ace->who)) { |
248 if(user->check_group(user, ace->who)) { |
249 // the user is in the group |
249 // the user is in the group |
259 } else if((ace->flags & ACL_GROUP) == ACL_GROUP) { |
259 } else if((ace->flags & ACL_GROUP) == ACL_GROUP) { |
260 // TODO |
260 // TODO |
261 } else if((ace->flags & ACL_EVERYONE) == ACL_EVERYONE) { |
261 } else if((ace->flags & ACL_EVERYONE) == ACL_EVERYONE) { |
262 check_access = 1; |
262 check_access = 1; |
263 } |
263 } |
264 |
264 |
265 return check_access; |
265 return check_access; |
266 } |
266 } |
267 |
267 |
268 int wsacl_check(WSAcl *acl, User *user, int access_mask) { |
268 int wsacl_check(WSAcl *acl, User *user, int access_mask) { |
269 int allow = 0; |
269 int allow = 0; |
270 uint32_t allowed_access = 0; |
270 uint32_t allowed_access = 0; |
271 // check each access control entry |
271 // check each access control entry |
272 for(int i=0;i<acl->acenum;i++) { |
272 for(int i=0;i<acl->acenum;i++) { |
273 WSAce *ace = acl->ace[i]; |
273 WSAce *ace = acl->ace[i]; |
274 if(wsacl_affects_user(ace, user)) { |
274 if(wsacl_affects_user(ace, user)) { |
275 if(ace->type == ACL_TYPE_ALLOWED) { |
275 if(ace->type == ACL_TYPE_ALLOWED) { |
276 // add all new access rights |
276 // add all new access rights |
277 allowed_access |= (access_mask & ace->access_mask); |
277 allowed_access |= (access_mask & ace->access_mask); |
278 // check if we have all requested rights |
278 // check if we have all requested rights |
279 if((allowed_access & access_mask) == access_mask) { |
279 if((allowed_access & access_mask) == access_mask) { |
280 allow = 1; |
280 allow = 1; |
281 break; |
281 break; |
282 } |
282 } |
283 } else { |
283 } else { |
284 // ACL_TYPE_DENIED |
284 // ACL_TYPE_DENIED |
285 |
285 |
286 if((ace->access_mask & access_mask) != 0) { |
286 if((ace->access_mask & access_mask) != 0) { |
287 // access denied |
287 // access denied |
288 break; |
288 break; |
289 } |
289 } |
290 } |
290 } |
291 } |
291 } |
292 } |
292 } |
293 |
293 |
294 // TODO: events |
294 // TODO: events |
295 |
295 |
296 return allow; // allow is 0, if no ace set it to 1 |
296 return allow; // allow is 0, if no ace set it to 1 |
297 } |
297 } |
298 |
298 |
299 |
299 |
300 /* filesystem acl functions */ |
300 /* filesystem acl functions */ |
330 return 0; |
330 return 0; |
331 } |
331 } |
332 } |
332 } |
333 sstr_t wd = sstr(cwd); |
333 sstr_t wd = sstr(cwd); |
334 sstr_t pp = sstr(path); |
334 sstr_t pp = sstr(path); |
335 |
335 |
336 p = sstrcat(3, wd, sstrn("/", 1), pp); |
336 p = sstrcat(3, wd, sstrn("/", 1), pp); |
337 } else { |
337 } else { |
338 p = sstrdup(sstr(path)); |
338 p = sstrdup(sstr(path)); |
339 } |
339 } |
340 if(p.ptr[p.length-1] == '/') { |
340 if(p.ptr[p.length-1] == '/') { |
341 p.ptr[p.length-1] = 0; |
341 p.ptr[p.length-1] = 0; |
342 p.length--; |
342 p.length--; |
343 } |
343 } |
344 |
344 |
345 // get uid/gid |
345 // get uid/gid |
346 struct passwd pw; |
346 struct passwd pw; |
347 if(user) { |
347 if(user) { |
348 char *pwbuf = malloc(DEF_PWBUF); |
348 char *pwbuf = malloc(DEF_PWBUF); |
349 if(pwbuf == NULL) { |
349 if(pwbuf == NULL) { |
405 mask |= ACE_WRITE_OWNER; |
405 mask |= ACE_WRITE_OWNER; |
406 } |
406 } |
407 if((access_mask & ACL_SYNCHRONIZE) == ACL_SYNCHRONIZE) { |
407 if((access_mask & ACL_SYNCHRONIZE) == ACL_SYNCHRONIZE) { |
408 mask |= ACE_SYNCHRONIZE; |
408 mask |= ACE_SYNCHRONIZE; |
409 } |
409 } |
410 |
410 |
411 /* |
411 /* |
412 * If the vfs wants to create new files, path does not name an existing |
412 * If the vfs wants to create new files, path does not name an existing |
413 * file. In this case, we check if the user has the ACE_ADD_FILE |
413 * file. In this case, we check if the user has the ACE_ADD_FILE |
414 * permission for the parent directory |
414 * permission for the parent directory |
415 */ |
415 */ |
426 free(p.ptr); |
426 free(p.ptr); |
427 return 0; |
427 return 0; |
428 } |
428 } |
429 } |
429 } |
430 } |
430 } |
431 |
431 |
432 /* |
432 /* |
433 * perform a acl check for the path and each parent directory |
433 * perform a acl check for the path and each parent directory |
434 * we don't check the file system root |
434 * we don't check the file system root |
435 * |
435 * |
436 * after the first check, we check only search permission for the |
436 * after the first check, we check only search permission for the |
437 * directories |
437 * directories |
438 */ |
438 */ |
439 if(!solaris_acl_check(p.ptr, &s, mask, pw.pw_uid, pw.pw_gid)) { |
439 if(!solaris_acl_check(p.ptr, &s, mask, pw.pw_uid, pw.pw_gid)) { |
440 free(p.ptr); |
440 free(p.ptr); |
441 return 0; |
441 return 0; |
442 } |
442 } |
443 |
443 |
444 p = util_path_remove_last(p); |
444 p = util_path_remove_last(p); |
445 mask = ACE_LIST_DIRECTORY; |
445 mask = ACE_LIST_DIRECTORY; |
446 while(p.length > 1) { |
446 while(p.length > 1) { |
447 if(stat(p.ptr, &s)) { |
447 if(stat(p.ptr, &s)) { |
448 free(p.ptr); |
448 free(p.ptr); |
450 } |
450 } |
451 if(!solaris_acl_check(p.ptr, &s, mask, pw.pw_uid, pw.pw_gid)) { |
451 if(!solaris_acl_check(p.ptr, &s, mask, pw.pw_uid, pw.pw_gid)) { |
452 free(p.ptr); |
452 free(p.ptr); |
453 return 0; |
453 return 0; |
454 } |
454 } |
455 |
455 |
456 // cut the last file name from the path |
456 // cut the last file name from the path |
457 p = util_path_remove_last(p); |
457 p = util_path_remove_last(p); |
458 } |
458 } |
459 |
459 |
460 |
460 |
461 return 1; |
461 return 1; |
462 } |
462 } |
463 |
463 |
464 int solaris_acl_check( |
464 int solaris_acl_check( |
465 char *path, |
465 char *path, |
481 perror("acl: ACE_GETACL"); |
481 perror("acl: ACE_GETACL"); |
482 // TODO: log error |
482 // TODO: log error |
483 free(aces); |
483 free(aces); |
484 return 0; |
484 return 0; |
485 } |
485 } |
486 |
486 |
487 int allow = 0; |
487 int allow = 0; |
488 uint32_t allowed_access = 0; |
488 uint32_t allowed_access = 0; |
489 for(int i=0;i<nace;i++) { |
489 for(int i=0;i<nace;i++) { |
490 ace_t ace = aces[i]; |
490 ace_t ace = aces[i]; |
491 if(solaris_acl_affects_user(&ace, uid, gid, s->st_uid, s->st_gid)) { |
491 if(solaris_acl_affects_user(&ace, uid, gid, s->st_uid, s->st_gid)) { |
492 if(ace.a_type == ACE_ACCESS_ALLOWED_ACE_TYPE) { |
492 if(ace.a_type == ACE_ACCESS_ALLOWED_ACE_TYPE) { |
493 // add all new access rights |
493 // add all new access rights |
494 allowed_access |= (mask & ace.a_access_mask); |
494 allowed_access |= (mask & ace.a_access_mask); |
495 // check if we have all requested rights |
495 // check if we have all requested rights |
496 if((allowed_access & mask) == mask) { |
496 if((allowed_access & mask) == mask) { |
497 allow = 1; |
497 allow = 1; |
498 break; |
498 break; |
499 } |
499 } |
500 } else if(ace.a_type == ACE_ACCESS_DENIED_ACE_TYPE) { |
500 } else if(ace.a_type == ACE_ACCESS_DENIED_ACE_TYPE) { |
501 // ACL_TYPE_DENIED |
501 // ACL_TYPE_DENIED |
502 |
502 |
503 if((ace.a_access_mask & mask) != 0) { |
503 if((ace.a_access_mask & mask) != 0) { |
504 // access denied |
504 // access denied |
505 break; |
505 break; |
506 } |
506 } |
507 } |
507 } |
508 } |
508 } |
509 } |
509 } |
510 |
510 |
511 free(aces); |
511 free(aces); |
512 |
512 |
513 //printf("return %d\n", allow); |
513 //printf("return %d\n", allow); |
514 return allow; |
514 return allow; |
515 } |
515 } |
516 |
516 |
517 int solaris_acl_affects_user( |
517 int solaris_acl_affects_user( |