summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--agent/call-pinentry.c16
-rw-r--r--agent/command.c23
-rw-r--r--g10/call-agent.c66
3 files changed, 102 insertions, 3 deletions
diff --git a/agent/call-pinentry.c b/agent/call-pinentry.c
index 487b21e81..c2105cd6e 100644
--- a/agent/call-pinentry.c
+++ b/agent/call-pinentry.c
@@ -1391,6 +1391,9 @@ agent_get_confirmation (ctrl_t ctrl,
if (ctrl->pinentry_mode == PINENTRY_MODE_CANCEL)
return gpg_error (GPG_ERR_CANCELED);
+ if (ctrl->pinentry_mode == PINENTRY_MODE_LOOPBACK)
+ return pinentry_loopback_confirm (ctrl, desc, 1, ok, notok);
+
return gpg_error (GPG_ERR_NO_PIN_ENTRY);
}
@@ -1486,7 +1489,15 @@ agent_popup_message_start (ctrl_t ctrl, const char *desc, const char *ok_btn)
int err;
if (ctrl->pinentry_mode != PINENTRY_MODE_ASK)
- return gpg_error (GPG_ERR_CANCELED);
+ {
+ if (ctrl->pinentry_mode == PINENTRY_MODE_CANCEL)
+ return gpg_error (GPG_ERR_CANCELED);
+
+ if (ctrl->pinentry_mode == PINENTRY_MODE_LOOPBACK)
+ return pinentry_loopback_confirm (ctrl, desc, 0, ok_btn, NULL);
+
+ return gpg_error (GPG_ERR_NO_PIN_ENTRY);
+ }
rc = start_pinentry (ctrl);
if (rc)
@@ -1537,6 +1548,9 @@ agent_popup_message_stop (ctrl_t ctrl)
(void)ctrl;
+ if (ctrl->pinentry_mode == PINENTRY_MODE_LOOPBACK)
+ return;
+
if (!popup_tid || !entry_ctx)
{
log_debug ("agent_popup_message_stop called with no active popup\n");
diff --git a/agent/command.c b/agent/command.c
index 3c2da183c..b59532ce5 100644
--- a/agent/command.c
+++ b/agent/command.c
@@ -3680,3 +3680,26 @@ pinentry_loopback(ctrl_t ctrl, const char *keyword,
assuan_end_confidential (ctx);
return rc;
}
+
+/* Helper for the pinentry loopback mode to ask confirmation
+ or just to show message. */
+gpg_error_t
+pinentry_loopback_confirm (ctrl_t ctrl, const char *desc,
+ int ask_confirmation,
+ const char *ok, const char *notok)
+{
+ gpg_error_t err = 0;
+ assuan_context_t ctx = ctrl->server_local->assuan_ctx;
+
+ if (desc)
+ err = print_assuan_status (ctx, "SETDESC", "%s", desc);
+ if (!err && ok)
+ err = print_assuan_status (ctx, "SETOK", "%s", ok);
+ if (!err && notok)
+ err = print_assuan_status (ctx, "SETNOTOK", "%s", notok);
+
+ if (!err)
+ err = assuan_inquire (ctx, ask_confirmation ? "CONFIRM 1" : "CONFIRM 0",
+ NULL, NULL, 0);
+ return err;
+}
diff --git a/g10/call-agent.c b/g10/call-agent.c
index f6c7d3951..19deb73d7 100644
--- a/g10/call-agent.c
+++ b/g10/call-agent.c
@@ -41,6 +41,7 @@
#include "../common/status.h"
#include "../common/shareddefs.h"
#include "../common/host2net.h"
+#include "../common/ttyio.h"
#define CONTROL_D ('D' - 'A' + 1)
@@ -48,6 +49,13 @@
static assuan_context_t agent_ctx = NULL;
static int did_early_card_test;
+struct confirm_parm_s
+{
+ char *desc;
+ char *ok;
+ char *notok;
+};
+
struct default_inq_parm_s
{
ctrl_t ctrl;
@@ -57,6 +65,7 @@ struct default_inq_parm_s
u32 *mainkeyid;
int pubkey_algo;
} keyinfo;
+ struct confirm_parm_s *confirm;
};
struct cipher_parm_s
@@ -136,6 +145,7 @@ default_inq_cb (void *opaque, const char *line)
{
gpg_error_t err = 0;
struct default_inq_parm_s *parm = opaque;
+ const char *s;
if (has_leading_keyword (line, "PINENTRY_LAUNCHED"))
{
@@ -151,7 +161,7 @@ default_inq_cb (void *opaque, const char *line)
{
if (have_static_passphrase ())
{
- const char *s = get_static_passphrase ();
+ s = get_static_passphrase ();
err = assuan_send_data (parm->ctx, s, strlen (s));
}
else
@@ -176,6 +186,27 @@ default_inq_cb (void *opaque, const char *line)
xfree (pw);
}
}
+ else if ((s = has_leading_keyword (line, "CONFIRM"))
+ && opt.pinentry_mode == PINENTRY_MODE_LOOPBACK
+ && parm->confirm)
+ {
+ int ask = atoi (s);
+ int yes;
+
+ if (ask)
+ {
+ yes = cpr_get_answer_is_yes (NULL, parm->confirm->desc);
+ if (yes)
+ err = assuan_send_data (parm->ctx, NULL, 0);
+ else
+ err = gpg_error (GPG_ERR_NOT_CONFIRMED);
+ }
+ else
+ {
+ tty_printf ("%s", parm->confirm->desc);
+ err = assuan_send_data (parm->ctx, NULL, 0);
+ }
+ }
else
log_debug ("ignoring gpg-agent inquiry '%s'\n", line);
@@ -2512,6 +2543,31 @@ agent_export_key (ctrl_t ctrl, const char *hexkeygrip, const char *desc,
}
+/* Status callback for handling confirmation. */
+static gpg_error_t
+confirm_status_cb (void *opaque, const char *line)
+{
+ struct confirm_parm_s *parm = opaque;
+ const char *s;
+
+ if ((s = has_leading_keyword (line, "SETDESC")))
+ {
+ xfree (parm->desc);
+ parm->desc = unescape_status_string (s);
+ }
+ else if ((s = has_leading_keyword (line, "SETOK")))
+ {
+ xfree (parm->ok);
+ parm->ok = unescape_status_string (s);
+ }
+ else if ((s = has_leading_keyword (line, "SETNOTOK")))
+ {
+ xfree (parm->notok);
+ parm->notok = unescape_status_string (s);
+ }
+
+ return 0;
+}
/* Ask the agent to delete the key identified by HEXKEYGRIP. If DESC
is not NULL, display DESC instead of the default description
@@ -2524,9 +2580,12 @@ agent_delete_key (ctrl_t ctrl, const char *hexkeygrip, const char *desc,
gpg_error_t err;
char line[ASSUAN_LINELENGTH];
struct default_inq_parm_s dfltparm;
+ struct confirm_parm_s confirm_parm;
+ memset (&confirm_parm, 0, sizeof confirm_parm);
memset (&dfltparm, 0, sizeof dfltparm);
dfltparm.ctrl = ctrl;
+ dfltparm.confirm = &confirm_parm;
err = start_agent (ctrl, 0);
if (err)
@@ -2548,7 +2607,10 @@ agent_delete_key (ctrl_t ctrl, const char *hexkeygrip, const char *desc,
force? " --force":"", hexkeygrip);
err = assuan_transact (agent_ctx, line, NULL, NULL,
default_inq_cb, &dfltparm,
- NULL, NULL);
+ confirm_status_cb, &confirm_parm);
+ xfree (confirm_parm.desc);
+ xfree (confirm_parm.ok);
+ xfree (confirm_parm.notok);
return err;
}