summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSree Harsha Totakura <totakura@in.tum.de>2014-02-09 21:54:56 +0000
committerSree Harsha Totakura <totakura@in.tum.de>2014-02-09 21:54:56 +0000
commit8a6d5d56ba09ddd8a8848bae490b84ef3ea2923d (patch)
treebf6550e218666d2df51dd02bf185298b2ab4cf03
parent09104d9e153cfce464ef38cda9ccbba4b029ae11 (diff)
Create UNIX domain sockets as abstract sockets when running in LINUX and the
option USE_ABSTRACT_SOCKETS is present in configuration.
-rw-r--r--src/transport/plugin_transport_unix.c22
-rw-r--r--src/util/client.c17
-rw-r--r--src/util/connection.c10
-rw-r--r--src/util/network.c29
-rw-r--r--src/util/service.c37
-rw-r--r--src/util/util.conf5
6 files changed, 97 insertions, 23 deletions
diff --git a/src/transport/plugin_transport_unix.c b/src/transport/plugin_transport_unix.c
index 56e1de426..6c0a02e2c 100644
--- a/src/transport/plugin_transport_unix.c
+++ b/src/transport/plugin_transport_unix.c
@@ -384,7 +384,8 @@ unix_address_to_string (void *cls, const void *addr, size_t addrlen)
static struct sockaddr_un *
-unix_address_to_sockaddr (const char *unixpath,
+unix_address_to_sockaddr (const struct GNUNET_CONFIGURATION_Handle *cfg,
+ const char *unixpath,
socklen_t *sock_len)
{
struct sockaddr_un *un;
@@ -398,6 +399,17 @@ unix_address_to_sockaddr (const char *unixpath,
slen = sizeof (un->sun_path) - 1;
memcpy (un->sun_path, unixpath, slen);
un->sun_path[slen] = '\0';
+#ifdef LINUX
+ {
+ int abstract;
+
+ abstract = GNUNET_CONFIGURATION_get_value_yesno (cfg,
+ "TESTING",
+ "USE_ABSTRACT_SOCKETS");
+ if (GNUNET_YES == abstract)
+ un->sun_path[0] = '\0';
+ }
+#endif
slen = sizeof (struct sockaddr_un);
#if HAVE_SOCKADDR_IN_SIN_LEN
un->sun_len = (u_char) slen;
@@ -633,7 +645,9 @@ unix_real_send (void *cls,
/* Prepare address */
unixpath = (const char *) &addr[1];
- if (NULL == (un = unix_address_to_sockaddr (unixpath, &un_len)))
+ if (NULL == (un = unix_address_to_sockaddr (plugin->env->cfg,
+ unixpath,
+ &un_len)))
{
GNUNET_break (0);
return -1;
@@ -1252,7 +1266,9 @@ unix_transport_server_start (void *cls)
struct sockaddr_un *un;
socklen_t un_len;
- un = unix_address_to_sockaddr (plugin->unix_socket_path, &un_len);
+ un = unix_address_to_sockaddr (plugin->env->cfg,
+ plugin->unix_socket_path,
+ &un_len);
plugin->ats_network = plugin->env->get_address_type (plugin->env->cls, (const struct sockaddr *) un, un_len);
plugin->unix_sock.desc =
GNUNET_NETWORK_socket_create (AF_UNIX, SOCK_DGRAM, 0);
diff --git a/src/util/client.c b/src/util/client.c
index ea3cc45f4..02bec5a8f 100644
--- a/src/util/client.c
+++ b/src/util/client.c
@@ -842,6 +842,7 @@ GNUNET_CLIENT_service_test (const char *service,
/* probe UNIX support */
struct sockaddr_un s_un;
char *unixpath;
+ int abstract;
unixpath = NULL;
if ((GNUNET_OK ==
@@ -862,17 +863,29 @@ GNUNET_CLIENT_service_test (const char *service,
_("Using `%s' instead\n"), unixpath);
}
}
- if (NULL != unixpath)
+#ifdef LINUX
+ abstract = GNUNET_CONFIGURATION_get_value_yesno (cfg,
+ "TESTING",
+ "USE_ABSTRACT_SOCKETS");
+#else
+ abstract = GNUNET_NO;
+#endif
+ if ((NULL != unixpath) && (GNUNET_YES != abstract))
{
if (GNUNET_SYSERR == GNUNET_DISK_directory_create_for_file (unixpath))
GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
- "mkdir", unixpath);
+ "mkdir", unixpath);
+ }
+ if (NULL != unixpath)
+ {
sock = GNUNET_NETWORK_socket_create (PF_UNIX, SOCK_STREAM, 0);
if (NULL != sock)
{
memset (&s_un, 0, sizeof (s_un));
s_un.sun_family = AF_UNIX;
strncpy (s_un.sun_path, unixpath, sizeof (s_un.sun_path) - 1);
+ if (GNUNET_YES == abstract)
+ s_un.sun_path[0] = '\0';
#if HAVE_SOCKADDR_IN_SIN_LEN
s_un.sun_len = (u_char) sizeof (struct sockaddr_un);
#endif
diff --git a/src/util/connection.c b/src/util/connection.c
index 39dad12c3..fb20617fd 100644
--- a/src/util/connection.c
+++ b/src/util/connection.c
@@ -832,6 +832,16 @@ GNUNET_CONNECTION_create_from_connect_to_unixpath (const struct
un = GNUNET_new (struct sockaddr_un);
un->sun_family = AF_UNIX;
strncpy (un->sun_path, unixpath, sizeof (un->sun_path) - 1);
+#ifdef LINUX
+ {
+ int abstract;
+
+ abstract = GNUNET_CONFIGURATION_get_value_yesno (cfg, "TESTING",
+ "USE_ABSTRACT_SOCKETS");
+ if (GNUNET_YES == abstract)
+ un->sun_path[0] = '\0';
+ }
+#endif
#if HAVE_SOCKADDR_IN_SIN_LEN
un->sun_len = (u_char) sizeof (struct sockaddr_un);
#endif
diff --git a/src/util/network.c b/src/util/network.c
index 2ee1a73a0..d321a7009 100644
--- a/src/util/network.c
+++ b/src/util/network.c
@@ -420,17 +420,23 @@ GNUNET_NETWORK_socket_bind (struct GNUNET_NETWORK_Handle *desc,
#endif
#ifndef WINDOWS
{
- /* set permissions of newly created UNIX domain socket to "user-only"; applications
- can choose to relax this later */
+ /* set permissions of newly created non-abstract UNIX domain socket to
+ "user-only"; applications can choose to relax this later */
mode_t old_mask = 0; /* assigned to make compiler happy */
-
- if (AF_UNIX == address->sa_family)
+ const struct sockaddr_un *un;
+ int not_abstract = 0;
+
+ if ((AF_UNIX == address->sa_family)
+ && (NULL != (un = (const struct sockaddr_un *) address)->sun_path)
+ && ('\0' != un->sun_path[0]) ) /* Not an abstract socket */
+ not_abstract = 1;
+ if (not_abstract)
old_mask = umask (S_IWGRP | S_IRGRP | S_IXGRP | S_IWOTH | S_IROTH | S_IXOTH);
#endif
ret = bind (desc->fd, address, address_len);
#ifndef WINDOWS
- if (AF_UNIX == address->sa_family)
+ if (not_abstract)
(void) umask (old_mask);
}
#endif
@@ -460,7 +466,7 @@ GNUNET_NETWORK_socket_close (struct GNUNET_NETWORK_Handle *desc)
{
int ret;
-#ifdef MINGW
+#ifdef WINDOWS
DWORD error = 0;
SetLastError (0);
@@ -473,10 +479,15 @@ GNUNET_NETWORK_socket_close (struct GNUNET_NETWORK_Handle *desc)
#else
ret = close (desc->fd);
#endif
-#ifndef MINGW
- if ((desc->af == AF_UNIX) && (NULL != desc->addr))
+#ifndef WINDOWS
+ const struct sockaddr_un *un;
+
+ /* Cleanup the UNIX domain socket and its parent directories in case of non
+ abstract sockets */
+ if ((AF_UNIX == desc->af) && (NULL != desc->addr)
+ && (NULL != (un = (const struct sockaddr_un *) desc->addr)->sun_path)
+ && ('\0' != un->sun_path[0]))
{
- const struct sockaddr_un *un = (const struct sockaddr_un *) desc->addr;
char *dirname = GNUNET_strndup (un->sun_path,
sizeof (un->sun_path));
diff --git a/src/util/service.c b/src/util/service.c
index c03247a6d..deb0be46b 100644
--- a/src/util/service.c
+++ b/src/util/service.c
@@ -475,10 +475,13 @@ process_acl6 (struct GNUNET_STRINGS_IPv6NetworkPolicy **ret, struct GNUNET_SERVI
* @param saddrs array to update
* @param saddrlens where to store the address length
* @param unixpath path to add
+ * @param abstract GNUNET_YES to add an abstract UNIX domain socket. This
+ * parameter is ignore on systems other than LINUX
*/
static void
add_unixpath (struct sockaddr **saddrs, socklen_t * saddrlens,
- const char *unixpath)
+ const char *unixpath,
+ int abstract)
{
#ifdef AF_UNIX
struct sockaddr_un *un;
@@ -486,6 +489,10 @@ add_unixpath (struct sockaddr **saddrs, socklen_t * saddrlens,
un = GNUNET_new (struct sockaddr_un);
un->sun_family = AF_UNIX;
strncpy (un->sun_path, unixpath, sizeof (un->sun_path) - 1);
+#ifdef LINUX
+ if (GNUNET_YES == abstract)
+ un->sun_path[0] = '\0';
+#endif
#if HAVE_SOCKADDR_IN_SIN_LEN
un->sun_len = (u_char) sizeof (struct sockaddr_un);
#endif
@@ -536,6 +543,7 @@ GNUNET_SERVICE_get_server_addresses (const char *service_name,
unsigned int i;
int resi;
int ret;
+ int abstract;
struct sockaddr **saddrs;
socklen_t *saddrlens;
char *hostname;
@@ -608,6 +616,7 @@ GNUNET_SERVICE_get_server_addresses (const char *service_name,
hostname = NULL;
unixpath = NULL;
+ abstract = GNUNET_NO;
#ifdef AF_UNIX
if ((GNUNET_YES ==
GNUNET_CONFIGURATION_have_value (cfg, service_name, "UNIXPATH")) &&
@@ -628,8 +637,16 @@ GNUNET_SERVICE_get_server_addresses (const char *service_name,
LOG (GNUNET_ERROR_TYPE_INFO,
_("Using `%s' instead\n"), unixpath);
}
- if (GNUNET_OK !=
- GNUNET_DISK_directory_create_for_file (unixpath))
+#ifdef LINUX
+ abstract = GNUNET_CONFIGURATION_get_value_yesno (cfg,
+ "TESTING",
+ "USE_ABSTRACT_SOCKETS");
+ if (GNUNET_SYSERR == abstract)
+ abstract = GNUNET_NO;
+#endif
+ if ((GNUNET_YES != abstract)
+ && (GNUNET_OK !=
+ GNUNET_DISK_directory_create_for_file (unixpath)))
GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
"mkdir",
unixpath);
@@ -673,7 +690,7 @@ GNUNET_SERVICE_get_server_addresses (const char *service_name,
{
saddrs = GNUNET_malloc (2 * sizeof (struct sockaddr *));
saddrlens = GNUNET_malloc (2 * sizeof (socklen_t));
- add_unixpath (saddrs, saddrlens, unixpath);
+ add_unixpath (saddrs, saddrlens, unixpath, abstract);
GNUNET_free_non_null (unixpath);
GNUNET_free_non_null (hostname);
*addrs = saddrs;
@@ -725,7 +742,7 @@ GNUNET_SERVICE_get_server_addresses (const char *service_name,
i = 0;
if (NULL != unixpath)
{
- add_unixpath (saddrs, saddrlens, unixpath);
+ add_unixpath (saddrs, saddrlens, unixpath, abstract);
i++;
}
next = res;
@@ -777,7 +794,7 @@ GNUNET_SERVICE_get_server_addresses (const char *service_name,
saddrlens = GNUNET_malloc ((resi + 1) * sizeof (socklen_t));
if (NULL != unixpath)
{
- add_unixpath (saddrs, saddrlens, unixpath);
+ add_unixpath (saddrs, saddrlens, unixpath, abstract);
i++;
}
saddrlens[i] = sizeof (struct sockaddr_in);
@@ -799,7 +816,7 @@ GNUNET_SERVICE_get_server_addresses (const char *service_name,
i = 0;
if (NULL != unixpath)
{
- add_unixpath (saddrs, saddrlens, unixpath);
+ add_unixpath (saddrs, saddrlens, unixpath, abstract);
i++;
}
saddrlens[i] = sizeof (struct sockaddr_in6);
@@ -1168,7 +1185,8 @@ service_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
#ifndef WINDOWS
if (NULL != sctx->addrs)
for (i = 0; NULL != sctx->addrs[i]; i++)
- if (AF_UNIX == sctx->addrs[i]->sa_family)
+ if ((AF_UNIX == sctx->addrs[i]->sa_family)
+ && ('\0' != ((const struct sockaddr_un *)sctx->addrs[i])->sun_path[0]))
GNUNET_DISK_fix_permissions (((const struct sockaddr_un *)sctx->addrs[i])->sun_path,
sctx->match_uid,
sctx->match_gid);
@@ -1589,7 +1607,8 @@ GNUNET_SERVICE_start (const char *service_name,
#ifndef WINDOWS
if (NULL != sctx->addrs)
for (i = 0; NULL != sctx->addrs[i]; i++)
- if (AF_UNIX == sctx->addrs[i]->sa_family)
+ if ((AF_UNIX == sctx->addrs[i]->sa_family)
+ && ('\0' != ((const struct sockaddr_un *)sctx->addrs[i])->sun_path[0]))
GNUNET_DISK_fix_permissions (((const struct sockaddr_un *)sctx->addrs[i])->sun_path,
sctx->match_uid,
sctx->match_gid);
diff --git a/src/util/util.conf b/src/util/util.conf
index 3df538f5d..1627b068a 100644
--- a/src/util/util.conf
+++ b/src/util/util.conf
@@ -49,3 +49,8 @@ PRIVATE_KEY = $GNUNET_DATA_HOME/private_key.ecc
[TESTING]
SPEEDUP_INTERVAL = 0 ms
SPEEDUP_DELTA = 0 ms
+# This following option is applicable to LINUX. Enabling this option causes all
+# UNIX domain sockets to be opened as abstract sockets. Note that the
+# filesystem level restrictions no longer apply for abstract sockets. An
+# end-user should not modify this option.
+USE_ABSTRACT_SOCKETS = NO