mirror of
git://git.gnupg.org/gnupg.git
synced 2025-01-03 12:11:33 +01:00
agent: Clear bogus pinentry cache, when it causes an error.
* agent/agent.h (PINENTRY_STATUS_*): Expose to public. (struct pin_entry_info_s): Add status. * agent/call-pinentry.c (agent_askpin): Clearing the ->status before the loop, let the assuan_transact set ->status. When failure with PINENTRY_STATUS_PASSWORD_FROM_CACHE, it returns soon. * agent/findkey.c (unprotect): Clear the pinentry cache, when it causes an error. -- GnuPG-bug-id: 4348 Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
This commit is contained in:
parent
1c92510045
commit
02a2633a7f
@ -266,6 +266,14 @@ struct server_control_s
|
||||
};
|
||||
|
||||
|
||||
/* Status of pinentry. */
|
||||
enum
|
||||
{
|
||||
PINENTRY_STATUS_CLOSE_BUTTON = 1 << 0,
|
||||
PINENTRY_STATUS_PIN_REPEATED = 1 << 8,
|
||||
PINENTRY_STATUS_PASSWORD_FROM_CACHE = 1 << 9
|
||||
};
|
||||
|
||||
/* Information pertaining to pinentry requests. */
|
||||
struct pin_entry_info_s
|
||||
{
|
||||
@ -275,7 +283,8 @@ struct pin_entry_info_s
|
||||
int failed_tries; /* Number of tries so far failed. */
|
||||
int with_qualitybar; /* Set if the quality bar should be displayed. */
|
||||
int with_repeat; /* Request repetition of the passphrase. */
|
||||
int repeat_okay; /* Repetition worked. */
|
||||
int repeat_okay; /* Repetition worked. */
|
||||
unsigned int status; /* Status. */
|
||||
gpg_error_t (*check_cb)(struct pin_entry_info_s *); /* CB used to check
|
||||
the PIN */
|
||||
void *check_cb_arg; /* optional argument which might be of use in the CB */
|
||||
|
@ -894,13 +894,6 @@ setup_qualitybar (ctrl_t ctrl)
|
||||
return 0;
|
||||
}
|
||||
|
||||
enum
|
||||
{
|
||||
PINENTRY_STATUS_CLOSE_BUTTON = 1 << 0,
|
||||
PINENTRY_STATUS_PIN_REPEATED = 1 << 8,
|
||||
PINENTRY_STATUS_PASSWORD_FROM_CACHE = 1 << 9
|
||||
};
|
||||
|
||||
/* Check the button_info line for a close action. Also check for the
|
||||
PIN_REPEATED flag. */
|
||||
static gpg_error_t
|
||||
@ -965,7 +958,6 @@ agent_askpin (ctrl_t ctrl,
|
||||
const char *errtext = NULL;
|
||||
int is_pin = 0;
|
||||
int saveflag;
|
||||
unsigned int pinentry_status;
|
||||
|
||||
if (opt.batch)
|
||||
return 0; /* fixme: we should return BAD PIN */
|
||||
@ -1076,6 +1068,7 @@ agent_askpin (ctrl_t ctrl,
|
||||
pininfo->with_repeat = 0; /* Pinentry does not support it. */
|
||||
}
|
||||
pininfo->repeat_okay = 0;
|
||||
pininfo->status = 0;
|
||||
|
||||
for (;pininfo->failed_tries < pininfo->max_tries; pininfo->failed_tries++)
|
||||
{
|
||||
@ -1109,10 +1102,9 @@ agent_askpin (ctrl_t ctrl,
|
||||
|
||||
saveflag = assuan_get_flag (entry_ctx, ASSUAN_CONFIDENTIAL);
|
||||
assuan_begin_confidential (entry_ctx);
|
||||
pinentry_status = 0;
|
||||
rc = assuan_transact (entry_ctx, "GETPIN", getpin_cb, &parm,
|
||||
inq_quality, entry_ctx,
|
||||
pinentry_status_cb, &pinentry_status);
|
||||
pinentry_status_cb, &pininfo->status);
|
||||
assuan_set_flag (entry_ctx, ASSUAN_CONFIDENTIAL, saveflag);
|
||||
/* Most pinentries out in the wild return the old Assuan error code
|
||||
for canceled which gets translated to an assuan Cancel error and
|
||||
@ -1124,7 +1116,7 @@ agent_askpin (ctrl_t ctrl,
|
||||
|
||||
/* Change error code in case the window close button was clicked
|
||||
to cancel the operation. */
|
||||
if ((pinentry_status & PINENTRY_STATUS_CLOSE_BUTTON)
|
||||
if ((pininfo->status & PINENTRY_STATUS_CLOSE_BUTTON)
|
||||
&& gpg_err_code (rc) == GPG_ERR_CANCELED)
|
||||
rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_FULLY_CANCELED);
|
||||
|
||||
@ -1151,12 +1143,19 @@ agent_askpin (ctrl_t ctrl,
|
||||
/* More checks by utilizing the optional callback. */
|
||||
pininfo->cb_errtext = NULL;
|
||||
rc = pininfo->check_cb (pininfo);
|
||||
if (gpg_err_code (rc) == GPG_ERR_BAD_PASSPHRASE
|
||||
&& pininfo->cb_errtext)
|
||||
errtext = pininfo->cb_errtext;
|
||||
else if (gpg_err_code (rc) == GPG_ERR_BAD_PASSPHRASE
|
||||
|| gpg_err_code (rc) == GPG_ERR_BAD_PIN)
|
||||
errtext = (is_pin? L_("Bad PIN") : L_("Bad Passphrase"));
|
||||
/* When pinentry cache causes an error, return now. */
|
||||
if (rc
|
||||
&& (pininfo->status & PINENTRY_STATUS_PASSWORD_FROM_CACHE))
|
||||
return unlock_pinentry (ctrl, rc);
|
||||
|
||||
if (gpg_err_code (rc) == GPG_ERR_BAD_PASSPHRASE)
|
||||
{
|
||||
if (pininfo->cb_errtext)
|
||||
errtext = pininfo->cb_errtext;
|
||||
else if (gpg_err_code (rc) == GPG_ERR_BAD_PASSPHRASE
|
||||
|| gpg_err_code (rc) == GPG_ERR_BAD_PIN)
|
||||
errtext = (is_pin? L_("Bad PIN") : L_("Bad Passphrase"));
|
||||
}
|
||||
else if (rc)
|
||||
return unlock_pinentry (ctrl, rc);
|
||||
}
|
||||
@ -1164,12 +1163,12 @@ agent_askpin (ctrl_t ctrl,
|
||||
if (!errtext)
|
||||
{
|
||||
if (pininfo->with_repeat
|
||||
&& (pinentry_status & PINENTRY_STATUS_PIN_REPEATED))
|
||||
&& (pininfo->status & PINENTRY_STATUS_PIN_REPEATED))
|
||||
pininfo->repeat_okay = 1;
|
||||
return unlock_pinentry (ctrl, 0); /* okay, got a PIN or passphrase */
|
||||
}
|
||||
|
||||
if ((pinentry_status & PINENTRY_STATUS_PASSWORD_FROM_CACHE))
|
||||
if ((pininfo->status & PINENTRY_STATUS_PASSWORD_FROM_CACHE))
|
||||
/* The password was read from the cache. Don't count this
|
||||
against the retry count. */
|
||||
pininfo->failed_tries --;
|
||||
|
@ -632,7 +632,17 @@ unprotect (ctrl_t ctrl, const char *cache_nonce, const char *desc_text,
|
||||
pi->check_cb_arg = &arg;
|
||||
|
||||
rc = agent_askpin (ctrl, desc_text, NULL, NULL, pi, hexgrip, cache_mode);
|
||||
if (!rc)
|
||||
if (rc)
|
||||
{
|
||||
if ((pi->status & PINENTRY_STATUS_PASSWORD_FROM_CACHE))
|
||||
{
|
||||
log_error ("Clearing pinentry cache which caused error %s\n",
|
||||
gpg_strerror (rc));
|
||||
|
||||
agent_clear_passphrase (ctrl, hexgrip, cache_mode);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
assert (arg.unprotected_key);
|
||||
if (arg.change_required)
|
||||
|
Loading…
x
Reference in New Issue
Block a user