No issues found
1 /*
2 * Copyright (C) 2009, Adrien Bustany <abustany@gnome.org>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 */
19
20 #include "config.h"
21
22 #include <glib-object.h>
23
24 #include <libsecret/secret.h>
25
26 #include "tracker-password-provider.h"
27
28 #define TRACKER_TYPE_PASSWORD_PROVIDER_GNOME (tracker_password_provider_gnome_get_type())
29 #define TRACKER_PASSWORD_PROVIDER_GNOME(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), TRACKER_TYPE_PASSWORD_PROVIDER_GNOME, TrackerPasswordProviderGnome))
30 #define TRACKER_PASSWORD_PROVIDER_GNOME_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), TRACKER_TYPE_PASSWORD_PROVIDER_GNOME, TrackerPasswordProviderGnomeClass))
31 #define TRACKER_IS_PASSWORD_PROVIDER_GNOME(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), TRACKER_TYPE_PASSWORD_PROVIDER_GNOME))
32 #define TRACKER_IS_PASSWORD_PROVIDER_GNOME_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), TRACKER_TYPE_PASSWORD_PROVIDER_GNOME))
33 #define TRACKER_PASSWORD_PROVIDER_GNOME_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), TRACKER_TYPE_PASSWORD_PROVIDER_GNOME, TrackerPasswordProviderGnomeClass))
34
35 #define TRACKER_PASSWORD_PROVIDER_GNOME_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TRACKER_TYPE_PASSWORD_PROVIDER_GNOME, TrackerPasswordProviderGnomePrivate))
36
37 #define PASSWORD_PROVIDER_GNOME_NAME "GNOME Keyring"
38
39 typedef struct TrackerPasswordProviderGnome TrackerPasswordProviderGnome;
40 typedef struct TrackerPasswordProviderGnomeClass TrackerPasswordProviderGnomeClass;
41 typedef struct TrackerPasswordProviderGnomePrivate TrackerPasswordProviderGnomePrivate;
42
43 struct TrackerPasswordProviderGnome {
44 GObject parent;
45 };
46
47 struct TrackerPasswordProviderGnomeClass {
48 GObjectClass parent_class;
49 };
50
51 struct TrackerPasswordProviderGnomePrivate {
52 gchar *name;
53 };
54
55 GType tracker_password_provider_gnome_get_type (void) G_GNUC_CONST;
56 static void tracker_password_provider_iface_init (TrackerPasswordProviderIface *iface);
57 static void password_provider_set_property (GObject *object,
58 guint prop_id,
59 const GValue *value,
60 GParamSpec *pspec);
61 static void password_provider_get_property (GObject *object,
62 guint prop_id,
63 GValue *value,
64 GParamSpec *pspec);
65 static gboolean password_provider_gnome_store (TrackerPasswordProvider *provider,
66 const gchar *service,
67 const gchar *description,
68 const gchar *username,
69 const gchar *password,
70 GError **error);
71 static gchar* password_provider_gnome_get (TrackerPasswordProvider *provider,
72 const gchar *service,
73 gchar **username,
74 GError **error);
75 static gboolean password_provider_gnome_forget (TrackerPasswordProvider *provider,
76 const gchar *service,
77 GError **error);
78 static const SecretSchema password_schema = {
79 "org.gnome.Tracker.Miner",
80 SECRET_SCHEMA_DONT_MATCH_NAME,
81 { { "service", SECRET_SCHEMA_ATTRIBUTE_STRING },
82 { "username", SECRET_SCHEMA_ATTRIBUTE_STRING },
83 { NULL, 0 }
84 }
85 };
86
87 enum {
88 PROP_0,
89 PROP_NAME
90 };
91
92 G_DEFINE_TYPE_WITH_CODE (TrackerPasswordProviderGnome,
93 tracker_password_provider_gnome,
94 G_TYPE_OBJECT,
95 G_IMPLEMENT_INTERFACE (TRACKER_TYPE_PASSWORD_PROVIDER,
96 tracker_password_provider_iface_init))
97
98 static void
99 tracker_password_provider_gnome_class_init (TrackerPasswordProviderGnomeClass *klass)
100 {
101 GObjectClass *object_class = G_OBJECT_CLASS (klass);
102
103 object_class->set_property = password_provider_set_property;
104 object_class->get_property = password_provider_get_property;
105
106 g_object_class_override_property (object_class, PROP_NAME, "name");
107
108 g_type_class_add_private (object_class, sizeof (TrackerPasswordProviderGnomePrivate));
109 }
110
111 static void
112 tracker_password_provider_gnome_init (TrackerPasswordProviderGnome *provider)
113 {
114 }
115
116 static void
117 tracker_password_provider_iface_init (TrackerPasswordProviderIface *iface)
118 {
119 iface->store_password = password_provider_gnome_store;
120 iface->get_password = password_provider_gnome_get;
121 iface->forget_password = password_provider_gnome_forget;
122 }
123
124 static void
125 password_provider_set_property (GObject *object,
126 guint prop_id,
127 const GValue *value,
128 GParamSpec *pspec)
129 {
130 TrackerPasswordProviderGnomePrivate *priv;
131
132 priv = TRACKER_PASSWORD_PROVIDER_GNOME_GET_PRIVATE (object);
133
134 switch (prop_id) {
135 case PROP_NAME:
136 g_free (priv->name);
137 priv->name = g_value_dup_string (value);
138 g_object_notify (object, "name");
139 break;
140
141 default:
142 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
143 break;
144 };
145 }
146
147 static void
148 password_provider_get_property (GObject *object,
149 guint prop_id,
150 GValue *value,
151 GParamSpec *pspec)
152 {
153 TrackerPasswordProviderGnomePrivate *priv;
154
155 priv = TRACKER_PASSWORD_PROVIDER_GNOME_GET_PRIVATE (object);
156
157 switch (prop_id) {
158 case PROP_NAME:
159 g_value_set_string (value, priv->name);
160 break;
161
162 default:
163 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
164 break;
165 };
166 }
167
168 static gboolean
169 password_provider_gnome_store (TrackerPasswordProvider *provider,
170 const gchar *service,
171 const gchar *description,
172 const gchar *username,
173 const gchar *password,
174 GError **error)
175 {
176 GError *secret_error = NULL;
177
178 secret_password_store_sync (&password_schema, NULL, description,
179 password, NULL, &secret_error,
180 "service", service,
181 "username", username,
182 NULL);
183
184 if (secret_error != NULL) {
185 g_set_error (error,
186 TRACKER_PASSWORD_PROVIDER_ERROR,
187 TRACKER_PASSWORD_PROVIDER_ERROR_SERVICE,
188 "Could not store GNOME keyring password, %s",
189 secret_error->message);
190 g_error_free (secret_error);
191 return FALSE;
192 }
193
194 return TRUE;
195 }
196
197 static gchar *
198 password_provider_gnome_get (TrackerPasswordProvider *provider,
199 const gchar *service,
200 gchar **username,
201 GError **error)
202 {
203 GList *found_items = NULL;
204 GHashTable *search_attributes;
205 GHashTable *attributes;
206 GError *secret_error = NULL;
207 SecretValue *secret = NULL;
208 SecretItem *found = NULL;
209 gchar *password;
210
211 search_attributes = secret_attributes_build (&password_schema,
212 "service", service,
213 NULL);
214
215 found_items = secret_service_search_sync (NULL,
216 &password_schema,
217 search_attributes,
218 SECRET_SEARCH_UNLOCK | SECRET_SEARCH_LOAD_SECRETS,
219 NULL,
220 &secret_error);
221
222 g_hash_table_unref (search_attributes);
223
224 if (secret_error != NULL) {
225 g_set_error (error,
226 TRACKER_PASSWORD_PROVIDER_ERROR,
227 TRACKER_PASSWORD_PROVIDER_ERROR_SERVICE,
228 "Could not fetch GNOME keyring password, %s",
229 secret_error->message);
230 g_error_free (secret_error);
231 return NULL;
232 }
233
234 if (found_items != NULL) {
235 found = found_items->data;
236 secret = secret_item_get_secret (found);
237 }
238
239 if (secret == NULL) {
240 g_set_error_literal (error,
241 TRACKER_PASSWORD_PROVIDER_ERROR,
242 TRACKER_PASSWORD_PROVIDER_ERROR_NOTFOUND,
243 "Could not find GNOME keyring password");
244 g_list_free_full (found_items, g_object_unref);
245 return NULL;
246 }
247
248 /* Find username if we asked for it */
249 if (username) {
250 /* Make sure it is always set */
251 attributes = secret_item_get_attributes (found);
252 *username = g_strdup (g_hash_table_lookup (attributes, "username"));
253 g_hash_table_unref (attributes);
254 }
255
256 password = tracker_password_provider_lock_password (secret_value_get (secret, NULL));
257 secret_value_unref (secret);
258 g_list_free_full (found_items, g_object_unref);
259
260 return password;
261 }
262
263 static gboolean
264 password_provider_gnome_forget (TrackerPasswordProvider *provider,
265 const gchar *service,
266 GError **error)
267 {
268 GError *secret_error = NULL;
269
270 secret_password_clear_sync (&password_schema,
271 NULL,
272 &secret_error,
273 "service", service,
274 NULL);
275
276 if (secret_error != NULL) {
277 g_set_error (error,
278 TRACKER_PASSWORD_PROVIDER_ERROR,
279 TRACKER_PASSWORD_PROVIDER_ERROR_SERVICE,
280 "Coult not delete GNOME keyring password, %s",
281 secret_error->message);
282 g_error_free (secret_error);
283 return FALSE;
284 }
285
286 return TRUE;
287 }
288
289 TrackerPasswordProvider *
290 tracker_password_provider_get (void)
291 {
292 static TrackerPasswordProvider *instance = NULL;
293 static GMutex mutex;
294
295 g_mutex_lock (&mutex);
296
297 if (!instance) {
298 instance = g_object_new (TRACKER_TYPE_PASSWORD_PROVIDER_GNOME,
299 "name", PASSWORD_PROVIDER_GNOME_NAME,
300 NULL);
301 }
302
303 g_mutex_unlock (&mutex);
304
305 return instance;
306 }