g10,agent: Support CONFIRM for --delete-key.

* agent/call-pinentry.c (agent_get_confirmation): Add call of
pinentry_loopback_confirm.
(agent_popup_message_start): Likewise.
(agent_popup_message_stop): Return if it's loopback mode.
* agent/command.c (pinentry_loopback_confirm): New.

* g10/call-agent.c (default_inq_cb): Support "CONFIRM" inquery
when PINENTRY_MODE_LOOPBACK mode.
(confirm_status_cb): New.
(agent_delete_key): Supply confirm_status_cb to set the description
string for confirmation.

--

In the Assuan communication, we introduce new interaction:

    [gpg]                            [gpg-agent]
            --- CMD: PKDECRYPT -->
            <-- STATUS: SETDESC "..."
            <-- STATUS: SETOK "..."
            <-- STATUS: SETNOTOK "..."
            <-- INQUERY: CONFIRM 0/1 (0 for display, 1 for user query)
	    --- INQUERY-result: -->
	    <-- RESULT: ...

GnuPG-bug-id: 3465
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
This commit is contained in:
NIIBE Yutaka 2019-06-04 09:17:21 +09:00
parent eaf3b89d11
commit 20acc7c022
3 changed files with 102 additions and 3 deletions

View File

@ -1391,6 +1391,9 @@ agent_get_confirmation (ctrl_t ctrl,
if (ctrl->pinentry_mode == PINENTRY_MODE_CANCEL) if (ctrl->pinentry_mode == PINENTRY_MODE_CANCEL)
return gpg_error (GPG_ERR_CANCELED); 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); 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; int err;
if (ctrl->pinentry_mode != PINENTRY_MODE_ASK) 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); rc = start_pinentry (ctrl);
if (rc) if (rc)
@ -1537,6 +1548,9 @@ agent_popup_message_stop (ctrl_t ctrl)
(void)ctrl; (void)ctrl;
if (ctrl->pinentry_mode == PINENTRY_MODE_LOOPBACK)
return;
if (!popup_tid || !entry_ctx) if (!popup_tid || !entry_ctx)
{ {
log_debug ("agent_popup_message_stop called with no active popup\n"); log_debug ("agent_popup_message_stop called with no active popup\n");

View File

@ -3680,3 +3680,26 @@ pinentry_loopback(ctrl_t ctrl, const char *keyword,
assuan_end_confidential (ctx); assuan_end_confidential (ctx);
return rc; 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;
}

View File

@ -41,6 +41,7 @@
#include "../common/status.h" #include "../common/status.h"
#include "../common/shareddefs.h" #include "../common/shareddefs.h"
#include "../common/host2net.h" #include "../common/host2net.h"
#include "../common/ttyio.h"
#define CONTROL_D ('D' - 'A' + 1) #define CONTROL_D ('D' - 'A' + 1)
@ -48,6 +49,13 @@
static assuan_context_t agent_ctx = NULL; static assuan_context_t agent_ctx = NULL;
static int did_early_card_test; static int did_early_card_test;
struct confirm_parm_s
{
char *desc;
char *ok;
char *notok;
};
struct default_inq_parm_s struct default_inq_parm_s
{ {
ctrl_t ctrl; ctrl_t ctrl;
@ -57,6 +65,7 @@ struct default_inq_parm_s
u32 *mainkeyid; u32 *mainkeyid;
int pubkey_algo; int pubkey_algo;
} keyinfo; } keyinfo;
struct confirm_parm_s *confirm;
}; };
struct cipher_parm_s struct cipher_parm_s
@ -136,6 +145,7 @@ default_inq_cb (void *opaque, const char *line)
{ {
gpg_error_t err = 0; gpg_error_t err = 0;
struct default_inq_parm_s *parm = opaque; struct default_inq_parm_s *parm = opaque;
const char *s;
if (has_leading_keyword (line, "PINENTRY_LAUNCHED")) if (has_leading_keyword (line, "PINENTRY_LAUNCHED"))
{ {
@ -151,7 +161,7 @@ default_inq_cb (void *opaque, const char *line)
{ {
if (have_static_passphrase ()) if (have_static_passphrase ())
{ {
const char *s = get_static_passphrase (); s = get_static_passphrase ();
err = assuan_send_data (parm->ctx, s, strlen (s)); err = assuan_send_data (parm->ctx, s, strlen (s));
} }
else else
@ -176,6 +186,27 @@ default_inq_cb (void *opaque, const char *line)
xfree (pw); 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 else
log_debug ("ignoring gpg-agent inquiry '%s'\n", line); 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 /* Ask the agent to delete the key identified by HEXKEYGRIP. If DESC
is not NULL, display DESC instead of the default description 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; gpg_error_t err;
char line[ASSUAN_LINELENGTH]; char line[ASSUAN_LINELENGTH];
struct default_inq_parm_s dfltparm; struct default_inq_parm_s dfltparm;
struct confirm_parm_s confirm_parm;
memset (&confirm_parm, 0, sizeof confirm_parm);
memset (&dfltparm, 0, sizeof dfltparm); memset (&dfltparm, 0, sizeof dfltparm);
dfltparm.ctrl = ctrl; dfltparm.ctrl = ctrl;
dfltparm.confirm = &confirm_parm;
err = start_agent (ctrl, 0); err = start_agent (ctrl, 0);
if (err) if (err)
@ -2548,7 +2607,10 @@ agent_delete_key (ctrl_t ctrl, const char *hexkeygrip, const char *desc,
force? " --force":"", hexkeygrip); force? " --force":"", hexkeygrip);
err = assuan_transact (agent_ctx, line, NULL, NULL, err = assuan_transact (agent_ctx, line, NULL, NULL,
default_inq_cb, &dfltparm, 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; return err;
} }