The current state of the nonce-tcp implementation
authorFrank Osterfeld <frank@kdab.net>
Wed, 21 Oct 2009 16:52:49 +0000 (19:52 +0300)
committerRalf Habacker <ralf.habacker@freenet.de>
Tue, 1 Dec 2009 07:43:36 +0000 (08:43 +0100)
Merged and cleaned up patch from my [Frank Osterfeld's] local work
branch.

Cherry-picked from commit e2801eca57b2d9e09afd662ed5ef6fc83be73afc and
edited by tml@iki.fi to make it apply, and fixing whitespace issues.

16 files changed:
cmake/CMakeLists.txt
cmake/dbus/CMakeLists.txt
dbus/Makefile.am
dbus/dbus-nonce.c [new file with mode: 0644]
dbus/dbus-nonce.h [new file with mode: 0644]
dbus/dbus-server-socket.c
dbus/dbus-server-socket.h
dbus/dbus-server-unix.c
dbus/dbus-server-win.c
dbus/dbus-sysdeps-unix.c
dbus/dbus-sysdeps-win.c
dbus/dbus-sysdeps-win.h
dbus/dbus-sysdeps.h
dbus/dbus-transport-socket.c
dbus/dbus-transport-socket.h
dbus/dbus-transport-win.c

index 33a0a76..7b74420 100644 (file)
@@ -459,8 +459,8 @@ set (DBUS_USER )
 
 
 if (WIN32)
-  set (DBUS_SESSION_BUS_DEFAULT_ADDRESS "tcp:host=localhost,port=0")
-  set (DBUS_SYSTEM_BUS_DEFAULT_ADDRESS "tcp:host=localhost,port=0")
+  set (DBUS_SESSION_BUS_DEFAULT_ADDRESS "nonce-tcp:host=localhost,port=0")
+  set (DBUS_SYSTEM_BUS_DEFAULT_ADDRESS "nonce-tcp:host=localhost,port=0")
   set (DBUS_SYSTEM_CONFIG_FILE "etc/system.conf")
   set (DBUS_SESSION_CONFIG_FILE "etc/session.conf")
   # bus-test expects a non empty string
index ce113a2..c1c2251 100644 (file)
@@ -46,6 +46,7 @@ set (DBUS_LIB_SOURCES
        ${DBUS_DIR}/dbus-marshal-validate.c
        ${DBUS_DIR}/dbus-message.c
        ${DBUS_DIR}/dbus-misc.c
+       ${DBUS_DIR}/dbus-nonce.c
        ${DBUS_DIR}/dbus-object-tree.c
        ${DBUS_DIR}/dbus-pending-call.c
        ${DBUS_DIR}/dbus-resources.c
index 5f8d703..c85556a 100644 (file)
@@ -138,6 +138,7 @@ DBUS_LIB_SOURCES=                           \
        dbus-message-internal.h                 \
        dbus-message-private.h                  \
        dbus-misc.c                             \
+       dbus-nonce.c                            \
        dbus-object-tree.c                      \
        dbus-object-tree.h                      \
        dbus-pending-call.c                     \
diff --git a/dbus/dbus-nonce.c b/dbus/dbus-nonce.c
new file mode 100644 (file)
index 0000000..e8de059
--- /dev/null
@@ -0,0 +1,239 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-nonce.c  Nonce handling functions used by nonce-tcp (internal to D-Bus implementation)
+ *
+ * Copyright (C) 2009 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.net
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+// major sections of this file are modified code from libassuan, (C) FSF
+#include "dbus-nonce.h"
+#include "dbus-internals.h"
+#include "dbus-protocol.h"
+#include "dbus-sysdeps.h"
+
+#include <stdio.h>
+
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
+#ifndef ENOFILE
+# define ENOFILE ENOENT
+#endif
+
+dbus_bool_t
+_dbus_check_nonce (int fd, const DBusString *nonce)
+{
+  DBusString buffer;
+  DBusString p;
+  size_t nleft;
+  dbus_bool_t result;
+  int n;
+
+  nleft = 16;
+
+  _dbus_string_init (&buffer);
+  _dbus_string_init (&p);
+//PENDING(kdab) replace errno by DBusError
+  while (nleft)
+    {
+      n = _dbus_read_socket (fd, &p, nleft);
+      if (n == -1 && _dbus_get_is_errno_eintr())
+        ;
+      else if (n == -1 && _dbus_get_is_errno_eagain_or_ewouldblock())
+        _dbus_sleep_milliseconds (100);
+      else if (n==-1)
+        {
+          _dbus_string_free (&p);
+          _dbus_string_free (&buffer);
+          return FALSE;
+        }
+      else if (!n)
+        {
+        _dbus_string_free (&p);
+        _dbus_string_free (&buffer);
+          errno = EIO;
+          return FALSE;
+        }
+      else
+        {
+          _dbus_string_append_len(&buffer, _dbus_string_get_const_data (&p), n);
+          nleft -= n;
+        }
+    }
+
+  result =  _dbus_string_equal_len (&buffer, nonce, 16);
+  if (!result)
+      errno = EACCES;
+
+  _dbus_string_free (&p);
+  _dbus_string_free (&buffer);
+
+  return result;
+}
+
+//PENDING(kdab) document
+dbus_bool_t
+_dbus_read_nonce (const DBusString *fname, DBusString *nonce)
+{
+  //PENDING(kdab) replace errno by DBusError
+  FILE *fp;
+  char buffer[17];
+  buffer[sizeof buffer - 1] = '\0';
+  size_t nread;
+  _dbus_verbose ("reading nonce from file: %s\n", _dbus_string_get_const_data (fname));
+
+
+  fp = fopen (_dbus_string_get_const_data (fname), "rb");
+  if (!fp)
+    return FALSE;
+  nread = fread (buffer, 1, sizeof buffer - 1, fp);
+  fclose (fp);
+  if (!nread)
+    {
+      errno = ENOFILE;
+      return FALSE;
+    }
+
+  if (!_dbus_string_append_len (nonce, buffer, sizeof buffer - 1 ))
+    {
+      errno = ENOMEM;
+      return FALSE;
+    }
+  return TRUE;
+}
+
+int
+_dbus_accept_with_nonce (int listen_fd, const DBusString *nonce)
+{
+  _dbus_assert (nonce != NULL);
+  int fd;
+  fd = _dbus_accept (listen_fd);
+  if (_dbus_socket_is_invalid (fd))
+    return fd;
+  if (_dbus_check_nonce(fd, nonce) != TRUE) {
+    _dbus_verbose ("nonce check failed. Closing socket.\n");
+    _dbus_close_socket(fd, NULL);
+    return -1;
+  }
+
+  return fd;
+}
+
+int
+_dbus_accept_with_noncefile (int listen_fd, const DBusString *noncefile)
+{
+  _dbus_assert (noncefile != NULL);
+  DBusString nonce;
+  _dbus_string_init (&nonce);
+  //PENDING(kdab): set better errors
+  if (_dbus_read_nonce (noncefile, &nonce) != TRUE)
+    return -1;
+  return _dbus_accept_with_nonce (listen_fd, &nonce);
+}
+
+dbus_bool_t
+_dbus_generate_noncefilename (DBusString *buf)
+{
+  dbus_bool_t ret;
+  DBusString randomStr;
+  ret = _dbus_string_init (&randomStr);
+  if (!ret)
+    return FALSE;
+  ret = _dbus_generate_random_ascii (&randomStr, 8);
+  if (!ret)
+    goto oom;
+  if (!_dbus_string_append (buf, _dbus_get_tmpdir())
+      || !_dbus_string_append (buf, DBUS_DIR_SEPARATOR "dbus_nonce-")
+      || !_dbus_string_append (buf, _dbus_string_get_const_data (&randomStr)) )
+    goto oom;
+
+  _dbus_string_free (&randomStr);
+  return TRUE;
+oom:
+  _dbus_string_free (&randomStr);
+  return FALSE;
+}
+
+int
+_dbus_generate_and_write_nonce (const DBusString *filename)
+{
+  DBusString nonce;
+  int ret;
+
+  _dbus_string_init (&nonce);
+
+  if (!_dbus_generate_random_bytes (&nonce, 16))
+    return -1;
+
+  ret = _dbus_write_to_file (_dbus_string_get_const_data (filename), _dbus_string_get_const_data (&nonce), 16);
+
+  _dbus_string_free (&nonce);
+
+  return ret;
+}
+
+dbus_bool_t
+_dbus_send_nonce(int fd, const DBusString *noncefile, DBusError *error)
+{
+  dbus_bool_t read_result;
+  int send_result;
+  size_t sendLen;
+  DBusString nonce;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  if (_dbus_string_get_length (noncefile) == 0)
+    return FALSE;
+
+  if ( !_dbus_string_init (&nonce) )
+    {
+      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+      return FALSE;
+  }
+
+  read_result = _dbus_read_nonce (noncefile, &nonce);
+
+  if (!read_result)
+    {
+      dbus_set_error (error,
+                      _dbus_error_from_errno (errno),
+                      "Could not read nonce from file %s (%s)",
+                      _dbus_string_get_const_data (noncefile), _dbus_strerror(errno));
+      _dbus_string_free (&nonce);
+      return FALSE;
+    }
+
+  send_result = _dbus_write_socket (fd, &nonce, 0, _dbus_string_get_length (&nonce));
+
+  _dbus_string_free (&nonce);
+
+  if (send_result == -1)
+  {
+    dbus_set_error (error,
+                    _dbus_error_from_errno (errno),
+                    "Failed to send nonce (fd=%d): %s",
+                    fd, _dbus_strerror(errno));
+    return FALSE;
+  }
+
+  return TRUE;
+}
+
+/** @} end of nonce */
diff --git a/dbus/dbus-nonce.h b/dbus/dbus-nonce.h
new file mode 100644 (file)
index 0000000..441a59e
--- /dev/null
@@ -0,0 +1,55 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-nonce.h  Nonce handling functions used by nonce-tcp (internal to D-Bus implementation)
+ *
+ * Copyright (C) 2009 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.net
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+#ifndef DBUS_NONCE_H
+#define DBUS_NONCE_H
+
+#include <dbus/dbus-macros.h>
+#include <dbus/dbus-types.h>
+#include <dbus/dbus-errors.h>
+#include <dbus/dbus-string.h>
+
+DBUS_BEGIN_DECLS
+
+dbus_bool_t _dbus_check_nonce (int fd,
+                               const DBusString *nonce);
+
+dbus_bool_t _dbus_read_nonce (const DBusString *fname,
+                              DBusString *nonce);
+
+int _dbus_accept_with_nonce (int listen_fd,
+                             const DBusString *nonce);
+
+int _dbus_accept_with_noncefile (int listen_fd,
+                                 const DBusString *noncefile);
+
+dbus_bool_t _dbus_generate_noncefilename (DBusString *buf);
+
+int _dbus_generate_and_write_nonce (const DBusString *filename);
+
+dbus_bool_t _dbus_send_nonce (int fd,
+                              const DBusString *noncefile,
+                              DBusError *error);
+
+DBUS_END_DECLS
+
+#endif /* DBUS_NONCE_H */
index 132fdb7..2c9d81c 100644 (file)
@@ -51,6 +51,7 @@ struct DBusServerSocket
   int *fds;          /**< File descriptor or -1 if disconnected. */
   DBusWatch **watch; /**< File descriptor watch. */
   char *socket_name; /**< Name of domain socket, to unlink if appropriate */
+  DBusString noncefile; /**< Nonce file used to authenticate clients */
 };
 
 static void
@@ -71,6 +72,11 @@ socket_finalize (DBusServer *server)
   dbus_free (socket_server->fds);
   dbus_free (socket_server->watch);
   dbus_free (socket_server->socket_name);
+  if (_dbus_string_get_length(&socket_server->noncefile) > 0)
+  {
+    _dbus_delete_file(&socket_server->noncefile, NULL);
+  }
+  _dbus_string_free (&socket_server->noncefile);
   dbus_free (server);
 }
 
