summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Barnes <mbarnes@redhat.com>2008-05-19 14:14:43 +0000
committerMatthew Barnes <mbarnes@src.gnome.org>2008-05-19 14:14:43 +0000
commit9e3b99a38dbb39d81b18cf6c0dc20a9dc154be45 (patch)
treea32348058ca926de457c1f83e7ee53d5bf5d7e51
parent33e6dbe5483de8165a8d697c946278e14dbb8c99 (diff)
downloadevolution-data-server-9e3b99a38dbb39d81b18cf6c0dc20a9dc154be45.tar.gz
** Fixes bug #354923
2008-05-19 Matthew Barnes <mbarnes@redhat.com> ** Fixes bug #354923 * libedataserverui/e-passwords.c: Store passwords in the keyring by server, username and protocol. Storing the protocol allows us to handle situations where, for example, you use the same server and username for IMAP and authenticated SMTP but the passwords are different. Also add sufficient backward-compatibility cruft that we can still find existing passwords that are stored in the keyring by server and username only. svn path=/trunk/; revision=8812
-rw-r--r--libedataserverui/ChangeLog14
-rw-r--r--libedataserverui/e-passwords.c121
2 files changed, 106 insertions, 29 deletions
diff --git a/libedataserverui/ChangeLog b/libedataserverui/ChangeLog
index fd5fd442e..df3d8fe31 100644
--- a/libedataserverui/ChangeLog
+++ b/libedataserverui/ChangeLog
@@ -1,3 +1,17 @@
+2008-05-19 Matthew Barnes <mbarnes@redhat.com>
+
+ ** Fixes bug #354923
+
+ * e-passwords.c:
+ Store passwords in the keyring by server, username and protocol.
+ Storing the protocol allows us to handle situations where, for
+ example, you use the same server and username for IMAP and
+ authenticated SMTP but the passwords are different.
+
+ Also add sufficient backward-compatibility cruft that we can still
+ find existing passwords that are stored in the keyring by server
+ and username only.
+
2008-05-16 Matthew Barnes <mbarnes@redhat.com>
** Fixes bug #532286
diff --git a/libedataserverui/e-passwords.c b/libedataserverui/e-passwords.c
index a9242e2d4..3d37fefa3 100644
--- a/libedataserverui/e-passwords.c
+++ b/libedataserverui/e-passwords.c
@@ -212,19 +212,21 @@ ep_keyring_uri_new (const gchar *string)
static gboolean
ep_keyring_validate (const gchar *user,
const gchar *server,
+ const gchar *protocol,
GnomeKeyringAttributeList *attributes)
{
const gchar *user_value = NULL;
const gchar *server_value = NULL;
+ const gchar *protocol_value = NULL;
gint ii;
g_return_val_if_fail (attributes != NULL, FALSE);
/* Is there anything to validate? */
- if (user == NULL && server == NULL)
+ if (user == NULL && server == NULL && protocol == NULL)
return TRUE;
- /* Look for "user" and "server" attributes. */
+ /* Look for "user", "server", and "protocol" attributes. */
for (ii = 0; ii < attributes->len; ii++) {
GnomeKeyringAttribute *attr;
@@ -235,6 +237,8 @@ ep_keyring_validate (const gchar *user,
user_value = attr->value.string;
else if (strcmp (attr->name, "server") == 0)
server_value = attr->value.string;
+ else if (strcmp (attr->name, "protocol") == 0)
+ protocol_value = attr->value.string;
}
/* Is there a "user" attribute? */
@@ -253,12 +257,21 @@ ep_keyring_validate (const gchar *user,
if (server != NULL && strcmp (server, server_value) != 0)
return FALSE;
+ /* Is there a "protocol" attribute? */
+ if (protocol != NULL && protocol_value == NULL)
+ return FALSE;
+
+ /* Does it match what we're looking for? */
+ if (protocol != NULL && strcmp (protocol, protocol_value) != 0)
+ return FALSE;
+
return TRUE;
}
static gboolean
ep_keyring_delete_passwords (const gchar *user,
const gchar *server,
+ const gchar *protocol,
GList *passwords,
GError **error)
{
@@ -267,9 +280,14 @@ ep_keyring_delete_passwords (const gchar *user,
GnomeKeyringResult result;
/* Validate the item before deleting it. */
- if (!ep_keyring_validate (user, server, found->attributes)) {
- passwords = g_list_next (passwords);
- continue;
+ if (!ep_keyring_validate (user, server, protocol, found->attributes)) {
+ /* XXX We didn't always store protocols in the
+ * keyring, so for backward-compatibility
+ * try validating by user and server only. */
+ if (!ep_keyring_validate (user, server, NULL, found->attributes)) {
+ passwords = g_list_next (passwords);
+ continue;
+ }
}
result = gnome_keyring_item_delete_sync (NULL, found->item_id);
@@ -291,6 +309,7 @@ ep_keyring_delete_passwords (const gchar *user,
static gboolean
ep_keyring_insert_password (const gchar *user,
const gchar *server,
+ const gchar *protocol,
const gchar *display_name,
const gchar *password,
GError **error)
@@ -301,6 +320,7 @@ ep_keyring_insert_password (const gchar *user,
g_return_val_if_fail (user != NULL, FALSE);
g_return_val_if_fail (server != NULL, FALSE);
+ g_return_val_if_fail (protocol != NULL, FALSE);
g_return_val_if_fail (display_name != NULL, FALSE);
g_return_val_if_fail (password != NULL, FALSE);
@@ -311,6 +331,8 @@ ep_keyring_insert_password (const gchar *user,
attributes, "user", user);
gnome_keyring_attribute_list_append_string (
attributes, "server", server);
+ gnome_keyring_attribute_list_append_string (
+ attributes, "protocol", protocol);
/* XXX We don't use item_id but gnome-keyring doesn't allow
* for a NULL pointer. In fact it doesn't even check! */
@@ -333,6 +355,7 @@ ep_keyring_insert_password (const gchar *user,
static GList *
ep_keyring_lookup_passwords (const gchar *user,
const gchar *server,
+ const gchar *protocol,
GError **error)
{
GnomeKeyringAttributeList *attributes;
@@ -348,6 +371,9 @@ ep_keyring_lookup_passwords (const gchar *user,
if (server != NULL)
gnome_keyring_attribute_list_append_string (
attributes, "server", server);
+ if (protocol != NULL)
+ gnome_keyring_attribute_list_append_string (
+ attributes, "protocol", protocol);
result = gnome_keyring_find_items_sync (
GNOME_KEYRING_ITEM_NETWORK_PASSWORD, attributes, &passwords);
@@ -479,9 +505,9 @@ ep_clear_passwords_keyring (EPassMsg *msg)
GError *error = NULL;
/* Find all Evolution passwords and delete them. */
- passwords = ep_keyring_lookup_passwords (NULL, NULL, &error);
+ passwords = ep_keyring_lookup_passwords (NULL, NULL, NULL, &error);
if (passwords != NULL) {
- ep_keyring_delete_passwords (NULL, NULL, passwords, &error);
+ ep_keyring_delete_passwords (NULL, NULL, NULL, passwords, &error);
gnome_keyring_found_list_free (passwords);
}
@@ -509,9 +535,9 @@ ep_clear_passwords_keyfile (EPassMsg *msg)
/* Not finding the requested group is acceptable, but we still
* want to leave an informational message on the terminal. */
- else if (g_error_matches (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_GROUP_NOT_FOUND)) {
- g_message ("%s", error->message);
- g_error_free (error);
+ else if (g_error_matches (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_GROUP_NOT_FOUND)) {
+ g_message ("%s", error->message);
+ g_error_free (error);
} else if (error != NULL)
g_propagate_error (&msg->error, error);
@@ -543,9 +569,9 @@ ep_forget_passwords_keyring (EPassMsg *msg)
GError *error = NULL;
/* Find all Evolution passwords and delete them. */
- passwords = ep_keyring_lookup_passwords (NULL, NULL, &error);
+ passwords = ep_keyring_lookup_passwords (NULL, NULL, NULL, &error);
if (passwords != NULL) {
- ep_keyring_delete_passwords (NULL, NULL, passwords, &error);
+ ep_keyring_delete_passwords (NULL, NULL, NULL, passwords, &error);
gnome_keyring_found_list_free (passwords);
}
@@ -623,7 +649,7 @@ ep_remember_password_keyring (EPassMsg *msg)
/* Only remove the password from the session hash
* if the keyring insertion was successful. */
- if (ep_keyring_insert_password (uri->user, uri->host, msg->key, password, &error))
+ if (ep_keyring_insert_password (uri->user, uri->host, uri->protocol, msg->key, password, &error))
g_hash_table_remove (password_cache, msg->key);
if (error != NULL)
@@ -684,10 +710,17 @@ ep_forget_password_keyring (EPassMsg *msg)
uri = ep_keyring_uri_new (msg->key);
g_return_if_fail (uri != NULL);
- /* Find all Evolution passwords matching the URI and delete them. */
- passwords = ep_keyring_lookup_passwords (uri->user, uri->host, &error);
+ /* Find all Evolution passwords matching the URI and delete them.
+ *
+ * XXX We didn't always store protocols in the keyring, so for
+ * backward-compatibility we need to lookup passwords by user
+ * and host only (no protocol). But we do send the protocol
+ * to ep_keyring_delete_passwords(), which also knows about
+ * the backward-compatibility issue and will filter the list
+ * appropriately. */
+ passwords = ep_keyring_lookup_passwords (uri->user, uri->host, NULL, &error);
if (passwords != NULL) {
- ep_keyring_delete_passwords (uri->user, uri->host, passwords, &error);
+ ep_keyring_delete_passwords (uri->user, uri->host, uri->protocol, passwords, &error);
gnome_keyring_found_list_free (passwords);
}
@@ -716,10 +749,10 @@ ep_forget_password_keyfile (EPassMsg *msg)
g_message ("%s", error->message);
g_error_free (error);
- /* Not finding the requested group is also acceptable. */
- } else if (g_error_matches (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_GROUP_NOT_FOUND)) {
- g_message ("%s", error->message);
- g_error_free (error);
+ /* Not finding the requested group is also acceptable. */
+ } else if (g_error_matches (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_GROUP_NOT_FOUND)) {
+ g_message ("%s", error->message);
+ g_error_free (error);
} else if (error != NULL)
g_propagate_error (&msg->error, error);
@@ -758,14 +791,43 @@ ep_get_password_keyring (EPassMsg *msg)
g_return_if_fail (uri != NULL);
/* Find the first Evolution password that matches the URI. */
- passwords = ep_keyring_lookup_passwords (uri->user, uri->host, &error);
+ passwords = ep_keyring_lookup_passwords (uri->user, uri->host, uri->protocol, &error);
+ if (passwords != NULL) {
+ GList *iter = passwords;
+
+ while (iter != NULL) {
+ GnomeKeyringFound *found = iter->data;
+
+ if (ep_keyring_validate (uri->user, uri->host, uri->protocol, found->attributes)) {
+ msg->password = g_strdup (found->secret);
+ break;
+ }
+
+ iter = g_list_next (iter);
+ }
+
+ gnome_keyring_found_list_free (passwords);
+ }
+
+ if (msg->password != NULL)
+ goto done;
+
+ /* Clear the previous error, if there was one. If the error was
+ * something other than NO_MATCH then it's likely to occur again. */
+ if (error != NULL)
+ g_clear_error (&error);
+
+ /* XXX We didn't always store protocols in the keyring, so for
+ * backward-compatibility we also need to lookup passwords
+ * by user and host only (no protocol). */
+ passwords = ep_keyring_lookup_passwords (uri->user, uri->host, NULL, &error);
if (passwords != NULL) {
GList *iter = passwords;
while (iter != NULL) {
GnomeKeyringFound *found = iter->data;
- if (ep_keyring_validate (uri->user, uri->host, found->attributes)) {
+ if (ep_keyring_validate (uri->user, uri->host, NULL, found->attributes)) {
msg->password = g_strdup (found->secret);
break;
}
@@ -776,6 +838,7 @@ ep_get_password_keyring (EPassMsg *msg)
gnome_keyring_found_list_free (passwords);
}
+done:
/* Not finding the requested key is acceptable, but we still
* want to leave an informational message on the terminal. */
if (g_error_matches (error, EP_KEYRING_ERROR, GNOME_KEYRING_RESULT_NO_MATCH)) {
@@ -809,10 +872,10 @@ ep_get_password_keyfile (EPassMsg *msg)
g_message ("%s", error->message);
g_error_free (error);
- /* Not finding the requested group is also acceptable. */
- } else if (g_error_matches (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_GROUP_NOT_FOUND)) {
- g_message ("%s", error->message);
- g_error_free (error);
+ /* Not finding the requested group is also acceptable. */
+ } else if (g_error_matches (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_GROUP_NOT_FOUND)) {
+ g_message ("%s", error->message);
+ g_error_free (error);
} else if (error != NULL)
g_propagate_error (&msg->error, error);
@@ -992,13 +1055,13 @@ ep_ask_password (EPassMsg *msg)
gtk_dialog_set_has_separator (GTK_DIALOG (widget), FALSE);
gtk_dialog_set_default_response (
GTK_DIALOG (widget), GTK_RESPONSE_OK);
- gtk_window_set_resizable (GTK_WINDOW (widget), FALSE);
+ gtk_window_set_resizable (GTK_WINDOW (widget), FALSE);
gtk_window_set_transient_for (GTK_WINDOW (widget), msg->parent);
gtk_window_set_position (GTK_WINDOW (widget), GTK_WIN_POS_CENTER_ON_PARENT);
gtk_container_set_border_width (GTK_CONTAINER (widget), 12);
password_dialog = GTK_DIALOG (widget);
- /* Override GtkDialog defaults */
+ /* Override GtkDialog defaults */
widget = password_dialog->vbox;
gtk_box_set_spacing (GTK_BOX (widget), 12);
gtk_container_set_border_width (GTK_CONTAINER (widget), 0);
@@ -1031,7 +1094,7 @@ ep_ask_password (EPassMsg *msg)
/* Password Label */
widget = gtk_label_new (NULL);
gtk_label_set_line_wrap (GTK_LABEL (widget), TRUE);
- gtk_label_set_markup (GTK_LABEL (widget), msg->prompt);
+ gtk_label_set_markup (GTK_LABEL (widget), msg->prompt);
gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
gtk_widget_show (widget);