dirmngr (10 files)
cvs user wk
cvs at cvs.gnupg.org
Mon Apr 18 12:21:14 CEST 2005
Date: Monday, April 18, 2005 @ 12:37:53
Author: wk
Path: /cvs/dirmngr/dirmngr
Modified: ChangeLog NEWS configure.ac src/ChangeLog src/certcache.c
src/certcache.h src/crlcache.c src/dirmngr.h src/server.c
src/validate.c
* configure.ac: Require libksba 0.9.11.
* certcache.c (find_issuing_cert): Fixed last resort method which
should be finding by subject and not by issuer. Try to locate it
also using the keyIdentifier method. Improve error reporting.
(cmp_simple_canon_sexp): New.
(find_cert_bysubject): New.
(find_cert_bysn): Ask back to the caller before trying an extarnl
lookup.
* server.c (get_cert_local_ski): New.
* crlcache.c (crl_parse_insert): Also try to locate issuer
certificate using the keyIdentifier. Improved error reporting.
-----------------+
ChangeLog | 4 +
NEWS | 4 +
configure.ac | 2
src/ChangeLog | 15 +++-
src/certcache.c | 199 ++++++++++++++++++++++++++++++++++++++++++++++++++----
src/certcache.h | 12 +++
src/crlcache.c | 29 ++++++-
src/dirmngr.h | 2
src/server.c | 79 ++++++++++++++++++++-
src/validate.c | 2
10 files changed, 322 insertions(+), 26 deletions(-)
Index: dirmngr/ChangeLog
diff -u dirmngr/ChangeLog:1.86 dirmngr/ChangeLog:1.87
--- dirmngr/ChangeLog:1.86 Tue Feb 8 12:30:41 2005
+++ dirmngr/ChangeLog Mon Apr 18 12:37:53 2005
@@ -1,3 +1,7 @@
+2005-04-18 Werner Koch <wk at g10code.com>
+
+ * configure.ac: Require libksba 0.9.11.
+
2005-02-08 Werner Koch <wk at g10code.com>
Released 0.9.1.
Index: dirmngr/NEWS
diff -u dirmngr/NEWS:1.36 dirmngr/NEWS:1.37
--- dirmngr/NEWS:1.36 Tue Feb 8 12:41:46 2005
+++ dirmngr/NEWS Mon Apr 18 12:37:53 2005
@@ -1,6 +1,10 @@
Noteworthy changes in version 0.9.2
------------------------------------------------
+ * Make use of authorityKeyidentifier.keyIdentifier.
+
+ * Fixed a possible hang in the LDAP lookup code.
+
Noteworthy changes in version 0.9.1 (2005-02-08)
------------------------------------------------
Index: dirmngr/configure.ac
diff -u dirmngr/configure.ac:1.71 dirmngr/configure.ac:1.72
--- dirmngr/configure.ac:1.71 Tue Feb 8 12:41:46 2005
+++ dirmngr/configure.ac Mon Apr 18 12:37:53 2005
@@ -31,7 +31,7 @@
NEED_LIBASSUAN_VERSION=0.6.8
-NEED_KSBA_VERSION=0.9.6
+NEED_KSBA_VERSION=0.9.11
PACKAGE=$PACKAGE_NAME
Index: dirmngr/src/ChangeLog
diff -u dirmngr/src/ChangeLog:1.46 dirmngr/src/ChangeLog:1.47
--- dirmngr/src/ChangeLog:1.46 Thu Apr 14 13:58:29 2005
+++ dirmngr/src/ChangeLog Mon Apr 18 12:37:53 2005
@@ -1,10 +1,23 @@
+2005-04-18 Werner Koch <wk at g10code.com>
+
+ * certcache.c (find_issuing_cert): Fixed last resort method which
+ should be finding by subject and not by issuer. Try to locate it
+ also using the keyIdentifier method. Improve error reporting.
+ (cmp_simple_canon_sexp): New.
+ (find_cert_bysubject): New.
+ (find_cert_bysn): Ask back to the caller before trying an extarnl
+ lookup.
+ * server.c (get_cert_local_ski): New.
+ * crlcache.c (crl_parse_insert): Also try to locate issuer
+ certificate using the keyIdentifier. Improved error reporting.
+
2005-04-14 Werner Koch <wk at g10code.com>
* ldap.c (start_cert_fetch_ldap): Really return ERR.
2005-03-17 Werner Koch <wk at g10code.com>
- * http.c (parse_response): Changed MAXLEN and LEN to size-t to
+ * http.c (parse_response): Changed MAXLEN and LEN to size_t to
match the requirement of read_line.
* http.h (http_context_s): Ditto for BUFFER_SIZE.
Index: dirmngr/src/certcache.c
diff -u dirmngr/src/certcache.c:1.9 dirmngr/src/certcache.c:1.10
--- dirmngr/src/certcache.c:1.9 Tue Feb 1 17:49:15 2005
+++ dirmngr/src/certcache.c Mon Apr 18 12:37:53 2005
@@ -39,10 +39,10 @@
#define MAX_EXTRA_CACHED_CERTS 1000
-/* A certificate cache item. This consists of a the ksba cert object
+/* A certificate cache item. This consists of a the KSBA cert object
and some meta data for easier lookup. We use a hash table to keep
- track of all items and use sue the randomly distributed first byte
- of the fingerprint directly as the hash which makes it pretty easy. */
+ track of all items and use the (randomly distributed) first byte of
+ the fingerprint directly as the hash which makes it pretty easy. */
struct cert_item_s
{
struct cert_item_s *next; /* Next item with the same hash value. */
@@ -138,6 +138,14 @@
return !!n_a;
}
+/* An alias for the above function to be used with S-expressions
+ similar to serial numbers. */
+int
+cmp_simple_canon_sexp (ksba_sexp_t a, ksba_sexp_t b)
+{
+ return compare_serialno (a, b);
+}
+
/* Compute the fingerprint of the certificate CERT and put it into
the 20 bytes large buffer DIGEST. Return address of this buffer. */
@@ -589,7 +597,7 @@
}
-/* Return the certificate matching SUBJEC_DN. SEQ should initially be
+/* Return the certificate matching SUBJECT_DN. SEQ should initially be
set to 0 and bumped up to get the next subject with that DN. */
ksba_cert_t
get_cert_bysubject (const char *subject_dn, unsigned int seq)
@@ -630,6 +638,36 @@
cert = get_cert_bysn (issuer_dn, serialno);
+ if (!cert)
+ {
+ char *hexsn, *buf;
+ /* Ask back to the service requester to return the certificate.
+ This is because we can assume that he already used the
+ certificate while checking for the CRL. */
+ hexsn = serial_hex (serialno);
+ if (!hexsn)
+ {
+ log_debug ("serial_hex() failed\n");
+ return NULL;
+ }
+ buf = xtrymalloc (1 + strlen (hexsn) + 1 + strlen (issuer_dn) + 1);
+ if (!buf)
+ {
+ log_error ("can't allocate enough memory: %s\n", strerror (errno));
+ xfree (hexsn);
+ return NULL;
+ }
+ strcpy (stpcpy (stpcpy (stpcpy (buf, "#"), hexsn),"/"), issuer_dn);
+ xfree (hexsn);
+ cert = get_cert_local (ctrl, buf);
+ xfree (buf);
+ if (cert)
+ {
+ cache_cert (cert);
+ return cert; /* Done. */
+ }
+ }
+
while (!cert)
{
ksba_sexp_t sn;
@@ -694,6 +732,119 @@
return cert;
}
+/* Return the certificate matching SUBJECT_DN and (if not NULL)
+ KEYID. If it is not already in the cache, try to find it from other
+ resources. Note, that the external search does not work for user
+ certificates because the LDAP lookup is on the caCertificate
+ attribute. For our purposes this is just fine. */
+ksba_cert_t
+find_cert_bysubject (ctrl_t ctrl, const char *subject_dn, ksba_sexp_t keyid)
+{
+ gpg_error_t err;
+ int seq;
+ ksba_cert_t cert = NULL;
+ cert_fetch_context_t context = NULL;
+ ksba_sexp_t subj;
+
+ for (seq=0; (cert = get_cert_bysubject (subject_dn, seq)); seq++)
+ {
+ if (!keyid)
+ break; /* No keyid requested, so return the first one found. */
+ if (!ksba_cert_get_subj_key_id (cert, NULL, &subj)
+ && !cmp_simple_canon_sexp (keyid, subj))
+ {
+ xfree (subj);
+ break; /* Found matching cert. */
+ }
+ xfree (subj);
+ ksba_cert_release (cert);
+ }
+
+ if (!cert)
+ {
+ /* Ask back to the service requester to return the certificate.
+ This is because we can assume that he already used the
+ certificate while checking for the CRL. */
+ cert = get_cert_local_ski (ctrl, subject_dn, keyid);
+ if (cert)
+ {
+ cache_cert (cert);
+ return cert; /* Done. */
+ }
+ }
+
+
+ while (!cert)
+ {
+ char *subjdn;
+
+ if (!context)
+ {
+ err = ca_cert_fetch (ctrl, &context, subject_dn);
+ if (err)
+ {
+ log_error (_("error fetching certificate by subject: %s\n"),
+ gpg_strerror (err));
+ break;
+ }
+ }
+
+ err = fetch_next_ksba_cert (context, &cert);
+ if (err)
+ {
+ log_error (_("error fetching certificate by subject: %s\n"),
+ gpg_strerror (err) );
+ break;
+ }
+
+ subjdn = ksba_cert_get_subject (cert, 0);
+ if (strcmp (subject_dn, subjdn))
+ {
+ log_info ("find_cert_bysubject: subject DN does not match\n");
+ ksba_cert_release (cert);
+ cert = NULL;
+ ksba_free (subjdn);
+ continue;
+ }
+
+
+ if (DBG_LOOKUP)
+ {
+ log_debug (" considering certificate (/");
+ dump_string (subjdn);
+ log_printf (")\n");
+ }
+ ksba_free (subjdn);
+
+ if (!keyid)
+ {
+ cache_cert (cert);
+ if (DBG_LOOKUP)
+ log_debug (" found\n");
+ break; /* Ready. */
+ }
+
+ if (!ksba_cert_get_subj_key_id (cert, NULL, &subj))
+ {
+ if (!cmp_simple_canon_sexp (keyid, subj))
+ {
+ ksba_free (subj);
+ cache_cert (cert);
+ if (DBG_LOOKUP)
+ log_debug (" found\n");
+ break; /* Ready. */
+ }
+ }
+
+ ksba_free (subj);
+ ksba_cert_release (cert);
+ cert = NULL;
+ }
+
+ end_cert_fetch (context);
+ return cert;
+}
+
/* Return 0 if the certificate is a trusted certificate. Returns
@@ -735,6 +886,7 @@
ksba_cert_t issuer_cert = NULL;
ksba_name_t authid;
ksba_sexp_t authidno;
+ ksba_sexp_t keyid;
*r_cert = NULL;
@@ -748,7 +900,7 @@
/* First we need to check whether we can return that certificate
using the authorithyKeyIdentifier. */
- err = ksba_cert_get_auth_key_id (cert, NULL, &authid, &authidno);
+ err = ksba_cert_get_auth_key_id (cert, &keyid, &authid, &authidno);
if (err)
{
log_info (_("error getting authorityKeyIdentifier: %s\n"),
@@ -761,27 +913,46 @@
{
issuer_cert = find_cert_bysn (ctrl, s, authidno);
}
+ if (!issuer_cert && keyid)
+ {
+ /* Not found by issuer+s/n. Now that we have an AKI
+ keyIdentifier look for a certificate with a matching
+ SKI. */
+ issuer_cert = find_cert_bysubject (ctrl, issuer_dn, keyid);
+ }
/* 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. */
if (!issuer_cert)
{
- log_info ("issuer certificate (#");
- dump_serial (authidno);
- log_printf ("/");
- dump_string (s);
- log_printf (") not found\n");
+ log_info ("issuer certificate ");
+ if (keyid)
+ {
+ log_printf ("{");
+ dump_serial (keyid);
+ log_printf ("} ");
+ }
+ if (authidno)
+ {
+ log_printf ("(#");
+ dump_serial (authidno);
+ log_printf ("/");
+ dump_string (s);
+ log_printf (") ");
+ }
+ log_printf ("not found using authorityKeyIdentifier\n");
}
ksba_name_release (authid);
xfree (authidno);
+ xfree (keyid);
}
- /* If this did not work, try just with the issuer's name. */
+ /* If this did not work, try just with the issuer's name and assume
+ that there is only one such certificate. We only look into our
+ cache then. */
if (err || !issuer_cert)
{
- /* FIXME: we need to save a sequence number here for later
- tries. */
- issuer_cert = get_cert_byissuer (issuer_dn, 0);
+ issuer_cert = get_cert_bysubject (issuer_dn, 0);
}
leave:
Index: dirmngr/src/certcache.h
diff -u dirmngr/src/certcache.h:1.7 dirmngr/src/certcache.h:1.8
--- dirmngr/src/certcache.h:1.7 Tue Feb 1 17:49:15 2005
+++ dirmngr/src/certcache.h Mon Apr 18 12:37:53 2005
@@ -34,6 +34,9 @@
the 20 bytes large buffer DIGEST. Return address of this buffer. */
unsigned char *cert_compute_fpr (ksba_cert_t cert, unsigned char *digest);
+/* Compare two simple S-exprerssions A and B and return 0 if they match. */
+int cmp_simple_canon_sexp (ksba_sexp_t a, ksba_sexp_t b);
+
/* Put CERT into the certificate cache. */
gpg_error_t cache_cert (ksba_cert_t cert);
@@ -72,6 +75,15 @@
ksba_cert_t find_cert_bysn (ctrl_t ctrl,
const char *issuer_dn, ksba_sexp_t serialno);
+
+/* Return the certificate matching SUBJECT_DN and (if not NULL) KEYID. If
+ it is not already in the cache, try to find it from other
+ resources. Note, that the external search does not work for user
+ certificates because the LDAP lookup is on the caCertificate
+ attribute. For our purposes this is just fine. */
+ksba_cert_t find_cert_bysubject (ctrl_t ctrl,
+ const char *subject_dn, ksba_sexp_t keyid);
+
/* Given the certificate CERT locate the issuer for this certificate
and return it at R_CERT. Returns 0 on success or
GPG_ERR_NOT_FOUND. */
Index: dirmngr/src/crlcache.c
diff -u dirmngr/src/crlcache.c:1.53 dirmngr/src/crlcache.c:1.54
--- dirmngr/src/crlcache.c:1.53 Tue Feb 1 17:49:15 2005
+++ dirmngr/src/crlcache.c Mon Apr 18 12:37:53 2005
@@ -1674,6 +1674,7 @@
char *crlissuer;
ksba_name_t authid;
ksba_sexp_t authidsn;
+ ksba_sexp_t keyid;
/* We need to look for the issuer only after having read
all items. The issuer itselfs comes before the items
@@ -1690,7 +1691,7 @@
*r_crlissuer = crlissuer; /* (Do it here so we don't need
to free it later) */
- if (!ksba_crl_get_auth_key_id (crl, NULL, &authid, &authidsn))
+ if (!ksba_crl_get_auth_key_id (crl, &keyid, &authid, &authidsn))
{
const char *s;
@@ -1701,16 +1702,32 @@
s = ksba_name_enum (authid, 0);
if (s && *authidsn)
crlissuer_cert = get_crlissuer_cert_bysn (ctrl, s, authidsn);
+ if (!crlissuer_cert && keyid)
+ crlissuer_cert = find_cert_bysubject (ctrl,
+ crlissuer, keyid);
+
if (!crlissuer_cert)
{
- log_info ("CRL issuer certificate (#");
- dump_serial (authidsn);
- log_printf ("/");
- dump_string (s);
- log_printf (") not found\n");
+ log_info ("CRL issuer certificate ");
+ if (keyid)
+ {
+ log_printf ("{");
+ dump_serial (keyid);
+ log_printf ("} ");
+ }
+ if (authidsn)
+ {
+ log_printf ("(#");
+ dump_serial (authidsn);
+ log_printf ("/");
+ dump_string (s);
+ log_printf (") ");
+ }
+ log_printf ("not found\n");
}
ksba_name_release (authid);
xfree (authidsn);
+ xfree (keyid);
}
else
crlissuer_cert = get_crlissuer_cert (ctrl, crlissuer);
Index: dirmngr/src/dirmngr.h
diff -u dirmngr/src/dirmngr.h:1.25 dirmngr/src/dirmngr.h:1.26
--- dirmngr/src/dirmngr.h:1.25 Mon Dec 13 16:16:35 2004
+++ dirmngr/src/dirmngr.h Mon Apr 18 12:37:53 2005
@@ -148,6 +148,8 @@
/*-- server.c --*/
ksba_cert_t get_cert_local (ctrl_t ctrl, const char *issuer);
ksba_cert_t get_issuing_cert_local (ctrl_t ctrl, const char *issuer);
+ksba_cert_t get_cert_local_ski (ctrl_t ctrl,
+ const char *name, ksba_sexp_t keyid);
void start_command_handler (int fd);
gpg_error_t dirmngr_status (ctrl_t ctrl, const char *keyword, ...);
gpg_error_t dirmngr_tick (ctrl_t ctrl);
Index: dirmngr/src/server.c
diff -u dirmngr/src/server.c:1.48 dirmngr/src/server.c:1.49
--- dirmngr/src/server.c:1.48 Fri Dec 3 15:42:36 2004
+++ dirmngr/src/server.c Mon Apr 18 12:37:53 2005
@@ -1,6 +1,6 @@
/* dirmngr.c - LDAP access
* Copyright (C) 2002 Klarälvdalens Datakonsult AB
- * Copyright (C) 2003, 2004 g10 Code GmbH
+ * Copyright (C) 2003, 2004, 2005 g10 Code GmbH
*
* This file is part of DirMngr.
*
@@ -39,6 +39,7 @@
#include "ocsp.h"
#include "certcache.h"
#include "validate.h"
+#include "misc.h"
/* To avoid DoS attacks we limit the size of a certificate to
something reasonable. */
@@ -128,7 +129,8 @@
xfree (buf);
if (rc)
{
- log_error (_("assuan_inquire failed: %s\n"), assuan_strerror (rc));
+ log_error (_("assuan_inquire(%s) failed: %s\n"),
+ command, assuan_strerror (rc));
return NULL;
}
@@ -171,12 +173,13 @@
return do_get_cert_local (ctrl, name, "SENDCERT");
}
-
+
/* Ask back to return the issuing certificate for name, given as a
regular gpgsm certificate indentificates (e.g. fingerprint or one
of the other methods). Alternatively, NULL may be used for NAME to
return thecurrent target certificate. Either return the certificate
in a KSBA object or NULL if it is not available.
+
*/
ksba_cert_t
get_issuing_cert_local (ctrl_t ctrl, const char *name)
@@ -189,6 +192,76 @@
return do_get_cert_local (ctrl, name, "SENDISSUERCERT");
}
+/* Ask back to return a certificate with subject NAME and a
+ subjectKeyIdentifier of KEYID. */
+ksba_cert_t
+get_cert_local_ski (ctrl_t ctrl, const char *name, ksba_sexp_t keyid)
+{
+ unsigned char *value;
+ size_t valuelen;
+ int rc;
+ char *buf;
+ ksba_cert_t cert;
+ char *hexkeyid;
+
+ if (!ctrl || !ctrl->server_local->assuan_ctx)
+ {
+ log_debug ("get_cert_local_ski called w/o context\n");
+ return NULL;
+ }
+ if (!name || !keyid)
+ {
+ log_debug ("get_cert_local_ski called with insufficient arguments\n");
+ return NULL;
+ }
+
+ hexkeyid = serial_hex (keyid);
+ if (!hexkeyid)
+ {
+ log_debug ("serial_hex() failed\n");
+ return NULL;
+ }
+
+ buf = xtrymalloc (15 + strlen (hexkeyid) + 2 + strlen(name) + 1);
+ if (!buf)
+ {
+
+ log_error ("can't allocate enough memory: %s\n", strerror (errno));
+ xfree (hexkeyid);
+ return NULL;
+ }
+ strcpy (stpcpy (stpcpy (stpcpy (buf, "SENDCERT_SKI "), hexkeyid)," /"),name);
+ xfree (hexkeyid);
+
+ rc = assuan_inquire (ctrl->server_local->assuan_ctx, buf,
+ &value, &valuelen, MAX_CERT_LENGTH);
+ xfree (buf);
+ if (rc)
+ {
+ log_error (_("assuan_inquire(%s) failed: %s\n"), "SENDCERT_SKI",
+ assuan_strerror (rc));
+ return NULL;
+ }
+
+ if (!valuelen)
+ {
+ xfree (value);
+ return NULL;
+ }
+
+ rc = ksba_cert_new (&cert);
+ if (!rc)
+ {
+ rc = ksba_cert_init_from_mem (cert, value, valuelen);
+ if (rc)
+ {
+ ksba_cert_release (cert);
+ cert = NULL;
+ }
+ }
+ xfree (value);
+ return cert;
+}
Index: dirmngr/src/validate.c
diff -u dirmngr/src/validate.c:1.7 dirmngr/src/validate.c:1.8
--- dirmngr/src/validate.c:1.7 Wed Dec 15 23:11:59 2004
+++ dirmngr/src/validate.c Mon Apr 18 12:37:53 2005
@@ -471,7 +471,7 @@
}
/* Now check the signature of the certificate. Well, we
- shouldnot delay this until later so that faked certificates
+ should delay this until later so that faked certificates
can't be turned into a DoS easily. */
err = check_cert_sig (issuer_cert, subject_cert);
if (err)
More information about the Gnupg-commits
mailing list