aboutsummaryrefslogtreecommitdiffstats
path: root/g10/cardglue.c
diff options
context:
space:
mode:
Diffstat (limited to 'g10/cardglue.c')
-rw-r--r--g10/cardglue.c97
1 files changed, 90 insertions, 7 deletions
diff --git a/g10/cardglue.c b/g10/cardglue.c
index 530e8a43f..9e7aef81f 100644
--- a/g10/cardglue.c
+++ b/g10/cardglue.c
@@ -43,12 +43,19 @@
#include "apdu.h"
#include "app-common.h"
-struct ctrl_ctx_s {
+struct ctrl_ctx_s
+{
int (*status_cb)(void *opaque, const char *line);
void *status_cb_arg;
};
+struct pincb_parm_s
+{
+ const char *sn;
+};
+
+
static char *default_reader_port;
static APP current_app;
@@ -334,6 +341,39 @@ card_close (void)
}
+/* Format a cache ID from the serialnumber in SN and return it as an
+ allocated string. In case of an error NULL is returned. */
+static char *
+format_cacheid (const char *sn)
+{
+ const char *s;
+ size_t snlen;
+ char *cacheid = NULL;
+
+ /* The serialnumber we use for a card is "CARDSN:serialno". Where
+ serialno is the BCD string (i.e. hex string) with the full
+ number. The serial number expect here constsis of hexdigits
+ followed by other characters, we cut off these other
+ characters. */
+ if (sn)
+ {
+ for (s=sn,snlen=0; hexdigitp (s); s++, snlen++)
+ ;
+ if (snlen == 32)
+ {
+ /* Yes, this looks indeed like an OpenPGP card S/N. */
+ cacheid = xtrymalloc (7+snlen+1);
+ if (cacheid)
+ {
+ memcpy (cacheid, "CARDSN:", 7);
+ memcpy (cacheid+7, sn, snlen);
+ cacheid[7+snlen] = 0;
+ }
+ }
+ }
+ return cacheid;
+}
+
/* Check that the serial number of the current card (as described by
APP) matches SERIALNO. If there is no match and we are not in
batch mode, present a prompt to insert the desired card. The
@@ -651,12 +691,14 @@ agent_scd_getattr (const char *name, struct agent_card_info_s *info)
static int
pin_cb (void *opaque, const char *info, char **retstr)
{
+ struct pincb_parm_s *parm = opaque;
char *value;
int canceled;
int isadmin = 0;
int newpin = 0;
const char *again_text = NULL;
const char *ends, *s;
+ char *cacheid = NULL;
*retstr = NULL;
/* log_debug ("asking for PIN '%s'\n", info); */
@@ -674,9 +716,23 @@ pin_cb (void *opaque, const char *info, char **retstr)
}
info = ends+1;
}
- else
+ else if (info && *info == '|')
log_debug ("pin_cb called without proper PIN info hack\n");
+ /* If we are not requesting a new PIN and we are not requesting an
+ AdminPIN, compute a string to be used as the cacheID for
+ gpg-agent. */
+ if (!newpin && !isadmin && parm)
+ {
+ cacheid = format_cacheid (parm->sn);
+ }
+ else if (newpin && parm)
+ {
+ /* Make really sure that it is not cached anymore. */
+ agent_clear_pin_cache (parm->sn);
+ }
+
+
again:
if (is_status_enabled())
write_status_text (STATUS_NEED_PASSPHRASE_PIN,
@@ -691,7 +747,10 @@ pin_cb (void *opaque, const char *info, char **retstr)
newpin? _("Enter New PIN: ") :
isadmin? _("Enter Admin PIN: ")
: _("Enter PIN: "),
+ cacheid,
&canceled);
+ xfree (cacheid);
+ cacheid = NULL;
again_text = NULL;
if (!value && canceled)
return -1;
@@ -702,7 +761,7 @@ pin_cb (void *opaque, const char *info, char **retstr)
{
char *value2;
- value2 = ask_passphrase (info, NULL,
+ value2 = ask_passphrase (info, NULL, NULL,
"passphrase.pin.repeat",
_("Repeat this PIN: "),
&canceled);
@@ -837,11 +896,14 @@ agent_scd_pksign (const char *serialno, int hashalgo,
const unsigned char *indata, size_t indatalen,
unsigned char **r_buf, size_t *r_buflen)
{
+ struct pincb_parm_s parm;
APP app;
int rc;
*r_buf = NULL;
*r_buflen = 0;
+ memset (&parm, 0, sizeof parm);
+ parm.sn = serialno;
retry:
app = current_app? current_app : open_card ();
if (!app)
@@ -854,11 +916,14 @@ agent_scd_pksign (const char *serialno, int hashalgo,
if (!rc)
rc = app->fnc.sign (app, serialno, hashalgo,
- pin_cb, NULL,
+ pin_cb, &parm,
indata, indatalen,
r_buf, r_buflen);
if (rc)
- write_status (STATUS_SC_OP_FAILURE);
+ {
+ write_status (STATUS_SC_OP_FAILURE);
+ agent_clear_pin_cache (serialno);
+ }
return rc;
}
@@ -869,11 +934,14 @@ agent_scd_pkdecrypt (const char *serialno,
const unsigned char *indata, size_t indatalen,
unsigned char **r_buf, size_t *r_buflen)
{
+ struct pincb_parm_s parm;
APP app;
int rc;
*r_buf = NULL;
*r_buflen = 0;
+ memset (&parm, 0, sizeof parm);
+ parm.sn = serialno;
retry:
app = current_app? current_app : open_card ();
if (!app)
@@ -886,11 +954,14 @@ agent_scd_pkdecrypt (const char *serialno,
if (!rc)
rc = app->fnc.decipher (app, serialno,
- pin_cb, NULL,
+ pin_cb, &parm,
indata, indatalen,
r_buf, r_buflen);
if (rc)
- write_status (STATUS_SC_OP_FAILURE);
+ {
+ write_status (STATUS_SC_OP_FAILURE);
+ agent_clear_pin_cache (serialno);
+ }
return rc;
}
@@ -960,3 +1031,15 @@ agent_openpgp_storekey (int keyno,
write_status (STATUS_SC_OP_FAILURE);
return rc;
}
+
+
+void
+agent_clear_pin_cache (const char *sn)
+{
+ char *cacheid = format_cacheid (sn);
+ if (cacheid)
+ {
+ passphrase_clear_cache (NULL, cacheid, 0);
+ xfree (cacheid);
+ }
+}