1 /* libsecret - GLib wrapper for Secret Service
2 *
3 * Copyright 2011 Collabora Ltd.
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU Lesser General Public License as published
7 * by the Free Software Foundation; either version 2.1 of the licence or (at
8 * your option) any later version.
9 *
10 * See the included COPYING file for more information.
11 *
12 * Author: Stef Walter <stefw@gnome.org>
13 */
14
15 #include "config.h"
16
17 #include "secret-attributes.h"
18 #include "secret-password.h"
19 #include "secret-private.h"
20 #include "secret-retrievable.h"
21 #include "secret-backend.h"
22 #include "secret-value.h"
23
24 #include <egg/egg-secure-memory.h>
25
26 /**
27 * SECTION:secret-password
28 * @title: Password storage
29 * @short_description: Simple password storage and lookup
30 *
31 * This is a simple API for storing passwords and retrieving passwords in the
32 * Secret Service.
33 *
34 * Each password is associated with a set of attributes. Attribute values can
35 * be either strings, integers or booleans.
36 *
37 * The names and types of allowed attributes for a given password are defined
38 * with a schema. Certain schemas are predefined. Additional schemas can be
39 * defined via the %SecretSchema structure.
40 *
41 * Each of the functions accept a variable list of attributes names and their
42 * values. Include a %NULL to terminate the list of attributes.
43 *
44 * Stability: Stable
45 */
46
47 /**
48 * secret_password_store: (skip)
49 * @schema: the schema for attributes
50 * @collection: (allow-none): a collection alias, or D-Bus object path of the collection where to store the secret
51 * @label: label for the secret
52 * @password: the null-terminated password to store
53 * @cancellable: optional cancellation object
54 * @callback: called when the operation completes
55 * @user_data: data to be passed to the callback
56 * @...: the attribute keys and values, terminated with %NULL
57 *
58 * Store a password in the secret service.
59 *
60 * The variable argument list should contain pairs of a) The attribute name as
61 * a null-terminated string, followed by b) attribute value, either a character
62 * string, an int number, or a gboolean value, as defined in the @schema.
63 * The list of attribtues should be terminated with a %NULL.
64 *
65 * If the attributes match a secret item already stored in the collection, then
66 * the item will be updated with these new values.
67 *
68 * If @collection is %NULL, then the default collection will be
69 * used. Use #SECRET_COLLECTION_SESSION to store the password in the session
70 * collection, which doesn't get stored across login sessions.
71 *
72 * This method will return immediately and complete asynchronously.
73 */
74 void
secret_password_store(const SecretSchema * schema,const gchar * collection,const gchar * label,const gchar * password,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data,...)75 secret_password_store (const SecretSchema *schema,
76 const gchar *collection,
77 const gchar *label,
78 const gchar *password,
79 GCancellable *cancellable,
80 GAsyncReadyCallback callback,
81 gpointer user_data,
82 ...)
83 {
84 GHashTable *attributes;
85 va_list va;
86
87 g_return_if_fail (schema != NULL);
88 g_return_if_fail (label != NULL);
89 g_return_if_fail (password != NULL);
90 g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
91
92 va_start (va, user_data);
93 attributes = secret_attributes_buildv (schema, va);
94 va_end (va);
95
96 /* Precondition failed, already warned */
97 if (!attributes)
98 return;
99
100 secret_password_storev (schema, attributes, collection, label, password,
101 cancellable, callback, user_data);
102
103 g_hash_table_unref (attributes);
104 }
105
106 typedef struct {
107 const SecretSchema *schema;
108 GHashTable *attributes;
109 gchar *collection;
110 gchar *label;
111 SecretValue *value;
112 } StoreClosure;
113
114 static void
store_closure_free(gpointer data)115 store_closure_free (gpointer data)
116 {
117 StoreClosure *store = data;
118 _secret_schema_unref_if_nonstatic (store->schema);
119 g_hash_table_unref (store->attributes);
120 g_free (store->collection);
121 g_free (store->label);
122 secret_value_unref (store->value);
123 g_slice_free (StoreClosure, store);
124 }
125
126 static void
on_store(GObject * source,GAsyncResult * result,gpointer user_data)127 on_store (GObject *source,
128 GAsyncResult *result,
129 gpointer user_data)
130 {
131 GTask *task = G_TASK (user_data);
132 SecretBackend *backend = SECRET_BACKEND (source);
133 SecretBackendInterface *iface;
134 GError *error = NULL;
135
136 iface = SECRET_BACKEND_GET_IFACE (backend);
137 g_return_if_fail (iface->store_finish != NULL);
138
139 if (!iface->store_finish (backend, result, &error)) {
140 g_task_return_error (task, error);
141 g_object_unref (task);
142 return;
143 }
144
145 g_task_return_boolean (task, TRUE);
146 g_object_unref (task);
147 }
148
149 static void
on_store_backend(GObject * source,GAsyncResult * result,gpointer user_data)150 on_store_backend (GObject *source,
151 GAsyncResult *result,
152 gpointer user_data)
153 {
154 GTask *task = G_TASK (user_data);
155 StoreClosure *store = g_task_get_task_data (task);
156 SecretBackend *backend;
157 SecretBackendInterface *iface;
158 GError *error = NULL;
159
160 backend = secret_backend_get_finish (result, &error);
161 if (backend == NULL) {
162 g_task_return_error (task, error);
163 g_object_unref (task);
164 return;
165 }
166
167 iface = SECRET_BACKEND_GET_IFACE (backend);
168 g_return_if_fail (iface->store != NULL);
169
170 iface->store (backend, store->schema, store->attributes,
171 store->collection, store->label, store->value,
172 g_task_get_cancellable (task),
173 on_store,
174 task);
175 }
176
177 /**
178 * secret_password_storev: (rename-to secret_password_store)
179 * @schema: (nullable): the schema for attributes
180 * @attributes: (element-type utf8 utf8) (transfer full): the attribute keys and values
181 * @collection: (allow-none): a collection alias, or D-Bus object path of the collection where to store the secret
182 * @label: label for the secret
183 * @password: the null-terminated password to store
184 * @cancellable: optional cancellation object
185 * @callback: (scope async): called when the operation completes
186 * @user_data: data to be passed to the callback
187 *
188 * Store a password in the secret service.
189 *
190 * The @attributes should be a set of key and value string pairs.
191 *
192 * If the attributes match a secret item already stored in the collection, then
193 * the item will be updated with these new values.
194 *
195 * If @collection is %NULL, then the default collection will be
196 * used. Use #SECRET_COLLECTION_SESSION to store the password in the session
197 * collection, which doesn't get stored across login sessions.
198 *
199 * This method will return immediately and complete asynchronously.
200 */
201 void
secret_password_storev(const SecretSchema * schema,GHashTable * attributes,const gchar * collection,const gchar * label,const gchar * password,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)202 secret_password_storev (const SecretSchema *schema,
203 GHashTable *attributes,
204 const gchar *collection,
205 const gchar *label,
206 const gchar *password,
207 GCancellable *cancellable,
208 GAsyncReadyCallback callback,
209 gpointer user_data)
210 {
211 StoreClosure *store;
212 GTask *task;
213
214 g_return_if_fail (label != NULL);
215 g_return_if_fail (password != NULL);
216 g_return_if_fail (attributes != NULL);
217 g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
218
219 /* Warnings raised already */
220 if (schema != NULL && !_secret_attributes_validate (schema, attributes, G_STRFUNC, FALSE))
221 return;
222
223 task = g_task_new (NULL, cancellable, callback, user_data);
224 store = g_slice_new0 (StoreClosure);
225 store->schema = _secret_schema_ref_if_nonstatic (schema);
226 store->attributes = g_hash_table_ref (attributes);
227 store->collection = g_strdup (collection);
228 store->label = g_strdup (label);
229 store->value = secret_value_new (password, -1, "text/plain");
230 g_task_set_task_data (task, store, store_closure_free);
231
232 secret_backend_get (SECRET_BACKEND_OPEN_SESSION,
233 cancellable,
234 on_store_backend, task);
235 }
236
237 /**
238 * secret_password_store_binary: (skip)
239 * @schema: the schema for attributes
240 * @collection: (allow-none): a collection alias, or D-Bus object path of the collection where to store the secret
241 * @label: label for the secret
242 * @value: a #SecretValue
243 * @cancellable: optional cancellation object
244 * @callback: called when the operation completes
245 * @user_data: data to be passed to the callback
246 * @...: the attribute keys and values, terminated with %NULL
247 *
248 * Store a password in the secret service.
249 *
250 * This is similar to secret_password_store(), but takes a
251 * #SecretValue as the argument instead of a null-terminated password.
252 *
253 * This method will return immediately and complete asynchronously.
254 *
255 * Since: 0.19.0
256 */
257 void
secret_password_store_binary(const SecretSchema * schema,const gchar * collection,const gchar * label,SecretValue * value,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data,...)258 secret_password_store_binary (const SecretSchema *schema,
259 const gchar *collection,
260 const gchar *label,
261 SecretValue *value,
262 GCancellable *cancellable,
263 GAsyncReadyCallback callback,
264 gpointer user_data,
265 ...)
266 {
267 GHashTable *attributes;
268 va_list va;
269
270 g_return_if_fail (schema != NULL);
271 g_return_if_fail (label != NULL);
272 g_return_if_fail (value != NULL);
273 g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
274
275 va_start (va, user_data);
276 attributes = secret_attributes_buildv (schema, va);
277 va_end (va);
278
279 /* Precondition failed, already warned */
280 if (!attributes)
281 return;
282
283 secret_password_storev_binary (schema, attributes, collection, label, value,
284 cancellable, callback, user_data);
285
286 g_hash_table_unref (attributes);
287 }
288
289 /**
290 * secret_password_storev_binary: (rename-to secret_password_store_binary)
291 * @schema: (nullable): the schema for attributes
292 * @attributes: (element-type utf8 utf8) (transfer full): the attribute keys and values
293 * @collection: (allow-none): a collection alias, or D-Bus object path of the collection where to store the secret
294 * @label: label for the secret
295 * @value: a #SecretValue
296 * @cancellable: optional cancellation object
297 * @callback: (scope async): called when the operation completes
298 * @user_data: data to be passed to the callback
299 *
300 * Store a password in the secret service.
301 *
302 * This is similar to secret_password_storev(), but takes a
303 * #SecretValue as the argument instead of a null-terminated password.
304 *
305 * This method will return immediately and complete asynchronously.
306 *
307 * Since: 0.19.0
308 */
309 void
secret_password_storev_binary(const SecretSchema * schema,GHashTable * attributes,const gchar * collection,const gchar * label,SecretValue * value,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)310 secret_password_storev_binary (const SecretSchema *schema,
311 GHashTable *attributes,
312 const gchar *collection,
313 const gchar *label,
314 SecretValue *value,
315 GCancellable *cancellable,
316 GAsyncReadyCallback callback,
317 gpointer user_data)
318 {
319 StoreClosure *store;
320 GTask *task;
321
322 g_return_if_fail (label != NULL);
323 g_return_if_fail (value != NULL);
324 g_return_if_fail (attributes != NULL);
325 g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
326
327 /* Warnings raised already */
328 if (schema != NULL && !_secret_attributes_validate (schema, attributes, G_STRFUNC, FALSE))
329 return;
330
331 task = g_task_new (NULL, cancellable, callback, user_data);
332 store = g_slice_new0 (StoreClosure);
333 store->schema = _secret_schema_ref_if_nonstatic (schema);
334 store->attributes = g_hash_table_ref (attributes);
335 store->collection = g_strdup (collection);
336 store->label = g_strdup (label);
337 store->value = secret_value_ref (value);
338 g_task_set_task_data (task, store, store_closure_free);
339
340 secret_backend_get (SECRET_BACKEND_OPEN_SESSION,
341 cancellable,
342 on_store_backend, task);
343 }
344
345 /**
346 * secret_password_store_finish:
347 * @result: the asynchronous result passed to the callback
348 * @error: location to place an error on failure
349 *
350 * Finish asynchronous operation to store a password in the secret service.
351 *
352 * Returns: whether the storage was successful or not
353 */
354 gboolean
secret_password_store_finish(GAsyncResult * result,GError ** error)355 secret_password_store_finish (GAsyncResult *result,
356 GError **error)
357 {
358 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
359 g_return_val_if_fail (g_task_is_valid (result, NULL), FALSE);
360
361 return g_task_propagate_boolean (G_TASK (result), error);
362 }
363
364 /**
365 * secret_password_store_sync:
366 * @schema: the schema for attributes
367 * @collection: (allow-none): a collection alias, or D-Bus object path of the collection where to store the secret
368 * @label: label for the secret
369 * @password: the null-terminated password to store
370 * @cancellable: optional cancellation object
371 * @error: location to place an error on failure
372 * @...: the attribute keys and values, terminated with %NULL
373 *
374 * Store a password in the secret service.
375 *
376 * The variable argument list should contain pairs of a) The attribute name as
377 * a null-terminated string, followed by b) attribute value, either a character
378 * string, an int number, or a gboolean value, as defined in the @schema.
379 * The list of attribtues should be terminated with a %NULL.
380 *
381 * If the attributes match a secret item already stored in the collection, then
382 * the item will be updated with these new values.
383 *
384 * If @collection is %NULL, then the default collection will be
385 * used. Use #SECRET_COLLECTION_SESSION to store the password in the session
386 * collection, which doesn't get stored across login sessions.
387 *
388 * This method may block indefinitely and should not be used in user interface
389 * threads.
390 *
391 * Returns: whether the storage was successful or not
392 */
393 gboolean
secret_password_store_sync(const SecretSchema * schema,const gchar * collection,const gchar * label,const gchar * password,GCancellable * cancellable,GError ** error,...)394 secret_password_store_sync (const SecretSchema *schema,
395 const gchar *collection,
396 const gchar *label,
397 const gchar *password,
398 GCancellable *cancellable,
399 GError **error,
400 ...)
401 {
402 GHashTable *attributes;
403 va_list va;
404 gboolean ret;
405
406 g_return_val_if_fail (schema != NULL, FALSE);
407 g_return_val_if_fail (label != NULL, FALSE);
408 g_return_val_if_fail (password != NULL, FALSE);
409 g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
410 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
411
412 va_start (va, error);
413 attributes = secret_attributes_buildv (schema, va);
414 va_end (va);
415
416 /* Precondition failed, already warned */
417 if (!attributes)
418 return FALSE;
419
420 ret = secret_password_storev_sync (schema, attributes, collection,
421 label, password, cancellable, error);
422
423 g_hash_table_unref (attributes);
424 return ret;
425 }
426
427 /**
428 * secret_password_storev_sync: (rename-to secret_password_store_sync)
429 * @schema: (nullable): the schema for attributes
430 * @attributes: (element-type utf8 utf8): the attribute keys and values
431 * @collection: (allow-none): a collection alias, or D-Bus object path of the collection where to store the secret
432 * @label: label for the secret
433 * @password: the null-terminated password to store
434 * @cancellable: optional cancellation object
435 * @error: location to place an error on failure
436 *
437 * Store a password in the secret service.
438 *
439 * The @attributes should be a set of key and value string pairs.
440 *
441 * If the attributes match a secret item already stored in the collection, then
442 * the item will be updated with these new values.
443 *
444 * If @collection is %NULL, then the default collection will be
445 * used. Use #SECRET_COLLECTION_SESSION to store the password in the session
446 * collection, which doesn't get stored across login sessions.
447 *
448 * This method may block indefinitely and should not be used in user interface
449 * threads.
450 *
451 * Returns: whether the storage was successful or not
452 */
453 gboolean
secret_password_storev_sync(const SecretSchema * schema,GHashTable * attributes,const gchar * collection,const gchar * label,const gchar * password,GCancellable * cancellable,GError ** error)454 secret_password_storev_sync (const SecretSchema *schema,
455 GHashTable *attributes,
456 const gchar *collection,
457 const gchar *label,
458 const gchar *password,
459 GCancellable *cancellable,
460 GError **error)
461 {
462 SecretSync *sync;
463 gboolean ret;
464
465 g_return_val_if_fail (label != NULL, FALSE);
466 g_return_val_if_fail (password != NULL, FALSE);
467 g_return_val_if_fail (attributes != NULL, FALSE);
468 g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
469 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
470
471 /* Warnings raised already */
472 if (schema != NULL && !_secret_attributes_validate (schema, attributes, G_STRFUNC, FALSE))
473 return FALSE;
474
475 sync = _secret_sync_new ();
476 g_main_context_push_thread_default (sync->context);
477
478 secret_password_storev (schema, attributes, collection, label, password,
479 cancellable, _secret_sync_on_result, sync);
480
481 g_main_loop_run (sync->loop);
482
483 ret = secret_password_store_finish (sync->result, error);
484
485 g_main_context_pop_thread_default (sync->context);
486 _secret_sync_free (sync);
487
488 return ret;
489 }
490
491 /**
492 * secret_password_store_binary_sync:
493 * @schema: the schema for attributes
494 * @collection: (allow-none): a collection alias, or D-Bus object path of the collection where to store the secret
495 * @label: label for the secret
496 * @value: a #SecretValue
497 * @cancellable: optional cancellation object
498 * @error: location to place an error on failure
499 * @...: the attribute keys and values, terminated with %NULL
500 *
501 * Store a password in the secret service.
502 *
503 * This is similar to secret_password_store_sync(), but takes a
504 * #SecretValue as the argument instead of a null terminated password.
505 *
506 * This method may block indefinitely and should not be used in user interface
507 * threads.
508 *
509 * Returns: whether the storage was successful or not
510 *
511 * Since: 0.19.0
512 */
513 gboolean
secret_password_store_binary_sync(const SecretSchema * schema,const gchar * collection,const gchar * label,SecretValue * value,GCancellable * cancellable,GError ** error,...)514 secret_password_store_binary_sync (const SecretSchema *schema,
515 const gchar *collection,
516 const gchar *label,
517 SecretValue *value,
518 GCancellable *cancellable,
519 GError **error,
520 ...)
521 {
522 GHashTable *attributes;
523 va_list va;
524 gboolean ret;
525
526 g_return_val_if_fail (schema != NULL, FALSE);
527 g_return_val_if_fail (label != NULL, FALSE);
528 g_return_val_if_fail (value != NULL, FALSE);
529 g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
530 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
531
532 va_start (va, error);
533 attributes = secret_attributes_buildv (schema, va);
534 va_end (va);
535
536 /* Precondition failed, already warned */
537 if (!attributes)
538 return FALSE;
539
540 ret = secret_password_storev_binary_sync (schema, attributes, collection,
541 label, value, cancellable, error);
542
543 g_hash_table_unref (attributes);
544 return ret;
545 }
546
547 /**
548 * secret_password_storev_binary_sync: (rename-to secret_password_store_binary_sync)
549 * @schema: (nullable): the schema for attributes
550 * @attributes: (element-type utf8 utf8): the attribute keys and values
551 * @collection: (allow-none): a collection alias, or D-Bus object path of the collection where to store the secret
552 * @label: label for the secret
553 * @value: a #SecretValue
554 * @cancellable: optional cancellation object
555 * @error: location to place an error on failure
556 *
557 * Store a password in the secret service.
558 *
559 * This is similar to secret_password_storev_sync(), but takes a
560 * #SecretValue as the argument instead of a null-terminated passwords.
561 *
562 * This method may block indefinitely and should not be used in user interface
563 * threads.
564 *
565 * Returns: whether the storage was successful or not
566 *
567 * Since: 0.19.0
568 */
569 gboolean
secret_password_storev_binary_sync(const SecretSchema * schema,GHashTable * attributes,const gchar * collection,const gchar * label,SecretValue * value,GCancellable * cancellable,GError ** error)570 secret_password_storev_binary_sync (const SecretSchema *schema,
571 GHashTable *attributes,
572 const gchar *collection,
573 const gchar *label,
574 SecretValue *value,
575 GCancellable *cancellable,
576 GError **error)
577 {
578 SecretSync *sync;
579 gboolean ret;
580
581 g_return_val_if_fail (label != NULL, FALSE);
582 g_return_val_if_fail (value != NULL, FALSE);
583 g_return_val_if_fail (attributes != NULL, FALSE);
584 g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
585 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
586
587 /* Warnings raised already */
588 if (schema != NULL && !_secret_attributes_validate (schema, attributes, G_STRFUNC, FALSE))
589 return FALSE;
590
591 sync = _secret_sync_new ();
592 g_main_context_push_thread_default (sync->context);
593
594 secret_password_storev_binary (schema, attributes, collection, label, value,
595 cancellable, _secret_sync_on_result, sync);
596
597 g_main_loop_run (sync->loop);
598
599 ret = secret_password_store_finish (sync->result, error);
600
601 g_main_context_pop_thread_default (sync->context);
602 _secret_sync_free (sync);
603
604 return ret;
605 }
606
607 /**
608 * secret_password_lookup: (skip)
609 * @schema: the schema for the attributes
610 * @cancellable: optional cancellation object
611 * @callback: called when the operation completes
612 * @user_data: data to be passed to the callback
613 * @...: the attribute keys and values, terminated with %NULL
614 *
615 * Lookup a password in the secret service.
616 *
617 * The variable argument list should contain pairs of a) The attribute name as
618 * a null-terminated string, followed by b) attribute value, either a character
619 * string, an int number, or a gboolean value, as defined in the password
620 * @schema. The list of attribtues should be terminated with a %NULL.
621 *
622 * If no secret is found then %NULL is returned.
623 *
624 * This method will return immediately and complete asynchronously.
625 */
626 void
secret_password_lookup(const SecretSchema * schema,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data,...)627 secret_password_lookup (const SecretSchema *schema,
628 GCancellable *cancellable,
629 GAsyncReadyCallback callback,
630 gpointer user_data,
631 ...)
632 {
633 GHashTable *attributes;
634 va_list va;
635
636 g_return_if_fail (schema != NULL);
637 g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
638
639 va_start (va, user_data);
640 attributes = secret_attributes_buildv (schema, va);
641 va_end (va);
642
643 /* Precondition failed, already warned */
644 if (!attributes)
645 return;
646
647 secret_password_lookupv (schema, attributes, cancellable,
648 callback, user_data);
649
650 g_hash_table_unref (attributes);
651 }
652
653 typedef struct {
654 const SecretSchema *schema;
655 GHashTable *attributes;
656 } LookupClosure;
657
658 static void
lookup_closure_free(gpointer data)659 lookup_closure_free (gpointer data)
660 {
661 LookupClosure *closure = data;
662 _secret_schema_unref_if_nonstatic (closure->schema);
663 g_hash_table_unref (closure->attributes);
664 g_slice_free (LookupClosure, closure);
665 }
666
667 static void
on_lookup(GObject * source,GAsyncResult * result,gpointer user_data)668 on_lookup (GObject *source,
669 GAsyncResult *result,
670 gpointer user_data)
671 {
672 GTask *task = G_TASK (user_data);
673 SecretBackend *backend = SECRET_BACKEND (source);
674 SecretBackendInterface *iface;
675 SecretValue *value;
676 GError *error = NULL;
677
678 iface = SECRET_BACKEND_GET_IFACE (backend);
679 g_return_if_fail (iface->store_finish != NULL);
680
681 value = iface->lookup_finish (backend, result, &error);
682 if (error) {
683 g_task_return_error (task, error);
684 g_object_unref (task);
685 return;
686 }
687
688 if (value)
689 g_task_return_pointer (task, value, secret_value_unref);
690 else
691 g_task_return_pointer (task, NULL, NULL);
692 g_object_unref (task);
693 }
694
695 static void
on_lookup_backend(GObject * source,GAsyncResult * result,gpointer user_data)696 on_lookup_backend (GObject *source,
697 GAsyncResult *result,
698 gpointer user_data)
699 {
700 GTask *task = G_TASK (user_data);
701 LookupClosure *lookup = g_task_get_task_data (task);
702 SecretBackend *backend;
703 SecretBackendInterface *iface;
704 GError *error = NULL;
705
706 backend = secret_backend_get_finish (result, &error);
707 if (backend == NULL) {
708 g_task_return_error (task, error);
709 g_object_unref (task);
710 return;
711 }
712
713 iface = SECRET_BACKEND_GET_IFACE (backend);
714 g_return_if_fail (iface->store != NULL);
715
716 iface->lookup (backend, lookup->schema, lookup->attributes,
717 g_task_get_cancellable (task),
718 on_lookup,
719 task);
720 }
721
722 /**
723 * secret_password_lookupv: (rename-to secret_password_lookup)
724 * @schema: (nullable): the schema for attributes
725 * @attributes: (element-type utf8 utf8) (transfer full): the attribute keys and values
726 * @cancellable: optional cancellation object
727 * @callback: (scope async): called when the operation completes
728 * @user_data: data to be passed to the callback
729 *
730 * Lookup a password in the secret service.
731 *
732 * The @attributes should be a set of key and value string pairs.
733 *
734 * If no secret is found then %NULL is returned.
735 *
736 * This method will return immediately and complete asynchronously.
737 */
738 void
secret_password_lookupv(const SecretSchema * schema,GHashTable * attributes,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)739 secret_password_lookupv (const SecretSchema *schema,
740 GHashTable *attributes,
741 GCancellable *cancellable,
742 GAsyncReadyCallback callback,
743 gpointer user_data)
744 {
745 LookupClosure *lookup;
746 GTask *task;
747
748 g_return_if_fail (attributes != NULL);
749 g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
750
751 /* Warnings raised already */
752 if (schema != NULL && !_secret_attributes_validate (schema, attributes, G_STRFUNC, TRUE))
753 return;
754
755 task = g_task_new (NULL, cancellable, callback, user_data);
756 lookup = g_slice_new0 (LookupClosure);
757 lookup->schema = _secret_schema_ref_if_nonstatic (schema);
758 lookup->attributes = g_hash_table_ref (attributes);
759 g_task_set_task_data (task, lookup, lookup_closure_free);
760
761 secret_backend_get (SECRET_BACKEND_OPEN_SESSION,
762 cancellable,
763 on_lookup_backend, task);
764 }
765
766 /**
767 * secret_password_lookup_nonpageable_finish: (skip)
768 * @result: the asynchronous result passed to the callback
769 * @error: location to place an error on failure
770 *
771 * Finish an asynchronous operation to lookup a password in the secret service.
772 *
773 * Returns: (transfer full): a new password string stored in nonpageable memory
774 * which must be freed with secret_password_free() when done
775 */
776 gchar *
secret_password_lookup_nonpageable_finish(GAsyncResult * result,GError ** error)777 secret_password_lookup_nonpageable_finish (GAsyncResult *result,
778 GError **error)
779 {
780 SecretValue *value;
781
782 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
783 g_return_val_if_fail (g_task_is_valid (result, NULL), NULL);
784
785 value = g_task_propagate_pointer (G_TASK (result), error);
786 if (value == NULL)
787 return NULL;
788
789 return _secret_value_unref_to_password (value);
790 }
791
792 /**
793 * secret_password_lookup_binary_finish: (skip)
794 * @result: the asynchronous result passed to the callback
795 * @error: location to place an error on failure
796 *
797 * Finish an asynchronous operation to lookup a password in the secret service.
798 *
799 * Returns: (transfer full): a newly allocated #SecretValue, which should be
800 * released with secret_value_unref(), or %NULL if no secret found
801 *
802 * Since: 0.19.0
803 */
804 SecretValue *
secret_password_lookup_binary_finish(GAsyncResult * result,GError ** error)805 secret_password_lookup_binary_finish (GAsyncResult *result,
806 GError **error)
807 {
808 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
809 g_return_val_if_fail (g_task_is_valid (result, NULL), NULL);
810
811 return g_task_propagate_pointer (G_TASK (result), error);
812 }
813
814 /**
815 * secret_password_lookup_finish:
816 * @result: the asynchronous result passed to the callback
817 * @error: location to place an error on failure
818 *
819 * Finish an asynchronous operation to lookup a password in the secret service.
820 *
821 * Returns: (transfer full): a new password string which should be freed with
822 * secret_password_free() or may be freed with g_free() when done
823 */
824 gchar *
secret_password_lookup_finish(GAsyncResult * result,GError ** error)825 secret_password_lookup_finish (GAsyncResult *result,
826 GError **error)
827 {
828 SecretValue *value;
829
830 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
831 g_return_val_if_fail (g_task_is_valid (result, NULL), NULL);
832
833 value = g_task_propagate_pointer (G_TASK (result), error);
834 if (value == NULL)
835 return NULL;
836
837 return _secret_value_unref_to_string (value);
838 }
839
840 /**
841 * secret_password_lookup_sync: (skip)
842 * @schema: the schema for the attributes
843 * @cancellable: optional cancellation object
844 * @error: location to place an error on failure
845 * @...: the attribute keys and values, terminated with %NULL
846 *
847 * Lookup a password in the secret service.
848 *
849 * The variable argument list should contain pairs of a) The attribute name as
850 * a null-terminated string, followed by b) attribute value, either a character
851 * string, an int number, or a gboolean value, as defined in the password
852 * @schema. The list of attributes should be terminated with a %NULL.
853 *
854 * If no secret is found then %NULL is returned.
855 *
856 * This method may block indefinitely and should not be used in user interface
857 * threads.
858 *
859 * Returns: (transfer full): a new password string which should be freed with
860 * secret_password_free() or may be freed with g_free() when done
861 */
862 gchar *
secret_password_lookup_sync(const SecretSchema * schema,GCancellable * cancellable,GError ** error,...)863 secret_password_lookup_sync (const SecretSchema *schema,
864 GCancellable *cancellable,
865 GError **error,
866 ...)
867 {
868 GHashTable *attributes;
869 gchar *password;
870 va_list va;
871
872 g_return_val_if_fail (schema != NULL, NULL);
873 g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
874 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
875
876 va_start (va, error);
877 attributes = secret_attributes_buildv (schema, va);
878 va_end (va);
879
880 /* Precondition failed, already warned */
881 if (!attributes)
882 return NULL;
883
884 password = secret_password_lookupv_sync (schema, attributes,
885 cancellable, error);
886
887 g_hash_table_unref (attributes);
888
889 return password;
890 }
891
892 /**
893 * secret_password_lookup_nonpageable_sync: (skip)
894 * @schema: the schema for the attributes
895 * @cancellable: optional cancellation object
896 * @error: location to place an error on failure
897 * @...: the attribute keys and values, terminated with %NULL
898 *
899 * Lookup a password in the secret service.
900 *
901 * The variable argument list should contain pairs of a) The attribute name as
902 * a null-terminated string, followed by b) attribute value, either a character
903 * string, an int number, or a gboolean value, as defined in the password
904 * @schema. The list of attribtues should be terminated with a %NULL.
905 *
906 * If no secret is found then %NULL is returned.
907 *
908 * This method may block indefinitely and should not be used in user interface
909 * threads.
910 *
911 * Returns: (transfer full): a new password string stored in nonpageable memory
912 * which must be freed with secret_password_free() when done
913 */
914 gchar *
secret_password_lookup_nonpageable_sync(const SecretSchema * schema,GCancellable * cancellable,GError ** error,...)915 secret_password_lookup_nonpageable_sync (const SecretSchema *schema,
916 GCancellable *cancellable,
917 GError **error,
918 ...)
919 {
920 GHashTable *attributes;
921 gchar *password;
922 va_list va;
923
924 g_return_val_if_fail (schema != NULL, NULL);
925 g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
926 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
927
928 va_start (va, error);
929 attributes = secret_attributes_buildv (schema, va);
930 va_end (va);
931
932 /* Precondition failed, already warned */
933 if (!attributes)
934 return NULL;
935
936 password = secret_password_lookupv_nonpageable_sync (schema, attributes,
937 cancellable, error);
938
939 g_hash_table_unref (attributes);
940
941 return password;
942 }
943
944 /**
945 * secret_password_lookupv_nonpageable_sync: (skip)
946 * @schema: (nullable): the schema for attributes
947 * @attributes: (element-type utf8 utf8): the attribute keys and values
948 * @cancellable: optional cancellation object
949 * @error: location to place an error on failure
950 *
951 * Lookup a password in the secret service.
952 *
953 * The @attributes should be a set of key and value string pairs.
954 *
955 * If no secret is found then %NULL is returned.
956 *
957 * This method may block indefinitely and should not be used in user interface
958 * threads.
959 *
960 * Returns: (transfer full): a new password string stored in non pageable memory
961 * which should be freed with secret_password_free() when done
962 */
963 gchar *
secret_password_lookupv_nonpageable_sync(const SecretSchema * schema,GHashTable * attributes,GCancellable * cancellable,GError ** error)964 secret_password_lookupv_nonpageable_sync (const SecretSchema *schema,
965 GHashTable *attributes,
966 GCancellable *cancellable,
967 GError **error)
968 {
969 SecretSync *sync;
970 gchar *password;
971
972 g_return_val_if_fail (attributes != NULL, NULL);
973 g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
974 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
975
976 /* Warnings raised already */
977 if (schema != NULL && !_secret_attributes_validate (schema, attributes, G_STRFUNC, TRUE))
978 return FALSE;
979
980 sync = _secret_sync_new ();
981 g_main_context_push_thread_default (sync->context);
982
983 secret_password_lookupv (schema, attributes, cancellable,
984 _secret_sync_on_result, sync);
985
986 g_main_loop_run (sync->loop);
987
988 password = secret_password_lookup_nonpageable_finish (sync->result, error);
989
990 g_main_context_pop_thread_default (sync->context);
991 _secret_sync_free (sync);
992
993 return password;
994 }
995
996 /**
997 * secret_password_lookup_binary_sync: (skip)
998 * @schema: the schema for the attributes
999 * @cancellable: optional cancellation object
1000 * @error: location to place an error on failure
1001 * @...: the attribute keys and values, terminated with %NULL
1002 *
1003 * Lookup a password in the secret service.
1004 *
1005 * This is similar to secret_password_lookup_sync(), but returns a
1006 * #SecretValue instead of a null-terminated password.
1007 *
1008 * This method may block indefinitely and should not be used in user interface
1009 * threads.
1010 *
1011 * Returns: (transfer full): a newly allocated #SecretValue, which should be
1012 * released with secret_value_unref(), or %NULL if no secret found
1013 *
1014 * Since: 0.19.0
1015 */
1016 SecretValue *
secret_password_lookup_binary_sync(const SecretSchema * schema,GCancellable * cancellable,GError ** error,...)1017 secret_password_lookup_binary_sync (const SecretSchema *schema,
1018 GCancellable *cancellable,
1019 GError **error,
1020 ...)
1021 {
1022 GHashTable *attributes;
1023 SecretValue *value;
1024 va_list va;
1025
1026 g_return_val_if_fail (schema != NULL, NULL);
1027 g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
1028 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
1029
1030 va_start (va, error);
1031 attributes = secret_attributes_buildv (schema, va);
1032 va_end (va);
1033
1034 /* Precondition failed, already warned */
1035 if (!attributes)
1036 return NULL;
1037
1038 value = secret_password_lookupv_binary_sync (schema, attributes,
1039 cancellable, error);
1040
1041 g_hash_table_unref (attributes);
1042
1043 return value;
1044 }
1045
1046 /**
1047 * secret_password_lookupv_binary_sync: (skip)
1048 * @schema: (nullable): the schema for attributes
1049 * @attributes: (element-type utf8 utf8): the attribute keys and values
1050 * @cancellable: optional cancellation object
1051 * @error: location to place an error on failure
1052 *
1053 * Lookup a password in the secret service.
1054 *
1055 * This is similar to secret_password_lookupv_sync(), but returns a
1056 * #SecretValue instead of a null-terminated password.
1057 *
1058 * This method may block indefinitely and should not be used in user interface
1059 * threads.
1060 *
1061 * Returns: (transfer full): a newly allocated #SecretValue, which should be
1062 * released with secret_value_unref(), or %NULL if no secret found
1063 *
1064 * Since: 0.19.0
1065 */
1066 SecretValue *
secret_password_lookupv_binary_sync(const SecretSchema * schema,GHashTable * attributes,GCancellable * cancellable,GError ** error)1067 secret_password_lookupv_binary_sync (const SecretSchema *schema,
1068 GHashTable *attributes,
1069 GCancellable *cancellable,
1070 GError **error)
1071 {
1072 SecretSync *sync;
1073 SecretValue *value;
1074
1075 g_return_val_if_fail (attributes != NULL, NULL);
1076 g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
1077 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
1078
1079 /* Warnings raised already */
1080 if (schema != NULL && !_secret_attributes_validate (schema, attributes, G_STRFUNC, TRUE))
1081 return FALSE;
1082
1083 sync = _secret_sync_new ();
1084 g_main_context_push_thread_default (sync->context);
1085
1086 secret_password_lookupv (schema, attributes, cancellable,
1087 _secret_sync_on_result, sync);
1088
1089 g_main_loop_run (sync->loop);
1090
1091 value = secret_password_lookup_binary_finish (sync->result, error);
1092
1093 g_main_context_pop_thread_default (sync->context);
1094 _secret_sync_free (sync);
1095
1096 return value;
1097 }
1098
1099 /**
1100 * secret_password_lookupv_sync: (rename-to secret_password_lookup_sync)
1101 * @schema: (nullable): the schema for attributes
1102 * @attributes: (element-type utf8 utf8): the attribute keys and values
1103 * @cancellable: optional cancellation object
1104 * @error: location to place an error on failure
1105 *
1106 * Lookup a password in the secret service.
1107 *
1108 * The @attributes should be a set of key and value string pairs.
1109 *
1110 * If no secret is found then %NULL is returned.
1111 *
1112 * This method may block indefinitely and should not be used in user interface
1113 * threads.
1114 *
1115 * Returns: (transfer full): a new password string which should be freed with
1116 * secret_password_free() or may be freed with g_free() when done
1117 */
1118 gchar *
secret_password_lookupv_sync(const SecretSchema * schema,GHashTable * attributes,GCancellable * cancellable,GError ** error)1119 secret_password_lookupv_sync (const SecretSchema *schema,
1120 GHashTable *attributes,
1121 GCancellable *cancellable,
1122 GError **error)
1123 {
1124 SecretSync *sync;
1125 gchar *string;
1126
1127 g_return_val_if_fail (attributes != NULL, NULL);
1128 g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
1129 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
1130
1131 /* Warnings raised already */
1132 if (schema != NULL && !_secret_attributes_validate (schema, attributes, G_STRFUNC, TRUE))
1133 return FALSE;
1134
1135 sync = _secret_sync_new ();
1136 g_main_context_push_thread_default (sync->context);
1137
1138 secret_password_lookupv (schema, attributes, cancellable,
1139 _secret_sync_on_result, sync);
1140
1141 g_main_loop_run (sync->loop);
1142
1143 string = secret_password_lookup_finish (sync->result, error);
1144
1145 g_main_context_pop_thread_default (sync->context);
1146 _secret_sync_free (sync);
1147
1148 return string;
1149 }
1150
1151 /**
1152 * secret_password_clear:
1153 * @schema: the schema for the attributes
1154 * @cancellable: optional cancellation object
1155 * @callback: called when the operation completes
1156 * @user_data: data to be passed to the callback
1157 * @...: the attribute keys and values, terminated with %NULL
1158 *
1159 * Clear unlocked matching passwords from the secret service.
1160 *
1161 * The variable argument list should contain pairs of a) The attribute name as
1162 * a null-terminated string, followed by b) attribute value, either a character
1163 * string, an int number, or a gboolean value, as defined in the password
1164 * @schema. The list of attribtues should be terminated with a %NULL.
1165 *
1166 * All unlocked items that match the attributes will be deleted.
1167 *
1168 * This method will return immediately and complete asynchronously.
1169 */
1170 void
secret_password_clear(const SecretSchema * schema,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data,...)1171 secret_password_clear (const SecretSchema *schema,
1172 GCancellable *cancellable,
1173 GAsyncReadyCallback callback,
1174 gpointer user_data,
1175 ...)
1176 {
1177 GHashTable *attributes;
1178 va_list va;
1179
1180 g_return_if_fail (schema != NULL);
1181 g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
1182
1183 va_start (va, user_data);
1184 attributes = secret_attributes_buildv (schema, va);
1185 va_end (va);
1186
1187 /* Precondition failed, already warned */
1188 if (!attributes)
1189 return;
1190
1191 secret_password_clearv (schema, attributes, cancellable,
1192 callback, user_data);
1193
1194 g_hash_table_unref (attributes);
1195 }
1196
1197 typedef struct {
1198 const SecretSchema *schema;
1199 GHashTable *attributes;
1200 } ClearClosure;
1201
1202 static void
clear_closure_free(gpointer data)1203 clear_closure_free (gpointer data)
1204 {
1205 ClearClosure *closure = data;
1206 _secret_schema_unref_if_nonstatic (closure->schema);
1207 g_hash_table_unref (closure->attributes);
1208 g_slice_free (ClearClosure, closure);
1209 }
1210
1211 static void
on_clear(GObject * source,GAsyncResult * result,gpointer user_data)1212 on_clear (GObject *source,
1213 GAsyncResult *result,
1214 gpointer user_data)
1215 {
1216 GTask *task = G_TASK (user_data);
1217 SecretBackend *backend = SECRET_BACKEND (source);
1218 SecretBackendInterface *iface;
1219 GError *error = NULL;
1220
1221 iface = SECRET_BACKEND_GET_IFACE (backend);
1222 g_return_if_fail (iface->clear_finish != NULL);
1223
1224 if (!iface->clear_finish (backend, result, &error)) {
1225 if (error)
1226 g_task_return_error (task, error);
1227 else
1228 g_task_return_boolean (task, FALSE);
1229 g_object_unref (task);
1230 return;
1231 }
1232
1233 g_task_return_boolean (task, TRUE);
1234 g_object_unref (task);
1235 }
1236
1237 static void
on_clear_backend(GObject * source,GAsyncResult * result,gpointer user_data)1238 on_clear_backend (GObject *source,
1239 GAsyncResult *result,
1240 gpointer user_data)
1241 {
1242 GTask *task = G_TASK (user_data);
1243 ClearClosure *clear = g_task_get_task_data (task);
1244 SecretBackend *backend;
1245 SecretBackendInterface *iface;
1246 GError *error = NULL;
1247
1248 backend = secret_backend_get_finish (result, &error);
1249 if (backend == NULL) {
1250 g_task_return_error (task, error);
1251 g_object_unref (task);
1252 return;
1253 }
1254
1255 iface = SECRET_BACKEND_GET_IFACE (backend);
1256 g_return_if_fail (iface->clear != NULL);
1257
1258 iface->clear (backend, clear->schema, clear->attributes,
1259 g_task_get_cancellable (task),
1260 on_clear,
1261 task);
1262 }
1263
1264 /**
1265 * secret_password_clearv: (rename-to secret_password_clear)
1266 * @schema: (nullable): the schema for the attributes
1267 * @attributes: (element-type utf8 utf8) (transfer full): the attribute keys and values
1268 * @cancellable: optional cancellation object
1269 * @callback: (scope async): called when the operation completes
1270 * @user_data: data to be passed to the callback
1271 *
1272 * Remove unlocked matching passwords from the secret service.
1273 *
1274 * The @attributes should be a set of key and value string pairs.
1275 *
1276 * All unlocked items that match the attributes will be deleted.
1277 *
1278 * This method will return immediately and complete asynchronously.
1279 */
1280 void
secret_password_clearv(const SecretSchema * schema,GHashTable * attributes,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)1281 secret_password_clearv (const SecretSchema *schema,
1282 GHashTable *attributes,
1283 GCancellable *cancellable,
1284 GAsyncReadyCallback callback,
1285 gpointer user_data)
1286 {
1287 ClearClosure *clear;
1288 GTask *task;
1289
1290 g_return_if_fail (attributes != NULL);
1291 g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
1292
1293 /* Warnings raised already */
1294 if (schema != NULL && !_secret_attributes_validate (schema, attributes, G_STRFUNC, TRUE))
1295 return;
1296
1297 task = g_task_new (NULL, cancellable, callback, user_data);
1298 clear = g_slice_new0 (ClearClosure);
1299 clear->schema = _secret_schema_ref_if_nonstatic (schema);
1300 clear->attributes = g_hash_table_ref (attributes);
1301 g_task_set_task_data (task, clear, clear_closure_free);
1302
1303 secret_backend_get (SECRET_SERVICE_NONE,
1304 cancellable,
1305 on_clear_backend, task);
1306 }
1307
1308 /**
1309 * secret_password_clear_finish:
1310 * @result: the asynchronous result passed to the callback
1311 * @error: location to place an error on failure
1312 *
1313 * Finish an asynchronous operation to remove passwords from the secret
1314 * service.
1315 *
1316 * Returns: whether any passwords were removed
1317 */
1318 gboolean
secret_password_clear_finish(GAsyncResult * result,GError ** error)1319 secret_password_clear_finish (GAsyncResult *result,
1320 GError **error)
1321 {
1322 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1323 g_return_val_if_fail (g_task_is_valid (result, NULL), FALSE);
1324
1325 return g_task_propagate_boolean (G_TASK (result), error);
1326 }
1327
1328 /**
1329 * secret_password_clear_sync:
1330 * @schema: the schema for the attributes
1331 * @cancellable: optional cancellation object
1332 * @error: location to place an error on failure
1333 * @...: the attribute keys and values, terminated with %NULL
1334 *
1335 * Remove unlocked matching passwords from the secret service.
1336 *
1337 * The variable argument list should contain pairs of a) The attribute name as
1338 * a null-terminated string, followed by b) attribute value, either a character
1339 * string, an int number, or a gboolean value, as defined in the password
1340 * @schema. The list of attribtues should be terminated with a %NULL.
1341 *
1342 * All unlocked items that match the attributes will be deleted.
1343 *
1344 * This method may block indefinitely and should not be used in user interface
1345 * threads.
1346 *
1347 * Returns: whether the any passwords were removed
1348 */
1349 gboolean
secret_password_clear_sync(const SecretSchema * schema,GCancellable * cancellable,GError ** error,...)1350 secret_password_clear_sync (const SecretSchema* schema,
1351 GCancellable *cancellable,
1352 GError **error,
1353 ...)
1354 {
1355 GHashTable *attributes;
1356 gboolean result;
1357 va_list va;
1358
1359 g_return_val_if_fail (schema != NULL, FALSE);
1360 g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
1361 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1362
1363 va_start (va, error);
1364 attributes = secret_attributes_buildv (schema, va);
1365 va_end (va);
1366
1367 /* Precondition failed, already warned */
1368 if (!attributes)
1369 return FALSE;
1370
1371 result = secret_password_clearv_sync (schema, attributes,
1372 cancellable, error);
1373
1374 g_hash_table_unref (attributes);
1375
1376 return result;
1377 }
1378
1379 /**
1380 * secret_password_clearv_sync: (rename-to secret_password_clear_sync)
1381 * @schema: (nullable): the schema for the attributes
1382 * @attributes: (element-type utf8 utf8): the attribute keys and values
1383 * @cancellable: optional cancellation object
1384 * @error: location to place an error on failure
1385 *
1386 * Remove unlocked matching passwords from the secret service.
1387 *
1388 * The @attributes should be a set of key and value string pairs.
1389 *
1390 * All unlocked items that match the attributes will be deleted.
1391 *
1392 * This method may block indefinitely and should not be used in user interface
1393 * threads.
1394 *
1395 * Returns: whether any passwords were removed
1396 */
1397 gboolean
secret_password_clearv_sync(const SecretSchema * schema,GHashTable * attributes,GCancellable * cancellable,GError ** error)1398 secret_password_clearv_sync (const SecretSchema *schema,
1399 GHashTable *attributes,
1400 GCancellable *cancellable,
1401 GError **error)
1402 {
1403 SecretSync *sync;
1404 gboolean result;
1405
1406 g_return_val_if_fail (attributes != NULL, FALSE);
1407 g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
1408 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1409
1410 /* Warnings raised already */
1411 if (schema != NULL && !_secret_attributes_validate (schema, attributes, G_STRFUNC, TRUE))
1412 return FALSE;
1413
1414 sync = _secret_sync_new ();
1415 g_main_context_push_thread_default (sync->context);
1416
1417 secret_password_clearv (schema, attributes, cancellable,
1418 _secret_sync_on_result, sync);
1419
1420 g_main_loop_run (sync->loop);
1421
1422 result = secret_password_clear_finish (sync->result, error);
1423
1424 g_main_context_pop_thread_default (sync->context);
1425 _secret_sync_free (sync);
1426
1427 return result;
1428 }
1429
1430 /**
1431 * secret_password_search: (skip)
1432 * @schema: the schema for the attributes
1433 * @flags: search option flags
1434 * @cancellable: optional cancellation object
1435 * @callback: called when the operation completes
1436 * @user_data: data to be passed to the callback
1437 * @...: the attribute keys and values, terminated with %NULL
1438 *
1439 * Search for items in the secret service.
1440 *
1441 * The variable argument list should contain pairs of a) The attribute name as
1442 * a null-terminated string, followed by b) attribute value, either a character
1443 * string, an int number, or a gboolean value, as defined in the password
1444 * @schema. The list of attribtues should be terminated with a %NULL.
1445 *
1446 * This method will return immediately and complete asynchronously.
1447 *
1448 * Since: 0.19.0
1449 */
1450 void
secret_password_search(const SecretSchema * schema,SecretSearchFlags flags,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data,...)1451 secret_password_search (const SecretSchema *schema,
1452 SecretSearchFlags flags,
1453 GCancellable *cancellable,
1454 GAsyncReadyCallback callback,
1455 gpointer user_data,
1456 ...)
1457 {
1458 GHashTable *attributes;
1459 va_list va;
1460
1461 g_return_if_fail (schema != NULL);
1462 g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
1463
1464 va_start (va, user_data);
1465 attributes = secret_attributes_buildv (schema, va);
1466 va_end (va);
1467
1468 /* Precondition failed, already warned */
1469 if (!attributes)
1470 return;
1471
1472 secret_password_searchv (schema, attributes, flags, cancellable,
1473 callback, user_data);
1474
1475 g_hash_table_unref (attributes);
1476 }
1477
1478 typedef struct {
1479 const SecretSchema *schema;
1480 GHashTable *attributes;
1481 SecretSearchFlags flags;
1482 } SearchClosure;
1483
1484 static void
search_closure_free(gpointer data)1485 search_closure_free (gpointer data)
1486 {
1487 SearchClosure *closure = data;
1488 _secret_schema_unref_if_nonstatic (closure->schema);
1489 g_hash_table_unref (closure->attributes);
1490 g_slice_free (SearchClosure, closure);
1491 }
1492
1493 static void
object_list_free(gpointer data)1494 object_list_free (gpointer data)
1495 {
1496 GList *list = data;
1497 g_list_free_full (list, g_object_unref);
1498 }
1499
1500 static void
on_search(GObject * source,GAsyncResult * result,gpointer user_data)1501 on_search (GObject *source,
1502 GAsyncResult *result,
1503 gpointer user_data)
1504 {
1505 GTask *task = G_TASK (user_data);
1506 SecretBackend *backend = SECRET_BACKEND (source);
1507 SecretBackendInterface *iface;
1508 GError *error = NULL;
1509 GList *items;
1510
1511 iface = SECRET_BACKEND_GET_IFACE (backend);
1512 g_return_if_fail (iface->search_finish != NULL);
1513
1514 items = iface->search_finish (backend, result, &error);
1515 if (error) {
1516 g_task_return_error (task, error);
1517 g_object_unref (task);
1518 return;
1519 }
1520
1521 g_task_return_pointer (task, items, object_list_free);
1522 g_object_unref (task);
1523 }
1524
1525 static void
on_search_backend(GObject * source,GAsyncResult * result,gpointer user_data)1526 on_search_backend (GObject *source,
1527 GAsyncResult *result,
1528 gpointer user_data)
1529 {
1530 GTask *task = G_TASK (user_data);
1531 SearchClosure *search = g_task_get_task_data (task);
1532 SecretBackend *backend;
1533 SecretBackendInterface *iface;
1534 GError *error = NULL;
1535
1536 backend = secret_backend_get_finish (result, &error);
1537 if (backend == NULL) {
1538 g_task_return_error (task, error);
1539 g_object_unref (task);
1540 return;
1541 }
1542
1543 iface = SECRET_BACKEND_GET_IFACE (backend);
1544 g_return_if_fail (iface->search != NULL);
1545
1546 iface->search (backend,
1547 search->schema, search->attributes, search->flags,
1548 g_task_get_cancellable (task),
1549 on_search,
1550 task);
1551 }
1552
1553 /**
1554 * secret_password_searchv: (rename-to secret_password_search)
1555 * @schema: (nullable): the schema for attributes
1556 * @attributes: (element-type utf8 utf8) (transfer full): the attribute keys and values
1557 * @flags: search option flags
1558 * @cancellable: optional cancellation object
1559 * @callback: (scope async): called when the operation completes
1560 * @user_data: data to be passed to the callback
1561 *
1562 * Search for items in the secret service.
1563 *
1564 * The @attributes should be a set of key and value string pairs.
1565 *
1566 * This method will return immediately and complete asynchronously.
1567 *
1568 * Since: 0.19.0
1569 */
1570 void
secret_password_searchv(const SecretSchema * schema,GHashTable * attributes,SecretSearchFlags flags,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)1571 secret_password_searchv (const SecretSchema *schema,
1572 GHashTable *attributes,
1573 SecretSearchFlags flags,
1574 GCancellable *cancellable,
1575 GAsyncReadyCallback callback,
1576 gpointer user_data)
1577 {
1578 SearchClosure *search;
1579 GTask *task;
1580
1581 g_return_if_fail (attributes != NULL);
1582 g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
1583
1584 /* Warnings raised already */
1585 if (schema != NULL && !_secret_attributes_validate (schema, attributes, G_STRFUNC, TRUE))
1586 return;
1587
1588 task = g_task_new (NULL, cancellable, callback, user_data);
1589 search = g_slice_new0 (SearchClosure);
1590 search->schema = _secret_schema_ref_if_nonstatic (schema);
1591 search->attributes = g_hash_table_ref (attributes);
1592 search->flags = flags;
1593 g_task_set_task_data (task, search, search_closure_free);
1594
1595 secret_backend_get (SECRET_SERVICE_NONE,
1596 cancellable,
1597 on_search_backend, task);
1598 }
1599
1600 /**
1601 * secret_password_search_finish:
1602 * @result: the asynchronous result passed to the callback
1603 * @error: location to place an error on failure
1604 *
1605 * Finish an asynchronous operation to search for items in the secret service.
1606 *
1607 * Returns: (transfer full) (element-type Secret.Retrievable): a list of
1608 * #SecretRetrievable containing attributes of the matched items
1609 *
1610 * Since: 0.19.0
1611 */
1612 GList *
secret_password_search_finish(GAsyncResult * result,GError ** error)1613 secret_password_search_finish (GAsyncResult *result,
1614 GError **error)
1615 {
1616 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
1617 g_return_val_if_fail (g_task_is_valid (result, NULL), NULL);
1618
1619 return g_task_propagate_pointer (G_TASK (result), error);
1620 }
1621
1622 /**
1623 * secret_password_search_sync: (skip)
1624 * @schema: the schema for the attributes
1625 * @flags: search option flags
1626 * @cancellable: optional cancellation object
1627 * @error: location to place an error on failure
1628 * @...: the attribute keys and values, terminated with %NULL
1629 *
1630 * Search for items in the secret service.
1631 *
1632 * The variable argument list should contain pairs of a) The attribute name as
1633 * a null-terminated string, followed by b) attribute value, either a character
1634 * string, an int number, or a gboolean value, as defined in the password
1635 * @schema. The list of attributes should be terminated with a %NULL.
1636 *
1637 * If no secret is found then %NULL is returned.
1638 *
1639 * This method may block indefinitely and should not be used in user interface
1640 * threads.
1641 *
1642 * Returns: (transfer full) (element-type Secret.Retrievable): a list of
1643 * #SecretRetrievable containing attributes of the matched items
1644 *
1645 * Since: 0.19.0
1646 */
1647 GList *
secret_password_search_sync(const SecretSchema * schema,SecretSearchFlags flags,GCancellable * cancellable,GError ** error,...)1648 secret_password_search_sync (const SecretSchema *schema,
1649 SecretSearchFlags flags,
1650 GCancellable *cancellable,
1651 GError **error,
1652 ...)
1653 {
1654 GHashTable *attributes;
1655 GList *items;
1656 va_list va;
1657
1658 g_return_val_if_fail (schema != NULL, NULL);
1659 g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
1660 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
1661
1662 va_start (va, error);
1663 attributes = secret_attributes_buildv (schema, va);
1664 va_end (va);
1665
1666 /* Precondition failed, already warned */
1667 if (!attributes)
1668 return NULL;
1669
1670 items = secret_password_searchv_sync (schema, attributes, flags,
1671 cancellable, error);
1672
1673 g_hash_table_unref (attributes);
1674
1675 return items;
1676 }
1677
1678 /**
1679 * secret_password_searchv_sync: (rename-to secret_password_search_sync)
1680 * @schema: (nullable): the schema for attributes
1681 * @attributes: (element-type utf8 utf8): the attribute keys and values
1682 * @flags: search option flags
1683 * @cancellable: optional cancellation object
1684 * @error: location to place an error on failure
1685 *
1686 * Search for items in the secret service.
1687 *
1688 * The @attributes should be a set of key and value string pairs.
1689 *
1690 * If no secret is found then %NULL is returned.
1691 *
1692 * This method may block indefinitely and should not be used in user interface
1693 * threads.
1694 *
1695 * Returns: (transfer full) (element-type Secret.Retrievable): a list of
1696 * #SecretRetrievable containing attributes of the matched items
1697 *
1698 * Since: 0.19.0
1699 */
1700 GList *
secret_password_searchv_sync(const SecretSchema * schema,GHashTable * attributes,SecretSearchFlags flags,GCancellable * cancellable,GError ** error)1701 secret_password_searchv_sync (const SecretSchema *schema,
1702 GHashTable *attributes,
1703 SecretSearchFlags flags,
1704 GCancellable *cancellable,
1705 GError **error)
1706 {
1707 SecretSync *sync;
1708 GList *items;
1709
1710 g_return_val_if_fail (attributes != NULL, NULL);
1711 g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
1712 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
1713
1714 /* Warnings raised already */
1715 if (schema != NULL && !_secret_attributes_validate (schema, attributes, G_STRFUNC, TRUE))
1716 return NULL;
1717
1718 sync = _secret_sync_new ();
1719 g_main_context_push_thread_default (sync->context);
1720
1721 secret_password_searchv (schema, attributes, flags, cancellable,
1722 _secret_sync_on_result, sync);
1723
1724 g_main_loop_run (sync->loop);
1725
1726 items = secret_password_search_finish (sync->result, error);
1727
1728 g_main_context_pop_thread_default (sync->context);
1729 _secret_sync_free (sync);
1730
1731 return items;
1732 }
1733
1734 /**
1735 * secret_password_free: (skip)
1736 * @password: (allow-none): password to free
1737 *
1738 * Clear the memory used by a password, and then free it.
1739 *
1740 * This function must be used to free nonpageable memory returned by
1741 * secret_password_lookup_nonpageable_finish(),
1742 * secret_password_lookup_nonpageable_sync() or
1743 * secret_password_lookupv_nonpageable_sync().
1744 */
1745 void
secret_password_free(gchar * password)1746 secret_password_free (gchar *password)
1747 {
1748 if (password == NULL)
1749 return;
1750
1751 egg_secure_strfree (password);
1752 }
1753
1754 /**
1755 * secret_password_wipe:
1756 * @password: (allow-none): password to clear
1757 *
1758 * Clear the memory used by a password.
1759 */
1760 void
secret_password_wipe(gchar * password)1761 secret_password_wipe (gchar *password)
1762 {
1763 if (password == NULL)
1764 return;
1765
1766 egg_secure_strclear (password);
1767 }
1768