diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/include/gnunet_connection_lib.h | 19 | ||||
-rw-r--r-- | src/include/gnunet_network_lib.h | 1 | ||||
-rw-r--r-- | src/include/platform.h | 3 | ||||
-rw-r--r-- | src/util/connection.c | 49 | ||||
-rw-r--r-- | src/util/network.c | 9 | ||||
-rw-r--r-- | src/util/service.c | 47 |
6 files changed, 124 insertions, 4 deletions
diff --git a/src/include/gnunet_connection_lib.h b/src/include/gnunet_connection_lib.h index 33afb0386..8d2dbb611 100644 --- a/src/include/gnunet_connection_lib.h +++ b/src/include/gnunet_connection_lib.h | |||
@@ -53,15 +53,34 @@ struct GNUNET_CONNECTION_Handle; | |||
53 | 53 | ||
54 | 54 | ||
55 | /** | 55 | /** |
56 | * Credentials for UNIX domain sockets. | ||
57 | */ | ||
58 | struct GNUNET_CONNECTION_Credentials | ||
59 | { | ||
60 | /** | ||
61 | * UID of the other end of the connection. | ||
62 | */ | ||
63 | uid_t uid; | ||
64 | |||
65 | /** | ||
66 | * GID of the other end of the connection. | ||
67 | */ | ||
68 | gid_t gid; | ||
69 | }; | ||
70 | |||
71 | |||
72 | /** | ||
56 | * Function to call for access control checks. | 73 | * Function to call for access control checks. |
57 | * | 74 | * |
58 | * @param cls closure | 75 | * @param cls closure |
76 | * @param ucred credentials, if available, otherwise NULL | ||
59 | * @param addr address | 77 | * @param addr address |
60 | * @param addrlen length of address | 78 | * @param addrlen length of address |
61 | * @return GNUNET_YES to allow, GNUNET_NO to deny, GNUNET_SYSERR | 79 | * @return GNUNET_YES to allow, GNUNET_NO to deny, GNUNET_SYSERR |
62 | * for unknown address family (will be denied). | 80 | * for unknown address family (will be denied). |
63 | */ | 81 | */ |
64 | typedef int (*GNUNET_CONNECTION_AccessCheck) (void *cls, | 82 | typedef int (*GNUNET_CONNECTION_AccessCheck) (void *cls, |
83 | const struct GNUNET_CONNECTION_Credentials *ucred, | ||
65 | const struct sockaddr * addr, | 84 | const struct sockaddr * addr, |
66 | socklen_t addrlen); | 85 | socklen_t addrlen); |
67 | 86 | ||
diff --git a/src/include/gnunet_network_lib.h b/src/include/gnunet_network_lib.h index 73303689a..34cb7bc32 100644 --- a/src/include/gnunet_network_lib.h +++ b/src/include/gnunet_network_lib.h | |||
@@ -309,6 +309,7 @@ void GNUNET_NETWORK_fdset_add (struct GNUNET_NETWORK_FDSet *dst, | |||
309 | void GNUNET_NETWORK_fdset_copy (struct GNUNET_NETWORK_FDSet *to, | 309 | void GNUNET_NETWORK_fdset_copy (struct GNUNET_NETWORK_FDSet *to, |
310 | const struct GNUNET_NETWORK_FDSet *from); | 310 | const struct GNUNET_NETWORK_FDSet *from); |
311 | 311 | ||
312 | |||
312 | /** | 313 | /** |
313 | * Return file descriptor for this network handle | 314 | * Return file descriptor for this network handle |
314 | * | 315 | * |
diff --git a/src/include/platform.h b/src/include/platform.h index cc2aa03ae..230031307 100644 --- a/src/include/platform.h +++ b/src/include/platform.h | |||
@@ -156,6 +156,9 @@ | |||
156 | #include <sys/loadavg.h> | 156 | #include <sys/loadavg.h> |
157 | #include <semaphore.h> | 157 | #include <semaphore.h> |
158 | #endif | 158 | #endif |
159 | #if HAVE_UCRED_H | ||
160 | #include <ucred.h> | ||
161 | #endif | ||
159 | #ifdef CYGWIN | 162 | #ifdef CYGWIN |
160 | #include <windows.h> | 163 | #include <windows.h> |
161 | #include <cygwin/if.h> | 164 | #include <cygwin/if.h> |
diff --git a/src/util/connection.c b/src/util/connection.c index aa5db91bf..12969b3ba 100644 --- a/src/util/connection.c +++ b/src/util/connection.c | |||
@@ -346,6 +346,12 @@ GNUNET_CONNECTION_create_from_accept (GNUNET_CONNECTION_AccessCheck access, | |||
346 | struct sockaddr_in6 *v6; | 346 | struct sockaddr_in6 *v6; |
347 | struct sockaddr *sa; | 347 | struct sockaddr *sa; |
348 | void *uaddr; | 348 | void *uaddr; |
349 | struct GNUNET_CONNECTION_Credentials *gcp; | ||
350 | struct GNUNET_CONNECTION_Credentials gc; | ||
351 | #ifdef SO_PEERCRED | ||
352 | struct ucred uc; | ||
353 | socklen_t olen; | ||
354 | #endif | ||
349 | 355 | ||
350 | addrlen = sizeof (addr); | 356 | addrlen = sizeof (addr); |
351 | sock = | 357 | sock = |
@@ -384,9 +390,50 @@ GNUNET_CONNECTION_create_from_accept (GNUNET_CONNECTION_AccessCheck access, | |||
384 | uaddr = GNUNET_malloc (addrlen); | 390 | uaddr = GNUNET_malloc (addrlen); |
385 | memcpy (uaddr, addr, addrlen); | 391 | memcpy (uaddr, addr, addrlen); |
386 | } | 392 | } |
393 | gcp = NULL; | ||
394 | gc.uid = 0; | ||
395 | gc.gid = 0; | ||
396 | if (sa->sa_family == AF_UNIX) | ||
397 | { | ||
398 | #if HAVE_GETPEEREID | ||
399 | /* most BSDs */ | ||
400 | if (0 == getpeereid (GNUNET_NETWORK_get_fd (sock), | ||
401 | &gc.uid, | ||
402 | &gc.gid)) | ||
403 | gcp = &gc; | ||
404 | #else | ||
405 | #ifdef SO_PEERCRED | ||
406 | /* largely traditional GNU/Linux */ | ||
407 | olen = sizeof (uc); | ||
408 | if ( (0 == | ||
409 | getsockopt (GNUNET_NETWORK_get_fd (sock), | ||
410 | SOL_SOCKET, SO_PEERCRED, &uc, &olen)) && | ||
411 | (olen == sizeof (uc)) ) | ||
412 | { | ||
413 | gc.uid = uc.uid; | ||
414 | gc.gid = uc.gid; | ||
415 | gcp = &gc; | ||
416 | } | ||
417 | #else | ||
418 | #if HAVE_GETPEERUCRED | ||
419 | /* this is for Solaris 10 */ | ||
420 | ucred_t *uc; | ||
421 | |||
422 | uc = NULL; | ||
423 | if (0 == getpeerucred (GNUNET_NETWORK_get_fd (sock), &uc)) | ||
424 | { | ||
425 | gc.uid = ucred_geteuid (uc); | ||
426 | gc.gid = ucred_getegid (uc); | ||
427 | gcp = &gc; | ||
428 | } | ||
429 | ucred_free (uc); | ||
430 | #endif | ||
431 | #endif | ||
432 | #endif | ||
433 | } | ||
387 | 434 | ||
388 | if ((access != NULL) && | 435 | if ((access != NULL) && |
389 | (GNUNET_YES != (aret = access (access_cls, uaddr, addrlen)))) | 436 | (GNUNET_YES != (aret = access (access_cls, gcp, uaddr, addrlen)))) |
390 | { | 437 | { |
391 | if (aret == GNUNET_NO) | 438 | if (aret == GNUNET_NO) |
392 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 439 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, |
diff --git a/src/util/network.c b/src/util/network.c index 9e85a3be9..f7c1e53c1 100644 --- a/src/util/network.c +++ b/src/util/network.c | |||
@@ -451,6 +451,7 @@ GNUNET_NETWORK_socket_recvfrom_amount (const struct GNUNET_NETWORK_Handle | |||
451 | return GNUNET_NO; | 451 | return GNUNET_NO; |
452 | } | 452 | } |
453 | 453 | ||
454 | |||
454 | /** | 455 | /** |
455 | * Read data from a connected socket (always non-blocking). | 456 | * Read data from a connected socket (always non-blocking). |
456 | * @param desc socket | 457 | * @param desc socket |
@@ -774,12 +775,20 @@ GNUNET_NETWORK_fdset_copy (struct GNUNET_NETWORK_FDSet *to, | |||
774 | #endif | 775 | #endif |
775 | } | 776 | } |
776 | 777 | ||
778 | |||
779 | /** | ||
780 | * Return file descriptor for this network handle | ||
781 | * | ||
782 | * @param desc wrapper to process | ||
783 | * @return POSIX file descriptor | ||
784 | */ | ||
777 | int | 785 | int |
778 | GNUNET_NETWORK_get_fd (struct GNUNET_NETWORK_Handle *desc) | 786 | GNUNET_NETWORK_get_fd (struct GNUNET_NETWORK_Handle *desc) |
779 | { | 787 | { |
780 | return desc->fd; | 788 | return desc->fd; |
781 | } | 789 | } |
782 | 790 | ||
791 | |||
783 | /** | 792 | /** |
784 | * Copy a native fd set | 793 | * Copy a native fd set |
785 | * | 794 | * |
diff --git a/src/util/service.c b/src/util/service.c index ac90eb93b..0594149d9 100644 --- a/src/util/service.c +++ b/src/util/service.c | |||
@@ -512,6 +512,18 @@ struct GNUNET_SERVICE_Context | |||
512 | int require_found; | 512 | int require_found; |
513 | 513 | ||
514 | /** | 514 | /** |
515 | * Do we require a matching UID for UNIX domain socket | ||
516 | * connections? | ||
517 | */ | ||
518 | int match_uid; | ||
519 | |||
520 | /** | ||
521 | * Do we require a matching GID for UNIX domain socket | ||
522 | * connections? | ||
523 | */ | ||
524 | int match_gid; | ||
525 | |||
526 | /** | ||
515 | * Our options. | 527 | * Our options. |
516 | */ | 528 | */ |
517 | enum GNUNET_SERVICE_Options options; | 529 | enum GNUNET_SERVICE_Options options; |
@@ -579,9 +591,18 @@ static const struct GNUNET_SERVER_MessageHandler defhandlers[] = { | |||
579 | 591 | ||
580 | /** | 592 | /** |
581 | * Check if access to the service is allowed from the given address. | 593 | * Check if access to the service is allowed from the given address. |
594 | * | ||
595 | * @param cls closure | ||
596 | * @param uc credentials, if available, otherwise NULL | ||
597 | * @param addr address | ||
598 | * @param addrlen length of address | ||
599 | * @return GNUNET_YES to allow, GNUNET_NO to deny, GNUNET_SYSERR | ||
600 | * for unknown address family (will be denied). | ||
582 | */ | 601 | */ |
583 | static int | 602 | static int |
584 | check_access (void *cls, const struct sockaddr *addr, socklen_t addrlen) | 603 | check_access (void *cls, |
604 | const struct GNUNET_CONNECTION_Credentials *uc, | ||
605 | const struct sockaddr *addr, socklen_t addrlen) | ||
585 | { | 606 | { |
586 | struct GNUNET_SERVICE_Context *sctx = cls; | 607 | struct GNUNET_SERVICE_Context *sctx = cls; |
587 | const struct sockaddr_in *i4; | 608 | const struct sockaddr_in *i4; |
@@ -609,8 +630,23 @@ check_access (void *cls, const struct sockaddr *addr, socklen_t addrlen) | |||
609 | (!check_ipv6_listed (sctx->v6_denied, &i6->sin6_addr))); | 630 | (!check_ipv6_listed (sctx->v6_denied, &i6->sin6_addr))); |
610 | break; | 631 | break; |
611 | case AF_UNIX: | 632 | case AF_UNIX: |
612 | /* FIXME: support checking UID/GID in the future... */ | ||
613 | ret = GNUNET_OK; /* always OK for now */ | 633 | ret = GNUNET_OK; /* always OK for now */ |
634 | if ( (sctx->match_uid == GNUNET_YES) || | ||
635 | (sctx->match_gid == GNUNET_YES) ) | ||
636 | ret = GNUNET_NO; | ||
637 | if ( (uc != NULL) && | ||
638 | ( (sctx->match_uid != GNUNET_YES) || | ||
639 | (uc->uid == geteuid()) || | ||
640 | (uc->uid == getuid()) ) && | ||
641 | ( (sctx->match_gid != GNUNET_YES) || | ||
642 | (uc->gid == getegid()) || | ||
643 | (uc->gid == getgid())) ) | ||
644 | ret = GNUNET_YES; | ||
645 | else | ||
646 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
647 | _("Access denied to UID %d / GID %d\n"), | ||
648 | (uc == NULL) ? -1 : uc->uid, | ||
649 | (uc == NULL) ? -1 : uc->gid); | ||
614 | break; | 650 | break; |
615 | default: | 651 | default: |
616 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | 652 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, |
@@ -1187,7 +1223,12 @@ setup_service (struct GNUNET_SERVICE_Context *sctx) | |||
1187 | &sctx->addrlens)) ) | 1223 | &sctx->addrlens)) ) |
1188 | return GNUNET_SYSERR; | 1224 | return GNUNET_SYSERR; |
1189 | sctx->require_found = tolerant ? GNUNET_NO : GNUNET_YES; | 1225 | sctx->require_found = tolerant ? GNUNET_NO : GNUNET_YES; |
1190 | 1226 | sctx->match_uid = GNUNET_CONFIGURATION_get_value_yesno (sctx->cfg, | |
1227 | sctx->serviceName, | ||
1228 | "UNIX_MATCH_UID"); | ||
1229 | sctx->match_gid = GNUNET_CONFIGURATION_get_value_yesno (sctx->cfg, | ||
1230 | sctx->serviceName, | ||
1231 | "UNIX_MATCH_GID"); | ||
1191 | process_acl4 (&sctx->v4_denied, sctx, "REJECT_FROM"); | 1232 | process_acl4 (&sctx->v4_denied, sctx, "REJECT_FROM"); |
1192 | process_acl4 (&sctx->v4_allowed, sctx, "ACCEPT_FROM"); | 1233 | process_acl4 (&sctx->v4_allowed, sctx, "ACCEPT_FROM"); |
1193 | process_acl6 (&sctx->v6_denied, sctx, "REJECT_FROM6"); | 1234 | process_acl6 (&sctx->v6_denied, sctx, "REJECT_FROM6"); |