Try to get the only-valid-if-cert-valid cert from the dirmngr first.
authorWerner Koch <wk@gnupg.org>
Thu, 21 Jul 2011 08:39:38 +0000 (10:39 +0200)
committerWerner Koch <wk@gnupg.org>
Thu, 21 Jul 2011 08:39:38 +0000 (10:39 +0200)
This should always work because the dirmngr asked us to validate the
given certificate.  This should make OCSP configuration easier because
there is less requirement to install all certificates for Dirmngr and
gpgsm.

CAUTION:  This code has not yet been tested.

NEWS
sm/ChangeLog
sm/call-dirmngr.c

diff --git a/NEWS b/NEWS
index b3ce8e0..ca7185a 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -5,6 +5,8 @@ Noteworthy changes in version 2.0.18 (unreleased)
 
  * Bug fix for newer versions of Libgcrypt.
 
+ * Improved dirmngr/gpgsm interaction for OCSP.
+
 
 Noteworthy changes in version 2.0.17 (2011-01-13)
 -------------------------------------------------
@@ -176,7 +178,7 @@ Noteworthy changes in version 2.0.10 (2009-01-12)
    the installation directory to %CSIDL_COMMON_APPDATA%/GNU/etc/gnupg.
 
  * [w32] The gnupg2.nls directory is not anymore used.  The standard
-   locale directory is now used.  
+   locale directory is now used.
 
  * [w32] Fixed a race condition between gpg and gpgsm in the use of
    temporary file names.
@@ -228,7 +230,7 @@ Noteworthy changes in version 2.0.8 (2007-12-20)
  * The envvars XAUTHORITY and PINENTRY_USER_DATA are now passed to the
    Pinentry.
 
- * Fixed the auto creation of the key stub for smartcards.  
+ * Fixed the auto creation of the key stub for smartcards.
 
  * Fixed a rare bug in decryption using the OpenPGP card.
 
@@ -270,7 +272,7 @@ Noteworthy changes in version 2.0.6 (2007-08-16)
 
  * GPGSM does now grok --default-key.
 
- * GPGCONF is now aware of --default-key and --encrypt-to. 
+ * GPGCONF is now aware of --default-key and --encrypt-to.
 
  * GPGSM does again correctly print the serial number as well the the
    various keyids.  This was broken since 2.0.4.
@@ -279,7 +281,7 @@ Noteworthy changes in version 2.0.6 (2007-08-16)
 
  * Improved Windows support.
 
+
 Noteworthy changes in version 2.0.5 (2007-07-05)
 ------------------------------------------------
 
@@ -319,7 +321,7 @@ Noteworthy changes in version 2.0.3 (2007-03-08)
    such messages by default which makes those programs safe again.
    --allow-multiple-messages returns to the old behavior. [CVE-2007-1263].
 
- * New --verify-option show-primary-uid-only. 
+ * New --verify-option show-primary-uid-only.
 
  * gpgconf may now reads a global configuration file to select which
    options are changeable by a frontend.  The new applygnupgdefaults
@@ -483,7 +485,7 @@ Noteworthy changes in version 1.9.21 (2006-06-20)
 
  * Support for the CardMan 4040 PCMCIA reader (Linux 2.6.15 required).
 
- * Scdaemon does not anymore reset cards at the end of a connection. 
+ * Scdaemon does not anymore reset cards at the end of a connection.
 
  * Kludge to allow use of Bundesnetzagentur issued X.509 certificates.
 
@@ -503,7 +505,7 @@ Noteworthy changes in version 1.9.20 (2005-12-20)
 
  * Basic support for qualified signatures.
 
- * New debug tool gpgparsemail. 
+ * New debug tool gpgparsemail.
 
 
 Noteworthy changes in version 1.9.19 (2005-09-12)
index 5368410..d36a3ae 100644 (file)
@@ -1,3 +1,9 @@
+2011-07-21  Werner Koch  <wk@g10code.com>
+
+       * call-dirmngr.c (get_cached_cert, get_cached_cert_data_cb): New.
+       (gpgsm_dirmngr_isvalid): Try to get the only-valid-if-cert-valid
+       certificate from the dirmngr first.
+
 2010-09-16  Werner Koch  <wk@g10code.com>
 
        * certchain.c (gpgsm_walk_cert_chain): Use GPG_ERR_MISSING_ISSUER_CERT.
        * server.c (cmd_encrypt): Ditto.
        (cmd_decrypt, cmd_verify, cmd_import, cmd_genkey): Ditto.
        * call-agent.c (gpgsm_scd_pksign): Ditto.
