tracker-0.16.2/src/libtracker-miner/tracker-password-provider.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 <string.h>
 23 #include <sys/mman.h>
 24 
 25 #include "tracker-password-provider.h"
 26 
 27 /**
 28  * SECTION:tracker-password-provider
 29  * @short_description: Password storage interface for cross platform backends
 30  * @include: libtracker-miner/tracker-miner.h
 31  *
 32  * The #TrackerPasswordProvider allows different backends to be
 33  * written for storing sensitive information about web services which
 34  * are needed to authenticate and mine data. Currently, there are two
 35  * implementations. One for GNOME Keyring and one using #GKeyFile (as a
 36  * fallback if GNOME Keyring is installed).
 37  **/
 38 
 39 static void
 40 tracker_password_provider_init (gpointer object_class)
 41 {
 42 	static gboolean is_initialized = FALSE;
 43 
 44 	if (!is_initialized) {
 45 		g_object_interface_install_property (object_class,
 46 		                                     g_param_spec_string ("name",
 47 		                                                          "Password provider name",
 48 		                                                          "Password provider name",
 49 		                                                          NULL,
 50 		                                                          G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
 51 		is_initialized = TRUE;
 52 	}
 53 }
 54 
 55 /* That would be better done with G_DECLARE_INTERFACE, but it's GLib 2.24. */
 56 /**
 57  * tracker_password_provider_get_type:
 58  *
 59  * Returns: a #GType representing a %TrackerPasswordProvider.
 60  **/
 61 GType
 62 tracker_password_provider_get_type (void)
 63 {
 64 	static GType iface_type = 0;
 65 
 66 	if (iface_type == 0) {
 67 		static const GTypeInfo info = {
 68 			sizeof (TrackerPasswordProviderIface),
 69 			tracker_password_provider_init,
 70 			NULL
 71 		};
 72 
 73 		iface_type = g_type_register_static (G_TYPE_INTERFACE,
 74 		                                     "TrackerPasswordProvider",
 75 		                                     &info,
 76 		                                     0);
 77 	}
 78 
 79 	return iface_type;
 80 }
 81 
 82 /**
 83  * tracker_password_provider_error_quark:
 84  *
 85  * Returns: the #GQuark used to identify password provider errors in
 86  * GError structures.
 87  *
 88  * Since: 0.8
 89  **/
 90 GQuark
 91 tracker_password_provider_error_quark (void)
 92 {
 93 	return g_quark_from_static_string (TRACKER_PASSWORD_PROVIDER_ERROR_DOMAIN);
 94 }
 95 
 96 /**
 97  * tracker_password_provider_get_name:
 98  * @provider: a TrackerPasswordProvider
 99  *
100  * At the moment there are only two providers, "GNOME Keyring" and
101  * "GKeyFile". Either of these is what will be returned unless new
102  * providers are written.
103  *
104  * Returns: (out) (transfer full): a newly allocated string representing the name which must
105  * be freed with g_free().
106  *
107  * Since: 0.8
108  **/
109 gchar *
110 tracker_password_provider_get_name (TrackerPasswordProvider *provider)
111 {
112 	gchar *name;
113 
114 	g_return_val_if_fail (TRACKER_IS_PASSWORD_PROVIDER (provider), NULL);
115 
116 	g_object_get (provider, "name", &name, NULL);
117 
118 	return name;
119 }
120 
121 /**
122  * tracker_password_provider_store_password:
123  * @provider: a TrackerPasswordProvider
124  * @service: the name of the remote service associated with @username
125  * and @password
126  * @description: the description for @service
127  * @username: the username to store
128  * @password: the password to store
129  * @error: (out callee-allocates) (transfer full) (allow-none): return location for errors
130  *
131  * This function calls the password provider's "store_password"
132  * implementation with @service, @description, @username and @password.
133  *
134  * Returns: %TRUE if the password was saved, otherwise %FALSE is
135  * returned and @error will be set.
136  *
137  * Since: 0.8
138  **/
139 gboolean
140 tracker_password_provider_store_password (TrackerPasswordProvider  *provider,
141                                           const gchar              *service,
142                                           const gchar              *description,
143                                           const gchar              *username,
144                                           const gchar              *password,
145                                           GError                  **error)
146 {
147 	TrackerPasswordProviderIface *iface;
148 
149 	g_return_val_if_fail (TRACKER_IS_PASSWORD_PROVIDER (provider), FALSE);
150 	g_return_val_if_fail (service != NULL, FALSE);
151 	g_return_val_if_fail (description != NULL, FALSE);
152 	g_return_val_if_fail (password != NULL, FALSE);
153 
154 	iface = TRACKER_PASSWORD_PROVIDER_GET_INTERFACE (provider);
155 
156 	if (!iface || !iface->store_password) {
157 		return FALSE;
158 	}
159 
160 	return iface->store_password (provider, service, description, username, password, error);
161 }
162 
163 /**
164  * tracker_password_provider_get_password:
165  * @provider: a TrackerPasswordProvider
166  * @service: the name of the remote service associated with @username
167  * @username: (out): the username associated with the password we are returning
168  * @error: (out callee-allocates) (transfer full) (allow-none): return location for errors
169  *
170  * This function calls the password provider's "get_password"
171  * implementation with @service and @username.
172  *
173  * Returns: a newly allocated string representing a password which
174  * must be freed with g_free(), otherwise %NULL is returned and @error
175  * will be set.
176  *
177  * Since: 0.8
178  **/
179 gchar *
180 tracker_password_provider_get_password (TrackerPasswordProvider  *provider,
181                                         const gchar              *service,
182                                         gchar                   **username,
183                                         GError                  **error)
184 {
185 	TrackerPasswordProviderIface *iface;
186 
187 	g_return_val_if_fail (TRACKER_IS_PASSWORD_PROVIDER (provider), NULL);
188 	g_return_val_if_fail (service != NULL, NULL);
189 
190 	iface = TRACKER_PASSWORD_PROVIDER_GET_INTERFACE (provider);
191 
192 	if (!iface || !iface->get_password) {
193 		return NULL;
194 	}
195 
196 	return iface->get_password (provider, service, username, error);
197 }
198 
199 /**
200  * tracker_password_provider_forget_password:
201  * @provider: a TrackerPasswordProvider
202  * @service: the name of the remote service associated with @username
203  * @error: (out callee-allocates) (transfer full) (allow-none): return location for errors
204  *
205  * This function calls the password provider's "forget_password"
206  * implementation with @service.
207  *
208  * On failure @error will be set.
209  *
210  * Since: 0.8
211  **/
212 void
213 tracker_password_provider_forget_password (TrackerPasswordProvider  *provider,
214                                            const gchar              *service,
215                                            GError                  **error)
216 {
217 	TrackerPasswordProviderIface *iface;
218 
219 	g_return_if_fail (TRACKER_IS_PASSWORD_PROVIDER (provider));
220 	g_return_if_fail (service != NULL);
221 
222 	iface = TRACKER_PASSWORD_PROVIDER_GET_INTERFACE (provider);
223 
224 	if (!iface || !iface->forget_password) {
225 		return;
226 	}
227 
228 	iface->forget_password (provider, service, error);
229 }
230 
231 /**
232  * tracker_password_provider_lock_password:
233  * @password: a string pointer
234  *
235  * This function calls mlock() to secure a memory region newly
236  * allocated and @password is copied using memcpy() into the new
237  * address.
238  *
239  * Password can not be %NULL or an empty string ("").
240  *
241  * Returns: (transfer full): a newly allocated string which <emphasis>MUST</emphasis>
242  * be freed with tracker_password_provider_unlock_password(). On
243  * failure %NULL is returned.
244  *
245  * Since: 0.8
246  **/
247 gchar *
248 tracker_password_provider_lock_password (const gchar *password)
249 {
250 	gchar *dest;
251 	int retval;
252 
253 	g_return_val_if_fail (password != NULL, NULL);
254 	g_return_val_if_fail (password[0] != '\0', NULL);
255 
256 	dest = g_malloc0 (strlen (password) + 1);
257 	retval = mlock (dest, sizeof (dest));
258 
259 	if (retval != 0) {
260 		g_free (dest);
261 		return NULL;
262 	}
263 
264 	memcpy (dest, password, strlen (password));
265 
266 	return dest;
267 }
268 
269 /**
270  * tracker_password_provider_unlock_password:
271  * @password: a string pointer
272  *
273  * This function calls munlock() on @password which should be a
274  * secured memory region. The @password is zeroed first with bzero()
275  * and once unlocked it is freed with g_free().
276  *
277  * The @password can not be %NULL or an empty string (""). In
278  * addition, @password <emphasis>MUST</emphasis> be a string created
279  * with tracker_password_provider_lock_password().
280  *
281  * Returns: %TRUE if munlock() succeeded, otherwise %FALSE is returned.
282  *
283  * Since: 0.8
284  **/
285 gboolean
286 tracker_password_provider_unlock_password (gchar *password)
287 {
288 	int retval;
289 
290 	g_return_val_if_fail (password != NULL, FALSE);
291 	g_return_val_if_fail (password[0] != '\0', FALSE);
292 
293 	bzero (password, strlen (password));
294 	retval = munlock (password, sizeof (password));
295 	g_free (password);
296 
297 	if (retval != 0) {
298 		/* FIXME: Handle errors? */
299 		return FALSE;
300 	}
301 
302 	return TRUE;
303 }