From 75636faa679422cb7e360167d03163ca1985f772 Mon Sep 17 00:00:00 2001 From: Nokis Mavrogiannopoulos Date: Wed, 20 Feb 2008 18:50:41 +0000 Subject: added tags --- Makefile.am | 4 +- NEWS | 13 +++ NOTICE | 3 + README | 44 +++++--- README.ENV | 8 +- configure.ac | 18 ++-- include/mod_gnutls.h.in | 22 +++- libgnutls.m4 | 174 ++++++++++++++++++++++++++++++ src/gnutls_cache.c | 84 ++++++++------- src/gnutls_config.c | 131 +++++++++++++++++++++-- src/gnutls_hooks.c | 273 +++++++++++++++++++++++++++++++++++++----------- src/mod_gnutls.c | 28 ++++- 12 files changed, 667 insertions(+), 135 deletions(-) create mode 100644 libgnutls.m4 diff --git a/Makefile.am b/Makefile.am index d61ebd3..a19e755 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,11 +1,11 @@ AUTOMAKE_OPTIONS = foreign dist-bzip2 EXTRA_DIST = m4/outoforder.m4 m4/apache.m4 \ - m4/libgnutls.m4 m4/apr_memcache.m4 \ + libgnutls.m4 m4/apr_memcache.m4 \ m4/apache_test.m4 m4/lua.m4 \ include/mod_gnutls.h.in \ README README.ENV NEWS \ NOTICE LICENSE autogen.sh -SUBDIRS = src data +SUBDIRS = src ACLOCAL_AMFLAGS = -I m4 diff --git a/NEWS b/NEWS index e4b908d..a9fe9fd 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,16 @@ +** Version 0.5.0-alpha (2008-01-24) + +- Added support for OpenPGP keys. The new directives are: + GnuTLSPGPKeyringFile, GnuTLSPGPCertificateFile, GnuTLSPGPKeyFile + +** Version 0.4.2 (2007-12-10) + +- Added support for sending a certificate chain. + +- Corrected bug which did not allow the TLS session cache to be used. + +- Do not allow resuming sessions on different servers. + ** Version 0.4.1 (2007-12-03) - Added support for subject alternative names in certificates. diff --git a/NOTICE b/NOTICE index 7b09606..25efd6f 100644 --- a/NOTICE +++ b/NOTICE @@ -1,3 +1,6 @@ +This product includes software developed by +Nikos Mavrogiannopoulos (http://www.gnutls.org/). + This product includes software developed by Paul Querna (http://www.outoforder.cc/). diff --git a/README b/README index 85418de..5198ed7 100644 --- a/README +++ b/README @@ -11,7 +11,7 @@ to debug. I wanted to understand how it worked, and I had recently heard about GnuTLS, so long story short, I decided to implement a mod_gnutls. Lines of Code in mod_ssl: 15,324 -Lines of Code in mod_gnutls: 1,886 +Lines of Code in mod_gnutls: 3,594 Because of writing mod_gnutls, I now understand how input and output filters work, better than I ever thought possible. It was a little painful at times, and some parts @@ -54,31 +54,26 @@ GnuTLSCache dbm conf/gnutls_cache GnuTLSEnable On # This is the Private key for your server. - GnuTLSKeyFile conf/server.key + GnuTLSX509KeyFile conf/server.key # This is the Server Certificate. - GnuTLSCertificateFile conf/server.cert + GnuTLSX509CertificateFile conf/server.cert - # a more advanced configuration GnuTLSCache dbm "/var/cache/www-tls-cache/cache" -GnuTLSCacheTimeout 500 -GnuTLSProtocols TLS1.1 TLS1.0 SSL3.0 +GnuTLSCacheTimeout 600 NameVirtualHost 1.2.3.4:443 Servername server.com:443 GnuTLSEnable on - GnuTLSCiphers AES-128-CBC 3DES-CBC ARCFOUR-128 - GnuTLSKeyExchangeAlgorithms RSA DHE-RSA DHE-DSS SRP SRP-RSA SRP-DSS - GnuTLSMACAlgorithms SHA1 MD5 - GnuTLSCompressionMethods NULL + GnuTLSPriority NORMAL # To export exactly the same environment variables as mod_ssl to CGI scripts. GNUTLSExportCertificates on - GnuTLSCertificateFile /etc/apache2/server-cert.pem - GnuTLSKeyFile /etc/apache2/server-key.pem + GnuTLSX509CertificateFile /etc/apache2/server-cert.pem + GnuTLSX509KeyFile /etc/apache2/server-keyGravatar Nokis Mavrogiannopoulos 2008-03-03 14:04:01 +0000 committerGravatar Nokis Mavrogiannopoulos 2008-03-03 14:04:01 +0000 commit9b5f7b906208c1ccc7469aae6aada611ca010e07 (patch) tree6a32b9c486e92bd3cbaefea3f248ef325e972177 parent4149b4f93e99e5134c1599cc1c2fb4a0603e2007 (diff)
corrected SRP enable flag, and corrected the DBM hook support. It now free data needed by some DBM providers.
Diffstat
-rwxr-xr-xautogen.sh17
-rw-r--r--configure.ac7
-rw-r--r--src/gnutls_cache.c9
-rw-r--r--src/mod_gnutls.c1
4 files changed, 14 insertions, 20 deletions
diff --git a/autogen.sh b/autogen.sh
index 742b2cc..541e187 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -1,25 +1,10 @@
1#!/bin/sh 1#!/bin/sh
2 2
3if [ -z $ACLOCAL ]; then
4 ACLOCAL=aclocal
5fi
6if [ -z $AUTOCONF ]; then
7 AUTOCONF=autoconf
8fi
9if [ -z $AUTOHEADER ]; then
10 AUTOHEADER=autoheader
11fi
12if [ -z $AUTORECONF ]; then 3if [ -z $AUTORECONF ]; then
13 AUTORECONF=autoreconf 4 AUTORECONF=autoreconf
14fi 5fi
15 6
16#rm -rf autom4te.cache 7#rm -rf autom4te.cache
17$AUTORECONF -f -i 8$AUTORECONF -f -v -i
18#touch stamp-h.in 9#touch stamp-h.in
19 10
20for x in providers/*; do
21 if [ -e $x/autogen.sh ]; then
22 echo Generating Config files in $x
23 (cd $x; ./autogen.sh $*)
24 fi
25done
diff --git a/configure.ac b/configure.ac
index 28001b3..62db2af 100644
--- a/configure.ac
+++ b/configure.ac
@@ -41,8 +41,10 @@ AC_ARG_ENABLE(srp,
41 AS_HELP_STRING([--disable-srp], 41 AS_HELP_STRING([--disable-srp],
42 [unconditionally disable the SRP functionality]), 42 [unconditionally disable the SRP functionality]),
43 use_srp=$enableval, use_srp=yes) 43 use_srp=$enableval, use_srp=yes)
44
45SRP_CFLAGS=""
44if test "$use_srp" != "no"; then 46if test "$use_srp" != "no"; then
45 AC_DEFINE_UNQUOTED(ENABLE_SRP, 1, [whether to enable SRP]) 47 SRP_CFLAGS="-DENABLE_SRP=1"
46fi 48fi
47AC_MSG_CHECKING([whether to enable SRP functionality]) 49AC_MSG_CHECKING([whether to enable SRP functionality])
48AC_MSG_RESULT($use_srp) 50AC_MSG_RESULT($use_srp)
@@ -53,7 +55,7 @@ have_apr_memcache=0
53CHECK_APR_MEMCACHE([have_apr_memcache=1], [have_apr_memcache=0]) 55CHECK_APR_MEMCACHE([have_apr_memcache=1], [have_apr_memcache=0])
54AC_SUBST(have_apr_memcache) 56AC_SUBST(have_apr_memcache)
55 57
56MODULE_CFLAGS="${LIBGNUTLS_EXTRA_CFLAGS} ${APR_MEMCACHE_CFLAGS} ${APXS_CFLAGS} ${AP_INCLUDES} ${APR_INCLUDES} ${APU_INCLUDES}" 58MODULE_CFLAGS="${LIBGNUTLS_EXTRA_CFLAGS} ${SRP_CFLAGS} ${APR_MEMCACHE_CFLAGS} ${APXS_CFLAGS} ${AP_INCLUDES} ${APR_INCLUDES} ${APU_INCLUDES}"
57MODULE_LIBS="${APR_MEMCACHE_LIBS} ${LIBGNUTLS_EXTRA_LIBS}" 59MODULE_LIBS="${APR_MEMCACHE_LIBS} ${LIBGNUTLS_EXTRA_LIBS}"
58 60
59AC_SUBST(MODULE_CFLAGS) 61AC_SUBST(MODULE_CFLAGS)
@@ -68,5 +70,6 @@ echo ""
68echo " * mod_gnutls version: ${MOD_GNUTLS_VERSION}" 70echo " * mod_gnutls version: ${MOD_GNUTLS_VERSION}"
69echo " * Apache Modules directory: ${AP_LIBEXECDIR}" 71echo " * Apache Modules directory: ${AP_LIBEXECDIR}"
70echo " * GnuTLS Library version: ${LIBGNUTLS_VERSION}" 72echo " * GnuTLS Library version: ${LIBGNUTLS_VERSION}"
73echo " * SRP Authentication: ${use_srp}"
71echo "" 74echo ""
72echo "---" 75echo "---"
diff --git a/src/gnutls_cache.c b/src/gnutls_cache.c
index 83e7bb5..90f5a86 100644
--- a/src/gnutls_cache.c
+++ b/src/gnutls_cache.c
@@ -1,5 +1,6 @@
1/** 1/**
2 * Copyright 2004-2005 Paul Querna 2 * Copyright 2004-2005 Paul Querna
3 * Portions Copyright 2008 Nikos Mavrogiannopoulos
3 * 4 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 6 * you may not use this file except in compliance with the License.
@@ -345,6 +346,7 @@ static int dbm_cache_expire(mgs_handle_t *ctxt)
345 break; 346 break;
346 } 347 }
347 } 348 }
349 apr_dbm_freedatum( dbm, dbmval);
348 350
349 } 351 }
350 apr_dbm_nextkey(dbm, &dbmkey); 352 apr_dbm_nextkey(dbm, &dbmkey);
@@ -401,20 +403,25 @@ static gnutls_datum_t dbm_cache_fetch(void* baton, gnutls_datum_t key)
401 } 403 }
402 404
403 if (dbmval.dptr == NULL || dbmval.dsize <= sizeof(apr_time_t)) { 405 if (dbmval.dptr == NULL || dbmval.dsize <= sizeof(apr_time_t)) {
406 apr_dbm_freedatum( dbm, dbmval);
404 apr_dbm_close(dbm); 407 apr_dbm_close(dbm);
405 return data; 408 return data;
406 } 409 }
407 apr_dbm_close(dbm);
408 410
409 data.size = dbmval.dsize - sizeof(apr_time_t); 411 data.size = dbmval.dsize - sizeof(apr_time_t);
410 412
411 data.data = gnutls_malloc(data.size); 413 data.data = gnutls_malloc(data.size);
412 if (data.data == NULL) { 414 if (data.data == NULL) {
415 apr_dbm_freedatum( dbm, dbmval);
416 apr_dbm_close(dbm);
413 return data; 417 return data;
414 } 418 }
415 419
416 memcpy(data.data, dbmval.dptr+sizeof(apr_time_t), data.size); 420 memcpy(data.data, dbmval.dptr+sizeof(apr_time_t), data.size);
417 421
422 apr_dbm_freedatum( dbm, dbmval);
423 apr_dbm_close(dbm);
424
418 return data; 425 return data;
419} 426}
420 427
diff --git a/src/mod_gnutls.c b/src/mod_gnutls.c
index 5207641..08e7dba 100644
--- a/src/mod_gnutls.c
+++ b/src/mod_gnutls.c
@@ -17,7 +17,6 @@
17 17
18#include "mod_gnutls.h" 18#include "mod_gnutls.h"
19 19
20
21static void gnutls_hooks(apr_pool_t * p) 20static void gnutls_hooks(apr_pool_t * p)
22{ 21{
23 ap_hook_pre_connection(mgs_hook_pre_connection, NULL, NULL, 22 ap_hook_pre_connection(mgs_hook_pre_connection, NULL, NULL,
_pstrcat(r->pool, MGS_SIDE, "_CERT", NULL), + apr_pstrmemdup(r->pool, cert_buf, len)); + + } + + len = sizeof(buf); + gnutls_openpgp_crt_get_name(cert, 0, buf, &len); + apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_NAME", NULL), + apr_pstrmemdup(r->pool, buf, len)); + + len = sizeof(sbuf); + gnutls_openpgp_crt_get_fingerprint(cert, sbuf, &len); + tmp = mgs_session_id2sz(sbuf, len, buf, sizeof(buf)); + apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_FINGERPRINT", NULL), + apr_pstrdup(r->pool, tmp)); + + ret = gnutls_openpgp_crt_get_version(cert); + if (ret > 0) + apr_table_setn(env, + apr_pstrcat(r->pool, MGS_SIDE, "_M_VERSION", NULL), + apr_psprintf(r->pool, "%u", ret)); + + apr_table_setn(env, + apr_pstrcat(r->pool, MGS_SIDE, "_CERT_TYPE", NULL), "OPENPGP"); + + tmp = + mgs_time2sz(gnutls_openpgp_crt_get_expiration_time + (cert), buf, sizeof(buf)); + apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_V_END", NULL), + apr_pstrdup(r->pool, tmp)); + + tmp = + mgs_time2sz(gnutls_openpgp_crt_get_creation_time + (cert), buf, sizeof(buf)); + apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_V_START", NULL), + apr_pstrdup(r->pool, tmp)); + + ret = gnutls_openpgp_crt_get_pk_algorithm(cert, NULL); + if (ret >= 0) { + apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_A_KEY", NULL), + gnutls_pk_algorithm_get_name(ret)); + } + +} +/* TODO: Allow client sending a X.509 certificate chain */ static int mgs_cert_verify(request_rec * r, mgs_handle_t * ctxt) { const gnutls_datum_t *cert_list; unsigned int cert_list_size, status, expired; int rv, ret; - gnutls_x509_crt_t cert; + union { + gnutls_x509_crt_t x509; + gnutls_openpgp_crt_t pgp; + } cert; apr_time_t activation_time, expiration_time, cur_time; cert_list = @@ -890,32 +1017,56 @@ static int mgs_cert_verify(request_rec * r, mgs_handle_t * ctxt) return HTTP_FORBIDDEN; } - gnutls_x509_crt_init(&cert); - rv = gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER); + if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_X509) { + gnutls_x509_crt_init(&cert.x509); + rv = gnutls_x509_crt_import(cert.x509, &cert_list[0], GNUTLS_X509_FMT_DER); + } else if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_OPENPGP) { + gnutls_openpgp_crt_init(&cert.pgp); + rv = gnutls_openpgp_crt_import(cert.pgp, &cert_list[0], GNUTLS_OPENPGP_FMT_RAW); + } else return HTTP_FORBIDDEN; + if (rv < 0) { - ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, + ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, "GnuTLS: Failed to Verify Peer: " "Failed to import peer certificates."); - ret = HTTP_FORBIDDEN; - goto exit; + ret = HTTP_FORBIDDEN; + goto exit; } - apr_time_ansi_put(&expiration_time, - gnutls_x509_crt_get_expiration_time(cert)); - apr_time_ansi_put(&activation_time, - gnutls_x509_crt_get_activation_time(cert)); + if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_X509) { + apr_time_ansi_put(&expiration_time, + gnutls_x509_crt_get_expiration_time(cert.x509)); + apr_time_ansi_put(&activation_time, + gnutls_x509_crt_get_activation_time(cert.x509)); - rv = gnutls_x509_crt_verify(cert, ctxt->sc->ca_list, + rv = gnutls_x509_crt_verify(cert.x509, ctxt->sc->ca_list, ctxt->sc->ca_list_size, 0, &status); + } else { + apr_time_ansi_put(&expiration_time, + gnutls_openpgp_crt_get_expiration_time(cert.pgp)); + apr_time_ansi_put(&activation_time, + gnutls_openpgp_crt_get_creation_time(cert.pgp)); + + rv = gnutls_openpgp_crt_verify_ring(cert.pgp, ctxt->sc->pgp_list, + 0, &status); + } if (rv < 0) { ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, "GnuTLS: Failed to Verify Peer certificate: (%d) %s", rv, gnutls_strerror(rv)); + if (rv == GNUTLS_E_NO_CERTIFICATE_FOUND) + ap_log_rerror(APLOG_MARK, APLOG_EMERG, 0, r, + "GnuTLS: No certificate was found for verification. Did you set the GnuTLSX509CAFile or GnuTLSPGPKeyringFile directives?"); ret = HTTP_FORBIDDEN; goto exit; } + /* TODO: X509 CRL Verification. */ + /* May add later if anyone needs it. + */ + /* ret = gnutls_x509_crt_check_revocation(crt, crl_list, crl_list_size); */ + expired = 0; cur_time = apr_time_now(); if (activation_time > cur_time) { @@ -950,16 +1101,11 @@ static int mgs_cert_verify(request_rec * r, mgs_handle_t * ctxt) "GnuTLS: Peer Certificate is revoked."); } - /* TODO: Further Verification. */ - /* Revocation is X.509 non workable paradigm, I really doubt implementation - * is worth doing --nmav - */ -/// ret = gnutls_x509_crt_check_revocation(crt, crl_list, crl_list_size); - -// mgs_hook_fixups(r); -// rv = mgs_authz_lua(r); - - mgs_add_common_cert_vars(r, cert, 1, + if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_X509) + mgs_add_common_cert_vars(r, cert.x509, 1, + ctxt->sc->export_certificates_enabled); + else if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_OPENPGP) + mgs_add_common_pgpcert_vars(r, cert.pgp, 1, ctxt->sc->export_certificates_enabled); { @@ -983,7 +1129,10 @@ static int mgs_cert_verify(request_rec * r, mgs_handle_t * ctxt) } exit: - gnutls_x509_crt_deinit(cert); + if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_X509) + gnutls_x509_crt_deinit(cert.x509); + else if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_OPENPGP) + gnutls_openpgp_crt_deinit(cert.pgp); return ret; diff --git a/src/mod_gnutls.c b/src/mod_gnutls.c index a6e5528..014bfc8 100644 --- a/src/mod_gnutls.c +++ b/src/mod_gnutls.c @@ -64,6 +64,14 @@ static const command_rec mgs_config_cmds[] = { NULL, RSRC_CONF, "Set the CA File to verify Client Certificates"), + AP_INIT_TAKE1("GnuTLSX509CAFile", mgs_set_client_ca_file, + NULL, + RSRC_CONF, + "Set the CA File to verify Client Certificates"), + AP_INIT_TAKE1("GnuTLSPGPKeyringFile", mgs_set_keyring_file, + NULL, + RSRC_CONF, + "Set the Keyring File to verify Client Certificates"), AP_INIT_TAKE1("GnuTLSDHFile", mgs_set_dh_file, NULL, RSRC_CONF, @@ -75,11 +83,27 @@ static const command_rec mgs_config_cmds[] = { AP_INIT_TAKE1("GnuTLSCertificateFile", mgs_set_cert_file, NULL, RSRC_CONF, - "SSL Server Key file"), + "SSL Server X509 Certificate file"), AP_INIT_TAKE1("GnuTLSKeyFile", mgs_set_key_file, NULL, RSRC_CONF, - "SSL Server SRP Password file"), + "SSL Server X509 Private Key file"), + AP_INIT_TAKE1("GnuTLSX509CertificateFile", mgs_set_cert_file, + NULL, + RSRC_CONF, + "SSL Server X509 Certificate file"), + AP_INIT_TAKE1("GnuTLSX509KeyFile", mgs_set_key_file, + NULL, + RSRC_CONF, + "SSL Server X509 Private Key file"), + AP_INIT_TAKE1("GnuTLSPGPCertificateFile", mgs_set_pgpcert_file, + NULL, + RSRC_CONF, + "SSL Server PGP Certificate file"), + AP_INIT_TAKE1("GnuTLSPGPKeyFile", mgs_set_pgpkey_file, + NULL, + RSRC_CONF, + "SSL Server PGP Private key file"), AP_INIT_TAKE1("GnuTLSSRPPasswdFile", mgs_set_srp_tpasswd_file, NULL, RSRC_CONF, -- cgit