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