Skip to content

Commit

Permalink
Include supporting certificates from PKCS#11 tokens
Browse files Browse the repository at this point in the history
Sometimes, we really need to include the supporting CA on the wire, and
it is only found in the PKCS#11 alongside the user's own certificate.

Seen with the Belgian eID devices, and a server which didn't appear to
know the 'Citizen CA' for itself, but did trust 'Belguim Root CA2'.

Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
  • Loading branch information
David Woodhouse authored and David Woodhouse committed Nov 15, 2013
1 parent 04ccc26 commit b06b862
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 14 deletions.
2 changes: 2 additions & 0 deletions configure.ac
Expand Up @@ -254,6 +254,8 @@ if test "$with_gnutls" = "yes"; then
CFLAGS="$CFLAGS $GNUTLS_CFLAGS"
AC_CHECK_FUNC(gnutls_dtls_set_data_mtu,
[AC_DEFINE(HAVE_GNUTLS_DTLS_SET_DATA_MTU, 1)], [])
AC_CHECK_FUNC(gnutls_pkcs11_get_raw_issuer,
[AC_DEFINE(HAVE_GNUTLS_PKCS11_GET_RAW_ISSUER, 1)], [])
AC_CHECK_FUNC(gnutls_certificate_set_x509_system_trust,
[AC_DEFINE(HAVE_GNUTLS_CERTIFICATE_SET_X509_SYSTEM_TRUST, 1)], [])
if test "$ac_cv_func_gnutls_certificate_set_x509_system_trust" != "yes"; then
Expand Down
50 changes: 36 additions & 14 deletions gnutls.c
Expand Up @@ -397,7 +397,8 @@ static int load_pkcs12_certificate(struct openconnect_info *vpninfo,
}

/* Older versions of GnuTLS didn't actually bother to check this, so we'll
do it for them. */
do it for them. Is there a bug reference for this? Or just the git commit
reference (c1ef7efb in master, 5196786c in gnutls_3_0_x-2)? */
static int check_issuer_sanity(gnutls_x509_crt_t cert, gnutls_x509_crt_t issuer)
{
#if GNUTLS_VERSION_NUMBER > 0x300014
Expand Down Expand Up @@ -1475,34 +1476,55 @@ static int load_certificate(struct openconnect_info *vpninfo)
/* Look for it in the system trust cafile too. */
err = gnutls_certificate_get_issuer(vpninfo->https_cred,
last_cert, &issuer, 0);
if (err)
break;

/* The check_issuer_sanity() function works fine as a workaround where
it was used above, but when gnutls_certificate_get_issuer() returns
a bogus cert, there's nothing we can do to fix it up. We don't get
to iterate over all the available certs like we can over our own
list. */
if (check_issuer_sanity(last_cert, issuer)) {
/* Hm, is there a bug reference for this? Or just the git commit
reference (c1ef7efb in master, 5196786c in gnutls_3_0_x-2)? */
if (!err && check_issuer_sanity(last_cert, issuer)) {
vpn_progress(vpninfo, PRG_ERR,
_("WARNING: GnuTLS returned incorrect issuer certs; authentication may fail!\n"));
break;
}
free_issuer = 0;

#if defined(HAVE_P11KIT) && defined(HAVE_GNUTLS_PKCS11_GET_RAW_ISSUER)
if (err && cert_is_p11) {
gnutls_datum_t t;

err = gnutls_pkcs11_get_raw_issuer(cert_url, last_cert, &t, GNUTLS_X509_FMT_DER, 0);
if (!err) {
err = gnutls_x509_crt_init(&issuer);
if (!err) {
err = gnutls_x509_crt_import(issuer, &t, GNUTLS_X509_FMT_DER);
if (err)
gnutls_x509_crt_deinit(issuer);
}
}
if (err) {
vpn_progress(vpninfo, PRG_ERR,
"Got no issuer from PKCS#11\n");
} else {
get_cert_name(issuer, name, sizeof(name));

vpn_progress(vpninfo, PRG_ERR,
_("Got next CA '%s' from PKCS11\n"), name);
}
free_issuer = 1;
gnutls_free(t.data);
}
#endif
if (err)
break;

}

if (issuer == last_cert) {
if (gnutls_x509_crt_check_issuer(issuer, issuer)) {
/* Don't actually include the root CA. If they don't already trust it,
then handing it to them isn't going to help. But don't omit the
original certificate if it's self-signed. */
if (nr_supporting_certs > 1) {
nr_supporting_certs--;
if (free_issuer)
gnutls_x509_crt_deinit(issuer);
}

if (free_issuer)
gnutls_x509_crt_deinit(issuer);
break;
}

Expand Down
1 change: 1 addition & 0 deletions www/changelog.xml
Expand Up @@ -20,6 +20,7 @@
<li>Reduce limit of queued packets on DTLS socket, to fix VoIP latency.</li>
<li>Fix Solaris build breakage due to missing <tt>&amp;lt;string.h&amp;gt;</tt> includes.</li>
<li>Include path in <tt>&amp;lt;group-access&amp;gt;</tt> node.</li>
<li>Include supporting CA certificates from PKCS#11 tokens <i>(with GnuTLS 3.2.7+)</i>.</li>
</ul><br/>
</li>
<li><b><a href="ftp://ftp.infradead.org/pub/openconnect/openconnect-5.01.tar.gz">OpenConnect v5.01</a></b>
Expand Down

0 comments on commit b06b862

Please sign in to comment.