aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--agent/agent.h11
-rw-r--r--agent/call-pinentry.c37
-rw-r--r--agent/findkey.c12
3 files changed, 39 insertions, 21 deletions
diff --git a/agent/agent.h b/agent/agent.h
index 05080f1f2..ee5a31eef 100644
--- a/agent/agent.h
+++ b/agent/agent.h
@@ -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 */
diff --git a/agent/call-pinentry.c b/agent/call-pinentry.c
index 38c01e26f..541a4a3f1 100644
--- a/agent/call-pinentry.c
+++ b/agent/call-pinentry.c
@@ -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 --;
diff --git a/agent/findkey.c b/agent/findkey.c
index 78c3b1a47..89a18fa9e 100644
--- a/agent/findkey.c
+++ b/agent/findkey.c
@@ -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)