tracker-0.16.2/src/libtracker-miner/tracker-password-provider-gnome.c

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 }