-       * call-dirmngr.c (release_dirmngr, release_dirmngr2) 
+       * call-dirmngr.c (release_dirmngr, release_dirmngr2)
        (run_command_cb): Ditto.
        * certlist.c (gpgsm_add_cert_to_certlist): Ditto.
        * certchain.c (find_up_dirmngr): Ditto.
 2008-09-03  Werner Koch  <wk@g10code.com>
 
        * sign.c (MY_GCRY_MD_SHA224): New, so that we don't need libgcrypt
-       1.2. 
+       1.2.
 
 2008-08-13  Werner Koch  <wk@g10code.com>
 
        (gpgsm_walk_cert_chain): Use it here.
 
        * gpgsm.c: Add option --no-common-certs-import.
-       
+
        * certchain.c (find_up_dirmngr, find_up, do_validate_chain)
        (check_cert_policy): Be more silent with --quiet.
 
        * server.c (option_handler): Add option allow-pinentry-notify.
        (gpgsm_proxy_pinentry_notify): New.
        * call-agent.c (default_inq_cb): New.
-       (gpgsm_agent_pksign, gpgsm_scd_pksign, gpgsm_agent_readkey) 
-       (gpgsm_agent_istrusted, gpgsm_agent_marktrusted) 
+       (gpgsm_agent_pksign, gpgsm_scd_pksign, gpgsm_agent_readkey)
+       (gpgsm_agent_istrusted, gpgsm_agent_marktrusted)
        (gpgsm_agent_passwd, gpgsm_agent_get_confirmation): Call it.
        (struct cipher_parm_s, struct genkey_parm_s): Add field CTRL.
        (inq_ciphertext_cb): Test keyword and fallback to default_inq_cb.
@@ -554,7 +560,7 @@ h2007-11-22  Werner Koch  <wk@g10code.com>
 
        * gpgsm.c (get_status_string): Remove.
        * gpgsm.h: Include status.h instead of errors.h.
-       
+
 2007-10-19  Werner Koch  <wk@g10code.com>
 
        * qualified.c (gpgsm_qualified_consent): Use i18N-swicth functions.
@@ -568,7 +574,7 @@ h2007-11-22  Werner Koch  <wk@g10code.com>
 
 2007-08-24  Werner Koch  <wk@g10code.com>
 
-       * Makefile.am (common_libs): Swap libkeybox and jnlib. 
+       * Makefile.am (common_libs): Swap libkeybox and jnlib.
 
 2007-08-23  Werner Koch  <wk@g10code.com>
 
@@ -588,7 +594,7 @@ h2007-11-22  Werner Koch  <wk@g10code.com>
 
        * import.c (parse_p12): Use gnupg_tmpfile.
        * export.c (export_p12): Ditto.
-       
+
 2007-08-20  Werner Koch  <wk@g10code.com>
 
        * certreqgen.c (read_parameters): Change FP to an estream_t.
@@ -643,7 +649,7 @@ h2007-11-22  Werner Koch  <wk@g10code.com>
 2007-08-06  Werner Koch  <wk@g10code.com>
 
        Implementation of the chain model.
-       
+
        * gpgsm.h (struct rootca_flags_s): Define new members VALID and
        CHAIN_MODEL.
        * call-agent.c (gpgsm_agent_istrusted): Mark ROOTCA_FLAGS valid.
@@ -695,7 +701,7 @@ h2007-11-22  Werner Koch  <wk@g10code.com>
        when passing an int value.
        * server.c (cmd_encrypt, cmd_decrypt, cmd_verify, cmd_import)
        (cmd_export, cmd_message, cmd_genkey):  Translate file descriptors.
-       
+
 2007-07-05  Werner Koch  <wk@g10code.com>
 
        * Makefile.am (common_libs): Changed order of libs.
@@ -720,7 +726,7 @@ h2007-11-22  Werner Koch  <wk@g10code.com>
 2007-06-24  Werner Koch  <wk@g10code.com>
 
        * gpgsm.c (open_es_fwrite): Avoid the dup by using the new
