From: Russ Allbery <rra@debian.org>
Date: Mon, 30 Jun 2008 19:06:34 -0700
Subject: Support GnuTLS via OpenSSL compat library
Detect the GnuTLS OpenSSL compatibility library and probe for a few
small things that it does differently than OpenSSL.
---
configure.in | 18 +++++++++++++-----
src/socket.c | 19 ++++++++++++++-----
src/tfconfig.h.in | 2 ++
3 files changed, 29 insertions(+), 10 deletions(-)
diff --git a/configure.in b/configure.in
index ffed268..e783564 100644
--- a/configure.in
+++ b/configure.in
@@ -294,14 +294,19 @@ if test "$enable_ssl" = "yes"; then
old_CPPFLAGS="$CPPFLAGS"
while true; do
dnl -lssl needs -lcrypto
- dnl Try in default locations first, then /usr/local/ssl
+ dnl Try in default locations first, then /usr/local/ssl, then try the
+ dnl GnuTLS compatibility layer
LIBS="$LIBS -lssl -lcrypto"
AC_MSG_CHECKING([for libcrypto and libssl])
AC_TRY_LINK_FUNC(SSL_new, AC_MSG_RESULT([yes]),
CFLAGS="$CFLAGS -L/usr/local/ssl/lib";
CPPFLAGS="-I/usr/local/ssl/include $CPPFLAGS";
AC_TRY_LINK_FUNC(SSL_new, AC_MSG_RESULT([/usr/local/ssl]),
- AC_MSG_RESULT([no]); break))
+ LIBS="$old_LIBS -lgnutls-openssl"
+ CFLAGS="$old_CFLAGS"
+ CPPFLAGS="$old_CPPFLAGS"
+ AC_TRY_LINK_FUNC(SSL_new, AC_MSG_RESULT([gnutls]),
+ AC_MSG_RESULT([no]); break)))
dnl Red Hat 9 and Yellow Dog Linux have ssl.h in a standard place,
dnl but it depends on krb5.h which isn't in a standard place.
AC_MSG_CHECKING(for ssl kerberos dependency)
@@ -311,9 +316,12 @@ if test "$enable_ssl" = "yes"; then
else
AC_MSG_RESULT([no])
fi
- AC_CHECK_HEADER(openssl/ssl.h, , break)
- AC_DEFINE(HAVE_SSL)
- ok=1
+ AC_CHECK_HEADER(openssl/ssl.h, ok=1,
+ [AC_CHECK_HEADERS([gnutls/openssl.h], [ok=1])])
+ if test "$ok" = "1"; then
+ AC_DEFINE(HAVE_SSL)
+ AC_CHECK_FUNCS(ERR_peek_error)
+ fi
break
done
if test "$ok" = "0"; then
diff --git a/src/socket.c b/src/socket.c
index 6b671cf..f699504 100644
--- a/src/socket.c
+++ b/src/socket.c
@@ -30,8 +30,12 @@ static const char RCSid[] = "$Id: socket.c,v 35004.288 2007/01/13 23:12:39 kkeys
#include <signal.h> /* for killing resolver child process */
#if HAVE_SSL
-# include <openssl/ssl.h>
-# include <openssl/err.h>
+# if HAVE_GNUTLS_OPENSSL_H
+# include <gnutls/openssl.h>
+# else
+# include <openssl/ssl.h>
+# include <openssl/err.h>
+# endif
SSL_CTX *ssl_ctx;
#endif
@@ -532,9 +536,11 @@ static void ssl_io_err(Sock *sock, int ret, int hook)
case SSL_ERROR_WANT_WRITE:
ssl_io_err_hook("SSL", "SSL_ERROR_WANT_WRITE");
break;
+#ifdef SSL_ERROR_WANT_CONNECT
case SSL_ERROR_WANT_CONNECT:
ssl_io_err_hook("SSL", "SSL_ERROR_WANT_CONNECT");
break;
+#endif
case SSL_ERROR_SYSCALL:
if (ret == 0) {
ssl_io_err_hook("SSL/system", "invalid EOF");
@@ -2904,9 +2910,12 @@ static int handle_socket_input(const char *simbuffer, int simlen)
#if HAVE_SSL
if (xsock->ssl) {
count = SSL_read(xsock->ssl, inbuffer, sizeof(inbuffer));
- if (count == 0 &&
- SSL_get_error(xsock->ssl, 0) == SSL_ERROR_SYSCALL &&
- ERR_peek_error() == 0)
+ if (count == 0
+# if HAVE_ERR_PEEK_ERROR
+ && SSL_get_error(xsock->ssl, 0) == SSL_ERROR_SYSCALL &&
+ ERR_peek_error() == 0
+# endif
+ )
{
/* Treat a count of 0 with no errors as a normal EOF */
goto eof;
diff --git a/src/tfconfig.h.in b/src/tfconfig.h.in
index ef9a245..b67bc1f 100644
--- a/src/tfconfig.h.in
+++ b/src/tfconfig.h.in
@@ -37,10 +37,12 @@
#define HAVE_LIBZ 0
#define SOCKS 0
#define HAVE_SSL 0
+#define HAVE_GNUTLS_OPENSSL_H 0
#define HAVE_BCOPY 0
#define HAVE_BZERO 0
#define HAVE_CONNECT 0
+#define HAVE_ERR_PEEK_ERROR 0
#define HAVE_FILENO 0
#define HAVE_GETCWD 0
#define HAVE_GETHOSTBYNAME 0