diff options
Diffstat (limited to 'src/util/service.c')
-rw-r--r-- | src/util/service.c | 65 |
1 files changed, 52 insertions, 13 deletions
diff --git a/src/util/service.c b/src/util/service.c index 8235830c9..243e7daa9 100644 --- a/src/util/service.c +++ b/src/util/service.c | |||
@@ -501,14 +501,18 @@ struct GNUNET_SERVICE_Context | |||
501 | int require_found; | 501 | int require_found; |
502 | 502 | ||
503 | /** | 503 | /** |
504 | * Do we require a matching UID for UNIX domain socket | 504 | * Do we require a matching UID for UNIX domain socket connections? |
505 | * connections? | 505 | * GNUNET_NO means that the UID does not have to match (however, |
506 | * "match_gid" may still impose other access control checks). | ||
506 | */ | 507 | */ |
507 | int match_uid; | 508 | int match_uid; |
508 | 509 | ||
509 | /** | 510 | /** |
510 | * Do we require a matching GID for UNIX domain socket | 511 | * Do we require a matching GID for UNIX domain socket connections? |
511 | * connections? | 512 | * Ignored if "match_uid" is GNUNET_YES. Note that this is about |
513 | * checking that the client's UID is in our group OR that the | ||
514 | * client's GID is our GID. If both "match_gid" and "match_uid" are | ||
515 | * "GNUNET_NO", all users on the local system have access. | ||
512 | */ | 516 | */ |
513 | int match_gid; | 517 | int match_gid; |
514 | 518 | ||
@@ -617,15 +621,50 @@ check_access (void *cls, const struct GNUNET_CONNECTION_Credentials *uc, | |||
617 | #ifndef WINDOWS | 621 | #ifndef WINDOWS |
618 | case AF_UNIX: | 622 | case AF_UNIX: |
619 | ret = GNUNET_OK; /* always OK for now */ | 623 | ret = GNUNET_OK; /* always OK for now */ |
620 | if ((sctx->match_uid == GNUNET_YES) || (sctx->match_gid == GNUNET_YES)) | 624 | if (sctx->match_uid == GNUNET_YES) |
621 | ret = GNUNET_NO; | 625 | { |
622 | if ((uc != NULL) && | 626 | /* UID match required */ |
623 | ((sctx->match_uid != GNUNET_YES) || (uc->uid == geteuid ()) || | 627 | ret = (uc != NULL) && (uc->uid == geteuid ()); |
624 | (uc->uid == getuid ())) && ((sctx->match_gid != GNUNET_YES) || | 628 | } |
625 | (uc->gid == getegid ()) || | 629 | else if (sctx->match_gid == GNUNET_YES) |
626 | (uc->gid == getgid ()))) | 630 | { |
627 | ret = GNUNET_YES; | 631 | /* group match required */ |
628 | else | 632 | if (uc == NULL) |
633 | { | ||
634 | /* no credentials, group match not possible */ | ||
635 | ret = GNUNET_NO; | ||
636 | } | ||
637 | else | ||
638 | { | ||
639 | struct group *grp; | ||
640 | unsigned int i; | ||
641 | |||
642 | if (uc->gid != getegid()) | ||
643 | { | ||
644 | /* default group did not match, but maybe the user is in our group, let's check */ | ||
645 | grp = getgrgid (getegid ()); | ||
646 | if (NULL == grp) | ||
647 | { | ||
648 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "getgrgid"); | ||
649 | return GNUNET_NO; | ||
650 | } | ||
651 | ret = GNUNET_NO; | ||
652 | for (i=0; NULL != grp->gr_mem[i]; i++) | ||
653 | { | ||
654 | struct passwd *nam = getpwnam (grp->gr_mem[i]); | ||
655 | if (NULL == nam) | ||
656 | continue; /* name in group that is not in user DB !? */ | ||
657 | if (nam->pw_uid == uc->uid) | ||
658 | { | ||
659 | /* yes, uid is in our group, allow! */ | ||
660 | ret = GNUNET_YES; | ||
661 | break; | ||
662 | } | ||
663 | } | ||
664 | } | ||
665 | } | ||
666 | } | ||
667 | if (GNUNET_NO == ret) | ||
629 | LOG (GNUNET_ERROR_TYPE_WARNING, _("Access denied to UID %d / GID %d\n"), | 668 | LOG (GNUNET_ERROR_TYPE_WARNING, _("Access denied to UID %d / GID %d\n"), |
630 | (uc == NULL) ? -1 : uc->uid, (uc == NULL) ? -1 : uc->gid); | 669 | (uc == NULL) ? -1 : uc->uid, (uc == NULL) ? -1 : uc->gid); |
631 | break; | 670 | break; |