aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/include/gnunet_connection_lib.h19
-rw-r--r--src/include/gnunet_network_lib.h1
-rw-r--r--src/include/platform.h3
-rw-r--r--src/util/connection.c49
-rw-r--r--src/util/network.c9
-rw-r--r--src/util/service.c47
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 */
58struct 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 */
64typedef int (*GNUNET_CONNECTION_AccessCheck) (void *cls, 82typedef 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,
309void GNUNET_NETWORK_fdset_copy (struct GNUNET_NETWORK_FDSet *to, 309void 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 */
777int 785int
778GNUNET_NETWORK_get_fd (struct GNUNET_NETWORK_Handle *desc) 786GNUNET_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 */
583static int 602static int
584check_access (void *cls, const struct sockaddr *addr, socklen_t addrlen) 603check_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");