[PINENTRY PATCH 7/8] gnome3: Convert password/confirmation to asynchronous model.

Daniel Kahn Gillmor dkg at fifthhorseman.net
Fri Nov 4 23:57:51 CET 2016


* gnome3/pinentry-gnome3.c (gnome3_cmd_handler): Convert main part of
password or confirmation fetching into asynchronous code by moving
completion into...
(_gcr_prompt_password_done): ... here and...
(_gcr_prompt_confirm_done): ... here.

--

The async programming interface to gcr is necessary if we want to be
able to enforce a timeout, which will happen in the next patch in this
series.

Signed-off-by: Daniel Kahn Gillmor <dkg at fifthhorseman.net>
---
 gnome3/pinentry-gnome3.c | 98 ++++++++++++++++++++++++++++++++++++------------
 1 file changed, 73 insertions(+), 25 deletions(-)

diff --git a/gnome3/pinentry-gnome3.c b/gnome3/pinentry-gnome3.c
index 40be2a4..06c2076 100644
--- a/gnome3/pinentry-gnome3.c
+++ b/gnome3/pinentry-gnome3.c
@@ -69,6 +69,19 @@ pinentry_utf8_validate (gchar *text)
   return result;
 }
 
+struct _gnome3_run {
+  pinentry_t pinentry;
+  GcrPrompt *prompt;
+  GMainLoop *main_loop;
+  int ret;
+};
+
+static void
+_gcr_prompt_password_done (GObject *source_object, GAsyncResult *res, gpointer user_data);
+
+static void
+_gcr_prompt_confirm_done (GObject *source_object, GAsyncResult *res, gpointer user_data);
+
 static void
 _propagate_g_error_to_pinentry (pinentry_t pe, GError *error, gpg_err_code_t code, const char *loc)
 {
@@ -181,26 +194,55 @@ create_prompt (pinentry_t pe, int confirm)
 static int
 gnome3_cmd_handler (pinentry_t pe)
 {
-  GcrPrompt *prompt = NULL;
-  GError *error = NULL;
-  int ret = -1;
+  struct _gnome3_run state;
 
-  if (pe->pin)
-    /* Passphrase mode.  */
+  state.main_loop = g_main_loop_new (NULL, FALSE);
+  if (!state.main_loop)
     {
-      const char *password;
-
-      prompt = create_prompt (pe, 0);
-      if (! prompt)
-	/* Something went wrong.  */
+      pe->specific_err_info = strdup ("Failed to create GMainLoop");
+      pe->specific_err = gpg_error (GPG_ERR_PIN_ENTRY);
+      pe->specific_err_loc = "g_main_loop_new";
+      pe->canceled = 1;
+      return -1;
+    }      
+  state.pinentry = pe;
+  state.ret = 0;
+  state.prompt = create_prompt (pe, !!(pe->pin));
+  if (!state.prompt)
 	{
 	  pe->canceled = 1;
 	  return -1;
 	}
+  if (pe->pin)
+    gcr_prompt_password_async (state.prompt, NULL, _gcr_prompt_password_done, &state);
+  else
+    gcr_prompt_confirm_async (state.prompt, NULL, _gcr_prompt_confirm_done, &state);
+
+  g_main_loop_run (state.main_loop);
+
+  /* clean up state: */
+  g_clear_object (&state.prompt);
+  g_main_loop_unref (state.main_loop);
+  return state.ret;
+};
+
+
+static void
+_gcr_prompt_password_done (GObject *source_object, GAsyncResult *res, gpointer user_data)
+{
+  struct _gnome3_run *state = (struct _gnome3_run *) user_data;
+  GcrPrompt *prompt = GCR_PROMPT (source_object);
+  
+  if (state && prompt && state->prompt == prompt)
+    {
+      const char *password;
+      GError *error = NULL;
+      pinentry_t pe = state->pinentry;
+      int ret = -1;
 
       /* "The returned password is valid until the next time a method
 	 is called to display another prompt."  */
-      password = gcr_prompt_password (prompt, NULL, &error);
+      password = gcr_prompt_password_finish (prompt, res, &error);
       if (error)
 	/* Error.  */
 	{
@@ -228,23 +270,29 @@ gnome3_cmd_handler (pinentry_t pe)
 
 	  ret = 1;
 	}
+      state->ret = ret;
     }
-  else
-    /* Message box mode.  */
-    {
-      GcrPromptReply reply;
 
-      prompt = create_prompt (pe, 1);
-      if (! prompt)
-	/* Something went wrong.  */
+  if (state)
+    g_main_loop_quit (state->main_loop);
+}
+
+static void
+_gcr_prompt_confirm_done (GObject *source_object, GAsyncResult *res, gpointer user_data)
+{
+  struct _gnome3_run *state = (struct _gnome3_run *) user_data;
+  GcrPrompt *prompt = GCR_PROMPT (source_object);
+
+  if (state && prompt && state->prompt == prompt)
 	{
-	  pe->canceled = 1;
-	  return -1;
-	}
+      GcrPromptReply reply;
+      GError *error = NULL;
+      pinentry_t pe = state->pinentry;
+      int ret = -1;
 
       /* XXX: We don't support a third button!  */
 
-      reply = gcr_prompt_confirm_run (prompt, NULL, &error);
+      reply = gcr_prompt_confirm_finish (prompt, res, &error);
       if (error)
 	{
           _propagate_g_error_to_pinentry (state->pinentry, error, GPG_ERR_PIN_ENTRY,
@@ -263,11 +311,11 @@ gnome3_cmd_handler (pinentry_t pe)
 	  pe->canceled = 1;
 	  ret = 0;
 	}
+      state->ret = ret;
     }
 
-  if (prompt)
-    g_clear_object (&prompt);
-  return ret;
+  if (state)
+    g_main_loop_quit (state->main_loop);
 }
 
 pinentry_cmd_handler_t pinentry_cmd_handler = gnome3_cmd_handler;
-- 
2.10.1




More information about the Gnupg-devel mailing list