summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjoe <joe@61a7d7f5-40b7-0310-9c16-bb0ea8cb1845>2004-10-04 21:20:31 +0000
committerjoe <joe@61a7d7f5-40b7-0310-9c16-bb0ea8cb1845>2004-10-04 21:20:31 +0000
commite44d925681dfb819b10eef3d32ef9b54636af1f1 (patch)
tree88e37dfb24fadeb261afd908ccffc1d663bce236
parentb32b6401fdbbb484d2ed5e6650125ad169b99fc2 (diff)
downloadneon-e44d925681dfb819b10eef3d32ef9b54636af1f1.tar.gz
Begin integration of GNU TLS support from Aleix Conchillo Flaque:
* macros/neon.m4 (NE_CHECK_OPENSSLVER): Renamed from NE_CHECK_SSLVER. (NEON_SSL): Add detection support for GNU TLS. Define HAVE_GNUTLS or HAVE_OPENSSL as appropriate. * src/ne_utils.c (version_string): Update to include GNU TLS version string. * src/ne_privssl.h (HAVE_GNUTLS): Add alternative private structure definitions. * src/ne_auth.c (get_cnonce): Adjust to use HAVE_OPENSSL rather than NE_HAVE_SSL. * src/ne_gnutls.c: New file. git-svn-id: http://svn.webdav.org/repos/projects/neon/trunk@274 61a7d7f5-40b7-0310-9c16-bb0ea8cb1845
-rw-r--r--AUTHORS1
-rw-r--r--macros/neon.m446
-rw-r--r--src/ne_auth.c6
-rw-r--r--src/ne_gnutls.c423
-rw-r--r--src/ne_privssl.h36
-rw-r--r--src/ne_utils.c13
6 files changed, 504 insertions, 21 deletions
diff --git a/AUTHORS b/AUTHORS
index 4f3c725..1fc4a51 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -3,3 +3,4 @@ Portions are:
Copyright (C) 1999-2000 Tommi Komulainen <Tommi.Komulainen@iki.fi>
Copyright (C) 1999-2000 Peter Boos <pedib@colorfullife.com>
Copyright (C) 1991, 1995, 1996, 1997 Free Software Foundation, Inc.
+Copyright (C) 2004 Aleix Conchillo Flaque <aleix@member.fsf.org>
diff --git a/macros/neon.m4 b/macros/neon.m4
index d077f6b..f037db5 100644
--- a/macros/neon.m4
+++ b/macros/neon.m4
@@ -1,4 +1,5 @@
# Copyright (C) 1998-2004 Joe Orton <joe@manyfish.co.uk> -*- autoconf -*-
+# Copyright (C) 2004 Aleix Conchillo Flaque <aleix@member.fsf.org>
#
# This file is free software; you may copy and/or distribute it with
# or without modifications, as long as this notice is preserved.
@@ -759,9 +760,9 @@ AC_CHECK_FUNCS(snprintf vsnprintf,,[
break
])])
-dnl Usage: NE_CHECK_SSLVER(variable, version-string, version-hex)
+dnl Usage: NE_CHECK_OPENSSLVER(variable, version-string, version-hex)
dnl Define 'variable' to 'yes' if OpenSSL version is >= version-hex
-AC_DEFUN([NE_CHECK_SSLVER], [
+AC_DEFUN([NE_CHECK_OPENSSLVER], [
AC_CACHE_CHECK([OpenSSL version is >= $2], $1, [
AC_EGREP_CPP(good, [#include <openssl/opensslv.h>
#if OPENSSL_VERSION_NUMBER >= $3
@@ -794,17 +795,22 @@ else
fi
fi])
-dnl Check for OpenSSL
+dnl Check for an SSL library (GNU TLS or OpenSSL)
AC_DEFUN([NEON_SSL], [
-AC_ARG_WITH(ssl, AS_HELP_STRING([--with-ssl], [enable OpenSSL support]))
+AC_ARG_WITH(ssl,
+ AS_HELP_STRING([--with-ssl=openssl|gnutls],
+ [enable SSL support (default OpenSSL)]))
AC_ARG_WITH(egd,
[[ --with-egd[=PATH] enable EGD support [using EGD socket at PATH]]])
case $with_ssl in
-yes)
-
+/*)
+ AC_MSG_NOTICE([to use SSL libraries in non-standard locations, try --with-ssl --with-libs=$with_ssl])
+ AC_MSG_ERROR([--with-ssl does not take a path argument])
+ ;;
+yes|openssl)
NE_PKG_CONFIG(NE_SSL, openssl,
[AC_MSG_NOTICE(using SSL library configuration from pkg-config)
CPPFLAGS="$CPPFLAGS ${NE_SSL_CFLAGS}"
@@ -817,13 +823,13 @@ yes)
[AC_MSG_ERROR([OpenSSL headers not found, cannot enable SSL support])])
# Enable EGD support if using 0.9.7 or newer
- NE_CHECK_SSLVER(ne_cv_lib_ssl097, 0.9.7, 0x00907000L)
+ NE_CHECK_OPENSSLVER(ne_cv_lib_ssl097, 0.9.7, 0x00907000L)
if test "$ne_cv_lib_ssl097" = "yes"; then
AC_MSG_NOTICE([OpenSSL >= 0.9.7; EGD support not needed in neon])
NE_ENABLE_SUPPORT(SSL, [SSL support enabled, using OpenSSL (0.9.7 or later)])
else
# Fail if OpenSSL is older than 0.9.6
- NE_CHECK_SSLVER(ne_cv_lib_ssl096, 0.9.6, 0x00906000L)
+ NE_CHECK_OPENSSLVER(ne_cv_lib_ssl096, 0.9.6, 0x00906000L)
if test "$ne_cv_lib_ssl096" != "yes"; then
AC_MSG_ERROR([OpenSSL 0.9.6 or later is required])
fi
@@ -849,8 +855,32 @@ yes)
fi
fi
+ AC_DEFINE([HAVE_OPENSSL], 1, [Define if OpenSSL support is enabled])
NEON_EXTRAOBJS="$NEON_EXTRAOBJS ne_openssl"
;;
+gnutls)
+ AC_PATH_PROG(GNUTLS_CONFIG, libgnutls-config, no)
+
+ if test "$GNUTLS_CONFIG" = "no"; then
+ AC_MSG_ERROR([could not find libgnutls-config in \$PATH])
+ fi
+
+ ne_gnutls_ver=`$GNUTLS_CONFIG --version`
+ case $ne_gnutls_ver in
+ 1.*) ;;
+ *) AC_MSG_ERROR([GNU TLS major version "$ne_gnutls_ver" not supported]) ;;
+ esac
+
+ CPPFLAGS="$CPPFLAGS `$GNUTLS_CONFIG --cflags`"
+
+ AC_CHECK_HEADER([gnutls/gnutls.h],,
+ [AC_MSG_ERROR([could not find gnutls/gnutls.h in include path])])
+
+ NE_ENABLE_SUPPORT(SSL, [SSL support enabled, using GnuTLS $ne_gnutls_ver])
+ NEON_EXTRAOBJS="$NEON_EXTRAOBJS ne_gnutls"
+ NEON_LIBS="$NEON_LIBS `$GNUTLS_CONFIG --libs`"
+ AC_DEFINE([HAVE_GNUTLS], 1, [Define if GnuTLS support is enabled])
+ ;;
*) # Default to off; only create crypto-enabled binaries if requested.
NE_DISABLE_SUPPORT(SSL, [SSL support is not enabled])
NEON_EXTRAOBJS="$NEON_EXTRAOBJS ne_stubssl"
diff --git a/src/ne_auth.c b/src/ne_auth.c
index 52a137c..84eef89 100644
--- a/src/ne_auth.c
+++ b/src/ne_auth.c
@@ -50,7 +50,7 @@
#include <windows.h> /* for GetCurrentThreadId() etc */
#endif
-#ifdef NE_HAVE_SSL
+#ifdef HAVE_OPENSSL
#include <openssl/rand.h>
#endif
@@ -241,7 +241,7 @@ static char *get_cnonce(void)
ne_md5_init_ctx(&hash);
-#ifdef NE_HAVE_SSL
+#ifdef HAVE_OPENSSL
if (RAND_status() == 1 && RAND_pseudo_bytes(data, sizeof data) >= 0)
ne_md5_process_bytes(data, sizeof data, &hash);
else {
@@ -274,7 +274,7 @@ static char *get_cnonce(void)
ne_md5_process_bytes(&pid, sizeof pid, &hash);
}
-#ifdef NE_HAVE_SSL
+#ifdef HAVE_OPENSSL
}
#endif
diff --git a/src/ne_gnutls.c b/src/ne_gnutls.c
new file mode 100644
index 0000000..6b0e551
--- /dev/null
+++ b/src/ne_gnutls.c
@@ -0,0 +1,423 @@
+/*
+ neon SSL/TLS support using GNU TLS
+ Copyright (C) 2002-2004, Joe Orton <joe@manyfish.co.uk>
+ Copyright (C) 2004, Aleix Conchillo Flaque <aleix@member.fsf.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ MA 02111-1307, USA
+
+*/
+
+#include "config.h"
+
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#include <stdio.h>
+
+#include <gnutls/gnutls.h>
+#include <gnutls/pkcs12.h>
+
+#include "ne_ssl.h"
+#include "ne_string.h"
+#include "ne_session.h"
+#include "ne_i18n.h"
+
+#include "ne_private.h"
+#include "ne_privssl.h"
+
+struct ne_ssl_dname_s {
+ char *dn;
+};
+
+struct ne_ssl_certificate_s {
+ ne_ssl_dname subj_dn, issuer_dn;
+ gnutls_x509_crt subject;
+ ne_ssl_certificate *issuer;
+ char *identity;
+};
+
+struct ne_ssl_client_cert_s {
+ gnutls_pkcs12 p12;
+ int decrypted; /* non-zero if successfully decrypted. */
+ ne_ssl_certificate cert;
+ char *friendly_name;
+};
+
+char *ne_ssl_readable_dname(const ne_ssl_dname *name)
+{
+ return name->dn;
+}
+
+int ne_ssl_dname_cmp(const ne_ssl_dname *dn1, const ne_ssl_dname *dn2)
+{
+ return strcmp(dn1->dn, dn2->dn);
+}
+
+void ne_ssl_clicert_free(ne_ssl_client_cert *cc)
+{
+#warning incomplete
+}
+
+void ne_ssl_cert_validity(const ne_ssl_certificate *cert,
+ char *from, char *until)
+{
+ if (from) {
+ time_t t = gnutls_x509_crt_get_activation_time(cert->subject);
+ strftime(from, NE_SSL_VDATELEN, "%b %d %H:%M:%S %Y%Z", localtime(&t));
+ }
+ if (until) {
+ time_t t = gnutls_x509_crt_get_expiration_time(cert->subject);
+ strftime(from, NE_SSL_VDATELEN, "%b %d %H:%M:%S %Y%Z", localtime(&t));
+ }
+}
+
+/* Returns a new buffer with X509 subject's (or issuer) distinguished name. */
+static char *x509_get_dn(gnutls_x509_crt x5, int subject)
+{
+ int ret, len;
+ char *dn;
+
+ if (subject)
+ ret = gnutls_x509_crt_get_dn(x5, NULL, &len);
+ else
+ ret = gnutls_x509_crt_get_issuer_dn(x5, NULL, &len);
+
+ if (ret < 0)
+ return NULL;
+
+ dn = ne_malloc(len);
+ if (subject)
+ gnutls_x509_crt_get_dn(x5, dn, &len);
+ else
+ gnutls_x509_crt_get_issuer_dn(x5, dn, &len);
+
+ return dn;
+}
+
+/* Populate an ne_ssl_certificate structure from an X509 object. */
+static ne_ssl_certificate *populate_cert(ne_ssl_certificate *cert,
+ gnutls_x509_crt x5)
+{
+ cert->subj_dn.dn = x509_get_dn(x5, 1);
+ cert->issuer_dn.dn = x509_get_dn(x5, 0);
+ cert->issuer = NULL;
+ cert->subject = x5;
+ cert->identity = NULL;
+ return cert;
+}
+
+void ne_ssl_set_clicert(ne_session *sess, const ne_ssl_client_cert *cc)
+{
+#warning incomplete
+}
+
+ne_ssl_context *ne_ssl_context_create(void)
+{
+ ne_ssl_context *ctx = ne_malloc(sizeof *ctx);
+
+ gnutls_dh_params_init(&ctx->dh_params);
+ gnutls_dh_params_generate2(ctx->dh_params, 1024);
+
+ gnutls_rsa_params_init(&ctx->rsa_params);
+ gnutls_rsa_params_generate2(ctx->rsa_params, 1024);
+
+ gnutls_certificate_allocate_credentials(&ctx->cred.cert);
+ gnutls_certificate_set_dh_params(ctx->cred.cert, ctx->dh_params);
+ gnutls_certificate_set_rsa_params(ctx->cred.cert, ctx->rsa_params);
+
+ return ctx;
+}
+
+void ne_ssl_context_destroy(ne_ssl_context *ctx)
+{
+ if (ctx->sess)
+ gnutls_deinit(ctx->sess);
+ if (ctx->dh_params)
+ gnutls_dh_params_deinit(ctx->dh_params);
+ if (ctx->rsa_params)
+ gnutls_rsa_params_deinit(ctx->rsa_params);
+ if (ctx->cred.cert)
+ gnutls_certificate_free_credentials(ctx->cred.cert);
+ ne_free(ctx);
+}
+
+/* For internal use only. */
+int ne_negotiate_ssl(ne_request *req)
+{
+ ne_session *sess = ne_get_session(req);
+ ne_ssl_context *ctx = sess->ssl_context;
+ const gnutls_datum *chain;
+ unsigned int chain_size;
+
+ NE_DEBUG(NE_DBG_SSL, "Doing SSL negotiation.\n");
+
+ if (ne_sock_connect_ssl(sess->socket, ctx)) {
+ if (ctx->sess) {
+ /* remove cached session. */
+ gnutls_deinit(ctx->sess);
+ ctx->sess = NULL;
+ }
+ ne_set_error(sess, _("SSL negotiation failed: %s"),
+ ne_sock_error(sess->socket));
+ return NE_ERROR;
+ }
+
+ return NE_OK;
+}
+
+const ne_ssl_dname *ne_ssl_cert_issuer(const ne_ssl_certificate *cert)
+{
+ return &cert->issuer_dn;
+}
+
+const ne_ssl_dname *ne_ssl_cert_subject(const ne_ssl_certificate *cert)
+{
+ return &cert->subj_dn;
+}
+
+const ne_ssl_certificate *ne_ssl_cert_signedby(const ne_ssl_certificate *cert)
+{
+ return cert->issuer;
+}
+
+const char *ne_ssl_cert_identity(const ne_ssl_certificate *cert)
+{
+ return cert->identity;
+}
+
+void ne_ssl_ctx_trustcert(ne_ssl_context *ctx, const ne_ssl_certificate *cert)
+{
+#warning incomplete
+}
+
+void ne_ssl_trust_default_ca(ne_session *sess)
+{
+#warning incomplete
+}
+
+/* Functions from GNU TLS manual examples.
+ *
+ * Helper functions to load a certificate and key
+ * files into memory. They use mmap for simplicity.
+ */
+static gnutls_datum mmap_file(const char* filename)
+{
+ int fd;
+ gnutls_datum mmaped_file = { NULL, 0 };
+ struct stat stat_st;
+ void* ptr;
+
+ fd = open(filename, 0);
+ if (fd == -1)
+ return mmaped_file;
+
+ fstat(fd, &stat_st);
+
+ if ((ptr = mmap(NULL, stat_st.st_size,
+ PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED)
+ return mmaped_file;
+
+ mmaped_file.data = ptr;
+ mmaped_file.size = stat_st.st_size;
+
+ return mmaped_file;
+}
+
+static void munmap_file( gnutls_datum data)
+{
+ munmap(data.data, data.size);
+}
+
+ne_ssl_client_cert *ne_ssl_clicert_read(const char *filename)
+{
+ return NULL;
+}
+
+int ne_ssl_clicert_encrypted(const ne_ssl_client_cert *cc)
+{
+ return !cc->decrypted;
+}
+
+int ne_ssl_clicert_decrypt(ne_ssl_client_cert *cc, const char *password)
+{
+ return 0;
+}
+
+const ne_ssl_certificate *ne_ssl_clicert_owner(const ne_ssl_client_cert *cc)
+{
+ return &cc->cert;
+}
+
+const char *ne_ssl_clicert_name(ne_ssl_client_cert *ccert)
+{
+ return ccert->friendly_name;
+}
+
+ne_ssl_certificate *ne_ssl_cert_read(const char *filename)
+{
+ int ret;
+ gnutls_datum data;
+ gnutls_x509_crt x5;
+
+ data = mmap_file(filename);
+ if (data.data == NULL)
+ return NULL;
+
+ if (gnutls_x509_crt_init(&x5) != 0)
+ return NULL;
+
+ ret = gnutls_x509_crt_import(x5, &data, GNUTLS_X509_FMT_PEM);
+ if (ret < 0) {
+ gnutls_x509_crt_deinit(x5);
+ return NULL;
+ }
+
+ return populate_cert(ne_calloc(sizeof(struct ne_ssl_certificate_s)), x5);
+}
+
+int ne_ssl_cert_write(const ne_ssl_certificate *cert, const char *filename)
+{
+ int ret;
+ unsigned char buffer[10*1024];
+ int len = sizeof buffer;
+
+ FILE *fp = fopen(filename, "w");
+
+ if (fp == NULL) return -1;
+
+ if (gnutls_x509_crt_export(cert->subject, GNUTLS_X509_FMT_PEM, buffer,
+ &len) < 0) {
+ fclose(fp);
+ return -1;
+ }
+
+ if (fwrite(buffer, len, 1, fp) != 1) {
+ fclose(fp);
+ return -1;
+ }
+
+ if (fclose(fp) != 0)
+ return -1;
+
+ return 0;
+}
+
+void ne_ssl_cert_free(ne_ssl_certificate *cert)
+{
+ gnutls_x509_crt_deinit(cert->subject);
+ if (cert->subj_dn.dn) ne_free(cert->subj_dn.dn);
+ if (cert->issuer_dn.dn) ne_free(cert->issuer_dn.dn);
+ if (cert->identity) ne_free(cert->identity);
+
+ if (cert->issuer)
+ ne_ssl_cert_free(cert->issuer);
+ if (cert->identity)
+ ne_free(cert->identity);
+ ne_free(cert);
+}
+
+int ne_ssl_cert_cmp(const ne_ssl_certificate *c1, const ne_ssl_certificate *c2)
+{
+ int ret1, ret2;
+ char digest1[100], digest2[100];
+
+ ret1 = ne_ssl_cert_digest(c1, digest1);
+ ret2 = ne_ssl_cert_digest(c2, digest2);
+
+ if (ret1 < 0 || ret2 < 0)
+ return -1;
+
+ return strcmp(digest1, digest2);
+}
+
+/* The certificate import/export format is the base64 encoding of the
+ * raw DER; PEM without the newlines and wrapping. */
+
+ne_ssl_certificate *ne_ssl_cert_import(const char *data)
+{
+ int ret;
+ size_t len;
+ unsigned char *der;
+ gnutls_datum buffer = { NULL, 0 };
+ gnutls_x509_crt x5;
+
+ if (gnutls_x509_crt_init(&x5) != 0)
+ return NULL;
+
+ /* decode the base64 to get the raw DER representation */
+ len = ne_unbase64(data, &der);
+ if (len == 0) return NULL;
+
+ buffer.data = der;
+ buffer.size = len;
+
+ ret = gnutls_x509_crt_import(x5, &buffer, GNUTLS_X509_FMT_PEM);
+ if (ret < 0) {
+ gnutls_x509_crt_deinit(x5);
+ return NULL;
+ }
+
+ return populate_cert(ne_calloc(sizeof(struct ne_ssl_certificate_s)), x5);
+}
+
+char *ne_ssl_cert_export(const ne_ssl_certificate *cert)
+{
+ int ret;
+ unsigned char der[10*1024];
+ int len = sizeof der;
+
+ /* find the length of the DER encoding. */
+ ret = gnutls_x509_crt_export(cert->subject, GNUTLS_X509_FMT_DER, der, &len);
+ if (ret < 0)
+ return NULL;
+
+ return ne_base64(der, len);
+}
+
+int ne_ssl_cert_digest(const ne_ssl_certificate *cert, char *digest)
+{
+ int ret;
+ size_t len;
+ unsigned char *sha1;
+ unsigned int j;
+ char *p;
+
+ ret = gnutls_x509_crt_get_fingerprint(cert->subject, GNUTLS_DIG_SHA,
+ NULL, &len);
+ if (ret < 0 || len != 20)
+ return -1;
+
+ sha1 = (unsigned char*) gnutls_malloc(len);
+ if (sha1 == NULL)
+ return -1;
+
+ gnutls_x509_crt_get_fingerprint(cert->subject, GNUTLS_DIG_SHA,
+ sha1, &len);
+
+ for (j = 0, p = digest; j < 20; j++) {
+ *p++ = NE_HEX2ASC((sha1[j] >> 4) & 0x0f);
+ *p++ = NE_HEX2ASC(sha1[j] & 0x0f);
+ *p++ = ':';
+ }
+
+ *--p = '\0';
+ return 0;
+}
diff --git a/src/ne_privssl.h b/src/ne_privssl.h
index ea3a840..2340c5f 100644
--- a/src/ne_privssl.h
+++ b/src/ne_privssl.h
@@ -1,6 +1,7 @@
/*
SSL interface definitions internal to neon.
- Copyright (C) 2003, Joe Orton <joe@manyfish.co.uk>
+ Copyright (C) 2003, 2004, Joe Orton <joe@manyfish.co.uk>
+ Copyright (C) 2004, Aleix Conchillo Flaque <aleix@member.fsf.org>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
@@ -25,15 +26,15 @@
#ifndef NE_PRIVSSL_H
#define NE_PRIVSSL_H
-/* This is the private interface between ne_socket and ne_openssl. */
+/* This is the private interface between ne_socket, ne_gnutls and
+ * ne_openssl. */
-#ifdef NE_HAVE_SSL
+#include "ne_ssl.h"
-#include <openssl/ssl.h>
+#ifdef HAVE_OPENSSL
-#include "ne_ssl.h"
+#include <openssl/ssl.h>
-/* SSL context */
struct ne_ssl_context_s {
SSL_CTX *ctx;
SSL_SESSION *sess;
@@ -43,6 +44,27 @@ struct ne_ssl_socket_s {
SSL *ssl;
};
-#endif /* NE_HAVE_SSL */
+#endif /* HAVE_OPENSSL */
+
+#ifdef HAVE_GNUTLS
+
+#include <gnutls/gnutls.h>
+
+struct ne_ssl_context_s {
+ gnutls_session sess;
+ gnutls_dh_params dh_params;
+ gnutls_rsa_params rsa_params;
+ /* Use union in case other credentials want to be added
+ * (anonymous, SRP) */
+ union {
+ gnutls_certificate_credentials cert;
+ } cred;
+};
+
+struct ne_ssl_socket_s {
+ gnutls_session sess;
+};
+
+#endif /* HAVE_GNUTLS */
#endif
diff --git a/src/ne_utils.c b/src/ne_utils.c
index 1df2414..9b22f09 100644
--- a/src/ne_utils.c
+++ b/src/ne_utils.c
@@ -34,10 +34,14 @@
#include <zlib.h>
#endif
-#ifdef NE_HAVE_SSL
+#ifdef HAVE_OPENSSL
#include <openssl/opensslv.h>
#endif
+#ifdef HAVE_GNUTLS
+#include <gnutls/gnutls.h>
+#endif
+
/* libxml2: pick up the version string. */
#if defined(HAVE_LIBXML)
#include <libxml/xmlversion.h>
@@ -107,13 +111,16 @@ static const char version_string[] = "neon " NEON_VERSION ": "
#ifdef NE_HAVE_IDNA
", IDNA"
#endif
-#ifdef NE_HAVE_SSL
+#ifdef HAVE_OPENSSL
#ifdef OPENSSL_VERSION_TEXT
", " OPENSSL_VERSION_TEXT
#else
"OpenSSL (unknown version)"
#endif /* OPENSSL_VERSION_TEXT */
-#endif
+#endif /* HAVE_OPENSSL */
+#ifdef HAVE_GNUTLS
+ ", GNU TLS " LIBGNUTLS_VERSION
+#endif /* HAVE_GNUTLS */
"."
;