-       es_fdopen_nc().  
+       es_fdopen_nc().
 
 2007-06-21  Werner Koch  <wk@g10code.com>
 
@@ -823,14 +829,14 @@ h2007-11-22  Werner Koch  <wk@g10code.com>
        the certificate is not available.
 
        * gpgsm.c: Add option --p12-charset.
-       * gpgsm.h (struct opt): Add p12_charset. 
+       * gpgsm.h (struct opt): Add p12_charset.
        * export.c (popen_protect_tool): Use new option.
 
 2007-03-19  Werner Koch  <wk@g10code.com>
 
         Changes to let export and key listing use estream to help systems
        without funopen.
-       
+
        * keylist.c: Use estream in place of stdio functions.
        * gpgsm.c (open_es_fwrite): New.
        (main): Use it for the list commands.
@@ -846,7 +852,7 @@ h2007-11-22  Werner Koch  <wk@g10code.com>
        (print_dn_parts): Ditto.
        * certchain.c (gpgsm_validate_chain): Changed FP to type
        estream_t.
-       (do_list, unknown_criticals, allowed_ca, check_cert_policy) 
+       (do_list, unknown_criticals, allowed_ca, check_cert_policy)
        (is_cert_still_valid): Ditto.
 
        * export.c (gpgsm_export): New arg STREAM.
@@ -948,7 +954,7 @@ h2007-11-22  Werner Koch  <wk@g10code.com>
 
 2006-10-17  Werner Koch  <wk@g10code.com>
 
-       * gpgsm.c: No need for pth.h.  
+       * gpgsm.c: No need for pth.h.
        (main): or to init it. It used to be hack for W32.
 
        * sign.c (gpgsm_get_default_cert): Changed to return only
@@ -956,7 +962,7 @@ h2007-11-22  Werner Koch  <wk@g10code.com>
 
 2006-10-16  Werner Koch  <wk@g10code.com>
 
-       * certchain.c (already_asked_marktrusted) 
+       * certchain.c (already_asked_marktrusted)
        (set_already_asked_marktrusted): New.
        (gpgsm_validate_chain) <not trusted>: Keep track of certificates
        we already asked for.
@@ -988,7 +994,7 @@ h2007-11-22  Werner Koch  <wk@g10code.com>
 
        * certchain.c (gpgsm_validate_chain): More changes for the relax
        feature.  Use certificate reference counting instead of the old
-       explicit tests. Added a missing free. 
+       explicit tests. Added a missing free.
 
 2006-09-25  Werner Koch  <wk@g10code.com>
 
@@ -1039,9 +1045,9 @@ h2007-11-22  Werner Koch  <wk@g10code.com>
 
        Replaced all Assuan error codes by libgpg-error codes.  Removed
        all map_to_assuan_status and map_assuan_err.
-       
+
        * gpgsm.c (main): Call assuan_set_assuan_err_source to have Assuan
-       switch to gpg-error codes.  
+       switch to gpg-error codes.
        * server.c (set_error): Adjusted.
 
 2006-08-29  Werner Koch  <wk@g10code.com>
@@ -1085,7 +1091,7 @@ h2007-11-22  Werner Koch  <wk@g10code.com>
        * keydb.c (keydb_delete): Likewise.  Only unlock if this is set.
        * delete.c (delete_one): Add new argument to invocation of
        keydb_delete.
-       
+
 2006-05-15  Werner Koch  <wk@g10code.com>
 
        * keylist.c (print_names_raw): Sanitize URI.
@@ -1304,7 +1310,7 @@ h2007-11-22  Werner Koch  <wk@g10code.com>
        (run_command_status_cb): Return cancel status if gpgsm_status
        returned an error.
 
-       * server.c (gpgsm_status, gpgsm_status2) 
+       * server.c (gpgsm_status, gpgsm_status2)
        (gpgsm_status_with_err_code): Return an error code.
        (gpgsm_status2): Always call va_end().
 
@@ -1394,7 +1400,7 @@ h2007-11-22  Werner Koch  <wk@g10code.com>
        * Makefile.am: Adjusted for gettext 0.14.
 
        * keylist.c (list_cert_colon): Make sure that the expired flag has
-       a higher precedence than the invalid flag. 
+       a higher precedence than the invalid flag.
 
 2004-09-29  Werner Koch  <wk@g10code.com>
 
