1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2 /* gkd-dbus-secrets.c - dbus secret service
3 
4    Copyright (C) 2009, Stefan Walter
5 
6    The Gnome Keyring Library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Library General Public License as
8    published by the Free Software Foundation; either version 2 of the
9    License, or (at your option) any later version.
10 
11    The Gnome Keyring Library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Library General Public License for more details.
15 
16    You should have received a copy of the GNU Library General Public
17    License along with the Gnome Library; see the file COPYING.LIB.  If not,
18    <http://www.gnu.org/licenses/>.
19 
20    Author: Stef Walter <stef@memberwebs.com>
21 */
22 
23 #include "config.h"
24 
25 #include "gkd-dbus.h"
26 #include "gkd-dbus-private.h"
27 #include "gkd-secret-service.h"
28 
29 #include "daemon/gkd-pkcs11.h"
30 
31 #include "egg/egg-cleanup.h"
32 #include "egg/egg-error.h"
33 
34 #include <gck/gck.h>
35 
36 static GDBusConnection *dbus_conn = NULL;
37 static GkdSecretService *secrets_service = NULL;
38 
39 static GckSlot*
calculate_secrets_slot(void)40 calculate_secrets_slot (void)
41 {
42 	GckSlot *slot = NULL;
43 	GckModule *module;
44 	GList *modules;
45 	GError *err = NULL;
46 	CK_FUNCTION_LIST_PTR funcs;
47 
48 	/* TODO: Should we be handling just one module here? */
49 	funcs = gkd_pkcs11_get_functions ();
50 	g_return_val_if_fail (funcs != NULL, NULL);
51 
52 	module = gck_module_new (funcs);
53 	g_return_val_if_fail (module, NULL);
54 
55 	modules = g_list_prepend (NULL, module);
56 	slot = gck_modules_token_for_uri (modules, "pkcs11:token=Secret%20Store", &err);
57 	if (!slot && err) {
58 		g_warning ("couldn't find secret store: %s", egg_error_message (err));
59 		g_clear_error (&err);
60 	}
61 
62 	gck_list_unref_free (modules);
63 	return slot;
64 }
65 
66 gboolean
gkd_dbus_secrets_startup(void)67 gkd_dbus_secrets_startup (void)
68 {
69 	const gchar *service = NULL;
70 	unsigned int flags = 0;
71 	GckSlot *slot;
72 	GError *error = NULL;
73 	GVariant *request_variant;
74 	guint res;
75 
76 	g_return_val_if_fail (dbus_conn, FALSE);
77 	g_return_val_if_fail (!secrets_service, FALSE);
78 
79 #ifdef WITH_DEBUG
80 	service = g_getenv ("GNOME_KEYRING_TEST_SERVICE");
81 	if (service && service[0])
82 		flags = G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT | G_BUS_NAME_OWNER_FLAGS_REPLACE;
83 	else
84 #endif
85 		service = SECRET_SERVICE;
86 
87 	/* Figure out which slot to use */
88 	slot = calculate_secrets_slot ();
89 	g_return_val_if_fail (slot, FALSE);
90 	secrets_service = g_object_new (GKD_SECRET_TYPE_SERVICE,
91 					"connection", dbus_conn, "pkcs11-slot", slot, NULL);
92 	g_object_unref (slot);
93 
94 	/* Try and grab our name */
95 	request_variant = g_dbus_connection_call_sync (dbus_conn,
96 						       "org.freedesktop.DBus",  /* bus name */
97 						       "/org/freedesktop/DBus", /* object path */
98 						       "org.freedesktop.DBus",  /* interface name */
99 						       "RequestName",           /* method name */
100 						       g_variant_new ("(su)",
101 								      service,
102 								      flags),
103 						       G_VARIANT_TYPE ("(u)"),
104 						       G_DBUS_CALL_FLAGS_NONE,
105 						       -1, NULL, &error);
106 
107 	if (error != NULL) {
108 		g_message ("couldn't request name '%s' on session bus: %s",
109 			   service, error->message);
110 		g_error_free (error);
111 	} else {
112 		g_variant_get (request_variant, "(u)", &res);
113 		g_variant_unref (request_variant);
114 
115 		switch (res) {
116 		/* We acquired the service name */
117 		case 1: /* DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER */
118 		/* We already acquired the service name. */
119 		case 4: /* DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER */
120 			break;
121 		/* Another daemon is running */
122 		case 2: /* DBUS_REQUEST_NAME_REPLY_IN_QUEUE */
123 		case 3: /* DBUS_REQUEST_NAME_REPLY_EXISTS */
124 			g_message ("another secret service is running");
125 			break;
126 		default:
127 			g_clear_object (&secrets_service);
128 			g_return_val_if_reached (FALSE);
129 			break;
130 		};
131 	}
132 
133 	return TRUE;
134 }
135 
136 static void
cleanup_dbus_conn(gpointer unused)137 cleanup_dbus_conn (gpointer unused)
138 {
139 	g_assert (dbus_conn);
140 	g_clear_object (&dbus_conn);
141 }
142 
143 void
gkd_dbus_secrets_init(GDBusConnection * conn)144 gkd_dbus_secrets_init (GDBusConnection *conn)
145 {
146 	dbus_conn = g_object_ref (conn);
147 	egg_cleanup_register (cleanup_dbus_conn, NULL);
148 }
149 
150 void
gkd_dbus_secrets_cleanup(GDBusConnection * conn)151 gkd_dbus_secrets_cleanup (GDBusConnection *conn)
152 {
153 	if (secrets_service) {
154 		g_object_run_dispose (G_OBJECT (secrets_service));
155 		g_object_unref (secrets_service);
156 		secrets_service = NULL;
157 	}
158 }
159