Changeset d2b32f1 in mod_gnutls
- Timestamp:
- Dec 17, 2016, 6:56:34 PM (5 years ago)
- Branches:
- debian/master, debian/stretch-backports
- Children:
- b9d5b2e
- Parents:
- baa4ed5 (diff), d8afa3e (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:
-
- 19 added
- 18 edited
Legend:
- Unmodified
- Added
- Removed
-
CHANGELOG
rbaa4ed5 rd2b32f1 1 **TODO: 2 - Handle Unclean Shutdowns 3 - make session cache use generic apache caches 1 ** Version 0.8.0 (2016-12-11) 2 - New: Support for OCSP stapling 3 - Bugfix: Access to DBM cache is locked using global mutex 4 "gnutls-cache" 5 - Bugfix: GnuTLSSessionTickets is now disabled by default as described 6 in the handbook 7 - Fixed memory leak while checking proxy backend certificate 8 - Fixed memory leaks in post_config 9 - Safely delete session ticket key (requires GnuTLS >= 3.4) 10 - Improved error handling in post_config hook 11 - Various handbook updates 12 - Internal API documentation can be generated using Doxygen 13 - Unused code has been removed (conditionals for GnuTLS 2.x and Apache 14 versions before 2.2, internal Lua bytecode structure last used in 15 2011). 16 - Test suite: Fixed locking for access to the PGP keyring of the test 17 certificate authority 18 - mod_gnutls can be built using Clang (unsupported) 4 19 5 20 ** Version 0.7.5 (2016-05-28) -
Makefile.am
rbaa4ed5 rd2b32f1 10 10 AM_DISTCHECK_CONFIGURE_FLAGS = "--enable-vpath-install" 11 11 DISTCLEANFILES = config.nice 12 MOSTLYCLEANFILES = $(DX_CLEANFILES) 12 13 13 14 SUBDIRS = src test doc 14 15 ACLOCAL_AMFLAGS = -I m4 16 17 @DX_RULES@ -
README
rbaa4ed5 rd2b32f1 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 <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
rbaa4ed5 rd2b32f1 1 1 dnl 2 AC_INIT(mod_gnutls, 0. 7.5)2 AC_INIT(mod_gnutls, 0.8.0) 3 3 OOO_CONFIG_NICE(config.nice) 4 4 MOD_GNUTLS_VERSION=AC_PACKAGE_VERSION … … 26 26 AC_CONFIG_MACRO_DIR([m4]) 27 27 28 AP_VERSION=2. 2.028 AP_VERSION=2.4.0 29 29 CHECK_APACHE(,$AP_VERSION, 30 30 :,:, … … 32 32 ) 33 33 34 PKG_CHECK_MODULES([LIBGNUTLS], [gnutls >= 3. 1.4])34 PKG_CHECK_MODULES([LIBGNUTLS], [gnutls >= 3.3.0]) 35 35 36 36 LIBGNUTLS_VERSION=`pkg-config --modversion gnutls` … … 91 91 AM_CONDITIONAL([DISABLE_FLOCK], 92 92 [test "$enable_flock" = "no" || test "$flock_works" = "no"]) 93 94 # openssl is needed as the responder for OCSP tests 95 AC_PATH_PROG([OPENSSL], [openssl], [no]) 96 # OCSP checks with gnutls-cli from GnuTLS versions before 3.3.23, 97 # 3.4.12, or 3.5.1 (on the respective 3.x branch) fail if intermediate 98 # CAs cannot be status checked, even if there are no intermediate CAs 99 # like in the mod_gnutls test suite where end entity certificates are 100 # directly issued by a root CA. 101 AC_MSG_CHECKING([for gnutls-cli version supporting OCSP for EE under root CA]) 102 AC_PREPROC_IFELSE( 103 [AC_LANG_SOURCE([[#include "gnutls/gnutls.h" 104 #if GNUTLS_VERSION_NUMBER < 0x030317 105 #error 106 #elif GNUTLS_VERSION_NUMBER >= 0x030400 && GNUTLS_VERSION_NUMBER < 0x03040c 107 #error 108 #elif GNUTLS_VERSION_NUMBER == 0x030500 109 #error 110 #endif 111 ]])], 112 [gnutls_ocsp_ok="yes"], 113 [gnutls_ocsp_ok="no"], 114 ) 115 AC_MSG_RESULT([$gnutls_ocsp_ok]) 116 AM_CONDITIONAL([ENABLE_OCSP_TEST], [test "${OPENSSL}" != "no" && test "${gnutls_ocsp_ok}" = "yes"]) 93 117 94 118 dnl Enable test namespaces? Default is "yes". … … 216 240 217 241 dnl Build list of "Listen" statements for Apache 218 LISTEN_LIST=" #Listen addresses for the test servers"242 LISTEN_LIST="@%:@ Listen addresses for the test servers" 219 243 for i in ${TEST_IP}; do 220 244 LISTEN_LIST="${LISTEN_LIST} 221 245 Listen ${i}:\${TEST_PORT}" 222 246 done 223 dnl HTTP ports, only active if TEST_HTTP_PORT is defined 247 # Available extra ports, tests can "Define" variables of the listed 248 # names in their apache.conf to enable them. 249 for j in TEST_HTTP_PORT OCSP_PORT; do 224 250 LISTEN_LIST="${LISTEN_LIST} 225 <IfDefine TEST_HTTP_PORT>"251 <IfDefine ${j}>" 226 252 for i in ${TEST_IP}; do 227 253 LISTEN_LIST="${LISTEN_LIST} 228 Listen ${i}:\${ TEST_HTTP_PORT}"254 Listen ${i}:\${${j}}" 229 255 done 230 256 LISTEN_LIST="${LISTEN_LIST} 231 257 </IfDefine>" 258 done 232 259 AC_SUBST(LISTEN_LIST) 233 260 AM_SUBST_NOTMAKE(LISTEN_LIST) 234 261 262 DX_DOXYGEN_FEATURE(ON) 263 DX_DOT_FEATURE(ON) 264 DX_HTML_FEATURE(ON) 265 DX_MAN_FEATURE(OFF) 266 DX_RTF_FEATURE(OFF) 267 DX_XML_FEATURE(OFF) 268 DX_PDF_FEATURE(ON) 269 DX_PS_FEATURE(OFF) 270 DX_INIT_DOXYGEN([mod_gnutls], [doc/doxygen.conf], [doc/api]) 271 235 272 AC_CONFIG_FILES([Makefile src/Makefile test/Makefile test/tests/Makefile \ 236 doc/Makefile include/mod_gnutls.h \273 doc/Makefile doc/doxygen.conf include/mod_gnutls.h \ 237 274 test/proxy_backend.conf \ 238 275 test/apache-conf/listen.conf \ -
doc/mod_gnutls_manual.mdwn
rbaa4ed5 rd2b32f1 53 53 ======================== 54 54 55 `GnuTLSEnable` 56 -------------- 55 General Options 56 --------------- 57 58 ### GnuTLSEnable 57 59 58 60 Enable GnuTLS for this virtual host … … 65 67 This directive enables SSL/TLS Encryption for a Virtual Host. 66 68 67 `GnuTLSCache` 68 ------------- 69 70 Configure SSL Session Cache 69 ### GnuTLSCache 70 71 Configure TLS Session Cache 71 72 72 73 GnuTLSCache [dbm|gdbm|memcache|none] [PATH|SERVERLIST|-] … … 75 76 Context: server config 76 77 77 This directive configures the SSL Session Cache for `mod_gnutls`. 78 This could be shared between machines of different architectures. 78 This directive configures the TLS Session Cache for `mod_gnutls`. 79 This could be shared between machines of different architectures. If a 80 DBM cache is used, access is serialized using the `gnutls-cache` 81 mutex. Which DBM types are available is part of the APR (Apache 82 Portable Runtime) compile time configuration. 79 83 80 84 `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. 85 : Uses the Berkeley DB backend of APR DBM to cache TLS Session 86 data. 87 88 The argument is a relative or absolute path to be used as 89 the DBM Cache file. This is compatible with most operating 90 systems. 91 92 `gdbm` (Requires GDBM) 93 : Uses the GDBM backend of APR DBM to cache TLS Session data. 94 95 The argument is a relative or absolute path to be used as the DBM 96 Cache file. 92 97 93 98 `memcache` 94 : Uses a memcached server to cache the SSL Session.99 : Uses memcached server(s) to cache TLS Session data. 95 100 96 101 The argument is a space separated list of servers. If no port … … 99 104 100 105 `none` 101 : Turns off all caching of SSLSessions.106 : Turns off all caching of TLS Sessions. 102 107 103 108 This can significantly reduce the performance of `mod_gnutls` since … … 106 111 requires no configuration. 107 112 108 `GnuTLSCacheTimeout` 109 -------------------- 110 111 Timeout for SSL Session Cache expiration 113 ### GnuTLSCacheTimeout 114 115 Timeout for TLS Session Cache expiration 112 116 113 117 GnuTLSCacheTimeout SECONDS … … 116 120 Context: server config 117 121 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 ---------------------- 122 Sets the timeout for TLS Session Cache entries expiration. This value 123 is also used for OCSP responses if they do not contain a `nextUpdate` 124 time. 125 126 ### GnuTLSSessionTickets 124 127 125 128 Enable Session Tickets for the server … … 130 133 Context: server config, virtual host 131 134 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\ 135 To avoid storing data for TLS session resumption the server can 136 provide clients with tickets, to use on return. Tickets are an 137 alternative to using a session cache, mostly used for busy servers 138 with limited storage. For a pool of servers this option is not 139 recommended since the tickets are bound to the issuing server only. 140 141 If this option is set in the global configuration, virtual hosts 142 without a `GnuTLSSessionTickets` setting will use the global setting. 143 144 *Warning:* Currently the master key that protects the tickets is 145 generated only on server start, and there is no mechanism to roll over 146 the key. If session tickets are enabled it is highly recommened to 147 restart the server regularly to protect past sessions in case an 148 attacker gains access to server memory. 149 150 ### GnuTLSClientVerify 151 152 Enable Client Certificate Verification 213 153 214 154 GnuTLSClientVerify [ignore|request|require] … … 217 157 Context: server config, virtual host, directory, .htaccess 218 158 219 This directive controls the use of SSLClient Certificate159 This directive controls the use of TLS Client Certificate 220 160 Authentication. If used in the .htaccess context, it can force TLS 221 161 re-negotiation. 222 162 223 163 `ignore` 224 : `mod_gnutls` will ignore the contents of any SSLClient Certificates164 : `mod_gnutls` will ignore the contents of any TLS Client Certificates 225 165 sent. It will not request that the client sends a certificate. 226 166 … … 236 176 environment variable will only be set to `SUCCESS`. 237 177 238 `GnuTLSClientCAFile` 239 -------------------- 240 241 Set to the PEM Encoded Certificate Authority Certificate 242 243 GnuTLSClientCAFile FILEPATH 244 245 Default: *none* 246 Context: server config, virtual host 247 248 Takes an absolute or relative path to a PEM Encoded Certificate to use 249 as a Certificate Authority with Client Certificate Authentication. 250 This file may contain a list of trusted authorities. 251 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 -------------- 178 ### GnuTLSDHFile 268 179 269 180 Set to the PKCS \#3 encoded Diffie Hellman parameters … … 279 190 2048`. If not set `mod_gnutls` will use the included parameters. 280 191 281 `GnuTLSSRPPasswdFile` 282 --------------------- 283 284 Set to the SRP password file for SRP ciphersuites 285 286 GnuTLSSRPPasswdFile FILEPATH 287 288 Default: *none*\ 289 Context: server config, virtual host 290 291 Takes an absolute or relative path to an SRP password file. This is 292 the same format as used in libsrp. You can generate such file using 293 the command `srptool --passwd /etc/tpasswd --passwd-conf 294 /etc/tpasswd.conf -u test` to set a password for user test. This 295 password file holds the username, a password verifier and the 296 dependency to the SRP parameters. 297 298 `GnuTLSSRPPasswdConfFile` 299 ------------------------- 300 301 Set to the SRP password.conf file for SRP ciphersuites 302 303 GnuTLSSRPPasswdConfFile FILEPATH 304 305 Default: *none*\ 306 Context: server config, virtual host 307 308 Takes an absolute or relative path to an SRP password.conf file. This 309 is the same format as used in `libsrp`. You can generate such file 310 using the command `srptool --create-conf /etc/tpasswd.conf`. This 311 file holds the SRP parameters and is associate with the password file 312 (the verifiers depends on these parameters). 313 314 `GnuTLSPriorities` 315 ------------------ 316 317 Set the allowed ciphers, key exchange algorithms, MACs and compression 318 methods 192 ### GnuTLSPriorities 193 194 Set the allowed protocol versions, ciphers, key exchange algorithms, 195 MACs and compression methods 319 196 320 197 GnuTLSPriorities NORMAL:+CIPHER_0:+CIPHER_1:...:+CIPHER_N … … 323 200 Context: server config, virtual host 324 201 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. 202 Takes a colon separated list of protocol version, ciphers, key 203 exchange methods message authentication codes, and compression methods 204 to enable. The allowed keywords are specified in the 205 `gnutls_priority_init()` function of GnuTLS. 206 207 Please refer to [the GnuTLS documentation](https://gnutls.org/manual/html_node/Priority-Strings.html#Priority-Strings) 208 for details. A few commonly used sets are listed below, note that 209 their exact meaning may change with GnuTLS versions. 339 210 340 211 `PERFORMANCE` 341 : A list with all the secure cipher combinations sorted in terms of performance. 212 : A list with all the secure cipher combinations sorted in terms of 213 performance. 342 214 343 215 `NORMAL` … … 345 217 with respect to security margin (subjective term). 346 218 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`). 219 `SECURE128` 220 : A list with all the secure cipher suites that offer a security level 221 of 128-bit or more. 222 223 `PFS` 224 : Only cipher suites offering perfect forward secrecy (ECDHE and DHE), 225 sorted by security margin. 226 227 You can add or remove algorithms using the `+` and `!` prefixes 228 respectively. For example, in order to use the `NORMAL` set but 229 disable TLS 1.0 and 1.1 you can use the string 230 `NORMAL:!VERS-TLS1.0:!VERS-TLS1.1`. 370 231 371 232 You can find a list of all supported Ciphers, Versions, MACs, etc. by 372 233 running `gnutls-cli --list`. 373 234 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 ------------------ 235 ### GnuTLSP11Module 380 236 381 237 Load this PKCS #11 module. … … 389 245 defaults. May occur multiple times to load multiple modules. 390 246 391 `GnuTLSPIN` 392 ------------------ 247 ### GnuTLSPIN 393 248 394 249 Set the PIN to be used to access encrypted key files or PKCS #11 objects. … … 403 258 or openssl encrypted keys. 404 259 405 `GnuTLSSRKPIN` 406 ------------------ 407 408 Set the SRK PIN to be used to unlaccess the TPM. 260 ### GnuTLSSRKPIN 261 262 Set the SRK PIN to be used to access the TPM. 409 263 410 264 GnuTLSSRKPIN XXXXXX … … 416 270 the TPM module. 417 271 418 `GnuTLSExportCertificates` 419 -------------------------- 272 ### GnuTLSExportCertificates 420 273 421 274 Export the PEM encoded certificates to CGIs … … 444 297 environment variables to the CGI process as `mod_ssl`. 445 298 446 447 `GnuTLSProxyEngine` 448 -------------- 299 X.509 Certificate Authentication 300 -------------------------------- 301 302 ### GnuTLSCertificateFile 303 304 Set to the PEM Encoded Server Certificate 305 306 GnuTLSCertificateFile FILEPATH 307 308 Default: *none*\ 309 Context: server config, virtual host 310 311 Takes an absolute or relative path to a PEM-encoded X.509 certificate to 312 use as this Server's End Entity (EE) certificate. If you need to supply 313 certificates for intermediate Certificate Authorities (iCAs), they 314 should be listed in sequence in the file, from EE to the iCA closest to 315 the root CA. Optionally, you can also include the root CA's certificate 316 as the last certificate in the list. 317 318 Since version 0.7 this can be a PKCS #11 URL. 319 320 ### GnuTLSKeyFile 321 322 Set to the PEM Encoded Server Private Key 323 324 GnuTLSKeyFile FILEPATH 325 326 Default: *none*\ 327 Context: server config, virtual host 328 329 Takes an absolute or relative path to the Server Private Key. Set 330 `GnuTLSPIN` if the key file is encrypted. 331 332 Since version 0.7 this can be a PKCS #11 URL. 333 334 **Security Warning:**\ 335 This private key must be protected. It is read while Apache is still 336 running as root, and does not need to be readable by the nobody or 337 apache user. 338 339 ### GnuTLSClientCAFile 340 341 Set the PEM encoded Certificate Authority list to use for X.509 base 342 client authentication 343 344 GnuTLSClientCAFile FILEPATH 345 346 Default: *none* 347 Context: server config, virtual host 348 349 Takes an absolute or relative path to a PEM Encoded Certificate to use 350 as a Certificate Authority with Client Certificate Authentication. 351 This file may contain a list of trusted authorities. 352 353 OpenPGP Certificate Authentication 354 ---------------------------------- 355 356 ### GnuTLSPGPCertificateFile 357 358 Set to a base64 Encoded Server OpenPGP Certificate 359 360 GnuTLSPGPCertificateFile FILEPATH 361 362 Default: *none*\ 363 Context: server config, virtual host 364 365 Takes an absolute or relative path to a base64 Encoded OpenPGP 366 Certificate to use as this Server's Certificate. 367 368 ### GnuTLSPGPKeyFile 369 370 Set to the Server OpenPGP Secret Key 371 372 GnuTLSPGPKeyFile FILEPATH 373 374 Default: *none*\ 375 Context: server config, virtual host 376 377 Takes an absolute or relative path to the Server Private Key. This key 378 cannot currently be password protected. 379 380 **Security Warning:**\ 381 This private key must be protected. It is read while Apache is still 382 running as root, and does not need to be readable by the nobody or 383 apache user. 384 385 ### GnuTLSPGPKeyringFile 386 387 Set to a base64 Encoded key ring 388 389 GnuTLSPGPKeyringFile FILEPATH 390 391 Default: *none*\ 392 Context: server config, virtual host 393 394 Takes an absolute or relative path to a base64 Encoded Certificate 395 list (key ring) to use as a means of verification of Client 396 Certificates. This file should contain a list of trusted signers. 397 398 SRP Authentication 399 ------------------ 400 401 ### GnuTLSSRPPasswdFile 402 403 Set to the SRP password file for SRP ciphersuites 404 405 GnuTLSSRPPasswdFile FILEPATH 406 407 Default: *none*\ 408 Context: server config, virtual host 409 410 Takes an absolute or relative path to an SRP password file. This is 411 the same format as used in libsrp. You can generate such file using 412 the command `srptool --passwd /etc/tpasswd --passwd-conf 413 /etc/tpasswd.conf -u test` to set a password for user test. This 414 password file holds the username, a password verifier and the 415 dependency to the SRP parameters. 416 417 ### GnuTLSSRPPasswdConfFile 418 419 Set to the SRP password.conf file for SRP ciphersuites 420 421 GnuTLSSRPPasswdConfFile FILEPATH 422 423 Default: *none*\ 424 Context: server config, virtual host 425 426 Takes an absolute or relative path to an SRP password.conf file. This 427 is the same format as used in `libsrp`. You can generate such file 428 using the command `srptool --create-conf /etc/tpasswd.conf`. This 429 file holds the SRP parameters and is associate with the password file 430 (the verifiers depends on these parameters). 431 432 TLS Proxy Configuration 433 ----------------------- 434 435 ### GnuTLSProxyEngine 449 436 450 437 Enable TLS proxy connections for this virtual host … … 458 445 host. 459 446 460 `GnuTLSProxyCAFile` 461 -------------------- 447 ### GnuTLSProxyCAFile 462 448 463 449 Set to the PEM encoded Certificate Authority Certificate … … 474 460 always fail due to lack of a trusted CA. 475 461 476 `GnuTLSProxyCRLFile` 477 -------------------- 462 ### GnuTLSProxyCRLFile 478 463 479 464 Set to the PEM encoded Certificate Revocation List … … 488 473 back end servers. The file may contain a list of CRLs. 489 474 490 `GnuTLSProxyCertificateFile` 491 ----------------------- 475 ### GnuTLSProxyCertificateFile 492 476 493 477 Set to the PEM encoded Client Certificate … … 510 494 provide the matching private key. 511 495 512 `GnuTLSProxyKeyFile` 513 --------------- 496 ### GnuTLSProxyKeyFile 514 497 515 498 Set to the PEM encoded Private Key … … 529 512 apache user. 530 513 531 `GnuTLSProxyPriorities` 532 ------------------ 514 ### GnuTLSProxyPriorities 533 515 534 516 Set the allowed ciphers, key exchange algorithms, MACs and compression … … 545 527 `GnuTLSProxyEngine` is `On`. 546 528 529 OCSP Stapling Configuration 530 --------------------------- 531 532 ### GnuTLSOCSPStapling 533 534 Enable OCSP stapling for this (virtual) host. 535 536 GnuTLSOCSPStapling [On|Off] 537 538 Default: *off*\ 539 Context: server config, virtual host 540 541 OCSP stapling, formally known as the TLS Certificate Status Request 542 extension, allows the server to provide the client with an OCSP 543 response for its certificate during the handshake. This way the client 544 does not have to send an OCSP request to the CA to check the 545 certificate status, which offers privacy and performance advantages. 546 547 Using OCSP stapling has a few requirements: 548 549 * Caching OCSP responses requires a cache, so `GnuTLSCache` must not 550 be `none`. 551 * `GnuTLSCertificateFile` must contain the issuer CA certificate in 552 addition to the server certificate so responses can be verified. 553 * The certificate must either contain an OCSP access URI using HTTP, 554 or `GnuTLSOCSPResponseFile` must be set. 555 556 OCSP cache updates are serialized using the `gnutls-ocsp` mutex. 557 558 ### GnuTLSOCSPCheckNonce 559 560 Check the nonce in OCSP responses? 561 562 GnuTLSOCSPCheckNonce [On|Off] 563 564 Default: *on*\ 565 Context: server config, virtual host 566 567 Some CAs refuse to send nonces in their OCSP responses, probably 568 because that way they can cache responses. If your CA is one of them 569 you can use this flag to disable nonce verification. Note that 570 `mod_gnutls` will _send_ a nonce either way. 571 572 ### GnuTLSOCSPResponseFile 573 574 Read the OCSP response for stapling from this file instead of sending 575 a request over HTTP. 576 577 GnuTLSOCSPResponseFile /path/to/response.der 578 579 Default: *empty*\ 580 Context: server config, virtual host 581 582 The response file must be updated externally, for example using a cron 583 job. This option is an alternative to the server fetching OCSP 584 responses over HTTP. Reasons to use this option include: 585 586 * Performing OCSP requests separate from the web server, to prevent slow 587 responses from stalling handshakes. 588 * The issuer CA uses an access method other than HTTP. 589 * Testing 590 591 You can use a GnuTLS `ocsptool` command like the following to create 592 and update the response file: 593 594 ocsptool --ask --nonce --load-issuer ca_cert.pem \ 595 --load-cert server_cert.pem --outfile ocsp_response.der 596 597 Additional error checking is highly recommended. You may have to 598 remove the `--nonce` option if the OCSP responder of your CA does not 599 support nonces. 600 601 ### GnuTLSOCSPCacheTimeout 602 603 Cache timeout for OCSP responses 604 605 GnuTLSOCSPCacheTimeout SECONDS 606 607 Default: *3600*\ 608 Context: server config, virtual host 609 610 Cached OCSP responses will be refreshed after the configured number of 611 seconds. How long this timeout should reasonably be depends on your 612 CA, namely how often its OCSP responder is updated and how long 613 responses are valid. Note that a response will not be cached beyond 614 its lifetime as denoted in the `nextUpdate` field of the response. 615 616 ### GnuTLSOCSPFailureTimeout 617 618 Wait this many seconds before retrying a failed OCSP request. 619 620 GnuTLSOCSPFailureTimeout SECONDS 621 622 Default: *300*\ 623 Context: server config, virtual host 624 625 Retries of failed OCSP requests must be rate limited to avoid 626 overloading both the server using mod_gnutls and the CA's OCSP 627 responder. A shorter value increases the load on both sides, a longer 628 one means that stapling will remain disabled for longer after a failed 629 request. 630 631 ### GnuTLSOCSPSocketTimeout 632 633 Timeout for TCP sockets used to send OCSP requests 634 635 GnuTLSOCSPFailureTimeout SECONDS 636 637 Default: *6*\ 638 Context: server config, virtual host 639 640 Stalled OCSP requests must time out after a while to prevent stalling 641 the server too much. However, if the timeout is too short requests may 642 fail with a slow OCSP responder or high latency network 643 connection. This parameter allows you to adjust the timeout if 644 necessary. 645 646 Note that this is not an upper limit for the completion of an OCSP 647 request but a socket timeout. The connection will time out if there is 648 no activity (successful send or receive) at all for the configured 649 time. 650 547 651 * * * * * 548 652 … … 550 654 ====================== 551 655 552 Simple Standard SSLExample656 Simple Standard TLS Example 553 657 --------------------------- 554 658 555 The following is an example of s tandard SSL Hosting, using one IP556 Addresses for each virtual host 659 The following is an example of simple TLS hosting, using one IP 660 Addresses for each virtual host. 557 661 558 662 # Load the module into Apache. … … 560 664 GnuTLSCache gdbm /var/cache/www-tls-cache 561 665 GnuTLSCacheTimeout 500 562 # With normal SSL Websites, you need one IP Address per-site. 563 Listen 1.2.3.1:443 564 Listen 1.2.3.2:443 565 Listen 1.2.3.3:443 566 Listen 1.2.3.4:443 567 <VirtualHost 1.2.3.1:443> 568 GnuTLSEnable on 569 GnuTLSPriorities NONE:+AES-128-CBC:+3DES-CBC:+ARCFOUR-128:+RSA:+DHE-RSA:+DHE-DSS:+SHA1:+MD5:+COMP-NULL 570 DocumentRoot /www/site1.example.com/html 571 ServerName site1.example.com:443 572 GnuTLSCertificateFile conf/ssl/site1.crt 573 GnuTLSKeyFile conf/ss/site1.key 666 667 # Without SNI you need one IP Address per-site. 668 Listen 192.0.2.1:443 669 Listen 192.0.2.2:443 670 Listen 192.0.2.3:443 671 Listen 192.0.2.4:443 672 673 <VirtualHost 192.0.2.1:443> 674 GnuTLSEnable on 675 GnuTLSPriorities SECURE128 676 DocumentRoot /www/site1.example.com/html 677 ServerName site1.example.com:443 678 GnuTLSCertificateFile conf/tls/site1.crt 679 GnuTLSKeyFile conf/tls/site1.key 574 680 </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 681 682 <VirtualHost 192.0.2.2:443> 683 # This virtual host enables SRP authentication 684 GnuTLSEnable on 685 GnuTLSPriorities NORMAL:+SRP 686 DocumentRoot /www/site2.example.com/html 687 ServerName site2.example.com:443 688 GnuTLSSRPPasswdFile conf/tls/tpasswd.site2 689 GnuTLSSRPPasswdConfFile conf/tls/tpasswd.site2.conf 583 690 </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 691 692 <VirtualHost 192.0.2.3:443> 693 # This server enables SRP, OpenPGP and X.509 authentication. 694 GnuTLSEnable on 695 GnuTLSPriorities NORMAL:+SRP:+SRP-RSA:+SRP-DSS:+CTYPE-OPENPGP 696 DocumentRoot /www/site3.example.com/html 697 ServerName site3.example.com:443 698 GnuTLSCertificateFile conf/tls/site3.crt 699 GnuTLSKeyFile conf/tls/site3.key 700 GnuTLSClientVerify ignore 701 GnuTLSPGPCertificateFile conf/tls/site3.pub.asc 702 GnuTLSPGPKeyFile conf/tls/site3.sec.asc 703 GnuTLSSRPPasswdFile conf/tls/tpasswd.site3 704 GnuTLSSRPPasswdConfFile conf/tls/tpasswd.site3.conf 597 705 </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 706 707 <VirtualHost 192.0.2.4:443> 708 GnuTLSEnable on 709 # %COMPAT disables some security features to enable maximum 710 # compatibility with clients. Don't use this if you need strong 711 # security. 712 GnuTLSPriorities NORMAL:%COMPAT 713 DocumentRoot /www/site4.example.com/html 714 ServerName site4.example.com:443 715 GnuTLSCertificateFile conf/tls/site4.crt 716 GnuTLSKeyFile conf/tls/site4.key 606 717 </VirtualHost> 607 718 … … 609 720 ------------------------------ 610 721 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 722 `mod_gnutls` supports "Server Name Indication", as specified in 723 RFC 3546. This allows hosting many TLS websites with a single IP 724 address. All recent browsers support this standard. Here is an 725 example using SNI: 616 726 617 727 # Load the module into Apache. 618 728 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 729 730 # SNI allows hosting multiple sites using one IP address. This 731 # could also be 'Listen *:443', just like '*:80' is common for 732 # non-HTTPS 733 Listen 198.51.100.1:443 734 735 <VirtualHost _default_:443> 736 GnuTLSEnable on 737 GnuTLSSessionTickets on 738 GnuTLSPriorities NORMAL 739 DocumentRoot /www/site1.example.com/html 740 ServerName site1.example.com:443 741 GnuTLSCertificateFile conf/tls/site1.crt 742 GnuTLSKeyFile conf/tls/site1.key 638 743 </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 744 745 <VirtualHost _default_:443> 746 GnuTLSEnable on 747 GnuTLSPriorities NORMAL 748 DocumentRoot /www/site2.example.com/html 749 ServerName site2.example.com:443 750 GnuTLSCertificateFile conf/tls/site2.crt 751 GnuTLSKeyFile conf/tls/site2.key 646 752 </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 753 754 <VirtualHost _default_:443> 755 GnuTLSEnable on 756 GnuTLSPriorities NORMAL 757 DocumentRoot /www/site3.example.com/html 758 ServerName site3.example.com:443 759 GnuTLSCertificateFile conf/tls/site3.crt 760 GnuTLSKeyFile conf/tls/site3.key 654 761 </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 762 763 <VirtualHost _default_:443> 764 GnuTLSEnable on 765 GnuTLSPriorities NORMAL 766 DocumentRoot /www/site4.example.com/html 767 ServerName site4.example.com:443 768 GnuTLSCertificateFile conf/tls/site4.crt 769 GnuTLSKeyFile conf/tls/site4.key 662 770 </VirtualHost> 663 771 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 772 OCSP Stapling Example 773 --------------------- 774 775 This example uses an X.509 server certificate. The server will fetch 776 OCSP responses from the responder listed in the certificate and store 777 them im a memcached cache shared with another server. 674 778 675 779 # Load the module into Apache. 676 780 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" 781 GnuTLSCache memcache "192.0.2.1:11211 192.0.2.2:11211" 679 782 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 783 784 Listen 192.0.2.1:443 785 786 <VirtualHost _default_:443> 787 GnuTLSEnable On 788 GnuTLSPriorities NORMAL 789 DocumentRoot /www/site1.example.com/html 790 ServerName site1.example.com:443 791 GnuTLSCertificateFile conf/tls/site1.crt 792 GnuTLSKeyFile conf/tls/site1.key 793 GnuTLSPriorities NORMAL 794 GnuTLSOCSPStapling On 705 795 </VirtualHost> 706 796 -
include/mod_gnutls.h.in
rbaa4ed5 rd2b32f1 1 /* *1 /* 2 2 * Copyright 2004-2005 Paul Querna 3 3 * Copyright 2014 Nikos Mavrogiannopoulos 4 * Copyright 2015 Thomas Klute4 * Copyright 2015-2016 Thomas 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 … … 33 32 /* GnuTLS Library Headers */ 34 33 #include <gnutls/gnutls.h> 35 #if GNUTLS_VERSION_MAJOR == 236 #include <gnutls/extra.h>37 #endif38 34 #include <gnutls/abstract.h> 39 35 #include <gnutls/openpgp.h> … … 59 55 /* Module Debug Mode */ 60 56 #define MOD_GNUTLS_DEBUG @OOO_MAINTAIN@ 61 62 /*63 * Recent Versions of 2.1 renamed several hooks.64 * This allows us to compile on 2.0.xx65 */66 #if AP_SERVER_MINORVERSION_NUMBER >= 2 || (AP_SERVER_MINORVERSION_NUMBER == 1 && AP_SERVER_PATCHLEVEL_NUMBER >= 3)67 #define USING_2_1_RECENT 168 #else69 #define USING_2_1_RECENT 070 #endif71 57 72 58 /* mod_gnutls Cache Types */ … … 85 71 } mgs_cache_e; 86 72 73 /* Internal cache data, defined in gnutls_cache.h */ 74 typedef struct mgs_cache* mgs_cache_t; 75 87 76 typedef enum { 88 77 mgs_cvm_unset, … … 95 84 typedef struct { 96 85 int client_verify_mode; 97 const char* lua_bytecode;98 apr_size_t lua_bytecode_len;99 86 } mgs_dirconf_rec; 87 88 89 /* Internal per-vhost config for OCSP, defined in gnutls_ocsp.h */ 90 typedef struct mgs_ocsp_data* mgs_ocsp_data_t; 100 91 101 92 … … 146 137 mgs_cache_e cache_type; 147 138 const char* cache_config; 139 /* Internal cache data */ 140 mgs_cache_t cache; 148 141 149 142 /* GnuTLS uses Session Tickets */ … … 216 209 /* Last Cache timestamp */ 217 210 apr_time_t last_cache_check; 211 212 /* Enable OCSP stapling */ 213 unsigned char ocsp_staple; 214 /* Check nonce in OCSP responses? */ 215 unsigned char ocsp_check_nonce; 216 /* Read OCSP response for stapling from this file instead of 217 * sending a request over HTTP */ 218 char *ocsp_response_file; 219 /* Internal OCSP data for this server */ 220 mgs_ocsp_data_t ocsp; 221 /* Mutex to prevent parallel OCSP requests */ 222 apr_global_mutex_t *ocsp_mutex; 223 /* Cache timeout for OCSP responses. Note that the nextUpdate 224 * field of the response takes precedence if shorter. */ 225 apr_interval_time_t ocsp_cache_time; 226 /* If an OCSP request fails wait this long before trying again. */ 227 apr_interval_time_t ocsp_failure_timeout; 228 /* Socket timeout for OCSP requests */ 229 apr_interval_time_t ocsp_socket_timeout; 218 230 } mgs_srvconf_rec; 219 231 … … 347 359 348 360 /** 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 361 * Perform any reinitialization required in PKCS #11 368 362 */ 369 363 int mgs_pkcs11_reinit(server_rec * s); 370 364 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 365 389 366 … … 391 368 392 369 /* Loads all files set in the configuration */ 393 int mgs_load_files(apr_pool_t * p, server_rec * s); 370 int mgs_load_files(apr_pool_t *pconf, apr_pool_t *ptemp, server_rec *s) 371 __attribute__((nonnull)); 394 372 395 373 const char *mgs_set_srp_tpasswd_conf_file(cmd_parms * parms, void *dummy, … … 414 392 const char *type, const char* arg); 415 393 416 const char *mgs_set_cache_timeout(cmd_parms * parms, void *dummy, 417 const char *arg); 394 const char *mgs_set_timeout(cmd_parms *parms, void *dummy, const char *arg); 418 395 419 396 const char *mgs_set_client_verify(cmd_parms * parms, void *dummy, … … 470 447 apr_pool_t * plog, apr_pool_t * ptemp); 471 448 472 int mgs_hook_post_config(apr_pool_t * p, apr_pool_t * plog, 473 apr_pool_t * ptemp, 474 server_rec * base_server); 449 int mgs_hook_post_config(apr_pool_t *pconf, 450 apr_pool_t *plog, 451 apr_pool_t *ptemp, 452 server_rec *base_server); 475 453 476 454 void mgs_hook_child_init(apr_pool_t *p, server_rec *s); -
src/Makefile.am
rbaa4ed5 rd2b32f1 6 6 endif 7 7 8 mod_gnutls_la_SOURCES = mod_gnutls.c gnutls_io.c gnutls_cache.c gnutls_config.c gnutls_hooks.c 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_util.c 9 10 mod_gnutls_la_CFLAGS = -Wall ${MODULE_CFLAGS} 10 11 mod_gnutls_la_LDFLAGS = -module -avoid-version ${MODULE_LIBS} 12 noinst_HEADERS = gnutls_cache.h gnutls_config.h gnutls_ocsp.h gnutls_util.h 11 13 12 14 apmodpkglib_LTLIBRARIES = mod_gnutls.la -
src/gnutls_cache.c
rbaa4ed5 rd2b32f1 1 /* *1 /* 2 2 * Copyright 2004-2005 Paul Querna 3 3 * Copyright 2008 Nikos Mavrogiannopoulos 4 4 * Copyright 2011 Dash Shendy 5 * Copyright 2015 Thomas Klute5 * Copyright 2015-2016 Thomas 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 /** 21 * @file gnutls_cache.c 22 * 23 * The signatures of the `(dbm|mc)_cache_...()` functions may be a bit 24 * confusing: "store" and "expire" take a server_rec, "fetch" an 25 * mgs_handle_t, and "delete" the `void*` required for a 26 * `gnutls_db_remove_func`. The first two have matching `..._session` 27 * functions to fit their respective GnuTLS session cache signatures. 28 * 29 * This is because "store", "expire" (dbm only), and "fetch" are also 30 * needed for the OCSP cache. Their `..._session` variants have been 31 * created to take care of the session cache specific parts, mainly 32 * calculating the DB key from the session ID. They have to match the 33 * appropriate GnuTLS DB function signatures. 34 * 35 * Additionally, there are the `mc_cache_(store|fetch)_generic()` 36 * functions. They exist because memcached requires string keys while 37 * DBM accepts binary keys, and provide wrappers to turn binary keys 38 * into hex strings with a `mod_gnutls:` prefix. 39 * 40 * To update cached OCSP responses independent of client connections, 41 * "store" and "expire" have to work without a connection context. On 42 * the other hand "fetch" does not need to do that, because cached 43 * OCSP responses will be retrieved for use in client connections. 44 */ 45 46 #include "gnutls_cache.h" 21 47 #include "mod_gnutls.h" 48 #include "gnutls_config.h" 22 49 23 50 #if HAVE_APR_MEMCACHE … … 26 53 27 54 #include "apr_dbm.h" 55 #include <apr_escape.h> 28 56 29 57 #include "ap_mpm.h" 58 #include <util_mutex.h> 30 59 31 60 #include <unistd.h> … … 36 65 #endif 37 66 38 /* it seems the default has some strange errors. Use SDBM 39 */ 67 /** Default session cache timeout */ 68 #define MGS_DEFAULT_CACHE_TIMEOUT 300 69 70 /** Prefix for keys used with a memcached cache */ 40 71 #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) 72 /** Maximum length of the hex string representation of a GnuTLS 73 * session ID: two characters per byte, plus one more for `\0` */ 74 #if GNUTLS_VERSION_NUMBER >= 0x030400 75 #define GNUTLS_SESSION_ID_STRING_LEN ((GNUTLS_MAX_SESSION_ID_SIZE * 2) + 1) 76 #else 77 #define GNUTLS_SESSION_ID_STRING_LEN ((GNUTLS_MAX_SESSION_ID * 2) + 1) 78 #endif 43 79 44 80 #if MODULE_MAGIC_NUMBER_MAJOR < 20081201 … … 50 86 #endif 51 87 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 88 /** 89 * Turn a GnuTLS session ID into the key format we use with DBM 90 * caches. Name the Session ID as `server:port.SessionID` to disallow 91 * resuming sessions on different servers. 92 * 93 * @return `0` on success, `-1` on failure 69 94 */ 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) 77 return -1; 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 95 static int mgs_session_id2dbm(conn_rec *c, unsigned char *id, int idlen, 96 gnutls_datum_t *dbmkey) 97 { 98 char sz[GNUTLS_SESSION_ID_STRING_LEN]; 99 apr_status_t rv = apr_escape_hex(sz, id, idlen, 0, NULL); 100 if (rv != APR_SUCCESS) 101 return -1; 102 103 char *newkey = apr_psprintf(c->pool, "%s:%d.%s", 104 c->base_server->server_hostname, 105 c->base_server->port, sz); 106 dbmkey->size = strlen(newkey); 107 /* signedness does not matter for arbitrary bits */ 108 dbmkey->data = (unsigned char*) newkey; 85 109 return 0; 86 110 } 87 111 88 #define CTIME "%b %d %k:%M:%S %Y %Z" 89 90 char *mgs_time2sz(time_t in_time, char *str, int strsize) { 112 /** The OPENSSL_TIME_FORMAT macro and mgs_time2sz() serve to print 113 * time in a format compatible with OpenSSL's `ASN1_TIME_print()` 114 * function. */ 115 #define OPENSSL_TIME_FORMAT "%b %d %k:%M:%S %Y %Z" 116 117 char *mgs_time2sz(time_t in_time, char *str, int strsize) 118 { 91 119 apr_time_exp_t vtm; 92 120 apr_size_t ret_size; … … 96 124 apr_time_ansi_put(&t, in_time); 97 125 apr_time_exp_gmt(&vtm, t); 98 apr_strftime(str, &ret_size, strsize - 1, CTIME, &vtm);126 apr_strftime(str, &ret_size, strsize - 1, OPENSSL_TIME_FORMAT, &vtm); 99 127 100 128 return str; … … 103 131 #if HAVE_APR_MEMCACHE 104 132 105 /* Name the Session ID as: 106 * server:port.SessionID 107 * to disallow resuming sessions on different servers 133 /** 134 * Turn a GnuTLS session ID into the key format we use with memcached 135 * caches. Name the Session ID as `server:port.SessionID` to disallow 136 * resuming sessions on different servers. 137 * 138 * @return `0` on success, `-1` on failure 108 139 */ 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) 140 static char *mgs_session_id2mc(conn_rec * c, unsigned char *id, int idlen) 141 { 142 char sz[GNUTLS_SESSION_ID_STRING_LEN]; 143 apr_status_t rv = apr_escape_hex(sz, id, idlen, 0, NULL); 144 if (rv != APR_SUCCESS) 115 145 return NULL; 116 146 … … 150 180 if (rv != APR_SUCCESS) { 151 181 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, 152 "[gnutls_cache] Failed to create Memcache Object of '%d' size.",153 nservers);182 "Failed to create Memcache object of size '%d'.", 183 nservers); 154 184 return rv; 155 185 } … … 168 198 if (rv != APR_SUCCESS) { 169 199 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, 170 "[gnutls_cache] Failed to Parse Server: '%s'", 171 split); 200 "Failed to parse server: '%s'", split); 172 201 return rv; 173 202 } … … 175 204 if (host_str == NULL) { 176 205 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, 177 "[gnutls_cache] Failed to Parse Server, "178 "no hostname specified: '%s'", split);206 "Failed to parse server, " 207 "no hostname specified: '%s'", split); 179 208 return rv; 180 209 } … … 191 220 if (rv != APR_SUCCESS) { 192 221 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, 193 "[gnutls_cache] Failed to Create Server: %s:%d",194 host_str, port);222 "Failed to create server: %s:%d", 223 host_str, port); 195 224 return rv; 196 225 } … … 199 228 if (rv != APR_SUCCESS) { 200 229 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, 201 "[gnutls_cache] Failed to Add Server: %s:%d",202 host_str, port);230 "Failed to add server: %s:%d", 231 host_str, port); 203 232 return rv; 204 233 } … … 209 238 } 210 239 211 static int mc_cache_store(void *baton, gnutls_datum_t key, 212 gnutls_datum_t data) { 240 static int mc_cache_store(server_rec *s, const char *key, 241 gnutls_datum_t data, apr_uint32_t timeout) 242 { 243 apr_status_t rv = apr_memcache_set(mc, key, (char *) data.data, 244 data.size, timeout, 0); 245 246 if (rv != APR_SUCCESS) 247 { 248 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, 249 "error storing key '%s' with %d bytes of data", 250 key, data.size); 251 return -1; 252 } 253 254 return 0; 255 } 256 257 static int mc_cache_store_generic(server_rec *s, gnutls_datum_t key, 258 gnutls_datum_t data, apr_time_t expiry) 259 { 260 apr_uint32_t timeout = apr_time_sec(expiry - apr_time_now()); 261 262 apr_pool_t *p; 263 apr_pool_create(&p, NULL); 264 265 const char *hex = apr_pescape_hex(p, key.data, key.size, 1); 266 if (hex == NULL) 267 { 268 apr_pool_destroy(p); 269 return -1; 270 } 271 272 const char *strkey = apr_psprintf(p, MC_TAG "%s", hex); 273 274 int ret = mc_cache_store(s, strkey, data, timeout); 275 276 apr_pool_destroy(p); 277 return ret; 278 } 279 280 static int mc_cache_store_session(void *baton, gnutls_datum_t key, 281 gnutls_datum_t data) 282 { 283 mgs_handle_t *ctxt = baton; 284 285 const char *strkey = mgs_session_id2mc(ctxt->c, key.data, key.size); 286 if (!strkey) 287 return -1; 288 289 apr_uint32_t timeout = apr_time_sec(ctxt->sc->cache_timeout); 290 291 return mc_cache_store(ctxt->c->base_server, strkey, data, timeout); 292 } 293 294 static gnutls_datum_t mc_cache_fetch(conn_rec *c, const char *key) 295 { 213 296 apr_status_t rv = APR_SUCCESS; 214 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)220 return -1;221 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 297 char *value; 243 298 apr_size_t value_len; 244 299 gnutls_datum_t data = {NULL, 0}; 245 300 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) { 301 rv = apr_memcache_getp(mc, c->pool, key, &value, &value_len, NULL); 302 303 if (rv != APR_SUCCESS) 304 { 255 305 #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; 306 ap_log_cerror(APLOG_MARK, APLOG_DEBUG, rv, c, 307 "error fetching key '%s'", 308 key); 309 #endif 263 310 return data; 264 311 } … … 275 322 } 276 323 324 static gnutls_datum_t mc_cache_fetch_generic(mgs_handle_t *ctxt, 325 gnutls_datum_t key) 326 { 327 gnutls_datum_t data = {NULL, 0}; 328 const char *hex = apr_pescape_hex(ctxt->c->pool, key.data, key.size, 1); 329 if (hex == NULL) 330 return data; 331 332 const char *strkey = apr_psprintf(ctxt->c->pool, MC_TAG "%s", hex); 333 return mc_cache_fetch(ctxt->c, strkey); 334 } 335 336 static gnutls_datum_t mc_cache_fetch_session(void *baton, gnutls_datum_t key) 337 { 338 mgs_handle_t *ctxt = baton; 339 gnutls_datum_t data = {NULL, 0}; 340 341 const char *strkey = mgs_session_id2mc(ctxt->c, key.data, key.size); 342 if (!strkey) 343 return data; 344 345 return mc_cache_fetch(ctxt->c, strkey); 346 } 347 277 348 static int mc_cache_delete(void *baton, gnutls_datum_t key) { 278 349 apr_status_t rv = APR_SUCCESS; … … 288 359 if (rv != APR_SUCCESS) { 289 360 ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, 290 ctxt->c->base_server,291 "[gnutls_cache] error deleting key '%s'",292 strkey);361 ctxt->c->base_server, 362 "error deleting key '%s'", 363 strkey); 293 364 return -1; 294 365 } … … 308 379 #define SSL_DBM_FILE_MODE ( APR_UREAD | APR_UWRITE | APR_GREAD | APR_WREAD ) 309 380 310 static void dbm_cache_expire(mgs_handle_t * ctxt) { 381 static void dbm_cache_expire(server_rec *s) 382 { 383 mgs_srvconf_rec *sc = (mgs_srvconf_rec *) 384 ap_get_module_config(s->module_config, &gnutls_module); 385 311 386 apr_status_t rv; 312 387 apr_dbm_t *dbm; 313 388 apr_datum_t dbmkey; 314 389 apr_datum_t dbmval; 315 apr_time_t now;316 390 apr_time_t dtime; 317 391 apr_pool_t *spool; 318 392 int total, deleted; 319 393 320 now = apr_time_now(); 321 322 if (now - ctxt->sc->last_cache_check < 323 (ctxt->sc->cache_timeout) / 2) 394 apr_time_t now = apr_time_now(); 395 396 if (now - sc->last_cache_check < (sc->cache_timeout) / 2) 324 397 return; 325 398 326 ctxt->sc->last_cache_check = now;327 328 apr_pool_create(&spool, ctxt->c->pool);399 sc->last_cache_check = now; 400 401 apr_pool_create(&spool, NULL); 329 402 330 403 total = 0; 331 404 deleted = 0; 332 405 333 rv = apr_dbm_open_ex(&dbm, db_type(ctxt->sc), 334 ctxt->sc->cache_config, APR_DBM_RWCREATE, 406 apr_global_mutex_lock(sc->cache->mutex); 407 408 rv = apr_dbm_open_ex(&dbm, db_type(sc), 409 sc->cache_config, APR_DBM_RWCREATE, 335 410 SSL_DBM_FILE_MODE, spool); 336 411 if (rv != APR_SUCCESS) { 337 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);412 ap_log_error(APLOG_MARK, APLOG_NOTICE, rv, s, 413 "error opening cache '%s'", 414 sc->cache_config); 415 apr_global_mutex_unlock(sc->cache->mutex); 341 416 apr_pool_destroy(spool); 342 417 return; … … 364 439 apr_dbm_close(dbm); 365 440 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); 441 rv = apr_global_mutex_unlock(sc->cache->mutex); 442 443 ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, s, 444 "Cleaned up cache '%s'. Deleted %d and left %d", 445 sc->cache_config, deleted, total - deleted); 370 446 371 447 apr_pool_destroy(spool); … … 374 450 } 375 451 376 static gnutls_datum_t dbm_cache_fetch(void *baton, gnutls_datum_t key) { 452 static gnutls_datum_t dbm_cache_fetch(mgs_handle_t *ctxt, gnutls_datum_t key) 453 { 377 454 gnutls_datum_t data = {NULL, 0}; 378 455 apr_dbm_t *dbm; 379 apr_datum_t dbmkey ;456 apr_datum_t dbmkey = {(char*) key.data, key.size}; 380 457 apr_datum_t dbmval; 381 mgs_handle_t *ctxt = baton;458 apr_time_t expiry = 0; 382 459 apr_status_t rv; 383 460 384 if (mgs_session_id2dbm(ctxt->c, key.data, key.size, &dbmkey) < 0) 385 return data; 461 /* check if it is time for cache expiration */ 462 dbm_cache_expire(ctxt->c->base_server); 463 464 apr_global_mutex_lock(ctxt->sc->cache->mutex); 386 465 387 466 rv = apr_dbm_open_ex(&dbm, db_type(ctxt->sc), … … 389 468 SSL_DBM_FILE_MODE, ctxt->c->pool); 390 469 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);470 ap_log_cerror(APLOG_MARK, APLOG_NOTICE, rv, ctxt->c, 471 "error opening cache '%s'", 472 ctxt->sc->cache_config); 473 apr_global_mutex_unlock(ctxt->sc->cache->mutex); 395 474 return data; 396 475 } … … 398 477 rv = apr_dbm_fetch(dbm, dbmkey, &dbmval); 399 478 400 if (rv != APR_SUCCESS) { 401 apr_dbm_close(dbm); 479 if (rv != APR_SUCCESS) 480 goto close_db; 481 482 if (dbmval.dptr == NULL || dbmval.dsize <= sizeof (apr_time_t)) 483 goto cleanup; 484 485 data.size = dbmval.dsize - sizeof (apr_time_t); 486 /* get data expiration tag */ 487 expiry = *((apr_time_t *) dbmval.dptr); 488 489 data.data = gnutls_malloc(data.size); 490 if (data.data == NULL) 491 { 492 data.size = 0; 493 goto cleanup; 494 } 495 496 ap_log_cerror(APLOG_MARK, APLOG_TRACE1, rv, ctxt->c, 497 "fetched %ld bytes from cache", 498 dbmval.dsize); 499 500 memcpy(data.data, dbmval.dptr + sizeof (apr_time_t), data.size); 501 502 cleanup: 503 apr_dbm_freedatum(dbm, dbmval); 504 close_db: 505 apr_dbm_close(dbm); 506 apr_global_mutex_unlock(ctxt->sc->cache->mutex); 507 508 /* cache entry might have expired since last cache cleanup */ 509 if (expiry != 0 && expiry < apr_time_now()) 510 { 511 gnutls_free(data.data); 512 data.data = NULL; 513 data.size = 0; 514 ap_log_cerror(APLOG_MARK, APLOG_TRACE1, APR_SUCCESS, ctxt->c, 515 "dropped expired cache data"); 516 } 517 518 return data; 519 } 520 521 static gnutls_datum_t dbm_cache_fetch_session(void *baton, gnutls_datum_t key) 522 { 523 gnutls_datum_t data = {NULL, 0}; 524 gnutls_datum_t dbmkey; 525 mgs_handle_t *ctxt = baton; 526 527 if (mgs_session_id2dbm(ctxt->c, key.data, key.size, &dbmkey) < 0) 402 528 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) { 529 530 return dbm_cache_fetch(ctxt, dbmkey); 531 } 532 533 static int dbm_cache_store(server_rec *s, gnutls_datum_t key, 534 gnutls_datum_t data, apr_time_t expiry) 535 { 536 mgs_srvconf_rec *sc = (mgs_srvconf_rec *) 537 ap_get_module_config(s->module_config, &gnutls_module); 538 430 539 apr_dbm_t *dbm; 431 apr_datum_t dbmkey ;540 apr_datum_t dbmkey = {(char*) key.data, key.size}; 432 541 apr_datum_t dbmval; 433 mgs_handle_t *ctxt = baton;434 542 apr_status_t rv; 435 apr_time_t expiry;436 543 apr_pool_t *spool; 437 544 438 if (mgs_session_id2dbm(ctxt->c, key.data, key.size, &dbmkey) < 0) 439 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); 545 /* check if it is time for cache expiration */ 546 dbm_cache_expire(s); 547 548 apr_pool_create(&spool, NULL); 446 549 447 550 /* create DBM value */ … … 449 552 dbmval.dptr = (char *) apr_palloc(spool, dbmval.dsize); 450 553 451 expiry = apr_time_now() + ctxt->sc->cache_timeout; 452 554 /* prepend expiration time */ 453 555 memcpy((char *) dbmval.dptr, &expiry, sizeof (apr_time_t)); 454 556 memcpy((char *) dbmval.dptr + sizeof (apr_time_t), 455 557 data.data, data.size); 558 559 apr_global_mutex_lock(sc->cache->mutex); 560 561 rv = apr_dbm_open_ex(&dbm, db_type(sc), 562 sc->cache_config, APR_DBM_RWCREATE, 563 SSL_DBM_FILE_MODE, spool); 564 if (rv != APR_SUCCESS) 565 { 566 ap_log_error(APLOG_MARK, APLOG_NOTICE, rv, s, 567 "error opening cache '%s'", 568 sc->cache_config); 569 apr_global_mutex_unlock(sc->cache->mutex); 570 apr_pool_destroy(spool); 571 return -1; 572 } 573 574 rv = apr_dbm_store(dbm, dbmkey, dbmval); 575 if (rv != APR_SUCCESS) 576 { 577 ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, s, 578 "error storing in cache '%s'", 579 sc->cache_config); 580 apr_dbm_close(dbm); 581 apr_global_mutex_unlock(sc->cache->mutex); 582 apr_pool_destroy(spool); 583 return -1; 584 } 585 586 apr_dbm_close(dbm); 587 apr_global_mutex_unlock(sc->cache->mutex); 588 589 ap_log_error(APLOG_MARK, APLOG_TRACE1, rv, s, 590 "stored %ld bytes of data (%ld byte key) in cache '%s'", 591 dbmval.dsize, dbmkey.dsize, sc->cache_config); 592 593 apr_pool_destroy(spool); 594 595 return 0; 596 } 597 598 static int dbm_cache_store_session(void *baton, gnutls_datum_t key, 599 gnutls_datum_t data) 600 { 601 mgs_handle_t *ctxt = baton; 602 gnutls_datum_t dbmkey; 603 604 if (mgs_session_id2dbm(ctxt->c, key.data, key.size, &dbmkey) < 0) 605 return -1; 606 607 apr_time_t expiry = apr_time_now() + ctxt->sc->cache_timeout; 608 609 return dbm_cache_store(ctxt->c->base_server, dbmkey, data, expiry); 610 } 611 612 static int dbm_cache_delete(void *baton, gnutls_datum_t key) 613 { 614 apr_dbm_t *dbm; 615 gnutls_datum_t tmpkey; 616 mgs_handle_t *ctxt = baton; 617 apr_status_t rv; 618 619 if (mgs_session_id2dbm(ctxt->c, key.data, key.size, &tmpkey) < 0) 620 return -1; 621 apr_datum_t dbmkey = {(char*) tmpkey.data, tmpkey.size}; 622 623 apr_global_mutex_lock(ctxt->sc->cache->mutex); 456 624 457 625 rv = apr_dbm_open_ex(&dbm, db_type(ctxt->sc), … … 460 628 if (rv != APR_SUCCESS) { 461 629 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 485 return 0; 486 } 487 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); 630 ctxt->c->base_server, 631 "error opening cache '%s'", 632 ctxt->sc->cache_config); 633 apr_global_mutex_unlock(ctxt->sc->cache->mutex); 634 return -1; 635 } 636 637 rv = apr_dbm_delete(dbm, dbmkey); 638 500 639 if (rv != APR_SUCCESS) { 501 640 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); 641 ctxt->c->base_server, 642 "error deleting from cache '%s'", 643 ctxt->sc->cache_config); 515 644 apr_dbm_close(dbm); 645 apr_global_mutex_unlock(ctxt->sc->cache->mutex); 516 646 return -1; 517 647 } 518 648 519 649 apr_dbm_close(dbm); 650 apr_global_mutex_unlock(ctxt->sc->cache->mutex); 520 651 521 652 return 0; … … 571 702 sc->cache_type = mgs_cache_none; 572 703 /* 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) { 704 if (sc->cache_timeout == MGS_TIMEOUT_UNSET) 705 sc->cache_timeout = apr_time_from_sec(MGS_DEFAULT_CACHE_TIMEOUT); 706 707 /* initialize mutex only once */ 708 if (sc->cache == NULL) 709 { 710 sc->cache = apr_palloc(p, sizeof(struct mgs_cache)); 711 apr_status_t rv = ap_global_mutex_create(&sc->cache->mutex, NULL, 712 MGS_CACHE_MUTEX_NAME, 713 NULL, s, p, 0); 714 if (rv != APR_SUCCESS) 715 return rv; 716 } 717 718 if (sc->cache_type == mgs_cache_dbm || sc->cache_type == mgs_cache_gdbm) 719 { 720 sc->cache->store = dbm_cache_store; 721 sc->cache->fetch = dbm_cache_fetch; 578 722 return dbm_cache_post_config(p, s, sc); 579 723 } 580 return 0;581 }582 583 724 #if HAVE_APR_MEMCACHE 725 else if (sc->cache_type == mgs_cache_memcache) 726 { 727 sc->cache->store = mc_cache_store_generic; 728 sc->cache->fetch = mc_cache_fetch_generic; 729 } 730 #endif 731 732 return APR_SUCCESS; 733 } 734 584 735 int mgs_cache_child_init(apr_pool_t * p, 585 736 server_rec * s, 586 737 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 { 738 { 739 /* reinit cache mutex */ 740 const char *lockfile = apr_global_mutex_lockfile(sc->cache->mutex); 741 apr_status_t rv = apr_global_mutex_child_init(&sc->cache->mutex, 742 lockfile, p); 743 if (rv != APR_SUCCESS) 744 ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s, 745 "Failed to reinit mutex '%s'", MGS_CACHE_MUTEX_NAME); 746 593 747 if (sc->cache_type == mgs_cache_dbm 594 748 || sc->cache_type == mgs_cache_gdbm) { … … 609 763 || ctxt->sc->cache_type == mgs_cache_gdbm) { 610 764 gnutls_db_set_retrieve_function(ctxt->session, 611 dbm_cache_fetch );765 dbm_cache_fetch_session); 612 766 gnutls_db_set_remove_function(ctxt->session, 613 767 dbm_cache_delete); 614 768 gnutls_db_set_store_function(ctxt->session, 615 dbm_cache_store );769 dbm_cache_store_session); 616 770 gnutls_db_set_ptr(ctxt->session, ctxt); 617 771 } … … 619 773 else if (ctxt->sc->cache_type == mgs_cache_memcache) { 620 774 gnutls_db_set_retrieve_function(ctxt->session, 621 mc_cache_fetch );775 mc_cache_fetch_session); 622 776 gnutls_db_set_remove_function(ctxt->session, 623 777 mc_cache_delete); 624 778 gnutls_db_set_store_function(ctxt->session, 625 mc_cache_store );779 mc_cache_store_session); 626 780 gnutls_db_set_ptr(ctxt->session, ctxt); 627 781 } -
src/gnutls_config.c
rbaa4ed5 rd2b32f1 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 Thomas Klute5 * Copyright 2015-2016 Thomas 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_config.h" 21 21 #include "mod_gnutls.h" 22 #include "gnutls_ocsp.h" 22 23 #include "apr_lib.h" 23 24 #include <gnutls/abstract.h> … … 93 94 "-----END DH PARAMETERS-----\n"; 94 95 95 int mgs_load_files(apr_pool_t * p, server_rec * s) 96 /* 97 * Clean up the various GnuTLS data structures allocated from 98 * mgs_load_files() 99 */ 100 static apr_status_t mgs_pool_free_credentials(void *arg) 101 { 102 mgs_srvconf_rec *sc = (mgs_srvconf_rec *) arg; 103 104 if (sc->certs) 105 { 106 gnutls_certificate_free_credentials(sc->certs); 107 sc->certs = NULL; 108 } 109 110 if (sc->anon_creds) 111 { 112 gnutls_anon_free_server_credentials(sc->anon_creds); 113 sc->anon_creds = NULL; 114 } 115 116 #ifdef ENABLE_SRP 117 if (sc->srp_creds) 118 { 119 gnutls_srp_free_server_credentials(sc->srp_creds); 120 sc->srp_creds = NULL; 121 } 122 #endif 123 124 if (sc->dh_params) 125 { 126 gnutls_dh_params_deinit(sc->dh_params); 127 sc->dh_params = NULL; 128 } 129 130 for (unsigned int i = 0; i < sc->certs_x509_chain_num; i++) 131 { 132 gnutls_pcert_deinit(&sc->certs_x509_chain[i]); 133 gnutls_x509_crt_deinit(sc->certs_x509_crt_chain[i]); 134 } 135 136 if (sc->privkey_x509) 137 { 138 gnutls_privkey_deinit(sc->privkey_x509); 139 sc->privkey_x509 = NULL; 140 } 141 142 if (sc->ca_list) 143 { 144 for (unsigned int i = 0; i < sc->ca_list_size; i++) 145 { 146 gnutls_x509_crt_deinit(sc->ca_list[i]); 147 } 148 gnutls_free(sc->ca_list); 149 sc->ca_list = NULL; 150 } 151 152 if (sc->cert_pgp) 153 { 154 gnutls_pcert_deinit(&sc->cert_pgp[0]); 155 sc->cert_pgp = NULL; 156 gnutls_openpgp_crt_deinit(sc->cert_crt_pgp[0]); 157 sc->cert_crt_pgp = NULL; 158 } 159 160 if (sc->privkey_pgp) 161 { 162 gnutls_privkey_deinit(sc->privkey_pgp); 163 sc->privkey_pgp = NULL; 164 #if GNUTLS_VERSION_NUMBER < 0x030312 165 gnutls_openpgp_privkey_deinit(sc->privkey_pgp_internal); 166 sc->privkey_pgp_internal = NULL; 167 #endif 168 } 169 170 if (sc->pgp_list) 171 { 172 gnutls_openpgp_keyring_deinit(sc->pgp_list); 173 sc->pgp_list = NULL; 174 } 175 176 if (sc->priorities) 177 { 178 gnutls_priority_deinit(sc->priorities); 179 sc->priorities = NULL; 180 } 181 182 return APR_SUCCESS; 183 } 184 185 int mgs_load_files(apr_pool_t *pconf, apr_pool_t *ptemp, server_rec *s) 96 186 { 97 187 apr_pool_t *spool; … … 100 190 int ret; 101 191 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; 192 (mgs_srvconf_rec *) ap_get_module_config(s->module_config, 193 &gnutls_module); 194 195 apr_pool_create(&spool, ptemp); 196 197 /* Cleanup function for the GnuTLS structures allocated below */ 198 apr_pool_cleanup_register(pconf, sc, mgs_pool_free_credentials, 199 apr_pool_cleanup_null); 200 201 if (sc->certs == NULL) 202 { 203 ret = gnutls_certificate_allocate_credentials(&sc->certs); 204 if (ret < 0) { 205 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 206 "GnuTLS: Failed to initialize" ": (%d) %s", ret, 207 gnutls_strerror(ret)); 208 ret = -1; 209 goto cleanup; 210 } 211 } 212 213 if (sc->anon_creds == NULL) 214 { 215 ret = gnutls_anon_allocate_server_credentials(&sc->anon_creds); 216 if (ret < 0) { 217 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 218 "GnuTLS: Failed to initialize" ": (%d) %s", ret, 219 gnutls_strerror(ret)); 220 ret = -1; 221 goto cleanup; 222 } 131 223 } 132 224 133 225 /* Load SRP parameters */ 134 226 #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 } 227 if (sc->srp_creds == NULL) 228 { 229 ret = gnutls_srp_allocate_server_credentials(&sc->srp_creds); 230 if (ret < 0) { 231 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 232 "GnuTLS: Failed to initialize" ": (%d) %s", ret, 233 gnutls_strerror(ret)); 234 ret = -1; 235 goto cleanup; 236 } 237 } 238 239 if (sc->srp_tpasswd_conf_file != NULL && sc->srp_tpasswd_file != NULL) 240 { 241 ret = gnutls_srp_set_server_credentials_file 242 (sc->srp_creds, sc->srp_tpasswd_file, 243 sc->srp_tpasswd_conf_file); 244 245 if (ret < 0 && sc->enabled == GNUTLS_ENABLED_TRUE) { 246 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 247 "GnuTLS: Host '%s:%d' is missing a " 248 "SRP password or conf File!", 249 s->server_hostname, s->port); 250 ret = -1; 251 goto cleanup; 252 } 158 253 } 159 254 #endif 160 255 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); 197 if (ret < 0) { 198 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)); 201 ret = -1; 202 goto cleanup; 203 } 204 } 205 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 } 256 if (sc->dh_params == NULL) 257 { 258 ret = gnutls_dh_params_init(&sc->dh_params); 259 if (ret < 0) { 260 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 261 "GnuTLS: Failed to initialize" 262 ": (%d) %s", ret, gnutls_strerror(ret)); 263 ret = -1; 264 goto cleanup; 265 } 266 267 /* Load DH parameters */ 268 if (sc->dh_file) 269 { 270 if (load_datum_from_file(spool, sc->dh_file, &data) != 0) { 271 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 272 "GnuTLS: Error Reading " "DH params '%s'", sc->dh_file); 273 ret = -1; 274 goto cleanup; 275 } 276 277 ret = 278 gnutls_dh_params_import_pkcs3(sc->dh_params, &data, 279 GNUTLS_X509_FMT_PEM); 280 if (ret < 0) { 281 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 282 "GnuTLS: Failed to Import " 283 "DH params '%s': (%d) %s", sc->dh_file, ret, 284 gnutls_strerror(ret)); 285 ret = -1; 286 goto cleanup; 287 } 288 } else { 289 gnutls_datum_t pdata = { 290 (void *) static_dh_params, 291 sizeof(static_dh_params) 292 }; 293 294 ret = gnutls_dh_params_import_pkcs3(sc->dh_params, &pdata, GNUTLS_X509_FMT_PEM); 295 if (ret < 0) { 296 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 297 "GnuTLS: Unable to generate or load DH Params: (%d) %s", 298 ret, gnutls_strerror(ret)); 299 ret = -1; 300 goto cleanup; 301 } 302 } 303 } 304 305 if (sc->x509_cert_file != NULL && sc->certs_x509_crt_chain == NULL) 306 { 307 sc->certs_x509_chain = 308 apr_pcalloc(pconf, 309 MAX_CHAIN_SIZE * sizeof(sc->certs_x509_chain[0])); 310 sc->certs_x509_crt_chain = 311 apr_pcalloc(pconf, 312 MAX_CHAIN_SIZE * sizeof(sc->certs_x509_crt_chain[0])); 313 unsigned int chain_num = MAX_CHAIN_SIZE; 314 unsigned format = GNUTLS_X509_FMT_PEM; 315 316 /* Load X.509 certificate */ 317 if (strncmp(sc->x509_cert_file, "pkcs11:", 7) == 0) { 318 gnutls_pkcs11_obj_t obj; 319 320 file = sc->x509_cert_file; 321 322 ret = gnutls_pkcs11_obj_init(&obj); 323 if (ret < 0) { 324 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 325 "GnuTLS: Error Initializing PKCS #11 object"); 326 ret = -1; 327 goto cleanup; 328 } 329 330 gnutls_pkcs11_obj_set_pin_function(obj, pin_callback, sc); 331 332 ret = gnutls_pkcs11_obj_import_url(obj, file, 333 GNUTLS_PKCS11_OBJ_FLAG_LOGIN); 334 if (ret < 0) { 335 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 336 "GnuTLS: Error Importing PKCS #11 object: " 337 "'%s': %s", 338 file, gnutls_strerror(ret)); 339 ret = -1; 340 goto cleanup; 341 } 342 343 format = GNUTLS_X509_FMT_DER; 344 ret = gnutls_pkcs11_obj_export2(obj, &data); 345 if (ret < 0) { 346 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 347 "GnuTLS: Error Exporting a PKCS #11 object: " 348 "'%s': %s", 349 file, gnutls_strerror(ret)); 350 ret = -1; 351 goto cleanup; 352 } 353 354 gnutls_pkcs11_obj_deinit(obj); 355 } else { 356 file = ap_server_root_relative(spool, sc->x509_cert_file); 357 358 ret = gnutls_load_file(file, &data); 359 if (ret < 0) { 360 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 361 "GnuTLS: Error Reading Certificate '%s': %s", 362 file, gnutls_strerror(ret)); 363 ret = -1; 364 goto cleanup; 365 } 366 } 367 368 ret = gnutls_x509_crt_list_import(sc->certs_x509_crt_chain, 369 &chain_num, &data, format, 370 GNUTLS_X509_CRT_LIST_FAIL_IF_UNSORTED); 371 gnutls_free(data.data); 372 sc->certs_x509_chain_num = chain_num; 373 374 if (ret < 0) { 375 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 376 "GnuTLS: Failed to Import Certificate Chain " 377 "'%s': (%d) %s", 378 file, ret, gnutls_strerror(ret)); 379 ret = -1; 380 goto cleanup; 381 } 382 383 for (unsigned int i = 0; i < chain_num; i++) 384 { 385 ret = 386 gnutls_pcert_import_x509(&sc->certs_x509_chain[i], 387 sc->certs_x509_crt_chain[i], 0); 388 if (ret < 0) { 389 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 390 "GnuTLS: Failed to Import pCertificate " 391 "'%s': (%d) %s", 392 file, ret, gnutls_strerror(ret)); 393 ret = -1; 394 goto cleanup; 395 } 396 } 397 sc->certs_x509_chain_num = chain_num; 398 } 399 400 if (sc->x509_key_file && sc->privkey_x509 == NULL) 401 { 402 ret = gnutls_privkey_init(&sc->privkey_x509); 403 if (ret < 0) { 404 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 405 "GnuTLS: Failed to initialize: (%d) %s", ret, 406 gnutls_strerror(ret)); 407 ret = -1; 408 goto cleanup; 409 } 410 411 if (gnutls_url_is_supported(sc->x509_key_file) != 0) { 412 file = sc->x509_key_file; 413 414 gnutls_privkey_set_pin_function(sc->privkey_x509, pin_callback, 415 sc); 416 417 ret = gnutls_privkey_import_url(sc->privkey_x509, file, 0); 418 419 if (ret < 0) { 420 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 421 "GnuTLS: Failed to Import Private Key URL " 422 "'%s': (%d) %s", 423 file, ret, gnutls_strerror(ret)); 424 ret = -1; 425 goto cleanup; 426 } 427 } else { 428 file = ap_server_root_relative(spool, sc->x509_key_file); 429 430 if (load_datum_from_file(spool, file, &data) != 0) { 431 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 432 "GnuTLS: Error Reading Private Key '%s'", 433 file); 434 ret = -1; 435 goto cleanup; 436 } 437 438 ret = 439 gnutls_privkey_import_x509_raw(sc->privkey_x509, &data, 440 GNUTLS_X509_FMT_PEM, sc->pin, 441 0); 442 443 if (ret < 0) { 444 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 445 "GnuTLS: Failed to Import Private Key " 446 "'%s': (%d) %s", 447 file, ret, gnutls_strerror(ret)); 448 ret = -1; 449 goto cleanup; 450 } 451 } 338 452 } 339 453 340 454 /* 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 } 455 if (sc->x509_ca_file) 456 { 457 if (load_datum_from_file(spool, sc->x509_ca_file, &data) != 0) { 458 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 459 "GnuTLS: Error Reading " "Client CA File '%s'", 460 sc->x509_ca_file); 461 ret = -1; 462 goto cleanup; 463 } 464 465 ret = gnutls_x509_crt_list_import2(&sc->ca_list, &sc->ca_list_size, 466 &data, GNUTLS_X509_FMT_PEM, 0); 467 if (ret < 0) { 468 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 469 "GnuTLS: Failed to load " 470 "Client CA File '%s': (%d) %s", sc->x509_ca_file, 471 ret, gnutls_strerror(ret)); 472 ret = -1; 473 goto cleanup; 474 } 475 } 476 477 if (sc->pgp_cert_file && sc->cert_pgp == NULL) 478 { 479 sc->cert_pgp = apr_pcalloc(pconf, sizeof(sc->cert_pgp[0])); 480 sc->cert_crt_pgp = apr_pcalloc(pconf, sizeof(sc->cert_crt_pgp[0])); 481 482 if (load_datum_from_file(spool, sc->pgp_cert_file, &data) != 0) { 483 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 484 "GnuTLS: Error Reading " "Certificate '%s'", 485 sc->pgp_cert_file); 486 ret = -1; 487 goto cleanup; 488 } 489 490 ret = gnutls_openpgp_crt_init(&sc->cert_crt_pgp[0]); 491 if (ret < 0) { 492 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 493 "GnuTLS: Failed to Init " 494 "PGP Certificate: (%d) %s", ret, 495 gnutls_strerror(ret)); 496 ret = -1; 497 goto cleanup; 498 } 499 500 ret = gnutls_openpgp_crt_import(sc->cert_crt_pgp[0], &data, 501 GNUTLS_OPENPGP_FMT_BASE64); 502 if (ret < 0) { 503 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 504 "GnuTLS: Failed to Import " 505 "PGP Certificate: (%d) %s", ret, 506 gnutls_strerror(ret)); 507 ret = -1; 508 goto cleanup; 509 } 510 511 ret = gnutls_pcert_import_openpgp(sc->cert_pgp, 512 sc->cert_crt_pgp[0], 0); 513 if (ret < 0) { 514 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 515 "GnuTLS: Failed to Import " 516 "PGP pCertificate: (%d) %s", ret, 517 gnutls_strerror(ret)); 518 ret = -1; 519 goto cleanup; 520 } 404 521 } 405 522 406 523 /* 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 } 524 if (sc->pgp_key_file && sc->privkey_pgp == NULL) 525 { 526 if (load_datum_from_file(spool, sc->pgp_key_file, &data) != 0) { 527 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 528 "GnuTLS: Error Reading " "Private Key '%s'", 529 sc->pgp_key_file); 530 ret = -1; 531 goto cleanup; 532 } 533 534 ret = gnutls_privkey_init(&sc->privkey_pgp); 535 if (ret < 0) { 536 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 537 "GnuTLS: Failed to initialize" 538 ": (%d) %s", ret, gnutls_strerror(ret)); 539 ret = -1; 540 goto cleanup; 541 } 424 542 425 543 #if GNUTLS_VERSION_NUMBER < 0x030312 … … 433 551 * gnutls_privkey_import_openpgp. */ 434 552 ret = gnutls_openpgp_privkey_init(&sc->privkey_pgp_internal); 435 436 437 438 439 440 441 442 553 if (ret != 0) { 554 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 555 "GnuTLS: Failed to initialize " 556 "PGP Private Key '%s': (%d) %s", 557 sc->pgp_key_file, ret, gnutls_strerror(ret)); 558 ret = -1; 559 goto cleanup; 560 } 443 561 444 562 ret = gnutls_openpgp_privkey_import(sc->privkey_pgp_internal, &data, 445 563 GNUTLS_OPENPGP_FMT_BASE64, NULL, 0); 446 447 448 449 450 451 452 453 564 if (ret != 0) { 565 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 566 "GnuTLS: Failed to Import " 567 "PGP Private Key '%s': (%d) %s", 568 sc->pgp_key_file, ret, gnutls_strerror(ret)); 569 ret = -1; 570 goto cleanup; 571 } 454 572 455 573 ret = gnutls_privkey_import_openpgp(sc->privkey_pgp, … … 461 579 "to gnutls_privkey_t structure: (%d) %s", 462 580 sc->pgp_key_file, ret, gnutls_strerror(ret)); 463 464 465 581 ret = -1; 582 goto cleanup; 583 } 466 584 #else 467 585 ret = gnutls_privkey_import_openpgp_raw(sc->privkey_pgp, &data, 468 586 GNUTLS_OPENPGP_FMT_BASE64, 469 587 NULL, NULL); 470 588 if (ret != 0) 471 589 { 472 590 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, … … 474 592 "PGP Private Key '%s': (%d) %s", 475 593 sc->pgp_key_file, ret, gnutls_strerror(ret)); 476 477 478 594 ret = -1; 595 goto cleanup; 596 } 479 597 #endif 480 598 } 481 599 482 600 /* 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) { 601 if (sc->pgp_ring_file && sc->pgp_list == NULL) 602 { 603 if (load_datum_from_file(spool, sc->pgp_ring_file, &data) != 0) { 604 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 605 "GnuTLS: Error Reading " "Keyring File '%s'", 606 sc->pgp_ring_file); 607 ret = -1; 608 goto cleanup; 609 } 610 611 ret = gnutls_openpgp_keyring_init(&sc->pgp_list); 612 if (ret < 0) { 613 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 614 "GnuTLS: Failed to initialize" 615 "keyring: (%d) %s", ret, gnutls_strerror(ret)); 616 ret = -1; 617 goto cleanup; 618 } 619 620 ret = gnutls_openpgp_keyring_import(sc->pgp_list, &data, 621 GNUTLS_OPENPGP_FMT_BASE64); 622 if (ret < 0) { 623 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 624 "GnuTLS: Failed to load " 625 "Keyring File '%s': (%d) %s", sc->pgp_ring_file, 626 ret, gnutls_strerror(ret)); 627 ret = -1; 628 goto cleanup; 629 } 630 } 631 632 if (sc->priorities_str && sc->priorities == NULL) 633 { 514 634 const char *err; 515 635 ret = gnutls_priority_init(&sc->priorities, sc->priorities_str, &err); 516 636 517 518 519 520 521 522 523 524 525 526 527 528 529 637 if (ret < 0) { 638 if (ret == GNUTLS_E_INVALID_REQUEST) { 639 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 640 "GnuTLS: Syntax error parsing priorities string at: %s", 641 err); 642 } else { 643 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 644 "GnuTLS: error parsing priorities string"); 645 646 } 647 ret = -1; 648 goto cleanup; 649 } 530 650 } 531 651 532 652 ret = 0; 533 653 cleanup: 534 654 apr_pool_destroy(spool); 535 655 … … 727 847 } 728 848 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 } 849 const char *mgs_set_timeout(cmd_parms * parms, 850 void *dummy __attribute__((unused)), 851 const char *arg) 852 { 853 apr_int64_t argint = apr_atoi64(arg); 854 /* timeouts cannot be negative */ 855 if (argint < 0) 856 return apr_psprintf(parms->pool, "%s: Invalid argument", 857 parms->directive->directive); 858 859 mgs_srvconf_rec *sc = (mgs_srvconf_rec *) 860 ap_get_module_config(parms->server->module_config, &gnutls_module); 861 862 if (!apr_strnatcasecmp(parms->directive->directive, "GnuTLSCacheTimeout")) 863 { 864 const char *err; 865 if ((err = ap_check_cmd_context(parms, GLOBAL_ONLY))) 866 return err; 867 sc->cache_timeout = apr_time_from_sec(argint); 868 } 869 else if (!apr_strnatcasecmp(parms->directive->directive, 870 "GnuTLSOCSPCacheTimeout")) 871 sc->ocsp_cache_time = apr_time_from_sec(argint); 872 else if (!apr_strnatcasecmp(parms->directive->directive, 873 "GnuTLSOCSPFailureTimeout")) 874 sc->ocsp_failure_timeout = apr_time_from_sec(argint); 875 else if (!apr_strnatcasecmp(parms->directive->directive, 876 "GnuTLSOCSPSocketTimeout")) 877 sc->ocsp_socket_timeout = apr_time_from_sec(argint); 878 else 879 /* Can't happen unless there's a serious bug in mod_gnutls or Apache */ 880 return apr_psprintf(parms->pool, 881 "mod_gnutls: %s called for invalid option '%s'", 882 __func__, parms->directive->directive); 751 883 752 884 return NULL; … … 950 1082 951 1083 sc->privkey_x509 = NULL; 952 sc->privkey_pgp = NULL; 1084 sc->anon_creds = NULL; 1085 #ifdef ENABLE_SRP 1086 sc->srp_creds = NULL; 1087 #endif 1088 sc->certs = NULL; 1089 sc->certs_x509_chain = NULL; 1090 sc->certs_x509_crt_chain = NULL; 953 1091 sc->certs_x509_chain_num = 0; 954 1092 sc->p11_modules = NULL; 955 1093 sc->pin = NULL; 1094 1095 sc->cert_pgp = NULL; 1096 sc->cert_crt_pgp = NULL; 1097 sc->privkey_pgp = NULL; 1098 #if GNUTLS_VERSION_NUMBER < 0x030312 1099 sc->privkey_pgp_internal = NULL; 1100 #endif 1101 sc->pgp_list = NULL; 1102 956 1103 sc->priorities_str = NULL; 957 sc->cache_timeout = -1; /* -1 means "unset" */1104 sc->cache_timeout = MGS_TIMEOUT_UNSET; 958 1105 sc->cache_type = mgs_cache_unset; 959 1106 sc->cache_config = NULL; 1107 sc->cache = NULL; 960 1108 sc->tickets = GNUTLS_ENABLED_UNSET; 961 1109 sc->priorities = NULL; 962 1110 sc->dh_params = NULL; 1111 sc->ca_list = NULL; 1112 sc->ca_list_size = 0; 963 1113 sc->proxy_enabled = GNUTLS_ENABLED_UNSET; 964 1114 sc->export_certificates_size = -1; … … 970 1120 sc->proxy_x509_crl_file = NULL; 971 1121 sc->proxy_priorities_str = NULL; 1122 sc->proxy_x509_creds = NULL; 1123 sc->anon_client_creds = NULL; 972 1124 sc->proxy_priorities = NULL; 1125 sc->proxy_x509_tl = NULL; 1126 1127 sc->ocsp_staple = GNUTLS_ENABLED_UNSET; 1128 sc->ocsp_check_nonce = GNUTLS_ENABLED_UNSET; 1129 sc->ocsp_response_file = NULL; 1130 sc->ocsp_mutex = NULL; 1131 sc->ocsp_cache_time = MGS_TIMEOUT_UNSET; 1132 sc->ocsp_failure_timeout = MGS_TIMEOUT_UNSET; 1133 sc->ocsp_socket_timeout = MGS_TIMEOUT_UNSET; 973 1134 974 1135 /* this relies on GnuTLS never changing the gnutls_certificate_request_t enum to define -1 */ … … 1028 1189 gnutls_srvconf_merge(proxy_priorities, NULL); 1029 1190 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 */ 1191 gnutls_srvconf_merge(ocsp_staple, GNUTLS_ENABLED_UNSET); 1192 gnutls_srvconf_merge(ocsp_check_nonce, GNUTLS_ENABLED_UNSET); 1193 gnutls_srvconf_assign(ocsp_response_file); 1194 gnutls_srvconf_merge(ocsp_cache_time, MGS_TIMEOUT_UNSET); 1195 gnutls_srvconf_merge(ocsp_failure_timeout, MGS_TIMEOUT_UNSET); 1196 gnutls_srvconf_merge(ocsp_socket_timeout, MGS_TIMEOUT_UNSET); 1197 1036 1198 gnutls_srvconf_assign(ca_list); 1037 1199 gnutls_srvconf_assign(ca_list_size); -
src/gnutls_hooks.c
rbaa4ed5 rd2b32f1 1 /* *1 /* 2 2 * Copyright 2004-2005 Paul Querna 3 3 * Copyright 2008, 2014 Nikos Mavrogiannopoulos … … 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_ocsp.h" 23 24 #include "http_vhost.h" 24 25 #include "ap_mpm.h" 25 26 #include "mod_status.h" 27 #include <util_mutex.h> 28 #include <apr_escape.h> 26 29 27 30 #ifdef ENABLE_MSVA … … 33 36 #endif 34 37 35 #if !USING_2_1_RECENT36 extern server_rec *ap_server_conf;37 #endif38 39 38 #if MOD_GNUTLS_DEBUG 40 39 static apr_file_t *debug_log_fp; … … 44 43 ((c->is_proxy == GNUTLS_ENABLED_TRUE) ? "proxy " : "") 45 44 45 /** Key to encrypt session tickets. Must be kept secret. This key is 46 * generated in the `pre_config` hook and thus constant across 47 * forks. The problem with this approach is that it does not support 48 * regular key rotation. */ 46 49 static gnutls_datum_t session_ticket_key = {NULL, 0}; 47 50 … … 54 57 static const char* mgs_x509_construct_uid(request_rec * pool, gnutls_x509_crt_t cert); 55 58 #endif 56 static int load_proxy_x509_credentials(server_rec *s); 59 static int load_proxy_x509_credentials(apr_pool_t *pconf, apr_pool_t *ptemp, server_rec *s) 60 __attribute__((nonnull)); 57 61 58 62 /* Pool Cleanup Function */ 59 apr_status_t mgs_cleanup_pre_config(void *data __attribute__((unused))) { 60 /* Free all session data */ 63 apr_status_t mgs_cleanup_pre_config(void *data __attribute__((unused))) 64 { 65 /* Free session ticket master key */ 66 #if GNUTLS_VERSION_NUMBER >= 0x030400 67 gnutls_memset(session_ticket_key.data, 0, session_ticket_key.size); 68 #endif 61 69 gnutls_free(session_ticket_key.data); 62 70 session_ticket_key.data = NULL; … … 126 134 AP_OPTIONAL_HOOK(status_hook, mgs_status_hook, NULL, NULL, APR_HOOK_MIDDLE); 127 135 128 /* Register a pool clean-up function */ 136 ap_mutex_register(pconf, MGS_CACHE_MUTEX_NAME, NULL, APR_LOCK_DEFAULT, 0); 137 ap_mutex_register(pconf, MGS_OCSP_MUTEX_NAME, NULL, APR_LOCK_DEFAULT, 0); 138 139 /* Register a pool clean-up function */ 129 140 apr_pool_cleanup_register(pconf, NULL, mgs_cleanup_pre_config, apr_pool_cleanup_null); 130 141 … … 156 167 /* Set Anon credentials */ 157 168 gnutls_credentials_set(session, GNUTLS_CRD_ANON, ctxt->sc->anon_creds); 169 170 if (ctxt->sc->ocsp_staple) 171 { 172 gnutls_certificate_set_ocsp_status_request_function(ctxt->sc->certs, 173 mgs_get_ocsp_response, 174 ctxt); 175 } 158 176 159 177 #ifdef ENABLE_SRP … … 295 313 } 296 314 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 315 /** 316 * Post config hook. 317 * 318 * Must return OK or DECLINED on success, something else on 319 * error. These codes are defined in Apache httpd.h along with the 320 * HTTP status codes, so I'm going to use HTTP error codes both for 321 * fun (and to avoid conflicts). 322 */ 323 int mgs_hook_post_config(apr_pool_t *pconf, 324 apr_pool_t *plog __attribute__((unused)), 325 apr_pool_t *ptemp, 326 server_rec *base_server) 327 { 299 328 int rv; 300 329 server_rec *s; … … 316 345 317 346 318 rv = mgs_cache_post_config(p, s, sc_base); 319 if (rv != 0) { 347 rv = mgs_cache_post_config(pconf, s, sc_base); 348 if (rv != APR_SUCCESS) 349 { 320 350 ap_log_error(APLOG_MARK, APLOG_STARTUP, rv, s, 321 "GnuTLS: Post Config for GnuTLSCache Failed." 322 " Shutting Down."); 323 exit(-1); 351 "Post config for cache failed."); 352 return HTTP_INSUFFICIENT_STORAGE; 353 } 354 355 if (sc_base->ocsp_mutex == NULL) 356 { 357 rv = ap_global_mutex_create(&sc_base->ocsp_mutex, NULL, 358 MGS_OCSP_MUTEX_NAME, NULL, 359 base_server, pconf, 0); 360 if (rv != APR_SUCCESS) 361 { 362 ap_log_error(APLOG_MARK, APLOG_STARTUP, rv, base_server, 363 "Failed to create mutex '" MGS_OCSP_MUTEX_NAME 364 "'."); 365 return HTTP_INTERNAL_SERVER_ERROR; 366 } 324 367 } 325 368 … … 352 395 } 353 396 354 for (s = base_server; s; s = s->next) { 397 for (s = base_server; s; s = s->next) 398 { 355 399 sc = (mgs_srvconf_rec *) ap_get_module_config(s->module_config, &gnutls_module); 356 400 sc->cache_type = sc_base->cache_type; 357 401 sc->cache_config = sc_base->cache_config; 358 402 sc->cache_timeout = sc_base->cache_timeout; 359 360 rv = mgs_load_files(p, s); 403 sc->cache = sc_base->cache; 404 405 rv = mgs_load_files(pconf, ptemp, s); 361 406 if (rv != 0) { 362 407 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 363 408 "GnuTLS: Loading required files failed." 364 409 " Shutting Down."); 365 exit(-1); 410 return HTTP_NOT_FOUND; 411 } 412 413 if (sc->ocsp_staple == GNUTLS_ENABLED_UNSET) 414 sc->ocsp_staple = GNUTLS_ENABLED_FALSE; 415 416 sc->ocsp_mutex = sc_base->ocsp_mutex; 417 /* init OCSP configuration if OCSP is enabled for this host */ 418 if (sc->ocsp_staple) 419 { 420 rv = mgs_ocsp_post_config_server(pconf, ptemp, s); 421 if (rv != OK && rv != DECLINED) 422 return rv; 366 423 } 367 424 … … 370 427 sc->enabled = GNUTLS_ENABLED_FALSE; 371 428 if (sc->tickets == GNUTLS_ENABLED_UNSET) 372 sc->tickets = GNUTLS_ENABLED_ TRUE;429 sc->tickets = GNUTLS_ENABLED_FALSE; 373 430 if (sc->export_certificates_size < 0) 374 431 sc->export_certificates_size = 0; … … 383 440 "GnuTLS: Host '%s:%d' is missing the GnuTLSPriorities directive!", 384 441 s->server_hostname, s->port); 385 exit(-1);442 return HTTP_NOT_ACCEPTABLE; 386 443 } 387 444 … … 415 472 "GnuTLS: Host '%s:%d' is missing a Certificate File!", 416 473 s->server_hostname, s->port); 417 exit(-1);474 return HTTP_UNAUTHORIZED; 418 475 } 419 476 if (sc->enabled == GNUTLS_ENABLED_TRUE && 420 477 ((sc->certs_x509_chain_num > 0 && sc->privkey_x509 == NULL) || 421 (sc->cert_crt_pgp[0] != NULL && sc->privkey_pgp == NULL))) { 478 (sc->cert_crt_pgp != NULL && sc->privkey_pgp == NULL))) 479 { 422 480 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 423 481 "GnuTLS: Host '%s:%d' is missing a Private Key File!", 424 482 s->server_hostname, s->port); 425 exit(-1);483 return HTTP_UNAUTHORIZED; 426 484 } 427 485 … … 429 487 rv = -1; 430 488 if (sc->certs_x509_chain_num > 0) { 431 rv = read_crt_cn(s, p , sc->certs_x509_crt_chain[0], &sc->cert_cn);489 rv = read_crt_cn(s, pconf, sc->certs_x509_crt_chain[0], &sc->cert_cn); 432 490 } 433 491 if (rv < 0 && sc->cert_pgp != NULL) { 434 rv = read_pgpcrt_cn(s, p , sc->cert_crt_pgp[0], &sc->cert_cn);492 rv = read_pgpcrt_cn(s, pconf, sc->cert_crt_pgp[0], &sc->cert_cn); 435 493 } 436 494 … … 446 504 if (sc->enabled == GNUTLS_ENABLED_TRUE 447 505 && sc->proxy_enabled == GNUTLS_ENABLED_TRUE 448 && load_proxy_x509_credentials( s) != APR_SUCCESS)506 && load_proxy_x509_credentials(pconf, ptemp, s) != APR_SUCCESS) 449 507 { 450 508 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, … … 452 510 "'%s:%d' failed, exiting!", 453 511 __func__, s->server_hostname, s->port); 454 exit(-1);455 } 456 } 457 458 459 ap_add_version_component(p , "mod_gnutls/" MOD_GNUTLS_VERSION);512 return HTTP_PROXY_AUTHENTICATION_REQUIRED; 513 } 514 } 515 516 517 ap_add_version_component(pconf, "mod_gnutls/" MOD_GNUTLS_VERSION); 460 518 461 519 { 462 520 const char* libvers = gnutls_check_version(NULL); 463 521 char* gnutls_version = NULL; 464 if(libvers && (gnutls_version = apr_psprintf(p , "GnuTLS/%s", libvers))) {465 ap_add_version_component(p , gnutls_version);522 if(libvers && (gnutls_version = apr_psprintf(pconf, "GnuTLS/%s", libvers))) { 523 ap_add_version_component(pconf, gnutls_version); 466 524 } else { 467 525 // 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");526 ap_add_version_component(pconf, "GnuTLS/" GNUTLS_VERSION "-static"); 469 527 } 470 528 } … … 473 531 } 474 532 475 void mgs_hook_child_init(apr_pool_t * p, server_rec *s) { 533 void mgs_hook_child_init(apr_pool_t *p, server_rec *s) 534 { 476 535 apr_status_t rv = APR_SUCCESS; 477 mgs_srvconf_rec *sc = 478 (mgs_srvconf_rec *)ap_get_module_config(s->module_config, &gnutls_module);536 mgs_srvconf_rec *sc = (mgs_srvconf_rec *) 537 ap_get_module_config(s->module_config, &gnutls_module); 479 538 480 539 _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); 540 481 541 /* if we use PKCS #11 reinitialize it */ 482 483 542 if (mgs_pkcs11_reinit(s) < 0) { 484 543 ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, … … 494 553 } 495 554 } 555 556 /* reinit OCSP mutex */ 557 const char *lockfile = apr_global_mutex_lockfile(sc->ocsp_mutex); 558 rv = apr_global_mutex_child_init(&sc->ocsp_mutex, lockfile, p); 559 if (rv != APR_SUCCESS) 560 ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s, 561 "Failed to reinit mutex '" MGS_OCSP_MUTEX_NAME "'."); 562 496 563 /* Block SIGPIPE Signals */ 497 564 rv = apr_signal_block(SIGPIPE); … … 541 608 #define MAX_HOST_LEN 255 542 609 543 #if USING_2_1_RECENT544 545 610 typedef struct { 546 611 mgs_handle_t *ctxt; … … 554 619 * @param x vhost callback record 555 620 * @param s server record 621 * @param tsc mod_gnutls server data for `s` 622 * 556 623 * @return true if a match, false otherwise 557 624 * 558 625 */ 559 int check_server_aliases(vhost_cb_rec *x, server_rec * s, mgs_srvconf_rec *tsc) { 626 int check_server_aliases(vhost_cb_rec *x, server_rec * s, mgs_srvconf_rec *tsc) 627 { 560 628 apr_array_header_t *names; 561 629 int rv = 0; … … 600 668 } 601 669 602 static int vhost_cb(void *baton, conn_rec * conn __attribute__((unused)), server_rec * s) { 670 static int vhost_cb(void *baton, conn_rec *conn, server_rec * s) 671 { 603 672 mgs_srvconf_rec *tsc; 604 673 vhost_cb_rec *x = baton; … … 618 687 ret = gnutls_x509_crt_check_hostname(tsc->certs_x509_crt_chain[0], s->server_hostname); 619 688 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);689 ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, conn, 690 "GnuTLS: the certificate doesn't match requested " 691 "hostname '%s'", s->server_hostname); 623 692 } 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); 693 ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, conn, 694 "GnuTLS: SNI request for '%s' but no X.509 certs " 695 "available at all", 696 s->server_hostname); 627 697 } 628 698 return check_server_aliases(x, s, tsc); 629 699 } 630 #endif631 700 632 701 mgs_srvconf_rec *mgs_find_sni_server(gnutls_session_t session) … … 637 706 char sni_name[MAX_HOST_LEN]; 638 707 mgs_handle_t *ctxt; 639 #if USING_2_1_RECENT640 708 vhost_cb_rec cbx; 641 #else642 server_rec *s;643 mgs_srvconf_rec *tsc;644 #endif645 709 646 710 if (session == NULL) … … 658 722 659 723 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); 724 ap_log_cerror(APLOG_MARK, APLOG_CRIT, 0, ctxt->c, 725 "GnuTLS: Unknown type '%d' for SNI: '%s'", 726 sni_type, sni_name); 664 727 return NULL; 665 728 } … … 669 732 * for this IP/Port combo. Trust that the core did the 'right' thing. 670 733 */ 671 #if USING_2_1_RECENT672 734 cbx.ctxt = ctxt; 673 735 cbx.sc = NULL; … … 678 740 return cbx.sc; 679 741 } 680 #else681 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 }692 #endif693 742 return NULL; 694 743 } … … 791 840 gnutls_strerror(err), err); 792 841 /* Initialize Session Tickets */ 793 if (session_ticket_key.data != NULL && ctxt->sc->tickets != 0) 842 if (session_ticket_key.data != NULL && 843 ctxt->sc->tickets == GNUTLS_ENABLED_TRUE) 794 844 { 795 845 err = gnutls_session_ticket_enable_server(ctxt->session, &session_ticket_key); … … 876 926 int mgs_hook_fixups(request_rec * r) { 877 927 unsigned char sbuf[GNUTLS_MAX_SESSION_ID]; 878 char buf[AP_IOBUFSIZE];879 928 const char *tmp; 880 929 size_t len; … … 946 995 len = sizeof (sbuf); 947 996 gnutls_session_get_id(ctxt->session, sbuf, &len); 948 tmp = mgs_session_id2sz(sbuf, len, buf, sizeof (buf));949 apr_table_setn(env, "SSL_SESSION_ID", apr_pstrdup(r->pool, tmp));997 apr_table_setn(env, "SSL_SESSION_ID", 998 apr_pescape_hex(r->pool, sbuf, len, 0)); 950 999 951 1000 if (gnutls_certificate_type_get(ctxt->session) == GNUTLS_CRT_X509) { … … 1082 1131 len = sizeof (sbuf); 1083 1132 gnutls_x509_crt_get_serial(cert, sbuf, &len); 1084 tmp = mgs_session_id2sz(sbuf, len, buf, sizeof (buf));1085 apr_table_setn(env, MGS_SIDE("_M_SERIAL"), apr_pstrdup(r->pool, tmp));1133 apr_table_setn(env, MGS_SIDE("_M_SERIAL"), 1134 apr_pescape_hex(r->pool, sbuf, len, 0)); 1086 1135 1087 1136 ret = gnutls_x509_crt_get_version(cert); … … 1199 1248 len = sizeof (sbuf); 1200 1249 gnutls_openpgp_crt_get_fingerprint(cert, sbuf, &len); 1201 tmp = mgs_session_id2sz(sbuf, len, buf, sizeof (buf));1202 apr_table_setn(env, MGS_SIDE("_FINGERPRINT"), apr_pstrdup(r->pool, tmp));1250 apr_table_setn(env, MGS_SIDE("_FINGERPRINT"), 1251 apr_pescape_hex(r->pool, sbuf, len, 0)); 1203 1252 1204 1253 ret = gnutls_openpgp_crt_get_version(cert); … … 1761 1810 } 1762 1811 1763 gnutls_datum_t * out = gnutls_malloc(sizeof(gnutls_datum_t)); 1764 /* GNUTLS_CRT_X509: ATM, only X509 is supported for proxy certs 1765 * 0: according to function API, the last argument should be 0 */ 1766 err = gnutls_certificate_verification_status_print(status, GNUTLS_CRT_X509, 1767 out, 0); 1768 if (err != GNUTLS_E_SUCCESS) 1812 if (status == 0) 1769 1813 ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, ctxt->c, 1770 "%s: server verify print failed: %s (%d)",1771 __func__ , gnutls_strerror(err), err);1814 "%s: server certificate is trusted.", 1815 __func__); 1772 1816 else 1773 1817 { 1774 /* If the certificate is trusted, logging the result is just 1775 * nice for debugging. But if the back end server provided an 1776 * untrusted certificate, warn! */ 1777 int level = (status == 0 ? APLOG_DEBUG : APLOG_WARNING); 1778 ap_log_cerror(APLOG_MARK, level, 0, ctxt->c, 1779 "%s: server certificate verify result: %s", 1780 __func__, out->data); 1781 } 1782 1783 gnutls_free(out); 1818 gnutls_datum_t out; 1819 /* GNUTLS_CRT_X509: ATM, only X509 is supported for proxy 1820 * certs 0: according to function API, the last argument 1821 * should be 0 */ 1822 err = gnutls_certificate_verification_status_print(status, 1823 GNUTLS_CRT_X509, 1824 &out, 0); 1825 if (err != GNUTLS_E_SUCCESS) 1826 ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, ctxt->c, 1827 "%s: server verify print failed: %s (%d)", 1828 __func__, gnutls_strerror(err), err); 1829 else 1830 ap_log_cerror(APLOG_MARK, APLOG_WARNING, 0, ctxt->c, 1831 "%s: %s", 1832 __func__, out.data); 1833 gnutls_free(out.data); 1834 } 1835 1784 1836 return status; 1785 1837 } … … 1787 1839 1788 1840 1789 static apr_status_t load_proxy_x509_credentials(server_rec *s) 1841 static apr_status_t cleanup_proxy_x509_credentials(void *arg) 1842 { 1843 mgs_srvconf_rec *sc = (mgs_srvconf_rec *) arg; 1844 1845 if (sc->proxy_x509_creds) 1846 { 1847 /* This implicitly releases the associated trust list 1848 * sc->proxy_x509_tl, too. */ 1849 gnutls_certificate_free_credentials(sc->proxy_x509_creds); 1850 sc->proxy_x509_creds = NULL; 1851 sc->proxy_x509_tl = NULL; 1852 } 1853 1854 if (sc->anon_client_creds) 1855 { 1856 gnutls_anon_free_client_credentials(sc->anon_client_creds); 1857 sc->anon_client_creds = NULL; 1858 } 1859 1860 if (sc->proxy_priorities) 1861 { 1862 gnutls_priority_deinit(sc->proxy_priorities); 1863 sc->proxy_priorities = NULL; 1864 } 1865 1866 return APR_SUCCESS; 1867 } 1868 1869 1870 1871 static apr_status_t load_proxy_x509_credentials(apr_pool_t *pconf, 1872 apr_pool_t *ptemp, 1873 server_rec *s) 1790 1874 { 1791 1875 mgs_srvconf_rec *sc = (mgs_srvconf_rec *) … … 1795 1879 return APR_EGENERAL; 1796 1880 1797 apr_status_t ret = APR_ SUCCESS;1881 apr_status_t ret = APR_EINIT; 1798 1882 int err = GNUTLS_E_SUCCESS; 1883 1884 /* Cleanup function for the GnuTLS structures allocated below */ 1885 apr_pool_cleanup_register(pconf, sc, cleanup_proxy_x509_credentials, 1886 apr_pool_cleanup_null); 1799 1887 1800 1888 /* Function pool, gets destroyed before exit. */ 1801 1889 apr_pool_t *pool; 1802 ret = apr_pool_create(&pool, s->process->pool);1890 ret = apr_pool_create(&pool, ptemp); 1803 1891 if (ret != APR_SUCCESS) 1804 1892 { -
src/gnutls_io.c
rbaa4ed5 rd2b32f1 1 /* *1 /* 2 2 * Copyright 2004-2005 Paul Querna 3 3 * Copyright 2008 Nikos Mavrogiannopoulos 4 4 * Copyright 2011 Dash Shendy 5 * Copyright 2015 Thomas Klute5 * Copyright 2015-2016 Thomas 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 … … 25 24 #endif 26 25 26 #if defined(__GNUC__) && __GNUC__ < 5 && !defined(__clang__) 27 #include <inttypes.h> 28 #endif 29 27 30 /** 31 * @file 28 32 * Describe how the GnuTLS Filter system works here 29 33 * - Basicly the same as what mod_ssl does with OpenSSL. … … 43 47 44 48 /** 45 * Convert APR_EINTR or APR_EAGAIN to the match raw error code. Needed46 * to pass the status on to GnuTLS from the pull function.49 * Convert `APR_EINTR` or `APR_EAGAIN` to the matching errno. Needed 50 * to pass the status on to GnuTLS from the pull and push functions. 47 51 */ 48 52 #define EAI_APR_TO_RAW(s) (APR_STATUS_IS_EAGAIN(s) ? EAGAIN : EINTR) … … 59 63 case HTTP_BAD_REQUEST: 60 64 /* log the situation */ 61 ap_log_error(APLOG_MARK, APLOG_INFO, 0, 62 f->c->base_server, 63 "GnuTLS handshake failed: HTTP spoken on HTTPS port; " 64 "trying to send HTML error page"); 65 ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, f->c, 66 "GnuTLS handshake failed: HTTP spoken on HTTPS port; " 67 "trying to send HTML error page"); 65 68 mgs_srvconf_rec *sc = (mgs_srvconf_rec *) 66 69 ap_get_module_config(f->c->base_server->module_config, … … 401 404 if (maxtries < 1) { 402 405 ctxt->status = -1; 403 #if USING_2_1_RECENT404 406 ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, ctxt->c, 405 407 "GnuTLS: Handshake Failed. Hit Maximum Attempts"); 406 #else407 ap_log_error(APLOG_MARK, APLOG_ERR, 0,408 ctxt->c->base_server,409 "GnuTLS: Handshake Failed. Hit Maximum Attempts");410 #endif411 408 if (ctxt->session) { 412 409 gnutls_alert_send(ctxt->session, GNUTLS_AL_FATAL, … … 423 420 || ret == GNUTLS_E_FATAL_ALERT_RECEIVED) { 424 421 errcode = gnutls_alert_get(ctxt->session); 425 ap_log_error(APLOG_MARK, APLOG_INFO, 0, 426 ctxt->c->base_server, 427 "GnuTLS: Handshake Alert (%d) '%s'.", 428 errcode, 429 gnutls_alert_get_name(errcode)); 422 ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, ctxt->c, 423 "GnuTLS: Handshake Alert (%d) '%s'.", 424 errcode, gnutls_alert_get_name(errcode)); 430 425 } 431 426 432 427 if (!gnutls_error_is_fatal(ret)) { 433 ap_log_error(APLOG_MARK, APLOG_INFO, 0, 434 ctxt->c->base_server, 435 "GnuTLS: Non-Fatal Handshake Error: (%d) '%s'", 436 ret, gnutls_strerror(ret)); 428 ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, ctxt->c, 429 "GnuTLS: Non-Fatal Handshake Error: (%d) '%s'", 430 ret, gnutls_strerror(ret)); 437 431 goto tryagain; 438 432 } 439 #if USING_2_1_RECENT440 433 ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, ctxt->c, 441 434 "GnuTLS: Handshake Failed (%d) '%s'", ret, 442 435 gnutls_strerror(ret)); 443 #else444 ap_log_error(APLOG_MARK, APLOG_INFO, 0,445 ctxt->c->base_server,446 "GnuTLS: Handshake Failed (%d) '%s'", ret,447 gnutls_strerror(ret));448 #endif449 436 ctxt->status = -1; 450 437 if (ctxt->session) { … … 483 470 if (rv != 0) { 484 471 /* the client did not want to rehandshake. goodbye */ 485 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, 486 ctxt->c->base_server, 487 "GnuTLS: Client Refused Rehandshake request."); 472 ap_log_cerror(APLOG_MARK, APLOG_WARNING, 0, ctxt->c, 473 "GnuTLS: Client Refused Rehandshake request."); 488 474 return -1; 489 475 } … … 501 487 * Close the TLS session associated with the given connection 502 488 * structure and free its resources 489 * 490 * @param ctxt the mod_gnutls session context 491 * 492 * @return a GnuTLS status code, hopefully `GNUTLS_E_SUCCESS` 503 493 */ 504 494 static int mgs_bye(mgs_handle_t* ctxt) … … 579 569 return APR_ENOTIMPL; 580 570 } 581 /* Err. This is bad. readbytes *can* be a 64bit int! len.. is NOT */ 582 if ((apr_size_t) readbytes < len) { 571 /* 'readbytes' and 'len' are of different integer types, which 572 * might have different lengths. Read sizes should be too 573 * small for 32 or 64 bit to matter, but we have to make 574 * sure. */ 575 #if defined(__GNUC__) && __GNUC__ < 5 && !defined(__clang__) 576 if ((apr_size_t) readbytes < len) 577 { 578 /* If readbytes is negative the function fails in the 579 * check above, but the compiler doesn't get that. */ 580 if (__builtin_expect(imaxabs(readbytes) > SIZE_MAX, 0)) 581 { 582 ap_log_cerror(APLOG_MARK, APLOG_CRIT, APR_EINVAL, ctxt->c, 583 "%s: prevented buffer length overflow", 584 __func__); 585 return APR_EINVAL; 586 } 583 587 len = (apr_size_t) readbytes; 584 588 } 589 #else 590 if ((apr_size_t) readbytes < len 591 && __builtin_add_overflow(readbytes, 0, &len)) 592 { 593 ap_log_cerror(APLOG_MARK, APLOG_CRIT, APR_EINVAL, ctxt->c, 594 "%s: prevented buffer length overflow", 595 __func__); 596 return APR_EINVAL; 597 } 598 #endif 585 599 status = 586 600 gnutls_io_input_read(ctxt, ctxt->input_buffer, &len); … … 619 633 } 620 634 635 /** 636 * Try to flush the output bucket brigade. 637 * 638 * @param ctxt the mod_gnutls session context 639 * 640 * @return `1` on success, `-1` on failure. 641 */ 621 642 static ssize_t write_flush(mgs_handle_t * ctxt) { 622 643 apr_bucket *e; … … 735 756 if (ret < 0) { 736 757 /* error sending output */ 737 ap_log_error(APLOG_MARK, 738 APLOG_INFO, 739 ctxt->output_rc, 740 ctxt->c->base_server, 741 "GnuTLS: Error writing data." 742 " (%d) '%s'", 743 (int) ret, 744 gnutls_strerror(ret)); 758 ap_log_cerror(APLOG_MARK, APLOG_INFO, ctxt->output_rc, 759 ctxt->c, 760 "GnuTLS: Error writing data. (%d) '%s'", 761 ret, gnutls_strerror(ret)); 745 762 if (ctxt->output_rc == APR_SUCCESS) { 746 763 ctxt->output_rc = … … 766 783 * Pull function for GnuTLS 767 784 * 768 * Generic errnos used for gnutls_transport_set_errno: 769 * EIO: Unknown I/O error 770 * ECONNABORTED: Input BB does not exist (NULL) 771 * 772 * The reason we are not using APR_TO_OS_ERROR to map apr_status_t to 773 * errnos is this warning in the APR documentation: "If the statcode 774 * was not created by apr_get_os_error or APR_FROM_OS_ERROR, the 775 * results are undefined." We cannot know if this applies to any error 776 * we might encounter. 785 * Generic errnos used for `gnutls_transport_set_errno()`: 786 * * `EAGAIN`: no data available at the moment, try again (maybe later) 787 * * `EINTR`: read was interrupted, try again 788 * * `EIO`: Unknown I/O error 789 * * `ECONNABORTED`: Input BB does not exist (`NULL`) 790 * 791 * The reason we are not using `APR_TO_OS_ERROR` to map `apr_status_t` 792 * to errnos is this warning [in the APR documentation][apr-warn]: 793 * 794 * > If the statcode was not created by apr_get_os_error or 795 * > APR_FROM_OS_ERROR, the results are undefined. 796 * 797 * We cannot know if this applies to any error we might encounter. 798 * 799 * @param ptr GnuTLS session data pointer (the mod_gnutls context 800 * structure) 801 * 802 * @param buffer buffer for the read data 803 * 804 * @param len maximum number of bytes to read (must fit into the 805 * buffer) 806 * 807 * @return The number of bytes read (may be zero on EOF), or `-1` on 808 * error. Note that some errors may warrant another try (see above). 809 * 810 * [apr-warn]: https://apr.apache.org/docs/apr/1.4/group__apr__errno.html#ga2385cae04b04afbdcb65f1a45c4d8506 "Apache Portable Runtime: Error Codes" 777 811 */ 778 812 ssize_t mgs_transport_read(gnutls_transport_ptr_t ptr, … … 871 905 * Push function for GnuTLS 872 906 * 873 * In case of unexpected errors gnutls_transport_set_errno is called 874 * with EIO. The reason we are not using APR_TO_OS_ERROR to map 875 * apr_status_t to errnos is this warning in the APR documentation: 876 * "If the statcode was not created by apr_get_os_error or 877 * APR_FROM_OS_ERROR, the results are undefined." We cannot know if 878 * this applies to any error we might encounter. 907 * `gnutls_transport_set_errno()` will be called with `EAGAIN` or 908 * `EINTR` on recoverable errors, or `EIO` in case of unexpected 909 * errors. See the description of mgs_transport_read() for details on 910 * possible error codes. 911 * 912 * @param ptr GnuTLS session data pointer (the mod_gnutls context 913 * structure) 914 * 915 * @param buffer buffer containing the data to send 916 * 917 * @param len length of the data 918 * buffer) 919 * 920 * @return The number of written bytes, or `-1` on error. Note that 921 * some errors may warrant another try (see above). 879 922 */ 880 923 ssize_t mgs_transport_write(gnutls_transport_ptr_t ptr, -
src/mod_gnutls.c
rbaa4ed5 rd2b32f1 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 Thomas Klute5 * Copyright 2015-2016 Thomas 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 21 20 #include "mod_gnutls.h" 21 #include "gnutls_ocsp.h" 22 22 23 23 #ifdef APLOG_USE_MODULE … … 32 32 APR_HOOK_REALLY_LAST); 33 33 /* HTTP Scheme Hook */ 34 #if USING_2_1_RECENT35 34 ap_hook_http_scheme(mgs_hook_http_scheme, NULL, NULL, APR_HOOK_MIDDLE); 36 #else37 ap_hook_http_method(mgs_hook_http_scheme, NULL, NULL, APR_HOOK_MIDDLE);38 #endif39 35 /* Default Port Hook */ 40 36 ap_hook_default_port(mgs_hook_default_port, NULL, NULL, APR_HOOK_MIDDLE); … … 76 72 77 73 78 /* 79 * mod_rewrite calls this function to fill %{HTTPS}. A non-zero return 80 * value means that HTTPS is in use. 74 /** 75 * mod_rewrite calls this function to fill %{HTTPS}. 76 * 77 * @param c the connection to check 78 * @return non-zero value if HTTPS is in use, zero if not 81 79 */ 82 80 int ssl_is_https(conn_rec *c) … … 229 227 "TLS Server SRP Parameters file"), 230 228 #endif 231 AP_INIT_TAKE1("GnuTLSCacheTimeout", mgs_set_ cache_timeout,229 AP_INIT_TAKE1("GnuTLSCacheTimeout", mgs_set_timeout, 232 230 NULL, 233 231 RSRC_CONF, … … 275 273 "The priorities to enable for proxy connections (ciphers, key exchange, " 276 274 "MACs, compression)."), 275 AP_INIT_FLAG("GnuTLSOCSPStapling", mgs_ocsp_stapling_enable, 276 NULL, RSRC_CONF, 277 "Enable OCSP stapling"), 278 AP_INIT_FLAG("GnuTLSOCSPCheckNonce", mgs_set_ocsp_check_nonce, 279 NULL, RSRC_CONF, 280 "Check nonce in OCSP responses?"), 281 AP_INIT_TAKE1("GnuTLSOCSPResponseFile", mgs_store_ocsp_response_path, 282 NULL, RSRC_CONF, 283 "Read OCSP response for stapling from this file instead " 284 "of sending a request over HTTP (must be updated " 285 "externally)"), 286 AP_INIT_TAKE1("GnuTLSOCSPCacheTimeout", mgs_set_timeout, 287 NULL, RSRC_CONF, 288 "Cache timeout for OCSP responses"), 289 AP_INIT_TAKE1("GnuTLSOCSPFailureTimeout", mgs_set_timeout, 290 NULL, RSRC_CONF, 291 "Wait this many seconds before retrying a failed OCSP " 292 "request"), 293 AP_INIT_TAKE1("GnuTLSOCSPSocketTimeout", mgs_set_timeout, 294 NULL, RSRC_CONF, 295 "Socket timeout for OCSP requests"), 296 #ifdef __clang__ 297 /* Workaround for this clang bug: 298 * https://llvm.org/bugs/show_bug.cgi?id=21689 */ 299 {}, 300 #else 277 301 { NULL }, 302 #endif 278 303 }; 279 304 -
test/Makefile.am
rbaa4ed5 rd2b32f1 29 29 test-24_pkcs11_cert.bash \ 30 30 test-25_Disable_TLS_1.0.bash \ 31 test-26_redirect_HTTP_to_HTTPS.bash 31 test-26_redirect_HTTP_to_HTTPS.bash \ 32 test-27_OCSP_server.bash 32 33 33 34 TESTS = $(dist_check_SCRIPTS) … … 35 36 check_PROGRAMS = pgpcrc 36 37 pgpcrc_SOURCES = pgpcrc.c 38 39 # build OCSP database tool 40 if ENABLE_OCSP_TEST 41 check_PROGRAMS += gen_ocsp_index 42 gen_ocsp_index_SOURCES = gen_ocsp_index.c cert_helper.c 43 gen_ocsp_index_LDFLAGS = $(LIBGNUTLS_LIBS) 44 noinst_HEADERS = cert_helper.h 45 endif 37 46 38 47 # Identities in the miniature CA, server, and client environment for … … 41 50 pgp_identities = $(shared_identities) 42 51 x509_only_identities = rogueclient 52 if ENABLE_OCSP_TEST 53 x509_only_identities += ocsp-responder 54 endif 43 55 x509_identities = $(shared_identities) $(x509_only_identities) 44 56 identities = $(shared_identities) $(x509_only_identities) … … 74 86 75 87 cert_templates = authority.template.in client.template.in \ 76 imposter.template.in rogueca.template rogueclient.template.in\77 server.template.in88 imposter.template.in ocsp-responder.template rogueca.template \ 89 rogueclient.template.in server.template.in 78 90 generated_templates = authority.template client.template \ 79 91 imposter.template rogueclient.template server.template … … 117 129 endif 118 130 131 if ENABLE_OCSP_TEST 132 # rules to build OCSP database 133 check_DATA += authority/ocsp_index.txt 134 MOSTLYCLEANFILES += authority/ocsp_index.txt authority/ocsp_index.txt.attr 135 authority/ocsp_index.txt: $(x509_tokens) gen_ocsp_index authority/ocsp_index.txt.attr 136 ./gen_ocsp_index server/x509.pem client/x509.pem > $@ 137 138 authority/ocsp_index.txt.attr: authority/secret.key 139 echo "unique_subject = no" > $@ 140 141 # build certificate chain file for server 142 check_DATA += server/x509-chain.pem 143 MOSTLYCLEANFILES += server/x509-chain.pem 144 %/x509-chain.pem: %/x509.pem authority/x509.pem 145 cat $< authority/x509.pem > $@ 146 endif 119 147 120 148 # SoftHSM tokens. Note that the SoftHSM 2 token is a directory and … … 159 187 160 188 # Apache configuration and data files 161 apache_data = base_apache.conf cgi_module.conf data/dump.cgi data/secret.txt data/test.txt mime.types proxy_mods.conf 189 apache_data = base_apache.conf cgi_module.conf data/dump.cgi data/ocsp.cgi \ 190 data/secret.txt data/test.txt mime.types ocsp_server.conf \ 191 proxy_mods.conf 162 192 163 193 EXTRA_DIST = $(apache_data) $(cert_templates) $(shared_identities:=.uid.in) \ … … 177 207 # port for MSVA in test cases that use it 178 208 MSVA_PORT ?= 9933 209 # port for OCSP server (Apache vhost if enabled) 210 if ENABLE_OCSP_TEST 211 OCSP_PORT ?= 9936 212 endif 179 213 # maximum time to wait for MSVA startup (milliseconds) 180 214 TEST_MSVA_MAX_WAIT ?= 10000 … … 202 236 endif 203 237 238 if ENABLE_OCSP_TEST 239 AM_TESTS_ENVIRONMENT += export OPENSSL="@OPENSSL@"; \ 240 export OCSP_PORT="$(OCSP_PORT)"; 241 endif 242 204 243 if ENABLE_NETNS 205 244 AM_TESTS_ENVIRONMENT += export UNSHARE="@UNSHARE@"; \ -
test/client.template.in
rbaa4ed5 rd2b32f1 5 5 signing_key 6 6 encryption_key 7 ### ocsp_uri=http://__HOSTNAME__:__OCSP_PORT__/ocsp/ -
test/runtests
rbaa4ed5 rd2b32f1 189 189 fi 190 190 191 # check OCSP server 192 if [ -n "${CHECK_OCSP_SERVER}" ]; then 193 if [ -n "${OCSP_RESPONSE_FILE}" ]; then 194 store_ocsp="--outfile ${OCSP_RESPONSE_FILE}" 195 fi 196 echo "---- Testing OCSP server ----" 197 ocsptool --ask --nonce --load-issuer authority/x509.pem --load-cert server/x509.pem ${store_ocsp} 198 echo "---- OCSP test done ----" 199 fi 200 191 201 # PID file for sleep command (explanation below) 192 202 sleep_pidfile="$(mktemp mod_gnutls_test-XXXXXX.pid)" -
test/server.template.in
rbaa4ed5 rd2b32f1 5 5 encryption_key 6 6 dns_name="__HOSTNAME__" 7 ### ocsp_uri=http://__HOSTNAME__:__OCSP_PORT__/ocsp/ -
test/test_ca.mk
rbaa4ed5 rd2b32f1 9 9 %.template: $(srcdir)/%.template.in 10 10 sed s/__HOSTNAME__/$(TEST_HOST)/ < $< > $@ 11 if test -n "$(OCSP_PORT)"; then \ 12 sed -i -e 's/^### ocsp/ocsp/' \ 13 -e s/__OCSP_PORT__/$(OCSP_PORT)/ $@; \ 14 fi 11 15 12 16 %.uid: $(srcdir)/%.uid.in … … 39 43 40 44 # Import and signing modify the shared keyring, which leads to race 41 # conditions with parallel make. Locking avoids this problem. 42 %/cert.pgp: %/minimal.pgp authority/gpg.conf 45 # conditions with parallel make. Locking avoids this problem. Building 46 # authority/minimal.pgp (instead of just authority/gpg.conf) before 47 # */cert.pgp avoids having to lock for all */minimal.pgp, too. 48 %/cert.pgp: %/minimal.pgp authority/minimal.pgp 43 49 if test -r $@; then rm $@; fi 44 50 GNUPGHOME=authority $(GPG_FLOCK) gpg --import $< 45 51 GNUPGHOME=authority $(GPG_FLOCK) gpg --batch --sign-key --no-tty --yes "$$(GNUPGHOME=$(dir $@) gpg --with-colons --list-secret-keys --fingerprint | grep ^fpr: | cut -f 10 -d :)" 46 GNUPGHOME=authority gpg --output $@ --armor --export "$$(GNUPGHOME=$(dir $@) gpg --with-colons --list-secret-keys --fingerprint | grep ^fpr: | cut -f 10 -d :)"52 GNUPGHOME=authority $(GPG_FLOCK) gpg --output $@ --armor --export "$$(GNUPGHOME=$(dir $@) gpg --with-colons --list-secret-keys --fingerprint | grep ^fpr: | cut -f 10 -d :)" 47 53 48 54 # special cases for the authorities' root certs: -
test/tests/Makefile.am
rbaa4ed5 rd2b32f1 26 26 24_pkcs11_cert/apache.conf 24_pkcs11_cert/gnutls-cli.args 24_pkcs11_cert/input 24_pkcs11_cert/output \ 27 27 25_Disable_TLS_1.0/apache.conf 25_Disable_TLS_1.0/fail.client 25_Disable_TLS_1.0/gnutls-cli.args 25_Disable_TLS_1.0/input \ 28 26_redirect_HTTP_to_HTTPS/apache.conf 28 26_redirect_HTTP_to_HTTPS/apache.conf \ 29 27_OCSP_server/apache.conf 27_OCSP_server/gnutls-cli.args 27_OCSP_server/input 27_OCSP_server/output
Note: See TracChangeset
for help on using the changeset viewer.