[mod_gnutls] GnuTLS option for TLS (fixes #109)

(experimental)

mod_gnutls supports most ssl.* config options supported by mod_openssl

x-ref:
  "GnuTLS support for the mod_ssl"
  https://redmine.lighttpd.net/issues/109
This commit is contained in:
Glenn Strauss 2020-05-14 02:03:14 -04:00
parent 68d626fa9f
commit bf4054f8ec
16 changed files with 3317 additions and 2 deletions

View File

@ -252,6 +252,7 @@ vars.AddVariables(
BoolVariable('with_memcached', 'enable memcached support', 'no'),
PackageVariable('with_mysql', 'enable mysql support', 'no'),
BoolVariable('with_openssl', 'enable openssl support', 'no'),
PackageVariable('with_gnutls', 'enable GnuTLS support', 'no'),
PackageVariable('with_mbedtls', 'enable mbedTLS support', 'no'),
PackageVariable('with_wolfssl', 'enable wolfSSL support', 'no'),
BoolVariable('with_nettle', 'enable Nettle support', 'no'),
@ -328,6 +329,7 @@ if 1:
LIBDL = '',
LIBFCGI = '',
LIBGDBM = '',
LIBGNUTLS = '',
LIBGSSAPI_KRB5 = '',
LIBKRB5 = '',
LIBLBER = '',
@ -629,6 +631,18 @@ if 1:
LIBCRYPTO = 'nettle',
)
if env['with_gnutls']:
if not autoconf.CheckLibWithHeader('gnutls', 'gnutls/crypto.h', 'C'):
fail("Couldn't find gnutls")
autoconf.env.Append(
CPPFLAGS = [ '-DHAVE_GNUTLS_CRYPTO_H' ],
LIBGNUTLS = 'gnutls',
)
if not autoconf.env.exists('LIBCRYPTO'):
autoconf.env.Append(
LIBCRYPTO = 'gnutls',
)
if env['with_pam']:
if not autoconf.CheckLibWithHeader('pam', 'security/pam_appl.h', 'C'):
fail("Couldn't find pam")

View File

@ -815,6 +815,43 @@ if test "$WITH_NETTLE" != no; then
AC_SUBST([CRYPTO_LIB])
fi
dnl Check for GnuTLS
AC_MSG_NOTICE([----------------------------------------])
AC_MSG_CHECKING([for GnuTLS])
AC_ARG_WITH([gnutls],
AC_HELP_STRING([--with-gnutls@<:@=DIR@:>@],[Include GnuTLS support. DIR points to the installation root. (default no)]),
[WITH_GNUTLS=$withval],
[WITH_GNUTLS=no]
)
if test "$WITH_GNUTLS" != "no"; then
use_gnutls=yes
else
use_gnutls=no
fi
AC_MSG_RESULT([$use_gnutls])
AM_CONDITIONAL(BUILD_WITH_GNUTLS, test ! $WITH_GNUTLS = no)
GNUTLS_CFLAGS=
GNUTLS_LIBS=
if test "x$use_gnutls" = "xyes"; then
if test "$WITH_GNUTLS" != "yes"; then
GNUTLS_CFLAGS="-I$WITH_GNUTLS/include"
GNUTLS_LIBS="-L$WITH_GNUTLS/lib"
else
dnl oldest GnuTLS supported release is 3.3.x at time this is being written
PKG_CHECK_MODULES([GNUTLS], [gnutls >= 3.3.0])
fi
AC_SUBST([GNUTLS_CFLAGS])
AC_SUBST([GNUTLS_LIBS])
AC_DEFINE([HAVE_GNUTLS_CRYPTO_H], [1], [gnutls/crypto.h])
if test "$WITH_OPENSSL" = no && test "$WITH_WOLFSSL" = no && \
test "$WITH_MBEDTLS" = no && test "$WITH_NETTLE" = no; then
AC_SUBST([CRYPTO_LIB],[$GNUTLS_LIBS])
fi
fi
dnl pcre support
AC_MSG_NOTICE([----------------------------------------])
@ -1612,6 +1649,9 @@ lighty_track_feature "network-openssl" "mod_openssl" \
lighty_track_feature "network-mbedtls" "mod_mbedtls" \
'test "$WITH_MBEDTLS" != no'
lighty_track_feature "network-gnutls" "mod_gnutls" \
'test "$WITH_GNUTLS" != no'
lighty_track_feature "auth-crypt" "" \
'test "$found_crypt" != no'

View File

@ -23,6 +23,11 @@ option('with_geoip',
value: false,
description: 'with GeoIP-support mod_geoip [default: off]',
)
option('with_gnutls',
type: 'string',
value: 'false',
description: 'with GnuTLS-support [default: off]',
)
option('with_krb5',
type: 'boolean',
value: false,

View File

@ -20,6 +20,7 @@ option(WITH_XATTR "with xattr-support for the stat-cache [default: off]")
option(WITH_MYSQL "with mysql-support for mod_vhostdb_mysql [default: off]")
option(WITH_PGSQL "with postgres-support for mod_vhostdb_pgsql [default: off]")
option(WITH_DBI "with dbi-support for mod_vhostdb_dbi [default: off]")
option(WITH_GNUTLS "with GnuTLS-support [default: off]")
option(WITH_MBEDTLS "with mbedTLS-support [default: off]")
option(WITH_OPENSSL "with openssl-support [default: off]")
option(WITH_WOLFSSL "with wolfSSL-support [default: off]")
@ -410,6 +411,15 @@ else()
unset(HAVE_NETTLE_NETTLE_TYPES_H)
endif()
if(WITH_GNUTLS)
pkg_check_modules(LIBGNUTLS REQUIRED gnutls)
set(HAVE_LIBGNUTLS 1)
add_definitions(-DHAVE_GNUTLS_CRYPTO_H)
if(NOT WITH_OPENSSL AND NOT WITH_WOLFSSL AND NOT WITH_MBEDTLS AND NOT WITH_NETTLE)
set(CRYPTO_LIBRARY gnutls)
endif()
endif()
if(WITH_PCRE)
## if we have pcre-config, use it
xconfig(pcre-config PCRE_INCDIR PCRE_LIBDIR PCRE_LDFLAGS PCRE_CFLAGS)
@ -1091,6 +1101,11 @@ if(NOT ${CRYPTO_LIBRARY} EQUAL "")
target_link_libraries(mod_wstunnel ${CRYPTO_LIBRARY})
endif()
if(HAVE_LIBGNUTLS)
add_and_install_library(mod_gnutls "mod_gnutls.c")
target_link_libraries(mod_gnutls gnutls)
endif()
if(HAVE_LIBMBEDTLS AND HAVE_LIBMEDCRYPTO AND HAVE_LIBMEDX509)
target_link_libraries(lighttpd mbedtls)
target_link_libraries(lighttpd mbedcrypto)

View File

@ -398,6 +398,14 @@ mod_mbedtls_la_LDFLAGS = $(common_module_ldflags)
mod_mbedtls_la_LIBADD = $(MTLS_LIB) $(common_libadd)
endif
if BUILD_WITH_GNUTLS
lib_LTLIBRARIES += mod_gnutls.la
mod_gnutls_la_SOURCES = mod_gnutls.c
mod_gnutls_la_LDFLAGS = $(common_module_ldflags)
mod_gnutls_la_LIBADD = $(GNUTLS_LIBS) $(common_libadd)
mod_gnutls_la_CPPFLAGS = $(GNUTLS_CFLAGS)
endif
lib_LTLIBRARIES += mod_rewrite.la
mod_rewrite_la_SOURCES = mod_rewrite.c

View File

@ -182,6 +182,9 @@ if env['with_wolfssl']:
if env['with_mbedtls']:
modules['mod_mbedtls'] = { 'src' : [ 'mod_mbedtls.c' ], 'lib' : [ env['LIBSSL'], env['LIBX509'], env['LIBCRYPTO'] ] }
if env['with_gnutls']:
modules['mod_gnutls'] = { 'src' : [ 'mod_gnutls.c' ], 'lib' : [ env['LIBGNUTLS'] ] }
staticenv = env.Clone(CPPFLAGS=[ env['CPPFLAGS'], '-DLIGHTTPD_STATIC' ])
## all the core-sources + the modules

View File

@ -48,6 +48,26 @@ SHA1_Update(SHA_CTX *ctx, const void *data, size_t length)
#include <openssl/sha.h>
#elif defined(USE_GNUTLS_CRYPTO)
#include <gnutls/crypto.h>
#ifndef SHA_DIGEST_LENGTH
#define SHA_DIGEST_LENGTH 20
#endif
typedef gnutls_hash_hd_t SHA_CTX;
#define SHA1_Init(ctx) \
do { \
if (gnutls_hash_init((ctx), GNUTLS_DIG_SHA1) < 0) \
SEGFAULT(); \
} while (0)
#define SHA1_Final(digest, ctx) \
gnutls_hash_deinit(*(ctx),(digest))
static void
SHA1_Update(SHA_CTX *ctx, const void *data, size_t length)
{
gnutls_hash(*ctx, data, length);
}
#endif
#else /* ! USE_LIB_CRYPTO */

View File

@ -307,6 +307,8 @@ static void config_compat_module_load (server *srv) {
append_mod_staticfile = 0;
else if (buffer_eq_slen(m, CONST_STR_LEN("mod_dirlisting")))
append_mod_dirlisting = 0;
else if (buffer_eq_slen(m, CONST_STR_LEN("mod_gnutls")))
append_mod_openssl = 0;
else if (buffer_eq_slen(m, CONST_STR_LEN("mod_mbedtls")))
append_mod_openssl = 0;
else if (buffer_eq_slen(m, CONST_STR_LEN("mod_openssl")))
@ -704,7 +706,9 @@ static int config_insert_srvconf(server *srv) {
break;
case 30:/* ssl.engine */
ssl_enabled = (0 != cpv->v.u);
#if !defined(USE_OPENSSL_CRYPTO) && !defined(USE_MBEDTLS_CRYPTO)
#if !defined(USE_OPENSSL_CRYPTO) \
&& !defined(USE_MBEDTLS_CRYPTO) \
&& !defined(USE_GNUTLS_CRYPTO)
if (ssl_enabled) {
log_error(srv->errh, __FILE__, __LINE__,
"ssl support is missing; "

View File

@ -397,6 +397,7 @@ endif
libssl = []
libx509 = []
libcrypto = []
libgnutls = []
if get_option('with_openssl')
# manual search:
# header: openssl/ssl.h
@ -439,6 +440,16 @@ if get_option('with_nettle') != 'false'
libcrypto = [ dependency('libnettle') ]
conf_data.set('HAVE_NETTLE_NETTLE_TYPES_H', true)
endif
if get_option('with_gnutls')
# manual search:
# header: gnutls/gnutls.h
# function: gnutls_check_version (-lgnutls)
libgnutls = [ dependency('libgnutls') ]
conf_data.set('HAVE_GNUTLS_CRYPTO_H', true)
if not(get_option('with_openssl')) and not(get_option('with_wolfssl')) and not(get_option('with_mbedtls')) and not(getoption('with_nettle'))
libcrypto = [ dependency('libgnutls') ]
endif
endif
libpcre = []
if get_option('with_pcre')
@ -1002,6 +1013,12 @@ if get_option('with_mbedtls') != 'false'
]
endif
if get_option('with_gnutls') != 'false'
modules += [
[ 'mod_gnutls', [ 'mod_gnutls.c' ], libgnutls ],
]
endif
if get_option('with_pam')
modules += [
[ 'mod_authn_pam', [ 'mod_authn_pam.c' ], libpam ],

View File

@ -57,6 +57,23 @@ SHA256_Update(SHA256_CTX *ctx, const void *data, size_t length)
#include <openssl/sha.h>
#elif defined(USE_GNUTLS_CRYPTO)
#include <gnutls/crypto.h>
typedef gnutls_hash_hd_t SHA256_CTX;
#define SHA256_Init(ctx) \
do { \
if (gnutls_hash_init((ctx), GNUTLS_DIG_SHA256) < 0) \
SEGFAULT(); \
} while (0)
#define SHA256_Final(digest, ctx) \
gnutls_hash_deinit(*(ctx),(digest))
static void
SHA256_Update(SHA256_CTX *ctx, const void *data, size_t length)
{
gnutls_hash(*ctx, data, length);
}
#endif
#endif /* USE_LIB_CRYPTO */

View File

@ -95,6 +95,24 @@ SHA256_Update(SHA256_CTX *ctx, const void *data, size_t length)
#include <openssl/md4.h>
#include <openssl/sha.h>
#elif defined(USE_GNUTLS_CRYPTO)
#include <gnutls/crypto.h>
#define NO_MD4
typedef gnutls_hash_hd_t SHA256_CTX;
#define SHA256_Init(ctx) \
do { \
if (gnutls_hash_init((ctx), GNUTLS_DIG_SHA256) < 0) \
SEGFAULT(); \
} while (0)
#define SHA256_Final(digest, ctx) \
gnutls_hash_deinit(*(ctx),(digest))
static void
SHA256_Update(SHA256_CTX *ctx, const void *data, size_t length)
{
gnutls_hash(*ctx, data, length);
}
#endif
#endif /* USE_LIB_CRYPTO */

3092
src/mod_gnutls.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -20,6 +20,8 @@
#elif defined(USE_OPENSSL_CRYPTO)
#include <openssl/evp.h>
#include <openssl/hmac.h>
#elif defined(USE_GNUTLS_CRYPTO)
#include <gnutls/crypto.h>
#endif
#endif
@ -215,6 +217,18 @@ static int secdl_verify_mac(plugin_config *config, const char* protected_path, c
"hmac-sha1: HMAC() failed");
return 0;
}
#elif defined(USE_GNUTLS_CRYPTO)
int rc =
gnutls_hmac_fast(GNUTLS_MAC_SHA1,
(const unsigned char *)config->secret->ptr,
buffer_string_length(config->secret),
(const unsigned char *)protected_path,
strlen(protected_path), digest);
if (0 != rc) {
log_error(errh, __FILE__, __LINE__,
"hmac-sha1: HMAC() failed");
return 0;
}
#else
#error "unexpected; crypto lib not configured for use by mod_secdownload"
#endif
@ -256,6 +270,18 @@ static int secdl_verify_mac(plugin_config *config, const char* protected_path, c
"hmac-sha256: HMAC() failed");
return 0;
}
#elif defined(USE_GNUTLS_CRYPTO)
int rc =
gnutls_hmac_fast(GNUTLS_MAC_SHA256,
(const unsigned char *)config->secret->ptr,
buffer_string_length(config->secret),
(const unsigned char *)protected_path,
strlen(protected_path), digest);
if (0 != rc) {
log_error(errh, __FILE__, __LINE__,
"hmac-sha256: HMAC() failed");
return 0;
}
#else
#error "unexpected; crypto lib not configured for use by mod_secdownload"
#endif

View File

@ -18,19 +18,25 @@
#ifdef USE_NETTLE_CRYPTO
#undef USE_MBEDTLS_CRYPTO
#undef USE_OPENSSL_CRYPTO
#undef USE_GNUTLS_CRYPTO
#include <nettle/knuth-lfib.h>
#include <nettle/arcfour.h>
#include <nettle/yarrow.h>
#endif
#ifdef USE_MBEDTLS_CRYPTO
#undef USE_OPENSSL_CRYPTO
#undef USE_GNUTLS_CRYPTO
#include <mbedtls/ctr_drbg.h>
#include <mbedtls/entropy.h>
#endif
#ifdef USE_OPENSSL_CRYPTO
#undef USE_GNUTLS_CRYPTO
#include <openssl/opensslv.h> /* OPENSSL_VERSION_NUMBER */
#include <openssl/rand.h>
#endif
#ifdef USE_GNUTLS_CRYPTO
#include <gnutls/crypto.h>
#endif
#ifdef HAVE_GETENTROPY
#include <sys/random.h>
#endif
@ -238,6 +244,10 @@ static void li_rand_init (void)
void li_rand_reseed (void)
{
#ifdef USE_GNUTLS_CRYPTO
gnutls_rnd_refresh();
return;
#endif
#ifdef USE_MBEDTLS_CRYPTO
if (li_rand_inited) {
#ifdef MBEDTLS_ENTROPY_C
@ -253,6 +263,10 @@ void li_rand_reseed (void)
int li_rand_pseudo (void)
{
#ifdef USE_GNUTLS_CRYPTO
int i;
if (0 == gnutls_rnd(GNUTLS_RND_NONCE, &i, sizeof(i))) return i;
#endif
if (!li_rand_inited) li_rand_init();
/* randomness *is not* cryptographically strong */
/* (attempt to use better mechanisms to replace the more portable rand()) */
@ -291,6 +305,9 @@ int li_rand_pseudo (void)
void li_rand_pseudo_bytes (unsigned char *buf, int num)
{
#ifdef USE_GNUTLS_CRYPTO
if (0 == gnutls_rnd(GNUTLS_RND_NONCE, buf, (size_t)num)) return;
#endif
#ifdef USE_MBEDTLS_CRYPTO
#ifdef MBEDTLS_CTR_DRBG_C
if (0 == mbedtls_ctr_drbg_random(&ctr_drbg, buf, (size_t)num)) return;
@ -302,6 +319,9 @@ void li_rand_pseudo_bytes (unsigned char *buf, int num)
int li_rand_bytes (unsigned char *buf, int num)
{
#ifdef USE_GNUTLS_CRYPTO /* should use GNUTLS_RND_KEY for long-term keys */
if (0 == gnutls_rnd(GNUTLS_RND_RANDOM, buf, (size_t)num)) return 1;
#endif
#ifdef USE_NETTLE_CRYPTO
#if 0 /* not implemented: periodic nettle_yarrow256_update() and reseed */
if (!nettle_yarrow256_is_seeded(&yarrow256_ctx)) {

View File

@ -72,7 +72,8 @@ static const buffer default_server_tag = { CONST_STR_LEN(PACKAGE_DESC), 0 };
#include "sys-crypto.h"
#if defined(USE_OPENSSL_CRYPTO) \
|| defined(USE_MBEDTLS_CRYPTO)
|| defined(USE_MBEDTLS_CRYPTO) \
|| defined(USE_GNUTLS_CRYPTO)
#define TEXT_SSL " (ssl)"
#else
#define TEXT_SSL
@ -440,6 +441,16 @@ static void show_features (void) {
#else
"\t- mbedTLS support\n"
#endif
#ifdef USE_GNUTLS_CRYPTO
"\t+ GnuTLS support\n"
#else
"\t- GnuTLS support\n"
#endif
#ifdef USE_NETTLE_CRYPTO
"\t+ Nettle support\n"
#else
"\t- Nettle support\n"
#endif
#ifdef HAVE_LIBPCRE
"\t+ PCRE support\n"
#else

View File

@ -29,4 +29,9 @@
#define USE_NETTLE_CRYPTO
#endif
#ifdef HAVE_GNUTLS_CRYPTO_H
#define USE_LIB_CRYPTO
#define USE_GNUTLS_CRYPTO
#endif
#endif