View Issue Details

IDProjectCategoryView StatusLast Update
0002887GNUnetutil librarypublic2013-12-24 20:54
Reporterhelmut Assigned ToChristian Grothoff  
PrioritylowSeverityfeatureReproducibilityalways
Status closedResolutionfixed 
PlatformLinux 
Product VersionGit master 
Target Version0.10.0Fixed in Version0.10.0 
Summary0002887: use regular unix sockets instead of abstract unix sockets
DescriptionThe current way to expose services locally is via abstract unix sockets. No permission checks are done by the kernel when connecting to such sockets, so gnunet currently does these itself (util/service.c: check_access). It checks against PAM, but not the actual auxiliary groups of the connecting user, because it cannot know them. This can be counterintuitive when the groups command reports a gnunet group membership, but the service rejects the connection.

The proposed alternative is to use pathname unix sockets. They should be relative to SERVICEHOME. During creation umask should be used to enforce proper permission on them. Benefits of this approach:

 * The kernel checks permission. Large parts of check_access can be discarded from gnunet.
 * Having sockets relative to SERVICEHOME eliminates the need to configure socket paths even when running multiple peers on the same host.
 * Abstract sockets are not portable beyond Linux. This is why gnunet supports TCP sockets for local communication as well. Using pathname unix sockets is portable on BSDish systems.

Downsides:

 * SERVICEHOME currently defaults to 700 and some files therein are world readable. So SERVICEHOME would need at least permission 711 exposing the files bona tined. All file creation utilities therefore would need an audit.
