Merge branch 'wip/dueno/simple-item' into 'master'

secret-password: Add necessary functions to migrate from D-Bus based API

See merge request GNOME/libsecret!32
This commit is contained in:
Daiki Ueno 2019-07-22 10:55:30 +00:00
commit f7e73bab6d
16 changed files with 1419 additions and 143 deletions

View File

@ -26,6 +26,7 @@
<xi:include href="xml/secret-service.xml"/>
<xi:include href="xml/secret-collection.xml"/>
<xi:include href="xml/secret-item.xml"/>
<xi:include href="xml/secret-retrievable.xml"/>
<xi:include href="xml/secret-value.xml"/>
<xi:include href="xml/secret-attributes.xml"/>
<xi:include href="xml/secret-prompt.xml"/>

View File

@ -120,6 +120,10 @@ secret_password_storev
secret_password_store_finish
secret_password_store_sync
secret_password_storev_sync
secret_password_store_binary
secret_password_store_binary_sync
secret_password_storev_binary
secret_password_storev_binary_sync
secret_password_lookup
secret_password_lookupv
secret_password_lookup_finish
@ -128,15 +132,38 @@ secret_password_lookup_sync
secret_password_lookup_nonpageable_sync
secret_password_lookupv_sync
secret_password_lookupv_nonpageable_sync
secret_password_lookup_binary_finish
secret_password_lookup_binary_sync
secret_password_lookupv_binary_sync
secret_password_clear
secret_password_clearv
secret_password_clear_finish
secret_password_clear_sync
secret_password_clearv_sync
secret_password_search
secret_password_search_finish
secret_password_search_sync
secret_password_searchv
secret_password_searchv_sync
secret_password_wipe
secret_password_free
</SECTION>
<SECTION>
<FILE>secret-retrievable</FILE>
<INCLUDE>libsecret/secret.h</INCLUDE>
SECRET_TYPE_RETRIEVABLE
SecretRetrievable
SecretRetrievableInterface
secret_retrievable_get_attributes
secret_retrievable_get_created
secret_retrievable_get_label
secret_retrievable_get_modified
secret_retrievable_retrieve_secret
secret_retrievable_retrieve_secret_finish
secret_retrievable_retrieve_secret_sync
</SECTION>
<SECTION>
<FILE>secret-schema</FILE>
<INCLUDE>libsecret/secret.h</INCLUDE>
@ -306,6 +333,7 @@ secret_value_get_text
secret_value_get_content_type
secret_value_ref
secret_value_unref
secret_value_unref_to_password
<SUBSECTION Standard>
SECRET_TYPE_VALUE
secret_value_get_type

View File

@ -12,6 +12,7 @@ libsecret_HEADS = \
libsecret/secret-password.h \
libsecret/secret-paths.h \
libsecret/secret-prompt.h \
libsecret/secret-retrievable.h \
libsecret/secret-schema.h \
libsecret/secret-schemas.h \
libsecret/secret-service.h \
@ -42,6 +43,7 @@ libsecret_PUBLIC = \
libsecret/secret-methods.c \
libsecret/secret-password.h libsecret/secret-password.c \
libsecret/secret-prompt.h libsecret/secret-prompt.c \
libsecret/secret-retrievable.h libsecret/secret-retrievable.c \
libsecret/secret-schema.h libsecret/secret-schema.c \
libsecret/secret-schemas.h libsecret/secret-schemas.c \
libsecret/secret-service.h libsecret/secret-service.c \

View File

