diff options
-rw-r--r-- | Makefile.am | 4 | ||||
-rw-r--r-- | NEWS | 13 | ||||
-rw-r--r-- | NOTICE | 3 | ||||
-rw-r--r-- | README | 44 | ||||
-rw-r--r-- | README.ENV | 8 | ||||
-rw-r--r-- | configure.ac | 18 | ||||
-rw-r--r-- | include/mod_gnutls.h.in | 22 | ||||
-rw-r--r-- | libgnutls.m4 | 174 | ||||
-rw-r--r-- | src/gnutls_cache.c | 84 | ||||
-rw-r--r-- | src/gnutls_config.c | 131 | ||||
-rw-r--r-- | src/gnutls_hooks.c | 273 | ||||
-rw-r--r-- | src/mod_gnutls.c | 28 |
12 files changed, 667 insertions, 135 deletions
diff --git a/Makefile.am b/Makefile.am index d61ebd3..a19e755 100644 --- a/Makefile.am +++ b/Makefile.am | |||
@@ -1,11 +1,11 @@ | |||
1 | AUTOMAKE_OPTIONS = foreign dist-bzip2 | 1 | AUTOMAKE_OPTIONS = foreign dist-bzip2 |
2 | 2 | ||
3 | EXTRA_DIST = m4/outoforder.m4 m4/apache.m4 \ | 3 | EXTRA_DIST = m4/outoforder.m4 m4/apache.m4 \ |
4 | m4/libgnutls.m4 m4/apr_memcache.m4 \ | 4 | libgnutls.m4 m4/apr_memcache.m4 \ |
5 | m4/apache_test.m4 m4/lua.m4 \ | 5 | m4/apache_test.m4 m4/lua.m4 \ |
6 | include/mod_gnutls.h.in \ | 6 | include/mod_gnutls.h.in \ |
7 | README README.ENV NEWS \ | 7 | README README.ENV NEWS \ |
8 | NOTICE LICENSE autogen.sh | 8 | NOTICE LICENSE autogen.sh |
9 | 9 | ||
10 | SUBDIRS = src data | 10 | SUBDIRS = src |
11 | ACLOCAL_AMFLAGS = -I m4 | 11 | ACLOCAL_AMFLAGS = -I m4 |
@@ -1,3 +1,16 @@ | |||
1 | ** Version 0.5.0-alpha (2008-01-24) | ||
2 | |||
3 | - Added support for OpenPGP keys. The new directives are: | ||
4 | GnuTLSPGPKeyringFile, GnuTLSPGPCertificateFile, GnuTLSPGPKeyFile | ||
5 | |||
6 | ** Version 0.4.2 (2007-12-10) | ||
7 | |||
8 | - Added support for sending a certificate chain. | ||
9 | |||
10 | - Corrected bug which did not allow the TLS session cache to be used. | ||
11 | |||
12 | - Do not allow resuming sessions on different servers. | ||
13 | |||
1 | ** Version 0.4.1 (2007-12-03) | 14 | ** Version 0.4.1 (2007-12-03) |
2 | 15 | ||
3 | - Added support for subject alternative names in certificates. | 16 | - Added support for subject alternative names in certificates. |
@@ -1,4 +1,7 @@ | |||
1 | This product includes software developed by | 1 | This product includes software developed by |
2 | Nikos Mavrogiannopoulos (http://www.gnutls.org/). | ||
3 | |||
4 | This product includes software developed by | ||
2 | Paul Querna (http://www.outoforder.cc/). | 5 | Paul Querna (http://www.outoforder.cc/). |
3 | 6 | ||
4 | This product includes software developed by | 7 | This product includes software developed by |
@@ -11,7 +11,7 @@ to debug. I wanted to understand how it worked, and I had recently heard about | |||
11 | GnuTLS, so long story short, I decided to implement a mod_gnutls. | 11 | GnuTLS, so long story short, I decided to implement a mod_gnutls. |
12 | 12 | ||
13 | Lines of Code in mod_ssl: 15,324 | 13 | Lines of Code in mod_ssl: 15,324 |
14 | Lines of Code in mod_gnutls: 1,886 | 14 | Lines of Code in mod_gnutls: 3,594 |
15 | 15 | ||
16 | Because of writing mod_gnutls, I now understand how input and output filters work, | 16 | Because of writing mod_gnutls, I now understand how input and output filters work, |
17 | better than I ever thought possible. It was a little painful at times, and some parts | 17 | 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 | |||
54 | GnuTLSEnable On | 54 | GnuTLSEnable On |
55 | 55 | ||
56 | # This is the Private key for your server. | 56 | # This is the Private key for your server. |
57 | GnuTLSKeyFile conf/server.key | 57 | GnuTLSX509KeyFile conf/server.key |
58 | 58 | ||
59 | # This is the Server Certificate. | 59 | # This is the Server Certificate. |
60 | GnuTLSCertificateFile conf/server.cert | 60 | GnuTLSX509CertificateFile conf/server.cert |
61 | </VirtualHost> | 61 | </VirtualHost> |
62 | 62 | ||
63 | |||
64 | # a more advanced configuration | 63 | # a more advanced configuration |
65 | GnuTLSCache dbm "/var/cache/www-tls-cache/cache" | 64 | GnuTLSCache dbm "/var/cache/www-tls-cache/cache" |
66 | GnuTLSCacheTimeout 500 | 65 | GnuTLSCacheTimeout 600 |
67 | GnuTLSProtocols TLS1.1 TLS1.0 SSL3.0 | ||
68 | NameVirtualHost 1.2.3.4:443 | 66 | NameVirtualHost 1.2.3.4:443 |
69 | 67 | ||
70 | <VirtualHost 1.2.3.4:443> | 68 | <VirtualHost 1.2.3.4:443> |
71 | Servername server.com:443 | 69 | Servername server.com:443 |
72 | GnuTLSEnable on | 70 | GnuTLSEnable on |
73 | GnuTLSCiphers AES-128-CBC 3DES-CBC ARCFOUR-128 | 71 | GnuTLSPriority NORMAL |
74 | GnuTLSKeyExchangeAlgorithms RSA DHE-RSA DHE-DSS SRP SRP-RSA SRP-DSS | ||
75 | GnuTLSMACAlgorithms SHA1 MD5 | ||
76 | GnuTLSCompressionMethods NULL | ||
77 | # To export exactly the same environment variables as mod_ssl to CGI scripts. | 72 | # To export exactly the same environment variables as mod_ssl to CGI scripts. |
78 | GNUTLSExportCertificates on | 73 | GNUTLSExportCertificates on |
79 | 74 | ||
80 | GnuTLSCertificateFile /etc/apache2/server-cert.pem | 75 | GnuTLSX509CertificateFile /etc/apache2/server-cert.pem |
81 | GnuTLSKeyFile /etc/apache2/server-key.pem | 76 | GnuTLSX509KeyFile /etc/apache2/server-key.pem |
82 | 77 | ||
83 | # To enable SRP you must have these files installed. Check the gnutls srptool. | 78 | # To enable SRP you must have these files installed. Check the gnutls srptool. |
84 | GnuTLSSRPPasswdFile /etc/apache2/tpasswd | 79 | GnuTLSSRPPasswdFile /etc/apache2/tpasswd |
@@ -88,6 +83,29 @@ NameVirtualHost 1.2.3.4:443 | |||
88 | # GnuTLSClientVerify could be ignore or require. The GnuTLSClientCAFile | 83 | # GnuTLSClientVerify could be ignore or require. The GnuTLSClientCAFile |
89 | # contains the CAs to verify client certificates. | 84 | # contains the CAs to verify client certificates. |
90 | GnuTLSClientVerify request | 85 | GnuTLSClientVerify request |
91 | GnuTLSClientCAFile ca.pem | 86 | GnuTLSX509CAFile ca.pem |
92 | ... | 87 | ... |
93 | </VirtualHost> | 88 | </VirtualHost> |
89 | |||
90 | # A setup for OpenPGP and X.509 authentication | ||
91 | <VirtualHost 1.2.3.4:443> | ||
92 | Servername crystal.lan:443 | ||
93 | GnuTLSEnable on | ||
94 | GnuTLSPriorities NORMAL:+COMP-NULL | ||
95 | |||
96 | # setup the openpgp keys | ||
97 | GnuTLSPGPCertificateFile /etc/apache2/test.pub.asc | ||
98 | GnuTLSPGPKeyFile /etc/apache2/test.sec.asc | ||
99 | |||
100 | # and the X.509 keys | ||
101 | GnuTLSCertificateFile /etc/apache2/server-cert.pem | ||
102 | GnuTLSKeyFile /etc/apache2/server-key.pem | ||
103 | GnuTLSClientVerify ignore | ||
104 | |||
105 | # To avoid using the default DH params | ||
106 | GnuTLSDHFile /etc/apache2/dh.pem | ||
107 | |||
108 | # these are only needed if GnuTLSClientVerify != ignore | ||
109 | GnuTLSClientCAFile ca.pem | ||
110 | GnuTLSPGPKeyringFile /etc/apache2/ring.asc | ||
111 | </VirtualHost> | ||
@@ -19,7 +19,7 @@ SSL_CLIENT_V_START: The activation time of client's certificate. | |||
19 | SSL_CLIENT_V_END: The expiration time of client's certificate. | 19 | SSL_CLIENT_V_END: The expiration time of client's certificate. |
20 | SSL_CLIENT_S_DN: The distinguished name of client's certificate in RFC2253 format. | 20 | SSL_CLIENT_S_DN: The distinguished name of client's certificate in RFC2253 format. |
21 | SSL_CLIENT_I_DN: The distinguished name of client's issuer certificate in RFC2253 format. | 21 | SSL_CLIENT_I_DN: The distinguished name of client's issuer certificate in RFC2253 format. |
22 | SSL_CLIENT_S_SAN%: These will contain the alternative names of the client certificate | 22 | SSL_CLIENT_S_AN%: These will contain the alternative names of the client certificate |
23 | (% is a number starting from zero). The values will be prepended by "DNSNAME:", | 23 | (% is a number starting from zero). The values will be prepended by "DNSNAME:", |
24 | "RFC822NAME:" or "URI:" depending on the type. If it is not supported the value | 24 | "RFC822NAME:" or "URI:" depending on the type. If it is not supported the value |
25 | "UNSUPPORTED" will be set. | 25 | "UNSUPPORTED" will be set. |
@@ -30,13 +30,13 @@ SSL_CLIENT_A_KEY: The public key algorithm in client's certificate. | |||
30 | SSL_CLIENT_CERT: The PEM-encoded client certificate | 30 | SSL_CLIENT_CERT: The PEM-encoded client certificate |
31 | SSL_CLIENT_VERIFY: | 31 | SSL_CLIENT_VERIFY: |
32 | whether the client's certificate was verified. (NONE if none was sent, or SUCCESS or FAILED) | 32 | whether the client's certificate was verified. (NONE if none was sent, or SUCCESS or FAILED) |
33 | SSL_CLIENT_S_TYPE: The certificate type can be X.509 or OPENPGP. | 33 | SSL_CLIENT_CERT_TYPE: The certificate type can be X.509 or OPENPGP. |
34 | 34 | ||
35 | SSL_SERVER_V_START: The activation time of server's certificate. | 35 | SSL_SERVER_V_START: The activation time of server's certificate. |
36 | SSL_SERVER_V_END: The expiration time of server's certificate. | 36 | SSL_SERVER_V_END: The expiration time of server's certificate. |
37 | SSL_SERVER_S_DN: The distinguished name of the server's certificate in RFC2253 format. | 37 | SSL_SERVER_S_DN: The distinguished name of the server's certificate in RFC2253 format. |
38 | SSL_SERVER_I_DN: The distinguished name of the server's issuer certificate in RFC2253 format. | 38 | SSL_SERVER_I_DN: The distinguished name of the server's issuer certificate in RFC2253 format. |
39 | SSL_SERVER_S_SAN%: These will contain the alternative names of the server certificate | 39 | SSL_SERVER_S_AN%: These will contain the alternative names of the server certificate |
40 | (% is a number starting from zero). The values will be prepended by "DNSNAME:", | 40 | (% is a number starting from zero). The values will be prepended by "DNSNAME:", |
41 | "RFC822NAME:" or "URI:" depending on the type. If it is not supported the value | 41 | "RFC822NAME:" or "URI:" depending on the type. If it is not supported the value |
42 | "UNSUPPORTED" will be set. | 42 | "UNSUPPORTED" will be set. |
@@ -45,5 +45,5 @@ SSL_SERVER_M_VERSION: The version of the server's certificate. | |||
45 | SSL_SERVER_A_SIG: The algorithm used for the signature in server's certificate. | 45 | SSL_SERVER_A_SIG: The algorithm used for the signature in server's certificate. |
46 | SSL_SERVER_A_KEY: The public key algorithm in server's certificate. | 46 | SSL_SERVER_A_KEY: The public key algorithm in server's certificate. |
47 | SSL_SERVER_CERT: The PEM-encoded server certificate | 47 | SSL_SERVER_CERT: The PEM-encoded server certificate |
48 | SSL_SERVER_S_TYPE: The certificate type can be X.509 or OPENPGP. | 48 | SSL_SERVER_CERT_TYPE: The certificate type can be X.509 or OPENPGP. |
49 | 49 | ||
diff --git a/configure.ac b/configure.ac index c401940..0cdcdd9 100644 --- a/configure.ac +++ b/configure.ac | |||
@@ -1,5 +1,5 @@ | |||
1 | dnl | 1 | dnl |
2 | AC_INIT(mod_gnutls, 0.4.1) | 2 | AC_INIT(mod_gnutls, 0.5.0-alpha) |
3 | OOO_CONFIG_NICE(config.nice) | 3 | OOO_CONFIG_NICE(config.nice) |
4 | MOD_GNUTLS_VERSION=AC_PACKAGE_VERSION | 4 | MOD_GNUTLS_VERSION=AC_PACKAGE_VERSION |
5 | AC_PREREQ(2.53) | 5 | AC_PREREQ(2.53) |
@@ -28,8 +28,14 @@ CHECK_APACHE(,$AP_VERSION, | |||
28 | dnl LIBTOOL="`${APR_CONFIG} --apr-libtool`" | 28 | dnl LIBTOOL="`${APR_CONFIG} --apr-libtool`" |
29 | dnl AC_SUBST(LIBTOOL) | 29 | dnl AC_SUBST(LIBTOOL) |
30 | 30 | ||
31 | MIN_TLS_VERSION=2.1.7 | 31 | MIN_TLS_VERSION=2.2.1 |
32 | CHECK_LIBGNUTLS($MIN_TLS_VERSION) | 32 | AM_PATH_LIBGNUTLS_EXTRA($MIN_TLS_VERSION,, |
33 | AC_MSG_ERROR([[ | ||
34 | *** | ||
35 | *** libgnutls and libgnutls-extra were not found. You may want to get it from | ||
36 | *** http://www.gnutls.org/ | ||
37 | *** | ||
38 | ]])) | ||
33 | 39 | ||
34 | dnl CHECK_LUA() | 40 | dnl CHECK_LUA() |
35 | 41 | ||
@@ -37,13 +43,13 @@ have_apr_memcache=0 | |||
37 | CHECK_APR_MEMCACHE([have_apr_memcache=1], [have_apr_memcache=0]) | 43 | CHECK_APR_MEMCACHE([have_apr_memcache=1], [have_apr_memcache=0]) |
38 | AC_SUBST(have_apr_memcache) | 44 | AC_SUBST(have_apr_memcache) |
39 | 45 | ||
40 | MODULE_CFLAGS="${LIBGNUTLS_CFLAGS} ${APR_MEMCACHE_CFLAGS} ${APXS_CFLAGS} ${AP_INCLUDES} ${APR_INCLUDES} ${APU_INCLUDES}" | 46 | MODULE_CFLAGS="${LIBGNUTLS_EXTRA_CFLAGS} ${APR_MEMCACHE_CFLAGS} ${APXS_CFLAGS} ${AP_INCLUDES} ${APR_INCLUDES} ${APU_INCLUDES}" |
41 | MODULE_LIBS="${APR_MEMCACHE_LIBS} ${LIBGNUTLS_LIBS}" | 47 | MODULE_LIBS="${APR_MEMCACHE_LIBS} ${LIBGNUTLS_EXTRA_LIBS}" |
42 | 48 | ||
43 | AC_SUBST(MODULE_CFLAGS) | 49 | AC_SUBST(MODULE_CFLAGS) |
44 | AC_SUBST(MODULE_LIBS) | 50 | AC_SUBST(MODULE_LIBS) |
45 | 51 | ||
46 | AC_CONFIG_FILES([Makefile src/Makefile include/mod_gnutls.h data/Makefile]) | 52 | AC_CONFIG_FILES([Makefile src/Makefile include/mod_gnutls.h]) |
47 | AC_OUTPUT | 53 | AC_OUTPUT |
48 | 54 | ||
49 | echo "---" | 55 | echo "---" |
diff --git a/include/mod_gnutls.h.in b/include/mod_gnutls.h.in index 6a311a3..db7e7dd 100644 --- a/include/mod_gnutls.h.in +++ b/include/mod_gnutls.h.in | |||
@@ -29,6 +29,8 @@ | |||
29 | 29 | ||
30 | #include <gcrypt.h> | 30 | #include <gcrypt.h> |
31 | #include <gnutls/gnutls.h> | 31 | #include <gnutls/gnutls.h> |
32 | #include <gnutls/extra.h> | ||
33 | #include <gnutls/openpgp.h> | ||
32 | #include <gnutls/x509.h> | 34 | #include <gnutls/x509.h> |
33 | 35 | ||
34 | #ifndef __mod_gnutls_h_inc | 36 | #ifndef __mod_gnutls_h_inc |
@@ -80,7 +82,10 @@ typedef struct | |||
80 | /* The maximum number of client CA certificates allowed. | 82 | /* The maximum number of client CA certificates allowed. |
81 | */ | 83 | */ |
82 | #define MAX_CA_CRTS 128 | 84 | #define MAX_CA_CRTS 128 |
83 | #define MAX_CIPHERS 16 | 85 | |
86 | /* The maximum number of certificates to send in a chain | ||
87 | */ | ||
88 | #define MAX_CHAIN_SIZE 8 | ||
84 | 89 | ||
85 | typedef struct | 90 | typedef struct |
86 | { | 91 | { |
@@ -88,8 +93,11 @@ typedef struct | |||
88 | gnutls_srp_server_credentials_t srp_creds; | 93 | gnutls_srp_server_credentials_t srp_creds; |
89 | gnutls_anon_server_credentials_t anon_creds; | 94 | gnutls_anon_server_credentials_t anon_creds; |
90 | char* cert_cn; | 95 | char* cert_cn; |
91 | gnutls_x509_crt_t cert_x509; | 96 | gnutls_x509_crt_t certs_x509[MAX_CHAIN_SIZE]; /* A certificate chain */ |
97 | unsigned int certs_x509_num; | ||
92 | gnutls_x509_privkey_t privkey_x509; | 98 | gnutls_x509_privkey_t privkey_x509; |
99 | gnutls_openpgp_crt_t cert_pgp; /* A certificate chain */ | ||
100 | gnutls_openpgp_privkey_t privkey_pgp; | ||
93 | int enabled; | 101 | int enabled; |
94 | /* whether to send the PEM encoded certificates | 102 | /* whether to send the PEM encoded certificates |
95 | * to CGIs | 103 | * to CGIs |
@@ -104,6 +112,7 @@ typedef struct | |||
104 | const char* srp_tpasswd_file; | 112 | const char* srp_tpasswd_file; |
105 | const char* srp_tpasswd_conf_file; | 113 | const char* srp_tpasswd_conf_file; |
106 | gnutls_x509_crt_t ca_list[MAX_CA_CRTS]; | 114 | gnutls_x509_crt_t ca_list[MAX_CA_CRTS]; |
115 | gnutls_openpgp_keyring_t pgp_list; | ||
107 | unsigned int ca_list_size; | 116 | unsigned int ca_list_size; |
108 | int client_verify_mode; | 117 | int client_verify_mode; |
109 | } mgs_srvconf_rec; | 118 | } mgs_srvconf_rec; |
@@ -250,6 +259,12 @@ const char *mgs_set_cert_file(cmd_parms * parms, void *dummy, | |||
250 | const char *mgs_set_key_file(cmd_parms * parms, void *dummy, | 259 | const char *mgs_set_key_file(cmd_parms * parms, void *dummy, |
251 | const char *arg); | 260 | const char *arg); |
252 | 261 | ||
262 | const char *mgs_set_pgpcert_file(cmd_parms * parms, void *dummy, | ||
263 | const char *arg); | ||
264 | |||
265 | const char *mgs_set_pgpkey_file(cmd_parms * parms, void *dummy, | ||
266 | const char *arg); | ||
267 | |||
253 | const char *mgs_set_cache(cmd_parms * parms, void *dummy, | 268 | const char *mgs_set_cache(cmd_parms * parms, void *dummy, |
254 | const char *type, const char* arg); | 269 | const char *type, const char* arg); |
255 | 270 | ||
@@ -262,6 +277,9 @@ const char *mgs_set_client_verify(cmd_parms * parms, void *dummy, | |||
262 | const char *mgs_set_client_ca_file(cmd_parms * parms, void *dummy, | 277 | const char *mgs_set_client_ca_file(cmd_parms * parms, void *dummy, |
263 | const char *arg); | 278 | const char *arg); |
264 | 279 | ||
280 | const char *mgs_set_keyring_file(cmd_parms * parms, void *dummy, | ||
281 | const char *arg); | ||
282 | |||
265 | const char *mgs_set_enabled(cmd_parms * parms, void *dummy, | 283 | const char *mgs_set_enabled(cmd_parms * parms, void *dummy, |
266 | const char *arg); | 284 | const char *arg); |
267 | const char *mgs_set_export_certificates_enabled(cmd_parms * parms, void *dummy, | 285 | const char *mgs_set_export_certificates_enabled(cmd_parms * parms, void *dummy, |
diff --git a/libgnutls.m4 b/libgnutls.m4 new file mode 100644 index 0000000..dd86431 --- /dev/null +++ b/libgnutls.m4 | |||
@@ -0,0 +1,174 @@ | |||
1 | dnl Autoconf macros for libgnutls-extra | ||
2 | dnl $id$ | ||
3 | |||
4 | # Modified for LIBGNUTLS_EXTRA -- nmav | ||
5 | # Configure paths for LIBGCRYPT | ||
6 | # Shamelessly stolen from the one of XDELTA by Owen Taylor | ||
7 | # Werner Koch 99-12-09 | ||
8 | |||
9 | dnl AM_PATH_LIBGNUTLS_EXTRA([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND ]]]) | ||
10 | dnl Test for libgnutls-extra, and define LIBGNUTLS_EXTRA_CFLAGS and LIBGNUTLS_EXTRA_LIBS | ||
11 | dnl | ||
12 | AC_DEFUN([AM_PATH_LIBGNUTLS_EXTRA], | ||
13 | [dnl | ||
14 | dnl Get the cflags and libraries from the libgnutls-extra-config script | ||
15 | dnl | ||
16 | AC_ARG_WITH(libgnutls-extra-prefix, | ||
17 | [ --with-libgnutls-extra-prefix=PFX Prefix where libgnutls-extra is installed (optional)], | ||
18 | libgnutls_extra_config_prefix="$withval", libgnutls_extra_config_prefix="") | ||
19 | |||
20 | if test x$libgnutls_extra_config_prefix != x ; then | ||
21 | if test x${LIBGNUTLS_EXTRA_CONFIG+set} != xset ; then | ||
22 | LIBGNUTLS_EXTRA_CONFIG=$libgnutls_extra_config_prefix/bin/libgnutls-extra-config | ||
23 | fi | ||
24 | fi | ||
25 | |||
26 | AC_PATH_PROG(LIBGNUTLS_EXTRA_CONFIG, libgnutls-extra-config, no) | ||
27 | min_libgnutls_version=ifelse([$1], ,0.1.0,$1) | ||
28 | AC_MSG_CHECKING(for libgnutls - version >= $min_libgnutls_version) | ||
29 | no_libgnutls="" | ||
30 | if test "$LIBGNUTLS_EXTRA_CONFIG" = "no" ; then | ||
31 | no_libgnutls=yes | ||
32 | else | ||
33 | LIBGNUTLS_EXTRA_CFLAGS=`$LIBGNUTLS_EXTRA_CONFIG $libgnutls_extra_config_args --cflags` | ||
34 | LIBGNUTLS_EXTRA_LIBS=`$LIBGNUTLS_EXTRA_CONFIG $libgnutls_extra_config_args --libs` | ||
35 | libgnutls_extra_config_version=`$LIBGNUTLS_EXTRA_CONFIG $libgnutls_extra_config_args --version` | ||
36 | |||
37 | |||
38 | ac_save_CFLAGS="$CFLAGS" | ||
39 | ac_save_LIBS="$LIBS" | ||
40 | CFLAGS="$CFLAGS $LIBGNUTLS_EXTRA_CFLAGS" | ||
41 | LIBS="$LIBS $LIBGNUTLS_EXTRA_LIBS" | ||
42 | dnl | ||
43 | dnl Now check if the installed libgnutls is sufficiently new. Also sanity | ||
44 | dnl checks the results of libgnutls-extra-config to some extent | ||
45 | dnl | ||
46 | rm -f conf.libgnutlstest | ||
47 | AC_TRY_RUN([ | ||
48 | #include <stdio.h> | ||
49 | #include <stdlib.h> | ||
50 | #include <string.h> | ||
51 | #include <gnutls/extra.h> | ||
52 | |||
53 | int | ||
54 | main () | ||
55 | { | ||
56 | system ("touch conf.libgnutlstest"); | ||
57 | |||
58 | if( strcmp( gnutls_extra_check_version(NULL), "$libgnutls_extra_config_version" ) ) | ||
59 | { | ||
60 | printf("\n*** 'libgnutls-extra-config --version' returned %s, but LIBGNUTLS_EXTRA (%s)\n", | ||
61 | "$libgnutls_extra_config_version", gnutls_extra_check_version(NULL) ); | ||
62 | printf("*** was found! If libgnutls-extra-config was correct, then it is best\n"); | ||
63 | printf("*** to remove the old version of LIBGNUTLS_EXTRA. You may also be able to fix the error\n"); | ||
64 | printf("*** by modifying your LD_LIBRARY_PATH enviroment variable, or by editing\n"); | ||
65 | printf("*** /etc/ld.so.conf. Make sure you have run ldconfig if that is\n"); | ||
66 | printf("*** required on your system.\n"); | ||
67 | printf("*** If libgnutls-extra-config was wrong, set the environment variable LIBGNUTLS_EXTRA_CONFIG\n"); | ||
68 | printf("*** to point to the correct copy of libgnutls-extra-config, and remove the file config.cache\n"); | ||
69 | printf("*** before re-running configure\n"); | ||
70 | } | ||
71 | else if ( strcmp(gnutls_extra_check_version(NULL), LIBGNUTLS_EXTRA_VERSION ) ) | ||
72 | { | ||
73 | printf("\n*** LIBGNUTLS_EXTRA header file (version %s) does not match\n", LIBGNUTLS_EXTRA_VERSION); | ||
74 | printf("*** library (version %s). This is may be due to a different version of gnutls\n", gnutls_extra_check_version(NULL) ); | ||
75 | printf("*** and gnutls-extra.\n"); | ||
76 | } | ||
77 | else | ||
78 | { | ||
79 | if ( gnutls_extra_check_version( "$min_libgnutls_version" ) ) | ||
80 | { | ||
81 | return 0; | ||
82 | } | ||
83 | else | ||
84 | { | ||
85 | printf("no\n*** An old version of LIBGNUTLS_EXTRA (%s) was found.\n", | ||
86 | gnutls_extra_check_version(NULL) ); | ||
87 | printf("*** You need a version of LIBGNUTLS_EXTRA newer than %s. The latest version of\n", | ||
88 | "$min_libgnutls_version" ); | ||
89 | printf("*** LIBGNUTLS_EXTRA is always available from ftp://gnutls.hellug.gr/pub/gnutls.\n"); | ||
90 | printf("*** \n"); | ||
91 | printf("*** If you have already installed a sufficiently new version, this error\n"); | ||
92 | printf("*** probably means that the wrong copy of the libgnutls-extra-config shell script is\n"); | ||
93 | printf("*** being found. The easiest way to fix this is to remove the old version\n"); | ||
94 | printf("*** of LIBGNUTLS_EXTRA, but you can also set the LIBGNUTLS_EXTRA_CONFIG environment to point to the\n"); | ||
95 | printf("*** correct copy of libgnutls-extra-config. (In this case, you will have to\n"); | ||
96 | printf("*** modify your LD_LIBRARY_PATH enviroment variable, or edit /etc/ld.so.conf\n"); | ||
97 | printf("*** so that the correct libraries are found at run-time))\n"); | ||
98 | } | ||
99 | } | ||
100 | return 1; | ||
101 | } | ||
102 | ],, no_libgnutls=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"]) | ||
103 | CFLAGS="$ac_save_CFLAGS" | ||
104 | LIBS="$ac_save_LIBS" | ||
105 | fi | ||
106 | |||
107 | if test "x$no_libgnutls" = x ; then | ||
108 | AC_MSG_RESULT(yes) | ||
109 | ifelse([$2], , :, [$2]) | ||
110 | else | ||
111 | if test -f conf.libgnutlstest ; then | ||
112 | : | ||
113 | else | ||
114 | AC_MSG_RESULT(no) | ||
115 | fi | ||
116 | if test "$LIBGNUTLS_EXTRA_CONFIG" = "no" ; then | ||
117 | echo "*** The libgnutls-extra-config script installed by LIBGNUTLS_EXTRA could not be found" | ||
118 | echo "*** If LIBGNUTLS_EXTRA was installed in PREFIX, make sure PREFIX/bin is in" | ||
119 | echo "*** your path, or set the LIBGNUTLS_EXTRA_CONFIG environment variable to the" | ||
120 | echo "*** full path to libgnutls-extra-config." | ||
121 | else | ||
122 | if test -f conf.libgnutlstest ; then | ||
123 | : | ||
124 | else | ||
125 | echo "*** Could not run libgnutls test program, checking why..." | ||
126 | CFLAGS="$CFLAGS $LIBGNUTLS_EXTRA_CFLAGS" | ||
127 | LIBS="$LIBS $LIBGNUTLS_EXTRA_LIBS" | ||
128 | AC_TRY_LINK([ | ||
129 | #include <stdio.h> | ||
130 | #include <stdlib.h> | ||
131 | #include <string.h> | ||
132 | #include <gnutls/extra.h> | ||
133 | ], [ return !!gnutls_extra_check_version(NULL); ], | ||
134 | [ echo "*** The test program compiled, but did not run. This usually means" | ||
135 | echo "*** that the run-time linker is not finding LIBGNUTLS_EXTRA or finding the wrong" | ||
136 | echo "*** version of LIBGNUTLS_EXTRA. If it is not finding LIBGNUTLS_EXTRA, you'll need to set your" | ||
137 | echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point" | ||
138 | echo "*** to the installed location Also, make sure you have run ldconfig if that" | ||
139 | echo "*** is required on your system" | ||
140 | echo "***" | ||
141 | echo "*** If you have an old version installed, it is best to remove it, although" | ||
142 | echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH" | ||
143 | echo "***" ], | ||
144 | [ echo "*** The test program failed to compile or link. See the file config.log for the" | ||
145 | echo "*** exact error that occured. This usually means LIBGNUTLS_EXTRA was incorrectly installed" | ||
146 | echo "*** or that you have moved LIBGNUTLS_EXTRA since it was installed. In the latter case, you" | ||
147 | echo "*** may want to edit the libgnutls-extra-config script: $LIBGNUTLS_EXTRA_CONFIG" ]) | ||
148 | CFLAGS="$ac_save_CFLAGS" | ||
149 | LIBS="$ac_save_LIBS" | ||
150 | fi | ||
151 | fi | ||
152 | LIBGNUTLS_EXTRA_CFLAGS="" | ||
153 | LIBGNUTLS_EXTRA_LIBS="" | ||
154 | ifelse([$3], , :, [$3]) | ||
155 | fi | ||
156 | rm -f conf.libgnutlstest | ||
157 | AC_SUBST(LIBGNUTLS_EXTRA_CFLAGS) | ||
158 | AC_SUBST(LIBGNUTLS_EXTRA_LIBS) | ||
159 | |||
160 | LIBGNUTLS_LIBS=$LIBGNUTLS_EXTRA_LIBS | ||
161 | LIBGNUTLS_CFLAGS=$LIBGNUTLS_EXTRA_CFLAGS | ||
162 | LIBGNUTLS_VERSION=`$LIBGNUTLS_EXTRA_CONFIG $libgnutls_extra_config_args --version` | ||
163 | LIBGNUTLS_PREFIX="`$LIBGNUTLS_EXTRA_CONFIG $libgnutls_extra_config_args --prefix`" | ||
164 | GNUTLS_CERTTOOL="${LIBGNUTLS_PREFIX}/bin/certtool" | ||
165 | |||
166 | AC_SUBST(LIBGNUTLS_CFLAGS) | ||
167 | AC_SUBST(LIBGNUTLS_LIBS) | ||
168 | AC_SUBST(LIBGNUTLS_VERSION) | ||
169 | AC_SUBST(LIBGNUTLS_PREFIX) | ||
170 | AC_SUBST(LIBGNUTLS_CERTTOOL) | ||
171 | |||
172 | ]) | ||
173 | |||
174 | dnl *-*wedit:notab*-* Please keep this as the last line. | ||
diff --git a/src/gnutls_cache.c b/src/gnutls_cache.c index 86b843e..83e7bb5 100644 --- a/src/gnutls_cache.c +++ b/src/gnutls_cache.c | |||
@@ -34,18 +34,16 @@ | |||
34 | 34 | ||
35 | 35 | ||
36 | #define MC_TAG "mod_gnutls:" | 36 | #define MC_TAG "mod_gnutls:" |
37 | #define MC_TAG_LEN \ | 37 | #define MC_TAG_LEN sizeof(MC_TAG) |
38 | (sizeof(MC_TAG)) | ||
39 | #define STR_SESSION_LEN (GNUTLS_SESSION_ID_STRING_LEN + MC_TAG_LEN) | 38 | #define STR_SESSION_LEN (GNUTLS_SESSION_ID_STRING_LEN + MC_TAG_LEN) |
40 | 39 | ||
41 | #if 0 | 40 | char *mgs_session_id2sz(unsigned char *id, int idlen, |
42 | static char *gnutls_session_id2sz(unsigned char *id, int idlen, | ||
43 | char *str, int strsize) | 41 | char *str, int strsize) |
44 | { | 42 | { |
45 | char *cp; | 43 | char *cp; |
46 | int n; | 44 | int n; |
47 | 45 | ||
48 | cp = apr_cpystrn(str, MC_TAG, MC_TAG_LEN); | 46 | cp = str; |
49 | for (n = 0; n < idlen && n < GNUTLS_MAX_SESSION_ID; n++) { | 47 | for (n = 0; n < idlen && n < GNUTLS_MAX_SESSION_ID; n++) { |
50 | apr_snprintf(cp, strsize - (cp-str), "%02X", id[n]); | 48 | apr_snprintf(cp, strsize - (cp-str), "%02X", id[n]); |
51 | cp += 2; | 49 | cp += 2; |
@@ -53,7 +51,27 @@ static char *gnutls_session_id2sz(unsigned char *id, int idlen, | |||
53 | *cp = '\0'; | 51 | *cp = '\0'; |
54 | return str; | 52 | return str; |
55 | } | 53 | } |
56 | #endif | 54 | |
55 | |||
56 | /* Name the Session ID as: | ||
57 | * server:port.SessionID | ||
58 | * to disallow resuming sessions on different servers | ||
59 | */ | ||
60 | static int mgs_session_id2dbm(conn_rec* c, unsigned char *id, int idlen, | ||
61 | apr_datum_t* dbmkey) | ||
62 | { | ||
63 | char buf[STR_SESSION_LEN]; | ||
64 | char *sz; | ||
65 | |||
66 | sz = mgs_session_id2sz(id, idlen, buf, sizeof(buf)); | ||
67 | if (sz == NULL) | ||
68 | return -1; | ||
69 | |||
70 | dbmkey->dptr = apr_psprintf(c->pool, "%s:%d.%s", c->base_server->server_hostname, c->base_server->port, sz); | ||
71 | dbmkey->dsize = strlen( dbmkey->dptr); | ||
72 | |||
73 | return 0; | ||
74 | } | ||
57 | 75 | ||
58 | #define CTIME "%b %d %k:%M:%S %Y %Z" | 76 | #define CTIME "%b %d %k:%M:%S %Y %Z" |
59 | char *mgs_time2sz(time_t in_time, char *str, int strsize) | 77 | char *mgs_time2sz(time_t in_time, char *str, int strsize) |
@@ -70,24 +88,23 @@ char *mgs_time2sz(time_t in_time, char *str, int strsize) | |||
70 | return str; | 88 | return str; |
71 | } | 89 | } |
72 | 90 | ||
73 | char *mgs_session_id2sz(unsigned char *id, int idlen, | 91 | #if HAVE_APR_MEMCACHE |
74 | char *str, int strsize) | 92 | /* Name the Session ID as: |
93 | * server:port.SessionID | ||
94 | * to disallow resuming sessions on different servers | ||
95 | */ | ||
96 | static char* mgs_session_id2mc(conn_rec* c, unsigned char *id, int idlen) | ||
75 | { | 97 | { |
76 | char *cp; | 98 | char buf[STR_SESSION_LEN]; |
77 | int n; | 99 | char *sz; |
78 | 100 | ||
79 | cp = str; | 101 | sz = mgs_session_id2sz(id, idlen, buf, sizeof(buf)); |
80 | for (n = 0; n < idlen && n < GNUTLS_MAX_SESSION_ID; n++) { | 102 | if (sz == NULL) |
81 | apr_snprintf(cp, strsize - (cp-str), "%02X", id[n]); | 103 | return NULL; |
82 | cp += 2; | 104 | |
83 | } | 105 | return apr_psprintf(c->pool, MC_TAG"%s:%d.%s", c->base_server->server_hostname, c->base_server->port, sz); |
84 | *cp = '\0'; | ||
85 | return str; | ||
86 | } | 106 | } |
87 | 107 | ||
88 | |||
89 | #if HAVE_APR_MEMCACHE | ||
90 | |||
91 | /** | 108 | /** |
92 | * GnuTLS Session Cache using libmemcached | 109 | * GnuTLS Session Cache using libmemcached |
93 | * | 110 | * |
@@ -184,11 +201,10 @@ static int mc_cache_store(void* baton, gnutls_datum_t key, | |||
184 | { | 201 | { |
185 | apr_status_t rv = APR_SUCCESS; | 202 | apr_status_t rv = APR_SUCCESS; |
186 | mgs_handle_t *ctxt = baton; | 203 | mgs_handle_t *ctxt = baton; |
187 | char buf[STR_SESSION_LEN]; | ||
188 | char* strkey = NULL; | 204 | char* strkey = NULL; |
189 | apr_uint32_t timeout; | 205 | apr_uint32_t timeout; |
190 | 206 | ||
191 | strkey = gnutls_session_id2sz(key.data, key.size, buf, sizeof(buf)); | 207 | strkey = mgs_session_id2mc(ctxt->c, key.data, key.size); |
192 | if(!strkey) | 208 | if(!strkey) |
193 | return -1; | 209 | return -1; |
194 | 210 | ||
@@ -211,13 +227,12 @@ static gnutls_datum_t mc_cache_fetch(void* baton, gnutls_datum_t key) | |||
211 | { | 227 | { |
212 | apr_status_t rv = APR_SUCCESS; | 228 | apr_status_t rv = APR_SUCCESS; |
213 | mgs_handle_t *ctxt = baton; | 229 | mgs_handle_t *ctxt = baton; |
214 | char buf[STR_SESSION_LEN]; | ||
215 | char* strkey = NULL; | 230 | char* strkey = NULL; |
216 | char* value; | 231 | char* value; |
217 | apr_size_t value_len; | 232 | apr_size_t value_len; |
218 | gnutls_datum_t data = { NULL, 0 }; | 233 | gnutls_datum_t data = { NULL, 0 }; |
219 | 234 | ||
220 | strkey = gnutls_session_id2sz(key.data, key.size, buf, sizeof(buf)); | 235 | strkey = mgs_session_id2mc(ctxt->c, key.data, key.size); |
221 | if (!strkey) { | 236 | if (!strkey) { |
222 | return data; | 237 | return data; |
223 | } | 238 | } |
@@ -252,10 +267,9 @@ static int mc_cache_delete(void* baton, gnutls_datum_t key) | |||
252 | { | 267 | { |
253 | apr_status_t rv = APR_SUCCESS; | 268 | apr_status_t rv = APR_SUCCESS; |
254 | mgs_handle_t *ctxt = baton; | 269 | mgs_handle_t *ctxt = baton; |
255 | char buf[STR_SESSION_LEN]; | ||
256 | char* strkey = NULL; | 270 | char* strkey = NULL; |
257 | 271 | ||
258 | strkey = gnutls_session_id2sz(key.data, key.size, buf, sizeof(buf)); | 272 | strkey = mgs_session_id2mc(ctxt->c, key.data, key.size); |
259 | if(!strkey) | 273 | if(!strkey) |
260 | return -1; | 274 | return -1; |
261 | 275 | ||
@@ -366,8 +380,8 @@ static gnutls_datum_t dbm_cache_fetch(void* baton, gnutls_datum_t key) | |||
366 | mgs_handle_t *ctxt = baton; | 380 | mgs_handle_t *ctxt = baton; |
367 | apr_status_t rv; | 381 | apr_status_t rv; |
368 | 382 | ||
369 | dbmkey.dptr = (void*)key.data; | 383 | if (mgs_session_id2dbm(ctxt->c, key.data, key.size, &dbmkey) < 0) |
370 | dbmkey.dsize = key.size; | 384 | return data; |
371 | 385 | ||
372 | rv = apr_dbm_open(&dbm, ctxt->sc->cache_config, | 386 | rv = apr_dbm_open(&dbm, ctxt->sc->cache_config, |
373 | APR_DBM_RWCREATE, SSL_DBM_FILE_MODE, ctxt->c->pool); | 387 | APR_DBM_RWCREATE, SSL_DBM_FILE_MODE, ctxt->c->pool); |
@@ -413,9 +427,9 @@ static int dbm_cache_store(void* baton, gnutls_datum_t key, | |||
413 | mgs_handle_t *ctxt = baton; | 427 | mgs_handle_t *ctxt = baton; |
414 | apr_status_t rv; | 428 | apr_status_t rv; |
415 | apr_time_t expiry; | 429 | apr_time_t expiry; |
416 | 430 | ||
417 | dbmkey.dptr = (char *)key.data; | 431 | if (mgs_session_id2dbm(ctxt->c, key.data, key.size, &dbmkey) < 0) |
418 | dbmkey.dsize = key.size; | 432 | return -1; |
419 | 433 | ||
420 | /* create DBM value */ | 434 | /* create DBM value */ |
421 | dbmval.dsize = data.size + sizeof(apr_time_t); | 435 | dbmval.dsize = data.size + sizeof(apr_time_t); |
@@ -467,9 +481,9 @@ static int dbm_cache_delete(void* baton, gnutls_datum_t key) | |||
467 | apr_datum_t dbmkey; | 481 | apr_datum_t dbmkey; |
468 | mgs_handle_t *ctxt = baton; | 482 | mgs_handle_t *ctxt = baton; |
469 | apr_status_t rv; | 483 | apr_status_t rv; |
470 | 484 | ||
471 | dbmkey.dptr = (char *)key.data; | 485 | if (mgs_session_id2dbm(ctxt->c, key.data, key.size, &dbmkey) < 0) |
472 | dbmkey.dsize = key.size; | 486 | return -1; |
473 | 487 | ||
474 | rv = apr_dbm_open(&dbm, ctxt->sc->cache_config, | 488 | rv = apr_dbm_open(&dbm, ctxt->sc->cache_config, |
475 | APR_DBM_RWCREATE, SSL_DBM_FILE_MODE, ctxt->c->pool); | 489 | APR_DBM_RWCREATE, SSL_DBM_FILE_MODE, ctxt->c->pool); |
diff --git a/src/gnutls_config.c b/src/gnutls_config.c index 7b5a42b..f08512e 100644 --- a/src/gnutls_config.c +++ b/src/gnutls_config.c | |||
@@ -1,5 +1,6 @@ | |||
1 | /** | 1 | /** |
2 | * Copyright 2004-2005 Paul Querna | 2 | * Copyright 2004-2005 Paul Querna |
3 | * Copyright 2007 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. |
@@ -151,15 +152,10 @@ const char *mgs_set_cert_file(cmd_parms * parms, void *dummy, | |||
151 | "Certificate '%s'", file); | 152 | "Certificate '%s'", file); |
152 | } | 153 | } |
153 | 154 | ||
154 | ret = gnutls_x509_crt_init(&sc->cert_x509); | 155 | sc->certs_x509_num = MAX_CHAIN_SIZE; |
155 | if (ret < 0) { | ||
156 | return apr_psprintf(parms->pool, "GnuTLS: Failed to initialize" | ||
157 | ": (%d) %s", ret, gnutls_strerror(ret)); | ||
158 | } | ||
159 | |||
160 | ret = | 156 | ret = |
161 | gnutls_x509_crt_import(sc->cert_x509, &data, GNUTLS_X509_FMT_PEM); | 157 | gnutls_x509_crt_list_import(sc->certs_x509, &sc->certs_x509_num, &data, GNUTLS_X509_FMT_PEM, 0); |
162 | if (ret != 0) { | 158 | if (ret < 0) { |
163 | return apr_psprintf(parms->pool, "GnuTLS: Failed to Import " | 159 | return apr_psprintf(parms->pool, "GnuTLS: Failed to Import " |
164 | "Certificate '%s': (%d) %s", file, ret, | 160 | "Certificate '%s': (%d) %s", file, ret, |
165 | gnutls_strerror(ret)); | 161 | gnutls_strerror(ret)); |
@@ -207,6 +203,84 @@ const char *mgs_set_key_file(cmd_parms * parms, void *dummy, | |||
207 | return NULL; | 203 | return NULL; |
208 | } | 204 | } |
209 | 205 | ||
206 | const char *mgs_set_pgpcert_file(cmd_parms * parms, void *dummy, | ||
207 | const char *arg) | ||
208 | { | ||
209 | int ret; | ||
210 | gnutls_datum_t data; | ||
211 | const char *file; | ||
212 | apr_pool_t *spool; | ||
213 | mgs_srvconf_rec *sc = | ||
214 | (mgs_srvconf_rec *) ap_get_module_config(parms->server-> | ||
215 | module_config, | ||
216 | &gnutls_module); | ||
217 | apr_pool_create(&spool, parms->pool); | ||
218 | |||
219 | file = ap_server_root_relative(spool, arg); | ||
220 | |||
221 | if (load_datum_from_file(spool, file, &data) != 0) { | ||
222 | return apr_psprintf(parms->pool, "GnuTLS: Error Reading " | ||
223 | "Certificate '%s'", file); | ||
224 | } | ||
225 | |||
226 | ret = gnutls_openpgp_crt_init( &sc->cert_pgp); | ||
227 | if (ret < 0) { | ||
228 | return apr_psprintf(parms->pool, "GnuTLS: Failed to Init " | ||
229 | "PGP Certificate: (%d) %s", ret, | ||
230 | gnutls_strerror(ret)); | ||
231 | } | ||
232 | |||
233 | ret = | ||
234 | gnutls_openpgp_crt_import(sc->cert_pgp, &data, GNUTLS_OPENPGP_FMT_BASE64); | ||
235 | if (ret < 0) { | ||
236 | return apr_psprintf(parms->pool, "GnuTLS: Failed to Import " | ||
237 | "PGP Certificate '%s': (%d) %s", file, ret, | ||
238 | gnutls_strerror(ret)); | ||
239 | } | ||
240 | |||
241 | apr_pool_destroy(spool); | ||
242 | return NULL; | ||
243 | } | ||
244 | |||
245 | const char *mgs_set_pgpkey_file(cmd_parms * parms, void *dummy, | ||
246 | const char *arg) | ||
247 | { | ||
248 | int ret; | ||
249 | gnutls_datum_t data; | ||
250 | const char *file; | ||
251 | apr_pool_t *spool; | ||
252 | mgs_srvconf_rec *sc = | ||
253 | (mgs_srvconf_rec *) ap_get_module_config(parms->server-> | ||
254 | module_config, | ||
255 | &gnutls_module); | ||
256 | apr_pool_create(&spool, parms->pool); | ||
257 | |||
258 | file = ap_server_root_relative(spool, arg); | ||
259 | |||
260 | if (load_datum_from_file(spool, file, &data) != 0) { | ||
261 | return apr_psprintf(parms->pool, "GnuTLS: Error Reading " | ||
262 | "Private Key '%s'", file); | ||
263 | } | ||
264 | |||
265 | ret = gnutls_openpgp_privkey_init(&sc->privkey_pgp); | ||
266 | if (ret < 0) { | ||
267 | return apr_psprintf(parms->pool, "GnuTLS: Failed to initialize" | ||
268 | ": (%d) %s", ret, gnutls_strerror(ret)); | ||
269 | } | ||
270 | |||
271 | ret = | ||
272 | gnutls_openpgp_privkey_import(sc->privkey_pgp, &data, | ||
273 | GNUTLS_OPENPGP_FMT_BASE64, NULL, 0); | ||
274 | if (ret != 0) { | ||
275 | return apr_psprintf(parms->pool, "GnuTLS: Failed to Import " | ||
276 | "PGP Private Key '%s': (%d) %s", file, ret, | ||
277 | gnutls_strerror(ret)); | ||
278 | } | ||
279 | apr_pool_destroy(spool); | ||
280 | return NULL; | ||
281 | } | ||
282 | |||
283 | |||
210 | const char *mgs_set_srp_tpasswd_file(cmd_parms * parms, void *dummy, | 284 | const char *mgs_set_srp_tpasswd_file(cmd_parms * parms, void *dummy, |
211 | const char *arg) | 285 | const char *arg) |
212 | { | 286 | { |
@@ -355,6 +429,44 @@ const char *mgs_set_client_ca_file(cmd_parms * parms, void *dummy, | |||
355 | return NULL; | 429 | return NULL; |
356 | } | 430 | } |
357 | 431 | ||
432 | const char *mgs_set_keyring_file(cmd_parms * parms, void *dummy, | ||
433 | const char *arg) | ||
434 | { | ||
435 | int rv; | ||
436 | const char *file; | ||
437 | apr_pool_t *spool; | ||
438 | gnutls_datum_t data; | ||
439 | |||
440 | mgs_srvconf_rec *sc = | ||
441 | (mgs_srvconf_rec *) ap_get_module_config(parms->server-> | ||
442 | module_config, | ||
443 | &gnutls_module); | ||
444 | apr_pool_create(&spool, parms->pool); | ||
445 | |||
446 | file = ap_server_root_relative(spool, arg); | ||
447 | |||
448 | if (load_datum_from_file(spool, file, &data) != 0) { | ||
449 | return apr_psprintf(parms->pool, "GnuTLS: Error Reading " | ||
450 | "Keyring File '%s'", file); | ||
451 | } | ||
452 | |||
453 | rv = gnutls_openpgp_keyring_init(&sc->pgp_list); | ||
454 | if (rv < 0) { | ||
455 | return apr_psprintf(parms->pool, "GnuTLS: Failed to initialize" | ||
456 | "keyring: (%d) %s", rv, gnutls_strerror(rv)); | ||
457 | } | ||
458 | |||
459 | rv = gnutls_openpgp_keyring_import(sc->pgp_list, &data, GNUTLS_OPENPGP_FMT_BASE64); | ||
460 | if (rv < 0) { | ||
461 | return apr_psprintf(parms->pool, "GnuTLS: Failed to load " | ||
462 | "Keyring File '%s': (%d) %s", file, rv, | ||
463 | gnutls_strerror(rv)); | ||
464 | } | ||
465 | |||
466 | apr_pool_destroy(spool); | ||
467 | return NULL; | ||
468 | } | ||
469 | |||
358 | const char *mgs_set_enabled(cmd_parms * parms, void *dummy, | 470 | const char *mgs_set_enabled(cmd_parms * parms, void *dummy, |
359 | const char *arg) | 471 | const char *arg) |
360 | { | 472 | { |
@@ -440,7 +552,8 @@ void *mgs_config_server_create(apr_pool_t * p, server_rec * s) | |||
440 | sc->srp_tpasswd_conf_file = NULL; | 552 | sc->srp_tpasswd_conf_file = NULL; |
441 | sc->srp_tpasswd_file = NULL; | 553 | sc->srp_tpasswd_file = NULL; |
442 | sc->privkey_x509 = NULL; | 554 | sc->privkey_x509 = NULL; |
443 | sc->cert_x509 = NULL; | 555 | memset( sc->certs_x509, 0, sizeof(sc->certs_x509)); |
556 | sc->certs_x509_num = 0; | ||
444 | sc->cache_timeout = apr_time_from_sec(300); | 557 | sc->cache_timeout = apr_time_from_sec(300); |
445 | sc->cache_type = mgs_cache_dbm; | 558 | sc->cache_type = mgs_cache_dbm; |
446 | sc->cache_config = ap_server_root_relative(p, "conf/gnutls_cache"); | 559 | sc->cache_config = ap_server_root_relative(p, "conf/gnutls_cache"); |
diff --git a/src/gnutls_hooks.c b/src/gnutls_hooks.c index 4364add..26917b8 100644 --- a/src/gnutls_hooks.c +++ b/src/gnutls_hooks.c | |||
@@ -36,7 +36,10 @@ static int mpm_is_threaded; | |||
36 | 36 | ||
37 | static int mgs_cert_verify(request_rec * r, mgs_handle_t * ctxt); | 37 | static int mgs_cert_verify(request_rec * r, mgs_handle_t * ctxt); |
38 | /* use side==0 for server and side==1 for client */ | 38 | /* use side==0 for server and side==1 for client */ |
39 | static void mgs_add_common_cert_vars(request_rec * r, gnutls_x509_crt cert, | 39 | static void mgs_add_common_cert_vars(request_rec * r, gnutls_x509_crt_t cert, |
40 | int side, | ||
41 | int export_certificates_enabled); | ||
42 | static void mgs_add_common_pgpcert_vars(request_rec * r, gnutls_openpgp_crt_t cert, | ||
40 | int side, | 43 | int side, |
41 | int export_certificates_enabled); | 44 | int export_certificates_enabled); |
42 | 45 | ||
@@ -68,9 +71,23 @@ int ret; | |||
68 | mpm_is_threaded = 0; | 71 | mpm_is_threaded = 0; |
69 | #endif | 72 | #endif |
70 | 73 | ||
74 | if (gnutls_check_version(LIBGNUTLS_VERSION)==NULL) { | ||
75 | fprintf(stderr, "gnutls_check_version() failed. Required: gnutls-%s Found: gnutls-%s\n", | ||
76 | LIBGNUTLS_VERSION, gnutls_check_version(NULL)); | ||
77 | return -3; | ||
78 | } | ||
79 | |||
71 | ret = gnutls_global_init(); | 80 | ret = gnutls_global_init(); |
72 | if (ret < 0) /* FIXME: can we print here? */ | 81 | if (ret < 0) { |
73 | exit(ret); | 82 | fprintf(stderr, "gnutls_global_init: %s\n", gnutls_strerror(ret)); |
83 | return -3; | ||
84 | } | ||
85 | |||
86 | ret = gnutls_global_init_extra(); | ||
87 | if (ret < 0) { | ||
88 | fprintf(stderr, "gnutls_global_init_extra: %s\n", gnutls_strerror(ret)); | ||
89 | return -3; | ||
90 | } | ||
74 | 91 | ||
75 | apr_pool_cleanup_register(pconf, NULL, mgs_cleanup_pre_config, | 92 | apr_pool_cleanup_register(pconf, NULL, mgs_cleanup_pre_config, |
76 | apr_pool_cleanup_null); | 93 | apr_pool_cleanup_null); |
@@ -82,19 +99,18 @@ int ret; | |||
82 | 99 | ||
83 | gnutls_global_set_log_level(9); | 100 | gnutls_global_set_log_level(9); |
84 | gnutls_global_set_log_function(gnutls_debug_log_all); | 101 | gnutls_global_set_log_function(gnutls_debug_log_all); |
102 | apr_file_printf(debug_log_fp, "gnutls: %s\n", gnutls_check_version(NULL)); | ||
85 | #endif | 103 | #endif |
86 | 104 | ||
87 | return OK; | 105 | return OK; |
88 | } | 106 | } |
89 | 107 | ||
90 | /* We don't support openpgp certificates, yet */ | ||
91 | const static int cert_type_prio[2] = { GNUTLS_CRT_X509, 0 }; | ||
92 | |||
93 | static int mgs_select_virtual_server_cb(gnutls_session_t session) | 108 | static int mgs_select_virtual_server_cb(gnutls_session_t session) |
94 | { | 109 | { |
95 | mgs_handle_t *ctxt; | 110 | mgs_handle_t *ctxt; |
96 | mgs_srvconf_rec *tsc; | 111 | mgs_srvconf_rec *tsc; |
97 | int ret; | 112 | int ret; |
113 | int cprio[2]; | ||
98 | 114 | ||
99 | ctxt = gnutls_transport_get_ptr(session); | 115 | ctxt = gnutls_transport_get_ptr(session); |
100 | 116 | ||
@@ -126,17 +142,22 @@ static int mgs_select_virtual_server_cb(gnutls_session_t session) | |||
126 | * negotiation. | 142 | * negotiation. |
127 | */ | 143 | */ |
128 | ret = gnutls_priority_set(session, ctxt->sc->priorities); | 144 | ret = gnutls_priority_set(session, ctxt->sc->priorities); |
129 | gnutls_certificate_type_set_priority(session, cert_type_prio); | ||
130 | |||
131 | |||
132 | /* actually it shouldn't fail since we have checked at startup */ | 145 | /* actually it shouldn't fail since we have checked at startup */ |
133 | if (ret < 0) | 146 | if (ret < 0) |
134 | return ret; | 147 | return ret; |
135 | 148 | ||
136 | /* allow separate caches per virtual host. Actually allowing the same is a | 149 | /* If both certificate types are not present disallow them from |
137 | * bad idea, since they might have different security requirements. | 150 | * being negotiated. |
138 | */ | 151 | */ |
139 | mgs_cache_session_init(ctxt); | 152 | if (ctxt->sc->certs_x509[0] != NULL && ctxt->sc->cert_pgp == NULL) { |
153 | cprio[0] = GNUTLS_CRT_X509; | ||
154 | cprio[1] = 0; | ||
155 | gnutls_certificate_type_set_priority( session, cprio); | ||
156 | } else if (ctxt->sc->cert_pgp != NULL && ctxt->sc->certs_x509[0]==NULL) { | ||
157 | cprio[0] = GNUTLS_CRT_OPENPGP; | ||
158 | cprio[1] = 0; | ||
159 | gnutls_certificate_type_set_priority( session, cprio); | ||
160 | } | ||
140 | 161 | ||
141 | return 0; | 162 | return 0; |
142 | } | 163 | } |
@@ -147,15 +168,31 @@ static int cert_retrieve_fn(gnutls_session_t session, gnutls_retr_st * ret) | |||
147 | 168 | ||
148 | ctxt = gnutls_transport_get_ptr(session); | 169 | ctxt = gnutls_transport_get_ptr(session); |
149 | 170 | ||
150 | ret->type = GNUTLS_CRT_X509; | 171 | if (gnutls_certificate_type_get( session) == GNUTLS_CRT_X509) { |
151 | ret->ncerts = 1; | 172 | ret->type = GNUTLS_CRT_X509; |
152 | ret->deinit_all = 0; | 173 | ret->ncerts = ctxt->sc->certs_x509_num; |
174 | ret->deinit_all = 0; | ||
175 | |||
176 | ret->cert.x509 = ctxt->sc->certs_x509; | ||
177 | ret->key.x509 = ctxt->sc->privkey_x509; | ||
178 | |||
179 | return 0; | ||
180 | } else if (gnutls_certificate_type_get( session) == GNUTLS_CRT_OPENPGP) { | ||
181 | ret->type = GNUTLS_CRT_OPENPGP; | ||
182 | ret->ncerts = 1; | ||
183 | ret->deinit_all = 0; | ||
184 | |||
185 | ret->cert.pgp = ctxt->sc->cert_pgp; | ||
186 | ret->key.pgp = ctxt->sc->privkey_pgp; | ||
187 | |||
188 | return 0; | ||
189 | |||
190 | } | ||
153 | 191 | ||
154 | ret->cert.x509 = &ctxt->sc->cert_x509; | 192 | return GNUTLS_E_INTERNAL_ERROR; |
155 | ret->key.x509 = ctxt->sc->privkey_x509; | ||
156 | return 0; | ||
157 | } | 193 | } |
158 | 194 | ||
195 | /* 2048-bit group parameters from SRP specification */ | ||
159 | const char static_dh_params[] = "-----BEGIN DH PARAMETERS-----\n" | 196 | const char static_dh_params[] = "-----BEGIN DH PARAMETERS-----\n" |
160 | "MIIBBwKCAQCsa9tBMkqam/Fm3l4TiVgvr3K2ZRmH7gf8MZKUPbVgUKNzKcu0oJnt\n" | 197 | "MIIBBwKCAQCsa9tBMkqam/Fm3l4TiVgvr3K2ZRmH7gf8MZKUPbVgUKNzKcu0oJnt\n" |
161 | "gZPgdXdnoT3VIxKrSwMxDc1/SKnaBP1Q6Ag5ae23Z7DPYJUXmhY6s2YaBfvV+qro\n" | 198 | "gZPgdXdnoT3VIxKrSwMxDc1/SKnaBP1Q6Ag5ae23Z7DPYJUXmhY6s2YaBfvV+qro\n" |
@@ -171,7 +208,7 @@ const char static_dh_params[] = "-----BEGIN DH PARAMETERS-----\n" | |||
171 | * Returns negative on error. | 208 | * Returns negative on error. |
172 | */ | 209 | */ |
173 | static int read_crt_cn(server_rec * s, apr_pool_t * p, | 210 | static int read_crt_cn(server_rec * s, apr_pool_t * p, |
174 | gnutls_x509_crt cert, char **cert_cn) | 211 | gnutls_x509_crt_t cert, char **cert_cn) |
175 | { | 212 | { |
176 | int rv = 0, i; | 213 | int rv = 0, i; |
177 | size_t data_len; | 214 | size_t data_len; |
@@ -179,6 +216,7 @@ static int read_crt_cn(server_rec * s, apr_pool_t * p, | |||
179 | 216 | ||
180 | *cert_cn = NULL; | 217 | *cert_cn = NULL; |
181 | 218 | ||
219 | data_len = 0; | ||
182 | rv = gnutls_x509_crt_get_dn_by_oid(cert, | 220 | rv = gnutls_x509_crt_get_dn_by_oid(cert, |
183 | GNUTLS_OID_X520_COMMON_NAME, | 221 | GNUTLS_OID_X520_COMMON_NAME, |
184 | 0, 0, NULL, &data_len); | 222 | 0, 0, NULL, &data_len); |
@@ -189,8 +227,8 @@ static int read_crt_cn(server_rec * s, apr_pool_t * p, | |||
189 | GNUTLS_OID_X520_COMMON_NAME, 0, | 227 | GNUTLS_OID_X520_COMMON_NAME, 0, |
190 | 0, *cert_cn, &data_len); | 228 | 0, *cert_cn, &data_len); |
191 | } else { /* No CN return subject alternative name */ | 229 | } else { /* No CN return subject alternative name */ |
192 | ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, | 230 | ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, |
193 | "No common name found in certificate for '%s:%d'. Looking for subject alternative name.", | 231 | "No common name found in certificate for '%s:%d'. Looking for subject alternative name...", |
194 | s->server_hostname, s->port); | 232 | s->server_hostname, s->port); |
195 | rv = 0; | 233 | rv = 0; |
196 | /* read subject alternative name */ | 234 | /* read subject alternative name */ |
@@ -218,9 +256,33 @@ static int read_crt_cn(server_rec * s, apr_pool_t * p, | |||
218 | } | 256 | } |
219 | 257 | ||
220 | return rv; | 258 | return rv; |
259 | } | ||
260 | |||
261 | static int read_pgpcrt_cn(server_rec * s, apr_pool_t * p, | ||
262 | gnutls_openpgp_crt_t cert, char **cert_cn) | ||
263 | { | ||
264 | int rv = 0; | ||
265 | size_t data_len; | ||
266 | |||
267 | |||
268 | *cert_cn = NULL; | ||
269 | |||
270 | data_len = 0; | ||
271 | rv = gnutls_openpgp_crt_get_name(cert, 0, NULL, &data_len); | ||
272 | |||
273 | if (rv == GNUTLS_E_SHORT_MEMORY_BUFFER && data_len > 1) { | ||
274 | *cert_cn = apr_palloc(p, data_len); | ||
275 | rv = gnutls_openpgp_crt_get_name(cert, 0, *cert_cn, &data_len); | ||
276 | } else { /* No CN return subject alternative name */ | ||
277 | ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, | ||
278 | "No name found in PGP certificate for '%s:%d'.", | ||
279 | s->server_hostname, s->port); | ||
280 | } | ||
221 | 281 | ||
282 | return rv; | ||
222 | } | 283 | } |
223 | 284 | ||
285 | |||
224 | int | 286 | int |
225 | mgs_hook_post_config(apr_pool_t * p, apr_pool_t * plog, | 287 | mgs_hook_post_config(apr_pool_t * p, apr_pool_t * plog, |
226 | apr_pool_t * ptemp, server_rec * base_server) | 288 | apr_pool_t * ptemp, server_rec * base_server) |
@@ -334,7 +396,7 @@ mgs_hook_post_config(apr_pool_t * p, apr_pool_t * plog, | |||
334 | } | 396 | } |
335 | } | 397 | } |
336 | 398 | ||
337 | if (sc->cert_x509 == NULL | 399 | if (sc->certs_x509[0] == NULL |
338 | && sc->enabled == GNUTLS_ENABLED_TRUE) { | 400 | && sc->enabled == GNUTLS_ENABLED_TRUE) { |
339 | ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, | 401 | ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, |
340 | "[GnuTLS] - Host '%s:%d' is missing a " | 402 | "[GnuTLS] - Host '%s:%d' is missing a " |
@@ -353,7 +415,10 @@ mgs_hook_post_config(apr_pool_t * p, apr_pool_t * plog, | |||
353 | } | 415 | } |
354 | 416 | ||
355 | if (sc->enabled == GNUTLS_ENABLED_TRUE) { | 417 | if (sc->enabled == GNUTLS_ENABLED_TRUE) { |
356 | rv = read_crt_cn(s, p, sc->cert_x509, &sc->cert_cn); | 418 | rv = read_crt_cn(s, p, sc->certs_x509[0], &sc->cert_cn); |
419 | if (rv < 0 && sc->cert_pgp != NULL) /* try openpgp certificate */ | ||
420 | rv = read_pgpcrt_cn(s, p, sc->cert_pgp, &sc->cert_cn); | ||
421 | |||
357 | if (rv < 0) { | 422 | if (rv < 0) { |
358 | ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, | 423 | ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, |
359 | "[GnuTLS] - Cannot find a certificate for host '%s:%d'!", | 424 | "[GnuTLS] - Cannot find a certificate for host '%s:%d'!", |
@@ -482,15 +547,6 @@ mgs_srvconf_rec *mgs_find_sni_server(gnutls_session_t session) | |||
482 | 547 | ||
483 | ctxt = gnutls_transport_get_ptr(session); | 548 | ctxt = gnutls_transport_get_ptr(session); |
484 | 549 | ||
485 | sni_type = gnutls_certificate_type_get(session); | ||
486 | if (sni_type != GNUTLS_CRT_X509) { | ||
487 | /* In theory, we could support OpenPGP Certificates. Theory != code. */ | ||
488 | ap_log_error(APLOG_MARK, APLOG_CRIT, 0, | ||
489 | ctxt->c->base_server, | ||
490 | "GnuTLS: Only x509 Certificates are currently supported."); | ||
491 | return NULL; | ||
492 | } | ||
493 | |||
494 | rv = gnutls_server_name_get(ctxt->session, sni_name, | 550 | rv = gnutls_server_name_get(ctxt->session, sni_name, |
495 | &data_len, &sni_type, 0); | 551 | &data_len, &sni_type, 0); |
496 | 552 | ||
@@ -591,6 +647,8 @@ static mgs_handle_t *create_gnutls_handle(apr_pool_t * pool, conn_rec * c) | |||
591 | gnutls_handshake_set_post_client_hello_function(ctxt->session, | 647 | gnutls_handshake_set_post_client_hello_function(ctxt->session, |
592 | mgs_select_virtual_server_cb); | 648 | mgs_select_virtual_server_cb); |
593 | 649 | ||
650 | mgs_cache_session_init(ctxt); | ||
651 | |||
594 | return ctxt; | 652 | return ctxt; |
595 | } | 653 | } |
596 | 654 | ||
@@ -686,7 +744,11 @@ int mgs_hook_fixups(request_rec * r) | |||
686 | tmp = mgs_session_id2sz(sbuf, len, buf, sizeof(buf)); | 744 | tmp = mgs_session_id2sz(sbuf, len, buf, sizeof(buf)); |
687 | apr_table_setn(env, "SSL_SESSION_ID", apr_pstrdup(r->pool, tmp)); | 745 | apr_table_setn(env, "SSL_SESSION_ID", apr_pstrdup(r->pool, tmp)); |
688 | 746 | ||
689 | mgs_add_common_cert_vars(r, ctxt->sc->cert_x509, 0, | 747 | if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_X509) |
748 | mgs_add_common_cert_vars(r, ctxt->sc->certs_x509[0], 0, | ||
749 | ctxt->sc->export_certificates_enabled); | ||
750 | else if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_OPENPGP) | ||
751 | mgs_add_common_pgpcert_vars(r, ctxt->sc->cert_pgp, 0, | ||
690 | ctxt->sc->export_certificates_enabled); | 752 | ctxt->sc->export_certificates_enabled); |
691 | 753 | ||
692 | return rv; | 754 | return rv; |
@@ -748,7 +810,7 @@ int mgs_hook_authz(request_rec * r) | |||
748 | */ | 810 | */ |
749 | #define MGS_SIDE ((side==0)?"SSL_SERVER":"SSL_CLIENT") | 811 | #define MGS_SIDE ((side==0)?"SSL_SERVER":"SSL_CLIENT") |
750 | static void | 812 | static void |
751 | mgs_add_common_cert_vars(request_rec * r, gnutls_x509_crt cert, int side, | 813 | mgs_add_common_cert_vars(request_rec * r, gnutls_x509_crt_t cert, int side, |
752 | int export_certificates_enabled) | 814 | int export_certificates_enabled) |
753 | { | 815 | { |
754 | unsigned char sbuf[64]; /* buffer to hold serials */ | 816 | unsigned char sbuf[64]; /* buffer to hold serials */ |
@@ -795,7 +857,7 @@ mgs_add_common_cert_vars(request_rec * r, gnutls_x509_crt cert, int side, | |||
795 | apr_psprintf(r->pool, "%u", ret)); | 857 | apr_psprintf(r->pool, "%u", ret)); |
796 | 858 | ||
797 | apr_table_setn(env, | 859 | apr_table_setn(env, |
798 | apr_pstrcat(r->pool, MGS_SIDE, "_S_TYPE", NULL), "X.509"); | 860 | apr_pstrcat(r->pool, MGS_SIDE, "_CERT_TYPE", NULL), "X.509"); |
799 | 861 | ||
800 | tmp = | 862 | tmp = |
801 | mgs_time2sz(gnutls_x509_crt_get_expiration_time | 863 | mgs_time2sz(gnutls_x509_crt_get_expiration_time |
@@ -837,34 +899,99 @@ mgs_add_common_cert_vars(request_rec * r, gnutls_x509_crt cert, int side, | |||
837 | 899 | ||
838 | if (ret == GNUTLS_SAN_DNSNAME) { | 900 | if (ret == GNUTLS_SAN_DNSNAME) { |
839 | apr_table_setn(env, | 901 | apr_table_setn(env, |
840 | apr_psprintf(r->pool, "%s_S_SAN%u", MGS_SIDE, i), | 902 | apr_psprintf(r->pool, "%s_S_AN%u", MGS_SIDE, i), |
841 | apr_psprintf(r->pool, "DNSNAME:%s", tmp2)); | 903 | apr_psprintf(r->pool, "DNSNAME:%s", tmp2)); |
842 | } else if (ret == GNUTLS_SAN_RFC822NAME) { | 904 | } else if (ret == GNUTLS_SAN_RFC822NAME) { |
843 | apr_table_setn(env, | 905 | apr_table_setn(env, |
844 | apr_psprintf(r->pool, "%s_S_SAN%u", MGS_SIDE, i), | 906 | apr_psprintf(r->pool, "%s_S_AN%u", MGS_SIDE, i), |
845 | apr_psprintf(r->pool, "RFC822NAME:%s", tmp2)); | 907 | apr_psprintf(r->pool, "RFC822NAME:%s", tmp2)); |
846 | } else if (ret == GNUTLS_SAN_URI) { | 908 | } else if (ret == GNUTLS_SAN_URI) { |
847 | apr_table_setn(env, | 909 | apr_table_setn(env, |
848 | apr_psprintf(r->pool, "%s_S_SAN%u", MGS_SIDE, i), | 910 | apr_psprintf(r->pool, "%s_S_AN%u", MGS_SIDE, i), |
849 | apr_psprintf(r->pool, "URI:%s", tmp2)); | 911 | apr_psprintf(r->pool, "URI:%s", tmp2)); |
850 | } else { | 912 | } else { |
851 | apr_table_setn(env, | 913 | apr_table_setn(env, |
852 | apr_psprintf(r->pool, "%s_S_SAN%u", MGS_SIDE, i), | 914 | apr_psprintf(r->pool, "%s_S_AN%u", MGS_SIDE, i), |
853 | "UNSUPPORTED"); | 915 | "UNSUPPORTED"); |
854 | } | 916 | } |
855 | } | 917 | } |
856 | } | 918 | } |
919 | } | ||
857 | 920 | ||
921 | static void | ||
922 | mgs_add_common_pgpcert_vars(request_rec * r, gnutls_openpgp_crt_t cert, int side, | ||
923 | int export_certificates_enabled) | ||
924 | { | ||
925 | unsigned char sbuf[64]; /* buffer to hold serials */ | ||
926 | char buf[AP_IOBUFSIZE]; | ||
927 | const char *tmp; | ||
928 | size_t len; | ||
929 | int ret; | ||
858 | 930 | ||
859 | } | 931 | apr_table_t *env = r->subprocess_env; |
860 | 932 | ||
933 | if (export_certificates_enabled != 0) { | ||
934 | char cert_buf[10 * 1024]; | ||
935 | len = sizeof(cert_buf); | ||
936 | |||
937 | if (gnutls_openpgp_crt_export | ||
938 | (cert, GNUTLS_OPENPGP_FMT_BASE64, cert_buf, &len) >= 0) | ||
939 | apr_table_setn(env, | ||
940 | apr_pstrcat(r->pool, MGS_SIDE, "_CERT", NULL), | ||
941 | apr_pstrmemdup(r->pool, cert_buf, len)); | ||
942 | |||
943 | } | ||
944 | |||
945 | len = sizeof(buf); | ||
946 | gnutls_openpgp_crt_get_name(cert, 0, buf, &len); | ||
947 | apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_NAME", NULL), | ||
948 | apr_pstrmemdup(r->pool, buf, len)); | ||
949 | |||
950 | len = sizeof(sbuf); | ||
951 | gnutls_openpgp_crt_get_fingerprint(cert, sbuf, &len); | ||
952 | tmp = mgs_session_id2sz(sbuf, len, buf, sizeof(buf)); | ||
953 | apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_FINGERPRINT", NULL), | ||
954 | apr_pstrdup(r->pool, tmp)); | ||
955 | |||
956 | ret = gnutls_openpgp_crt_get_version(cert); | ||
957 | if (ret > 0) | ||
958 | apr_table_setn(env, | ||
959 | apr_pstrcat(r->pool, MGS_SIDE, "_M_VERSION", NULL), | ||
960 | apr_psprintf(r->pool, "%u", ret)); | ||
961 | |||
962 | apr_table_setn(env, | ||
963 | apr_pstrcat(r->pool, MGS_SIDE, "_CERT_TYPE", NULL), "OPENPGP"); | ||
964 | |||
965 | tmp = | ||
966 | mgs_time2sz(gnutls_openpgp_crt_get_expiration_time | ||
967 | (cert), buf, sizeof(buf)); | ||
968 | apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_V_END", NULL), | ||
969 | apr_pstrdup(r->pool, tmp)); | ||
970 | |||
971 | tmp = | ||
972 | mgs_time2sz(gnutls_openpgp_crt_get_creation_time | ||
973 | (cert), buf, sizeof(buf)); | ||
974 | apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_V_START", NULL), | ||
975 | apr_pstrdup(r->pool, tmp)); | ||
976 | |||
977 | ret = gnutls_openpgp_crt_get_pk_algorithm(cert, NULL); | ||
978 | if (ret >= 0) { | ||
979 | apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_A_KEY", NULL), | ||
980 | gnutls_pk_algorithm_get_name(ret)); | ||
981 | } | ||
982 | |||
983 | } | ||
861 | 984 | ||
985 | /* TODO: Allow client sending a X.509 certificate chain */ | ||
862 | static int mgs_cert_verify(request_rec * r, mgs_handle_t * ctxt) | 986 | static int mgs_cert_verify(request_rec * r, mgs_handle_t * ctxt) |
863 | { | 987 | { |
864 | const gnutls_datum_t *cert_list; | 988 | const gnutls_datum_t *cert_list; |
865 | unsigned int cert_list_size, status, expired; | 989 | unsigned int cert_list_size, status, expired; |
866 | int rv, ret; | 990 | int rv, ret; |
867 | gnutls_x509_crt_t cert; | 991 | union { |
992 | gnutls_x509_crt_t x509; | ||
993 | gnutls_openpgp_crt_t pgp; | ||
994 | } cert; | ||
868 | apr_time_t activation_time, expiration_time, cur_time; | 995 | apr_time_t activation_time, expiration_time, cur_time; |
869 | 996 | ||
870 | cert_list = | 997 | cert_list = |
@@ -890,32 +1017,56 @@ static int mgs_cert_verify(request_rec * r, mgs_handle_t * ctxt) | |||
890 | return HTTP_FORBIDDEN; | 1017 | return HTTP_FORBIDDEN; |
891 | } | 1018 | } |
892 | 1019 | ||
893 | gnutls_x509_crt_init(&cert); | 1020 | if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_X509) { |
894 | rv = gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER); | 1021 | gnutls_x509_crt_init(&cert.x509); |
1022 | rv = gnutls_x509_crt_import(cert.x509, &cert_list[0], GNUTLS_X509_FMT_DER); | ||
1023 | } else if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_OPENPGP) { | ||
1024 | gnutls_openpgp_crt_init(&cert.pgp); | ||
1025 | rv = gnutls_openpgp_crt_import(cert.pgp, &cert_list[0], GNUTLS_OPENPGP_FMT_RAW); | ||
1026 | } else return HTTP_FORBIDDEN; | ||
1027 | |||
895 | if (rv < 0) { | 1028 | if (rv < 0) { |
896 | ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, | 1029 | ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, |
897 | "GnuTLS: Failed to Verify Peer: " | 1030 | "GnuTLS: Failed to Verify Peer: " |
898 | "Failed to import peer certificates."); | 1031 | "Failed to import peer certificates."); |
899 | ret = HTTP_FORBIDDEN; | 1032 | ret = HTTP_FORBIDDEN; |
900 | goto exit; | 1033 | goto exit; |
901 | } | 1034 | } |
902 | 1035 | ||
903 | apr_time_ansi_put(&expiration_time, | 1036 | if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_X509) { |
904 | gnutls_x509_crt_get_expiration_time(cert)); | 1037 | apr_time_ansi_put(&expiration_time, |
905 | apr_time_ansi_put(&activation_time, | 1038 | gnutls_x509_crt_get_expiration_time(cert.x509)); |
906 | gnutls_x509_crt_get_activation_time(cert)); | 1039 | apr_time_ansi_put(&activation_time, |
1040 | gnutls_x509_crt_get_activation_time(cert.x509)); | ||
907 | 1041 | ||
908 | rv = gnutls_x509_crt_verify(cert, ctxt->sc->ca_list, | 1042 | rv = gnutls_x509_crt_verify(cert.x509, ctxt->sc->ca_list, |
909 | ctxt->sc->ca_list_size, 0, &status); | 1043 | ctxt->sc->ca_list_size, 0, &status); |
1044 | } else { | ||
1045 | apr_time_ansi_put(&expiration_time, | ||
1046 | gnutls_openpgp_crt_get_expiration_time(cert.pgp)); | ||
1047 | apr_time_ansi_put(&activation_time, | ||
1048 | gnutls_openpgp_crt_get_creation_time(cert.pgp)); | ||
1049 | |||
1050 | rv = gnutls_openpgp_crt_verify_ring(cert.pgp, ctxt->sc->pgp_list, | ||
1051 | 0, &status); | ||
1052 | } | ||
910 | 1053 | ||
911 | if (rv < 0) { | 1054 | if (rv < 0) { |
912 | ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, | 1055 | ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, |
913 | "GnuTLS: Failed to Verify Peer certificate: (%d) %s", | 1056 | "GnuTLS: Failed to Verify Peer certificate: (%d) %s", |
914 | rv, gnutls_strerror(rv)); | 1057 | rv, gnutls_strerror(rv)); |
1058 | if (rv == GNUTLS_E_NO_CERTIFICATE_FOUND) | ||
1059 | ap_log_rerror(APLOG_MARK, APLOG_EMERG, 0, r, | ||
1060 | "GnuTLS: No certificate was found for verification. Did you set the GnuTLSX509CAFile or GnuTLSPGPKeyringFile directives?"); | ||
915 | ret = HTTP_FORBIDDEN; | 1061 | ret = HTTP_FORBIDDEN; |
916 | goto exit; | 1062 | goto exit; |
917 | } | 1063 | } |
918 | 1064 | ||
1065 | /* TODO: X509 CRL Verification. */ | ||
1066 | /* May add later if anyone needs it. | ||
1067 | */ | ||
1068 | /* ret = gnutls_x509_crt_check_revocation(crt, crl_list, crl_list_size); */ | ||
1069 | |||
919 | expired = 0; | 1070 | expired = 0; |
920 | cur_time = apr_time_now(); | 1071 | cur_time = apr_time_now(); |
921 | if (activation_time > cur_time) { | 1072 | if (activation_time > cur_time) { |
@@ -950,16 +1101,11 @@ static int mgs_cert_verify(request_rec * r, mgs_handle_t * ctxt) | |||
950 | "GnuTLS: Peer Certificate is revoked."); | 1101 | "GnuTLS: Peer Certificate is revoked."); |
951 | } | 1102 | } |
952 | 1103 | ||
953 | /* TODO: Further Verification. */ | 1104 | if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_X509) |
954 | /* Revocation is X.509 non workable paradigm, I really doubt implementation | 1105 | mgs_add_common_cert_vars(r, cert.x509, 1, |
955 | * is worth doing --nmav | 1106 | ctxt->sc->export_certificates_enabled); |
956 | */ | 1107 | else if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_OPENPGP) |
957 | /// ret = gnutls_x509_crt_check_revocation(crt, crl_list, crl_list_size); | 1108 | mgs_add_common_pgpcert_vars(r, cert.pgp, 1, |
958 | |||
959 | // mgs_hook_fixups(r); | ||
960 | // rv = mgs_authz_lua(r); | ||
961 | |||
962 | mgs_add_common_cert_vars(r, cert, 1, | ||
963 | ctxt->sc->export_certificates_enabled); | 1109 | ctxt->sc->export_certificates_enabled); |
964 | 1110 | ||
965 | { | 1111 | { |
@@ -983,7 +1129,10 @@ static int mgs_cert_verify(request_rec * r, mgs_handle_t * ctxt) | |||
983 | } | 1129 | } |
984 | 1130 | ||
985 | exit: | 1131 | exit: |
986 | gnutls_x509_crt_deinit(cert); | 1132 | if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_X509) |
1133 | gnutls_x509_crt_deinit(cert.x509); | ||
1134 | else if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_OPENPGP) | ||
1135 | gnutls_openpgp_crt_deinit(cert.pgp); | ||
987 | return ret; | 1136 | return ret; |
988 | 1137 | ||
989 | 1138 | ||
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[] = { | |||
64 | NULL, | 64 | NULL, |
65 | RSRC_CONF, | 65 | RSRC_CONF, |
66 | "Set the CA File to verify Client Certificates"), | 66 | "Set the CA File to verify Client Certificates"), |
67 | AP_INIT_TAKE1("GnuTLSX509CAFile", mgs_set_client_ca_file, | ||
68 | NULL, | ||
69 | RSRC_CONF, | ||
70 | "Set the CA File to verify Client Certificates"), | ||
71 | AP_INIT_TAKE1("GnuTLSPGPKeyringFile", mgs_set_keyring_file, | ||
72 | NULL, | ||
73 | RSRC_CONF, | ||
74 | "Set the Keyring File to verify Client Certificates"), | ||
67 | AP_INIT_TAKE1("GnuTLSDHFile", mgs_set_dh_file, | 75 | AP_INIT_TAKE1("GnuTLSDHFile", mgs_set_dh_file, |
68 | NULL, | 76 | NULL, |
69 | RSRC_CONF, | 77 | RSRC_CONF, |
@@ -75,11 +83,27 @@ static const command_rec mgs_config_cmds[] = { | |||
75 | AP_INIT_TAKE1("GnuTLSCertificateFile", mgs_set_cert_file, | 83 | AP_INIT_TAKE1("GnuTLSCertificateFile", mgs_set_cert_file, |
76 | NULL, | 84 | NULL, |
77 | RSRC_CONF, | 85 | RSRC_CONF, |
78 | "SSL Server Key file"), | 86 | "SSL Server X509 Certificate file"), |
79 | AP_INIT_TAKE1("GnuTLSKeyFile", mgs_set_key_file, | 87 | AP_INIT_TAKE1("GnuTLSKeyFile", mgs_set_key_file, |
80 | NULL, | 88 | NULL, |
81 | RSRC_CONF, | 89 | RSRC_CONF, |
82 | "SSL Server SRP Password file"), | 90 | "SSL Server X509 Private Key file"), |
91 | AP_INIT_TAKE1("GnuTLSX509CertificateFile", mgs_set_cert_file, | ||
92 | NULL, | ||
93 | RSRC_CONF, | ||
94 | "SSL Server X509 Certificate file"), | ||
95 | AP_INIT_TAKE1("GnuTLSX509KeyFile", mgs_set_key_file, | ||
96 | NULL, | ||
97 | RSRC_CONF, | ||
98 | "SSL Server X509 Private Key file"), | ||
99 | AP_INIT_TAKE1("GnuTLSPGPCertificateFile", mgs_set_pgpcert_file, | ||
100 | NULL, | ||
101 | RSRC_CONF, | ||
102 | "SSL Server PGP Certificate file"), | ||
103 | AP_INIT_TAKE1("GnuTLSPGPKeyFile", mgs_set_pgpkey_file, | ||
104 | NULL, | ||
105 | RSRC_CONF, | ||
106 | "SSL Server PGP Private key file"), | ||
83 | AP_INIT_TAKE1("GnuTLSSRPPasswdFile", mgs_set_srp_tpasswd_file, | 107 | AP_INIT_TAKE1("GnuTLSSRPPasswdFile", mgs_set_srp_tpasswd_file, |
84 | NULL, | 108 | NULL, |
85 | RSRC_CONF, | 109 | RSRC_CONF, |