Steps To ReproduceRun newgrp gnunet. Observe that the spawned sub shell is able to access gnunet services. Run newgrp othergroup from that sub shell. Observe that the spawned sub sub shell is a member of gnunet. Observe that it is unable to access gnunet services.
TagsNo tags attached.
Attached Files
trim_abstract_socket_paths.diff (2,078 bytes)   
Index: src/util/network.c
===================================================================
--- src/util/network.c	(revision 29604)
+++ src/util/network.c	(working copy)
@@ -393,7 +393,21 @@
                             int flags)
 {
   int ret;
+  socklen_t bind_address_len = address_len;
 
+#ifdef LINUX
+  if (address->sa_family == AF_UNIX)
+  {
+    const struct sockaddr_un *address_un = (const struct sockaddr_un *)address;
+    if (address_un->sun_path[0] == '\0')
+      bind_address_len = \
+          sizeof (struct sockaddr_un) \
+        - sizeof (address_un->sun_path) \
+        + strnlen (address_un->sun_path + 1, sizeof (address_un->sun_path) - 1) \
+        + 1;
+  }
+#endif
+
 #ifdef IPV6_V6ONLY
 #ifdef IPPROTO_IPV6
   {
@@ -427,7 +441,7 @@
   }
 #endif
 #endif
-  ret = bind (desc->fd, address, address_len);
+  ret = bind (desc->fd, address, bind_address_len);
 #ifdef MINGW
   if (SOCKET_ERROR == ret)
     SetErrnoFromWinsockError (WSAGetLastError ());
@@ -544,6 +558,18 @@
 {
   int ret;
 
+#ifdef LINUX
+  if (address->sa_family == AF_UNIX)
+  {
+    const struct sockaddr_un *address_un = (const struct sockaddr_un *)address;
+    if(address_un->sun_path[0] == '\0')
+      address_len = \
+          sizeof (struct sockaddr_un) \
+        - sizeof (address_un->sun_path) \
+        + strnlen (address_un->sun_path + 1, sizeof (address_un->sun_path) - 1) \
+        + 1;
+  }
+#endif
   ret = connect (desc->fd, address, address_len);
 
 #ifdef MINGW
@@ -768,6 +794,18 @@
 #ifdef MSG_NOSIGNAL
   flags |= MSG_NOSIGNAL;
 #endif
+#ifdef LINUX
+  if (dest_addr->sa_family == AF_UNIX)
+  {
+    const struct sockaddr_un *dest_addr_un = (const struct sockaddr_un *)dest_addr;
+    if (dest_addr_un->sun_path[0] == '\0')
+      dest_len = \
+          sizeof (struct sockaddr) \
+        - sizeof (dest_addr_un->sun_path) \
+        + strnlen (dest_addr_un->sun_path + 1, sizeof (dest_addr_un->sun_path) - 1) \
+        + 1;
+  }
+#endif
   ret = sendto (desc->fd, message, length, flags, dest_addr, dest_len);
 #ifdef MINGW
   if (SOCKET_ERROR == ret)
dont_drop_first_character_of_abstract_socket_path.diff (6,908 bytes)   
Index: src/transport/plugin_transport_unix.c
===================================================================
--- src/transport/plugin_transport_unix.c	(revision 29604)
+++ src/transport/plugin_transport_unix.c	(working copy)
@@ -572,7 +572,6 @@
   const void *sb;
   size_t sbs;
   struct sockaddr_un un;
-  size_t slen;
   const char *unix_path;
 
 
@@ -592,21 +591,16 @@
   unix_path = (const char *)  &addr[1];
   memset (&un, 0, sizeof (un));
   un.sun_family = AF_UNIX;
-  slen =  strlen (unix_path);
-  if (slen >= sizeof (un.sun_path))
-    slen = sizeof (un.sun_path) - 1;
-  GNUNET_assert (slen < sizeof (un.sun_path));
-  memcpy (un.sun_path, unix_path, slen);
-  un.sun_path[slen] = '\0';
-  slen = sizeof (struct sockaddr_un);
 #if LINUX
-  un.sun_path[0] = '\0';
+  strncpy (un.sun_path + 1, unix_path, sizeof (un.sun_path) - 2);
+#else
+  strncpy (un.sun_path, unix_path, sizeof (un.sun_path) - 1);
 #endif
 #if HAVE_SOCKADDR_IN_SIN_LEN
-  un.sun_len = (u_char) slen;
+  un.sun_len = (u_char) sizeof (struct sockaddr_un);
 #endif
   sb = (struct sockaddr *) &un;
-  sbs = slen;
+  sbs = sizeof (struct sockaddr_un);
 
 resend:
   /* Send the data */
@@ -1223,26 +1217,21 @@
   struct sockaddr *serverAddr;
   socklen_t addrlen;
   struct sockaddr_un un;
-  size_t slen;
 
   memset (&un, 0, sizeof (un));
   un.sun_family = AF_UNIX;
-  slen = strlen (plugin->unix_socket_path) + 1;
-  if (slen >= sizeof (un.sun_path))
-    slen = sizeof (un.sun_path) - 1;
+#if LINUX
+  strncpy (un.sun_path + 1, plugin->unix_socket_path, sizeof (un.sun_path) - 2);
+#else
+  strncpy (un.sun_path, plugin->unix_socket_path, sizeof (un.sun_path) - 1);
+#endif
 
-  memcpy (un.sun_path, plugin->unix_socket_path, slen);
-  un.sun_path[slen] = '\0';
-  slen = sizeof (struct sockaddr_un);
 #if HAVE_SOCKADDR_IN_SIN_LEN
-  un.sun_len = (u_char) slen;
+  un.sun_len = (u_char) sizeof (struct sockaddr_un);
 #endif
 
   serverAddr = (struct sockaddr *) &un;
-  addrlen = slen;
-#if LINUX
-  un.sun_path[0] = '\0';
-#endif
+  addrlen = sizeof (struct sockaddr_un);
   plugin->ats_network = plugin->env->get_address_type (plugin->env->cls, serverAddr, addrlen);
   plugin->unix_sock.desc =
       GNUNET_NETWORK_socket_create (AF_UNIX, SOCK_DGRAM, 0);
Index: src/util/client.c
===================================================================
--- src/util/client.c	(revision 29604)
+++ src/util/client.c	(working copy)
@@ -829,7 +829,6 @@
   {
     /* probe UNIX support */
     struct sockaddr_un s_un;
-    size_t slen;
     char *unixpath;
 
     unixpath = NULL;
@@ -852,21 +851,17 @@
       {
 	memset (&s_un, 0, sizeof (s_un));
 	s_un.sun_family = AF_UNIX;
-	slen = strlen (unixpath) + 1;
-	if (slen >= sizeof (s_un.sun_path))
-	  slen = sizeof (s_un.sun_path) - 1;
-	memcpy (s_un.sun_path, unixpath, slen);
-	s_un.sun_path[slen] = '\0';
-	slen = sizeof (struct sockaddr_un);
 #if LINUX
-	s_un.sun_path[0] = '\0';
+        strncpy (s_un.sun_path + 1, unixpath, sizeof (s_un.sun_path) - 2);
+#else
+        strncpy (s_un.sun_path, unixpath, sizeof (s_un.sun_path) - 1);
 #endif
 #if HAVE_SOCKADDR_IN_SIN_LEN
-	s_un.sun_len = (u_char) slen;
+        s_un.sun_len = (u_char) sizeof (struct sockaddr_un);
 #endif
 	if (GNUNET_OK !=
 	    GNUNET_NETWORK_socket_bind (sock, (const struct sockaddr *) &s_un,
-					slen, GNUNET_BIND_EXCLUSIVE))
+					sizeof (struct sockaddr_un), GNUNET_BIND_EXCLUSIVE))
         {
 	  /* failed to bind => service must be running */
 	  GNUNET_free (unixpath);
Index: src/util/connection.c
===================================================================
--- src/util/connection.c	(revision 29604)
+++ src/util/connection.c	(working copy)
@@ -828,23 +828,18 @@
 #ifdef AF_UNIX
   struct GNUNET_CONNECTION_Handle *connection;
   struct sockaddr_un *un;
-  size_t slen;
 
   GNUNET_assert (0 < strlen (unixpath));        /* sanity check */
   un = GNUNET_new (struct sockaddr_un);
   un->sun_family = AF_UNIX;
-  slen = strlen (unixpath);
-  if (slen >= sizeof (un->sun_path))
-    slen = sizeof (un->sun_path) - 1;
-  memcpy (un->sun_path, unixpath, slen);
-  un->sun_path[slen] = '\0';
-  slen = sizeof (struct sockaddr_un);
+#if LINUX
+  strncpy(un->sun_path + 1, unixpath, sizeof(un->sun_path) - 2);
+#else
+  strncpy(un->sun_path, unixpath, sizeof(un->sun_path) - 1);
+#endif
 #if HAVE_SOCKADDR_IN_SIN_LEN
-  un->sun_len = (u_char) slen;
+  un->sun_len = (u_char) sizeof (struct sockaddr_un);
 #endif
-#if LINUX
-  un->sun_path[0] = '\0';
-#endif
   connection = GNUNET_new (struct GNUNET_CONNECTION_Handle);
   connection->cfg = cfg;
   connection->write_buffer_size = GNUNET_SERVER_MIN_BUFFER_SIZE;
@@ -852,7 +847,7 @@
   connection->port = 0;
   connection->hostname = NULL;
   connection->addr = (struct sockaddr *) un;
-  connection->addrlen = slen;
+  connection->addrlen = sizeof (struct sockaddr_un);
   connection->sock = GNUNET_NETWORK_socket_create (AF_UNIX, SOCK_STREAM, 0);
   if (NULL == connection->sock)
   {
Index: src/util/service.c
===================================================================
--- src/util/service.c	(revision 29604)
+++ src/util/service.c	(working copy)
@@ -841,24 +841,19 @@
 {
 #ifdef AF_UNIX
   struct sockaddr_un *un;
-  size_t slen;
 
   un = GNUNET_malloc (sizeof (struct sockaddr_un));
   un->sun_family = AF_UNIX;
-  slen = strlen (unixpath) + 1;
-  if (slen >= sizeof (un->sun_path))
-    slen = sizeof (un->sun_path) - 1;
-  memcpy (un->sun_path, unixpath, slen);
-  un->sun_path[slen] = '\0';
-  slen = sizeof (struct sockaddr_un);
 #if LINUX
-  un->sun_path[0] = '\0';
+  strncpy (un->sun_path + 1, unixpath, sizeof (un->sun_path) - 2);
+#else
+  strncpy (un->sun_path, unixpath, sizeof (un->sun_path) - 1);
 #endif
 #if HAVE_SOCKADDR_IN_SIN_LEN
-  un->sun_len = (u_char) slen;
+  un->sun_len = (u_char) sizeof (struct sockaddr_un);
 #endif
   *saddrs = (struct sockaddr *) un;
-  *saddrlens = slen;
+  *saddrlens = sizeof (struct sockaddr_un);
 #else
   /* this function should never be called
    * unless AF_UNIX is defined! */
Index: src/util/test_server_with_client_unix.c
===================================================================
--- src/util/test_server_with_client_unix.c	(revision 29604)
+++ src/util/test_server_with_client_unix.c	(working copy)
@@ -134,20 +134,19 @@
 {
   struct sockaddr_un un;
   const char *unixpath = "/tmp/testsock";
-  size_t slen = strlen (unixpath);
   struct sockaddr *sap[2];
   socklen_t slens[2];
 
   memset (&un, 0, sizeof (un));
   un.sun_family = AF_UNIX;
-  memcpy (un.sun_path, unixpath, slen);
-  un.sun_path[slen] = '\0';
+#if LINUX
+  strncpy(un.sun_path + 1, unixpath, sizeof (un.sun_path) - 2);
+#else
+  strncpy(un.sun_path, unixpath, sizeof (un.sun_path) - 1);
+#endif
 #if HAVE_SOCKADDR_IN_SIN_LEN
   un.sun_len = (u_char) sizeof (un);
 #endif
-#if LINUX
-  un.sun_path[0] = '\0';
-#endif
 
   sap[0] = (struct sockaddr *) &un;
   slens[0] = sizeof (un);
29640.diff (37,863 bytes)   
Index: src/dns/dnsstub.c
===================================================================
--- src/dns/dnsstub.c	(revision 29640)
+++ src/dns/dnsstub.c	(revision 29639)
@@ -167,11 +167,11 @@
     return NULL;
   }
   sa->sa_family = af;
-  if (GNUNET_OK != 
-      GNUNET_NETWORK_socket_bind (ret,
-				  sa, 
-				  alen))
-    {
+  if (GNUNET_OK != GNUNET_NETWORK_socket_bind (ret,
+					       sa, 
+					       alen,
+                                               0))
+  {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 
 		_("Could not bind to any port: %s\n"),
 		STRERROR (errno));
Index: src/dns/dns.conf.in
===================================================================
--- src/dns/dns.conf.in	(revision 29640)
+++ src/dns/dns.conf.in	(revision 29639)
@@ -3,7 +3,7 @@
 HOSTNAME = localhost
 HOME = $SERVICEHOME
 BINARY = gnunet-service-dns
-UNIXPATH = $SERVICEHOME/gnunet-service-dns.sock
+UNIXPATH = /tmp/gnunet-service-dns.sock
 
 # Access to this service can compromise all DNS queries in this
 # system.  Thus access should be restricted to the same UID.
Index: src/datastore/datastore.conf.in
===================================================================
--- src/datastore/datastore.conf.in	(revision 29640)
+++ src/datastore/datastore.conf.in	(revision 29639)
@@ -1,6 +1,6 @@
 [datastore]
 AUTOSTART = YES
-UNIXPATH = $SERVICEHOME/gnunet-service-datastore.sock
+UNIXPATH = /tmp/gnunet-service-datastore.sock
 UNIX_MATCH_UID = NO
 UNIX_MATCH_GID = YES
 @UNIXONLY@ PORT = 2093
Index: src/gns/gns.conf.in
===================================================================
--- src/gns/gns.conf.in	(revision 29640)
+++ src/gns/gns.conf.in	(revision 29639)
@@ -3,7 +3,7 @@
 HOSTNAME = localhost
 HOME = $SERVICEHOME
 BINARY = gnunet-service-gns
-UNIXPATH = $SERVICEHOME/gnunet-service-gns.sock
+UNIXPATH = /tmp/gnunet-service-gns.sock
 @UNIXONLY@PORT = 2102
 
 ZONE_DIR = $SERVICEHOME/gns/
@@ -32,7 +32,7 @@
 
 # Where is the certificate for the GNS proxy stored?
 PROXY_CACERT = $SERVICEHOME/gns/gnsCAcert.pem
-PROXY_UNIXPATH = $SERVICEHOME/gnunet-gns-proxy.sock
+PROXY_UNIXPATH = /tmp/gnunet-gns-proxy.sock
 
 
 [fcfsd]
Index: src/gns/gnunet-dns2gns.c
===================================================================
--- src/gns/gnunet-dns2gns.c	(revision 29640)
+++ src/gns/gnunet-dns2gns.c	(revision 29639)
@@ -616,7 +616,8 @@
       if (GNUNET_OK !=
 	  GNUNET_NETWORK_socket_bind (listen_socket4,
 				      (struct sockaddr *) &v4,
-				      sizeof (v4)))
+				      sizeof (v4),
+                                      0))
 	{
 	  GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "bind");
 	  GNUNET_NETWORK_socket_close (listen_socket4);
@@ -639,7 +640,8 @@
       if (GNUNET_OK !=
 	  GNUNET_NETWORK_socket_bind (listen_socket6,
 				      (struct sockaddr *) &v6,
-				      sizeof (v6)))
+				      sizeof (v6),
+                                      0))
 	{
 	  GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "bind");
 	  GNUNET_NETWORK_socket_close (listen_socket6);
Index: src/ats/ats.conf.in
===================================================================
--- src/ats/ats.conf.in	(revision 29640)
+++ src/ats/ats.conf.in	(revision 29639)
@@ -6,7 +6,7 @@
 BINARY = gnunet-service-ats
 ACCEPT_FROM = 127.0.0.1;
 ACCEPT_FROM6 = ::1;
-UNIXPATH = $SERVICEHOME/gnunet-service-ats.sock
+UNIXPATH = /tmp/gnunet-service-ats.sock
 UNIX_MATCH_UID = YES
 UNIX_MATCH_GID = YES
 
Index: src/core/core.conf.in
===================================================================
--- src/core/core.conf.in	(revision 29640)
+++ src/core/core.conf.in	(revision 29639)
@@ -6,7 +6,7 @@
 BINARY = gnunet-service-core
 ACCEPT_FROM = 127.0.0.1;
 ACCEPT_FROM6 = ::1;
-UNIXPATH = $SERVICEHOME/gnunet-service-core.sock
+UNIXPATH = /tmp/gnunet-service-core.sock
 UNIX_MATCH_UID = YES
 UNIX_MATCH_GID = YES
 # DISABLE_SOCKET_FORWARDING = NO
Index: src/statistics/statistics.conf.in
===================================================================
--- src/statistics/statistics.conf.in	(revision 29640)
+++ src/statistics/statistics.conf.in	(revision 29639)
@@ -6,7 +6,7 @@
 BINARY = gnunet-service-statistics
 ACCEPT_FROM = 127.0.0.1;
 ACCEPT_FROM6 = ::1;
-UNIXPATH = $SERVICEHOME/gnunet-service-statistics.sock
+UNIXPATH = /tmp/gnunet-service-statistics.sock
 UNIX_MATCH_UID = NO
 UNIX_MATCH_GID = YES
 # DISABLE_SOCKET_FORWARDING = NO
Index: src/namestore/namestore.conf.in
===================================================================
--- src/namestore/namestore.conf.in	(revision 29640)
+++ src/namestore/namestore.conf.in	(revision 29639)
@@ -1,6 +1,6 @@
 [namestore]
 AUTOSTART = YES
-UNIXPATH = $SERVICEHOME/gnunet-service-namestore.sock
+UNIXPATH = /tmp/gnunet-service-namestore.sock
 UNIX_MATCH_UID = NO
 UNIX_MATCH_GID = YES
 @UNIXONLY@ PORT = 2099
Index: src/vpn/vpn.conf.in
===================================================================
--- src/vpn/vpn.conf.in	(revision 29640)
+++ src/vpn/vpn.conf.in	(revision 29639)
@@ -6,7 +6,7 @@
 BINARY = gnunet-service-vpn
 ACCEPT_FROM = 127.0.0.1;
 ACCEPT_FROM6 = ::1;
-UNIXPATH = $SERVICEHOME/gnunet-service-vpn.sock
+UNIXPATH = /tmp/gnunet-service-vpn.sock
 UNIX_MATCH_UID = YES
 UNIX_MATCH_GID = YES
 
Index: src/peerinfo/peerinfo.conf.in
===================================================================
--- src/peerinfo/peerinfo.conf.in	(revision 29640)
+++ src/peerinfo/peerinfo.conf.in	(revision 29639)
@@ -6,7 +6,7 @@
 BINARY = gnunet-service-peerinfo
 ACCEPT_FROM = 127.0.0.1;
 ACCEPT_FROM6 = ::1;
-UNIXPATH = $SERVICEHOME/gnunet-service-peerinfo.sock
+UNIXPATH = /tmp/gnunet-service-peerinfo.sock
 UNIX_MATCH_UID = NO
 UNIX_MATCH_GID = YES
 # DISABLE_SOCKET_FORWARDING = NO
Index: src/fs/fs.conf.in
===================================================================
--- src/fs/fs.conf.in	(revision 29640)
+++ src/fs/fs.conf.in	(revision 29639)
@@ -22,7 +22,7 @@
 # (may improve anonymity, probably not a good idea if content_caching is NO)
 CONTENT_PUSHING = YES
 
-UNIXPATH = $SERVICEHOME/gnunet-service-fs.sock
+UNIXPATH = /tmp/gnunet-service-fs.sock
 
 # Do we require users that want to access file-sharing to run this process 
 # (usually not a good idea)
Index: src/dv/dv.conf.in
===================================================================
--- src/dv/dv.conf.in	(revision 29640)
+++ src/dv/dv.conf.in	(revision 29639)
@@ -6,7 +6,7 @@
 HOME = $SERVICEHOME
 HOSTNAME = localhost
 @UNIXONLY@ PORT = 2571
-UNIXPATH = $SERVICEHOME/gnunet-service-dv.sock
+UNIXPATH = /tmp/gnunet-service-dv.sock
 UNIX_MATCH_UID = YES
 UNIX_MATCH_GID = YES
 # ACCEPT_FROM =
Index: src/regex/regex.conf.in
===================================================================
--- src/regex/regex.conf.in	(revision 29640)
+++ src/regex/regex.conf.in	(revision 29639)
@@ -1,7 +1,7 @@
 [regex]
 AUTOSTART = YES
 @UNIXONLY@ PORT = 2107
-UNIXPATH = $SERVICEHOME/gnunet-service-regex.sock
+UNIXPATH = /tmp/gnunet-service-regex.sock
 HOSTNAME = localhost
 HOME = $SERVICEHOME
 BINARY = gnunet-service-regex
Index: src/experimentation/experimentation.conf.in
===================================================================
--- src/experimentation/experimentation.conf.in	(revision 29640)
+++ src/experimentation/experimentation.conf.in	(revision 29639)
@@ -6,7 +6,7 @@
 BINARY = gnunet-daemon-experimentation
 ACCEPT_FROM = 127.0.0.1;
 ACCEPT_FROM6 = ::1;
-UNIXPATH = $SERVICEHOME/gnunet-daemon-experimentation.sock
+UNIXPATH = /tmp/gnunet-daemon-experimentation.sock
 UNIX_MATCH_UID = YES
 UNIX_MATCH_GID = YES
 ISSUERS = TFRM29O2RQNKLVBQIGODJ6GD58LSQ2NM9TNFBC6N48BRJHQO38Q73N2OM3V4CLKDM6CILQV4CU8PMJDRG0FNB0PDI057DBRANMLPLRG
\ No newline at end of file
Index: src/testing/testing.c
===================================================================
--- src/testing/testing.c	(revision 29640)
+++ src/testing/testing.c	(revision 29639)
@@ -619,7 +619,8 @@
           continue;
         bind_status = GNUNET_NETWORK_socket_bind (socket,
                                                   ai->ai_addr,
-                                                  ai->ai_addrlen);
+                                                  ai->ai_addrlen,
+                                                  0);
         GNUNET_NETWORK_socket_close (socket);
         if (GNUNET_OK != bind_status)
           break;
@@ -628,7 +629,8 @@
           continue;
         bind_status = GNUNET_NETWORK_socket_bind (socket,
                                                   ai->ai_addr,
-                                                  ai->ai_addrlen);
+                                                  ai->ai_addrlen,
+                                                  0);
         GNUNET_NETWORK_socket_close (socket);
         if (GNUNET_OK != bind_status)
           break;