@@ -1429,7 +1435,7 @@ h2007-11-22  Werner Koch  <wk@g10code.com>
 
        * certchain.c (gpgsm_basic_cert_check): Print more detailed error
        messages.
-       
+
        * certcheck.c (do_encode_md): Partly support DSA.  Add new arg
        PKALGO. Changed all callers to pass it.
        (pk_algo_from_sexp): New.
@@ -1466,7 +1472,7 @@ h2007-11-22  Werner Koch  <wk@g10code.com>
 2004-06-06  Werner Koch  <wk@gnupg.org>
 
        * certreqgen.c (get_parameter_uint, create_request): Create
-       an extension for key usage when requested. 
+       an extension for key usage when requested.
 
 2004-05-12  Werner Koch  <wk@gnupg.org>
 
@@ -1522,9 +1528,9 @@ h2007-11-22  Werner Koch  <wk@g10code.com>
        * gpgsm.c (main) <gpgconf>: Do not use /dev/null as default config
        filename.
 
-       * call-agent.c (gpgsm_agent_pksign, gpgsm_agent_pkdecrypt) 
-       (gpgsm_agent_genkey, gpgsm_agent_istrusted) 
-       (gpgsm_agent_marktrusted, gpgsm_agent_havekey) 
+       * call-agent.c (gpgsm_agent_pksign, gpgsm_agent_pkdecrypt)
+       (gpgsm_agent_genkey, gpgsm_agent_istrusted)
+       (gpgsm_agent_marktrusted, gpgsm_agent_havekey)
        (gpgsm_agent_passwd): Add new arg CTRL and changed all callers.
        (start_agent): New arg CTRL.  Send progress item when starting a
        new agent.
@@ -1556,7 +1562,7 @@ h2007-11-22  Werner Koch  <wk@g10code.com>
 
 2004-04-08  Werner Koch  <wk@gnupg.org>
 
-       * decrypt.c (gpgsm_decrypt): Return GPG_ERR_NO_DATA if it is not a 
+       * decrypt.c (gpgsm_decrypt): Return GPG_ERR_NO_DATA if it is not a
        encrypted message.
 
 2004-04-07  Werner Koch  <wk@gnupg.org>
@@ -1660,12 +1666,12 @@ h2007-11-22  Werner Koch  <wk@g10code.com>
 
        * export.c (export_p12, popen_protect_tool)
        (gpgsm_p12_export): New.
-       * gpgsm.c (main): New command --export-secret-key-p12. 
+       * gpgsm.c (main): New command --export-secret-key-p12.
 
 2004-02-18  Werner Koch  <wk@gnupg.org>
 
        * gpgsm.c (set_debug): Set the new --debug-level flags.
-       (main): New option --gpgconf-list.  
+       (main): New option --gpgconf-list.
        (main): Do not setup -u and -r keys when not required.
        (main): Setup the used character set.
 
@@ -1687,7 +1693,7 @@ h2007-11-22  Werner Koch  <wk@g10code.com>
        WITH_VALIDATION. Changed callers to set it.
        (list_external_cb, list_external_keys): Pass CTRL to the callback.
        (list_cert_colon): Add arg CTRL.  Check validation if requested.
-       * certchain.c (unknown_criticals, allowed_ca, check_cert_policy) 
+       * certchain.c (unknown_criticals, allowed_ca, check_cert_policy)
        (gpgsm_validate_chain): New args LISTMODE and FP.
        (do_list): New helper for info output.
        (find_up): New arg FIND_NEXT.
@@ -1704,7 +1710,7 @@ h2007-11-22  Werner Koch  <wk@g10code.com>
        * certcheck.c (gpgsm_create_cms_signature): Format a description
        for use by the pinentry.
        * decrypt.c (gpgsm_decrypt): Ditto. Free HEXKEYGRIP.
-       * certdump.c (format_name_cookie, format_name_writer) 
+       * certdump.c (format_name_cookie, format_name_writer)
        (gpgsm_format_name): New.
        (gpgsm_format_serial): New.
        (gpgsm_format_keydesc): New.
@@ -1778,7 +1784,7 @@ h2007-11-22  Werner Koch  <wk@g10code.com>
        (print_dn_part): Do not delimit multiple RDN by " + ".  Handle
        multi-valued RDNs in a special way, i.e. in the order specified by
        the certificate.
