mirror of
https://gitlab.gnome.org/GNOME/libsecret.git
synced 2025-01-03 02:28:53 +00:00
Tests for GSecretItem and GSecretValue
* And fix bugs found in the process
This commit is contained in:
parent
116447c59e
commit
f44aae6efa
@ -20,6 +20,7 @@ libgsecret_la_SOURCES = \
|
|||||||
gsecret-password.h gsecret-password.c \
|
gsecret-password.h gsecret-password.c \
|
||||||
gsecret-prompt.h gsecret-prompt.c \
|
gsecret-prompt.h gsecret-prompt.c \
|
||||||
gsecret-service.h gsecret-service.c \
|
gsecret-service.h gsecret-service.c \
|
||||||
|
gsecret-session.h gsecret-session.c \
|
||||||
gsecret-util.c \
|
gsecret-util.c \
|
||||||
gsecret-value.h gsecret-value.c \
|
gsecret-value.h gsecret-value.c \
|
||||||
$(BUILT_SOURCES) \
|
$(BUILT_SOURCES) \
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/* GSecret - GLib wrapper for Secret Service
|
/* GSecret - GLib wrapper for Secret Service
|
||||||
*
|
*
|
||||||
* Copyright 2011 Red Hat Inc.
|
* Copyright 2012 Red Hat Inc.
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU Lesser General Public License as published
|
||||||
@ -23,6 +23,7 @@
|
|||||||
|
|
||||||
enum {
|
enum {
|
||||||
PROP_0,
|
PROP_0,
|
||||||
|
PROP_SERVICE,
|
||||||
PROP_ITEMS,
|
PROP_ITEMS,
|
||||||
PROP_LABEL,
|
PROP_LABEL,
|
||||||
PROP_LOCKED,
|
PROP_LOCKED,
|
||||||
@ -34,6 +35,7 @@ struct _GSecretCollectionPrivate {
|
|||||||
/* Doesn't change between construct and finalize */
|
/* Doesn't change between construct and finalize */
|
||||||
GSecretService *service;
|
GSecretService *service;
|
||||||
GCancellable *cancellable;
|
GCancellable *cancellable;
|
||||||
|
gboolean constructing;
|
||||||
|
|
||||||
/* Protected by mutex */
|
/* Protected by mutex */
|
||||||
GMutex mutex;
|
GMutex mutex;
|
||||||
@ -58,6 +60,7 @@ gsecret_collection_init (GSecretCollection *self)
|
|||||||
g_mutex_init (&self->pv->mutex);
|
g_mutex_init (&self->pv->mutex);
|
||||||
self->pv->cancellable = g_cancellable_new ();
|
self->pv->cancellable = g_cancellable_new ();
|
||||||
self->pv->items = items_table_new ();
|
self->pv->items = items_table_new ();
|
||||||
|
self->pv->constructing = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -86,6 +89,13 @@ gsecret_collection_set_property (GObject *obj,
|
|||||||
GSecretCollection *self = GSECRET_COLLECTION (obj);
|
GSecretCollection *self = GSECRET_COLLECTION (obj);
|
||||||
|
|
||||||
switch (prop_id) {
|
switch (prop_id) {
|
||||||
|
case PROP_SERVICE:
|
||||||
|
g_return_if_fail (self->pv->service == NULL);
|
||||||
|
self->pv->service = g_value_get_object (value);
|
||||||
|
if (self->pv->service)
|
||||||
|
g_object_add_weak_pointer (G_OBJECT (self->pv->service),
|
||||||
|
(gpointer *)&self->pv->service);
|
||||||
|
break;
|
||||||
case PROP_LABEL:
|
case PROP_LABEL:
|
||||||
gsecret_collection_set_label (self, g_value_get_string (value),
|
gsecret_collection_set_label (self, g_value_get_string (value),
|
||||||
self->pv->cancellable, on_set_label,
|
self->pv->cancellable, on_set_label,
|
||||||
@ -106,6 +116,9 @@ gsecret_collection_get_property (GObject *obj,
|
|||||||
GSecretCollection *self = GSECRET_COLLECTION (obj);
|
GSecretCollection *self = GSECRET_COLLECTION (obj);
|
||||||
|
|
||||||
switch (prop_id) {
|
switch (prop_id) {
|
||||||
|
case PROP_SERVICE:
|
||||||
|
g_value_set_object (value, self->pv->service);
|
||||||
|
break;
|
||||||
case PROP_ITEMS:
|
case PROP_ITEMS:
|
||||||
g_value_take_boxed (value, gsecret_collection_get_items (self));
|
g_value_take_boxed (value, gsecret_collection_get_items (self));
|
||||||
break;
|
break;
|
||||||
@ -132,10 +145,9 @@ gsecret_collection_dispose (GObject *obj)
|
|||||||
{
|
{
|
||||||
GSecretCollection *self = GSECRET_COLLECTION (obj);
|
GSecretCollection *self = GSECRET_COLLECTION (obj);
|
||||||
|
|
||||||
g_clear_object (&self->pv->service);
|
|
||||||
g_cancellable_cancel (self->pv->cancellable);
|
g_cancellable_cancel (self->pv->cancellable);
|
||||||
|
|
||||||
G_OBJECT_GET_CLASS (obj)->dispose (obj);
|
G_OBJECT_CLASS (gsecret_collection_parent_class)->dispose (obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -143,14 +155,19 @@ gsecret_collection_finalize (GObject *obj)
|
|||||||
{
|
{
|
||||||
GSecretCollection *self = GSECRET_COLLECTION (obj);
|
GSecretCollection *self = GSECRET_COLLECTION (obj);
|
||||||
|
|
||||||
|
if (self->pv->service)
|
||||||
|
g_object_remove_weak_pointer (G_OBJECT (self->pv->service),
|
||||||
|
(gpointer *)&self->pv->service);
|
||||||
|
|
||||||
g_mutex_clear (&self->pv->mutex);
|
g_mutex_clear (&self->pv->mutex);
|
||||||
g_hash_table_destroy (self->pv->items);
|
g_hash_table_destroy (self->pv->items);
|
||||||
g_object_unref (self->pv->cancellable);
|
g_object_unref (self->pv->cancellable);
|
||||||
|
|
||||||
G_OBJECT_GET_CLASS (obj)->finalize (obj);
|
G_OBJECT_CLASS (gsecret_collection_parent_class)->finalize (obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
GSecretCollection *collection;
|
||||||
GCancellable *cancellable;
|
GCancellable *cancellable;
|
||||||
GHashTable *items;
|
GHashTable *items;
|
||||||
gint items_loading;
|
gint items_loading;
|
||||||
@ -160,6 +177,7 @@ static void
|
|||||||
load_closure_free (gpointer data)
|
load_closure_free (gpointer data)
|
||||||
{
|
{
|
||||||
LoadClosure *closure = data;
|
LoadClosure *closure = data;
|
||||||
|
g_object_unref (closure->collection);
|
||||||
g_clear_object (&closure->cancellable);
|
g_clear_object (&closure->cancellable);
|
||||||
g_hash_table_unref (closure->items);
|
g_hash_table_unref (closure->items);
|
||||||
g_slice_free (LoadClosure, closure);
|
g_slice_free (LoadClosure, closure);
|
||||||
@ -174,7 +192,7 @@ load_result_new (GCancellable *cancellable,
|
|||||||
LoadClosure *closure;
|
LoadClosure *closure;
|
||||||
|
|
||||||
res = g_simple_async_result_new (NULL, callback, user_data, load_result_new);
|
res = g_simple_async_result_new (NULL, callback, user_data, load_result_new);
|
||||||
closure = g_slice_new (LoadClosure);
|
closure = g_slice_new0 (LoadClosure);
|
||||||
closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
|
closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
|
||||||
closure->items = items_table_new ();
|
closure->items = items_table_new ();
|
||||||
g_simple_async_result_set_op_res_gpointer (res, closure, load_closure_free);
|
g_simple_async_result_set_op_res_gpointer (res, closure, load_closure_free);
|
||||||
@ -183,10 +201,10 @@ load_result_new (GCancellable *cancellable,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
load_items_complete (GSecretCollection *self,
|
load_items_complete (GSimpleAsyncResult *res)
|
||||||
GSimpleAsyncResult *res)
|
|
||||||
{
|
{
|
||||||
LoadClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
|
LoadClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
|
||||||
|
GSecretCollection *self = closure->collection;
|
||||||
GHashTable *items;
|
GHashTable *items;
|
||||||
|
|
||||||
g_assert (closure->items_loading == 0);
|
g_assert (closure->items_loading == 0);
|
||||||
@ -209,7 +227,6 @@ on_item_loading (GObject *source,
|
|||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
|
GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
|
||||||
GSecretCollection *self = GSECRET_COLLECTION (g_async_result_get_source_object (user_data));
|
|
||||||
LoadClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
|
LoadClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
|
||||||
const gchar *item_path;
|
const gchar *item_path;
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
@ -223,14 +240,13 @@ on_item_loading (GObject *source,
|
|||||||
g_simple_async_result_take_error (res, error);
|
g_simple_async_result_take_error (res, error);
|
||||||
|
|
||||||
if (item != NULL) {
|
if (item != NULL) {
|
||||||
item_path = g_dbus_proxy_get_object_path (G_DBUS_PROXY (self));
|
item_path = g_dbus_proxy_get_object_path (G_DBUS_PROXY (item));
|
||||||
g_hash_table_insert (closure->items, g_strdup (item_path), item);
|
g_hash_table_insert (closure->items, g_strdup (item_path), item);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (closure->items_loading == 0)
|
if (closure->items_loading == 0)
|
||||||
load_items_complete (self, res);
|
load_items_complete (res);
|
||||||
|
|
||||||
g_object_unref (self);
|
|
||||||
g_object_unref (res);
|
g_object_unref (res);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -244,16 +260,23 @@ load_items_perform (GSecretCollection *self,
|
|||||||
GVariantIter iter;
|
GVariantIter iter;
|
||||||
gchar *item_path;
|
gchar *item_path;
|
||||||
|
|
||||||
|
g_assert (GSECRET_IS_COLLECTION (self));
|
||||||
|
g_assert (item_paths != NULL);
|
||||||
|
g_assert (closure->collection == NULL);
|
||||||
|
|
||||||
|
closure->collection = g_object_ref (self);
|
||||||
|
|
||||||
g_variant_iter_init (&iter, item_paths);
|
g_variant_iter_init (&iter, item_paths);
|
||||||
while (g_variant_iter_loop (&iter, "o", &item_path)) {
|
while (g_variant_iter_loop (&iter, "o", &item_path)) {
|
||||||
|
|
||||||
g_mutex_lock (&self->pv->mutex);
|
g_mutex_lock (&self->pv->mutex);
|
||||||
item = g_hash_table_lookup (self->pv->items, item_path);
|
item = g_hash_table_lookup (self->pv->items, item_path);
|
||||||
if (item == NULL)
|
if (item != NULL)
|
||||||
g_object_ref (item);
|
g_object_ref (item);
|
||||||
g_mutex_unlock (&self->pv->mutex);
|
g_mutex_unlock (&self->pv->mutex);
|
||||||
|
|
||||||
if (item == NULL) {
|
if (item == NULL) {
|
||||||
|
// TODO: xxxxxxxxxxxx;
|
||||||
gsecret_item_new (self->pv->service, item_path,
|
gsecret_item_new (self->pv->service, item_path,
|
||||||
closure->cancellable, on_item_loading,
|
closure->cancellable, on_item_loading,
|
||||||
g_object_ref (res));
|
g_object_ref (res));
|
||||||
@ -267,9 +290,7 @@ load_items_perform (GSecretCollection *self,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (closure->items_loading == 0)
|
if (closure->items_loading == 0)
|
||||||
load_items_complete (self, res);
|
load_items_complete (res);
|
||||||
|
|
||||||
g_variant_unref (item_paths);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -291,7 +312,7 @@ handle_property_changed (GSecretCollection *self,
|
|||||||
else if (g_str_equal (property_name, "Modified"))
|
else if (g_str_equal (property_name, "Modified"))
|
||||||
g_object_notify (G_OBJECT (self), "modified");
|
g_object_notify (G_OBJECT (self), "modified");
|
||||||
|
|
||||||
else if (g_str_equal (property_name, "Items")) {
|
else if (g_str_equal (property_name, "Items") && !self->pv->constructing) {
|
||||||
res = load_result_new (self->pv->cancellable, NULL, NULL);
|
res = load_result_new (self->pv->cancellable, NULL, NULL);
|
||||||
|
|
||||||
if (value == NULL)
|
if (value == NULL)
|
||||||
@ -302,6 +323,7 @@ handle_property_changed (GSecretCollection *self,
|
|||||||
g_warning ("couldn't retrieve Collection Items property");
|
g_warning ("couldn't retrieve Collection Items property");
|
||||||
g_simple_async_result_complete (res);
|
g_simple_async_result_complete (res);
|
||||||
} else {
|
} else {
|
||||||
|
// TODO: yyyy;
|
||||||
load_items_perform (self, res, value);
|
load_items_perform (self, res, value);
|
||||||
g_variant_unref (value);
|
g_variant_unref (value);
|
||||||
}
|
}
|
||||||
@ -324,6 +346,7 @@ gsecret_collection_properties_changed (GDBusProxy *proxy,
|
|||||||
|
|
||||||
g_variant_iter_init (&iter, changed_properties);
|
g_variant_iter_init (&iter, changed_properties);
|
||||||
while (g_variant_iter_loop (&iter, "{sv}", &property_name, &value))
|
while (g_variant_iter_loop (&iter, "{sv}", &property_name, &value))
|
||||||
|
// TODO: zzzz;
|
||||||
handle_property_changed (self, property_name, value);
|
handle_property_changed (self, property_name, value);
|
||||||
|
|
||||||
g_object_thaw_notify (G_OBJECT (self));
|
g_object_thaw_notify (G_OBJECT (self));
|
||||||
@ -342,25 +365,31 @@ gsecret_collection_class_init (GSecretCollectionClass *klass)
|
|||||||
|
|
||||||
proxy_class->g_properties_changed = gsecret_collection_properties_changed;
|
proxy_class->g_properties_changed = gsecret_collection_properties_changed;
|
||||||
|
|
||||||
|
g_object_class_install_property (gobject_class, PROP_SERVICE,
|
||||||
|
g_param_spec_object ("service", "Service", "Secret Service",
|
||||||
|
GSECRET_TYPE_SERVICE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
g_object_class_install_property (gobject_class, PROP_ITEMS,
|
g_object_class_install_property (gobject_class, PROP_ITEMS,
|
||||||
g_param_spec_boxed ("items", "Items", "Items in collection",
|
g_param_spec_boxed ("items", "Items", "Items in collection",
|
||||||
_gsecret_list_get_type (), G_PARAM_READABLE));
|
_gsecret_list_get_type (), G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
g_object_class_install_property (gobject_class, PROP_LABEL,
|
g_object_class_install_property (gobject_class, PROP_LABEL,
|
||||||
g_param_spec_string ("label", "Label", "Item label",
|
g_param_spec_string ("label", "Label", "Item label",
|
||||||
NULL, G_PARAM_READWRITE));
|
NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
g_object_class_install_property (gobject_class, PROP_LOCKED,
|
g_object_class_install_property (gobject_class, PROP_LOCKED,
|
||||||
g_param_spec_boolean ("locked", "Locked", "Item locked",
|
g_param_spec_boolean ("locked", "Locked", "Item locked",
|
||||||
TRUE, G_PARAM_READABLE));
|
TRUE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
g_object_class_install_property (gobject_class, PROP_CREATED,
|
g_object_class_install_property (gobject_class, PROP_CREATED,
|
||||||
g_param_spec_uint64 ("created", "Created", "Item creation date",
|
g_param_spec_uint64 ("created", "Created", "Item creation date",
|
||||||
0UL, G_MAXUINT64, 0UL, G_PARAM_READWRITE));
|
0UL, G_MAXUINT64, 0UL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
g_object_class_install_property (gobject_class, PROP_MODIFIED,
|
g_object_class_install_property (gobject_class, PROP_MODIFIED,
|
||||||
g_param_spec_uint64 ("modified", "Modified", "Item modified date",
|
g_param_spec_uint64 ("modified", "Modified", "Item modified date",
|
||||||
0UL, G_MAXUINT64, 0UL, G_PARAM_READWRITE));
|
0UL, G_MAXUINT64, 0UL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
|
g_type_class_add_private (gobject_class, sizeof (GSecretCollectionPrivate));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -369,24 +398,40 @@ on_collection_new (GObject *source,
|
|||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
|
GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
|
||||||
|
GSecretCollection *self;
|
||||||
GObject *source_object;
|
GObject *source_object;
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
|
GVariant *item_paths;
|
||||||
GObject *object;
|
GObject *object;
|
||||||
|
GDBusProxy *proxy;
|
||||||
|
|
||||||
source_object = g_async_result_get_source_object (user_data);
|
source_object = g_async_result_get_source_object (result);
|
||||||
object = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object),
|
object = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object),
|
||||||
result, &error);
|
result, &error);
|
||||||
g_object_unref (source_object);
|
g_object_unref (source_object);
|
||||||
|
|
||||||
|
proxy = G_DBUS_PROXY (object);
|
||||||
|
if (error == NULL && !_gsecret_util_have_cached_properties (proxy)) {
|
||||||
|
g_set_error (&error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD,
|
||||||
|
"No such secret collection at path: %s", g_dbus_proxy_get_object_path (proxy));
|
||||||
|
}
|
||||||
|
|
||||||
if (error == NULL) {
|
if (error == NULL) {
|
||||||
load_items_perform (GSECRET_COLLECTION (object), res, NULL);
|
self = GSECRET_COLLECTION (object);
|
||||||
g_simple_async_result_set_op_res_gpointer (res, object, g_object_unref);
|
self->pv->constructing = FALSE;
|
||||||
|
|
||||||
|
item_paths = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (object), "Items");
|
||||||
|
g_return_if_fail (item_paths != NULL);
|
||||||
|
// TODO: yyyy;
|
||||||
|
load_items_perform (self, res, item_paths);
|
||||||
|
g_variant_unref (item_paths);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
g_simple_async_result_take_error (res, error);
|
g_simple_async_result_take_error (res, error);
|
||||||
g_simple_async_result_complete (res);
|
g_simple_async_result_complete (res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g_clear_object (&object);
|
||||||
g_object_unref (res);
|
g_object_unref (res);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -410,6 +455,7 @@ gsecret_collection_new (GSecretService *service,
|
|||||||
g_async_initable_new_async (GSECRET_SERVICE_GET_CLASS (service)->collection_gtype,
|
g_async_initable_new_async (GSECRET_SERVICE_GET_CLASS (service)->collection_gtype,
|
||||||
G_PRIORITY_DEFAULT,
|
G_PRIORITY_DEFAULT,
|
||||||
cancellable,
|
cancellable,
|
||||||
|
// TODO: zzzz;
|
||||||
on_collection_new,
|
on_collection_new,
|
||||||
g_object_ref (res),
|
g_object_ref (res),
|
||||||
"g-flags", G_DBUS_CALL_FLAGS_NONE,
|
"g-flags", G_DBUS_CALL_FLAGS_NONE,
|
||||||
@ -418,6 +464,7 @@ gsecret_collection_new (GSecretService *service,
|
|||||||
"g-connection", g_dbus_proxy_get_connection (proxy),
|
"g-connection", g_dbus_proxy_get_connection (proxy),
|
||||||
"g-object-path", collection_path,
|
"g-object-path", collection_path,
|
||||||
"g-interface-name", GSECRET_COLLECTION_INTERFACE,
|
"g-interface-name", GSECRET_COLLECTION_INTERFACE,
|
||||||
|
"service", service,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
g_object_unref (res);
|
g_object_unref (res);
|
||||||
@ -427,18 +474,19 @@ GSecretCollection *
|
|||||||
gsecret_collection_new_finish (GAsyncResult *result,
|
gsecret_collection_new_finish (GAsyncResult *result,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
GObject *object;
|
GSimpleAsyncResult *res;
|
||||||
GObject *source_object;
|
LoadClosure *closure;
|
||||||
|
|
||||||
source_object = g_async_result_get_source_object (result);
|
g_return_val_if_fail (g_simple_async_result_is_valid (result, NULL, load_result_new), NULL);
|
||||||
object = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object),
|
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
||||||
result, error);
|
|
||||||
g_object_unref (source_object);
|
|
||||||
|
|
||||||
if (object != NULL)
|
res = G_SIMPLE_ASYNC_RESULT (result);
|
||||||
return GSECRET_COLLECTION (object);
|
|
||||||
else
|
if (g_simple_async_result_propagate_error (res, error))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
closure = g_simple_async_result_get_op_res_gpointer (res);
|
||||||
|
return g_object_ref (closure->collection);
|
||||||
}
|
}
|
||||||
|
|
||||||
GSecretCollection *
|
GSecretCollection *
|
||||||
@ -458,6 +506,7 @@ gsecret_collection_new_sync (GSecretService *service,
|
|||||||
sync = _gsecret_sync_new ();
|
sync = _gsecret_sync_new ();
|
||||||
g_main_context_push_thread_default (sync->context);
|
g_main_context_push_thread_default (sync->context);
|
||||||
|
|
||||||
|
// TODO: xxxxx;
|
||||||
gsecret_collection_new (service, collection_path, cancellable,
|
gsecret_collection_new (service, collection_path, cancellable,
|
||||||
_gsecret_sync_on_result, sync);
|
_gsecret_sync_on_result, sync);
|
||||||
|
|
||||||
@ -590,7 +639,7 @@ gsecret_collection_set_label (GSecretCollection *self,
|
|||||||
GAsyncReadyCallback callback,
|
GAsyncReadyCallback callback,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
g_return_if_fail (GSECRET_IS_ITEM (self));
|
g_return_if_fail (GSECRET_IS_COLLECTION (self));
|
||||||
g_return_if_fail (label != NULL);
|
g_return_if_fail (label != NULL);
|
||||||
|
|
||||||
_gsecret_util_set_property (G_DBUS_PROXY (self), "Label",
|
_gsecret_util_set_property (G_DBUS_PROXY (self), "Label",
|
||||||
@ -604,7 +653,7 @@ gsecret_collection_set_label_finish (GSecretCollection *self,
|
|||||||
GAsyncResult *result,
|
GAsyncResult *result,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
g_return_val_if_fail (GSECRET_IS_ITEM (self), FALSE);
|
g_return_val_if_fail (GSECRET_IS_COLLECTION (self), FALSE);
|
||||||
|
|
||||||
return _gsecret_util_set_property_finish (G_DBUS_PROXY (self),
|
return _gsecret_util_set_property_finish (G_DBUS_PROXY (self),
|
||||||
gsecret_collection_set_label,
|
gsecret_collection_set_label,
|
||||||
@ -617,7 +666,7 @@ gsecret_collection_set_label_sync (GSecretCollection *self,
|
|||||||
GCancellable *cancellable,
|
GCancellable *cancellable,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
g_return_val_if_fail (GSECRET_IS_ITEM (self), FALSE);
|
g_return_val_if_fail (GSECRET_IS_COLLECTION (self), FALSE);
|
||||||
g_return_val_if_fail (label != NULL, FALSE);
|
g_return_val_if_fail (label != NULL, FALSE);
|
||||||
|
|
||||||
return _gsecret_util_set_property_sync (G_DBUS_PROXY (self), "Label",
|
return _gsecret_util_set_property_sync (G_DBUS_PROXY (self), "Label",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/* GSecret - GLib wrapper for Secret Service
|
/* GSecret - GLib wrapper for Secret Service
|
||||||
*
|
*
|
||||||
* Copyright 2011 Collabora Ltd.
|
* Copyright 2012 Red Hat Inc.
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU Lesser General Public License as published
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/* GSecret - GLib wrapper for Secret Service
|
/* GSecret - GLib wrapper for Secret Service
|
||||||
*
|
*
|
||||||
* Copyright 2011 Collabora Ltd.
|
* Copyright 2012 Red Hat Inc.
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU Lesser General Public License as published
|
||||||
@ -23,6 +23,7 @@
|
|||||||
|
|
||||||
enum {
|
enum {
|
||||||
PROP_0,
|
PROP_0,
|
||||||
|
PROP_SERVICE,
|
||||||
PROP_ATTRIBUTES,
|
PROP_ATTRIBUTES,
|
||||||
PROP_LABEL,
|
PROP_LABEL,
|
||||||
PROP_LOCKED,
|
PROP_LOCKED,
|
||||||
@ -38,17 +39,11 @@ typedef struct _GSecretItemPrivate {
|
|||||||
|
|
||||||
G_DEFINE_TYPE (GSecretItem, gsecret_item, G_TYPE_DBUS_PROXY);
|
G_DEFINE_TYPE (GSecretItem, gsecret_item, G_TYPE_DBUS_PROXY);
|
||||||
|
|
||||||
static GSecretItemPrivate *
|
|
||||||
gsecret_item_private_get (GSecretItem *self)
|
|
||||||
{
|
|
||||||
return G_TYPE_INSTANCE_GET_PRIVATE (self, GSECRET_TYPE_ITEM, GSecretItemPrivate);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gsecret_item_init (GSecretItem *self)
|
gsecret_item_init (GSecretItem *self)
|
||||||
{
|
{
|
||||||
GSecretItemPrivate *pv = gsecret_item_private_get (self);
|
self->pv = G_TYPE_INSTANCE_GET_PRIVATE (self, GSECRET_TYPE_ITEM, GSecretItemPrivate);
|
||||||
pv->cancellable = g_cancellable_new ();
|
self->pv->cancellable = g_cancellable_new ();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -92,17 +87,23 @@ gsecret_item_set_property (GObject *obj,
|
|||||||
GParamSpec *pspec)
|
GParamSpec *pspec)
|
||||||
{
|
{
|
||||||
GSecretItem *self = GSECRET_ITEM (obj);
|
GSecretItem *self = GSECRET_ITEM (obj);
|
||||||
GSecretItemPrivate *pv = gsecret_item_private_get (self);
|
|
||||||
|
|
||||||
switch (prop_id) {
|
switch (prop_id) {
|
||||||
|
case PROP_SERVICE:
|
||||||
|
g_return_if_fail (self->pv->service == NULL);
|
||||||
|
self->pv->service = g_value_get_object (value);
|
||||||
|
if (self->pv->service)
|
||||||
|
g_object_add_weak_pointer (G_OBJECT (self->pv->service),
|
||||||
|
(gpointer *)&self->pv->service);
|
||||||
|
break;
|
||||||
case PROP_ATTRIBUTES:
|
case PROP_ATTRIBUTES:
|
||||||
gsecret_item_set_attributes (self, g_value_get_boxed (value),
|
gsecret_item_set_attributes (self, g_value_get_boxed (value),
|
||||||
pv->cancellable, on_set_attributes,
|
self->pv->cancellable, on_set_attributes,
|
||||||
g_object_ref (self));
|
g_object_ref (self));
|
||||||
break;
|
break;
|
||||||
case PROP_LABEL:
|
case PROP_LABEL:
|
||||||
gsecret_item_set_label (self, g_value_get_string (value),
|
gsecret_item_set_label (self, g_value_get_string (value),
|
||||||
pv->cancellable, on_set_label,
|
self->pv->cancellable, on_set_label,
|
||||||
g_object_ref (self));
|
g_object_ref (self));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -120,6 +121,9 @@ gsecret_item_get_property (GObject *obj,
|
|||||||
GSecretItem *self = GSECRET_ITEM (obj);
|
GSecretItem *self = GSECRET_ITEM (obj);
|
||||||
|
|
||||||
switch (prop_id) {
|
switch (prop_id) {
|
||||||
|
case PROP_SERVICE:
|
||||||
|
g_value_set_object (value, self->pv->service);
|
||||||
|
break;
|
||||||
case PROP_ATTRIBUTES:
|
case PROP_ATTRIBUTES:
|
||||||
g_value_take_boxed (value, gsecret_item_get_attributes (self));
|
g_value_take_boxed (value, gsecret_item_get_attributes (self));
|
||||||
break;
|
break;
|
||||||
@ -145,23 +149,24 @@ static void
|
|||||||
gsecret_item_dispose (GObject *obj)
|
gsecret_item_dispose (GObject *obj)
|
||||||
{
|
{
|
||||||
GSecretItem *self = GSECRET_ITEM (obj);
|
GSecretItem *self = GSECRET_ITEM (obj);
|
||||||
GSecretItemPrivate *pv = gsecret_item_private_get (self);
|
|
||||||
|
|
||||||
g_clear_object (&pv->service);
|
g_cancellable_cancel (self->pv->cancellable);
|
||||||
g_cancellable_cancel (pv->cancellable);
|
|
||||||
|
|
||||||
G_OBJECT_GET_CLASS (obj)->dispose (obj);
|
G_OBJECT_CLASS (gsecret_item_parent_class)->dispose (obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gsecret_item_finalize (GObject *obj)
|
gsecret_item_finalize (GObject *obj)
|
||||||
{
|
{
|
||||||
GSecretItem *self = GSECRET_ITEM (obj);
|
GSecretItem *self = GSECRET_ITEM (obj);
|
||||||
GSecretItemPrivate *pv = gsecret_item_private_get (self);
|
|
||||||
|
|
||||||
g_clear_object (&pv->cancellable);
|
if (self->pv->service)
|
||||||
|
g_object_remove_weak_pointer (G_OBJECT (self->pv->service),
|
||||||
|
(gpointer *)&self->pv->service);
|
||||||
|
|
||||||
G_OBJECT_GET_CLASS (obj)->finalize (obj);
|
g_object_unref (self->pv->cancellable);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (gsecret_item_parent_class)->finalize (obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -216,27 +221,48 @@ gsecret_item_class_init (GSecretItemClass *klass)
|
|||||||
|
|
||||||
proxy_class->g_properties_changed = gsecret_item_properties_changed;
|
proxy_class->g_properties_changed = gsecret_item_properties_changed;
|
||||||
|
|
||||||
|
g_object_class_install_property (gobject_class, PROP_SERVICE,
|
||||||
|
g_param_spec_object ("service", "Service", "Secret Service",
|
||||||
|
GSECRET_TYPE_SERVICE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
g_object_class_install_property (gobject_class, PROP_ATTRIBUTES,
|
g_object_class_install_property (gobject_class, PROP_ATTRIBUTES,
|
||||||
g_param_spec_boxed ("attributes", "Attributes", "Item attributes",
|
g_param_spec_boxed ("attributes", "Attributes", "Item attributes",
|
||||||
G_TYPE_HASH_TABLE, G_PARAM_READWRITE));
|
G_TYPE_HASH_TABLE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
g_object_class_install_property (gobject_class, PROP_LABEL,
|
g_object_class_install_property (gobject_class, PROP_LABEL,
|
||||||
g_param_spec_string ("label", "Label", "Item label",
|
g_param_spec_string ("label", "Label", "Item label",
|
||||||
NULL, G_PARAM_READWRITE));
|
NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
g_object_class_install_property (gobject_class, PROP_LOCKED,
|
g_object_class_install_property (gobject_class, PROP_LOCKED,
|
||||||
g_param_spec_boolean ("locked", "Locked", "Item locked",
|
g_param_spec_boolean ("locked", "Locked", "Item locked",
|
||||||
TRUE, G_PARAM_READABLE));
|
TRUE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
g_object_class_install_property (gobject_class, PROP_CREATED,
|
g_object_class_install_property (gobject_class, PROP_CREATED,
|
||||||
g_param_spec_uint64 ("created", "Created", "Item creation date",
|
g_param_spec_uint64 ("created", "Created", "Item creation date",
|
||||||
0UL, G_MAXUINT64, 0UL, G_PARAM_READWRITE));
|
0UL, G_MAXUINT64, 0UL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
g_object_class_install_property (gobject_class, PROP_MODIFIED,
|
g_object_class_install_property (gobject_class, PROP_MODIFIED,
|
||||||
g_param_spec_uint64 ("modified", "Modified", "Item modified date",
|
g_param_spec_uint64 ("modified", "Modified", "Item modified date",
|
||||||
0UL, G_MAXUINT64, 0UL, G_PARAM_READWRITE));
|
0UL, G_MAXUINT64, 0UL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
|
g_type_class_add_private (gobject_class, sizeof (GSecretItemPrivate));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
static void
|
||||||
|
all_properties_changed (GSecretItem *item)
|
||||||
|
{
|
||||||
|
GObject *obj = G_OBJECT (item);
|
||||||
|
gchar **property_names;
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
property_names = g_dbus_proxy_get_cached_property_names (G_DBUS_PROXY (item));
|
||||||
|
for (i = 0; property_names != NULL && property_names[i] != NULL; i++)
|
||||||
|
handle_property_changed (obj, property_names[i]);
|
||||||
|
g_strfreev (property_names);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void
|
void
|
||||||
gsecret_item_new (GSecretService *service,
|
gsecret_item_new (GSecretService *service,
|
||||||
const gchar *item_path,
|
const gchar *item_path,
|
||||||
@ -263,6 +289,7 @@ gsecret_item_new (GSecretService *service,
|
|||||||
"g-connection", g_dbus_proxy_get_connection (proxy),
|
"g-connection", g_dbus_proxy_get_connection (proxy),
|
||||||
"g-object-path", item_path,
|
"g-object-path", item_path,
|
||||||
"g-interface-name", GSECRET_ITEM_INTERFACE,
|
"g-interface-name", GSECRET_ITEM_INTERFACE,
|
||||||
|
"service", service,
|
||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -272,16 +299,25 @@ gsecret_item_new_finish (GAsyncResult *result,
|
|||||||
{
|
{
|
||||||
GObject *object;
|
GObject *object;
|
||||||
GObject *source_object;
|
GObject *source_object;
|
||||||
|
GDBusProxy *proxy;
|
||||||
|
|
||||||
source_object = g_async_result_get_source_object (result);
|
source_object = g_async_result_get_source_object (result);
|
||||||
object = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object),
|
object = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object),
|
||||||
result, error);
|
result, error);
|
||||||
g_object_unref (source_object);
|
g_object_unref (source_object);
|
||||||
|
|
||||||
if (object != NULL)
|
if (object == NULL)
|
||||||
return GSECRET_ITEM (object);
|
|
||||||
else
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
proxy = G_DBUS_PROXY (object);
|
||||||
|
if (!_gsecret_util_have_cached_properties (proxy)) {
|
||||||
|
g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD,
|
||||||
|
"No such secret item at path: %s", g_dbus_proxy_get_object_path (proxy));
|
||||||
|
g_object_unref (object);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return GSECRET_ITEM (object);
|
||||||
}
|
}
|
||||||
|
|
||||||
GSecretItem *
|
GSecretItem *
|
||||||
@ -290,30 +326,29 @@ gsecret_item_new_sync (GSecretService *service,
|
|||||||
GCancellable *cancellable,
|
GCancellable *cancellable,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
GInitable *initable;
|
GSecretSync *sync;
|
||||||
GDBusProxy *proxy;
|
GSecretItem *item;
|
||||||
|
|
||||||
proxy = G_DBUS_PROXY (service);
|
|
||||||
|
|
||||||
g_return_val_if_fail (GSECRET_IS_SERVICE (service), NULL);
|
g_return_val_if_fail (GSECRET_IS_SERVICE (service), NULL);
|
||||||
g_return_val_if_fail (item_path != NULL, NULL);
|
g_return_val_if_fail (item_path != NULL, NULL);
|
||||||
|
g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
|
||||||
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
||||||
|
|
||||||
initable = g_initable_new (GSECRET_TYPE_ITEM,
|
sync = _gsecret_sync_new ();
|
||||||
cancellable,
|
g_main_context_push_thread_default (sync->context);
|
||||||
error,
|
|
||||||
"g-flags", G_DBUS_CALL_FLAGS_NONE,
|
|
||||||
"g-interface-info", _gsecret_gen_item_interface_info (),
|
|
||||||
"g-name", g_dbus_proxy_get_name (proxy),
|
|
||||||
"g-connection", g_dbus_proxy_get_connection (proxy),
|
|
||||||
"g-object-path", item_path,
|
|
||||||
"g-interface-name", GSECRET_ITEM_INTERFACE,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
if (initable != NULL)
|
// TODO: xxxxx;
|
||||||
return GSECRET_ITEM (initable);
|
gsecret_item_new (service, item_path, cancellable,
|
||||||
else
|
_gsecret_sync_on_result, sync);
|
||||||
return NULL;
|
|
||||||
|
g_main_loop_run (sync->loop);
|
||||||
|
|
||||||
|
item = gsecret_item_new_finish (sync->result, error);
|
||||||
|
|
||||||
|
g_main_context_pop_thread_default (sync->context);
|
||||||
|
_gsecret_sync_free (sync);
|
||||||
|
|
||||||
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -335,8 +370,10 @@ on_item_deleted (GObject *source,
|
|||||||
GSecretItem *self = GSECRET_ITEM (g_async_result_get_source_object (user_data));
|
GSecretItem *self = GSECRET_ITEM (g_async_result_get_source_object (user_data));
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
|
|
||||||
if (gsecret_service_delete_path_finish (GSECRET_SERVICE (source), result, &error))
|
if (gsecret_service_delete_path_finish (GSECRET_SERVICE (source), result, &error)) {
|
||||||
|
g_simple_async_result_set_op_res_gboolean (res, TRUE);
|
||||||
g_object_run_dispose (G_OBJECT (self));
|
g_object_run_dispose (G_OBJECT (self));
|
||||||
|
}
|
||||||
|
|
||||||
if (error != NULL)
|
if (error != NULL)
|
||||||
g_simple_async_result_take_error (res, error);
|
g_simple_async_result_take_error (res, error);
|
||||||
@ -352,19 +389,17 @@ gsecret_item_delete (GSecretItem *self,
|
|||||||
GAsyncReadyCallback callback,
|
GAsyncReadyCallback callback,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
GSecretItemPrivate *pv;
|
|
||||||
GSimpleAsyncResult *res;
|
GSimpleAsyncResult *res;
|
||||||
const gchar *object_path;
|
const gchar *object_path;
|
||||||
|
|
||||||
g_return_if_fail (GSECRET_IS_ITEM (self));
|
g_return_if_fail (GSECRET_IS_ITEM (self));
|
||||||
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
|
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
|
||||||
|
|
||||||
pv = gsecret_item_private_get (self);
|
|
||||||
object_path = g_dbus_proxy_get_object_path (G_DBUS_PROXY (self));
|
object_path = g_dbus_proxy_get_object_path (G_DBUS_PROXY (self));
|
||||||
res = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
|
res = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
|
||||||
gsecret_item_delete);
|
gsecret_item_delete);
|
||||||
|
|
||||||
gsecret_service_delete_path (pv->service, object_path, cancellable,
|
gsecret_service_delete_path (self->pv->service, object_path, cancellable,
|
||||||
on_item_deleted, g_object_ref (res));
|
on_item_deleted, g_object_ref (res));
|
||||||
|
|
||||||
g_object_unref (res);
|
g_object_unref (res);
|
||||||
@ -375,13 +410,19 @@ gsecret_item_delete_finish (GSecretItem *self,
|
|||||||
GAsyncResult *result,
|
GAsyncResult *result,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
GSecretItemPrivate *pv;
|
GSimpleAsyncResult *res;
|
||||||
|
|
||||||
g_return_val_if_fail (GSECRET_IS_ITEM (self), FALSE);
|
g_return_val_if_fail (GSECRET_IS_ITEM (self), FALSE);
|
||||||
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
||||||
|
g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self),
|
||||||
|
gsecret_item_delete), FALSE);
|
||||||
|
|
||||||
pv = gsecret_item_private_get (self);
|
res = G_SIMPLE_ASYNC_RESULT (result);
|
||||||
return gsecret_service_delete_path_finish (pv->service, result, error);
|
|
||||||
|
if (g_simple_async_result_propagate_error (res, error))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
return g_simple_async_result_get_op_res_gboolean (res);
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
@ -411,31 +452,47 @@ gsecret_item_delete_sync (GSecretItem *self,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
GCancellable *cancellable;
|
||||||
|
GSecretValue *value;
|
||||||
|
} GetClosure;
|
||||||
|
|
||||||
|
static void
|
||||||
|
get_closure_free (gpointer data)
|
||||||
|
{
|
||||||
|
GetClosure *closure = data;
|
||||||
|
g_clear_object (&closure->cancellable);
|
||||||
|
gsecret_value_unref (closure->value);
|
||||||
|
g_slice_free (GetClosure, closure);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
on_item_get_secret_ready (GObject *source, GAsyncResult *result, gpointer user_data)
|
on_item_get_secret_ready (GObject *source, GAsyncResult *result, gpointer user_data)
|
||||||
{
|
{
|
||||||
GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
|
GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
|
||||||
GSecretItem *self = GSECRET_ITEM (g_async_result_get_source_object (user_data));
|
GSecretItem *self = GSECRET_ITEM (g_async_result_get_source_object (user_data));
|
||||||
GSecretItemPrivate *pv = gsecret_item_private_get (self);
|
GetClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
|
||||||
|
GSecretSession *session;
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
GSecretValue *value;
|
GVariant *retval;
|
||||||
GVariant *ret;
|
GVariant *child;
|
||||||
|
|
||||||
ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (source), result, &error);
|
retval = g_dbus_proxy_call_finish (G_DBUS_PROXY (source), result, &error);
|
||||||
if (error == NULL) {
|
if (error == NULL) {
|
||||||
value = _gsecret_service_decode_secret (pv->service, ret);
|
child = g_variant_get_child_value (retval, 0);
|
||||||
if (value == NULL) {
|
g_variant_unref (retval);
|
||||||
|
|
||||||
|
session = _gsecret_service_get_session (self->pv->service);
|
||||||
|
closure->value = _gsecret_session_decode_secret (session, child);
|
||||||
|
g_variant_unref (child);
|
||||||
|
|
||||||
|
if (closure->value == NULL)
|
||||||
g_set_error (&error, GSECRET_ERROR, GSECRET_ERROR_PROTOCOL,
|
g_set_error (&error, GSECRET_ERROR, GSECRET_ERROR_PROTOCOL,
|
||||||
_("Received invalid secret from the secret storage"));
|
_("Received invalid secret from the secret storage"));
|
||||||
}
|
|
||||||
g_object_unref (ret);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (error != NULL)
|
if (error != NULL)
|
||||||
g_simple_async_result_take_error (res, error);
|
g_simple_async_result_take_error (res, error);
|
||||||
else
|
|
||||||
g_simple_async_result_set_op_res_gpointer (res, value,
|
|
||||||
gsecret_value_unref);
|
|
||||||
|
|
||||||
g_simple_async_result_complete (res);
|
g_simple_async_result_complete (res);
|
||||||
g_object_unref (res);
|
g_object_unref (res);
|
||||||
@ -446,13 +503,11 @@ on_service_ensure_session (GObject *source, GAsyncResult *result, gpointer user_
|
|||||||
{
|
{
|
||||||
GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
|
GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
|
||||||
GSecretItem *self = GSECRET_ITEM (g_async_result_get_source_object (user_data));
|
GSecretItem *self = GSECRET_ITEM (g_async_result_get_source_object (user_data));
|
||||||
GSecretItemPrivate *pv = gsecret_item_private_get (self);
|
GetClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
|
||||||
GError *error = NULL;
|
|
||||||
GCancellable *cancellable = NULL;
|
|
||||||
const gchar *session_path;
|
const gchar *session_path;
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
session_path = _gsecret_service_ensure_session_finish (pv->service, result,
|
session_path = gsecret_service_ensure_session_finish (self->pv->service, result, &error);
|
||||||
&cancellable, &error);
|
|
||||||
if (error != NULL) {
|
if (error != NULL) {
|
||||||
g_simple_async_result_take_error (res, error);
|
g_simple_async_result_take_error (res, error);
|
||||||
g_simple_async_result_complete (res);
|
g_simple_async_result_complete (res);
|
||||||
@ -460,31 +515,33 @@ on_service_ensure_session (GObject *source, GAsyncResult *result, gpointer user_
|
|||||||
} else {
|
} else {
|
||||||
g_assert (session_path != NULL && session_path[0] != '\0');
|
g_assert (session_path != NULL && session_path[0] != '\0');
|
||||||
g_dbus_proxy_call (G_DBUS_PROXY (self), "GetSecret",
|
g_dbus_proxy_call (G_DBUS_PROXY (self), "GetSecret",
|
||||||
g_variant_new ("o", session_path),
|
g_variant_new ("(o)", session_path),
|
||||||
G_DBUS_CALL_FLAGS_NONE, -1, cancellable,
|
G_DBUS_CALL_FLAGS_NONE, -1, closure->cancellable,
|
||||||
on_item_get_secret_ready, g_object_ref (res));
|
on_item_get_secret_ready, g_object_ref (res));
|
||||||
}
|
}
|
||||||
|
|
||||||
g_clear_object (&cancellable);
|
|
||||||
g_object_unref (res);
|
g_object_unref (res);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
gsecret_item_get_secret (GSecretItem *self, GCancellable *cancellable,
|
gsecret_item_get_secret (GSecretItem *self,
|
||||||
GAsyncReadyCallback callback, gpointer user_data)
|
GCancellable *cancellable,
|
||||||
|
GAsyncReadyCallback callback,
|
||||||
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
GSimpleAsyncResult *res;
|
GSimpleAsyncResult *res;
|
||||||
GSecretItemPrivate *pv;
|
GetClosure *closure;
|
||||||
|
|
||||||
|
|
||||||
g_return_if_fail (GSECRET_IS_ITEM (self));
|
g_return_if_fail (GSECRET_IS_ITEM (self));
|
||||||
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
|
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
|
||||||
|
|
||||||
res = g_simple_async_result_new (G_OBJECT (self), callback,
|
res = g_simple_async_result_new (G_OBJECT (self), callback,
|
||||||
user_data, gsecret_item_get_secret);
|
user_data, gsecret_item_get_secret);
|
||||||
|
closure = g_slice_new0 (GetClosure);
|
||||||
|
closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
|
||||||
|
g_simple_async_result_set_op_res_gpointer (res, closure, get_closure_free);
|
||||||
|
|
||||||
pv = gsecret_item_private_get (self);
|
gsecret_service_ensure_session (self->pv->service, cancellable,
|
||||||
gsecret_service_ensure_session (pv->service, cancellable,
|
|
||||||
on_service_ensure_session,
|
on_service_ensure_session,
|
||||||
g_object_ref (res));
|
g_object_ref (res));
|
||||||
|
|
||||||
@ -492,10 +549,12 @@ gsecret_item_get_secret (GSecretItem *self, GCancellable *cancellable,
|
|||||||
}
|
}
|
||||||
|
|
||||||
GSecretValue*
|
GSecretValue*
|
||||||
gsecret_item_get_secret_finish (GSecretItem *self, GAsyncResult *result,
|
gsecret_item_get_secret_finish (GSecretItem *self,
|
||||||
|
GAsyncResult *result,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
GSimpleAsyncResult *res;
|
GSimpleAsyncResult *res;
|
||||||
|
GetClosure *closure;
|
||||||
|
|
||||||
g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self),
|
g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self),
|
||||||
gsecret_item_get_secret), NULL);
|
gsecret_item_get_secret), NULL);
|
||||||
@ -504,7 +563,8 @@ gsecret_item_get_secret_finish (GSecretItem *self, GAsyncResult *result,
|
|||||||
if (g_simple_async_result_propagate_error (res, error))
|
if (g_simple_async_result_propagate_error (res, error))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
return gsecret_value_ref (g_simple_async_result_get_op_res_gpointer (res));
|
closure = g_simple_async_result_get_op_res_gpointer (res);
|
||||||
|
return closure->value ? gsecret_value_ref (closure->value) : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
GSecretValue*
|
GSecretValue*
|
||||||
@ -558,18 +618,13 @@ gsecret_item_set_attributes (GSecretItem *self,
|
|||||||
GAsyncReadyCallback callback,
|
GAsyncReadyCallback callback,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
GVariant *variant;
|
|
||||||
|
|
||||||
g_return_if_fail (GSECRET_IS_ITEM (self));
|
g_return_if_fail (GSECRET_IS_ITEM (self));
|
||||||
g_return_if_fail (attributes != NULL);
|
g_return_if_fail (attributes != NULL);
|
||||||
|
|
||||||
variant = _gsecret_util_variant_for_attributes (attributes);
|
_gsecret_util_set_property (G_DBUS_PROXY (self), "Attributes",
|
||||||
|
_gsecret_util_variant_for_attributes (attributes),
|
||||||
_gsecret_util_set_property (G_DBUS_PROXY (self), "Attributes", variant,
|
|
||||||
gsecret_item_set_attributes, cancellable,
|
gsecret_item_set_attributes, cancellable,
|
||||||
callback, user_data);
|
callback, user_data);
|
||||||
|
|
||||||
g_variant_unref (variant);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
@ -590,20 +645,12 @@ gsecret_item_set_attributes_sync (GSecretItem *self,
|
|||||||
GCancellable *cancellable,
|
GCancellable *cancellable,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
GVariant *variant;
|
|
||||||
gboolean ret;
|
|
||||||
|
|
||||||
g_return_val_if_fail (GSECRET_IS_ITEM (self), FALSE);
|
g_return_val_if_fail (GSECRET_IS_ITEM (self), FALSE);
|
||||||
g_return_val_if_fail (attributes != NULL, FALSE);
|
g_return_val_if_fail (attributes != NULL, FALSE);
|
||||||
|
|
||||||
variant = _gsecret_util_variant_for_attributes (attributes);
|
return _gsecret_util_set_property_sync (G_DBUS_PROXY (self), "Attributes",
|
||||||
|
_gsecret_util_variant_for_attributes (attributes),
|
||||||
ret = _gsecret_util_set_property_sync (G_DBUS_PROXY (self), "Attributes",
|
cancellable, error);
|
||||||
variant, cancellable, error);
|
|
||||||
|
|
||||||
g_variant_unref (variant);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
gchar *
|
gchar *
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/* GSecret - GLib wrapper for Secret Service
|
/* GSecret - GLib wrapper for Secret Service
|
||||||
*
|
*
|
||||||
* Copyright 2011 Collabora Ltd.
|
* Copyright 2012 Red Hat Inc.
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU Lesser General Public License as published
|
||||||
@ -29,10 +29,11 @@ G_BEGIN_DECLS
|
|||||||
#define GSECRET_ITEM_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), GSECRET_TYPE_ITEM, GSecretItemClass))
|
#define GSECRET_ITEM_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), GSECRET_TYPE_ITEM, GSecretItemClass))
|
||||||
|
|
||||||
typedef struct _GSecretItemClass GSecretItemClass;
|
typedef struct _GSecretItemClass GSecretItemClass;
|
||||||
|
typedef struct _GSecretItemPrivate GSecretItemPrivate;
|
||||||
|
|
||||||
struct _GSecretItem {
|
struct _GSecretItem {
|
||||||
GDBusProxy parent_instance;
|
GDBusProxy parent_instance;
|
||||||
gpointer padding;
|
GSecretItemPrivate *pv;;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GSecretItemClass {
|
struct _GSecretItemClass {
|
||||||
|
@ -26,6 +26,8 @@ typedef struct {
|
|||||||
GMainLoop *loop;
|
GMainLoop *loop;
|
||||||
} GSecretSync;
|
} GSecretSync;
|
||||||
|
|
||||||
|
typedef struct _GSecretSession GSecretSession;
|
||||||
|
|
||||||
#define GSECRET_SERVICE_PATH "/org/freedesktop/secrets"
|
#define GSECRET_SERVICE_PATH "/org/freedesktop/secrets"
|
||||||
|
|
||||||
#define GSECRET_SERVICE_BUS_NAME "org.freedesktop.Secret.Service"
|
#define GSECRET_SERVICE_BUS_NAME "org.freedesktop.Secret.Service"
|
||||||
@ -93,6 +95,8 @@ gboolean _gsecret_util_set_property_sync (GDBusProxy *prox
|
|||||||
GCancellable *cancellable,
|
GCancellable *cancellable,
|
||||||
GError **error);
|
GError **error);
|
||||||
|
|
||||||
|
gboolean _gsecret_util_have_cached_properties (GDBusProxy *proxy);
|
||||||
|
|
||||||
void _gsecret_service_set_default_bus_name (const gchar *bus_name);
|
void _gsecret_service_set_default_bus_name (const gchar *bus_name);
|
||||||
|
|
||||||
GSecretService * _gsecret_service_bare_instance (GDBusConnection *connection,
|
GSecretService * _gsecret_service_bare_instance (GDBusConnection *connection,
|
||||||
@ -107,16 +111,10 @@ void _gsecret_service_bare_connect (const gchar *bus
|
|||||||
GSecretService * _gsecret_service_bare_connect_finish (GAsyncResult *result,
|
GSecretService * _gsecret_service_bare_connect_finish (GAsyncResult *result,
|
||||||
GError **error);
|
GError **error);
|
||||||
|
|
||||||
GVariant * _gsecret_service_encode_secret (GSecretService *self,
|
GSecretSession * _gsecret_service_get_session (GSecretService *self);
|
||||||
GSecretValue *value);
|
|
||||||
|
|
||||||
GSecretValue * _gsecret_service_decode_secret (GSecretService *service,
|
void _gsecret_service_take_session (GSecretService *self,
|
||||||
GVariant *encoded);
|
GSecretSession *session);
|
||||||
|
|
||||||
const gchar * _gsecret_service_ensure_session_finish (GSecretService *self,
|
|
||||||
GAsyncResult *result,
|
|
||||||
GCancellable **cancellable,
|
|
||||||
GError **error);
|
|
||||||
|
|
||||||
GSecretItem * _gsecret_service_find_item_instance (GSecretService *self,
|
GSecretItem * _gsecret_service_find_item_instance (GSecretService *self,
|
||||||
const gchar *item_path);
|
const gchar *item_path);
|
||||||
@ -126,6 +124,26 @@ GSecretItem * _gsecret_collection_find_item_instance (GSecretCollectio
|
|||||||
|
|
||||||
gchar * _gsecret_value_unref_to_password (GSecretValue *value);
|
gchar * _gsecret_value_unref_to_password (GSecretValue *value);
|
||||||
|
|
||||||
|
void _gsecret_session_free (gpointer data);
|
||||||
|
|
||||||
|
const gchar * _gsecret_session_get_algorithms (GSecretSession *session);
|
||||||
|
|
||||||
|
const gchar * _gsecret_session_get_path (GSecretSession *session);
|
||||||
|
|
||||||
|
void _gsecret_session_open (GSecretService *service,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GAsyncReadyCallback callback,
|
||||||
|
gpointer user_data);
|
||||||
|
|
||||||
|
GSecretSession * _gsecret_session_open_finish (GAsyncResult *result,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
GVariant * _gsecret_session_encode_secret (GSecretSession *session,
|
||||||
|
GSecretValue *value);
|
||||||
|
|
||||||
|
GSecretValue * _gsecret_session_decode_secret (GSecretSession *session,
|
||||||
|
GVariant *encoded);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __G_SERVICE_H___ */
|
#endif /* __G_SERVICE_H___ */
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
/* GSecret - GLib wrapper for Secret Service
|
/* GSecret - GLib wrapper for Secret Service
|
||||||
*
|
*
|
||||||
* Copyright 2011 Collabora Ltd.
|
* Copyright 2011 Collabora Ltd.
|
||||||
|
* Copyright 2012 Red Hat Inc.
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU Lesser General Public License as published
|
||||||
@ -20,13 +21,6 @@
|
|||||||
#include "gsecret-types.h"
|
#include "gsecret-types.h"
|
||||||
#include "gsecret-value.h"
|
#include "gsecret-value.h"
|
||||||
|
|
||||||
#ifdef WITH_GCRYPT
|
|
||||||
#include "egg/egg-dh.h"
|
|
||||||
#include "egg/egg-hkdf.h"
|
|
||||||
#include "egg/egg-libgcrypt.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "egg/egg-hex.h"
|
|
||||||
#include "egg/egg-secure-memory.h"
|
#include "egg/egg-secure-memory.h"
|
||||||
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
@ -40,21 +34,6 @@ EGG_SECURE_DECLARE (secret_service);
|
|||||||
|
|
||||||
static const gchar *default_bus_name = GSECRET_SERVICE_BUS_NAME;
|
static const gchar *default_bus_name = GSECRET_SERVICE_BUS_NAME;
|
||||||
|
|
||||||
#define ALGORITHMS_AES "dh-ietf1024-sha256-aes128-cbc-pkcs7"
|
|
||||||
#define ALGORITHMS_PLAIN "plain"
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
gchar *path;
|
|
||||||
const gchar *algorithms;
|
|
||||||
#ifdef WITH_GCRYPT
|
|
||||||
gcry_mpi_t prime;
|
|
||||||
gcry_mpi_t privat;
|
|
||||||
gcry_mpi_t publi;
|
|
||||||
#endif
|
|
||||||
gpointer key;
|
|
||||||
gsize n_key;
|
|
||||||
} GSecretSession;
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
PROP_0,
|
PROP_0,
|
||||||
PROP_COLLECTIONS
|
PROP_COLLECTIONS
|
||||||
@ -75,24 +54,6 @@ static gpointer service_instance = NULL;
|
|||||||
|
|
||||||
G_DEFINE_TYPE (GSecretService, gsecret_service, G_TYPE_DBUS_PROXY);
|
G_DEFINE_TYPE (GSecretService, gsecret_service, G_TYPE_DBUS_PROXY);
|
||||||
|
|
||||||
static void
|
|
||||||
gsecret_session_free (gpointer data)
|
|
||||||
{
|
|
||||||
GSecretSession *session = data;
|
|
||||||
|
|
||||||
if (session == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
g_free (session->path);
|
|
||||||
#ifdef WITH_GCRYPT
|
|
||||||
gcry_mpi_release (session->publi);
|
|
||||||
gcry_mpi_release (session->privat);
|
|
||||||
gcry_mpi_release (session->prime);
|
|
||||||
#endif
|
|
||||||
egg_secure_free (session->key);
|
|
||||||
g_free (session);
|
|
||||||
}
|
|
||||||
|
|
||||||
static GHashTable *
|
static GHashTable *
|
||||||
collections_table_new (void)
|
collections_table_new (void)
|
||||||
{
|
{
|
||||||
@ -144,7 +105,7 @@ gsecret_service_finalize (GObject *obj)
|
|||||||
{
|
{
|
||||||
GSecretService *self = GSECRET_SERVICE (obj);
|
GSecretService *self = GSECRET_SERVICE (obj);
|
||||||
|
|
||||||
gsecret_session_free (self->pv->session);
|
_gsecret_session_free (self->pv->session);
|
||||||
g_hash_table_destroy (self->pv->collections);
|
g_hash_table_destroy (self->pv->collections);
|
||||||
g_clear_object (&self->pv->cancellable);
|
g_clear_object (&self->pv->cancellable);
|
||||||
|
|
||||||
@ -315,6 +276,7 @@ load_collections_perform (GSecretService *self,
|
|||||||
g_mutex_unlock (&self->pv->mutex);
|
g_mutex_unlock (&self->pv->mutex);
|
||||||
|
|
||||||
if (collection == NULL) {
|
if (collection == NULL) {
|
||||||
|
// TODO: xxxxx;
|
||||||
gsecret_collection_new (self, collection_path, closure->cancellable,
|
gsecret_collection_new (self, collection_path, closure->cancellable,
|
||||||
on_collection_loading, g_object_ref (res));
|
on_collection_loading, g_object_ref (res));
|
||||||
closure->collections_loading++;
|
closure->collections_loading++;
|
||||||
@ -349,6 +311,7 @@ handle_property_changed (GSecretService *self,
|
|||||||
g_warning ("couldn't retrieve Service Collections property");
|
g_warning ("couldn't retrieve Service Collections property");
|
||||||
g_simple_async_result_complete (res);
|
g_simple_async_result_complete (res);
|
||||||
} else {
|
} else {
|
||||||
|
// TODO: yyyy;
|
||||||
load_collections_perform (self, res, value);
|
load_collections_perform (self, res, value);
|
||||||
g_variant_unref (value);
|
g_variant_unref (value);
|
||||||
}
|
}
|
||||||
@ -392,6 +355,9 @@ gsecret_service_class_init (GSecretServiceClass *klass)
|
|||||||
klass->prompt_async = gsecret_service_real_prompt_async;
|
klass->prompt_async = gsecret_service_real_prompt_async;
|
||||||
klass->prompt_finish = gsecret_service_real_prompt_finish;
|
klass->prompt_finish = gsecret_service_real_prompt_finish;
|
||||||
|
|
||||||
|
klass->item_gtype = GSECRET_TYPE_ITEM;
|
||||||
|
klass->collection_gtype = GSECRET_TYPE_COLLECTION;
|
||||||
|
|
||||||
g_type_class_add_private (klass, sizeof (GSecretServicePrivate));
|
g_type_class_add_private (klass, sizeof (GSecretServicePrivate));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -744,6 +710,35 @@ _gsecret_service_find_item_instance (GSecretService *self,
|
|||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GSecretSession *
|
||||||
|
_gsecret_service_get_session (GSecretService *self)
|
||||||
|
{
|
||||||
|
GSecretSession *session;
|
||||||
|
|
||||||
|
g_return_val_if_fail (GSECRET_IS_SERVICE (self), NULL);
|
||||||
|
|
||||||
|
g_mutex_lock (&self->pv->mutex);
|
||||||
|
session = self->pv->session;
|
||||||
|
g_mutex_lock (&self->pv->mutex);
|
||||||
|
|
||||||
|
return session;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_gsecret_service_take_session (GSecretService *self,
|
||||||
|
GSecretSession *session)
|
||||||
|
{
|
||||||
|
g_return_if_fail (GSECRET_IS_SERVICE (self));
|
||||||
|
g_return_if_fail (session != NULL);
|
||||||
|
|
||||||
|
g_mutex_lock (&self->pv->mutex);
|
||||||
|
if (self->pv->session == NULL)
|
||||||
|
self->pv->session = session;
|
||||||
|
else
|
||||||
|
_gsecret_session_free (session);
|
||||||
|
g_mutex_unlock (&self->pv->mutex);
|
||||||
|
}
|
||||||
|
|
||||||
const gchar *
|
const gchar *
|
||||||
gsecret_service_get_session_algorithms (GSecretService *self)
|
gsecret_service_get_session_algorithms (GSecretService *self)
|
||||||
{
|
{
|
||||||
@ -754,7 +749,7 @@ gsecret_service_get_session_algorithms (GSecretService *self)
|
|||||||
|
|
||||||
g_mutex_lock (&self->pv->mutex);
|
g_mutex_lock (&self->pv->mutex);
|
||||||
session = self->pv->session;
|
session = self->pv->session;
|
||||||
algorithms = session ? session->algorithms : NULL;
|
algorithms = session ? _gsecret_session_get_algorithms (session) : NULL;
|
||||||
g_mutex_unlock (&self->pv->mutex);
|
g_mutex_unlock (&self->pv->mutex);
|
||||||
|
|
||||||
/* Session never changes once established, so can return const */
|
/* Session never changes once established, so can return const */
|
||||||
@ -771,266 +766,13 @@ gsecret_service_get_session_path (GSecretService *self)
|
|||||||
|
|
||||||
g_mutex_lock (&self->pv->mutex);
|
g_mutex_lock (&self->pv->mutex);
|
||||||
session = self->pv->session;
|
session = self->pv->session;
|
||||||
path = session ? session->path : NULL;
|
path = session ? _gsecret_session_get_path (session) : NULL;
|
||||||
g_mutex_unlock (&self->pv->mutex);
|
g_mutex_unlock (&self->pv->mutex);
|
||||||
|
|
||||||
/* Session never changes once established, so can return const */
|
/* Session never changes once established, so can return const */
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WITH_GCRYPT
|
|
||||||
|
|
||||||
static GVariant *
|
|
||||||
request_open_session_aes (GSecretSession *session)
|
|
||||||
{
|
|
||||||
gcry_error_t gcry;
|
|
||||||
gcry_mpi_t base;
|
|
||||||
unsigned char *buffer;
|
|
||||||
size_t n_buffer;
|
|
||||||
GVariant *argument;
|
|
||||||
|
|
||||||
g_assert (session->prime == NULL);
|
|
||||||
g_assert (session->privat == NULL);
|
|
||||||
g_assert (session->publi == NULL);
|
|
||||||
|
|
||||||
/* Initialize our local parameters and values */
|
|
||||||
if (!egg_dh_default_params ("ietf-ike-grp-modp-1536",
|
|
||||||
&session->prime, &base))
|
|
||||||
g_return_val_if_reached (NULL);
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
g_printerr ("\n lib prime: ");
|
|
||||||
gcry_mpi_dump (session->prime);
|
|
||||||
g_printerr ("\n lib base: ");
|
|
||||||
gcry_mpi_dump (base);
|
|
||||||
g_printerr ("\n");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!egg_dh_gen_pair (session->prime, base, 0,
|
|
||||||
&session->publi, &session->privat))
|
|
||||||
g_return_val_if_reached (NULL);
|
|
||||||
gcry_mpi_release (base);
|
|
||||||
|
|
||||||
gcry = gcry_mpi_aprint (GCRYMPI_FMT_USG, &buffer, &n_buffer, session->publi);
|
|
||||||
g_return_val_if_fail (gcry == 0, NULL);
|
|
||||||
argument = g_variant_new_from_data (G_VARIANT_TYPE ("ay"),
|
|
||||||
buffer, n_buffer, TRUE,
|
|
||||||
gcry_free, buffer);
|
|
||||||
|
|
||||||
return g_variant_new ("(sv)", ALGORITHMS_AES, argument);
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
response_open_session_aes (GSecretSession *session,
|
|
||||||
GVariant *response)
|
|
||||||
{
|
|
||||||
gconstpointer buffer;
|
|
||||||
GVariant *argument;
|
|
||||||
const gchar *sig;
|
|
||||||
gsize n_buffer;
|
|
||||||
gcry_mpi_t peer;
|
|
||||||
gcry_error_t gcry;
|
|
||||||
gpointer ikm;
|
|
||||||
gsize n_ikm;
|
|
||||||
|
|
||||||
sig = g_variant_get_type_string (response);
|
|
||||||
g_return_val_if_fail (sig != NULL, FALSE);
|
|
||||||
|
|
||||||
if (!g_str_equal (sig, "(vo)")) {
|
|
||||||
g_warning ("invalid OpenSession() response from daemon with signature: %s", sig);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_assert (session->path == NULL);
|
|
||||||
g_variant_get (response, "(vo)", &argument, &session->path);
|
|
||||||
|
|
||||||
buffer = g_variant_get_fixed_array (argument, &n_buffer, sizeof (guchar));
|
|
||||||
gcry = gcry_mpi_scan (&peer, GCRYMPI_FMT_USG, buffer, n_buffer, NULL);
|
|
||||||
g_return_val_if_fail (gcry == 0, FALSE);
|
|
||||||
g_variant_unref (argument);
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
g_printerr (" lib publi: ");
|
|
||||||
gcry_mpi_dump (session->publi);
|
|
||||||
g_printerr ("\n lib peer: ");
|
|
||||||
gcry_mpi_dump (peer);
|
|
||||||
g_printerr ("\n");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ikm = egg_dh_gen_secret (peer, session->privat, session->prime, &n_ikm);
|
|
||||||
gcry_mpi_release (peer);
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
g_printerr (" lib ikm: %s\n", egg_hex_encode (ikm, n_ikm));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (ikm == NULL) {
|
|
||||||
g_warning ("couldn't negotiate a valid AES session key");
|
|
||||||
g_free (session->path);
|
|
||||||
session->path = NULL;
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
session->n_key = 16;
|
|
||||||
session->key = egg_secure_alloc (session->n_key);
|
|
||||||
if (!egg_hkdf_perform ("sha256", ikm, n_ikm, NULL, 0, NULL, 0,
|
|
||||||
session->key, session->n_key))
|
|
||||||
g_return_val_if_reached (FALSE);
|
|
||||||
egg_secure_free (ikm);
|
|
||||||
|
|
||||||
session->algorithms = ALGORITHMS_AES;
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* WITH_GCRYPT */
|
|
||||||
|
|
||||||
static GVariant *
|
|
||||||
request_open_session_plain (GSecretSession *session)
|
|
||||||
{
|
|
||||||
GVariant *argument = g_variant_new_string ("");
|
|
||||||
return g_variant_new ("(sv)", "plain", argument);
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
response_open_session_plain (GSecretSession *session,
|
|
||||||
GVariant *response)
|
|
||||||
{
|
|
||||||
GVariant *argument;
|
|
||||||
const gchar *sig;
|
|
||||||
|
|
||||||
sig = g_variant_get_type_string (response);
|
|
||||||
g_return_val_if_fail (sig != NULL, FALSE);
|
|
||||||
|
|
||||||
if (!g_str_equal (sig, "(vo)")) {
|
|
||||||
g_warning ("invalid OpenSession() response from daemon with signature: %s",
|
|
||||||
g_variant_get_type_string (response));
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_assert (session->path == NULL);
|
|
||||||
g_variant_get (response, "(vo)", &argument, &session->path);
|
|
||||||
g_variant_unref (argument);
|
|
||||||
|
|
||||||
g_assert (session->key == NULL);
|
|
||||||
g_assert (session->n_key == 0);
|
|
||||||
|
|
||||||
session->algorithms = ALGORITHMS_PLAIN;
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
GCancellable *cancellable;
|
|
||||||
GSecretSession *session;
|
|
||||||
} OpenSessionClosure;
|
|
||||||
|
|
||||||
static void
|
|
||||||
open_session_closure_free (gpointer data)
|
|
||||||
{
|
|
||||||
OpenSessionClosure *closure = data;
|
|
||||||
g_assert (closure);
|
|
||||||
g_clear_object (&closure->cancellable);
|
|
||||||
gsecret_session_free (closure->session);
|
|
||||||
g_free (closure);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
on_service_open_session_plain (GObject *source,
|
|
||||||
GAsyncResult *result,
|
|
||||||
gpointer user_data)
|
|
||||||
{
|
|
||||||
GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
|
|
||||||
OpenSessionClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
|
|
||||||
GSecretService *self = GSECRET_SERVICE (source);
|
|
||||||
GError *error = NULL;
|
|
||||||
GVariant *response;
|
|
||||||
|
|
||||||
response = g_dbus_proxy_call_finish (G_DBUS_PROXY (self), result, &error);
|
|
||||||
|
|
||||||
/* A successful response, decode it */
|
|
||||||
if (response != NULL) {
|
|
||||||
if (response_open_session_plain (closure->session, response)) {
|
|
||||||
|
|
||||||
g_mutex_lock (&self->pv->mutex);
|
|
||||||
if (self->pv->session == NULL) {
|
|
||||||
self->pv->session = closure->session;
|
|
||||||
closure->session = NULL; /* Service takes ownership */
|
|
||||||
}
|
|
||||||
g_mutex_unlock (&self->pv->mutex);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
g_simple_async_result_set_error (res, GSECRET_ERROR, GSECRET_ERROR_PROTOCOL,
|
|
||||||
_("Couldn't communicate with the secret storage"));
|
|
||||||
}
|
|
||||||
|
|
||||||
g_simple_async_result_complete (res);
|
|
||||||
g_variant_unref (response);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
g_simple_async_result_take_error (res, error);
|
|
||||||
g_simple_async_result_complete (res);
|
|
||||||
}
|
|
||||||
|
|
||||||
g_object_unref (res);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef WITH_GCRYPT
|
|
||||||
|
|
||||||
static void
|
|
||||||
on_service_open_session_aes (GObject *source,
|
|
||||||
GAsyncResult *result,
|
|
||||||
gpointer user_data)
|
|
||||||
{
|
|
||||||
GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
|
|
||||||
OpenSessionClosure * closure = g_simple_async_result_get_op_res_gpointer (res);
|
|
||||||
GSecretService *self = GSECRET_SERVICE (source);
|
|
||||||
GError *error = NULL;
|
|
||||||
GVariant *response;
|
|
||||||
|
|
||||||
response = g_dbus_proxy_call_finish (G_DBUS_PROXY (self), result, &error);
|
|
||||||
|
|
||||||
/* A successful response, decode it */
|
|
||||||
if (response != NULL) {
|
|
||||||
if (response_open_session_aes (closure->session, response)) {
|
|
||||||
|
|
||||||
g_mutex_lock (&self->pv->mutex);
|
|
||||||
if (self->pv->session == NULL) {
|
|
||||||
self->pv->session = closure->session;
|
|
||||||
closure->session = NULL; /* Service takes ownership */
|
|
||||||
}
|
|
||||||
g_mutex_unlock (&self->pv->mutex);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
g_simple_async_result_set_error (res, GSECRET_ERROR, GSECRET_ERROR_PROTOCOL,
|
|
||||||
_("Couldn't communicate with the secret storage"));
|
|
||||||
}
|
|
||||||
|
|
||||||
g_simple_async_result_complete (res);
|
|
||||||
g_variant_unref (response);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
/* AES session not supported, request a plain session */
|
|
||||||
if (g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_NOT_SUPPORTED)) {
|
|
||||||
g_dbus_proxy_call (G_DBUS_PROXY (source), "OpenSession",
|
|
||||||
request_open_session_plain (closure->session),
|
|
||||||
G_DBUS_CALL_FLAGS_NONE, -1,
|
|
||||||
closure->cancellable, on_service_open_session_plain,
|
|
||||||
g_object_ref (res));
|
|
||||||
g_error_free (error);
|
|
||||||
|
|
||||||
/* Other errors result in a failure */
|
|
||||||
} else {
|
|
||||||
g_simple_async_result_take_error (res, error);
|
|
||||||
g_simple_async_result_complete (res);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
g_object_unref (res);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* WITH_GCRYPT */
|
|
||||||
|
|
||||||
void
|
void
|
||||||
gsecret_service_ensure_session (GSecretService *self,
|
gsecret_service_ensure_session (GSecretService *self,
|
||||||
GCancellable *cancellable,
|
GCancellable *cancellable,
|
||||||
@ -1038,72 +780,24 @@ gsecret_service_ensure_session (GSecretService *self,
|
|||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
GSimpleAsyncResult *res;
|
GSimpleAsyncResult *res;
|
||||||
OpenSessionClosure *closure;
|
|
||||||
GSecretSession *session;
|
GSecretSession *session;
|
||||||
|
|
||||||
g_return_if_fail (GSECRET_IS_SERVICE (self));
|
g_return_if_fail (GSECRET_IS_SERVICE (self));
|
||||||
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
|
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
|
||||||
|
|
||||||
res = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
|
|
||||||
gsecret_service_ensure_session);
|
|
||||||
|
|
||||||
g_mutex_lock (&self->pv->mutex);
|
g_mutex_lock (&self->pv->mutex);
|
||||||
session = self->pv->session;
|
session = self->pv->session;
|
||||||
g_mutex_unlock (&self->pv->mutex);
|
g_mutex_unlock (&self->pv->mutex);
|
||||||
|
|
||||||
/* If we have no session, then request an AES session */
|
|
||||||
if (session == NULL) {
|
if (session == NULL) {
|
||||||
|
_gsecret_session_open (self, cancellable, callback, user_data);
|
||||||
|
|
||||||
closure = g_new (OpenSessionClosure, 1);
|
|
||||||
closure->cancellable = cancellable ? g_object_ref (cancellable) : cancellable;
|
|
||||||
closure->session = g_new0 (GSecretSession, 1);
|
|
||||||
g_simple_async_result_set_op_res_gpointer (res, closure, open_session_closure_free);
|
|
||||||
|
|
||||||
g_dbus_proxy_call (G_DBUS_PROXY (self), "OpenSession",
|
|
||||||
#ifdef WITH_GCRYPT
|
|
||||||
request_open_session_aes (closure->session),
|
|
||||||
G_DBUS_CALL_FLAGS_NONE, -1,
|
|
||||||
cancellable, on_service_open_session_aes,
|
|
||||||
#else
|
|
||||||
request_open_session_plain (closure->session),
|
|
||||||
G_DBUS_CALL_FLAGS_NONE, -1,
|
|
||||||
cancellable, on_service_open_session_plain,
|
|
||||||
#endif
|
|
||||||
g_object_ref (res));
|
|
||||||
|
|
||||||
/* Already have a session */
|
|
||||||
} else {
|
} else {
|
||||||
|
res = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
|
||||||
|
gsecret_service_ensure_session);
|
||||||
g_simple_async_result_complete_in_idle (res);
|
g_simple_async_result_complete_in_idle (res);
|
||||||
|
g_object_unref (res);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_object_unref (res);
|
|
||||||
}
|
|
||||||
|
|
||||||
const gchar *
|
|
||||||
_gsecret_service_ensure_session_finish (GSecretService *self,
|
|
||||||
GAsyncResult *result,
|
|
||||||
GCancellable **cancellable,
|
|
||||||
GError **error)
|
|
||||||
{
|
|
||||||
OpenSessionClosure *closure;
|
|
||||||
|
|
||||||
g_return_val_if_fail (GSECRET_IS_SERVICE (self), NULL);
|
|
||||||
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
|
||||||
g_return_val_if_fail (cancellable == NULL || *cancellable == NULL, NULL);
|
|
||||||
|
|
||||||
g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self),
|
|
||||||
gsecret_service_ensure_session), NULL);
|
|
||||||
|
|
||||||
if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if (cancellable) {
|
|
||||||
closure = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result));
|
|
||||||
*cancellable = closure->cancellable ? g_object_ref (closure->cancellable) : NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The session we have should never change once created */
|
|
||||||
return gsecret_service_get_session_path (self);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const gchar *
|
const gchar *
|
||||||
@ -1111,7 +805,17 @@ gsecret_service_ensure_session_finish (GSecretService *self,
|
|||||||
GAsyncResult *result,
|
GAsyncResult *result,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
return _gsecret_service_ensure_session_finish (self, result, NULL, error);
|
g_return_val_if_fail (GSECRET_IS_SERVICE (self), NULL);
|
||||||
|
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
||||||
|
|
||||||
|
if (!g_simple_async_result_is_valid (result, G_OBJECT (self),
|
||||||
|
gsecret_service_ensure_session)) {
|
||||||
|
if (!_gsecret_session_open_finish (result, error))
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_return_val_if_fail (self->pv->session != NULL, NULL);
|
||||||
|
return gsecret_service_get_session_path (self->pv->session);
|
||||||
}
|
}
|
||||||
|
|
||||||
const gchar *
|
const gchar *
|
||||||
@ -1142,328 +846,47 @@ gsecret_service_ensure_session_sync (GSecretService *self,
|
|||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WITH_GCRYPT
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
pkcs7_unpad_bytes_in_place (guchar *padded,
|
|
||||||
gsize *n_padded)
|
|
||||||
{
|
|
||||||
gsize n_pad, i;
|
|
||||||
|
|
||||||
if (*n_padded == 0)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
n_pad = padded[*n_padded - 1];
|
|
||||||
|
|
||||||
/* Validate the padding */
|
|
||||||
if (n_pad == 0 || n_pad > 16)
|
|
||||||
return FALSE;
|
|
||||||
if (n_pad > *n_padded)
|
|
||||||
return FALSE;
|
|
||||||
for (i = *n_padded - n_pad; i < *n_padded; ++i) {
|
|
||||||
if (padded[i] != n_pad)
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The last bit of data */
|
|
||||||
*n_padded -= n_pad;
|
|
||||||
|
|
||||||
/* Null teriminate as a courtesy */
|
|
||||||
padded[*n_padded] = 0;
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static GSecretValue *
|
|
||||||
service_decode_aes_secret (GSecretSession *session,
|
|
||||||
gconstpointer param,
|
|
||||||
gsize n_param,
|
|
||||||
gconstpointer value,
|
|
||||||
gsize n_value,
|
|
||||||
const gchar *content_type)
|
|
||||||
{
|
|
||||||
gcry_cipher_hd_t cih;
|
|
||||||
gsize n_padded;
|
|
||||||
gcry_error_t gcry;
|
|
||||||
guchar *padded;
|
|
||||||
gsize pos;
|
|
||||||
|
|
||||||
if (n_param != 16) {
|
|
||||||
g_message ("received an encrypted secret structure with invalid parameter");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (n_value == 0 || n_value % 16 != 0) {
|
|
||||||
g_message ("received an encrypted secret structure with bad secret length");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
gcry = gcry_cipher_open (&cih, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_CBC, 0);
|
|
||||||
if (gcry != 0) {
|
|
||||||
g_warning ("couldn't create AES cipher: %s", gcry_strerror (gcry));
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
g_printerr (" lib iv: %s\n", egg_hex_encode (param, n_param));
|
void
|
||||||
|
gsecret_service_ensure_collections (GSecretService *self,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GAsyncReadyCallback callback,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
GSimpleAsyncResult *res;
|
||||||
|
|
||||||
|
g_return_if_fail (GSECRET_IS_SERVICE (self));
|
||||||
|
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gsecret_service_ensure_collections_finish (GSecretService *self,
|
||||||
|
GAsyncResult *result,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (GSECRET_IS_SERVICE (self), FALSE);
|
||||||
|
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
||||||
|
g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self),
|
||||||
|
gsecret_service_ensure_collections), FALSE);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gsecret_service_ensure_collections_sync (GSecretService *self,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (GSECRET_IS_SERVICE (self), FALSE);
|
||||||
|
g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
|
||||||
|
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
gcry = gcry_cipher_setiv (cih, param, n_param);
|
|
||||||
g_return_val_if_fail (gcry == 0, NULL);
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
g_printerr (" lib key: %s\n", egg_hex_encode (session->key, session->n_key));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
gcry = gcry_cipher_setkey (cih, session->key, session->n_key);
|
|
||||||
g_return_val_if_fail (gcry == 0, NULL);
|
|
||||||
|
|
||||||
/* Copy the memory buffer */
|
|
||||||
n_padded = n_value;
|
|
||||||
padded = egg_secure_alloc (n_padded);
|
|
||||||
memcpy (padded, value, n_padded);
|
|
||||||
|
|
||||||
/* Perform the decryption */
|
|
||||||
for (pos = 0; pos < n_padded; pos += 16) {
|
|
||||||
gcry = gcry_cipher_decrypt (cih, (guchar*)padded + pos, 16, NULL, 0);
|
|
||||||
g_return_val_if_fail (gcry == 0, FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
gcry_cipher_close (cih);
|
|
||||||
|
|
||||||
/* Unpad the resulting value */
|
|
||||||
if (!pkcs7_unpad_bytes_in_place (padded, &n_padded)) {
|
|
||||||
egg_secure_clear (padded, n_padded);
|
|
||||||
egg_secure_free (padded);
|
|
||||||
g_message ("received an invalid or unencryptable secret");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return gsecret_value_new_full ((gchar *)padded, n_padded, content_type, egg_secure_free);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* WITH_GCRYPT */
|
|
||||||
|
|
||||||
static GSecretValue *
|
|
||||||
service_decode_plain_secret (GSecretSession *session,
|
|
||||||
gconstpointer param,
|
|
||||||
gsize n_param,
|
|
||||||
gconstpointer value,
|
|
||||||
gsize n_value,
|
|
||||||
const gchar *content_type)
|
|
||||||
{
|
|
||||||
if (n_param != 0) {
|
|
||||||
g_message ("received a plain secret structure with invalid parameter");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return gsecret_value_new (value, n_value, content_type);
|
|
||||||
}
|
|
||||||
|
|
||||||
GSecretValue *
|
|
||||||
_gsecret_service_decode_secret (GSecretService *self,
|
|
||||||
GVariant *encoded)
|
|
||||||
{
|
|
||||||
GSecretSession *session;
|
|
||||||
GSecretValue *result;
|
|
||||||
gconstpointer param;
|
|
||||||
gconstpointer value;
|
|
||||||
gchar *session_path;
|
|
||||||
gchar *content_type;
|
|
||||||
gsize n_param;
|
|
||||||
gsize n_value;
|
|
||||||
GVariant *vparam;
|
|
||||||
GVariant *vvalue;
|
|
||||||
|
|
||||||
g_return_val_if_fail (GSECRET_IS_SERVICE (self), NULL);
|
|
||||||
g_return_val_if_fail (encoded, NULL);
|
|
||||||
|
|
||||||
g_mutex_lock (&self->pv->mutex);
|
|
||||||
session = self->pv->session;
|
|
||||||
g_assert (session == NULL || session->path != NULL);
|
|
||||||
g_mutex_unlock (&self->pv->mutex);
|
|
||||||
|
|
||||||
g_return_val_if_fail (session != NULL, NULL);
|
|
||||||
|
|
||||||
/* Parsing (oayays) */
|
|
||||||
g_variant_get_child (encoded, 0, "o", &session_path);
|
|
||||||
|
|
||||||
if (session_path == NULL || !g_str_equal (session_path, session->path)) {
|
|
||||||
g_message ("received a secret encoded with wrong session: %s != %s",
|
|
||||||
session_path, session->path);
|
|
||||||
g_free (session_path);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
vparam = g_variant_get_child_value (encoded, 1);
|
|
||||||
param = g_variant_get_fixed_array (vparam, &n_param, sizeof (guchar));
|
|
||||||
vvalue = g_variant_get_child_value (encoded, 2);
|
|
||||||
value = g_variant_get_fixed_array (vvalue, &n_value, sizeof (guchar));
|
|
||||||
g_variant_get_child (encoded, 3, "s", &content_type);
|
|
||||||
|
|
||||||
#ifdef WITH_GCRYPT
|
|
||||||
if (session->key != NULL)
|
|
||||||
result = service_decode_aes_secret (session, param, n_param,
|
|
||||||
value, n_value, content_type);
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
result = service_decode_plain_secret (session, param, n_param,
|
|
||||||
value, n_value, content_type);
|
|
||||||
|
|
||||||
g_variant_unref (vparam);
|
|
||||||
g_variant_unref (vvalue);
|
|
||||||
g_free (content_type);
|
|
||||||
g_free (session_path);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef WITH_GCRYPT
|
|
||||||
|
|
||||||
static guchar*
|
|
||||||
pkcs7_pad_bytes_in_secure_memory (gconstpointer secret,
|
|
||||||
gsize length,
|
|
||||||
gsize *n_padded)
|
|
||||||
{
|
|
||||||
gsize n_pad;
|
|
||||||
guchar *padded;
|
|
||||||
|
|
||||||
/* Pad the secret */
|
|
||||||
*n_padded = ((length + 16) / 16) * 16;
|
|
||||||
g_assert (length < *n_padded);
|
|
||||||
g_assert (*n_padded > 0);
|
|
||||||
n_pad = *n_padded - length;
|
|
||||||
g_assert (n_pad > 0 && n_pad <= 16);
|
|
||||||
padded = egg_secure_alloc (*n_padded);
|
|
||||||
memcpy (padded, secret, length);
|
|
||||||
memset (padded + length, n_pad, n_pad);
|
|
||||||
return padded;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
service_encode_aes_secret (GSecretSession *session,
|
|
||||||
GSecretValue *value,
|
|
||||||
GVariantBuilder *builder)
|
|
||||||
{
|
|
||||||
gcry_cipher_hd_t cih;
|
|
||||||
guchar *padded;
|
|
||||||
gsize n_padded, pos;
|
|
||||||
gcry_error_t gcry;
|
|
||||||
gpointer iv;
|
|
||||||
gconstpointer secret;
|
|
||||||
gsize n_secret;
|
|
||||||
GVariant *child;
|
|
||||||
|
|
||||||
g_variant_builder_add (builder, "o", session->path);
|
|
||||||
|
|
||||||
/* Create the cipher */
|
|
||||||
gcry = gcry_cipher_open (&cih, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_CBC, 0);
|
|
||||||
if (gcry != 0) {
|
|
||||||
g_warning ("couldn't create AES cipher: %s", gcry_strerror (gcry));
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
secret = gsecret_value_get (value, &n_secret);
|
|
||||||
|
|
||||||
/* Perform the encoding here */
|
|
||||||
padded = pkcs7_pad_bytes_in_secure_memory (secret, n_secret, &n_padded);
|
|
||||||
g_assert (padded != NULL);
|
|
||||||
|
|
||||||
/* Setup the IV */
|
|
||||||
iv = g_malloc0 (16);
|
|
||||||
gcry_create_nonce (iv, 16);
|
|
||||||
gcry = gcry_cipher_setiv (cih, iv, 16);
|
|
||||||
g_return_val_if_fail (gcry == 0, FALSE);
|
|
||||||
|
|
||||||
/* Setup the key */
|
|
||||||
gcry = gcry_cipher_setkey (cih, session->key, session->n_key);
|
|
||||||
g_return_val_if_fail (gcry == 0, FALSE);
|
|
||||||
|
|
||||||
/* Perform the encryption */
|
|
||||||
for (pos = 0; pos < n_padded; pos += 16) {
|
|
||||||
gcry = gcry_cipher_encrypt (cih, (guchar*)padded + pos, 16, NULL, 0);
|
|
||||||
g_return_val_if_fail (gcry == 0, FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
gcry_cipher_close (cih);
|
|
||||||
|
|
||||||
child = g_variant_new_from_data (G_VARIANT_TYPE ("ay"), iv, 16, TRUE, g_free, iv);
|
|
||||||
g_variant_builder_add_value (builder, child);
|
|
||||||
g_variant_unref (child);
|
|
||||||
|
|
||||||
child = g_variant_new_from_data (G_VARIANT_TYPE ("ay"), padded, n_padded, TRUE, egg_secure_free, padded);
|
|
||||||
g_variant_builder_add_value (builder, child);
|
|
||||||
g_variant_unref (child);
|
|
||||||
|
|
||||||
g_variant_builder_add (builder, "s", gsecret_value_get_content_type (value));
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* WITH_GCRYPT */
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
service_encode_plain_secret (GSecretSession *session,
|
|
||||||
GSecretValue *value,
|
|
||||||
GVariantBuilder *builder)
|
|
||||||
{
|
|
||||||
gconstpointer secret;
|
|
||||||
gsize n_secret;
|
|
||||||
GVariant *child;
|
|
||||||
|
|
||||||
g_variant_builder_add (builder, "o", session->path);
|
|
||||||
|
|
||||||
secret = gsecret_value_get (value, &n_secret);
|
|
||||||
|
|
||||||
child = g_variant_new_from_data (G_VARIANT_TYPE ("ay"), "", 0, TRUE, NULL, NULL);
|
|
||||||
g_variant_builder_add_value (builder, child);
|
|
||||||
g_variant_unref (child);
|
|
||||||
|
|
||||||
child = g_variant_new_from_data (G_VARIANT_TYPE ("ay"), secret, n_secret, TRUE,
|
|
||||||
gsecret_value_unref, gsecret_value_ref (value));
|
|
||||||
g_variant_builder_add_value (builder, child);
|
|
||||||
g_variant_unref (child);
|
|
||||||
|
|
||||||
g_variant_builder_add (builder, "s", gsecret_value_get_content_type (value));
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
GVariant *
|
|
||||||
_gsecret_service_encode_secret (GSecretService *self,
|
|
||||||
GSecretValue *value)
|
|
||||||
{
|
|
||||||
GVariantBuilder *builder;
|
|
||||||
GSecretSession *session;
|
|
||||||
GVariant *result = NULL;
|
|
||||||
GVariantType *type;
|
|
||||||
gboolean ret;
|
|
||||||
|
|
||||||
g_return_val_if_fail (GSECRET_IS_SERVICE (self), NULL);
|
|
||||||
g_return_val_if_fail (value, NULL);
|
|
||||||
|
|
||||||
g_mutex_lock (&self->pv->mutex);
|
|
||||||
session = self->pv->session;
|
|
||||||
g_assert (session == NULL || session->path != NULL);
|
|
||||||
g_mutex_unlock (&self->pv->mutex);
|
|
||||||
|
|
||||||
g_return_val_if_fail (session != NULL, NULL);
|
|
||||||
|
|
||||||
type = g_variant_type_new ("(oayays)");
|
|
||||||
builder = g_variant_builder_new (type);
|
|
||||||
|
|
||||||
#ifdef WITH_GCRYPT
|
|
||||||
if (session->key)
|
|
||||||
ret = service_encode_aes_secret (session, value, builder);
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
ret = service_encode_plain_secret (session, value, builder);
|
|
||||||
if (ret)
|
|
||||||
result = g_variant_builder_end (builder);
|
|
||||||
|
|
||||||
g_variant_builder_unref (builder);
|
|
||||||
g_variant_type_free (type);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
on_search_items_complete (GObject *source,
|
on_search_items_complete (GObject *source,
|
||||||
GAsyncResult *result,
|
GAsyncResult *result,
|
||||||
@ -1640,6 +1063,7 @@ search_load_item (GSecretService *self,
|
|||||||
|
|
||||||
item = _gsecret_service_find_item_instance (self, path);
|
item = _gsecret_service_find_item_instance (self, path);
|
||||||
if (item == NULL) {
|
if (item == NULL) {
|
||||||
|
// TODO: xxxxxxxxxx;
|
||||||
gsecret_item_new (self, path, closure->cancellable,
|
gsecret_item_new (self, path, closure->cancellable,
|
||||||
on_search_loaded, g_object_ref (res));
|
on_search_loaded, g_object_ref (res));
|
||||||
closure->loading++;
|
closure->loading++;
|
||||||
@ -1875,14 +1299,16 @@ static GSecretValue *
|
|||||||
service_decode_get_secrets_first (GSecretService *self,
|
service_decode_get_secrets_first (GSecretService *self,
|
||||||
GVariant *out)
|
GVariant *out)
|
||||||
{
|
{
|
||||||
|
GSecretSession *session;
|
||||||
|
GSecretValue *value;
|
||||||
GVariantIter *iter;
|
GVariantIter *iter;
|
||||||
GVariant *variant;
|
GVariant *variant;
|
||||||
GSecretValue *value;
|
|
||||||
const gchar *path;
|
const gchar *path;
|
||||||
|
|
||||||
g_variant_get (out, "(a{o(oayays)})", &iter);
|
g_variant_get (out, "(a{o(oayays)})", &iter);
|
||||||
while (g_variant_iter_next (iter, "{&o@(oayays)}", &path, &variant)) {
|
while (g_variant_iter_next (iter, "{&o@(oayays)}", &path, &variant)) {
|
||||||
value = _gsecret_service_decode_secret (self, variant);
|
session = _gsecret_service_get_session (self);
|
||||||
|
value = _gsecret_session_decode_secret (session, variant);
|
||||||
g_variant_unref (variant);
|
g_variant_unref (variant);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1894,17 +1320,19 @@ static GHashTable *
|
|||||||
service_decode_get_secrets_all (GSecretService *self,
|
service_decode_get_secrets_all (GSecretService *self,
|
||||||
GVariant *out)
|
GVariant *out)
|
||||||
{
|
{
|
||||||
|
GSecretSession *session;
|
||||||
GVariantIter *iter;
|
GVariantIter *iter;
|
||||||
GVariant *variant;
|
GVariant *variant;
|
||||||
GHashTable *values;
|
GHashTable *values;
|
||||||
GSecretValue *value;
|
GSecretValue *value;
|
||||||
gchar *path;
|
gchar *path;
|
||||||
|
|
||||||
|
session = _gsecret_service_get_session (self);
|
||||||
values = g_hash_table_new_full (g_str_hash, g_str_equal,
|
values = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||||
g_free, gsecret_value_unref);
|
g_free, gsecret_value_unref);
|
||||||
g_variant_get (out, "(a{o(oayays)})", &iter);
|
g_variant_get (out, "(a{o(oayays)})", &iter);
|
||||||
while (g_variant_iter_loop (iter, "{o@(oayays)}", &path, &variant)) {
|
while (g_variant_iter_loop (iter, "{o@(oayays)}", &path, &variant)) {
|
||||||
value = _gsecret_service_decode_secret (self, variant);
|
value = _gsecret_session_decode_secret (session, variant);
|
||||||
if (value && path)
|
if (value && path)
|
||||||
g_hash_table_insert (values, g_strdup (path), value);
|
g_hash_table_insert (values, g_strdup (path), value);
|
||||||
}
|
}
|
||||||
@ -2778,6 +2206,7 @@ gsecret_service_storev (GSecretService *self,
|
|||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
GSimpleAsyncResult *res;
|
GSimpleAsyncResult *res;
|
||||||
|
GSecretSession *session;
|
||||||
GVariant *attrs;
|
GVariant *attrs;
|
||||||
StoreClosure *closure;
|
StoreClosure *closure;
|
||||||
GVariantBuilder builder;
|
GVariantBuilder builder;
|
||||||
@ -2808,9 +2237,10 @@ gsecret_service_storev (GSecretService *self,
|
|||||||
closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
|
closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
|
||||||
g_simple_async_result_set_op_res_gpointer (res, closure, store_closure_free);
|
g_simple_async_result_set_op_res_gpointer (res, closure, store_closure_free);
|
||||||
|
|
||||||
|
session = _gsecret_service_get_session (self);
|
||||||
params = g_variant_new ("(&a{sv}&(oayays)b)",
|
params = g_variant_new ("(&a{sv}&(oayays)b)",
|
||||||
g_variant_builder_end (&builder),
|
g_variant_builder_end (&builder),
|
||||||
_gsecret_service_encode_secret (self, value),
|
_gsecret_session_encode_secret (session, value),
|
||||||
TRUE);
|
TRUE);
|
||||||
|
|
||||||
proxy = G_DBUS_PROXY (self);
|
proxy = G_DBUS_PROXY (self);
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
/* GSecret - GLib wrapper for Secret Service
|
/* GSecret - GLib wrapper for Secret Service
|
||||||
*
|
*
|
||||||
* Copyright 2011 Collabora Ltd.
|
* Copyright 2011 Collabora Ltd.
|
||||||
|
* Copyright 2012 Red Hat Inc.
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU Lesser General Public License as published
|
||||||
@ -72,12 +73,12 @@ GSecretService * gsecret_service_get_finish (GAsyncResult
|
|||||||
GSecretService * gsecret_service_get_sync (GCancellable *cancellable,
|
GSecretService * gsecret_service_get_sync (GCancellable *cancellable,
|
||||||
GError **error);
|
GError **error);
|
||||||
|
|
||||||
GList * gsecret_service_get_collections (GSecretService *self);
|
|
||||||
|
|
||||||
const gchar * gsecret_service_get_session_algorithms (GSecretService *self);
|
const gchar * gsecret_service_get_session_algorithms (GSecretService *self);
|
||||||
|
|
||||||
const gchar * gsecret_service_get_session_path (GSecretService *self);
|
const gchar * gsecret_service_get_session_path (GSecretService *self);
|
||||||
|
|
||||||
|
GList * gsecret_service_get_collections (GSecretService *self);
|
||||||
|
|
||||||
void gsecret_service_ensure_session (GSecretService *self,
|
void gsecret_service_ensure_session (GSecretService *self,
|
||||||
GCancellable *cancellable,
|
GCancellable *cancellable,
|
||||||
GAsyncReadyCallback callback,
|
GAsyncReadyCallback callback,
|
||||||
@ -91,6 +92,19 @@ const gchar * gsecret_service_ensure_session_sync (GSecretServi
|
|||||||
GCancellable *cancellable,
|
GCancellable *cancellable,
|
||||||
GError **error);
|
GError **error);
|
||||||
|
|
||||||
|
void gsecret_service_ensure_collections (GSecretService *self,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GAsyncReadyCallback callback,
|
||||||
|
gpointer user_data);
|
||||||
|
|
||||||
|
gboolean gsecret_service_ensure_collections_finish (GSecretService *self,
|
||||||
|
GAsyncResult *result,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
gboolean gsecret_service_ensure_collections_sync (GSecretService *self,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
void gsecret_service_search (GSecretService *self,
|
void gsecret_service_search (GSecretService *self,
|
||||||
GHashTable *attributes,
|
GHashTable *attributes,
|
||||||
GCancellable *cancellable,
|
GCancellable *cancellable,
|
||||||
|
671
library/gsecret-session.c
Normal file
671
library/gsecret-session.c
Normal file
@ -0,0 +1,671 @@
|
|||||||
|
/* GSecret - GLib wrapper for Secret Service
|
||||||
|
*
|
||||||
|
* Copyright 2011 Collabora Ltd.
|
||||||
|
* Copyright 2012 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 of the licence or (at
|
||||||
|
* your option) any later version.
|
||||||
|
*
|
||||||
|
* See the included COPYING file for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "gsecret-private.h"
|
||||||
|
|
||||||
|
#ifdef WITH_GCRYPT
|
||||||
|
#include "egg/egg-dh.h"
|
||||||
|
#include "egg/egg-hkdf.h"
|
||||||
|
#include "egg/egg-libgcrypt.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "egg/egg-hex.h"
|
||||||
|
#include "egg/egg-secure-memory.h"
|
||||||
|
|
||||||
|
#include <glib/gi18n-lib.h>
|
||||||
|
|
||||||
|
EGG_SECURE_DECLARE (secret_session);
|
||||||
|
|
||||||
|
#define ALGORITHMS_AES "dh-ietf1024-sha256-aes128-cbc-pkcs7"
|
||||||
|
#define ALGORITHMS_PLAIN "plain"
|
||||||
|
|
||||||
|
struct _GSecretSession {
|
||||||
|
gchar *path;
|
||||||
|
const gchar *algorithms;
|
||||||
|
#ifdef WITH_GCRYPT
|
||||||
|
gcry_mpi_t prime;
|
||||||
|
gcry_mpi_t privat;
|
||||||
|
gcry_mpi_t publi;
|
||||||
|
#endif
|
||||||
|
gpointer key;
|
||||||
|
gsize n_key;
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
_gsecret_session_free (gpointer data)
|
||||||
|
{
|
||||||
|
GSecretSession *session = data;
|
||||||
|
|
||||||
|
if (session == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
g_free (session->path);
|
||||||
|
#ifdef WITH_GCRYPT
|
||||||
|
gcry_mpi_release (session->publi);
|
||||||
|
gcry_mpi_release (session->privat);
|
||||||
|
gcry_mpi_release (session->prime);
|
||||||
|
#endif
|
||||||
|
egg_secure_free (session->key);
|
||||||
|
g_free (session);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef WITH_GCRYPT
|
||||||
|
|
||||||
|
static GVariant *
|
||||||
|
request_open_session_aes (GSecretSession *session)
|
||||||
|
{
|
||||||
|
gcry_error_t gcry;
|
||||||
|
gcry_mpi_t base;
|
||||||
|
unsigned char *buffer;
|
||||||
|
size_t n_buffer;
|
||||||
|
GVariant *argument;
|
||||||
|
|
||||||
|
g_assert (session->prime == NULL);
|
||||||
|
g_assert (session->privat == NULL);
|
||||||
|
g_assert (session->publi == NULL);
|
||||||
|
|
||||||
|
/* Initialize our local parameters and values */
|
||||||
|
if (!egg_dh_default_params ("ietf-ike-grp-modp-1536",
|
||||||
|
&session->prime, &base))
|
||||||
|
g_return_val_if_reached (NULL);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
g_printerr ("\n lib prime: ");
|
||||||
|
gcry_mpi_dump (session->prime);
|
||||||
|
g_printerr ("\n lib base: ");
|
||||||
|
gcry_mpi_dump (base);
|
||||||
|
g_printerr ("\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!egg_dh_gen_pair (session->prime, base, 0,
|
||||||
|
&session->publi, &session->privat))
|
||||||
|
g_return_val_if_reached (NULL);
|
||||||
|
gcry_mpi_release (base);
|
||||||
|
|
||||||
|
gcry = gcry_mpi_aprint (GCRYMPI_FMT_USG, &buffer, &n_buffer, session->publi);
|
||||||
|
g_return_val_if_fail (gcry == 0, NULL);
|
||||||
|
argument = g_variant_new_from_data (G_VARIANT_TYPE ("ay"),
|
||||||
|
buffer, n_buffer, TRUE,
|
||||||
|
gcry_free, buffer);
|
||||||
|
|
||||||
|
return g_variant_new ("(sv)", ALGORITHMS_AES, argument);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
response_open_session_aes (GSecretSession *session,
|
||||||
|
GVariant *response)
|
||||||
|
{
|
||||||
|
gconstpointer buffer;
|
||||||
|
GVariant *argument;
|
||||||
|
const gchar *sig;
|
||||||
|
gsize n_buffer;
|
||||||
|
gcry_mpi_t peer;
|
||||||
|
gcry_error_t gcry;
|
||||||
|
gpointer ikm;
|
||||||
|
gsize n_ikm;
|
||||||
|
|
||||||
|
sig = g_variant_get_type_string (response);
|
||||||
|
g_return_val_if_fail (sig != NULL, FALSE);
|
||||||
|
|
||||||
|
if (!g_str_equal (sig, "(vo)")) {
|
||||||
|
g_warning ("invalid OpenSession() response from daemon with signature: %s", sig);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_assert (session->path == NULL);
|
||||||
|
g_variant_get (response, "(vo)", &argument, &session->path);
|
||||||
|
|
||||||
|
buffer = g_variant_get_fixed_array (argument, &n_buffer, sizeof (guchar));
|
||||||
|
gcry = gcry_mpi_scan (&peer, GCRYMPI_FMT_USG, buffer, n_buffer, NULL);
|
||||||
|
g_return_val_if_fail (gcry == 0, FALSE);
|
||||||
|
g_variant_unref (argument);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
g_printerr (" lib publi: ");
|
||||||
|
gcry_mpi_dump (session->publi);
|
||||||
|
g_printerr ("\n lib peer: ");
|
||||||
|
gcry_mpi_dump (peer);
|
||||||
|
g_printerr ("\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ikm = egg_dh_gen_secret (peer, session->privat, session->prime, &n_ikm);
|
||||||
|
gcry_mpi_release (peer);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
g_printerr (" lib ikm: %s\n", egg_hex_encode (ikm, n_ikm));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (ikm == NULL) {
|
||||||
|
g_warning ("couldn't negotiate a valid AES session key");
|
||||||
|
g_free (session->path);
|
||||||
|
session->path = NULL;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
session->n_key = 16;
|
||||||
|
session->key = egg_secure_alloc (session->n_key);
|
||||||
|
if (!egg_hkdf_perform ("sha256", ikm, n_ikm, NULL, 0, NULL, 0,
|
||||||
|
session->key, session->n_key))
|
||||||
|
g_return_val_if_reached (FALSE);
|
||||||
|
egg_secure_free (ikm);
|
||||||
|
|
||||||
|
session->algorithms = ALGORITHMS_AES;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* WITH_GCRYPT */
|
||||||
|
|
||||||
|
static GVariant *
|
||||||
|
request_open_session_plain (GSecretSession *session)
|
||||||
|
{
|
||||||
|
GVariant *argument = g_variant_new_string ("");
|
||||||
|
return g_variant_new ("(sv)", "plain", argument);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
response_open_session_plain (GSecretSession *session,
|
||||||
|
GVariant *response)
|
||||||
|
{
|
||||||
|
GVariant *argument;
|
||||||
|
const gchar *sig;
|
||||||
|
|
||||||
|
sig = g_variant_get_type_string (response);
|
||||||
|
g_return_val_if_fail (sig != NULL, FALSE);
|
||||||
|
|
||||||
|
if (!g_str_equal (sig, "(vo)")) {
|
||||||
|
g_warning ("invalid OpenSession() response from daemon with signature: %s",
|
||||||
|
g_variant_get_type_string (response));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_assert (session->path == NULL);
|
||||||
|
g_variant_get (response, "(vo)", &argument, &session->path);
|
||||||
|
g_variant_unref (argument);
|
||||||
|
|
||||||
|
g_assert (session->key == NULL);
|
||||||
|
g_assert (session->n_key == 0);
|
||||||
|
|
||||||
|
session->algorithms = ALGORITHMS_PLAIN;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
GCancellable *cancellable;
|
||||||
|
GSecretSession *session;
|
||||||
|
} OpenSessionClosure;
|
||||||
|
|
||||||
|
static void
|
||||||
|
open_session_closure_free (gpointer data)
|
||||||
|
{
|
||||||
|
OpenSessionClosure *closure = data;
|
||||||
|
g_assert (closure);
|
||||||
|
g_clear_object (&closure->cancellable);
|
||||||
|
_gsecret_session_free (closure->session);
|
||||||
|
g_free (closure);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_service_open_session_plain (GObject *source,
|
||||||
|
GAsyncResult *result,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
|
||||||
|
OpenSessionClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
|
||||||
|
GSecretService *service = GSECRET_SERVICE (source);
|
||||||
|
GError *error = NULL;
|
||||||
|
GVariant *response;
|
||||||
|
|
||||||
|
response = g_dbus_proxy_call_finish (G_DBUS_PROXY (service), result, &error);
|
||||||
|
|
||||||
|
/* A successful response, decode it */
|
||||||
|
if (response != NULL) {
|
||||||
|
if (response_open_session_plain (closure->session, response)) {
|
||||||
|
_gsecret_service_take_session (service, closure->session);
|
||||||
|
closure->session = NULL;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
g_simple_async_result_set_error (res, GSECRET_ERROR, GSECRET_ERROR_PROTOCOL,
|
||||||
|
_("Couldn't communicate with the secret storage"));
|
||||||
|
}
|
||||||
|
|
||||||
|
g_simple_async_result_complete (res);
|
||||||
|
g_variant_unref (response);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
g_simple_async_result_take_error (res, error);
|
||||||
|
g_simple_async_result_complete (res);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_object_unref (res);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef WITH_GCRYPT
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_service_open_session_aes (GObject *source,
|
||||||
|
GAsyncResult *result,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
|
||||||
|
OpenSessionClosure * closure = g_simple_async_result_get_op_res_gpointer (res);
|
||||||
|
GSecretService *service = GSECRET_SERVICE (source);
|
||||||
|
GError *error = NULL;
|
||||||
|
GVariant *response;
|
||||||
|
|
||||||
|
response = g_dbus_proxy_call_finish (G_DBUS_PROXY (service), result, &error);
|
||||||
|
|
||||||
|
/* A successful response, decode it */
|
||||||
|
if (response != NULL) {
|
||||||
|
if (response_open_session_aes (closure->session, response)) {
|
||||||
|
_gsecret_service_take_session (service, closure->session);
|
||||||
|
closure->session = NULL;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
g_simple_async_result_set_error (res, GSECRET_ERROR, GSECRET_ERROR_PROTOCOL,
|
||||||
|
_("Couldn't communicate with the secret storage"));
|
||||||
|
}
|
||||||
|
|
||||||
|
g_simple_async_result_complete (res);
|
||||||
|
g_variant_unref (response);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
/* AES session not supported, request a plain session */
|
||||||
|
if (g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_NOT_SUPPORTED)) {
|
||||||
|
g_dbus_proxy_call (G_DBUS_PROXY (source), "OpenSession",
|
||||||
|
request_open_session_plain (closure->session),
|
||||||
|
G_DBUS_CALL_FLAGS_NONE, -1,
|
||||||
|
closure->cancellable, on_service_open_session_plain,
|
||||||
|
g_object_ref (res));
|
||||||
|
g_error_free (error);
|
||||||
|
|
||||||
|
/* Other errors result in a failure */
|
||||||
|
} else {
|
||||||
|
g_simple_async_result_take_error (res, error);
|
||||||
|
g_simple_async_result_complete (res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
g_object_unref (res);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* WITH_GCRYPT */
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
_gsecret_session_open (GSecretService *service,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GAsyncReadyCallback callback,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
GSimpleAsyncResult *res;
|
||||||
|
OpenSessionClosure *closure;
|
||||||
|
|
||||||
|
res = g_simple_async_result_new (G_OBJECT (service), callback, user_data,
|
||||||
|
_gsecret_session_open);
|
||||||
|
closure = g_new (OpenSessionClosure, 1);
|
||||||
|
closure->cancellable = cancellable ? g_object_ref (cancellable) : cancellable;
|
||||||
|
closure->session = g_new0 (GSecretSession, 1);
|
||||||
|
g_simple_async_result_set_op_res_gpointer (res, closure, open_session_closure_free);
|
||||||
|
|
||||||
|
g_dbus_proxy_call (G_DBUS_PROXY (service), "OpenSession",
|
||||||
|
#ifdef WITH_GCRYPT
|
||||||
|
request_open_session_aes (closure->session),
|
||||||
|
G_DBUS_CALL_FLAGS_NONE, -1,
|
||||||
|
cancellable, on_service_open_session_aes,
|
||||||
|
#else
|
||||||
|
request_open_session_plain (closure->session),
|
||||||
|
G_DBUS_CALL_FLAGS_NONE, -1,
|
||||||
|
cancellable, on_service_open_session_plain,
|
||||||
|
#endif
|
||||||
|
g_object_ref (res));
|
||||||
|
|
||||||
|
g_object_unref (res);
|
||||||
|
}
|
||||||
|
|
||||||
|
GSecretSession *
|
||||||
|
_gsecret_session_open_finish (GAsyncResult *result,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
OpenSessionClosure *closure;
|
||||||
|
GSecretSession *session;
|
||||||
|
|
||||||
|
if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
closure = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result));
|
||||||
|
session = closure->session;
|
||||||
|
closure->session = NULL;
|
||||||
|
return session;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef WITH_GCRYPT
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
pkcs7_unpad_bytes_in_place (guchar *padded,
|
||||||
|
gsize *n_padded)
|
||||||
|
{
|
||||||
|
gsize n_pad, i;
|
||||||
|
|
||||||
|
if (*n_padded == 0)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
n_pad = padded[*n_padded - 1];
|
||||||
|
|
||||||
|
/* Validate the padding */
|
||||||
|
if (n_pad == 0 || n_pad > 16)
|
||||||
|
return FALSE;
|
||||||
|
if (n_pad > *n_padded)
|
||||||
|
return FALSE;
|
||||||
|
for (i = *n_padded - n_pad; i < *n_padded; ++i) {
|
||||||
|
if (padded[i] != n_pad)
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The last bit of data */
|
||||||
|
*n_padded -= n_pad;
|
||||||
|
|
||||||
|
/* Null teriminate as a courtesy */
|
||||||
|
padded[*n_padded] = 0;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GSecretValue *
|
||||||
|
service_decode_aes_secret (GSecretSession *session,
|
||||||
|
gconstpointer param,
|
||||||
|
gsize n_param,
|
||||||
|
gconstpointer value,
|
||||||
|
gsize n_value,
|
||||||
|
const gchar *content_type)
|
||||||
|
{
|
||||||
|
gcry_cipher_hd_t cih;
|
||||||
|
gsize n_padded;
|
||||||
|
gcry_error_t gcry;
|
||||||
|
guchar *padded;
|
||||||
|
gsize pos;
|
||||||
|
|
||||||
|
if (n_param != 16) {
|
||||||
|
g_message ("received an encrypted secret structure with invalid parameter");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n_value == 0 || n_value % 16 != 0) {
|
||||||
|
g_message ("received an encrypted secret structure with bad secret length");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
gcry = gcry_cipher_open (&cih, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_CBC, 0);
|
||||||
|
if (gcry != 0) {
|
||||||
|
g_warning ("couldn't create AES cipher: %s", gcry_strerror (gcry));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
g_printerr (" lib iv: %s\n", egg_hex_encode (param, n_param));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
gcry = gcry_cipher_setiv (cih, param, n_param);
|
||||||
|
g_return_val_if_fail (gcry == 0, NULL);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
g_printerr (" lib key: %s\n", egg_hex_encode (session->key, session->n_key));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
gcry = gcry_cipher_setkey (cih, session->key, session->n_key);
|
||||||
|
g_return_val_if_fail (gcry == 0, NULL);
|
||||||
|
|
||||||
|
/* Copy the memory buffer */
|
||||||
|
n_padded = n_value;
|
||||||
|
padded = egg_secure_alloc (n_padded);
|
||||||
|
memcpy (padded, value, n_padded);
|
||||||
|
|
||||||
|
/* Perform the decryption */
|
||||||
|
for (pos = 0; pos < n_padded; pos += 16) {
|
||||||
|
gcry = gcry_cipher_decrypt (cih, (guchar*)padded + pos, 16, NULL, 0);
|
||||||
|
g_return_val_if_fail (gcry == 0, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
gcry_cipher_close (cih);
|
||||||
|
|
||||||
|
/* Unpad the resulting value */
|
||||||
|
if (!pkcs7_unpad_bytes_in_place (padded, &n_padded)) {
|
||||||
|
egg_secure_clear (padded, n_padded);
|
||||||
|
egg_secure_free (padded);
|
||||||
|
g_message ("received an invalid or unencryptable secret");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return gsecret_value_new_full ((gchar *)padded, n_padded, content_type, egg_secure_free);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* WITH_GCRYPT */
|
||||||
|
|
||||||
|
static GSecretValue *
|
||||||
|
service_decode_plain_secret (GSecretSession *session,
|
||||||
|
gconstpointer param,
|
||||||
|
gsize n_param,
|
||||||
|
gconstpointer value,
|
||||||
|
gsize n_value,
|
||||||
|
const gchar *content_type)
|
||||||
|
{
|
||||||
|
if (n_param != 0) {
|
||||||
|
g_message ("received a plain secret structure with invalid parameter");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return gsecret_value_new (value, n_value, content_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
GSecretValue *
|
||||||
|
_gsecret_session_decode_secret (GSecretSession *session,
|
||||||
|
GVariant *encoded)
|
||||||
|
{
|
||||||
|
GSecretValue *result;
|
||||||
|
gconstpointer param;
|
||||||
|
gconstpointer value;
|
||||||
|
gchar *session_path;
|
||||||
|
gchar *content_type;
|
||||||
|
gsize n_param;
|
||||||
|
gsize n_value;
|
||||||
|
GVariant *vparam;
|
||||||
|
GVariant *vvalue;
|
||||||
|
|
||||||
|
g_return_val_if_fail (session != NULL, NULL);
|
||||||
|
g_return_val_if_fail (encoded != NULL, NULL);
|
||||||
|
|
||||||
|
/* Parsing (oayays) */
|
||||||
|
g_variant_get_child (encoded, 0, "o", &session_path);
|
||||||
|
|
||||||
|
if (session_path == NULL || !g_str_equal (session_path, session->path)) {
|
||||||
|
g_message ("received a secret encoded with wrong session: %s != %s",
|
||||||
|
session_path, session->path);
|
||||||
|
g_free (session_path);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
vparam = g_variant_get_child_value (encoded, 1);
|
||||||
|
param = g_variant_get_fixed_array (vparam, &n_param, sizeof (guchar));
|
||||||
|
vvalue = g_variant_get_child_value (encoded, 2);
|
||||||
|
value = g_variant_get_fixed_array (vvalue, &n_value, sizeof (guchar));
|
||||||
|
g_variant_get_child (encoded, 3, "s", &content_type);
|
||||||
|
|
||||||
|
#ifdef WITH_GCRYPT
|
||||||
|
if (session->key != NULL)
|
||||||
|
result = service_decode_aes_secret (session, param, n_param,
|
||||||
|
value, n_value, content_type);
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
result = service_decode_plain_secret (session, param, n_param,
|
||||||
|
value, n_value, content_type);
|
||||||
|
|
||||||
|
g_variant_unref (vparam);
|
||||||
|
g_variant_unref (vvalue);
|
||||||
|
g_free (content_type);
|
||||||
|
g_free (session_path);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef WITH_GCRYPT
|
||||||
|
|
||||||
|
static guchar*
|
||||||
|
pkcs7_pad_bytes_in_secure_memory (gconstpointer secret,
|
||||||
|
gsize length,
|
||||||
|
gsize *n_padded)
|
||||||
|
{
|
||||||
|
gsize n_pad;
|
||||||
|
guchar *padded;
|
||||||
|
|
||||||
|
/* Pad the secret */
|
||||||
|
*n_padded = ((length + 16) / 16) * 16;
|
||||||
|
g_assert (length < *n_padded);
|
||||||
|
g_assert (*n_padded > 0);
|
||||||
|
n_pad = *n_padded - length;
|
||||||
|
g_assert (n_pad > 0 && n_pad <= 16);
|
||||||
|
padded = egg_secure_alloc (*n_padded);
|
||||||
|
memcpy (padded, secret, length);
|
||||||
|
memset (padded + length, n_pad, n_pad);
|
||||||
|
return padded;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
service_encode_aes_secret (GSecretSession *session,
|
||||||
|
GSecretValue *value,
|
||||||
|
GVariantBuilder *builder)
|
||||||
|
{
|
||||||
|
gcry_cipher_hd_t cih;
|
||||||
|
guchar *padded;
|
||||||
|
gsize n_padded, pos;
|
||||||
|
gcry_error_t gcry;
|
||||||
|
gpointer iv;
|
||||||
|
gconstpointer secret;
|
||||||
|
gsize n_secret;
|
||||||
|
GVariant *child;
|
||||||
|
|
||||||
|
g_variant_builder_add (builder, "o", session->path);
|
||||||
|
|
||||||
|
/* Create the cipher */
|
||||||
|
gcry = gcry_cipher_open (&cih, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_CBC, 0);
|
||||||
|
if (gcry != 0) {
|
||||||
|
g_warning ("couldn't create AES cipher: %s", gcry_strerror (gcry));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
secret = gsecret_value_get (value, &n_secret);
|
||||||
|
|
||||||
|
/* Perform the encoding here */
|
||||||
|
padded = pkcs7_pad_bytes_in_secure_memory (secret, n_secret, &n_padded);
|
||||||
|
g_assert (padded != NULL);
|
||||||
|
|
||||||
|
/* Setup the IV */
|
||||||
|
iv = g_malloc0 (16);
|
||||||
|
gcry_create_nonce (iv, 16);
|
||||||
|
gcry = gcry_cipher_setiv (cih, iv, 16);
|
||||||
|
g_return_val_if_fail (gcry == 0, FALSE);
|
||||||
|
|
||||||
|
/* Setup the key */
|
||||||
|
gcry = gcry_cipher_setkey (cih, session->key, session->n_key);
|
||||||
|
g_return_val_if_fail (gcry == 0, FALSE);
|
||||||
|
|
||||||
|
/* Perform the encryption */
|
||||||
|
for (pos = 0; pos < n_padded; pos += 16) {
|
||||||
|
gcry = gcry_cipher_encrypt (cih, (guchar*)padded + pos, 16, NULL, 0);
|
||||||
|
g_return_val_if_fail (gcry == 0, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
gcry_cipher_close (cih);
|
||||||
|
|
||||||
|
child = g_variant_new_from_data (G_VARIANT_TYPE ("ay"), iv, 16, TRUE, g_free, iv);
|
||||||
|
g_variant_builder_add_value (builder, child);
|
||||||
|
g_variant_unref (child);
|
||||||
|
|
||||||
|
child = g_variant_new_from_data (G_VARIANT_TYPE ("ay"), padded, n_padded, TRUE, egg_secure_free, padded);
|
||||||
|
g_variant_builder_add_value (builder, child);
|
||||||
|
g_variant_unref (child);
|
||||||
|
|
||||||
|
g_variant_builder_add (builder, "s", gsecret_value_get_content_type (value));
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* WITH_GCRYPT */
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
service_encode_plain_secret (GSecretSession *session,
|
||||||
|
GSecretValue *value,
|
||||||
|
GVariantBuilder *builder)
|
||||||
|
{
|
||||||
|
gconstpointer secret;
|
||||||
|
gsize n_secret;
|
||||||
|
GVariant *child;
|
||||||
|
|
||||||
|
g_variant_builder_add (builder, "o", session->path);
|
||||||
|
|
||||||
|
secret = gsecret_value_get (value, &n_secret);
|
||||||
|
|
||||||
|
child = g_variant_new_from_data (G_VARIANT_TYPE ("ay"), "", 0, TRUE, NULL, NULL);
|
||||||
|
g_variant_builder_add_value (builder, child);
|
||||||
|
g_variant_unref (child);
|
||||||
|
|
||||||
|
child = g_variant_new_from_data (G_VARIANT_TYPE ("ay"), secret, n_secret, TRUE,
|
||||||
|
gsecret_value_unref, gsecret_value_ref (value));
|
||||||
|
g_variant_builder_add_value (builder, child);
|
||||||
|
g_variant_unref (child);
|
||||||
|
|
||||||
|
g_variant_builder_add (builder, "s", gsecret_value_get_content_type (value));
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
GVariant *
|
||||||
|
_gsecret_session_encode_secret (GSecretSession *session,
|
||||||
|
GSecretValue *value)
|
||||||
|
{
|
||||||
|
GVariantBuilder *builder;
|
||||||
|
GVariant *result = NULL;
|
||||||
|
GVariantType *type;
|
||||||
|
gboolean ret;
|
||||||
|
|
||||||
|
g_return_val_if_fail (session != NULL, NULL);
|
||||||
|
g_return_val_if_fail (value != NULL, NULL);
|
||||||
|
|
||||||
|
type = g_variant_type_new ("(oayays)");
|
||||||
|
builder = g_variant_builder_new (type);
|
||||||
|
|
||||||
|
#ifdef WITH_GCRYPT
|
||||||
|
if (session->key)
|
||||||
|
ret = service_encode_aes_secret (session, value, builder);
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
ret = service_encode_plain_secret (session, value, builder);
|
||||||
|
if (ret)
|
||||||
|
result = g_variant_builder_end (builder);
|
||||||
|
|
||||||
|
g_variant_builder_unref (builder);
|
||||||
|
g_variant_type_free (type);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
const gchar *
|
||||||
|
_gsecret_session_get_algorithms (GSecretSession *session)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (session != NULL, NULL);
|
||||||
|
return session->algorithms;
|
||||||
|
}
|
||||||
|
|
||||||
|
const gchar *
|
||||||
|
_gsecret_session_get_path (GSecretSession *session)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (session != NULL, NULL);
|
||||||
|
return session->path;
|
||||||
|
}
|
@ -118,7 +118,7 @@ _gsecret_util_attributes_for_variant (GVariant *variant)
|
|||||||
attributes = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
|
attributes = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
|
||||||
|
|
||||||
g_variant_iter_init (&iter, variant);
|
g_variant_iter_init (&iter, variant);
|
||||||
while (g_variant_iter_next (&iter, "{sv}", &key, &value))
|
while (g_variant_iter_next (&iter, "{ss}", &key, &value))
|
||||||
g_hash_table_insert (attributes, key, value);
|
g_hash_table_insert (attributes, key, value);
|
||||||
|
|
||||||
return attributes;
|
return attributes;
|
||||||
@ -288,6 +288,20 @@ _gsecret_util_get_properties_finish (GDBusProxy *proxy,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
gchar *property;
|
||||||
|
GVariant *value;
|
||||||
|
gboolean result;
|
||||||
|
} SetClosure;
|
||||||
|
|
||||||
|
static void
|
||||||
|
set_closure_free (gpointer data)
|
||||||
|
{
|
||||||
|
SetClosure *closure = data;
|
||||||
|
g_free (closure->property);
|
||||||
|
g_variant_unref (closure->value);
|
||||||
|
g_slice_free (SetClosure, closure);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
on_set_property (GObject *source,
|
on_set_property (GObject *source,
|
||||||
@ -295,6 +309,8 @@ on_set_property (GObject *source,
|
|||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
|
GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
|
||||||
|
SetClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
|
||||||
|
GDBusProxy *proxy = G_DBUS_PROXY (g_async_result_get_source_object (user_data));
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
GVariant *retval;
|
GVariant *retval;
|
||||||
|
|
||||||
@ -304,7 +320,13 @@ on_set_property (GObject *source,
|
|||||||
g_simple_async_result_take_error (res, error);
|
g_simple_async_result_take_error (res, error);
|
||||||
if (retval != NULL)
|
if (retval != NULL)
|
||||||
g_variant_unref (retval);
|
g_variant_unref (retval);
|
||||||
g_simple_async_result_set_op_res_gboolean (res, retval != NULL);
|
|
||||||
|
closure->result = retval != NULL;
|
||||||
|
if (closure->result)
|
||||||
|
g_dbus_proxy_set_cached_property (proxy, closure->property, closure->value);
|
||||||
|
|
||||||
|
g_simple_async_result_complete (res);
|
||||||
|
g_object_unref (proxy);
|
||||||
g_object_unref (res);
|
g_object_unref (res);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -318,10 +340,15 @@ _gsecret_util_set_property (GDBusProxy *proxy,
|
|||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
GSimpleAsyncResult *res;
|
GSimpleAsyncResult *res;
|
||||||
|
SetClosure *closure;
|
||||||
|
|
||||||
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
|
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
|
||||||
|
|
||||||
res = g_simple_async_result_new (G_OBJECT (proxy), callback, user_data, result_tag);
|
res = g_simple_async_result_new (G_OBJECT (proxy), callback, user_data, result_tag);
|
||||||
|
closure = g_slice_new0 (SetClosure);
|
||||||
|
closure->property = g_strdup (property);
|
||||||
|
closure->value = g_variant_ref_sink (value);
|
||||||
|
g_simple_async_result_set_op_res_gpointer (res, closure, set_closure_free);
|
||||||
|
|
||||||
g_dbus_connection_call (g_dbus_proxy_get_connection (proxy),
|
g_dbus_connection_call (g_dbus_proxy_get_connection (proxy),
|
||||||
g_dbus_proxy_get_name (proxy),
|
g_dbus_proxy_get_name (proxy),
|
||||||
@ -331,7 +358,7 @@ _gsecret_util_set_property (GDBusProxy *proxy,
|
|||||||
g_variant_new ("(ssv)",
|
g_variant_new ("(ssv)",
|
||||||
g_dbus_proxy_get_interface_name (proxy),
|
g_dbus_proxy_get_interface_name (proxy),
|
||||||
property,
|
property,
|
||||||
value),
|
closure->value),
|
||||||
G_VARIANT_TYPE ("()"),
|
G_VARIANT_TYPE ("()"),
|
||||||
G_DBUS_CALL_FLAGS_NO_AUTO_START, -1,
|
G_DBUS_CALL_FLAGS_NO_AUTO_START, -1,
|
||||||
cancellable, on_set_property,
|
cancellable, on_set_property,
|
||||||
@ -347,6 +374,7 @@ _gsecret_util_set_property_finish (GDBusProxy *proxy,
|
|||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
GSimpleAsyncResult *res;
|
GSimpleAsyncResult *res;
|
||||||
|
SetClosure *closure;
|
||||||
|
|
||||||
g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (proxy), result_tag), FALSE);
|
g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (proxy), result_tag), FALSE);
|
||||||
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
||||||
@ -356,7 +384,8 @@ _gsecret_util_set_property_finish (GDBusProxy *proxy,
|
|||||||
if (g_simple_async_result_propagate_error (res, error))
|
if (g_simple_async_result_propagate_error (res, error))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
return g_simple_async_result_get_op_res_gboolean (res);
|
closure = g_simple_async_result_get_op_res_gpointer (res);
|
||||||
|
return closure->result;
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
@ -366,11 +395,14 @@ _gsecret_util_set_property_sync (GDBusProxy *proxy,
|
|||||||
GCancellable *cancellable,
|
GCancellable *cancellable,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
|
gboolean result = FALSE;
|
||||||
GVariant *retval;
|
GVariant *retval;
|
||||||
|
|
||||||
g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
|
g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
|
||||||
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
||||||
|
|
||||||
|
g_variant_ref_sink (value);
|
||||||
|
|
||||||
retval = g_dbus_connection_call_sync (g_dbus_proxy_get_connection (proxy),
|
retval = g_dbus_connection_call_sync (g_dbus_proxy_get_connection (proxy),
|
||||||
g_dbus_proxy_get_name (proxy),
|
g_dbus_proxy_get_name (proxy),
|
||||||
g_dbus_proxy_get_object_path (proxy),
|
g_dbus_proxy_get_object_path (proxy),
|
||||||
@ -384,10 +416,26 @@ _gsecret_util_set_property_sync (GDBusProxy *proxy,
|
|||||||
G_DBUS_CALL_FLAGS_NO_AUTO_START, -1,
|
G_DBUS_CALL_FLAGS_NO_AUTO_START, -1,
|
||||||
cancellable, error);
|
cancellable, error);
|
||||||
|
|
||||||
if (retval != NULL)
|
if (retval != NULL) {
|
||||||
|
result = TRUE;
|
||||||
g_variant_unref (retval);
|
g_variant_unref (retval);
|
||||||
|
g_dbus_proxy_set_cached_property (proxy, property, value);
|
||||||
|
}
|
||||||
|
|
||||||
return (retval != NULL);
|
g_variant_unref (value);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
_gsecret_util_have_cached_properties (GDBusProxy *proxy)
|
||||||
|
{
|
||||||
|
gchar **names;
|
||||||
|
|
||||||
|
names = g_dbus_proxy_get_cached_property_names (proxy);
|
||||||
|
g_strfreev (names);
|
||||||
|
|
||||||
|
return names != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
GSecretSync *
|
GSecretSync *
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
#define GSECRET_TYPE_VALUE (gsecret_service_get_type ())
|
#define GSECRET_TYPE_VALUE (gsecret_value_get_type ())
|
||||||
|
|
||||||
GType gsecret_value_get_type (void) G_GNUC_CONST;
|
GType gsecret_value_get_type (void) G_GNUC_CONST;
|
||||||
|
|
||||||
|
@ -26,10 +26,13 @@ LDADD = \
|
|||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
TEST_PROGS = \
|
TEST_PROGS = \
|
||||||
|
test-value \
|
||||||
test-prompt \
|
test-prompt \
|
||||||
test-service \
|
test-service \
|
||||||
test-session \
|
test-session \
|
||||||
test-password \
|
test-password \
|
||||||
|
test-item \
|
||||||
|
test-collection \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
check_PROGRAMS = \
|
check_PROGRAMS = \
|
||||||
|
@ -149,8 +149,9 @@ class SecretSession(dbus.service.Object):
|
|||||||
(params, data) = self.algorithm.encrypt(self.key, secret)
|
(params, data) = self.algorithm.encrypt(self.key, secret)
|
||||||
# print " mock iv: ", hex_encode(params)
|
# print " mock iv: ", hex_encode(params)
|
||||||
# print " mock ciph: ", hex_encode(data)
|
# print " mock ciph: ", hex_encode(data)
|
||||||
return dbus.Struct((self.path, dbus.ByteArray(params), dbus.ByteArray(data),
|
return dbus.Struct((dbus.ObjectPath(self.path), dbus.ByteArray(params),
|
||||||
dbus.String(content_type)), signature="oayays")
|
dbus.ByteArray(data), dbus.String(content_type)),
|
||||||
|
signature="oayays")
|
||||||
|
|
||||||
@dbus.service.method('org.freedesktop.Secret.Session')
|
@dbus.service.method('org.freedesktop.Secret.Session')
|
||||||
def Close(self):
|
def Close(self):
|
||||||
@ -167,9 +168,9 @@ class SecretItem(dbus.service.Object):
|
|||||||
self.secret = secret
|
self.secret = secret
|
||||||
self.attributes = attributes
|
self.attributes = attributes
|
||||||
self.content_type = content_type
|
self.content_type = content_type
|
||||||
self.locked = collection.locked
|
|
||||||
self.path = "%s/%s" % (collection.path, identifier)
|
self.path = "%s/%s" % (collection.path, identifier)
|
||||||
self.confirm = confirm
|
self.confirm = confirm
|
||||||
|
self.created = self.modified = time.time()
|
||||||
dbus.service.Object.__init__(self, collection.service.bus_name, self.path)
|
dbus.service.Object.__init__(self, collection.service.bus_name, self.path)
|
||||||
collection.items[identifier] = self
|
collection.items[identifier] = self
|
||||||
objects[self.path] = self
|
objects[self.path] = self
|
||||||
@ -183,13 +184,14 @@ class SecretItem(dbus.service.Object):
|
|||||||
def perform_delete(self):
|
def perform_delete(self):
|
||||||
del self.collection.items[self.identifier]
|
del self.collection.items[self.identifier]
|
||||||
del objects[self.path]
|
del objects[self.path]
|
||||||
|
self.remove_from_connection()
|
||||||
|
|
||||||
@dbus.service.method('org.freedesktop.Secret.Item', sender_keyword='sender')
|
@dbus.service.method('org.freedesktop.Secret.Item', sender_keyword='sender')
|
||||||
def GetSecret(self, session_path, sender=None):
|
def GetSecret(self, session_path, sender=None):
|
||||||
session = objects.get(session_path, None)
|
session = objects.get(session_path, None)
|
||||||
if not session or session.sender != sender:
|
if not session or session.sender != sender:
|
||||||
raise InvalidArgs("session invalid: %s" % session_path)
|
raise InvalidArgs("session invalid: %s" % session_path)
|
||||||
if self.locked:
|
if self.collection.locked:
|
||||||
raise IsLocked("secret is locked: %s" % self.path)
|
raise IsLocked("secret is locked: %s" % self.path)
|
||||||
return session.encode_secret(self.secret, self.content_type)
|
return session.encode_secret(self.secret, self.content_type)
|
||||||
|
|
||||||
@ -203,14 +205,49 @@ class SecretItem(dbus.service.Object):
|
|||||||
self.perform_delete()
|
self.perform_delete()
|
||||||
return dbus.ObjectPath("/")
|
return dbus.ObjectPath("/")
|
||||||
|
|
||||||
|
@dbus.service.method(dbus.PROPERTIES_IFACE, in_signature='ss', out_signature='v')
|
||||||
|
def Get(self, interface_name, property_name):
|
||||||
|
return self.GetAll(interface_name)[property_name]
|
||||||
|
|
||||||
|
@dbus.service.method(dbus.PROPERTIES_IFACE, in_signature='s', out_signature='a{sv}')
|
||||||
|
def GetAll(self, interface_name):
|
||||||
|
if interface_name == 'org.freedesktop.Secret.Item':
|
||||||
|
return {
|
||||||
|
'Locked': self.collection.locked,
|
||||||
|
'Attributes': dbus.Dictionary(self.attributes, signature='ss'),
|
||||||
|
'Label': self.label,
|
||||||
|
'Created': dbus.UInt64(self.created),
|
||||||
|
'Modified': dbus.UInt64(self.modified)
|
||||||
|
}
|
||||||
|
else:
|
||||||
|
raise InvalidArgs('Unknown %s interface' % interface_name)
|
||||||
|
|
||||||
|
@dbus.service.method(dbus.PROPERTIES_IFACE, in_signature='ssv')
|
||||||
|
def Set(self, interface_name, property_name, new_value):
|
||||||
|
if interface_name != 'org.freedesktop.Secret.Item':
|
||||||
|
raise InvalidArgs('Unknown %s interface' % interface_name)
|
||||||
|
if property_name == "Label":
|
||||||
|
self.label = str(new_value)
|
||||||
|
elif property_name == "Attributes":
|
||||||
|
self.attributes = dict(new_value)
|
||||||
|
else:
|
||||||
|
raise InvalidArgs('Unknown %s interface' % property_name)
|
||||||
|
self.PropertiesChanged(interface_name, { property_name: new_value }, [])
|
||||||
|
|
||||||
|
@dbus.service.signal(dbus.PROPERTIES_IFACE, signature='sa{sv}as')
|
||||||
|
def PropertiesChanged(self, interface_name, changed_properties, invalidated_properties):
|
||||||
|
self.modified = time.time()
|
||||||
|
|
||||||
|
|
||||||
class SecretCollection(dbus.service.Object):
|
class SecretCollection(dbus.service.Object):
|
||||||
def __init__(self, service, identifier, label="Collection", locked=False):
|
def __init__(self, service, identifier, label="Collection", locked=False, confirm=False):
|
||||||
self.service = service
|
self.service = service
|
||||||
self.identifier = identifier
|
self.identifier = identifier
|
||||||
self.label = label
|
self.label = label
|
||||||
self.locked = locked
|
self.locked = locked
|
||||||
self.items = { }
|
self.items = { }
|
||||||
|
self.confirm = confirm
|
||||||
|
self.created = self.modified = time.time()
|
||||||
self.path = "%s%s" % (COLLECTION_PREFIX, identifier)
|
self.path = "%s%s" % (COLLECTION_PREFIX, identifier)
|
||||||
dbus.service.Object.__init__(self, service.bus_name, self.path)
|
dbus.service.Object.__init__(self, service.bus_name, self.path)
|
||||||
service.collections[identifier] = self
|
service.collections[identifier] = self
|
||||||
@ -223,6 +260,54 @@ class SecretCollection(dbus.service.Object):
|
|||||||
results.append(item)
|
results.append(item)
|
||||||
return results
|
return results
|
||||||
|
|
||||||
|
def perform_delete(self):
|
||||||
|
for item in self.items.values():
|
||||||
|
item.perform_delete()
|
||||||
|
del self.service.collections[self.identifier]
|
||||||
|
del objects[self.path]
|
||||||
|
self.remove_from_connection()
|
||||||
|
|
||||||
|
@dbus.service.method('org.freedesktop.Secret.Collection', sender_keyword='sender')
|
||||||
|
def Delete(self, sender=None):
|
||||||
|
if self.confirm:
|
||||||
|
prompt = SecretPrompt(self.collection.service, sender,
|
||||||
|
dismiss=False, action=self.perform_delete)
|
||||||
|
return dbus.ObjectPath(prompt.path)
|
||||||
|
else:
|
||||||
|
self.perform_delete()
|
||||||
|
return dbus.ObjectPath("/")
|
||||||
|
|
||||||
|
@dbus.service.method(dbus.PROPERTIES_IFACE, in_signature='ss', out_signature='v')
|
||||||
|
def Get(self, interface_name, property_name):
|
||||||
|
return self.GetAll(interface_name)[property_name]
|
||||||
|
|
||||||
|
@dbus.service.method(dbus.PROPERTIES_IFACE, in_signature='s', out_signature='a{sv}')
|
||||||
|
def GetAll(self, interface_name):
|
||||||
|
if interface_name == 'org.freedesktop.Secret.Collection':
|
||||||
|
return {
|
||||||
|
'Locked': self.locked,
|
||||||
|
'Label': self.label,
|
||||||
|
'Created': dbus.UInt64(self.created),
|
||||||
|
'Modified': dbus.UInt64(self.modified),
|
||||||
|
'Items': [dbus.ObjectPath(i.path) for i in self.items.values()]
|
||||||
|
}
|
||||||
|
else:
|
||||||
|
raise InvalidArgs('Unknown %s interface' % interface_name)
|
||||||
|
|
||||||
|
@dbus.service.method(dbus.PROPERTIES_IFACE, in_signature='ssv')
|
||||||
|
def Set(self, interface_name, property_name, new_value):
|
||||||
|
if interface_name != 'org.freedesktop.Secret.Collection':
|
||||||
|
raise InvalidArgs('Unknown %s interface' % interface_name)
|
||||||
|
if property_name == "Label":
|
||||||
|
self.label = str(new_value)
|
||||||
|
else:
|
||||||
|
raise InvalidArgs('Unknown %s interface' % property_name)
|
||||||
|
self.PropertiesChanged(interface_name, { property_name: new_value }, [])
|
||||||
|
|
||||||
|
@dbus.service.signal(dbus.PROPERTIES_IFACE, signature='sa{sv}as')
|
||||||
|
def PropertiesChanged(self, interface_name, changed_properties, invalidated_properties):
|
||||||
|
self.modified = time.time()
|
||||||
|
|
||||||
|
|
||||||
class SecretService(dbus.service.Object):
|
class SecretService(dbus.service.Object):
|
||||||
|
|
||||||
@ -251,8 +336,8 @@ class SecretService(dbus.service.Object):
|
|||||||
'org.freedesktop.DBus')
|
'org.freedesktop.DBus')
|
||||||
|
|
||||||
def add_standard_objects(self):
|
def add_standard_objects(self):
|
||||||
collection = SecretCollection(self, "collection", locked=False)
|
collection = SecretCollection(self, "collection", label="Collection One", locked=False)
|
||||||
SecretItem(collection, "item_one", attributes={ "number": "1", "string": "one", "parity": "odd" }, secret="uno")
|
SecretItem(collection, "item_one", label="Item One", attributes={ "number": "1", "string": "one", "parity": "odd" }, secret="uno")
|
||||||
SecretItem(collection, "item_two", attributes={ "number": "2", "string": "two", "parity": "even" }, secret="dos")
|
SecretItem(collection, "item_two", attributes={ "number": "2", "string": "two", "parity": "even" }, secret="dos")
|
||||||
SecretItem(collection, "item_three", attributes={ "number": "3", "string": "three", "parity": "odd" }, secret="tres")
|
SecretItem(collection, "item_three", attributes={ "number": "3", "string": "three", "parity": "odd" }, secret="tres")
|
||||||
|
|
||||||
@ -323,7 +408,7 @@ class SecretService(dbus.service.Object):
|
|||||||
results = dbus.Dictionary(signature="o(oayays)")
|
results = dbus.Dictionary(signature="o(oayays)")
|
||||||
for item_path in item_paths:
|
for item_path in item_paths:
|
||||||
item = objects.get(item_path, None)
|
item = objects.get(item_path, None)
|
||||||
if item and not item.locked:
|
if item and not item.collection.locked:
|
||||||
results[item_path] = item.GetSecret(session_path, sender)
|
results[item_path] = item.GetSecret(session_path, sender)
|
||||||
return results
|
return results
|
||||||
|
|
||||||
|
339
library/tests/test-collection.c
Normal file
339
library/tests/test-collection.c
Normal file
@ -0,0 +1,339 @@
|
|||||||
|
/* GSecret - GLib wrapper for Secret Service
|
||||||
|
*
|
||||||
|
* Copyright 2012 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 of the licence or (at
|
||||||
|
* your option) any later version.
|
||||||
|
*
|
||||||
|
* See the included COPYING file for more information.
|
||||||
|
*
|
||||||
|
* Author: Stef Walter <stefw@gnome.org>
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "gsecret-collection.h"
|
||||||
|
#include "gsecret-service.h"
|
||||||
|
#include "gsecret-private.h"
|
||||||
|
|
||||||
|
#include "mock-service.h"
|
||||||
|
|
||||||
|
#include "egg/egg-testing.h"
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
GDBusConnection *connection;
|
||||||
|
GSecretService *service;
|
||||||
|
} Test;
|
||||||
|
|
||||||
|
static void
|
||||||
|
setup (Test *test,
|
||||||
|
gconstpointer data)
|
||||||
|
{
|
||||||
|
GError *error = NULL;
|
||||||
|
const gchar *mock_script = data;
|
||||||
|
|
||||||
|
mock_service_start (mock_script, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
|
||||||
|
test->connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
|
||||||
|
test->service = _gsecret_service_bare_instance (test->connection, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
teardown (Test *test,
|
||||||
|
gconstpointer unused)
|
||||||
|
{
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
|
g_object_unref (test->service);
|
||||||
|
egg_assert_not_object (test->service);
|
||||||
|
|
||||||
|
mock_service_stop ();
|
||||||
|
|
||||||
|
g_dbus_connection_flush_sync (test->connection, NULL, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
g_object_unref (test->connection);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_async_result (GObject *source,
|
||||||
|
GAsyncResult *result,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
GAsyncResult **ret = user_data;
|
||||||
|
g_assert (ret != NULL);
|
||||||
|
g_assert (*ret == NULL);
|
||||||
|
*ret = g_object_ref (result);
|
||||||
|
egg_test_wait_stop ();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_notify_stop (GObject *obj,
|
||||||
|
GParamSpec *spec,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
guint *sigs = user_data;
|
||||||
|
g_assert (sigs != NULL);
|
||||||
|
g_assert (*sigs > 0);
|
||||||
|
if (--(*sigs) == 0)
|
||||||
|
egg_test_wait_stop ();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_new_sync (Test *test,
|
||||||
|
gconstpointer unused)
|
||||||
|
{
|
||||||
|
const gchar *collection_path = "/org/freedesktop/secrets/collection/collection";
|
||||||
|
GError *error = NULL;
|
||||||
|
GSecretCollection *collection;
|
||||||
|
|
||||||
|
collection = gsecret_collection_new_sync (test->service, collection_path, NULL, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
|
||||||
|
g_assert_cmpstr (g_dbus_proxy_get_object_path (G_DBUS_PROXY (collection)), ==, collection_path);
|
||||||
|
|
||||||
|
g_object_unref (collection);
|
||||||
|
egg_assert_not_object (collection);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_new_async (Test *test,
|
||||||
|
gconstpointer unused)
|
||||||
|
{
|
||||||
|
const gchar *collection_path = "/org/freedesktop/secrets/collection/collection";
|
||||||
|
GError *error = NULL;
|
||||||
|
GSecretCollection *collection;
|
||||||
|
GAsyncResult *result = NULL;
|
||||||
|
|
||||||
|
gsecret_collection_new (test->service, collection_path, NULL, on_async_result, &result);
|
||||||
|
g_assert (result == NULL);
|
||||||
|
|
||||||
|
egg_test_wait ();
|
||||||
|
|
||||||
|
collection = gsecret_collection_new_finish (result, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
g_object_unref (result);
|
||||||
|
|
||||||
|
g_assert_cmpstr (g_dbus_proxy_get_object_path (G_DBUS_PROXY (collection)), ==, collection_path);
|
||||||
|
|
||||||
|
g_object_unref (collection);
|
||||||
|
egg_assert_not_object (collection);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_properties (Test *test,
|
||||||
|
gconstpointer unused)
|
||||||
|
{
|
||||||
|
const gchar *collection_path = "/org/freedesktop/secrets/collection/collection";
|
||||||
|
GError *error = NULL;
|
||||||
|
GSecretCollection *collection;
|
||||||
|
guint64 created;
|
||||||
|
guint64 modified;
|
||||||
|
gboolean locked;
|
||||||
|
gchar *label;
|
||||||
|
|
||||||
|
collection = gsecret_collection_new_sync (test->service, collection_path, NULL, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
|
||||||
|
g_assert (gsecret_collection_get_locked (collection) == FALSE);
|
||||||
|
g_assert_cmpuint (gsecret_collection_get_created (collection), <=, time (NULL));
|
||||||
|
g_assert_cmpuint (gsecret_collection_get_modified (collection), <=, time (NULL));
|
||||||
|
|
||||||
|
label = gsecret_collection_get_label (collection);
|
||||||
|
g_assert_cmpstr (label, ==, "Collection One");
|
||||||
|
g_free (label);
|
||||||
|
|
||||||
|
g_object_get (collection,
|
||||||
|
"locked", &locked,
|
||||||
|
"created", &created,
|
||||||
|
"modified", &modified,
|
||||||
|
"label", &label,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
g_assert (locked == FALSE);
|
||||||
|
g_assert_cmpuint (created, <=, time (NULL));
|
||||||
|
g_assert_cmpuint (modified, <=, time (NULL));
|
||||||
|
|
||||||
|
g_assert_cmpstr (label, ==, "Collection One");
|
||||||
|
g_free (label);
|
||||||
|
|
||||||
|
g_object_unref (collection);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_set_label_sync (Test *test,
|
||||||
|
gconstpointer unused)
|
||||||
|
{
|
||||||
|
const gchar *collection_path = "/org/freedesktop/secrets/collection/collection";
|
||||||
|
GError *error = NULL;
|
||||||
|
GSecretCollection *collection;
|
||||||
|
gboolean ret;
|
||||||
|
gchar *label;
|
||||||
|
|
||||||
|
collection = gsecret_collection_new_sync (test->service, collection_path, NULL, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
|
||||||
|
label = gsecret_collection_get_label (collection);
|
||||||
|
g_assert_cmpstr (label, ==, "Collection One");
|
||||||
|
g_free (label);
|
||||||
|
|
||||||
|
ret = gsecret_collection_set_label_sync (collection, "Another label", NULL, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
g_assert (ret == TRUE);
|
||||||
|
|
||||||
|
label = gsecret_collection_get_label (collection);
|
||||||
|
g_assert_cmpstr (label, ==, "Another label");
|
||||||
|
g_free (label);
|
||||||
|
|
||||||
|
g_object_unref (collection);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_set_label_async (Test *test,
|
||||||
|
gconstpointer unused)
|
||||||
|
{
|
||||||
|
const gchar *collection_path = "/org/freedesktop/secrets/collection/collection";
|
||||||
|
GAsyncResult *result = NULL;
|
||||||
|
GError *error = NULL;
|
||||||
|
GSecretCollection *collection;
|
||||||
|
gboolean ret;
|
||||||
|
gchar *label;
|
||||||
|
|
||||||
|
collection = gsecret_collection_new_sync (test->service, collection_path, NULL, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
|
||||||
|
label = gsecret_collection_get_label (collection);
|
||||||
|
g_assert_cmpstr (label, ==, "Collection One");
|
||||||
|
g_free (label);
|
||||||
|
|
||||||
|
gsecret_collection_set_label (collection, "Another label", NULL, on_async_result, &result);
|
||||||
|
g_assert (result == NULL);
|
||||||
|
|
||||||
|
egg_test_wait ();
|
||||||
|
|
||||||
|
ret = gsecret_collection_set_label_finish (collection, result, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
g_assert (ret == TRUE);
|
||||||
|
g_object_unref (result);
|
||||||
|
|
||||||
|
label = gsecret_collection_get_label (collection);
|
||||||
|
g_assert_cmpstr (label, ==, "Another label");
|
||||||
|
g_free (label);
|
||||||
|
|
||||||
|
g_object_unref (collection);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_set_label_prop (Test *test,
|
||||||
|
gconstpointer unused)
|
||||||
|
{
|
||||||
|
const gchar *collection_path = "/org/freedesktop/secrets/collection/collection";
|
||||||
|
GError *error = NULL;
|
||||||
|
GSecretCollection *collection;
|
||||||
|
guint sigs = 2;
|
||||||
|
gchar *label;
|
||||||
|
|
||||||
|
collection = gsecret_collection_new_sync (test->service, collection_path, NULL, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
|
||||||
|
label = gsecret_collection_get_label (collection);
|
||||||
|
g_assert_cmpstr (label, ==, "Collection One");
|
||||||
|
g_free (label);
|
||||||
|
|
||||||
|
g_signal_connect (collection, "notify::label", G_CALLBACK (on_notify_stop), &sigs);
|
||||||
|
g_object_set (collection, "label", "Blah blah", NULL);
|
||||||
|
|
||||||
|
/* Wait for the property to actually 'take' */
|
||||||
|
egg_test_wait ();
|
||||||
|
|
||||||
|
label = gsecret_collection_get_label (collection);
|
||||||
|
g_assert_cmpstr (label, ==, "Blah blah");
|
||||||
|
g_free (label);
|
||||||
|
|
||||||
|
g_object_unref (collection);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
static void
|
||||||
|
test_delete_sync (Test *test,
|
||||||
|
gconstpointer unused)
|
||||||
|
{
|
||||||
|
const gchar *item_path = "/org/freedesktop/secrets/collection/collection/item_one";
|
||||||
|
GError *error = NULL;
|
||||||
|
GSecretItem *item;
|
||||||
|
gboolean ret;
|
||||||
|
|
||||||
|
item = gsecret_item_new_sync (test->service, item_path, NULL, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
|
||||||
|
ret = gsecret_item_delete_sync (item, NULL, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
g_assert (ret == TRUE);
|
||||||
|
|
||||||
|
g_object_unref (item);
|
||||||
|
|
||||||
|
item = gsecret_item_new_sync (test->service, item_path, NULL, &error);
|
||||||
|
g_assert_error (error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD);
|
||||||
|
g_assert (item == NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_delete_async (Test *test,
|
||||||
|
gconstpointer unused)
|
||||||
|
{
|
||||||
|
const gchar *item_path = "/org/freedesktop/secrets/collection/collection/item_one";
|
||||||
|
GAsyncResult *result = NULL;
|
||||||
|
GError *error = NULL;
|
||||||
|
GSecretItem *item;
|
||||||
|
gboolean ret;
|
||||||
|
|
||||||
|
item = gsecret_item_new_sync (test->service, item_path, NULL, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
|
||||||
|
gsecret_item_delete (item, NULL, on_async_result, &result);
|
||||||
|
g_assert (result == NULL);
|
||||||
|
|
||||||
|
egg_test_wait ();
|
||||||
|
|
||||||
|
ret = gsecret_item_delete_finish (item, result, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
g_assert (ret == TRUE);
|
||||||
|
|
||||||
|
g_object_unref (item);
|
||||||
|
|
||||||
|
item = gsecret_item_new_sync (test->service, item_path, NULL, &error);
|
||||||
|
g_assert_error (error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD);
|
||||||
|
g_assert (item == NULL);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc, char **argv)
|
||||||
|
{
|
||||||
|
g_test_init (&argc, &argv, NULL);
|
||||||
|
g_set_prgname ("test-collection");
|
||||||
|
g_type_init ();
|
||||||
|
|
||||||
|
g_test_add ("/collection/new-sync", Test, "mock-service-normal.py", setup, test_new_sync, teardown);
|
||||||
|
g_test_add ("/collection/new-async", Test, "mock-service-normal.py", setup, test_new_async, teardown);
|
||||||
|
g_test_add ("/collection/properties", Test, "mock-service-normal.py", setup, test_properties, teardown);
|
||||||
|
g_test_add ("/collection/set-label-sync", Test, "mock-service-normal.py", setup, test_set_label_sync, teardown);
|
||||||
|
g_test_add ("/collection/set-label-async", Test, "mock-service-normal.py", setup, test_set_label_async, teardown);
|
||||||
|
g_test_add ("/collection/set-label-prop", Test, "mock-service-normal.py", setup, test_set_label_prop, teardown);
|
||||||
|
#if 0
|
||||||
|
g_test_add ("/item/delete-sync", Test, "mock-service-normal.py", setup, test_delete_sync, teardown);
|
||||||
|
g_test_add ("/item/delete-async", Test, "mock-service-normal.py", setup, test_delete_async, teardown);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return egg_tests_run_with_loop ();
|
||||||
|
}
|
534
library/tests/test-item.c
Normal file
534
library/tests/test-item.c
Normal file
@ -0,0 +1,534 @@
|
|||||||
|
/* GSecret - GLib wrapper for Secret Service
|
||||||
|
*
|
||||||
|
* Copyright 2012 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 of the licence or (at
|
||||||
|
* your option) any later version.
|
||||||
|
*
|
||||||
|
* See the included COPYING file for more information.
|
||||||
|
*
|
||||||
|
* Author: Stef Walter <stefw@gnome.org>
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "gsecret-item.h"
|
||||||
|
#include "gsecret-service.h"
|
||||||
|
#include "gsecret-private.h"
|
||||||
|
|
||||||
|
#include "mock-service.h"
|
||||||
|
|
||||||
|
#include "egg/egg-testing.h"
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
GDBusConnection *connection;
|
||||||
|
GSecretService *service;
|
||||||
|
} Test;
|
||||||
|
|
||||||
|
static void
|
||||||
|
setup (Test *test,
|
||||||
|
gconstpointer data)
|
||||||
|
{
|
||||||
|
GError *error = NULL;
|
||||||
|
const gchar *mock_script = data;
|
||||||
|
|
||||||
|
mock_service_start (mock_script, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
|
||||||
|
test->connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
|
||||||
|
test->service = _gsecret_service_bare_instance (test->connection, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
teardown (Test *test,
|
||||||
|
gconstpointer unused)
|
||||||
|
{
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
|
g_object_unref (test->service);
|
||||||
|
egg_assert_not_object (test->service);
|
||||||
|
|
||||||
|
mock_service_stop ();
|
||||||
|
|
||||||
|
g_dbus_connection_flush_sync (test->connection, NULL, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
g_object_unref (test->connection);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_async_result (GObject *source,
|
||||||
|
GAsyncResult *result,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
GAsyncResult **ret = user_data;
|
||||||
|
g_assert (ret != NULL);
|
||||||
|
g_assert (*ret == NULL);
|
||||||
|
*ret = g_object_ref (result);
|
||||||
|
egg_test_wait_stop ();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_notify_stop (GObject *obj,
|
||||||
|
GParamSpec *spec,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
guint *sigs = user_data;
|
||||||
|
g_assert (sigs != NULL);
|
||||||
|
g_assert (*sigs > 0);
|
||||||
|
if (--(*sigs) == 0)
|
||||||
|
egg_test_wait_stop ();
|
||||||
|
g_printerr ("sigs: %u\n", *sigs);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_new_sync (Test *test,
|
||||||
|
gconstpointer unused)
|
||||||
|
{
|
||||||
|
const gchar *item_path = "/org/freedesktop/secrets/collection/collection/item_one";
|
||||||
|
GError *error = NULL;
|
||||||
|
GSecretItem *item;
|
||||||
|
|
||||||
|
item = gsecret_item_new_sync (test->service, item_path, NULL, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
|
||||||
|
g_assert_cmpstr (g_dbus_proxy_get_object_path (G_DBUS_PROXY (item)), ==, item_path);
|
||||||
|
|
||||||
|
g_object_unref (item);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_new_async (Test *test,
|
||||||
|
gconstpointer unused)
|
||||||
|
{
|
||||||
|
const gchar *item_path = "/org/freedesktop/secrets/collection/collection/item_one";
|
||||||
|
GAsyncResult *result = NULL;
|
||||||
|
GError *error = NULL;
|
||||||
|
GSecretItem *item;
|
||||||
|
|
||||||
|
gsecret_item_new (test->service, item_path, NULL, on_async_result, &result);
|
||||||
|
g_assert (result == NULL);
|
||||||
|
|
||||||
|
egg_test_wait ();
|
||||||
|
|
||||||
|
item = gsecret_item_new_finish (result, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
g_object_unref (result);
|
||||||
|
|
||||||
|
g_assert_cmpstr (g_dbus_proxy_get_object_path (G_DBUS_PROXY (item)), ==, item_path);
|
||||||
|
|
||||||
|
g_object_unref (item);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_properties (Test *test,
|
||||||
|
gconstpointer unused)
|
||||||
|
{
|
||||||
|
const gchar *item_path = "/org/freedesktop/secrets/collection/collection/item_one";
|
||||||
|
GError *error = NULL;
|
||||||
|
GHashTable *attributes;
|
||||||
|
GSecretItem *item;
|
||||||
|
guint64 created;
|
||||||
|
guint64 modified;
|
||||||
|
gboolean locked;
|
||||||
|
gchar *label;
|
||||||
|
|
||||||
|
item = gsecret_item_new_sync (test->service, item_path, NULL, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
|
||||||
|
g_assert (gsecret_item_get_locked (item) == FALSE);
|
||||||
|
g_assert_cmpuint (gsecret_item_get_created (item), <=, time (NULL));
|
||||||
|
g_assert_cmpuint (gsecret_item_get_modified (item), <=, time (NULL));
|
||||||
|
|
||||||
|
label = gsecret_item_get_label (item);
|
||||||
|
g_assert_cmpstr (label, ==, "Item One");
|
||||||
|
g_free (label);
|
||||||
|
|
||||||
|
attributes = gsecret_item_get_attributes (item);
|
||||||
|
g_assert_cmpstr (g_hash_table_lookup (attributes, "string"), ==, "one");
|
||||||
|
g_assert_cmpstr (g_hash_table_lookup (attributes, "number"), ==, "1");
|
||||||
|
g_assert_cmpstr (g_hash_table_lookup (attributes, "parity"), ==, "odd");
|
||||||
|
g_assert_cmpuint (g_hash_table_size (attributes), ==, 3);
|
||||||
|
g_hash_table_unref (attributes);
|
||||||
|
|
||||||
|
g_object_get (item,
|
||||||
|
"locked", &locked,
|
||||||
|
"created", &created,
|
||||||
|
"modified", &modified,
|
||||||
|
"label", &label,
|
||||||
|
"attributes", &attributes,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
g_assert (locked == FALSE);
|
||||||
|
g_assert_cmpuint (created, <=, time (NULL));
|
||||||
|
g_assert_cmpuint (modified, <=, time (NULL));
|
||||||
|
|
||||||
|
g_assert_cmpstr (label, ==, "Item One");
|
||||||
|
g_free (label);
|
||||||
|
|
||||||
|
g_assert_cmpstr (g_hash_table_lookup (attributes, "string"), ==, "one");
|
||||||
|
g_assert_cmpstr (g_hash_table_lookup (attributes, "number"), ==, "1");
|
||||||
|
g_assert_cmpstr (g_hash_table_lookup (attributes, "parity"), ==, "odd");
|
||||||
|
g_assert_cmpuint (g_hash_table_size (attributes), ==, 3);
|
||||||
|
g_hash_table_unref (attributes);
|
||||||
|
|
||||||
|
g_object_unref (item);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_set_label_sync (Test *test,
|
||||||
|
gconstpointer unused)
|
||||||
|
{
|
||||||
|
const gchar *item_path = "/org/freedesktop/secrets/collection/collection/item_one";
|
||||||
|
GError *error = NULL;
|
||||||
|
GSecretItem *item;
|
||||||
|
gboolean ret;
|
||||||
|
gchar *label;
|
||||||
|
|
||||||
|
item = gsecret_item_new_sync (test->service, item_path, NULL, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
|
||||||
|
label = gsecret_item_get_label (item);
|
||||||
|
g_assert_cmpstr (label, ==, "Item One");
|
||||||
|
g_free (label);
|
||||||
|
|
||||||
|
ret = gsecret_item_set_label_sync (item, "Another label", NULL, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
g_assert (ret == TRUE);
|
||||||
|
|
||||||
|
label = gsecret_item_get_label (item);
|
||||||
|
g_assert_cmpstr (label, ==, "Another label");
|
||||||
|
g_free (label);
|
||||||
|
|
||||||
|
g_object_unref (item);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_set_label_async (Test *test,
|
||||||
|
gconstpointer unused)
|
||||||
|
{
|
||||||
|
const gchar *item_path = "/org/freedesktop/secrets/collection/collection/item_one";
|
||||||
|
GAsyncResult *result = NULL;
|
||||||
|
GError *error = NULL;
|
||||||
|
GSecretItem *item;
|
||||||
|
gboolean ret;
|
||||||
|
gchar *label;
|
||||||
|
|
||||||
|
item = gsecret_item_new_sync (test->service, item_path, NULL, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
|
||||||
|
label = gsecret_item_get_label (item);
|
||||||
|
g_assert_cmpstr (label, ==, "Item One");
|
||||||
|
g_free (label);
|
||||||
|
|
||||||
|
gsecret_item_set_label (item, "Another label", NULL, on_async_result, &result);
|
||||||
|
g_assert (result == NULL);
|
||||||
|
|
||||||
|
egg_test_wait ();
|
||||||
|
|
||||||
|
ret = gsecret_item_set_label_finish (item, result, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
g_assert (ret == TRUE);
|
||||||
|
g_object_unref (result);
|
||||||
|
|
||||||
|
label = gsecret_item_get_label (item);
|
||||||
|
g_assert_cmpstr (label, ==, "Another label");
|
||||||
|
g_free (label);
|
||||||
|
|
||||||
|
g_object_unref (item);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_set_label_prop (Test *test,
|
||||||
|
gconstpointer unused)
|
||||||
|
{
|
||||||
|
const gchar *item_path = "/org/freedesktop/secrets/collection/collection/item_one";
|
||||||
|
GError *error = NULL;
|
||||||
|
GSecretItem *item;
|
||||||
|
guint sigs = 2;
|
||||||
|
gchar *label;
|
||||||
|
|
||||||
|
item = gsecret_item_new_sync (test->service, item_path, NULL, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
|
||||||
|
label = gsecret_item_get_label (item);
|
||||||
|
g_assert_cmpstr (label, ==, "Item One");
|
||||||
|
g_free (label);
|
||||||
|
|
||||||
|
g_signal_connect (item, "notify::label", G_CALLBACK (on_notify_stop), &sigs);
|
||||||
|
g_object_set (item, "label", "Blah blah", NULL);
|
||||||
|
|
||||||
|
/* Wait for the property to actually 'take' */
|
||||||
|
egg_test_wait ();
|
||||||
|
|
||||||
|
label = gsecret_item_get_label (item);
|
||||||
|
g_assert_cmpstr (label, ==, "Blah blah");
|
||||||
|
g_free (label);
|
||||||
|
|
||||||
|
g_object_unref (item);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_set_attributes_sync (Test *test,
|
||||||
|
gconstpointer unused)
|
||||||
|
{
|
||||||
|
const gchar *item_path = "/org/freedesktop/secrets/collection/collection/item_one";
|
||||||
|
GError *error = NULL;
|
||||||
|
GSecretItem *item;
|
||||||
|
gboolean ret;
|
||||||
|
GHashTable *attributes;
|
||||||
|
|
||||||
|
item = gsecret_item_new_sync (test->service, item_path, NULL, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
|
||||||
|
attributes = gsecret_item_get_attributes (item);
|
||||||
|
g_assert_cmpstr (g_hash_table_lookup (attributes, "string"), ==, "one");
|
||||||
|
g_assert_cmpstr (g_hash_table_lookup (attributes, "number"), ==, "1");
|
||||||
|
g_assert_cmpstr (g_hash_table_lookup (attributes, "parity"), ==, "odd");
|
||||||
|
g_assert_cmpuint (g_hash_table_size (attributes), ==, 3);
|
||||||
|
g_hash_table_unref (attributes);
|
||||||
|
|
||||||
|
attributes = g_hash_table_new (g_str_hash, g_str_equal);
|
||||||
|
g_hash_table_insert (attributes, "string", "five");
|
||||||
|
g_hash_table_insert (attributes, "number", "5");
|
||||||
|
ret = gsecret_item_set_attributes_sync (item, attributes, NULL, &error);
|
||||||
|
g_hash_table_unref (attributes);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
g_assert (ret == TRUE);
|
||||||
|
|
||||||
|
attributes = gsecret_item_get_attributes (item);
|
||||||
|
g_assert_cmpstr (g_hash_table_lookup (attributes, "string"), ==, "five");
|
||||||
|
g_assert_cmpstr (g_hash_table_lookup (attributes, "number"), ==, "5");
|
||||||
|
g_assert_cmpuint (g_hash_table_size (attributes), ==, 2);
|
||||||
|
g_hash_table_unref (attributes);
|
||||||
|
|
||||||
|
g_object_unref (item);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_set_attributes_async (Test *test,
|
||||||
|
gconstpointer unused)
|
||||||
|
{
|
||||||
|
const gchar *item_path = "/org/freedesktop/secrets/collection/collection/item_one";
|
||||||
|
GHashTable *attributes;
|
||||||
|
GError *error = NULL;
|
||||||
|
GAsyncResult *result = NULL;
|
||||||
|
GSecretItem *item;
|
||||||
|
gboolean ret;
|
||||||
|
|
||||||
|
item = gsecret_item_new_sync (test->service, item_path, NULL, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
|
||||||
|
attributes = gsecret_item_get_attributes (item);
|
||||||
|
g_assert_cmpstr (g_hash_table_lookup (attributes, "string"), ==, "one");
|
||||||
|
g_assert_cmpstr (g_hash_table_lookup (attributes, "number"), ==, "1");
|
||||||
|
g_assert_cmpstr (g_hash_table_lookup (attributes, "parity"), ==, "odd");
|
||||||
|
g_assert_cmpuint (g_hash_table_size (attributes), ==, 3);
|
||||||
|
g_hash_table_unref (attributes);
|
||||||
|
|
||||||
|
attributes = g_hash_table_new (g_str_hash, g_str_equal);
|
||||||
|
g_hash_table_insert (attributes, "string", "five");
|
||||||
|
g_hash_table_insert (attributes, "number", "5");
|
||||||
|
gsecret_item_set_attributes (item, attributes, NULL, on_async_result, &result);
|
||||||
|
g_assert (result == NULL);
|
||||||
|
|
||||||
|
egg_test_wait ();
|
||||||
|
|
||||||
|
ret = gsecret_item_set_attributes_finish (item, result, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
g_assert (ret == TRUE);
|
||||||
|
g_object_unref (result);
|
||||||
|
|
||||||
|
attributes = gsecret_item_get_attributes (item);
|
||||||
|
g_assert_cmpstr (g_hash_table_lookup (attributes, "string"), ==, "five");
|
||||||
|
g_assert_cmpstr (g_hash_table_lookup (attributes, "number"), ==, "5");
|
||||||
|
g_assert_cmpuint (g_hash_table_size (attributes), ==, 2);
|
||||||
|
g_hash_table_unref (attributes);
|
||||||
|
|
||||||
|
g_object_unref (item);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_set_attributes_prop (Test *test,
|
||||||
|
gconstpointer unused)
|
||||||
|
{
|
||||||
|
const gchar *item_path = "/org/freedesktop/secrets/collection/collection/item_one";
|
||||||
|
GError *error = NULL;
|
||||||
|
GSecretItem *item;
|
||||||
|
GHashTable *attributes;
|
||||||
|
guint sigs = 2;
|
||||||
|
|
||||||
|
item = gsecret_item_new_sync (test->service, item_path, NULL, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
|
||||||
|
attributes = gsecret_item_get_attributes (item);
|
||||||
|
g_assert_cmpstr (g_hash_table_lookup (attributes, "string"), ==, "one");
|
||||||
|
g_assert_cmpstr (g_hash_table_lookup (attributes, "number"), ==, "1");
|
||||||
|
g_assert_cmpstr (g_hash_table_lookup (attributes, "parity"), ==, "odd");
|
||||||
|
g_assert_cmpuint (g_hash_table_size (attributes), ==, 3);
|
||||||
|
g_hash_table_unref (attributes);
|
||||||
|
|
||||||
|
g_signal_connect (item, "notify::attributes", G_CALLBACK (on_notify_stop), &sigs);
|
||||||
|
|
||||||
|
attributes = g_hash_table_new (g_str_hash, g_str_equal);
|
||||||
|
g_hash_table_insert (attributes, "string", "five");
|
||||||
|
g_hash_table_insert (attributes, "number", "5");
|
||||||
|
g_object_set (item, "attributes", attributes, NULL);
|
||||||
|
g_hash_table_unref (attributes);
|
||||||
|
|
||||||
|
/* Wait for the property to actually 'take' */
|
||||||
|
egg_test_wait ();
|
||||||
|
|
||||||
|
attributes = gsecret_item_get_attributes (item);
|
||||||
|
g_assert_cmpstr (g_hash_table_lookup (attributes, "string"), ==, "five");
|
||||||
|
g_assert_cmpstr (g_hash_table_lookup (attributes, "number"), ==, "5");
|
||||||
|
g_assert_cmpuint (g_hash_table_size (attributes), ==, 2);
|
||||||
|
g_hash_table_unref (attributes);
|
||||||
|
|
||||||
|
g_object_unref (item);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_get_secret_sync (Test *test,
|
||||||
|
gconstpointer unused)
|
||||||
|
{
|
||||||
|
const gchar *item_path = "/org/freedesktop/secrets/collection/collection/item_one";
|
||||||
|
GError *error = NULL;
|
||||||
|
GSecretItem *item;
|
||||||
|
GSecretValue *value;
|
||||||
|
gconstpointer data;
|
||||||
|
gsize length;
|
||||||
|
|
||||||
|
item = gsecret_item_new_sync (test->service, item_path, NULL, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
|
||||||
|
value = gsecret_item_get_secret_sync (item, NULL, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
g_assert (value != NULL);
|
||||||
|
|
||||||
|
data = gsecret_value_get (value, &length);
|
||||||
|
egg_assert_cmpmem (data, length, ==, "uno", 3);
|
||||||
|
|
||||||
|
gsecret_value_unref (value);
|
||||||
|
|
||||||
|
g_object_unref (item);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_get_secret_async (Test *test,
|
||||||
|
gconstpointer unused)
|
||||||
|
{
|
||||||
|
const gchar *item_path = "/org/freedesktop/secrets/collection/collection/item_one";
|
||||||
|
GAsyncResult *result = NULL;
|
||||||
|
GError *error = NULL;
|
||||||
|
GSecretItem *item;
|
||||||
|
GSecretValue *value;
|
||||||
|
gconstpointer data;
|
||||||
|
gsize length;
|
||||||
|
|
||||||
|
item = gsecret_item_new_sync (test->service, item_path, NULL, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
|
||||||
|
gsecret_item_get_secret (item, NULL, on_async_result, &result);
|
||||||
|
g_assert (result == NULL);
|
||||||
|
|
||||||
|
egg_test_wait ();
|
||||||
|
|
||||||
|
value = gsecret_item_get_secret_finish (item, result, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
g_assert (value != NULL);
|
||||||
|
g_object_unref (result);
|
||||||
|
|
||||||
|
data = gsecret_value_get (value, &length);
|
||||||
|
egg_assert_cmpmem (data, length, ==, "uno", 3);
|
||||||
|
|
||||||
|
gsecret_value_unref (value);
|
||||||
|
|
||||||
|
g_object_unref (item);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_delete_sync (Test *test,
|
||||||
|
gconstpointer unused)
|
||||||
|
{
|
||||||
|
const gchar *item_path = "/org/freedesktop/secrets/collection/collection/item_one";
|
||||||
|
GError *error = NULL;
|
||||||
|
GSecretItem *item;
|
||||||
|
gboolean ret;
|
||||||
|
|
||||||
|
item = gsecret_item_new_sync (test->service, item_path, NULL, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
|
||||||
|
ret = gsecret_item_delete_sync (item, NULL, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
g_assert (ret == TRUE);
|
||||||
|
|
||||||
|
g_object_unref (item);
|
||||||
|
|
||||||
|
item = gsecret_item_new_sync (test->service, item_path, NULL, &error);
|
||||||
|
g_assert_error (error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD);
|
||||||
|
g_assert (item == NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_delete_async (Test *test,
|
||||||
|
gconstpointer unused)
|
||||||
|
{
|
||||||
|
const gchar *item_path = "/org/freedesktop/secrets/collection/collection/item_one";
|
||||||
|
GAsyncResult *result = NULL;
|
||||||
|
GError *error = NULL;
|
||||||
|
GSecretItem *item;
|
||||||
|
gboolean ret;
|
||||||
|
|
||||||
|
item = gsecret_item_new_sync (test->service, item_path, NULL, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
|
||||||
|
gsecret_item_delete (item, NULL, on_async_result, &result);
|
||||||
|
g_assert (result == NULL);
|
||||||
|
|
||||||
|
egg_test_wait ();
|
||||||
|
|
||||||
|
ret = gsecret_item_delete_finish (item, result, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
g_assert (ret == TRUE);
|
||||||
|
|
||||||
|
g_object_unref (item);
|
||||||
|
|
||||||
|
item = gsecret_item_new_sync (test->service, item_path, NULL, &error);
|
||||||
|
g_assert_error (error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD);
|
||||||
|
g_assert (item == NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc, char **argv)
|
||||||
|
{
|
||||||
|
g_test_init (&argc, &argv, NULL);
|
||||||
|
g_set_prgname ("test-item");
|
||||||
|
g_type_init ();
|
||||||
|
|
||||||
|
g_test_add ("/item/new-sync", Test, "mock-service-normal.py", setup, test_new_sync, teardown);
|
||||||
|
g_test_add ("/item/new-async", Test, "mock-service-normal.py", setup, test_new_async, teardown);
|
||||||
|
g_test_add ("/item/properties", Test, "mock-service-normal.py", setup, test_properties, teardown);
|
||||||
|
g_test_add ("/item/set-label-sync", Test, "mock-service-normal.py", setup, test_set_label_sync, teardown);
|
||||||
|
g_test_add ("/item/set-label-async", Test, "mock-service-normal.py", setup, test_set_label_async, teardown);
|
||||||
|
g_test_add ("/item/set-attributes-sync", Test, "mock-service-normal.py", setup, test_set_attributes_sync, teardown);
|
||||||
|
g_test_add ("/item/set-attributes-async", Test, "mock-service-normal.py", setup, test_set_attributes_async, teardown);
|
||||||
|
g_test_add ("/item/get-secret-sync", Test, "mock-service-normal.py", setup, test_get_secret_sync, teardown);
|
||||||
|
g_test_add ("/item/get-secret-async", Test, "mock-service-normal.py", setup, test_get_secret_async, teardown);
|
||||||
|
g_test_add ("/item/delete-sync", Test, "mock-service-normal.py", setup, test_delete_sync, teardown);
|
||||||
|
g_test_add ("/item/delete-async", Test, "mock-service-normal.py", setup, test_delete_async, teardown);
|
||||||
|
|
||||||
|
g_test_add ("/item/set-attributes-prop", Test, "mock-service-normal.py", setup, test_set_attributes_prop, teardown);
|
||||||
|
g_test_add ("/item/set-label-prop", Test, "mock-service-normal.py", setup, test_set_label_prop, teardown);
|
||||||
|
|
||||||
|
return egg_tests_run_with_loop ();
|
||||||
|
}
|
210
library/tests/test-value.c
Normal file
210
library/tests/test-value.c
Normal file
@ -0,0 +1,210 @@
|
|||||||
|
/* GSecret - GLib wrapper for Secret Service
|
||||||
|
*
|
||||||
|
* Copyright 2012 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 of the licence or (at
|
||||||
|
* your option) any later version.
|
||||||
|
*
|
||||||
|
* See the included COPYING file for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "gsecret-value.h"
|
||||||
|
#include "gsecret-private.h"
|
||||||
|
|
||||||
|
#include "egg/egg-testing.h"
|
||||||
|
#include "egg/egg-secure-memory.h"
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
EGG_SECURE_DECLARE (test_value);
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_new (void)
|
||||||
|
{
|
||||||
|
GSecretValue *value;
|
||||||
|
gsize length;
|
||||||
|
|
||||||
|
value = gsecret_value_new ("blahblah", 4, "text/plain");
|
||||||
|
|
||||||
|
g_assert_cmpstr (gsecret_value_get (value, &length), ==, "blah");
|
||||||
|
g_assert_cmpuint (length, ==, 4);
|
||||||
|
|
||||||
|
g_assert_cmpstr (gsecret_value_get_content_type (value), ==, "text/plain");
|
||||||
|
|
||||||
|
gsecret_value_unref (value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_new_terminated (void)
|
||||||
|
{
|
||||||
|
GSecretValue *value;
|
||||||
|
gsize length;
|
||||||
|
|
||||||
|
value = gsecret_value_new ("blah", -1, "text/plain");
|
||||||
|
|
||||||
|
g_assert_cmpstr (gsecret_value_get (value, &length), ==, "blah");
|
||||||
|
g_assert_cmpuint (length, ==, 4);
|
||||||
|
|
||||||
|
g_assert_cmpstr (gsecret_value_get_content_type (value), ==, "text/plain");
|
||||||
|
|
||||||
|
gsecret_value_unref (value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_new_full (void)
|
||||||
|
{
|
||||||
|
GSecretValue *value;
|
||||||
|
gchar *data = g_strdup ("blah");
|
||||||
|
gsize length;
|
||||||
|
|
||||||
|
value = gsecret_value_new_full (data, 4, "text/plain", g_free);
|
||||||
|
|
||||||
|
g_assert_cmpstr (gsecret_value_get (value, &length), ==, "blah");
|
||||||
|
g_assert_cmpuint (length, ==, 4);
|
||||||
|
|
||||||
|
/* No copy done here */
|
||||||
|
g_assert (gsecret_value_get (value, NULL) == data);
|
||||||
|
|
||||||
|
gsecret_value_unref (value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_new_full_terminated (void)
|
||||||
|
{
|
||||||
|
GSecretValue *value;
|
||||||
|
gchar *data = g_strdup ("blah");
|
||||||
|
gsize length;
|
||||||
|
|
||||||
|
value = gsecret_value_new_full (data, -1, "text/plain", g_free);
|
||||||
|
|
||||||
|
g_assert_cmpstr (gsecret_value_get (value, &length), ==, "blah");
|
||||||
|
g_assert_cmpuint (length, ==, 4);
|
||||||
|
|
||||||
|
/* No copy done here */
|
||||||
|
g_assert (gsecret_value_get (value, NULL) == data);
|
||||||
|
|
||||||
|
gsecret_value_unref (value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_ref_unref (void)
|
||||||
|
{
|
||||||
|
GSecretValue *value;
|
||||||
|
GSecretValue *value2;
|
||||||
|
gsize length;
|
||||||
|
|
||||||
|
value = gsecret_value_new ("blah", 4, "text/plain");
|
||||||
|
value2 = gsecret_value_ref(value);
|
||||||
|
gsecret_value_unref (value);
|
||||||
|
|
||||||
|
g_assert_cmpstr (gsecret_value_get (value2, &length), ==, "blah");
|
||||||
|
g_assert_cmpuint (length, ==, 4);
|
||||||
|
|
||||||
|
gsecret_value_unref (value2);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_boxed (void)
|
||||||
|
{
|
||||||
|
GSecretValue *value;
|
||||||
|
GSecretValue *value2;
|
||||||
|
gsize length;
|
||||||
|
|
||||||
|
value = gsecret_value_new ("blah", 4, "text/plain");
|
||||||
|
value2 = g_boxed_copy (GSECRET_TYPE_VALUE, value);
|
||||||
|
g_boxed_free (GSECRET_TYPE_VALUE, value);
|
||||||
|
|
||||||
|
g_assert_cmpstr (gsecret_value_get (value2, &length), ==, "blah");
|
||||||
|
g_assert_cmpuint (length, ==, 4);
|
||||||
|
|
||||||
|
g_boxed_free (GSECRET_TYPE_VALUE, value2);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_to_password (void)
|
||||||
|
{
|
||||||
|
GSecretValue *value;
|
||||||
|
gchar *password;
|
||||||
|
|
||||||
|
value = gsecret_value_new_full (egg_secure_strdup ("blah"), -1,
|
||||||
|
"text/plain", egg_secure_free);
|
||||||
|
|
||||||
|
password = _gsecret_value_unref_to_password (value);
|
||||||
|
g_assert_cmpstr (password, ==, "blah");
|
||||||
|
|
||||||
|
egg_secure_free (password);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_to_password_bad_destroy (void)
|
||||||
|
{
|
||||||
|
GSecretValue *value;
|
||||||
|
gchar *password;
|
||||||
|
|
||||||
|
value = gsecret_value_new_full (g_strdup ("blah"), -1,
|
||||||
|
"text/plain", g_free);
|
||||||
|
|
||||||
|
password = _gsecret_value_unref_to_password (value);
|
||||||
|
g_assert_cmpstr (password, ==, "blah");
|
||||||
|
|
||||||
|
egg_secure_free (password);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_to_password_bad_content (void)
|
||||||
|
{
|
||||||
|
GSecretValue *value;
|
||||||
|
gchar *password;
|
||||||
|
|
||||||
|
value = gsecret_value_new_full (g_strdup ("wooowhee"), -1,
|
||||||
|
"application/octet-stream", g_free);
|
||||||
|
|
||||||
|
password = _gsecret_value_unref_to_password (value);
|
||||||
|
g_assert_cmpstr (password, ==, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_to_password_extra_ref (void)
|
||||||
|
{
|
||||||
|
GSecretValue *value;
|
||||||
|
gchar *password;
|
||||||
|
|
||||||
|
value = gsecret_value_new_full (egg_secure_strdup ("blah"), -1,
|
||||||
|
"text/plain", egg_secure_free);
|
||||||
|
gsecret_value_ref (value);
|
||||||
|
|
||||||
|
password = _gsecret_value_unref_to_password (value);
|
||||||
|
g_assert_cmpstr (password, ==, "blah");
|
||||||
|
|
||||||
|
egg_secure_free (password);
|
||||||
|
gsecret_value_unref (value);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc, char **argv)
|
||||||
|
{
|
||||||
|
g_test_init (&argc, &argv, NULL);
|
||||||
|
g_set_prgname ("test-value");
|
||||||
|
g_type_init ();
|
||||||
|
|
||||||
|
g_test_add_func ("/value/new", test_new);
|
||||||
|
g_test_add_func ("/value/new-terminated", test_new_terminated);
|
||||||
|
g_test_add_func ("/value/new-full", test_new_full);
|
||||||
|
g_test_add_func ("/value/new-full-terminated", test_new_full_terminated);
|
||||||
|
g_test_add_func ("/value/ref-unref", test_ref_unref);
|
||||||
|
g_test_add_func ("/value/boxed", test_boxed);
|
||||||
|
g_test_add_func ("/value/to-password", test_to_password);
|
||||||
|
g_test_add_func ("/value/to-password-bad-destroy", test_to_password_bad_destroy);
|
||||||
|
g_test_add_func ("/value/to-password-bad-content", test_to_password_bad_content);
|
||||||
|
g_test_add_func ("/value/to-password-extra-ref", test_to_password_extra_ref);
|
||||||
|
|
||||||
|
return egg_tests_run_with_loop ();
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user