Index: src/psyc/psyc.conf.in
===================================================================
--- src/psyc/psyc.conf.in	(revision 29640)
+++ src/psyc/psyc.conf.in	(revision 29639)
@@ -2,6 +2,6 @@
 AUTOSTART = YES
 HOME = $SERVICEHOME
 BINARY = gnunet-service-psyc
-UNIXPATH = $SERVICEHOME/gnunet-service-psyc.sock
+UNIXPATH = /tmp/gnunet-service-psyc.sock
 UNIX_MATCH_UID = NO
 UNIX_MATCH_GID = YES
Index: src/nat/nat_test.c
===================================================================
--- src/nat/nat_test.c	(revision 29640)
+++ src/nat/nat_test.c	(revision 29639)
@@ -404,7 +404,7 @@
     if ((ret->lsock == NULL) ||
         (GNUNET_OK !=
          GNUNET_NETWORK_socket_bind (ret->lsock, (const struct sockaddr *) &sa,
-                                     sizeof (sa))))
+                                     sizeof (sa), 0)))
     {
       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                   _
Index: src/include/gnunet_network_lib.h
===================================================================
--- src/include/gnunet_network_lib.h	(revision 29640)
+++ src/include/gnunet_network_lib.h	(revision 29639)
@@ -132,17 +132,25 @@
 
 
 /**
+ * Fail to bind if an address is already in use.
+ */
+#define GNUNET_BIND_EXCLUSIVE 0x01
+
+
+/**
  * Bind a socket to a particular address.
  *
  * @param desc socket to bind
  * @param address address to be bound
  * @param address_len length of address
+ * @param flags flags affecting bind behaviour
  * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
  */
 int
 GNUNET_NETWORK_socket_bind (struct GNUNET_NETWORK_Handle *desc,
                             const struct sockaddr *address,
-                            socklen_t address_len);
+                            socklen_t address_len,
+                            int flags);
 
 /**
  * Close a socket.
Index: src/lockmanager/lockmanager.conf.in
===================================================================
--- src/lockmanager/lockmanager.conf.in	(revision 29640)
+++ src/lockmanager/lockmanager.conf.in	(revision 29639)
@@ -6,7 +6,7 @@
 BINARY = gnunet-service-lockmanager
 ACCEPT_FROM = 127.0.0.1;
 ACCEPT_FROM6 = ::1;
-UNIXPATH = $SERVICEHOME/gnunet-service-lockmanager.sock
+UNIXPATH = /tmp/gnunet-service-lockmanager.sock
 UNIX_MATCH_UID = YES
 UNIX_MATCH_GID = YES
 
Index: src/nse/nse.conf.in
===================================================================
--- src/nse/nse.conf.in	(revision 29640)
+++ src/nse/nse.conf.in	(revision 29639)
@@ -6,7 +6,7 @@
 BINARY = gnunet-service-nse
 ACCEPT_FROM = 127.0.0.1;
 ACCEPT_FROM6 = ::1;
-UNIXPATH = $SERVICEHOME/gnunet-service-nse.unix
+UNIXPATH = /tmp/gnunet-service-nse.unix
 UNIX_MATCH_UID = NO
 UNIX_MATCH_GID = YES
 PROOFFILE = $SERVICEHOME/.nse-proof
Index: src/identity/identity.conf.in
===================================================================
--- src/identity/identity.conf.in	(revision 29640)
+++ src/identity/identity.conf.in	(revision 29639)
@@ -6,7 +6,7 @@
 BINARY = gnunet-service-identity
 ACCEPT_FROM = 127.0.0.1;
 ACCEPT_FROM6 = ::1;
-UNIXPATH = $SERVICEHOME/gnunet-service-identity.unix
+UNIXPATH = /tmp/gnunet-service-identity.unix
 UNIX_MATCH_UID = NO
 UNIX_MATCH_GID = YES
 
Index: src/testbed/testbed.conf.in
===================================================================
--- src/testbed/testbed.conf.in	(revision 29640)
+++ src/testbed/testbed.conf.in	(revision 29639)
@@ -19,7 +19,7 @@
 ACCEPT_FROM = 127.0.0.1;
 ACCEPT_FROM6 = ::1;
 
-UNIXPATH = $SERVICEHOME/gnunet-service-testbed.sock
+UNIXPATH = /tmp/gnunet-service-testbed.sock
 UNIX_MATCH_UID = YES
 UNIX_MATCH_GID = YES
 
@@ -88,7 +88,7 @@
 @UNIXONLY@ PORT = 2102
 HOSTNAME = localhost
 BINARY = gnunet-service-testbed-logger
-UNIXPATH = $SERVICEHOME/gnunet-gnunet-testbed-logger.sock
+UNIXPATH = /tmp/gnunet-gnunet-testbed-logger.sock
 DIR = /tmp
 UNIX_MATCH_UID = YES
 UNIX_MATCH_GID = YES
@@ -98,6 +98,6 @@
 AUTOSTART = NO
 @UNIXONLY@ PORT = 2103
 HOSTNAME = localhost
-UNIXPATH = $SERVICEHOME/gnunet-service-testbed-barrier.sock
+UNIXPATH = /tmp/gnunet-service-testbed-barrier.sock
 UNIX_MATCH_UID = YES
 UNIX_MATCH_GID = YES
Index: src/psycstore/psycstore.conf.in
===================================================================
--- src/psycstore/psycstore.conf.in	(revision 29640)
+++ src/psycstore/psycstore.conf.in	(revision 29639)
@@ -2,7 +2,7 @@
 AUTOSTART = YES
 HOME = $SERVICEHOME
 BINARY = gnunet-service-psycstore
-UNIXPATH = $SERVICEHOME/gnunet-service-psycstore.sock
+UNIXPATH = /tmp/gnunet-service-psycstore.sock
 @UNIXONLY@PORT = 2111
 UNIX_MATCH_UID = NO
 UNIX_MATCH_GID = YES
Index: src/set/set.conf.in
===================================================================
--- src/set/set.conf.in	(revision 29640)
+++ src/set/set.conf.in	(revision 29639)
@@ -6,6 +6,6 @@
 BINARY = gnunet-service-set
 ACCEPT_FROM = 127.0.0.1;
 ACCEPT_FROM6 = ::1;
-UNIXPATH = $SERVICEHOME/gnunet-service-set.sock
+UNIXPATH = /tmp/gnunet-service-set.sock
 UNIX_MATCH_UID = YES
 UNIX_MATCH_GID = YES
Index: src/mesh/mesh.conf.in
===================================================================
--- src/mesh/mesh.conf.in	(revision 29640)
+++ src/mesh/mesh.conf.in	(revision 29639)
@@ -6,7 +6,7 @@
 BINARY = gnunet-service-mesh
 ACCEPT_FROM = 127.0.0.1;
 ACCEPT_FROM6 = ::1;
-UNIXPATH = $SERVICEHOME/gnunet-service-mesh.sock
+UNIXPATH = /tmp/gnunet-service-mesh.sock
 UNIX_MATCH_UID = YES
 UNIX_MATCH_GID = YES
 REFRESH_CONNECTION_TIME = 5 min
Index: src/transport/transport.conf.in
===================================================================
--- src/transport/transport.conf.in	(revision 29640)
+++ src/transport/transport.conf.in	(revision 29639)
@@ -9,7 +9,7 @@
 ACCEPT_FROM = 127.0.0.1;
 ACCEPT_FROM6 = ::1;
 PLUGINS = tcp udp
-UNIXPATH = $SERVICEHOME/gnunet-service-transport.sock
+UNIXPATH = /tmp/gnunet-service-transport.sock
 BLACKLIST_FILE = $SERVICEHOME/blacklist
 UNIX_MATCH_UID = NO
 UNIX_MATCH_GID = YES
Index: src/transport/plugin_transport_udp.c
===================================================================
--- src/transport/plugin_transport_udp.c	(revision 29640)
+++ src/transport/plugin_transport_udp.c	(revision 29639)
@@ -2808,7 +2808,7 @@
       				 GNUNET_a2s (serverAddr, addrlen));
       		/* binding */
       		if (GNUNET_OK == GNUNET_NETWORK_socket_bind (plugin->sockv6,
-      		                                             serverAddr, addrlen))
+      		                                             serverAddr, addrlen, 0))
       			break;
       		eno = errno;
       		if (0 != plugin->port)
