gnome-keyring r1369 - in trunk: . common daemon library
- From: nnielsen svn gnome org
- To: svn-commits-list gnome org
- Subject: gnome-keyring r1369 - in trunk: . common daemon library
- Date: Sun, 9 Nov 2008 23:02:23 +0000 (UTC)
Author: nnielsen
Date: Sun Nov 9 23:02:22 2008
New Revision: 1369
URL: http://svn.gnome.org/viewvc/gnome-keyring?rev=1369&view=rev
Log:
* configure.in:
* common/gkr-daemon-util.c:
* common/gkr-daemon-util.h:
* daemon/Makefile.am:
* daemon/gkr-daemon-dbus.c:
* daemon/gkr-daemon-ops.c:
* daemon/gkr-daemon.c:
* daemon/gkr-daemon.h:
* daemon/gnome-keyring-daemon.desktop.in:
* library/Makefile.am:
* library/gnome-keyring-private.h:
* library/gnome-keyring-socket.c:
* library/gnome-keyring-utils.c:
* library/gnome-keyring.c: Add --start option to daemon which allows
initialization of a running daemon or start one if none found.
This reworks the startup interactions with gnome-session.
Added:
trunk/daemon/gnome-keyring-daemon.desktop.in
trunk/library/gnome-keyring-socket.c
Modified:
trunk/ChangeLog
trunk/common/gkr-daemon-util.c
trunk/common/gkr-daemon-util.h
trunk/configure.in
trunk/daemon/ (props changed)
trunk/daemon/Makefile.am
trunk/daemon/gkr-daemon-dbus.c
trunk/daemon/gkr-daemon-ops.c
trunk/daemon/gkr-daemon.c
trunk/daemon/gkr-daemon.h
trunk/library/Makefile.am
trunk/library/gnome-keyring-private.h
trunk/library/gnome-keyring-utils.c
trunk/library/gnome-keyring.c
Modified: trunk/common/gkr-daemon-util.c
==============================================================================
--- trunk/common/gkr-daemon-util.c (original)
+++ trunk/common/gkr-daemon-util.c Sun Nov 9 23:02:22 2008
@@ -335,6 +335,18 @@
g_array_append_val (published_environ, env);
}
+void
+gkr_daemon_util_push_environment_full (const gchar *var)
+{
+ gchar *env;
+
+ g_return_if_fail (strchr (var, '=') != NULL);
+ init_environment ();
+
+ env = g_strdup (var);
+ g_array_append_val (published_environ, env);
+}
+
const gchar**
gkr_daemon_util_get_environment (void)
{
Modified: trunk/common/gkr-daemon-util.h
==============================================================================
--- trunk/common/gkr-daemon-util.h (original)
+++ trunk/common/gkr-daemon-util.h Sun Nov 9 23:02:22 2008
@@ -35,6 +35,8 @@
void gkr_daemon_util_push_environment (const gchar *name, const gchar *value);
+void gkr_daemon_util_push_environment_full (const gchar *env);
+
const gchar** gkr_daemon_util_get_environment (void);
#define GKR_TYPE_DAEMON_CLIENT (gkr_daemon_client_get_type ())
Modified: trunk/configure.in
==============================================================================
--- trunk/configure.in (original)
+++ trunk/configure.in Sun Nov 9 23:02:22 2008
@@ -484,11 +484,15 @@
AC_SUBST(LIBRARY_CFLAGS)
AC_SUBST(LIBRARY_LIBS)
+BINDIR="$bindir"
+AC_SUBST(BINDIR)
+
AC_OUTPUT([
Makefile
common/Makefile
common/tests/Makefile
daemon/Makefile
+daemon/gnome-keyring-daemon.desktop
daemon/data/Makefile
daemon/keyrings/Makefile
daemon/keyrings/tests/Makefile
Modified: trunk/daemon/Makefile.am
==============================================================================
--- trunk/daemon/Makefile.am (original)
+++ trunk/daemon/Makefile.am Sun Nov 9 23:02:22 2008
@@ -51,8 +51,13 @@
$(GOBJECT_LIBS) \
$(GLIB_LIBS)
-EXTRA_DIST = org.gnome.keyring.service.in
-CLEANFILES = org.gnome.keyring.service
+EXTRA_DIST = \
+ org.gnome.keyring.service.in \
+ gnome-keyring-daemon.desktop.in
+
+CLEANFILES = \
+ org.gnome.keyring.service \
+ gnome-keyring-daemon.desktop
servicedir = $(DBUS_SERVICES_DIR)
service_in_files = org.gnome.keyring.service.in
@@ -61,3 +66,5 @@
$(service_DATA): $(service_in_files) Makefile
@sed -e "s|\ BINDIR\@|$(bindir)|" $< > $@
+desktopdir = $(datadir)/gnome/autostart
+desktop_DATA = gnome-keyring-daemon.desktop
Modified: trunk/daemon/gkr-daemon-dbus.c
==============================================================================
--- trunk/daemon/gkr-daemon-dbus.c (original)
+++ trunk/daemon/gkr-daemon-dbus.c Sun Nov 9 23:02:22 2008
@@ -26,14 +26,21 @@
#include "common/gkr-cleanup.h"
#include "common/gkr-dbus.h"
+#include "common/gkr-daemon-util.h"
#include "library/gnome-keyring.h"
#include "library/gnome-keyring-private.h"
#include <dbus/dbus.h>
+#include <string.h>
+
+/* Rule to send to DBus bus for which signals we're interested in */
+#define SIGNAL_MATCH_RULE "type='signal',interface='org.gnome.SessionManager'"
+
static DBusConnection *dbus_conn = NULL;
static const char* socket_path = NULL;
+static gboolean dbus_initialized = FALSE;
static DBusHandlerResult
message_handler_cb (DBusConnection *conn, DBusMessage *message, void *user_data)
@@ -63,17 +70,29 @@
return DBUS_HANDLER_RESULT_HANDLED;
}
+static DBusHandlerResult
+signal_filter (DBusConnection *conn, DBusMessage *msg, void *user_data)
+{
+ /* Quit the daemon when the session is over */
+ if (dbus_message_is_signal (msg, "org.gnome.SessionManager", "SessionOver")) {
+ gkr_daemon_quit ();
+ return DBUS_HANDLER_RESULT_HANDLED;
+ }
+
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
static DBusObjectPathVTable object_vtable = {
NULL,
message_handler_cb,
NULL,
};
-
static void
daemon_dbus_cleanup (gpointer unused)
{
if (dbus_conn) {
+ dbus_bus_remove_match (dbus_conn, SIGNAL_MATCH_RULE, NULL);
dbus_connection_unregister_object_path (dbus_conn, GNOME_KEYRING_DAEMON_PATH);
gkr_dbus_disconnect_from_mainloop (dbus_conn, NULL);
dbus_connection_unref (dbus_conn);
@@ -81,16 +100,138 @@
}
}
+/*
+ * Here we register our environment variables with a gnome-session style
+ * session manager via DBus.
+ */
+static void
+register_environment_in_session (void)
+{
+ DBusMessageIter args;
+ DBusMessage *msg;
+ DBusMessage *reply;
+ DBusError derr = { 0 };
+ const gchar **envp;
+ const gchar *value;
+ gchar *name;
+
+ g_return_if_fail (dbus_conn);
+
+ /*
+ * The list of all environment variables registered by
+ * various components in the daemon.
+ */
+ envp = gkr_daemon_util_get_environment ();
+
+ for (; *envp; ++envp) {
+
+ /* Find the value part of the environment variable */
+ value = strchr (*envp, '=');
+ if (!value)
+ continue;
+
+ name = g_strndup (*envp, value - *envp);
+ ++value;
+
+ msg = dbus_message_new_method_call ("org.gnome.SessionManager",
+ "/org/gnome/SessionManager",
+ "org.gnome.SessionManager",
+ "Setenv");
+ g_return_if_fail (msg);
+
+ dbus_message_iter_init_append (msg, &args);
+ if (!dbus_message_iter_append_basic (&args, DBUS_TYPE_STRING, &name) ||
+ !dbus_message_iter_append_basic (&args, DBUS_TYPE_STRING, &value))
+ g_return_if_reached ();
+
+ g_free (name);
+ value = name = NULL;
+
+ /* Send message and get a handle for a reply */
+ reply = dbus_connection_send_with_reply_and_block (dbus_conn, msg, 1000, &derr);
+ dbus_message_unref (msg);
+
+ if (!reply) {
+ g_warning ("couldn't set environment variable in session: %s", derr.message);
+ return;
+ }
+
+ dbus_message_unref (reply);
+ }
+}
+
+/*
+ * Here we register our desktop autostart id gnome-session style
+ * session manager via DBus.
+ */
+static void
+register_daemon_in_session (void)
+{
+ DBusMessageIter args;
+ DBusMessage *msg;
+ DBusMessage *reply;
+ DBusError derr = { 0 };
+ const gchar *app_id = "gnome-keyring-daemon";
+ const gchar *client_id;
+
+ client_id = g_getenv ("DESKTOP_AUTOSTART_ID");
+ if(!client_id)
+ return;
+
+ g_return_if_fail (dbus_conn);
+
+ msg = dbus_message_new_method_call ("org.gnome.SessionManager",
+ "/org/gnome/SessionManager",
+ "org.gnome.SessionManager",
+ "RegisterClient");
+ g_return_if_fail (msg);
+
+ dbus_message_iter_init_append (msg, &args);
+ if (!dbus_message_iter_append_basic (&args, DBUS_TYPE_STRING, &app_id) ||
+ !dbus_message_iter_append_basic (&args, DBUS_TYPE_STRING, &client_id))
+ g_return_if_reached ();
+
+ /* Send message and get a handle for a reply */
+ reply = dbus_connection_send_with_reply_and_block (dbus_conn, msg, 1000, &derr);
+ dbus_message_unref (msg);
+
+ if (!reply) {
+ g_warning ("couldn't register in session: %s", derr.message);
+ return;
+ }
+
+ dbus_message_unref (reply);
+
+ /*
+ * Unset DESKTOP_AUTOSTART_ID in order to avoid child processes to
+ * use the same client id.
+ */
+ g_unsetenv ("DESKTOP_AUTOSTART_ID");
+}
+
void
-gkr_daemon_dbus_setup (GMainLoop *loop)
+gkr_daemon_dbus_setup (void)
{
dbus_uint32_t res = 0;
DBusError derr = { 0 };
+ const gchar *env;
+
+ /*
+ * We may be launched before the DBUS session, (ie: via PAM)
+ * and DBus tries to launch itself somehow, so double check
+ * that it has really started.
+ */
+ env = getenv ("DBUS_SESSION_BUS_ADDRESS");
+ if (!env || !env[0])
+ return;
+
+ if (dbus_initialized)
+ return;
#ifdef WITH_TESTS
/* If running as a test, don't do DBUS stuff */
- const gchar *env = g_getenv ("GNOME_KEYRING_TEST_PATH");
- if (env && *env)
+ env = g_getenv ("GNOME_KEYRING_TEST_PATH");
+ if (env && env[0])
return;
#endif
@@ -114,7 +255,7 @@
/* Try and grab our name */
res = dbus_bus_request_name (dbus_conn, GNOME_KEYRING_DAEMON_SERVICE,
- DBUS_NAME_FLAG_DO_NOT_QUEUE, &derr);
+ DBUS_NAME_FLAG_DO_NOT_QUEUE, &derr);
if (dbus_error_is_set (&derr)) {
g_warning ("couldn't request name on session bus: %s", derr.message);
dbus_error_free (&derr);
@@ -144,4 +285,13 @@
g_warning ("couldn't register dbus object path");
return;
}
+
+ /* Listen in to signals that tell us when the session will be over */
+ dbus_bus_add_match (dbus_conn, SIGNAL_MATCH_RULE, NULL);
+ dbus_connection_add_filter (dbus_conn, signal_filter, NULL, NULL);
+
+ dbus_initialized = TRUE;
+
+ register_environment_in_session ();
+ register_daemon_in_session ();
}
Modified: trunk/daemon/gkr-daemon-ops.c
==============================================================================
--- trunk/daemon/gkr-daemon-ops.c (original)
+++ trunk/daemon/gkr-daemon-ops.c Sun Nov 9 23:02:22 2008
@@ -1689,6 +1689,7 @@
const gchar **daemonenv;
gchar **environment, **e;
gchar *x;
+ gint i;
if (!gkr_proto_decode_prepare_environment (packet, &environment))
return FALSE;
@@ -1699,24 +1700,25 @@
if (x) {
*(x++) = 0;
- /* We're only interested in these guys */
- if (g_str_equal (*e, "DISPLAY"))
- g_setenv ("DISPLAY", x, FALSE);
- else if (g_str_equal (*e, "DBUS_SESSION_BUS_ADDRESS"))
- g_setenv ("DBUS_SESSION_BUS_ADDRESS", x, FALSE);
- else if (g_str_equal (*e, "XAUTHORITY"))
- g_setenv ("XAUTHORITY", x, FALSE);
- else if (g_str_equal (*e, "XDG_SESSION_COOKIE"))
- g_setenv ("XDG_SESSION_COOKIE", x, FALSE);
- else if (g_str_equal (*e, "LANG"))
- g_setenv ("LANG", x, FALSE);
+ /* We're only interested in these environment variables */
+ for (i = 0; GNOME_KEYRING_IN_ENVIRONMENT[i] != NULL; ++i) {
+ if (g_str_equal (*e, GNOME_KEYRING_IN_ENVIRONMENT[i]))
+ {
+ g_setenv (*e, x, FALSE);
+ break;
+ }
+ }
}
}
g_strfreev (environment);
+
+ /* We may have received DBUS environment variable so try and setup DBUS */
+ gkr_daemon_dbus_setup ();
gkr_buffer_add_uint32 (result, GNOME_KEYRING_RESULT_OK);
+ /* These are the environment variables that the daemon setup */
daemonenv = gkr_daemon_util_get_environment ();
g_return_val_if_fail (daemonenv, FALSE);
Modified: trunk/daemon/gkr-daemon.c
==============================================================================
--- trunk/daemon/gkr-daemon.c (original)
+++ trunk/daemon/gkr-daemon.c Sun Nov 9 23:02:22 2008
@@ -29,6 +29,7 @@
#include "common/gkr-crypto.h"
#include "common/gkr-daemon-util.h"
#include "common/gkr-secure-memory.h"
+#include "common/gkr-unix-credentials.h"
#include "common/gkr-unix-signal.h"
#include "keyrings/gkr-keyring-login.h"
@@ -97,6 +98,7 @@
static gboolean run_foreground = FALSE;
static gboolean run_daemonized = FALSE;
static gboolean unlock_with_login = FALSE;
+static gboolean start_any_daemon = FALSE;
static gchar* run_components = NULL;
static GOptionEntry option_entries[] = {
@@ -106,6 +108,8 @@
"Run as a daemon", NULL },
{ "login", 'l', 0, G_OPTION_ARG_NONE, &unlock_with_login,
"Use login password from stdin", NULL },
+ { "start", 's', 0, G_OPTION_ARG_NONE, &start_any_daemon,
+ "Start or initialize an already running daemon" },
{ "components", 'c', 0, G_OPTION_ARG_STRING, &run_components,
"The components to run", DEFAULT_COMPONENTS },
{ NULL }
@@ -131,6 +135,13 @@
gkr_cleanup_register (g_free, run_components);
}
+ /* Check the arguments */
+ if (unlock_with_login && start_any_daemon) {
+ g_printerr ("gnome-keyring-daemon: The --start option is incompatible with --login");
+ start_any_daemon = FALSE;
+ }
+
+
g_option_context_free (context);
}
@@ -326,10 +337,16 @@
g_log_set_default_handler (log_handler, NULL);
}
+void
+gkr_daemon_quit (void)
+{
+ g_main_loop_quit (loop);
+}
+
static gboolean
signal_handler (guint sig, gpointer unused)
{
- g_main_loop_quit (loop);
+ gkr_daemon_quit ();
return TRUE;
}
@@ -423,7 +440,96 @@
const gchar **env;
for (env = gkr_daemon_util_get_environment (); *env; ++env)
printf ("%s\n", *env);
- printf ("GNOME_KEYRING_PID=%d\n", (gint)pid);
+ if (pid)
+ printf ("GNOME_KEYRING_PID=%d\n", (gint)pid);
+}
+
+static gboolean
+initialize_running_daemon (int sock)
+{
+ GnomeKeyringResult res;
+ gchar **envp, **e;
+ GkrBuffer buf;
+ gboolean ret;
+
+ if (gkr_unix_credentials_write (sock) < 0)
+ return FALSE;
+
+ gkr_buffer_init_full (&buf, 128, (GkrBufferAllocator)g_realloc);
+
+ envp = gnome_keyring_build_environment (GNOME_KEYRING_IN_ENVIRONMENT);
+ ret = gkr_proto_encode_prepare_environment (&buf, (const gchar**)envp);
+ g_strfreev (envp);
+
+ if (!ret) {
+ gkr_buffer_uninit (&buf);
+ g_return_val_if_reached (FALSE);
+ }
+
+ envp = NULL;
+
+ ret = gnome_keyring_socket_write_buffer (sock, &buf) &&
+ gnome_keyring_socket_read_buffer (sock, &buf) &&
+ gkr_proto_decode_prepare_environment_reply (&buf, &res, &envp);
+
+
+ gkr_buffer_uninit (&buf);
+
+ if(!ret) {
+ g_warning ("couldn't initialize running daemon");
+ return FALSE;
+ }
+
+ if (res == GNOME_KEYRING_RESULT_OK) {
+ g_return_val_if_fail (envp, FALSE);
+ for (e = envp; *e; ++e)
+ gkr_daemon_util_push_environment_full (*e);
+ ret = TRUE;
+ } else {
+ g_warning ("couldn't initialize running daemon: %s", gnome_keyring_result_to_message (res));
+ ret = FALSE;
+ }
+
+ g_strfreev (envp);
+
+ return ret;
+}
+
+static gboolean
+start_or_initialize_daemon (void)
+{
+ gboolean ret;
+ int sock;
+
+ /*
+ * Is a daemon already running? If not we need to run
+ * a daemon process, just return and let things go
+ * their normal way.
+ */
+ sock = gnome_keyring_socket_connect_daemon (FALSE);
+ if (sock == -1)
+ return FALSE;
+
+ ret = initialize_running_daemon (sock);
+ close (sock);
+
+ /* Initialization failed, start this process up as a daemon */
+ if (!ret)
+ return FALSE;
+
+ /*
+ * Now we've initialized the daemon, we need to print out
+ * the daemon's environment for any callers, and possibly
+ * block if we've been asked to remain in the foreground.
+ */
+ print_environment (0);
+
+ /* TODO: Better way to sleep forever? */
+ if (run_foreground) {
+ while (sleep(0x08000000) == 0);
+ }
+
+ return TRUE;
}
int
@@ -441,7 +547,7 @@
g_thread_init (NULL);
parse_arguments (&argc, &argv);
-
+
#ifdef HAVE_LOCALE_H
/* internationalisation */
setlocale (LC_ALL, "");
@@ -453,6 +559,15 @@
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
#endif
+ /*
+ * If asked to start a daemon, see if one is already running
+ * and initialize it if so.
+ */
+ if (start_any_daemon) {
+ if (start_or_initialize_daemon ())
+ return 0;
+ }
+
gkr_crypto_setup ();
gcry_create_nonce (&seed, sizeof (seed));
@@ -578,19 +693,10 @@
lifetime_slave_pipe_io, NULL);
g_io_channel_unref (channel);
}
-
}
gkr_async_workers_init (loop);
-
- /*
- * We may be launched before the DBUS session, (ie: via PAM)
- * and DBus tries to launch itself somehow, so double check
- * that it has really started.
- */
- env = getenv ("DBUS_SESSION_BUS_ADDRESS");
- if (env && env[0])
- gkr_daemon_dbus_setup (loop);
+ gkr_daemon_dbus_setup ();
/*
* Unlock the login keyring if we were given a password on STDIN.
Modified: trunk/daemon/gkr-daemon.h
==============================================================================
--- trunk/daemon/gkr-daemon.h (original)
+++ trunk/daemon/gkr-daemon.h Sun Nov 9 23:02:22 2008
@@ -45,10 +45,12 @@
extern GkrDaemonOperation keyring_ops[];
+void gkr_daemon_quit (void);
+
gboolean gkr_daemon_io_create_master_socket (void);
const gchar* gkr_daemon_io_get_socket_path (void);
/* Dbus Initialization/Cleanup */
-void gkr_daemon_dbus_setup (GMainLoop *loop);
+void gkr_daemon_dbus_setup (void);
#endif /* GNOME_KEYRING_DAEMON_H */
Added: trunk/daemon/gnome-keyring-daemon.desktop.in
==============================================================================
--- (empty file)
+++ trunk/daemon/gnome-keyring-daemon.desktop.in Sun Nov 9 23:02:22 2008
@@ -0,0 +1,12 @@
+[Desktop Entry]
+Type=Application
+Name=GNOME Keyring Daemon
+Exec=gnome-keyring-daemon --start
+OnlyShowIn=GNOME;
+X-GNOME-Autostart-Phase=Initialization
+X-GNOME-AutoRestart=false
+X-GNOME-Autostart-Notify=true
+X-GNOME-Bugzilla-Bugzilla=GNOME
+X-GNOME-Bugzilla-Product=gnome-keyring
+X-GNOME-Bugzilla-Component=general
+X-GNOME-Bugzilla-Version= VERSION@
\ No newline at end of file
Modified: trunk/library/Makefile.am
==============================================================================
--- trunk/library/Makefile.am (original)
+++ trunk/library/Makefile.am Sun Nov 9 23:02:22 2008
@@ -19,6 +19,7 @@
gnome-keyring-private.h \
gnome-keyring-proto.c \
gnome-keyring-proto.h \
+ gnome-keyring-socket.c \
gnome-keyring-utils.c
libgnome_keyring_common_la_LIBADD = \
Modified: trunk/library/gnome-keyring-private.h
==============================================================================
--- trunk/library/gnome-keyring-private.h (original)
+++ trunk/library/gnome-keyring-private.h Sun Nov 9 23:02:22 2008
@@ -25,6 +25,7 @@
#define GNOME_KEYRING_PRIVATE_H
#include "gnome-keyring.h"
+#include "gnome-keyring-proto.h"
struct GnomeKeyringApplicationRef {
char *display_name;
@@ -56,6 +57,18 @@
#define GNOME_KEYRING_DAEMON_PATH "/org/gnome/keyring/daemon"
#define GNOME_KEYRING_DAEMON_INTERFACE "org.gnome.keyring.Daemon"
+int gnome_keyring_socket_connect_daemon (gboolean non_blocking);
+int gnome_keyring_socket_read_all (int fd, guchar *buf, size_t len);
+int gnome_keyring_socket_write_all (int fd, const guchar *buf, size_t len);
+gboolean gnome_keyring_socket_read_buffer (int fd, GkrBuffer *buffer);
+gboolean gnome_keyring_socket_write_buffer (int fd, GkrBuffer *buffer);
+
+extern const gchar *GNOME_KEYRING_OUT_ENVIRONMENT[];
+extern const gchar *GNOME_KEYRING_IN_ENVIRONMENT[];
+
+gchar** gnome_keyring_build_environment (const gchar **names);
+void gnome_keyring_apply_environment (gchar **envp);
+
void _gnome_keyring_memory_dump (void);
extern gboolean gnome_keyring_memory_warning;
Added: trunk/library/gnome-keyring-socket.c
==============================================================================
--- (empty file)
+++ trunk/library/gnome-keyring-socket.c Sun Nov 9 23:02:22 2008
@@ -0,0 +1,247 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* gnome-keyring.c - library for talking to the keyring daemon.
+
+ Copyright (C) 2003 Red Hat, Inc
+ Copyright (C) 2008 Stefan Walter
+
+ The Gnome Keyring Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The Gnome Keyring Library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the Gnome Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Author: Alexander Larsson <alexl redhat com>
+ Author: Stef Walter <stef memberwebs com>
+*/
+
+#include "config.h"
+
+#include "gnome-keyring-private.h"
+
+#include <glib.h>
+
+#include <dbus/dbus.h>
+
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/un.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+static gchar*
+find_daemon_via_dbus ()
+{
+ DBusConnection *dconn;
+ DBusMessage *reply;
+ DBusMessage *msg;
+ DBusMessageIter args;
+ DBusError derr;
+ char* socket = NULL;
+
+ if (!g_getenv ("DBUS_SESSION_BUS_ADDRESS"))
+ return NULL;
+
+ dbus_error_init (&derr);
+ dconn = dbus_bus_get (DBUS_BUS_SESSION, &derr);
+ if (!dconn) {
+ g_warning ("couldn't connect to dbus session bus: %s", derr.message);
+ return NULL;
+ }
+
+ msg = dbus_message_new_method_call (GNOME_KEYRING_DAEMON_SERVICE,
+ GNOME_KEYRING_DAEMON_PATH,
+ GNOME_KEYRING_DAEMON_INTERFACE,
+ "GetSocketPath");
+ if (!msg) {
+ g_warning ("couldn't create dbus message");
+ dbus_connection_unref (dconn);
+ return NULL;
+ }
+
+ /* Send message and get a handle for a reply */
+ reply = dbus_connection_send_with_reply_and_block (dconn, msg, 1000, &derr);
+ dbus_message_unref (msg);
+ if (!reply) {
+ g_warning ("couldn't communicate with gnome keyring daemon via dbus: %s", derr.message);
+ dbus_connection_unref (dconn);
+ return NULL;
+ }
+
+ /* Read the return value */
+ if (!dbus_message_iter_init(reply, &args) ||
+ dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_STRING) {
+ g_warning ("gnome-keyring-daemon sent back an invalid reply");
+ } else {
+ dbus_message_iter_get_basic(&args, &socket);
+ socket = g_strdup (socket);
+ }
+
+ dbus_message_unref (reply);
+ dbus_connection_unref (dconn);
+
+ return socket;
+}
+
+static int
+connect_to_daemon_at (const gchar *path)
+{
+ struct sockaddr_un addr;
+ int sock;
+
+ addr.sun_family = AF_UNIX;
+ strncpy (addr.sun_path, path, sizeof (addr.sun_path));
+
+ sock = socket (AF_UNIX, SOCK_STREAM, 0);
+ if (sock < 0) {
+ return -1;
+ }
+
+ /* close on exec */
+ if (fcntl (sock, F_SETFD, 1) == -1) {
+ close (sock);
+ return -1;
+ }
+
+ if (connect (sock, (struct sockaddr *) &addr, sizeof (addr)) < 0) {
+ close (sock);
+ return -1;
+ }
+
+ return sock;
+}
+
+int
+gnome_keyring_socket_connect_daemon (gboolean non_blocking)
+{
+ const gchar *epath = NULL;
+ int sock = -1;
+ int val;
+
+ /* Try using the environment variable */
+ epath = g_getenv ("GNOME_KEYRING_SOCKET");
+ if (epath && epath[0]) {
+ sock = connect_to_daemon_at (epath);
+ if (sock < 0) {
+ g_warning ("couldn't connect to daemon at $GNOME_KEYRING_SOCKET: %s: %s",
+ epath, g_strerror (errno));
+ }
+ }
+
+ /* Try using DBus to find daemon */
+ if (sock < 0) {
+ gchar *dpath = find_daemon_via_dbus ();
+ if (dpath) {
+ sock = connect_to_daemon_at (dpath);
+ g_free (dpath);
+ if (sock < 0) {
+ g_warning ("couldn't connect to daemon at DBus discovered socket: %s: %s",
+ dpath, g_strerror (errno));
+ }
+ }
+ }
+
+ if (sock < 0)
+ return -1;
+
+ /* Setup non blocking */
+ if (non_blocking) {
+ val = fcntl (sock, F_GETFL, 0);
+ if (val < 0) {
+ close (sock);
+ return -1;
+ }
+
+ if (fcntl (sock, F_SETFL, val | O_NONBLOCK) < 0) {
+ close (sock);
+ return -1;
+ }
+ }
+
+ return sock;
+}
+
+int
+gnome_keyring_socket_read_all (int fd, guchar *buf, size_t len)
+{
+ size_t bytes;
+ ssize_t res;
+
+ bytes = 0;
+ while (bytes < len) {
+ res = read (fd, buf + bytes, len - bytes);
+ if (res <= 0) {
+ if (res == 0)
+ res = -1;
+ else if (errno == EAGAIN)
+ continue;
+ else
+ g_warning ("couldn't read %u bytes from gnome-keyring socket: %s",
+ (unsigned int)len, g_strerror (errno));
+ return res;
+ }
+ bytes += res;
+ }
+ return 0;
+}
+
+
+int
+gnome_keyring_socket_write_all (int fd, const guchar *buf, size_t len)
+{
+ size_t bytes;
+ ssize_t res;
+
+ bytes = 0;
+ while (bytes < len) {
+ res = write (fd, buf + bytes, len - bytes);
+ if (res < 0) {
+ if (errno != EINTR &&
+ errno != EAGAIN) {
+ g_warning ("write_all write failure: %s", g_strerror (errno));
+ return -1;
+ }
+ } else {
+ bytes += res;
+ }
+ }
+ return 0;
+}
+
+gboolean
+gnome_keyring_socket_read_buffer (int fd, GkrBuffer *buffer)
+{
+ guint32 packet_size;
+
+ gkr_buffer_resize (buffer, 4);
+ if (gnome_keyring_socket_read_all (fd, buffer->buf, 4) < 0)
+ return FALSE;
+
+ if (!gkr_proto_decode_packet_size (buffer, &packet_size) ||
+ packet_size < 4)
+ return FALSE;
+
+ gkr_buffer_resize (buffer, packet_size);
+ if (gnome_keyring_socket_read_all (fd, buffer->buf + 4, packet_size - 4) < 0)
+ return FALSE;
+
+ return TRUE;
+}
+
+gboolean
+gnome_keyring_socket_write_buffer (int fd, GkrBuffer *buffer)
+{
+ return gnome_keyring_socket_write_all (fd, buffer->buf, buffer->len) >= 0;
+}
+
Modified: trunk/library/gnome-keyring-utils.c
==============================================================================
--- trunk/library/gnome-keyring-utils.c (original)
+++ trunk/library/gnome-keyring-utils.c Sun Nov 9 23:02:22 2008
@@ -34,6 +34,68 @@
/* Functions used by both the library and the daemon */
+/*
+ * A list of all the environment variables the daemon can
+ * possibly send out when it starts.
+ */
+const gchar *GNOME_KEYRING_OUT_ENVIRONMENT[] = {
+ "SSH_AUTH_SOCK",
+ "GNOME_KEYRING_SOCKET",
+ "GNOME_KEYRING_PID",
+ "SSH_AGENT_PID",
+ NULL
+};
+
+/*
+ * A list of all the environment variables the daemon
+ * is interested in from clients if it was started
+ * early before these environment variables were set.
+ */
+const gchar *GNOME_KEYRING_IN_ENVIRONMENT[] = {
+ "DISPLAY",
+ "DBUS_SESSION_BUS_ADDRESS",
+ "XAUTHORITY",
+ "XDG_SESSION_COOKIE",
+ "DESKTOP_AUTOSTART_ID",
+ "LANG",
+ NULL
+};
+
+gchar**
+gnome_keyring_build_environment (const gchar **names)
+{
+ GArray *array = g_array_sized_new (TRUE, TRUE, sizeof (gchar*), 8);
+ const gchar *value;
+ const gchar **name;
+ gchar *env;
+
+ /* Transform them into NAME=VALUE pairs */
+ for (name = names; *name; ++name) {
+ value = g_getenv (*name);
+ if (value) {
+ env = g_strdup_printf ("%s=%s", *name, value);
+ g_array_append_val (array, env);
+ }
+ }
+
+ return (gchar**)g_array_free (array, FALSE);
+}
+
+void
+gnome_keyring_apply_environment (gchar **envp)
+{
+ gchar **e, **parts;
+
+ g_return_if_fail (envp);
+
+ for (e = envp; *e; ++e) {
+ parts = g_strsplit (*e, "=", 2);
+ if (parts && parts[0] && parts[1])
+ g_setenv (parts[0], parts[1], TRUE);
+ g_strfreev (parts);
+ }
+}
+
/**
* gnome_keyring_free_password:
* @password: the password to be freed
Modified: trunk/library/gnome-keyring.c
==============================================================================
--- trunk/library/gnome-keyring.c (original)
+++ trunk/library/gnome-keyring.c Sun Nov 9 23:02:22 2008
@@ -35,7 +35,6 @@
#include <time.h>
#include <unistd.h>
-#include <fcntl.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
@@ -43,11 +42,8 @@
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/uio.h>
-#include <sys/un.h>
#include <stdarg.h>
-#include <dbus/dbus.h>
-
typedef enum {
CALLBACK_DONE,
CALLBACK_GET_STRING,
@@ -98,135 +94,6 @@
GDestroyNotify destroy_reply_data;
};
-static gchar*
-find_daemon_via_dbus ()
-{
- DBusConnection *dconn;
- DBusMessage *reply;
- DBusMessage *msg;
- DBusMessageIter args;
- DBusError derr;
- char* socket = NULL;
-
- dbus_error_init (&derr);
- dconn = dbus_bus_get (DBUS_BUS_SESSION, &derr);
- if (!dconn) {
- g_warning ("couldn't connect to dbus session bus: %s", derr.message);
- return NULL;
- }
-
- msg = dbus_message_new_method_call (GNOME_KEYRING_DAEMON_SERVICE,
- GNOME_KEYRING_DAEMON_PATH,
- GNOME_KEYRING_DAEMON_INTERFACE,
- "GetSocketPath");
- if (!msg) {
- g_warning ("couldn't create dbus message");
- dbus_connection_unref (dconn);
- return NULL;
- }
-
- /* Send message and get a handle for a reply */
- reply = dbus_connection_send_with_reply_and_block (dconn, msg, 1000, &derr);
- dbus_message_unref (msg);
- if (!reply) {
- g_warning ("couldn't communicate with gnome keyring daemon via dbus: %s", derr.message);
- dbus_connection_unref (dconn);
- return NULL;
- }
-
- /* Read the return value */
- if (!dbus_message_iter_init(reply, &args) ||
- dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_STRING) {
- g_warning ("gnome-keyring-daemon sent back an invalid reply");
- } else {
- dbus_message_iter_get_basic(&args, &socket);
- socket = g_strdup (socket);
- }
-
- dbus_message_unref (reply);
- dbus_connection_unref (dconn);
-
- return socket;
-}
-
-static int
-connect_to_daemon_at (const gchar *path)
-{
- struct sockaddr_un addr;
- int sock;
-
- addr.sun_family = AF_UNIX;
- strncpy (addr.sun_path, path, sizeof (addr.sun_path));
-
- sock = socket (AF_UNIX, SOCK_STREAM, 0);
- if (sock < 0) {
- return -1;
- }
-
- /* close on exec */
- if (fcntl (sock, F_SETFD, 1) == -1) {
- close (sock);
- return -1;
- }
-
- if (connect (sock, (struct sockaddr *) &addr, sizeof (addr)) < 0) {
- close (sock);
- return -1;
- }
-
- return sock;
-}
-
-static int
-connect_to_daemon (gboolean non_blocking)
-{
- const gchar *epath = NULL;
- int sock = -1;
- int val;
-
- /* Try using the environment variable */
- epath = g_getenv ("GNOME_KEYRING_SOCKET");
- if (epath && epath[0]) {
- sock = connect_to_daemon_at (epath);
- if (sock < 0) {
- g_warning ("couldn't connect to daemon at $GNOME_KEYRING_SOCKET: %s: %s",
- epath, g_strerror (errno));
- }
- }
-
- /* Try using DBus to find daemon */
- if (sock < 0) {
- gchar *dpath = find_daemon_via_dbus ();
- if (dpath) {
- sock = connect_to_daemon_at (dpath);
- g_free (dpath);
- if (sock < 0) {
- g_warning ("couldn't connect to daemon at DBus discovered socket: %s: %s",
- dpath, g_strerror (errno));
- }
- }
- }
-
- if (sock < 0)
- return -1;
-
- /* Setup non blocking */
- if (non_blocking) {
- val = fcntl (sock, F_GETFL, 0);
- if (val < 0) {
- close (sock);
- return -1;
- }
-
- if (fcntl (sock, F_SETFL, val | O_NONBLOCK) < 0) {
- close (sock);
- return -1;
- }
- }
-
- return sock;
-}
-
static void
operation_free (GnomeKeyringOperation *op)
{
@@ -307,53 +174,6 @@
op->idle_watch = g_idle_add (op_failed, op);
}
-static int
-read_all (int fd, guchar *buf, size_t len)
-{
- size_t bytes;
- ssize_t res;
-
- bytes = 0;
- while (bytes < len) {
- res = read (fd, buf + bytes, len - bytes);
- if (res <= 0) {
- if (res == 0)
- res = -1;
- else if (errno == EAGAIN)
- continue;
- else
- g_warning ("couldn't read %u bytes from gnome-keyring socket: %s",
- (unsigned int)len, g_strerror (errno));
- return res;
- }
- bytes += res;
- }
- return 0;
-}
-
-
-static int
-write_all (int fd, const guchar *buf, size_t len)
-{
- size_t bytes;
- ssize_t res;
-
- bytes = 0;
- while (bytes < len) {
- res = write (fd, buf + bytes, len - bytes);
- if (res < 0) {
- if (errno != EINTR &&
- errno != EAGAIN) {
- perror ("write_all write failure:");
- return -1;
- }
- } else {
- bytes += res;
- }
- }
- return 0;
-}
-
static GnomeKeyringResult
write_credentials_byte_sync (int socket)
{
@@ -519,7 +339,7 @@
close (op->socket);
}
- op->socket = connect_to_daemon (TRUE);
+ op->socket = gnome_keyring_socket_connect_daemon (TRUE);
if (op->socket < 0) {
schedule_op_failed (op, GNOME_KEYRING_RESULT_NO_KEYRING_DAEMON);
} else {
@@ -542,45 +362,27 @@
{
GnomeKeyringResult res;
int socket;
- guint32 packet_size;
g_assert (buffer != NULL);
g_assert (receive_buffer != NULL);
- socket = connect_to_daemon (FALSE);
- if (socket < 0) {
+ socket = gnome_keyring_socket_connect_daemon (FALSE);
+ if (socket < 0)
return GNOME_KEYRING_RESULT_NO_KEYRING_DAEMON;
- }
+
res = write_credentials_byte_sync (socket);
if (res != GNOME_KEYRING_RESULT_OK) {
close (socket);
return res;
}
- if (write_all (socket,
- buffer->buf, buffer->len) < 0) {
+ if (!gnome_keyring_socket_write_buffer (socket, buffer) ||
+ !gnome_keyring_socket_read_buffer (socket, receive_buffer)) {
close (socket);
return GNOME_KEYRING_RESULT_IO_ERROR;
}
- gkr_buffer_resize (receive_buffer, 4);
- if (read_all (socket, receive_buffer->buf, 4) < 0) {
- close (socket);
- return GNOME_KEYRING_RESULT_IO_ERROR;
- }
-
- if (!gkr_proto_decode_packet_size (receive_buffer, &packet_size) ||
- packet_size < 4) {
- close (socket);
- return GNOME_KEYRING_RESULT_IO_ERROR;
- }
- gkr_buffer_resize (receive_buffer, packet_size);
- if (read_all (socket, receive_buffer->buf + 4, packet_size - 4) < 0) {
- close (socket);
- return GNOME_KEYRING_RESULT_IO_ERROR;
- }
close (socket);
-
return GNOME_KEYRING_RESULT_OK;
}
@@ -597,7 +399,7 @@
{
int socket;
- socket = connect_to_daemon (FALSE);
+ socket = gnome_keyring_socket_connect_daemon (FALSE);
if (socket < 0) {
return FALSE;
}
@@ -1776,23 +1578,13 @@
{
GkrBuffer send, receive;
GnomeKeyringResult res;
- gchar **envp, **e, *name;
- gchar **parts;
+ gchar **envp;
gboolean ret;
gkr_buffer_init_full (&send, 128, NORMAL_ALLOCATOR);
/* Get all the environment names */
- envp = g_listenv ();
- g_return_val_if_fail (envp, GNOME_KEYRING_RESULT_BAD_ARGUMENTS);
-
- /* Transform them into NAME=VALUE pairs */
- for (e = envp; *e; ++e) {
- name = *e;
- *e = g_strdup_printf ("%s=%s", name, g_getenv (name));
- g_free (name);
- }
-
+ envp = gnome_keyring_build_environment (GNOME_KEYRING_IN_ENVIRONMENT);
ret = gkr_proto_encode_prepare_environment (&send, (const gchar**)envp);
g_strfreev (envp);
@@ -1817,12 +1609,7 @@
if (res == GNOME_KEYRING_RESULT_OK) {
g_return_val_if_fail (envp, GNOME_KEYRING_RESULT_IO_ERROR);
- for (e = envp; *e; ++e) {
- parts = g_strsplit (*e, "=", 2);
- if (parts && parts[0] && parts[1])
- g_setenv (parts[0], parts[1], TRUE);
- g_strfreev (parts);
- }
+ gnome_keyring_apply_environment (envp);
}
g_strfreev (envp);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]