From 4738256f2e0d22302377c9ec7b2ae3999338e6c6 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Thu, 26 Oct 2017 14:40:38 +0900 Subject: [PATCH] agent: Allow recursive use of pinentry. * agent/agent.h (struct server_control_s): Add pinentry_level. * agent/call-pinentry.c (agent_popup_message_stop): Not clear ENTRY_CTX here. (unlock_pinentry): Handle recursion. Clear ENTRY_CTX here. (start_pinentry): Allow recursive use. -- GnuPG-bug-id: 3190 Signed-off-by: NIIBE Yutaka (cherry picked from commit 3b66a256e3760e88066ca11b7b49d924e42aa46b) --- agent/agent.h | 3 +++ agent/call-pinentry.c | 34 +++++++++++++++++++++++----------- 2 files changed, 26 insertions(+), 11 deletions(-) diff --git a/agent/agent.h b/agent/agent.h index f5df75e6e..cde38fe4a 100644 --- a/agent/agent.h +++ b/agent/agent.h @@ -254,6 +254,9 @@ struct server_control_s /* The current S2K which might be different from the calibrated count. */ unsigned long s2k_count; + + /* Recursion level of pinentry. */ + int pinentry_level; }; diff --git a/agent/call-pinentry.c b/agent/call-pinentry.c index 6a5c1fe1e..0fe83454e 100644 --- a/agent/call-pinentry.c +++ b/agent/call-pinentry.c @@ -177,15 +177,19 @@ unlock_pinentry (gpg_error_t rc) } } - entry_ctx = NULL; - err = npth_mutex_unlock (&entry_lock); - if (err) + if (--entry_owner->pinentry_level == 0) { - log_error ("failed to release the entry lock: %s\n", strerror (err)); - if (!rc) - rc = gpg_error_from_errno (err); + entry_owner = NULL; + entry_ctx = NULL; + err = npth_mutex_unlock (&entry_lock); + if (err) + { + log_error ("failed to release the entry lock: %s\n", strerror (err)); + if (!rc) + rc = gpg_error_from_errno (err); + } + assuan_release (ctx); } - assuan_release (ctx); return rc; } @@ -288,6 +292,13 @@ start_pinentry (ctrl_t ctrl) char *flavor_version; int err; + if (entry_owner == ctrl) + { + /* Allow recursive use of pinentry. */ + ctrl->pinentry_level++; + return 0; + } + npth_clock_gettime (&abstime); abstime.tv_sec += LOCK_TIMEOUT; err = npth_mutex_timedlock (&entry_lock, &abstime); @@ -371,6 +382,10 @@ start_pinentry (ctrl_t ctrl) log_error ("can't allocate assuan context: %s\n", gpg_strerror (rc)); return rc; } + + ctrl->pinentry_level = 1; + entry_ctx = ctx; + /* We don't want to log the pinentry communication to make the logs easier to read. We might want to add a new debug option to enable pinentry logging. */ @@ -382,17 +397,15 @@ start_pinentry (ctrl_t ctrl) that atfork is used to change the environment for pinentry. We start the server in detached mode to suppress the console window under Windows. */ - rc = assuan_pipe_connect (ctx, full_pgmname, argv, + rc = assuan_pipe_connect (entry_ctx, full_pgmname, argv, no_close_list, atfork_cb, ctrl, ASSUAN_PIPE_CONNECT_DETACHED); if (rc) { log_error ("can't connect to the PIN entry module '%s': %s\n", full_pgmname, gpg_strerror (rc)); - assuan_release (ctx); return unlock_pinentry (gpg_error (GPG_ERR_NO_PIN_ENTRY)); } - entry_ctx = ctx; if (DBG_IPC) log_debug ("connection to PIN entry established\n"); @@ -1551,7 +1564,6 @@ agent_popup_message_stop (ctrl_t ctrl) /* Thread IDs are opaque, but we try our best here by resetting it to the same content that a static global variable has. */ memset (&popup_tid, '\0', sizeof (popup_tid)); - entry_owner = NULL; /* Now we can close the connection. */ unlock_pinentry (0);