@ -7,6 +7,7 @@ libsecret_sources = [
'secret-methods.c',
'secret-password.c',
'secret-prompt.c',
'secret-retrievable.c',
'secret-schema.c',
'secret-schemas.c',
'secret-service.c',
@ -24,6 +25,7 @@ libsecret_headers = [
'secret-password.h',
'secret-paths.h',
'secret-prompt.h',
'secret-retrievable.h',
'secret-schema.h',
'secret-schemas.h',
'secret-service.h',
@ -104,6 +106,8 @@ libsecret_gir_sources = [
'secret-paths.h',
'secret-prompt.c',
'secret-prompt.h',
'secret-retrievable.c',
'secret-retrievable.h',
'secret-schema.c',
'secret-schema.h',
'secret-schemas.c',

View File

@ -19,6 +19,7 @@
#include "secret-item.h"
#include "secret-paths.h"
#include "secret-private.h"
#include "secret-retrievable.h"
#include "secret-service.h"
#include "secret-types.h"
#include "secret-value.h"
@ -105,16 +106,21 @@ struct _SecretItemPrivate {
gint disposed;
};
static SecretRetrievableInterface *secret_item_retrievable_parent_iface = NULL;
static GInitableIface *secret_item_initable_parent_iface = NULL;
static GAsyncInitableIface *secret_item_async_initable_parent_iface = NULL;
static void secret_item_retrievable_iface (SecretRetrievableInterface *iface);
static void secret_item_initable_iface (GInitableIface *iface);
static void secret_item_async_initable_iface (GAsyncInitableIface *iface);
G_DEFINE_TYPE_WITH_CODE (SecretItem, secret_item, G_TYPE_DBUS_PROXY,
G_ADD_PRIVATE (SecretItem)
G_IMPLEMENT_INTERFACE (SECRET_TYPE_RETRIEVABLE, secret_item_retrievable_iface);
G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, secret_item_initable_iface);
G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, secret_item_async_initable_iface);
);
@ -355,9 +361,7 @@ secret_item_class_init (SecretItemClass *klass)
* The attributes set on this item. Attributes are used to locate an
* item. They are not guaranteed to be stored or transferred securely.
*/
g_object_class_install_property (gobject_class, PROP_ATTRIBUTES,
g_param_spec_boxed ("attributes", "Attributes", "Item attributes",
G_TYPE_HASH_TABLE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_override_property (gobject_class, PROP_ATTRIBUTES, "attributes");
/**
* SecretItem:label:
@ -368,9 +372,7 @@ secret_item_class_init (SecretItemClass *klass)
* set asynchronously. To properly track the changing of the label use the
* secret_item_set_label() function.
*/
g_object_class_install_property (gobject_class, PROP_LABEL,
g_param_spec_string ("label", "Label", "Item label",
NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_override_property (gobject_class, PROP_LABEL, "label");
/**
* SecretItem:locked:
@ -391,9 +393,7 @@ secret_item_class_init (SecretItemClass *klass)
* The date and time (in seconds since the UNIX epoch) that this
* item was created.
*/
g_object_class_install_property (gobject_class, PROP_CREATED,
g_param_spec_uint64 ("created", "Created", "Item creation date",
0UL, G_MAXUINT64, 0UL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_override_property (gobject_class, PROP_CREATED, "created");
/**
* SecretItem:modified:
@ -401,9 +401,7 @@ secret_item_class_init (SecretItemClass *klass)
* The date and time (in seconds since the UNIX epoch) that this
* item was last modified.
*/
g_object_class_install_property (gobject_class, PROP_MODIFIED,
g_param_spec_uint64 ("modified", "Modified", "Item modified date",
0UL, G_MAXUINT64, 0UL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_override_property (gobject_class, PROP_MODIFIED, "modified");
}
typedef struct {
@ -1320,6 +1318,55 @@ secret_item_load_secret_sync (SecretItem *self,
return result;
}
static void
on_retrieve_load (GObject *source_object,
GAsyncResult *res,
gpointer user_data)
{
SecretItem *self = SECRET_ITEM (source_object);
GTask *task = G_TASK (user_data);
GError *error = NULL;
if (secret_item_load_secret_finish (self, res, &error)) {
g_task_return_pointer (task,
secret_item_get_secret (self),
secret_value_unref);
g_object_unref (task);
} else {
g_task_return_error (task, error);
g_object_unref (task);
}
}
static void
secret_item_retrieve_secret (SecretRetrievable *self,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
GTask *task = g_task_new (self, cancellable, callback, user_data);
secret_item_load_secret (SECRET_ITEM (self), cancellable, on_retrieve_load, task);
}
static SecretValue *
secret_item_retrieve_secret_finish (SecretRetrievable *self,
GAsyncResult *result,
GError **error)
{
g_return_val_if_fail (g_task_is_valid (result, self), NULL);
return g_task_propagate_pointer (G_TASK (result), error);
}
static void
secret_item_retrievable_iface (SecretRetrievableInterface *iface)
{
secret_item_retrievable_parent_iface = g_type_interface_peek_parent (iface);
iface->retrieve_secret = secret_item_retrieve_secret;
iface->retrieve_secret_finish = secret_item_retrieve_secret_finish;
}
typedef struct {
SecretService *service;
GCancellable *cancellable;

View File

@ -17,6 +17,7 @@
#include "secret-attributes.h"
#include "secret-password.h"
#include "secret-private.h"
#include "secret-retrievable.h"
#include "secret-value.h"
#include <egg/egg-secure-memory.h>
@ -103,7 +104,7 @@ secret_password_store (const SecretSchema *schema,
/**
* secret_password_storev: (rename-to secret_password_store)
* @schema: the schema for attributes
* @schema: (nullable): the schema for attributes
* @attributes: (element-type utf8 utf8): the attribute keys and values
* @collection: (allow-none): a collection alias, or D-Bus object path of the collection where to store the secret
* @label: label for the secret
@ -137,14 +138,13 @@ secret_password_storev (const SecretSchema *schema,
{
SecretValue *value;
g_return_if_fail (schema != NULL);
g_return_if_fail (label != NULL);
g_return_if_fail (password != NULL);
g_return_if_fail (attributes != NULL);
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
/* Warnings raised already */
if (!_secret_attributes_validate (schema, attributes, G_STRFUNC, FALSE))
if (schema != NULL && !_secret_attributes_validate (schema, attributes, G_STRFUNC, FALSE))
return;
value = secret_value_new (password, -1, "text/plain");
@ -155,6 +155,101 @@ secret_password_storev (const SecretSchema *schema,
secret_value_unref (value);
}
/**
* secret_password_store_binary: (skip)
* @schema: the schema for attributes
* @collection: (allow-none): a collection alias, or D-Bus object path of the collection where to store the secret
* @label: label for the secret
* @value: a #SecretValue
* @cancellable: optional cancellation object
* @callback: called when the operation completes
* @user_data: data to be passed to the callback
* @...: the attribute keys and values, terminated with %NULL
*
* Store a password in the secret service.
*
* This is similar to secret_password_store(), but takes a
* #SecretValue as the argument instead of a null-terminated password.
*
* This method will return immediately and complete asynchronously.
*
* Since: 0.19.0
*/
void
secret_password_store_binary (const SecretSchema *schema,
const gchar *collection,
const gchar *label,
SecretValue *value,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data,
...)
{
GHashTable *attributes;
va_list va;
g_return_if_fail (schema != NULL);
g_return_if_fail (label != NULL);
g_return_if_fail (value != NULL);
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
va_start (va, user_data);
attributes = secret_attributes_buildv (schema, va);
va_end (va);
/* Precondition failed, already warned */
if (!attributes)
return;
secret_password_storev_binary (schema, attributes, collection, label, value,
cancellable, callback, user_data);
g_hash_table_unref (attributes);
}
/**
* secret_password_storev_binary: (rename-to secret_password_store_binary)
* @schema: (nullable): the schema for attributes
* @attributes: (element-type utf8 utf8): the attribute keys and values
* @collection: (allow-none): a collection alias, or D-Bus object path of the collection where to store the secret
* @label: label for the secret
* @value: a #SecretValue
* @cancellable: optional cancellation object
* @callback: called when the operation completes
* @user_data: data to be passed to the callback
*
* Store a password in the secret service.
*
* This is similar to secret_password_storev(), but takes a
* #SecretValue as the argument instead of a null-terminated password.
*
* This method will return immediately and complete asynchronously.
*
* Since: 0.19.0
*/
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)
{
g_return_if_fail (label != NULL);
g_return_if_fail (value != NULL);
g_return_if_fail (attributes != NULL);
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
/* Warnings raised already */
if (schema != NULL && !_secret_attributes_validate (schema, attributes, G_STRFUNC, FALSE))
return;
secret_service_store (NULL, schema, attributes, collection,
label, value, cancellable, callback, user_data);
}
/**
* secret_password_store_finish:
* @result: the asynchronous result passed to the callback
@ -237,7 +332,7 @@ secret_password_store_sync (const SecretSchema *schema,
/**
* secret_password_storev_sync: (rename-to secret_password_store_sync)
* @schema: the schema for attributes
* @schema: (nullable): the schema for attributes
* @attributes: (element-type utf8 utf8): the attribute keys and values
* @collection: (allow-none): a collection alias, or D-Bus object path of the collection where to store the secret
* @label: label for the secret
@ -273,7 +368,6 @@ secret_password_storev_sync (const SecretSchema *schema,
SecretSync *sync;
gboolean ret;
g_return_val_if_fail (schema != NULL, FALSE);
g_return_val_if_fail (label != NULL, FALSE);
g_return_val_if_fail (password != NULL, FALSE);
g_return_val_if_fail (attributes != NULL, FALSE);
@ -281,7 +375,7 @@ secret_password_storev_sync (const SecretSchema *schema,
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
/* Warnings raised already */
if (!_secret_attributes_validate (schema, attributes, G_STRFUNC, FALSE))
if (schema != NULL && !_secret_attributes_validate (schema, attributes, G_STRFUNC, FALSE))
return FALSE;
sync = _secret_sync_new ();
@ -300,6 +394,122 @@ secret_password_storev_sync (const SecretSchema *schema,
return ret;
}
/**
* secret_password_store_binary_sync:
* @schema: the schema for attributes
* @collection: (allow-none): a collection alias, or D-Bus object path of the collection where to store the secret
* @label: label for the secret
* @value: a #SecretValue
* @cancellable: optional cancellation object
* @error: location to place an error on failure
* @...: the attribute keys and values, terminated with %NULL
*
* Store a password in the secret service.
*
* This is similar to secret_password_store_sync(), but takes a
* #SecretValue as the argument instead of a null terminated password.
*
* This method may block indefinitely and should not be used in user interface
* threads.
*
* Returns: whether the storage was successful or not
*
* Since: 0.19.0
*/
gboolean
secret_password_store_binary_sync (const SecretSchema *schema,
const gchar *collection,
const gchar *label,
SecretValue *value,
GCancellable *cancellable,
GError **error,
...)
{
GHashTable *attributes;
va_list va;
gboolean ret;
g_return_val_if_fail (schema != NULL, FALSE);
g_return_val_if_fail (label != NULL, FALSE);
g_return_val_if_fail (value != NULL, FALSE);
g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
va_start (va, error);
attributes = secret_attributes_buildv (schema, va);
va_end (va);
/* Precondition failed, already warned */
if (!attributes)
return FALSE;
ret = secret_password_storev_binary_sync (schema, attributes, collection,
label, value, cancellable, error);
g_hash_table_unref (attributes);
return ret;
}
/**
* secret_password_storev_binary_sync: (rename-to secret_password_store_binary_sync)
* @schema: (nullable): the schema for attributes
* @attributes: (element-type utf8 utf8): the attribute keys and values
* @collection: (allow-none): a collection alias, or D-Bus object path of the collection where to store the secret
* @label: label for the secret
* @value: a #SecretValue
* @cancellable: optional cancellation object
* @error: location to place an error on failure
*
* Store a password in the secret service.
*
* This is similar to secret_password_storev_sync(), but takes a
* #SecretValue as the argument instead of a null-terminated passwords.
*
* This method may block indefinitely and should not be used in user interface
* threads.
*
* Returns: whether the storage was successful or not
*
* Since: 0.19.0
*/
gboolean
secret_password_storev_binary_sync (const SecretSchema *schema,
GHashTable *attributes,
const gchar *collection,
const gchar *label,
SecretValue *value,
GCancellable *cancellable,
GError **error)
{
SecretSync *sync;
gboolean ret;
g_return_val_if_fail (label != NULL, FALSE);
g_return_val_if_fail (value != NULL, FALSE);
g_return_val_if_fail (attributes != NULL, FALSE);
g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
/* Warnings raised already */
if (schema != NULL && !_secret_attributes_validate (schema, attributes, G_STRFUNC, FALSE))
return FALSE;
sync = _secret_sync_new ();
g_main_context_push_thread_default (sync->context);
secret_password_storev_binary (schema, attributes, collection, label, value,
cancellable, _secret_sync_on_result, sync);
g_main_loop_run (sync->loop);
ret = secret_password_store_finish (sync->result, error);
g_main_context_pop_thread_default (sync->context);
_secret_sync_free (sync);
return ret;
}
/**
* secret_password_lookup: (skip)
* @schema: the schema for the attributes
@ -348,7 +558,7 @@ secret_password_lookup (const SecretSchema *schema,
/**
* secret_password_lookupv: (rename-to secret_password_lookup)
* @schema: the schema for attributes
* @schema: (nullable): the schema for attributes
* @attributes: (element-type utf8 utf8): the attribute keys and values
* @cancellable: optional cancellation object
* @callback: called when the operation completes
@ -369,12 +579,11 @@ secret_password_lookupv (const SecretSchema *schema,
GAsyncReadyCallback callback,
gpointer user_data)
{
g_return_if_fail (schema != NULL);
g_return_if_fail (attributes != NULL);
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
/* Warnings raised already */
if (!_secret_attributes_validate (schema, attributes, G_STRFUNC, TRUE))
if (schema != NULL && !_secret_attributes_validate (schema, attributes, G_STRFUNC, TRUE))
return;
secret_service_lookup (NULL, schema, attributes,
@ -406,6 +615,27 @@ secret_password_lookup_nonpageable_finish (GAsyncResult *result,
return _secret_value_unref_to_password (value);
}
/**
* secret_password_lookup_binary_finish: (skip)
* @result: the asynchronous result passed to the callback
* @error: location to place an error on failure
*
* Finish an asynchronous operation to lookup a password in the secret service.
*
* Returns: (transfer full): a newly allocated #SecretValue, which should be
* released with secret_value_unref(), or %NULL if no secret found
*
* Since: 0.19.0
*/
SecretValue *
secret_password_lookup_binary_finish (GAsyncResult *result,
GError **error)
{
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
return secret_service_lookup_finish (NULL, result, error);
}
/**
* secret_password_lookup_finish:
* @result: the asynchronous result passed to the callback
@ -537,7 +767,7 @@ secret_password_lookup_nonpageable_sync (const SecretSchema *schema,
/**
* secret_password_lookupv_nonpageable_sync: (skip)
* @schema: the schema for attributes
* @schema: (nullable): the schema for attributes
* @attributes: (element-type utf8 utf8): the attribute keys and values
* @cancellable: optional cancellation object
* @error: location to place an error on failure
@ -563,13 +793,12 @@ secret_password_lookupv_nonpageable_sync (const SecretSchema *schema,
SecretSync *sync;
gchar *password;
g_return_val_if_fail (schema != NULL, NULL);
g_return_val_if_fail (attributes != NULL, NULL);
g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
/* Warnings raised already */
if (!_secret_attributes_validate (schema, attributes, G_STRFUNC, TRUE))
if (schema != NULL && !_secret_attributes_validate (schema, attributes, G_STRFUNC, TRUE))
return FALSE;
sync = _secret_sync_new ();
@ -588,9 +817,112 @@ secret_password_lookupv_nonpageable_sync (const SecretSchema *schema,
return password;
}
/**
* secret_password_lookup_binary_sync: (skip)
* @schema: the schema for the attributes
* @cancellable: optional cancellation object
* @error: location to place an error on failure
* @...: the attribute keys and values, terminated with %NULL
*
* Lookup a password in the secret service.
*
* This is similar to secret_password_lookup_sync(), but returns a
* #SecretValue instead of a null-terminated password.
*
* This method may block indefinitely and should not be used in user interface
* threads.
*
* Returns: (transfer full): a newly allocated #SecretValue, which should be
* released with secret_value_unref(), or %NULL if no secret found
*
* Since: 0.19.0
*/
SecretValue *
secret_password_lookup_binary_sync (const SecretSchema *schema,
GCancellable *cancellable,
GError **error,
...)
{
GHashTable *attributes;
SecretValue *value;
va_list va;
g_return_val_if_fail (schema != NULL, NULL);
g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
va_start (va, error);
attributes = secret_attributes_buildv (schema, va);
va_end (va);
/* Precondition failed, already warned */
if (!attributes)
return NULL;
value = secret_password_lookupv_binary_sync (schema, attributes,
cancellable, error);
g_hash_table_unref (attributes);
return value;
}
/**
* secret_password_lookupv_binary_sync: (skip)
* @schema: (nullable): the schema for attributes
* @attributes: (element-type utf8 utf8): the attribute keys and values
* @cancellable: optional cancellation object
* @error: location to place an error on failure
*
* Lookup a password in the secret service.
*
* This is similar to secret_password_lookupv_sync(), but returns a
* #SecretValue instead of a null-terminated password.
*
* This method may block indefinitely and should not be used in user interface
* threads.
*
* Returns: (transfer full): a newly allocated #SecretValue, which should be
* released with secret_value_unref(), or %NULL if no secret found
*
* Since: 0.19.0
*/
SecretValue *
secret_password_lookupv_binary_sync (const SecretSchema *schema,
GHashTable *attributes,
GCancellable *cancellable,
GError **error)
{
SecretSync *sync;
SecretValue *value;
g_return_val_if_fail (attributes != NULL, NULL);
g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
/* Warnings raised already */
if (schema != NULL && !_secret_attributes_validate (schema, attributes, G_STRFUNC, TRUE))
return FALSE;
sync = _secret_sync_new ();
g_main_context_push_thread_default (sync->context);
secret_password_lookupv (schema, attributes, cancellable,
_secret_sync_on_result, sync);
g_main_loop_run (sync->loop);
value = secret_password_lookup_binary_finish (sync->result, error);
g_main_context_pop_thread_default (sync->context);
_secret_sync_free (sync);
return value;
}
/**
* secret_password_lookupv_sync: (rename-to secret_password_lookup_sync)
* @schema: the schema for attributes
* @schema: (nullable): the schema for attributes
* @attributes: (element-type utf8 utf8): the attribute keys and values
* @cancellable: optional cancellation object
* @error: location to place an error on failure
@ -616,13 +948,12 @@ secret_password_lookupv_sync (const SecretSchema *schema,
SecretSync *sync;
gchar *string;
g_return_val_if_fail (schema != NULL, NULL);
g_return_val_if_fail (attributes != NULL, NULL);
g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
/* Warnings raised already */
if (!_secret_attributes_validate (schema, attributes, G_STRFUNC, TRUE))
if (schema != NULL && !_secret_attributes_validate (schema, attributes, G_STRFUNC, TRUE))
return FALSE;
sync = _secret_sync_new ();
@ -690,7 +1021,7 @@ secret_password_clear (const SecretSchema *schema,
/**
* secret_password_clearv: (rename-to secret_password_clear)
* @schema: the schema for the attributes
* @schema: (nullable): the schema for the attributes
* @attributes: (element-type utf8 utf8): the attribute keys and values
* @cancellable: optional cancellation object
* @callback: called when the operation completes
@ -711,12 +1042,11 @@ secret_password_clearv (const SecretSchema *schema,
GAsyncReadyCallback callback,
gpointer user_data)
{
g_return_if_fail (schema != NULL);
g_return_if_fail (attributes != NULL);
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
/* Warnings raised already */
if (!_secret_attributes_validate (schema, attributes, G_STRFUNC, TRUE))
if (schema != NULL && !_secret_attributes_validate (schema, attributes, G_STRFUNC, TRUE))
return;
secret_service_clear (NULL, schema, attributes,
@ -794,7 +1124,7 @@ secret_password_clear_sync (const SecretSchema* schema,
/**
* secret_password_clearv_sync: (rename-to secret_password_clear_sync)
* @schema: the schema for the attributes
* @schema: (nullable): the schema for the attributes
* @attributes: (element-type utf8 utf8): the attribute keys and values
* @cancellable: optional cancellation object
* @error: location to place an error on failure
@ -819,13 +1149,12 @@ secret_password_clearv_sync (const SecretSchema *schema,
SecretSync *sync;
gboolean result;
g_return_val_if_fail (schema != NULL, FALSE);
g_return_val_if_fail (attributes != NULL, FALSE);
g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
/* Warnings raised already */
if (!_secret_attributes_validate (schema, attributes, G_STRFUNC, TRUE))
if (schema != NULL && !_secret_attributes_validate (schema, attributes, G_STRFUNC, TRUE))
return FALSE;
sync = _secret_sync_new ();
@ -844,6 +1173,223 @@ secret_password_clearv_sync (const SecretSchema *schema,
return result;
}
/**
* secret_password_search: (skip)
* @schema: the schema for the attributes
* @flags: search option flags
* @cancellable: optional cancellation object
* @callback: called when the operation completes
* @user_data: data to be passed to the callback
* @...: the attribute keys and values, terminated with %NULL
*
* Search for items in the secret service.
*
* The variable argument list should contain pairs of a) The attribute name as
* a null-terminated string, followed by b) attribute value, either a character
* string, an int number, or a gboolean value, as defined in the password
* @schema. The list of attribtues should be terminated with a %NULL.
*
* This method will return immediately and complete asynchronously.
*
* Since: 0.19.0
*/
void
secret_password_search (const SecretSchema *schema,
SecretSearchFlags flags,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data,
...)
{
GHashTable *attributes;
va_list va;
g_return_if_fail (schema != NULL);
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
va_start (va, user_data);
attributes = secret_attributes_buildv (schema, va);
va_end (va);
/* Precondition failed, already warned */
if (!attributes)
return;
secret_password_searchv (schema, attributes, flags, cancellable,
callback, user_data);
g_hash_table_unref (attributes);
}
/**
* secret_password_searchv: (rename-to secret_password_search)
* @schema: (nullable): the schema for attributes
* @attributes: (element-type utf8 utf8): the attribute keys and values
* @flags: search option flags
* @cancellable: optional cancellation object
* @callback: called when the operation completes
* @user_data: data to be passed to the callback
*
* Search for items in the secret service.
*
* The @attributes should be a set of key and value string pairs.
*
* This method will return immediately and complete asynchronously.
*
* Since: 0.19.0
*/
void
secret_password_searchv (const SecretSchema *schema,
GHashTable *attributes,
SecretSearchFlags flags,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
g_return_if_fail (attributes != NULL);
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
/* Warnings raised already */
if (schema != NULL && !_secret_attributes_validate (schema, attributes, G_STRFUNC, TRUE))
return;
secret_service_search (NULL, schema, attributes, flags,
cancellable, callback, user_data);
}
/**
* secret_password_search_finish:
* @result: the asynchronous result passed to the callback
* @error: location to place an error on failure
*
* Finish an asynchronous operation to search for items in the secret service.
*
* Returns: (transfer full) (element-type Secret.Retrievable): a list of
* #SecretRetrievable containing attributes of the matched items
*
* Since: 0.19.0
*/
GList *
secret_password_search_finish (GAsyncResult *result,
GError **error)
{
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
return secret_service_search_finish (NULL, result, error);
}
/**
* secret_password_search_sync: (skip)
* @schema: the schema for the attributes
* @flags: search option flags
* @cancellable: optional cancellation object
* @error: location to place an error on failure
* @...: the attribute keys and values, terminated with %NULL
*
* Search for items in the secret service.
*
* The variable argument list should contain pairs of a) The attribute name as
* a null-terminated string, followed by b) attribute value, either a character
* string, an int number, or a gboolean value, as defined in the password
* @schema. The list of attributes should be terminated with a %NULL.
*
* If no secret is found then %NULL is returned.
*
* This method may block indefinitely and should not be used in user interface
* threads.
*
* Returns: (transfer full) (element-type Secret.Retrievable): a list of
* #SecretRetrievable containing attributes of the matched items
*
* Since: 0.19.0
*/
GList *
secret_password_search_sync (const SecretSchema *schema,
SecretSearchFlags flags,
GCancellable *cancellable,
GError **error,
...)
{
GHashTable *attributes;
GList *items;
va_list va;
g_return_val_if_fail (schema != NULL, NULL);
g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
va_start (va, error);
attributes = secret_attributes_buildv (schema, va);
va_end (va);
/* Precondition failed, already warned */
if (!attributes)
return NULL;
items = secret_password_searchv_sync (schema, attributes, flags,
cancellable, error);
g_hash_table_unref (attributes);
return items;
}
/**
* secret_password_searchv_sync: (rename-to secret_password_search_sync)
* @schema: (nullable): the schema for attributes
* @attributes: (element-type utf8 utf8): the attribute keys and values
* @flags: search option flags
* @cancellable: optional cancellation object
* @error: location to place an error on failure
*
* Search for items in the secret service.
*
* The @attributes should be a set of key and value string pairs.
*
* If no secret is found then %NULL is returned.
*
* This method may block indefinitely and should not be used in user interface
* threads.
*
* Returns: (transfer full) (element-type Secret.Retrievable): a list of
* #SecretRetrievable containing attributes of the matched items
*
* Since: 0.19.0
*/
GList *
secret_password_searchv_sync (const SecretSchema *schema,
GHashTable *attributes,
SecretSearchFlags flags,
GCancellable *cancellable,
GError **error)
{
SecretSync *sync;
GList *items;
g_return_val_if_fail (attributes != NULL, NULL);
g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
/* Warnings raised already */
if (schema != NULL && !_secret_attributes_validate (schema, attributes, G_STRFUNC, TRUE))
return NULL;
sync = _secret_sync_new ();
g_main_context_push_thread_default (sync->context);
secret_password_searchv (schema, attributes, flags, cancellable,
_secret_sync_on_result, sync);
g_main_loop_run (sync->loop);
items = secret_password_search_finish (sync->result, error);
g_main_context_pop_thread_default (sync->context);
_secret_sync_free (sync);
return items;
}
/**
* secret_password_free: (skip)
* @password: (allow-none): password to free

View File

@ -25,6 +25,7 @@ G_BEGIN_DECLS
#include "secret-schema.h"
#include "secret-types.h"
#include "secret-value.h"
void secret_password_store (const SecretSchema *schema,
const gchar *collection,
@ -44,6 +45,24 @@ void secret_password_storev (const SecretSchema *sche
GAsyncReadyCallback callback,
gpointer user_data);
void secret_password_store_binary (const SecretSchema *schema,
const gchar *collection,
const gchar *label,
SecretValue *value,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data,
...);
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);
gboolean secret_password_store_finish (GAsyncResult *result,
GError **error);
@ -63,6 +82,22 @@ gboolean secret_password_storev_sync (const SecretSchema *sche
GCancellable *cancellable,
GError **error);
gboolean secret_password_store_binary_sync (const SecretSchema *schema,
const gchar *collection,
const gchar *label,
SecretValue *value,
GCancellable *cancellable,
GError **error,
...);
gboolean secret_password_storev_binary_sync (const SecretSchema *schema,
GHashTable *attributes,
const gchar *collection,
const gchar *label,
SecretValue *value,
GCancellable *cancellable,
GError **error);
void secret_password_lookup (const SecretSchema *schema,
GCancellable *cancellable,
GAsyncReadyCallback callback,
@ -80,6 +115,8 @@ gchar * secret_password_lookup_finish (GAsyncResult *result,
gchar * secret_password_lookup_nonpageable_finish (GAsyncResult *result,
GError **error);
SecretValue *secret_password_lookup_binary_finish (GAsyncResult *result,
GError **error);
gchar * secret_password_lookup_sync (const SecretSchema *schema,
GCancellable *cancellable,
@ -90,6 +127,10 @@ gchar * secret_password_lookup_nonpageable_sync (const SecretSchema *sche
GCancellable *cancellable,
GError **error,
...);
SecretValue *secret_password_lookup_binary_sync (const SecretSchema *schema,
GCancellable *cancellable,
GError **error,
...);
gchar * secret_password_lookupv_sync (const SecretSchema *schema,
GHashTable *attributes,
@ -100,6 +141,10 @@ gchar * secret_password_lookupv_nonpageable_sync (const SecretSchema *sche
GHashTable *attributes,
GCancellable *cancellable,
GError **error);
SecretValue *secret_password_lookupv_binary_sync (const SecretSchema *schema,
GHashTable *attributes,
GCancellable *cancellable,
GError **error);
void secret_password_clear (const SecretSchema *schema,
GCancellable *cancellable,
@ -126,6 +171,35 @@ gboolean secret_password_clearv_sync (const SecretSchema *sche
GCancellable *cancellable,
GError **error);
void secret_password_search (const SecretSchema *schema,
SecretSearchFlags flags,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data,
...) G_GNUC_NULL_TERMINATED;
void secret_password_searchv (const SecretSchema *schema,
GHashTable *attributes,
SecretSearchFlags flags,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
GList * secret_password_search_sync (const SecretSchema *schema,
SecretSearchFlags flags,
GCancellable *cancellable,
GError **error,
...) G_GNUC_NULL_TERMINATED;
GList * secret_password_searchv_sync (const SecretSchema *schema,
GHashTable *attributes,
SecretSearchFlags flags,
GCancellable *cancellable,
GError **error);
GList * secret_password_search_finish (GAsyncResult *result,
GError **error);
void secret_password_free (gchar *password);
void secret_password_wipe (gchar *password);

View File

@ -0,0 +1,307 @@
/* libsecret - GLib wrapper for Secret Service
*
* Copyright 2019 Red Hat, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2.1 of the licence or (at
* your option) any later version.
*
* See the included COPYING file for more information.
*
* Author: Daiki Ueno
*/
#include "config.h"
#include "secret-retrievable.h"
#include "secret-private.h"
/**
* SECTION:secret-retrievable
* @title: SecretRetrievable
* @short_description: A read-only secret item
*
* #SecretRetrievable provides a read-only view of a secret item
* stored in the Secret Service.
*
* Each item has a value, represented by a #SecretValue, which can be
* retrieved by secret_retrievable_retrieve_secret() and
* secret_retrievable_retrieve_secret_finish().
*
* Stability: Stable
*/
/**
* SecretRetrievable:
*
* An object representing a read-only view of a secret item in the
* Secret Service.
*
* Since: 0.19.0
*/
/**
* SecretRetrievableInterface:
* @parent_iface: the parent interface
* @retrieve_secret: implementation of secret_retrievable_retrieve_secret(),
* required
* @retrieve_secret_finish: implementation of
* secret_retrievable_retrieve_secret_finish(), required
*
* The interface for #SecretRetrievable.
*
* Since: 0.19.0
*/
G_DEFINE_INTERFACE (SecretRetrievable, secret_retrievable, G_TYPE_OBJECT);
static void
secret_retrievable_default_init (SecretRetrievableInterface *iface)
{
/**
* SecretRetrievable:attributes: (type GLib.HashTable(utf8,utf8)) (transfer full)
*
* The attributes set on this item. Attributes are used to locate an
* item. They are not guaranteed to be stored or transferred securely.
*
* Since: 0.19.0
*/
g_object_interface_install_property (iface,
g_param_spec_boxed ("attributes", "Attributes", "Item attributes",
G_TYPE_HASH_TABLE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
/**
* SecretRetrievable:label:
*
* The human readable label for the item.
*
* Since: 0.19.0
*/
g_object_interface_install_property (iface,
g_param_spec_string ("label", "Label", "Item label",
NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
/**
* SecretRetrievable:created:
*
* The date and time (in seconds since the UNIX epoch) that this
* item was created.
*
* Since: 0.19.0
*/
g_object_interface_install_property (iface,
g_param_spec_uint64 ("created", "Created", "Item creation date",
0UL, G_MAXUINT64, 0UL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
/**
* SecretRetrievable:modified:
*
* The date and time (in seconds since the UNIX epoch) that this
* item was last modified.
*
* Since: 0.19.0
*/
g_object_interface_install_property (iface,
g_param_spec_uint64 ("modified", "Modified", "Item modified date",
0UL, G_MAXUINT64, 0UL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
}
/**
* secret_retrievable_retrieve_secret:
* @self: a retrievable object
* @cancellable: (nullable): optional cancellation object
* @callback: called when the operation completes
* @user_data: data to pass to the callback
*
* Retrieve the secret value of this object.
*
* Each retrievable object has a single secret which might be a
* password or some other secret binary value.
*
* This function returns immediately and completes asynchronously.
*
* Since: 0.19.0
*/
void
secret_retrievable_retrieve_secret (SecretRetrievable *self,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
SecretRetrievableInterface *iface;
g_return_if_fail (SECRET_IS_RETRIEVABLE (self));
iface = SECRET_RETRIEVABLE_GET_IFACE (self);
g_return_if_fail (iface->retrieve_secret != NULL);
iface->retrieve_secret (self, cancellable, callback, user_data);
}
/**
* secret_retrievable_retrieve_secret_finish:
* @self: a retrievable object
* @result: asynchronous result passed to callback
* @error: location to place error on failure
*
* Complete asynchronous operation to retrieve the secret value of this object.
*
* Returns: (transfer full) (nullable): the secret value which should be
* released with secret_value_unref(), or %NULL
*
* Since: 0.19.0
*/
SecretValue *
secret_retrievable_retrieve_secret_finish (SecretRetrievable *self,
GAsyncResult *result,
GError **error)
{
SecretRetrievableInterface *iface;
g_return_val_if_fail (SECRET_IS_RETRIEVABLE (self), NULL);
iface = SECRET_RETRIEVABLE_GET_IFACE (self);
g_return_val_if_fail (iface->retrieve_secret_finish != NULL, NULL);
return iface->retrieve_secret_finish (self, result, error);
}
/**
* secret_retrievable_retrieve_secret_sync:
* @self: a retrievable object
* @cancellable: (nullable): optional cancellation object
* @error: location to place error on failure
*
* Retrieve the secret value of this object synchronously.
*
* Each retrievable object has a single secret which might be a
* password or some other secret binary value.
*
* This method may block indefinitely and should not be used in user interface
* threads.
*
* Returns: (transfer full) (nullable): the secret value which should be
* released with secret_value_unref(), or %NULL
*
* Since: 0.19.0
*/
SecretValue *
secret_retrievable_retrieve_secret_sync (SecretRetrievable *self,
GCancellable *cancellable,
GError **error)
{
SecretSync *sync;
SecretValue *value;
g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
sync = _secret_sync_new ();
g_main_context_push_thread_default (sync->context);
secret_retrievable_retrieve_secret (self,
cancellable,
_secret_sync_on_result, sync);
g_main_loop_run (sync->loop);
value = secret_retrievable_retrieve_secret_finish (self,
sync->result,
error);
g_main_context_pop_thread_default (sync->context);
_secret_sync_free (sync);
return value;
}
/**
* secret_retrievable_get_attributes:
* @self: a retrievable object
*
* Get the attributes of this object.
*
* The attributes are a mapping of string keys to string values.
* Attributes are used to search for items. Attributes are not stored
* or transferred securely by the secret service.
*
* Do not modify the attribute returned by this method.
*
* Returns: (transfer full) (element-type utf8 utf8): a new reference
* to the attributes, which should not be modified, and
* released with g_hash_table_unref()
*
* Since: 0.19.0
*/
GHashTable *
secret_retrievable_get_attributes (SecretRetrievable *self)
{
GHashTable *value;
g_return_val_if_fail (SECRET_IS_RETRIEVABLE (self), NULL);
g_object_get (G_OBJECT (self), "attributes", &value, NULL);
return value;
}
/**
* secret_retrievable_get_label:
* @self: a retrievable object
*
* Get the label of this item.
*
* Returns: (transfer full): the label, which should be freed with g_free()
*
* Since: 0.19.0
*/
gchar *
secret_retrievable_get_label (SecretRetrievable *self)
{
gchar *value;
g_return_val_if_fail (SECRET_IS_RETRIEVABLE (self), NULL);
g_object_get (G_OBJECT (self), "label", &value, NULL);
return value;
}
/**
* secret_retrievable_get_created:
* @self: a retrievable object
*
* Get the created date and time of the object. The return value is
* the number of seconds since the unix epoch, January 1st 1970.
*
* Returns: the created date and time
*
* Since: 0.19.0
*/
guint64
secret_retrievable_get_created (SecretRetrievable *self)
{
guint64 value;
g_return_val_if_fail (SECRET_IS_RETRIEVABLE (self), 0);
g_object_get (G_OBJECT (self), "created", &value, NULL);
return value;
}
/**
* secret_retrievable_get_modified:
* @self: a retrievable object
*
* Get the modified date and time of the object. The return value is
* the number of seconds since the unix epoch, January 1st 1970.
*
* Returns: the modified date and time
*
* Since: 0.19.0
*/
guint64
secret_retrievable_get_modified (SecretRetrievable *self)
{
guint64 value;
g_return_val_if_fail (SECRET_IS_RETRIEVABLE (self), 0);
g_object_get (G_OBJECT (self), "modified", &value, NULL);
return value;
}

View File

@ -0,0 +1,64 @@
/* libsecret - GLib wrapper for Secret Service
*
* Copyright 2019 Red Hat, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2.1 of the licence or (at
* your option) any later version.
*
* See the included COPYING file for more information.
*
* Author: Daiki Ueno
*/
#if !defined (__SECRET_INSIDE_HEADER__) && !defined (SECRET_COMPILATION)
#error "Only <libsecret/secret.h> can be included directly."
#endif
#ifndef __SECRET_RETRIEVABLE_H__
#define __SECRET_RETRIEVABLE_H__
#include <glib-object.h>
#include "secret-value.h"
G_BEGIN_DECLS
#define SECRET_TYPE_RETRIEVABLE secret_retrievable_get_type ()
G_DECLARE_INTERFACE (SecretRetrievable, secret_retrievable, SECRET, RETRIEVABLE, GObject)
struct _SecretRetrievableInterface
{
GTypeInterface parent_iface;
void (*retrieve_secret) (SecretRetrievable *self,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
SecretValue *(*retrieve_secret_finish) (SecretRetrievable *self,
GAsyncResult *result,
GError **error);
};
void secret_retrievable_retrieve_secret (SecretRetrievable *self,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
SecretValue *secret_retrievable_retrieve_secret_finish (SecretRetrievable *self,
GAsyncResult *result,
GError **error);
SecretValue *secret_retrievable_retrieve_secret_sync (SecretRetrievable *self,
GCancellable *cancellable,
GError **error);
GHashTable *secret_retrievable_get_attributes (SecretRetrievable *self);
gchar *secret_retrievable_get_label (SecretRetrievable *self);
guint64 secret_retrievable_get_created (SecretRetrievable *self);
guint64 secret_retrievable_get_modified (SecretRetrievable *self);
G_END_DECLS
#endif /* __SECRET_RETRIEVABLE_H__ */

View File

@ -35,13 +35,6 @@ typedef enum {
SECRET_SERVICE_LOAD_COLLECTIONS = 1 << 2,
} SecretServiceFlags;
typedef enum {
SECRET_SEARCH_NONE = 0,
SECRET_SEARCH_ALL = 1 << 1,
SECRET_SEARCH_UNLOCK = 1 << 2,
SECRET_SEARCH_LOAD_SECRETS = 1 << 3,
} SecretSearchFlags;
#define SECRET_TYPE_SERVICE (secret_service_get_type ())
#define SECRET_SERVICE(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), SECRET_TYPE_SERVICE, SecretService))
#define SECRET_SERVICE_CLASS(class) (G_TYPE_CHECK_CLASS_CAST ((class), SECRET_TYPE_SERVICE, SecretServiceClass))

View File

@ -38,6 +38,13 @@ typedef enum {
#define SECRET_COLLECTION_SESSION "session"
typedef enum {
SECRET_SEARCH_NONE = 0,
SECRET_SEARCH_ALL = 1 << 1,
SECRET_SEARCH_UNLOCK = 1 << 2,
SECRET_SEARCH_LOAD_SECRETS = 1 << 3,
} SecretSearchFlags;
G_END_DECLS
#endif /* __G_SERVICE_H___ */

View File

@ -256,36 +256,64 @@ is_password_value (SecretValue *value)
return FALSE;
}
/**
* secret_value_unref_to_password:
* @value: the value
* @length: the length of the secret
*
* Unreference a #SecretValue and steal the secret data in
* #SecretValue as nonpageable memory.
*
* Returns: (transfer full): a new password string stored in nonpageable memory
* which must be freed with secret_password_free() when done
*
* Since: 0.19.0
*/
gchar *
_secret_value_unref_to_password (SecretValue *value)
secret_value_unref_to_password (SecretValue *value,
gsize *length)
{
SecretValue *val = value;
gchar *result;
g_return_val_if_fail (value != NULL, NULL);
if (g_atomic_int_dec_and_test (&val->refs)) {
if (val->destroy == egg_secure_free) {
result = val->secret;
if (length)
*length = val->length;
} else {
result = egg_secure_strndup (val->secret, val->length);
if (val->destroy)
(val->destroy) (val->secret);
if (length)
*length = val->length;
}
g_free (val->content_type);
g_slice_free (SecretValue, val);
} else {
result = egg_secure_strndup (val->secret, val->length);
if (length)
*length = val->length;
}
return result;
}
gchar *
_secret_value_unref_to_password (SecretValue *value)
{
g_return_val_if_fail (value != NULL, NULL);
if (!is_password_value (value)) {
secret_value_unref (value);
return NULL;
}
if (g_atomic_int_dec_and_test (&val->refs)) {
if (val->destroy == egg_secure_free) {
result = val->secret;
} else {
result = egg_secure_strndup (val->secret, val->length);
if (val->destroy)
(val->destroy) (val->secret);
}
g_free (val->content_type);
g_slice_free (SecretValue, val);
} else {
result = egg_secure_strndup (val->secret, val->length);
}
return result;
return secret_value_unref_to_password (value, NULL);
}
gchar *

View File

@ -51,6 +51,9 @@ SecretValue * secret_value_ref (SecretValue *value);
void secret_value_unref (gpointer value);
gchar * secret_value_unref_to_password (SecretValue *value,
gsize *length);
G_DEFINE_AUTOPTR_CLEANUP_FUNC (SecretValue, secret_value_unref)
G_END_DECLS

View File

@ -25,6 +25,7 @@
#include <libsecret/secret-item.h>
#include <libsecret/secret-password.h>
#include <libsecret/secret-prompt.h>
#include <libsecret/secret-retrievable.h>
#include <libsecret/secret-schema.h>
#include <libsecret/secret-schemas.h>
#include <libsecret/secret-service.h>

View File

@ -356,6 +356,160 @@ test_clear_no_name (Test *test,
g_assert_true (ret);
}
static void
free_attributes (gpointer data,
gpointer user_data)
{
g_object_unref ((GObject *)data);
}
static void
test_search_sync (Test *test,
gconstpointer used)
{
GList *items;
GError *error = NULL;
items = secret_password_search_sync (&MOCK_SCHEMA, SECRET_SEARCH_ALL,
NULL, &error,
"even", FALSE,
"string", "one",
"number", 1,
NULL);
g_assert_no_error (error);
g_assert_cmpint (g_list_length (items), ==, 1);
g_list_foreach (items, free_attributes, NULL);
g_list_free (items);
}
static void
test_search_async (Test *test,
gconstpointer used)
{
GAsyncResult *result = NULL;
GError *error = NULL;
GList *items;
secret_password_search (&MOCK_SCHEMA, SECRET_SEARCH_ALL,
NULL, on_complete_get_result, &result,
"even", FALSE,
"string", "one",
"number", 1,
NULL);
g_assert (result == NULL);
egg_test_wait ();
items = secret_password_search_finish (result, &error);
g_assert_no_error (error);
g_object_unref (result);
g_assert_cmpint (g_list_length (items), ==, 1);
g_list_foreach (items, free_attributes, NULL);
g_list_free (items);
}
static void
test_search_no_name (Test *test,
gconstpointer used)
{
GError *error = NULL;
GList *items;
/* should return null, because nothing with mock schema and 5 */
items = secret_password_search_sync (&MOCK_SCHEMA, SECRET_SEARCH_ALL,
NULL, &error,
"number", 5,
NULL);
g_assert_no_error (error);
g_assert (items == NULL);
/* should return an item, because we have a prime schema with 5, and flags not to match name */
items = secret_password_search_sync (&NO_NAME_SCHEMA, SECRET_SEARCH_ALL,
NULL, &error,
"number", 5,
NULL);
g_assert_no_error (error);
g_assert_cmpint (g_list_length (items), ==, 1);
g_list_foreach (items, free_attributes, NULL);
g_list_free (items);
}
static void
test_binary_sync (Test *test,
gconstpointer used)
{
const gchar *collection_path = "/org/freedesktop/secrets/collection/english";
GError *error = NULL;
SecretValue *value;
gboolean ret;
value = secret_value_new ("the password", -1, "text/plain");
ret = secret_password_store_binary_sync (&MOCK_SCHEMA, collection_path,
"Label here", value, NULL, &error,
"even", TRUE,
"string", "twelve",
"number", 12,
NULL);
g_assert_no_error (error);
g_assert_true (ret);
secret_value_unref (value);
value = secret_password_lookup_binary_sync (&MOCK_SCHEMA, NULL, &error,
"string", "twelve",
NULL);
g_assert_no_error (error);
g_assert_cmpstr (secret_value_get_text (value), ==, "the password");
secret_value_unref (value);
}
static void
test_binary_async (Test *test,
gconstpointer used)
{
const gchar *collection_path = "/org/freedesktop/secrets/collection/english";
GAsyncResult *result = NULL;
GError *error = NULL;
SecretValue *value;
gboolean ret;
value = secret_value_new ("the password", -1, "text/plain");
secret_password_store_binary (&MOCK_SCHEMA, collection_path, "Label here",
value, NULL, on_complete_get_result, &result,
"even", TRUE,
"string", "twelve",
"number", 12,
NULL);
g_assert_null (result);
secret_value_unref (value);
egg_test_wait ();
ret = secret_password_store_finish (result, &error);
g_assert_no_error (error);
g_assert_true (ret);
g_object_unref (result);
value = secret_password_lookup_binary_sync (&MOCK_SCHEMA, NULL, &error,
"string", "twelve",
NULL);
g_assert_no_error (error);
g_assert_nonnull (value);
g_assert_cmpstr (secret_value_get_text (value), ==, "the password");
secret_value_unref (value);
}
static void
test_password_free_null (void)
{
@ -380,6 +534,13 @@ main (int argc, char **argv)
g_test_add ("/password/delete-async", Test, "mock-service-delete.py", setup, test_delete_async, teardown);
g_test_add ("/password/clear-no-name", Test, "mock-service-delete.py", setup, test_clear_no_name, teardown);
g_test_add ("/password/search-sync", Test, "mock-service-normal.py", setup, test_search_sync, teardown);
g_test_add ("/password/search-async", Test, "mock-service-normal.py", setup, test_search_async, teardown);
g_test_add ("/password/search-no-name", Test, "mock-service-normal.py", setup, test_search_no_name, teardown);
g_test_add ("/password/binary-sync", Test, "mock-service-normal.py", setup, test_binary_sync, teardown);
g_test_add ("/password/binary-async", Test, "mock-service-normal.py", setup, test_binary_async, teardown);
g_test_add_func ("/password/free-null", test_password_free_null);
return egg_tests_run_with_loop ();

View File

@ -16,7 +16,7 @@
#include "libsecret/secret-item.h"
#include "libsecret/secret-password.h"
#include "libsecret/secret-service.h"
#include "libsecret/secret-retrievable.h"
#include "libsecret/secret-value.h"
#include <glib/gi18n.h>
@ -122,8 +122,8 @@ secret_tool_action_clear (int argc,
{
GError *error = NULL;
GOptionContext *context;
SecretService *service;
GHashTable *attributes;
gboolean ret;
context = g_option_context_new ("attribute value ...");
g_option_context_add_main_entries (context, CLEAR_OPTIONS, GETTEXT_PACKAGE);
@ -137,14 +137,11 @@ secret_tool_action_clear (int argc,
attributes = attributes_from_arguments (attribute_args);
g_strfreev (attribute_args);
service = secret_service_get_sync (SECRET_SERVICE_NONE, NULL, &error);
if (error == NULL)
secret_service_clear_sync (service, NULL, attributes, NULL, &error);
ret = secret_password_clearv_sync (NULL, attributes, NULL, &error);
g_object_unref (service);
g_hash_table_unref (attributes);
if (error != NULL) {
if (!ret) {
g_printerr ("%s: %s\n", g_get_prgname (), error->message);
return 1;
}
@ -197,7 +194,6 @@ secret_tool_action_lookup (int argc,
{
GError *error = NULL;
GOptionContext *context;
SecretService *service;
GHashTable *attributes;
SecretValue *value = NULL;
@ -213,11 +209,8 @@ secret_tool_action_lookup (int argc,
attributes = attributes_from_arguments (attribute_args);
g_strfreev (attribute_args);
service = secret_service_get_sync (SECRET_SERVICE_NONE, NULL, &error);
if (error == NULL)
value = secret_service_lookup_sync (service, NULL, attributes, NULL, &error);
value = secret_password_lookupv_binary_sync (NULL, attributes, NULL, &error);
g_object_unref (service);
g_hash_table_unref (attributes);
if (error != NULL) {
@ -285,10 +278,10 @@ secret_tool_action_store (int argc,
{
GError *error = NULL;
GOptionContext *context;
SecretService *service;
GHashTable *attributes;
SecretValue *value;
gchar *collection = NULL;
gboolean ret;
context = g_option_context_new ("attribute value ...");
g_option_context_add_main_entries (context, STORE_OPTIONS, GETTEXT_PACKAGE);
@ -315,24 +308,20 @@ secret_tool_action_store (int argc,
collection = g_strconcat (SECRET_ALIAS_PREFIX, store_collection, NULL);
}
service = secret_service_get_sync (SECRET_SERVICE_NONE, NULL, &error);
if (error == NULL) {
if (isatty (0))
value = read_password_tty ();
else
value = read_password_stdin ();
secret_service_store_sync (service, NULL, attributes, collection, store_label, value, NULL, &error);
ret = secret_password_storev_binary_sync (NULL, attributes, collection, store_label, value, NULL, &error);
secret_value_unref (value);
}
g_object_unref (service);
g_hash_table_unref (attributes);
g_free (store_label);
g_free (store_collection);
g_free (collection);
if (error != NULL) {
if (!ret) {
g_printerr ("%s: %s\n", g_get_prgname (), error->message);
return 1;
}
@ -360,16 +349,30 @@ print_item_when (const char *field,
}
static void
print_item_details (SecretItem *item)
on_retrieve_secret (GObject *source_object,
GAsyncResult *res,
gpointer user_data)
{
SecretRetrievable *item = SECRET_RETRIEVABLE (source_object);
GMainLoop *loop = user_data;
SecretValue *secret;
GHashTableIter iter;
GHashTable *attributes;
gchar *value, *key;
const gchar *value, *key;
guint64 when;
gchar *label;
const gchar *part;
const gchar *path;
GError *error;
error = NULL;
secret = secret_retrievable_retrieve_secret_finish (item, res, &error);
if (!secret) {
g_printerr ("%s: %s\n", g_get_prgname (), error->message);
g_clear_error (&error);
}
if (G_IS_DBUS_PROXY (item)) {
path = g_dbus_proxy_get_object_path (G_DBUS_PROXY (item));
g_return_if_fail (path != NULL);
@ -378,40 +381,44 @@ print_item_details (SecretItem *item)
if (part == NULL)
part = path;
g_print ("[%s]\n", path);
} else {
g_print ("[no path]\n");
}
/* The label */
value = secret_item_get_label (item);
g_print ("label = %s\n", value);
g_free (value);
label = secret_retrievable_get_label (item);
g_print ("label = %s\n", label);
g_free (label);
if (secret) {
/* The secret value */
secret = secret_item_get_secret (item);
g_print ("secret = ");
if (secret != NULL) {
write_password_data (secret);
secret_value_unref (secret);
}
g_print ("\n");
}
/* The dates */
when = secret_item_get_created (item);
when = secret_retrievable_get_created (item);
print_item_when ("created", when);
when = secret_item_get_modified (item);
when = secret_retrievable_get_modified (item);
print_item_when ("modified", when);
/* The schema */
value = secret_item_get_schema_name (item);
g_print ("schema = %s\n", value);
g_free (value);
/* The attributes */
attributes = secret_item_get_attributes (item);
attributes = secret_retrievable_get_attributes (item);
value = g_hash_table_lookup (attributes, "xdg:schema");
if (value)
g_print ("schema = %s\n", value);
g_hash_table_iter_init (&iter, attributes);
while (g_hash_table_iter_next (&iter, (void **)&key, (void **)&value)) {
if (strcmp (key, "xdg:schema") != 0)
g_printerr ("attribute.%s = %s\n", key, value);
}
g_hash_table_unref (attributes);
g_main_loop_quit (loop);
}
static int
@ -420,7 +427,6 @@ secret_tool_action_search (int argc,
{
GError *error = NULL;
GOptionContext *context;
SecretService *service;
GHashTable *attributes;
SecretSearchFlags flags;
gboolean flag_all = FALSE;
@ -450,21 +456,25 @@ secret_tool_action_search (int argc,
attributes = attributes_from_arguments (attribute_args);
g_strfreev (attribute_args);
service = secret_service_get_sync (SECRET_SERVICE_NONE, NULL, &error);
if (error == NULL) {
flags = SECRET_SEARCH_LOAD_SECRETS;
if (flag_all)
flags |= SECRET_SEARCH_ALL;
if (flag_unlock)
flags |= SECRET_SEARCH_UNLOCK;
items = secret_service_search_sync (service, NULL, attributes, flags, NULL, &error);
items = secret_password_searchv_sync (NULL, attributes, flags, NULL, &error);
if (error == NULL) {
for (l = items; l != NULL; l = g_list_next (l))
print_item_details (l->data);
g_list_free_full (items, g_object_unref);
GMainLoop *loop = g_main_loop_new (NULL, FALSE);
for (l = items; l != NULL; l = g_list_next (l)) {
SecretRetrievable *retrievable = SECRET_RETRIEVABLE (l->data);
secret_retrievable_retrieve_secret (retrievable,
NULL,
on_retrieve_secret,
loop);
g_main_loop_run (loop);
}
g_object_unref (service);
g_list_free_full (items, g_object_unref);
}
g_hash_table_unref (attributes);