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 }