@@ -2885,7 +2885,7 @@
       
       /* binding */
       if (GNUNET_OK == GNUNET_NETWORK_socket_bind (plugin->sockv4,
-                                                   serverAddr, addrlen))
+                                                   serverAddr, addrlen, 0))
       		break;
       eno = errno;
       if (0 != plugin->port)
Index: src/transport/gnunet-helper-transport-bluetooth.c
===================================================================
--- src/transport/gnunet-helper-transport-bluetooth.c	(revision 29640)
+++ src/transport/gnunet-helper-transport-bluetooth.c	(revision 29639)
@@ -1070,7 +1070,6 @@
   return count;
 }
 
-
 /**
  * Open the bluetooth interface for reading/writing
  *
@@ -1088,8 +1087,7 @@
     addr.btAddr = 0;
     addr.port = BT_PORT_ANY;
 
-    if (GNUNET_OK != 
-	GNUNET_NETWORK_socket_bind (dev->handle, (const SOCKADDR*)&addr, sizeof (SOCKADDR_BTH)))
+    if (GNUNET_NETWORK_socket_bind (dev->handle, (const SOCKADDR*)&addr, sizeof (SOCKADDR_BTH), 0) != GNUNET_OK)
     {
       fprintf (stderr, "Failed to bind the socket: ");
       if (GetLastError() == WSAENETDOWN)
Index: src/transport/plugin_transport_unix.c
===================================================================
--- src/transport/plugin_transport_unix.c	(revision 29640)
+++ src/transport/plugin_transport_unix.c	(revision 29639)
@@ -572,6 +572,7 @@
   const void *sb;
   size_t sbs;
   struct sockaddr_un un;
+  size_t slen;
   const char *unix_path;
 
 
@@ -591,12 +592,21 @@
   unix_path = (const char *)  &addr[1];
   memset (&un, 0, sizeof (un));
   un.sun_family = AF_UNIX;
-  strncpy (un.sun_path, unix_path, sizeof (un.sun_path) - 1);
+  slen =  strlen (unix_path);
+  if (slen >= sizeof (un.sun_path))
+    slen = sizeof (un.sun_path) - 1;
+  GNUNET_assert (slen < sizeof (un.sun_path));
+  memcpy (un.sun_path, unix_path, slen);
+  un.sun_path[slen] = '\0';
+  slen = sizeof (struct sockaddr_un);
+#if LINUX
+  un.sun_path[0] = '\0';
+#endif
 #if HAVE_SOCKADDR_IN_SIN_LEN
-  un.sun_len = (u_char) sizeof (struct sockaddr_un);
+  un.sun_len = (u_char) slen;
 #endif
   sb = (struct sockaddr *) &un;
-  sbs = sizeof (struct sockaddr_un);
+  sbs = slen;
 
 resend:
   /* Send the data */
