summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2011-01-24 12:03:32 +0000
committerChristian Grothoff <christian@grothoff.org>2011-01-24 12:03:32 +0000
commit48718834d4fb6c411ff5b00b86662a3dee3ac6cc (patch)
treea5651f8f3066fb0e68bfc87cbd23be1c0dea6ba5
parent1b97726713d88e1ec485aa1e827365a707ebc02f (diff)
UNIX domain socket authentication support added
-rw-r--r--TODO8
-rw-r--r--configure.ac4
-rw-r--r--contrib/defaults.conf18
-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
9 files changed, 147 insertions, 11 deletions
diff --git a/TODO b/TODO
index afd45f091..6b3a2230b 100644
--- a/TODO
+++ b/TODO
@@ -7,13 +7,13 @@
+ implement UDP, HTTP/HTTPS
* Transport:
- UDP fragmentation
-* UTIL / FS:
- - gnunet-publish tires to connect to service even if
- run with 'simulation' option (-s)
* DHT: [Nate]
- track paths content travels (PUT, reply-to-get) in messages,
pass to client (client API & protocol already support this!)
* FS: [CG]
+ - gnunet-publish tires to connect to service even if
+ run with 'simulation' option (-s)
+ - gnunet-download does not *always* use inline full data (?)
- implement multi-peer FS performance tests
+ insert
+ download
@@ -65,8 +65,6 @@
- Remove KBlocks in gnunet-unindex (see discussion with Kenneth Almquist on gnunet-devs in 9/2009)
- use different queue prioritization for probe-downloads vs. normal downloads
- re-implement gnunet-auto-share
-* UTIL: [CG]
- - allow limiting UNIX socket access by UID/GID
* GNUNET-GTK: [CG]
- add tool bar
- do meaningful update to status line (starting up, peer running, #connections, shutdown, ...)
diff --git a/configure.ac b/configure.ac
index a57030a5c..7938ff1d8 100644
--- a/configure.ac
+++ b/configure.ac
@@ -293,7 +293,7 @@ AC_HEADER_STDC
AC_CHECK_HEADERS([fcntl.h math.h errno.h ctype.h limits.h stdio.h stdlib.h string.h unistd.h stdarg.h signal.h locale.h sys/stat.h sys/types.h],,AC_MSG_ERROR([Compiling GNUnet requires standard UNIX headers files]))
# Checks for headers that are only required on some systems or opional (and where we do NOT abort if they are not there)
-AC_CHECK_HEADERS([langinfo.h sys/param.h sys/mount.h sys/statvfs.h sys/select.h sockLib.h sys/mman.h sys/msg.h sys/vfs.h arpa/inet.h fcntl.h libintl.h netdb.h netinet/in.h netinet/in_systm.h sys/ioctl.h sys/socket.h sys/time.h unistd.h kstat.h sys/sysinfo.h kvm.h sys/file.h sys/resource.h ifaddrs.h mach/mach.h stddef.h sys/timeb.h terminos.h argz.h])
+AC_CHECK_HEADERS([langinfo.h sys/param.h sys/mount.h sys/statvfs.h sys/select.h sockLib.h sys/mman.h sys/msg.h sys/vfs.h arpa/inet.h fcntl.h libintl.h netdb.h netinet/in.h netinet/in_systm.h sys/ioctl.h sys/socket.h sys/time.h unistd.h kstat.h sys/sysinfo.h kvm.h sys/file.h sys/resource.h ifaddrs.h mach/mach.h stddef.h sys/timeb.h terminos.h argz.h ucred.h])
SAVE_LDFLAGS=$LDFLAGS
SAVE_CPPFLAGS=$CPPFLAGS
@@ -664,7 +664,7 @@ AC_FUNC_VPRINTF
AC_HEADER_SYS_WAIT
AC_TYPE_OFF_T
AC_TYPE_UID_T
-AC_CHECK_FUNCS([floor gethostname memmove rmdir strncasecmp strrchr strtol atoll dup2 fdatasync ftruncate gettimeofday memset mkdir mkfifo select socket strcasecmp strchr strdup strerror strstr clock_gettime getrusage rand uname setlocale getcwd mktime gmtime_r gmtime strlcpy strlcat ftruncate stat64 sbrk mmap mremap setrlimit sysconf gethostbyaddr initgroups getifaddrs freeifaddrs getnameinfo getaddrinfo inet_ntoa localtime_r nl_langinfo putenv realpath strndup gethostbyname2 gethostbyname])
+AC_CHECK_FUNCS([floor gethostname memmove rmdir strncasecmp strrchr strtol atoll dup2 fdatasync ftruncate gettimeofday memset mkdir mkfifo select socket strcasecmp strchr strdup strerror strstr clock_gettime getrusage rand uname setlocale getcwd mktime gmtime_r gmtime strlcpy strlcat ftruncate stat64 sbrk mmap mremap setrlimit sysconf gethostbyaddr initgroups getifaddrs freeifaddrs getnameinfo getaddrinfo inet_ntoa localtime_r nl_langinfo putenv realpath strndup gethostbyname2 gethostbyname getpeerucred getpeereid])
# restore LIBS
LIBS=$SAVE_LIBS
diff --git a/contrib/defaults.conf b/contrib/defaults.conf
index 621230c73..5c54b362b 100644
--- a/contrib/defaults.conf
+++ b/contrib/defaults.conf
@@ -82,6 +82,8 @@ ACCEPT_FROM = 127.0.0.1;
ACCEPT_FROM6 = ::1;
DEFAULTSERVICES = topology hostlist
UNIXPATH = /tmp/gnunet-service-arm.sock
+UNIX_MATCH_UID = YES
+UNIX_MATCH_GID = YES
# GLOBAL_POSTFIX = -l $SERVICEHOME/{}-logs
# GLOBAL_PREFIX =
# USERNAME =
@@ -103,6 +105,8 @@ BINARY = gnunet-service-statistics
ACCEPT_FROM = 127.0.0.1;
ACCEPT_FROM6 = ::1;
UNIXPATH = /tmp/gnunet-service-statistics.sock
+UNIX_MATCH_UID = NO
+UNIX_MATCH_GID = YES
# DISABLE_SOCKET_FORWARDING = NO
# USERNAME =
# MAXBUF =
@@ -123,6 +127,8 @@ BINARY = gnunet-service-resolver
ACCEPT_FROM = 127.0.0.1;
ACCEPT_FROM6 = ::1;
UNIXPATH = /tmp/gnunet-service-resolver.sock
+UNIX_MATCH_UID = NO
+UNIX_MATCH_GID = NO
# DISABLE_SOCKET_FORWARDING = NO
# USERNAME =
# MAXBUF =
@@ -143,6 +149,8 @@ BINARY = gnunet-service-peerinfo
ACCEPT_FROM = 127.0.0.1;
ACCEPT_FROM6 = ::1;
UNIXPATH = /tmp/gnunet-service-peerinfo.sock
+UNIX_MATCH_UID = NO
+UNIX_MATCH_GID = YES
# DISABLE_SOCKET_FORWARDING = NO
# USERNAME =
# MAXBUF =
@@ -168,6 +176,8 @@ ACCEPT_FROM6 = ::1;
PLUGINS = tcp
UNIXPATH = /tmp/gnunet-service-transport.sock
BLACKLIST_FILE = $SERVICEHOME/blacklist
+UNIX_MATCH_UID = YES
+UNIX_MATCH_GID = YES
# DISABLE_SOCKET_FORWARDING = NO
# USERNAME =
# MAXBUF =
@@ -191,6 +201,8 @@ ACCEPT_FROM6 = ::1;
TOTAL_QUOTA_IN = 65536
TOTAL_QUOTA_OUT = 65536
UNIXPATH = /tmp/gnunet-service-core.sock
+UNIX_MATCH_UID = YES
+UNIX_MATCH_GID = YES
# DISABLE_SOCKET_FORWARDING = NO
# DEBUG = YES
# USERNAME =
@@ -229,6 +241,8 @@ HTTP-PROXY =
[datastore]
AUTOSTART = YES
UNIXPATH = /tmp/gnunet-service-datastore.sock
+UNIX_MATCH_UID = YES
+UNIX_MATCH_GID = YES
PORT = 2093
HOSTNAME = localhost
HOME = $SERVICEHOME
@@ -283,6 +297,8 @@ CONTENT_CACHING = YES
CONTENT_PUSHING = YES
UNIXPATH = /tmp/gnunet-service-fs.sock
+UNIX_MATCH_UID = NO
+UNIX_MATCH_GID = YES
# DISABLE_SOCKET_FORWARDING = NO
# DEBUG = YES
MAX_PENDING_REQUESTS = 65536
@@ -303,6 +319,8 @@ ACCEPT_FROM = 127.0.0.1;
ACCEPT_FROM6 = ::1;
BUCKET_SIZE = 4
UNIXPATH = /tmp/gnunet-service-dht.sock
+UNIX_MATCH_UID = YES
+UNIX_MATCH_GID = YES
# DISABLE_SOCKET_FORWARDING = NO
# DEBUG = YES
# USERNAME =
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;
/**
+ * Credentials for UNIX domain sockets.
+ */
+struct GNUNET_CONNECTION_Credentials
+{
+ /**
+ * UID of the other end of the connection.
+ */
+ uid_t uid;
+
+ /**
+ * GID of the other end of the connection.
+ */
+ gid_t gid;
+};
+
+
+/**
* Function to call for access control checks.
*
* @param cls closure
+ * @param ucred credentials, if available, otherwise NULL
* @param addr address
* @param addrlen length of address
* @return GNUNET_YES to allow, GNUNET_NO to deny, GNUNET_SYSERR
* for unknown address family (will be denied).
*/
typedef int (*GNUNET_CONNECTION_AccessCheck) (void *cls,
+ const struct GNUNET_CONNECTION_Credentials *ucred,
const struct sockaddr * addr,
socklen_t addrlen);
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,
void GNUNET_NETWORK_fdset_copy (struct GNUNET_NETWORK_FDSet *to,
const struct GNUNET_NETWORK_FDSet *from);
+
/**
* Return file descriptor for this network handle
*
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 @@
#include <sys/loadavg.h>
#include <semaphore.h>
#endif
+#if HAVE_UCRED_H
+#include <ucred.h>
+#endif
#ifdef CYGWIN
#include <windows.h>
#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,
struct sockaddr_in6 *v6;
struct sockaddr *sa;
void *uaddr;
+ struct GNUNET_CONNECTION_Credentials *gcp;
+ struct GNUNET_CONNECTION_Credentials gc;
+#ifdef SO_PEERCRED
+ struct ucred uc;
+ socklen_t olen;
+#endif
addrlen = sizeof (addr);
sock =
@@ -384,9 +390,50 @@ GNUNET_CONNECTION_create_from_accept (GNUNET_CONNECTION_AccessCheck access,
uaddr = GNUNET_malloc (addrlen);
memcpy (uaddr, addr, addrlen);
}
+ gcp = NULL;
+ gc.uid = 0;
+ gc.gid = 0;
+ if (sa->sa_family == AF_UNIX)
+ {
+#if HAVE_GETPEEREID
+ /* most BSDs */
+ if (0 == getpeereid (GNUNET_NETWORK_get_fd (sock),
+ &gc.uid,
+ &gc.gid))
+ gcp = &gc;
+#else
+#ifdef SO_PEERCRED
+ /* largely traditional GNU/Linux */
+ olen = sizeof (uc);
+ if ( (0 ==
+ getsockopt (GNUNET_NETWORK_get_fd (sock),
+ SOL_SOCKET, SO_PEERCRED, &uc, &olen)) &&
+ (olen == sizeof (uc)) )
+ {
+ gc.uid = uc.uid;
+ gc.gid = uc.gid;
+ gcp = &gc;
+ }
+#else
+#if HAVE_GETPEERUCRED
+ /* this is for Solaris 10 */
+ ucred_t *uc;
+
+ uc = NULL;
+ if (0 == getpeerucred (GNUNET_NETWORK_get_fd (sock), &uc))
+ {
+ gc.uid = ucred_geteuid (uc);
+ gc.gid = ucred_getegid (uc);
+ gcp = &gc;
+ }
+ ucred_free (uc);
+#endif
+#endif
+#endif
+ }
if ((access != NULL) &&
- (GNUNET_YES != (aret = access (access_cls, uaddr, addrlen))))
+ (GNUNET_YES != (aret = access (access_cls, gcp, uaddr, addrlen))))
{
if (aret == GNUNET_NO)
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
return GNUNET_NO;
}
+
/**
* Read data from a connected socket (always non-blocking).
* @param desc socket
@@ -774,12 +775,20 @@ GNUNET_NETWORK_fdset_copy (struct GNUNET_NETWORK_FDSet *to,
#endif
}
+
+/**
+ * Return file descriptor for this network handle
+ *
+ * @param desc wrapper to process
+ * @return POSIX file descriptor
+ */
int
GNUNET_NETWORK_get_fd (struct GNUNET_NETWORK_Handle *desc)
{
return desc->fd;
}
+
/**
* Copy a native fd set
*
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
int require_found;
/**
+ * Do we require a matching UID for UNIX domain socket
+ * connections?
+ */
+ int match_uid;
+
+ /**
+ * Do we require a matching GID for UNIX domain socket
+ * connections?
+ */
+ int match_gid;
+
+ /**
* Our options.
*/
enum GNUNET_SERVICE_Options options;
@@ -579,9 +591,18 @@ static const struct GNUNET_SERVER_MessageHandler defhandlers[] = {
/**
* Check if access to the service is allowed from the given address.
+ *
+ * @param cls closure
+ * @param uc credentials, if available, otherwise NULL
+ * @param addr address
+ * @param addrlen length of address
+ * @return GNUNET_YES to allow, GNUNET_NO to deny, GNUNET_SYSERR
+ * for unknown address family (will be denied).
*/
static int
-check_access (void *cls, const struct sockaddr *addr, socklen_t addrlen)
+check_access (void *cls,
+ const struct GNUNET_CONNECTION_Credentials *uc,
+ const struct sockaddr *addr, socklen_t addrlen)
{
struct GNUNET_SERVICE_Context *sctx = cls;
const struct sockaddr_in *i4;
@@ -609,8 +630,23 @@ check_access (void *cls, const struct sockaddr *addr, socklen_t addrlen)
(!check_ipv6_listed (sctx->v6_denied, &i6->sin6_addr)));
break;
case AF_UNIX:
- /* FIXME: support checking UID/GID in the future... */
ret = GNUNET_OK; /* always OK for now */
+ if ( (sctx->match_uid == GNUNET_YES) ||
+ (sctx->match_gid == GNUNET_YES) )
+ ret = GNUNET_NO;
+ if ( (uc != NULL) &&
+ ( (sctx->match_uid != GNUNET_YES) ||
+ (uc->uid == geteuid()) ||
+ (uc->uid == getuid()) ) &&
+ ( (sctx->match_gid != GNUNET_YES) ||
+ (uc->gid == getegid()) ||
+ (uc->gid == getgid())) )
+ ret = GNUNET_YES;
+ else
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ _("Access denied to UID %d / GID %d\n"),
+ (uc == NULL) ? -1 : uc->uid,
+ (uc == NULL) ? -1 : uc->gid);
break;
default:
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
@@ -1187,7 +1223,12 @@ setup_service (struct GNUNET_SERVICE_Context *sctx)
&sctx->addrlens)) )
return GNUNET_SYSERR;
sctx->require_found = tolerant ? GNUNET_NO : GNUNET_YES;
-
+ sctx->match_uid = GNUNET_CONFIGURATION_get_value_yesno (sctx->cfg,
+ sctx->serviceName,
+ "UNIX_MATCH_UID");
+ sctx->match_gid = GNUNET_CONFIGURATION_get_value_yesno (sctx->cfg,
+ sctx->serviceName,
+ "UNIX_MATCH_GID");
process_acl4 (&sctx->v4_denied, sctx, "REJECT_FROM");
process_acl4 (&sctx->v4_allowed, sctx, "ACCEPT_FROM");
process_acl6 (&sctx->v6_denied, sctx, "REJECT_FROM6");