-       (print_dn_parts): Simplified. 
+       (print_dn_parts): Simplified.
 
 2004-01-16  Werner Koch  <wk@gnupg.org>
 
@@ -1866,7 +1872,7 @@ h2007-11-22  Werner Koch  <wk@g10code.com>
 2003-08-14  Timo Schulz  <twoaday@freakmail.de>
 
        * encrypt.c (encode_session_key): Use new Libgcrypt interface.
-       
+
 2003-07-31  Werner Koch  <wk@gnupg.org>
 
        * Makefile.am (gpgsm_LDADD): Added INTLLIBS.
@@ -1889,7 +1895,7 @@ h2007-11-22  Werner Koch  <wk@g10code.com>
        * verify.c (strtimestamp): Renamed to strtimestamp_r
 
        Adjusted for changes in the libgcrypt API. Some more fixes for the
-       libgpg-error stuff.  
+       libgpg-error stuff.
 
 2003-06-04  Werner Koch  <wk@gnupg.org>
 
@@ -1918,7 +1924,7 @@ h2007-11-22  Werner Koch  <wk@g10code.com>
 
 2002-11-25  Werner Koch  <wk@gnupg.org>
 
-       * verify.c (gpgsm_verify): Handle content-type attribute. 
+       * verify.c (gpgsm_verify): Handle content-type attribute.
 
 2002-11-13  Werner Koch  <wk@gnupg.org>
 
@@ -1928,7 +1934,7 @@ h2007-11-22  Werner Koch  <wk@g10code.com>
 
 2002-11-12  Werner Koch  <wk@gnupg.org>
 
-       * gpgsm.c: New command --call-dirmngr. 
+       * gpgsm.c: New command --call-dirmngr.
        * call-dirmngr.c (gpgsm_dirmngr_run_command)
        (run_command_inq_cb,run_command_cb)
        (run_command_status_cb): New.
@@ -1946,7 +1952,7 @@ h2007-11-22  Werner Koch  <wk@g10code.com>
 
        * certcheck.c (gpgsm_check_cert_sig): Add cert hash debugging.
 
-       * certchain.c (find_up): Print info when the cert was not found 
+       * certchain.c (find_up): Print info when the cert was not found
        by the autorithyKeyIdentifier.
 
 2002-09-03  Werner Koch  <wk@gnupg.org>
@@ -2020,10 +2026,10 @@ h2007-11-22  Werner Koch  <wk@g10code.com>
        * sign.c (gpgsm_sign): New argument SIGNERLIST and implemt
        multiple signers.
        * gpgsm.c (main): Support more than one -u.
-       
+
        * server.c (cmd_recipient): Return reason code 1 for No_Public_Key
        which is actually what gets returned from add_to_certlist.
-       
+
 2002-07-26  Werner Koch  <wk@gnupg.org>
 
        * certcheck.c (gpgsm_check_cert_sig): Implement proper cleanup.
@@ -2125,7 +2131,7 @@ h2007-11-22  Werner Koch  <wk@g10code.com>
 2002-06-24  Werner Koch  <wk@gnupg.org>
 
        * gpgsm.c: Removed duped help entry for --list-keys.
-       
+
        * gpgsm.c, gpgsm.h: New option --debug-no-path-validation.
 
        * certpath.c (gpgsm_validate_path): Use it here instead of the
@@ -2168,7 +2174,7 @@ h2007-11-22  Werner Koch  <wk@g10code.com>
        * export.c (gpgsm_export): Kludge to export epehmeral certificates.
 
        * gpgsm.c (main): New command --list-external-keys.
-       
+
 2002-06-17  Werner Koch  <wk@gnupg.org>
 
        * certreqgen.c (read_parameters): Improved error handling.
@@ -2190,7 +2196,7 @@ h2007-11-22  Werner Koch  <wk@g10code.com>
        * sign.c (hash_and_copy_data): New.
        (gpgsm_sign): Implemented normal (non-detached) signatures.
        * gpgsm.c (main): Ditto.
-       
+
        * certpath.c (gpgsm_validate_path): Special error handling for
        no policy match.
 
@@ -2198,7 +2204,7 @@ h2007-11-22  Werner Koch  <wk@g10code.com>
 
        * server.c (get_status_string): Add STATUS_ERROR.
 
