[PATCH] shell, libview: new feature for password lookup



This patch introduces a new function to find a matching password to a
document by iteration through all existing passwords (for document files)
in the keyring.
Assume there are two ore more files encrypted with the same
password, we don't want to enter the password for every file we open.
First the old, direct password lookup using the file's uri is used. If this
wasn't successful, the new brute force function get called.
If a matching password was found (in the default keyring), the uri and
password of the file are being saved to speedup future lookups.
---
 libview/ev-jobs.c  |    5 +++
 libview/ev-jobs.h  |   15 ++++++++++
 shell/ev-keyring.c |   75 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 shell/ev-keyring.h |    2 +
 shell/ev-window.c  |   48 +++++++++++++++++++++++++--------
 5 files changed, 133 insertions(+), 12 deletions(-)

diff --git a/libview/ev-jobs.c b/libview/ev-jobs.c
index a0866d5..900c2d3 100644
--- a/libview/ev-jobs.c
+++ b/libview/ev-jobs.c
@@ -880,6 +880,11 @@ ev_job_load_new (const gchar *uri)
 	
 	job = g_object_new (EV_TYPE_JOB_LOAD, NULL);
 	job->uri = g_strdup (uri);
+	job->other_password_count = 0;
+	job->num_key_ids = 0;
+	job->list_of_all_key_ids = NULL;
+	job->direct_lookup_tried = FALSE;
+	job->doing_bruteforce = FALSE;
 
 	return EV_JOB (job);
 }
diff --git a/libview/ev-jobs.h b/libview/ev-jobs.h
index 144ec06..61cfb66 100644
--- a/libview/ev-jobs.h
+++ b/libview/ev-jobs.h
@@ -274,6 +274,21 @@ struct _EvJobLoad
 
 	gchar *uri;
 	gchar *password;
+
+	/* first method (old): lookup by uri */
+	gboolean direct_lookup_tried;
+
+	/* second method (new): lookup by brute force */
+	gboolean doing_bruteforce;
+
+	/* position in id list */
+	gint other_password_count;
+
+	/* number of array elements */
+	gint num_key_ids;
+
+	/* list of all ids found in the keyring */
+	GList *list_of_all_key_ids;
 };
 
 struct _EvJobLoadClass
diff --git a/shell/ev-keyring.c b/shell/ev-keyring.c
index 0199863..5f0c6e7 100644
--- a/shell/ev-keyring.c
+++ b/shell/ev-keyring.c
@@ -78,6 +78,81 @@ ev_keyring_lookup_password (const gchar *uri)
 	return retval;
 }
 
