From e45e4382274149ca60c11f068ccca719f3598074 Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Sun, 6 Apr 2003 18:03:03 +0000 Subject: 2003-04-06 Havoc Pennington * bus/bus.c (bus_context_new): fix wrong handling of server_data_slot_unref() in the error case. * dbus/dbus-internals.h (_dbus_assert): change so it passes "(condition) != 0" to _dbus_real_assert so that "_dbus_assert (pointer)" doesn't cause a warning * bus/main.c (main): accept --print-address option to print out the message bus address * dbus/dbus-sysdeps.c (_dbus_generate_random_ascii): export this * dbus/dbus-transport.c (_dbus_transport_open): special error for "tmpdir" option to unix: address on client side * dbus/dbus-server.c (dbus_server_listen): handle "tmpdir" option to unix: address * configure.in (TEST_SOCKET_DIR): locate a temporary directory we can use to create sockets in the test suite. * bus/main.c (signal_handler): on SIGTERM, exit the daemon cleanly. To be used for testing. * dbus/dbus-spawn.c (babysit): use _dbus_set_signal_handler() * dbus/dbus-sysdeps.c (_dbus_set_signal_handler): new * dbus/dbus-server-debug-pipe.c (_dbus_transport_debug_pipe_new): handle trying to call this when there's no servers active --- dbus/dbus-errors.c | 2 +- dbus/dbus-internals.h | 4 +- dbus/dbus-server-debug-pipe.c | 8 +- dbus/dbus-server.c | 73 ++++++++++++++--- dbus/dbus-spawn.c | 12 +-- dbus/dbus-sysdeps.c | 186 ++++++++++++++++++++++++++---------------- dbus/dbus-sysdeps.h | 8 ++ dbus/dbus-transport.c | 11 ++- 8 files changed, 205 insertions(+), 99 deletions(-) (limited to 'dbus') diff --git a/dbus/dbus-errors.c b/dbus/dbus-errors.c index 7e3aa69b..0f70bcb1 100644 --- a/dbus/dbus-errors.c +++ b/dbus/dbus-errors.c @@ -93,7 +93,7 @@ message_from_error (const char *error) else if (strcmp (error, DBUS_ERROR_AUTH_FAILED) == 0) return "Could not authenticate to server"; else if (strcmp (error, DBUS_ERROR_NO_SERVER) == 0) - return "No server"; + return "No server available at address"; else if (strcmp (error, DBUS_ERROR_TIMEOUT) == 0) return "Connection timed out"; else if (strcmp (error, DBUS_ERROR_NO_NETWORK) == 0) diff --git a/dbus/dbus-internals.h b/dbus/dbus-internals.h index dbfd0681..f37009b9 100644 --- a/dbus/dbus-internals.h +++ b/dbus/dbus-internals.h @@ -1,7 +1,7 @@ /* -*- mode: C; c-file-style: "gnu" -*- */ /* dbus-internals.h random utility stuff (internal to D-BUS implementation) * - * Copyright (C) 2002 Red Hat, Inc. + * Copyright (C) 2002, 2003 Red Hat, Inc. * * Licensed under the Academic Free License version 1.2 * @@ -81,7 +81,7 @@ void _dbus_real_assert (dbus_bool_t condition, const char *file, int line); #define _dbus_assert(condition) \ - _dbus_real_assert ((condition), #condition, __FILE__, __LINE__) + _dbus_real_assert ((condition) != 0, #condition, __FILE__, __LINE__) #endif /* !DBUS_DISABLE_ASSERT */ #ifdef DBUS_DISABLE_ASSERT diff --git a/dbus/dbus-server-debug-pipe.c b/dbus/dbus-server-debug-pipe.c index 905349be..151e32b8 100644 --- a/dbus/dbus-server-debug-pipe.c +++ b/dbus/dbus-server-debug-pipe.c @@ -220,13 +220,19 @@ _dbus_transport_debug_pipe_new (const char *server_name, DBusString address; _DBUS_ASSERT_ERROR_IS_CLEAR (error); + + if (server_pipe_hash == NULL) + { + dbus_set_error (error, DBUS_ERROR_NO_SERVER, NULL); + return NULL; + } server = _dbus_hash_table_lookup_string (server_pipe_hash, server_name); if (server == NULL || ((DBusServerDebugPipe*)server)->disconnected) { - dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS, NULL); + dbus_set_error (error, DBUS_ERROR_NO_SERVER, NULL); return NULL; } diff --git a/dbus/dbus-server.c b/dbus/dbus-server.c index 566e9178..3f877a0f 100644 --- a/dbus/dbus-server.c +++ b/dbus/dbus-server.c @@ -305,18 +305,68 @@ dbus_server_listen (const char *address, if (strcmp (method, "unix") == 0) { const char *path = dbus_address_entry_get_value (entries[i], "path"); - - if (path == NULL) + const char *tmpdir = dbus_address_entry_get_value (entries[i], "tmpdir"); + + if (path == NULL && tmpdir == NULL) { address_problem_type = "unix"; - address_problem_field = "path"; + address_problem_field = "path or tmpdir"; goto bad_address; } - server = _dbus_server_new_for_domain_socket (path, error); + if (path && tmpdir) + { + address_problem_other = "cannot specify both \"path\" and \"tmpdir\" at the same time"; + goto bad_address; + } - if (server) - break; + if (tmpdir != NULL) + { + DBusString full_path; + DBusString filename; + + if (!_dbus_string_init (&full_path)) + { + dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); + goto out; + } + + if (!_dbus_string_init (&filename)) + { + _dbus_string_free (&full_path); + dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); + goto out; + } + + if (!_dbus_string_append (&filename, + "dbus-") || + !_dbus_generate_random_ascii (&filename, 10) || + !_dbus_string_append (&full_path, tmpdir) || + !_dbus_concat_dir_and_file (&full_path, &filename)) + { + _dbus_string_free (&full_path); + _dbus_string_free (&filename); + dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); + goto out; + } + + /* FIXME - we will unconditionally unlink() the path. + * unlink() does not follow symlinks, but would like + * independent confirmation this is safe enough. See + * also _dbus_listen_unix_socket() and comments therein. + */ + + server = + _dbus_server_new_for_domain_socket (_dbus_string_get_const_data (&full_path), + error); + + _dbus_string_free (&full_path); + _dbus_string_free (&filename); + } + else + { + server = _dbus_server_new_for_domain_socket (path, error); + } } else if (strcmp (method, "tcp") == 0) { @@ -361,9 +411,6 @@ dbus_server_listen (const char *address, } server = _dbus_server_debug_new (name, error); - - if (server) - break; } else if (strcmp (method, "debug-pipe") == 0) { @@ -377,9 +424,6 @@ dbus_server_listen (const char *address, } server = _dbus_server_debug_pipe_new (name, error); - - if (server) - break; } #endif else @@ -387,7 +431,12 @@ dbus_server_listen (const char *address, address_problem_other = "Unknown address type (examples of valid types are \"unix\" and \"tcp\")"; goto bad_address; } + + if (server) + break; } + + out: dbus_address_entries_free (entries); return server; diff --git a/dbus/dbus-spawn.c b/dbus/dbus-spawn.c index 2273a4e3..87e1ffc2 100644 --- a/dbus/dbus-spawn.c +++ b/dbus/dbus-spawn.c @@ -916,9 +916,7 @@ babysit_signal_handler (int signo) static void babysit (pid_t grandchild_pid, int parent_pipe) -{ - struct sigaction act; - sigset_t empty_mask; +{ int sigchld_pipe[2]; /* I thought SIGCHLD would just wake up the poll, but @@ -933,12 +931,8 @@ babysit (pid_t grandchild_pid, } babysit_sigchld_pipe = sigchld_pipe[WRITE_END]; - - sigemptyset (&empty_mask); - act.sa_handler = babysit_signal_handler; - act.sa_mask = empty_mask; - act.sa_flags = 0; - sigaction (SIGCHLD, &act, 0); + + _dbus_set_signal_handler (SIGCHLD, babysit_signal_handler); write_pid (parent_pipe, grandchild_pid); diff --git a/dbus/dbus-sysdeps.c b/dbus/dbus-sysdeps.c index 3588f762..7a389956 100644 --- a/dbus/dbus-sysdeps.c +++ b/dbus/dbus-sysdeps.c @@ -2007,36 +2007,6 @@ _dbus_file_get_contents (DBusString *str, } } -static dbus_bool_t -append_unique_chars (DBusString *str) -{ - static const char letters[] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; - int i; - int len; - -#define N_UNIQUE_CHARS 8 - - if (!_dbus_generate_random_bytes (str, N_UNIQUE_CHARS)) - return FALSE; - - len = _dbus_string_get_length (str); - i = len - N_UNIQUE_CHARS; - while (i < len) - { - _dbus_string_set_byte (str, i, - letters[_dbus_string_get_byte (str, i) % - (sizeof (letters) - 1)]); - - ++i; - } - - _dbus_assert (_dbus_string_validate_ascii (str, len - N_UNIQUE_CHARS, - N_UNIQUE_CHARS)); - - return TRUE; -} - /** * Writes a string out to a file. If the file exists, * it will be atomically overwritten by the new data. @@ -2083,8 +2053,9 @@ _dbus_string_save_to_file (const DBusString *str, dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); return FALSE; } - - if (!append_unique_chars (&tmp_filename)) + +#define N_TMP_FILENAME_RANDOM_BYTES 8 + if (!_dbus_generate_random_ascii (&tmp_filename, N_TMP_FILENAME_RANDOM_BYTES)) { dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); return FALSE; @@ -2487,13 +2458,52 @@ _dbus_directory_close (DBusDirIter *iter) dbus_free (iter); } +static dbus_bool_t +pseudorandom_generate_random_bytes (DBusString *str, + int n_bytes) +{ + int old_len; + unsigned long tv_usec; + int i; + + old_len = _dbus_string_get_length (str); + + /* fall back to pseudorandom */ + _dbus_verbose ("Falling back to pseudorandom for %d bytes\n", + n_bytes); + + _dbus_get_current_time (NULL, &tv_usec); + srand (tv_usec); + + i = 0; + while (i < n_bytes) + { + double r; + unsigned int b; + + r = rand (); + b = (r / (double) RAND_MAX) * 255.0; + + if (!_dbus_string_append_byte (str, b)) + goto failed; + + ++i; + } + + return TRUE; + + failed: + _dbus_string_set_length (str, old_len); + return FALSE; +} + /** * Generates the given number of random bytes, * using the best mechanism we can come up with. * * @param str the string * @param n_bytes the number of random bytes to append to string - * @returns #TRUE on success, #FALSE if no memory or other failure + * @returns #TRUE on success, #FALSE if no memory */ dbus_bool_t _dbus_generate_random_bytes (DBusString *str, @@ -2501,6 +2511,12 @@ _dbus_generate_random_bytes (DBusString *str, { int old_len; int fd; + + /* FALSE return means "no memory", if it could + * mean something else then we'd need to return + * a DBusError. So we always fall back to pseudorandom + * if the I/O fails. + */ old_len = _dbus_string_get_length (str); fd = -1; @@ -2508,52 +2524,58 @@ _dbus_generate_random_bytes (DBusString *str, /* note, urandom on linux will fall back to pseudorandom */ fd = open ("/dev/urandom", O_RDONLY); if (fd < 0) + return pseudorandom_generate_random_bytes (str, n_bytes); + + if (_dbus_read (fd, str, n_bytes) != n_bytes) { - unsigned long tv_usec; - int i; + close (fd); + _dbus_string_set_length (str, old_len); + return pseudorandom_generate_random_bytes (str, n_bytes); + } - /* fall back to pseudorandom */ - _dbus_verbose ("Falling back to pseudorandom for %d bytes\n", - n_bytes); - - _dbus_get_current_time (NULL, &tv_usec); - srand (tv_usec); - - i = 0; - while (i < n_bytes) - { - double r; - unsigned int b; - - r = rand (); - b = (r / (double) RAND_MAX) * 255.0; - - if (!_dbus_string_append_byte (str, b)) - goto failed; - - ++i; - } + _dbus_verbose ("Read %d bytes from /dev/urandom\n", + n_bytes); + + close (fd); + + return TRUE; +} - return TRUE; - } - else +/** + * Generates the given number of random bytes, where the bytes are + * chosen from the alphanumeric ASCII subset. + * + * @param str the string + * @param n_bytes the number of random ASCII bytes to append to string + * @returns #TRUE on success, #FALSE if no memory or other failure + */ +dbus_bool_t +_dbus_generate_random_ascii (DBusString *str, + int n_bytes) +{ + static const char letters[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz"; + int i; + int len; + + if (!_dbus_generate_random_bytes (str, n_bytes)) + return FALSE; + + len = _dbus_string_get_length (str); + i = len - n_bytes; + while (i < len) { - if (_dbus_read (fd, str, n_bytes) != n_bytes) - goto failed; - - _dbus_verbose ("Read %d bytes from /dev/urandom\n", - n_bytes); - - close (fd); + _dbus_string_set_byte (str, i, + letters[_dbus_string_get_byte (str, i) % + (sizeof (letters) - 1)]); - return TRUE; + ++i; } - failed: - _dbus_string_set_length (str, old_len); - if (fd >= 0) - close (fd); - return FALSE; + _dbus_assert (_dbus_string_validate_ascii (str, len - n_bytes, + n_bytes)); + + return TRUE; } /** @@ -3005,6 +3027,26 @@ _dbus_change_identity (unsigned long uid, return TRUE; } +/** Installs a UNIX signal handler + * + * @param sig the signal to handle + * @param handler the handler + */ +void +_dbus_set_signal_handler (int sig, + DBusSignalHandler handler) +{ + struct sigaction act; + sigset_t empty_mask; + + sigemptyset (&empty_mask); + act.sa_handler = handler; + act.sa_mask = empty_mask; + act.sa_flags = 0; + sigaction (sig, &act, 0); +} + + #ifdef DBUS_BUILD_TESTS #include static void diff --git a/dbus/dbus-sysdeps.h b/dbus/dbus-sysdeps.h index 77d54c8c..933e2775 100644 --- a/dbus/dbus-sysdeps.h +++ b/dbus/dbus-sysdeps.h @@ -180,6 +180,8 @@ void _dbus_directory_close (DBusDirIter *iter); dbus_bool_t _dbus_generate_random_bytes (DBusString *str, int n_bytes); +dbus_bool_t _dbus_generate_random_ascii (DBusString *str, + int n_bytes); const char *_dbus_errno_to_string (int errnum); const char* _dbus_error_from_errno (int error_number); @@ -220,6 +222,12 @@ dbus_bool_t _dbus_change_identity (unsigned long uid, unsigned long gid, DBusError *error); +typedef void (* DBusSignalHandler) (int sig); + +void _dbus_set_signal_handler (int sig, + DBusSignalHandler handler); + + DBUS_END_DECLS; #endif /* DBUS_SYSDEPS_H */ diff --git a/dbus/dbus-transport.c b/dbus/dbus-transport.c index e56c8b0c..d074480a 100644 --- a/dbus/dbus-transport.c +++ b/dbus/dbus-transport.c @@ -235,7 +235,14 @@ _dbus_transport_open (const char *address, if (strcmp (method, "unix") == 0) { const char *path = dbus_address_entry_get_value (entries[i], "path"); + const char *tmpdir = dbus_address_entry_get_value (entries[i], "tmpdir"); + if (tmpdir != NULL) + { + address_problem_other = "cannot use the \"tmpdir\" option for an address to connect to, only in an address to listen on"; + goto bad_address; + } + if (path == NULL) { address_problem_type = "unix"; @@ -243,7 +250,7 @@ _dbus_transport_open (const char *address, goto bad_address; } - transport = _dbus_transport_new_for_domain_socket (path, error); + transport = _dbus_transport_new_for_domain_socket (path, error); } else if (strcmp (method, "tcp") == 0) { @@ -309,7 +316,7 @@ _dbus_transport_open (const char *address, if (transport) break; } - + dbus_address_entries_free (entries); return transport; -- cgit