@@ -1013,18 +1023,19 @@
   }
   else
   {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, 
-	 "Read %d bytes from socket %s\n", 
-	 (int) ret,
-	 un.sun_path);
+#if LINUX
+    un.sun_path[0] = '/';
+#endif
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "Read %d bytes from socket %s\n", ret,
+                &un.sun_path[0]);
   }
 
   GNUNET_assert (AF_UNIX == (un.sun_family));
-  ua_len = sizeof (struct UnixAddress) + strlen (un.sun_path) + 1;
+  ua_len = sizeof (struct UnixAddress) + strlen (&un.sun_path[0]) +1;
   ua = GNUNET_malloc (ua_len);
   ua->addrlen = htonl (strlen (&un.sun_path[0]) +1);
   ua->options = htonl (0);
-  memcpy (&ua[1], &un.sun_path[0], strlen (un.sun_path) + 1);
+  memcpy (&ua[1], &un.sun_path[0], strlen (&un.sun_path[0]) +1);
 
   msg = (struct UNIXMessage *) buf;
   csize = ntohs (msg->header.size);
@@ -1203,7 +1214,7 @@
  * Create a slew of UNIX sockets.  If possible, use IPv6 and IPv4.
  *
  * @param cls closure for server start, should be a struct Plugin *
- * @return number of sockets created or #GNUNET_SYSERR on error
+ * @return number of sockets created or GNUNET_SYSERR on error
  */
 static int
 unix_transport_server_start (void *cls)
@@ -1212,16 +1223,26 @@
   struct sockaddr *serverAddr;
   socklen_t addrlen;
   struct sockaddr_un un;
+  size_t slen;
 
   memset (&un, 0, sizeof (un));
   un.sun_family = AF_UNIX;
-  strncpy (un.sun_path, plugin->unix_socket_path, sizeof (un.sun_path) - 1);
+  slen = strlen (plugin->unix_socket_path) + 1;
+  if (slen >= sizeof (un.sun_path))
+    slen = sizeof (un.sun_path) - 1;
+
+  memcpy (un.sun_path, plugin->unix_socket_path, slen);
+  un.sun_path[slen] = '\0';
+  slen = sizeof (struct sockaddr_un);
 #if HAVE_SOCKADDR_IN_SIN_LEN
-  un.sun_len = (u_char) sizeof (struct sockaddr_un);
+  un.sun_len = (u_char) slen;
 #endif
 
   serverAddr = (struct sockaddr *) &un;
-  addrlen = sizeof (struct sockaddr_un);
+  addrlen = slen;
+#if LINUX
+  un.sun_path[0] = '\0';
+#endif
   plugin->ats_network = plugin->env->get_address_type (plugin->env->cls, serverAddr, addrlen);
   plugin->unix_sock.desc =
       GNUNET_NETWORK_socket_create (AF_UNIX, SOCK_DGRAM, 0);
@@ -1230,8 +1251,8 @@
     GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "socket");
     return GNUNET_SYSERR;
   }
-  if (GNUNET_OK !=
-      GNUNET_NETWORK_socket_bind (plugin->unix_sock.desc, serverAddr, addrlen))
+  if (GNUNET_NETWORK_socket_bind (plugin->unix_sock.desc, serverAddr, addrlen, 0)
+      != GNUNET_OK)
   {
     GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "bind");
     GNUNET_NETWORK_socket_close (plugin->unix_sock.desc);
Index: src/multicast/multicast.conf.in
===================================================================
--- src/multicast/multicast.conf.in	(revision 29640)
+++ src/multicast/multicast.conf.in	(revision 29639)
@@ -6,7 +6,7 @@
 BINARY = gnunet-service-multicast
 ACCEPT_FROM = 127.0.0.1;
 ACCEPT_FROM6 = ::1;
-UNIXPATH = $SERVICEHOME/gnunet-service-multicast.sock
+UNIXPATH = /tmp/gnunet-service-multicast.sock
 UNIX_MATCH_UID = YES
 UNIX_MATCH_GID = YES
 # DISABLE_SOCKET_FORWARDING = NO
Index: src/scalarproduct/scalarproduct.conf.in
===================================================================
--- src/scalarproduct/scalarproduct.conf.in	(revision 29640)
+++ src/scalarproduct/scalarproduct.conf.in	(revision 29639)
@@ -1,6 +1,6 @@
 [vectorproduct]
 BINARY = gnunet-service-vectorproduct
