* certcheck.c: Fixed use of DBG_CRYPTO and DBG_X509.

* certchain.c (gpgsm_basic_cert_check): Dump certificates after a
failed gcry_pk_verify.
(find_up): Do an external lookup also for an authorityKeyIdentifier
lookup. Factored external lookup code out to ..
(find_up_external): .. new.
This commit is contained in:
Werner Koch 2005-03-17 19:10:37 +00:00
parent c6de0c2d4e
commit fde76a2cf8
3 changed files with 98 additions and 55 deletions

View File

@ -1,3 +1,13 @@
2005-03-17 Werner Koch <wk@g10code.com>
* certcheck.c: Fixed use of DBG_CRYPTO and DBG_X509.
* certchain.c (gpgsm_basic_cert_check): Dump certificates after a
failed gcry_pk_verify.
(find_up): Do an external lookup also for an authorityKeyIdentifier
lookup. Factored external lookup code out to ..
(find_up_external): .. new.
2005-03-03 Werner Koch <wk@g10code.com>
* Makefile.am (gpgsm_LDADD): Added PTH_LIBS. Noted by Kazu Yamamoto.
@ -1407,7 +1417,7 @@
* server.c (rc_to_assuan_status): New. Use it for all commands.
Copyright 2001, 2002, 2003 Free Software Foundation, Inc.
Copyright 2001, 2002, 2003, 2004, 2005 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

View File

