diff --git a/doc/gpgsm.texi b/doc/gpgsm.texi index a0da96d56..b5c87b77c 100644 --- a/doc/gpgsm.texi +++ b/doc/gpgsm.texi @@ -161,6 +161,15 @@ List certificates matching @var{pattern} using an external server. This utilizes the @code{dirmngr} service. It uses a format useful mainly for debugging. +@item --keydb-clear-some-cert-flags +@opindex keydb-clear-some-cert-flags +This is a debugging aid to reset certain flags in the key database +which are used to cache certain certificate stati. It is especially +useful if a bad CRL or a weird running OCSP reponder did accidently +revoke certificate. There is no security issue with this command +because gpgsm always make sure that the validity of a certificate is +checked right before it is used. + @item --delete-keys @var{pattern} @opindex delete-keys Delete the keys matching @var{pattern}. diff --git a/sm/ChangeLog b/sm/ChangeLog index aaf5d9047..105b84443 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,10 @@ +2004-04-28 Werner Koch + + * gpgsm.c: New command --keydb-clear-some-cert-flags. + * keydb.c (keydb_clear_some_cert_flags): New. + (keydb_update_keyblock, keydb_set_flags): Change error code + CONFLICT to NOT_LOCKED. + 2004-04-26 Werner Koch * gpgsm.c (main) : Do not use /dev/null as default config diff --git a/sm/gpgsm.c b/sm/gpgsm.c index 33d8a2c48..61307701a 100644 --- a/sm/gpgsm.c +++ b/sm/gpgsm.c @@ -85,6 +85,7 @@ enum cmd_and_opt_values { aDumpKeys, aDumpSecretKeys, aDumpExternalKeys, + aKeydbClearSomeCertFlags, oOptions, oDebug, @@ -252,6 +253,7 @@ static ARGPARSE_OPTS opts[] = { { aDumpKeys, "dump-keys", 256, "@"}, { aDumpExternalKeys, "dump-external-keys", 256, "@"}, { aDumpSecretKeys, "dump-secret-keys", 256, "@"}, + { aKeydbClearSomeCertFlags, "keydb-clear-some-cert-flags", 256, "@"}, { 301, NULL, 0, N_("@\nOptions:\n ") }, @@ -894,6 +896,7 @@ main ( int argc, char **argv) case aListSigs: case aLearnCard: case aPasswd: + case aKeydbClearSomeCertFlags: do_not_setup_keys = 1; set_cmd (&cmd, pargs.r_opt); break; @@ -1531,6 +1534,14 @@ main ( int argc, char **argv) } break; + case aKeydbClearSomeCertFlags: + for (sl=NULL; argc; argc--, argv++) + add_to_strlist (&sl, *argv); + keydb_clear_some_cert_flags (&ctrl, sl); + free_strlist(sl); + break; + + default: log_error ("invalid command (there is no implicit command)\n"); break; diff --git a/sm/keydb.c b/sm/keydb.c index 322307553..8832643b9 100644 --- a/sm/keydb.c +++ b/sm/keydb.c @@ -526,7 +526,7 @@ keydb_update_keyblock (KEYDB_HANDLE hd, KBNODE kb) return 0; if (!hd->locked) - return gpg_error (GPG_ERR_CONFLICT); + return gpg_error (GPG_ERR_NOT_LOCKED); switch (hd->active[hd->found].type) { case KEYDB_RESOURCE_TYPE_NONE: @@ -660,7 +660,7 @@ keydb_set_flags (KEYDB_HANDLE hd, int which, int idx, unsigned int value) return gpg_error (GPG_ERR_NOTHING_FOUND); if (!hd->locked) - return gpg_error (GPG_ERR_CONFLICT); + return gpg_error (GPG_ERR_NOT_LOCKED); switch (hd->active[hd->found].type) { @@ -1374,7 +1374,7 @@ keydb_store_cert (ksba_cert_t cert, int ephemeral, int *existed) /* This is basically keydb_set_flags but it implements a complete - transaction by locating teh certificate in the DB and updating the + transaction by locating the certificate in the DB and updating the flags. */ gpg_error_t keydb_set_cert_flags (ksba_cert_t cert, int which, int idx, unsigned int value) @@ -1435,3 +1435,98 @@ keydb_set_cert_flags (ksba_cert_t cert, int which, int idx, unsigned int value) return 0; } + +/* Reset all the certificate flags we have stored with the certificates + for performance reasons. */ +void +keydb_clear_some_cert_flags (ctrl_t ctrl, STRLIST names) +{ + gpg_error_t err; + KEYDB_HANDLE hd = NULL; + KEYDB_SEARCH_DESC *desc = NULL; + int ndesc; + STRLIST sl; + int rc=0; + unsigned int old_value, value; + + hd = keydb_new (0); + if (!hd) + { + log_error ("keydb_new failed\n"); + goto leave; + } + + if (!names) + ndesc = 1; + else + { + for (sl=names, ndesc=0; sl; sl = sl->next, ndesc++) + ; + } + + desc = xtrycalloc (ndesc, sizeof *desc); + if (!ndesc) + { + log_error ("allocating memory failed: %s\n", + gpg_strerror (OUT_OF_CORE (errno))); + goto leave; + } + + if (!names) + desc[0].mode = KEYDB_SEARCH_MODE_FIRST; + else + { + for (ndesc=0, sl=names; sl; sl = sl->next) + { + rc = keydb_classify_name (sl->d, desc+ndesc); + if (rc) + { + log_error ("key `%s' not found: %s\n", + sl->d, gpg_strerror (rc)); + rc = 0; + } + else + ndesc++; + } + } + + err = keydb_lock (hd); + if (err) + { + log_error (_("error locking keybox: %s\n"), gpg_strerror (err)); + goto leave; + } + + while (!(rc = keydb_search (hd, desc, ndesc))) + { + if (!names) + desc[0].mode = KEYDB_SEARCH_MODE_NEXT; + + err = keydb_get_flags (hd, KEYBOX_FLAG_VALIDITY, 0, &old_value); + if (err) + { + log_error (_("error getting stored flags: %s\n"), + gpg_strerror (err)); + goto leave; + } + + value = (old_value & ~VALIDITY_REVOKED); + if (value != old_value) + { + err = keydb_set_flags (hd, KEYBOX_FLAG_VALIDITY, 0, value); + if (err) + { + log_error (_("error storing flags: %s\n"), gpg_strerror (err)); + goto leave; + } + } + } + if (rc && rc != -1) + log_error ("keydb_search failed: %s\n", gpg_strerror (rc)); + + leave: + xfree (desc); + keydb_release (hd); +} + + diff --git a/sm/keydb.h b/sm/keydb.h index 2e9ed1573..924ad77c4 100644 --- a/sm/keydb.h +++ b/sm/keydb.h @@ -75,6 +75,8 @@ int keydb_store_cert (ksba_cert_t cert, int ephemeral, int *existed); gpg_error_t keydb_set_cert_flags (ksba_cert_t cert, int which, int idx, unsigned int value); +void keydb_clear_some_cert_flags (ctrl_t ctrl, STRLIST names); + #endif /*GNUPG_KEYDB_H*/