src/server/daemon/acl.c

changeset 202
c374d11d6720
parent 141
ff311b63c3af
child 211
2160585200ac
equal deleted inserted replaced
201:196a3caebdc7 202:c374d11d6720
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;
101 101
102 User* acllist_getuser(Session *sn, Request *rq, ACLListHandle *list) { 102 User* acllist_getuser(Session *sn, Request *rq, ACLListHandle *list) {
103 if(!sn || !rq || !list) { 103 if(!sn || !rq || !list) {
104 return NULL; 104 return NULL;
105 } 105 }
106 106
107 // get user 107 // get user
108 User *user = NULL; 108 User *user = NULL;
109 if(list->defaultauthdb) { 109 if(list->defaultauthdb) {
110 char *usr; 110 char *usr;
111 char *pw; 111 char *pw;
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,
203 return NULL; 203 return NULL;
204 } 204 }
205 if(externacl) { 205 if(externacl) {
206 *externacl = NULL; 206 *externacl = NULL;
207 } 207 }
208 208
209 // evaluate each acl until one denies access 209 // evaluate each acl until one denies access
210 ACLListElm *elm = list->listhead; 210 ACLListElm *elm = list->listhead;
211 while(elm) { 211 while(elm) {
212 ACLList *acl = elm->acl; 212 ACLList *acl = elm->acl;
213 if(acl->isextern) { 213 if(acl->isextern) {
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) {
360 acl->user_gid = pw.pw_gid; 360 acl->user_gid = pw.pw_gid;
361 } else { 361 } else {
362 acl->user_uid = -1; 362 acl->user_uid = -1;
363 acl->user_gid = -1; 363 acl->user_gid = -1;
364 } 364 }
365 365
366 // translate access_mask 366 // translate access_mask
367 uint32_t mask = 0; 367 uint32_t mask = 0;
368 if((access_mask & ACL_READ_DATA) == ACL_READ_DATA) { 368 if((access_mask & ACL_READ_DATA) == ACL_READ_DATA) {
369 mask |= ACE_READ_DATA; 369 mask |= ACE_READ_DATA;
370 } 370 }
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,
467 uint32_t mask, 467 uint32_t mask,
468 uid_t uid, 468 uid_t uid,
469 gid_t gid) 469 gid_t gid)
470 { 470 {
471 //printf("solaris_acl_check %s\n", path); 471 //printf("solaris_acl_check %s\n", path);
472 472
473 int nace = acl(path, ACE_GETACLCNT, 0, NULL); 473 int nace = acl(path, ACE_GETACLCNT, 0, NULL);
474 if(nace == -1) { 474 if(nace == -1) {
475 perror("acl: ACE_GETACLCNT"); 475 perror("acl: ACE_GETACLCNT");
476 // TODO: log error 476 // TODO: log error
477 return 0; 477 return 0;
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(
522 gid_t owninggroup) 522 gid_t owninggroup)
523 { 523 {
524 /* 524 /*
525 * mostly the same as wsacl_affects_user 525 * mostly the same as wsacl_affects_user
526 */ 526 */
527 527
528 int check_access = 0; 528 int check_access = 0;
529 529
530 if((ace->a_flags & ACE_OWNER) == ACE_OWNER) { 530 if((ace->a_flags & ACE_OWNER) == ACE_OWNER) {
531 if(uid == owner) { 531 if(uid == owner) {
532 check_access = 1; 532 check_access = 1;
533 } 533 }
534 } else if((ace->a_flags & ACE_GROUP) == ACE_GROUP) { 534 } else if((ace->a_flags & ACE_GROUP) == ACE_GROUP) {
549 if(ace->a_who == uid) { 549 if(ace->a_who == uid) {
550 check_access = 1; 550 check_access = 1;
551 } 551 }
552 } 552 }
553 } 553 }
554 554
555 return check_access; 555 return check_access;
556 } 556 }
557 557
558 void fs_acl_finish() { 558 void fs_acl_finish() {
559 559
560 } 560 }
561 561
562 #endif 562 #endif
563 563
564 /* 564 /*
570 int fs_acl_check(SysACL *acl, User *user, char *path, uint32_t access_mask) { 570 int fs_acl_check(SysACL *acl, User *user, char *path, uint32_t access_mask) {
571 return 1; 571 return 1;
572 } 572 }
573 573
574 void fs_acl_finish() { 574 void fs_acl_finish() {
575 575
576 } 576 }
577 577
578 #endif 578 #endif
579 579
580 #ifdef BSD 580 #ifdef BSD
582 int fs_acl_check(SysACL *acl, User *user, char *path, uint32_t access_mask) { 582 int fs_acl_check(SysACL *acl, User *user, char *path, uint32_t access_mask) {
583 return 1; 583 return 1;
584 } 584 }
585 585
586 void fs_acl_finish() { 586 void fs_acl_finish() {
587 587
588 } 588 }
589 589
590 #endif 590 #endif
591 591
592 592
598 struct passwd *ws_pw = conf_getglobals()->Vuserpw; 598 struct passwd *ws_pw = conf_getglobals()->Vuserpw;
599 if(!ws_pw) { 599 if(!ws_pw) {
600 log_ereport(LOG_FAILURE, "fs_acl_check: unknown webserver uid/gid"); 600 log_ereport(LOG_FAILURE, "fs_acl_check: unknown webserver uid/gid");
601 return 1; 601 return 1;
602 } 602 }
603 603
604 // get uid/gid 604 // get uid/gid
605 struct passwd pw; 605 struct passwd pw;
606 if(user) { 606 if(user) {
607 char *pwbuf = malloc(DEF_PWBUF); 607 char *pwbuf = malloc(DEF_PWBUF);
608 if(pwbuf == NULL) { 608 if(pwbuf == NULL) {
617 acl->user_gid = pw.pw_gid; 617 acl->user_gid = pw.pw_gid;
618 } else { 618 } else {
619 acl->user_uid = 0; 619 acl->user_uid = 0;
620 acl->user_gid = 0; 620 acl->user_gid = 0;
621 } 621 }
622 622
623 // set fs uid/gid 623 // set fs uid/gid
624 if(acl->user_uid != 0) { 624 if(acl->user_uid != 0) {
625 if(setfsuid(pw.pw_uid)) { 625 if(setfsuid(pw.pw_uid)) {
626 log_ereport( 626 log_ereport(
627 LOG_FAILURE, 627 LOG_FAILURE,
631 log_ereport( 631 log_ereport(
632 LOG_FAILURE, 632 LOG_FAILURE,
633 "Cannot set fsgid to gid: %u", pw.pw_gid); 633 "Cannot set fsgid to gid: %u", pw.pw_gid);
634 } 634 }
635 } 635 }
636 636
637 637
638 return 1; 638 return 1;
639 } 639 }
640 640
641 void fs_acl_finish() { 641 void fs_acl_finish() {
642 struct passwd *pw = conf_getglobals()->Vuserpw; 642 struct passwd *pw = conf_getglobals()->Vuserpw;

mercurial