diff --git a/gnome-keyring-2.30.0-better-error-handling.patch b/gnome-keyring-2.30.0-better-error-handling.patch new file mode 100644 index 0000000..67502cd --- /dev/null +++ b/gnome-keyring-2.30.0-better-error-handling.patch @@ -0,0 +1,1361 @@ +From 9225955b8374d0d301e0a251410ae347a3bd884b Mon Sep 17 00:00:00 2001 +From: Stef Walter +Date: Fri, 19 Mar 2010 23:03:33 +0000 +Subject: More robust error display and handling. + +Handle all cases where a function may return a failure +with a NULL GError, such as preconditions and warnings. + +Also use proper function for checking error codes. +--- +diff --git a/daemon/dbus/gkd-dbus-util.c b/daemon/dbus/gkd-dbus-util.c +index 1b094ea..33b303b 100644 +--- a/daemon/dbus/gkd-dbus-util.c ++++ b/daemon/dbus/gkd-dbus-util.c +@@ -26,6 +26,8 @@ + #include "gkd-dbus-util.h" + #include "gkd-secret-types.h" + ++#include "egg/egg-error.h" ++ + #include + + GType +@@ -71,7 +73,7 @@ gkd_dbus_introspect_handle (DBusMessage *message, const gchar *type) + + if (error != NULL) { + g_warning ("couldn't load introspect data file: %s: %s", +- filename, error->message ? error->message : ""); ++ filename, egg_error_message (error)); + g_clear_error (&error); + return NULL; + } +diff --git a/daemon/dbus/gkd-secret-change.c b/daemon/dbus/gkd-secret-change.c +index 3dee7a7..0fba515 100644 +--- a/daemon/dbus/gkd-secret-change.c ++++ b/daemon/dbus/gkd-secret-change.c +@@ -29,6 +29,7 @@ + #include "gkd-secret-types.h" + #include "gkd-secret-util.h" + ++#include "egg/egg-error.h" + #include "egg/egg-secure-memory.h" + + #include "pkcs11/pkcs11i.h" +@@ -69,7 +70,7 @@ prepare_change_prompt (GkdSecretChange *self, GP11Object *collection, gboolean f + + data = gp11_object_get_data (collection, CKA_LABEL, &n_data, &error); + if (!data) { +- g_warning ("couldn't get label for collection: %s", error->message); ++ g_warning ("couldn't get label for collection: %s", egg_error_message (error)); + g_clear_error (&error); + } + +@@ -304,10 +305,10 @@ cleanup: + gp11_attributes_unref (attrs); + + if (!result && error) { +- if (error->code == CKR_USER_NOT_LOGGED_IN) ++ if (g_error_matches (error, GP11_ERROR, CKR_USER_NOT_LOGGED_IN)) + dbus_set_error (derr, INTERNAL_ERROR_DENIED, "The original password was invalid"); + else +- g_warning ("failure occurred while changing password: %s", error->message); ++ g_warning ("failure occurred while changing password: %s", egg_error_message (error)); + } + + if (!result && !dbus_error_is_set (derr)) +diff --git a/daemon/dbus/gkd-secret-create.c b/daemon/dbus/gkd-secret-create.c +index d56cf92..5f61af1 100644 +--- a/daemon/dbus/gkd-secret-create.c ++++ b/daemon/dbus/gkd-secret-create.c +@@ -30,6 +30,7 @@ + #include "gkd-secret-types.h" + #include "gkd-secret-util.h" + ++#include "egg/egg-error.h" + #include "egg/egg-secure-memory.h" + + #include "pkcs11/pkcs11i.h" +@@ -303,7 +304,7 @@ gkd_secret_create_with_secret (GP11Attributes *attrs, GkdSecretSecret *master, + g_object_unref (cred); + + if (collection == NULL) { +- g_warning ("couldn't create collection: %s", error->message); ++ g_warning ("couldn't create collection: %s", egg_error_message (error)); + g_clear_error (&error); + dbus_set_error (derr, DBUS_ERROR_FAILED, "Couldn't create new collection"); + return FALSE; +@@ -314,7 +315,7 @@ gkd_secret_create_with_secret (GP11Attributes *attrs, GkdSecretSecret *master, + g_object_unref (collection); + + if (!identifier) { +- g_warning ("couldn't lookup new collection identifier: %s", error->message); ++ g_warning ("couldn't lookup new collection identifier: %s", egg_error_message (error)); + g_clear_error (&error); + dbus_set_error (derr, DBUS_ERROR_FAILED, "Couldn't find new collection just created"); + return FALSE; +diff --git a/daemon/dbus/gkd-secret-lock.c b/daemon/dbus/gkd-secret-lock.c +index abecf63..c348d78 100644 +--- a/daemon/dbus/gkd-secret-lock.c ++++ b/daemon/dbus/gkd-secret-lock.c +@@ -24,6 +24,8 @@ + #include "gkd-secret-lock.h" + #include "gkd-secret-service.h" + ++#include "egg/egg-error.h" ++ + #include "pkcs11/pkcs11i.h" + + #include +@@ -46,7 +48,7 @@ gkd_secret_lock (GP11Object *collection, DBusError *derr) + + if (error != NULL) { + g_object_unref (session); +- g_warning ("couldn't search for credential objects: %s", error->message); ++ g_warning ("couldn't search for credential objects: %s", egg_error_message (error)); + dbus_set_error (derr, DBUS_ERROR_FAILED, "Couldn't lock collection"); + g_clear_error (&error); + return FALSE; +@@ -56,7 +58,7 @@ gkd_secret_lock (GP11Object *collection, DBusError *derr) + cred = GP11_OBJECT (l->data); + gp11_object_set_session (cred, session); + if (!gp11_object_destroy (cred, &error)) { +- g_warning ("couldn't destroy credential object: %s", error->message); ++ g_warning ("couldn't destroy credential object: %s", egg_error_message (error)); + g_clear_error (&error); + } + } +diff --git a/daemon/dbus/gkd-secret-objects.c b/daemon/dbus/gkd-secret-objects.c +index 55b1f2d..6af6a91 100644 +--- a/daemon/dbus/gkd-secret-objects.c ++++ b/daemon/dbus/gkd-secret-objects.c +@@ -32,6 +32,8 @@ + #include "gkd-secret-types.h" + #include "gkd-secret-util.h" + ++#include "egg/egg-error.h" ++ + #include "pkcs11/pkcs11i.h" + + #include +@@ -110,7 +112,7 @@ iter_append_item_path (const gchar *base, GP11Object *object, DBusMessageIter *i + if (base == NULL) { + identifier = gp11_object_get_data (object, CKA_G_COLLECTION, &n_identifier, &error); + if (!identifier) { +- g_warning ("couldn't get item collection identifier: %s", error->message); ++ g_warning ("couldn't get item collection identifier: %s", egg_error_message (error)); + g_clear_error (&error); + return; + } +@@ -121,7 +123,7 @@ iter_append_item_path (const gchar *base, GP11Object *object, DBusMessageIter *i + + identifier = gp11_object_get_data (object, CKA_ID, &n_identifier, &error); + if (identifier == NULL) { +- g_warning ("couldn't get item identifier: %s", error->message); ++ g_warning ("couldn't get item identifier: %s", egg_error_message (error)); + g_clear_error (&error); + } else { + path = gkd_secret_util_build_path (base, identifier, n_identifier); +@@ -163,7 +165,7 @@ iter_append_collection_paths (GList *collections, DBusMessageIter *iter) + + identifier = gp11_object_get_data (l->data, CKA_ID, &n_identifier, &error); + if (identifier == NULL) { +- g_warning ("couldn't get collection identifier: %s", error->message); ++ g_warning ("couldn't get collection identifier: %s", egg_error_message (error)); + g_clear_error (&error); + continue; + } +@@ -198,7 +200,7 @@ object_property_get (GP11Object *object, DBusMessage *message, + if (error != NULL) { + reply = dbus_message_new_error_printf (message, DBUS_ERROR_FAILED, + "Couldn't retrieve '%s' property: %s", +- prop_name, error->message); ++ prop_name, egg_error_message (error)); + g_clear_error (&error); + return reply; + } +@@ -244,13 +246,13 @@ object_property_set (GP11Object *object, DBusMessage *message, + gp11_attributes_unref (attrs); + + if (error != NULL) { +- if (error->code == CKR_USER_NOT_LOGGED_IN) ++ if (g_error_matches (error, GP11_ERROR, CKR_USER_NOT_LOGGED_IN)) + reply = dbus_message_new_error (message, SECRET_ERROR_IS_LOCKED, + "Cannot set property on a locked object"); + else + reply = dbus_message_new_error_printf (message, DBUS_ERROR_FAILED, + "Couldn't set '%s' property: %s", +- prop_name, error->message); ++ prop_name, egg_error_message (error)); + g_clear_error (&error); + return reply; + } +@@ -330,7 +332,7 @@ item_property_getall (GP11Object *object, DBusMessage *message) + if (error != NULL) + return dbus_message_new_error_printf (message, DBUS_ERROR_FAILED, + "Couldn't retrieve properties: %s", +- error->message); ++ egg_error_message (error)); + + reply = dbus_message_new_method_return (message); + +@@ -352,13 +354,13 @@ item_method_delete (GkdSecretObjects *self, GP11Object *object, DBusMessage *mes + return NULL; + + if (!gp11_object_destroy (object, &error)) { +- if (error->code == CKR_USER_NOT_LOGGED_IN) ++ if (g_error_matches (error, GP11_ERROR, CKR_USER_NOT_LOGGED_IN)) + reply = dbus_message_new_error_printf (message, SECRET_ERROR_IS_LOCKED, + "Cannot delete a locked item"); + else + reply = dbus_message_new_error_printf (message, DBUS_ERROR_FAILED, + "Couldn't delete collection: %s", +- error->message); ++ egg_error_message (error)); + g_clear_error (&error); + return reply; + } +@@ -474,8 +476,8 @@ item_cleanup_search_results (GP11Session *session, GList *items, + gp11_object_set_session (l->data, session); + value = gp11_object_get_data (l->data, CKA_G_LOCKED, &n_value, &error); + if (value == NULL) { +- if (error->code != CKR_OBJECT_HANDLE_INVALID) +- g_warning ("couldn't check if item is locked: %s", error->message); ++ if (!g_error_matches (error, GP11_ERROR, CKR_OBJECT_HANDLE_INVALID)) ++ g_warning ("couldn't check if item is locked: %s", egg_error_message (error)); + g_clear_error (&error); + + /* Is not locked */ +@@ -573,7 +575,7 @@ collection_property_getall (GkdSecretObjects *self, GP11Object *object, DBusMess + if (error != NULL) + return dbus_message_new_error_printf (message, DBUS_ERROR_FAILED, + "Couldn't retrieve properties: %s", +- error->message); ++ egg_error_message (error)); + + reply = dbus_message_new_method_return (message); + +@@ -623,7 +625,7 @@ collection_find_matching_item (GkdSecretObjects *self, GP11Session *session, + gp11_attributes_unref (attrs); + + if (error != NULL) { +- g_warning ("couldn't search for matching item: %s", error->message); ++ g_warning ("couldn't search for matching item: %s", egg_error_message (error)); + g_clear_error (&error); + return NULL; + } +@@ -731,12 +733,12 @@ collection_method_create_item (GkdSecretObjects *self, GP11Object *object, DBusM + cleanup: + if (error) { + if (!reply) { +- if (error->code == CKR_USER_NOT_LOGGED_IN) ++ if (g_error_matches (error, GP11_ERROR, CKR_USER_NOT_LOGGED_IN)) + reply = dbus_message_new_error_printf (message, SECRET_ERROR_IS_LOCKED, + "Cannot create an item in a locked collection"); + else + reply = dbus_message_new_error_printf (message, DBUS_ERROR_FAILED, +- "Couldn't create item: %s", error->message); ++ "Couldn't create item: %s", egg_error_message (error)); + } + g_clear_error (&error); + } +@@ -771,7 +773,7 @@ collection_method_delete (GkdSecretObjects *self, GP11Object *object, DBusMessag + if (!gp11_object_destroy (object, &error)) { + reply = dbus_message_new_error_printf (message, DBUS_ERROR_FAILED, + "Couldn't delete collection: %s", +- error->message); ++ egg_error_message (error)); + g_clear_error (&error); + return reply; + } +@@ -987,7 +989,7 @@ gkd_secret_objects_dispatch (GkdSecretObjects *self, DBusMessage *message) + g_free (i_ident); + + if (error != NULL) { +- g_warning ("couldn't lookup object: %s: %s", path, error->message); ++ g_warning ("couldn't lookup object: %s: %s", path, egg_error_message (error)); + g_clear_error (&error); + } + +@@ -1033,7 +1035,7 @@ gkd_secret_objects_lookup_collection (GkdSecretObjects *self, const gchar *calle + g_free (identifier); + + if (error != NULL) { +- g_warning ("couldn't lookup collection: %s: %s", path, error->message); ++ g_warning ("couldn't lookup collection: %s: %s", path, egg_error_message (error)); + g_clear_error (&error); + } + +@@ -1078,7 +1080,7 @@ gkd_secret_objects_lookup_item (GkdSecretObjects *self, const gchar *caller, + g_free (collection); + + if (error != NULL) { +- g_warning ("couldn't lookup item: %s: %s", path, error->message); ++ g_warning ("couldn't lookup item: %s: %s", path, egg_error_message (error)); + g_clear_error (&error); + } + +@@ -1123,7 +1125,7 @@ gkd_secret_objects_append_item_paths (GkdSecretObjects *self, const gchar *base, + iter_append_item_paths (base, items, &variant); + dbus_message_iter_close_container (iter, &variant); + } else { +- g_warning ("couldn't lookup items in '%s' collection: %s", identifier, error->message); ++ g_warning ("couldn't lookup items in '%s' collection: %s", identifier, egg_error_message (error)); + g_clear_error (&error); + } + +@@ -1152,7 +1154,7 @@ gkd_secret_objects_append_collection_paths (GkdSecretObjects *self, DBusMessageI + GP11_INVALID); + + if (error != NULL) { +- g_warning ("couldn't lookup collections: %s", error->message); ++ g_warning ("couldn't lookup collections: %s", egg_error_message (error)); + g_clear_error (&error); + return; + } +@@ -1217,7 +1219,7 @@ gkd_secret_objects_handle_search_items (GkdSecretObjects *self, DBusMessage *mes + if (error != NULL) { + reply = dbus_message_new_error_printf (message, DBUS_ERROR_FAILED, + "Couldn't search for items: %s", +- error->message); ++ egg_error_message (error)); + g_clear_error (&error); + return reply; + } +@@ -1231,7 +1233,7 @@ gkd_secret_objects_handle_search_items (GkdSecretObjects *self, DBusMessage *mes + if (error != NULL) { + reply = dbus_message_new_error_printf (message, DBUS_ERROR_FAILED, + "Couldn't retrieve matched items: %s", +- error->message); ++ egg_error_message (error)); + g_clear_error (&error); + return reply; + } +diff --git a/daemon/dbus/gkd-secret-service.c b/daemon/dbus/gkd-secret-service.c +index 6c282de..8d51f3a 100644 +--- a/daemon/dbus/gkd-secret-service.c ++++ b/daemon/dbus/gkd-secret-service.c +@@ -36,6 +36,7 @@ + #include "gkd-secret-unlock.h" + #include "gkd-secret-util.h" + ++#include "egg/egg-error.h" + #include "egg/egg-unix-credentials.h" + + #include "gp11/gp11.h" +@@ -120,10 +121,8 @@ store_default (GkdSecretService *self) + return; + + path = default_path (); +- if (!g_file_set_contents (path, identifier, -1, &error)) { +- g_message ("couldn't store default keyring: %s", +- error->message ? error->message : ""); +- } ++ if (!g_file_set_contents (path, identifier, -1, &error)) ++ g_message ("couldn't store default keyring: %s", egg_error_message (error)); + g_free (path); + } + +@@ -1224,7 +1223,7 @@ gkd_secret_service_get_pkcs11_session (GkdSecretService *self, const gchar *call + NULL, NULL, &error); + if (!client->pkcs11_session) { + g_warning ("couldn't open pkcs11 session for secret service: %s", +- error->message); ++ egg_error_message (error)); + g_clear_error (&error); + return NULL; + } +@@ -1235,7 +1234,7 @@ gkd_secret_service_get_pkcs11_session (GkdSecretService *self, const gchar *call + gp11_token_info_free (info); + if (login && !gp11_session_login (client->pkcs11_session, CKU_USER, NULL, 0, &error)) { + g_warning ("couldn't log in to pkcs11 session for secret service: %s", +- error->message); ++ egg_error_message (error)); + g_clear_error (&error); + g_object_unref (client->pkcs11_session); + client->pkcs11_session = NULL; +diff --git a/daemon/dbus/gkd-secret-session.c b/daemon/dbus/gkd-secret-session.c +index 7d6efb6..80cd054 100644 +--- a/daemon/dbus/gkd-secret-session.c ++++ b/daemon/dbus/gkd-secret-session.c +@@ -29,6 +29,7 @@ + #include "gkd-dbus-util.h" + + #include "egg/egg-dh.h" ++#include "egg/egg-error.h" + + #include "pkcs11/pkcs11i.h" + +@@ -105,7 +106,7 @@ aes_create_dh_keys (GP11Session *session, const gchar *group, + gp11_attributes_unref (attrs); + + if (ret == FALSE) { +- g_warning ("couldn't generate dh key pair: %s", error->message); ++ g_warning ("couldn't generate dh key pair: %s", egg_error_message (error)); + g_clear_error (&error); + return FALSE; + } +@@ -135,7 +136,7 @@ aes_derive_key (GP11Session *session, GP11Object *priv_key, + gp11_attributes_unref (attrs); + + if (!*aes_key) { +- g_warning ("couldn't derive aes key from dh key pair: %s", error->message); ++ g_warning ("couldn't derive aes key from dh key pair: %s", egg_error_message (error)); + g_clear_error (&error); + return FALSE; + } +@@ -169,7 +170,7 @@ aes_negotiate (GkdSecretSession *self, DBusMessage *message, gconstpointer input + g_object_unref (pub); + + if (output == NULL) { +- g_warning ("couldn't get public key DH value: %s", error->message); ++ g_warning ("couldn't get public key DH value: %s", egg_error_message (error)); + g_clear_error (&error); + g_object_unref (priv); + return dbus_message_new_error_printf (message, DBUS_ERROR_FAILED, +@@ -221,7 +222,7 @@ plain_negotiate (GkdSecretSession *self, DBusMessage *message) + GP11_INVALID); + + if (key == NULL) { +- g_warning ("couldn't create null key: %s", error->message); ++ g_warning ("couldn't create null key: %s", egg_error_message (error)); + g_clear_error (&error); + return dbus_message_new_error_printf (message, DBUS_ERROR_FAILED, + "Failed to create necessary plain keys."); +@@ -444,7 +445,7 @@ gkd_secret_session_begin (GkdSecretSession *self, const gchar *group, + g_object_unref (public); + + if (output == NULL) { +- g_warning ("couldn't get public key DH value: %s", error->message); ++ g_warning ("couldn't get public key DH value: %s", egg_error_message (error)); + g_clear_error (&error); + return NULL; + } +@@ -597,11 +598,11 @@ gkd_secret_session_get_item_secret (GkdSecretSession *self, GP11Object *item, + gp11_mechanism_unref (mech); + + if (value == NULL) { +- if (error->code == CKR_USER_NOT_LOGGED_IN) { ++ if (g_error_matches (error, GP11_ERROR, CKR_USER_NOT_LOGGED_IN)) { + dbus_set_error_const (derr, SECRET_ERROR_IS_LOCKED, + "Cannot get secret of a locked object"); + } else { +- g_message ("couldn't wrap item secret: %s", error->message); ++ g_message ("couldn't wrap item secret: %s", egg_error_message (error)); + dbus_set_error_const (derr, DBUS_ERROR_FAILED, + "Couldn't get item secret"); + } +@@ -636,7 +637,7 @@ gkd_secret_session_set_item_secret (GkdSecretSession *self, GP11Object *item, + + attrs = gp11_object_get (item, &error, CKA_ID, CKA_G_COLLECTION, GP11_INVALID); + if (attrs == NULL) { +- g_message ("couldn't get item attributes: %s", error->message); ++ g_message ("couldn't get item attributes: %s", egg_error_message (error)); + dbus_set_error_const (derr, DBUS_ERROR_FAILED, "Couldn't set item secret"); + g_clear_error (&error); + return FALSE; +@@ -656,16 +657,16 @@ gkd_secret_session_set_item_secret (GkdSecretSession *self, GP11Object *item, + gp11_attributes_unref (attrs); + + if (object == NULL) { +- if (error->code == CKR_USER_NOT_LOGGED_IN) { ++ if (g_error_matches (error, GP11_ERROR, CKR_USER_NOT_LOGGED_IN)) { + dbus_set_error_const (derr, SECRET_ERROR_IS_LOCKED, + "Cannot set secret of a locked item"); +- } else if (error->code == CKR_WRAPPED_KEY_INVALID || +- error->code == CKR_WRAPPED_KEY_LEN_RANGE || +- error->code == CKR_MECHANISM_PARAM_INVALID) { ++ } else if (g_error_matches (error, GP11_ERROR, CKR_WRAPPED_KEY_INVALID) || ++ g_error_matches (error, GP11_ERROR, CKR_WRAPPED_KEY_LEN_RANGE) || ++ g_error_matches (error, GP11_ERROR, CKR_MECHANISM_PARAM_INVALID)) { + dbus_set_error_const (derr, DBUS_ERROR_INVALID_ARGS, + "The secret was transferred or encrypted in an invalid way."); + } else { +- g_message ("couldn't unwrap item secret: %s", error->message); ++ g_message ("couldn't unwrap item secret: %s", egg_error_message (error)); + dbus_set_error_const (derr, DBUS_ERROR_FAILED, "Couldn't set item secret"); + } + g_clear_error (&error); +@@ -716,15 +717,15 @@ gkd_secret_session_create_credential (GkdSecretSession *self, GP11Session *sessi + gp11_attributes_unref (alloc); + + if (object == NULL) { +- if (error->code == CKR_PIN_INCORRECT) { ++ if (g_error_matches (error, GP11_ERROR, CKR_PIN_INCORRECT)) { + dbus_set_error_const (derr, INTERNAL_ERROR_DENIED, "The password was incorrect."); +- } else if (error->code == CKR_WRAPPED_KEY_INVALID || +- error->code == CKR_WRAPPED_KEY_LEN_RANGE || +- error->code == CKR_MECHANISM_PARAM_INVALID) { ++ } else if (g_error_matches (error, GP11_ERROR, CKR_WRAPPED_KEY_INVALID) || ++ g_error_matches (error, GP11_ERROR, CKR_WRAPPED_KEY_LEN_RANGE) || ++ g_error_matches (error, GP11_ERROR, CKR_MECHANISM_PARAM_INVALID)) { + dbus_set_error_const (derr, DBUS_ERROR_INVALID_ARGS, + "The secret was transferred or encrypted in an invalid way."); + } else { +- g_message ("couldn't unwrap credential: %s", error->message); ++ g_message ("couldn't unwrap credential: %s", egg_error_message (error)); + dbus_set_error_const (derr, DBUS_ERROR_FAILED, "Couldn't use credentials"); + } + g_clear_error (&error); +diff --git a/daemon/dbus/gkd-secret-unlock.c b/daemon/dbus/gkd-secret-unlock.c +index 6f182a9..ee17fd1 100644 +--- a/daemon/dbus/gkd-secret-unlock.c ++++ b/daemon/dbus/gkd-secret-unlock.c +@@ -30,6 +30,7 @@ + #include "gkd-secret-unlock.h" + #include "gkd-secret-util.h" + ++#include "egg/egg-error.h" + #include "egg/egg-secure-memory.h" + + #include "login/gkd-login.h" +@@ -63,7 +64,7 @@ attributes_for_collection (GP11Object *collection) + + attrs = gp11_object_get (collection, &error, CKA_LABEL, CKA_ID, GP11_INVALID); + if (attrs == NULL) { +- g_warning ("couldn't get attributes for collection: %s", error->message); ++ g_warning ("couldn't get attributes for collection: %s", egg_error_message (error)); + g_clear_error (&error); + return NULL; + } +@@ -206,7 +207,8 @@ prepare_unlock_prompt (GkdSecretUnlock *self, GP11Object *coll, gboolean first) + gkd_prompt_set_unlock_options (prompt, template); + gp11_attributes_unref (template); + } else { +- g_warning ("couldn't get credential template for collection: %s", error->message); ++ g_warning ("couldn't get credential template for collection: %s", ++ egg_error_message (error)); + g_clear_error (&error); + } + } +@@ -228,9 +230,9 @@ check_locked_collection (GP11Object *collection, gboolean *locked) + + value = gp11_object_get_data (collection, CKA_G_LOCKED, &n_value, &error); + if (value == NULL) { +- if (error->code != CKR_OBJECT_HANDLE_INVALID) ++ if (!g_error_matches (error, GP11_ERROR, CKR_OBJECT_HANDLE_INVALID)) + g_warning ("couldn't check locked status of collection: %s", +- error->message); ++ egg_error_message (error)); + return FALSE; + } + +@@ -269,7 +271,8 @@ attach_credential_to_login (GP11Object *collection, GP11Object *cred) + egg_secure_free (value); + + } else { +- g_warning ("couldn't read unlock credentials to save in login keyring: %s", error->message); ++ g_warning ("couldn't read unlock credentials to save in login keyring: %s", ++ egg_error_message (error)); + g_clear_error (&error); + } + +@@ -634,10 +637,10 @@ gkd_secret_unlock_with_password (GP11Object *collection, const guchar *password, + + cred = gp11_session_create_object_full (session, attrs, NULL, &error); + if (cred == NULL) { +- if (error->code == CKR_PIN_INCORRECT) { ++ if (g_error_matches (error, GP11_ERROR, CKR_PIN_INCORRECT)) { + dbus_set_error_const (derr, INTERNAL_ERROR_DENIED, "The password was incorrect."); + } else { +- g_message ("couldn't create credential: %s", error->message); ++ g_message ("couldn't create credential: %s", egg_error_message (error)); + dbus_set_error_const (derr, DBUS_ERROR_FAILED, "Couldn't use credentials"); + } + g_clear_error (&error); +diff --git a/daemon/gkd-main.c b/daemon/gkd-main.c +index dab83cc..6ac0b65 100644 +--- a/daemon/gkd-main.c ++++ b/daemon/gkd-main.c +@@ -31,6 +31,7 @@ + #include "dbus/gkd-dbus.h" + + #include "egg/egg-cleanup.h" ++#include "egg/egg-error.h" + #include "egg/egg-libgcrypt.h" + #include "egg/egg-secure-memory.h" + #include "egg/egg-unix-credentials.h" +@@ -122,7 +123,7 @@ parse_arguments (int *argc, char** argv[]) + g_option_context_add_main_entries (context, option_entries, GETTEXT_PACKAGE); + + if (!g_option_context_parse (context, argc, argv, &err)) { +- g_printerr ("gnome-keyring-daemon: %s", err && err->message ? err->message : ""); ++ g_printerr ("gnome-keyring-daemon: %s", egg_error_message (err)); + g_clear_error (&err); + } + +diff --git a/daemon/login/gkd-login.c b/daemon/login/gkd-login.c +index 9d38125..bdef57d 100644 +--- a/daemon/login/gkd-login.c ++++ b/daemon/login/gkd-login.c +@@ -23,6 +23,7 @@ + + #include "gkd-login.h" + ++#include "egg/egg-error.h" + #include "egg/egg-secure-memory.h" + + #include "pkcs11/gkd-pkcs11.h" +@@ -117,8 +118,8 @@ lookup_login_session (GP11Module *module) + g_return_val_if_fail (slot, NULL); + + session = open_and_login_session (slot, CKU_USER, &error); +- if (session == NULL) { +- g_warning ("couldn't open pkcs11 session for login: %s", error->message); ++ if (error) { ++ g_warning ("couldn't open pkcs11 session for login: %s", egg_error_message (error)); + g_clear_error (&error); + } + +@@ -144,7 +145,7 @@ lookup_login_keyring (GP11Session *session) + GP11_INVALID); + + if (error) { +- g_warning ("couldn't search for login keyring: %s", error->message); ++ g_warning ("couldn't search for login keyring: %s", egg_error_message (error)); + g_clear_error (&error); + return NULL; + } +@@ -238,17 +239,17 @@ unlock_or_create_login (GP11Module *module, const gchar *master) + + /* Failure, bad password? */ + if (cred == NULL) { +- if (login && error->code == CKR_PIN_INCORRECT) ++ if (login && g_error_matches (error, GP11_ERROR, CKR_PIN_INCORRECT)) + note_that_unlock_failed (); + else +- g_warning ("couldn't create login credential: %s", error->message); ++ g_warning ("couldn't create login credential: %s", egg_error_message (error)); + g_clear_error (&error); + + /* Non login keyring, create it */ + } else if (!login) { + login = create_login_keyring (session, cred, &error); +- if (login == NULL) { +- g_warning ("couldn't create login keyring: %s", error->message); ++ if (login == NULL && error) { ++ g_warning ("couldn't create login keyring: %s", egg_error_message (error)); + g_clear_error (&error); + } + +@@ -293,8 +294,9 @@ init_pin_for_uninitialized_slots (GP11Module *module, const gchar *master) + "serial-number", info->serial_number, + NULL); + } else { +- if (error->code != CKR_FUNCTION_NOT_SUPPORTED) +- g_warning ("couldn't initialize slot with master password: %s", error->message); ++ if (!g_error_matches (error, GP11_ERROR, CKR_FUNCTION_NOT_SUPPORTED)) ++ g_warning ("couldn't initialize slot with master password: %s", ++ egg_error_message (error)); + g_clear_error (&error); + } + g_object_unref (session); +@@ -348,19 +350,21 @@ change_or_create_login (GP11Module *module, const gchar *original, const gchar * + /* Create the new credential we'll be changing to */ + mcred = create_credential (session, NULL, master, &error); + if (mcred == NULL) { +- g_warning ("couldn't create new login credential: %s", error->message); ++ g_warning ("couldn't create new login credential: %s", egg_error_message (error)); + g_clear_error (&error); + + /* Create original credentials */ + } else if (login) { + ocred = create_credential (session, login, original, &error); + if (ocred == NULL) { +- if (error->code == CKR_PIN_INCORRECT) { ++ if (g_error_matches (error, GP11_ERROR, CKR_PIN_INCORRECT)) { + g_message ("couldn't change login master password, " +- "original password was wrong: %s", error->message); ++ "original password was wrong: %s", ++ egg_error_message (error)); + note_that_unlock_failed (); + } else { +- g_warning ("couldn't create original login credential: %s", error->message); ++ g_warning ("couldn't create original login credential: %s", ++ egg_error_message (error)); + } + g_clear_error (&error); + } +@@ -370,7 +374,7 @@ change_or_create_login (GP11Module *module, const gchar *original, const gchar * + if (!login && mcred) { + login = create_login_keyring (session, mcred, &error); + if (login == NULL) { +- g_warning ("couldn't create login keyring: %s", error->message); ++ g_warning ("couldn't create login keyring: %s", egg_error_message (error)); + g_clear_error (&error); + } else { + success = TRUE; +@@ -381,7 +385,7 @@ change_or_create_login (GP11Module *module, const gchar *original, const gchar * + if (!gp11_object_set (login, &error, + CKA_G_CREDENTIAL, GP11_ULONG, gp11_object_get_handle (mcred), + GP11_INVALID)) { +- g_warning ("couldn't change login master password: %s", error->message); ++ g_warning ("couldn't change login master password: %s", egg_error_message (error)); + g_clear_error (&error); + } else { + success = TRUE; +@@ -432,8 +436,10 @@ set_pin_for_any_slots (GP11Module *module, const gchar *original, const gchar *m + "serial-number", info->serial_number, + NULL); + } else { +- if (error->code != CKR_PIN_INCORRECT && error->code != CKR_FUNCTION_NOT_SUPPORTED) +- g_warning ("couldn't change slot master password: %s", error->message); ++ if (!g_error_matches (error, GP11_ERROR, CKR_PIN_INCORRECT) && ++ !g_error_matches (error, GP11_ERROR, CKR_FUNCTION_NOT_SUPPORTED)) ++ g_warning ("couldn't change slot master password: %s", ++ egg_error_message (error)); + g_clear_error (&error); + } + g_object_unref (session); +@@ -537,7 +543,7 @@ find_login_keyring_item (GP11Session *session, GP11Attribute *fields) + GP11_INVALID); + + if (!search) { +- g_warning ("couldn't create search for login keyring: %s", error->message); ++ g_warning ("couldn't create search for login keyring: %s", egg_error_message (error)); + g_clear_error (&error); + return NULL; + } +@@ -549,7 +555,7 @@ find_login_keyring_item (GP11Session *session, GP11Attribute *fields) + g_object_unref (search); + + if (data == NULL) { +- g_warning ("couldn't read search in login keyring: %s", error->message); ++ g_warning ("couldn't read search in login keyring: %s", egg_error_message (error)); + g_clear_error (&error); + return NULL; + } +@@ -613,7 +619,7 @@ gkd_login_attach_secret (const gchar *label, const gchar *secret, + } + + if (error != NULL) { +- g_warning ("couldn't store secret in login keyring: %s", error->message); ++ g_warning ("couldn't store secret in login keyring: %s", egg_error_message (error)); + g_clear_error (&error); + } + +@@ -684,8 +690,9 @@ gkd_login_remove_secret (const gchar *first, ...) + item = find_login_keyring_item (session, &fields); + if (item != NULL) { + if (!gp11_object_destroy (item, &error)) { +- if (error->code != CKR_OBJECT_HANDLE_INVALID) +- g_warning ("couldn't remove stored secret from login keyring: %s", error->message); ++ if (!g_error_matches (error, GP11_ERROR, CKR_OBJECT_HANDLE_INVALID)) ++ g_warning ("couldn't remove stored secret from login keyring: %s", ++ egg_error_message (error)); + g_clear_error (&error); + } + g_object_unref (item); +diff --git a/daemon/prompt/gkd-prompt-tool.c b/daemon/prompt/gkd-prompt-tool.c +index 19257f2..ab03fdb 100644 +--- a/daemon/prompt/gkd-prompt-tool.c ++++ b/daemon/prompt/gkd-prompt-tool.c +@@ -26,6 +26,7 @@ + + #include "egg/egg-dh.h" + #include "egg/egg-entry-buffer.h" ++#include "egg/egg-error.h" + #include "egg/egg-libgcrypt.h" + #include "egg/egg-secure-memory.h" + +@@ -359,8 +360,7 @@ prepare_dialog (GtkBuilder *builder) + GtkDialog *dialog; + + if (!gtk_builder_add_from_file (builder, UIDIR "gkd-prompt.ui", &error)) { +- g_warning ("couldn't load prompt ui file: %s", +- error && error->message ? error->message : ""); ++ g_warning ("couldn't load prompt ui file: %s", egg_error_message (error)); + g_clear_error (&error); + return NULL; + } +@@ -889,7 +889,7 @@ main (int argc, char *argv[]) + g_free (data); + + if (!ret) +- fatal ("couldn't parse auth dialog instructions", err ? err->message : ""); ++ fatal ("couldn't parse auth dialog instructions", egg_error_message (err)); + + run_dialog (); + +@@ -906,7 +906,7 @@ main (int argc, char *argv[]) + g_key_file_free (output_data); + + if (!data) +- fatal ("couldn't format auth dialog response: %s", err ? err->message : ""); ++ fatal ("couldn't format auth dialog response: %s", egg_error_message (err)); + + write_all_output (data, length); + g_free (data); +diff --git a/daemon/prompt/gkd-prompt.c b/daemon/prompt/gkd-prompt.c +index 104db8f..a4ea7fc 100644 +--- a/daemon/prompt/gkd-prompt.c ++++ b/daemon/prompt/gkd-prompt.c +@@ -27,6 +27,7 @@ + + #include "egg/egg-cleanup.h" + #include "egg/egg-dh.h" ++#include "egg/egg-error.h" + #include "egg/egg-hex.h" + #include "egg/egg-secure-memory.h" + #include "egg/egg-spawn.h" +@@ -256,8 +257,7 @@ on_io_completed (gpointer user_data) + if (!g_key_file_load_from_data (self->pv->output, self->pv->out_data->str, + self->pv->out_data->len, G_KEY_FILE_NONE, &error)) { + g_key_file_free (self->pv->output); +- g_warning ("couldn't parse output from prompt: %s", +- error && error->message ? error->message : ""); ++ g_warning ("couldn't parse output from prompt: %s", egg_error_message (error)); + g_clear_error (&error); + mark_failed (self); + } else { +@@ -372,8 +372,7 @@ prepare_input_data (GkdPrompt *self) + + self->pv->in_data = g_key_file_to_data (self->pv->input, &self->pv->in_length, &error); + if (!self->pv->in_data) { +- g_warning ("couldn't encode data for prompt: %s", +- error && error->message ? error->message : ""); ++ g_warning ("couldn't encode data for prompt: %s", egg_error_message (error)); + g_clear_error (&error); + mark_failed (self); + return FALSE; +@@ -434,8 +433,7 @@ display_async_prompt (GkdPrompt *self) + &self->pv->pid, &callbacks, g_object_ref (self), + NULL, &error); + if (!self->pv->io_tag) { +- g_warning ("couldn't spawn prompt tool: %s", +- error && error->message ? error->message : ""); ++ g_warning ("couldn't spawn prompt tool: %s", egg_error_message (error)); + g_clear_error (&error); + self->pv->pid = 0; + mark_failed (self); +diff --git a/daemon/ssh-agent/gkd-ssh-agent-ops.c b/daemon/ssh-agent/gkd-ssh-agent-ops.c +index a8d2da7..759a06a 100644 +--- a/daemon/ssh-agent/gkd-ssh-agent-ops.c ++++ b/daemon/ssh-agent/gkd-ssh-agent-ops.c +@@ -30,6 +30,7 @@ + #include "pkcs11/pkcs11g.h" + #include "pkcs11/pkcs11i.h" + ++#include "egg/egg-error.h" + #include "egg/egg-secure-memory.h" + + #include +@@ -72,7 +73,7 @@ login_session (GP11Session *session) + /* Log in the session if necessary */ + if (info->state == CKS_RO_PUBLIC_SESSION || info->state == CKS_RW_PUBLIC_SESSION) { + if (!gp11_session_login (session, CKU_USER, NULL, 0, &error)) { +- g_message ("couldn't log in to session: %s", error->message); ++ g_message ("couldn't log in to session: %s", egg_error_message (error)); + ret = FALSE; + } + } +@@ -134,7 +135,7 @@ search_keys_like_attributes (gpointer session_or_module, GP11Attributes *attrs, + if (GP11_IS_MODULE (session_or_module)) { + if (!gp11_module_enumerate_objects_full (session_or_module, search, NULL, + func, user_data, &error)) { +- g_warning ("couldn't enumerate matching keys: %s", error->message); ++ g_warning ("couldn't enumerate matching keys: %s", egg_error_message (error)); + g_clear_error (&error); + } + +@@ -143,7 +144,7 @@ search_keys_like_attributes (gpointer session_or_module, GP11Attributes *attrs, + keys = gp11_session_find_objects_full (session_or_module, search, NULL, &error); + + if (error) { +- g_warning ("couldn't find matching keys: %s", error->message); ++ g_warning ("couldn't find matching keys: %s", egg_error_message (error)); + g_clear_error (&error); + + } else { +@@ -206,7 +207,7 @@ return_private_matching (GP11Object *object, gpointer user_data) + /* Get the key identifier and token */ + attrs = gp11_object_get (object, &error, CKA_ID, CKA_TOKEN, GP11_INVALID); + if (error) { +- g_warning ("error retrieving attributes for public key: %s", error->message); ++ g_warning ("error retrieving attributes for public key: %s", egg_error_message (error)); + g_clear_error (&error); + return TRUE; + } +@@ -264,7 +265,7 @@ load_identity_v1_attributes (GP11Object *object, gpointer user_data) + attrs = gp11_object_get (object, &error, CKA_ID, CKA_LABEL, CKA_KEY_TYPE, CKA_MODULUS, + CKA_PUBLIC_EXPONENT, CKA_CLASS, CKA_MODULUS_BITS, GP11_INVALID); + if (error) { +- g_warning ("error retrieving attributes for public key: %s", error->message); ++ g_warning ("error retrieving attributes for public key: %s", egg_error_message (error)); + g_clear_error (&error); + return TRUE; + } +@@ -295,7 +296,7 @@ load_identity_v2_attributes (GP11Object *object, gpointer user_data) + CKA_PUBLIC_EXPONENT, CKA_PRIME, CKA_SUBPRIME, CKA_BASE, + CKA_VALUE, CKA_CLASS, CKA_MODULUS_BITS, CKA_TOKEN, GP11_INVALID); + if (error) { +- g_warning ("error retrieving attributes for public key: %s", error->message); ++ g_warning ("error retrieving attributes for public key: %s", egg_error_message (error)); + g_clear_error (&error); + return TRUE; + } +@@ -339,8 +340,8 @@ remove_key_pair (GP11Session *session, GP11Object *priv, GP11Object *pub) + gp11_object_destroy (priv, &error); + + if (error) { +- if (error->code != CKR_OBJECT_HANDLE_INVALID) +- g_warning ("couldn't remove ssh private key: %s", error->message); ++ if (!g_error_matches (error, GP11_ERROR, CKR_OBJECT_HANDLE_INVALID)) ++ g_warning ("couldn't remove ssh private key: %s", egg_error_message (error)); + g_clear_error (&error); + } + } +@@ -350,8 +351,8 @@ remove_key_pair (GP11Session *session, GP11Object *priv, GP11Object *pub) + gp11_object_destroy (pub, &error); + + if (error) { +- if (error->code != CKR_OBJECT_HANDLE_INVALID) +- g_warning ("couldn't remove ssh public key: %s", error->message); ++ if (!g_error_matches (error, GP11_ERROR, CKR_OBJECT_HANDLE_INVALID)) ++ g_warning ("couldn't remove ssh public key: %s", egg_error_message (error)); + g_clear_error (&error); + } + } +@@ -377,7 +378,7 @@ lock_key_pair (GP11Session *session, GP11Object *priv, GP11Object *pub) + GP11_INVALID); + + if (error) { +- g_warning ("couldn't search for authenticator objects: %s", error->message); ++ g_warning ("couldn't search for authenticator objects: %s", egg_error_message (error)); + g_clear_error (&error); + return; + } +@@ -386,7 +387,7 @@ lock_key_pair (GP11Session *session, GP11Object *priv, GP11Object *pub) + for (l = objects; l; l = g_list_next (l)) { + gp11_object_destroy (l->data, &error); + if (error) { +- g_warning ("couldn't delete authenticator object: %s", error->message); ++ g_warning ("couldn't delete authenticator object: %s", egg_error_message (error)); + g_clear_error (&error); + } + } +@@ -412,7 +413,7 @@ remove_by_public_key (GP11Session *session, GP11Object *pub, gboolean exclude_v1 + CKA_LABEL, CKA_ID, CKA_TOKEN, + GP11_INVALID); + if (error) { +- g_warning ("couldn't lookup attributes for key: %s", error->message); ++ g_warning ("couldn't lookup attributes for key: %s", egg_error_message (error)); + g_clear_error (&error); + return; + } +@@ -436,7 +437,7 @@ remove_by_public_key (GP11Session *session, GP11Object *pub, gboolean exclude_v1 + gp11_attributes_unref (attrs); + + if (error) { +- g_warning ("couldn't search for related key: %s", error->message); ++ g_warning ("couldn't search for related key: %s", egg_error_message (error)); + g_clear_error (&error); + return; + } +@@ -466,14 +467,14 @@ create_key_pair (GP11Session *session, GP11Attributes *priv, GP11Attributes *pub + + priv_key = gp11_session_create_object_full (session, priv, NULL, &error); + if (error) { +- g_warning ("couldn't create session private key: %s", error->message); ++ g_warning ("couldn't create session private key: %s", egg_error_message (error)); + g_clear_error (&error); + return FALSE; + } + + pub_key = gp11_session_create_object_full (session, pub, NULL, &error); + if (error) { +- g_warning ("couldn't create session public key: %s", error->message); ++ g_warning ("couldn't create session public key: %s", egg_error_message (error)); + g_clear_error (&error); + + /* Failed, so remove private as well */ +@@ -501,8 +502,9 @@ destroy_replaced_keys (GP11Session *session, GList *keys) + for (l = keys; l; l = g_list_next (l)) { + gp11_object_set_session (l->data, session); + if (!gp11_object_destroy (l->data, &error)) { +- if (error->code != CKR_OBJECT_HANDLE_INVALID) +- g_warning ("couldn't delete a SSH key we replaced: %s", error->message); ++ if (!g_error_matches (error, GP11_ERROR, CKR_OBJECT_HANDLE_INVALID)) ++ g_warning ("couldn't delete a SSH key we replaced: %s", ++ egg_error_message (error)); + g_clear_error (&error); + } + } +@@ -967,8 +969,8 @@ op_sign_request (GkdSshAgentCall *call) + g_free (hash); + + if (error) { +- if (error->code != CKR_FUNCTION_CANCELED) +- g_message ("signing of the data failed: %s", error->message); ++ if (!g_error_matches (error, GP11_ERROR, CKR_FUNCTION_CANCELED)) ++ g_message ("signing of the data failed: %s", egg_error_message (error)); + g_clear_error (&error); + egg_buffer_add_byte (call->resp, GKD_SSH_RES_FAILURE); + return TRUE; +@@ -1084,8 +1086,8 @@ op_v1_challenge (GkdSshAgentCall *call) + g_object_unref (key); + + if (error) { +- if (error->code != CKR_FUNCTION_CANCELED) +- g_message ("decryption of the data failed: %s", error->message); ++ if (!g_error_matches (error, GP11_ERROR, CKR_FUNCTION_CANCELED)) ++ g_message ("decryption of the data failed: %s", egg_error_message (error)); + g_clear_error (&error); + egg_buffer_add_byte (call->resp, GKD_SSH_RES_FAILURE); + return TRUE; +diff --git a/daemon/ssh-agent/gkd-ssh-agent-standalone.c b/daemon/ssh-agent/gkd-ssh-agent-standalone.c +index acfe3c9..349f86d 100644 +--- a/daemon/ssh-agent/gkd-ssh-agent-standalone.c ++++ b/daemon/ssh-agent/gkd-ssh-agent-standalone.c +@@ -25,6 +25,7 @@ + #include "gkd-ssh-agent.h" + #include "gkd-ssh-agent-private.h" + ++#include "egg/egg-error.h" + #include "egg/egg-secure-memory.h" + + #include "gp11/gp11.h" +@@ -98,7 +99,7 @@ main(int argc, char *argv[]) + + module = gp11_module_initialize (argv[1], argc > 2 ? argv[2] : NULL, &error); + if (!module) { +- g_message ("couldn't load pkcs11 module: %s", error->message); ++ g_message ("couldn't load pkcs11 module: %s", egg_error_message (error)); + g_clear_error (&error); + return 1; + } +diff --git a/daemon/ssh-agent/gkd-ssh-agent.c b/daemon/ssh-agent/gkd-ssh-agent.c +index 50a1b79..be2f89e 100644 +--- a/daemon/ssh-agent/gkd-ssh-agent.c ++++ b/daemon/ssh-agent/gkd-ssh-agent.c +@@ -37,6 +37,7 @@ + #include "gkd-ssh-agent-private.h" + + #include "egg/egg-buffer.h" ++#include "egg/egg-error.h" + #include "egg/egg-secure-memory.h" + + #ifndef HAVE_SOCKLEN_T +@@ -285,7 +286,7 @@ gkd_ssh_agent_accept (void) + client->thread = g_thread_create (run_client_thread, &client->sock, TRUE, &error); + if (!client->thread) { + g_warning ("couldn't create thread SSH agent connection: %s", +- error && error->message ? error->message : ""); ++ egg_error_message (error)); + g_slice_free (Client, client); + return; + } +@@ -382,7 +383,7 @@ gkd_ssh_agent_initialize_with_module (GP11Module *module) + /* Try and open a session */ + session = gp11_slot_open_session (l->data, CKF_SERIAL_SESSION, &error); + if (!session) { +- g_warning ("couldn't create pkcs#11 session: %s", error->message); ++ g_warning ("couldn't create pkcs#11 session: %s", egg_error_message (error)); + g_clear_error (&error); + } + } +diff --git a/egg/egg-error.h b/egg/egg-error.h +new file mode 100644 +index 0000000..50f459c +--- a/dev/null ++++ b/egg/egg-error.h +@@ -0,0 +1,34 @@ ++/* ++ * gnome-keyring ++ * ++ * Copyright (C) 2010 Stefan Walter ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU Lesser General License as ++ * published by the Free Software Foundation; either version 2.1 of ++ * the License, or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General ++ * License along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA ++ * 02111-1307, USA. ++ */ ++ ++#ifndef EGG_ERROR_H_ ++#define EGG_ERROR_H_ ++ ++#include ++ ++static inline const gchar* ++egg_error_message (GError *error) ++{ ++ g_return_val_if_fail (error, "(unknown)"); ++ return error->message ? error->message : "(null)"; ++} ++ ++#endif /* EGG_ERROR_H_ */ +diff --git a/gcr/gcr-library.c b/gcr/gcr-library.c +index 6f91ae2..cf08716 100644 +--- a/gcr/gcr-library.c ++++ b/gcr/gcr-library.c +@@ -25,6 +25,7 @@ + #include "gcr-types.h" + #include "gcr-internal.h" + ++#include "egg/egg-error.h" + #include "egg/egg-libgcrypt.h" + #include "egg/egg-secure-memory.h" + +@@ -127,7 +128,7 @@ _gcr_initialize (void) + all_modules = g_list_prepend (all_modules, module); + } else { + g_message ("couldn't initialize PKCS#11 module: %s", +- error && error->message ? error->message : ""); ++ egg_error_message (error)); + } + + g_once_init_leave (&gcr_initialized, 1); +diff --git a/gcr/tests/unit-test-parser.c b/gcr/tests/unit-test-parser.c +index 252d1db..cf0108e 100644 +--- a/gcr/tests/unit-test-parser.c ++++ b/gcr/tests/unit-test-parser.c +@@ -25,6 +25,7 @@ + + #include "run-auto-test.h" + ++#include "egg/egg-error.h" + #include "egg/egg-secure-memory.h" + + #include "gcr/gcr-parser.h" +@@ -129,7 +130,7 @@ DEFINE_TEST(parse_all) + result = gcr_parser_parse_data (parser, contents, len, &err); + if (!result) { + g_warning ("couldn't parse file data: %s: %s", +- filename, err && err->message ? err->message : ""); ++ filename, egg_error_message (err)); + g_error_free (err); + g_assert (FALSE); + } +diff --git a/gp11/gp11-module.c b/gp11/gp11-module.c +index 3fb3faa..8537a2d 100644 +--- a/gp11/gp11-module.c ++++ b/gp11/gp11-module.c +@@ -1172,7 +1172,7 @@ gp11_module_enumerate_objects_full (GP11Module *self, GP11Attributes *attrs, + g_return_val_if_fail (error != NULL, FALSE); + + /* Ignore these errors when enumerating */ +- if (error->code == CKR_USER_PIN_NOT_INITIALIZED) { ++ if (g_error_matches (error, GP11_ERROR, CKR_USER_PIN_NOT_INITIALIZED)) { + g_clear_error (&error); + + } else { +diff --git a/pkcs11/gck/gck-file-tracker.c b/pkcs11/gck/gck-file-tracker.c +index c21de4a..517677d 100644 +--- a/pkcs11/gck/gck-file-tracker.c ++++ b/pkcs11/gck/gck-file-tracker.c +@@ -25,6 +25,8 @@ + + #include "gck-file-tracker.h" + ++#include "egg/egg-error.h" ++ + #include + #include + +@@ -155,8 +157,8 @@ update_directory (GckFileTracker *self, gboolean force_all, GHashTable *checks) + dir = g_dir_open (self->directory_path, 0, &err); + if (dir == NULL) { + if (errno != ENOENT && errno != ENOTDIR && errno != EPERM) +- g_message ("couldn't list keyrings at: %s: %s", self->directory_path, +- err && err->message ? err->message : ""); ++ g_message ("couldn't list keyrings at: %s: %s", self->directory_path, ++ egg_error_message (err)); + g_error_free (err); + return; + } +diff --git a/pkcs11/gck/gck-timer.c b/pkcs11/gck/gck-timer.c +index 999670b..70b653d 100644 +--- a/pkcs11/gck/gck-timer.c ++++ b/pkcs11/gck/gck-timer.c +@@ -23,6 +23,8 @@ + + #include "gck-timer.h" + ++#include "egg/egg-error.h" ++ + #include + + struct _GckTimer { +@@ -116,7 +118,7 @@ gck_timer_initialize (void) + timer_cond = g_cond_new (); + } else { + g_warning ("could not create timer thread: %s", +- error && error->message ? error->message : ""); ++ egg_error_message (error)); + } + } + +diff --git a/pkcs11/roots-store/gck-roots-module.c b/pkcs11/roots-store/gck-roots-module.c +index 5d391de..f6418e8 100644 +--- a/pkcs11/roots-store/gck-roots-module.c ++++ b/pkcs11/roots-store/gck-roots-module.c +@@ -28,6 +28,7 @@ + #include "gck/gck-file-tracker.h" + #include "gck/gck-serializable.h" + ++#include "egg/egg-error.h" + #include "egg/egg-openssl.h" + + #include +@@ -187,7 +188,7 @@ file_load (GckFileTracker *tracker, const gchar *path, GckRootsModule *self) + /* Read in the public key */ + if (!g_file_get_contents (path, (gchar**)&data, &n_data, &error)) { + g_warning ("couldn't load root certificates: %s: %s", +- path, error && error->message ? error->message : ""); ++ path, egg_error_message (error)); + return; + } + +diff --git a/pkcs11/rpc-layer/gck-rpc-dispatch.c b/pkcs11/rpc-layer/gck-rpc-dispatch.c +index 73839ff..f2961d0 100644 +--- a/pkcs11/rpc-layer/gck-rpc-dispatch.c ++++ b/pkcs11/rpc-layer/gck-rpc-dispatch.c +@@ -30,6 +30,7 @@ + #include "pkcs11/pkcs11g.h" + #include "pkcs11/pkcs11i.h" + ++#include "egg/egg-error.h" + #include "egg/egg-unix-credentials.h" + + #include +@@ -2223,7 +2224,7 @@ gck_rpc_layer_accept (void) + + ds->thread = g_thread_create (run_dispatch_thread, &(ds->socket), TRUE, &error); + if (!ds->thread) { +- gck_rpc_warn ("couldn't start thread: %s", error && error->message ? error->message : ""); ++ gck_rpc_warn ("couldn't start thread: %s", egg_error_message (error)); + close (new_fd); + free (ds); + return; +diff --git a/pkcs11/secret-store/gck-secret-collection.c b/pkcs11/secret-store/gck-secret-collection.c +index aceb3be..e27d1ef 100644 +--- a/pkcs11/secret-store/gck-secret-collection.c ++++ b/pkcs11/secret-store/gck-secret-collection.c +@@ -27,6 +27,8 @@ + #include "gck-secret-item.h" + #include "gck-secret-textual.h" + ++#include "egg/egg-error.h" ++ + #include "gck/gck-attributes.h" + #include "gck/gck-credential.h" + #include "gck/gck-secret.h" +@@ -73,7 +75,7 @@ load_collection_and_secret_data (GckSecretCollection *self, GckSecretData *sdata + /* Read in the keyring */ + if (!g_file_get_contents (path, (gchar**)&data, &n_data, &error)) { + g_message ("problem reading keyring: %s: %s", +- path, error && error->message ? error->message : ""); ++ path, egg_error_message (error)); + g_clear_error (&error); + return GCK_DATA_FAILURE; + } +diff --git a/pkcs11/secret-store/gck-secret-textual.c b/pkcs11/secret-store/gck-secret-textual.c +index 2eaddd9..1627ac9 100644 +--- a/pkcs11/secret-store/gck-secret-textual.c ++++ b/pkcs11/secret-store/gck-secret-textual.c +@@ -30,8 +30,9 @@ + #include "gck-secret-item.h" + #include "gck-secret-textual.h" + +-#include "egg/egg-secure-memory.h" ++#include "egg/egg-error.h" + #include "egg/egg-hex.h" ++#include "egg/egg-secure-memory.h" + + #include "gck/gck-secret.h" + +@@ -424,7 +425,7 @@ gck_secret_textual_write (GckSecretCollection *collection, GckSecretData *sdata, + g_key_file_free (file); + + if (!*data) { +- g_warning ("couldn't generate textual keyring file: %s", err->message); ++ g_warning ("couldn't generate textual keyring file: %s", egg_error_message (err)); + return GCK_DATA_FAILURE; + } + +diff --git a/pkcs11/ssh-store/gck-ssh-module.c b/pkcs11/ssh-store/gck-ssh-module.c +index b9fa2cf..1f851a3 100644 +--- a/pkcs11/ssh-store/gck-ssh-module.c ++++ b/pkcs11/ssh-store/gck-ssh-module.c +@@ -25,6 +25,8 @@ + #include "gck-ssh-private-key.h" + #include "gck-ssh-public-key.h" + ++#include "egg/egg-error.h" ++ + #include "gck/gck-file-tracker.h" + + #include +@@ -130,8 +132,7 @@ file_load (GckFileTracker *tracker, const gchar *path, GckSshModule *self) + /* Parse the data into the key */ + if (!gck_ssh_private_key_parse (key, path, private_path, &error)) { + if (error) { +- g_message ("couldn't parse data: %s: %s", path, +- error->message ? error->message : ""); ++ g_message ("couldn't parse data: %s: %s", path, egg_error_message (error)); + g_clear_error (&error); + } + gck_object_expose (GCK_OBJECT (key), FALSE); +diff --git a/pkcs11/user-store/gck-user-storage.c b/pkcs11/user-store/gck-user-storage.c +index 5b002e6..3d46e6f 100644 +--- a/pkcs11/user-store/gck-user-storage.c ++++ b/pkcs11/user-store/gck-user-storage.c +@@ -34,6 +34,7 @@ + #include "gck/gck-serializable.h" + #include "gck/gck-util.h" + ++#include "egg/egg-error.h" + #include "egg/egg-hex.h" + + #include "pkcs11/pkcs11i.h" +@@ -530,7 +531,7 @@ data_file_entry_added (GckDataFile *store, const gchar *identifier, GckUserStora + + if (ret == FALSE) { + g_warning ("couldn't read file in user store: %s: %s", identifier, +- error && error->message ? error->message : ""); ++ egg_error_message (error)); + g_clear_error (&error); + return; + } +@@ -624,7 +625,7 @@ relock_object (GckUserStorage *self, GckTransaction *transaction, const gchar *p + /* Read in the data for the object */ + if (!g_file_get_contents (path, (gchar**)&data, &n_data, &error)) { + g_message ("couldn't load file in user store in order to relock: %s: %s", identifier, +- error && error->message ? error->message : ""); ++ egg_error_message (error)); + g_clear_error (&error); + g_object_unref (object); + gck_transaction_fail (transaction, CKR_GENERAL_ERROR); +diff --git a/tests/gtest-helpers.c b/tests/gtest-helpers.c +index d8164fb..bf976ea 100644 +--- a/tests/gtest-helpers.c ++++ b/tests/gtest-helpers.c +@@ -35,6 +35,7 @@ + + #include "gtest-helpers.h" + ++#include "egg/egg-error.h" + #include "egg/egg-secure-memory.h" + + #include "pkcs11/pkcs11.h" +@@ -150,7 +151,7 @@ test_data_read (const gchar *basename, gsize *n_result) + file = test_data_filename (basename); + if (!g_file_get_contents (file, &result, n_result, &error)) { + g_warning ("could not read test data file: %s: %s", file, +- error && error->message ? error->message : ""); ++ egg_error_message (error)); + g_assert_not_reached (); + } + +-- +cgit v0.8.3.1 diff --git a/gnome-keyring-2.30.0-dont-save-session-keyring-to-disk.patch b/gnome-keyring-2.30.0-dont-save-session-keyring-to-disk.patch new file mode 100644 index 0000000..01dba1d --- /dev/null +++ b/gnome-keyring-2.30.0-dont-save-session-keyring-to-disk.patch @@ -0,0 +1,259 @@ +From d30630070b2e7f6173ea872f45bb47b70948e796 Mon Sep 17 00:00:00 2001 +From: Stef Walter +Date: Sat, 20 Mar 2010 02:19:44 +0000 +Subject: [secret-store] Don't save session keyring to disk. + +There was a major problem where the session keyring was being saved +to disk, and since it had to master password, as a cleartext keyring + +Mark the session keyring as transient so it doesn't even come near +the storage code. Also rework the collection storage code, so that +it properly handles various corner cases. + +Fixes bug #612977 +--- +diff --git a/pkcs11/gck/gck-object.c b/pkcs11/gck/gck-object.c +index a568042..a2d03e2 100644 +--- a/pkcs11/gck/gck-object.c ++++ b/pkcs11/gck/gck-object.c +@@ -41,7 +41,8 @@ enum { + PROP_MODULE, + PROP_MANAGER, + PROP_STORE, +- PROP_UNIQUE ++ PROP_UNIQUE, ++ PROP_TRANSIENT + }; + + enum { +@@ -201,6 +202,13 @@ find_credential (GckCredential *cred, GckObject *object, gpointer user_data) + return TRUE; + } + ++static void ++mark_object_transient (GckObject *self) ++{ ++ if (!self->pv->transient) ++ self->pv->transient = g_slice_new0 (GckObjectTransient); ++} ++ + /* ----------------------------------------------------------------------------- + * OBJECT + */ +@@ -337,7 +345,7 @@ gck_object_real_create_attributes (GckObject *self, GckSession *session, + CKA_G_DESTRUCT_IDLE, CKA_GNOME_TRANSIENT, G_MAXULONG); + + if (transient) { +- self->pv->transient = g_slice_new0 (GckObjectTransient); ++ mark_object_transient (self); + self->pv->transient->timed_after = after; + self->pv->transient->timed_idle = idle; + } +@@ -481,6 +489,11 @@ gck_object_set_property (GObject *obj, guint prop_id, const GValue *value, + g_return_if_fail (!self->pv->unique); + self->pv->unique = g_value_dup_string (value); + break; ++ case PROP_TRANSIENT: ++ g_return_if_fail (!self->pv->transient); ++ if (g_value_get_boolean (value)) ++ mark_object_transient (self); ++ break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec); + break; +@@ -510,6 +523,9 @@ gck_object_get_property (GObject *obj, guint prop_id, GValue *value, + case PROP_UNIQUE: + g_value_set_string (value, gck_object_get_unique (self)); + break; ++ case PROP_TRANSIENT: ++ g_value_set_boolean (value, gck_object_is_transient (self)); ++ break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec); + break; +@@ -556,7 +572,11 @@ gck_object_class_init (GckObjectClass *klass) + g_object_class_install_property (gobject_class, PROP_UNIQUE, + g_param_spec_string ("unique", "Unique Identifer", "Machine unique identifier", + NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); +- ++ ++ g_object_class_install_property (gobject_class, PROP_TRANSIENT, ++ g_param_spec_boolean ("transient", "Transient Object", "Transient Object", ++ FALSE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); ++ + signals[EXPOSE_OBJECT] = g_signal_new ("expose-object", GCK_TYPE_OBJECT, + G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GckObjectClass, expose_object), + NULL, NULL, g_cclosure_marshal_VOID__BOOLEAN, +diff --git a/pkcs11/secret-store/gck-secret-module.c b/pkcs11/secret-store/gck-secret-module.c +index 5b08008..c3cba91 100644 +--- a/pkcs11/secret-store/gck-secret-module.c ++++ b/pkcs11/secret-store/gck-secret-module.c +@@ -42,10 +42,7 @@ struct _GckSecretModule { + GckFileTracker *tracker; + GHashTable *collections; + gchar *directory; +- +- /* Special 'session' keyring */ + GckCredential *session_credential; +- GckSecretCollection *session_collection; + }; + + static const CK_SLOT_INFO gck_secret_module_slot_info = { +@@ -301,42 +298,52 @@ gck_secret_module_real_refresh_token (GckModule *base) + } + + static void ++gck_secret_module_real_add_object (GckModule *module, GckTransaction *transaction, ++ GckObject *object) ++{ ++ GckSecretModule *self = GCK_SECRET_MODULE (module); ++ GckSecretCollection *collection; ++ const gchar *identifier; ++ gchar *filename; ++ ++ g_return_if_fail (!gck_transaction_get_failed (transaction)); ++ ++ if (GCK_IS_SECRET_COLLECTION (object)) { ++ collection = GCK_SECRET_COLLECTION (object); ++ ++ /* Setup a filename for this collection */ ++ identifier = gck_secret_object_get_identifier (GCK_SECRET_OBJECT (collection)); ++ filename = identifier_to_new_filename (self, identifier); ++ gck_secret_collection_set_filename (collection, filename); ++ g_free (filename); ++ ++ add_collection (self, transaction, collection); ++ } ++} ++ ++static void + gck_secret_module_real_store_object (GckModule *module, GckTransaction *transaction, + GckObject *object) + { + GckSecretModule *self = GCK_SECRET_MODULE (module); + GckSecretCollection *collection = NULL; +- const gchar *identifier; +- gchar *filename; + +- /* Storing an item */ ++ /* Store the item's collection */ + if (GCK_IS_SECRET_ITEM (object)) { + collection = gck_secret_item_get_collection (GCK_SECRET_ITEM (object)); + g_return_if_fail (GCK_IS_SECRET_COLLECTION (collection)); ++ gck_module_store_token_object (GCK_MODULE (self), transaction, GCK_OBJECT (collection)); + + /* Storing a collection */ + } else if (GCK_IS_SECRET_COLLECTION (object)) { + collection = GCK_SECRET_COLLECTION (object); +- } ++ gck_secret_collection_save (collection, transaction); + + /* No other kind of token object */ +- if (collection == NULL) { ++ } else { + g_warning ("can't store object of type '%s' on secret token", G_OBJECT_TYPE_NAME (object)); + gck_transaction_fail (transaction, CKR_GENERAL_ERROR); +- return; +- } +- +- /* Setup a filename for this collection */ +- if (!gck_secret_collection_get_filename (collection)) { +- identifier = gck_secret_object_get_identifier (GCK_SECRET_OBJECT (collection)); +- filename = identifier_to_new_filename (self, identifier); +- gck_secret_collection_set_filename (collection, filename); +- g_free (filename); + } +- +- gck_secret_collection_save (collection, transaction); +- if (!gck_transaction_get_failed (transaction)) +- add_collection (self, transaction, collection); + } + + static void +@@ -351,11 +358,6 @@ gck_secret_module_real_remove_object (GckModule *module, GckTransaction *transac + GCK_OBJECT (self->session_credential) == object) + return; + +- /* Ignore the session keyring collection */ +- if (self->session_collection != NULL && +- GCK_OBJECT (self->session_collection) == object) +- return; +- + /* Removing an item */ + if (GCK_IS_SECRET_ITEM (object)) { + collection = gck_secret_item_get_collection (GCK_SECRET_ITEM (object)); +@@ -384,6 +386,7 @@ gck_secret_module_constructor (GType type, guint n_props, GObjectConstructParam + { + GckSecretModule *self = GCK_SECRET_MODULE (G_OBJECT_CLASS (gck_secret_module_parent_class)->constructor(type, n_props, props)); + GckManager *manager; ++ GckObject *collection; + CK_RV rv; + + g_return_val_if_fail (self, NULL); +@@ -401,22 +404,27 @@ gck_secret_module_constructor (GType type, guint n_props, GObjectConstructParam + + manager = gck_module_get_manager (GCK_MODULE (self)); + ++ collection = g_object_new (GCK_TYPE_SECRET_COLLECTION, ++ "module", self, ++ "identifier", "session", ++ "manager", manager, ++ "transient", TRUE, ++ NULL); ++ + /* Create the 'session' keyring, which is not stored to disk */ +- self->session_collection = g_object_new (GCK_TYPE_SECRET_COLLECTION, +- "module", self, +- "identifier", "session", +- "manager", manager, +- NULL); +- gck_object_expose (GCK_OBJECT (self->session_collection), TRUE); ++ g_return_val_if_fail (gck_object_is_transient (collection), NULL); ++ gck_module_add_token_object (GCK_MODULE (self), NULL, collection); ++ gck_object_expose (collection, TRUE); + + /* Unlock the 'session' keyring */ +- rv = gck_credential_create (GCK_MODULE (self), manager, GCK_OBJECT (self->session_collection), ++ rv = gck_credential_create (GCK_MODULE (self), manager, GCK_OBJECT (collection), + NULL, 0, &self->session_credential); + if (rv == CKR_OK) + gck_object_expose (GCK_OBJECT (self->session_credential), TRUE); + else + g_warning ("couldn't unlock the 'session' keyring"); + ++ g_object_unref (collection); + return G_OBJECT (self); + } + +@@ -438,10 +446,6 @@ gck_secret_module_dispose (GObject *obj) + g_object_unref (self->tracker); + self->tracker = NULL; + +- if (self->session_collection) +- g_object_unref (self->session_collection); +- self->session_collection = NULL; +- + if (self->session_credential) + g_object_unref (self->session_credential); + self->session_credential = NULL; +@@ -465,7 +469,6 @@ gck_secret_module_finalize (GObject *obj) + self->directory = NULL; + + g_assert (!self->session_credential); +- g_assert (!self->session_collection); + + G_OBJECT_CLASS (gck_secret_module_parent_class)->finalize (obj); + } +@@ -484,8 +487,9 @@ gck_secret_module_class_init (GckSecretModuleClass *klass) + module_class->get_token_info = gck_secret_module_real_get_token_info; + module_class->parse_argument = gck_secret_module_real_parse_argument; + module_class->refresh_token = gck_secret_module_real_refresh_token; +- module_class->remove_token_object = gck_secret_module_real_remove_object; ++ module_class->add_token_object = gck_secret_module_real_add_object; + module_class->store_token_object = gck_secret_module_real_store_object; ++ module_class->remove_token_object = gck_secret_module_real_remove_object; + } + + /* --------------------------------------------------------------------------------------- +-- +cgit v0.8.3.1 diff --git a/gnome-keyring-2.30.0-fix-storing-autounlock.patch b/gnome-keyring-2.30.0-fix-storing-autounlock.patch new file mode 100644 index 0000000..9088170 --- /dev/null +++ b/gnome-keyring-2.30.0-fix-storing-autounlock.patch @@ -0,0 +1,335 @@ +From d864698a290c55d1ccda5cc20946894ade5e827d Mon Sep 17 00:00:00 2001 +From: Stef Walter +Date: Sun, 21 Mar 2010 15:55:51 +0000 +Subject: [login] Fix various issues storing and using auto unlock passwords. + + * Unwrap secrets directly into login keyring for auto unlock. + * Fix various corner cases using auto unlock stuff in login keyring. +--- +diff --git a/daemon/dbus/gkd-secret-session.c b/daemon/dbus/gkd-secret-session.c +index 80cd054..73551df 100644 +--- a/daemon/dbus/gkd-secret-session.c ++++ b/daemon/dbus/gkd-secret-session.c +@@ -730,6 +730,8 @@ gkd_secret_session_create_credential (GkdSecretSession *self, GP11Session *sessi + } + g_clear_error (&error); + return NULL; ++ } else { ++ gp11_object_set_session (object, session); + } + + return object; +diff --git a/daemon/dbus/gkd-secret-unlock.c b/daemon/dbus/gkd-secret-unlock.c +index 8a70ddc..f5df63b 100644 +--- a/daemon/dbus/gkd-secret-unlock.c ++++ b/daemon/dbus/gkd-secret-unlock.c +@@ -247,43 +247,35 @@ check_locked_collection (GP11Object *collection, gboolean *locked) + } + + static void +-attach_credential_to_login (GP11Object *collection, GP11Object *cred) ++attach_unlock_to_login (GP11Object *collection, GkdSecretSecret *master) + { +- GError *error = NULL; ++ DBusError derr = DBUS_ERROR_INIT; + GP11Attributes *attrs; +- gpointer value; +- gsize n_value; ++ GP11Object *cred; + gchar *location; + gchar *label; + + g_assert (GP11_IS_OBJECT (collection)); +- g_assert (GP11_IS_OBJECT (cred)); + ++ /* Relevant information for the unlock item */ + attrs = attributes_for_collection (collection); + g_return_if_fail (attrs); +- + location = location_string_for_attributes (attrs); + label = label_string_for_attributes (attrs); + gp11_attributes_unref (attrs); + +- value = gp11_object_get_data_full (cred, CKA_VALUE, egg_secure_realloc, NULL, &n_value, &error); +- if (value) { +- if (g_utf8_validate (value, n_value, NULL)) +- gkd_login_attach_secret (label, value, "keyring", location, NULL); +- else +- g_warning ("couldn't save non utf-8 unlock credentials in login keyring"); +- egg_secure_clear (value, n_value); +- egg_secure_free (value); +- +- } else { +- if (!g_error_matches (error, GP11_ERROR, CKR_USER_NOT_LOGGED_IN)) +- g_warning ("couldn't read unlock credentials to save in login keyring: %s", +- egg_error_message (error)); +- g_clear_error (&error); +- } +- ++ attrs = gkd_login_attach_make_attributes (label, "keyring", location, NULL); + g_free (location); + g_free (label); ++ ++ cred = gkd_secret_session_create_credential (master->session, NULL, attrs, master, &derr); ++ gp11_attributes_unref (attrs); ++ g_object_unref (cred); ++ ++ if (!cred) { ++ g_warning ("couldn't save unlock password in login collection: %s", derr.message); ++ dbus_error_free (&derr); ++ } + } + + static void +@@ -304,6 +296,7 @@ authenticate_collection (GkdSecretUnlock *self, GP11Object *collection, gboolean + GP11Attribute *attr; + GP11Object *cred; + gboolean transient; ++ gboolean result; + + g_assert (GKD_SECRET_IS_UNLOCK (self)); + g_assert (GP11_IS_OBJECT (collection)); +@@ -336,35 +329,37 @@ authenticate_collection (GkdSecretUnlock *self, GP11Object *collection, gboolean + } + + cred = gkd_secret_session_create_credential (master->session, NULL, template, master, &derr); +- gkd_secret_secret_free (master); ++ g_object_unref (cred); + + if (cred) { + /* Save it to the login keyring */ + if (!transient) +- attach_credential_to_login (collection, cred); +- g_object_unref (cred); ++ attach_unlock_to_login (collection, master); + + /* Save away the unlock options for next time */ + gp11_object_set_template (collection, CKA_G_CREDENTIAL_TEMPLATE, template, NULL); + gp11_attributes_unref (template); + + *locked = FALSE; +- return TRUE; /* Operation succeeded, and unlocked */ ++ result = TRUE; /* Operation succeeded, and unlocked */ + + } else { + gp11_attributes_unref (template); + if (dbus_error_has_name (&derr, INTERNAL_ERROR_DENIED)) { + dbus_error_free (&derr); + *locked = TRUE; +- return TRUE; /* Operation succeded, although not unlocked*/ ++ result = TRUE; /* Operation succeded, although not unlocked*/ + + } else { + g_warning ("couldn't create credential for collection: %s", + derr.message); + dbus_error_free (&derr); +- return FALSE; /* Operation failed */ ++ result = FALSE; /* Operation failed */ + } + } ++ ++ gkd_secret_secret_free (master); ++ return result; + } + + /* ----------------------------------------------------------------------------- +diff --git a/daemon/login/gkd-login.c b/daemon/login/gkd-login.c +index bdef57d..373561c 100644 +--- a/daemon/login/gkd-login.c ++++ b/daemon/login/gkd-login.c +@@ -77,7 +77,9 @@ open_and_login_session (GP11Slot *slot, CK_USER_TYPE user_type, GError **error) + session = gp11_slot_open_session (slot, CKF_RW_SESSION, error); + if (session != NULL) { + if (!gp11_session_login (session, user_type, NULL, 0, error)) { +- if ((*error)->code != CKR_USER_ALREADY_LOGGED_IN) { ++ if (g_error_matches (*error, GP11_ERROR, CKR_USER_ALREADY_LOGGED_IN)) { ++ g_clear_error (error); ++ } else { + g_object_unref (session); + session = NULL; + } +@@ -574,20 +576,88 @@ find_login_keyring_item (GP11Session *session, GP11Attribute *fields) + return item; + } + ++static GP11Attributes* ++attach_make_attributes_va (GP11Session *session, const gchar *label, ++ const gchar *first, va_list va) ++{ ++ GP11Attributes *attrs; ++ GP11Attribute fields; ++ gchar *display_name; ++ GP11Object* item; ++ GError *error = NULL; ++ gpointer value; ++ gsize n_value; ++ ++ attrs = gp11_attributes_new (); ++ ++ gp11_attribute_init_empty (&fields, CKA_G_FIELDS); ++ string_attribute_list_va (va, first, &fields); ++ ++ /* ++ * If there already is such an item, then include its identifier. ++ * What this does is overwrite that item, rather than creating new. ++ */ ++ item = find_login_keyring_item (session, &fields); ++ if (item) { ++ value = gp11_object_get_data (item, CKA_ID, &n_value, &error); ++ if (value != NULL) { ++ gp11_attributes_add_data (attrs, CKA_ID, value, n_value); ++ g_free (value); ++ } else { ++ g_warning ("couldn't retrieve id for previous login item: %s", ++ egg_error_message (error)); ++ g_clear_error (&error); ++ } ++ g_object_unref (item); ++ } ++ ++ if (label == NULL) ++ label = _("Unnamed"); ++ ++ display_name = g_strdup_printf (_("Unlock password for: %s"), label); ++ gp11_attributes_add_string (attrs, CKA_LABEL, display_name); ++ ++ gp11_attributes_add_boolean (attrs, CKA_TOKEN, TRUE); ++ gp11_attributes_add_ulong (attrs, CKA_CLASS, CKO_SECRET_KEY); ++ gp11_attributes_add_data (attrs, CKA_G_COLLECTION, "login", (gsize)5); ++ gp11_attributes_add (attrs, &fields); ++ ++ gp11_attribute_clear (&fields); ++ return attrs; ++} ++ ++GP11Attributes* ++gkd_login_attach_make_attributes (const gchar *label, const gchar *first, ...) ++{ ++ GP11Attributes *attrs; ++ GP11Session *session; ++ GP11Module *module; ++ va_list va; ++ ++ module = module_instance (); ++ session = lookup_login_session (module); ++ ++ va_start (va, first); ++ attrs = attach_make_attributes_va (session, label, first, va); ++ va_end (va); ++ ++ g_object_unref (session); ++ g_object_unref (module); ++ ++ return attrs; ++} ++ + void + gkd_login_attach_secret (const gchar *label, const gchar *secret, + const gchar *first, ...) + { + GError *error = NULL; +- GP11Attribute fields; + GP11Session *session; + GP11Module *module; +- gchar *display_name; +- GP11Object* item; ++ GP11Attributes *attrs; ++ GP11Object *item; + va_list va; + +- if (label == NULL) +- label = _("Unnamed"); + if (secret == NULL) + secret = ""; + +@@ -595,29 +665,11 @@ gkd_login_attach_secret (const gchar *label, const gchar *secret, + session = lookup_login_session (module); + + va_start(va, first); +- gp11_attribute_init_empty (&fields, CKA_G_FIELDS); +- string_attribute_list_va (va, first, &fields); ++ attrs = attach_make_attributes_va (session, label, first, va); + va_end(va); + +- display_name = g_strdup_printf (_("Unlock password for: %s"), label); +- +- item = find_login_keyring_item (session, &fields); +- if (item) { +- gp11_object_set (item, &error, +- CKA_LABEL, strlen (display_name), display_name, +- CKA_VALUE, strlen (secret), secret, +- GP11_INVALID); +- } else { +- item = gp11_session_create_object (session, &error, +- CKA_TOKEN, GP11_BOOLEAN, TRUE, +- CKA_CLASS, GP11_ULONG, CKO_SECRET_KEY, +- CKA_LABEL, strlen (display_name), display_name, +- CKA_VALUE, strlen (secret), secret, +- CKA_G_COLLECTION, (gsize)5, "login", +- CKA_G_FIELDS, fields.length, fields.value, +- GP11_INVALID); +- } +- ++ gp11_attributes_add_string (attrs, CKA_VALUE, secret); ++ item = gp11_session_create_object_full (session, attrs, NULL, &error); + if (error != NULL) { + g_warning ("couldn't store secret in login keyring: %s", egg_error_message (error)); + g_clear_error (&error); +@@ -625,8 +677,8 @@ gkd_login_attach_secret (const gchar *label, const gchar *secret, + + if (item) + g_object_unref (item); +- g_free (display_name); +- gp11_attribute_clear (&fields); ++ ++ gp11_attributes_unref (attrs); + g_object_unref (session); + g_object_unref (module); + } +@@ -701,22 +753,3 @@ gkd_login_remove_secret (const gchar *first, ...) + g_object_unref (session); + g_object_unref (module); + } +- +-GP11Attributes* +-gkd_login_attributes_for_secret (const gchar *first, ...) +-{ +- GP11Attributes *attrs; +- GP11Attribute *fields; +- va_list va; +- +- attrs = gp11_attributes_newv (CKA_CLASS, GP11_ULONG, CKO_SECRET_KEY, +- CKA_G_COLLECTION, (gsize)5, "login", +- GP11_INVALID); +- +- va_start(va, first); +- fields = gp11_attributes_add_empty (attrs, CKA_G_FIELDS); +- string_attribute_list_va (va, first, fields); +- va_end(va); +- +- return attrs; +-} +diff --git a/daemon/login/gkd-login.h b/daemon/login/gkd-login.h +index 89157b1..849b9f4 100644 +--- a/daemon/login/gkd-login.h ++++ b/daemon/login/gkd-login.h +@@ -40,13 +40,14 @@ void gkd_login_attach_secret (const gchar *label, + const gchar *first, + ...); + +-gchar* gkd_login_lookup_secret (const gchar *first, ++GP11Attributes* gkd_login_attach_make_attributes (const gchar *label, ++ const gchar *first, + ...); + +-void gkd_login_remove_secret (const gchar *first, ++gchar* gkd_login_lookup_secret (const gchar *first, + ...); + +-GP11Attributes* gkd_login_attributes_for_secret (const gchar *first, ++void gkd_login_remove_secret (const gchar *first, + ...); + + #endif /* __GKD_LOGIN_H__ */ +-- +cgit v0.8.3.1 diff --git a/gnome-keyring-2.30.0-hide-automaticall-unlock.patch b/gnome-keyring-2.30.0-hide-automaticall-unlock.patch new file mode 100644 index 0000000..4178ca9 --- /dev/null +++ b/gnome-keyring-2.30.0-hide-automaticall-unlock.patch @@ -0,0 +1,26 @@ +From 0512a0b5a30b432f53ee8c48d75acd582c5c9c9d Mon Sep 17 00:00:00 2001 +From: Stef Walter +Date: Sun, 21 Mar 2010 14:24:33 +0000 +Subject: [dbus] Hide the automatically unlock check when login not usable. + +If the login keyring is locked or not present, hide the auto +unlock check box since that option isn't usable. +--- +diff --git a/daemon/dbus/gkd-secret-unlock.c b/daemon/dbus/gkd-secret-unlock.c +index 52e4978..8a70ddc 100644 +--- a/daemon/dbus/gkd-secret-unlock.c ++++ b/daemon/dbus/gkd-secret-unlock.c +@@ -200,6 +200,11 @@ prepare_unlock_prompt (GkdSecretUnlock *self, GP11Object *coll, gboolean first) + + g_free (label); + ++ if (gkd_login_is_usable ()) ++ gkd_prompt_show_widget (prompt, "auto_unlock_check"); ++ else ++ gkd_prompt_hide_widget (prompt, "auto_unlock_check"); ++ + /* Setup the unlock options */ + if (first) { + template = gp11_object_get_template (coll, CKA_G_CREDENTIAL_TEMPLATE, &error); +-- +cgit v0.8.3.1 diff --git a/gnome-keyring-2.30.0-unlocking-when-unavailable.patch b/gnome-keyring-2.30.0-unlocking-when-unavailable.patch new file mode 100644 index 0000000..2833140 --- /dev/null +++ b/gnome-keyring-2.30.0-unlocking-when-unavailable.patch @@ -0,0 +1,52 @@ +From e43a24701767d1a8fd72f2f3ed01fe0937364b6d Mon Sep 17 00:00:00 2001 +From: Stef Walter +Date: Sun, 21 Mar 2010 14:06:43 +0000 +Subject: [dbus] Allow unlocking even when always unlock is not available. + +When the Always Unlock option could not work (due to a missing or +locked login keyring) unlocking a keyring fail when that option +was selected. + +Fixes bug #610998 +--- +diff --git a/daemon/dbus/gkd-secret-unlock.c b/daemon/dbus/gkd-secret-unlock.c +index ee17fd1..52e4978 100644 +--- a/daemon/dbus/gkd-secret-unlock.c ++++ b/daemon/dbus/gkd-secret-unlock.c +@@ -271,8 +271,9 @@ attach_credential_to_login (GP11Object *collection, GP11Object *cred) + egg_secure_free (value); + + } else { +- g_warning ("couldn't read unlock credentials to save in login keyring: %s", +- egg_error_message (error)); ++ if (!g_error_matches (error, GP11_ERROR, CKR_USER_NOT_LOGGED_IN)) ++ g_warning ("couldn't read unlock credentials to save in login keyring: %s", ++ egg_error_message (error)); + g_clear_error (&error); + } + +@@ -295,6 +296,7 @@ authenticate_collection (GkdSecretUnlock *self, GP11Object *collection, gboolean + DBusError derr = DBUS_ERROR_INIT; + GkdSecretSecret *master; + GP11Attributes *template; ++ GP11Attribute *attr; + GP11Object *cred; + gboolean transient; + +@@ -321,8 +323,12 @@ authenticate_collection (GkdSecretUnlock *self, GP11Object *collection, gboolean + gkd_prompt_get_unlock_options (GKD_PROMPT (self), template); + + /* If it's supposed to save non-transient, then we override that */ +- if (!gp11_attributes_find_boolean (template, CKA_GNOME_TRANSIENT, &transient)) +- transient = TRUE; ++ attr = gp11_attributes_find (template, CKA_GNOME_TRANSIENT); ++ if (attr != NULL) { ++ transient = gp11_attribute_get_boolean (attr); ++ gp11_attribute_clear (attr); ++ gp11_attribute_init_boolean (attr, CKA_GNOME_TRANSIENT, TRUE); ++ } + + cred = gkd_secret_session_create_credential (master->session, NULL, template, master, &derr); + gkd_secret_secret_free (master); +-- +cgit v0.8.3.1 diff --git a/gnome-keyring.spec b/gnome-keyring.spec index 022fcd0..16bc7e5 100644 --- a/gnome-keyring.spec +++ b/gnome-keyring.spec @@ -8,7 +8,7 @@ Summary: Framework for managing passwords and other secrets Name: gnome-keyring Version: 2.29.92 -Release: 1%{?dist} +Release: 2%{?dist} License: GPLv2+ and LGPLv2+ Group: System Environment/Libraries Source: http://download.gnome.org/sources/gnome-keyring/2.29/gnome-keyring-%{version}.tar.bz2 @@ -17,6 +17,13 @@ Source: http://download.gnome.org/sources/gnome-keyring/2.29/gnome-keyring-%{ver # http://bugs.gnome.org/598494 Patch3: gnome-keyring-2.28.1-nopass.patch +# from master +Patch4: gnome-keyring-2.30.0-better-error-handling.patch +Patch5: gnome-keyring-2.30.0-dont-save-session-keyring-to-disk.patch +Patch6: gnome-keyring-2.30.0-unlocking-when-unavailable.patch +Patch7: gnome-keyring-2.30.0-hide-automaticall-unlock.patch +Patch8: gnome-keyring-2.30.0-fix-storing-autounlock.patch + URL: http://www.gnome.org BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) @@ -76,6 +83,11 @@ automatically unlock the "login" keyring when the user logs in. %prep %setup -q -n gnome-keyring-%{version} %patch3 -p1 -b .no-pass +%patch4 -p1 -b .better-error-handling +%patch5 -p1 -b .dont-save-session-keyring-to-disk +%patch6 -p1 -b .unlocking-when-unavailable +%patch7 -p1 -b .hide-automaticall-unlock +%patch8 -p1 -b .fix-storing-autounlock %build @@ -154,6 +166,13 @@ fi %changelog +* Mon Mar 22 2010 Tomas Bzatek - 2.29.92-2 +- More robust error display and handling +- [secret-store] Don't save session keyring to disk +- [dbus] Allow unlocking even when always unlock is not available +- [dbus] Hide the automatically unlock check when login not usable +- [login] Fix various issues storing and using auto unlock passwords + * Wed Mar 10 2010 Tomas Bzatek - 2.29.92-1 - Update to 2.29.92