* 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> 2005-03-03 Werner Koch <wk@g10code.com>
* Makefile.am (gpgsm_LDADD): Added PTH_LIBS. Noted by Kazu Yamamoto. * 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. * 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 This file is free software; as a special exception the author gives
unlimited permission to copy and/or distribute it, with or without unlimited permission to copy and/or distribute it, with or without

View File

@ -1,5 +1,5 @@
/* certchain.c - certificate chain validation /* 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. * 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 static int
find_up (KEYDB_HANDLE kh, ksba_cert_t cert, const char *issuer, int find_next) 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); keydb_search_reset (kh);
/* In case of an error try the ephemeral DB. We can't do /* 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. */ state then. */
if (rc == -1 && !find_next) 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); 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 /* Print a note so that the user does not feel too helpless when
an issuer certificate was found and gpgsm prints BAD an issuer certificate was found and gpgsm prints BAD
signature because it is not the correct one. */ 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); gpgsm_dump_serial (authidno);
log_printf ("/"); log_printf ("/");
gpgsm_dump_string (s); gpgsm_dump_string (s);
log_printf (") not found\n"); log_printf (") not found using authorityKeyIdentifier\n");
} }
else if (rc) else if (rc)
log_error ("failed to find authorityKeyIdentifier: rc=%d\n", rc); log_error ("failed to find authorityKeyIdentifier: rc=%d\n", rc);
ksba_name_release (authid); ksba_name_release (authid);
xfree (authidno); 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); rc = keydb_search_subject (kh, issuer);
if (rc == -1 && !find_next) 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); keydb_set_ephemeral (kh, old);
} }
/* Still not found. If enabled, try an external lookup. */
if (rc == -1 && opt.auto_issuer_key_retrieve && !find_next) if (rc == -1 && opt.auto_issuer_key_retrieve && !find_next)
{ rc = find_up_external (kh, issuer);
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;
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; return rc;
} }
@ -959,7 +987,7 @@ gpgsm_basic_cert_check (ksba_cert_t cert)
} }
else else
{ {
/* find the next cert up the tree */ /* Find the next cert up the tree. */
keydb_search_reset (kh); keydb_search_reset (kh);
rc = find_up (kh, cert, issuer, 0); rc = find_up (kh, cert, issuer, 0);
if (rc) if (rc)
@ -990,6 +1018,11 @@ gpgsm_basic_cert_check (ksba_cert_t cert)
{ {
log_error ("certificate has a BAD signature: %s\n", log_error ("certificate has a BAD signature: %s\n",
gpg_strerror (rc)); 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); rc = gpg_error (GPG_ERR_BAD_CERT);
goto leave; 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; memcpy ( frame+n, gcry_md_read(md, algo), len ); n += len;
assert ( n == nframe ); assert ( n == nframe );
} }
if (DBG_X509) if (DBG_CRYPTO)
{ {
int j; int j;
log_debug ("encoded hash:"); log_debug ("encoded hash:");
@ -196,7 +196,7 @@ gpgsm_check_cert_sig (ksba_cert_t issuer_cert, ksba_cert_t cert)
ksba_free (p); ksba_free (p);
return gpg_error (GPG_ERR_BUG); return gpg_error (GPG_ERR_BUG);
} }
if (DBG_X509) if (DBG_CRYPTO)
{ {
int j; int j;
log_debug ("signature value:"); 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); 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)); log_debug ("gcry_pk_verify: %s\n", gpg_strerror (rc));
gcry_md_close (md); gcry_md_close (md);
gcry_sexp_release (s_sig); 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); gcry_sexp_release (s_sig);
return gpg_error (GPG_ERR_BUG); return gpg_error (GPG_ERR_BUG);
} }
if (DBG_X509) if (DBG_CRYPTO)
log_printhex ("public key: ", p, n); log_printhex ("public key: ", p, n);
rc = gcry_sexp_sscan ( &s_pkey, NULL, 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); gcry_mpi_release (frame);
rc = gcry_pk_verify (s_sig, s_hash, s_pkey); 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)); log_debug ("gcry_pk_verify: %s\n", gpg_strerror (rc));
gcry_sexp_release (s_sig); gcry_sexp_release (s_sig);
gcry_sexp_release (s_hash); gcry_sexp_release (s_hash);