-UNIXPATH = $SERVICEHOME/gnunet-service-vectorproduct.sock
+UNIXPATH = /tmp/gnunet-service-vectorproduct.sock
 HOME = $SERVICEHOME
 # PORT = 2106
 @UNIXONLY@ PORT = 2087
Index: src/util/client.c
===================================================================
--- src/util/client.c	(revision 29640)
+++ src/util/client.c	(revision 29639)
@@ -251,9 +251,7 @@
   struct sockaddr_un s_un;
 
   unixpath = NULL;
-  if ((GNUNET_OK == 
-       GNUNET_CONFIGURATION_get_value_filename (cfg, service_name,
-						"UNIXPATH", &unixpath)) && 
+  if ((GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (cfg, service_name, "UNIXPATH", &unixpath)) && 
       (0 < strlen (unixpath)))     
   {
     /* We have a non-NULL unixpath, need to validate it */
@@ -301,8 +299,7 @@
 #if AF_UNIX
   char *unixpath = NULL;
 
-  if ((GNUNET_OK == 
-       GNUNET_CONFIGURATION_get_value_filename (cfg, service_name, "UNIXPATH", &unixpath)) && 
+  if ((GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (cfg, service_name, "UNIXPATH", &unixpath)) && 
       (0 < strlen (unixpath)))     
     ret = GNUNET_OK;
   GNUNET_free_non_null (unixpath);
@@ -832,12 +829,11 @@
   {
     /* probe UNIX support */
     struct sockaddr_un s_un;
+    size_t slen;
     char *unixpath;
 
     unixpath = NULL;
-    if ((GNUNET_OK == 
-	 GNUNET_CONFIGURATION_get_value_filename (cfg, service, "UNIXPATH", &unixpath)) && 
-	(0 < strlen (unixpath)))  /* We have a non-NULL unixpath, does that mean it's valid? */
+    if ((GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (cfg, service, "UNIXPATH", &unixpath)) && (0 < strlen (unixpath)))  /* We have a non-NULL unixpath, does that mean it's valid? */
     {
       if (strlen (unixpath) >= sizeof (s_un.sun_path))
       {
@@ -856,13 +852,21 @@
       {
 	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);
+	slen = strlen (unixpath) + 1;
+	if (slen >= sizeof (s_un.sun_path))
+	  slen = sizeof (s_un.sun_path) - 1;
+	memcpy (s_un.sun_path, unixpath, slen);
+	s_un.sun_path[slen] = '\0';
+	slen = sizeof (struct sockaddr_un);
+#if LINUX
+	s_un.sun_path[0] = '\0';
+#endif
 #if HAVE_SOCKADDR_IN_SIN_LEN
-        s_un.sun_len = (u_char) sizeof (struct sockaddr_un);
+	s_un.sun_len = (u_char) slen;
 #endif
 	if (GNUNET_OK !=
 	    GNUNET_NETWORK_socket_bind (sock, (const struct sockaddr *) &s_un,
-					sizeof (struct sockaddr_un)))
+					slen, GNUNET_BIND_EXCLUSIVE))
         {
 	  /* failed to bind => service must be running */
 	  GNUNET_free (unixpath);
@@ -912,7 +916,7 @@
     {
       if (GNUNET_OK !=
           GNUNET_NETWORK_socket_bind (sock, (const struct sockaddr *) &s_in,
-                                      sizeof (s_in)))
+                                      sizeof (s_in), GNUNET_BIND_EXCLUSIVE))
       {
         /* failed to bind => service must be running */
         GNUNET_free (hostname);
@@ -945,7 +949,7 @@
     {
       if (GNUNET_OK !=
           GNUNET_NETWORK_socket_bind (sock, (const struct sockaddr *) &s_in6,
-                                      sizeof (s_in6)))
+                                      sizeof (s_in6), GNUNET_BIND_EXCLUSIVE))
       {
         /* failed to bind => service must be running */
         GNUNET_free (hostname);
Index: src/util/network.c
===================================================================
--- src/util/network.c	(revision 29640)
+++ src/util/network.c	(revision 29639)
@@ -87,9 +87,7 @@
   {
     if (EAFNOSUPPORT == errno)
       return GNUNET_NO;
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 
-		"Failed to create test socket: %s\n", 
-		STRERROR (errno));
+    fprintf (stderr, "Failed to create test socket: %s\n", STRERROR (errno));
     return GNUNET_SYSERR;
   }
 #if WINDOWS
@@ -385,18 +383,20 @@
  * @param desc socket to bind
  * @param address address to be bound
  * @param address_len length of @a address
+ * @param flags flags affecting bind behaviour
  * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
  */
 int
 GNUNET_NETWORK_socket_bind (struct GNUNET_NETWORK_Handle *desc,
                             const struct sockaddr *address,
-                            socklen_t address_len)
+                            socklen_t address_len,
+                            int flags)
 {
   int ret;
   socklen_t bind_address_len = address_len;
 
 #ifdef LINUX
-  if (AF_UNIX == address->sa_family)
+  if (address->sa_family == AF_UNIX)
   {
     const struct sockaddr_un *address_un = (const struct sockaddr_un *)address;
     if (address_un->sun_path[0] == '\0')
@@ -431,6 +431,16 @@
       LOG_STRERROR (GNUNET_ERROR_TYPE_DEBUG, "setsockopt");
   }
 #endif
+#ifndef LINUX
+#ifndef MINGW
+  if (address->sa_family == AF_UNIX && (flags & GNUNET_BIND_EXCLUSIVE) == 0)
+  {
+    const struct sockaddr_un *un = (const struct sockaddr_un *) address;
+
+    (void) unlink (un->sun_path);
+  }
+#endif
+#endif
   ret = bind (desc->fd, address, bind_address_len);
 #ifdef MINGW
   if (SOCKET_ERROR == ret)
@@ -439,10 +449,12 @@
   if (ret != 0)
     return GNUNET_SYSERR;
 #ifndef MINGW
+#ifndef LINUX
   desc->addr = GNUNET_malloc (address_len);
   memcpy (desc->addr, address, address_len);
   desc->addrlen = address_len;
 #endif
+#endif
   return GNUNET_OK;
 }
 
@@ -471,17 +483,17 @@
 #else
   ret = close (desc->fd);
 #endif
+#ifndef LINUX
 #ifndef MINGW
   if ((desc->af == AF_UNIX) && (NULL != desc->addr))
   {
     const struct sockaddr_un *un = (const struct sockaddr_un *) desc->addr;
 
     if (0 != unlink (un->sun_path))
-      LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, 
-			 "unlink", 
-			 un->sun_path);
+      LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "unlink", un->sun_path);
   }
 #endif
+#endif
   GNUNET_NETWORK_socket_free_memory_only_ (desc);
   return (ret == 0) ? GNUNET_OK : GNUNET_SYSERR;
 }
Index: src/util/disk.c
===================================================================
--- src/util/disk.c	(revision 29640)
+++ src/util/disk.c	(revision 29639)
@@ -759,12 +759,13 @@
 
 
 /**
- * Create the directory structure for storing a file.
+ * Create the directory structure for storing
+ * a file.
  *
  * @param filename name of a file in the directory
- * @returns #GNUNET_OK on success,
- *          #GNUNET_SYSERR on failure,
- *          #GNUNET_NO if the directory
+ * @returns GNUNET_OK on success,
+ *          GNUNET_SYSERR on failure,
+ *          GNUNET_NO if the directory
  *          exists but is not writeable for us
  */
 int
@@ -791,11 +792,10 @@
 
 /**
  * Read the contents of a binary file into a buffer.
- *
  * @param h handle to an open file
  * @param result the buffer to write the result to
  * @param len the maximum number of bytes to read
- * @return the number of bytes read on success, #GNUNET_SYSERR on failure
+ * @return the number of bytes read on success, GNUNET_SYSERR on failure
  */
 ssize_t
 GNUNET_DISK_file_read (const struct GNUNET_DISK_FileHandle * h, void *result,
Index: src/util/test_connection.c
===================================================================
--- src/util/test_connection.c	(revision 29640)
+++ src/util/test_connection.c	(revision 29639)
@@ -65,9 +65,9 @@
   if (GNUNET_NETWORK_socket_setsockopt
       (desc, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)) != GNUNET_OK)
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "setsockopt");
-  GNUNET_assert (GNUNET_OK ==
-		 GNUNET_NETWORK_socket_bind (desc, (const struct sockaddr *) &sa,
-					     sizeof (sa)));
+  GNUNET_assert (GNUNET_NETWORK_socket_bind
+                 (desc, (const struct sockaddr *) &sa,
+                  sizeof (sa), 0) == GNUNET_OK);
   GNUNET_NETWORK_socket_listen (desc, 5);
   return desc;
 }