-       * certpath.c (gpgsm_validate_path): Tweaked the error checking to 
+       * certpath.c (gpgsm_validate_path): Tweaked the error checking to
        return error codes in a more sensitive way.
        * verify.c (gpgsm_verify): Send status TRUST_NEVER also for a bad
        CA certificate and when the certificate has been revoked.  Issue
@@ -2320,7 +2326,7 @@ h2007-11-22  Werner Koch  <wk@g10code.com>
        * export.c: New.
        * gpgsm.c: Add command --export.
        * server.c (cmd_export): New.
-       
+
 2002-03-13  Werner Koch  <wk@gnupg.org>
 
        * decrypt.c (gpgsm_decrypt): Allow multiple recipients.
@@ -2562,10 +2568,10 @@ h2007-11-22  Werner Koch  <wk@g10code.com>
        print the first item.
        * keylist.c (list_cert_colon): Ditto.
        * keydb.c (keydb_search_issuer_sn): Ditto.
-       * decrypt.c (print_integer_sexp): Removed and made callers 
+       * decrypt.c (print_integer_sexp): Removed and made callers
        use gpgsm_dump_serial.
        * verify.c (print_time): Removed, made callers use gpgsm_dump_time.
-       
+
 2001-12-19  Marcus Brinkmann  <marcus@g10code.de>
 
        * call-agent.c (start_agent): Add new argument to assuan_pipe_connect.
@@ -2621,7 +2627,7 @@ h2007-11-22  Werner Koch  <wk@g10code.com>
        * base64.c (base64_reader_cb): Reset the linelen when we need to
        skip the line and adjusted test; I somehow forgot about DeMorgan.
 
-       * server.c (cmd_encrypt,cmd_decrypt,cmd_sign,cmd_verify) 
+       * server.c (cmd_encrypt,cmd_decrypt,cmd_sign,cmd_verify)
        (cmd_import): Close the FDs on success.
        (close_message_fd): New.
        (input_notify): Setting autodetect_encoding to 0 after initializing
@@ -2645,7 +2651,7 @@ h2007-11-22  Werner Koch  <wk@g10code.com>
 
 2001-12-12  Werner Koch  <wk@gnupg.org>
 
-       * gpgsm.c (main): New options --assume-{armor,base64,binary}. 
+       * gpgsm.c (main): New options --assume-{armor,base64,binary}.
        * base64.c (base64_reader_cb): Fixed non-autodetection mode.
 
 2001-12-04  Werner Koch  <wk@gnupg.org>
@@ -2673,7 +2679,7 @@ h2007-11-22  Werner Koch  <wk@g10code.com>
 
        * server.c (rc_to_assuan_status): New.  Use it for all commands.
 
-       
+
  Copyright 2001, 2002, 2003, 2004, 2005, 2006,
           2007, 2008, 2009 Free Software Foundation, Inc.
 
index ba6cf6f..6540a8f 100644 (file)
@@ -1,4 +1,4 @@
-/* call-dirmngr.c - communication with the dromngr 
+/* call-dirmngr.c - communication with the dromngr
  * Copyright (C) 2002, 2003, 2005, 2007, 2008 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
@@ -22,7 +22,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
-#include <unistd.h> 
+#include <unistd.h>
 #include <time.h>
 #include <assert.h>
 #include <ctype.h>
@@ -82,6 +82,13 @@ struct run_command_parm_s {
 };
 
 
+
+static gpg_error_t get_cached_cert (assuan_context_t ctx,
+                                    const unsigned char *fpr,
+                                    ksba_cert_t *r_cert);
+
+
+\f
 /* A simple implementation of a dynamic buffer.  Use init_membuf() to
    create a buffer, put_membuf to append bytes and get_membuf to
    release and return the buffer.  Allocation errors are detected but
@@ -108,7 +115,7 @@ put_membuf (struct membuf *mb, const void *buf, size_t len)
   if (mb->len + len >= mb->size)
     {
       char *p;
-      
+
       mb->size += len + 1024;
       p = xtryrealloc (mb->buf, mb->size);
       if (!p)
@@ -169,7 +176,7 @@ prepare_dirmngr (ctrl_t ctrl, assuan_context_t ctx, gpg_error_t err)
       char *user = server->user ? server->user : "";
       char *pass = server->pass ? server->pass : "";
       char *base = server->base ? server->base : "";
-      
+
       snprintf (line, DIM (line) - 1, "LDAPSERVER %s:%i:%s:%s:%s",
                server->host, server->port, user, pass, base);
       line[DIM (line) - 1] = 0;
@@ -244,7 +251,7 @@ start_dirmngr_ext (ctrl_t ctrl, assuan_context_t *ctx_r)
       if (opt.verbose)
         log_info (_("no running dirmngr - starting `%s'\n"),
                   opt.dirmngr_program);
-      
+
       if (fflush (NULL))
         {
           gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno));
@@ -345,7 +352,7 @@ start_dirmngr (ctrl_t ctrl)
      an error in prepare_dirmngr?  */
   if (!dirmngr_ctx)
     dirmngr_ctx_locked = 0;
