From: Frank Osterfeld Date: Wed, 21 Oct 2009 16:52:49 +0000 (+0300) Subject: The current state of the nonce-tcp implementation X-Git-Tag: dbus-1.3.1~175 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=5e2a99c12c7e3531d908ed4fca82caca9cb02825;p=platform%2Fupstream%2Fdbus.git The current state of the nonce-tcp implementation 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. --- diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index 33a0a76..7b74420 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -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 diff --git a/cmake/dbus/CMakeLists.txt b/cmake/dbus/CMakeLists.txt index ce113a2..c1c2251 100644 --- a/cmake/dbus/CMakeLists.txt +++ b/cmake/dbus/CMakeLists.txt @@ -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 diff --git a/dbus/Makefile.am b/dbus/Makefile.am index 5f8d703..c85556a 100644 --- a/dbus/Makefile.am +++ b/dbus/Makefile.am @@ -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 index 0000000..e8de059 --- /dev/null +++ b/dbus/dbus-nonce.c @@ -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 + +#ifdef HAVE_ERRNO_H +#include +#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 index 0000000..441a59e --- /dev/null +++ b/dbus/dbus-nonce.h @@ -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 +#include +#include +#include + +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 */ diff --git a/dbus/dbus-server-socket.c b/dbus/dbus-server-socket.c index 132fdb7..2c9d81c 100644 --- a/dbus/dbus-server-socket.c +++ b/dbus/dbus-server-socket.c @@ -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) { diff --git a/dbus/dbus-server-socket.h b/dbus/dbus-server-socket.h index 5918658..891f56f 100644 --- a/dbus/dbus-server-socket.h +++ b/dbus/dbus-server-socket.h @@ -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); diff --git a/dbus/dbus-server-unix.c b/dbus/dbus-server-unix.c index 07800c8..597d0f8 100644 --- a/dbus/dbus-server-unix.c +++ b/dbus/dbus-server-unix.c @@ -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); diff --git a/dbus/dbus-server-win.c b/dbus/dbus-server-win.c index d6acc1e..ca37669 100644 --- a/dbus/dbus-server-win.c +++ b/dbus/dbus-server-win.c @@ -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; } +} /** @} */ diff --git a/dbus/dbus-sysdeps-unix.c b/dbus/dbus-sysdeps-unix.c index e60e614..fc51709 100644 --- a/dbus/dbus-sysdeps-unix.c +++ b/dbus/dbus-sysdeps-unix.c @@ -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 * diff --git a/dbus/dbus-sysdeps-win.c b/dbus/dbus-sysdeps-win.c index 7d3c7f6..f34e57f 100644 --- a/dbus/dbus-sysdeps-win.c +++ b/dbus/dbus-sysdeps-win.c @@ -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 */ diff --git a/dbus/dbus-sysdeps-win.h b/dbus/dbus-sysdeps-win.h index e6ebfc6..ed118b0 100644 --- a/dbus/dbus-sysdeps-win.h +++ b/dbus/dbus-sysdeps-win.h @@ -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 */ - - diff --git a/dbus/dbus-sysdeps.h b/dbus/dbus-sysdeps.h index 739a454..999aade 100644 --- a/dbus/dbus-sysdeps.h +++ b/dbus/dbus-sysdeps.h @@ -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 diff --git a/dbus/dbus-transport-socket.c b/dbus/dbus-transport-socket.c index 4b88af7..96a7eba 100644 --- a/dbus/dbus-transport-socket.c +++ b/dbus/dbus-transport-socket.c @@ -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 diff --git a/dbus/dbus-transport-socket.h b/dbus/dbus-transport-socket.h index eb83326..8aefae3 100644 --- a/dbus/dbus-transport-socket.h +++ b/dbus/dbus-transport-socket.h @@ -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, diff --git a/dbus/dbus-transport-win.c b/dbus/dbus-transport-win.c index 6a99b07..cd28204 100644 --- a/dbus/dbus-transport-win.c +++ b/dbus/dbus-transport-win.c @@ -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; + } +} + /** @} */