Index: src/util/connection.c
===================================================================
--- src/util/connection.c	(revision 29640)
+++ src/util/connection.c	(revision 29639)
@@ -828,14 +828,23 @@
 #ifdef AF_UNIX
   struct GNUNET_CONNECTION_Handle *connection;
   struct sockaddr_un *un;
+  size_t slen;
 
   GNUNET_assert (0 < strlen (unixpath));        /* sanity check */
   un = GNUNET_new (struct sockaddr_un);
   un->sun_family = AF_UNIX;
-  strncpy(un->sun_path, unixpath, sizeof(un->sun_path) - 1);
+  slen = strlen (unixpath);
+  if (slen >= sizeof (un->sun_path))
+    slen = sizeof (un->sun_path) - 1;
+  memcpy (un->sun_path, unixpath, slen);
+  un->sun_path[slen] = '\0';
+  slen = sizeof (struct sockaddr_un);
 #if HAVE_SOCKADDR_IN_SIN_LEN
-  un->sun_len = (u_char) sizeof (struct sockaddr_un);
+  un->sun_len = (u_char) slen;
 #endif
+#if LINUX
+  un->sun_path[0] = '\0';
+#endif
   connection = GNUNET_new (struct GNUNET_CONNECTION_Handle);
   connection->cfg = cfg;
   connection->write_buffer_size = GNUNET_SERVER_MIN_BUFFER_SIZE;
@@ -843,7 +852,7 @@
   connection->port = 0;
   connection->hostname = NULL;
   connection->addr = (struct sockaddr *) un;
-  connection->addrlen = sizeof (struct sockaddr_un);
+  connection->addrlen = slen;
   connection->sock = GNUNET_NETWORK_socket_create (AF_UNIX, SOCK_STREAM, 0);
   if (NULL == connection->sock)
   {
Index: src/util/server.c
===================================================================
--- src/util/server.c	(revision 29640)
+++ src/util/server.c	(revision 29639)
@@ -469,7 +469,7 @@
     return NULL;
   }
   /* bind the socket */
-  if (GNUNET_OK != GNUNET_NETWORK_socket_bind (sock, serverAddr, socklen))
+  if (GNUNET_OK != GNUNET_NETWORK_socket_bind (sock, serverAddr, socklen, 0))
   {
     eno = errno;
     if (EADDRINUSE != errno)
Index: src/util/service.c
===================================================================
--- src/util/service.c	(revision 29640)
+++ src/util/service.c	(revision 29639)
@@ -841,15 +841,24 @@
 {
 #ifdef AF_UNIX
   struct sockaddr_un *un;
+  size_t slen;
 
   un = GNUNET_malloc (sizeof (struct sockaddr_un));
   un->sun_family = AF_UNIX;
-  strncpy (un->sun_path, unixpath, sizeof (un->sun_path) - 1);
+  slen = strlen (unixpath) + 1;
+  if (slen >= sizeof (un->sun_path))
+    slen = sizeof (un->sun_path) - 1;
+  memcpy (un->sun_path, unixpath, slen);
+  un->sun_path[slen] = '\0';
+  slen = sizeof (struct sockaddr_un);
+#if LINUX
+  un->sun_path[0] = '\0';
+#endif
 #if HAVE_SOCKADDR_IN_SIN_LEN
-  un->sun_len = (u_char) sizeof (struct sockaddr_un);
+  un->sun_len = (u_char) slen;
 #endif
   *saddrs = (struct sockaddr *) un;
-  *saddrlens = sizeof (struct sockaddr_un);
+  *saddrlens = slen;
 #else
   /* this function should never be called
    * unless AF_UNIX is defined! */
@@ -971,8 +980,8 @@
   if ((GNUNET_YES ==
        GNUNET_CONFIGURATION_have_value (cfg, service_name, "UNIXPATH")) &&
       (GNUNET_OK ==
-       GNUNET_CONFIGURATION_get_value_filename (cfg, service_name, "UNIXPATH",
-						&unixpath)) &&
+       GNUNET_CONFIGURATION_get_value_string (cfg, service_name, "UNIXPATH",
+                                              &unixpath)) &&
       (0 < strlen (unixpath)))
   {
     /* probe UNIX support */
@@ -987,11 +996,6 @@
       LOG (GNUNET_ERROR_TYPE_INFO,
 	   _("Using `%s' instead\n"), unixpath);
     }
-    if (GNUNET_OK !=
-	GNUNET_DISK_directory_create_for_file (unixpath))
-      GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
-				"mkdir",
-				unixpath);
   }
   if (NULL != unixpath)
   {
Index: src/util/resolver.conf.in
===================================================================
--- src/util/resolver.conf.in	(revision 29640)
+++ src/util/resolver.conf.in	(revision 29639)
@@ -6,7 +6,7 @@
 BINARY = gnunet-service-resolver
 ACCEPT_FROM = 127.0.0.1;
 ACCEPT_FROM6 = ::1;
-UNIXPATH = $SERVICEHOME/gnunet-service-resolver.sock
+UNIXPATH = /tmp/gnunet-service-resolver.sock
 UNIX_MATCH_UID = NO
 UNIX_MATCH_GID = NO
 # DISABLE_SOCKET_FORWARDING = NO
Index: src/util/test_server_with_client_unix.c
===================================================================
--- src/util/test_server_with_client_unix.c	(revision 29640)
+++ src/util/test_server_with_client_unix.c	(revision 29639)
@@ -134,15 +134,20 @@
 {
   struct sockaddr_un un;
   const char *unixpath = "/tmp/testsock";
+  size_t slen = strlen (unixpath);
   struct sockaddr *sap[2];
   socklen_t slens[2];
 
   memset (&un, 0, sizeof (un));
   un.sun_family = AF_UNIX;
-  strncpy(un.sun_path, unixpath, sizeof (un.sun_path) - 1);
+  memcpy (un.sun_path, unixpath, slen);
+  un.sun_path[slen] = '\0';
 #if HAVE_SOCKADDR_IN_SIN_LEN
   un.sun_len = (u_char) sizeof (un);
 #endif
+#if LINUX
+  un.sun_path[0] = '\0';
+#endif
 
   sap[0] = (struct sockaddr *) &un;
   slens[0] = sizeof (un);
Index: src/util/test_connection_addressing.c
===================================================================
--- src/util/test_connection_addressing.c	(revision 29640)
+++ src/util/test_connection_addressing.c	(revision 29639)
@@ -68,7 +68,7 @@
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "setsockopt");
   if (GNUNET_OK !=
       GNUNET_NETWORK_socket_bind (desc, (const struct sockaddr *) &sa,
-                                  sizeof (sa)))
+                                  sizeof (sa), 0))
   {
     GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
                          "bind");
Index: src/util/test_connection_receive_cancel.c
===================================================================
--- src/util/test_connection_receive_cancel.c	(revision 29640)
+++ src/util/test_connection_receive_cancel.c	(revision 29639)
@@ -64,9 +64,9 @@
   if (GNUNET_NETWORK_socket_setsockopt
       (desc, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)) != GNUNET_OK)
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "setsockopt");
-  GNUNET_assert (GNUNET_OK ==
-		 GNUNET_NETWORK_socket_bind (desc, (const struct sockaddr *) &sa,
-					     sizeof (sa)));
+  GNUNET_assert (GNUNET_NETWORK_socket_bind
+                 (desc, (const struct sockaddr *) &sa,
+                  sizeof (sa), 0) == GNUNET_OK);
   GNUNET_NETWORK_socket_listen (desc, 5);
   return desc;
 }
