From d109441850c873dcced2ea3101314d40d4ea0703 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Tue, 12 Jun 2012 22:59:07 +0100 Subject: [PATCH] Explicitly check for gnutls_certificate_set_key(), separate it from p11-kit Signed-off-by: David Woodhouse --- configure.ac | 2 ++ gnutls.c | 38 ++++++++++++++++++++++---------------- 2 files changed, 24 insertions(+), 16 deletions(-) diff --git a/configure.ac b/configure.ac index 1ab7e41d..0c731aef 100644 --- a/configure.ac +++ b/configure.ac @@ -209,6 +209,8 @@ if test "$with_gnutls" = "yes"; then [AC_DEFINE(HAVE_GNUTLS_CERTIFICATE_SET_X509_SYSTEM_TRUST, 1)], []) AC_CHECK_FUNC(gnutls_pkcs12_simple_parse, [AC_DEFINE(HAVE_GNUTLS_PKCS12_SIMPLE_PARSE, 1)], []) + AC_CHECK_FUNC(gnutls_certificate_set_key, + [AC_DEFINE(HAVE_GNUTLS_CERTIFICATE_SET_KEY, 1)], []) if test "$with_openssl" != "" || test "$with_openssl" = "no"; then AC_CHECK_FUNC(gnutls_session_set_premaster, [have_gnutls_dtls=yes], [have_gnutls_dtls=no]) diff --git a/gnutls.c b/gnutls.c index 83bdf5cb..f673df92 100644 --- a/gnutls.c +++ b/gnutls.c @@ -52,9 +52,6 @@ static P11KitPin *pin_callback(const char *pin_source, P11KitUri *pin_uri, const char *pin_description, P11KitPinFlags flags, void *_vpninfo); -#if GNUTLS_VERSION_MAJOR >= 3 -#define HAVE_P11KIT_AND_GNUTLS_3 -#endif #endif #include "openconnect-internal.h" @@ -431,8 +428,10 @@ static int load_certificate(struct openconnect_info *vpninfo) { gnutls_datum_t fdata; gnutls_x509_privkey_t key = NULL; -#ifdef HAVE_P11KIT +#ifdef HAVE_GNUTLS_CERTIFICATE_SET_KEY gnutls_privkey_t pkey = NULL; +#endif +#ifdef HAVE_P11KIT char *cert_url = (char *)vpninfo->cert; char *key_url = (char *)vpninfo->sslkey; #endif @@ -451,12 +450,6 @@ static int load_certificate(struct openconnect_info *vpninfo) fdata.data = NULL; - if (vpninfo->cert_type == CERT_TYPE_TPM) { - vpn_progress(vpninfo, PRG_ERR, - _("TPM support not available with GnuTLS\n")); - return -EINVAL; - } - key_is_p11 = !strncmp(vpninfo->sslkey, "pkcs11:", 7); cert_is_p11 = !strncmp(vpninfo->cert, "pkcs11:", 7); @@ -511,7 +504,7 @@ static int load_certificate(struct openconnect_info *vpninfo) /* Load certificate(s) first... */ #ifdef HAVE_P11KIT -#ifndef HAVE_P11KIT_AND_GNUTLS_3 +#ifndef HAVE_GNUTLS_CERTIFICATE_SET_KEY if (key_is_p11) { /* With GnuTLS 2.12 we can't *see* the key so we can't do the expiry check or fill in intermediate CAs. */ @@ -528,7 +521,10 @@ static int load_certificate(struct openconnect_info *vpninfo) ret = 0; goto out; } -#endif +#endif /* PKCS#11 for GnuTLS v2.12 */ + + /* GnuTLS 2.12 *can* handle the cert being in PKCS#11, if the key + isn't. Although it's not clear why anyone would ever do that. */ if (cert_is_p11) { vpn_progress(vpninfo, PRG_TRACE, _("Using PKCS#11 certificate %s\n"), cert_url); @@ -551,7 +547,7 @@ static int load_certificate(struct openconnect_info *vpninfo) } goto got_certs; } -#endif +#endif /* HAVE_P11KIT */ vpn_progress(vpninfo, PRG_TRACE, _("Using certificate file %s\n"), vpninfo->cert); @@ -617,7 +613,7 @@ static int load_certificate(struct openconnect_info *vpninfo) goto got_certs; got_certs: /* Now we have the certificate(s) and we're looking for the private key... */ -#ifdef HAVE_P11KIT_AND_GNUTLS_3 +#if defined (HAVE_P11KIT) && defined (HAVE_GNUTLS_CERTIFICATE_SET_KEY) if (key_is_p11) { gnutls_pkcs11_privkey_t p11key = NULL; @@ -692,6 +688,14 @@ static int load_certificate(struct openconnect_info *vpninfo) goto out; } + if (vpninfo->cert_type == CERT_TYPE_TPM || + (vpninfo->cert_type == CERT_TYPE_UNKNOWN && + strstr((char *)fdata.data, "-----BEGIN TSS KEY BLOB-----"))) { + vpn_progress(vpninfo, PRG_ERR, + _("This version of OpenConnect was built without TPM support\n")); + return -EINVAL; + } + gnutls_x509_privkey_init(&key); /* Try PKCS#1 (and PKCS#8 without password) first. GnuTLS doesn't support OpenSSL's old PKCS#1-based encrypted format. We should @@ -874,7 +878,7 @@ static int load_certificate(struct openconnect_info *vpninfo) _("Adding supporting CA '%s'\n"), name); } -#ifdef HAVE_P11KIT_AND_GNUTLS_3 +#if defined(HAVE_GNUTLS_CERTIFICATE_SET_KEY) if (pkey) { /* Ug. If we got a gnutls_privkey_t from PKCS#11 rather than the gnutls_x509_privkey_t that we get from PEM or PKCS#12 files, then @@ -944,9 +948,11 @@ static int load_certificate(struct openconnect_info *vpninfo) gnutls_free(extra_certs); gnutls_free(supporting_certs); gnutls_free(fdata.data); -#ifdef HAVE_P11KIT +#ifdef HAVE_GNUTLS_CERTIFICATE_SET_KEY if (pkey) gnutls_privkey_deinit(pkey); +#endif +#ifdef HAVE_P11KIT if (cert_url != vpninfo->cert) free(cert_url); if (key_url != vpninfo->sslkey)