X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gio%2Fgdbusaddress.c;h=8c1d31c76876e3d64c8f7b22f9bf191f76c763f4;hb=b8c13a01b6bd5601eb3519dd3b20daed4bbc2e72;hp=b9509ef21153a6c8497590903ace8bf32129a0a2;hpb=4143842eb47c1f38b2b4742b0928e4049e38afb9;p=platform%2Fupstream%2Fglib.git diff --git a/gio/gdbusaddress.c b/gio/gdbusaddress.c index b9509ef..8c1d31c 100644 --- a/gio/gdbusaddress.c +++ b/gio/gdbusaddress.c @@ -37,11 +37,19 @@ #include "giostream.h" #include "gasyncresult.h" #include "gsimpleasyncresult.h" +#include "glib-private.h" #include "gdbusprivate.h" +#include "giomodule-priv.h" +#include "gdbusdaemon.h" #ifdef G_OS_UNIX #include -#include +#endif + +#ifdef G_OS_WIN32 +#include +#include +#include #endif #include "glibintl.h" @@ -443,7 +451,7 @@ _g_dbus_address_parse_entry (const gchar *address_entry, g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, - _("Address element `%s', does not contain a colon (:)"), + _("Address element `%s' does not contain a colon (:)"), address_entry); goto out; } @@ -464,7 +472,7 @@ _g_dbus_address_parse_entry (const gchar *address_entry, g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, - _("Key/Value pair %d, `%s', in address element `%s', does not contain an equal sign"), + _("Key/Value pair %d, `%s', in address element `%s' does not contain an equal sign"), n, kv_pair, address_entry); @@ -1015,6 +1023,14 @@ get_session_address_dbus_launch (GError **error) restore_dbus_verbose = FALSE; old_dbus_verbose = NULL; + /* Don't run binaries as root if we're setuid. */ + if (GLIB_PRIVATE_CALL (g_check_setuid) ()) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, + _("Cannot spawn a message bus when setuid")); + goto out; + } + machine_id = _g_dbus_get_machine_id (error); if (machine_id == NULL) { @@ -1055,36 +1071,12 @@ get_session_address_dbus_launch (GError **error) &exit_status, error)) { - g_prefix_error (error, _("Error spawning command line `%s': "), command_line); - goto out; - } - - if (!WIFEXITED (exit_status)) - { - gchar *escaped_stderr; - escaped_stderr = g_strescape (launch_stderr, ""); - g_set_error (error, - G_IO_ERROR, - G_IO_ERROR_FAILED, - _("Abnormal program termination spawning command line `%s': %s"), - command_line, - escaped_stderr); - g_free (escaped_stderr); goto out; } - if (WEXITSTATUS (exit_status) != 0) + if (!g_spawn_check_exit_status (exit_status, error)) { - gchar *escaped_stderr; - escaped_stderr = g_strescape (launch_stderr, ""); - g_set_error (error, - G_IO_ERROR, - G_IO_ERROR_FAILED, - _("Command line `%s' exited with non-zero exit status %d: %s"), - command_line, - WEXITSTATUS (exit_status), - escaped_stderr); - g_free (escaped_stderr); + g_prefix_error (error, _("Error spawning command line `%s': "), command_line); goto out; } @@ -1138,17 +1130,311 @@ get_session_address_dbus_launch (GError **error) } #endif +#ifdef G_OS_WIN32 + +#define DBUS_DAEMON_ADDRESS_INFO "DBusDaemonAddressInfo" +#define DBUS_DAEMON_MUTEX "DBusDaemonMutex" +#define UNIQUE_DBUS_INIT_MUTEX "UniqueDBusInitMutex" +#define DBUS_AUTOLAUNCH_MUTEX "DBusAutolaunchMutex" + +static void +release_mutex (HANDLE mutex) +{ + ReleaseMutex (mutex); + CloseHandle (mutex); +} + +static HANDLE +acquire_mutex (const char *mutexname) +{ + HANDLE mutex; + DWORD res; + + mutex = CreateMutexA (NULL, FALSE, mutexname); + if (!mutex) + return 0; + + res = WaitForSingleObject (mutex, INFINITE); + switch (res) + { + case WAIT_ABANDONED: + release_mutex (mutex); + return 0; + case WAIT_FAILED: + case WAIT_TIMEOUT: + return 0; + } + + return mutex; +} + +static gboolean +is_mutex_owned (const char *mutexname) +{ + HANDLE mutex; + gboolean res = FALSE; + + mutex = CreateMutexA (NULL, FALSE, mutexname); + if (WaitForSingleObject (mutex, 10) == WAIT_TIMEOUT) + res = TRUE; + else + ReleaseMutex (mutex); + CloseHandle (mutex); + + return res; +} + +static char * +read_shm (const char *shm_name) +{ + HANDLE shared_mem; + char *shared_data; + char *res; + int i; + + res = NULL; + + for (i = 0; i < 20; i++) + { + shared_mem = OpenFileMappingA (FILE_MAP_READ, FALSE, shm_name); + if (shared_mem != 0) + break; + Sleep (100); + } + + if (shared_mem != 0) + { + shared_data = MapViewOfFile (shared_mem, FILE_MAP_READ, 0, 0, 0); + if (shared_data != NULL) + { + res = g_strdup (shared_data); + UnmapViewOfFile (shared_data); + } + CloseHandle (shared_mem); + } + + return res; +} + +static HANDLE +set_shm (const char *shm_name, const char *value) +{ + HANDLE shared_mem; + char *shared_data; + + shared_mem = CreateFileMappingA (INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, + 0, strlen (value) + 1, shm_name); + if (shared_mem == 0) + return 0; + + shared_data = MapViewOfFile (shared_mem, FILE_MAP_WRITE, 0, 0, 0 ); + if (shared_data == NULL) + return 0; + + strcpy (shared_data, value); + + UnmapViewOfFile (shared_data); + + return shared_mem; +} + +/* These keep state between publish_session_bus and unpublish_session_bus */ +static HANDLE published_daemon_mutex; +static HANDLE published_shared_mem; + +static gboolean +publish_session_bus (const char *address) +{ + HANDLE init_mutex; + + init_mutex = acquire_mutex (UNIQUE_DBUS_INIT_MUTEX); + + published_daemon_mutex = CreateMutexA (NULL, FALSE, DBUS_DAEMON_MUTEX); + if (WaitForSingleObject (published_daemon_mutex, 10 ) != WAIT_OBJECT_0) + { + release_mutex (init_mutex); + CloseHandle (published_daemon_mutex); + published_daemon_mutex = NULL; + return FALSE; + } + + published_shared_mem = set_shm (DBUS_DAEMON_ADDRESS_INFO, address); + if (!published_shared_mem) + { + release_mutex (init_mutex); + CloseHandle (published_daemon_mutex); + published_daemon_mutex = NULL; + return FALSE; + } + + release_mutex (init_mutex); + return TRUE; +} + +static void +unpublish_session_bus (void) +{ + HANDLE init_mutex; + + init_mutex = acquire_mutex (UNIQUE_DBUS_INIT_MUTEX); + + CloseHandle (published_shared_mem); + published_shared_mem = NULL; + + release_mutex (published_daemon_mutex); + published_daemon_mutex = NULL; + + release_mutex (init_mutex); +} + +static void +wait_console_window (void) +{ + FILE *console = fopen ("CONOUT$", "w"); + + SetConsoleTitleW (L"gdbus-daemon output. Type any character to close this window."); + fprintf (console, _("(Type any character to close this window)\n")); + fflush (console); + _getch (); +} + +static void +open_console_window (void) +{ + if (((HANDLE) _get_osfhandle (fileno (stdout)) == INVALID_HANDLE_VALUE || + (HANDLE) _get_osfhandle (fileno (stderr)) == INVALID_HANDLE_VALUE) && AllocConsole ()) + { + if ((HANDLE) _get_osfhandle (fileno (stdout)) == INVALID_HANDLE_VALUE) + freopen ("CONOUT$", "w", stdout); + + if ((HANDLE) _get_osfhandle (fileno (stderr)) == INVALID_HANDLE_VALUE) + freopen ("CONOUT$", "w", stderr); + + SetConsoleTitleW (L"gdbus-daemon debug output."); + + atexit (wait_console_window); + } +} +static void +idle_timeout_cb (GDBusDaemon *daemon, gpointer user_data) +{ + GMainLoop *loop = user_data; + g_main_loop_quit (loop); +} + +__declspec(dllexport) void CALLBACK g_win32_run_session_bus (HWND hwnd, HINSTANCE hinst, char *cmdline, int nCmdShow); + +__declspec(dllexport) void CALLBACK +g_win32_run_session_bus (HWND hwnd, HINSTANCE hinst, char *cmdline, int nCmdShow) +{ + GDBusDaemon *daemon; + GMainLoop *loop; + const char *address; + GError *error = NULL; + + if (g_getenv ("GDBUS_DAEMON_DEBUG") != NULL) + open_console_window (); + + loop = g_main_loop_new (NULL, FALSE); + + address = "nonce-tcp:"; + daemon = _g_dbus_daemon_new (address, NULL, &error); + if (daemon == NULL) + { + g_printerr ("Can't init bus: %s\n", error->message); + return; + } + + g_signal_connect (daemon, "idle-timeout", G_CALLBACK (idle_timeout_cb), loop); + + if ( publish_session_bus (_g_dbus_daemon_get_address (daemon))) + { + g_main_loop_run (loop); + + unpublish_session_bus (); + } + + g_main_loop_unref (loop); + g_object_unref (daemon); +} + +static gchar * +get_session_address_dbus_launch (GError **error) +{ + HANDLE autolaunch_mutex, init_mutex; + char *address = NULL; + wchar_t gio_path[MAX_PATH+1+200]; + + autolaunch_mutex = acquire_mutex (DBUS_AUTOLAUNCH_MUTEX); + + init_mutex = acquire_mutex (UNIQUE_DBUS_INIT_MUTEX); + + if (is_mutex_owned (DBUS_DAEMON_MUTEX)) + address = read_shm (DBUS_DAEMON_ADDRESS_INFO); + + release_mutex (init_mutex); + + if (address == NULL) + { + gio_path[MAX_PATH] = 0; + if (GetModuleFileNameW (_g_io_win32_get_module (), gio_path, MAX_PATH)) + { + PROCESS_INFORMATION pi = { 0 }; + STARTUPINFOW si = { 0 }; + BOOL res; + wchar_t gio_path_short[MAX_PATH]; + wchar_t rundll_path[MAX_PATH*2]; + wchar_t args[MAX_PATH*4]; + + GetShortPathNameW (gio_path, gio_path_short, MAX_PATH); + + GetWindowsDirectoryW (rundll_path, MAX_PATH); + wcscat (rundll_path, L"\\rundll32.exe"); + if (GetFileAttributesW (rundll_path) == INVALID_FILE_ATTRIBUTES) + { + GetSystemDirectoryW (rundll_path, MAX_PATH); + wcscat (rundll_path, L"\\rundll32.exe"); + } + + wcscpy (args, L"\""); + wcscat (args, rundll_path); + wcscat (args, L"\" "); + wcscat (args, gio_path_short); + wcscat (args, L",g_win32_run_session_bus@16"); + + res = CreateProcessW (rundll_path, args, + 0, 0, FALSE, + NORMAL_PRIORITY_CLASS | CREATE_NO_WINDOW | DETACHED_PROCESS, + 0, NULL /* TODO: Should be root */, + &si, &pi); + if (res) + address = read_shm (DBUS_DAEMON_ADDRESS_INFO); + } + } + + release_mutex (autolaunch_mutex); + + if (address == NULL) + g_set_error (error, + G_IO_ERROR, + G_IO_ERROR_FAILED, + _("Session dbus not running, and autolaunch failed")); + + return address; +} +#endif + /* ---------------------------------------------------------------------------------------------------- */ static gchar * get_session_address_platform_specific (GError **error) { gchar *ret; -#ifdef G_OS_UNIX +#if defined (G_OS_UNIX) || defined(G_OS_WIN32) /* need to handle OS X in a different way since `dbus-launch --autolaunch' probably won't work there */ ret = get_session_address_dbus_launch (error); #else - /* TODO: implement for UNIX, Win32 and OS X */ + /* TODO: implement for OS X */ ret = NULL; g_set_error (error, G_IO_ERROR,