Index: src/util/test_connection_timeout.c
===================================================================
--- src/util/test_connection_timeout.c	(revision 29640)
+++ src/util/test_connection_timeout.c	(revision 29639)
@@ -61,9 +61,9 @@
   if (GNUNET_NETWORK_socket_setsockopt
       (desc, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)) != GNUNET_OK)
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "setsockopt");
-  GNUNET_assert (GNUNET_OK ==
-		 GNUNET_NETWORK_socket_bind (desc, (const struct sockaddr *) &sa,
-					     sizeof (sa)));
+  GNUNET_assert (GNUNET_NETWORK_socket_bind
+                 (desc, (const struct sockaddr *) &sa,
+                  sizeof (sa), 0) == GNUNET_OK);
   GNUNET_NETWORK_socket_listen (desc, 5);
   return desc;
 }
Index: src/arm/arm.conf.in
===================================================================
--- src/arm/arm.conf.in	(revision 29640)
+++ src/arm/arm.conf.in	(revision 29639)
@@ -7,7 +7,7 @@
 ACCEPT_FROM = 127.0.0.1;
 ACCEPT_FROM6 = ::1;
 DEFAULTSERVICES = topology hostlist dht nse mesh fs
-UNIXPATH = $SERVICEHOME/gnunet-service-arm.sock
+UNIXPATH = /tmp/gnunet-service-arm.sock
 UNIX_MATCH_UID = YES
 UNIX_MATCH_GID = YES
 
Index: src/arm/gnunet-service-arm.c
===================================================================
--- src/arm/gnunet-service-arm.c	(revision 29640)
+++ src/arm/gnunet-service-arm.c	(revision 29639)
@@ -622,8 +622,8 @@
 			 "setsockopt");
 #endif
 
-  if (GNUNET_OK !=
-      GNUNET_NETWORK_socket_bind (sock, (const struct sockaddr *) sa, addr_len))
+  if (GNUNET_NETWORK_socket_bind
+      (sock, (const struct sockaddr *) sa, addr_len, 0) != GNUNET_OK)
     {
       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
 		  _
Index: src/arm/test_exponential_backoff.c
===================================================================
--- src/arm/test_exponential_backoff.c	(revision 29640)
+++ src/arm/test_exponential_backoff.c	(revision 29639)
@@ -42,7 +42,7 @@
 
 #define BINARY "mockup-service"
 
-#define CFGFILENAME "test_arm_api_data_copy.conf"
+#define CFGFILENAME "test_arm_api_data.conf"
 
 
 static const struct GNUNET_CONFIGURATION_Handle *cfg;
Index: src/dht/dht.conf.in
===================================================================
--- src/dht/dht.conf.in	(revision 29640)
+++ src/dht/dht.conf.in	(revision 29639)
@@ -7,7 +7,7 @@
 ACCEPT_FROM = 127.0.0.1;
 ACCEPT_FROM6 = ::1;
 BUCKET_SIZE = 4
-UNIXPATH = $SERVICEHOME/gnunet-service-dht.sock
+UNIXPATH = /tmp/gnunet-service-dht.sock
 # This could be relaxed...
 UNIX_MATCH_UID = YES
 UNIX_MATCH_GID = YES
Index: src/consensus/consensus.conf.in
===================================================================
--- src/consensus/consensus.conf.in	(revision 29640)
+++ src/consensus/consensus.conf.in	(revision 29639)
@@ -6,6 +6,6 @@
 BINARY = gnunet-service-consensus
 ACCEPT_FROM = 127.0.0.1;
 ACCEPT_FROM6 = ::1;
-UNIXPATH = $SERVICEHOME/gnunet-service-consensus.sock
+UNIXPATH = /tmp/gnunet-service-consensus.sock
 UNIX_MATCH_UID = YES
 UNIX_MATCH_GID = YES
29640.diff (37,863 bytes)   

Activities

Christian Grothoff

2013-09-26 16:33

manager   ~0007475

Andrew Cann wrote:

These two patches fix a couple of bugs in the way abstract unix domain
sockets are used on Linux.

https://canndrew.org/misc/trim_abstract_socket_paths.diff

This changes the addrlen argument passed to the connect, bind and sendto
syscalls to reflect the length of the string in sockaddr_un.sun_path. I
was trying to talk to GNUnet services using socat and discovered that it
expects abstract sockets to be created this way and won't connect
otherwise. Looking at some other programs that I could talk to using
socat (dbus, X11), this is how they create abstract sockets as well.

https://canndrew.org/misc/dont_drop_first_character_of_abstract_socket_path.diff

Currently when using an abstract socket the first character of the path
get chopped off. So, for example, trying to create a socket called
"/tmp/gnunet-service-foo.sock" results in a socket called
"tmp/gnunet-service-foo.sock". This patch fixes this.

 - Andrew

Christian Grothoff

2013-09-26 16:38

manager   ~0007476

My reply:

Hi Andrew,

Thanks for looking into this!

The first patch looks OK, I'll likely apply it when I had the time to
test it a bit. The second one is technically OK, however there was
a very different suggestion before to get rid of abstract sockets so
that we can use the file system for access control:
https://gnunet.org/bugs/view.php?id=2887

Thus, I think that patch might rather be useful as a hints for us as to
where we'd need to make changes to address 0002887. As that's a rather
different direction, I'm likely not going to apply your second patch for
now.

I've attached both of your patches to 0002887 for future reference.

Happy hacking!

Christian

Christian Grothoff

2013-09-26 20:50

manager   ~0007477

SVN 29640 moves to normal, non-abstract UNIX domain socket paths. However, the file-system is not yet really used for access control, so this does not fully resolve this bug.

Christian Grothoff

2013-09-27 11:50

manager   ~0007480

Undid SVN 29640 in SVN 29645 as it caused unexpected problems that somehow didn't show up during initial testing.

Christian Grothoff

2013-10-09 20:01

manager   ~0007514

Ok, this time it seems to work fine, committed as SVN 30063.

Christian Grothoff

2013-10-09 20:02

manager   ~0007515

(bug still open as we still didn't do the access control part (note 7477).

Christian Grothoff

2013-10-09 22:04

manager   ~0007516

SVN 30065 changes file access checks from UDS credentials to file system (using umask and chmod as needed, avoiding possibility of race).

Christian Grothoff

2013-10-09 22:17

manager   ~0007517

Last remnants of abstract UDS were removed in SVN 30066.

Issue History

Date Modified Username Field Change
2013-05-22 10:43 helmut New Issue
2013-07-13 21:17 Christian Grothoff Status new => confirmed
2013-07-13 21:17 Christian Grothoff Target Version => 0.10.1
2013-09-26 16:32 Christian Grothoff File Added: trim_abstract_socket_paths.diff
2013-09-26 16:32 Christian Grothoff File Added: dont_drop_first_character_of_abstract_socket_path.diff
2013-09-26 16:33 Christian Grothoff Note Added: 0007475
2013-09-26 16:38 Christian Grothoff Note Added: 0007476
2013-09-26 19:07 Christian Grothoff Assigned To => Christian Grothoff
2013-09-26 19:07 Christian Grothoff Status confirmed => assigned
2013-09-26 20:50 Christian Grothoff Note Added: 0007477
2013-09-27 11:50 Christian Grothoff Note Added: 0007480
2013-09-30 13:50 Christian Grothoff File Added: 29640.diff
2013-10-09 19:38 Christian Grothoff Target Version 0.10.1 => 0.10.0
2013-10-09 20:01 Christian Grothoff Note Added: 0007514
2013-10-09 20:02 Christian Grothoff Note Added: 0007515
2013-10-09 22:04 Christian Grothoff Note Added: 0007516
2013-10-09 22:17 Christian Grothoff Note Added: 0007517
2013-10-09 22:17 Christian Grothoff Status assigned => resolved
2013-10-09 22:17 Christian Grothoff Fixed in Version => 0.10.0
2013-10-09 22:17 Christian Grothoff Resolution open => fixed
2013-12-24 20:54 Christian Grothoff Status resolved => closed