diff options
author | Werner Koch <[email protected]> | 2009-03-06 17:31:27 +0000 |
---|---|---|
committer | Werner Koch <[email protected]> | 2009-03-06 17:31:27 +0000 |
commit | a9c317a95c440a083809346d61cdb78abff71b12 (patch) | |
tree | 6f5199efe8fba5473afc346f003abe74f6ab424e /sm | |
parent | New PIN Callback attributes in gpg-agent. (diff) | |
download | gnupg-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/ChangeLog | 13 | ||||
-rw-r--r-- | sm/call-agent.c | 67 | ||||
-rw-r--r-- | sm/export.c | 22 | ||||
-rw-r--r-- | sm/fingerprint.c | 4 | ||||
-rw-r--r-- | sm/gpgsm.h | 2 | ||||
-rw-r--r-- | sm/keylist.c | 41 |
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 |