Changeset ea9c699 in mod_gnutls
- Timestamp:
- Jan 28, 2019, 2:50:38 PM (2 years ago)
- Branches:
- debian/master
- Children:
- 19e80a5
- Parents:
- 8a264b0 (diff), 510764a (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - Files:
-
- 68 added
- 27 deleted
- 72 edited
- 2 moved
Legend:
- Unmodified
- Added
- Removed
-
CHANGELOG
r8a264b0 rea9c699 1 **TODO: 2 - Handle Unclean Shutdowns 3 - make session cache use generic apache caches 1 ** Version 0.9.0 (2019-01-23) 2 - Security fix: Refuse to send or receive any data over a failed TLS 3 connection (commit 72b669eae8c45dda1850e8e5b30a97c918357b51). The 4 previous behavior could lead to requests on reverse proxy TLS 5 connections being sent in plain text, and might have allowed faking 6 requests in plain text. 7 - Security fix: Reject HTTP requests if they try to access virtual 8 hosts that do not match their TLS connections (commit 9 de3fad3c12f53cdbf082ad675e4b10f521a02811). Additionally check if SNI 10 and Host header match. Thanks to Krista Karppinen for contributing 11 tests! 12 - OCSP stapling is now enabled by default, if possible. OCSP responses 13 are updated regularly and stored in a cache separate from the 14 session cache. The OCSP cache uses mod_socache_shmcb by default 15 (if the module is loaded, no other configuration required). 16 - Session tickets are now enabled by default if using GnuTLS 3.6.4 or 17 newer. GnuTLS 3.6.4 introduced automatic rotation for the used key, 18 and TLS 1.3 takes care of other reasons not to use tickets while 19 requiring them for session resumption. Note that there is currently 20 no mechanism to synchronize ticket keys across a cluster of servers. 21 - The internal cache implementation has been replaced with 22 mod_socache. Users may need to update their GnuTLSCache settings and 23 load the appropriate socache modules. 24 - ALPN (required for HTTP/2) now works correctly with different 25 "Protocols" directives between virtual hosts if building with GnuTLS 26 3.6.3 or newer. Older versions require identical "Protocols" 27 directives for overlapping virtual hosts. Thanks to Vincent Tamet 28 for the bug report! 29 - ALPN is now supported for proxy connections, making HTTP/2 proxy 30 connections using mod_proxy_http2 possible. 31 - GnuTLSPriorities is optional now and defaults to "NORMAL" if 32 missing. The same applies to GnuTLSProxyPriorities (if TLS proxy is 33 enabled). 34 - The manual is now built as a manual page, too, if pandoc is 35 available. 36 - OpenPGP support has been removed. 37 - Don't require pem2openpgp for tests when building without MSVA 38 support. 39 40 ** Version 0.8.4 (2018-04-13) 41 - Support Apache HTTPD 2.4.33 API for proxy TLS connections 42 - Support TLS for HTTP/2 connections with mod_http2 43 - Fix configuration of OCSP stapling callback 44 45 ** Version 0.8.3 (2017-10-20) 46 - Use GnuTLS' default DH parameters by default 47 - Handle long Server Name Indication data and gracefully ignore 48 unknown SNI types 49 - Send SNI for proxy connections 50 - Deprecate OpenPGP support like GnuTLS did (will be removed 51 completely in a future release) 52 - Do not announce session ticket support for proxy connections 53 - Minor documentation updates (SSL_CLIENT_I_DN, reference for SNI) 54 - Test suite: Simplify handling of proxy backend servers and OCSP 55 responders 56 - Test suite: stability/compatibility fixes 57 58 ** Version 0.8.2 (2017-01-08) 59 - Test suite: Ensure CRLF line ends in HTTP headers 60 - Test suite, gen_ocsp_index.c: Handle serial as fixed order byte array 61 62 ** Version 0.8.1 (2016-12-20) 63 - Bugfix: Use APR_SIZE_T_FMT for portable apr_size_t formatting 64 65 ** Version 0.8.0 (2016-12-11) 66 - New: Support for OCSP stapling 67 - Bugfix: Access to DBM cache is locked using global mutex 68 "gnutls-cache" 69 - Bugfix: GnuTLSSessionTickets is now disabled by default as described 70 in the handbook 71 - Fixed memory leak while checking proxy backend certificate 72 - Fixed memory leaks in post_config 73 - Safely delete session ticket key (requires GnuTLS >= 3.4) 74 - Improved error handling in post_config hook 75 - Various handbook updates 76 - Internal API documentation can be generated using Doxygen 77 - Unused code has been removed (conditionals for GnuTLS 2.x and Apache 78 versions before 2.2, internal Lua bytecode structure last used in 79 2011). 80 - Test suite: Fixed locking for access to the PGP keyring of the test 81 certificate authority 82 - mod_gnutls can be built using Clang (unsupported) 83 84 ** Version 0.7.5 (2016-05-28) 85 - Sunil Mohan Adapa reported retry loops during session shutdown in 86 cleanup_gnutls_session() due to gnutls_bye() incorrectly returning 87 GNUTLS_E_INTERRUPTED or GNUTLS_E_AGAIN. Setting the GnuTLS session 88 errno in mgs_transport_write() fixes the problem. 89 - Import Daniel Kahn Gillmor's patches for GnuPG v2 support from the 90 Debian package. 91 - Build system improvements that allow VPATH builds and get "make 92 distcheck" to work 93 94 ** Version 0.7.4 (2016-04-13) 95 - Support SoftHSM 2 for PKCS #11 testing 96 - Increase verbosity of test logs 4 97 5 98 ** Version 0.7.3 (2016-01-12) -
Makefile.am
r8a264b0 rea9c699 1 AUTOMAKE_OPTIONS = foreign dist-bzip2 1 AUTOMAKE_OPTIONS = foreign dist-bzip2 no-dist-gzip 2 2 3 3 EXTRA_DIST = m4/outoforder.m4 m4/apache.m4 \ 4 m4/apr_memcache.m4 \5 4 m4/apache_test.m4 \ 6 5 include/mod_gnutls.h.in \ … … 8 7 NOTICE LICENSE 9 8 9 AM_DISTCHECK_CONFIGURE_FLAGS = "--enable-vpath-install" \ 10 "SOFTHSM_LIB='$(SOFTHSM_LIB)'" 11 DISTCLEANFILES = config.nice 12 MOSTLYCLEANFILES = $(DX_CLEANFILES) 13 10 14 SUBDIRS = src test doc 11 15 ACLOCAL_AMFLAGS = -I m4 16 17 @DX_RULES@ -
README
r8a264b0 rea9c699 10 10 Lead Maintainer: 11 11 12 Thomas Klute <thomas2.klute@uni-dortmund.de>12 Fiona Klute <fiona.klute@gmx.de> 13 13 14 14 Past maintainers and other contributors: … … 22 22 ------------- 23 23 24 * GnuTLS >= 3. 1.4 <http://www.gnutls.org/> (3.2.* or newer preferred)25 * Apache HTTPD >= 2. 2 <http://httpd.apache.org/> (2.4.* preferred)26 * autotools, GNU make, & gcc24 * GnuTLS >= 3.3 <https://www.gnutls.org/> (3.4 or newer recommended) 25 * Apache HTTPD >= 2.4.17 <https://httpd.apache.org/> 26 * autotools, GNU make, & GCC 27 27 * libmsv >= 0.1 (Optional, enable with ./configure --enable-msva) 28 28 * pandoc (for documentation, optional) … … 32 32 ------------ 33 33 34 tar xzvf mod_gnutls-version.tar. gz34 tar xzvf mod_gnutls-version.tar.bz2 35 35 cd mod_gnutls-version/ 36 36 autoreconf -fiv … … 44 44 correctly, please see test/README for details. 45 45 46 If Doxygen is available, you can build internal API documentation 47 using "make doxygen-doc". The documentation will be placed in 48 doc/api/. 49 46 50 Configuration 47 51 ------------- -
configure.ac
r8a264b0 rea9c699 1 dnl 2 AC_INIT(mod_gnutls, 0.7.3) 1 AC_INIT(mod_gnutls, 0.9.0) 3 2 OOO_CONFIG_NICE(config.nice) 4 3 MOD_GNUTLS_VERSION=AC_PACKAGE_VERSION … … 14 13 AM_CONFIG_HEADER(include/mod_gnutls_config.h:config.in) 15 14 15 LT_INIT([disable-static]) 16 16 17 AC_SUBST(MOD_GNUTLS_VERSION) 17 18 … … 24 25 AC_CONFIG_MACRO_DIR([m4]) 25 26 26 AP_VERSION=2. 2.027 AP_VERSION=2.4.17 27 28 CHECK_APACHE(,$AP_VERSION, 28 29 :,:, … … 30 31 ) 31 32 32 PKG_CHECK_MODULES([LIBGNUTLS], [gnutls >= 3.1.4]) 33 dnl Maybe use the binaries for tests, too? 34 AC_ARG_WITH([gnutls-dev], 35 AS_HELP_STRING([--with-gnutls-dev=DIR], 36 [Use GnuTLS libraries from a development (git) tree. Use \ 37 this if you want to test mod_gnutls with the latest \ 38 GnuTLS code.]), 39 [ 40 AS_IF([test -d "${with_gnutls_dev}" ], 41 [ 42 LIBGNUTLS_CFLAGS="-I${with_gnutls_dev}/lib/includes" 43 LIBGNUTLS_LIBS="-lgnutls -L${with_gnutls_dev}/lib/.libs -R${with_gnutls_dev}/lib/.libs" 44 ], 45 [AC_MSG_ERROR([--with-gnutls-dev=DIR requires a directory!])]) 46 ], []) 47 48 PKG_CHECK_MODULES([LIBGNUTLS], [gnutls >= 3.3.0]) 33 49 34 50 LIBGNUTLS_VERSION=`pkg-config --modversion gnutls` 51 52 AC_ARG_ENABLE(vpath-install, 53 AS_HELP_STRING([--enable-vpath-install], 54 [Modify the Apache module directory provided by apxs to \ 55 follow --prefix, if necessary. Most users will not want this, \ 56 but it is required for VPATH builds including "make \ 57 distcheck".]), 58 vpath_install=$enableval, vpath_install=no) 59 AM_CONDITIONAL([ENABLE_VPATH_INSTALL], [test "$vpath_install" = "yes"]) 35 60 36 61 AC_ARG_ENABLE(srp, … … 42 67 AC_SEARCH_LIBS([gnutls_srp_server_get_username], [gnutls], [], [use_srp="no"]) 43 68 44 SRP_CFLAGS=""69 GNUTLS_FEAT_CFLAGS="" 45 70 if test "$use_srp" != "no"; then 46 SRP_CFLAGS="-DENABLE_SRP=1" 47 fi 71 GNUTLS_FEAT_CFLAGS="-DENABLE_SRP=1" 72 fi 73 74 # check if the available GnuTLS library supports raw extension parsing 75 AC_SEARCH_LIBS([gnutls_ext_raw_parse], [gnutls], [early_sni="yes"], 76 [early_sni="no"]) 77 if test "$early_sni" != "no"; then 78 ENABLE_EARLY_SNI=1 79 # This is for the test server configuration 80 EXPECT_EARLY_SNI="Define EXPECT_EARLY_SNI" 81 else 82 ENABLE_EARLY_SNI=0 83 EXPECT_EARLY_SNI="" 84 fi 85 AC_SUBST(ENABLE_EARLY_SNI) 86 AC_SUBST(EXPECT_EARLY_SNI) 87 AM_SUBST_NOTMAKE(EXPECT_EARLY_SNI) 48 88 49 89 AC_ARG_ENABLE(strict, … … 54 94 STRICT_CFLAGS="" 55 95 if test "$use_strict" != "no"; then 56 STRICT_CFLAGS="-Wall -Werror -Wextra"96 STRICT_CFLAGS="-Wall -Werror -Wextra -Wno-error=deprecated-declarations" 57 97 fi 58 98 … … 73 113 AS_IF([${FLOCK} --timeout 1 ${lockfile} true >&AS_MESSAGE_LOG_FD 2>&1], 74 114 [flock_works="yes"], [flock_works="no"]) 115 AC_MSG_RESULT([$flock_works]) 116 # Old versions of flock do not support --verbose. They fail 117 # without executing the command but still return 0. Check for 118 # this behavior by testing if the rm command was executed. 119 AC_MSG_CHECKING([whether ${FLOCK} supports --verbose]) 120 testfile="$(mktemp)" 121 AS_IF([${FLOCK} --verbose --timeout 1 ${lockfile} rm "${testfile}" \ 122 >&AS_MESSAGE_LOG_FD 2>&1; test ! -e "${testfile}"], 123 [flock_verbose="yes"; FLOCK="${FLOCK} --verbose"], 124 [flock_verbose="no"; rm "${testfile}"]) 125 AC_MSG_RESULT([$flock_verbose]) 75 126 rm "${lockfile}" 76 AC_MSG_RESULT([$flock_works])77 127 ], 78 128 [flock_works="no"]) … … 81 131 [test "$enable_flock" = "no" || test "$flock_works" = "no"]) 82 132 133 # openssl is needed as the responder for OCSP tests 134 AC_PATH_PROG([OPENSSL], [openssl], [no]) 135 # OCSP checks with gnutls-cli from GnuTLS versions before 3.3.23, 136 # 3.4.12, or 3.5.1 (on the respective 3.x branch) fail if intermediate 137 # CAs cannot be status checked, even if there are no intermediate CAs 138 # like in the mod_gnutls test suite where end entity certificates are 139 # directly issued by a root CA. 140 AC_MSG_CHECKING([for gnutls-cli version supporting OCSP for EE under root CA]) 141 AC_PREPROC_IFELSE( 142 [AC_LANG_SOURCE([[#include "gnutls/gnutls.h" 143 #if GNUTLS_VERSION_NUMBER < 0x030317 144 #error 145 #elif GNUTLS_VERSION_NUMBER >= 0x030400 && GNUTLS_VERSION_NUMBER < 0x03040c 146 #error 147 #elif GNUTLS_VERSION_NUMBER == 0x030500 148 #error 149 #endif 150 ]])], 151 [gnutls_ocsp_ok="yes"], 152 [gnutls_ocsp_ok="no"], 153 ) 154 AC_MSG_RESULT([$gnutls_ocsp_ok]) 155 AM_CONDITIONAL([ENABLE_OCSP_TEST], [test "${OPENSSL}" != "no" && test "${gnutls_ocsp_ok}" = "yes"]) 156 83 157 dnl Enable test namespaces? Default is "yes". 84 158 AC_ARG_ENABLE(test-namespaces, 85 AS_HELP_STRING([--disable-test-namespaces], [Disable use of network \ 86 namespaces to run tests in parallel (some architectures might not \ 87 support it)]), 159 AS_HELP_STRING([--disable-test-namespaces], [Disable use of \ 160 namespaces for tests (limits parallelization)]), 88 161 [use_netns=$enableval], [use_netns=yes]) 89 162 90 # Check if "unshare" is available and has permission to create network91 # and user namespaces163 # Check if "unshare" is available and has permission to create 164 # network, IPC, and user namespaces 92 165 AC_PATH_PROG([UNSHARE], [unshare], [no]) 93 166 AS_IF([test "${UNSHARE}" != "no"], 94 167 [ 95 AC_MSG_CHECKING([for permission to create network and usernamespaces])96 AS_IF([${UNSHARE} --net - r /bin/sh -c \168 AC_MSG_CHECKING([for permission to use namespaces]) 169 AS_IF([${UNSHARE} --net --ipc -r /bin/sh -c \ 97 170 "ip link set up lo && ip addr show" >&AS_MESSAGE_LOG_FD 2>&1], 98 171 [unshare_works="yes"], [unshare_works="no"]) … … 108 181 # and test specific PID files if using namespaces, defaults otherwise. 109 182 AS_IF([test "$use_netns" = "yes"], 110 [MUTEX_ TYPE="pthread"; PID_AFFIX="-\${TEST_NAME}"],111 [MUTEX_ TYPE="default"; PID_AFFIX=""])112 AC_SUBST(MUTEX_ TYPE)183 [MUTEX_CONF="Mutex pthread default"; PID_AFFIX="-\${TEST_NAME}"], 184 [MUTEX_CONF=""; PID_AFFIX=""]) 185 AC_SUBST(MUTEX_CONF) 113 186 AC_SUBST(PID_AFFIX) 114 AM_SUBST_NOTMAKE(MUTEX_ TYPE)187 AM_SUBST_NOTMAKE(MUTEX_CONF) 115 188 AM_SUBST_NOTMAKE(PID_AFFIX) 116 189 … … 133 206 AC_MSG_RESULT($use_msva) 134 207 135 have_apr_memcache=0136 CHECK_APR_MEMCACHE([have_apr_memcache=1], [have_apr_memcache=0])137 AC_SUBST(have_apr_memcache)138 139 208 # Building documentation requires pandoc, which in turn needs pdflatex 140 209 # to build PDF output. … … 144 213 AC_PATH_PROG([PDFLATEX], [pdflatex], [no]) 145 214 if test "$PDFLATEX" != "no"; then 146 build_doc= yes215 build_doc="html, manual page, pdf" 147 216 else 148 build_doc="html only"217 build_doc="html, manual page" 149 218 fi 150 219 else … … 169 238 AC_PATH_PROGS([HTTP_CLI], [curl wget], [no]) 170 239 171 MODULE_CFLAGS="${LIBGNUTLS_CFLAGS} ${SRP_CFLAGS} ${MSVA_CFLAGS} ${APR_MEMCACHE_CFLAGS} ${APXS_CFLAGS} ${AP_INCLUDES} ${APR_INCLUDES} ${APU_INCLUDES} ${STRICT_CFLAGS}" 172 MODULE_LIBS="${APR_MEMCACHE_LIBS} ${LIBGNUTLS_LIBS}" 240 MODULE_CFLAGS="${LIBGNUTLS_CFLAGS} ${GNUTLS_FEAT_CFLAGS} ${MSVA_CFLAGS} ${APXS_CFLAGS} ${AP_INCLUDES} ${APR_INCLUDES} ${APU_INCLUDES} ${STRICT_CFLAGS}" 241 MODULE_LIBS="${LIBGNUTLS_LIBS}" 242 243 AC_PATH_PROGS([SOFTHSM], [softhsm2-util softhsm], [no]) 244 if test "${SOFTHSM}" != "no"; then 245 softhsm_version=$(${SOFTHSM} --version) 246 AS_VERSION_COMPARE([$(${SOFTHSM} --version)], [2.0.0], 247 [AC_SUBST(SOFTHSM_MAJOR_VERSION, [1])], 248 [AC_SUBST(SOFTHSM_MAJOR_VERSION, [2])], 249 [AC_SUBST(SOFTHSM_MAJOR_VERSION, [2])]) 250 fi 251 AM_CONDITIONAL([HAVE_SOFTHSM], [test "${SOFTHSM}" != "no"]) 252 AM_CONDITIONAL([HAVE_SOFTHSM1], [test "${SOFTHSM_MAJOR_VERSION}" = "1"]) 253 AM_CONDITIONAL([HAVE_SOFTHSM2], [test "${SOFTHSM_MAJOR_VERSION}" = "2"]) 173 254 174 255 AC_SUBST(MODULE_CFLAGS) … … 185 266 "[::1] 127.0.0.1". Note that IPv6 addresses must be \ 186 267 enclosed in square brackets.]) 187 AM_SUBST_NOTMAKE(TEST_IP) 268 269 : ${TEST_LOCK_WAIT:="30"} 270 : ${TEST_QUERY_TIMEOUT:="30"} 271 AC_ARG_VAR([TEST_LOCK_WAIT], [Timeout in seconds to acquire locks for \ 272 Apache instances in the test suite, or the \ 273 previous instance to remove its PID file if \ 274 flock is not used. Default is 30.]) 275 AC_ARG_VAR([TEST_QUERY_TIMEOUT], [Timeout in seconds for HTTPS requests \ 276 sent using gnutls-cli in the test suite. \ 277 Default is 30.]) 278 279 dnl Allow user to set SoftHSM PKCS #11 module 280 AC_ARG_VAR([SOFTHSM_LIB], [Absolute path of the SoftHSM PKCS @%:@11 module to \ 281 use. By default the test suite will search common \ 282 library paths.]) 188 283 189 284 dnl Build list of "Listen" statements for Apache 190 LISTEN_LIST=" #Listen addresses for the test servers"285 LISTEN_LIST="@%:@ Listen addresses for the test servers" 191 286 for i in ${TEST_IP}; do 192 287 LISTEN_LIST="${LISTEN_LIST} 193 288 Listen ${i}:\${TEST_PORT}" 194 289 done 195 dnl HTTP ports, only active if TEST_HTTP_PORT is defined 290 # Available extra ports, tests can "Define" variables of the listed 291 # names in their apache.conf to enable them. 292 for j in TEST_HTTP_PORT; do 196 293 LISTEN_LIST="${LISTEN_LIST} 197 <IfDefine TEST_HTTP_PORT>"294 <IfDefine ${j}>" 198 295 for i in ${TEST_IP}; do 199 296 LISTEN_LIST="${LISTEN_LIST} 200 Listen ${i}:\${ TEST_HTTP_PORT}"297 Listen ${i}:\${${j}}" 201 298 done 202 299 LISTEN_LIST="${LISTEN_LIST} 203 300 </IfDefine>" 301 done 204 302 AC_SUBST(LISTEN_LIST) 205 303 AM_SUBST_NOTMAKE(LISTEN_LIST) 206 304 305 DX_DOXYGEN_FEATURE(ON) 306 DX_DOT_FEATURE(ON) 307 DX_HTML_FEATURE(ON) 308 DX_MAN_FEATURE(OFF) 309 DX_RTF_FEATURE(OFF) 310 DX_XML_FEATURE(OFF) 311 DX_PDF_FEATURE(OFF) 312 DX_PS_FEATURE(OFF) 313 DX_INIT_DOXYGEN([mod_gnutls], [doc/doxygen.conf], [doc/api]) 314 207 315 AC_CONFIG_FILES([Makefile src/Makefile test/Makefile test/tests/Makefile \ 208 doc/Makefile include/mod_gnutls.h \ 209 test/proxy_backend.conf \ 316 doc/Makefile doc/doxygen.conf include/mod_gnutls.h \ 317 test/proxy_backend.conf test/ocsp_server.conf \ 318 test/apache-conf/early_sni.conf \ 210 319 test/apache-conf/listen.conf \ 211 320 test/apache-conf/netns.conf]) … … 218 327 echo " * Apache Modules directory: ${AP_LIBEXECDIR}" 219 328 echo " * GnuTLS Library version: ${LIBGNUTLS_VERSION}" 329 echo " * CFLAGS for GnuTLS: ${LIBGNUTLS_CFLAGS}" 330 echo " * LDFLAGS for GnuTLS: ${LIBGNUTLS_LIBS}" 220 331 echo " * SRP Authentication: ${use_srp}" 221 332 echo " * MSVA Client Verification: ${use_msva}" 333 echo " * Early SNI: ${early_sni}" 222 334 echo " * Build documentation: ${build_doc}" 223 335 echo "" -
doc/Makefile.am
r8a264b0 rea9c699 1 EXTRA_DIST = mod_gnutls_manual.mdwn 1 EXTRA_DIST = mod_gnutls_manual.mdwn mod_gnutls_manual.yaml.in 2 2 3 3 if USE_PANDOC 4 4 html_DATA = mod_gnutls_manual.html 5 man3_MANS = mod_gnutls_manual.man 5 6 if USE_PDFLATEX 6 7 # pandoc && pdflatex … … 14 15 endif 15 16 16 MOSTLYCLEANFILES = $(html_DATA) $(pdf_DATA) 17 MOSTLYCLEANFILES = $(html_DATA) $(pdf_DATA) $(man3_MANS) 17 18 18 # pdf_DATA will be empty if pandoc isn't available 19 $(html_DATA) $(pdf_DATA): mod_gnutls_manual.mdwn 19 %.yaml: %.yaml.in 20 sed -e s/__MOD_GNUTLS_VERSION__/@MOD_GNUTLS_VERSION@/ < $< > $@ 21 22 if USE_PANDOC 23 %.man: %.mdwn %.yaml 24 $(PANDOC) --standalone -f markdown -t man -o $@ $^ 25 26 if USE_PDFLATEX 27 %.pdf: %.mdwn 28 $(PANDOC) --toc -f markdown -o $@ $< 29 endif 30 endif 31 32 %.html: %.mdwn 20 33 if USE_PANDOC 21 34 $(PANDOC) --toc --standalone -f markdown -o $@ $< -
doc/mod_gnutls_manual.mdwn
r8a264b0 rea9c699 4 4 5 5 `mod_gnutls` is a module for the Apache web server that provides HTTPS 6 (HTTP over Transport Layer Security (TLS) or the older Secure Sockets7 Layer (SSL)) using the GnuTLS library. More information about the 8 module can be found at[the project's website](https://mod.gnutls.org/).6 (HTTP over Transport Layer Security (TLS)) using the GnuTLS library. 7 More information about the module can be found at 8 [the project's website](https://mod.gnutls.org/). 9 9 10 10 * * * * * … … 48 48 LoadModule gnutls_module modules/mod_gnutls.so 49 49 50 Note on HTTP/2 51 -------------- 52 53 HTTP/2 is supported with `mod_gnutls`. However, full support requires 54 compiling with GnuTLS 3.6.3 or later. When using lower versions all 55 virtual hosts using `mod_gnutls` with overlapping IP/port combinations 56 need to use identical `Protocols` directives for protocol negotiation 57 to work correctly. 58 59 The technical reason is that using HTTP/2 requires ALPN (Application 60 Layer Protocol Negotiation) to be set up before GnuTLS parses the TLS 61 ClientHello message, but earlier hooks cannot use 62 `gnutls_server_name_get()` to retrieve SNI (Server Name Indication) 63 data for virtual host selection. Because of this `mod_gnutls` provides 64 its own early SNI parser, which requires the `gnutls_ext_raw_parse()` 65 function introduced in GnuTLS 3.6.3 to retrieve the extension data in 66 a *pre* client hello hook. 67 68 During build `./configure` will report "Early SNI: yes" if your 69 version of GnuTLS is new enough. 70 50 71 * * * * * 51 72 … … 53 74 ======================== 54 75 55 `GnuTLSEnable` 56 -------------- 76 General Options 77 --------------- 78 79 ### GnuTLSEnable 57 80 58 81 Enable GnuTLS for this virtual host … … 65 88 This directive enables SSL/TLS Encryption for a Virtual Host. 66 89 67 `GnuTLSCache` 68 ------------- 69 70 Configure SSL Session Cache 71 72 GnuTLSCache [dbm|gdbm|memcache|none] [PATH|SERVERLIST|-] 90 ### GnuTLSCache 91 92 Configure TLS Session Cache 93 94 GnuTLSCache (shmcb|dbm|memcache|...|none)[:PARAMETERS] 73 95 74 96 Default: `GnuTLSCache none`\ 75 97 Context: server config 76 98 77 This directive configures the SSL Session Cache for `mod_gnutls`. 78 This could be shared between machines of different architectures. 79 80 `dbm` (Requires Berkeley DBM) 81 : Uses the default Berkeley DB backend of APR DBM to cache SSL 82 Sessions results. The argument is a relative or absolute path to 83 be used as the DBM Cache file. This is compatible with most 84 operating systems, but needs the Apache Runtime to be compiled 85 with Berkeley DBM support. 86 87 `gdbm` 88 : Uses the GDBM backend of APR DBM to cache SSL Sessions results. 89 90 The argument is a relative or absolute path to be used as the DBM Cache 91 file. This is the recommended option. 99 This directive configures the TLS Session Cache for `mod_gnutls`. This 100 could be shared between machines of different architectures. If the 101 selected cache implementation is not thread-safe, access is serialized 102 using the `gnutls-cache` mutex. 103 104 Which cache implementations are available depends on your Apache 105 installation and configuration, `mod_gnutls` can use any socache 106 provider. In general you will need to load a `mod_socache_PROVIDER` 107 module. Common options are described below, please check the Apache 108 HTTPD documentation for details on available providers and their 109 configuration. 110 111 `shmcb` 112 : Uses a shared memory segment. This is a high performance local 113 cache. The parameter is a relative or absolute path to be used if 114 the local shared memory implementation requires one, followed by 115 the cache size in bytes enclosed in parentheses. 116 117 Example: `shmcb:cache/gnutls_cache(65536)` 118 119 `dbm` 120 : Uses a DBM cache file. The parameter is a relative or absolute 121 path to be used as the DBM cache file. 122 123 Example: `dbm:cache/gnutls_cache` 92 124 93 125 `memcache` 94 : Uses a memcached server to cache the SSL Session.95 96 The argument is a space separated list of servers. If no port97 number is supplied, the default of 11211 is used. This can be 98 used to share a session cache between all servers in a cluster.126 : Uses memcached server(s) to cache TLS session data. The parameter 127 is a comma separated list of servers (host:port). This can be used 128 to share a session cache between all servers in a cluster. 129 130 Example: `memcache:memcache.example.com:12345,memcache2.example.com:12345` 99 131 100 132 `none` 101 : Turns off all caching of SSL Sessions. 102 103 This can significantly reduce the performance of `mod_gnutls` since 104 even followup connections by a client must renegotiate parameters 105 instead of reusing old ones. This is the default, since it 106 requires no configuration. 107 108 `GnuTLSCacheTimeout` 109 -------------------- 110 111 Timeout for SSL Session Cache expiration 133 : Turns off all caching of TLS sessions. 134 135 This can significantly reduce the performance of `mod_gnutls` 136 since even followup connections by a client must renegotiate 137 parameters instead of reusing old ones. This is the default, since 138 it requires no configuration. 139 140 Session tickets are an alternative to using a session cache, 141 please see `GnuTLSSessionTickets`. Note that for TLS 1.3 GnuTLS 142 supports resumption using session tickets only as of version 143 3.6.4. 144 145 ### GnuTLSCacheTimeout 146 147 Timeout for TLS Session Cache expiration 112 148 113 149 GnuTLSCacheTimeout SECONDS 114 150 115 151 Default: `GnuTLSCacheTimeout 300`\ 116 Context: server config 117 118 Sets the timeout for SSL Session Cache entries expiration. This 119 directive is valid even if Session Tickets are used, and indicates the 120 expiration time of the ticket in seconds. 121 122 `GnuTLSSessionTickets` 123 ---------------------- 152 Context: server config, virtual host 153 154 Sets the expiration timeout for cached TLS sessions. 155 156 ### GnuTLSSessionTickets 124 157 125 158 Enable Session Tickets for the server … … 127 160 GnuTLSSessionTickets [on|off] 128 161 129 Default: `off`\ 130 Context: server config, virtual host 131 132 To avoid storing data for TLS session resumption it is allowed to 133 provide client with a ticket, to use on return. Use for servers with 134 limited storage, and don't combine with GnuTLSCache. For a pool of 135 servers this option is not recommended since the tickets are unique 136 for the issuing server only. 137 138 139 `GnuTLSCertificateFile` 140 ----------------------- 141 142 Set to the PEM Encoded Server Certificate 143 144 GnuTLSCertificateFile FILEPATH 145 146 Default: *none*\ 147 Context: server config, virtual host 148 149 Takes an absolute or relative path to a PEM-encoded X.509 certificate to 150 use as this Server's End Entity (EE) certificate. If you need to supply 151 certificates for intermediate Certificate Authorities (iCAs), they 152 should be listed in sequence in the file, from EE to the iCA closest to 153 the root CA. Optionally, you can also include the root CA's certificate 154 as the last certificate in the list. 155 156 Since version 0.7 this can be a PKCS #11 URL. 157 158 `GnuTLSKeyFile` 159 --------------- 160 161 Set to the PEM Encoded Server Private Key 162 163 GnuTLSKeyFile FILEPATH 164 165 Default: *none*\ 166 Context: server config, virtual host 167 168 Takes an absolute or relative path to the Server Private Key. Set 169 `GnuTLSPIN` if the key file is encrypted. 170 171 Since version 0.7 this can be a PKCS #11 URL. 172 173 **Security Warning:**\ 174 This private key must be protected. It is read while Apache is still 175 running as root, and does not need to be readable by the nobody or 176 apache user. 177 178 `GnuTLSPGPCertificateFile` 179 -------------------------- 180 181 Set to a base64 Encoded Server OpenPGP Certificate 182 183 GnuTLSPGPCertificateFile FILEPATH 184 185 Default: *none*\ 186 Context: server config, virtual host 187 188 Takes an absolute or relative path to a base64 Encoded OpenPGP 189 Certificate to use as this Server's Certificate. 190 191 `GnuTLSPGPKeyFile` 192 ------------------ 193 194 Set to the Server OpenPGP Secret Key 195 196 GnuTLSPGPKeyFile FILEPATH 197 198 Default: *none*\ 199 Context: server config, virtual host 200 201 Takes an absolute or relative path to the Server Private Key. This key 202 cannot currently be password protected. 203 204 **Security Warning:**\ 205 This private key must be protected. It is read while Apache is still 206 running as root, and does not need to be readable by the nobody or 207 apache user. 208 209 `GnuTLSClientVerify` 210 -------------------- 211 212 Enable Client Certificate Verification\ 162 Default: `on` with GnuTLS 3.6.4 and newer, `off` otherwise\ 163 Context: server config, virtual host 164 165 Session tickets allow TLS session resumption without session state 166 stored on the server, using encrypted tickets provided to the clients 167 instead. Tickets are an alternative to using a session cache, and 168 currently the only session resumption mechanism in TLS 1.3. For a pool 169 of servers this option is not recommended since the tickets are bound 170 to the issuing server only. 171 172 If this option is set in the global configuration, virtual hosts 173 without a `GnuTLSSessionTickets` setting will use the global setting. 174 175 *Warning:* With GnuTLS version before 3.6.4 the master key that 176 protects the tickets is generated only on server start, and there is 177 no mechanism to roll over the key. If session tickets are enabled it 178 is highly recommended to restart the server regularly to protect past 179 sessions in case an attacker gains access to server memory. GnuTLS 180 3.6.4 introduced an automatic TOTP-based key rollover, so this warning 181 does not apply any more and tickets are enabled by default. 182 183 ### GnuTLSClientVerify 184 185 Enable Client Certificate Verification 213 186 214 187 GnuTLSClientVerify [ignore|request|require] … … 217 190 Context: server config, virtual host, directory, .htaccess 218 191 219 This directive controls the use of SSLClient Certificate192 This directive controls the use of TLS Client Certificate 220 193 Authentication. If used in the .htaccess context, it can force TLS 221 194 re-negotiation. 222 195 223 196 `ignore` 224 : `mod_gnutls` will ignore the contents of any SSLClient Certificates197 : `mod_gnutls` will ignore the contents of any TLS Client Certificates 225 198 sent. It will not request that the client sends a certificate. 226 199 … … 236 209 environment variable will only be set to `SUCCESS`. 237 210 238 `GnuTLSClientCAFile` 239 -------------------- 240 241 Set to the PEM Encoded Certificate Authority Certificate 211 ### GnuTLSDHFile 212 213 Use the provided PKCS \#3 encoded Diffie-Hellman parameters 214 215 GnuTLSDHFile FILEPATH 216 217 Default: *none*\ 218 Context: server config, virtual host 219 220 By default, `mod_gnutls` uses the DH parameters included with GnuTLS 221 corresponding to the security level of the configured private keys if 222 compiled with GnuTLS 3.5.6 or newer, and the ffdhe2048 DH group as 223 defined in RFC 7919, Appendix A.1 otherwise. 224 225 If you need to use different DH parameters, you can provide a PEM file 226 containing them in PKCS \#3 encoding using this option. Please see the 227 "[Parameter 228 generation](https://gnutls.org/manual/html_node/Parameter-generation.html)" 229 section of the GnuTLS documentation for a short discussion of the 230 security implications. 231 232 ### GnuTLSPriorities 233 234 Set the allowed protocol versions, ciphers, key exchange algorithms, 235 MACs and compression methods 236 237 GnuTLSPriorities NORMAL:+CIPHER_0:+CIPHER_1:...:+CIPHER_N 238 239 Default: `NORMAL`\ 240 Context: server config, virtual host 241 242 Sets the allowed protocol version(s), ciphers, key exchange methods, 243 message authentication codes, and other TLS parameters for the server. 244 The parameter is a GnuTLS priority string as described in the 245 [the GnuTLS documentation](https://gnutls.org/manual/html_node/Priority-Strings.html). 246 247 For example, to disable TLS 1.0 use `NORMAL:-VERS-TLS1.0`. 248 249 ### GnuTLSP11Module 250 251 Load this PKCS #11 module. 252 253 GnuTLSP11Module PATH_TO_LIBRARY 254 255 Default: *none*\ 256 Context: server config 257 258 Load this PKCS #11 provider module, instead of the system 259 defaults. May occur multiple times to load multiple modules. 260 261 ### GnuTLSPIN 262 263 Set the PIN to be used to access encrypted key files or PKCS #11 objects. 264 265 GnuTLSPIN XXXXXX 266 267 Default: *none*\ 268 Context: server config, virtual host 269 270 Takes a string to be used as a PIN for the protected objects in 271 a security module, or as a key to be used to decrypt PKCS #8, PKCS #12, 272 or openssl encrypted keys. 273 274 ### GnuTLSSRKPIN 275 276 Set the SRK PIN to be used to access the TPM. 277 278 GnuTLSSRKPIN XXXXXX 279 280 Default: *none*\ 281 Context: server config, virtual host 282 283 Takes a string to be used as a PIN for the protected objects in 284 the TPM module. 285 286 ### GnuTLSExportCertificates 287 288 Export the PEM encoded certificates to CGIs 289 290 GnuTLSExportCertificates [off|on|SIZE] 291 292 Default: `off`\ 293 Context: server config, virtual host 294 295 This directive configures exporting the full certificates of the 296 server and the client to CGI scripts via the `SSL_SERVER_CERT` and 297 `SSL_CLIENT_CERT` environment variables. The exported certificates 298 will be PEM-encoded, limited to the given size. The type of the 299 certificate will be exported in `SSL_SERVER_CERT_TYPE` and 300 `SSL_CLIENT_CERT_TYPE`. 301 302 SIZE should be an integer number of bytes, or may be written with a 303 trailing `K` to indicate kibibytes. `off` means the same thing as 304 `0`, in which case the certificates will not be exported to the 305 environment. `on` is an alias for `16K`. If a non-zero size is 306 specified for this directive, but a certificate is too large to fit in 307 the buffer, then the corresponding environment variable will contain 308 the fixed string `GNUTLS_CERTIFICATE_SIZE_LIMIT_EXCEEDED`. 309 310 With GnuTLSExportCertificates enabled, `mod_gnutls` exports the same 311 environment variables to the CGI process as `mod_ssl`. 312 313 X.509 Certificate Authentication 314 -------------------------------- 315 316 ### GnuTLSCertificateFile 317 318 Set the PEM encoded server certificate or certificate chain 319 320 GnuTLSCertificateFile FILEPATH 321 322 Default: *none*\ 323 Context: server config, virtual host 324 325 FILEPATH is an absolute or relative path to a file containing the 326 PEM-encoded X.509 certificate to use as this Server's End Entity (EE) 327 certificate, and optionally those of the issuing Certificate 328 Authorities (CAs). If the file contains multiple certificates they 329 should be ordered from EE to the CA closest to the root CA (or the 330 root CA itself). 331 332 Including at least the immediately issuing CA is highly recommended 333 because it is required for OCSP stapling. 334 335 Since version 0.7 this can be a PKCS #11 URL instead of a file. 336 337 On Linux and other Unix-like systems you can create the file with a 338 command like this (assuming "CA 1" issued the server certificate and 339 has been issued by "Root CA" itself): 340 341 $ cat server.pem ca-1.pem root-ca.pem >server-chain.pem 342 343 ### GnuTLSKeyFile 344 345 Set to the PEM Encoded Server Private Key 346 347 GnuTLSKeyFile FILEPATH 348 349 Default: *none*\ 350 Context: server config, virtual host 351 352 Takes an absolute or relative path to the Server Private Key. Set 353 `GnuTLSPIN` if the key file is encrypted. 354 355 Since version 0.7 this can be a PKCS #11 URL. 356 357 **Security Warning:**\ 358 This private key must be protected. It is read while Apache is still 359 running as root, and does not need to be readable by the nobody or 360 apache user. 361 362 ### GnuTLSClientCAFile 363 364 Set the PEM encoded Certificate Authority list to use for X.509 base 365 client authentication 242 366 243 367 GnuTLSClientCAFile FILEPATH … … 250 374 This file may contain a list of trusted authorities. 251 375 252 `GnuTLSPGPKeyringFile` 253 ---------------------- 254 255 Set to a base64 Encoded key ring 256 257 GnuTLSPGPKeyringFile FILEPATH 258 259 Default: *none*\ 260 Context: server config, virtual host 261 262 Takes an absolute or relative path to a base64 Encoded Certificate 263 list (key ring) to use as a means of verification of Client 264 Certificates. This file should contain a list of trusted signers. 265 266 `GnuTLSDHFile` 267 -------------- 268 269 Set to the PKCS \#3 encoded Diffie Hellman parameters 270 271 GnuTLSDHFile FILEPATH 272 273 Default: *none*\ 274 Context: server config, virtual host 275 276 Takes an absolute or relative path to a PKCS \#3 encoded DH 277 parameters.Those are used when the DHE key exchange method is enabled. 278 You can generate this file using `certtool --generate-dh-params --bits 279 2048`. If not set `mod_gnutls` will use the included parameters. 280 281 `GnuTLSSRPPasswdFile` 282 --------------------- 376 SRP Authentication 377 ------------------ 378 379 ### GnuTLSSRPPasswdFile 283 380 284 381 Set to the SRP password file for SRP ciphersuites … … 296 393 dependency to the SRP parameters. 297 394 298 `GnuTLSSRPPasswdConfFile` 299 ------------------------- 395 ### GnuTLSSRPPasswdConfFile 300 396 301 397 Set to the SRP password.conf file for SRP ciphersuites 302 398 303 GnuTLSSRPPasswdConfFile FILEPATH 399 GnuTLSSRPPasswdConfFile FILEPATH 304 400 305 401 Default: *none*\ … … 312 408 (the verifiers depends on these parameters). 313 409 314 `GnuTLSPriorities` 315 ------------------ 316 317 Set the allowed ciphers, key exchange algorithms, MACs and compression 318 methods 319 320 GnuTLSPriorities NORMAL:+CIPHER_0:+CIPHER_1:...:+CIPHER_N 321 322 Default: *none*\ 323 Context: server config, virtual host 324 325 Takes a semi-colon separated list of ciphers, key exchange methods 326 Message authentication codes and compression methods to enable. 327 The allowed keywords are specified in the `gnutls_priority_init()` 328 function of GnuTLS. 329 330 Full details can be found at [the GnuTLS documentation](http://gnutls.org/manual/html_node/Priority-Strings.html#Priority-Strings). 331 In brief you can specify a set of ciphersuites from the choices: 332 333 `NONE` 334 : The empty list. 335 336 `EXPORT` 337 : A list with all the supported cipher combinations 338 including the `EXPORT` strength algorithms. 339 340 `PERFORMANCE` 341 : A list with all the secure cipher combinations sorted in terms of performance. 342 343 `NORMAL` 344 : A list with all the secure cipher combinations sorted 345 with respect to security margin (subjective term). 346 347 `SECURE` 348 : A list with all the secure cipher combinations including 349 the 256-bit ciphers sorted with respect to security margin. 350 351 Additionally you can add or remove algorithms using the `+` and `!` 352 prefixes respectively. 353 354 For example, in order to disable the `ARCFOUR` cipher from the `NORMAL` set 355 you can use the string `NORMAL:!ARCFOUR-128` 356 357 Other options such as the protocol version and the compression method 358 can be specified using the `VERS-` and `COMP-` prefixes. 359 360 So in order to remove or add a specific TLS version from the `NORMAL` 361 set, use `NORMAL:!VERS-SSL3.0`. And to enable zlib compression use 362 `NORMAL:+COMP-DEFLATE`. 363 364 365 However it is recommended not to add compression at this level. With 366 the `NONE` set, in order to be usable, you have to specify a complete 367 set of combinations of protocol versions, cipher algorithms 368 (`AES-128-CBC`), key exchange algorithms (`RSA`), message 369 authentication codes (`SHA1`) and compression methods (`COMP-NULL`). 370 371 You can find a list of all supported Ciphers, Versions, MACs, etc. by 372 running `gnutls-cli --list`. 373 374 The special keyword `%COMPAT` will disable some security features such 375 as protection against statistical attacks to ciphertext data in order to 376 achieve maximum compatibility (some broken mobile clients need this). 377 378 `GnuTLSP11Module` 379 ------------------ 380 381 Load this PKCS #11 module. 382 383 GnuTLSP11Module PATH_TO_LIBRARY 384 385 Default: *none*\ 386 Context: server config 387 388 Load this PKCS #11 provider module, instead of the system 389 defaults. May occur multiple times to load multiple modules. 390 391 `GnuTLSPIN` 392 ------------------ 393 394 Set the PIN to be used to access encrypted key files or PKCS #11 objects. 395 396 GnuTLSPIN XXXXXX 397 398 Default: *none*\ 399 Context: server config, virtual host 400 401 Takes a string to be used as a PIN for the protected objects in 402 a security module, or as a key to be used to decrypt PKCS #8, PKCS #12, 403 or openssl encrypted keys. 404 405 `GnuTLSSRKPIN` 406 ------------------ 407 408 Set the SRK PIN to be used to unlaccess the TPM. 409 410 GnuTLSSRKPIN XXXXXX 411 412 Default: *none*\ 413 Context: server config, virtual host 414 415 Takes a string to be used as a PIN for the protected objects in 416 the TPM module. 417 418 `GnuTLSExportCertificates` 419 -------------------------- 420 421 Export the PEM encoded certificates to CGIs 422 423 GnuTLSExportCertificates [off|on|SIZE] 424 425 Default: `off`\ 426 Context: server config, virtual host 427 428 This directive configures exporting the full certificates of the 429 server and the client to CGI scripts via the `SSL_SERVER_CERT` and 430 `SSL_CLIENT_CERT` environment variables. The exported certificates 431 will be PEM-encoded (if X.509) or ASCII-armored (if OpenPGP) up to the 432 size given. The type of the certificate will be exported in 433 `SSL_SERVER_CERT_TYPE` and `SSL_CLIENT_CERT_TYPE`. 434 435 SIZE should be an integer number of bytes, or may be written with a 436 trailing `K` to indicate kibibytes. `off` means the same thing as 437 `0`, in which case the certificates will not be exported to the 438 environment. `on` is an alias for `16K`. If a non-zero size is 439 specified for this directive, but a certificate is too large to fit in 440 the buffer, then the corresponding environment variable will contain 441 the fixed string `GNUTLS_CERTIFICATE_SIZE_LIMIT_EXCEEDED`. 442 443 With GnuTLSExportCertificates enabled, `mod_gnutls` exports the same 444 environment variables to the CGI process as `mod_ssl`. 445 446 447 `GnuTLSProxyEngine` 448 -------------- 410 TLS Proxy Configuration 411 ----------------------- 412 413 ### GnuTLSProxyEngine 449 414 450 415 Enable TLS proxy connections for this virtual host … … 458 423 host. 459 424 460 `GnuTLSProxyCAFile` 461 -------------------- 425 ### GnuTLSProxyCAFile 462 426 463 427 Set to the PEM encoded Certificate Authority Certificate … … 474 438 always fail due to lack of a trusted CA. 475 439 476 `GnuTLSProxyCRLFile` 477 -------------------- 440 ### GnuTLSProxyCRLFile 478 441 479 442 Set to the PEM encoded Certificate Revocation List … … 488 451 back end servers. The file may contain a list of CRLs. 489 452 490 `GnuTLSProxyCertificateFile` 491 ----------------------- 453 ### GnuTLSProxyCertificateFile 492 454 493 455 Set to the PEM encoded Client Certificate … … 510 472 provide the matching private key. 511 473 512 `GnuTLSProxyKeyFile` 513 --------------- 474 ### GnuTLSProxyKeyFile 514 475 515 476 Set to the PEM encoded Private Key … … 529 490 apache user. 530 491 531 `GnuTLSProxyPriorities` 532 ------------------ 492 ### GnuTLSProxyPriorities 533 493 534 494 Set the allowed ciphers, key exchange algorithms, MACs and compression … … 537 497 GnuTLSProxyPriorities NORMAL:+CIPHER_0:+CIPHER_1:...:+CIPHER_N 538 498 539 Default: *none*\ 540 Context: server config, virtual host 541 542 This option is used to set the allowed ciphers, key exchange 543 algorithms, MACs and compression methods for proxy connections. It 544 takes the same parameters as `GnuTLSPriorities`. Required if 545 `GnuTLSProxyEngine` is `On`. 499 Default: `NORMAL`\ 500 Context: server config, virtual host 501 502 Sets the allowed protocol version(s), ciphers, key exchange methods, 503 message authentication codes, and other TLS parameters for TLS proxy 504 connections. Like for `GnuTLSPriorities` the parameter is a GnuTLS 505 priority string as described in the 506 [the GnuTLS documentation](https://gnutls.org/manual/html_node/Priority-Strings.html). 507 508 OCSP Stapling Configuration 509 --------------------------- 510 511 ### GnuTLSOCSPStapling 512 513 Enable OCSP stapling for this (virtual) host. 514 515 GnuTLSOCSPStapling [On|Off] 516 517 Default: *on* if requirements are met, *off* otherwise\ 518 Context: server config, virtual host 519 520 OCSP stapling, formally known as the TLS Certificate Status Request 521 extension, allows the server to provide the client with a cached OCSP 522 response for its certificate during the handshake. With OCSP stapling 523 the client does not have to send an OCSP request to the issuer CA to 524 check the certificate status, which offers privacy and performance 525 advantages, and avoids the security issue of how to handle errors that 526 prevent the client from getting a response. 527 528 Using OCSP stapling has a few requirements: 529 530 * `GnuTLSCertificateFile` must contain the issuer CA certificate in 531 addition to the server certificate so responses can be verified. 532 * The server certificate must either contain an OCSP access URI using 533 HTTP, or `GnuTLSOCSPResponseFile` must be set. 534 * Caching OCSP responses requires a cache to store responses. If 535 `mod_socache_shmcb` is loaded `mod_gnutls` can set up the cache 536 automatically without additional configuration, see 537 `GnuTLSOCSPCache`. 538 539 Stapling is activated by default if these requirements are met. If 540 `GnuTLSOCSPStapling` is explicitly set to `on` unmet requirements are 541 an error. 542 543 OCSP cache updates are serialized using the `gnutls-ocsp` mutex. 544 545 ### GnuTLSOCSPCache 546 547 OCSP stapling cache configuration 548 549 GnuTLSOCSPCache (shmcb|memcache|...|none)[:PARAMETERS] 550 551 Default: `shmcb:gnutls_ocsp_cache`\ 552 Context: server config 553 554 This directive configures the OCSP stapling cache, and uses the same 555 syntax as `GnuTLSOCSPCache`. Please check there for details. 556 557 The default should be reasonable for most servers and requires 558 [mod\_socache\_shmcb](http://httpd.apache.org/docs/current/en/mod/mod_socache_shmcb.html) 559 to be loaded. Servers with very many virtual hosts may need to 560 increase the default cache size via the parameters string, those with 561 few virtual hosts and memory constraints could save a few KB by reducing 562 it. Note that `mod_socache_dbm` has a size constraint for entries that 563 is generally too small for OCSP responses. 564 565 If the selected cache implementation is not thread-safe, access 566 is serialized using the `gnutls-ocsp-cache` mutex. 567 568 ### GnuTLSOCSPAutoRefresh 569 570 Regularly refresh cached OCSP response independent of TLS handshakes? 571 572 GnuTLSOCSPAutoRefresh [On|Off] 573 574 Default: *on*\ 575 Context: server config, virtual host 576 577 By default `mod_gnutls` will regularly refresh the cached OCSP 578 response for hosts that have OCSP stapling enabled, regardless of 579 whether it is used. This has advantages over updating the OCSP 580 response only if a TLS handshake needs it: 581 582 * Updating the cached response before it expires can hide short 583 unavailability of the OCSP responder, if a repeated request is 584 successful before the cache expires (see below). 585 586 * Handshakes are not slowed down by fetching responses. 587 588 The interval to the next request is determined as follows: After a 589 successful OCSP request the next one is scheduled for a random period 590 between `GnuTLSOCSPFuzzTime` and half of it before 591 `GnuTLSOCSPCacheTimeout` expires. For example, if the cache timeout is 592 3600 seconds and the fuzz time 600 seconds, the next request will be 593 sent after 3000 to 3300 seconds. If the validity period of the 594 response expires before then, the selected interval is halved until it 595 is smaller than the time until expiry. If an OCSP request fails, it is 596 retried after `GnuTLSOCSPFailureTimeout`. 597 598 Regularly updating the OCSP cache requires `mod_watchdog`, 599 `mod_gnutls` will fall back to updating the OCSP cache during 600 handshakes if `mod_watchdog` is not available or this option is set to 601 `Off`. 602 603 ### GnuTLSOCSPCheckNonce 604 605 Check the nonce in OCSP responses? 606 607 GnuTLSOCSPCheckNonce [On|Off] 608 609 Default: *on*\ 610 Context: server config, virtual host 611 612 Some CAs refuse to send nonces in their OCSP responses, probably 613 because that way they can cache responses. If your CA is one of them 614 you can use this flag to disable nonce verification. Note that 615 `mod_gnutls` will _send_ a nonce either way. 616 617 ### GnuTLSOCSPResponseFile 618 619 Read the OCSP response for stapling from this file instead of sending 620 a request over HTTP. 621 622 GnuTLSOCSPResponseFile /path/to/response.der 623 624 Default: *empty*\ 625 Context: server config, virtual host 626 627 The response file must be updated externally, for example using a cron 628 job. This option is an alternative to the server fetching OCSP 629 responses over HTTP. Reasons to use this option include: 630 631 * Performing OCSP requests separate from the web server, to prevent slow 632 responses from stalling handshakes. 633 * The issuer CA uses an access method other than HTTP. 634 * Testing 635 636 You can use a GnuTLS `ocsptool` command like the following to create 637 and update the response file: 638 639 ocsptool --ask --nonce --load-issuer ca_cert.pem \ 640 --load-cert server_cert.pem --outfile ocsp_response.der 641 642 Additional error checking is highly recommended. You may have to 643 remove the `--nonce` option if the OCSP responder of your CA does not 644 support nonces. 645 646 ### GnuTLSOCSPCacheTimeout 647 648 Cache timeout for OCSP responses 649 650 GnuTLSOCSPCacheTimeout SECONDS 651 652 Default: *3600*\ 653 Context: server config, virtual host 654 655 Cached OCSP responses will be refreshed after the configured number of 656 seconds. How long this timeout should reasonably be depends on your 657 CA, namely how often its OCSP responder is updated and how long 658 responses are valid. Note that a response will not be cached beyond 659 its lifetime as denoted in the `nextUpdate` field of the response. 660 661 ### GnuTLSOCSPFailureTimeout 662 663 Wait this many seconds before retrying a failed OCSP request. 664 665 GnuTLSOCSPFailureTimeout SECONDS 666 667 Default: *300*\ 668 Context: server config, virtual host 669 670 Retries of failed OCSP requests must be rate limited to avoid 671 overloading both the server using mod_gnutls and the CA's OCSP 672 responder. A shorter value increases the load on both sides, a longer 673 one means that stapling will remain disabled for longer after a failed 674 request. 675 676 ### GnuTLSOCSPFuzzTime 677 678 Update the cached OCSP response up to this time before the cache expires 679 680 GnuTLSOCSPFuzzTime SECONDS 681 682 Default: *larger of GnuTLSOCSPCacheTimeout / 8 and GnuTLSOCSPFailureTimeout \* 2*\ 683 Context: server config, virtual host 684 685 Refreshing the cached response before it expires hides short OCSP 686 responder unavailability. See `GnuTLSOCSPAutoRefresh` for how this 687 value is used, using at least twice `GnuTLSOCSPFailureTimeout` is 688 recommended. 689 690 ### GnuTLSOCSPSocketTimeout 691 692 Timeout for TCP sockets used to send OCSP requests 693 694 GnuTLSOCSPFailureTimeout SECONDS 695 696 Default: *6*\ 697 Context: server config, virtual host 698 699 Stalled OCSP requests must time out after a while to prevent stalling 700 the server too much. However, if the timeout is too short requests may 701 fail with a slow OCSP responder or high latency network 702 connection. This parameter allows you to adjust the timeout if 703 necessary. 704 705 Note that this is not an upper limit for the completion of an OCSP 706 request but a socket timeout. The connection will time out if there is 707 no activity (successful send or receive) at all for the configured 708 time. 546 709 547 710 * * * * * … … 550 713 ====================== 551 714 552 Simple Standard SSL Example 553 --------------------------- 554 555 The following is an example of standard SSL Hosting, using one IP 556 Addresses for each virtual host 715 Minimal Example 716 --------------- 717 718 A minimal server configuration using mod_gnutls might look like this 719 (other than the default setup): 720 721 # Load mod_gnutls into Apache. 722 LoadModule gnutls_module modules/mod_gnutls.so 723 724 Listen 192.0.2.1:443 725 726 <VirtualHost _default_:443> 727 # Standard virtual host stuff 728 DocumentRoot /www/site1.example.com/html 729 ServerName site1.example.com:443 730 731 # Minimal mod_gnutls setup: enable, and set credentials 732 GnuTLSEnable on 733 GnuTLSCertificateFile conf/tls/site1_cert_chain.pem 734 GnuTLSKeyFile conf/tls/site1_key.pem 735 </VirtualHost> 736 737 This gives you an HTTPS site using the GnuTLS `NORMAL` set of 738 ciphersuites. OCSP stapling will be enabled if the server certificate 739 contains an OCSP URI, `conf/tls/site1_cert_chain.pem` contains the 740 issuer certificate in addition to the server's, and 741 [mod\_socache\_shmcb](http://httpd.apache.org/docs/current/en/mod/mod_socache_shmcb.html) 742 is loaded. With Gnutls 3.6.4 or newer session tickets are enabled, 743 too. 744 745 Virtual Hosts with Server Name Indication 746 ----------------------------------------- 747 748 `mod_gnutls` supports Server Name Indication (SNI), as specified in 749 [RFC 6066, Section 3](https://tools.ietf.org/html/rfc6066#section-3). 750 This allows hosting many TLS websites with a single IP address, you 751 can just add virtual host configurations. All recent browsers support 752 this standard. Here is an example using SNI: 557 753 558 754 # Load the module into Apache. 559 755 LoadModule gnutls_module modules/mod_gnutls.so 560 GnuTLSCache gdbm /var/cache/www-tls-cache 561 GnuTLS CacheTimeout 500562 # With normal SSL Websites, you need one IP Address per-site. 563 Listen 1.2.3.1:443564 Listen 1.2.3.2:443565 Listen 1.2.3.3:443566 Listen 1 .2.3.4:443567 <VirtualHost 1.2.3.1:443> 568 GnuTLSEnable on569 GnuTLSPriorities NONE:+AES-128-CBC:+3DES-CBC:+ARCFOUR-128:+RSA:+DHE-RSA:+DHE-DSS:+SHA1:+MD5:+COMP-NULL570 DocumentRoot /www/site1.example.com/html571 ServerName site1.example.com:443572 GnuTLSCertificateFile conf/ssl/site1.crt573 GnuTLSKeyFile conf/ss/site1.key756 # This example server uses session tickets, no cache. 757 GnuTLSSessionTickets on 758 759 # SNI allows hosting multiple sites using one IP address. This 760 # could also be 'Listen *:443', just like '*:80' is common for 761 # non-HTTPS 762 Listen 198.51.100.1:443 763 764 <VirtualHost _default_:443> 765 GnuTLSEnable on 766 DocumentRoot /www/site1.example.com/html 767 ServerName site1.example.com:443 768 GnuTLSCertificateFile conf/tls/site1.crt 769 GnuTLSKeyFile conf/tls/site1.key 574 770 </VirtualHost> 575 <VirtualHost 1.2.3.2:443> 576 # This virtual host enables SRP authentication 577 GnuTLSEnable on 578 GnuTLSPriorities NORMAL:+SRP 579 DocumentRoot /www/site2.example.com/html 580 ServerName site2.example.com:443 581 GnuTLSSRPPasswdFile conf/ssl/tpasswd.site2 582 GnuTLSSRPPasswdConfFile conf/ssl/tpasswd.site2.conf 771 772 <VirtualHost _default_:443> 773 GnuTLSEnable on 774 DocumentRoot /www/site2.example.com/html 775 ServerName site2.example.com:443 776 GnuTLSCertificateFile conf/tls/site2.crt 777 GnuTLSKeyFile conf/tls/site2.key 583 778 </VirtualHost> 584 <VirtualHost 1.2.3.3:443> 585 # This server enables SRP, OpenPGP and X.509 authentication. 586 GnuTLSEnable on 587 GnuTLSPriorities NORMAL:+SRP:+SRP-RSA:+SRP-DSS 588 DocumentRoot /www/site3.example.com/html 589 ServerName site3.example.com:443 590 GnuTLSCertificateFile conf/ssl/site3.crt 591 GnuTLSKeyFile conf/ss/site3.key 592 GnuTLSClientVerify ignore 593 GnuTLSPGPCertificateFile conf/ss/site3.pub.asc 594 GnuTLSPGPKeyFile conf/ss/site3.sec.asc 595 GnuTLSSRPPasswdFile conf/ssl/tpasswd.site3 596 GnuTLSSRPPasswdConfFile conf/ssl/tpasswd.site3.conf 779 780 <VirtualHost _default_:443> 781 GnuTLSEnable on 782 DocumentRoot /www/site3.example.com/html 783 ServerName site3.example.com:443 784 GnuTLSCertificateFile conf/tls/site3.crt 785 GnuTLSKeyFile conf/tls/site3.key 786 # Enable HTTP/2. With GnuTLS before version 3.6.3 all 787 # virtual hosts in this example would have to share this 788 # directive to work correctly. 789 Protocols h2 http/1.1 597 790 </VirtualHost> 598 <VirtualHost 1.2.3.4:443> 599 GnuTLSEnable on 600 # %COMPAT disables some security features to enable maximum compatibility with clients. 601 GnuTLSPriorities NONE:+AES-128-CBC:+ARCFOUR-128:+RSA:+SHA1:+MD5:+COMP-NULL:%COMPAT 602 DocumentRoot /www/site4.example.com/html 603 ServerName site4.example.com:443 604 GnuTLSCertificateFile conf/ssl/site4.crt 605 GnuTLSKeyFile conf/ss/site4.key 606 </VirtualHost> 607 608 Server Name Indication Example 609 ------------------------------ 610 611 `mod_gnutls` can also use "Server Name Indication", as specified in 612 RFC 3546. This allows hosting many SSL Websites, with a Single IP 613 Address. Currently all the recent browsers support this 614 standard. Here is an example, using SNI: ` ` 615 791 792 Virtual Hosts without SNI 793 ------------------------- 794 795 If you need to support clients that do not use SNI, you have to use a 796 unique IP address/port combination for each virtual host. In this 797 example all virtual hosts use the default port for HTTPS (443) and 798 different IP addresses. 616 799 617 800 # Load the module into Apache. 618 801 LoadModule gnutls_module modules/mod_gnutls.so 619 # With normal SSL Websites, you need one IP Address per-site. 620 Listen 1.2.3.1:443 621 # This could also be 'Listen *:443', 622 # just like '*:80' is common for non-https 623 # No caching. Enable session tickets. Timeout is still used for 624 # ticket expiration. 625 GnuTLSCacheTimeout 600 626 # This tells apache, that for this IP/Port combination, we want to use 627 # Name Based Virtual Hosting. In the case of Server Name Indication, 628 # it lets mod_gnutls pick the correct Server Certificate. 629 NameVirtualHost 1.2.3.1:443 630 <VirtualHost 1.2.3.1:443> 631 GnuTLSEnable on 632 GnuTLSSessionTickets on 633 GnuTLSPriorities NORMAL 634 DocumentRoot /www/site1.example.com/html 635 ServerName site1.example.com:443 636 GnuTLSCertificateFile conf/ssl/site1.crt 637 GnuTLSKeyFile conf/ss/site1.key 802 # This example server uses a session cache. 803 GnuTLSCache dbm:/var/cache/www-tls-cache 804 GnuTLSCacheTimeout 1200 805 806 # Without SNI you need one IP Address per site. The IP addresses 807 # are listed separately for clarity, you could also use "Listen 443" 808 # to use that port on all available IP addresses. 809 Listen 192.0.2.1:443 810 Listen 192.0.2.2:443 811 Listen 192.0.2.3:443 812 813 <VirtualHost 192.0.2.1:443> 814 GnuTLSEnable on 815 GnuTLSPriorities SECURE128 816 DocumentRoot /www/site1.example.com/html 817 ServerName site1.example.com:443 818 GnuTLSCertificateFile conf/tls/site1.crt 819 GnuTLSKeyFile conf/tls/site1.key 638 820 </VirtualHost> 639 <VirtualHost 1.2.3.1:443> 640 GnuTLSEnable on 641 GnuTLSPriorities NORMAL 642 DocumentRoot /www/site2.example.com/html 643 ServerName site2.example.com:443 644 GnuTLSCertificateFile conf/ssl/site2.crt 645 GnuTLSKeyFile conf/ss/site2.key 821 822 <VirtualHost 192.0.2.2:443> 823 # This virtual host enables SRP authentication 824 GnuTLSEnable on 825 GnuTLSPriorities NORMAL:+SRP 826 DocumentRoot /www/site2.example.com/html 827 ServerName site2.example.com:443 828 GnuTLSSRPPasswdFile conf/tls/tpasswd.site2 829 GnuTLSSRPPasswdConfFile conf/tls/tpasswd.site2.conf 646 830 </VirtualHost> 647 <VirtualHost 1.2.3.1:443> 648 GnuTLSEnable on 649 GnuTLSPriorities NORMAL 650 DocumentRoot /www/site3.example.com/html 651 ServerName site3.example.com:443 652 GnuTLSCertificateFile conf/ssl/site3.crt 653 GnuTLSKeyFile conf/ss/site3.key 831 832 <VirtualHost 192.0.2.3:443> 833 # This server enables SRP and X.509 authentication. 834 GnuTLSEnable on 835 GnuTLSPriorities NORMAL:+SRP:+SRP-RSA:+SRP-DSS 836 DocumentRoot /www/site3.example.com/html 837 ServerName site3.example.com:443 838 GnuTLSCertificateFile conf/tls/site3.crt 839 GnuTLSKeyFile conf/tls/site3.key 840 GnuTLSClientVerify ignore 841 GnuTLSSRPPasswdFile conf/tls/tpasswd.site3 842 GnuTLSSRPPasswdConfFile conf/tls/tpasswd.site3.conf 654 843 </VirtualHost> 655 <VirtualHost 1.2.3.1:443> 656 GnuTLSEnable on 657 GnuTLSPriorities NORMAL 658 DocumentRoot /www/site4.example.com/html 659 ServerName site4.example.com:443 660 GnuTLSCertificateFile conf/ssl/site4.crt 661 GnuTLSKeyFile conf/ss/site4.key 662 </VirtualHost> 663 664 665 * * * * * 666 667 Performance Issues 668 ================== 669 670 `mod_gnutls` by default uses conservative settings for the server. 671 You can fine tune the configuration to reduce the load on a busy 672 server. The following examples do exactly this: 673 844 845 OCSP Stapling Example 846 --------------------- 847 848 This is an example with a customized OCSP stapling configuration. What 849 is a resonable cache timeout varies depending on how long your CA's 850 OCSP responses are valid. Some CAs provide responses that are valid 851 for multiple days, in that case timeout and fuzz time could be 852 significantly larger. 674 853 675 854 # Load the module into Apache. 676 855 LoadModule gnutls_module modules/mod_gnutls.so 677 # Using 4 memcache servers to distribute the SSL Session Cache. 678 GnuTLSCache memcache "mc1.example.com mc2.example.com mc3.example.com mc4.example.com" 679 GnuTLSCacheTimeout 600 680 Listen 1.2.3.1:443 681 NameVirtualHost 1.2.3.1:443 682 <VirtualHost 1.2.3.1:443> 683 GnuTLSEnable on 684 # Here we disable the Perfect forward secrecy ciphersuites (DHE) 685 # and disallow AES-256 since AES-128 is just fine. 686 GnuTLSPriorities NORMAL:!DHE-RSA:!DHE-DSS:!AES-256-CBC:%COMPAT 687 DocumentRoot /www/site1.example.com/html 688 ServerName site1.example.com:443 689 GnuTLSCertificateFile conf/ssl/site1.crt 690 GnuTLSKeyFile conf/ss/site1.key 691 </VirtualHost> 692 <VirtualHost 1.2.3.1:443> 693 GnuTLSEnable on 694 # Here we instead of disabling the DHE ciphersuites we use 695 # Diffie Hellman parameters of smaller size than the default (2048 bits). 696 # Using small numbers from 768 to 1024 bits should be ok once they are 697 # regenerated every few hours. 698 # Use "certtool --generate-dh-params --bits 1024" to get those 699 GnuTLSDHFile /etc/apache2/dh.params 700 GnuTLSPriorities NORMAL:!AES-256-CBC:%COMPAT 701 DocumentRoot /www/site2.example.com/html 702 ServerName site2.example.com:443 703 GnuTLSCertificateFile conf/ssl/site2.crt 704 GnuTLSKeyFile conf/ss/site2.key 856 # A 64K cache is more than enough for one response 857 GnuTLSOCSPCache shmcb:ocsp_cache(65536) 858 859 Listen 192.0.2.1:443 860 861 <VirtualHost _default_:443> 862 GnuTLSEnable On 863 DocumentRoot /www/site1.example.com/html 864 ServerName site1.example.com:443 865 GnuTLSCertificateFile conf/tls/site1_cert_chain.pem 866 GnuTLSKeyFile conf/tls/site1_key.pem 867 GnuTLSOCSPStapling On 868 # The cached OCSP response is kept for up to 4 hours, 869 # with updates scheduled every 3 to 3.5 hours. 870 GnuTLSOCSPCacheTimeout 21600 871 GnuTLSOCSPFuzzTime 3600 705 872 </VirtualHost> 706 873 … … 799 966 ----------------- 800 967 801 The SSL or TLS cipher suite name 968 The distinguished name of the issuer of the client's certificate in 969 RFC2253 format. 802 970 803 971 `SSL_CLIENT_S_AN%` … … 835 1003 ------------------ 836 1004 837 The PEM-encoded (X.509) or ASCII-armored (OpenPGP) server certificate838 (see the`GnuTLSExportCertificates` directive).1005 The PEM-encoded (X.509) server certificate (see the 1006 `GnuTLSExportCertificates` directive). 839 1007 840 1008 `SSL_SERVER_CERT_TYPE` 841 1009 ---------------------- 842 1010 843 The certificate type can be `X.509` or `OPENPGP`.1011 The certificate type will be `X.509`. 844 1012 845 1013 `SSL_CLIENT_CERT` 846 1014 ------------------ 847 1015 848 The PEM-encoded (X.509) or ASCII-armored (OpenPGP) client certificate849 (see the`GnuTLSExportCertificates` directive).1016 PEM-encoded (X.509) client certificate, if any (see the 1017 `GnuTLSExportCertificates` directive). 850 1018 851 1019 `SSL_CLIENT_CERT_TYPE` 852 1020 ---------------------- 853 1021 854 The certificate type can be `X.509` or `OPENPGP`.1022 The certificate type will be `X.509`, if any. -
include/mod_gnutls.h.in
r8a264b0 rea9c699 1 /* *1 /* 2 2 * Copyright 2004-2005 Paul Querna 3 3 * Copyright 2014 Nikos Mavrogiannopoulos 4 * Copyright 2015 ThomasKlute4 * Copyright 2015-2018 Fiona Klute 5 5 * 6 6 * Licensed under the Apache License, Version 2.0 (the "License"); … … 15 15 * See the License for the specific language governing permissions and 16 16 * limitations under the License. 17 *18 17 */ 19 18 … … 27 26 #include "http_log.h" 28 27 #include "apr_buckets.h" 29 #include "apr_strings.h"30 28 #include "apr_tables.h" 31 29 #include "ap_release.h" 32 #include "apr_fnmatch.h"33 30 /* GnuTLS Library Headers */ 34 31 #include <gnutls/gnutls.h> 35 #if GNUTLS_VERSION_MAJOR == 236 #include <gnutls/extra.h>37 #endif38 32 #include <gnutls/abstract.h> 39 #include <gnutls/openpgp.h>40 33 #include <gnutls/x509.h> 41 34 42 35 #ifndef __mod_gnutls_h_inc 43 36 #define __mod_gnutls_h_inc 44 45 #define HAVE_APR_MEMCACHE @have_apr_memcache@46 37 47 38 extern module AP_MODULE_DECLARE_DATA gnutls_module; … … 60 51 #define MOD_GNUTLS_DEBUG @OOO_MAINTAIN@ 61 52 62 /* 63 * Recent Versions of 2.1 renamed several hooks. 64 * This allows us to compile on 2.0.xx 65 */ 66 #if AP_SERVER_MINORVERSION_NUMBER >= 2 || (AP_SERVER_MINORVERSION_NUMBER == 1 && AP_SERVER_PATCHLEVEL_NUMBER >= 3) 67 #define USING_2_1_RECENT 1 68 #else 69 #define USING_2_1_RECENT 0 53 /* Compile support for early SNI? */ 54 #if @ENABLE_EARLY_SNI@ == 1 55 #define ENABLE_EARLY_SNI 70 56 #endif 71 57 72 /* mod_gnutls Cache Types */ 73 typedef enum { 74 /* No Cache */ 75 mgs_cache_none, 76 /* Use Old Berkley DB */ 77 mgs_cache_dbm, 78 /* Use Gnu's version of Berkley DB */ 79 mgs_cache_gdbm, 80 #if HAVE_APR_MEMCACHE 81 /* Use Memcache */ 82 mgs_cache_memcache, 83 #endif 84 mgs_cache_unset 85 } mgs_cache_e; 58 /** Name of the module-wide singleton watchdog */ 59 #define MGS_SINGLETON_WATCHDOG "_mod_gnutls_singleton_" 60 61 62 /* Internal cache data, defined in gnutls_cache.h */ 63 typedef struct mgs_cache* mgs_cache_t; 86 64 87 65 typedef enum { … … 95 73 typedef struct { 96 74 int client_verify_mode; 97 const char* lua_bytecode;98 apr_size_t lua_bytecode_len;99 75 } mgs_dirconf_rec; 76 77 78 /* Internal per-vhost config for OCSP, defined in gnutls_ocsp.h */ 79 typedef struct mgs_ocsp_data* mgs_ocsp_data_t; 100 80 101 81 102 82 /* The maximum number of certificates to send in a chain */ 103 83 #define MAX_CHAIN_SIZE 8 104 /* The maximum number of SANs to read from a x509 certificate */ 105 #define MAX_CERT_SAN 5 106 107 /* Server Configuration Record */ 84 85 /** Server Configuration Record */ 108 86 typedef struct { 87 /** Server this mod_gnutls configuration is for */ 88 server_rec* s; 89 109 90 /* --- Configuration values --- */ 110 91 /* Is the module enabled? */ … … 112 93 /* Is mod_proxy enabled? */ 113 94 int proxy_enabled; 114 /* A Plain HTTP request */115 int non_ssl_request;116 95 117 96 /* List of PKCS #11 provider modules to load, only valid in the … … 129 108 char *x509_ca_file; 130 109 131 char *pgp_cert_file;132 char *pgp_key_file;133 char *pgp_ring_file;134 135 110 char *dh_file; 136 111 … … 143 118 /* Cache timeout value */ 144 119 int cache_timeout; 145 /* Chose Cache Type */ 146 mgs_cache_e cache_type; 147 const char* cache_config; 120 /* Enable cache */ 121 unsigned char cache_enable : 2; 122 /* Internal cache data */ 123 mgs_cache_t cache; 148 124 149 125 /* GnuTLS uses Session Tickets */ 150 126 int tickets; 151 152 /* --- Things initialized at _child_init --- */153 127 154 128 /* x509 Certificate Structure */ … … 171 145 * connections */ 172 146 gnutls_anon_client_credentials_t anon_client_creds; 173 /* Current x509 Certificate CN [Common Name] */174 char* cert_cn;175 /* Current x509 Certificate SAN [Subject Alternate Name]s*/176 char* cert_san[MAX_CERT_SAN];177 147 /* An x509 Certificate Chain */ 178 148 gnutls_pcert_st *certs_x509_chain; … … 183 153 /* Current x509 Certificate Private Key */ 184 154 gnutls_privkey_t privkey_x509; 185 186 /* OpenPGP Certificate */187 gnutls_pcert_st *cert_pgp;188 gnutls_openpgp_crt_t *cert_crt_pgp;189 190 /* OpenPGP Certificate Private Key */191 gnutls_privkey_t privkey_pgp;192 #if GNUTLS_VERSION_NUMBER < 0x030312193 /* Internal structure for the OpenPGP private key, used in the194 * workaround for a bug in gnutls_privkey_import_openpgp_raw that195 * frees memory that is still needed. DO NOT USE for any other196 * purpose. */197 gnutls_openpgp_privkey_t privkey_pgp_internal;198 #endif199 155 200 156 /* Export full certificates to CGI environment: */ … … 206 162 /* A list of CA Certificates */ 207 163 gnutls_x509_crt_t *ca_list; 208 /* OpenPGP Key Ring */209 gnutls_openpgp_keyring_t pgp_list;210 164 /* CA Certificate list size */ 211 165 unsigned int ca_list_size; … … 214 168 /* Client Certificate Verification Method */ 215 169 mgs_client_verification_method_e client_verify_method; 216 /* Last Cache timestamp */ 217 apr_time_t last_cache_check; 170 171 /* Enable OCSP stapling */ 172 unsigned char ocsp_staple; 173 /* Automatically refresh cached OCSP response? */ 174 unsigned char ocsp_auto_refresh; 175 /* Check nonce in OCSP responses? */ 176 unsigned char ocsp_check_nonce; 177 /* Read OCSP response for stapling from this file instead of 178 * sending a request over HTTP */ 179 char *ocsp_response_file; 180 /* Internal OCSP data for this server */ 181 mgs_ocsp_data_t ocsp; 182 /* Mutex to prevent parallel OCSP requests */ 183 apr_global_mutex_t *ocsp_mutex; 184 /* Internal OCSP cache data */ 185 mgs_cache_t ocsp_cache; 186 /* Cache timeout for OCSP responses. Note that the nextUpdate 187 * field of the response takes precedence if shorter. */ 188 apr_interval_time_t ocsp_cache_time; 189 /* If an OCSP request fails wait this long before trying again. */ 190 apr_interval_time_t ocsp_failure_timeout; 191 /** How long before a cached OCSP response expires should it be 192 * updated? During configuration parsing this is set to the 193 * maximum, during post configuration the value will be set to 194 * half that. After each update the interval to for the next one 195 * is choosen randomly as `ocsp_fuzz_time + ocsp_fuzz_time * 196 * RANDOM` with `0 <= RANDOM <= 1`. */ 197 apr_interval_time_t ocsp_fuzz_time; 198 /* Socket timeout for OCSP requests */ 199 apr_interval_time_t ocsp_socket_timeout; 200 201 /** This module's singleton watchdog, used for async OCSP cache 202 * updates. */ 203 struct mgs_watchdog *singleton_wd; 218 204 } mgs_srvconf_rec; 219 205 … … 224 210 } mgs_char_buffer_t; 225 211 226 /* GnuTLS Handle */212 /** GnuTLS connection handle */ 227 213 typedef struct { 228 214 /* Server configuration record */ … … 236 222 /* GnuTLS Session handle */ 237 223 gnutls_session_t session; 224 /** Server name requested via SNI if any, or NULL. */ 225 const char *sni_name; 238 226 /* module input status */ 239 227 apr_status_t input_rc; … … 262 250 /* Output length */ 263 251 apr_size_t output_length; 264 /* General Status */ 252 /** Connection status: 0 before (re-)handshake, 1 when up, -1 on 253 * error (checks use status < 0 or status > 0) */ 265 254 int status; 266 255 } mgs_handle_t; … … 273 262 apr_status_t apr_signal_block(int signum); 274 263 275 264 /* Proxy Support */ 276 265 /* An optional function which returns non-zero if the given connection 277 266 is using SSL/TLS. */ 278 267 APR_DECLARE_OPTIONAL_FN(int, ssl_is_https, (conn_rec *)); 268 /* The ssl_var_lookup() optional function retrieves SSL environment 269 * variables. */ 270 APR_DECLARE_OPTIONAL_FN(char *, ssl_var_lookup, 271 (apr_pool_t *, server_rec *, 272 conn_rec *, request_rec *, 273 char *)); 279 274 /* The ssl_proxy_enable() and ssl_engine_disable() optional functions 280 275 * are used by mod_proxy to enable use of SSL for outgoing … … 282 277 APR_DECLARE_OPTIONAL_FN(int, ssl_proxy_enable, (conn_rec *)); 283 278 APR_DECLARE_OPTIONAL_FN(int, ssl_engine_disable, (conn_rec *)); 279 APR_DECLARE_OPTIONAL_FN(int, ssl_engine_set, (conn_rec *, 280 ap_conf_vector_t *, 281 int proxy, int enable)); 282 mgs_handle_t* get_effective_gnutls_ctxt(conn_rec *c); 284 283 int ssl_is_https(conn_rec *c); 284 char* ssl_var_lookup(apr_pool_t *p, server_rec *s, conn_rec *c, 285 request_rec *r, char *var); 285 286 int ssl_proxy_enable(conn_rec *c); 286 287 int ssl_engine_disable(conn_rec *c); … … 347 348 348 349 /** 349 * Init the Cache after Configuration is done350 */351 int mgs_cache_post_config(apr_pool_t *p, server_rec *s,352 mgs_srvconf_rec *sc);353 /**354 * Init the Cache inside each Process355 */356 int mgs_cache_child_init(apr_pool_t *p, server_rec *s,357 mgs_srvconf_rec *sc);358 /**359 * Setup the Session Caching360 */361 int mgs_cache_session_init(mgs_handle_t *ctxt);362 363 #define GNUTLS_SESSION_ID_STRING_LEN \364 ((GNUTLS_MAX_SESSION_ID + 1) * 2)365 366 /**367 350 * Perform any reinitialization required in PKCS #11 368 351 */ 369 352 int mgs_pkcs11_reinit(server_rec * s); 370 353 371 /**372 * Convert a SSL Session ID into a Null Terminated Hex Encoded String373 * @param id raw SSL Session ID374 * @param idlen Length of the raw Session ID375 * @param str Location to store the Hex Encoded String376 * @param strsize The Maximum Length that can be stored in str377 */378 char *mgs_session_id2sz(unsigned char *id, int idlen,379 char *str, int strsize);380 381 /**382 * Convert a time_t into a Null Terminated String383 * @param t time_t time384 * @param str Location to store the Hex Encoded String385 * @param strsize The Maximum Length that can be stored in str386 */387 char *mgs_time2sz(time_t t, char *str, int strsize);388 354 389 355 … … 391 357 392 358 /* Loads all files set in the configuration */ 393 int mgs_load_files(apr_pool_t * p, server_rec * s); 359 int mgs_load_files(apr_pool_t *pconf, apr_pool_t *ptemp, server_rec *s) 360 __attribute__((nonnull)); 394 361 395 362 const char *mgs_set_srp_tpasswd_conf_file(cmd_parms * parms, void *dummy, … … 405 372 const char *arg); 406 373 407 const char *mgs_set_pgpcert_file(cmd_parms * parms, void *dummy, 408 const char *arg); 409 410 const char *mgs_set_pgpkey_file(cmd_parms * parms, void *dummy, 411 const char *arg); 412 413 const char *mgs_set_cache(cmd_parms * parms, void *dummy, 414 const char *type, const char* arg); 415 416 const char *mgs_set_cache_timeout(cmd_parms * parms, void *dummy, 417 const char *arg); 374 const char *mgs_set_timeout(cmd_parms *parms, void *dummy, const char *arg); 418 375 419 376 const char *mgs_set_client_verify(cmd_parms * parms, void *dummy, … … 433 390 434 391 const char *mgs_set_srk_pin(cmd_parms * parms, void *dummy, 435 const char *arg);436 437 const char *mgs_set_keyring_file(cmd_parms * parms, void *dummy,438 392 const char *arg); 439 393 … … 447 401 const int arg); 448 402 449 const char *mgs_set_require_section(cmd_parms *cmd,450 void *mconfig, const char *arg);451 403 void *mgs_config_server_create(apr_pool_t * p, server_rec * s); 452 404 void *mgs_config_server_merge(apr_pool_t *p, void *BASE, void *ADD); … … 455 407 456 408 void *mgs_config_dir_create(apr_pool_t *p, char *dir); 457 458 const char *mgs_set_require_bytecode(cmd_parms *cmd,459 void *mconfig, const char *arg);460 461 mgs_srvconf_rec* mgs_find_sni_server(gnutls_session_t session);462 409 463 410 const char *mgs_store_cred_path(cmd_parms * parms, … … 470 417 apr_pool_t * plog, apr_pool_t * ptemp); 471 418 472 int mgs_hook_post_config(apr_pool_t * p, apr_pool_t * plog, 473 apr_pool_t * ptemp, 474 server_rec * base_server); 419 int mgs_hook_post_config(apr_pool_t *pconf, 420 apr_pool_t *plog, 421 apr_pool_t *ptemp, 422 server_rec *base_server); 475 423 476 424 void mgs_hook_child_init(apr_pool_t *p, server_rec *s); … … 482 430 int mgs_hook_pre_connection(conn_rec * c, void *csd); 483 431 432 int mgs_hook_process_connection(conn_rec* c); 433 484 434 int mgs_hook_fixups(request_rec *r); 485 435 436 /** Post request hook, checks if TLS connection and vhost match */ 437 int mgs_req_vhost_check(request_rec *r); 438 486 439 int mgs_hook_authz(request_rec *r); 487 440 -
m4/apache.m4
r8a264b0 rea9c699 39 39 40 40 AP_PREFIX="`$APXS_BIN -q prefix 2>/dev/null`" 41 AP_EXEC_PREFIX="`$APXS_BIN -q exec_prefix 2>/dev/null`" 41 42 42 43 AP_BINDIR="`$APXS_BIN -q bindir 2>/dev/null`" … … 126 127 AC_SUBST(AP_DEFS) 127 128 AC_SUBST(AP_PREFIX) 129 AC_SUBST(AP_EXEC_PREFIX) 128 130 AC_SUBST(AP_CFLAGS) 129 131 AC_SUBST(AP_CPPFLAGS) -
src/Makefile.am
r8a264b0 rea9c699 1 CLEANFILES = .libs/libmod_gnutls *~ 1 # installation directory for Apache modules 2 if ENABLE_VPATH_INSTALL 3 apmodpkglibdir = $(subst ${AP_EXEC_PREFIX},${prefix},${AP_LIBEXECDIR}) 4 else 5 apmodpkglibdir = ${AP_LIBEXECDIR} 6 endif 2 7 3 libmod_gnutls_la_SOURCES = mod_gnutls.c gnutls_io.c gnutls_cache.c gnutls_config.c gnutls_hooks.c 4 libmod_gnutls_la_CFLAGS = -Wall ${MODULE_CFLAGS} 5 libmod_gnutls_la_LDFLAGS = -rpath ${AP_LIBEXECDIR} -module -avoid-version ${MODULE_LIBS} 8 mod_gnutls_la_SOURCES = mod_gnutls.c gnutls_io.c gnutls_cache.c \ 9 gnutls_config.c gnutls_hooks.c gnutls_ocsp.c gnutls_proxy.c \ 10 gnutls_sni.c gnutls_util.c gnutls_watchdog.c 11 mod_gnutls_la_CFLAGS = -Wall ${MODULE_CFLAGS} 12 mod_gnutls_la_LDFLAGS = -module -avoid-version ${MODULE_LIBS} 13 noinst_HEADERS = gnutls_cache.h gnutls_config.h gnutls_ocsp.h \ 14 gnutls_proxy.h gnutls_sni.h gnutls_util.h gnutls_watchdog.h 6 15 7 lib_LTLIBRARIES = libmod_gnutls.la 8 9 make_so: $(lib_LTLIBRARIES) 10 @if test ! -L mod_gnutls.so ; then ln -s .libs/libmod_gnutls.so mod_gnutls.so ; fi 11 12 clean: 13 rm -f mod_gnutls.so 14 rm -f *.o *.lo *.la 15 rm -fr .libs 16 17 install: make_so 18 @${APXS_BIN} -i -n gnutls mod_gnutls.so 19 @echo "" 20 @echo "" 21 @echo "***********************************************" 22 @echo "" 23 @echo " Please read the manual in the doc/ directory for" 24 @echo " details on the configuration of this module" 25 @echo "" 26 @echo "***********************************************" 27 @echo "" 16 apmodpkglib_LTLIBRARIES = mod_gnutls.la -
src/gnutls_cache.c
r8a264b0 rea9c699 1 /* *1 /* 2 2 * Copyright 2004-2005 Paul Querna 3 3 * Copyright 2008 Nikos Mavrogiannopoulos 4 4 * Copyright 2011 Dash Shendy 5 * Copyright 2015 ThomasKlute5 * Copyright 2015-2018 Fiona Klute 6 6 * 7 7 * Licensed under the Apache License, Version 2.0 (the "License"); … … 16 16 * See the License for the specific language governing permissions and 17 17 * limitations under the License. 18 * 19 */ 20 18 */ 19 20 /** 21 * @file gnutls_cache.c 22 * 23 * This file contains the cache implementation used for session 24 * caching and OCSP stapling. The `socache_*_session` functions 25 * implement the GnuTLS session cache API using the configured cache, 26 * using mgs_cache_store() and mgs_cache_fetch() as appropriate (see 27 * gnutls_cache.h). 28 */ 29 30 #include "gnutls_cache.h" 21 31 #include "mod_gnutls.h" 22 23 #if HAVE_APR_MEMCACHE 24 #include "apr_memcache.h" 25 #endif 26 27 #include "apr_dbm.h" 28 29 #include "ap_mpm.h" 30 31 #include <unistd.h> 32 #include <sys/types.h> 33 34 #if !defined(OS2) && !defined(WIN32) && !defined(BEOS) && !defined(NETWARE) 35 #include "unixd.h" 36 #endif 37 38 /* it seems the default has some strange errors. Use SDBM 39 */ 40 #define MC_TAG "mod_gnutls:" 41 #define MC_TAG_LEN sizeof(MC_TAG) 42 #define STR_SESSION_LEN (GNUTLS_SESSION_ID_STRING_LEN + MC_TAG_LEN) 43 44 #if MODULE_MAGIC_NUMBER_MAJOR < 20081201 45 #define ap_unixd_config unixd_config 32 #include "gnutls_config.h" 33 #include "gnutls_ocsp.h" 34 35 #include <ap_socache.h> 36 #include <apr_strings.h> 37 #include <mod_status.h> 38 #include <apr_escape.h> 39 #include <util_mutex.h> 40 41 /** Default session cache timeout */ 42 #define MGS_DEFAULT_CACHE_TIMEOUT 300 43 44 /** Session cache name */ 45 #define MGS_SESSION_CACHE_NAME "gnutls_session" 46 47 /** Default type for OCSP cache */ 48 #define DEFAULT_OCSP_CACHE_TYPE "shmcb" 49 /** Default config string for OCSP cache */ 50 #define DEFAULT_OCSP_CACHE_CONF "gnutls_ocsp_cache" 51 52 /** Maximum length of the hex string representation of a GnuTLS 53 * session ID: two characters per byte, plus one more for `\0` */ 54 #if GNUTLS_VERSION_NUMBER >= 0x030400 55 #define GNUTLS_SESSION_ID_STRING_LEN ((GNUTLS_MAX_SESSION_ID_SIZE * 2) + 1) 56 #else 57 #define GNUTLS_SESSION_ID_STRING_LEN ((GNUTLS_MAX_SESSION_ID * 2) + 1) 46 58 #endif 47 59 … … 50 62 #endif 51 63 52 char *mgs_session_id2sz(unsigned char *id, int idlen, 53 char *str, int strsize) { 54 char *cp; 55 int n; 56 57 cp = str; 58 for (n = 0; n < idlen && n < GNUTLS_MAX_SESSION_ID; n++) { 59 apr_snprintf(cp, strsize - (cp - str), "%02X", id[n]); 60 cp += 2; 61 } 62 *cp = '\0'; 63 return str; 64 } 65 66 /* Name the Session ID as: 67 * server:port.SessionID 68 * to disallow resuming sessions on different servers 69 */ 70 static int mgs_session_id2dbm(conn_rec * c, unsigned char *id, int idlen, 71 apr_datum_t * dbmkey) { 72 char buf[STR_SESSION_LEN]; 73 char *sz; 74 75 sz = mgs_session_id2sz(id, idlen, buf, sizeof (buf)); 76 if (sz == NULL) 64 /** 65 * Turn a GnuTLS session ID into the key format we use for 66 * caches. Name the Session ID as `server:port.SessionID` to disallow 67 * resuming sessions on different servers. 68 * 69 * @return `0` on success, `-1` on failure 70 */ 71 static int mgs_session_id2dbm(conn_rec *c, unsigned char *id, int idlen, 72 gnutls_datum_t *dbmkey) 73 { 74 char sz[GNUTLS_SESSION_ID_STRING_LEN]; 75 apr_status_t rv = apr_escape_hex(sz, id, idlen, 0, NULL); 76 if (rv != APR_SUCCESS) 77 77 return -1; 78 78 79 dbmkey->dptr =80 apr_psprintf(c->pool, "%s:%d.%s",81 c->base_server->server_hostname,82 c->base_server->port, sz);83 dbmkey->dsize = strlen(dbmkey->dptr);84 79 char *newkey = apr_psprintf(c->pool, "%s:%d.%s", 80 c->base_server->server_hostname, 81 c->base_server->port, sz); 82 dbmkey->size = strlen(newkey); 83 /* signedness does not matter for arbitrary bits */ 84 dbmkey->data = (unsigned char*) newkey; 85 85 return 0; 86 86 } 87 87 88 #define CTIME "%b %d %k:%M:%S %Y %Z" 89 90 char *mgs_time2sz(time_t in_time, char *str, int strsize) { 88 /** The OPENSSL_TIME_FORMAT macro and mgs_time2sz() serve to print 89 * time in a format compatible with OpenSSL's `ASN1_TIME_print()` 90 * function. */ 91 #define OPENSSL_TIME_FORMAT "%b %d %k:%M:%S %Y %Z" 92 93 char *mgs_time2sz(time_t in_time, char *str, int strsize) 94 { 91 95 apr_time_exp_t vtm; 92 96 apr_size_t ret_size; … … 96 100 apr_time_ansi_put(&t, in_time); 97 101 apr_time_exp_gmt(&vtm, t); 98 apr_strftime(str, &ret_size, strsize - 1, CTIME, &vtm);102 apr_strftime(str, &ret_size, strsize - 1, OPENSSL_TIME_FORMAT, &vtm); 99 103 100 104 return str; 101 105 } 102 106 103 #if HAVE_APR_MEMCACHE 104 105 /* Name the Session ID as: 106 * server:port.SessionID 107 * to disallow resuming sessions on different servers 108 */ 109 static char *mgs_session_id2mc(conn_rec * c, unsigned char *id, int idlen) { 110 char buf[STR_SESSION_LEN]; 111 char *sz; 112 113 sz = mgs_session_id2sz(id, idlen, buf, sizeof (buf)); 114 if (sz == NULL) 115 return NULL; 116 117 return apr_psprintf(c->pool, MC_TAG "%s:%d.%s", 118 c->base_server->server_hostname, 119 c->base_server->port, sz); 120 } 107 108 109 int mgs_cache_store(mgs_cache_t cache, server_rec *server, 110 gnutls_datum_t key, gnutls_datum_t data, 111 apr_time_t expiry) 112 { 113 apr_pool_t *spool; 114 apr_pool_create(&spool, NULL); 115 116 if (cache->prov->flags & AP_SOCACHE_FLAG_NOTMPSAFE) 117 apr_global_mutex_lock(cache->mutex); 118 apr_status_t rv = cache->prov->store(cache->socache, server, 119 key.data, key.size, 120 expiry, 121 data.data, data.size, 122 spool); 123 if (cache->prov->flags & AP_SOCACHE_FLAG_NOTMPSAFE) 124 apr_global_mutex_unlock(cache->mutex); 125 126 if (rv != APR_SUCCESS) 127 { 128 ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, server, 129 "error storing in cache '%s:%s'", 130 cache->prov->name, cache->config); 131 apr_pool_destroy(spool); 132 return -1; 133 } 134 135 ap_log_error(APLOG_MARK, APLOG_TRACE1, rv, server, 136 "stored %u bytes of data (%u byte key) in cache '%s:%s'", 137 data.size, key.size, 138 cache->prov->name, cache->config); 139 apr_pool_destroy(spool); 140 return 0; 141 } 142 143 121 144 122 145 /** 123 * GnuTLS Session Cache using libmemcached 124 * 125 */ 126 127 /* The underlying apr_memcache system is thread safe... woohoo */ 128 static apr_memcache_t *mc; 129 130 static int mc_cache_child_init(apr_pool_t * p, server_rec * s, 131 mgs_srvconf_rec * sc) { 132 apr_status_t rv = APR_SUCCESS; 133 int thread_limit = 0; 134 int nservers = 0; 135 char *cache_config; 136 char *split; 137 char *tok; 138 139 ap_mpm_query(AP_MPMQ_HARD_LIMIT_THREADS, &thread_limit); 140 141 /* Find all the servers in the first run to get a total count */ 142 cache_config = apr_pstrdup(p, sc->cache_config); 143 split = apr_strtok(cache_config, " ", &tok); 144 while (split) { 145 nservers++; 146 split = apr_strtok(NULL, " ", &tok); 147 } 148 149 rv = apr_memcache_create(p, nservers, 0, &mc); 150 if (rv != APR_SUCCESS) { 151 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, 152 "[gnutls_cache] Failed to create Memcache Object of '%d' size.", 153 nservers); 154 return rv; 155 } 156 157 /* Now add each server to the memcache */ 158 cache_config = apr_pstrdup(p, sc->cache_config); 159 split = apr_strtok(cache_config, " ", &tok); 160 while (split) { 161 apr_memcache_server_t *st; 162 char *host_str; 163 char *scope_id; 164 apr_port_t port; 165 166 rv = apr_parse_addr_port(&host_str, &scope_id, &port, 167 split, p); 168 if (rv != APR_SUCCESS) { 169 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, 170 "[gnutls_cache] Failed to Parse Server: '%s'", 171 split); 172 return rv; 173 } 174 175 if (host_str == NULL) { 176 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, 177 "[gnutls_cache] Failed to Parse Server, " 178 "no hostname specified: '%s'", split); 179 return rv; 180 } 181 182 if (port == 0) { 183 port = 11211; /* default port */ 184 } 185 186 /* Should Max Conns be (thread_limit / nservers) ? */ 187 rv = apr_memcache_server_create(p, 188 host_str, port, 189 0, 190 1, thread_limit, 600, &st); 191 if (rv != APR_SUCCESS) { 192 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, 193 "[gnutls_cache] Failed to Create Server: %s:%d", 194 host_str, port); 195 return rv; 196 } 197 198 rv = apr_memcache_add_server(mc, st); 199 if (rv != APR_SUCCESS) { 200 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, 201 "[gnutls_cache] Failed to Add Server: %s:%d", 202 host_str, port); 203 return rv; 204 } 205 206 split = apr_strtok(NULL, " ", &tok); 207 } 208 return rv; 209 } 210 211 static int mc_cache_store(void *baton, gnutls_datum_t key, 212 gnutls_datum_t data) { 213 apr_status_t rv = APR_SUCCESS; 146 * Store function for the GnuTLS session cache, see 147 * gnutls_db_set_store_function(). 148 * 149 * @param baton mgs_handle_t for the connection, as set via 150 * gnutls_db_set_ptr() 151 * 152 * @param key object key to store 153 * 154 * @param data the object to store 155 * 156 * @return `0` in case of success, `-1` in case of failure 157 */ 158 static int socache_store_session(void *baton, gnutls_datum_t key, 159 gnutls_datum_t data) 160 { 214 161 mgs_handle_t *ctxt = baton; 215 char *strkey = NULL; 216 apr_uint32_t timeout; 217 218 strkey = mgs_session_id2mc(ctxt->c, key.data, key.size); 219 if (!strkey) 162 gnutls_datum_t dbmkey; 163 164 if (mgs_session_id2dbm(ctxt->c, key.data, key.size, &dbmkey) < 0) 220 165 return -1; 221 166 222 timeout = apr_time_sec(ctxt->sc->cache_timeout); 223 224 rv = apr_memcache_set(mc, strkey, (char *) data.data, data.size, timeout, 225 0); 226 227 if (rv != APR_SUCCESS) { 228 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, 229 ctxt->c->base_server, 230 "[gnutls_cache] error setting key '%s' " 231 "with %d bytes of data", strkey, data.size); 232 return -1; 233 } 234 235 return 0; 236 } 237 238 static gnutls_datum_t mc_cache_fetch(void *baton, gnutls_datum_t key) { 239 apr_status_t rv = APR_SUCCESS; 240 mgs_handle_t *ctxt = baton; 241 char *strkey = NULL; 242 char *value; 243 apr_size_t value_len; 167 apr_time_t expiry = apr_time_now() + ctxt->sc->cache_timeout; 168 169 return mgs_cache_store(ctxt->sc->cache, ctxt->c->base_server, 170 dbmkey, data, expiry); 171 } 172 173 174 175 /** 8K is the maximum size accepted when receiving OCSP responses, 176 * sessions cache entries should be much smaller. The buffer is 177 * reallocated to actual size after fetching, so memory waste is 178 * minimal and temporary. */ 179 #define SOCACHE_FETCH_BUF_SIZE (8 * 1024) 180 181 gnutls_datum_t mgs_cache_fetch(mgs_cache_t cache, server_rec *server, 182 gnutls_datum_t key, apr_pool_t *pool) 183 { 244 184 gnutls_datum_t data = {NULL, 0}; 245 246 strkey = mgs_session_id2mc(ctxt->c, key.data, key.size); 247 if (!strkey) { 248 return data; 249 } 250 251 rv = apr_memcache_getp(mc, ctxt->c->pool, strkey, 252 &value, &value_len, NULL); 253 254 if (rv != APR_SUCCESS) { 255 #if MOD_GNUTLS_DEBUG 256 ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, 257 ctxt->c->base_server, 258 "[gnutls_cache] error fetching key '%s' ", 259 strkey); 260 #endif 261 data.size = 0; 262 data.data = NULL; 263 return data; 264 } 265 266 /* TODO: Eliminate this memcpy. gnutls-- */ 267 data.data = gnutls_malloc(value_len); 185 data.data = gnutls_malloc(SOCACHE_FETCH_BUF_SIZE); 268 186 if (data.data == NULL) 269 187 return data; 270 271 data.size = value_len; 272 memcpy(data.data, value, value_len); 188 data.size = SOCACHE_FETCH_BUF_SIZE; 189 190 apr_pool_t *spool; 191 apr_pool_create(&spool, pool); 192 193 if (cache->prov->flags & AP_SOCACHE_FLAG_NOTMPSAFE) 194 apr_global_mutex_lock(cache->mutex); 195 apr_status_t rv = cache->prov->retrieve(cache->socache, server, 196 key.data, key.size, 197 data.data, &data.size, 198 spool); 199 if (cache->prov->flags & AP_SOCACHE_FLAG_NOTMPSAFE) 200 apr_global_mutex_unlock(cache->mutex); 201 202 if (rv != APR_SUCCESS) 203 { 204 /* APR_NOTFOUND means there's no such object. */ 205 if (rv == APR_NOTFOUND) 206 ap_log_error(APLOG_MARK, APLOG_TRACE1, rv, server, 207 "requested entry not found in cache '%s:%s'.", 208 cache->prov->name, cache->config); 209 else 210 ap_log_error(APLOG_MARK, APLOG_WARNING, rv, server, 211 "error fetching from cache '%s:%s'", 212 cache->prov->name, cache->config); 213 /* free unused buffer */ 214 gnutls_free(data.data); 215 data.data = NULL; 216 data.size = 0; 217 } 218 else 219 { 220 ap_log_error(APLOG_MARK, APLOG_TRACE1, rv, server, 221 "fetched %u bytes from cache '%s:%s'", 222 data.size, cache->prov->name, cache->config); 223 224 /* Realloc buffer to data.size. Data size must be less than or 225 * equal to the initial buffer size, so this REALLY should not 226 * fail. */ 227 data.data = gnutls_realloc(data.data, data.size); 228 if (__builtin_expect(data.data == NULL, 0)) 229 { 230 ap_log_error(APLOG_MARK, APLOG_CRIT, APR_ENOMEM, server, 231 "%s: Could not realloc fetch buffer to data size!", 232 __func__); 233 data.size = 0; 234 } 235 } 236 apr_pool_destroy(spool); 273 237 274 238 return data; 275 239 } 276 240 277 static int mc_cache_delete(void *baton, gnutls_datum_t key) { 278 apr_status_t rv = APR_SUCCESS; 241 242 243 /** 244 * Fetch function for the GnuTLS session cache, see 245 * gnutls_db_set_retrieve_function(). 246 * 247 * *Warning*: The `data` element of the returned `gnutls_datum_t` is 248 * allocated using `gnutls_malloc()` for compatibility with the GnuTLS 249 * session caching API, and must be released using `gnutls_free()`. 250 * 251 * @param baton mgs_handle_t for the connection, as set via 252 * gnutls_db_set_ptr() 253 * 254 * @param key object key to fetch 255 * 256 * @return the requested cache entry, or `{NULL, 0}` 257 */ 258 static gnutls_datum_t socache_fetch_session(void *baton, gnutls_datum_t key) 259 { 260 gnutls_datum_t data = {NULL, 0}; 261 gnutls_datum_t dbmkey; 279 262 mgs_handle_t *ctxt = baton; 280 char *strkey = NULL; 281 282 strkey = mgs_session_id2mc(ctxt->c, key.data, key.size); 283 if (!strkey) 263 264 if (mgs_session_id2dbm(ctxt->c, key.data, key.size, &dbmkey) < 0) 265 return data; 266 267 return mgs_cache_fetch(ctxt->sc->cache, ctxt->c->base_server, 268 dbmkey, ctxt->c->pool); 269 } 270 271 272 273 /** 274 * Remove function for the GnuTLS session cache, see 275 * gnutls_db_set_remove_function(). 276 * 277 * @param baton mgs_handle_t for the connection, as set via 278 * gnutls_db_set_ptr() 279 * 280 * @param key object key to remove 281 * 282 * @return `0` in case of success, `-1` in case of failure 283 */ 284 static int socache_delete_session(void *baton, gnutls_datum_t key) 285 { 286 gnutls_datum_t tmpkey; 287 mgs_handle_t *ctxt = baton; 288 289 if (mgs_session_id2dbm(ctxt->c, key.data, key.size, &tmpkey) < 0) 284 290 return -1; 285 291 286 rv = apr_memcache_delete(mc, strkey, 0); 287 288 if (rv != APR_SUCCESS) { 289 ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, 290 ctxt->c->base_server, 291 "[gnutls_cache] error deleting key '%s' ", 292 strkey); 293 return -1; 294 } 295 296 return 0; 297 } 298 299 #endif /* have_apr_memcache */ 300 301 static const char *db_type(mgs_srvconf_rec * sc) { 302 if (sc->cache_type == mgs_cache_gdbm) 303 return "gdbm"; 304 else 305 return "db"; 306 } 307 308 #define SSL_DBM_FILE_MODE ( APR_UREAD | APR_UWRITE | APR_GREAD | APR_WREAD ) 309 310 static void dbm_cache_expire(mgs_handle_t * ctxt) { 311 apr_status_t rv; 312 apr_dbm_t *dbm; 313 apr_datum_t dbmkey; 314 apr_datum_t dbmval; 315 apr_time_t now; 316 apr_time_t dtime; 317 apr_pool_t *spool; 318 int total, deleted; 319 320 now = apr_time_now(); 321 322 if (now - ctxt->sc->last_cache_check < 323 (ctxt->sc->cache_timeout) / 2) 324 return; 325 326 ctxt->sc->last_cache_check = now; 327 328 apr_pool_create(&spool, ctxt->c->pool); 329 330 total = 0; 331 deleted = 0; 332 333 rv = apr_dbm_open_ex(&dbm, db_type(ctxt->sc), 334 ctxt->sc->cache_config, APR_DBM_RWCREATE, 335 SSL_DBM_FILE_MODE, spool); 292 if (ctxt->sc->cache->prov->flags & AP_SOCACHE_FLAG_NOTMPSAFE) 293 apr_global_mutex_lock(ctxt->sc->cache->mutex); 294 apr_status_t rv = ctxt->sc->cache->prov->remove(ctxt->sc->cache->socache, 295 ctxt->c->base_server, 296 key.data, key.size, 297 ctxt->c->pool); 298 if (ctxt->sc->cache->prov->flags & AP_SOCACHE_FLAG_NOTMPSAFE) 299 apr_global_mutex_unlock(ctxt->sc->cache->mutex); 300 336 301 if (rv != APR_SUCCESS) { 337 302 ap_log_error(APLOG_MARK, APLOG_NOTICE, rv, 338 ctxt->c->base_server, 339 "[gnutls_cache] error opening cache searcher '%s'", 340 ctxt->sc->cache_config); 341 apr_pool_destroy(spool); 342 return; 343 } 344 345 apr_dbm_firstkey(dbm, &dbmkey); 346 while (dbmkey.dptr != NULL) { 347 apr_dbm_fetch(dbm, dbmkey, &dbmval); 348 if (dbmval.dptr != NULL 349 && dbmval.dsize >= sizeof (apr_time_t)) { 350 memcpy(&dtime, dbmval.dptr, sizeof (apr_time_t)); 351 352 if (now >= dtime) { 353 apr_dbm_delete(dbm, dbmkey); 354 deleted++; 355 } 356 apr_dbm_freedatum(dbm, dbmval); 357 } else { 358 apr_dbm_delete(dbm, dbmkey); 359 deleted++; 360 } 361 total++; 362 apr_dbm_nextkey(dbm, &dbmkey); 363 } 364 apr_dbm_close(dbm); 365 366 ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, 367 ctxt->c->base_server, 368 "[gnutls_cache] Cleaned up cache '%s'. Deleted %d and left %d", 369 ctxt->sc->cache_config, deleted, total - deleted); 370 371 apr_pool_destroy(spool); 372 373 return; 374 } 375 376 static gnutls_datum_t dbm_cache_fetch(void *baton, gnutls_datum_t key) { 377 gnutls_datum_t data = {NULL, 0}; 378 apr_dbm_t *dbm; 379 apr_datum_t dbmkey; 380 apr_datum_t dbmval; 381 mgs_handle_t *ctxt = baton; 382 apr_status_t rv; 383 384 if (mgs_session_id2dbm(ctxt->c, key.data, key.size, &dbmkey) < 0) 385 return data; 386 387 rv = apr_dbm_open_ex(&dbm, db_type(ctxt->sc), 388 ctxt->sc->cache_config, APR_DBM_READONLY, 389 SSL_DBM_FILE_MODE, ctxt->c->pool); 390 if (rv != APR_SUCCESS) { 391 ap_log_error(APLOG_MARK, APLOG_NOTICE, rv, 392 ctxt->c->base_server, 393 "[gnutls_cache] error opening cache '%s'", 394 ctxt->sc->cache_config); 395 return data; 396 } 397 398 rv = apr_dbm_fetch(dbm, dbmkey, &dbmval); 399 400 if (rv != APR_SUCCESS) { 401 apr_dbm_close(dbm); 402 return data; 403 } 404 405 if (dbmval.dptr == NULL || dbmval.dsize <= sizeof (apr_time_t)) { 406 apr_dbm_freedatum(dbm, dbmval); 407 apr_dbm_close(dbm); 408 return data; 409 } 410 411 data.size = dbmval.dsize - sizeof (apr_time_t); 412 413 data.data = gnutls_malloc(data.size); 414 if (data.data == NULL) { 415 apr_dbm_freedatum(dbm, dbmval); 416 apr_dbm_close(dbm); 417 return data; 418 } 419 420 memcpy(data.data, dbmval.dptr + sizeof (apr_time_t), data.size); 421 422 apr_dbm_freedatum(dbm, dbmval); 423 apr_dbm_close(dbm); 424 425 return data; 426 } 427 428 static int dbm_cache_store(void *baton, gnutls_datum_t key, 429 gnutls_datum_t data) { 430 apr_dbm_t *dbm; 431 apr_datum_t dbmkey; 432 apr_datum_t dbmval; 433 mgs_handle_t *ctxt = baton; 434 apr_status_t rv; 435 apr_time_t expiry; 436 apr_pool_t *spool; 437 438 if (mgs_session_id2dbm(ctxt->c, key.data, key.size, &dbmkey) < 0) 303 ctxt->c->base_server, 304 "error deleting from cache '%s:%s'", 305 ctxt->sc->cache->prov->name, ctxt->sc->cache->config); 439 306 return -1; 440 441 /* we expire dbm only on every store 442 */ 443 dbm_cache_expire(ctxt); 444 445 apr_pool_create(&spool, ctxt->c->pool); 446 447 /* create DBM value */ 448 dbmval.dsize = data.size + sizeof (apr_time_t); 449 dbmval.dptr = (char *) apr_palloc(spool, dbmval.dsize); 450 451 expiry = apr_time_now() + ctxt->sc->cache_timeout; 452 453 memcpy((char *) dbmval.dptr, &expiry, sizeof (apr_time_t)); 454 memcpy((char *) dbmval.dptr + sizeof (apr_time_t), 455 data.data, data.size); 456 457 rv = apr_dbm_open_ex(&dbm, db_type(ctxt->sc), 458 ctxt->sc->cache_config, APR_DBM_RWCREATE, 459 SSL_DBM_FILE_MODE, ctxt->c->pool); 460 if (rv != APR_SUCCESS) { 461 ap_log_error(APLOG_MARK, APLOG_NOTICE, rv, 462 ctxt->c->base_server, 463 "[gnutls_cache] error opening cache '%s'", 464 ctxt->sc->cache_config); 465 apr_pool_destroy(spool); 466 return -1; 467 } 468 469 rv = apr_dbm_store(dbm, dbmkey, dbmval); 470 471 if (rv != APR_SUCCESS) { 472 ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, 473 ctxt->c->base_server, 474 "[gnutls_cache] error storing in cache '%s'", 475 ctxt->sc->cache_config); 476 apr_dbm_close(dbm); 477 apr_pool_destroy(spool); 478 return -1; 479 } 480 481 apr_dbm_close(dbm); 482 483 apr_pool_destroy(spool); 484 307 } 485 308 return 0; 486 309 } 487 310 488 static int dbm_cache_delete(void *baton, gnutls_datum_t key) { 489 apr_dbm_t *dbm; 490 apr_datum_t dbmkey; 491 mgs_handle_t *ctxt = baton; 492 apr_status_t rv; 493 494 if (mgs_session_id2dbm(ctxt->c, key.data, key.size, &dbmkey) < 0) 495 return -1; 496 497 rv = apr_dbm_open_ex(&dbm, db_type(ctxt->sc), 498 ctxt->sc->cache_config, APR_DBM_RWCREATE, 499 SSL_DBM_FILE_MODE, ctxt->c->pool); 500 if (rv != APR_SUCCESS) { 501 ap_log_error(APLOG_MARK, APLOG_NOTICE, rv, 502 ctxt->c->base_server, 503 "[gnutls_cache] error opening cache '%s'", 504 ctxt->sc->cache_config); 505 return -1; 506 } 507 508 rv = apr_dbm_delete(dbm, dbmkey); 509 510 if (rv != APR_SUCCESS) { 511 ap_log_error(APLOG_MARK, APLOG_NOTICE, rv, 512 ctxt->c->base_server, 513 "[gnutls_cache] error deleting from cache '%s'", 514 ctxt->sc->cache_config); 515 apr_dbm_close(dbm); 516 return -1; 517 } 518 519 apr_dbm_close(dbm); 520 311 312 313 const char *mgs_cache_inst_config(mgs_cache_t *cache, server_rec *server, 314 const char* type, const char* config, 315 apr_pool_t *pconf, apr_pool_t *ptemp) 316 { 317 /* Allocate cache structure, will be assigned to *cache after 318 * successful configuration. */ 319 mgs_cache_t c = apr_pcalloc(pconf, sizeof(struct mgs_cache)); 320 if (c == NULL) 321 return "Could not allocate memory for cache configuration!"; 322 323 /* Find the right socache provider */ 324 c->prov = ap_lookup_provider(AP_SOCACHE_PROVIDER_GROUP, 325 type, 326 AP_SOCACHE_PROVIDER_VERSION); 327 if (c->prov == NULL) 328 { 329 return apr_psprintf(ptemp, 330 "Could not find socache provider '%s', please " 331 "make sure that the provider name is valid and " 332 "the appropriate module is loaded (maybe " 333 "mod_socache_%s.so?).", 334 type, type); 335 } 336 337 /* shmcb works fine with NULL, but make sure there's a valid (if 338 * empty) string for logging */ 339 if (config != NULL) 340 c->config = apr_pstrdup(pconf, config); 341 else 342 c->config = ""; 343 344 /* Create and configure the cache instance. */ 345 const char *err = c->prov->create(&c->socache, c->config, ptemp, pconf); 346 if (err != NULL) 347 { 348 return apr_psprintf(ptemp, 349 "Creating cache '%s:%s' failed: %s", 350 c->prov->name, c->config, err); 351 } 352 ap_log_error(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, server, 353 "%s: Socache '%s:%s' created.", 354 __func__, c->prov->name, c->config); 355 356 /* assign configured cache structure to server */ 357 *cache = c; 358 359 return NULL; 360 } 361 362 363 364 /** 365 * This function is supposed to be called during post_config to 366 * initialize mutex and socache instance associated with an 367 * mgs_cache_t. 368 * 369 * @param cache the mod_gnutls cache structure 370 * 371 * @param cache_name name for socache initialization 372 * 373 * @param mutex_name name to pass to ap_global_mutex_create(), must 374 * have been registered during pre_config. 375 * 376 * @param server server for logging purposes 377 * 378 * @param pconf memory pool for server configuration 379 */ 380 static apr_status_t mgs_cache_inst_init(mgs_cache_t cache, 381 const char *cache_name, 382 const char *mutex_name, 383 server_rec *server, 384 apr_pool_t *pconf) 385 { 386 apr_status_t rv = APR_SUCCESS; 387 388 if (cache->mutex == NULL) 389 { 390 rv = ap_global_mutex_create(&cache->mutex, NULL, 391 mutex_name, 392 NULL, server, pconf, 0); 393 ap_log_error(APLOG_MARK, APLOG_TRACE1, rv, server, 394 "%s: create mutex", __func__); 395 if (rv != APR_SUCCESS) 396 return rv; 397 } 398 399 rv = cache->prov->init(cache->socache, cache_name, NULL, server, pconf); 400 if (rv != APR_SUCCESS) 401 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, server, 402 "Initializing cache '%s:%s' failed!", 403 cache->prov->name, cache->config); 404 else 405 ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, server, 406 "%s: socache '%s:%s' initialized.", __func__, 407 cache->prov->name, cache->config); 408 return rv; 409 } 410 411 412 413 static apr_status_t cleanup_socache(void *data) 414 { 415 server_rec *s = data; 416 mgs_srvconf_rec *sc = (mgs_srvconf_rec *) 417 ap_get_module_config(s->module_config, &gnutls_module); 418 if (sc->cache) 419 { 420 ap_log_error(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, s, 421 "Cleaning up session cache '%s:%s'", 422 sc->cache->prov->name, sc->cache->config); 423 sc->cache->prov->destroy(sc->cache->socache, s); 424 } 425 if (sc->ocsp_cache) 426 { 427 ap_log_error(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, s, 428 "Cleaning up OCSP cache '%s:%s'", 429 sc->ocsp_cache->prov->name, sc->ocsp_cache->config); 430 sc->ocsp_cache->prov->destroy(sc->ocsp_cache->socache, s); 431 } 432 return APR_SUCCESS; 433 } 434 435 436 437 int mgs_cache_post_config(apr_pool_t *pconf, apr_pool_t *ptemp, 438 server_rec *s, mgs_srvconf_rec *sc) 439 { 440 apr_status_t rv = APR_SUCCESS; 441 442 /* If the OCSP cache is unconfigured initialize it with 443 * defaults. */ 444 if (sc->ocsp_cache == NULL) 445 { 446 ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, s, 447 "%s: OCSP cache unconfigured, using '%s:%s'.", __func__, 448 DEFAULT_OCSP_CACHE_TYPE, DEFAULT_OCSP_CACHE_CONF); 449 const char *err = mgs_cache_inst_config(&sc->ocsp_cache, s, 450 DEFAULT_OCSP_CACHE_TYPE, 451 DEFAULT_OCSP_CACHE_CONF, 452 pconf, ptemp); 453 if (err != NULL) 454 ap_log_error(APLOG_MARK, APLOG_WARNING, rv, s, 455 "%s: Configuring default OCSP cache '%s:%s' failed, " 456 "make sure that mod_socache_%s is loaded.", __func__, 457 DEFAULT_OCSP_CACHE_TYPE, DEFAULT_OCSP_CACHE_CONF, 458 DEFAULT_OCSP_CACHE_TYPE); 459 } 460 461 /* Initialize the OCSP cache first so it's not skipped if the 462 * session cache is disabled. */ 463 if (sc->ocsp_cache != NULL) 464 { 465 /* TODO: Maybe initialize only if explicitly enabled OR at 466 * least one (virtual) host has OCSP enabled? */ 467 rv = mgs_cache_inst_init(sc->ocsp_cache, MGS_OCSP_CACHE_NAME, 468 MGS_OCSP_CACHE_MUTEX_NAME, s, pconf); 469 if (rv != APR_SUCCESS) 470 return HTTP_INSUFFICIENT_STORAGE; 471 } 472 473 /* GnuTLSCache was never explicitly set or is disabled: */ 474 if (sc->cache_enable == GNUTLS_ENABLED_UNSET 475 || sc->cache_enable == GNUTLS_ENABLED_FALSE) 476 { 477 sc->cache_enable = GNUTLS_ENABLED_FALSE; 478 /* Cache disabled, done. */ 479 return APR_SUCCESS; 480 } 481 /* if GnuTLSCacheTimeout was never explicitly set: */ 482 if (sc->cache_timeout == MGS_TIMEOUT_UNSET) 483 sc->cache_timeout = apr_time_from_sec(MGS_DEFAULT_CACHE_TIMEOUT); 484 485 rv = mgs_cache_inst_init(sc->cache, MGS_SESSION_CACHE_NAME, 486 MGS_CACHE_MUTEX_NAME, s, pconf); 487 if (rv != APR_SUCCESS) 488 return HTTP_INSUFFICIENT_STORAGE; 489 490 apr_pool_pre_cleanup_register(pconf, s, cleanup_socache); 491 492 return APR_SUCCESS; 493 } 494 495 int mgs_cache_child_init(apr_pool_t *p, server_rec *server, 496 mgs_cache_t cache, const char *mutex_name) 497 { 498 /* reinit cache mutex */ 499 const char *lockfile = apr_global_mutex_lockfile(cache->mutex); 500 apr_status_t rv = apr_global_mutex_child_init(&cache->mutex, 501 lockfile, p); 502 if (rv != APR_SUCCESS) 503 ap_log_error(APLOG_MARK, APLOG_EMERG, rv, server, 504 "Failed to reinit mutex '%s'", mutex_name); 505 506 return rv; 507 } 508 509 int mgs_cache_session_init(mgs_handle_t * ctxt) 510 { 511 if (ctxt->sc->cache_enable) 512 { 513 gnutls_db_set_retrieve_function(ctxt->session, 514 socache_fetch_session); 515 gnutls_db_set_remove_function(ctxt->session, 516 socache_delete_session); 517 gnutls_db_set_store_function(ctxt->session, 518 socache_store_session); 519 gnutls_db_set_ptr(ctxt->session, ctxt); 520 } 521 521 return 0; 522 522 } 523 523 524 static int dbm_cache_post_config(apr_pool_t * p, server_rec * s, 525 mgs_srvconf_rec * sc) { 526 apr_status_t rv; 527 apr_dbm_t *dbm; 528 const char *path1; 529 const char *path2; 530 531 rv = apr_dbm_open_ex(&dbm, db_type(sc), sc->cache_config, 532 APR_DBM_RWCREATE, SSL_DBM_FILE_MODE, p); 533 534 if (rv != APR_SUCCESS) { 535 ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, 536 "GnuTLS: Cannot create DBM Cache at `%s'", 537 sc->cache_config); 538 return rv; 539 } 540 541 apr_dbm_close(dbm); 542 543 apr_dbm_get_usednames_ex(p, db_type(sc), sc->cache_config, &path1, 544 &path2); 545 546 /* The Following Code takes logic directly from mod_ssl's DBM Cache */ 547 #if !defined(OS2) && !defined(WIN32) && !defined(BEOS) && !defined(NETWARE) 548 /* Running as Root */ 549 if (path1 && geteuid() == 0) { 550 if (0 != chown(path1, ap_unixd_config.user_id, -1)) 551 ap_log_error(APLOG_MARK, APLOG_NOTICE, -1, s, 552 "GnuTLS: could not chown cache path1 `%s' to uid %d (errno: %d)", 553 path1, ap_unixd_config.user_id, errno); 554 if (path2 != NULL) { 555 if (0 != chown(path2, ap_unixd_config.user_id, -1)) 556 ap_log_error(APLOG_MARK, APLOG_NOTICE, -1, s, 557 "GnuTLS: could not chown cache path2 `%s' to uid %d (errno: %d)", 558 path2, ap_unixd_config.user_id, errno); 559 } 560 } 561 #endif 562 563 return rv; 564 } 565 566 int mgs_cache_post_config(apr_pool_t * p, server_rec * s, 567 mgs_srvconf_rec * sc) { 568 569 /* if GnuTLSCache was never explicitly set: */ 570 if (sc->cache_type == mgs_cache_unset) 571 sc->cache_type = mgs_cache_none; 572 /* if GnuTLSCacheTimeout was never explicitly set: */ 573 if (sc->cache_timeout == -1) 574 sc->cache_timeout = apr_time_from_sec(300); 575 576 if (sc->cache_type == mgs_cache_dbm 577 || sc->cache_type == mgs_cache_gdbm) { 578 return dbm_cache_post_config(p, s, sc); 579 } 580 return 0; 581 } 582 583 #if HAVE_APR_MEMCACHE 584 int mgs_cache_child_init(apr_pool_t * p, 585 server_rec * s, 586 mgs_srvconf_rec * sc) 587 #else 588 int mgs_cache_child_init(apr_pool_t * p __attribute__((unused)), 589 server_rec * s __attribute__((unused)), 590 mgs_srvconf_rec * sc) 591 #endif 592 { 593 if (sc->cache_type == mgs_cache_dbm 594 || sc->cache_type == mgs_cache_gdbm) { 595 return 0; 596 } 597 #if HAVE_APR_MEMCACHE 598 else if (sc->cache_type == mgs_cache_memcache) { 599 return mc_cache_child_init(p, s, sc); 600 } 601 #endif 602 return 0; 603 } 604 605 #include <assert.h> 606 607 int mgs_cache_session_init(mgs_handle_t * ctxt) { 608 if (ctxt->sc->cache_type == mgs_cache_dbm 609 || ctxt->sc->cache_type == mgs_cache_gdbm) { 610 gnutls_db_set_retrieve_function(ctxt->session, 611 dbm_cache_fetch); 612 gnutls_db_set_remove_function(ctxt->session, 613 dbm_cache_delete); 614 gnutls_db_set_store_function(ctxt->session, 615 dbm_cache_store); 616 gnutls_db_set_ptr(ctxt->session, ctxt); 617 } 618 #if HAVE_APR_MEMCACHE 619 else if (ctxt->sc->cache_type == mgs_cache_memcache) { 620 gnutls_db_set_retrieve_function(ctxt->session, 621 mc_cache_fetch); 622 gnutls_db_set_remove_function(ctxt->session, 623 mc_cache_delete); 624 gnutls_db_set_store_function(ctxt->session, 625 mc_cache_store); 626 gnutls_db_set_ptr(ctxt->session, ctxt); 627 } 628 #endif 629 630 return 0; 631 } 524 525 526 int mgs_cache_status(mgs_cache_t cache, const char *header_title, 527 request_rec *r, int flags) 528 { 529 if (!(flags & AP_STATUS_SHORT)) 530 ap_rprintf(r, "<h3>%s:</h3>\n", header_title); 531 else 532 ap_rprintf(r, "%s:\n", header_title); 533 534 if (cache->prov->flags & AP_SOCACHE_FLAG_NOTMPSAFE) 535 apr_global_mutex_lock(cache->mutex); 536 cache->prov->status(cache->socache, r, flags); 537 if (cache->prov->flags & AP_SOCACHE_FLAG_NOTMPSAFE) 538 apr_global_mutex_unlock(cache->mutex); 539 540 return OK; 541 } -
src/gnutls_config.c
r8a264b0 rea9c699 1 /* *1 /* 2 2 * Copyright 2004-2005 Paul Querna 3 3 * Copyright 2008, 2014 Nikos Mavrogiannopoulos 4 4 * Copyright 2011 Dash Shendy 5 * Copyright 2015 ThomasKlute5 * Copyright 2015-2018 Fiona Klute 6 6 * 7 7 * Licensed under the Apache License, Version 2.0 (the "License"); … … 16 16 * See the License for the specific language governing permissions and 17 17 * limitations under the License. 18 *19 18 */ 20 19 20 #include "gnutls_cache.h" 21 #include "gnutls_config.h" 21 22 #include "mod_gnutls.h" 23 #include "gnutls_ocsp.h" 24 22 25 #include "apr_lib.h" 26 #include <apr_strings.h> 23 27 #include <gnutls/abstract.h> 24 28 … … 83 87 } 84 88 85 /* 2048-bit group parameters from SRP specification */ 86 const char static_dh_params[] = "-----BEGIN DH PARAMETERS-----\n" 87 "MIIBBwKCAQCsa9tBMkqam/Fm3l4TiVgvr3K2ZRmH7gf8MZKUPbVgUKNzKcu0oJnt\n" 88 "gZPgdXdnoT3VIxKrSwMxDc1/SKnaBP1Q6Ag5ae23Z7DPYJUXmhY6s2YaBfvV+qro\n" 89 "KRipli8Lk7hV+XmT7Jde6qgNdArb9P90c1nQQdXDPqcdKB5EaxR3O8qXtDoj+4AW\n" 90 "dr0gekNsZIHx0rkHhxdGGludMuaI+HdIVEUjtSSw1X1ep3onddLs+gMs+9v1L7N4\n" 91 "YWAnkATleuavh05zA85TKZzMBBx7wwjYKlaY86jQw4JxrjX46dv7tpS1yAPYn3rk\n" 92 "Nd4jbVJfVHWbZeNy/NaO8g+nER+eSv9zAgEC\n" 93 "-----END DH PARAMETERS-----\n"; 94 95 int mgs_load_files(apr_pool_t * p, server_rec * s) 89 90 91 /** 92 * Clean up the various GnuTLS data structures allocated by 93 * mgs_load_files() 94 */ 95 static apr_status_t mgs_pool_free_credentials(void *arg) 96 { 97 mgs_srvconf_rec *sc = (mgs_srvconf_rec *) arg; 98 99 if (sc->certs) 100 { 101 gnutls_certificate_free_credentials(sc->certs); 102 sc->certs = NULL; 103 } 104 105 if (sc->anon_creds) 106 { 107 gnutls_anon_free_server_credentials(sc->anon_creds); 108 sc->anon_creds = NULL; 109 } 110 111 #ifdef ENABLE_SRP 112 if (sc->srp_creds) 113 { 114 gnutls_srp_free_server_credentials(sc->srp_creds); 115 sc->srp_creds = NULL; 116 } 117 #endif 118 119 if (sc->dh_params) 120 { 121 gnutls_dh_params_deinit(sc->dh_params); 122 sc->dh_params = NULL; 123 } 124 125 for (unsigned int i = 0; i < sc->certs_x509_chain_num; i++) 126 { 127 gnutls_pcert_deinit(&sc->certs_x509_chain[i]); 128 gnutls_x509_crt_deinit(sc->certs_x509_crt_chain[i]); 129 } 130 131 if (sc->privkey_x509) 132 { 133 gnutls_privkey_deinit(sc->privkey_x509); 134 sc->privkey_x509 = NULL; 135 } 136 137 if (sc->ca_list) 138 { 139 for (unsigned int i = 0; i < sc->ca_list_size; i++) 140 { 141 gnutls_x509_crt_deinit(sc->ca_list[i]); 142 } 143 gnutls_free(sc->ca_list); 144 sc->ca_list = NULL; 145 } 146 147 /* Deinit server priorities only if set from 148 * sc->priorities_str. Otherwise the server is using the default 149 * global priority cache, which must not be deinitialized here. */ 150 if (sc->priorities_str && sc->priorities) 151 { 152 gnutls_priority_deinit(sc->priorities); 153 sc->priorities = NULL; 154 } 155 156 return APR_SUCCESS; 157 } 158 159 int mgs_load_files(apr_pool_t *pconf, apr_pool_t *ptemp, server_rec *s) 96 160 { 97 161 apr_pool_t *spool; … … 100 164 int ret; 101 165 mgs_srvconf_rec *sc = 102 (mgs_srvconf_rec *) ap_get_module_config(s->module_config, 103 &gnutls_module); 104 105 apr_pool_create(&spool, p); 106 107 sc->cert_pgp = apr_pcalloc(p, sizeof(sc->cert_pgp[0])); 108 sc->cert_crt_pgp = apr_pcalloc(p, sizeof(sc->cert_crt_pgp[0])); 109 sc->certs_x509_chain = 110 apr_pcalloc(p, MAX_CHAIN_SIZE * sizeof(sc->certs_x509_chain[0])); 111 sc->certs_x509_crt_chain = 112 apr_pcalloc(p, 113 MAX_CHAIN_SIZE * sizeof(sc->certs_x509_crt_chain[0])); 114 115 ret = gnutls_certificate_allocate_credentials(&sc->certs); 116 if (ret < 0) { 117 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 118 "GnuTLS: Failed to initialize" ": (%d) %s", ret, 119 gnutls_strerror(ret)); 120 ret = -1; 121 goto cleanup; 122 } 123 124 ret = gnutls_anon_allocate_server_credentials(&sc->anon_creds); 125 if (ret < 0) { 126 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 127 "GnuTLS: Failed to initialize" ": (%d) %s", ret, 128 gnutls_strerror(ret)); 129 ret = -1; 130 goto cleanup; 166 (mgs_srvconf_rec *) ap_get_module_config(s->module_config, 167 &gnutls_module); 168 169 apr_pool_create(&spool, ptemp); 170 171 /* Cleanup function for the GnuTLS structures allocated below */ 172 apr_pool_cleanup_register(pconf, sc, mgs_pool_free_credentials, 173 apr_pool_cleanup_null); 174 175 if (sc->certs == NULL) 176 { 177 ret = gnutls_certificate_allocate_credentials(&sc->certs); 178 if (ret < 0) { 179 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 180 "GnuTLS: Failed to initialize" ": (%d) %s", ret, 181 gnutls_strerror(ret)); 182 ret = -1; 183 goto cleanup; 184 } 185 } 186 187 if (sc->anon_creds == NULL) 188 { 189 ret = gnutls_anon_allocate_server_credentials(&sc->anon_creds); 190 if (ret < 0) { 191 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 192 "GnuTLS: Failed to initialize" ": (%d) %s", ret, 193 gnutls_strerror(ret)); 194 ret = -1; 195 goto cleanup; 196 } 131 197 } 132 198 133 199 /* Load SRP parameters */ 134 200 #ifdef ENABLE_SRP 135 ret = gnutls_srp_allocate_server_credentials(&sc->srp_creds); 136 if (ret < 0) { 137 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 138 "GnuTLS: Failed to initialize" ": (%d) %s", ret, 139 gnutls_strerror(ret)); 140 ret = -1; 141 goto cleanup; 142 } 143 144 if (sc->srp_tpasswd_conf_file != NULL && sc->srp_tpasswd_file != NULL) { 145 ret = gnutls_srp_set_server_credentials_file 146 (sc->srp_creds, sc->srp_tpasswd_file, 147 sc->srp_tpasswd_conf_file); 148 149 if (ret < 0 && sc->enabled == GNUTLS_ENABLED_TRUE) { 150 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, 151 s, 152 "GnuTLS: Host '%s:%d' is missing a " 153 "SRP password or conf File!", 154 s->server_hostname, s->port); 155 ret = -1; 156 goto cleanup; 157 } 158 } 159 #endif 160 161 ret = gnutls_dh_params_init(&sc->dh_params); 162 if (ret < 0) { 163 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 164 "GnuTLS: Failed to initialize" 165 ": (%d) %s", ret, gnutls_strerror(ret)); 166 ret = -1; 167 goto cleanup; 168 } 169 170 /* Load DH parameters */ 171 if (sc->dh_file) { 172 if (load_datum_from_file(spool, sc->dh_file, &data) != 0) { 173 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 174 "GnuTLS: Error Reading " "DH params '%s'", sc->dh_file); 175 ret = -1; 176 goto cleanup; 177 } 178 179 ret = 180 gnutls_dh_params_import_pkcs3(sc->dh_params, &data, 181 GNUTLS_X509_FMT_PEM); 182 if (ret < 0) { 183 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 184 "GnuTLS: Failed to Import " 185 "DH params '%s': (%d) %s", sc->dh_file, ret, 186 gnutls_strerror(ret)); 187 ret = -1; 188 goto cleanup; 189 } 190 } else { 191 gnutls_datum_t pdata = { 192 (void *) static_dh_params, 193 sizeof(static_dh_params) 194 }; 195 196 ret = gnutls_dh_params_import_pkcs3(sc->dh_params, &pdata, GNUTLS_X509_FMT_PEM); 201 if (sc->srp_creds == NULL) 202 { 203 ret = gnutls_srp_allocate_server_credentials(&sc->srp_creds); 197 204 if (ret < 0) { 198 205 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 199 "GnuTLS: Unable to generate or load DH Params: (%d) %s",200 ret,gnutls_strerror(ret));206 "GnuTLS: Failed to initialize" ": (%d) %s", ret, 207 gnutls_strerror(ret)); 201 208 ret = -1; 202 209 goto cleanup; … … 204 211 } 205 212 206 if (sc->x509_cert_file != NULL) { 207 unsigned int chain_num, i; 208 unsigned format = GNUTLS_X509_FMT_PEM; 209 210 /* Load X.509 certificate */ 211 if (strncmp(sc->x509_cert_file, "pkcs11:", 7) == 0) { 212 gnutls_pkcs11_obj_t obj; 213 214 file = sc->x509_cert_file; 215 216 ret = gnutls_pkcs11_obj_init(&obj); 217 if (ret < 0) { 218 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 219 "GnuTLS: Error Initializing PKCS #11 object"); 220 ret = -1; 221 goto cleanup; 222 } 223 224 gnutls_pkcs11_obj_set_pin_function(obj, pin_callback, sc); 225 226 ret = gnutls_pkcs11_obj_import_url(obj, file, GNUTLS_PKCS11_OBJ_FLAG_LOGIN); 227 if (ret < 0) { 228 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 229 "GnuTLS: Error Importing PKCS #11 object: '%s': %s", 230 file, gnutls_strerror(ret)); 231 ret = -1; 232 goto cleanup; 233 } 234 235 format = GNUTLS_X509_FMT_DER; 236 ret = gnutls_pkcs11_obj_export2(obj, &data); 237 if (ret < 0) { 238 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 239 "GnuTLS: Error Exporting a PKCS #11 object: '%s': %s", 240 file, gnutls_strerror(ret)); 241 ret = -1; 242 goto cleanup; 243 } 244 245 gnutls_pkcs11_obj_deinit(obj); 246 } else { 247 file = ap_server_root_relative(spool, sc->x509_cert_file); 248 249 ret = gnutls_load_file(file, &data); 250 if (ret < 0) { 251 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 252 "GnuTLS: Error Reading Certificate '%s': %s", 253 file, gnutls_strerror(ret)); 254 ret = -1; 255 goto cleanup; 256 } 257 } 258 259 ret = 260 gnutls_x509_crt_list_import2(&sc->certs_x509_crt_chain, 261 &chain_num, &data, format, 262 GNUTLS_X509_CRT_LIST_FAIL_IF_UNSORTED); 263 gnutls_free(data.data); 264 sc->certs_x509_chain_num = chain_num; 265 266 if (ret < 0) { 267 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 268 "GnuTLS: Failed to Import Certificate Chain '%s': (%d) %s", 269 file, ret, gnutls_strerror(ret)); 270 ret = -1; 271 goto cleanup; 272 } 273 274 for (i = 0; i < chain_num; i++) { 275 ret = 276 gnutls_pcert_import_x509(&sc->certs_x509_chain[i], 277 sc->certs_x509_crt_chain[i], 0); 278 if (ret < 0) { 279 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 280 "GnuTLS: Failed to Import pCertificate '%s': (%d) %s", 281 file, ret, gnutls_strerror(ret)); 282 ret = -1; 283 goto cleanup; 284 } 285 } 286 sc->certs_x509_chain_num = chain_num; 287 } 288 289 if (sc->x509_key_file) { 290 ret = gnutls_privkey_init(&sc->privkey_x509); 291 if (ret < 0) { 292 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 293 "GnuTLS: Failed to initialize: (%d) %s", ret, 294 gnutls_strerror(ret)); 295 ret = -1; 296 goto cleanup; 297 } 298 299 if (gnutls_url_is_supported(sc->x509_key_file) != 0) { 300 file = sc->x509_key_file; 301 302 gnutls_privkey_set_pin_function(sc->privkey_x509, pin_callback, 303 sc); 304 305 ret = gnutls_privkey_import_url(sc->privkey_x509, file, 0); 306 307 if (ret < 0) { 308 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 309 "GnuTLS: Failed to Import Private Key URL '%s': (%d) %s", 310 file, ret, gnutls_strerror(ret)); 311 ret = -1; 312 goto cleanup; 313 } 314 } else { 315 file = ap_server_root_relative(spool, sc->x509_key_file); 316 317 if (load_datum_from_file(spool, file, &data) != 0) { 318 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 319 "GnuTLS: Error Reading Private Key '%s'", 320 file); 321 ret = -1; 322 goto cleanup; 323 } 324 325 ret = 326 gnutls_privkey_import_x509_raw(sc->privkey_x509, &data, 327 GNUTLS_X509_FMT_PEM, sc->pin, 328 0); 329 330 if (ret < 0) { 331 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 332 "GnuTLS: Failed to Import Private Key '%s': (%d) %s", 333 file, ret, gnutls_strerror(ret)); 334 ret = -1; 335 goto cleanup; 336 } 337 } 338 } 339 340 /* Load the X.509 CA file */ 341 if (sc->x509_ca_file) { 342 if (load_datum_from_file(spool, sc->x509_ca_file, &data) != 0) { 343 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 344 "GnuTLS: Error Reading " "Client CA File '%s'", 345 sc->x509_ca_file); 346 ret = -1; 347 goto cleanup; 348 } 349 350 ret = gnutls_x509_crt_list_import2(&sc->ca_list, &sc->ca_list_size, 351 &data, GNUTLS_X509_FMT_PEM, 0); 352 if (ret < 0) { 353 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 354 "GnuTLS: Failed to load " 355 "Client CA File '%s': (%d) %s", sc->x509_ca_file, 356 ret, gnutls_strerror(ret)); 357 ret = -1; 358 goto cleanup; 359 } 360 } 361 362 if (sc->pgp_cert_file) { 363 if (load_datum_from_file(spool, sc->pgp_cert_file, &data) != 0) { 364 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 365 "GnuTLS: Error Reading " "Certificate '%s'", 366 sc->pgp_cert_file); 367 ret = -1; 368 goto cleanup; 369 } 370 371 ret = gnutls_openpgp_crt_init(&sc->cert_crt_pgp[0]); 372 if (ret < 0) { 373 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 374 "GnuTLS: Failed to Init " 375 "PGP Certificate: (%d) %s", ret, 376 gnutls_strerror(ret)); 377 ret = -1; 378 goto cleanup; 379 } 380 381 ret = 382 gnutls_openpgp_crt_import(sc->cert_crt_pgp[0], &data, 383 GNUTLS_OPENPGP_FMT_BASE64); 384 if (ret < 0) { 385 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 386 "GnuTLS: Failed to Import " 387 "PGP Certificate: (%d) %s", ret, 388 gnutls_strerror(ret)); 389 ret = -1; 390 goto cleanup; 391 } 392 393 ret = 394 gnutls_pcert_import_openpgp(sc->cert_pgp, sc->cert_crt_pgp[0], 395 0); 396 if (ret < 0) { 397 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 398 "GnuTLS: Failed to Import " 399 "PGP pCertificate: (%d) %s", ret, 400 gnutls_strerror(ret)); 401 ret = -1; 402 goto cleanup; 403 } 404 } 405 406 /* Load the PGP key file */ 407 if (sc->pgp_key_file) { 408 if (load_datum_from_file(spool, sc->pgp_key_file, &data) != 0) { 409 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 410 "GnuTLS: Error Reading " "Private Key '%s'", 411 sc->pgp_key_file); 412 ret = -1; 413 goto cleanup; 414 } 415 416 ret = gnutls_privkey_init(&sc->privkey_pgp); 417 if (ret < 0) { 418 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 419 "GnuTLS: Failed to initialize" 420 ": (%d) %s", ret, gnutls_strerror(ret)); 421 ret = -1; 422 goto cleanup; 423 } 424 425 #if GNUTLS_VERSION_NUMBER < 0x030312 426 /* GnuTLS versions before 3.3.12 contain a bug in 427 * gnutls_privkey_import_openpgp_raw which frees data that is 428 * accessed when the key is used, leading to segfault. Loading 429 * the key into a gnutls_openpgp_privkey_t and then assigning 430 * it to the gnutls_privkey_t works around the bug, hence this 431 * chain of gnutls_openpgp_privkey_init, 432 * gnutls_openpgp_privkey_import and 433 * gnutls_privkey_import_openpgp. */ 434 ret = gnutls_openpgp_privkey_init(&sc->privkey_pgp_internal); 435 if (ret != 0) { 436 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 437 "GnuTLS: Failed to initialize " 438 "PGP Private Key '%s': (%d) %s", 439 sc->pgp_key_file, ret, gnutls_strerror(ret)); 440 ret = -1; 441 goto cleanup; 442 } 443 444 ret = gnutls_openpgp_privkey_import(sc->privkey_pgp_internal, &data, 445 GNUTLS_OPENPGP_FMT_BASE64, NULL, 0); 446 if (ret != 0) { 447 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 448 "GnuTLS: Failed to Import " 449 "PGP Private Key '%s': (%d) %s", 450 sc->pgp_key_file, ret, gnutls_strerror(ret)); 451 ret = -1; 452 goto cleanup; 453 } 454 455 ret = gnutls_privkey_import_openpgp(sc->privkey_pgp, 456 sc->privkey_pgp_internal, 0); 457 if (ret != 0) 213 if (sc->srp_tpasswd_conf_file != NULL && sc->srp_tpasswd_file != NULL) 214 { 215 ret = gnutls_srp_set_server_credentials_file 216 (sc->srp_creds, sc->srp_tpasswd_file, 217 sc->srp_tpasswd_conf_file); 218 219 if (ret < 0 && sc->enabled == GNUTLS_ENABLED_TRUE) { 220 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 221 "GnuTLS: Host '%s:%d' is missing a " 222 "SRP password or conf File!", 223 s->server_hostname, s->port); 224 ret = -1; 225 goto cleanup; 226 } 227 } 228 #endif 229 230 /* Load user provided DH parameters, if any */ 231 if (sc->dh_file) 232 { 233 if (sc->dh_params == NULL) 458 234 { 235 ret = gnutls_dh_params_init(&sc->dh_params); 236 if (ret < 0) { 237 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 238 "GnuTLS: Failed to initialize" 239 ": (%d) %s", ret, gnutls_strerror(ret)); 240 ret = -1; 241 goto cleanup; 242 } 243 } 244 245 if (load_datum_from_file(spool, sc->dh_file, &data) != 0) { 459 246 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 460 "GnuTLS: Failed to assign PGP Private Key '%s' " 461 "to gnutls_privkey_t structure: (%d) %s", 462 sc->pgp_key_file, ret, gnutls_strerror(ret)); 463 ret = -1; 464 goto cleanup; 465 } 466 #else 467 ret = gnutls_privkey_import_openpgp_raw(sc->privkey_pgp, &data, 468 GNUTLS_OPENPGP_FMT_BASE64, 469 NULL, NULL); 470 if (ret != 0) 471 { 247 "GnuTLS: Error Reading " "DH params '%s'", sc->dh_file); 248 ret = -1; 249 goto cleanup; 250 } 251 252 ret = 253 gnutls_dh_params_import_pkcs3(sc->dh_params, &data, 254 GNUTLS_X509_FMT_PEM); 255 if (ret < 0) { 472 256 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 473 257 "GnuTLS: Failed to Import " 474 "PGP Private Key '%s': (%d) %s", 475 sc->pgp_key_file, ret, gnutls_strerror(ret)); 476 ret = -1; 477 goto cleanup; 478 } 479 #endif 480 } 481 482 /* Load the keyring file */ 483 if (sc->pgp_ring_file) { 484 if (load_datum_from_file(spool, sc->pgp_ring_file, &data) != 0) { 485 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 486 "GnuTLS: Error Reading " "Keyring File '%s'", 487 sc->pgp_ring_file); 488 ret = -1; 489 goto cleanup; 490 } 491 492 ret = gnutls_openpgp_keyring_init(&sc->pgp_list); 493 if (ret < 0) { 494 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 495 "GnuTLS: Failed to initialize" 496 "keyring: (%d) %s", ret, gnutls_strerror(ret)); 497 ret = -1; 498 goto cleanup; 499 } 500 501 ret = gnutls_openpgp_keyring_import(sc->pgp_list, &data, 502 GNUTLS_OPENPGP_FMT_BASE64); 503 if (ret < 0) { 504 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 505 "GnuTLS: Failed to load " 506 "Keyring File '%s': (%d) %s", sc->pgp_ring_file, 507 ret, gnutls_strerror(ret)); 508 ret = -1; 509 goto cleanup; 510 } 511 } 512 513 if (sc->priorities_str) { 258 "DH params '%s': (%d) %s", sc->dh_file, ret, 259 gnutls_strerror(ret)); 260 ret = -1; 261 goto cleanup; 262 } 263 } 264 265 if (sc->x509_cert_file != NULL && sc->certs_x509_crt_chain == NULL) 266 { 267 sc->certs_x509_chain = 268 apr_pcalloc(pconf, 269 MAX_CHAIN_SIZE * sizeof(sc->certs_x509_chain[0])); 270 sc->certs_x509_crt_chain = 271 apr_pcalloc(pconf, 272 MAX_CHAIN_SIZE * sizeof(sc->certs_x509_crt_chain[0])); 273 unsigned int chain_num = MAX_CHAIN_SIZE; 274 unsigned format = GNUTLS_X509_FMT_PEM; 275 276 /* Load X.509 certificate */ 277 if (strncmp(sc->x509_cert_file, "pkcs11:", 7) == 0) { 278 gnutls_pkcs11_obj_t obj; 279 280 file = sc->x509_cert_file; 281 282 ret = gnutls_pkcs11_obj_init(&obj); 283 if (ret < 0) { 284 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 285 "GnuTLS: Error Initializing PKCS #11 object"); 286 ret = -1; 287 goto cleanup; 288 } 289 290 gnutls_pkcs11_obj_set_pin_function(obj, pin_callback, sc); 291 292 ret = gnutls_pkcs11_obj_import_url(obj, file, 293 GNUTLS_PKCS11_OBJ_FLAG_LOGIN); 294 if (ret < 0) { 295 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 296 "GnuTLS: Error Importing PKCS #11 object: " 297 "'%s': %s", 298 file, gnutls_strerror(ret)); 299 ret = -1; 300 goto cleanup; 301 } 302 303 format = GNUTLS_X509_FMT_DER; 304 ret = gnutls_pkcs11_obj_export2(obj, &data); 305 if (ret < 0) { 306 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 307 "GnuTLS: Error Exporting a PKCS #11 object: " 308 "'%s': %s", 309 file, gnutls_strerror(ret)); 310 ret = -1; 311 goto cleanup; 312 } 313 314 gnutls_pkcs11_obj_deinit(obj); 315 } else { 316 file = ap_server_root_relative(spool, sc->x509_cert_file); 317 318 ret = gnutls_load_file(file, &data); 319 if (ret < 0) { 320 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 321 "GnuTLS: Error Reading Certificate '%s': %s", 322 file, gnutls_strerror(ret)); 323 ret = -1; 324 goto cleanup; 325 } 326 } 327 328 ret = gnutls_x509_crt_list_import(sc->certs_x509_crt_chain, 329 &chain_num, &data, format, 330 GNUTLS_X509_CRT_LIST_FAIL_IF_UNSORTED); 331 gnutls_free(data.data); 332 sc->certs_x509_chain_num = chain_num; 333 334 if (ret < 0) { 335 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 336 "GnuTLS: Failed to Import Certificate Chain " 337 "'%s': (%d) %s", 338 file, ret, gnutls_strerror(ret)); 339 ret = -1; 340 goto cleanup; 341 } 342 343 for (unsigned int i = 0; i < chain_num; i++) 344 { 345 ret = 346 gnutls_pcert_import_x509(&sc->certs_x509_chain[i], 347 sc->certs_x509_crt_chain[i], 0); 348 if (ret < 0) { 349 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 350 "GnuTLS: Failed to Import pCertificate " 351 "'%s': (%d) %s", 352 file, ret, gnutls_strerror(ret)); 353 ret = -1; 354 goto cleanup; 355 } 356 } 357 sc->certs_x509_chain_num = chain_num; 358 } 359 360 if (sc->x509_key_file && sc->privkey_x509 == NULL) 361 { 362 ret = gnutls_privkey_init(&sc->privkey_x509); 363 if (ret < 0) { 364 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 365 "GnuTLS: Failed to initialize: (%d) %s", ret, 366 gnutls_strerror(ret)); 367 ret = -1; 368 goto cleanup; 369 } 370 371 if (gnutls_url_is_supported(sc->x509_key_file) != 0) { 372 file = sc->x509_key_file; 373 374 gnutls_privkey_set_pin_function(sc->privkey_x509, pin_callback, 375 sc); 376 377 ret = gnutls_privkey_import_url(sc->privkey_x509, file, 0); 378 379 if (ret < 0) { 380 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 381 "GnuTLS: Failed to Import Private Key URL " 382 "'%s': (%d) %s", 383 file, ret, gnutls_strerror(ret)); 384 ret = -1; 385 goto cleanup; 386 } 387 } else { 388 file = ap_server_root_relative(spool, sc->x509_key_file); 389 390 if (load_datum_from_file(spool, file, &data) != 0) { 391 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 392 "GnuTLS: Error Reading Private Key '%s'", 393 file); 394 ret = -1; 395 goto cleanup; 396 } 397 398 ret = 399 gnutls_privkey_import_x509_raw(sc->privkey_x509, &data, 400 GNUTLS_X509_FMT_PEM, sc->pin, 401 0); 402 403 if (ret < 0) { 404 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 405 "GnuTLS: Failed to Import Private Key " 406 "'%s': (%d) %s", 407 file, ret, gnutls_strerror(ret)); 408 ret = -1; 409 goto cleanup; 410 } 411 } 412 } 413 414 /* Load the X.509 CA file */ 415 if (sc->x509_ca_file) 416 { 417 if (load_datum_from_file(spool, sc->x509_ca_file, &data) != 0) { 418 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 419 "GnuTLS: Error Reading " "Client CA File '%s'", 420 sc->x509_ca_file); 421 ret = -1; 422 goto cleanup; 423 } 424 425 ret = gnutls_x509_crt_list_import2(&sc->ca_list, &sc->ca_list_size, 426 &data, GNUTLS_X509_FMT_PEM, 0); 427 if (ret < 0) { 428 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 429 "GnuTLS: Failed to load " 430 "Client CA File '%s': (%d) %s", sc->x509_ca_file, 431 ret, gnutls_strerror(ret)); 432 ret = -1; 433 goto cleanup; 434 } 435 } 436 437 if (sc->priorities_str && sc->priorities == NULL) 438 { 514 439 const char *err; 515 440 ret = gnutls_priority_init(&sc->priorities, sc->priorities_str, &err); 516 441 517 518 519 520 521 522 523 524 525 526 527 528 529 442 if (ret < 0) { 443 if (ret == GNUTLS_E_INVALID_REQUEST) { 444 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 445 "GnuTLS: Syntax error parsing priorities string at: %s", 446 err); 447 } else { 448 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 449 "GnuTLS: error parsing priorities string"); 450 451 } 452 ret = -1; 453 goto cleanup; 454 } 530 455 } 531 456 532 457 ret = 0; 533 458 cleanup: 534 459 apr_pool_destroy(spool); 535 460 … … 617 542 } 618 543 619 const char *mgs_set_pgpcert_file(cmd_parms * parms, void *dummy __attribute__((unused)),620 const char *arg)621 {622 mgs_srvconf_rec *sc =623 (mgs_srvconf_rec *) ap_get_module_config(parms->server->624 module_config,625 &gnutls_module);626 627 sc->pgp_cert_file = ap_server_root_relative(parms->pool, arg);628 629 return NULL;630 }631 632 const char *mgs_set_pgpkey_file(cmd_parms * parms, void *dummy __attribute__((unused)),633 const char *arg) {634 mgs_srvconf_rec *sc =635 (mgs_srvconf_rec *) ap_get_module_config(parms->server->636 module_config,637 &gnutls_module);638 639 sc->pgp_key_file = ap_server_root_relative(parms->pool, arg);640 641 return NULL;642 }643 644 544 const char *mgs_set_tickets(cmd_parms *parms, 645 545 void *dummy __attribute__((unused)), … … 686 586 #endif 687 587 688 const char *mgs_set_cache(cmd_parms * parms, void *dummy __attribute__((unused)), 689 const char *type, const char *arg) { 588 const char *mgs_set_cache(cmd_parms * parms, 589 void *dummy __attribute__((unused)), 590 const char *type, const char *arg) 591 { 690 592 const char *err; 691 593 mgs_srvconf_rec *sc = 692 ap_get_module_config(parms->server->module_config, 693 &gnutls_module); 694 if ((err = ap_check_cmd_context(parms, GLOBAL_ONLY))) { 695 return err; 696 } 697 698 if (strcasecmp("none", type) == 0) { 699 sc->cache_type = mgs_cache_none; 700 sc->cache_config = NULL; 701 return NULL; 702 } else if (strcasecmp("dbm", type) == 0) { 703 sc->cache_type = mgs_cache_dbm; 704 } else if (strcasecmp("gdbm", type) == 0) { 705 sc->cache_type = mgs_cache_gdbm; 706 } 707 #if HAVE_APR_MEMCACHE 708 else if (strcasecmp("memcache", type) == 0) { 709 sc->cache_type = mgs_cache_memcache; 710 } 711 #endif 712 else { 713 return "Invalid Type for GnuTLSCache!"; 714 } 715 716 if (arg == NULL) 717 return "Invalid argument 2 for GnuTLSCache!"; 718 719 if (sc->cache_type == mgs_cache_dbm 720 || sc->cache_type == mgs_cache_gdbm) { 721 sc->cache_config = ap_server_root_relative(parms->pool, arg); 722 } else { 723 sc->cache_config = apr_pstrdup(parms->pool, arg); 724 } 725 726 return NULL; 727 } 728 729 const char *mgs_set_cache_timeout(cmd_parms * parms, void *dummy __attribute__((unused)), 730 const char *arg) { 731 int argint; 732 const char *err; 733 mgs_srvconf_rec *sc = 734 (mgs_srvconf_rec *) ap_get_module_config(parms->server-> 735 module_config, 736 &gnutls_module); 737 738 if ((err = ap_check_cmd_context(parms, GLOBAL_ONLY))) { 739 return err; 740 } 741 742 argint = atoi(arg); 743 744 if (argint < 0) { 745 return "GnuTLSCacheTimeout: Invalid argument"; 746 } else if (argint == 0) { 747 sc->cache_timeout = 0; 748 } else { 749 sc->cache_timeout = apr_time_from_sec(argint); 750 } 594 ap_get_module_config(parms->server->module_config, 595 &gnutls_module); 596 if ((err = ap_check_cmd_context(parms, GLOBAL_ONLY))) 597 return err; 598 599 unsigned char enable = GNUTLS_ENABLED_TRUE; 600 /* none: disable cache */ 601 if (strcasecmp("none", type) == 0) 602 enable = GNUTLS_ENABLED_FALSE; 603 604 /* Try to split socache "type:config" style configuration */ 605 const char* sep = ap_strchr_c(type, ':'); 606 if (sep) 607 { 608 type = apr_pstrmemdup(parms->temp_pool, type, sep - type); 609 if (arg != NULL) 610 { 611 /* No mixing of socache style and legacy config! */ 612 return "GnuTLSCache appears to have a mod_socache style " 613 "type:config value, but there is a second parameter!"; 614 } 615 arg = ++sep; 616 } 617 618 mgs_cache_t *cache = NULL; 619 /* parms->directive->directive contains the directive string */ 620 if (!strcasecmp(parms->directive->directive, "GnuTLSCache")) 621 { 622 if (enable == GNUTLS_ENABLED_FALSE) 623 { 624 sc->cache_enable = GNUTLS_ENABLED_FALSE; 625 return NULL; 626 } 627 sc->cache_enable = GNUTLS_ENABLED_TRUE; 628 cache = &sc->cache; 629 } 630 else if (!strcasecmp(parms->directive->directive, "GnuTLSOCSPCache")) 631 { 632 if (enable == GNUTLS_ENABLED_FALSE) 633 return "\"GnuTLSOCSPCache none\" is invalid, use " 634 "\"GnuTLSOCSPStapling off\" if you want to disable " 635 "OCSP stapling."; 636 cache = &sc->ocsp_cache; 637 } 638 else 639 return apr_psprintf(parms->temp_pool, "Internal Error: %s " 640 "called for unknown directive %s", 641 __func__, parms->directive->directive); 642 643 return mgs_cache_inst_config(cache, parms->server, 644 type, arg, 645 parms->pool, parms->temp_pool); 646 } 647 648 const char *mgs_set_timeout(cmd_parms * parms, 649 void *dummy __attribute__((unused)), 650 const char *arg) 651 { 652 apr_int64_t argint = apr_atoi64(arg); 653 /* timeouts cannot be negative */ 654 if (argint < 0) 655 return apr_psprintf(parms->pool, "%s: Invalid argument", 656 parms->directive->directive); 657 658 mgs_srvconf_rec *sc = (mgs_srvconf_rec *) 659 ap_get_module_config(parms->server->module_config, &gnutls_module); 660 661 if (!strcasecmp(parms->directive->directive, "GnuTLSCacheTimeout")) 662 sc->cache_timeout = apr_time_from_sec(argint); 663 else if (!strcasecmp(parms->directive->directive, 664 "GnuTLSOCSPCacheTimeout")) 665 sc->ocsp_cache_time = apr_time_from_sec(argint); 666 else if (!strcasecmp(parms->directive->directive, 667 "GnuTLSOCSPFailureTimeout")) 668 sc->ocsp_failure_timeout = apr_time_from_sec(argint); 669 else if (!strcasecmp(parms->directive->directive, 670 "GnuTLSOCSPFuzzTime")) 671 sc->ocsp_fuzz_time = apr_time_from_sec(argint); 672 else if (!strcasecmp(parms->directive->directive, 673 "GnuTLSOCSPSocketTimeout")) 674 sc->ocsp_socket_timeout = apr_time_from_sec(argint); 675 else 676 /* Can't happen unless there's a serious bug in mod_gnutls or Apache */ 677 return apr_psprintf(parms->pool, 678 "mod_gnutls: %s called for invalid option '%s'", 679 __func__, parms->directive->directive); 751 680 752 681 return NULL; … … 810 739 811 740 sc->x509_ca_file = ap_server_root_relative(parms->pool, arg); 812 813 return NULL;814 }815 816 const char *mgs_set_keyring_file(cmd_parms * parms, void *dummy __attribute__((unused)),817 const char *arg) {818 mgs_srvconf_rec *sc =819 (mgs_srvconf_rec *) ap_get_module_config(parms->server->820 module_config,821 &gnutls_module);822 823 sc->pgp_ring_file = ap_server_root_relative(parms->pool, arg);824 741 825 742 return NULL; … … 950 867 951 868 sc->privkey_x509 = NULL; 952 sc->privkey_pgp = NULL; 869 sc->anon_creds = NULL; 870 #ifdef ENABLE_SRP 871 sc->srp_creds = NULL; 872 #endif 873 sc->certs = NULL; 874 sc->certs_x509_chain = NULL; 875 sc->certs_x509_crt_chain = NULL; 953 876 sc->certs_x509_chain_num = 0; 954 877 sc->p11_modules = NULL; 955 878 sc->pin = NULL; 879 956 880 sc->priorities_str = NULL; 957 sc->cache_timeout = -1; /* -1 means "unset" */958 sc->cache_ type = mgs_cache_unset;959 sc->cache _config= NULL;881 sc->cache_timeout = MGS_TIMEOUT_UNSET; 882 sc->cache_enable = GNUTLS_ENABLED_UNSET; 883 sc->cache = NULL; 960 884 sc->tickets = GNUTLS_ENABLED_UNSET; 961 885 sc->priorities = NULL; 962 886 sc->dh_params = NULL; 887 sc->dh_file = NULL; 888 sc->ca_list = NULL; 889 sc->ca_list_size = 0; 963 890 sc->proxy_enabled = GNUTLS_ENABLED_UNSET; 964 891 sc->export_certificates_size = -1; … … 970 897 sc->proxy_x509_crl_file = NULL; 971 898 sc->proxy_priorities_str = NULL; 899 sc->proxy_x509_creds = NULL; 900 sc->anon_client_creds = NULL; 972 901 sc->proxy_priorities = NULL; 902 sc->proxy_x509_tl = NULL; 903 904 sc->ocsp_staple = GNUTLS_ENABLED_UNSET; 905 sc->ocsp_auto_refresh = GNUTLS_ENABLED_UNSET; 906 sc->ocsp_check_nonce = GNUTLS_ENABLED_UNSET; 907 sc->ocsp_response_file = NULL; 908 sc->ocsp_mutex = NULL; 909 sc->ocsp_cache = NULL; 910 sc->ocsp_cache_time = MGS_TIMEOUT_UNSET; 911 sc->ocsp_failure_timeout = MGS_TIMEOUT_UNSET; 912 sc->ocsp_fuzz_time = MGS_TIMEOUT_UNSET; 913 sc->ocsp_socket_timeout = MGS_TIMEOUT_UNSET; 914 915 sc->singleton_wd = NULL; 973 916 974 917 /* this relies on GnuTLS never changing the gnutls_certificate_request_t enum to define -1 */ … … 993 936 void *mgs_config_server_merge(apr_pool_t * p, void *BASE, void *ADD) 994 937 { 995 int i;996 938 char *err = NULL; 997 939 mgs_srvconf_rec *base = (mgs_srvconf_rec *) BASE; … … 1015 957 gnutls_srvconf_merge(p11_modules, NULL); 1016 958 gnutls_srvconf_merge(pin, NULL); 1017 gnutls_srvconf_merge(pgp_cert_file, NULL);1018 gnutls_srvconf_merge(pgp_key_file, NULL);1019 gnutls_srvconf_merge(pgp_ring_file, NULL);1020 959 gnutls_srvconf_merge(dh_file, NULL); 1021 960 gnutls_srvconf_merge(priorities_str, NULL); 961 gnutls_srvconf_merge(cache_timeout, MGS_TIMEOUT_UNSET); 1022 962 1023 963 gnutls_srvconf_merge(proxy_x509_key_file, NULL); … … 1028 968 gnutls_srvconf_merge(proxy_priorities, NULL); 1029 969 1030 /* FIXME: the following items are pre-allocated, and should be 1031 * properly disposed of before assigning in order to avoid leaks; 1032 * so at the moment, we can't actually have them in the config. 1033 * what happens during de-allocation? */ 1034 /* TODO: mgs_load_files takes care of most of these now, verify 1035 * and clean up the following lines */ 970 gnutls_srvconf_merge(ocsp_staple, GNUTLS_ENABLED_UNSET); 971 gnutls_srvconf_merge(ocsp_auto_refresh, GNUTLS_ENABLED_UNSET); 972 gnutls_srvconf_merge(ocsp_check_nonce, GNUTLS_ENABLED_UNSET); 973 gnutls_srvconf_assign(ocsp_response_file); 974 gnutls_srvconf_merge(ocsp_cache_time, MGS_TIMEOUT_UNSET); 975 gnutls_srvconf_merge(ocsp_failure_timeout, MGS_TIMEOUT_UNSET); 976 gnutls_srvconf_merge(ocsp_fuzz_time, MGS_TIMEOUT_UNSET); 977 gnutls_srvconf_merge(ocsp_socket_timeout, MGS_TIMEOUT_UNSET); 978 1036 979 gnutls_srvconf_assign(ca_list); 1037 980 gnutls_srvconf_assign(ca_list_size); 1038 gnutls_srvconf_assign(cert_pgp);1039 gnutls_srvconf_assign(cert_crt_pgp);1040 gnutls_srvconf_assign(pgp_list);1041 981 gnutls_srvconf_assign(certs); 1042 982 gnutls_srvconf_assign(anon_creds); … … 1045 985 gnutls_srvconf_assign(certs_x509_crt_chain); 1046 986 gnutls_srvconf_assign(certs_x509_chain_num); 1047 1048 /* how do these get transferred cleanly before the data from ADD1049 * goes away? */1050 gnutls_srvconf_assign(cert_cn);1051 for (i = 0; i < MAX_CERT_SAN; i++)1052 gnutls_srvconf_assign(cert_san[i]);1053 987 1054 988 return sc; -
src/gnutls_hooks.c
r8a264b0 rea9c699 1 /* *1 /* 2 2 * Copyright 2004-2005 Paul Querna 3 3 * Copyright 2008, 2014 Nikos Mavrogiannopoulos 4 4 * Copyright 2011 Dash Shendy 5 5 * Copyright 2013-2014 Daniel Kahn Gillmor 6 * Copyright 2015-201 6 ThomasKlute6 * Copyright 2015-2019 Fiona Klute 7 7 * 8 8 * Licensed under the Apache License, Version 2.0 (the "License"); … … 17 17 * See the License for the specific language governing permissions and 18 18 * limitations under the License. 19 *20 19 */ 21 20 22 21 #include "mod_gnutls.h" 22 #include "gnutls_cache.h" 23 #include "gnutls_config.h" 24 #include "gnutls_ocsp.h" 25 #include "gnutls_proxy.h" 26 #include "gnutls_sni.h" 27 #include "gnutls_util.h" 28 #include "gnutls_watchdog.h" 29 23 30 #include "http_vhost.h" 24 31 #include "ap_mpm.h" 25 #include "mod_status.h" 32 #include <mod_status.h> 33 #include <util_mutex.h> 34 #include <apr_escape.h> 35 /* This provides strcmp and related functions */ 36 #define APR_WANT_STRFUNC 37 #include <apr_want.h> 26 38 27 39 #ifdef ENABLE_MSVA … … 33 45 #endif 34 46 35 #if !USING_2_1_RECENT36 extern server_rec *ap_server_conf;37 #endif38 39 47 #if MOD_GNUTLS_DEBUG 40 48 static apr_file_t *debug_log_fp; … … 44 52 ((c->is_proxy == GNUTLS_ENABLED_TRUE) ? "proxy " : "") 45 53 54 /** Key to encrypt session tickets. Must be kept secret. This key is 55 * generated in the `pre_config` hook and thus constant across 56 * forks. The problem with this approach is that it does not support 57 * regular key rotation. */ 46 58 static gnutls_datum_t session_ticket_key = {NULL, 0}; 47 59 60 61 48 62 static int mgs_cert_verify(request_rec * r, mgs_handle_t * ctxt); 49 /* use side==0 for server and side==1 for client */63 /** use side==0 for server and side==1 for client */ 50 64 static void mgs_add_common_cert_vars(request_rec * r, gnutls_x509_crt_t cert, int side, size_t export_cert_size); 51 static void mgs_add_common_pgpcert_vars(request_rec * r, gnutls_openpgp_crt_t cert, int side, size_t export_cert_size);65 mgs_srvconf_rec* mgs_find_sni_server(mgs_handle_t *ctxt); 52 66 static int mgs_status_hook(request_rec *r, int flags); 53 67 #ifdef ENABLE_MSVA 54 68 static const char* mgs_x509_construct_uid(request_rec * pool, gnutls_x509_crt_t cert); 55 69 #endif 56 static int load_proxy_x509_credentials(server_rec *s);57 70 58 71 /* Pool Cleanup Function */ 59 apr_status_t mgs_cleanup_pre_config(void *data __attribute__((unused))) { 60 /* Free all session data */ 72 apr_status_t mgs_cleanup_pre_config(void *data __attribute__((unused))) 73 { 74 /* Free session ticket master key */ 75 #if GNUTLS_VERSION_NUMBER >= 0x030400 76 gnutls_memset(session_ticket_key.data, 0, session_ticket_key.size); 77 #endif 61 78 gnutls_free(session_ticket_key.data); 62 79 session_ticket_key.data = NULL; 63 80 session_ticket_key.size = 0; 64 /* Deinitialize GnuTLS Library */ 65 gnutls_global_deinit(); 81 82 /* Deinit default priority setting */ 83 mgs_default_priority_deinit(); 66 84 return APR_SUCCESS; 67 85 } … … 110 128 } 111 129 112 /* Initialize GnuTLS Library */113 ret = gnutls_global_init();114 if (ret < 0) {115 ap_log_perror(APLOG_MARK, APLOG_EMERG, 0, plog, "gnutls_global_init: %s", gnutls_strerror(ret));116 return DONE;117 }118 119 130 /* Generate a Session Key */ 120 131 ret = gnutls_session_ticket_key_generate(&session_ticket_key); … … 124 135 } 125 136 137 /* Initialize default priority setting */ 138 ret = mgs_default_priority_init(); 139 if (ret < 0) 140 { 141 ap_log_perror(APLOG_MARK, APLOG_EMERG, 0, plog, 142 "gnutls_priority_init failed for default '%s': %s (%d)", 143 MGS_DEFAULT_PRIORITY, gnutls_strerror(ret), ret); 144 return DONE; 145 } 146 126 147 AP_OPTIONAL_HOOK(status_hook, mgs_status_hook, NULL, NULL, APR_HOOK_MIDDLE); 127 148 128 /* Register a pool clean-up function */ 149 ap_mutex_register(pconf, MGS_CACHE_MUTEX_NAME, NULL, APR_LOCK_DEFAULT, 0); 150 ap_mutex_register(pconf, MGS_OCSP_MUTEX_NAME, NULL, APR_LOCK_DEFAULT, 0); 151 ap_mutex_register(pconf, MGS_OCSP_CACHE_MUTEX_NAME, NULL, 152 APR_LOCK_DEFAULT, 0); 153 154 /* Register a pool clean-up function */ 129 155 apr_pool_cleanup_register(pconf, NULL, mgs_cleanup_pre_config, apr_pool_cleanup_null); 130 156 … … 132 158 } 133 159 134 static int mgs_select_virtual_server_cb(gnutls_session_t session) { 135 136 mgs_handle_t *ctxt = NULL; 137 mgs_srvconf_rec *tsc = NULL; 160 161 162 /** 163 * Get the list of available protocols for this connection and add it 164 * to the GnuTLS session. Must run before the client hello function. 165 */ 166 static void prepare_alpn_proposals(mgs_handle_t *ctxt) 167 { 168 /* Check if any protocol upgrades are available 169 * 170 * The "report_all" parameter to ap_get_protocol_upgrades() is 0 171 * (report only more preferable protocols) because setting it to 1 172 * doesn't actually report ALL protocols, but only all except the 173 * current one. This way we can at least list the current one as 174 * available by appending it without potentially negotiating a 175 * less preferred protocol. */ 176 const apr_array_header_t *pupgrades = NULL; 177 apr_status_t ret = 178 ap_get_protocol_upgrades(ctxt->c, NULL, ctxt->sc->s, 179 /*report_all*/ 0, &pupgrades); 180 if (ret != APR_SUCCESS) 181 { 182 ap_log_cerror(APLOG_MARK, APLOG_WARNING, 0, ctxt->c, 183 "%s: ap_get_protocol_upgrades() failed, " 184 "cannot configure ALPN!", __func__); 185 return; 186 } 187 188 if (pupgrades == NULL || pupgrades->nelts == 0) 189 { 190 ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, ctxt->c, 191 "%s: No protocol upgrades available.", __func__); 192 return; 193 } 194 195 ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, ctxt->c, 196 "%s: Found %d protocol upgrade(s) for ALPN: %s", 197 __func__, pupgrades->nelts, 198 apr_array_pstrcat(ctxt->c->pool, pupgrades, ',')); 199 gnutls_datum_t *alpn_protos = 200 mgs_str_array_to_datum_array(pupgrades, 201 ctxt->c->pool, 202 pupgrades->nelts + 1); 203 204 /* Add the current (default) protocol at the end of the list */ 205 alpn_protos[pupgrades->nelts].data = 206 (void*) apr_pstrdup(ctxt->c->pool, ap_get_protocol(ctxt->c)); 207 alpn_protos[pupgrades->nelts].size = 208 strlen((char*) alpn_protos[pupgrades->nelts].data); 209 ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, ctxt->c, 210 "%s: Adding current protocol %s to ALPN set.", 211 __func__, alpn_protos[pupgrades->nelts].data); 212 213 gnutls_alpn_set_protocols(ctxt->session, 214 alpn_protos, 215 pupgrades->nelts, 216 GNUTLS_ALPN_SERVER_PRECEDENCE); 217 } 218 219 220 221 /** 222 * Check if ALPN selected any protocol upgrade, try to switch if so. 223 */ 224 static int process_alpn_result(mgs_handle_t *ctxt) 225 { 138 226 int ret = 0; 139 140 _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); 141 142 ctxt = gnutls_transport_get_ptr(session); 143 144 /* find the virtual server */ 145 tsc = mgs_find_sni_server(session); 146 147 if (tsc != NULL) { 148 // Found a TLS vhost based on the SNI from the client; use it instead. 149 ctxt->sc = tsc; 150 } 151 152 gnutls_certificate_server_set_request(session, ctxt->sc->client_verify_mode); 227 gnutls_datum_t alpn_proto; 228 ret = gnutls_alpn_get_selected_protocol(ctxt->session, &alpn_proto); 229 if (ret != GNUTLS_E_SUCCESS) 230 { 231 ap_log_cerror(APLOG_MARK, APLOG_TRACE1, APR_SUCCESS, ctxt->c, 232 "%s: No ALPN result: %s (%d)", 233 __func__, gnutls_strerror(ret), ret); 234 return GNUTLS_E_SUCCESS; 235 } 236 237 apr_array_header_t *client_protos = 238 apr_array_make(ctxt->c->pool, 1, sizeof(char *)); 239 /* apr_pstrndup to ensure that the protocol is null terminated */ 240 APR_ARRAY_PUSH(client_protos, char *) = 241 apr_pstrndup(ctxt->c->pool, (char*) alpn_proto.data, alpn_proto.size); 242 const char *selected = 243 ap_select_protocol(ctxt->c, NULL, ctxt->sc->s, client_protos); 244 245 /* ap_select_protocol() will return NULL if none of the ALPN 246 * proposals matched. GnuTLS negotiated alpn_proto based on the 247 * list provided by the server, but the vhost might have changed 248 * based on SNI. Apache seems to adjust the proposal list to avoid 249 * such issues though. 250 * 251 * GnuTLS will return a fatal "no_application_protocol" alert as 252 * required by RFC 7301 if the post client hello function returns 253 * GNUTLS_E_NO_APPLICATION_PROTOCOL. */ 254 if (!selected) 255 { 256 ap_log_cerror(APLOG_MARK, APLOG_ERR, APR_EGENERAL, ctxt->c, 257 "%s: ap_select_protocol() returned NULL! Please " 258 "make sure any overlapping vhosts have the same " 259 "protocols available.", 260 __func__); 261 return GNUTLS_E_NO_APPLICATION_PROTOCOL; 262 } 263 264 if (strcmp(selected, ap_get_protocol(ctxt->c)) == 0) 265 { 266 ap_log_cerror(APLOG_MARK, APLOG_TRACE1, APR_SUCCESS, ctxt->c, 267 "%s: Already using protocol '%s', nothing to do.", 268 __func__, selected); 269 return GNUTLS_E_SUCCESS; 270 } 271 272 ap_log_cerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, ctxt->c, 273 "%s: Switching protocol to '%s' based on ALPN.", 274 __func__, selected); 275 apr_status_t status = ap_switch_protocol(ctxt->c, NULL, 276 ctxt->sc->s, 277 selected); 278 if (status != APR_SUCCESS) 279 { 280 ap_log_cerror(APLOG_MARK, APLOG_ERR, status, ctxt->c, 281 "%s: Protocol switch to '%s' failed!", 282 __func__, selected); 283 return GNUTLS_E_NO_APPLICATION_PROTOCOL; 284 } 285 /* ALPN done! */ 286 return GNUTLS_E_SUCCESS; 287 } 288 289 290 291 /** 292 * (Re-)Load credentials and priorities for the connection. This is 293 * meant to be called after virtual host selection in the pre or post 294 * client hello hook. 295 */ 296 static int reload_session_credentials(mgs_handle_t *ctxt) 297 { 298 int ret = 0; 299 300 gnutls_certificate_server_set_request(ctxt->session, 301 ctxt->sc->client_verify_mode); 153 302 154 303 /* Set x509 credentials */ 155 gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, ctxt->sc->certs); 304 gnutls_credentials_set(ctxt->session, 305 GNUTLS_CRD_CERTIFICATE, ctxt->sc->certs); 156 306 /* Set Anon credentials */ 157 gnutls_credentials_set(session, GNUTLS_CRD_ANON, ctxt->sc->anon_creds); 307 gnutls_credentials_set(ctxt->session, GNUTLS_CRD_ANON, 308 ctxt->sc->anon_creds); 158 309 159 310 #ifdef ENABLE_SRP 160 311 /* Set SRP credentials */ 161 312 if (ctxt->sc->srp_tpasswd_conf_file != NULL && ctxt->sc->srp_tpasswd_file != NULL) { 162 gnutls_credentials_set(session, GNUTLS_CRD_SRP, ctxt->sc->srp_creds); 313 gnutls_credentials_set(ctxt->session, GNUTLS_CRD_SRP, 314 ctxt->sc->srp_creds); 163 315 } 164 316 #endif 165 317 166 /* update the priorities - to avoid negotiating a ciphersuite that is not 318 /* Enable session tickets */ 319 if (session_ticket_key.data != NULL && 320 ctxt->sc->tickets == GNUTLS_ENABLED_TRUE) 321 { 322 ret = gnutls_session_ticket_enable_server(ctxt->session, &session_ticket_key); 323 if (ret != GNUTLS_E_SUCCESS) 324 ap_log_cerror(APLOG_MARK, APLOG_ERR, APR_EGENERAL, ctxt->c, 325 "gnutls_session_ticket_enable_server failed: %s (%d)", 326 gnutls_strerror(ret), ret); 327 } 328 329 /* Update the priorities - to avoid negotiating a ciphersuite that is not 167 330 * enabled on this virtual server. Note that here we ignore the version 168 * negotiation. 169 */ 170 171 ret = gnutls_priority_set(session, ctxt->sc->priorities); 331 * negotiation. */ 332 ret = gnutls_priority_set(ctxt->session, ctxt->sc->priorities); 333 334 return ret; 335 } 336 337 338 339 /** 340 * Post client hello hook function for GnuTLS. This function has two 341 * purposes: Firstly, it acts as a fallback for early_sni_hook(), by 342 * parsing SNI and selecting a virtual host based on it if 343 * necessary. Secondly, it calls ALPN processing. 344 * 345 * @param session the TLS session 346 * 347 * @return zero or a GnuTLS error code, as required by GnuTLS hook 348 * definition 349 */ 350 static int post_client_hello_hook(gnutls_session_t session) 351 { 352 int ret = 0; 353 mgs_handle_t *ctxt = gnutls_session_get_ptr(session); 354 355 /* If ctxt->sni_name is set at this point the early_sni_hook() 356 * function ran, found an SNI server name, selected a virtual 357 * host, and set up credentials, so we don't need to do that 358 * again. Otherwise try again, to cover GnuTLS versions < 3.6.3 359 * and pick up future extensions to gnutls_server_name_get(). */ 360 if (ctxt->sni_name == NULL) 361 { 362 /* try to find a virtual host */ 363 mgs_srvconf_rec *tsc = mgs_find_sni_server(ctxt); 364 if (tsc != NULL) 365 { 366 /* Found a TLS vhost based on the SNI, configure the 367 * connection context. */ 368 ctxt->sc = tsc; 369 } 370 371 ap_log_cerror(APLOG_MARK, APLOG_TRACE1, APR_SUCCESS, ctxt->c, 372 "%s: Loading credentials in post client hello hook", 373 __func__); 374 reload_session_credentials(ctxt); 375 } 376 377 ret = process_alpn_result(ctxt); 378 if (ret != GNUTLS_E_SUCCESS) 379 return ret; 380 172 381 /* actually it shouldn't fail since we have checked at startup */ 173 382 return ret; 174 175 383 } 176 384 … … 201 409 *privkey = ctxt->sc->privkey_x509; 202 410 return 0; 203 } else if (gnutls_certificate_type_get(session) == GNUTLS_CRT_OPENPGP) {204 // OPENPGP CERTIFICATE205 *pcerts = ctxt->sc->cert_pgp;206 *pcert_length = 1;207 *privkey = ctxt->sc->privkey_pgp;208 return 0;209 411 } else { 210 412 // UNKNOWN CERTIFICATE … … 213 415 } 214 416 215 /* Read the common name or the alternative name of the certificate. 216 * We only support a single name per certificate. 217 * 218 * Returns negative on error. 417 418 419 #if GNUTLS_VERSION_NUMBER >= 0x030506 420 #define HAVE_KNOWN_DH_GROUPS 1 421 #endif 422 #ifdef HAVE_KNOWN_DH_GROUPS 423 /** 424 * Try to estimate a GnuTLS security parameter based on the given 425 * private key. Any errors are logged. 426 * 427 * @param s The `server_rec` to use for logging 428 * 429 * @param key The private key to use 430 * 431 * @return `gnutls_sec_param_t` as returned by 432 * `gnutls_pk_bits_to_sec_param` for the key properties, or 433 * GNUTLS_SEC_PARAM_UNKNOWN in case of error 219 434 */ 220 static int read_crt_cn(server_rec * s, apr_pool_t * p, gnutls_x509_crt_t cert, char **cert_cn) { 221 222 int rv = 0; 223 size_t data_len; 224 225 226 _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); 227 *cert_cn = NULL; 228 229 data_len = 0; 230 rv = gnutls_x509_crt_get_dn_by_oid(cert, GNUTLS_OID_X520_COMMON_NAME, 0, 0, NULL, &data_len); 231 232 if (rv == GNUTLS_E_SHORT_MEMORY_BUFFER && data_len > 1) { 233 *cert_cn = apr_palloc(p, data_len); 234 rv = gnutls_x509_crt_get_dn_by_oid(cert, 235 GNUTLS_OID_X520_COMMON_NAME, 236 0, 0, *cert_cn, 237 &data_len); 238 } else { /* No CN return subject alternative name */ 239 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, 240 "No common name found in certificate for '%s:%d'. Looking for subject alternative name...", 241 s->server_hostname, s->port); 242 rv = 0; 243 /* read subject alternative name */ 244 for (int i = 0; !(rv < 0); i++) 245 { 246 data_len = 0; 247 rv = gnutls_x509_crt_get_subject_alt_name(cert, i, 248 NULL, 249 &data_len, 250 NULL); 251 252 if (rv == GNUTLS_E_SHORT_MEMORY_BUFFER 253 && data_len > 1) { 254 /* FIXME: not very efficient. What if we have several alt names 255 * before DNSName? 256 */ 257 *cert_cn = apr_palloc(p, data_len + 1); 258 259 rv = gnutls_x509_crt_get_subject_alt_name 260 (cert, i, *cert_cn, &data_len, NULL); 261 (*cert_cn)[data_len] = 0; 262 263 if (rv == GNUTLS_SAN_DNSNAME) 264 break; 265 } 266 } 267 } 268 269 return rv; 270 } 271 272 static int read_pgpcrt_cn(server_rec * s, apr_pool_t * p, 273 gnutls_openpgp_crt_t cert, char **cert_cn) { 274 int rv = 0; 275 size_t data_len; 276 277 278 _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); 279 *cert_cn = NULL; 280 281 data_len = 0; 282 rv = gnutls_openpgp_crt_get_name(cert, 0, NULL, &data_len); 283 284 if (rv == GNUTLS_E_SHORT_MEMORY_BUFFER && data_len > 1) { 285 *cert_cn = apr_palloc(p, data_len); 286 rv = gnutls_openpgp_crt_get_name(cert, 0, *cert_cn, 287 &data_len); 288 } else { /* No CN return subject alternative name */ 289 ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, 290 "No name found in PGP certificate for '%s:%d'.", 291 s->server_hostname, s->port); 292 } 293 294 return rv; 295 } 296 297 int mgs_hook_post_config(apr_pool_t * p, apr_pool_t * plog __attribute__((unused)), apr_pool_t * ptemp __attribute__((unused)), server_rec * base_server) { 298 435 static gnutls_sec_param_t sec_param_from_privkey(server_rec *server, 436 gnutls_privkey_t key) 437 { 438 unsigned int bits = 0; 439 int pk_algo = gnutls_privkey_get_pk_algorithm(key, &bits); 440 if (pk_algo < 0) 441 { 442 ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, server, 443 "%s: Could not get private key parameters: %s (%d)", 444 __func__, gnutls_strerror(pk_algo), pk_algo); 445 return GNUTLS_SEC_PARAM_UNKNOWN; 446 } 447 return gnutls_pk_bits_to_sec_param(pk_algo, bits); 448 } 449 #else 450 /** ffdhe2048 DH group as defined in RFC 7919, Appendix A.1. This is 451 * the default DH group if mod_gnutls is compiled agains a GnuTLS 452 * version that does not provide known DH groups based on security 453 * parameters (before 3.5.6). */ 454 static const char FFDHE2048_PKCS3[] = 455 "-----BEGIN DH PARAMETERS-----\n" 456 "MIIBDAKCAQEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz\n" 457 "+8yTnc4kmz75fS/jY2MMddj2gbICrsRhetPfHtXV/WVhJDP1H18GbtCFY2VVPe0a\n" 458 "87VXE15/V8k1mE8McODmi3fipona8+/och3xWKE2rec1MKzKT0g6eXq8CrGCsyT7\n" 459 "YdEIqUuyyOP7uWrat2DX9GgdT0Kj3jlN9K5W7edjcrsZCwenyO4KbXCeAvzhzffi\n" 460 "7MA0BM0oNC9hkXL+nOmFg/+OTxIy7vKBg8P+OxtMb61zO7X8vC7CIAXFjvGDfRaD\n" 461 "ssbzSibBsu/6iGtCOGEoXJf//////////wIBAgICAQA=\n" 462 "-----END DH PARAMETERS-----\n"; 463 const gnutls_datum_t default_dh_params = { 464 (void *) FFDHE2048_PKCS3, 465 sizeof(FFDHE2048_PKCS3) 466 }; 467 #endif 468 469 470 471 /** 472 * Configure the default DH groups to use for the given server. When 473 * compiled against GnuTLS version 3.5.6 or newer the known DH group 474 * matching the GnuTLS security parameter estimated from the private 475 * key is used. Otherwise the ffdhe2048 DH group as defined in RFC 476 * 7919, Appendix A.1 is the default. 477 * 478 * @param server the host to configure 479 * 480 * @return `OK` on success, `HTTP_UNAUTHORIZED` otherwise 481 */ 482 static int set_default_dh_param(server_rec *server) 483 { 484 mgs_srvconf_rec *sc = (mgs_srvconf_rec *) 485 ap_get_module_config(server->module_config, &gnutls_module); 486 487 #ifdef HAVE_KNOWN_DH_GROUPS 488 gnutls_sec_param_t seclevel = GNUTLS_SEC_PARAM_UNKNOWN; 489 if (sc->privkey_x509) 490 { 491 seclevel = sec_param_from_privkey(server, sc->privkey_x509); 492 ap_log_error(APLOG_MARK, APLOG_TRACE1, APR_SUCCESS, server, 493 "%s: GnuTLS security param estimated based on " 494 "private key '%s': %s", 495 __func__, sc->x509_key_file, 496 gnutls_sec_param_get_name(seclevel)); 497 } 498 499 if (seclevel == GNUTLS_SEC_PARAM_UNKNOWN) 500 seclevel = GNUTLS_SEC_PARAM_MEDIUM; 501 ap_log_error(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, server, 502 "%s: Setting DH params for security level '%s'.", 503 __func__, gnutls_sec_param_get_name(seclevel)); 504 505 int ret = gnutls_certificate_set_known_dh_params(sc->certs, seclevel); 506 if (ret < 0) 507 { 508 ap_log_error(APLOG_MARK, APLOG_EMERG, APR_EGENERAL, server, 509 "%s: setting known DH params failed: %s (%d)", 510 __func__, gnutls_strerror(ret), ret); 511 return HTTP_UNAUTHORIZED; 512 } 513 ret = gnutls_anon_set_server_known_dh_params(sc->anon_creds, seclevel); 514 if (ret < 0) 515 { 516 ap_log_error(APLOG_MARK, APLOG_EMERG, APR_EGENERAL, server, 517 "%s: setting known DH params failed: %s (%d)", 518 __func__, gnutls_strerror(ret), ret); 519 return HTTP_UNAUTHORIZED; 520 } 521 #else 522 int ret = gnutls_dh_params_init(&sc->dh_params); 523 if (ret < 0) 524 { 525 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, server, 526 "%s: Failed to initialize DH params structure: " 527 "%s (%d)", __func__, gnutls_strerror(ret), ret); 528 return HTTP_UNAUTHORIZED; 529 } 530 ret = gnutls_dh_params_import_pkcs3(sc->dh_params, &default_dh_params, 531 GNUTLS_X509_FMT_PEM); 532 if (ret < 0) 533 { 534 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, server, 535 "%s: Failed to import default DH params: %s (%d)", 536 __func__, gnutls_strerror(ret), ret); 537 return HTTP_UNAUTHORIZED; 538 } 539 540 gnutls_certificate_set_dh_params(sc->certs, sc->dh_params); 541 gnutls_anon_set_server_dh_params(sc->anon_creds, sc->dh_params); 542 #endif 543 544 return OK; 545 } 546 547 548 549 /** 550 * Post config hook. 551 * 552 * Must return OK or DECLINED on success, something else on 553 * error. These codes are defined in Apache httpd.h along with the 554 * HTTP status codes, so I'm going to use HTTP error codes both for 555 * fun (and to avoid conflicts). 556 */ 557 int mgs_hook_post_config(apr_pool_t *pconf, 558 apr_pool_t *plog __attribute__((unused)), 559 apr_pool_t *ptemp, 560 server_rec *base_server) 561 { 299 562 int rv; 300 563 server_rec *s; 301 gnutls_dh_params_t dh_params = NULL;302 564 mgs_srvconf_rec *sc; 303 565 mgs_srvconf_rec *sc_base; … … 316 578 317 579 318 rv = mgs_cache_post_config(p, s, sc_base); 319 if (rv != 0) { 580 rv = mgs_cache_post_config(pconf, ptemp, s, sc_base); 581 if (rv != APR_SUCCESS) 582 { 320 583 ap_log_error(APLOG_MARK, APLOG_STARTUP, rv, s, 321 "GnuTLS: Post Config for GnuTLSCache Failed." 322 " Shutting Down."); 323 exit(-1); 584 "Post config for cache failed."); 585 return HTTP_INSUFFICIENT_STORAGE; 586 } 587 588 if (sc_base->ocsp_mutex == NULL) 589 { 590 rv = ap_global_mutex_create(&sc_base->ocsp_mutex, NULL, 591 MGS_OCSP_MUTEX_NAME, NULL, 592 base_server, pconf, 0); 593 if (rv != APR_SUCCESS) 594 return rv; 324 595 } 325 596 … … 344 615 rv = gnutls_pkcs11_add_provider(p11_module, NULL); 345 616 if (rv != GNUTLS_E_SUCCESS) 346 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,617 ap_log_error(APLOG_MARK, APLOG_STARTUP, APR_EGENERAL, s, 347 618 "GnuTLS: Loading PKCS #11 provider module %s " 348 619 "failed: %s (%d).", 349 620 p11_module, gnutls_strerror(rv), rv); 621 else 622 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, 623 "%s: PKCS #11 provider module %s loaded.", 624 __func__, p11_module); 350 625 } 351 626 } 352 627 } 353 628 354 for (s = base_server; s; s = s->next) { 629 sc_base->singleton_wd = 630 mgs_new_singleton_watchdog(base_server, MGS_SINGLETON_WATCHDOG, pconf); 631 632 for (s = base_server; s; s = s->next) 633 { 355 634 sc = (mgs_srvconf_rec *) ap_get_module_config(s->module_config, &gnutls_module); 356 sc->cache_type = sc_base->cache_type; 357 sc->cache_config = sc_base->cache_config; 358 sc->cache_timeout = sc_base->cache_timeout; 359 360 rv = mgs_load_files(p, s); 361 if (rv != 0) { 362 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 363 "GnuTLS: Loading required files failed." 364 " Shutting Down."); 365 exit(-1); 366 } 635 sc->s = s; 636 sc->cache_enable = sc_base->cache_enable; 637 sc->cache = sc_base->cache; 638 if (sc->cache_timeout == MGS_TIMEOUT_UNSET) 639 sc->cache_timeout = sc_base->cache_timeout; 640 sc->ocsp_cache = sc_base->ocsp_cache; 641 642 sc->singleton_wd = sc_base->singleton_wd; 367 643 368 644 /* defaults for unset values: */ … … 370 646 sc->enabled = GNUTLS_ENABLED_FALSE; 371 647 if (sc->tickets == GNUTLS_ENABLED_UNSET) 372 sc->tickets = GNUTLS_ENABLED_TRUE; 648 { 649 /* GnuTLS 3.6.4 introduced automatic master key rotation */ 650 if (gnutls_check_version_numeric(3, 6, 4)) 651 sc->tickets = GNUTLS_ENABLED_TRUE; 652 else 653 sc->tickets = GNUTLS_ENABLED_FALSE; 654 } 373 655 if (sc->export_certificates_size < 0) 374 656 sc->export_certificates_size = 0; … … 378 660 sc->client_verify_method = mgs_cvm_cartel; 379 661 662 // TODO: None of the stuff below needs to be done if 663 // sc->enabled == GNUTLS_ENABLED_FALSE, we could just continue 664 // to the next host. 665 666 /* Load certificates and stuff (includes parsing priority) */ 667 rv = mgs_load_files(pconf, ptemp, s); 668 if (rv != 0) { 669 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 670 "%s: Loading credentials failed!", __func__); 671 return HTTP_NOT_FOUND; 672 } 673 674 sc->ocsp_mutex = sc_base->ocsp_mutex; 675 /* init OCSP configuration unless explicitly disabled */ 676 if (sc->enabled && sc->ocsp_staple != GNUTLS_ENABLED_FALSE) 677 { 678 const char *err = mgs_ocsp_configure_stapling(pconf, ptemp, s); 679 if (err != NULL) 680 { 681 /* If OCSP stapling is enabled only by default ignore 682 * error and disable stapling */ 683 if (sc->ocsp_staple == GNUTLS_ENABLED_UNSET) 684 { 685 ap_log_error(APLOG_MARK, APLOG_INFO, APR_SUCCESS, s, 686 "Cannnot enable OCSP stapling for " 687 "host '%s:%d': %s", 688 s->server_hostname, s->addrs->host_port, err); 689 sc->ocsp_staple = GNUTLS_ENABLED_FALSE; 690 } 691 /* If OCSP stapling is explicitly enabled this is a 692 * critical error. */ 693 else 694 { 695 ap_log_error(APLOG_MARK, APLOG_STARTUP, APR_EINVAL, s, 696 "OCSP stapling configuration failed for " 697 "host '%s:%d': %s", 698 s->server_hostname, s->addrs->host_port, err); 699 return HTTP_INTERNAL_SERVER_ERROR; 700 } 701 } 702 else 703 { 704 /* Might already be set */ 705 sc->ocsp_staple = GNUTLS_ENABLED_TRUE; 706 /* Set up stapling */ 707 rv = mgs_ocsp_enable_stapling(pconf, ptemp, s); 708 if (rv != OK && rv != DECLINED) 709 return rv; 710 } 711 } 712 380 713 /* Check if the priorities have been set */ 381 714 if (sc->priorities == NULL && sc->enabled == GNUTLS_ENABLED_TRUE) { 382 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 383 "GnuTLS: Host '%s:%d' is missing the GnuTLSPriorities directive!", 384 s->server_hostname, s->port); 385 exit(-1); 386 } 387 388 /* Check if DH params have been set per host */ 715 ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, 716 "No GnuTLSPriorities directive for host '%s:%d', " 717 "using default '%s'.", 718 s->server_hostname, s->addrs->host_port, 719 MGS_DEFAULT_PRIORITY); 720 sc->priorities = mgs_get_default_prio(); 721 } 722 723 /* Set host DH params from user configuration or defaults */ 389 724 if (sc->dh_params != NULL) { 390 725 gnutls_certificate_set_dh_params(sc->certs, sc->dh_params); 391 726 gnutls_anon_set_server_dh_params(sc->anon_creds, sc->dh_params); 392 } else if (dh_params) { 393 gnutls_certificate_set_dh_params(sc->certs, dh_params); 394 gnutls_anon_set_server_dh_params(sc->anon_creds, dh_params); 727 } else { 728 rv = set_default_dh_param(s); 729 if (rv != OK) 730 return rv; 395 731 } 396 732 … … 411 747 412 748 if ((sc->certs_x509_chain == NULL || sc->certs_x509_chain_num < 1) && 413 sc-> cert_pgp == NULL && sc->enabled == GNUTLS_ENABLED_TRUE) {749 sc->enabled == GNUTLS_ENABLED_TRUE) { 414 750 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 415 751 "GnuTLS: Host '%s:%d' is missing a Certificate File!", 416 s->server_hostname, s-> port);417 exit(-1);752 s->server_hostname, s->addrs->host_port); 753 return HTTP_UNAUTHORIZED; 418 754 } 419 755 if (sc->enabled == GNUTLS_ENABLED_TRUE && 420 ( (sc->certs_x509_chain_num > 0 && sc->privkey_x509 == NULL) ||421 (sc->cert_crt_pgp[0] != NULL && sc->privkey_pgp == NULL))){756 (sc->certs_x509_chain_num > 0 && sc->privkey_x509 == NULL)) 757 { 422 758 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 423 759 "GnuTLS: Host '%s:%d' is missing a Private Key File!", 424 s->server_hostname, s->port); 425 exit(-1); 426 } 427 428 if (sc->enabled == GNUTLS_ENABLED_TRUE) { 429 rv = -1; 430 if (sc->certs_x509_chain_num > 0) { 431 rv = read_crt_cn(s, p, sc->certs_x509_crt_chain[0], &sc->cert_cn); 432 } 433 if (rv < 0 && sc->cert_pgp != NULL) { 434 rv = read_pgpcrt_cn(s, p, sc->cert_crt_pgp[0], &sc->cert_cn); 435 } 436 437 if (rv < 0) { 438 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 439 "GnuTLS: Cannot find a certificate for host '%s:%d'!", 440 s->server_hostname, s->port); 441 sc->cert_cn = NULL; 442 continue; 443 } 760 s->server_hostname, s->addrs->host_port); 761 return HTTP_UNAUTHORIZED; 444 762 } 445 763 446 764 if (sc->enabled == GNUTLS_ENABLED_TRUE 447 765 && sc->proxy_enabled == GNUTLS_ENABLED_TRUE 448 && load_proxy_x509_credentials( s) != APR_SUCCESS)766 && load_proxy_x509_credentials(pconf, ptemp, s) != APR_SUCCESS) 449 767 { 450 768 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 451 769 "%s: loading proxy credentials for host " 452 770 "'%s:%d' failed, exiting!", 453 __func__, s->server_hostname, s-> port);454 exit(-1);455 } 456 } 457 458 459 ap_add_version_component(p , "mod_gnutls/" MOD_GNUTLS_VERSION);771 __func__, s->server_hostname, s->addrs->host_port); 772 return HTTP_PROXY_AUTHENTICATION_REQUIRED; 773 } 774 } 775 776 777 ap_add_version_component(pconf, "mod_gnutls/" MOD_GNUTLS_VERSION); 460 778 461 779 { 462 780 const char* libvers = gnutls_check_version(NULL); 463 781 char* gnutls_version = NULL; 464 if(libvers && (gnutls_version = apr_psprintf(p , "GnuTLS/%s", libvers))) {465 ap_add_version_component(p , gnutls_version);782 if(libvers && (gnutls_version = apr_psprintf(pconf, "GnuTLS/%s", libvers))) { 783 ap_add_version_component(pconf, gnutls_version); 466 784 } else { 467 785 // In case we could not create the above string go for the static version instead 468 ap_add_version_component(p , "GnuTLS/" GNUTLS_VERSION "-static");786 ap_add_version_component(pconf, "GnuTLS/" GNUTLS_VERSION "-static"); 469 787 } 470 788 } … … 473 791 } 474 792 475 void mgs_hook_child_init(apr_pool_t * p, server_rec *s) { 793 void mgs_hook_child_init(apr_pool_t *p, server_rec *s) 794 { 476 795 apr_status_t rv = APR_SUCCESS; 477 mgs_srvconf_rec *sc = 478 (mgs_srvconf_rec *)ap_get_module_config(s->module_config, &gnutls_module);796 mgs_srvconf_rec *sc = (mgs_srvconf_rec *) 797 ap_get_module_config(s->module_config, &gnutls_module); 479 798 480 799 _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); 800 481 801 /* if we use PKCS #11 reinitialize it */ 482 483 802 if (mgs_pkcs11_reinit(s) < 0) { 484 803 ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, … … 487 806 } 488 807 489 if (sc->cache_type != mgs_cache_none) { 490 rv = mgs_cache_child_init(p, s, sc); 491 if (rv != APR_SUCCESS) { 808 if (sc->cache_enable == GNUTLS_ENABLED_TRUE) 809 { 810 rv = mgs_cache_child_init(p, s, sc->cache, MGS_CACHE_MUTEX_NAME); 811 if (rv != APR_SUCCESS) 492 812 ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s, 493 "GnuTLS: Failed to run Cache Init"); 494 } 495 } 813 "Child init for session cache failed!"); 814 } 815 816 if (sc->ocsp_cache != NULL) 817 { 818 rv = mgs_cache_child_init(p, s, sc->ocsp_cache, 819 MGS_OCSP_CACHE_MUTEX_NAME); 820 if (rv != APR_SUCCESS) 821 ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s, 822 "Child init for OCSP cache failed!"); 823 } 824 825 /* reinit OCSP request mutex */ 826 const char *lockfile = apr_global_mutex_lockfile(sc->ocsp_mutex); 827 rv = apr_global_mutex_child_init(&sc->ocsp_mutex, lockfile, p); 828 if (rv != APR_SUCCESS) 829 ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s, 830 "Failed to reinit mutex '" MGS_OCSP_MUTEX_NAME "'."); 831 496 832 /* Block SIGPIPE Signals */ 497 833 rv = apr_signal_block(SIGPIPE); … … 539 875 } 540 876 541 #define MAX_HOST_LEN 255 542 543 #if USING_2_1_RECENT 877 544 878 545 879 typedef struct { … … 554 888 * @param x vhost callback record 555 889 * @param s server record 890 * @param tsc mod_gnutls server data for `s` 891 * 556 892 * @return true if a match, false otherwise 557 893 * 558 894 */ 559 int check_server_aliases(vhost_cb_rec *x, server_rec * s, mgs_srvconf_rec *tsc) { 560 apr_array_header_t *names; 561 int rv = 0; 562 char ** name; 563 564 /* Check ServerName First! */ 565 if(apr_strnatcasecmp(x->sni_name, s->server_hostname) == 0) { 566 // We have a match, save this server configuration 567 x->sc = tsc; 568 rv = 1; 569 /* Check any ServerAlias directives */ 570 } else if(s->names->nelts) { 571 names = s->names; 572 name = (char **)names->elts; 573 for (int i = 0; i < names->nelts; ++i) 895 int check_server_aliases(vhost_cb_rec *x, server_rec * s, mgs_srvconf_rec *tsc) 896 { 897 apr_array_header_t *names; 898 int rv = 0; 899 char ** name; 900 901 /* Check ServerName First! */ 902 if (strcasecmp(x->sni_name, s->server_hostname) == 0) { 903 // We have a match, save this server configuration 904 x->sc = tsc; 905 rv = 1; 906 /* Check any ServerAlias directives */ 907 } else if(s->names->nelts) { 908 names = s->names; 909 name = (char **) names->elts; 910 for (int i = 0; i < names->nelts; ++i) 574 911 { 575 if (!name[i]) { continue; } 576 if (apr_strnatcasecmp(x->sni_name, name[i]) == 0) { 577 // We have a match, save this server configuration 578 x->sc = tsc; 579 rv = 1; 580 } 581 } 582 /* Wild any ServerAlias Directives */ 583 } else if(s->wild_names->nelts) { 584 names = s->wild_names; 585 name = (char **)names->elts; 586 for (int i = 0; i < names->nelts; ++i) 912 if (!name[i]) 913 continue; 914 if (strcasecmp(x->sni_name, name[i]) == 0) 915 { 916 // We have a match, save this server configuration 917 x->sc = tsc; 918 rv = 1; 919 } 920 } 921 /* ServerAlias directives may contain wildcards, check those last. */ 922 } else if(s->wild_names->nelts) { 923 names = s->wild_names; 924 name = (char **) names->elts; 925 for (int i = 0; i < names->nelts; ++i) 587 926 { 588 if (!name[i]) { continue; } 589 if(apr_fnmatch(name[i], x->sni_name , 590 APR_FNM_CASE_BLIND| 591 APR_FNM_PERIOD| 592 APR_FNM_PATHNAME| 593 APR_FNM_NOESCAPE) == APR_SUCCESS) { 594 x->sc = tsc; 595 rv = 1; 596 } 597 } 598 } 599 return rv; 600 } 601 602 static int vhost_cb(void *baton, conn_rec * conn __attribute__((unused)), server_rec * s) { 927 if (!name[i]) 928 continue; 929 if (ap_strcasecmp_match(x->sni_name, name[i]) == 0) 930 { 931 x->sc = tsc; 932 rv = 1; 933 } 934 } 935 } 936 return rv; 937 } 938 939 static int vhost_cb(void *baton, conn_rec *conn, server_rec * s) 940 { 603 941 mgs_srvconf_rec *tsc; 604 942 vhost_cb_rec *x = baton; … … 609 947 &gnutls_module); 610 948 611 if (tsc->enabled != GNUTLS_ENABLED_TRUE || tsc->cert_cn == NULL) {949 if (tsc->enabled != GNUTLS_ENABLED_TRUE) { 612 950 return 0; 613 951 } … … 618 956 ret = gnutls_x509_crt_check_hostname(tsc->certs_x509_crt_chain[0], s->server_hostname); 619 957 if (0 == ret) 620 ap_log_ error(APLOG_MARK, APLOG_DEBUG, 0, s,621 "GnuTLS: the certificate doesn't match requested hostname"622 "'%s'", s->server_hostname);958 ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, conn, 959 "GnuTLS: the certificate doesn't match requested " 960 "hostname '%s'", s->server_hostname); 623 961 } else { 624 ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, 625 "GnuTLS: SNI request for '%s' but no X.509 certs available at all", 626 s->server_hostname); 962 ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, conn, 963 "GnuTLS: SNI request for '%s' but no X.509 certs " 964 "available at all", 965 s->server_hostname); 627 966 } 628 967 return check_server_aliases(x, s, tsc); 629 968 } 630 #endif 631 632 mgs_srvconf_rec *mgs_find_sni_server(gnutls_session_t session) 969 970 /** 971 * Get SNI data from GnuTLS (if any) and search for a matching virtual 972 * host configuration. This method is called from the post client 973 * hello function. 974 * 975 * @param ctxt the mod_gnutls connection handle 976 * 977 * @return either the matching mod_gnutls server config, or `NULL` 978 */ 979 mgs_srvconf_rec *mgs_find_sni_server(mgs_handle_t *ctxt) 633 980 { 634 int rv; 635 unsigned int sni_type; 636 size_t data_len = MAX_HOST_LEN; 637 char sni_name[MAX_HOST_LEN]; 638 mgs_handle_t *ctxt; 639 #if USING_2_1_RECENT 640 vhost_cb_rec cbx; 641 #else 642 server_rec *s; 643 mgs_srvconf_rec *tsc; 644 #endif 645 646 if (session == NULL) 647 return NULL; 648 649 _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); 650 ctxt = gnutls_transport_get_ptr(session); 651 652 rv = gnutls_server_name_get(ctxt->session, sni_name, 653 &data_len, &sni_type, 0); 654 655 if (rv != 0) { 656 return NULL; 657 } 658 659 if (sni_type != GNUTLS_NAME_DNS) { 660 ap_log_error(APLOG_MARK, APLOG_CRIT, 0, 661 ctxt->c->base_server, 662 "GnuTLS: Unknown type '%d' for SNI: " 663 "'%s'", sni_type, sni_name); 664 return NULL; 665 } 666 667 /** 668 * Code in the Core already sets up the c->base_server as the base 669 * for this IP/Port combo. Trust that the core did the 'right' thing. 670 */ 671 #if USING_2_1_RECENT 672 cbx.ctxt = ctxt; 673 cbx.sc = NULL; 674 cbx.sni_name = sni_name; 675 676 rv = ap_vhost_iterate_given_conn(ctxt->c, vhost_cb, &cbx); 981 if (ctxt->sni_name == NULL) 982 { 983 const char *sni_name = mgs_server_name_get(ctxt); 984 if (sni_name != NULL) 985 ctxt->sni_name = sni_name; 986 else 987 return NULL; 988 } 989 990 ap_log_cerror(APLOG_MARK, APLOG_TRACE1, APR_SUCCESS, ctxt->c, 991 "%s: client requested server '%s'.", 992 __func__, ctxt->sni_name); 993 994 /* Search for vhosts matching connection parameters and the 995 * SNI. If a match is found, cbx.sc will contain the mod_gnutls 996 * server config for the vhost. */ 997 vhost_cb_rec cbx = { 998 .ctxt = ctxt, 999 .sc = NULL, 1000 .sni_name = ctxt->sni_name 1001 }; 1002 int rv = ap_vhost_iterate_given_conn(ctxt->c, vhost_cb, &cbx); 677 1003 if (rv == 1) { 678 1004 return cbx.sc; 679 1005 } 680 #else 681 for (s = ap_server_conf; s; s = s->next) { 682 683 tsc = (mgs_srvconf_rec *) ap_get_module_config(s->module_config, 684 &gnutls_module); 685 686 if (tsc->enabled != GNUTLS_ENABLED_TRUE) { continue; } 687 688 if(check_server_aliases(x, s, tsc)) { 689 return tsc; 690 } 691 } 1006 return NULL; 1007 } 1008 1009 1010 1011 #ifdef ENABLE_EARLY_SNI 1012 /** 1013 * Pre client hello hook function for GnuTLS that implements early SNI 1014 * processing using `gnutls_ext_raw_parse()` (available since GnuTLS