aboutsummaryrefslogtreecommitdiffstats
path: root/sm
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2009-03-06 17:31:27 +0000
committerWerner Koch <[email protected]>2009-03-06 17:31:27 +0000
commita9c317a95c440a083809346d61cdb78abff71b12 (patch)
tree6f5199efe8fba5473afc346f003abe74f6ab424e /sm
parentNew PIN Callback attributes in gpg-agent. (diff)
downloadgnupg-a9c317a95c440a083809346d61cdb78abff71b12.tar.gz
gnupg-a9c317a95c440a083809346d61cdb78abff71b12.zip
New gpg-agent command to list key information.
Gpgsm does now print the S/N of cards. Consider ephemeral keys during listing an export.
Diffstat (limited to 'sm')
-rw-r--r--sm/ChangeLog13
-rw-r--r--sm/call-agent.c67
-rw-r--r--sm/export.c22
-rw-r--r--sm/fingerprint.c4
-rw-r--r--sm/gpgsm.h2
-rw-r--r--sm/keylist.c41
6 files changed, 130 insertions, 19 deletions
diff --git a/sm/ChangeLog b/sm/ChangeLog
index 83f4569ca..4d98dc50e 100644
--- a/sm/ChangeLog
+++ b/sm/ChangeLog
@@ -1,3 +1,14 @@
+2009-03-06 Werner Koch <[email protected]>
+
+ * call-agent.c (gpgsm_agent_keyinfo, keyinfo_status_cb): New.
+ * keylist.c (list_cert_colon): Print card S/N.
+
+ * keylist.c (list_internal_keys): Always list ephemeral keys if
+ specified by keygrip or fingerprint.
+ (list_cert_raw): Always show ephemeral flag.
+ * export.c (gpgsm_export): Export ephemeral keys if specified by
+ keygrip.
+
2009-02-09 Werner Koch <[email protected]>
* gpgsm.c (main): Change default cipher back to 3DES.
@@ -2451,7 +2462,7 @@ h2007-11-22 Werner Koch <[email protected]>
Copyright 2001, 2002, 2003, 2004, 2005, 2006,
- 2007, 2008 Free Software Foundation, Inc.
+ 2007, 2008, 2009 Free Software Foundation, Inc.
This file is free software; as a special exception the author gives
unlimited permission to copy and/or distribute it, with or without
diff --git a/sm/call-agent.c b/sm/call-agent.c
index 0add44aae..a6ac6da36 100644
--- a/sm/call-agent.c
+++ b/sm/call-agent.c
@@ -1,6 +1,6 @@
/* call-agent.c - Divert GPGSM operations to the agent
* Copyright (C) 2001, 2002, 2003, 2005, 2007,
- * 2008 Free Software Foundation, Inc.
+ * 2008, 2009 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -836,3 +836,68 @@ gpgsm_agent_send_nop (ctrl_t ctrl)
}
+
+static int
+keyinfo_status_cb (void *opaque, const char *line)
+{
+ char **serialno = opaque;
+ const char *s, *s2;
+
+ if (!strncmp (line, "KEYINFO ", 8) && !*serialno)
+ {
+ s = strchr (line+8, ' ');
+ if (s && s[1] == 'T' && s[2] == ' ' && s[3])
+ {
+ s += 3;
+ s2 = strchr (s, ' ');
+ if ( s2 > s )
+ {
+ *serialno = xtrymalloc ((s2 - s)+1);
+ if (*serialno)
+ {
+ memcpy (*serialno, s, s2 - s);
+ (*serialno)[s2 - s] = 0;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+/* Return the serial number for a secret key. If the returned serial
+ number is NULL, the key is not stored on a smartcard. Caller needs
+ to free R_SERIALNO. */
+gpg_error_t
+gpgsm_agent_keyinfo (ctrl_t ctrl, const char *hexkeygrip, char **r_serialno)
+{
+ gpg_error_t err;
+ char line[ASSUAN_LINELENGTH];
+ char *serialno = NULL;
+
+ *r_serialno = NULL;
+
+ err = start_agent (ctrl);
+ if (err)
+ return err;
+
+ if (!hexkeygrip || strlen (hexkeygrip) != 40)
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ snprintf (line, DIM(line)-1, "KEYINFO %s", hexkeygrip);
+ line[DIM(line)-1] = 0;
+
+ err = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL,
+ keyinfo_status_cb, &serialno);
+ if (!err && serialno)
+ {
+ /* Sanity check for bad characters. */
+ if (strpbrk (serialno, ":\n\r"))
+ err = GPG_ERR_INV_VALUE;
+ }
+ if (err)
+ xfree (serialno);
+ else
+ *r_serialno = serialno;
+ return err;
+}
+
diff --git a/sm/export.c b/sm/export.c
index fa2e9de1a..f8e23cec1 100644
--- a/sm/export.c
+++ b/sm/export.c
@@ -1,5 +1,5 @@
/* export.c - Export certificates and private keys.
- * Copyright (C) 2002, 2003, 2004, 2007 Free Software Foundation, Inc.
+ * Copyright (C) 2002, 2003, 2004, 2007, 2009 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -37,11 +37,11 @@
/* A table to store a fingerprint as used in a duplicates table. We
- don't need to hash here because a fingerprint is alrady a perfect
+ don't need to hash here because a fingerprint is already a perfect
hash value. This we use the most significant bits to index the
table and then use a linked list for the overflow. Possible
- enhancement for very large number of certictates: Add a second
- level table and then resort to a linked list. */
+ enhancement for very large number of certificates: Add a second
+ level table and then resort to a linked list. */
struct duptable_s
{
struct duptable_s *next;
@@ -192,18 +192,16 @@ gpgsm_export (ctrl_t ctrl, strlist_t names, FILE *fp, estream_t stream)
}
}
- /* If all specifications are done by fingerprint, we switch to
- ephemeral mode so that _all_ currently available and matching
- certificates are exported.
-
- fixme: we should in this case keep a list of certificates to
- avoid accidential export of duplicate certificates. */
+ /* If all specifications are done by fingerprint or keygrip, we
+ switch to ephemeral mode so that _all_ currently available and
+ matching certificates are exported. */
if (names && ndesc)
{
for (i=0; (i < ndesc
&& (desc[i].mode == KEYDB_SEARCH_MODE_FPR
|| desc[i].mode == KEYDB_SEARCH_MODE_FPR20
- || desc[i].mode == KEYDB_SEARCH_MODE_FPR16)); i++)
+ || desc[i].mode == KEYDB_SEARCH_MODE_FPR16
+ || desc[i].mode == KEYDB_SEARCH_MODE_KEYGRIP)); i++)
;
if (i == ndesc)
keydb_set_ephemeral (hd, 1);
@@ -228,7 +226,7 @@ gpgsm_export (ctrl_t ctrl, strlist_t names, FILE *fp, estream_t stream)
rc = insert_duptable (dtable, fpr, &exists);
if (rc)
{
- log_error ("inserting into duplicates table fauiled: %s\n",
+ log_error ("inserting into duplicates table failed: %s\n",
gpg_strerror (rc));
goto leave;
}
diff --git a/sm/fingerprint.c b/sm/fingerprint.c
index 6581688a8..addf56296 100644
--- a/sm/fingerprint.c
+++ b/sm/fingerprint.c
@@ -196,8 +196,8 @@ gpgsm_get_keygrip (ksba_cert_t cert, unsigned char *array)
return array;
}
-/* Return an allocated buffer with the keygrip of CERT in from of an
- hexstring. NULL is returned in case of error */
+/* Return an allocated buffer with the keygrip of CERT encoded as a
+ hexstring. NULL is returned in case of error. */
char *
gpgsm_get_keygrip_hexstring (ksba_cert_t cert)
{
diff --git a/sm/gpgsm.h b/sm/gpgsm.h
index 1460dc0d6..984dda135 100644
--- a/sm/gpgsm.h
+++ b/sm/gpgsm.h
@@ -395,6 +395,8 @@ int gpgsm_agent_learn (ctrl_t ctrl);
int gpgsm_agent_passwd (ctrl_t ctrl, const char *hexkeygrip, const char *desc);
gpg_error_t gpgsm_agent_get_confirmation (ctrl_t ctrl, const char *desc);
gpg_error_t gpgsm_agent_send_nop (ctrl_t ctrl);
+gpg_error_t gpgsm_agent_keyinfo (ctrl_t ctrl, const char *hexkeygrip,
+ char **r_serialno);
/*-- call-dirmngr.c --*/
int gpgsm_dirmngr_isvalid (ctrl_t ctrl,
diff --git a/sm/keylist.c b/sm/keylist.c
index b0d2f56dd..39b82c29d 100644
--- a/sm/keylist.c
+++ b/sm/keylist.c
@@ -1,6 +1,6 @@
/* keylist.c - Print certificates in various formats.
* Copyright (C) 1998, 1999, 2000, 2001, 2003,
- * 2004, 2005, 2008 Free Software Foundation, Inc.
+ * 2004, 2005, 2008, 2009 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -481,7 +481,24 @@ list_cert_colon (ctrl_t ctrl, ksba_cert_t cert, unsigned int validity,
es_putc (':', fp);
/* Field 12, capabilities: */
print_capabilities (cert, fp);
+ /* Field 13, not used: */
es_putc (':', fp);
+ if (have_secret)
+ {
+ char *cardsn;
+
+ p = gpgsm_get_keygrip_hexstring (cert);
+ if (!gpgsm_agent_keyinfo (ctrl, p, &cardsn) && cardsn)
+ {
+ /* Field 14, not used: */
+ es_putc (':', fp);
+ /* Field 15: Token serial number. */
+ es_fputs (cardsn, fp);
+ es_putc (':', fp);
+ }
+ xfree (cardsn);
+ xfree (p);
+ }
es_putc ('\n', fp);
/* FPR record */
@@ -989,7 +1006,7 @@ list_cert_raw (ctrl_t ctrl, KEYDB_HANDLE hd,
es_fprintf (fp, " [certificate is bad: %s]\n", gpg_strerror (err));
}
- if (opt.with_ephemeral_keys && hd)
+ if (hd)
{
unsigned int blobflags;
@@ -1275,6 +1292,7 @@ list_internal_keys (ctrl_t ctrl, strlist_t names, estream_t fp,
gpg_error_t rc = 0;
const char *lastresname, *resname;
int have_secret;
+ int want_ephemeral = opt.with_ephemeral_keys;
hd = keydb_new (0);
if (!hd)
@@ -1319,7 +1337,24 @@ list_internal_keys (ctrl_t ctrl, strlist_t names, estream_t fp,
}
- if (opt.with_ephemeral_keys)
+ /* If all specifications are done by fingerprint or keygrip, we
+ switch to ephemeral mode so that _all_ currently available and
+ matching certificates are listed. */
+ if (!want_ephemeral && names && ndesc)
+ {
+ int i;
+
+ for (i=0; (i < ndesc
+ && (desc[i].mode == KEYDB_SEARCH_MODE_FPR
+ || desc[i].mode == KEYDB_SEARCH_MODE_FPR20
+ || desc[i].mode == KEYDB_SEARCH_MODE_FPR16
+ || desc[i].mode == KEYDB_SEARCH_MODE_KEYGRIP)); i++)
+ ;
+ if (i == ndesc)
+ want_ephemeral = 1;
+ }
+
+ if (want_ephemeral)
keydb_set_ephemeral (hd, 1);
/* It would be nice to see which of the given users did actually