From 09e8f35d3808d6e49f891360c341aae3869e8650 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Thu, 22 Jan 2015 16:36:28 +0100 Subject: [PATCH] gpg: Improve skipping of PGP-2 keys. * g10/keydb.c (keydb_search_first, keydb_search_next): Skip legacy keys. * g10/keyring.c (keyring_get_keyblock): Handle GPG_ERR_LEGACY_KEY. (prepare_search): Ditto. (keyring_rebuild_cache): Skip legacy keys. * g10/keyserver.c (keyidlist): Ditto. * g10/trustdb.c (validate_key_list): Ditto. -- This is not the most elegant way to handle it but it reduces the chance for unwanted side effects. GnuPG-bug-id: 1816 Signed-off-by: Werner Koch --- g10/keydb.c | 24 ++++++++++++++++++++---- g10/keylist.c | 2 ++ g10/keyring.c | 27 +++++++++++++++++++++++---- g10/keyserver.c | 13 +++++++++++-- g10/trustdb.c | 6 +++++- 5 files changed, 61 insertions(+), 11 deletions(-) diff --git a/g10/keydb.c b/g10/keydb.c index 263b504e5..401478a1d 100644 --- a/g10/keydb.c +++ b/g10/keydb.c @@ -1489,24 +1489,40 @@ keydb_search (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc, } +/* Note that in contrast to using keydb_search in search first mode, + this function skips legacy keys. */ gpg_error_t keydb_search_first (KEYDB_HANDLE hd) { + gpg_error_t err; KEYDB_SEARCH_DESC desc; memset (&desc, 0, sizeof desc); desc.mode = KEYDB_SEARCH_MODE_FIRST; - return keydb_search (hd, &desc, 1, NULL); + err = keydb_search (hd, &desc, 1, NULL); + if (gpg_err_code (err) == GPG_ERR_LEGACY_KEY) + err = keydb_search_next (hd); + return err; } + +/* Note that in contrast to using keydb_search in search next mode, + this fucntion skips legacy keys. */ gpg_error_t keydb_search_next (KEYDB_HANDLE hd) { + gpg_error_t err; KEYDB_SEARCH_DESC desc; - memset (&desc, 0, sizeof desc); - desc.mode = KEYDB_SEARCH_MODE_NEXT; - return keydb_search (hd, &desc, 1, NULL); + do + { + memset (&desc, 0, sizeof desc); + desc.mode = KEYDB_SEARCH_MODE_NEXT; + err = keydb_search (hd, &desc, 1, NULL); + } + while (gpg_err_code (err) == GPG_ERR_LEGACY_KEY); + + return err; } gpg_error_t diff --git a/g10/keylist.c b/g10/keylist.c index daabc7dba..5fd9eb87e 100644 --- a/g10/keylist.c +++ b/g10/keylist.c @@ -466,6 +466,8 @@ list_all (int secret, int mark_secret) rc = keydb_get_keyblock (hd, &keyblock); if (rc) { + if (gpg_err_code (rc) == GPG_ERR_LEGACY_KEY) + continue; /* Skip legacy keys. */ log_error ("keydb_get_keyblock failed: %s\n", gpg_strerror (rc)); goto leave; } diff --git a/g10/keyring.c b/g10/keyring.c index 34829e711..6060f0894 100644 --- a/g10/keyring.c +++ b/g10/keyring.c @@ -398,6 +398,8 @@ keyring_get_keyblock (KEYRING_HANDLE hd, KBNODE *ret_kb) init_packet (pkt); continue; } + if (gpg_err_code (rc) == GPG_ERR_LEGACY_KEY) + break; /* Upper layer needs to handle this. */ if (rc) { log_error ("keyring_get_keyblock: read error: %s\n", gpg_strerror (rc) ); @@ -654,8 +656,14 @@ keyring_search_reset (KEYRING_HANDLE hd) static int prepare_search (KEYRING_HANDLE hd) { - if (hd->current.error) - return hd->current.error; /* still in error state */ + if (hd->current.error) { + /* If the last key was a legacy key, we simply ignore the error so that + we can easily use search_next. */ + if (gpg_err_code (hd->current.error) == GPG_ERR_LEGACY_KEY) + hd->current.error = 0; + else + return hd->current.error; /* still in error state */ + } if (hd->current.kr && !hd->current.eof) { if ( !hd->current.iobuf ) @@ -1354,8 +1362,12 @@ keyring_rebuild_cache (void *token,int noisy) if(rc) goto leave; - while ( !(rc = keyring_search (hd, &desc, 1, NULL)) ) + for (;;) { + rc = keyring_search (hd, &desc, 1, NULL); + if (rc && gpg_err_code (rc) != GPG_ERR_LEGACY_KEY) + break; /* ready. */ + desc.mode = KEYDB_SEARCH_MODE_NEXT; resname = keyring_get_resource_name (hd); if (lastresname != resname ) @@ -1387,10 +1399,15 @@ keyring_rebuild_cache (void *token,int noisy) goto leave; } + if (gpg_err_code (rc) == GPG_ERR_LEGACY_KEY) + continue; + release_kbnode (keyblock); rc = keyring_get_keyblock (hd, &keyblock); if (rc) { + if (gpg_err_code (rc) == GPG_ERR_LEGACY_KEY) + continue; /* Skip legacy keys. */ log_error ("keyring_get_keyblock failed: %s\n", gpg_strerror (rc)); goto leave; } @@ -1416,7 +1433,9 @@ keyring_rebuild_cache (void *token,int noisy) The code required to keep them in the keyring would be too complicated. Given that we do not touch the old secring.gpg a suitable backup for decryption of v3 stuff - using an older gpg version will always be available. */ + using an older gpg version will always be available. + Note: This test is actually superfluous because we + already acted upon GPG_ERR_LEGACY_KEY. */ } else { diff --git a/g10/keyserver.c b/g10/keyserver.c index 0530907a9..035cd031f 100644 --- a/g10/keyserver.c +++ b/g10/keyserver.c @@ -1248,16 +1248,25 @@ keyidlist(strlist_t users,KEYDB_SEARCH_DESC **klist,int *count,int fakev3) } } - while (!(rc = keydb_search (kdbhd, desc, ndesc, NULL))) + for (;;) { + rc = keydb_search (kdbhd, desc, ndesc, NULL); + if (rc && gpg_err_code (rc) != GPG_ERR_LEGACY_KEY) + break; /* ready. */ + if (!users) desc[0].mode = KEYDB_SEARCH_MODE_NEXT; + if (gpg_err_code (rc) == GPG_ERR_LEGACY_KEY) + continue; + /* read the keyblock */ rc = keydb_get_keyblock (kdbhd, &keyblock ); if( rc ) { - log_error (_("error reading keyblock: %s\n"), gpg_strerror (rc) ); + if (gpg_err_code (rc) == GPG_ERR_LEGACY_KEY) + continue; + log_error (_("error reading keyblock: %s\n"), gpg_strerror (rc) ); goto leave; } diff --git a/g10/trustdb.c b/g10/trustdb.c index 84179f0b0..08f6cf4a1 100644 --- a/g10/trustdb.c +++ b/g10/trustdb.c @@ -1604,6 +1604,9 @@ validate_key_list (KEYDB_HANDLE hd, KeyHashTable full_trust, { PKT_public_key *pk; + if (gpg_err_code (rc) == GPG_ERR_LEGACY_KEY) + continue; + rc = keydb_get_keyblock (hd, &keyblock); if (rc) { @@ -1660,7 +1663,8 @@ validate_key_list (KEYDB_HANDLE hd, KeyHashTable full_trust, release_kbnode (keyblock); keyblock = NULL; } - while (!(rc = keydb_search (hd, &desc, 1, NULL))); + while (!(rc = keydb_search (hd, &desc, 1, NULL)) + || gpg_err_code (rc) == GPG_ERR_LEGACY_KEY); if (rc && gpg_err_code (rc) != GPG_ERR_NOT_FOUND) {