@@ -82,8 +88,10 @@ handle_new_client_fd_and_unlock (DBusServer *server,
   DBusConnection *connection;
   DBusTransport *transport;
   DBusNewConnectionFunction new_connection_function;
+  DBusServerSocket* socket_server;
   void *new_connection_data;
   
+  socket_server = (DBusServerSocket*)server;
   _dbus_verbose ("Creating new client connection with fd %d\n", client_fd);
 
   HAVE_LOCK_CHECK (server);
@@ -179,7 +187,7 @@ socket_handle_watch (DBusWatch    *watch,
       
       listen_fd = dbus_watch_get_socket (watch);
 
-      client_fd = _dbus_accept (listen_fd);
+      client_fd = _dbus_accept_with_noncefile (listen_fd, &socket_server->noncefile);
       
       if (client_fd < 0)
         {
@@ -257,13 +265,15 @@ static const DBusServerVTable socket_vtable = {
  * @param fds list of file descriptors.
  * @param n_fds number of file descriptors
  * @param address the server's address
+ * @param noncefile the noncefile to use, NULL if without nonce
  * @returns the new server, or #NULL if no memory.
  * 
  */
 DBusServer*
 _dbus_server_new_for_socket (int              *fds,
                              int               n_fds,
-                             const DBusString *address)
+                             const DBusString *address,
+                             const DBusString *noncefile)
 {
   DBusServerSocket *socket_server;
   DBusServer *server;
@@ -302,6 +312,12 @@ _dbus_server_new_for_socket (int              *fds,
                                &socket_vtable, address))
     goto failed_2;
 
+  if (!_dbus_string_init (&socket_server->noncefile))
+    goto failed_2;
+
+  if (noncefile && !_dbus_string_copy (noncefile, 0, &socket_server->noncefile, 0))
+    goto failed_3;
+
   server = (DBusServer*)socket_server;
 
   SERVER_LOCK (server);
@@ -326,6 +342,8 @@ _dbus_server_new_for_socket (int              *fds,
   
   return (DBusServer*) socket_server;
 
+ failed_3:
+  _dbus_string_free (&socket_server->noncefile);
  failed_2:
   for (i = 0 ; i < n_fds ; i++)
     {
@@ -368,7 +386,8 @@ _dbus_server_new_for_tcp_socket (const char     *host,
                                  const char     *bind,
                                  const char     *port,
                                  const char     *family,
-                                 DBusError      *error)
+                                 DBusError      *error,
+                                 dbus_bool_t    use_nonce)
 {
   DBusServer *server;
   int *listen_fds = NULL;
@@ -376,6 +395,7 @@ _dbus_server_new_for_tcp_socket (const char     *host,
   DBusString address;
   DBusString host_str;
   DBusString port_str;
+  DBusString noncefile;
   
   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
 
@@ -412,7 +432,7 @@ _dbus_server_new_for_tcp_socket (const char     *host,
     }
 
   _dbus_string_init_const (&host_str, host);
-  if (!_dbus_string_append (&address, "tcp:host=") ||
+  if (!_dbus_string_append (&address, use_nonce ? "nonce-tcp:host=" : "tcp:host=") ||
       !_dbus_address_append_escaped (&address, &host_str) ||
       !_dbus_string_append (&address, ",port=") ||
       !_dbus_string_append (&address, _dbus_string_get_const_data(&port_str)))
@@ -428,7 +448,36 @@ _dbus_server_new_for_tcp_socket (const char     *host,
       goto failed_2;
     }
   
-  server = _dbus_server_new_for_socket (listen_fds, nlisten_fds, &address);
+  if (!_dbus_string_init (&noncefile))
+    {
+      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+      goto failed_2;
+    }
+
+  if (use_nonce)
+    {
+      if (!_dbus_generate_noncefilename (&noncefile))
+        {
+          dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+          goto failed_2;
+        }
+
+        if (_dbus_string_get_length(&noncefile) == 0 ||
+          !_dbus_string_append (&address, ",noncefile=") ||
+          !_dbus_address_append_escaped (&address, &noncefile))
+        {
+          dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+          goto failed_2;
+        }
+
+      if (_dbus_generate_and_write_nonce (&noncefile) != 0)
+        {
+          dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+          goto failed_2;
+        }
+    }
+
+  server = _dbus_server_new_for_socket (listen_fds, nlisten_fds, &address, &noncefile);
   if (server == NULL)
     {
       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
@@ -445,6 +494,7 @@ _dbus_server_new_for_tcp_socket (const char     *host,
   for (i = 0 ; i < nlisten_fds ; i++)
     _dbus_close_socket (listen_fds[i], NULL);
   dbus_free(listen_fds);
+  _dbus_string_free (&noncefile);
 
  failed_1:
   _dbus_string_free (&port_str);
@@ -457,7 +507,7 @@ _dbus_server_new_for_tcp_socket (const char     *host,
 
 /**
  * Tries to interpret the address entry for various socket-related
- * addresses (well, currently only tcp).
+ * addresses (well, currently only tcp and nonce-tcp).
  * 
  * Sets error if the result is not OK.
  * 
@@ -478,7 +528,7 @@ _dbus_server_listen_socket (DBusAddressEntry *entry,
   
   method = dbus_address_entry_get_method (entry);
   
-  if (strcmp (method, "tcp") == 0)
+  if (strcmp (method, "tcp") == 0 || strcmp (method, "nonce-tcp") == 0)
     {
       const char *host;
       const char *port;
@@ -491,7 +541,7 @@ _dbus_server_listen_socket (DBusAddressEntry *entry,
       family = dbus_address_entry_get_value (entry, "family");
 
       *server_p = _dbus_server_new_for_tcp_socket (host, bind, port,
-                                                   family, error);
+                                                   family, error, strcmp (method, "nonce-tcp") == 0 ? TRUE : FALSE);
 
       if (*server_p)
         {
index 5918658..891f56f 100644 (file)
@@ -30,12 +30,14 @@ DBUS_BEGIN_DECLS
 
 DBusServer* _dbus_server_new_for_socket           (int              *fds,
                                                    int               n_fds,
-                                                   const DBusString *address);
+                                                   const DBusString *address,
+                                                   const DBusString *noncefile);
 DBusServer* _dbus_server_new_for_tcp_socket       (const char       *host,
                                                    const char       *bind,
                                                    const char       *port,
                                                    const char       *family,
-                                                   DBusError        *error);
+                                                   DBusError        *error,
+                                                   dbus_bool_t      use_nonce);
 DBusServerListenResult _dbus_server_listen_socket (DBusAddressEntry  *entry,
                                                    DBusServer       **server_p,
                                                    DBusError         *error);
index 07800c8..597d0f8 100644 (file)
@@ -208,7 +208,7 @@ _dbus_server_new_for_domain_socket (const char     *path,
       goto failed_1;
     }
   
-  server = _dbus_server_new_for_socket (&listen_fd, 1, &address);
+  server = _dbus_server_new_for_socket (&listen_fd, 1, &address, 0);
   if (server == NULL)
     {
       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
index d6acc1e..ca37669 100644 (file)
@@ -25,8 +25,6 @@
 #include "dbus-internals.h"
 #include "dbus-server-win.h"
 #include "dbus-server-socket.h"
-#include "dbus-connection-internal.h"
-#include "dbus-sysdeps-win.h"
 
 /**
  * @defgroup DBusServerWin DBusServer implementations for Windows
@@ -52,13 +50,44 @@ _dbus_server_listen_platform_specific (DBusAddressEntry *entry,
                                        DBusServer      **server_p,
                                        DBusError        *error)
 {
-  /* don't handle any method yet, return NULL with the error unset, 
-   ** for a sample implementation see dbus-server-unix.c 
-   */
+  const char *method;
+
   *server_p  = NULL;
+
+  method = dbus_address_entry_get_method (entry);
+
+  if (strcmp (method, "nonce-tcp") == 0)
+    {
+      const char *host;
+      const char *port;
+      const char *bind;
+      const char *family;
+
+      host = dbus_address_entry_get_value (entry, "host");
+      bind = dbus_address_entry_get_value (entry, "bind");
+      port = dbus_address_entry_get_value (entry, "port");
+      family = dbus_address_entry_get_value (entry, "family");
+
+      *server_p = _dbus_server_new_for_tcp_socket (host, bind, port,
+                                                   family, error, TRUE);
+
+      if (*server_p)
+        {
+          _DBUS_ASSERT_ERROR_IS_CLEAR(error);
+          return DBUS_SERVER_LISTEN_OK;
+        }
+      else
+        {
+          _DBUS_ASSERT_ERROR_IS_SET(error);
+          return DBUS_SERVER_LISTEN_DID_NOT_CONNECT;
+        }
+    }
+  else
+    {
   _DBUS_ASSERT_ERROR_IS_CLEAR(error);
   return DBUS_SERVER_LISTEN_NOT_HANDLED;
 }
+}
 
 /** @} */
 
index e60e614..fc51709 100644 (file)
@@ -577,6 +577,11 @@ _dbus_write_socket_two (int               fd,
 #endif
 }
 
+dbus_bool_t
+_dbus_socket_is_invalid (int fd)
+{
+    return fd < 0 ? TRUE : FALSE;
+}
 
 /**
  * Thin wrapper around the read() system call that appends
@@ -1082,6 +1087,16 @@ _dbus_connect_tcp_socket (const char     *host,
                           const char     *family,
                           DBusError      *error)
 {
+    return _dbus_connect_tcp_socket_with_nonce (host, port, family, (const char*)NULL, error);
+}
+
+int
+_dbus_connect_tcp_socket_with_nonce (const char     *host,
+                                     const char     *port,
+                                     const char     *family,
+                                     const char     *noncefile,
+                                     DBusError      *error)
+{
   int saved_errno = 0;
   int fd = -1, res;
   struct addrinfo hints;
@@ -1159,12 +1174,24 @@ _dbus_connect_tcp_socket (const char     *host,
       return -1;
     }
 
+  if (noncefile != NULL)
+    {
+      DBusString noncefileStr;
+      dbus_bool_t ret;
+      _dbus_string_init_const (&noncefileStr, noncefile);
+      ret = _dbus_send_nonce (fd, &noncefileStr, error);
+      _dbus_string_free (&noncefileStr);
 
-  if (!_dbus_set_fd_nonblocking (fd, error))
+      if (!ret)
     {
       _dbus_close (fd, NULL);
-      fd = -1;
+          return -1;
+        }
+    }
 
+  if (!_dbus_set_fd_nonblocking (fd, error))
+    {
+      _dbus_close (fd, NULL);
       return -1;
     }
 
@@ -3881,6 +3908,35 @@ _dbus_get_is_errno_eagain_or_ewouldblock (void)
   return errno == EAGAIN || errno == EWOULDBLOCK;
 }
 
+int
+_dbus_write_to_file (const char* filename, const char* buf, size_t len)
+{
+  int filefd;
+  FILE *fp;
+  size_t written;
+
+  filefd = open (filename,
+                 (O_WRONLY|O_CREAT|O_EXCL|O_BINARY),
+                 (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP));
+  if (filefd == -1)
+    {
+      return -1;
+    }
+  fp = fdopen (filefd, "wb");
+  if (!fp)
+    {
+      int save_e = errno;
+      close (filefd);
+      errno = save_e;
+      return -1;
+    }
+
+  written = fwrite (buf, len, 1, fp);
+  fclose (fp);
+
+  return written == 1 ? 0 : -1;
+}
+
 /**
  *  Checks whether file descriptors may be passed via the socket
  *
index 7d3c7f6..f34e57f 100644 (file)
@@ -180,6 +180,7 @@ _dbus_pipe_close  (DBusPipe         *pipe,
  * @param count the amount of data to read
  * @returns the number of bytes read or -1
  */
+
 int
 _dbus_read_socket (int               fd,
                    DBusString       *buffer,
@@ -209,7 +210,7 @@ _dbus_read_socket (int               fd,
   if (bytes_read == SOCKET_ERROR)
        {
          DBUS_SOCKET_SET_ERRNO();
-         _dbus_verbose ("recv: failed: %s\n", _dbus_strerror (errno));
+         _dbus_verbose ("recv: failed: %s (%d)\n", _dbus_strerror (errno), errno);
          bytes_read = -1;
        }
        else
@@ -466,6 +467,12 @@ _dbus_write_socket_two (int               fd,
   return bytes_written;
 }
 
+dbus_bool_t
+_dbus_socket_is_invalid (int fd)
+{
+    return fd == INVALID_SOCKET ? TRUE : FALSE;
+}
+
 #if 0
 
 /**
@@ -1344,6 +1351,16 @@ _dbus_connect_tcp_socket (const char     *host,
                           const char     *family,
                           DBusError      *error)
 {
+  return _dbus_connect_tcp_socket_with_nonce (host, port, family, (const char*)NULL, error);
+}
+
+int
+_dbus_connect_tcp_socket_with_nonce (const char     *host,
+                                     const char     *port,
+                                     const char     *family,
+                                     const char     *noncefile,
+                                     DBusError      *error)
+{
   int fd = -1, res;
   struct addrinfo hints;
   struct addrinfo *ai, *tmp;
@@ -1414,7 +1431,7 @@ _dbus_connect_tcp_socket (const char     *host,
         }
       _DBUS_ASSERT_ERROR_IS_CLEAR(error);
 
-      if (connect (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) < 0)
+      if (connect (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) != 0)
         {
           closesocket(fd);
       fd = -1;
@@ -1435,12 +1452,32 @@ _dbus_connect_tcp_socket (const char     *host,
       return -1;
     }
 
+  if ( noncefile != NULL )
+    {
+      DBusString noncefileStr;
+      dbus_bool_t ret;
+      if (!_dbus_string_init (&noncefileStr) ||
+          !_dbus_string_append(&noncefileStr, noncefile))
+        {
+          closesocket (fd);
+          dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+          return -1;
+       }
+
+      ret = _dbus_send_nonce (fd, &noncefileStr, error);
 
-  if (!_dbus_set_fd_nonblocking (fd, error))
+      _dbus_string_free (&noncefileStr);
+
+      if (!ret)
     {
       closesocket (fd);
-      fd = -1;
+          return -1;
+        }
+    }
 
+  if (!_dbus_set_fd_nonblocking (fd, error) )
+    {
+      closesocket (fd);
       return -1;
     }
 
@@ -3632,6 +3669,7 @@ _dbus_win_warn_win_error (const char *message,
   _dbus_warn ("%s: %s\n", message, error.message);
   dbus_error_free (&error);
 }
+
 /** @} end of sysdeps-win */
 /* tests in dbus-sysdeps-util.c */
 
index e6ebfc6..ed118b0 100644 (file)
@@ -91,10 +91,12 @@ dbus_bool_t _dbus_file_exists (const char *filename);
 dbus_bool_t _dbus_get_config_file_name(DBusString *config_file, 
                                        char *s);
 
-
+int _dbus_connect_tcp_socket_with_nonce  (const char     *host,
+                                          const char     *port,
+                                          const char     *family,
+                                          const char     *noncefile,
+                                          DBusError      *error);
 
 #endif
 
 /** @} end of sysdeps-win.h */
-
-
index 739a454..999aade 100644 (file)
@@ -175,6 +175,8 @@ int _dbus_write_socket_with_unix_fds_two (int               fd,
                                           const int        *fds,
                                           int               n_fds);
 
+dbus_bool_t _dbus_socket_is_invalid (int              fd);
+
 int _dbus_connect_tcp_socket  (const char     *host,
                                const char     *port,
                                const char     *family,
@@ -540,6 +542,24 @@ dbus_pid_t    _dbus_getpid (void);
 
 void _dbus_flush_caches (void);
 
+dbus_bool_t _dbus_generate_noncefilename (DBusString *buf);
+
+int _dbus_generate_and_write_nonce (const DBusString *filename);
+
+int _dbus_generate_nonce (char *buffer, size_t nbytes);
+
+dbus_bool_t _dbus_check_nonce (int fd, const DBusString *nonce);
+
+dbus_bool_t dbus_read_nonce (const DBusString *noncefile, DBusString *nonce);
+
+int _dbus_accept_with_nonce (int listen_fd, const DBusString *nonce);
+
+int _dbus_accept_with_noncefile (int listen_fd, const DBusString *noncefile);
+
+dbus_bool_t _dbus_send_nonce (int fd, const DBusString *noncefile, DBusError* error);
+
+int _dbus_write_to_file (const char *filename, const char *buf, size_t len);
+
 /** @} */
 
 DBUS_END_DECLS
index 4b88af7..96a7eba 100644 (file)
@@ -1297,6 +1297,7 @@ _dbus_transport_new_for_socket (int               fd,
  * @param host the host to connect to
  * @param port the port to connect to
  * @param family the address family to connect to
+ * @param path to nonce file
  * @param error location to store reason for failure.
  * @returns a new transport, or #NULL on failure.
  */
@@ -1304,6 +1305,7 @@ DBusTransport*
 _dbus_transport_new_for_tcp_socket (const char     *host,
                                     const char     *port,
                                     const char     *family,
+                                    const char     *noncefile,
                                     DBusError      *error)
 {
   int fd;
@@ -1321,7 +1323,7 @@ _dbus_transport_new_for_tcp_socket (const char     *host,
   if (host == NULL)
     host = "localhost";
 
-  if (!_dbus_string_append (&address, "tcp:"))
+  if (!_dbus_string_append (&address, noncefile ? "nonce-tcp:" : "tcp:"))
     goto error;
 
   if (!_dbus_string_append (&address, "host=") ||
@@ -1337,7 +1339,12 @@ _dbus_transport_new_for_tcp_socket (const char     *host,
        !_dbus_string_append (&address, family)))
     goto error;
 
-  fd = _dbus_connect_tcp_socket (host, port, family, error);
+  if (noncefile != NULL &&
+      (!_dbus_string_append (&address, "noncefile=") ||
+       !_dbus_string_append (&address, noncefile)))
+    goto error;
+
+  fd = _dbus_connect_tcp_socket_with_nonce (host, port, family, noncefile, error);
   if (fd < 0)
     {
       _DBUS_ASSERT_ERROR_IS_SET (error);
@@ -1381,26 +1388,38 @@ _dbus_transport_open_socket(DBusAddressEntry  *entry,
                             DBusError         *error)
 {
   const char *method;
+  dbus_bool_t isTcp;
+  dbus_bool_t isNonceTcp;
   
   method = dbus_address_entry_get_method (entry);
   _dbus_assert (method != NULL);
 
-  if (strcmp (method, "tcp") == 0)
+  isTcp = strcmp (method, "tcp") == 0;
+  isNonceTcp = strcmp (method, "nonce-tcp") == 0;
+
+  if (isTcp || isNonceTcp)
     {
       const char *host = dbus_address_entry_get_value (entry, "host");
       const char *port = dbus_address_entry_get_value (entry, "port");
       const char *family = dbus_address_entry_get_value (entry, "family");
+      const char *noncefile = dbus_address_entry_get_value (entry, "noncefile");
+
+      if ((isNonceTcp == TRUE) != (noncefile != NULL)) {
+          _dbus_set_bad_address (error, method, "noncefile", NULL);
+          return DBUS_TRANSPORT_OPEN_BAD_ADDRESS;
+      }
 
       if (port == NULL)
         {
-          _dbus_set_bad_address (error, "tcp", "port", NULL);
+          _dbus_set_bad_address (error, method, "port", NULL);
           return DBUS_TRANSPORT_OPEN_BAD_ADDRESS;
         }
 
-      *transport_p = _dbus_transport_new_for_tcp_socket (host, port, family, error);
+      *transport_p = _dbus_transport_new_for_tcp_socket (host, port, family, noncefile, error);
       if (*transport_p == NULL)
         {
-          _DBUS_ASSERT_ERROR_IS_SET (error);
+          //PENDING(kdab)
+          //_DBUS_ASSERT_ERROR_IS_SET (error);
           return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT;
         }
       else
index eb83326..8aefae3 100644 (file)
@@ -33,6 +33,7 @@ DBusTransport*          _dbus_transport_new_for_socket     (int                f
 DBusTransport*          _dbus_transport_new_for_tcp_socket (const char        *host,
                                                             const char        *port,
                                                             const char        *family,
+                                                            const char        *noncefile,
                                                             DBusError         *error);
 DBusTransportOpenResult _dbus_transport_open_socket        (DBusAddressEntry  *entry,
                                                             DBusTransport    **transport_p,
index 6a99b07..cd28204 100644 (file)
@@ -50,8 +50,39 @@ _dbus_transport_open_platform_specific (DBusAddressEntry  *entry,
                                         DBusTransport    **transport_p,
                                         DBusError         *error)
 {
+  const char *method;
+
+  method = dbus_address_entry_get_method (entry);
+  _dbus_assert (method != NULL);
+
+  if (strcmp (method, "nonce-tcp") != 0)
+    {
   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
   return DBUS_TRANSPORT_OPEN_NOT_HANDLED;
 }
 
+  const char *host = dbus_address_entry_get_value (entry, "host");
+  const char *port = dbus_address_entry_get_value (entry, "port");
+  const char *family = dbus_address_entry_get_value (entry, "family");
+  const char *noncefile = dbus_address_entry_get_value (entry, "noncefile");
+
+  if (port == NULL)
+    {
+      _dbus_set_bad_address (error, "nonce-tcp", "port", NULL);
+      return DBUS_TRANSPORT_OPEN_BAD_ADDRESS;
+    }
+
+  *transport_p = _dbus_transport_new_for_tcp_socket (host, port, family, noncefile, error);
+  if (*transport_p == NULL)
+    {
+      _DBUS_ASSERT_ERROR_IS_SET (error);
+      return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT;
+    }
+  else
+    {
+      _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+      return DBUS_TRANSPORT_OPEN_OK;
+    }
+}
+
 /** @} */