+gchar *ev_keyring_lookup_other_password (EvJobLoad *job_load)
+{
+	int att_iterator;
+	guint id;
+	gchar *retval = NULL;
+	gchar *password;
+
+#ifdef WITH_KEYRING
+	GnomeKeyringAttributeList *attributes= NULL;
+	GnomeKeyringItemInfo *item_info = NULL;
+	GnomeKeyringResult result;
+	
+	/* first run */
+	if(!job_load->other_password_count) {
+		/* get all available key ids from default keyring */
+		result = gnome_keyring_list_item_ids_sync(NULL,
+							&job_load->list_of_all_key_ids);
+
+		if (result != GNOME_KEYRING_RESULT_OK) {
+			job_load->other_password_count = 0;
+			g_list_free(job_load->list_of_all_key_ids);
+			return NULL;
+		}
+		job_load->num_key_ids = g_list_length(job_load->list_of_all_key_ids);
+	}
+
+	/* get the next id from the array */
+	id = GPOINTER_TO_UINT (g_list_nth_data(job_load->list_of_all_key_ids,
+						job_load->other_password_count));
+	result = gnome_keyring_item_get_attributes_sync (NULL, id, &attributes);
+
+	if (result != GNOME_KEYRING_RESULT_OK) {
+		gnome_keyring_attribute_list_free(attributes);
+		g_list_free(job_load->list_of_all_key_ids);
+		job_load->other_password_count = 0;
+		job_load->num_key_ids = 0;
+		return NULL;
+	}
+
+	for (att_iterator = 0; att_iterator < attributes->len; att_iterator++) {
+		if (!strcmp (gnome_keyring_attribute_list_index(attributes,
+					att_iterator).name, "type")) {
+
+			/* We only want to get elements that were created by evince */
+			if (!strcmp (gnome_keyring_attribute_list_index(attributes,
+					att_iterator).value.string, "document_password")) {
+
+				/* beware! don't use the session specific gnome keyring here, as the
+				 * password might be saved into the permanent one later on */
+				result = gnome_keyring_item_get_info_sync (NULL,
+							id,&item_info);
+
+				if (result != GNOME_KEYRING_RESULT_OK) {
+					gnome_keyring_item_info_free(item_info);
+					gnome_keyring_attribute_list_free(attributes);
+					g_list_free(job_load->list_of_all_key_ids);
+					job_load->other_password_count = 0;
+					job_load->num_key_ids = 0;
+					return NULL;
+				}
+				password = gnome_keyring_item_info_get_secret(item_info);
+				if (password) {
+					retval = g_strdup (password);
+					g_free (password);
+				}
+				gnome_keyring_item_info_free(item_info);
+			}
+		}
+	}
+	gnome_keyring_attribute_list_free(attributes);
+	job_load->other_password_count++;
+#endif /* WITH_KEYRING */
+	return retval;
+}
+
 gboolean
 ev_keyring_save_password (const gchar  *uri,
 			  const gchar  *password,
diff --git a/shell/ev-keyring.h b/shell/ev-keyring.h
index f51410e..3057411 100644
--- a/shell/ev-keyring.h
+++ b/shell/ev-keyring.h
@@ -23,6 +23,7 @@
 
 #include <glib.h>
 #include <gio/gio.h>
+#include "ev-jobs.h"
 
 G_BEGIN_DECLS
 
@@ -31,6 +32,7 @@ gchar   *ev_keyring_lookup_password (const gchar  *uri);
 gboolean ev_keyring_save_password   (const gchar  *uri,
 				     const gchar  *password,
 				     GPasswordSave flags);
+gchar *ev_keyring_lookup_other_password (EvJobLoad *job_load);
 
 G_END_DECLS
 
diff --git a/shell/ev-window.c b/shell/ev-window.c
index fcd59de..844a81e 100644
--- a/shell/ev-window.c
+++ b/shell/ev-window.c
@@ -1378,9 +1378,17 @@ ev_window_load_job_cb (EvJob *job,
 					  EV_WINDOW_TITLE_DOCUMENT);
 		if (job_load->password) {
 			GPasswordSave flags;
-
-			flags = ev_password_view_get_password_save_flags (
-				EV_PASSWORD_VIEW (ev_window->priv->password_view));
+			
+			if (job_load->num_key_ids) {
+			/* brute force method was used
+			 * store the password using the uri sheme to speedup the next lookup
+			 * G_PASSWORD_SAVE_PERMANENTLY is save, as we _only_ use the default keyring,
+			 * not the session specific to obtain passwords */
+				flags = G_PASSWORD_SAVE_PERMANENTLY;
+			} else {
+				flags = ev_password_view_get_password_save_flags (
+					EV_PASSWORD_VIEW (ev_window->priv->password_view));
+			}
 			ev_keyring_save_password (ev_window->priv->uri,
 						  job_load->password,
 						  flags);
@@ -1428,22 +1436,38 @@ ev_window_load_job_cb (EvJob *job,
 		
 		setup_view_from_metadata (ev_window);
 		
-		/* First look whether password is in keyring */
-		password = ev_keyring_lookup_password (ev_window->priv->uri);
-		if (password) {
-			if (job_load->password && strcmp (password, job_load->password) == 0) {
-				/* Password in kering is wrong */
-				ev_job_load_set_password (job_load, NULL);
-				/* FIXME: delete password from keyring? */
-			} else {
+		/* First look whether password is in keyring using a direct lookup by uri*/
+		if (!job_load->direct_lookup_tried) { 
+			password = ev_keyring_lookup_password (ev_window->priv->uri);
+			job_load->direct_lookup_tried = TRUE;
+			if (password) {
 				ev_job_load_set_password (job_load, password);
 				ev_job_scheduler_push_job (job, EV_JOB_PRIORITY_NONE);
 				g_free (password);
 				return;
 			}
-
 			g_free (password);
 		}
+		
+		/* Now try to lookup the password of other docs */
+		if(job_load->num_key_ids <= job_load->other_password_count
+					&& job_load->doing_bruteforce) { // reached end of list
+				g_list_free(job_load->list_of_all_key_ids);
+				job_load->other_password_count = 0;
+				job_load->num_key_ids = 0;
+				job_load->list_of_all_key_ids = NULL;
+				job_load->direct_lookup_tried = FALSE;
+				job_load->doing_bruteforce = FALSE;
+				ev_job_load_set_password (job_load, NULL);
+		} else {
+			password = ev_keyring_lookup_other_password (job_load);
+			job_load->doing_bruteforce = TRUE;
+			ev_job_load_set_password (job_load, password);
+			ev_job_scheduler_push_job (job, EV_JOB_PRIORITY_NONE);
+			g_free (password);
+			return;
+		}
+		g_free (password);
 
 		/* We need to ask the user for a password */
 		ev_window_title_set_uri (ev_window->priv->title,
-- 
1.6.3.3

------=_20091203083543_96211--




[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]