-  return err;  
+  return err;
 }
 
 
@@ -441,7 +448,7 @@ inq_certificate (void *opaque, const char *line)
       for (s=line, n=0; n < 40; s++, n++)
         fpr[n] = (*s >= 'a')? (*s & 0xdf): *s;
       fpr[n] = 0;
-      
+
       if (!gpgsm_agent_istrusted (parm->ctrl, NULL, fpr, &rootca_flags))
         rc = assuan_send_data (parm->ctx, "1", 1);
       else
@@ -469,7 +476,7 @@ inq_certificate (void *opaque, const char *line)
                  "is not yet implemented\n");
       rc = gpg_error (GPG_ERR_ASS_UNKNOWN_INQUIRE);
     }
-  else 
+  else
     { /* Send the given certificate. */
       int err;
       ksba_cert_t cert;
@@ -493,7 +500,7 @@ inq_certificate (void *opaque, const char *line)
     }
 
   xfree (ski);
-  return rc; 
+  return rc;
 }
 
 
@@ -617,7 +624,7 @@ gpgsm_dirmngr_isvalid (ctrl_t ctrl,
                          NULL, NULL, NULL, NULL, NULL, NULL);
       did_options = 1;
     }
-  snprintf (line, DIM(line)-1, "ISVALID%s %s", 
+  snprintf (line, DIM(line)-1, "ISVALID%s %s",
             use_ocsp == 2? " --only-ocsp --force-default-responder":"",
             certid);
   line[DIM(line)-1] = 0;
@@ -640,25 +647,29 @@ gpgsm_dirmngr_isvalid (ctrl_t ctrl,
         }
       else
         {
-          KEYDB_HANDLE kh;
           ksba_cert_t rspcert = NULL;
 
-          /* Fixme: First try to get the certificate from the
-             dirmngr's cache - it should be there. */
-          kh = keydb_new (0);
-          if (!kh)
-            rc = gpg_error (GPG_ERR_ENOMEM);
-          if (!rc)
-            rc = keydb_search_fpr (kh, stparm.fpr);
-          if (!rc)
-            rc = keydb_get_cert (kh, &rspcert);
-          if (rc)
+          if (get_cached_cert (dirmngr_ctx, stparm.fpr, &rspcert))
             {
-              log_error ("unable to find the certificate used "
-                         "by the dirmngr: %s\n", gpg_strerror (rc));
-              rc = gpg_error (GPG_ERR_INV_CRL);
+              /* Ooops: Something went wrong getting the certificate
+                 from the dirmngr.  Try our own cert store now.  */
+              KEYDB_HANDLE kh;
+
+              kh = keydb_new (0);
+              if (!kh)
+                rc = gpg_error (GPG_ERR_ENOMEM);
+              if (!rc)
+                rc = keydb_search_fpr (kh, stparm.fpr);
+              if (!rc)
+                rc = keydb_get_cert (kh, &rspcert);
+              if (rc)
+                {
+                  log_error ("unable to find the certificate used "
+                             "by the dirmngr: %s\n", gpg_strerror (rc));
+                  rc = gpg_error (GPG_ERR_INV_CRL);
+                }
+              keydb_release (kh);
             }
-          keydb_release (kh);
 
           if (!rc)
             {
@@ -669,7 +680,7 @@ gpgsm_dirmngr_isvalid (ctrl_t ctrl,
                 {
                   /* Note the no_dirmngr flag: This avoids checking
                      this certificate over and over again. */
-                  rc = gpgsm_validate_chain (ctrl, rspcert, "", NULL, 0, NULL, 
+                  rc = gpgsm_validate_chain (ctrl, rspcert, "", NULL, 0, NULL,
                                              VALIDATE_FLAG_NO_DIRMNGR, NULL);
                   if (rc)
                     {
@@ -791,7 +802,7 @@ pattern_from_strlist (strlist_t names)
     *pattern = 0; /* is empty */
   else
     p[-1] = '\0'; /* remove trailing blank */
-  
+
   return pattern;
 }
 
@@ -828,10 +839,10 @@ lookup_status_cb (void *opaque, const char *line)
    the callback CB which will be passed cert by cert.  Note that CTRL
    is optional.  With CACHE_ONLY the dirmngr will search only its own
    key cache. */
-int 
+int
 gpgsm_dirmngr_lookup (ctrl_t ctrl, strlist_t names, int cache_only,
                       void (*cb)(void*, ksba_cert_t), void *cb_value)
-{ 
+{
   int rc;
   char *pattern;
   char line[ASSUAN_LINELENGTH];
@@ -870,7 +881,7 @@ gpgsm_dirmngr_lookup (ctrl_t ctrl, strlist_t names, int cache_only,
 
       return out_of_core ();
     }
-  snprintf (line, DIM(line)-1, "LOOKUP%s %s", 
+  snprintf (line, DIM(line)-1, "LOOKUP%s %s",
             cache_only? " --cache-only":"", pattern);
   line[DIM(line)-1] = 0;
   xfree (pattern);
@@ -898,6 +909,71 @@ gpgsm_dirmngr_lookup (ctrl_t ctrl, strlist_t names, int cache_only,
 
 
 \f
+static gpg_error_t
+get_cached_cert_data_cb (void *opaque, const void *buffer, size_t length)
+{
+  struct membuf *mb = opaque;
+
+  if (buffer)
+    put_membuf (mb, buffer, length);
+  return 0;
+}
+
+/* Return a certificate from the Directory Manager's cache.  This
+   function only returns one certificate which must be specified using
+   the fingerprint FPR and will be stored at R_CERT.  On error NULL is
+   stored at R_CERT and an error code returned.  Note that the caller
+   must provide the locked dirmngr context CTX. */
+static gpg_error_t
+get_cached_cert (assuan_context_t ctx,
+                 const unsigned char *fpr, ksba_cert_t *r_cert)
+{
+  gpg_error_t err;
+  char line[ASSUAN_LINELENGTH];
+  char hexfpr[2*20+1];
+  struct membuf mb;
+  char *buf;
+  size_t buflen;
+  ksba_cert_t cert;
+
+  *r_cert = NULL;
+
+  bin2hex (fpr, 20, hexfpr);
+  snprintf (line, DIM(line)-1, "LOOKUP --single --cache-only 0x%s", hexfpr);
+
+  init_membuf (&mb, 4096);
+  err = assuan_transact (ctx, line, get_cached_cert_data_cb, &mb,
+                         NULL, NULL, NULL, NULL);
+  buf = get_membuf (&mb, &buflen);
+  if (err)
+    {
+      xfree (buf);
+      return err;
+    }
+  if (!buf)
+    return gpg_error (GPG_ERR_ENOMEM);
+
+  err = ksba_cert_new (&cert);
+  if (err)
+    {
+      xfree (buf);
+      return err;
+    }
+  err = ksba_cert_init_from_mem (cert, buf, buflen);
+  xfree (buf);
+  if (err)
+    {
+      log_error ("failed to parse a certificate: %s\n", gpg_strerror (err));
+      ksba_cert_release (cert);
+      return err;
+    }
+
+  *r_cert = cert;
+  return 0;
+}
+
+
+\f
 /* Run Command helpers*/
 
 /* Fairly simple callback to write all output of dirmngr to stdout. */
@@ -959,7 +1035,7 @@ run_command_inq_cb (void *opaque, const char *line)
       rc = gpg_error (GPG_ERR_ASS_UNKNOWN_INQUIRE);
     }
 
-  return rc; 
+  return rc;
 }
 
 static gpg_error_t
@@ -994,7 +1070,7 @@ run_command_status_cb (void *opaque, const char *line)
 int
 gpgsm_dirmngr_run_command (ctrl_t ctrl, const char *command,
                            int argc, char **argv)
-{ 
+{
   int rc;
   int i;
   const char *s;