@ -1,5 +1,5 @@
/* certchain.c - certificate chain validation
* Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
* Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -275,6 +275,69 @@ find_up_store_certs_cb (void *cb_value, ksba_cert_t cert)
}
/* Helper for find_up(). Locate the certificate for ISSUER using an
external lookup. KH is the keydb context we are currently using.
On success 0 is returned and the certificate may be retrieved from
the keydb using keydb_get_cert().*/
static int
find_up_external (KEYDB_HANDLE kh, const char *issuer)
{
int rc;
strlist_t names = NULL;
int count = 0;
char *pattern;
const char *s;
if (opt.verbose)
log_info (_("looking up issuer at external location\n"));
/* The DIRMNGR process is confused about unknown attributes. As a
quick and ugly hack we locate the CN and use the issuer string
starting at this attribite. Fixme: we should have far better
parsing in the dirmngr. */
s = strstr (issuer, "CN=");
if (!s || s == issuer || s[-1] != ',')
s = issuer;
pattern = xtrymalloc (strlen (s)+2);
if (!pattern)
return gpg_error_from_errno (errno);
strcpy (stpcpy (pattern, "/"), s);
add_to_strlist (&names, pattern);
xfree (pattern);
rc = gpgsm_dirmngr_lookup (NULL, names, find_up_store_certs_cb, &count);
free_strlist (names);
if (opt.verbose)
log_info (_("number of issuers matching: %d\n"), count);
if (rc)
{
log_error ("external key lookup failed: %s\n", gpg_strerror (rc));
rc = -1;
}
else if (!count)
rc = -1;
else
{
int old;
/* The issuers are currently stored in the ephemeral key DB, so
we temporary switch to ephemeral mode. */
old = keydb_set_ephemeral (kh, 1);
keydb_search_reset (kh);
rc = keydb_search_subject (kh, issuer);
keydb_set_ephemeral (kh, old);
}
return rc;
}
/* Locate issuing certificate for CERT. ISSUER is the name of the
issuer used as a fallback if the other methods don't work. If
FIND_NEXT is true, the function shall return the next possible
issuer. The certificate itself is not directly returned but a
keydb_get_cert on the keyDb context KH will return it. Returns 0
on success, -1 if not found or an error code. */
static int
find_up (KEYDB_HANDLE kh, ksba_cert_t cert, const char *issuer, int find_next)
{
@ -292,7 +355,7 @@ find_up (KEYDB_HANDLE kh, ksba_cert_t cert, const char *issuer, int find_next)
keydb_search_reset (kh);
/* In case of an error try the ephemeral DB. We can't do
that in find-next mode because we can't keep the search
that in find_next mode because we can't keep the search
state then. */
if (rc == -1 && !find_next)
{
@ -305,7 +368,12 @@ find_up (KEYDB_HANDLE kh, ksba_cert_t cert, const char *issuer, int find_next)
}
keydb_set_ephemeral (kh, old);
}
/* If we didn't found it, try an external lookup. */
if (rc == -1 && opt.auto_issuer_key_retrieve && !find_next)
rc = find_up_external (kh, issuer);
}
/* Print a note so that the user does not feel too helpless when
an issuer certificate was found and gpgsm prints BAD
signature because it is not the correct one. */
@ -315,16 +383,17 @@ find_up (KEYDB_HANDLE kh, ksba_cert_t cert, const char *issuer, int find_next)
gpgsm_dump_serial (authidno);
log_printf ("/");
gpgsm_dump_string (s);
log_printf (") not found\n");
log_printf (") not found using authorityKeyIdentifier\n");
}
else if (rc)
log_error ("failed to find authorityKeyIdentifier: rc=%d\n", rc);
ksba_name_release (authid);
xfree (authidno);
/* Fixme: don't know how to do dirmngr lookup with serial+issuer. */
/* Fixme: There is no way to do an external lookup with
serial+issuer. */
}
if (rc) /* not found via authorithyKeyIdentifier, try regular issuer name */
if (rc) /* Not found via authorithyKeyIdentifier, try regular issuer name. */
rc = keydb_search_subject (kh, issuer);
if (rc == -1 && !find_next)
{
@ -338,51 +407,10 @@ find_up (KEYDB_HANDLE kh, ksba_cert_t cert, const char *issuer, int find_next)
keydb_set_ephemeral (kh, old);
}
/* Still not found. If enabled, try an external lookup. */
if (rc == -1 && opt.auto_issuer_key_retrieve && !find_next)
{
STRLIST names = NULL;
int count = 0;
char *pattern;
const char *s;
if (opt.verbose)
log_info (_("looking up issuer at external location\n"));
/* dirmngr is confused about unknown attributes so as a quick
and ugly hack we locate the CN and use this and the
following. Fixme: we should have far better parsing in the
dirmngr. */
s = strstr (issuer, "CN=");
if (!s || s == issuer || s[-1] != ',')
s = issuer;
rc = find_up_external (kh, issuer);
pattern = xtrymalloc (strlen (s)+2);
if (!pattern)
return OUT_OF_CORE (errno);
strcpy (stpcpy (pattern, "/"), s);
add_to_strlist (&names, pattern);
xfree (pattern);
rc = gpgsm_dirmngr_lookup (NULL, names, find_up_store_certs_cb, &count);
free_strlist (names);
if (opt.verbose)
log_info (_("number of issuers matching: %d\n"), count);
if (rc)
{
log_error ("external key lookup failed: %s\n", gpg_strerror (rc));
rc = -1;
}
else if (!count)
rc = -1;
else
{
int old;
/* The issuers are currently stored in the ephemeral key
DB, so we temporary switch to ephemeral mode. */
old = keydb_set_ephemeral (kh, 1);
keydb_search_reset (kh);
rc = keydb_search_subject (kh, issuer);
keydb_set_ephemeral (kh, old);
}
}
return rc;
}
@ -959,7 +987,7 @@ gpgsm_basic_cert_check (ksba_cert_t cert)
}
else
{
/* find the next cert up the tree */
/* Find the next cert up the tree. */
keydb_search_reset (kh);
rc = find_up (kh, cert, issuer, 0);
if (rc)
@ -990,6 +1018,11 @@ gpgsm_basic_cert_check (ksba_cert_t cert)
{
log_error ("certificate has a BAD signature: %s\n",
gpg_strerror (rc));
if (DBG_X509)
{
gpgsm_dump_cert ("signing issuer", issuer_cert);
gpgsm_dump_cert ("signed subject", cert);
}
rc = gpg_error (GPG_ERR_BAD_CERT);
goto leave;
}

View File

@ -101,7 +101,7 @@ do_encode_md (gcry_md_hd_t md, int algo, int pkalgo, unsigned int nbits,
memcpy ( frame+n, gcry_md_read(md, algo), len ); n += len;
assert ( n == nframe );
}
if (DBG_X509)
if (DBG_CRYPTO)
{
int j;
log_debug ("encoded hash:");
@ -196,7 +196,7 @@ gpgsm_check_cert_sig (ksba_cert_t issuer_cert, ksba_cert_t cert)
ksba_free (p);
return gpg_error (GPG_ERR_BUG);
}
if (DBG_X509)
if (DBG_CRYPTO)
{
int j;
log_debug ("signature value:");
@ -251,7 +251,7 @@ gpgsm_check_cert_sig (ksba_cert_t issuer_cert, ksba_cert_t cert)
rc = gcry_pk_verify (s_sig, s_hash, s_pkey);
if (DBG_CRYPTO)
if (DBG_X509)
log_debug ("gcry_pk_verify: %s\n", gpg_strerror (rc));
gcry_md_close (md);
gcry_sexp_release (s_sig);
@ -294,7 +294,7 @@ gpgsm_check_cms_signature (ksba_cert_t cert, ksba_const_sexp_t sigval,
gcry_sexp_release (s_sig);
return gpg_error (GPG_ERR_BUG);
}
if (DBG_X509)
if (DBG_CRYPTO)
log_printhex ("public key: ", p, n);
rc = gcry_sexp_sscan ( &s_pkey, NULL, p, n);
@ -321,7 +321,7 @@ gpgsm_check_cms_signature (ksba_cert_t cert, ksba_const_sexp_t sigval,
gcry_mpi_release (frame);
rc = gcry_pk_verify (s_sig, s_hash, s_pkey);
if (DBG_CRYPTO)
if (DBG_X509)
log_debug ("gcry_pk_verify: %s\n", gpg_strerror (rc));
gcry_sexp_release (s_sig);
gcry_sexp_release (s_hash);