diff options
| author | Arno Töll <debian@toell.net> | 2012-01-08 22:53:17 +0100 |
|---|---|---|
| committer | Arno Töll <debian@toell.net> | 2012-01-08 22:53:17 +0100 |
| commit | e072a2dd866b7cb9f14319b80326a4e7fd16fcdf (patch) | |
| tree | a49dfc56d94a26011fe157835ff6cbe14edbd8a9 /modules/ssl | |
| parent | 0890390c00801651d08d3794e13b31a5dabbf5ef (diff) | |
| download | apache2-e072a2dd866b7cb9f14319b80326a4e7fd16fcdf.tar.gz | |
Imported Upstream version 2.3.16-beta
Diffstat (limited to 'modules/ssl')
39 files changed, 4568 insertions, 9177 deletions
diff --git a/modules/ssl/Makefile.in b/modules/ssl/Makefile.in index 978b1c47..4395bc3a 100644 --- a/modules/ssl/Makefile.in +++ b/modules/ssl/Makefile.in @@ -18,22 +18,3 @@ # include $(top_srcdir)/build/special.mk - -# -# developer stuff -# (we really don't expect end users to use these targets!) -# - -ssl_expr_scan.c: $(top_srcdir)/modules/ssl/ssl_expr_scan.l ssl_expr_parse.h - flex -Pssl_expr_yy -s -B $(top_srcdir)/modules/ssl/ssl_expr_scan.l - sed -e '/$$Header:/d' -e "s|\"`pwd`/|\"|g" <lex.ssl_expr_yy.c >ssl_expr_scan.c && rm -f lex.ssl_expr_yy.c - -ssl_expr_parse.c ssl_expr_parse.h: $(top_srcdir)/modules/ssl/ssl_expr_parse.y - yacc -d $(top_srcdir)/modules/ssl/ssl_expr_parse.y - sed -e 's;yy;ssl_expr_yy;g' \ - -e "s|\"`pwd`/|\"|g" \ - -e '/#if defined(c_plusplus) || defined(__cplusplus)/,/#endif/d' \ - <y.tab.c >ssl_expr_parse.c && rm -f y.tab.c - sed -e 's;yy;ssl_expr_yy;g' \ - <y.tab.h >ssl_expr_parse.h && rm -f y.tab.h - diff --git a/modules/ssl/NWGNUmakefile b/modules/ssl/NWGNUmakefile index 048c1e42..933180f1 100644 --- a/modules/ssl/NWGNUmakefile +++ b/modules/ssl/NWGNUmakefile @@ -1,6 +1,9 @@ # -# This Makefile requires the environment var OSSLSDK +# This Makefile requires the environment var OSSLSDK # pointing to the base directory of your OpenSSL SDK. +# If you want to use the Novell NTLS SDK instead then +# define NTLSSDK pointing to the base directory of the +# SDK, and also set USE_NTLS=1 # # @@ -8,7 +11,7 @@ # SUBDIRS = \ - $(EOLIST) + $(EOLIST) # # Get the 'head' of the build environment. This includes default targets and @@ -23,23 +26,37 @@ include $(AP_WORK)/build/NWGNUhead.inc # Make sure all needed macro's are defined # -OSSLINC = $(OSSLSDK)/outinc_nw_libc -OSSLLIB = $(OSSLSDK)/out_nw_libc -OSSLAPP = $(OSSLSDK)/apps +ifeq "$(USE_NTLS)" "1" +SSL_INC = $(NTLSSDK)/inc +SSL_LIB = $(NTLSSDK)/imp +SSL_BIN = $(NTLSSDK)/bin +SSL_APP = $(NTLSSDK)/apps +ifneq "$(wildcard $(SSL_INC)/openssl/opensslv.h)" "$(SSL_INC)/openssl/opensslv.h" +$(error '$(NTLSSDK)' does NOT point to a valid NTLS SDK!) +endif +else +SSL_INC = $(OSSLSDK)/outinc_nw_libc +SSL_LIB = $(OSSLSDK)/out_nw_libc +SSL_BIN = $(OSSLSDK)/out_nw_libc +SSL_APP = $(OSSLSDK)/apps +ifneq "$(wildcard $(SSL_INC)/openssl/opensslv.h)" "$(SSL_INC)/openssl/opensslv.h" +$(error '$(OSSLSDK)' does NOT point to a valid OpenSSL SDK!) +endif +endif # # These directories will be at the beginning of the include list, followed by # INCDIRS # XINCDIRS += \ + $(SSL_INC) \ $(APR)/include \ $(APRUTIL)/include \ $(AP_WORK)/include \ + $(AP_WORK)/modules/cache \ + $(AP_WORK)/modules/generators \ + $(AP_WORK)/server/mpm/NetWare \ $(NWOS) \ - $(STDMOD)/generators \ - $(SERVER)/mpm/NetWare \ - $(OSSLINC) \ - $(OSSLINC)/openssl \ $(EOLIST) # @@ -59,7 +76,7 @@ XDEFINES += \ # These flags will be added to the link.opt file # XLFLAGS += \ - -l $(OSSLLIB) \ + -l $(SSL_LIB) \ $(EOLIST) # @@ -116,10 +133,14 @@ endif NLM_NAME = mod_ssl # -# This is used by the link '-desc ' directive. +# This is used by the link '-desc ' directive. # If left blank, NLM_NAME will be used. # -NLM_DESCRIPTION = Apache $(VERSION_STR) SSL module +ifeq "$(USE_NTLS)" "1" +NLM_DESCRIPTION = Apache $(VERSION_STR) SSL module (NTLS) +else +NLM_DESCRIPTION = Apache $(VERSION_STR) SSL module (OpenSSL) +endif # # This is used by the '-threadname' directive. If left blank, @@ -128,16 +149,16 @@ NLM_DESCRIPTION = Apache $(VERSION_STR) SSL module NLM_THREAD_NAME = $(NLM_NAME) # -# If this is specified, it will override VERSION value in +# If this is specified, it will override VERSION value in # $(AP_WORK)/build/NWGNUenvironment.inc # -NLM_VERSION = +NLM_VERSION = # # If this is specified, it will override the default of 64K # NLM_STACK_SIZE = 8192 - + # # If this is specified it will be used by the link '-entry' directive @@ -158,13 +179,13 @@ NLM_CHECK_SYM = # If this is specified it will be used by the link '-flags' directive # NLM_FLAGS = - + # -# If this is specified it will be linked in with the XDCData option in the def +# If this is specified it will be linked in with the XDCData option in the def # file instead of the default of $(NWOS)/apache.xdc. XDCData can be disabled # by setting APACHE_UNIPROC in the environment # -XDCDATA = +XDCDATA = # # Declare all target files (you must add your files here) @@ -196,10 +217,15 @@ FILES_nlm_objs := $(patsubst %.c,$(OBJDIR)/%.o,$(wildcard *.c)) # FILES_nlm_libs = \ $(PRELUDE) \ - $(OSSLLIB)/crypto.lib \ - $(OSSLLIB)/ssl.lib \ $(EOLIST) +ifneq "$(USE_NTLS)" "1" +FILES_nlm_libs += \ + $(SSL_LIB)/crypto.lib \ + $(SSL_LIB)/ssl.lib \ + $(EOLIST) +endif + # # These are the modules that the above NLM target depends on to load. # These will be added as a module command in the link.opt file. @@ -209,11 +235,16 @@ FILES_nlm_modules = \ Libc \ $(EOLIST) +ifeq "$(USE_NTLS)" "1" +FILES_nlm_modules += ntls \ + $(EOLIST) +endif + # # If the nlm has a msg file, put it's path here # FILE_nlm_msg = - + # # If the nlm has a hlp file put it's path here # @@ -231,25 +262,33 @@ FILES_nlm_Ximports = \ @libc.imp \ @aprlib.imp \ @httpd.imp \ + $(EOLIST) + +# Don't link with Winsock if standard sockets are being used +ifneq "$(USE_STDSOCKETS)" "1" +FILES_nlm_Ximports += @ws2nlm.imp \ + $(EOLIST) +endif + +ifeq "$(USE_NTLS)" "1" +FILES_nlm_Ximports += @ntls.imp \ + $(EOLIST) +else +FILES_nlm_Ximports += \ GetProcessSwitchCount \ RunningProcess \ GetSuperHighResolutionTimer \ $(EOLIST) - -# Don't link with Winsock if standard sockets are being used -ifndef USE_STDSOCKETS -FILES_nlm_Ximports += @ws2nlm.imp \ - $(EOLIST) endif - -# + +# # Any symbols exported to here # FILES_nlm_exports = \ ssl_module \ $(EOLIST) -# +# # These are the OBJ files needed to create the LIB target above. # Paths must all use the '/' character # @@ -265,32 +304,19 @@ libs :: $(OBJDIR) $(TARGET_lib) nlms :: libs $(TARGET_nlm) # -# Updated this target to create necessary directories and copy files to the +# Updated this target to create necessary directories and copy files to the # correct place. (See $(AP_WORK)/build/NWGNUhead.inc for examples) # install :: nlms FORCE - $(call COPY,$(OBJDIR)/*.nlm, $(INSTALLBASE)/modules/) - $(call COPY,$(OSSLLIB)/openssl.nlm ,$(INSTALLBASE)/bin/) - $(call COPY,$(OSSLAPP)/openssl.cnf ,$(INSTALLBASE)/bin/) + $(call COPY,$(OBJDIR)/*.nlm, $(INSTALLBASE)/modules/) + $(call COPY,$(SSL_BIN)/openssl.nlm, $(INSTALLBASE)/bin/) + $(call COPY,$(SSL_APP)/openssl.cnf, $(INSTALLBASE)/bin/) # # Any specialized rules here # vpath %.c $(AP_WORK)/modules/arch/netware -# Make sure that the build doesn't attempt to regenerate the shipping files. -# On Windows we use 'copy /b file.ext +,,' to assign the current time and date -# to a file without modifying the file (the TOUCH macro uses this) - see also: -# http://technet.microsoft.com/en-us/library/bb490886.aspx -ssl_expr_parse.h : ssl_expr_parse.y - $(call TOUCH, $@) - -ssl_expr_parse.c : ssl_expr_parse.y - $(call TOUCH, $@) - -ssl_expr_scan.c : ssl_expr_scan.l - $(call TOUCH, $@) - # # Include the 'tail' makefile that has targets that depend on variables defined # in this makefile diff --git a/modules/ssl/README b/modules/ssl/README index 49ef6623..c46377f2 100644 --- a/modules/ssl/README +++ b/modules/ssl/README @@ -98,7 +98,6 @@ MAJOR CHANGES the original SSLProxy* directives o per-directory SSLCACertificate{File,Path} is now thread-safe but requires SSL_set_cert_store patch to OpenSSL - o RSA sslc is supported via ssl_toolkit_compat.h o the ssl_engine_{ds,ext}.c source files are obsolete and no longer exist diff --git a/modules/ssl/config.m4 b/modules/ssl/config.m4 index 06479a9e..1ee122e2 100644 --- a/modules/ssl/config.m4 +++ b/modules/ssl/config.m4 @@ -1,89 +1,17 @@ -dnl Copyright 2001-2005 The Apache Software Foundation or its licensors, as -dnl applicable. -dnl Licensed under the Apache License, Version 2.0 (the "License"); -dnl you may not use this file except in compliance with the License. -dnl You may obtain a copy of the License at -dnl -dnl http://www.apache.org/licenses/LICENSE-2.0 -dnl -dnl Unless required by applicable law or agreed to in writing, software -dnl distributed under the License is distributed on an "AS IS" BASIS, -dnl WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -dnl See the License for the specific language governing permissions and -dnl limitations under the License. - -AC_DEFUN([CHECK_DISTCACHE], [ - AC_MSG_CHECKING(whether Distcache is required) - ap_ssltk_dc="no" - tmp_nomessage="" - tmp_forced="no" - AC_ARG_ENABLE(distcache, - APACHE_HELP_STRING(--enable-distcache,Select distcache support in mod_ssl), - ap_ssltk_dc="$enableval" - tmp_nomessage="" - tmp_forced="yes" - if test "x$ap_ssltk_dc" = "x"; then - ap_ssltk_dc="yes" - dnl our "error"s become "tests revealed that..." - tmp_forced="no" - fi - if test "$ap_ssltk_dc" != "yes" -a "$ap_ssltk_dc" != "no"; then - tmp_nomessage="--enable-distcache had illegal syntax - disabling" - ap_ssltk_dc="no" - fi) - if test "$tmp_forced" = "no"; then - AC_MSG_RESULT($ap_ssltk_dc (default)) - else - AC_MSG_RESULT($ap_ssltk_dc (specified)) - fi - if test "$tmp_forced" = "yes" -a "x$ap_ssltk_dc" = "xno" -a "x$tmp_nomessage" != "x"; then - AC_MSG_ERROR(distcache support failed: $tmp_nomessage) - fi - if test "$ap_ssltk_dc" = "yes"; then - AC_CHECK_HEADER( - [distcache/dc_client.h], - [], - [tmp_nomessage="can't include distcache headers" - ap_ssltk_dc="no"]) - if test "$tmp_forced" = "yes" -a "x$ap_ssltk_dc" = "xno"; then - AC_MSG_ERROR(distcache support failed: $tmp_nomessage) - fi - fi - if test "$ap_ssltk_dc" = "yes"; then - AC_MSG_CHECKING(for Distcache version) - AC_TRY_COMPILE( -[#include <distcache/dc_client.h>], -[#if DISTCACHE_CLIENT_API != 0x0001 -#error "distcache API version is unrecognised" -#endif], -[], -[tmp_nomessage="distcache has an unsupported API version" -ap_ssltk_dc="no"]) - AC_MSG_RESULT($ap_ssltk_dc) - if test "$tmp_forced" = "yes" -a "x$ap_ssltk_dc" = "xno"; then - AC_MSG_ERROR(distcache support failed: $tmp_nomessage) - fi - fi - if test "$ap_ssltk_dc" = "yes"; then - AC_MSG_CHECKING(for Distcache libraries) - save_libs=$LIBS - LIBS="$LIBS -ldistcache -lnal" - AC_TRY_LINK( - [#include <distcache/dc_client.h>], - [DC_CTX *foo = DC_CTX_new((const char *)0,0);], - [], - [tmp_no_message="failed to link with distcache libraries" - ap_ssltk_dc="no"]) - LIBS=$save_libs - AC_MSG_RESULT($ap_ssltk_dc) - if test "$tmp_forced" = "yes" -a "x$ap_ssltk_dc" = "xno"; then - AC_MSG_ERROR(distcache support failed: $tmp_nomessage) - else - APR_ADDTO(MOD_SSL_LDADD, [-ldistcache -lnal]) - AC_DEFINE(HAVE_DISTCACHE, 1, [Define if distcache support is enabled]) - fi - fi -]) +dnl Licensed to the Apache Software Foundation (ASF) under one or more +dnl contributor license agreements. See the NOTICE file distributed with +dnl this work for additional information regarding copyright ownership. +dnl The ASF licenses this file to You under the Apache License, Version 2.0 +dnl (the "License"); you may not use this file except in compliance with +dnl the License. You may obtain a copy of the License at +dnl +dnl http://www.apache.org/licenses/LICENSE-2.0 +dnl +dnl Unless required by applicable law or agreed to in writing, software +dnl distributed under the License is distributed on an "AS IS" BASIS, +dnl WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +dnl See the License for the specific language governing permissions and +dnl limitations under the License. dnl # start of module specific part APACHE_MODPATH_INIT(ssl) @@ -101,26 +29,25 @@ ssl_engine_mutex.lo dnl ssl_engine_pphrase.lo dnl ssl_engine_rand.lo dnl ssl_engine_vars.lo dnl -ssl_expr.lo dnl -ssl_expr_eval.lo dnl -ssl_expr_parse.lo dnl -ssl_expr_scan.lo dnl ssl_scache.lo dnl -ssl_scache_dbm.lo dnl -ssl_scache_shmcb.lo dnl -ssl_scache_dc.lo dnl +ssl_util_stapling.lo dnl ssl_util.lo dnl ssl_util_ssl.lo dnl +ssl_engine_ocsp.lo dnl +ssl_util_ocsp.lo dnl " dnl # hook module into the Autoconf mechanism (--enable-ssl option) -APACHE_MODULE(ssl, [SSL/TLS support (mod_ssl)], $ssl_objs, , no, [ - APACHE_CHECK_SSL_TOOLKIT - APR_SETVAR(MOD_SSL_LDADD, [\$(SSL_LIBS)]) - CHECK_DISTCACHE - if test "x$enable_ssl" = "xshared"; then - # The only symbol which needs to be exported is the module - # structure, so ask libtool to hide everything else: - APR_ADDTO(MOD_SSL_LDADD, [-export-symbols-regex ssl_module]) +APACHE_MODULE(ssl, [SSL/TLS support (mod_ssl)], $ssl_objs, , most, [ + APACHE_CHECK_OPENSSL + if test "$ac_cv_openssl" = "yes" ; then + APR_ADDTO(MOD_SSL_LDADD, [\$(SSL_LIBS)]) + if test "x$enable_ssl" = "xshared"; then + # The only symbol which needs to be exported is the module + # structure, so ask libtool to hide everything else: + APR_ADDTO(MOD_SSL_LDADD, [-export-symbols-regex ssl_module]) + fi + else + enable_ssl=no fi ]) diff --git a/modules/ssl/mod_ssl.c b/modules/ssl/mod_ssl.c index 5edb1c82..57bf2d94 100644 --- a/modules/ssl/mod_ssl.c +++ b/modules/ssl/mod_ssl.c @@ -27,6 +27,9 @@ #include "ssl_private.h" #include "mod_ssl.h" #include "util_md5.h" +#include "util_mutex.h" +#include "ap_provider.h" + #include <assert.h> /* @@ -47,103 +50,87 @@ #define AP_END_CMD { NULL } -const char ssl_valid_ssl_mutex_string[] = - "Valid SSLMutex mechanisms are: `none', `default'" -#if APR_HAS_FLOCK_SERIALIZE - ", `flock:/path/to/file'" -#endif -#if APR_HAS_FCNTL_SERIALIZE - ", `fcntl:/path/to/file'" -#endif -#if APR_HAS_SYSVSEM_SERIALIZE && !defined(PERCHILD_MPM) - ", `sysvsem'" -#endif -#if APR_HAS_POSIXSEM_SERIALIZE - ", `posixsem'" -#endif -#if APR_HAS_PROC_PTHREAD_SERIALIZE - ", `pthread'" -#endif -#if APR_HAS_FLOCK_SERIALIZE || APR_HAS_FCNTL_SERIALIZE - ", `file:/path/to/file'" -#endif -#if (APR_HAS_SYSVSEM_SERIALIZE && !defined(PERCHILD_MPM)) || APR_HAS_POSIXSEM_SERIALIZE - ", `sem'" -#endif - " "; - static const command_rec ssl_config_cmds[] = { /* * Global (main-server) context configuration directives */ - SSL_CMD_SRV(Mutex, TAKE1, ssl_valid_ssl_mutex_string) SSL_CMD_SRV(PassPhraseDialog, TAKE1, "SSL dialog mechanism for the pass phrase query " - "(`builtin', `|/path/to/pipe_program`, " - "or `exec:/path/to/cgi_program')") + "('builtin', '|/path/to/pipe_program', " + "or 'exec:/path/to/cgi_program')") SSL_CMD_SRV(SessionCache, TAKE1, "SSL Session Cache storage " - "(`none', `nonenotnull', `dbm:/path/to/file')") + "('none', 'nonenotnull', 'dbm:/path/to/file')") #if defined(HAVE_OPENSSL_ENGINE_H) && defined(HAVE_ENGINE_INIT) SSL_CMD_SRV(CryptoDevice, TAKE1, "SSL external Crypto Device usage " - "(`builtin', `...')") + "('builtin', '...')") #endif SSL_CMD_SRV(RandomSeed, TAKE23, "SSL Pseudo Random Number Generator (PRNG) seeding source " - "(`startup|connect builtin|file:/path|exec:/path [bytes]')") + "('startup|connect builtin|file:/path|exec:/path [bytes]')") /* * Per-server context configuration directives */ SSL_CMD_SRV(Engine, TAKE1, "SSL switch for the protocol engine " - "(`on', `off')") + "('on', 'off')") SSL_CMD_SRV(FIPS, FLAG, "Enable FIPS-140 mode " "(`on', `off')") SSL_CMD_ALL(CipherSuite, TAKE1, "Colon-delimited list of permitted SSL Ciphers " - "(`XXX:...:XXX' - see manual)") + "('XXX:...:XXX' - see manual)") SSL_CMD_SRV(CertificateFile, TAKE1, "SSL Server Certificate file " - "(`/path/to/file' - PEM or DER encoded)") + "('/path/to/file' - PEM or DER encoded)") SSL_CMD_SRV(CertificateKeyFile, TAKE1, "SSL Server Private Key file " - "(`/path/to/file' - PEM or DER encoded)") + "('/path/to/file' - PEM or DER encoded)") SSL_CMD_SRV(CertificateChainFile, TAKE1, "SSL Server CA Certificate Chain file " - "(`/path/to/file' - PEM encoded)") + "('/path/to/file' - PEM encoded)") + SSL_CMD_SRV(PKCS7CertificateFile, TAKE1, + "PKCS#7 file containing server certificate and chain" + " certificates ('/path/to/file' - PEM encoded)") +#ifdef HAVE_TLS_SESSION_TICKETS + SSL_CMD_SRV(SessionTicketKeyFile, TAKE1, + "TLS session ticket encryption/decryption key file (RFC 5077) " + "('/path/to/file' - file with 48 bytes of random data)") +#endif SSL_CMD_ALL(CACertificatePath, TAKE1, "SSL CA Certificate path " - "(`/path/to/dir' - contains PEM encoded files)") + "('/path/to/dir' - contains PEM encoded files)") SSL_CMD_ALL(CACertificateFile, TAKE1, "SSL CA Certificate file " - "(`/path/to/file' - PEM encoded)") + "('/path/to/file' - PEM encoded)") SSL_CMD_SRV(CADNRequestPath, TAKE1, "SSL CA Distinguished Name path " - "(`/path/to/dir' - symlink hashes to PEM of acceptable CA names to request)") + "('/path/to/dir' - symlink hashes to PEM of acceptable CA names to request)") SSL_CMD_SRV(CADNRequestFile, TAKE1, "SSL CA Distinguished Name file " - "(`/path/to/file' - PEM encoded to derive acceptable CA names to request)") + "('/path/to/file' - PEM encoded to derive acceptable CA names to request)") SSL_CMD_SRV(CARevocationPath, TAKE1, "SSL CA Certificate Revocation List (CRL) path " - "(`/path/to/dir' - contains PEM encoded files)") + "('/path/to/dir' - contains PEM encoded files)") SSL_CMD_SRV(CARevocationFile, TAKE1, "SSL CA Certificate Revocation List (CRL) file " - "(`/path/to/file' - PEM encoded)") + "('/path/to/file' - PEM encoded)") + SSL_CMD_SRV(CARevocationCheck, TAKE1, + "SSL CA Certificate Revocation List (CRL) checking mode") SSL_CMD_ALL(VerifyClient, TAKE1, "SSL Client verify type " - "(`none', `optional', `require', `optional_no_ca')") + "('none', 'optional', 'require', 'optional_no_ca')") SSL_CMD_ALL(VerifyDepth, TAKE1, "SSL Client verify depth " - "(`N' - number of intermediate certificates)") + "('N' - number of intermediate certificates)") SSL_CMD_SRV(SessionCacheTimeout, TAKE1, "SSL Session Cache object lifetime " - "(`N' - number of seconds)") + "('N' - number of seconds)") SSL_CMD_SRV(Protocol, RAW_ARGS, "Enable or disable various SSL protocols" - "(`[+-][SSLv2|SSLv3|TLSv1] ...' - see manual)") + "('[+-][SSLv2|SSLv3|TLSv1] ...' - see manual)") SSL_CMD_SRV(HonorCipherOrder, FLAG, "Use the server's cipher ordering preference") SSL_CMD_SRV(InsecureRenegotiation, FLAG, @@ -158,37 +145,43 @@ static const command_rec ssl_config_cmds[] = { */ SSL_CMD_SRV(ProxyEngine, FLAG, "SSL switch for the proxy protocol engine " - "(`on', `off')") + "('on', 'off')") SSL_CMD_SRV(ProxyProtocol, RAW_ARGS, "SSL Proxy: enable or disable SSL protocol flavors " - "(`[+-][SSLv2|SSLv3|TLSv1] ...' - see manual)") + "('[+-][SSLv2|SSLv3|TLSv1] ...' - see manual)") SSL_CMD_SRV(ProxyCipherSuite, TAKE1, "SSL Proxy: colon-delimited list of permitted SSL ciphers " - "(`XXX:...:XXX' - see manual)") + "('XXX:...:XXX' - see manual)") SSL_CMD_SRV(ProxyVerify, TAKE1, "SSL Proxy: whether to verify the remote certificate " - "(`on' or `off')") + "('on' or 'off')") SSL_CMD_SRV(ProxyVerifyDepth, TAKE1, "SSL Proxy: maximum certificate verification depth " - "(`N' - number of intermediate certificates)") + "('N' - number of intermediate certificates)") SSL_CMD_SRV(ProxyCACertificateFile, TAKE1, "SSL Proxy: file containing server certificates " - "(`/path/to/file' - PEM encoded certificates)") + "('/path/to/file' - PEM encoded certificates)") SSL_CMD_SRV(ProxyCACertificatePath, TAKE1, "SSL Proxy: directory containing server certificates " - "(`/path/to/dir' - contains PEM encoded certificates)") + "('/path/to/dir' - contains PEM encoded certificates)") SSL_CMD_SRV(ProxyCARevocationPath, TAKE1, "SSL Proxy: CA Certificate Revocation List (CRL) path " - "(`/path/to/dir' - contains PEM encoded files)") + "('/path/to/dir' - contains PEM encoded files)") SSL_CMD_SRV(ProxyCARevocationFile, TAKE1, "SSL Proxy: CA Certificate Revocation List (CRL) file " - "(`/path/to/file' - PEM encoded)") + "('/path/to/file' - PEM encoded)") + SSL_CMD_SRV(ProxyCARevocationCheck, TAKE1, + "SSL Proxy: CA Certificate Revocation List (CRL) checking mode") SSL_CMD_SRV(ProxyMachineCertificateFile, TAKE1, "SSL Proxy: file containing client certificates " - "(`/path/to/file' - PEM encoded certificates)") + "('/path/to/file' - PEM encoded certificates)") SSL_CMD_SRV(ProxyMachineCertificatePath, TAKE1, "SSL Proxy: directory containing client certificates " - "(`/path/to/dir' - contains PEM encoded certificates)") + "('/path/to/dir' - contains PEM encoded certificates)") + SSL_CMD_SRV(ProxyMachineCertificateChainFile, TAKE1, + "SSL Proxy: file containing issuing certificates " + "of the client certificate " + "(`/path/to/file' - PEM encoded certificates)") SSL_CMD_SRV(ProxyCheckPeerExpire, FLAG, "SSL Proxy: check the peers certificate expiration date") SSL_CMD_SRV(ProxyCheckPeerCN, FLAG, @@ -199,7 +192,7 @@ static const command_rec ssl_config_cmds[] = { */ SSL_CMD_DIR(Options, OPTIONS, RAW_ARGS, "Set one or more options to configure the SSL engine" - "(`[+-]option[=value] ...' - see manual)") + "('[+-]option[=value] ...' - see manual)") SSL_CMD_DIR(RequireSSL, AUTHCFG, NO_ARGS, "Require the SSL protocol for the per-directory context " "(no arguments)") @@ -211,6 +204,48 @@ static const command_rec ssl_config_cmds[] = { "request body if a per-location SSL renegotiation is required due to " "changed access control requirements") + SSL_CMD_SRV(OCSPEnable, FLAG, + "Enable use of OCSP to verify certificate revocation ('on', 'off')") + SSL_CMD_SRV(OCSPDefaultResponder, TAKE1, + "URL of the default OCSP Responder") + SSL_CMD_SRV(OCSPOverrideResponder, FLAG, + "Force use of the default responder URL ('on', 'off')") + SSL_CMD_SRV(OCSPResponseTimeSkew, TAKE1, + "Maximum time difference in OCSP responses") + SSL_CMD_SRV(OCSPResponseMaxAge, TAKE1, + "Maximum age of OCSP responses") + SSL_CMD_SRV(OCSPResponderTimeout, TAKE1, + "OCSP responder query timeout") + +#ifdef HAVE_OCSP_STAPLING + /* + * OCSP Stapling options + */ + SSL_CMD_SRV(StaplingCache, TAKE1, + "SSL Stapling Response Cache storage " + "(`dbm:/path/to/file')") + SSL_CMD_SRV(UseStapling, FLAG, + "SSL switch for the OCSP Stapling protocol " "(`on', `off')") + SSL_CMD_SRV(StaplingResponseTimeSkew, TAKE1, + "SSL stapling option for maximum time difference in OCSP responses") + SSL_CMD_SRV(StaplingResponderTimeout, TAKE1, + "SSL stapling option for OCSP responder timeout") + SSL_CMD_SRV(StaplingResponseMaxAge, TAKE1, + "SSL stapling option for maximum age of OCSP responses") + SSL_CMD_SRV(StaplingStandardCacheTimeout, TAKE1, + "SSL stapling option for normal OCSP Response Cache Lifetime") + SSL_CMD_SRV(StaplingReturnResponderErrors, FLAG, + "SSL stapling switch to return Status Errors Back to Client" + "(`on', `off')") + SSL_CMD_SRV(StaplingFakeTryLater, FLAG, + "SSL stapling switch to send tryLater response to client on error " + "(`on', `off')") + SSL_CMD_SRV(StaplingErrorCacheTimeout, TAKE1, + "SSL stapling option for OCSP Response Error Cache Lifetime") + SSL_CMD_SRV(StaplingForceURL, TAKE1, + "SSL stapling option to Force the OCSP Stapling URL") +#endif + /* Deprecated directives. */ AP_INIT_RAW_ARGS("SSLLog", ap_set_deprecated, NULL, OR_ALL, "SSLLog directive is no longer supported - use ErrorLog."), @@ -228,15 +263,11 @@ static apr_status_t ssl_cleanup_pre_config(void *data) /* * Try to kill the internals of the SSL library. */ -#ifdef HAVE_OPENSSL -#if OPENSSL_VERSION_NUMBER >= 0x00907001 /* Corresponds to OPENSSL_load_builtin_modules(): * XXX: borrowed from apps.h, but why not CONF_modules_free() * which also invokes CONF_modules_finish()? */ CONF_modules_unload(1); -#endif -#endif /* Corresponds to SSL_library_init: */ EVP_cleanup(); #if HAVE_ENGINE_LOAD_BUILTIN_ENGINES @@ -270,20 +301,14 @@ static int ssl_hook_pre_config(apr_pool_t *pconf, * code can successfully test the SSL environment. */ CRYPTO_malloc_init(); -#ifdef HAVE_OPENSSL ERR_load_crypto_strings(); -#endif SSL_load_error_strings(); SSL_library_init(); #if HAVE_ENGINE_LOAD_BUILTIN_ENGINES ENGINE_load_builtin_engines(); #endif -#ifdef HAVE_OPENSSL OpenSSL_add_all_algorithms(); -#if OPENSSL_VERSION_NUMBER >= 0x00907001 OPENSSL_load_builtin_modules(); -#endif -#endif /* * Let us cleanup the ssl library when the module is unloaded @@ -297,6 +322,12 @@ static int ssl_hook_pre_config(apr_pool_t *pconf, /* Register to handle mod_status status page generation */ ssl_scache_status_register(pconf); + /* Register mutex type names so they can be configured with Mutex */ + ap_mutex_register(pconf, SSL_CACHE_MUTEX_TYPE, NULL, APR_LOCK_DEFAULT, 0); +#ifdef HAVE_OCSP_STAPLING + ap_mutex_register(pconf, SSL_STAPLING_MUTEX_TYPE, NULL, APR_LOCK_DEFAULT, 0); +#endif + return OK; } @@ -311,6 +342,7 @@ static SSLConnRec *ssl_init_connection_ctx(conn_rec *c) sslconn = apr_pcalloc(c->pool, sizeof(*sslconn)); sslconn->server = c->base_server; + sslconn->verify_depth = UNSET; myConnConfigSet(c, sslconn); @@ -325,7 +357,7 @@ int ssl_proxy_enable(conn_rec *c) sc = mySrvConfig(sslconn->server); if (!sc->proxy_enabled) { - ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, + ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(01961) "SSL Proxy requested for %s but not enabled " "[Hint: SSLProxyEngine]", sc->vhost_id); @@ -361,7 +393,7 @@ int ssl_engine_disable(conn_rec *c) return 1; } -int ssl_init_ssl_connection(conn_rec *c) +int ssl_init_ssl_connection(conn_rec *c, request_rec *r) { SSLSrvConfigRec *sc; SSL *ssl; @@ -389,10 +421,10 @@ int ssl_init_ssl_connection(conn_rec *c) * so we can detach later. */ if (!(ssl = SSL_new(mctx->ssl_ctx))) { - ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, + ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(01962) "Unable to create a new SSL connection from the SSL " "context"); - ssl_log_ssl_error(APLOG_MARK, APLOG_ERR, server); + ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, server); c->aborted = 1; @@ -405,9 +437,9 @@ int ssl_init_ssl_connection(conn_rec *c) if (!SSL_set_session_id_context(ssl, (unsigned char *)vhost_md5, APR_MD5_DIGESTSIZE*2)) { - ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, - "Unable to set session id context to `%s'", vhost_md5); - ssl_log_ssl_error(APLOG_MARK, APLOG_ERR, server); + ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(01963) + "Unable to set session id context to '%s'", vhost_md5); + ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, server); c->aborted = 1; @@ -424,10 +456,13 @@ int ssl_init_ssl_connection(conn_rec *c) */ SSL_set_tmp_rsa_callback(ssl, ssl_callback_TmpRSA); SSL_set_tmp_dh_callback(ssl, ssl_callback_TmpDH); +#ifndef OPENSSL_NO_EC + SSL_set_tmp_ecdh_callback(ssl, ssl_callback_TmpECDH); +#endif SSL_set_verify_result(ssl, X509_V_OK); - ssl_io_filter_init(c, ssl); + ssl_io_filter_init(c, r, ssl); return APR_SUCCESS; } @@ -490,21 +525,11 @@ static int ssl_hook_pre_connection(conn_rec *c, void *csd) * later access inside callback functions */ - ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, c, + ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, c, APLOGNO(01964) "Connection to child %ld established " "(server %s)", c->id, sc->vhost_id); - return ssl_init_ssl_connection(c); -} - - -static void ssl_hook_Insert_Filter(request_rec *r) -{ - SSLSrvConfigRec *sc = mySrvConfig(r->server); - - if (sc->enabled == SSL_ENABLED_OPTIONAL) { - ap_add_output_filter("UPGRADE_FILTER", NULL, r, r->connection); - } + return ssl_init_ssl_connection(c, NULL); } /* @@ -526,20 +551,30 @@ static void ssl_register_hooks(apr_pool_t *p) ap_hook_default_port (ssl_hook_default_port, NULL,NULL, APR_HOOK_MIDDLE); ap_hook_pre_config (ssl_hook_pre_config, NULL,NULL, APR_HOOK_MIDDLE); ap_hook_child_init (ssl_init_Child, NULL,NULL, APR_HOOK_MIDDLE); - ap_hook_check_user_id (ssl_hook_UserCheck, NULL,NULL, APR_HOOK_FIRST); + ap_hook_check_authn (ssl_hook_UserCheck, NULL,NULL, APR_HOOK_FIRST, + AP_AUTH_INTERNAL_PER_CONF); ap_hook_fixups (ssl_hook_Fixup, NULL,NULL, APR_HOOK_MIDDLE); - ap_hook_access_checker(ssl_hook_Access, NULL,NULL, APR_HOOK_MIDDLE); - ap_hook_auth_checker (ssl_hook_Auth, NULL,NULL, APR_HOOK_MIDDLE); + ap_hook_check_access (ssl_hook_Access, NULL,NULL, APR_HOOK_MIDDLE, + AP_AUTH_INTERNAL_PER_CONF); + ap_hook_check_authz (ssl_hook_Auth, NULL,NULL, APR_HOOK_MIDDLE, + AP_AUTH_INTERNAL_PER_CONF); ap_hook_post_read_request(ssl_hook_ReadReq, pre_prr,NULL, APR_HOOK_MIDDLE); - ap_hook_insert_filter (ssl_hook_Insert_Filter, NULL,NULL, APR_HOOK_MIDDLE); -/* ap_hook_handler (ssl_hook_Upgrade, NULL,NULL, APR_HOOK_MIDDLE); */ ssl_var_register(p); APR_REGISTER_OPTIONAL_FN(ssl_proxy_enable); APR_REGISTER_OPTIONAL_FN(ssl_engine_disable); - APR_REGISTER_OPTIONAL_FN(ssl_extlist_by_oid); + ap_register_auth_provider(p, AUTHZ_PROVIDER_GROUP, "ssl", + AUTHZ_PROVIDER_VERSION, + &ssl_authz_provider_require_ssl, + AP_AUTH_INTERNAL_PER_CONF); + + ap_register_auth_provider(p, AUTHZ_PROVIDER_GROUP, "ssl-verify-client", + AUTHZ_PROVIDER_VERSION, + &ssl_authz_provider_verify_client, + AP_AUTH_INTERNAL_PER_CONF); + } module AP_MODULE_DECLARE_DATA ssl_module = { diff --git a/modules/ssl/mod_ssl.dep b/modules/ssl/mod_ssl.dep deleted file mode 100644 index 9256241a..00000000 --- a/modules/ssl/mod_ssl.dep +++ /dev/null @@ -1,1017 +0,0 @@ -# Microsoft Developer Studio Generated Dependency File, included by mod_ssl.mak - -.\mod_ssl.c : \ - "..\..\include\ap_config.h"\ - "..\..\include\ap_mmn.h"\ - "..\..\include\ap_regex.h"\ - "..\..\include\ap_release.h"\ - "..\..\include\http_config.h"\ - "..\..\include\http_connection.h"\ - "..\..\include\http_core.h"\ - "..\..\include\http_log.h"\ - "..\..\include\http_main.h"\ - "..\..\include\http_protocol.h"\ - "..\..\include\http_request.h"\ - "..\..\include\http_vhost.h"\ - "..\..\include\httpd.h"\ - "..\..\include\mpm.h"\ - "..\..\include\os.h"\ - "..\..\include\scoreboard.h"\ - "..\..\include\util_cfgtree.h"\ - "..\..\include\util_charset.h"\ - "..\..\include\util_ebcdic.h"\ - "..\..\include\util_filter.h"\ - "..\..\include\util_md5.h"\ - "..\..\include\util_script.h"\ - "..\..\srclib\apr-util\include\apr_dbm.h"\ - "..\..\srclib\apr-util\include\apr_hooks.h"\ - "..\..\srclib\apr-util\include\apr_md5.h"\ - "..\..\srclib\apr-util\include\apr_optional.h"\ - "..\..\srclib\apr-util\include\apr_optional_hooks.h"\ - "..\..\srclib\apr-util\include\apr_rmm.h"\ - "..\..\srclib\apr-util\include\apr_uri.h"\ - "..\..\srclib\apr\include\apr_fnmatch.h"\ - "..\..\srclib\apr\include\apr_hash.h"\ - "..\..\srclib\apr\include\apr_lib.h"\ - "..\..\srclib\apr\include\apr_mmap.h"\ - "..\..\srclib\apr\include\apr_poll.h"\ - "..\..\srclib\apr\include\apr_portable.h"\ - "..\..\srclib\apr\include\apr_strings.h"\ - "..\..\srclib\apr\include\apr_thread_rwlock.h"\ - "..\..\srclib\openssl\inc32\openssl\conf.h"\ - "..\..\srclib\openssl\inc32\openssl\engine.h"\ - "..\..\srclib\openssl\inc32\openssl\store.h"\ - "..\..\srclib\openssl\inc32\openssl\ui.h"\ - "..\..\srclib\openssl\inc32\openssl\x509v3.h"\ - ".\mod_ssl.h"\ - ".\ssl_expr.h"\ - ".\ssl_private.h"\ - ".\ssl_toolkit_compat.h"\ - ".\ssl_util_ssl.h"\ - - -.\ssl_engine_config.c : \ - "..\..\include\ap_config.h"\ - "..\..\include\ap_mmn.h"\ - "..\..\include\ap_regex.h"\ - "..\..\include\ap_release.h"\ - "..\..\include\http_config.h"\ - "..\..\include\http_connection.h"\ - "..\..\include\http_core.h"\ - "..\..\include\http_log.h"\ - "..\..\include\http_main.h"\ - "..\..\include\http_protocol.h"\ - "..\..\include\http_request.h"\ - "..\..\include\http_vhost.h"\ - "..\..\include\httpd.h"\ - "..\..\include\mpm.h"\ - "..\..\include\os.h"\ - "..\..\include\scoreboard.h"\ - "..\..\include\util_cfgtree.h"\ - "..\..\include\util_charset.h"\ - "..\..\include\util_ebcdic.h"\ - "..\..\include\util_filter.h"\ - "..\..\include\util_script.h"\ - "..\..\srclib\apr-util\include\apr_dbm.h"\ - "..\..\srclib\apr-util\include\apr_hooks.h"\ - "..\..\srclib\apr-util\include\apr_optional.h"\ - "..\..\srclib\apr-util\include\apr_optional_hooks.h"\ - "..\..\srclib\apr-util\include\apr_rmm.h"\ - "..\..\srclib\apr-util\include\apr_uri.h"\ - "..\..\srclib\apr\include\apr_fnmatch.h"\ - "..\..\srclib\apr\include\apr_hash.h"\ - "..\..\srclib\apr\include\apr_lib.h"\ - "..\..\srclib\apr\include\apr_mmap.h"\ - "..\..\srclib\apr\include\apr_poll.h"\ - "..\..\srclib\apr\include\apr_portable.h"\ - "..\..\srclib\apr\include\apr_strings.h"\ - "..\..\srclib\apr\include\apr_thread_rwlock.h"\ - "..\..\srclib\openssl\inc32\openssl\conf.h"\ - "..\..\srclib\openssl\inc32\openssl\engine.h"\ - "..\..\srclib\openssl\inc32\openssl\store.h"\ - "..\..\srclib\openssl\inc32\openssl\ui.h"\ - "..\..\srclib\openssl\inc32\openssl\x509v3.h"\ - ".\ssl_expr.h"\ - ".\ssl_private.h"\ - ".\ssl_toolkit_compat.h"\ - ".\ssl_util_ssl.h"\ - - -.\ssl_engine_dh.c : \ - "..\..\include\ap_config.h"\ - "..\..\include\ap_mmn.h"\ - "..\..\include\ap_regex.h"\ - "..\..\include\ap_release.h"\ - "..\..\include\http_config.h"\ - "..\..\include\http_connection.h"\ - "..\..\include\http_core.h"\ - "..\..\include\http_log.h"\ - "..\..\include\http_main.h"\ - "..\..\include\http_protocol.h"\ - "..\..\include\http_request.h"\ - "..\..\include\http_vhost.h"\ - "..\..\include\httpd.h"\ - "..\..\include\mpm.h"\ - "..\..\include\os.h"\ - "..\..\include\scoreboard.h"\ - "..\..\include\util_cfgtree.h"\ - "..\..\include\util_charset.h"\ - "..\..\include\util_ebcdic.h"\ - "..\..\include\util_filter.h"\ - "..\..\include\util_script.h"\ - "..\..\srclib\apr-util\include\apr_dbm.h"\ - "..\..\srclib\apr-util\include\apr_hooks.h"\ - "..\..\srclib\apr-util\include\apr_optional.h"\ - "..\..\srclib\apr-util\include\apr_optional_hooks.h"\ - "..\..\srclib\apr-util\include\apr_rmm.h"\ - "..\..\srclib\apr-util\include\apr_uri.h"\ - "..\..\srclib\apr\include\apr_fnmatch.h"\ - "..\..\srclib\apr\include\apr_hash.h"\ - "..\..\srclib\apr\include\apr_lib.h"\ - "..\..\srclib\apr\include\apr_mmap.h"\ - "..\..\srclib\apr\include\apr_poll.h"\ - "..\..\srclib\apr\include\apr_portable.h"\ - "..\..\srclib\apr\include\apr_strings.h"\ - "..\..\srclib\apr\include\apr_thread_rwlock.h"\ - "..\..\srclib\openssl\inc32\openssl\conf.h"\ - "..\..\srclib\openssl\inc32\openssl\engine.h"\ - "..\..\srclib\openssl\inc32\openssl\store.h"\ - "..\..\srclib\openssl\inc32\openssl\ui.h"\ - "..\..\srclib\openssl\inc32\openssl\x509v3.h"\ - ".\ssl_expr.h"\ - ".\ssl_private.h"\ - ".\ssl_toolkit_compat.h"\ - ".\ssl_util_ssl.h"\ - - -.\ssl_engine_init.c : \ - "..\..\include\ap_config.h"\ - "..\..\include\ap_mmn.h"\ - "..\..\include\ap_regex.h"\ - "..\..\include\ap_release.h"\ - "..\..\include\http_config.h"\ - "..\..\include\http_connection.h"\ - "..\..\include\http_core.h"\ - "..\..\include\http_log.h"\ - "..\..\include\http_main.h"\ - "..\..\include\http_protocol.h"\ - "..\..\include\http_request.h"\ - "..\..\include\http_vhost.h"\ - "..\..\include\httpd.h"\ - "..\..\include\mpm.h"\ - "..\..\include\os.h"\ - "..\..\include\scoreboard.h"\ - "..\..\include\util_cfgtree.h"\ - "..\..\include\util_charset.h"\ - "..\..\include\util_ebcdic.h"\ - "..\..\include\util_filter.h"\ - "..\..\include\util_script.h"\ - "..\..\srclib\apr-util\include\apr_dbm.h"\ - "..\..\srclib\apr-util\include\apr_hooks.h"\ - "..\..\srclib\apr-util\include\apr_optional.h"\ - "..\..\srclib\apr-util\include\apr_optional_hooks.h"\ - "..\..\srclib\apr-util\include\apr_rmm.h"\ - "..\..\srclib\apr-util\include\apr_uri.h"\ - "..\..\srclib\apr\include\apr_fnmatch.h"\ - "..\..\srclib\apr\include\apr_hash.h"\ - "..\..\srclib\apr\include\apr_lib.h"\ - "..\..\srclib\apr\include\apr_mmap.h"\ - "..\..\srclib\apr\include\apr_poll.h"\ - "..\..\srclib\apr\include\apr_portable.h"\ - "..\..\srclib\apr\include\apr_strings.h"\ - "..\..\srclib\apr\include\apr_thread_rwlock.h"\ - "..\..\srclib\openssl\inc32\openssl\conf.h"\ - "..\..\srclib\openssl\inc32\openssl\engine.h"\ - "..\..\srclib\openssl\inc32\openssl\store.h"\ - "..\..\srclib\openssl\inc32\openssl\ui.h"\ - "..\..\srclib\openssl\inc32\openssl\x509v3.h"\ - ".\ssl_expr.h"\ - ".\ssl_private.h"\ - ".\ssl_toolkit_compat.h"\ - ".\ssl_util_ssl.h"\ - - -.\ssl_engine_io.c : \ - "..\..\include\ap_config.h"\ - "..\..\include\ap_mmn.h"\ - "..\..\include\ap_regex.h"\ - "..\..\include\ap_release.h"\ - "..\..\include\http_config.h"\ - "..\..\include\http_connection.h"\ - "..\..\include\http_core.h"\ - "..\..\include\http_log.h"\ - "..\..\include\http_main.h"\ - "..\..\include\http_protocol.h"\ - "..\..\include\http_request.h"\ - "..\..\include\http_vhost.h"\ - "..\..\include\httpd.h"\ - "..\..\include\mpm.h"\ - "..\..\include\os.h"\ - "..\..\include\scoreboard.h"\ - "..\..\include\util_cfgtree.h"\ - "..\..\include\util_charset.h"\ - "..\..\include\util_ebcdic.h"\ - "..\..\include\util_filter.h"\ - "..\..\include\util_script.h"\ - "..\..\srclib\apr-util\include\apr_date.h"\ - "..\..\srclib\apr-util\include\apr_dbm.h"\ - "..\..\srclib\apr-util\include\apr_hooks.h"\ - "..\..\srclib\apr-util\include\apr_optional.h"\ - "..\..\srclib\apr-util\include\apr_optional_hooks.h"\ - "..\..\srclib\apr-util\include\apr_rmm.h"\ - "..\..\srclib\apr-util\include\apr_uri.h"\ - "..\..\srclib\apr\include\apr_fnmatch.h"\ - "..\..\srclib\apr\include\apr_hash.h"\ - "..\..\srclib\apr\include\apr_lib.h"\ - "..\..\srclib\apr\include\apr_mmap.h"\ - "..\..\srclib\apr\include\apr_poll.h"\ - "..\..\srclib\apr\include\apr_portable.h"\ - "..\..\srclib\apr\include\apr_strings.h"\ - "..\..\srclib\apr\include\apr_thread_rwlock.h"\ - "..\..\srclib\openssl\inc32\openssl\conf.h"\ - "..\..\srclib\openssl\inc32\openssl\engine.h"\ - "..\..\srclib\openssl\inc32\openssl\store.h"\ - "..\..\srclib\openssl\inc32\openssl\ui.h"\ - "..\..\srclib\openssl\inc32\openssl\x509v3.h"\ - ".\ssl_expr.h"\ - ".\ssl_private.h"\ - ".\ssl_toolkit_compat.h"\ - ".\ssl_util_ssl.h"\ - - -.\ssl_engine_kernel.c : \ - "..\..\include\ap_config.h"\ - "..\..\include\ap_mmn.h"\ - "..\..\include\ap_regex.h"\ - "..\..\include\ap_release.h"\ - "..\..\include\http_config.h"\ - "..\..\include\http_connection.h"\ - "..\..\include\http_core.h"\ - "..\..\include\http_log.h"\ - "..\..\include\http_main.h"\ - "..\..\include\http_protocol.h"\ - "..\..\include\http_request.h"\ - "..\..\include\http_vhost.h"\ - "..\..\include\httpd.h"\ - "..\..\include\mpm.h"\ - "..\..\include\os.h"\ - "..\..\include\scoreboard.h"\ - "..\..\include\util_cfgtree.h"\ - "..\..\include\util_charset.h"\ - "..\..\include\util_ebcdic.h"\ - "..\..\include\util_filter.h"\ - "..\..\include\util_script.h"\ - "..\..\srclib\apr-util\include\apr_dbm.h"\ - "..\..\srclib\apr-util\include\apr_hooks.h"\ - "..\..\srclib\apr-util\include\apr_optional.h"\ - "..\..\srclib\apr-util\include\apr_optional_hooks.h"\ - "..\..\srclib\apr-util\include\apr_rmm.h"\ - "..\..\srclib\apr-util\include\apr_uri.h"\ - "..\..\srclib\apr\include\apr_fnmatch.h"\ - "..\..\srclib\apr\include\apr_hash.h"\ - "..\..\srclib\apr\include\apr_lib.h"\ - "..\..\srclib\apr\include\apr_mmap.h"\ - "..\..\srclib\apr\include\apr_poll.h"\ - "..\..\srclib\apr\include\apr_portable.h"\ - "..\..\srclib\apr\include\apr_strings.h"\ - "..\..\srclib\apr\include\apr_thread_rwlock.h"\ - "..\..\srclib\openssl\inc32\openssl\conf.h"\ - "..\..\srclib\openssl\inc32\openssl\engine.h"\ - "..\..\srclib\openssl\inc32\openssl\store.h"\ - "..\..\srclib\openssl\inc32\openssl\ui.h"\ - "..\..\srclib\openssl\inc32\openssl\x509v3.h"\ - ".\ssl_expr.h"\ - ".\ssl_private.h"\ - ".\ssl_toolkit_compat.h"\ - ".\ssl_util_ssl.h"\ - - -.\ssl_engine_log.c : \ - "..\..\include\ap_config.h"\ - "..\..\include\ap_mmn.h"\ - "..\..\include\ap_regex.h"\ - "..\..\include\ap_release.h"\ - "..\..\include\http_config.h"\ - "..\..\include\http_connection.h"\ - "..\..\include\http_core.h"\ - "..\..\include\http_log.h"\ - "..\..\include\http_main.h"\ - "..\..\include\http_protocol.h"\ - "..\..\include\http_request.h"\ - "..\..\include\http_vhost.h"\ - "..\..\include\httpd.h"\ - "..\..\include\mpm.h"\ - "..\..\include\os.h"\ - "..\..\include\scoreboard.h"\ - "..\..\include\util_cfgtree.h"\ - "..\..\include\util_charset.h"\ - "..\..\include\util_ebcdic.h"\ - "..\..\include\util_filter.h"\ - "..\..\include\util_script.h"\ - "..\..\srclib\apr-util\include\apr_dbm.h"\ - "..\..\srclib\apr-util\include\apr_hooks.h"\ - "..\..\srclib\apr-util\include\apr_optional.h"\ - "..\..\srclib\apr-util\include\apr_optional_hooks.h"\ - "..\..\srclib\apr-util\include\apr_rmm.h"\ - "..\..\srclib\apr-util\include\apr_uri.h"\ - "..\..\srclib\apr\include\apr_fnmatch.h"\ - "..\..\srclib\apr\include\apr_hash.h"\ - "..\..\srclib\apr\include\apr_lib.h"\ - "..\..\srclib\apr\include\apr_mmap.h"\ - "..\..\srclib\apr\include\apr_poll.h"\ - "..\..\srclib\apr\include\apr_portable.h"\ - "..\..\srclib\apr\include\apr_strings.h"\ - "..\..\srclib\apr\include\apr_thread_rwlock.h"\ - "..\..\srclib\openssl\inc32\openssl\conf.h"\ - "..\..\srclib\openssl\inc32\openssl\engine.h"\ - "..\..\srclib\openssl\inc32\openssl\store.h"\ - "..\..\srclib\openssl\inc32\openssl\ui.h"\ - "..\..\srclib\openssl\inc32\openssl\x509v3.h"\ - ".\ssl_expr.h"\ - ".\ssl_private.h"\ - ".\ssl_toolkit_compat.h"\ - ".\ssl_util_ssl.h"\ - - -.\ssl_engine_mutex.c : \ - "..\..\include\ap_config.h"\ - "..\..\include\ap_mmn.h"\ - "..\..\include\ap_regex.h"\ - "..\..\include\ap_release.h"\ - "..\..\include\http_config.h"\ - "..\..\include\http_connection.h"\ - "..\..\include\http_core.h"\ - "..\..\include\http_log.h"\ - "..\..\include\http_main.h"\ - "..\..\include\http_protocol.h"\ - "..\..\include\http_request.h"\ - "..\..\include\http_vhost.h"\ - "..\..\include\httpd.h"\ - "..\..\include\mpm.h"\ - "..\..\include\os.h"\ - "..\..\include\scoreboard.h"\ - "..\..\include\util_cfgtree.h"\ - "..\..\include\util_charset.h"\ - "..\..\include\util_ebcdic.h"\ - "..\..\include\util_filter.h"\ - "..\..\include\util_script.h"\ - "..\..\srclib\apr-util\include\apr_dbm.h"\ - "..\..\srclib\apr-util\include\apr_hooks.h"\ - "..\..\srclib\apr-util\include\apr_optional.h"\ - "..\..\srclib\apr-util\include\apr_optional_hooks.h"\ - "..\..\srclib\apr-util\include\apr_rmm.h"\ - "..\..\srclib\apr-util\include\apr_uri.h"\ - "..\..\srclib\apr\include\apr_fnmatch.h"\ - "..\..\srclib\apr\include\apr_hash.h"\ - "..\..\srclib\apr\include\apr_lib.h"\ - "..\..\srclib\apr\include\apr_mmap.h"\ - "..\..\srclib\apr\include\apr_poll.h"\ - "..\..\srclib\apr\include\apr_portable.h"\ - "..\..\srclib\apr\include\apr_strings.h"\ - "..\..\srclib\apr\include\apr_thread_rwlock.h"\ - "..\..\srclib\openssl\inc32\openssl\conf.h"\ - "..\..\srclib\openssl\inc32\openssl\engine.h"\ - "..\..\srclib\openssl\inc32\openssl\store.h"\ - "..\..\srclib\openssl\inc32\openssl\ui.h"\ - "..\..\srclib\openssl\inc32\openssl\x509v3.h"\ - ".\ssl_expr.h"\ - ".\ssl_private.h"\ - ".\ssl_toolkit_compat.h"\ - ".\ssl_util_ssl.h"\ - - -.\ssl_engine_pphrase.c : \ - "..\..\include\ap_config.h"\ - "..\..\include\ap_mmn.h"\ - "..\..\include\ap_regex.h"\ - "..\..\include\ap_release.h"\ - "..\..\include\http_config.h"\ - "..\..\include\http_connection.h"\ - "..\..\include\http_core.h"\ - "..\..\include\http_log.h"\ - "..\..\include\http_main.h"\ - "..\..\include\http_protocol.h"\ - "..\..\include\http_request.h"\ - "..\..\include\http_vhost.h"\ - "..\..\include\httpd.h"\ - "..\..\include\mpm.h"\ - "..\..\include\os.h"\ - "..\..\include\scoreboard.h"\ - "..\..\include\util_cfgtree.h"\ - "..\..\include\util_charset.h"\ - "..\..\include\util_ebcdic.h"\ - "..\..\include\util_filter.h"\ - "..\..\include\util_script.h"\ - "..\..\srclib\apr-util\include\apr_dbm.h"\ - "..\..\srclib\apr-util\include\apr_hooks.h"\ - "..\..\srclib\apr-util\include\apr_optional.h"\ - "..\..\srclib\apr-util\include\apr_optional_hooks.h"\ - "..\..\srclib\apr-util\include\apr_rmm.h"\ - "..\..\srclib\apr-util\include\apr_uri.h"\ - "..\..\srclib\apr\include\apr_fnmatch.h"\ - "..\..\srclib\apr\include\apr_hash.h"\ - "..\..\srclib\apr\include\apr_lib.h"\ - "..\..\srclib\apr\include\apr_mmap.h"\ - "..\..\srclib\apr\include\apr_poll.h"\ - "..\..\srclib\apr\include\apr_portable.h"\ - "..\..\srclib\apr\include\apr_strings.h"\ - "..\..\srclib\apr\include\apr_thread_rwlock.h"\ - "..\..\srclib\openssl\inc32\openssl\conf.h"\ - "..\..\srclib\openssl\inc32\openssl\engine.h"\ - "..\..\srclib\openssl\inc32\openssl\store.h"\ - "..\..\srclib\openssl\inc32\openssl\ui.h"\ - "..\..\srclib\openssl\inc32\openssl\x509v3.h"\ - ".\ssl_expr.h"\ - ".\ssl_private.h"\ - ".\ssl_toolkit_compat.h"\ - ".\ssl_util_ssl.h"\ - - -.\ssl_engine_rand.c : \ - "..\..\include\ap_config.h"\ - "..\..\include\ap_mmn.h"\ - "..\..\include\ap_regex.h"\ - "..\..\include\ap_release.h"\ - "..\..\include\http_config.h"\ - "..\..\include\http_connection.h"\ - "..\..\include\http_core.h"\ - "..\..\include\http_log.h"\ - "..\..\include\http_main.h"\ - "..\..\include\http_protocol.h"\ - "..\..\include\http_request.h"\ - "..\..\include\http_vhost.h"\ - "..\..\include\httpd.h"\ - "..\..\include\mpm.h"\ - "..\..\include\os.h"\ - "..\..\include\scoreboard.h"\ - "..\..\include\util_cfgtree.h"\ - "..\..\include\util_charset.h"\ - "..\..\include\util_ebcdic.h"\ - "..\..\include\util_filter.h"\ - "..\..\include\util_script.h"\ - "..\..\srclib\apr-util\include\apr_dbm.h"\ - "..\..\srclib\apr-util\include\apr_hooks.h"\ - "..\..\srclib\apr-util\include\apr_optional.h"\ - "..\..\srclib\apr-util\include\apr_optional_hooks.h"\ - "..\..\srclib\apr-util\include\apr_rmm.h"\ - "..\..\srclib\apr-util\include\apr_uri.h"\ - "..\..\srclib\apr\include\apr_fnmatch.h"\ - "..\..\srclib\apr\include\apr_hash.h"\ - "..\..\srclib\apr\include\apr_lib.h"\ - "..\..\srclib\apr\include\apr_mmap.h"\ - "..\..\srclib\apr\include\apr_poll.h"\ - "..\..\srclib\apr\include\apr_portable.h"\ - "..\..\srclib\apr\include\apr_strings.h"\ - "..\..\srclib\apr\include\apr_thread_rwlock.h"\ - "..\..\srclib\openssl\inc32\openssl\conf.h"\ - "..\..\srclib\openssl\inc32\openssl\engine.h"\ - "..\..\srclib\openssl\inc32\openssl\store.h"\ - "..\..\srclib\openssl\inc32\openssl\ui.h"\ - "..\..\srclib\openssl\inc32\openssl\x509v3.h"\ - ".\ssl_expr.h"\ - ".\ssl_private.h"\ - ".\ssl_toolkit_compat.h"\ - ".\ssl_util_ssl.h"\ - - -.\ssl_engine_vars.c : \ - "..\..\include\ap_config.h"\ - "..\..\include\ap_mmn.h"\ - "..\..\include\ap_regex.h"\ - "..\..\include\ap_release.h"\ - "..\..\include\http_config.h"\ - "..\..\include\http_connection.h"\ - "..\..\include\http_core.h"\ - "..\..\include\http_log.h"\ - "..\..\include\http_main.h"\ - "..\..\include\http_protocol.h"\ - "..\..\include\http_request.h"\ - "..\..\include\http_vhost.h"\ - "..\..\include\httpd.h"\ - "..\..\include\mpm.h"\ - "..\..\include\os.h"\ - "..\..\include\scoreboard.h"\ - "..\..\include\util_cfgtree.h"\ - "..\..\include\util_charset.h"\ - "..\..\include\util_ebcdic.h"\ - "..\..\include\util_filter.h"\ - "..\..\include\util_script.h"\ - "..\..\srclib\apr-util\include\apr_dbm.h"\ - "..\..\srclib\apr-util\include\apr_hooks.h"\ - "..\..\srclib\apr-util\include\apr_optional.h"\ - "..\..\srclib\apr-util\include\apr_optional_hooks.h"\ - "..\..\srclib\apr-util\include\apr_rmm.h"\ - "..\..\srclib\apr-util\include\apr_uri.h"\ - "..\..\srclib\apr\include\apr_fnmatch.h"\ - "..\..\srclib\apr\include\apr_hash.h"\ - "..\..\srclib\apr\include\apr_lib.h"\ - "..\..\srclib\apr\include\apr_mmap.h"\ - "..\..\srclib\apr\include\apr_poll.h"\ - "..\..\srclib\apr\include\apr_portable.h"\ - "..\..\srclib\apr\include\apr_strings.h"\ - "..\..\srclib\apr\include\apr_thread_rwlock.h"\ - "..\..\srclib\openssl\inc32\openssl\conf.h"\ - "..\..\srclib\openssl\inc32\openssl\engine.h"\ - "..\..\srclib\openssl\inc32\openssl\store.h"\ - "..\..\srclib\openssl\inc32\openssl\ui.h"\ - "..\..\srclib\openssl\inc32\openssl\x509v3.h"\ - "..\loggers\mod_log_config.h"\ - ".\mod_ssl.h"\ - ".\ssl_expr.h"\ - ".\ssl_private.h"\ - ".\ssl_toolkit_compat.h"\ - ".\ssl_util_ssl.h"\ - - -.\ssl_expr.c : \ - "..\..\include\ap_config.h"\ - "..\..\include\ap_mmn.h"\ - "..\..\include\ap_regex.h"\ - "..\..\include\ap_release.h"\ - "..\..\include\http_config.h"\ - "..\..\include\http_connection.h"\ - "..\..\include\http_core.h"\ - "..\..\include\http_log.h"\ - "..\..\include\http_main.h"\ - "..\..\include\http_protocol.h"\ - "..\..\include\http_request.h"\ - "..\..\include\http_vhost.h"\ - "..\..\include\httpd.h"\ - "..\..\include\mpm.h"\ - "..\..\include\os.h"\ - "..\..\include\scoreboard.h"\ - "..\..\include\util_cfgtree.h"\ - "..\..\include\util_charset.h"\ - "..\..\include\util_ebcdic.h"\ - "..\..\include\util_filter.h"\ - "..\..\include\util_script.h"\ - "..\..\srclib\apr-util\include\apr_dbm.h"\ - "..\..\srclib\apr-util\include\apr_hooks.h"\ - "..\..\srclib\apr-util\include\apr_optional.h"\ - "..\..\srclib\apr-util\include\apr_optional_hooks.h"\ - "..\..\srclib\apr-util\include\apr_rmm.h"\ - "..\..\srclib\apr-util\include\apr_uri.h"\ - "..\..\srclib\apr\include\apr_fnmatch.h"\ - "..\..\srclib\apr\include\apr_hash.h"\ - "..\..\srclib\apr\include\apr_lib.h"\ - "..\..\srclib\apr\include\apr_mmap.h"\ - "..\..\srclib\apr\include\apr_poll.h"\ - "..\..\srclib\apr\include\apr_portable.h"\ - "..\..\srclib\apr\include\apr_strings.h"\ - "..\..\srclib\apr\include\apr_thread_rwlock.h"\ - "..\..\srclib\openssl\inc32\openssl\conf.h"\ - "..\..\srclib\openssl\inc32\openssl\engine.h"\ - "..\..\srclib\openssl\inc32\openssl\store.h"\ - "..\..\srclib\openssl\inc32\openssl\ui.h"\ - "..\..\srclib\openssl\inc32\openssl\x509v3.h"\ - ".\ssl_expr.h"\ - ".\ssl_private.h"\ - ".\ssl_toolkit_compat.h"\ - ".\ssl_util_ssl.h"\ - - -.\ssl_expr_eval.c : \ - "..\..\include\ap_config.h"\ - "..\..\include\ap_mmn.h"\ - "..\..\include\ap_regex.h"\ - "..\..\include\ap_release.h"\ - "..\..\include\http_config.h"\ - "..\..\include\http_connection.h"\ - "..\..\include\http_core.h"\ - "..\..\include\http_log.h"\ - "..\..\include\http_main.h"\ - "..\..\include\http_protocol.h"\ - "..\..\include\http_request.h"\ - "..\..\include\http_vhost.h"\ - "..\..\include\httpd.h"\ - "..\..\include\mpm.h"\ - "..\..\include\os.h"\ - "..\..\include\scoreboard.h"\ - "..\..\include\util_cfgtree.h"\ - "..\..\include\util_charset.h"\ - "..\..\include\util_ebcdic.h"\ - "..\..\include\util_filter.h"\ - "..\..\include\util_script.h"\ - "..\..\srclib\apr-util\include\apr_dbm.h"\ - "..\..\srclib\apr-util\include\apr_hooks.h"\ - "..\..\srclib\apr-util\include\apr_optional.h"\ - "..\..\srclib\apr-util\include\apr_optional_hooks.h"\ - "..\..\srclib\apr-util\include\apr_rmm.h"\ - "..\..\srclib\apr-util\include\apr_uri.h"\ - "..\..\srclib\apr\include\apr_fnmatch.h"\ - "..\..\srclib\apr\include\apr_hash.h"\ - "..\..\srclib\apr\include\apr_lib.h"\ - "..\..\srclib\apr\include\apr_mmap.h"\ - "..\..\srclib\apr\include\apr_poll.h"\ - "..\..\srclib\apr\include\apr_portable.h"\ - "..\..\srclib\apr\include\apr_strings.h"\ - "..\..\srclib\apr\include\apr_thread_rwlock.h"\ - "..\..\srclib\openssl\inc32\openssl\conf.h"\ - "..\..\srclib\openssl\inc32\openssl\engine.h"\ - "..\..\srclib\openssl\inc32\openssl\store.h"\ - "..\..\srclib\openssl\inc32\openssl\ui.h"\ - "..\..\srclib\openssl\inc32\openssl\x509v3.h"\ - ".\ssl_expr.h"\ - ".\ssl_private.h"\ - ".\ssl_toolkit_compat.h"\ - ".\ssl_util_ssl.h"\ - - -.\ssl_expr_parse.c : \ - "..\..\include\ap_config.h"\ - "..\..\include\ap_mmn.h"\ - "..\..\include\ap_regex.h"\ - "..\..\include\ap_release.h"\ - "..\..\include\http_config.h"\ - "..\..\include\http_connection.h"\ - "..\..\include\http_core.h"\ - "..\..\include\http_log.h"\ - "..\..\include\http_main.h"\ - "..\..\include\http_protocol.h"\ - "..\..\include\http_request.h"\ - "..\..\include\http_vhost.h"\ - "..\..\include\httpd.h"\ - "..\..\include\mpm.h"\ - "..\..\include\os.h"\ - "..\..\include\scoreboard.h"\ - "..\..\include\util_cfgtree.h"\ - "..\..\include\util_charset.h"\ - "..\..\include\util_ebcdic.h"\ - "..\..\include\util_filter.h"\ - "..\..\include\util_script.h"\ - "..\..\srclib\apr-util\include\apr_dbm.h"\ - "..\..\srclib\apr-util\include\apr_hooks.h"\ - "..\..\srclib\apr-util\include\apr_optional.h"\ - "..\..\srclib\apr-util\include\apr_optional_hooks.h"\ - "..\..\srclib\apr-util\include\apr_rmm.h"\ - "..\..\srclib\apr-util\include\apr_uri.h"\ - "..\..\srclib\apr\include\apr_fnmatch.h"\ - "..\..\srclib\apr\include\apr_hash.h"\ - "..\..\srclib\apr\include\apr_lib.h"\ - "..\..\srclib\apr\include\apr_mmap.h"\ - "..\..\srclib\apr\include\apr_poll.h"\ - "..\..\srclib\apr\include\apr_portable.h"\ - "..\..\srclib\apr\include\apr_strings.h"\ - "..\..\srclib\apr\include\apr_thread_rwlock.h"\ - "..\..\srclib\openssl\inc32\openssl\conf.h"\ - "..\..\srclib\openssl\inc32\openssl\engine.h"\ - "..\..\srclib\openssl\inc32\openssl\store.h"\ - "..\..\srclib\openssl\inc32\openssl\ui.h"\ - "..\..\srclib\openssl\inc32\openssl\x509v3.h"\ - ".\ssl_expr.h"\ - ".\ssl_private.h"\ - ".\ssl_toolkit_compat.h"\ - ".\ssl_util_ssl.h"\ - - -.\ssl_expr_scan.c : \ - "..\..\include\ap_config.h"\ - "..\..\include\ap_mmn.h"\ - "..\..\include\ap_regex.h"\ - "..\..\include\ap_release.h"\ - "..\..\include\http_config.h"\ - "..\..\include\http_connection.h"\ - "..\..\include\http_core.h"\ - "..\..\include\http_log.h"\ - "..\..\include\http_main.h"\ - "..\..\include\http_protocol.h"\ - "..\..\include\http_request.h"\ - "..\..\include\http_vhost.h"\ - "..\..\include\httpd.h"\ - "..\..\include\mpm.h"\ - "..\..\include\os.h"\ - "..\..\include\scoreboard.h"\ - "..\..\include\util_cfgtree.h"\ - "..\..\include\util_charset.h"\ - "..\..\include\util_ebcdic.h"\ - "..\..\include\util_filter.h"\ - "..\..\include\util_script.h"\ - "..\..\srclib\apr-util\include\apr_dbm.h"\ - "..\..\srclib\apr-util\include\apr_hooks.h"\ - "..\..\srclib\apr-util\include\apr_optional.h"\ - "..\..\srclib\apr-util\include\apr_optional_hooks.h"\ - "..\..\srclib\apr-util\include\apr_rmm.h"\ - "..\..\srclib\apr-util\include\apr_uri.h"\ - "..\..\srclib\apr\include\apr_fnmatch.h"\ - "..\..\srclib\apr\include\apr_hash.h"\ - "..\..\srclib\apr\include\apr_lib.h"\ - "..\..\srclib\apr\include\apr_mmap.h"\ - "..\..\srclib\apr\include\apr_poll.h"\ - "..\..\srclib\apr\include\apr_portable.h"\ - "..\..\srclib\apr\include\apr_strings.h"\ - "..\..\srclib\apr\include\apr_thread_rwlock.h"\ - "..\..\srclib\openssl\inc32\openssl\conf.h"\ - "..\..\srclib\openssl\inc32\openssl\engine.h"\ - "..\..\srclib\openssl\inc32\openssl\store.h"\ - "..\..\srclib\openssl\inc32\openssl\ui.h"\ - "..\..\srclib\openssl\inc32\openssl\x509v3.h"\ - ".\ssl_expr.h"\ - ".\ssl_expr_parse.h"\ - ".\ssl_private.h"\ - ".\ssl_toolkit_compat.h"\ - ".\ssl_util_ssl.h"\ - - -.\ssl_scache.c : \ - "..\..\include\ap_config.h"\ - "..\..\include\ap_mmn.h"\ - "..\..\include\ap_regex.h"\ - "..\..\include\ap_release.h"\ - "..\..\include\http_config.h"\ - "..\..\include\http_connection.h"\ - "..\..\include\http_core.h"\ - "..\..\include\http_log.h"\ - "..\..\include\http_main.h"\ - "..\..\include\http_protocol.h"\ - "..\..\include\http_request.h"\ - "..\..\include\http_vhost.h"\ - "..\..\include\httpd.h"\ - "..\..\include\mpm.h"\ - "..\..\include\os.h"\ - "..\..\include\scoreboard.h"\ - "..\..\include\util_cfgtree.h"\ - "..\..\include\util_charset.h"\ - "..\..\include\util_ebcdic.h"\ - "..\..\include\util_filter.h"\ - "..\..\include\util_script.h"\ - "..\..\srclib\apr-util\include\apr_dbm.h"\ - "..\..\srclib\apr-util\include\apr_hooks.h"\ - "..\..\srclib\apr-util\include\apr_optional.h"\ - "..\..\srclib\apr-util\include\apr_optional_hooks.h"\ - "..\..\srclib\apr-util\include\apr_rmm.h"\ - "..\..\srclib\apr-util\include\apr_uri.h"\ - "..\..\srclib\apr\include\apr_fnmatch.h"\ - "..\..\srclib\apr\include\apr_hash.h"\ - "..\..\srclib\apr\include\apr_lib.h"\ - "..\..\srclib\apr\include\apr_mmap.h"\ - "..\..\srclib\apr\include\apr_poll.h"\ - "..\..\srclib\apr\include\apr_portable.h"\ - "..\..\srclib\apr\include\apr_strings.h"\ - "..\..\srclib\apr\include\apr_thread_rwlock.h"\ - "..\..\srclib\openssl\inc32\openssl\conf.h"\ - "..\..\srclib\openssl\inc32\openssl\engine.h"\ - "..\..\srclib\openssl\inc32\openssl\store.h"\ - "..\..\srclib\openssl\inc32\openssl\ui.h"\ - "..\..\srclib\openssl\inc32\openssl\x509v3.h"\ - "..\generators\mod_status.h"\ - ".\ssl_expr.h"\ - ".\ssl_private.h"\ - ".\ssl_toolkit_compat.h"\ - ".\ssl_util_ssl.h"\ - - -.\ssl_scache_dbm.c : \ - "..\..\include\ap_config.h"\ - "..\..\include\ap_mmn.h"\ - "..\..\include\ap_regex.h"\ - "..\..\include\ap_release.h"\ - "..\..\include\http_config.h"\ - "..\..\include\http_connection.h"\ - "..\..\include\http_core.h"\ - "..\..\include\http_log.h"\ - "..\..\include\http_main.h"\ - "..\..\include\http_protocol.h"\ - "..\..\include\http_request.h"\ - "..\..\include\http_vhost.h"\ - "..\..\include\httpd.h"\ - "..\..\include\mpm.h"\ - "..\..\include\os.h"\ - "..\..\include\scoreboard.h"\ - "..\..\include\util_cfgtree.h"\ - "..\..\include\util_charset.h"\ - "..\..\include\util_ebcdic.h"\ - "..\..\include\util_filter.h"\ - "..\..\include\util_script.h"\ - "..\..\srclib\apr-util\include\apr_dbm.h"\ - "..\..\srclib\apr-util\include\apr_hooks.h"\ - "..\..\srclib\apr-util\include\apr_optional.h"\ - "..\..\srclib\apr-util\include\apr_optional_hooks.h"\ - "..\..\srclib\apr-util\include\apr_rmm.h"\ - "..\..\srclib\apr-util\include\apr_uri.h"\ - "..\..\srclib\apr\include\apr_fnmatch.h"\ - "..\..\srclib\apr\include\apr_hash.h"\ - "..\..\srclib\apr\include\apr_lib.h"\ - "..\..\srclib\apr\include\apr_mmap.h"\ - "..\..\srclib\apr\include\apr_poll.h"\ - "..\..\srclib\apr\include\apr_portable.h"\ - "..\..\srclib\apr\include\apr_strings.h"\ - "..\..\srclib\apr\include\apr_thread_rwlock.h"\ - "..\..\srclib\openssl\inc32\openssl\conf.h"\ - "..\..\srclib\openssl\inc32\openssl\engine.h"\ - "..\..\srclib\openssl\inc32\openssl\store.h"\ - "..\..\srclib\openssl\inc32\openssl\ui.h"\ - "..\..\srclib\openssl\inc32\openssl\x509v3.h"\ - ".\ssl_expr.h"\ - ".\ssl_private.h"\ - ".\ssl_toolkit_compat.h"\ - ".\ssl_util_ssl.h"\ - - -.\ssl_scache_dc.c : \ - "..\..\include\ap_config.h"\ - "..\..\include\ap_mmn.h"\ - "..\..\include\ap_regex.h"\ - "..\..\include\ap_release.h"\ - "..\..\include\http_config.h"\ - "..\..\include\http_connection.h"\ - "..\..\include\http_core.h"\ - "..\..\include\http_log.h"\ - "..\..\include\http_main.h"\ - "..\..\include\http_protocol.h"\ - "..\..\include\http_request.h"\ - "..\..\include\http_vhost.h"\ - "..\..\include\httpd.h"\ - "..\..\include\mpm.h"\ - "..\..\include\os.h"\ - "..\..\include\scoreboard.h"\ - "..\..\include\util_cfgtree.h"\ - "..\..\include\util_charset.h"\ - "..\..\include\util_ebcdic.h"\ - "..\..\include\util_filter.h"\ - "..\..\include\util_script.h"\ - "..\..\srclib\apr-util\include\apr_dbm.h"\ - "..\..\srclib\apr-util\include\apr_hooks.h"\ - "..\..\srclib\apr-util\include\apr_optional.h"\ - "..\..\srclib\apr-util\include\apr_optional_hooks.h"\ - "..\..\srclib\apr-util\include\apr_rmm.h"\ - "..\..\srclib\apr-util\include\apr_uri.h"\ - "..\..\srclib\apr\include\apr_fnmatch.h"\ - "..\..\srclib\apr\include\apr_hash.h"\ - "..\..\srclib\apr\include\apr_lib.h"\ - "..\..\srclib\apr\include\apr_mmap.h"\ - "..\..\srclib\apr\include\apr_poll.h"\ - "..\..\srclib\apr\include\apr_portable.h"\ - "..\..\srclib\apr\include\apr_strings.h"\ - "..\..\srclib\apr\include\apr_thread_rwlock.h"\ - "..\..\srclib\openssl\inc32\openssl\conf.h"\ - "..\..\srclib\openssl\inc32\openssl\engine.h"\ - "..\..\srclib\openssl\inc32\openssl\store.h"\ - "..\..\srclib\openssl\inc32\openssl\ui.h"\ - "..\..\srclib\openssl\inc32\openssl\x509v3.h"\ - ".\ssl_expr.h"\ - ".\ssl_private.h"\ - ".\ssl_toolkit_compat.h"\ - ".\ssl_util_ssl.h"\ - - -.\ssl_scache_shmcb.c : \ - "..\..\include\ap_config.h"\ - "..\..\include\ap_mmn.h"\ - "..\..\include\ap_regex.h"\ - "..\..\include\ap_release.h"\ - "..\..\include\http_config.h"\ - "..\..\include\http_connection.h"\ - "..\..\include\http_core.h"\ - "..\..\include\http_log.h"\ - "..\..\include\http_main.h"\ - "..\..\include\http_protocol.h"\ - "..\..\include\http_request.h"\ - "..\..\include\http_vhost.h"\ - "..\..\include\httpd.h"\ - "..\..\include\mpm.h"\ - "..\..\include\os.h"\ - "..\..\include\scoreboard.h"\ - "..\..\include\util_cfgtree.h"\ - "..\..\include\util_charset.h"\ - "..\..\include\util_ebcdic.h"\ - "..\..\include\util_filter.h"\ - "..\..\include\util_script.h"\ - "..\..\srclib\apr-util\include\apr_dbm.h"\ - "..\..\srclib\apr-util\include\apr_hooks.h"\ - "..\..\srclib\apr-util\include\apr_optional.h"\ - "..\..\srclib\apr-util\include\apr_optional_hooks.h"\ - "..\..\srclib\apr-util\include\apr_rmm.h"\ - "..\..\srclib\apr-util\include\apr_uri.h"\ - "..\..\srclib\apr\include\apr_fnmatch.h"\ - "..\..\srclib\apr\include\apr_hash.h"\ - "..\..\srclib\apr\include\apr_lib.h"\ - "..\..\srclib\apr\include\apr_mmap.h"\ - "..\..\srclib\apr\include\apr_poll.h"\ - "..\..\srclib\apr\include\apr_portable.h"\ - "..\..\srclib\apr\include\apr_strings.h"\ - "..\..\srclib\apr\include\apr_thread_rwlock.h"\ - "..\..\srclib\openssl\inc32\openssl\conf.h"\ - "..\..\srclib\openssl\inc32\openssl\engine.h"\ - "..\..\srclib\openssl\inc32\openssl\store.h"\ - "..\..\srclib\openssl\inc32\openssl\ui.h"\ - "..\..\srclib\openssl\inc32\openssl\x509v3.h"\ - ".\ssl_expr.h"\ - ".\ssl_private.h"\ - ".\ssl_toolkit_compat.h"\ - ".\ssl_util_ssl.h"\ - - -.\ssl_util.c : \ - "..\..\include\ap_config.h"\ - "..\..\include\ap_mmn.h"\ - "..\..\include\ap_mpm.h"\ - "..\..\include\ap_regex.h"\ - "..\..\include\ap_release.h"\ - "..\..\include\http_config.h"\ - "..\..\include\http_connection.h"\ - "..\..\include\http_core.h"\ - "..\..\include\http_log.h"\ - "..\..\include\http_main.h"\ - "..\..\include\http_protocol.h"\ - "..\..\include\http_request.h"\ - "..\..\include\http_vhost.h"\ - "..\..\include\httpd.h"\ - "..\..\include\mpm.h"\ - "..\..\include\os.h"\ - "..\..\include\scoreboard.h"\ - "..\..\include\util_cfgtree.h"\ - "..\..\include\util_charset.h"\ - "..\..\include\util_ebcdic.h"\ - "..\..\include\util_filter.h"\ - "..\..\include\util_script.h"\ - "..\..\srclib\apr-util\include\apr_dbm.h"\ - "..\..\srclib\apr-util\include\apr_hooks.h"\ - "..\..\srclib\apr-util\include\apr_optional.h"\ - "..\..\srclib\apr-util\include\apr_optional_hooks.h"\ - "..\..\srclib\apr-util\include\apr_rmm.h"\ - "..\..\srclib\apr-util\include\apr_uri.h"\ - "..\..\srclib\apr\include\apr_fnmatch.h"\ - "..\..\srclib\apr\include\apr_hash.h"\ - "..\..\srclib\apr\include\apr_lib.h"\ - "..\..\srclib\apr\include\apr_mmap.h"\ - "..\..\srclib\apr\include\apr_poll.h"\ - "..\..\srclib\apr\include\apr_portable.h"\ - "..\..\srclib\apr\include\apr_strings.h"\ - "..\..\srclib\apr\include\apr_thread_rwlock.h"\ - "..\..\srclib\openssl\inc32\openssl\conf.h"\ - "..\..\srclib\openssl\inc32\openssl\engine.h"\ - "..\..\srclib\openssl\inc32\openssl\store.h"\ - "..\..\srclib\openssl\inc32\openssl\ui.h"\ - "..\..\srclib\openssl\inc32\openssl\x509v3.h"\ - ".\ssl_expr.h"\ - ".\ssl_private.h"\ - ".\ssl_toolkit_compat.h"\ - ".\ssl_util_ssl.h"\ - - -.\ssl_util_ssl.c : \ - "..\..\include\ap_config.h"\ - "..\..\include\ap_mmn.h"\ - "..\..\include\ap_regex.h"\ - "..\..\include\ap_release.h"\ - "..\..\include\http_config.h"\ - "..\..\include\http_connection.h"\ - "..\..\include\http_core.h"\ - "..\..\include\http_log.h"\ - "..\..\include\http_main.h"\ - "..\..\include\http_protocol.h"\ - "..\..\include\http_request.h"\ - "..\..\include\http_vhost.h"\ - "..\..\include\httpd.h"\ - "..\..\include\mpm.h"\ - "..\..\include\os.h"\ - "..\..\include\scoreboard.h"\ - "..\..\include\util_cfgtree.h"\ - "..\..\include\util_charset.h"\ - "..\..\include\util_ebcdic.h"\ - "..\..\include\util_filter.h"\ - "..\..\include\util_script.h"\ - "..\..\srclib\apr-util\include\apr_dbm.h"\ - "..\..\srclib\apr-util\include\apr_hooks.h"\ - "..\..\srclib\apr-util\include\apr_optional.h"\ - "..\..\srclib\apr-util\include\apr_optional_hooks.h"\ - "..\..\srclib\apr-util\include\apr_rmm.h"\ - "..\..\srclib\apr-util\include\apr_uri.h"\ - "..\..\srclib\apr\include\apr_fnmatch.h"\ - "..\..\srclib\apr\include\apr_hash.h"\ - "..\..\srclib\apr\include\apr_lib.h"\ - "..\..\srclib\apr\include\apr_mmap.h"\ - "..\..\srclib\apr\include\apr_poll.h"\ - "..\..\srclib\apr\include\apr_portable.h"\ - "..\..\srclib\apr\include\apr_strings.h"\ - "..\..\srclib\apr\include\apr_thread_rwlock.h"\ - "..\..\srclib\openssl\inc32\openssl\conf.h"\ - "..\..\srclib\openssl\inc32\openssl\engine.h"\ - "..\..\srclib\openssl\inc32\openssl\store.h"\ - "..\..\srclib\openssl\inc32\openssl\ui.h"\ - "..\..\srclib\openssl\inc32\openssl\x509v3.h"\ - ".\ssl_expr.h"\ - ".\ssl_private.h"\ - ".\ssl_toolkit_compat.h"\ - ".\ssl_util_ssl.h"\ - - -!IF "$(CFG)" == "mod_ssl - Win32 Release" - -!ELSEIF "$(CFG)" == "mod_ssl - Win32 Debug" - -!ELSEIF "$(CFG)" == "mod_ssl - Win32 Lexical" - -!ENDIF - -!IF "$(CFG)" == "mod_ssl - Win32 Release" - -!ELSEIF "$(CFG)" == "mod_ssl - Win32 Debug" - -!ELSEIF "$(CFG)" == "mod_ssl - Win32 Lexical" - -!ENDIF - -..\..\build\win32\httpd.rc : \ - "..\..\include\ap_release.h"\ - diff --git a/modules/ssl/mod_ssl.dsp b/modules/ssl/mod_ssl.dsp index 19aa6fb6..fc86a7b6 100644 --- a/modules/ssl/mod_ssl.dsp +++ b/modules/ssl/mod_ssl.dsp @@ -19,7 +19,6 @@ CFG=mod_ssl - Win32 Release !MESSAGE !MESSAGE "mod_ssl - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") !MESSAGE "mod_ssl - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") -!MESSAGE "mod_ssl - Win32 Lexical" (based on "Win32 (x86) Dynamic-Link Library") !MESSAGE # Begin Project @@ -94,45 +93,12 @@ PostBuild_Desc=Embed .manifest PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2 # End Special Build Tool -!ELSEIF "$(CFG)" == "mod_ssl - Win32 Lexical" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "Release" -# PROP BASE Intermediate_Dir "Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "Release" -# PROP Intermediate_Dir "Release" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c -# ADD CPP /nologo /MD /W3 /O2 /Oy- /Zi /I "../../include" /I "../generators" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /I "../../srclib/openssl/inc32" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "WIN32_LEAN_AND_MEAN" /D "NO_IDEA" /D "NO_RC5" /D "NO_MDC2" /D "OPENSSL_NO_IDEA" /D "OPENSSL_NO_RC5" /D "OPENSSL_NO_MDC2" /D "HAVE_OPENSSL" /D "HAVE_SSL_SET_STATE" /D "HAVE_OPENSSL_ENGINE_H" /D "HAVE_ENGINE_INIT" /D "HAVE_ENGINE_LOAD_BUILTIN_ENGINES" /Fd"Release\mod_ssl_src" /FD /c -# ADD BASE MTL /nologo /D "NDEBUG" /win32 -# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /fo"Release/mod_ssl.res" /i "../../include" /i "../../srclib/apr/include" /d "NDEBUG" /d BIN_NAME="mod_ssl.so" /d LONG_NAME="proxy_ssl_module for Apache" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /out:".\Release\mod_ssl.so" /base:@..\..\os\win32\BaseAddr.ref,mod_ssl.so -# ADD LINK32 kernel32.lib user32.lib wsock32.lib ws2_32.lib advapi32.lib gdi32.lib libeay32.lib ssleay32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Release\mod_ssl.so" /libpath:"../../srclib/openssl/out32dll" /libpath:"../../srclib/openssl/out32" /base:@..\..\os\win32\BaseAddr.ref,mod_ssl.so /opt:ref -# Begin Special Build Tool -TargetPath=.\Release\mod_ssl.so -SOURCE="$(InputPath)" -PostBuild_Desc=Embed .manifest -PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2 -# End Special Build Tool - !ENDIF # Begin Target # Name "mod_ssl - Win32 Release" # Name "mod_ssl - Win32 Debug" -# Name "mod_ssl - Win32 Lexical" # Begin Group "Source Files" # PROP Default_Filter "*.c" @@ -182,19 +148,11 @@ SOURCE=.\ssl_engine_vars.c # End Source File # Begin Source File -SOURCE=.\ssl_expr.c +SOURCE=.\ssl_engine_ocsp.c # End Source File # Begin Source File -SOURCE=.\ssl_expr_eval.c -# End Source File -# Begin Source File - -SOURCE=.\ssl_expr_parse.c -# End Source File -# Begin Source File - -SOURCE=.\ssl_expr_scan.c +SOURCE=.\ssl_util_ocsp.c # End Source File # Begin Source File @@ -202,15 +160,7 @@ SOURCE=.\ssl_scache.c # End Source File # Begin Source File -SOURCE=.\ssl_scache_dbm.c -# End Source File -# Begin Source File - -SOURCE=.\ssl_scache_shmcb.c -# End Source File -# Begin Source File - -SOURCE=.\ssl_scache_dc.c +SOURCE=.\ssl_util_stapling.c # End Source File # Begin Source File @@ -230,22 +180,10 @@ SOURCE=.\mod_ssl.h # End Source File # Begin Source File -SOURCE=.\ssl_expr.h -# End Source File -# Begin Source File - SOURCE=.\ssl_private.h # End Source File # Begin Source File -SOURCE=.\ssl_expr_parse.h -# End Source File -# Begin Source File - -SOURCE=.\ssl_toolkit_compat.h -# End Source File -# Begin Source File - SOURCE=.\ssl_util_ssl.h # End Source File # Begin Source File @@ -253,73 +191,6 @@ SOURCE=.\ssl_util_ssl.h SOURCE=.\ssl_util_table.h # End Source File # End Group -# Begin Group "Generated Files" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\ssl_expr_parse.y - -!IF "$(CFG)" == "mod_ssl - Win32 Release" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "mod_ssl - Win32 Debug" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "mod_ssl - Win32 Lexical" - -# PROP Ignore_Default_Tool 1 -# Begin Custom Build - Generating ssl_expr_parse.c/.h from ssl_expr_parse.y -InputPath=.\ssl_expr_parse.y - -BuildCmds= \ - bison -y -d ssl_expr_parse.y \ - sed -e "s;yy;ssl_expr_yy;g" -e "/#if defined(c_plusplus) || defined(__cplusplus)/,/#endif/d" <y.tab.c >ssl_expr_parse.c \ - del y.tab.c \ - sed -e "s;yy;ssl_expr_yy;g" <y.tab.h >ssl_expr_parse.h \ - del y.tab.h - -"ssl_expr_parse.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" - $(BuildCmds) - -"ssl_expr_parse.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" - $(BuildCmds) -# End Custom Build - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\ssl_expr_scan.l - -!IF "$(CFG)" == "mod_ssl - Win32 Release" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "mod_ssl - Win32 Debug" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "mod_ssl - Win32 Lexical" - -# PROP Ignore_Default_Tool 1 -# Begin Custom Build - Generating ssl_expr_scan.c from ssl_expr_scan.l -InputPath=.\ssl_expr_scan.l - -"ssl_expr_scan.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" - flex -Pssl_expr_yy -s -B ssl_expr_scan.l - sed -e "/$$Header:/d" <lex.ssl_expr_yy.c >ssl_expr_scan.c - del lex.ssl_expr_yy.c - -# End Custom Build - -!ENDIF - -# End Source File -# End Group # Begin Source File SOURCE=..\..\build\win32\httpd.rc diff --git a/modules/ssl/mod_ssl.h b/modules/ssl/mod_ssl.h index ab2f90e5..48984e24 100644 --- a/modules/ssl/mod_ssl.h +++ b/modules/ssl/mod_ssl.h @@ -36,15 +36,20 @@ APR_DECLARE_OPTIONAL_FN(char *, ssl_var_lookup, conn_rec *, request_rec *, char *)); -/** The ssl_ext_lookup() optional function retrieves the value of a SSL - * certificate X.509 extension. The client certificate is used if - * peer is non-zero; the server certificate is used otherwise. The - * oidnum parameter specifies the numeric OID (e.g. "1.2.3.4") of the - * desired extension. The string value of the extension is returned, - * or NULL on error. */ -APR_DECLARE_OPTIONAL_FN(const char *, ssl_ext_lookup, +/** The ssl_ext_list() optional function attempts to build an array + * of all the values contained in the named X.509 extension. The + * returned array will be created in the supplied pool. + * The client certificate is used if peer is non-zero; the server + * certificate is used otherwise. + * Extension specifies the extensions to use as a string. This can be + * one of the "known" long or short names, or a numeric OID, + * e.g. "1.2.3.4", 'nsComment' and 'DN' are all valid. + * A pointer to an apr_array_header_t structure is returned if at + * least one matching extension is found, NULL otherwise. + */ +APR_DECLARE_OPTIONAL_FN(apr_array_header_t *, ssl_ext_list, (apr_pool_t *p, conn_rec *c, int peer, - const char *oidnum)); + const char *extension)); /** An optional function which returns non-zero if the given connection * is using SSL/TLS. */ @@ -58,7 +63,5 @@ APR_DECLARE_OPTIONAL_FN(int, ssl_proxy_enable, (conn_rec *)); APR_DECLARE_OPTIONAL_FN(int, ssl_engine_disable, (conn_rec *)); -APR_DECLARE_OPTIONAL_FN(apr_array_header_t *, ssl_extlist_by_oid, (request_rec *r, const char *oidstr)); - #endif /* __MOD_SSL_H__ */ /** @} */ diff --git a/modules/ssl/mod_ssl.mak b/modules/ssl/mod_ssl.mak deleted file mode 100644 index 003dad97..00000000 --- a/modules/ssl/mod_ssl.mak +++ /dev/null @@ -1,733 +0,0 @@ -# Microsoft Developer Studio Generated NMAKE File, Based on mod_ssl.dsp -!IF "$(CFG)" == "" -CFG=mod_ssl - Win32 Release -!MESSAGE No configuration specified. Defaulting to mod_ssl - Win32 Release. -!ENDIF - -!IF "$(CFG)" != "mod_ssl - Win32 Release" && "$(CFG)" != "mod_ssl - Win32 Debug" && "$(CFG)" != "mod_ssl - Win32 Lexical" -!MESSAGE Invalid configuration "$(CFG)" specified. -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "mod_ssl.mak" CFG="mod_ssl - Win32 Release" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "mod_ssl - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") -!MESSAGE "mod_ssl - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") -!MESSAGE "mod_ssl - Win32 Lexical" (based on "Win32 (x86) Dynamic-Link Library") -!MESSAGE -!ERROR An invalid configuration is specified. -!ENDIF - -!IF "$(OS)" == "Windows_NT" -NULL= -!ELSE -NULL=nul -!ENDIF - -!IF "$(CFG)" == "mod_ssl - Win32 Release" - -OUTDIR=.\Release -INTDIR=.\Release -DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep -# Begin Custom Macros -OutDir=.\Release -# End Custom Macros - -!IF "$(RECURSE)" == "0" - -ALL : "$(OUTDIR)\mod_ssl.so" "$(DS_POSTBUILD_DEP)" - -!ELSE - -ALL : "libhttpd - Win32 Release" "libaprutil - Win32 Release" "libapr - Win32 Release" "$(OUTDIR)\mod_ssl.so" "$(DS_POSTBUILD_DEP)" - -!ENDIF - -!IF "$(RECURSE)" == "1" -CLEAN :"libapr - Win32 ReleaseCLEAN" "libaprutil - Win32 ReleaseCLEAN" "libhttpd - Win32 ReleaseCLEAN" -!ELSE -CLEAN : -!ENDIF - -@erase "$(INTDIR)\mod_ssl.obj" - -@erase "$(INTDIR)\mod_ssl.res" - -@erase "$(INTDIR)\mod_ssl_src.idb" - -@erase "$(INTDIR)\mod_ssl_src.pdb" - -@erase "$(INTDIR)\ssl_engine_config.obj" - -@erase "$(INTDIR)\ssl_engine_dh.obj" - -@erase "$(INTDIR)\ssl_engine_init.obj" - -@erase "$(INTDIR)\ssl_engine_io.obj" - -@erase "$(INTDIR)\ssl_engine_kernel.obj" - -@erase "$(INTDIR)\ssl_engine_log.obj" - -@erase "$(INTDIR)\ssl_engine_mutex.obj" - -@erase "$(INTDIR)\ssl_engine_pphrase.obj" - -@erase "$(INTDIR)\ssl_engine_rand.obj" - -@erase "$(INTDIR)\ssl_engine_vars.obj" - -@erase "$(INTDIR)\ssl_expr.obj" - -@erase "$(INTDIR)\ssl_expr_eval.obj" - -@erase "$(INTDIR)\ssl_expr_parse.obj" - -@erase "$(INTDIR)\ssl_expr_scan.obj" - -@erase "$(INTDIR)\ssl_scache.obj" - -@erase "$(INTDIR)\ssl_scache_dbm.obj" - -@erase "$(INTDIR)\ssl_scache_dc.obj" - -@erase "$(INTDIR)\ssl_scache_shmcb.obj" - -@erase "$(INTDIR)\ssl_util.obj" - -@erase "$(INTDIR)\ssl_util_ssl.obj" - -@erase "$(OUTDIR)\mod_ssl.exp" - -@erase "$(OUTDIR)\mod_ssl.lib" - -@erase "$(OUTDIR)\mod_ssl.pdb" - -@erase "$(OUTDIR)\mod_ssl.so" - -"$(OUTDIR)" : - if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" - -CPP=cl.exe -CPP_PROJ=/nologo /MD /W3 /Zi /O2 /Oy- /I "../../include" /I "../generators" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /I "../../srclib/openssl/inc32" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "WIN32_LEAN_AND_MEAN" /D "NO_IDEA" /D "NO_RC5" /D "NO_MDC2" /D "OPENSSL_NO_IDEA" /D "OPENSSL_NO_RC5" /D "OPENSSL_NO_MDC2" /D "HAVE_OPENSSL" /D "HAVE_SSL_SET_STATE" /D "HAVE_OPENSSL_ENGINE_H" /D "HAVE_ENGINE_INIT" /D "HAVE_ENGINE_LOAD_BUILTIN_ENGINES" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_ssl_src" /FD /c - -.c{$(INTDIR)}.obj:: - $(CPP) @<< - $(CPP_PROJ) $< -<< - -.cpp{$(INTDIR)}.obj:: - $(CPP) @<< - $(CPP_PROJ) $< -<< - -.cxx{$(INTDIR)}.obj:: - $(CPP) @<< - $(CPP_PROJ) $< -<< - -.c{$(INTDIR)}.sbr:: - $(CPP) @<< - $(CPP_PROJ) $< -<< - -.cpp{$(INTDIR)}.sbr:: - $(CPP) @<< - $(CPP_PROJ) $< -<< - -.cxx{$(INTDIR)}.sbr:: - $(CPP) @<< - $(CPP_PROJ) $< -<< - -MTL=midl.exe -MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32 -RSC=rc.exe -RSC_PROJ=/l 0x409 /fo"$(INTDIR)\mod_ssl.res" /i "../../include" /i "../../srclib/apr/include" /d "NDEBUG" /d BIN_NAME="mod_ssl.so" /d LONG_NAME="proxy_ssl_module for Apache" -BSC32=bscmake.exe -BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_ssl.bsc" -BSC32_SBRS= \ - -LINK32=link.exe -LINK32_FLAGS=kernel32.lib user32.lib wsock32.lib ws2_32.lib advapi32.lib gdi32.lib libeay32.lib ssleay32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_ssl.pdb" /debug /out:"$(OUTDIR)\mod_ssl.so" /implib:"$(OUTDIR)\mod_ssl.lib" /libpath:"../../srclib/openssl/out32dll" /libpath:"../../srclib/openssl/out32" /base:@..\..\os\win32\BaseAddr.ref,mod_ssl.so /opt:ref -LINK32_OBJS= \ - "$(INTDIR)\mod_ssl.obj" \ - "$(INTDIR)\ssl_engine_config.obj" \ - "$(INTDIR)\ssl_engine_dh.obj" \ - "$(INTDIR)\ssl_engine_init.obj" \ - "$(INTDIR)\ssl_engine_io.obj" \ - "$(INTDIR)\ssl_engine_kernel.obj" \ - "$(INTDIR)\ssl_engine_log.obj" \ - "$(INTDIR)\ssl_engine_mutex.obj" \ - "$(INTDIR)\ssl_engine_pphrase.obj" \ - "$(INTDIR)\ssl_engine_rand.obj" \ - "$(INTDIR)\ssl_engine_vars.obj" \ - "$(INTDIR)\ssl_expr.obj" \ - "$(INTDIR)\ssl_expr_eval.obj" \ - "$(INTDIR)\ssl_expr_parse.obj" \ - "$(INTDIR)\ssl_expr_scan.obj" \ - "$(INTDIR)\ssl_scache.obj" \ - "$(INTDIR)\ssl_scache_dbm.obj" \ - "$(INTDIR)\ssl_scache_shmcb.obj" \ - "$(INTDIR)\ssl_scache_dc.obj" \ - "$(INTDIR)\ssl_util.obj" \ - "$(INTDIR)\ssl_util_ssl.obj" \ - "$(INTDIR)\mod_ssl.res" \ - "..\..\srclib\apr\Release\libapr-1.lib" \ - "..\..\srclib\apr-util\Release\libaprutil-1.lib" \ - "..\..\Release\libhttpd.lib" - -"$(OUTDIR)\mod_ssl.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) - $(LINK32) @<< - $(LINK32_FLAGS) $(LINK32_OBJS) -<< - -TargetPath=.\Release\mod_ssl.so -SOURCE="$(InputPath)" -PostBuild_Desc=Embed .manifest -DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep - -# Begin Custom Macros -OutDir=.\Release -# End Custom Macros - -"$(DS_POSTBUILD_DEP)" : "$(OUTDIR)\mod_ssl.so" - if exist .\Release\mod_ssl.so.manifest mt.exe -manifest .\Release\mod_ssl.so.manifest -outputresource:.\Release\mod_ssl.so;2 - echo Helper for Post-build step > "$(DS_POSTBUILD_DEP)" - -!ELSEIF "$(CFG)" == "mod_ssl - Win32 Debug" - -OUTDIR=.\Debug -INTDIR=.\Debug -DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep -# Begin Custom Macros -OutDir=.\Debug -# End Custom Macros - -!IF "$(RECURSE)" == "0" - -ALL : "$(OUTDIR)\mod_ssl.so" "$(DS_POSTBUILD_DEP)" - -!ELSE - -ALL : "libhttpd - Win32 Debug" "libaprutil - Win32 Debug" "libapr - Win32 Debug" "$(OUTDIR)\mod_ssl.so" "$(DS_POSTBUILD_DEP)" - -!ENDIF - -!IF "$(RECURSE)" == "1" -CLEAN :"libapr - Win32 DebugCLEAN" "libaprutil - Win32 DebugCLEAN" "libhttpd - Win32 DebugCLEAN" -!ELSE -CLEAN : -!ENDIF - -@erase "$(INTDIR)\mod_ssl.obj" - -@erase "$(INTDIR)\mod_ssl.res" - -@erase "$(INTDIR)\mod_ssl_src.idb" - -@erase "$(INTDIR)\mod_ssl_src.pdb" - -@erase "$(INTDIR)\ssl_engine_config.obj" - -@erase "$(INTDIR)\ssl_engine_dh.obj" - -@erase "$(INTDIR)\ssl_engine_init.obj" - -@erase "$(INTDIR)\ssl_engine_io.obj" - -@erase "$(INTDIR)\ssl_engine_kernel.obj" - -@erase "$(INTDIR)\ssl_engine_log.obj" - -@erase "$(INTDIR)\ssl_engine_mutex.obj" - -@erase "$(INTDIR)\ssl_engine_pphrase.obj" - -@erase "$(INTDIR)\ssl_engine_rand.obj" - -@erase "$(INTDIR)\ssl_engine_vars.obj" - -@erase "$(INTDIR)\ssl_expr.obj" - -@erase "$(INTDIR)\ssl_expr_eval.obj" - -@erase "$(INTDIR)\ssl_expr_parse.obj" - -@erase "$(INTDIR)\ssl_expr_scan.obj" - -@erase "$(INTDIR)\ssl_scache.obj" - -@erase "$(INTDIR)\ssl_scache_dbm.obj" - -@erase "$(INTDIR)\ssl_scache_dc.obj" - -@erase "$(INTDIR)\ssl_scache_shmcb.obj" - -@erase "$(INTDIR)\ssl_util.obj" - -@erase "$(INTDIR)\ssl_util_ssl.obj" - -@erase "$(OUTDIR)\mod_ssl.exp" - -@erase "$(OUTDIR)\mod_ssl.lib" - -@erase "$(OUTDIR)\mod_ssl.pdb" - -@erase "$(OUTDIR)\mod_ssl.so" - -"$(OUTDIR)" : - if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" - -CPP=cl.exe -CPP_PROJ=/nologo /MDd /W3 /Zi /Od /I "../../include" /I "../generators" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /I "../../srclib/openssl/inc32" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "WIN32_LEAN_AND_MEAN" /D "NO_IDEA" /D "NO_RC5" /D "NO_MDC2" /D "OPENSSL_NO_IDEA" /D "OPENSSL_NO_RC5" /D "OPENSSL_NO_MDC2" /D "HAVE_OPENSSL" /D "HAVE_SSL_SET_STATE" /D "HAVE_OPENSSL_ENGINE_H" /D "HAVE_ENGINE_INIT" /D "HAVE_ENGINE_LOAD_BUILTIN_ENGINES" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_ssl_src" /FD /EHsc /c - -.c{$(INTDIR)}.obj:: - $(CPP) @<< - $(CPP_PROJ) $< -<< - -.cpp{$(INTDIR)}.obj:: - $(CPP) @<< - $(CPP_PROJ) $< -<< - -.cxx{$(INTDIR)}.obj:: - $(CPP) @<< - $(CPP_PROJ) $< -<< - -.c{$(INTDIR)}.sbr:: - $(CPP) @<< - $(CPP_PROJ) $< -<< - -.cpp{$(INTDIR)}.sbr:: - $(CPP) @<< - $(CPP_PROJ) $< -<< - -.cxx{$(INTDIR)}.sbr:: - $(CPP) @<< - $(CPP_PROJ) $< -<< - -MTL=midl.exe -MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32 -RSC=rc.exe -RSC_PROJ=/l 0x409 /fo"$(INTDIR)\mod_ssl.res" /i "../../include" /i "../../srclib/apr/include" /d "_DEBUG" /d BIN_NAME="mod_ssl.so" /d LONG_NAME="proxy_ssl_module for Apache" -BSC32=bscmake.exe -BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_ssl.bsc" -BSC32_SBRS= \ - -LINK32=link.exe -LINK32_FLAGS=kernel32.lib user32.lib wsock32.lib ws2_32.lib advapi32.lib gdi32.lib libeay32.lib ssleay32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_ssl.pdb" /debug /out:"$(OUTDIR)\mod_ssl.so" /implib:"$(OUTDIR)\mod_ssl.lib" /libpath:"../../srclib/openssl/out32dll.dbg" /libpath:"../../srclib/openssl/out32.dbg" /libpath:"../../srclib/openssl/out32dll" /libpath:"../../srclib/openssl/out32" /base:@..\..\os\win32\BaseAddr.ref,mod_ssl.so -LINK32_OBJS= \ - "$(INTDIR)\mod_ssl.obj" \ - "$(INTDIR)\ssl_engine_config.obj" \ - "$(INTDIR)\ssl_engine_dh.obj" \ - "$(INTDIR)\ssl_engine_init.obj" \ - "$(INTDIR)\ssl_engine_io.obj" \ - "$(INTDIR)\ssl_engine_kernel.obj" \ - "$(INTDIR)\ssl_engine_log.obj" \ - "$(INTDIR)\ssl_engine_mutex.obj" \ - "$(INTDIR)\ssl_engine_pphrase.obj" \ - "$(INTDIR)\ssl_engine_rand.obj" \ - "$(INTDIR)\ssl_engine_vars.obj" \ - "$(INTDIR)\ssl_expr.obj" \ - "$(INTDIR)\ssl_expr_eval.obj" \ - "$(INTDIR)\ssl_expr_parse.obj" \ - "$(INTDIR)\ssl_expr_scan.obj" \ - "$(INTDIR)\ssl_scache.obj" \ - "$(INTDIR)\ssl_scache_dbm.obj" \ - "$(INTDIR)\ssl_scache_shmcb.obj" \ - "$(INTDIR)\ssl_scache_dc.obj" \ - "$(INTDIR)\ssl_util.obj" \ - "$(INTDIR)\ssl_util_ssl.obj" \ - "$(INTDIR)\mod_ssl.res" \ - "..\..\srclib\apr\Debug\libapr-1.lib" \ - "..\..\srclib\apr-util\Debug\libaprutil-1.lib" \ - "..\..\Debug\libhttpd.lib" - -"$(OUTDIR)\mod_ssl.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) - $(LINK32) @<< - $(LINK32_FLAGS) $(LINK32_OBJS) -<< - -TargetPath=.\Debug\mod_ssl.so -SOURCE="$(InputPath)" -PostBuild_Desc=Embed .manifest -DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep - -# Begin Custom Macros -OutDir=.\Debug -# End Custom Macros - -"$(DS_POSTBUILD_DEP)" : "$(OUTDIR)\mod_ssl.so" - if exist .\Debug\mod_ssl.so.manifest mt.exe -manifest .\Debug\mod_ssl.so.manifest -outputresource:.\Debug\mod_ssl.so;2 - echo Helper for Post-build step > "$(DS_POSTBUILD_DEP)" - -!ELSEIF "$(CFG)" == "mod_ssl - Win32 Lexical" - -OUTDIR=.\Release -INTDIR=.\Release -DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep -# Begin Custom Macros -OutDir=.\Release -# End Custom Macros - -!IF "$(RECURSE)" == "0" - -ALL : ".\ssl_expr_parse.h" ".\ssl_expr_parse.c" "$(OUTDIR)\mod_ssl.so" "$(DS_POSTBUILD_DEP)" - -!ELSE - -ALL : ".\ssl_expr_parse.h" ".\ssl_expr_parse.c" "$(OUTDIR)\mod_ssl.so" "$(DS_POSTBUILD_DEP)" - -!ENDIF - -!IF "$(RECURSE)" == "1" -CLEAN : -!ELSE -CLEAN : -!ENDIF - -@erase "$(INTDIR)\mod_ssl.obj" - -@erase "$(INTDIR)\mod_ssl.res" - -@erase "$(INTDIR)\mod_ssl_src.idb" - -@erase "$(INTDIR)\mod_ssl_src.pdb" - -@erase "$(INTDIR)\ssl_engine_config.obj" - -@erase "$(INTDIR)\ssl_engine_dh.obj" - -@erase "$(INTDIR)\ssl_engine_init.obj" - -@erase "$(INTDIR)\ssl_engine_io.obj" - -@erase "$(INTDIR)\ssl_engine_kernel.obj" - -@erase "$(INTDIR)\ssl_engine_log.obj" - -@erase "$(INTDIR)\ssl_engine_mutex.obj" - -@erase "$(INTDIR)\ssl_engine_pphrase.obj" - -@erase "$(INTDIR)\ssl_engine_rand.obj" - -@erase "$(INTDIR)\ssl_engine_vars.obj" - -@erase "$(INTDIR)\ssl_expr.obj" - -@erase "$(INTDIR)\ssl_expr_eval.obj" - -@erase "$(INTDIR)\ssl_expr_parse.obj" - -@erase "$(INTDIR)\ssl_expr_scan.obj" - -@erase "$(INTDIR)\ssl_scache.obj" - -@erase "$(INTDIR)\ssl_scache_dbm.obj" - -@erase "$(INTDIR)\ssl_scache_dc.obj" - -@erase "$(INTDIR)\ssl_scache_shmcb.obj" - -@erase "$(INTDIR)\ssl_util.obj" - -@erase "$(INTDIR)\ssl_util_ssl.obj" - -@erase "$(OUTDIR)\mod_ssl.exp" - -@erase "$(OUTDIR)\mod_ssl.lib" - -@erase "$(OUTDIR)\mod_ssl.pdb" - -@erase "$(OUTDIR)\mod_ssl.so" - -@erase "ssl_expr_parse.c" - -@erase "ssl_expr_parse.h" - -"$(OUTDIR)" : - if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" - -CPP=cl.exe -CPP_PROJ=/nologo /MD /W3 /Zi /O2 /Oy- /I "../../include" /I "../generators" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /I "../../srclib/openssl/inc32" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "WIN32_LEAN_AND_MEAN" /D "NO_IDEA" /D "NO_RC5" /D "NO_MDC2" /D "OPENSSL_NO_IDEA" /D "OPENSSL_NO_RC5" /D "OPENSSL_NO_MDC2" /D "HAVE_OPENSSL" /D "HAVE_SSL_SET_STATE" /D "HAVE_OPENSSL_ENGINE_H" /D "HAVE_ENGINE_INIT" /D "HAVE_ENGINE_LOAD_BUILTIN_ENGINES" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_ssl_src" /FD /c - -.c{$(INTDIR)}.obj:: - $(CPP) @<< - $(CPP_PROJ) $< -<< - -.cpp{$(INTDIR)}.obj:: - $(CPP) @<< - $(CPP_PROJ) $< -<< - -.cxx{$(INTDIR)}.obj:: - $(CPP) @<< - $(CPP_PROJ) $< -<< - -.c{$(INTDIR)}.sbr:: - $(CPP) @<< - $(CPP_PROJ) $< -<< - -.cpp{$(INTDIR)}.sbr:: - $(CPP) @<< - $(CPP_PROJ) $< -<< - -.cxx{$(INTDIR)}.sbr:: - $(CPP) @<< - $(CPP_PROJ) $< -<< - -MTL=midl.exe -MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32 -RSC=rc.exe -RSC_PROJ=/l 0x409 /fo"$(INTDIR)\mod_ssl.res" /i "../../include" /i "../../srclib/apr/include" /d "NDEBUG" /d BIN_NAME="mod_ssl.so" /d LONG_NAME="proxy_ssl_module for Apache" -BSC32=bscmake.exe -BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_ssl.bsc" -BSC32_SBRS= \ - -LINK32=link.exe -LINK32_FLAGS=kernel32.lib user32.lib wsock32.lib ws2_32.lib advapi32.lib gdi32.lib libeay32.lib ssleay32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_ssl.pdb" /debug /out:"$(OUTDIR)\mod_ssl.so" /implib:"$(OUTDIR)\mod_ssl.lib" /libpath:"../../srclib/openssl/out32dll" /libpath:"../../srclib/openssl/out32" /base:@..\..\os\win32\BaseAddr.ref,mod_ssl.so /opt:ref -LINK32_OBJS= \ - "$(INTDIR)\mod_ssl.obj" \ - "$(INTDIR)\ssl_engine_config.obj" \ - "$(INTDIR)\ssl_engine_dh.obj" \ - "$(INTDIR)\ssl_engine_init.obj" \ - "$(INTDIR)\ssl_engine_io.obj" \ - "$(INTDIR)\ssl_engine_kernel.obj" \ - "$(INTDIR)\ssl_engine_log.obj" \ - "$(INTDIR)\ssl_engine_mutex.obj" \ - "$(INTDIR)\ssl_engine_pphrase.obj" \ - "$(INTDIR)\ssl_engine_rand.obj" \ - "$(INTDIR)\ssl_engine_vars.obj" \ - "$(INTDIR)\ssl_expr.obj" \ - "$(INTDIR)\ssl_expr_eval.obj" \ - "$(INTDIR)\ssl_expr_parse.obj" \ - "$(INTDIR)\ssl_expr_scan.obj" \ - "$(INTDIR)\ssl_scache.obj" \ - "$(INTDIR)\ssl_scache_dbm.obj" \ - "$(INTDIR)\ssl_scache_shmcb.obj" \ - "$(INTDIR)\ssl_scache_dc.obj" \ - "$(INTDIR)\ssl_util.obj" \ - "$(INTDIR)\ssl_util_ssl.obj" \ - "$(INTDIR)\mod_ssl.res" - -"$(OUTDIR)\mod_ssl.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) - $(LINK32) @<< - $(LINK32_FLAGS) $(LINK32_OBJS) -<< - -TargetPath=.\Release\mod_ssl.so -SOURCE="$(InputPath)" -PostBuild_Desc=Embed .manifest -DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep - -# Begin Custom Macros -OutDir=.\Release -# End Custom Macros - -"$(DS_POSTBUILD_DEP)" : "$(OUTDIR)\mod_ssl.so" - if exist .\Release\mod_ssl.so.manifest mt.exe -manifest .\Release\mod_ssl.so.manifest -outputresource:.\Release\mod_ssl.so;2 - echo Helper for Post-build step > "$(DS_POSTBUILD_DEP)" - -!ENDIF - - -!IF "$(NO_EXTERNAL_DEPS)" != "1" -!IF EXISTS("mod_ssl.dep") -!INCLUDE "mod_ssl.dep" -!ELSE -!MESSAGE Warning: cannot find "mod_ssl.dep" -!ENDIF -!ENDIF - - -!IF "$(CFG)" == "mod_ssl - Win32 Release" || "$(CFG)" == "mod_ssl - Win32 Debug" || "$(CFG)" == "mod_ssl - Win32 Lexical" -SOURCE=.\mod_ssl.c - -"$(INTDIR)\mod_ssl.obj" : $(SOURCE) "$(INTDIR)" - - -SOURCE=.\ssl_engine_config.c - -"$(INTDIR)\ssl_engine_config.obj" : $(SOURCE) "$(INTDIR)" - - -SOURCE=.\ssl_engine_dh.c - -"$(INTDIR)\ssl_engine_dh.obj" : $(SOURCE) "$(INTDIR)" - - -SOURCE=.\ssl_engine_init.c - -"$(INTDIR)\ssl_engine_init.obj" : $(SOURCE) "$(INTDIR)" - - -SOURCE=.\ssl_engine_io.c - -"$(INTDIR)\ssl_engine_io.obj" : $(SOURCE) "$(INTDIR)" - - -SOURCE=.\ssl_engine_kernel.c - -"$(INTDIR)\ssl_engine_kernel.obj" : $(SOURCE) "$(INTDIR)" - - -SOURCE=.\ssl_engine_log.c - -"$(INTDIR)\ssl_engine_log.obj" : $(SOURCE) "$(INTDIR)" - - -SOURCE=.\ssl_engine_mutex.c - -"$(INTDIR)\ssl_engine_mutex.obj" : $(SOURCE) "$(INTDIR)" - - -SOURCE=.\ssl_engine_pphrase.c - -"$(INTDIR)\ssl_engine_pphrase.obj" : $(SOURCE) "$(INTDIR)" - - -SOURCE=.\ssl_engine_rand.c - -"$(INTDIR)\ssl_engine_rand.obj" : $(SOURCE) "$(INTDIR)" - - -SOURCE=.\ssl_engine_vars.c - -"$(INTDIR)\ssl_engine_vars.obj" : $(SOURCE) "$(INTDIR)" - - -SOURCE=.\ssl_expr.c - -"$(INTDIR)\ssl_expr.obj" : $(SOURCE) "$(INTDIR)" - - -SOURCE=.\ssl_expr_eval.c - -"$(INTDIR)\ssl_expr_eval.obj" : $(SOURCE) "$(INTDIR)" - - -SOURCE=.\ssl_expr_parse.c - -"$(INTDIR)\ssl_expr_parse.obj" : $(SOURCE) "$(INTDIR)" - - -SOURCE=.\ssl_expr_scan.c - -"$(INTDIR)\ssl_expr_scan.obj" : $(SOURCE) "$(INTDIR)" - - -SOURCE=.\ssl_scache.c - -"$(INTDIR)\ssl_scache.obj" : $(SOURCE) "$(INTDIR)" - - -SOURCE=.\ssl_scache_dbm.c - -"$(INTDIR)\ssl_scache_dbm.obj" : $(SOURCE) "$(INTDIR)" - - -SOURCE=.\ssl_scache_dc.c - -"$(INTDIR)\ssl_scache_dc.obj" : $(SOURCE) "$(INTDIR)" - - -SOURCE=.\ssl_scache_shmcb.c - -"$(INTDIR)\ssl_scache_shmcb.obj" : $(SOURCE) "$(INTDIR)" - - -SOURCE=.\ssl_util.c - -"$(INTDIR)\ssl_util.obj" : $(SOURCE) "$(INTDIR)" - - -SOURCE=.\ssl_util_ssl.c - -"$(INTDIR)\ssl_util_ssl.obj" : $(SOURCE) "$(INTDIR)" - - -SOURCE=.\ssl_expr_parse.y - -!IF "$(CFG)" == "mod_ssl - Win32 Release" - -!ELSEIF "$(CFG)" == "mod_ssl - Win32 Debug" - -!ELSEIF "$(CFG)" == "mod_ssl - Win32 Lexical" - -InputPath=.\ssl_expr_parse.y - -".\ssl_expr_parse.c" ".\ssl_expr_parse.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" - <<tempfile.bat - @echo off - bison -y -d ssl_expr_parse.y - sed -e "s;yy;ssl_expr_yy;g" -e "/#if defined(c_plusplus) || defined(__cplusplus)/,/#endif/d" <y.tab.c >ssl_expr_parse.c - del y.tab.c - sed -e "s;yy;ssl_expr_yy;g" <y.tab.h >ssl_expr_parse.h - del y.tab.h -<< - - -!ENDIF - -SOURCE=.\ssl_expr_scan.l - -!IF "$(CFG)" == "mod_ssl - Win32 Release" - -!ELSEIF "$(CFG)" == "mod_ssl - Win32 Debug" - -!ELSEIF "$(CFG)" == "mod_ssl - Win32 Lexical" - -InputPath=.\ssl_expr_scan.l - -".\ssl_expr_scan.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" - <<tempfile.bat - @echo off - flex -Pssl_expr_yy -s -B ssl_expr_scan.l - sed -e "/$$Header:/d" <lex.ssl_expr_yy.c >ssl_expr_scan.c - del lex.ssl_expr_yy.c -<< - - -!ENDIF - -!IF "$(CFG)" == "mod_ssl - Win32 Release" - -"libapr - Win32 Release" : - cd ".\..\..\srclib\apr" - $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Release" - cd "..\..\modules\ssl" - -"libapr - Win32 ReleaseCLEAN" : - cd ".\..\..\srclib\apr" - $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Release" RECURSE=1 CLEAN - cd "..\..\modules\ssl" - -!ELSEIF "$(CFG)" == "mod_ssl - Win32 Debug" - -"libapr - Win32 Debug" : - cd ".\..\..\srclib\apr" - $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Debug" - cd "..\..\modules\ssl" - -"libapr - Win32 DebugCLEAN" : - cd ".\..\..\srclib\apr" - $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Debug" RECURSE=1 CLEAN - cd "..\..\modules\ssl" - -!ELSEIF "$(CFG)" == "mod_ssl - Win32 Lexical" - -!ENDIF - -!IF "$(CFG)" == "mod_ssl - Win32 Release" - -"libaprutil - Win32 Release" : - cd ".\..\..\srclib\apr-util" - $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Release" - cd "..\..\modules\ssl" - -"libaprutil - Win32 ReleaseCLEAN" : - cd ".\..\..\srclib\apr-util" - $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Release" RECURSE=1 CLEAN - cd "..\..\modules\ssl" - -!ELSEIF "$(CFG)" == "mod_ssl - Win32 Debug" - -"libaprutil - Win32 Debug" : - cd ".\..\..\srclib\apr-util" - $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Debug" - cd "..\..\modules\ssl" - -"libaprutil - Win32 DebugCLEAN" : - cd ".\..\..\srclib\apr-util" - $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Debug" RECURSE=1 CLEAN - cd "..\..\modules\ssl" - -!ELSEIF "$(CFG)" == "mod_ssl - Win32 Lexical" - -!ENDIF - -!IF "$(CFG)" == "mod_ssl - Win32 Release" - -"libhttpd - Win32 Release" : - cd ".\..\.." - $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Release" - cd ".\modules\ssl" - -"libhttpd - Win32 ReleaseCLEAN" : - cd ".\..\.." - $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Release" RECURSE=1 CLEAN - cd ".\modules\ssl" - -!ELSEIF "$(CFG)" == "mod_ssl - Win32 Debug" - -"libhttpd - Win32 Debug" : - cd ".\..\.." - $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Debug" - cd ".\modules\ssl" - -"libhttpd - Win32 DebugCLEAN" : - cd ".\..\.." - $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Debug" RECURSE=1 CLEAN - cd ".\modules\ssl" - -!ELSEIF "$(CFG)" == "mod_ssl - Win32 Lexical" - -!ENDIF - -SOURCE=..\..\build\win32\httpd.rc - -!IF "$(CFG)" == "mod_ssl - Win32 Release" - - -"$(INTDIR)\mod_ssl.res" : $(SOURCE) "$(INTDIR)" - $(RSC) /l 0x409 /fo"$(INTDIR)\mod_ssl.res" /i "../../include" /i "../../srclib/apr/include" /i ".\..\..\build\win32" /d "NDEBUG" /d BIN_NAME="mod_ssl.so" /d LONG_NAME="proxy_ssl_module for Apache" $(SOURCE) - - -!ELSEIF "$(CFG)" == "mod_ssl - Win32 Debug" - - -"$(INTDIR)\mod_ssl.res" : $(SOURCE) "$(INTDIR)" - $(RSC) /l 0x409 /fo"$(INTDIR)\mod_ssl.res" /i "../../include" /i "../../srclib/apr/include" /i ".\..\..\build\win32" /d "_DEBUG" /d BIN_NAME="mod_ssl.so" /d LONG_NAME="proxy_ssl_module for Apache" $(SOURCE) - - -!ELSEIF "$(CFG)" == "mod_ssl - Win32 Lexical" - - -"$(INTDIR)\mod_ssl.res" : $(SOURCE) "$(INTDIR)" - $(RSC) /l 0x409 /fo"$(INTDIR)\mod_ssl.res" /i "../../include" /i "../../srclib/apr/include" /i ".\..\..\build\win32" /d "NDEBUG" /d BIN_NAME="mod_ssl.so" /d LONG_NAME="proxy_ssl_module for Apache" $(SOURCE) - - -!ENDIF - - -!ENDIF - diff --git a/modules/ssl/ssl_engine_config.c b/modules/ssl/ssl_engine_config.c index 8d3b99d4..8b2d53ad 100644 --- a/modules/ssl/ssl_engine_config.c +++ b/modules/ssl/ssl_engine_config.c @@ -27,6 +27,8 @@ damned if you don't.'' -- Unknown */ #include "ssl_private.h" +#include "util_mutex.h" +#include "ap_provider.h" /* _________________________________________________________________ ** @@ -57,15 +59,8 @@ SSLModConfigRec *ssl_config_global_create(server_rec *s) /* * initialize per-module configuration */ - mc->nSessionCacheMode = SSL_SCMODE_UNSET; - mc->szSessionCacheDataFile = NULL; - mc->nSessionCacheDataSize = 0; - mc->pSessionCacheDataMM = NULL; - mc->pSessionCacheDataRMM = NULL; - mc->tSessionCacheDataTable = NULL; - mc->nMutexMode = SSL_MUTEXMODE_UNSET; - mc->nMutexMech = APR_LOCK_DEFAULT; - mc->szMutexFile = NULL; + mc->sesscache_mode = SSL_SESS_CACHE_OFF; + mc->sesscache = NULL; mc->pMutex = NULL; mc->aRandSeed = apr_array_make(pool, 4, sizeof(ssl_randseed_t)); @@ -75,6 +70,10 @@ SSLModConfigRec *ssl_config_global_create(server_rec *s) #if defined(HAVE_OPENSSL_ENGINE_H) && defined(HAVE_ENGINE_INIT) mc->szCryptoDevice = NULL; #endif +#ifdef HAVE_OCSP_STAPLING + mc->stapling_cache = NULL; + mc->stapling_mutex = NULL; +#endif memset(mc->pTmpKeys, 0, sizeof(mc->pTmpKeys)); @@ -110,22 +109,46 @@ static void modssl_ctx_init(modssl_ctx_t *mctx) mctx->pks = NULL; mctx->pkp = NULL; +#ifdef HAVE_TLS_SESSION_TICKETS + mctx->ticket_key = NULL; +#endif + mctx->protocol = SSL_PROTOCOL_ALL; mctx->pphrase_dialog_type = SSL_PPTYPE_UNSET; mctx->pphrase_dialog_path = NULL; + mctx->pkcs7 = NULL; mctx->cert_chain = NULL; mctx->crl_path = NULL; mctx->crl_file = NULL; - mctx->crl = NULL; /* set during module init */ + mctx->crl_check_mode = SSL_CRLCHECK_UNSET; mctx->auth.ca_cert_path = NULL; mctx->auth.ca_cert_file = NULL; mctx->auth.cipher_suite = NULL; mctx->auth.verify_depth = UNSET; mctx->auth.verify_mode = SSL_CVERIFY_UNSET; + + mctx->ocsp_enabled = FALSE; + mctx->ocsp_force_default = FALSE; + mctx->ocsp_responder = NULL; + mctx->ocsp_resptime_skew = UNSET; + mctx->ocsp_resp_maxage = UNSET; + mctx->ocsp_responder_timeout = UNSET; + +#ifdef HAVE_OCSP_STAPLING + mctx->stapling_enabled = UNSET; + mctx->stapling_resptime_skew = UNSET; + mctx->stapling_resp_maxage = UNSET; + mctx->stapling_cache_timeout = UNSET; + mctx->stapling_return_errors = UNSET; + mctx->stapling_fake_trylater = UNSET; + mctx->stapling_errcache_timeout = UNSET; + mctx->stapling_responder_timeout = UNSET; + mctx->stapling_force_url = NULL; +#endif } static void modssl_ctx_init_proxy(SSLSrvConfigRec *sc, @@ -141,7 +164,9 @@ static void modssl_ctx_init_proxy(SSLSrvConfigRec *sc, mctx->pkp->cert_file = NULL; mctx->pkp->cert_path = NULL; + mctx->pkp->ca_cert_file = NULL; mctx->pkp->certs = NULL; + mctx->pkp->ca_certs = NULL; } static void modssl_ctx_init_server(SSLSrvConfigRec *sc, @@ -156,6 +181,10 @@ static void modssl_ctx_init_server(SSLSrvConfigRec *sc, mctx->pks = apr_pcalloc(p, sizeof(*mctx->pks)); /* mctx->pks->... certs/keys are set during module init */ + +#ifdef HAVE_TLS_SESSION_TICKETS + mctx->ticket_key = apr_pcalloc(p, sizeof(*mctx->ticket_key)); +#endif } static SSLSrvConfigRec *ssl_config_server_new(apr_pool_t *p) @@ -217,12 +246,31 @@ static void modssl_ctx_cfg_merge(modssl_ctx_t *base, cfgMerge(crl_path, NULL); cfgMerge(crl_file, NULL); + cfgMerge(crl_check_mode, SSL_CRLCHECK_UNSET); cfgMergeString(auth.ca_cert_path); cfgMergeString(auth.ca_cert_file); cfgMergeString(auth.cipher_suite); cfgMergeInt(auth.verify_depth); cfgMerge(auth.verify_mode, SSL_CVERIFY_UNSET); + + cfgMergeBool(ocsp_enabled); + cfgMergeBool(ocsp_force_default); + cfgMerge(ocsp_responder, NULL); + cfgMergeInt(ocsp_resptime_skew); + cfgMergeInt(ocsp_resp_maxage); + cfgMergeInt(ocsp_responder_timeout); +#ifdef HAVE_OCSP_STAPLING + cfgMergeBool(stapling_enabled); + cfgMergeInt(stapling_resptime_skew); + cfgMergeInt(stapling_resp_maxage); + cfgMergeInt(stapling_cache_timeout); + cfgMergeBool(stapling_return_errors); + cfgMergeBool(stapling_fake_trylater); + cfgMergeInt(stapling_errcache_timeout); + cfgMergeInt(stapling_responder_timeout); + cfgMerge(stapling_force_url, NULL); +#endif } static void modssl_ctx_cfg_merge_proxy(modssl_ctx_t *base, @@ -233,6 +281,7 @@ static void modssl_ctx_cfg_merge_proxy(modssl_ctx_t *base, cfgMergeString(pkp->cert_file); cfgMergeString(pkp->cert_path); + cfgMergeString(pkp->ca_cert_file); } static void modssl_ctx_cfg_merge_server(modssl_ctx_t *base, @@ -250,6 +299,10 @@ static void modssl_ctx_cfg_merge_server(modssl_ctx_t *base, cfgMergeString(pks->ca_name_path); cfgMergeString(pks->ca_name_file); + +#ifdef HAVE_TLS_SESSION_TICKETS + cfgMergeString(ticket_key->file_path); +#endif } /* @@ -352,99 +405,6 @@ void *ssl_config_perdir_merge(apr_pool_t *p, void *basev, void *addv) * Configuration functions for particular directives */ -const char *ssl_cmd_SSLMutex(cmd_parms *cmd, - void *dcfg, - const char *arg_) -{ - const char *err; - SSLModConfigRec *mc = myModConfig(cmd->server); - /* Split arg_ into meth and file */ - char *meth = apr_pstrdup(cmd->temp_pool, arg_); - char *file = strchr(meth, ':'); - if (file) { - *(file++) = '\0'; - if (!*file) { - file = NULL; - } - } - - if ((err = ap_check_cmd_context(cmd, GLOBAL_ONLY))) { - return err; - } - - if (ssl_config_global_isfixed(mc)) { - return NULL; - } - if (!strcasecmp(meth, "none") || !strcasecmp(meth, "no")) { - mc->nMutexMode = SSL_MUTEXMODE_NONE; - return NULL; - } - - /* APR determines temporary filename unless overridden below, - * we presume file indicates an szMutexFile is a file path - * unless the method sets szMutexFile=file and NULLs file - */ - mc->nMutexMode = SSL_MUTEXMODE_USED; - mc->szMutexFile = NULL; - - /* NOTE: previously, 'yes' implied 'sem' */ - if (!strcasecmp(meth, "default") || !strcasecmp(meth, "yes")) { - mc->nMutexMech = APR_LOCK_DEFAULT; - } -#if APR_HAS_FCNTL_SERIALIZE - else if ((!strcasecmp(meth, "fcntl") || !strcasecmp(meth, "file")) && file) { - mc->nMutexMech = APR_LOCK_FCNTL; - } -#endif -#if APR_HAS_FLOCK_SERIALIZE - else if ((!strcasecmp(meth, "flock") || !strcasecmp(meth, "file")) && file) { - mc->nMutexMech = APR_LOCK_FLOCK; - } -#endif -#if APR_HAS_POSIXSEM_SERIALIZE - else if (!strcasecmp(meth, "posixsem") || !strcasecmp(meth, "sem")) { - mc->nMutexMech = APR_LOCK_POSIXSEM; - /* Posix/SysV semaphores aren't file based, use the literal name - * if provided and fall back on APR's default if not. Today, APR - * will ignore it, but once supported it has an absurdly short limit. - */ - if (file) { - mc->szMutexFile = apr_pstrdup(cmd->server->process->pool, file); - - file = NULL; - } - } -#endif -#if APR_HAS_SYSVSEM_SERIALIZE && !defined(PERCHILD_MPM) - else if (!strcasecmp(meth, "sysvsem") || !strcasecmp(meth, "sem")) { - mc->nMutexMech = APR_LOCK_SYSVSEM; - } -#endif -#if APR_HAS_PROC_PTHREAD_SERIALIZE - else if (!strcasecmp(meth, "pthread")) { - mc->nMutexMech = APR_LOCK_PROC_PTHREAD; - } -#endif - else { - return apr_pstrcat(cmd->pool, "Invalid SSLMutex argument ", arg_, - " (", ssl_valid_ssl_mutex_string, ")", NULL); - } - - /* Unless the method above assumed responsibility for setting up - * mc->szMutexFile and NULLing out file, presume it is a file we - * are looking to use - */ - if (file) { - mc->szMutexFile = ap_server_root_relative(cmd->server->process->pool, file); - if (!mc->szMutexFile) { - return apr_pstrcat(cmd->pool, "Invalid SSLMutex ", meth, - ": filepath ", file, NULL); - } - } - - return NULL; -} - const char *ssl_cmd_SSLPassPhraseDialog(cmd_parms *cmd, void *dcfg, const char *arg) @@ -517,12 +477,11 @@ const char *ssl_cmd_SSLCryptoDevice(cmd_parms *cmd, "'builtin' (none)"; e = ENGINE_get_first(); while (e) { - ENGINE *en; err = apr_pstrcat(cmd->pool, err, ", '", ENGINE_get_id(e), "' (", ENGINE_get_name(e), ")", NULL); - en = ENGINE_get_next(e); - ENGINE_free(e); - e = en; + /* Iterate; this call implicitly decrements the refcount + * on the 'old' e, per the docs in engine.h. */ + e = ENGINE_get_next(e); } return err; } @@ -573,12 +532,8 @@ const char *ssl_cmd_SSLRandomSeed(cmd_parms *cmd, seed->cpPath = ap_server_root_relative(mc->pPool, arg2+5); } else if ((arg2len > 4) && strEQn(arg2, "egd:", 4)) { -#ifdef HAVE_SSL_RAND_EGD seed->nSrc = SSL_RSSRC_EGD; seed->cpPath = ap_server_root_relative(mc->pPool, arg2+4); -#else - return "egd not supported with this SSL toolkit"; -#endif } else if (strcEQ(arg2, "builtin")) { seed->nSrc = SSL_RSSRC_BUILTIN; @@ -835,23 +790,42 @@ const char *ssl_cmd_SSLCertificateChainFile(cmd_parms *cmd, return NULL; } -#define NO_PER_DIR_SSL_CA \ - "Your ssl library does not have support for per-directory CA" +const char *ssl_cmd_SSLPKCS7CertificateFile(cmd_parms *cmd, + void *dcfg, + const char *arg) +{ + SSLSrvConfigRec *sc = mySrvConfig(cmd->server); + const char *err; -#ifdef HAVE_SSL_SET_CERT_STORE -# define MODSSL_HAVE_SSL_SET_CERT_STORE 1 -#else -# define MODSSL_HAVE_SSL_SET_CERT_STORE 0 + if ((err = ssl_cmd_check_file(cmd, &arg))) { + return err; + } + + sc->server->pkcs7 = arg; + + return NULL; +} + +#ifdef HAVE_TLS_SESSION_TICKETS +const char *ssl_cmd_SSLSessionTicketKeyFile(cmd_parms *cmd, + void *dcfg, + const char *arg) +{ + SSLSrvConfigRec *sc = mySrvConfig(cmd->server); + const char *err; + + if ((err = ssl_cmd_check_file(cmd, &arg))) { + return err; + } + + sc->server->ticket_key->file_path = arg; + + return NULL; +} #endif -#define MODSSL_SET_CA(f) \ - if (cmd->path) \ - if (MODSSL_HAVE_SSL_SET_CERT_STORE) \ - dc->f = arg; \ - else \ - return NO_PER_DIR_SSL_CA; \ - else \ - sc->f = arg \ +#define NO_PER_DIR_SSL_CA \ + "Your SSL library does not have support for per-directory CA" const char *ssl_cmd_SSLCACertificatePath(cmd_parms *cmd, void *dcfg, @@ -865,6 +839,10 @@ const char *ssl_cmd_SSLCACertificatePath(cmd_parms *cmd, return err; } + if (cmd->path) { + return NO_PER_DIR_SSL_CA; + } + /* XXX: bring back per-dir */ sc->server->auth.ca_cert_path = arg; @@ -883,6 +861,10 @@ const char *ssl_cmd_SSLCACertificateFile(cmd_parms *cmd, return err; } + if (cmd->path) { + return NO_PER_DIR_SSL_CA; + } + /* XXX: bring back per-dir */ sc->server->auth.ca_cert_file = arg; @@ -951,6 +933,37 @@ const char *ssl_cmd_SSLCARevocationFile(cmd_parms *cmd, return NULL; } +static const char *ssl_cmd_crlcheck_parse(cmd_parms *parms, + const char *arg, + ssl_crlcheck_t *mode) +{ + if (strcEQ(arg, "none")) { + *mode = SSL_CRLCHECK_NONE; + } + else if (strcEQ(arg, "leaf")) { + *mode = SSL_CRLCHECK_LEAF; + } + else if (strcEQ(arg, "chain")) { + *mode = SSL_CRLCHECK_CHAIN; + } + else { + return apr_pstrcat(parms->temp_pool, parms->cmd->name, + ": Invalid argument '", arg, "'", + NULL); + } + + return NULL; +} + +const char *ssl_cmd_SSLCARevocationCheck(cmd_parms *cmd, + void *dcfg, + const char *arg) +{ + SSLSrvConfigRec *sc = mySrvConfig(cmd->server); + + return ssl_cmd_crlcheck_parse(cmd, arg, &sc->server->crl_check_mode); +} + static const char *ssl_cmd_verify_parse(cmd_parms *parms, const char *arg, ssl_verify_t *id) @@ -1035,103 +1048,77 @@ const char *ssl_cmd_SSLVerifyDepth(cmd_parms *cmd, return NULL; } -#define MODSSL_NO_SHARED_MEMORY_ERROR \ - "SSLSessionCache: shared memory cache not useable on this platform" - const char *ssl_cmd_SSLSessionCache(cmd_parms *cmd, void *dcfg, const char *arg) { SSLModConfigRec *mc = myModConfig(cmd->server); - const char *err, *colon; - char *cp, *cp2; - int arglen = strlen(arg); + const char *err, *sep, *name; + long enabled_flags; if ((err = ap_check_cmd_context(cmd, GLOBAL_ONLY))) { return err; } - if (ssl_config_global_isfixed(mc)) { - return NULL; - } + /* The OpenSSL session cache mode must have both the flags + * SSL_SESS_CACHE_SERVER and SSL_SESS_CACHE_NO_INTERNAL set if a + * session cache is configured; NO_INTERNAL prevents the + * OpenSSL-internal session cache being used in addition to the + * "external" (mod_ssl-provided) cache, which otherwise causes + * additional memory consumption. */ + enabled_flags = SSL_SESS_CACHE_SERVER | SSL_SESS_CACHE_NO_INTERNAL; if (strcEQ(arg, "none")) { - mc->nSessionCacheMode = SSL_SCMODE_NONE; - mc->szSessionCacheDataFile = NULL; + /* Nothing to do; session cache will be off. */ } else if (strcEQ(arg, "nonenotnull")) { - mc->nSessionCacheMode = SSL_SCMODE_NONE_NOT_NULL; - mc->szSessionCacheDataFile = NULL; - } - else if ((arglen > 4) && strcEQn(arg, "dbm:", 4)) { - mc->nSessionCacheMode = SSL_SCMODE_DBM; - mc->szSessionCacheDataFile = ap_server_root_relative(mc->pPool, arg+4); - if (!mc->szSessionCacheDataFile) { - return apr_psprintf(cmd->pool, - "SSLSessionCache: Invalid cache file path %s", - arg+4); - } + /* ### Having a separate mode for this seems logically + * unnecessary; the stated purpose of sending non-empty + * session IDs would be better fixed in OpenSSL or simply + * doing it by default if "none" is used. */ + mc->sesscache_mode = enabled_flags; } - else if (((arglen > 4) && strcEQn(arg, "shm:", 4)) || - ((arglen > 6) && strcEQn(arg, "shmht:", 6)) || - ((arglen > 6) && strcEQn(arg, "shmcb:", 6))) { -#if !APR_HAS_SHARED_MEMORY - return MODSSL_NO_SHARED_MEMORY_ERROR; -#endif - mc->nSessionCacheMode = SSL_SCMODE_SHMCB; - colon = ap_strchr_c(arg, ':'); - mc->szSessionCacheDataFile = - ap_server_root_relative(mc->pPool, colon+1); - if (!mc->szSessionCacheDataFile) { - return apr_psprintf(cmd->pool, - "SSLSessionCache: Invalid cache file path %s", - colon+1); + else { + /* Argument is of form 'name:args' or just 'name'. */ + sep = ap_strchr_c(arg, ':'); + if (sep) { + name = apr_pstrmemdup(cmd->pool, arg, sep - arg); + sep++; + } + else { + name = arg; } - mc->tSessionCacheDataTable = NULL; - mc->nSessionCacheDataSize = 1024*512; /* 512KB */ - - if ((cp = strchr(mc->szSessionCacheDataFile, '('))) { - *cp++ = NUL; - - if (!(cp2 = strchr(cp, ')'))) { - return "SSLSessionCache: Invalid argument: " - "no closing parenthesis"; - } - - *cp2 = NUL; - - mc->nSessionCacheDataSize = atoi(cp); - - if (mc->nSessionCacheDataSize < 8192) { - return "SSLSessionCache: Invalid argument: " - "size has to be >= 8192 bytes"; - - } - - if (mc->nSessionCacheDataSize >= APR_SHM_MAXSIZE) { - return apr_psprintf(cmd->pool, - "SSLSessionCache: Invalid argument: " - "size has to be < %d bytes on this " - "platform", APR_SHM_MAXSIZE); - } + /* Find the provider of given name. */ + mc->sesscache = ap_lookup_provider(AP_SOCACHE_PROVIDER_GROUP, + name, + AP_SOCACHE_PROVIDER_VERSION); + if (mc->sesscache) { + /* Cache found; create it, passing anything beyond the colon. */ + mc->sesscache_mode = enabled_flags; + err = mc->sesscache->create(&mc->sesscache_context, sep, + cmd->temp_pool, cmd->pool); } - } - else if ((arglen > 3) && strcEQn(arg, "dc:", 3)) { -#ifdef HAVE_DISTCACHE - mc->nSessionCacheMode = SSL_SCMODE_DC; - mc->szSessionCacheDataFile = apr_pstrdup(mc->pPool, arg+3); - if (!mc->szSessionCacheDataFile) { - return apr_pstrcat(cmd->pool, - "SSLSessionCache: Invalid cache file path: ", - arg+3, NULL); + else { + apr_array_header_t *name_list; + const char *all_names; + + /* Build a comma-separated list of all registered provider + * names: */ + name_list = ap_list_provider_names(cmd->pool, + AP_SOCACHE_PROVIDER_GROUP, + AP_SOCACHE_PROVIDER_VERSION); + all_names = apr_array_pstrcat(cmd->pool, name_list, ','); + + err = apr_psprintf(cmd->pool, "'%s' session cache not supported " + "(known names: %s). Maybe you need to load the " + "appropriate socache module (mod_socache_%s?).", + name, all_names, name); } -#else - return "SSLSessionCache: distcache support disabled"; -#endif } - else { - return "SSLSessionCache: Invalid argument"; + + if (err) { + return apr_psprintf(cmd->pool, "SSLSessionCache: %s", err); } return NULL; @@ -1162,7 +1149,7 @@ const char *ssl_cmd_SSLOptions(cmd_parms *cmd, char action, *w; while (*arg) { - w = ap_getword_conf(cmd->pool, &arg); + w = ap_getword_conf(cmd->temp_pool, &arg); action = NUL; if ((*w == '+') || (*w == '-')) { @@ -1188,6 +1175,9 @@ const char *ssl_cmd_SSLOptions(cmd_parms *cmd, else if (strcEQ(w, "OptRenegotiate")) { opt = SSL_OPT_OPTRENEGOTIATE; } + else if (strcEQ(w, "LegacyDNStringFormat")) { + opt = SSL_OPT_LEGACYDNFORMAT; + } else { return apr_pstrcat(cmd->pool, "SSLOptions: Illegal option '", w, "'", @@ -1228,17 +1218,22 @@ const char *ssl_cmd_SSLRequire(cmd_parms *cmd, const char *arg) { SSLDirConfigRec *dc = (SSLDirConfigRec *)dcfg; - ssl_expr *expr; + ap_expr_info_t *info = apr_pcalloc(cmd->pool, sizeof(ap_expr_info_t)); ssl_require_t *require; + const char *errstring; - if (!(expr = ssl_expr_comp(cmd->pool, (char *)arg))) { - return apr_pstrcat(cmd->pool, "SSLRequire: ", - ssl_expr_get_error(), NULL); + info->flags = AP_EXPR_FLAG_SSL_EXPR_COMPAT; + info->filename = cmd->directive->filename; + info->line_number = cmd->directive->line_num; + info->module_index = APLOG_MODULE_INDEX; + errstring = ap_expr_parse(cmd->pool, cmd->temp_pool, info, arg, NULL); + if (errstring) { + return apr_pstrcat(cmd->pool, "SSLRequire: ", errstring, NULL); } require = apr_array_push(dc->aRequirement); require->cpExpr = apr_pstrdup(cmd->pool, arg); - require->mpExpr = expr; + require->mpExpr = info; return NULL; } @@ -1246,12 +1241,14 @@ const char *ssl_cmd_SSLRequire(cmd_parms *cmd, const char *ssl_cmd_SSLRenegBufferSize(cmd_parms *cmd, void *dcfg, const char *arg) { SSLDirConfigRec *dc = dcfg; - - dc->nRenegBufferSize = atoi(arg); - if (dc->nRenegBufferSize < 0) { + int val; + + val = atoi(arg); + if (val < 0) { return apr_pstrcat(cmd->pool, "Invalid size for SSLRenegBufferSize: ", arg, NULL); } + dc->nRenegBufferSize = val; return NULL; } @@ -1273,12 +1270,12 @@ static const char *ssl_cmd_protocol_parse(cmd_parms *parms, } if (strcEQ(w, "SSLv2")) { -#ifdef OPENSSL_NO_SSL2 - if (action != '-') { - return "SSLv2 not supported by this version of OpenSSL"; + if (action == '-') { + continue; + } + else { + return "SSLProtocol: SSLv2 is no longer supported"; } -#endif - thisopt = SSL_PROTOCOL_SSLV2; } else if (strcEQ(w, "SSLv3")) { thisopt = SSL_PROTOCOL_SSLV3; @@ -1446,6 +1443,15 @@ const char *ssl_cmd_SSLProxyCARevocationFile(cmd_parms *cmd, return NULL; } +const char *ssl_cmd_SSLProxyCARevocationCheck(cmd_parms *cmd, + void *dcfg, + const char *arg) +{ + SSLSrvConfigRec *sc = mySrvConfig(cmd->server); + + return ssl_cmd_crlcheck_parse(cmd, arg, &sc->proxy->crl_check_mode); +} + const char *ssl_cmd_SSLProxyMachineCertificateFile(cmd_parms *cmd, void *dcfg, const char *arg) @@ -1478,6 +1484,21 @@ const char *ssl_cmd_SSLProxyMachineCertificatePath(cmd_parms *cmd, return NULL; } +const char *ssl_cmd_SSLProxyMachineCertificateChainFile(cmd_parms *cmd, + void *dcfg, + const char *arg) +{ + SSLSrvConfigRec *sc = mySrvConfig(cmd->server); + const char *err; + + if ((err = ssl_cmd_check_file(cmd, &arg))) { + return err; + } + + sc->proxy->pkp->ca_cert_file = arg; + + return NULL; +} const char *ssl_cmd_SSLUserName(cmd_parms *cmd, void *dcfg, const char *arg) @@ -1487,6 +1508,70 @@ const char *ssl_cmd_SSLUserName(cmd_parms *cmd, void *dcfg, return NULL; } +const char *ssl_cmd_SSLOCSPEnable(cmd_parms *cmd, void *dcfg, int flag) +{ + SSLSrvConfigRec *sc = mySrvConfig(cmd->server); + + sc->server->ocsp_enabled = flag ? TRUE : FALSE; + +#ifdef OPENSSL_NO_OCSP + if (flag) { + return "OCSP support disabled in SSL library; cannot enable " + "OCSP validation"; + } +#endif + + return NULL; +} + +const char *ssl_cmd_SSLOCSPOverrideResponder(cmd_parms *cmd, void *dcfg, int flag) +{ + SSLSrvConfigRec *sc = mySrvConfig(cmd->server); + + sc->server->ocsp_force_default = flag ? TRUE : FALSE; + + return NULL; +} + +const char *ssl_cmd_SSLOCSPDefaultResponder(cmd_parms *cmd, void *dcfg, const char *arg) +{ + SSLSrvConfigRec *sc = mySrvConfig(cmd->server); + + sc->server->ocsp_responder = arg; + + return NULL; +} + +const char *ssl_cmd_SSLOCSPResponseTimeSkew(cmd_parms *cmd, void *dcfg, const char *arg) +{ + SSLSrvConfigRec *sc = mySrvConfig(cmd->server); + sc->server->ocsp_resptime_skew = atoi(arg); + if (sc->server->ocsp_resptime_skew < 0) { + return "SSLOCSPResponseTimeSkew: invalid argument"; + } + return NULL; +} + +const char *ssl_cmd_SSLOCSPResponseMaxAge(cmd_parms *cmd, void *dcfg, const char *arg) +{ + SSLSrvConfigRec *sc = mySrvConfig(cmd->server); + sc->server->ocsp_resp_maxage = atoi(arg); + if (sc->server->ocsp_resp_maxage < 0) { + return "SSLOCSPResponseMaxAge: invalid argument"; + } + return NULL; +} + +const char *ssl_cmd_SSLOCSPResponderTimeout(cmd_parms *cmd, void *dcfg, const char *arg) +{ + SSLSrvConfigRec *sc = mySrvConfig(cmd->server); + sc->server->ocsp_responder_timeout = apr_time_from_sec(atoi(arg)); + if (sc->server->ocsp_responder_timeout < 0) { + return "SSLOCSPResponderTimeout: invalid argument"; + } + return NULL; +} + const char *ssl_cmd_SSLProxyCheckPeerExpire(cmd_parms *cmd, void *dcfg, int flag) { SSLSrvConfigRec *sc = mySrvConfig(cmd->server); @@ -1520,11 +1605,160 @@ const char *ssl_cmd_SSLStrictSNIVHostCheck(cmd_parms *cmd, void *dcfg, int flag #endif } +#ifdef HAVE_OCSP_STAPLING + +const char *ssl_cmd_SSLStaplingCache(cmd_parms *cmd, + void *dcfg, + const char *arg) +{ + SSLModConfigRec *mc = myModConfig(cmd->server); + const char *err, *sep, *name; + + if ((err = ap_check_cmd_context(cmd, GLOBAL_ONLY))) { + return err; + } + + /* Argument is of form 'name:args' or just 'name'. */ + sep = ap_strchr_c(arg, ':'); + if (sep) { + name = apr_pstrmemdup(cmd->pool, arg, sep - arg); + sep++; + } + else { + name = arg; + } + + /* Find the provider of given name. */ + mc->stapling_cache = ap_lookup_provider(AP_SOCACHE_PROVIDER_GROUP, + name, + AP_SOCACHE_PROVIDER_VERSION); + if (mc->stapling_cache) { + /* Cache found; create it, passing anything beyond the colon. */ + err = mc->stapling_cache->create(&mc->stapling_cache_context, + sep, cmd->temp_pool, + cmd->pool); + } + else { + apr_array_header_t *name_list; + const char *all_names; + + /* Build a comma-separated list of all registered provider + * names: */ + name_list = ap_list_provider_names(cmd->pool, + AP_SOCACHE_PROVIDER_GROUP, + AP_SOCACHE_PROVIDER_VERSION); + all_names = apr_array_pstrcat(cmd->pool, name_list, ','); + + err = apr_psprintf(cmd->pool, "'%s' stapling cache not supported " + "(known names: %s) Maybe you need to load the " + "appropriate socache module (mod_socache_%s?)", + name, all_names, name); + } + + if (err) { + return apr_psprintf(cmd->pool, "SSLStaplingCache: %s", err); + } + + return NULL; +} + +const char *ssl_cmd_SSLUseStapling(cmd_parms *cmd, void *dcfg, int flag) +{ + SSLSrvConfigRec *sc = mySrvConfig(cmd->server); + sc->server->stapling_enabled = flag ? TRUE : FALSE; + return NULL; +} + +const char *ssl_cmd_SSLStaplingResponseTimeSkew(cmd_parms *cmd, void *dcfg, + const char *arg) +{ + SSLSrvConfigRec *sc = mySrvConfig(cmd->server); + sc->server->stapling_resptime_skew = atoi(arg); + if (sc->server->stapling_resptime_skew < 0) { + return "SSLStaplingResponseTimeSkew: invalid argument"; + } + return NULL; +} + +const char *ssl_cmd_SSLStaplingResponseMaxAge(cmd_parms *cmd, void *dcfg, + const char *arg) +{ + SSLSrvConfigRec *sc = mySrvConfig(cmd->server); + sc->server->stapling_resp_maxage = atoi(arg); + if (sc->server->stapling_resp_maxage < 0) { + return "SSLStaplingResponseMaxAge: invalid argument"; + } + return NULL; +} + +const char *ssl_cmd_SSLStaplingStandardCacheTimeout(cmd_parms *cmd, void *dcfg, + const char *arg) +{ + SSLSrvConfigRec *sc = mySrvConfig(cmd->server); + sc->server->stapling_cache_timeout = atoi(arg); + if (sc->server->stapling_cache_timeout < 0) { + return "SSLStaplingStandardCacheTimeout: invalid argument"; + } + return NULL; +} + +const char *ssl_cmd_SSLStaplingErrorCacheTimeout(cmd_parms *cmd, void *dcfg, + const char *arg) +{ + SSLSrvConfigRec *sc = mySrvConfig(cmd->server); + sc->server->stapling_errcache_timeout = atoi(arg); + if (sc->server->stapling_errcache_timeout < 0) { + return "SSLStaplingErrorCacheTimeout: invalid argument"; + } + return NULL; +} + +const char *ssl_cmd_SSLStaplingReturnResponderErrors(cmd_parms *cmd, + void *dcfg, int flag) +{ + SSLSrvConfigRec *sc = mySrvConfig(cmd->server); + sc->server->stapling_return_errors = flag ? TRUE : FALSE; + return NULL; +} + +const char *ssl_cmd_SSLStaplingFakeTryLater(cmd_parms *cmd, + void *dcfg, int flag) +{ + SSLSrvConfigRec *sc = mySrvConfig(cmd->server); + sc->server->stapling_fake_trylater = flag ? TRUE : FALSE; + return NULL; +} + +const char *ssl_cmd_SSLStaplingResponderTimeout(cmd_parms *cmd, void *dcfg, + const char *arg) +{ + SSLSrvConfigRec *sc = mySrvConfig(cmd->server); + sc->server->stapling_responder_timeout = atoi(arg); + sc->server->stapling_responder_timeout *= APR_USEC_PER_SEC; + if (sc->server->stapling_responder_timeout < 0) { + return "SSLStaplingResponderTimeout: invalid argument"; + } + return NULL; +} + +const char *ssl_cmd_SSLStaplingForceURL(cmd_parms *cmd, void *dcfg, + const char *arg) +{ + SSLSrvConfigRec *sc = mySrvConfig(cmd->server); + sc->server->stapling_force_url = arg; + return NULL; +} + +#endif /* HAVE_OCSP_STAPLING */ + void ssl_hook_ConfigTest(apr_pool_t *pconf, server_rec *s) { + apr_file_t *out = NULL; if (!ap_exists_config_define("DUMP_CERTS")) { return; } + apr_file_open_stdout(&out, pconf); + apr_file_printf(out, "Server certificates:\n"); /* Dump the filenames of all configured server certificates to * stdout. */ @@ -1536,7 +1770,7 @@ void ssl_hook_ConfigTest(apr_pool_t *pconf, server_rec *s) int i; for (i = 0; (i < SSL_AIDX_MAX) && pks->cert_files[i]; i++) { - printf("%s\n", pks->cert_files[i]); + apr_file_printf(out, " %s\n", pks->cert_files[i]); } } diff --git a/modules/ssl/ssl_engine_dh.c b/modules/ssl/ssl_engine_dh.c index 91d2df47..0cc74555 100644 --- a/modules/ssl/ssl_engine_dh.c +++ b/modules/ssl/ssl_engine_dh.c @@ -69,8 +69,20 @@ static unsigned char dh512_g[] = { static DH *get_dh512(void) { - return modssl_dh_configure(dh512_p, sizeof(dh512_p), - dh512_g, sizeof(dh512_g)); + DH *dh; + + if (!(dh = DH_new())) { + return NULL; + } + + dh->p = BN_bin2bn(dh512_p, sizeof(dh512_p), NULL); + dh->g = BN_bin2bn(dh512_g, sizeof(dh512_g), NULL); + if (!(dh->p && dh->g)) { + DH_free(dh); + return NULL; + } + + return dh; } static unsigned char dh1024_p[] = { @@ -92,8 +104,20 @@ static unsigned char dh1024_g[] = { static DH *get_dh1024(void) { - return modssl_dh_configure(dh1024_p, sizeof(dh1024_p), - dh1024_g, sizeof(dh1024_g)); + DH *dh; + + if (!(dh = DH_new())) { + return NULL; + } + + dh->p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), NULL); + dh->g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), NULL); + if (!(dh->p && dh->g)) { + DH_free(dh); + return NULL; + } + + return dh; } /* ----END GENERATED SECTION---------- */ @@ -118,11 +142,7 @@ DH *ssl_dh_GetParamFromFile(char *file) if ((bio = BIO_new_file(file, "r")) == NULL) return NULL; -#if SSL_LIBRARY_VERSION < 0x00904000 - dh = PEM_read_bio_DHparams(bio, NULL, NULL); -#else dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); -#endif BIO_free(bio); return (dh); } @@ -175,18 +195,32 @@ close(FP); $dhinfo =~ s|^|** |mg; $dhinfo = "\n\/\*\n$dhinfo\*\/\n\n"; +my $indent_args = "-i4 -npsl -di0 -br -nce -d0 -cli0 -npcs -nfc1"; + # generate C source from DH params my $dhsource = ''; -open(FP, "openssl dh -noout -C -in dh512.pem | indent | expand |") || die; +open(FP, "openssl dh -noout -C -in dh512.pem | indent $indent_args | expand |") || die; $dhsource .= $_ while (<FP>); close(FP); -open(FP, "openssl dh -noout -C -in dh1024.pem | indent | expand |") || die; +open(FP, "openssl dh -noout -C -in dh1024.pem | indent $indent_args | expand |") || die; $dhsource .= $_ while (<FP>); close(FP); $dhsource =~ s|(DH\s+\*get_dh)(\d+)[^}]*\n}|static $1$2(void) { - return modssl_dh_configure(dh$2_p, sizeof(dh$2_p), - dh$2_g, sizeof(dh$2_g)); + DH *dh; + + if (!(dh = DH_new())) { + return NULL; + } + + dh->p = BN_bin2bn(dh$2_p, sizeof(dh$2_p), NULL); + dh->g = BN_bin2bn(dh$2_g, sizeof(dh$2_g), NULL); + if (!(dh->p && dh->g)) { + DH_free(dh); + return NULL; + } + + return dh; } |sg; diff --git a/modules/ssl/ssl_engine_init.c b/modules/ssl/ssl_engine_init.c index 34535410..dc4269d8 100644 --- a/modules/ssl/ssl_engine_init.c +++ b/modules/ssl/ssl_engine_init.c @@ -27,6 +27,7 @@ see Recursive.'' -- Unknown */ #include "ssl_private.h" +#include "mpm_common.h" /* _________________________________________________________________ ** @@ -40,13 +41,12 @@ static void ssl_add_version_components(apr_pool_t *p, { char *modver = ssl_var_lookup(p, s, NULL, NULL, "SSL_VERSION_INTERFACE"); char *libver = ssl_var_lookup(p, s, NULL, NULL, "SSL_VERSION_LIBRARY"); - char *incver = ssl_var_lookup(p, s, NULL, NULL, + char *incver = ssl_var_lookup(p, s, NULL, NULL, "SSL_VERSION_LIBRARY_INTERFACE"); - ap_add_version_component(p, modver); ap_add_version_component(p, libver); - ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, + ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, APLOGNO(01876) "%s compiled against Server: %s, Library: %s", modver, AP_SERVER_BASEVERSION, incver); } @@ -83,23 +83,42 @@ static int ssl_tmp_key_init_rsa(server_rec *s, if (FIPS_mode() && bits < 1024) { mc->pTmpKeys[idx] = NULL; - ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, + ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(01877) "Init: Skipping generating temporary " "%d bit RSA private key in FIPS mode", bits); return OK; } #endif - +#ifdef HAVE_GENERATE_EX + { + RSA *tkey; + BIGNUM *bn_f4; + if (!(tkey = RSA_new()) + || !(bn_f4 = BN_new()) + || !BN_set_word(bn_f4, RSA_F4) + || !RSA_generate_key_ex(tkey, bits, bn_f4, NULL)) + { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(01878) + "Init: Failed to generate temporary " + "%d bit RSA private key", bits); + ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, s); + return !OK; + } + BN_free(bn_f4); + mc->pTmpKeys[idx] = tkey; + } +#else if (!(mc->pTmpKeys[idx] = RSA_generate_key(bits, RSA_F4, NULL, NULL))) { - ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, + ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(01879) "Init: Failed to generate temporary " "%d bit RSA private key", bits); - ssl_log_ssl_error(APLOG_MARK, APLOG_ERR, s); + ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, s); return !OK; } +#endif return OK; } @@ -113,7 +132,7 @@ static int ssl_tmp_key_init_dh(server_rec *s, if (FIPS_mode() && bits < 1024) { mc->pTmpKeys[idx] = NULL; - ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, + ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(01880) "Init: Skipping generating temporary " "%d bit DH parameters in FIPS mode", bits); return OK; @@ -124,7 +143,7 @@ static int ssl_tmp_key_init_dh(server_rec *s, if (!(mc->pTmpKeys[idx] = ssl_dh_GetTmpParam(bits))) { - ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, + ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(01881) "Init: Failed to generate temporary " "%d bit DH parameters", bits); return !OK; @@ -141,7 +160,7 @@ static int ssl_tmp_key_init_dh(server_rec *s, static int ssl_tmp_keys_init(server_rec *s) { - ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, + ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, s, "Init: Generating temporary RSA private keys (512/1024 bits)"); if (MODSSL_TMP_KEY_INIT_RSA(s, 512) || @@ -149,7 +168,7 @@ static int ssl_tmp_keys_init(server_rec *s) return !OK; } - ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, + ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, s, "Init: Generating temporary DH parameters (512/1024 bits)"); if (MODSSL_TMP_KEY_INIT_DH(s, 512) || @@ -171,6 +190,14 @@ int ssl_init_Module(apr_pool_t *p, apr_pool_t *plog, SSLSrvConfigRec *sc; server_rec *s; + if (SSLeay() < SSL_LIBRARY_VERSION) { + ap_log_error(APLOG_MARK, APLOG_WARNING, 0, base_server, APLOGNO(01882) + "Init: this version of mod_ssl was compiled against " + "a newer library (%s, version currently loaded is %s)" + " - may result in undefined or erroneous behavior", + SSL_LIBRARY_TEXT, SSLeay_version(SSLEAY_VERSION)); + } + /* We initialize mc->pid per-process in the child init, * but it should be initialized for startup before we * call ssl_rand_seed() below. @@ -178,7 +205,7 @@ int ssl_init_Module(apr_pool_t *p, apr_pool_t *plog, mc->pid = getpid(); /* - * Let us cleanup on restarts and exists + * Let us cleanup on restarts and exits */ apr_pool_cleanup_register(p, base_server, ssl_init_ModuleKill, @@ -229,7 +256,7 @@ int ssl_init_Module(apr_pool_t *p, apr_pool_t *plog, sc->session_cache_timeout = SSL_SESSION_CACHE_TIMEOUT; } - if (sc->server->pphrase_dialog_type == SSL_PPTYPE_UNSET) { + if (sc->server && sc->server->pphrase_dialog_type == SSL_PPTYPE_UNSET) { sc->server->pphrase_dialog_type = SSL_PPTYPE_BUILTIN; } @@ -251,7 +278,7 @@ int ssl_init_Module(apr_pool_t *p, apr_pool_t *plog, ssl_init_Engine(base_server, p); #endif - ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, + ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, APLOGNO(01883) "Init: Initialized %s library", SSL_LIBRARY_NAME); /* @@ -265,18 +292,18 @@ int ssl_init_Module(apr_pool_t *p, apr_pool_t *plog, if(sc->fips) { if (!FIPS_mode()) { if (FIPS_mode_set(1)) { - ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, s, + ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, s, APLOGNO(01884) "Operating in SSL FIPS mode"); } else { - ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, "FIPS mode failed"); - ssl_log_ssl_error(APLOG_MARK, APLOG_EMERG, s); + ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(01885) "FIPS mode failed"); + ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s); ssl_die(); } } } else { - ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, s, + ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, s, APLOGNO(01886) "SSL FIPS mode disabled"); } #endif @@ -299,6 +326,9 @@ int ssl_init_Module(apr_pool_t *p, apr_pool_t *plog, if (!ssl_mutex_init(base_server, p)) { return HTTP_INTERNAL_SERVER_ERROR; } +#ifdef HAVE_OCSP_STAPLING + ssl_stapling_ex_init(); +#endif /* * initialize session caching @@ -308,7 +338,7 @@ int ssl_init_Module(apr_pool_t *p, apr_pool_t *plog, /* * initialize servers */ - ap_log_error(APLOG_MARK, APLOG_INFO, 0, base_server, + ap_log_error(APLOG_MARK, APLOG_INFO, 0, base_server, APLOGNO(01887) "Init: Initializing (virtual) servers for SSL"); for (s = base_server; s; s = s->next) { @@ -353,10 +383,10 @@ void ssl_init_Engine(server_rec *s, apr_pool_t *p) if (mc->szCryptoDevice) { if (!(e = ENGINE_by_id(mc->szCryptoDevice))) { - ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, + ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(01888) "Init: Failed to load Crypto Device API `%s'", mc->szCryptoDevice); - ssl_log_ssl_error(APLOG_MARK, APLOG_ERR, s); + ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s); ssl_die(); } @@ -365,14 +395,14 @@ void ssl_init_Engine(server_rec *s, apr_pool_t *p) } if (!ENGINE_set_default(e, ENGINE_METHOD_ALL)) { - ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, + ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(01889) "Init: Failed to enable Crypto Device API `%s'", mc->szCryptoDevice); - ssl_log_ssl_error(APLOG_MARK, APLOG_ERR, s); + ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s); ssl_die(); } - ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, - "Init: loaded Crypto Device API `%s'", + ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, APLOGNO(01890) + "Init: loaded Crypto Device API `%s'", mc->szCryptoDevice); ENGINE_free(e); @@ -389,8 +419,8 @@ static void ssl_init_server_check(server_rec *s, * check for important parameters and the * possibility that the user forgot to set them. */ - if (!mctx->pks->cert_files[0]) { - ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, + if (!mctx->pks->cert_files[0] && !mctx->pkcs7) { + ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(01891) "No SSL Certificate set [hint: SSLCertificateFile]"); ssl_die(); } @@ -399,9 +429,13 @@ static void ssl_init_server_check(server_rec *s, * Check for problematic re-initializations */ if (mctx->pks->certs[SSL_AIDX_RSA] || - mctx->pks->certs[SSL_AIDX_DSA]) + mctx->pks->certs[SSL_AIDX_DSA] +#ifndef OPENSSL_NO_EC + || mctx->pks->certs[SSL_AIDX_ECC] +#endif + ) { - ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, + ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(01892) "Illegal attempt to re-initialise SSL for server " "(SSLEngine On should go in the VirtualHost, not in global scope.)"); ssl_die(); @@ -417,7 +451,7 @@ static void ssl_init_ctx_tls_extensions(server_rec *s, /* * Configure TLS extensions support */ - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(01893) "Configuring TLS extension handling"); /* @@ -426,12 +460,21 @@ static void ssl_init_ctx_tls_extensions(server_rec *s, if (!SSL_CTX_set_tlsext_servername_callback(mctx->ssl_ctx, ssl_callback_ServerNameIndication) || !SSL_CTX_set_tlsext_servername_arg(mctx->ssl_ctx, mctx)) { - ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, + ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(01894) "Unable to initialize TLS servername extension " "callback (incompatible OpenSSL version?)"); - ssl_log_ssl_error(APLOG_MARK, APLOG_ERR, s); + ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s); ssl_die(); } + +#ifdef HAVE_OCSP_STAPLING + /* + * OCSP Stapling support, status_request extension + */ + if ((mctx->pkp == FALSE) && (mctx->stapling_enabled == TRUE)) { + modssl_init_stapling(s, p, ptemp, mctx); + } +#endif } #endif @@ -450,44 +493,43 @@ static void ssl_init_ctx_protocol(server_rec *s, * Create the new per-server SSL context */ if (protocol == SSL_PROTOCOL_NONE) { - ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, + ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02231) "No SSL protocols available [hint: SSLProtocol]"); ssl_die(); } cp = apr_pstrcat(p, - (protocol & SSL_PROTOCOL_SSLV2 ? "SSLv2, " : ""), (protocol & SSL_PROTOCOL_SSLV3 ? "SSLv3, " : ""), (protocol & SSL_PROTOCOL_TLSV1 ? "TLSv1, " : ""), NULL); cp[strlen(cp)-2] = NUL; - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, + ap_log_error(APLOG_MARK, APLOG_TRACE3, 0, s, "Creating new SSL context (protocols: %s)", cp); -#ifndef OPENSSL_NO_SSL2 - if (protocol == SSL_PROTOCOL_SSLV2) { + if (protocol == SSL_PROTOCOL_SSLV3) { method = mctx->pkp ? - SSLv2_client_method() : /* proxy */ - SSLv2_server_method(); /* server */ - ctx = SSL_CTX_new(method); /* only SSLv2 is left */ + SSLv3_client_method() : /* proxy */ + SSLv3_server_method(); /* server */ } - else -#endif - { + else if (protocol == SSL_PROTOCOL_TLSV1) { + method = mctx->pkp ? + TLSv1_client_method() : /* proxy */ + TLSv1_server_method(); /* server */ + } + else { /* For multiple protocols, we need a flexible method */ method = mctx->pkp ? SSLv23_client_method() : /* proxy */ SSLv23_server_method(); /* server */ - ctx = SSL_CTX_new(method); /* be more flexible */ } + ctx = SSL_CTX_new(method); mctx->ssl_ctx = ctx; SSL_CTX_set_options(ctx, SSL_OP_ALL); - if (!(protocol & SSL_PROTOCOL_SSLV2)) { - SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2); - } + /* always disable SSLv2, as per RFC 6176 */ + SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2); if (!(protocol & SSL_PROTOCOL_SSLV3)) { SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3); @@ -523,6 +565,12 @@ static void ssl_init_ctx_protocol(server_rec *s, */ SSL_CTX_set_options(ctx, SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION); #endif + +#ifdef SSL_MODE_RELEASE_BUFFERS + /* If httpd is configured to reduce mem usage, ask openssl to do so, too */ + if (ap_max_mem_free != APR_ALLOCATOR_MAX_FREE_UNLIMITED) + SSL_CTX_set_mode(ctx, SSL_MODE_RELEASE_BUFFERS); +#endif } static void ssl_init_ctx_session_cache(server_rec *s, @@ -532,20 +580,14 @@ static void ssl_init_ctx_session_cache(server_rec *s, { SSL_CTX *ctx = mctx->ssl_ctx; SSLModConfigRec *mc = myModConfig(s); - long cache_mode = SSL_SESS_CACHE_OFF; - if (mc->nSessionCacheMode != SSL_SCMODE_NONE) { - /* SSL_SESS_CACHE_NO_INTERNAL will force OpenSSL - * to ignore process local-caching and - * to always get/set/delete sessions using mod_ssl's callbacks. - */ - cache_mode = SSL_SESS_CACHE_SERVER|SSL_SESS_CACHE_NO_INTERNAL; - } - SSL_CTX_set_session_cache_mode(ctx, cache_mode); + SSL_CTX_set_session_cache_mode(ctx, mc->sesscache_mode); - SSL_CTX_sess_set_new_cb(ctx, ssl_callback_NewSessionCacheEntry); - SSL_CTX_sess_set_get_cb(ctx, ssl_callback_GetSessionCacheEntry); - SSL_CTX_sess_set_remove_cb(ctx, ssl_callback_DelSessionCacheEntry); + if (mc->sesscache) { + SSL_CTX_sess_set_new_cb(ctx, ssl_callback_NewSessionCacheEntry); + SSL_CTX_sess_set_get_cb(ctx, ssl_callback_GetSessionCacheEntry); + SSL_CTX_sess_set_remove_cb(ctx, ssl_callback_DelSessionCacheEntry); + } } static void ssl_init_ctx_callbacks(server_rec *s, @@ -557,6 +599,9 @@ static void ssl_init_ctx_callbacks(server_rec *s, SSL_CTX_set_tmp_rsa_callback(ctx, ssl_callback_TmpRSA); SSL_CTX_set_tmp_dh_callback(ctx, ssl_callback_TmpDH); +#ifndef OPENSSL_NO_EC + SSL_CTX_set_tmp_ecdh_callback(ctx,ssl_callback_TmpECDH); +#endif SSL_CTX_set_info_callback(ctx, ssl_callback_Info); } @@ -598,17 +643,17 @@ static void ssl_init_ctx_verify(server_rec *s, * Configure Client Authentication details */ if (mctx->auth.ca_cert_file || mctx->auth.ca_cert_path) { - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, + ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, s, "Configuring client authentication"); if (!SSL_CTX_load_verify_locations(ctx, - MODSSL_PCHAR_CAST mctx->auth.ca_cert_file, - MODSSL_PCHAR_CAST mctx->auth.ca_cert_path)) + mctx->auth.ca_cert_file, + mctx->auth.ca_cert_path)) { - ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, + ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(01895) "Unable to configure verify locations " "for client authentication"); - ssl_log_ssl_error(APLOG_MARK, APLOG_ERR, s); + ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s); ssl_die(); } @@ -620,8 +665,8 @@ static void ssl_init_ctx_verify(server_rec *s, ca_list = ssl_init_FindCAList(s, ptemp, mctx->auth.ca_cert_file, mctx->auth.ca_cert_path); - if (!ca_list) { - ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, + if (sk_X509_NAME_num(ca_list) <= 0) { + ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(01896) "Unable to determine list of acceptable " "CA certificates for client authentication"); ssl_die(); @@ -638,7 +683,7 @@ static void ssl_init_ctx_verify(server_rec *s, ca_list = SSL_CTX_get_client_CA_list(ctx); if (sk_X509_NAME_num(ca_list) == 0) { - ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, + ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(01897) "Init: Oops, you want to request client " "authentication, but no CAs are known for " "verification!? [Hint: SSLCACertificate*]"); @@ -661,14 +706,14 @@ static void ssl_init_ctx_cipher_suite(server_rec *s, return; } - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, + ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, s, "Configuring permitted SSL ciphers [%s]", suite); - if (!SSL_CTX_set_cipher_list(ctx, MODSSL_PCHAR_CAST suite)) { - ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, + if (!SSL_CTX_set_cipher_list(ctx, suite)) { + ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(01898) "Unable to configure permitted SSL ciphers"); - ssl_log_ssl_error(APLOG_MARK, APLOG_ERR, s); + ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s); ssl_die(); } } @@ -678,28 +723,67 @@ static void ssl_init_ctx_crl(server_rec *s, apr_pool_t *ptemp, modssl_ctx_t *mctx) { + X509_STORE *store = SSL_CTX_get_cert_store(mctx->ssl_ctx); + unsigned long crlflags = 0; + char *cfgp = mctx->pkp ? "SSLProxy" : "SSL"; + /* * Configure Certificate Revocation List (CRL) Details */ if (!(mctx->crl_file || mctx->crl_path)) { + if (mctx->crl_check_mode == SSL_CRLCHECK_LEAF || + mctx->crl_check_mode == SSL_CRLCHECK_CHAIN) { + ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(01899) + "Host %s: CRL checking has been enabled, but " + "neither %sCARevocationFile nor %sCARevocationPath " + "is configured", mctx->sc->vhost_id, cfgp, cfgp); + ssl_die(); + } return; } - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(01900) "Configuring certificate revocation facility"); - mctx->crl = - SSL_X509_STORE_create((char *)mctx->crl_file, - (char *)mctx->crl_path); - - if (!mctx->crl) { - ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, - "Unable to configure X.509 CRL storage " - "for certificate revocation"); - ssl_log_ssl_error(APLOG_MARK, APLOG_ERR, s); + if (!store || !X509_STORE_load_locations(store, mctx->crl_file, + mctx->crl_path)) { + ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(01901) + "Host %s: unable to configure X.509 CRL storage " + "for certificate revocation", mctx->sc->vhost_id); + ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s); ssl_die(); } + + switch (mctx->crl_check_mode) { + case SSL_CRLCHECK_LEAF: + crlflags = X509_V_FLAG_CRL_CHECK; + break; + case SSL_CRLCHECK_CHAIN: + crlflags = X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL; + break; + default: + crlflags = 0; + } + + if (crlflags) { + X509_STORE_set_flags(store, crlflags); + } else { + ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(01902) + "Host %s: X.509 CRL storage locations configured, " + "but CRL checking (%sCARevocationCheck) is not " + "enabled", mctx->sc->vhost_id, cfgp); + } +} + +static void ssl_init_ctx_pkcs7_cert_chain(server_rec *s, modssl_ctx_t *mctx) +{ + STACK_OF(X509) *certs = ssl_read_pkcs7(s, mctx->pkcs7); + int n; + + if (!mctx->ssl_ctx->extra_certs) + for (n = 1; n < sk_X509_num(certs); ++n) + SSL_CTX_add_extra_chain_cert(mctx->ssl_ctx, sk_X509_value(certs, n)); } static void ssl_init_ctx_cert_chain(server_rec *s, @@ -711,6 +795,11 @@ static void ssl_init_ctx_cert_chain(server_rec *s, int i, n; const char *chain = mctx->cert_chain; + if (mctx->pkcs7) { + ssl_init_ctx_pkcs7_cert_chain(s, mctx); + return; + } + /* * Optionally configure extra server certificate chain certificates. * This is usually done by OpenSSL automatically when one of the @@ -740,12 +829,12 @@ static void ssl_init_ctx_cert_chain(server_rec *s, (char *)chain, skip_first, NULL); if (n < 0) { - ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, + ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(01903) "Failed to configure CA certificate chain!"); ssl_die(); } - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(01904) "Configuring server certificate chain " "(%d CA certificate%s)", n, n == 1 ? "" : "s"); @@ -792,24 +881,33 @@ static int ssl_server_import_cert(server_rec *s, return FALSE; } - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(02232) "Configuring %s server certificate", type); ptr = asn1->cpData; if (!(cert = d2i_X509(NULL, &ptr, asn1->nData))) { - ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, + ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02233) "Unable to import %s server certificate", type); - ssl_log_ssl_error(APLOG_MARK, APLOG_ERR, s); + ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s); ssl_die(); } if (SSL_CTX_use_certificate(mctx->ssl_ctx, cert) <= 0) { - ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, + ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02234) "Unable to configure %s server certificate", type); - ssl_log_ssl_error(APLOG_MARK, APLOG_ERR, s); + ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s); ssl_die(); } +#ifdef HAVE_OCSP_STAPLING + if ((mctx->pkp == FALSE) && (mctx->stapling_enabled == TRUE)) { + if (!ssl_stapling_init_cert(s, mctx, cert)) { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(02235) + "Unable to configure server certificate for stapling"); + } + } +#endif + mctx->pks->certs[idx] = cert; return TRUE; @@ -824,29 +922,36 @@ static int ssl_server_import_key(server_rec *s, ssl_asn1_t *asn1; MODSSL_D2I_PrivateKey_CONST unsigned char *ptr; const char *type = ssl_asn1_keystr(idx); - int pkey_type = (idx == SSL_AIDX_RSA) ? EVP_PKEY_RSA : EVP_PKEY_DSA; + int pkey_type; EVP_PKEY *pkey; +#ifndef OPENSSL_NO_EC + if (idx == SSL_AIDX_ECC) + pkey_type = EVP_PKEY_EC; + else +#endif + pkey_type = (idx == SSL_AIDX_RSA) ? EVP_PKEY_RSA : EVP_PKEY_DSA; + if (!(asn1 = ssl_asn1_table_get(mc->tPrivateKey, id))) { return FALSE; } - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(02236) "Configuring %s server private key", type); ptr = asn1->cpData; if (!(pkey = d2i_PrivateKey(pkey_type, NULL, &ptr, asn1->nData))) { - ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, + ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02237) "Unable to import %s server private key", type); - ssl_log_ssl_error(APLOG_MARK, APLOG_ERR, s); + ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s); ssl_die(); } if (SSL_CTX_use_PrivateKey(mctx->ssl_ctx, pkey) <= 0) { - ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, + ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02238) "Unable to configure %s server private key", type); - ssl_log_ssl_error(APLOG_MARK, APLOG_ERR, s); + ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s); ssl_die(); } @@ -859,9 +964,9 @@ static int ssl_server_import_key(server_rec *s, if (pubkey && EVP_PKEY_missing_parameters(pubkey)) { EVP_PKEY_copy_parameters(pubkey, pkey); - ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, + ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(02239) "Copying DSA parameters from private key to certificate"); - ssl_log_ssl_error(APLOG_MARK, APLOG_ERR, s); + ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, s); EVP_PKEY_free(pubkey); } } @@ -877,7 +982,7 @@ static void ssl_check_public_cert(server_rec *s, int type) { int is_ca, pathlen; - char *cn; + apr_array_header_t *ids; if (!cert) { return; @@ -888,7 +993,7 @@ static void ssl_check_public_cert(server_rec *s, */ if (SSL_X509_isSGC(cert)) { - ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, + ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, APLOGNO(01905) "%s server certificate enables " "Server Gated Cryptography (SGC)", ssl_asn1_keystr(type)); @@ -896,37 +1001,69 @@ static void ssl_check_public_cert(server_rec *s, if (SSL_X509_getBC(cert, &is_ca, &pathlen)) { if (is_ca) { - ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, + ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(01906) "%s server certificate is a CA certificate " "(BasicConstraints: CA == TRUE !?)", ssl_asn1_keystr(type)); } if (pathlen > 0) { - ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, + ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(01907) "%s server certificate is not a leaf certificate " "(BasicConstraints: pathlen == %d > 0 !?)", ssl_asn1_keystr(type), pathlen); } } - if (SSL_X509_getCN(ptemp, cert, &cn)) { - int fnm_flags = APR_FNM_PERIOD|APR_FNM_CASE_BLIND; - - if (apr_fnmatch_test(cn)) { - if (apr_fnmatch(cn, s->server_hostname, - fnm_flags) == APR_FNM_NOMATCH) { - ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, - "%s server certificate wildcard CommonName " - "(CN) `%s' does NOT match server name!?", - ssl_asn1_keystr(type), cn); + /* + * Check if the server name is covered by the certificate. + * Consider both dNSName entries in the subjectAltName extension + * and, as a fallback, commonName attributes in the subject DN. + * (DNS-IDs and CN-IDs as defined in RFC 6125). + */ + if (SSL_X509_getIDs(ptemp, cert, &ids)) { + char *cp; + int i; + char **id = (char **)ids->elts; + BOOL is_wildcard, matched = FALSE; + + for (i = 0; i < ids->nelts; i++) { + if (!id[i]) + continue; + + /* + * Determine if it is a wildcard ID - we're restrictive + * in the sense that we require the wildcard character to be + * THE left-most label (i.e., the ID must start with "*.") + */ + is_wildcard = (*id[i] == '*' && *(id[i]+1) == '.') ? TRUE : FALSE; + + /* + * If the ID includes a wildcard character, check if it matches + * for the left-most DNS label (i.e., the wildcard character + * is not allowed to match a dot). Otherwise, try a simple + * string compare, case insensitively. + */ + if ((is_wildcard == TRUE && + (cp = strchr(s->server_hostname, '.')) && + !strcasecmp(id[i]+1, cp)) || + !strcasecmp(id[i], s->server_hostname)) { + matched = TRUE; + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(01908) + "%sID '%s' in %s certificate configured " + "for %s matches server name", + is_wildcard ? "Wildcard " : "", + id[i], ssl_asn1_keystr(type), + (mySrvConfig(s))->vhost_id); + break; } } - else if (strNE(s->server_hostname, cn)) { - ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, - "%s server certificate CommonName (CN) `%s' " - "does NOT match server name!?", - ssl_asn1_keystr(type), cn); + + if (matched == FALSE) { + ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(01909) + "%s certificate configured for %s does NOT include " + "an ID which matches the server name", + ssl_asn1_keystr(type), (mySrvConfig(s))->vhost_id); } } } @@ -937,19 +1074,39 @@ static void ssl_init_server_certs(server_rec *s, modssl_ctx_t *mctx) { const char *rsa_id, *dsa_id; +#ifndef OPENSSL_NO_EC + const char *ecc_id; +#endif const char *vhost_id = mctx->sc->vhost_id; int i; int have_rsa, have_dsa; +#ifndef OPENSSL_NO_EC + int have_ecc; +#endif rsa_id = ssl_asn1_table_keyfmt(ptemp, vhost_id, SSL_AIDX_RSA); dsa_id = ssl_asn1_table_keyfmt(ptemp, vhost_id, SSL_AIDX_DSA); +#ifndef OPENSSL_NO_EC + ecc_id = ssl_asn1_table_keyfmt(ptemp, vhost_id, SSL_AIDX_ECC); +#endif have_rsa = ssl_server_import_cert(s, mctx, rsa_id, SSL_AIDX_RSA); have_dsa = ssl_server_import_cert(s, mctx, dsa_id, SSL_AIDX_DSA); +#ifndef OPENSSL_NO_EC + have_ecc = ssl_server_import_cert(s, mctx, ecc_id, SSL_AIDX_ECC); +#endif - if (!(have_rsa || have_dsa)) { - ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, + if (!(have_rsa || have_dsa +#ifndef OPENSSL_NO_EC + || have_ecc +#endif +)) { + ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(01910) +#ifndef OPENSSL_NO_EC + "Oops, no RSA, DSA or ECC server certificate found " +#else "Oops, no RSA or DSA server certificate found " +#endif "for '%s:%d'?!", s->server_hostname, s->port); ssl_die(); } @@ -960,13 +1117,81 @@ static void ssl_init_server_certs(server_rec *s, have_rsa = ssl_server_import_key(s, mctx, rsa_id, SSL_AIDX_RSA); have_dsa = ssl_server_import_key(s, mctx, dsa_id, SSL_AIDX_DSA); +#ifndef OPENSSL_NO_EC + have_ecc = ssl_server_import_key(s, mctx, ecc_id, SSL_AIDX_ECC); +#endif - if (!(have_rsa || have_dsa)) { - ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, + if (!(have_rsa || have_dsa +#ifndef OPENSSL_NO_EC + || have_ecc +#endif + )) { + ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(01911) +#ifndef OPENSSL_NO_EC + "Oops, no RSA, DSA or ECC server private key found?!"); +#else "Oops, no RSA or DSA server private key found?!"); +#endif + ssl_die(); + } +} + +#ifdef HAVE_TLS_SESSION_TICKETS +static void ssl_init_ticket_key(server_rec *s, + apr_pool_t *p, + apr_pool_t *ptemp, + modssl_ctx_t *mctx) +{ + apr_status_t rv; + apr_file_t *fp; + apr_size_t len; + char buf[TLSEXT_TICKET_KEY_LEN]; + char *path; + modssl_ticket_key_t *ticket_key = mctx->ticket_key; + + if (!ticket_key->file_path) { + return; + } + + path = ap_server_root_relative(p, ticket_key->file_path); + + rv = apr_file_open(&fp, path, APR_READ|APR_BINARY, + APR_OS_DEFAULT, ptemp); + + if (rv != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02286) + "Failed to open ticket key file %s: (%d) %pm", + path, rv, &rv); + ssl_die(); + } + + rv = apr_file_read_full(fp, &buf[0], TLSEXT_TICKET_KEY_LEN, &len); + + if (rv != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02287) + "Failed to read %d bytes from %s: (%d) %pm", + TLSEXT_TICKET_KEY_LEN, path, rv, &rv); + ssl_die(); + } + + memcpy(ticket_key->key_name, buf, 16); + memcpy(ticket_key->hmac_secret, buf + 16, 16); + memcpy(ticket_key->aes_key, buf + 32, 16); + + if (!SSL_CTX_set_tlsext_ticket_key_cb(mctx->ssl_ctx, + ssl_callback_SessionTicket)) { + ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(01913) + "Unable to initialize TLS session ticket key callback " + "(incompatible OpenSSL version?)"); + ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s); ssl_die(); } + + ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, APLOGNO(02288) + "TLS session ticket key for %s successfully loaded from %s", + (mySrvConfig(s))->vhost_id, path); } +#endif static void ssl_init_proxy_certs(server_rec *s, apr_pool_t *p, @@ -976,6 +1201,9 @@ static void ssl_init_proxy_certs(server_rec *s, int n, ncerts = 0; STACK_OF(X509_INFO) *sk; modssl_pk_proxy_t *pkp = mctx->pkp; + STACK_OF(X509) *chain; + X509_STORE_CTX *sctx; + X509_STORE *store = SSL_CTX_get_cert_store(mctx->ssl_ctx); SSL_CTX_set_client_cert_cb(mctx->ssl_ctx, ssl_callback_proxy_cert); @@ -996,7 +1224,7 @@ static void ssl_init_proxy_certs(server_rec *s, if ((ncerts = sk_X509_INFO_num(sk)) <= 0) { sk_X509_INFO_free(sk); - ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, + ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(02206) "no client certs found for SSL proxy"); return; } @@ -1008,7 +1236,7 @@ static void ssl_init_proxy_certs(server_rec *s, if (!inf->x509 || !inf->x_pkey) { sk_X509_INFO_free(sk); - ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, + ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, APLOGNO(02252) "incomplete client cert configured for SSL proxy " "(missing or encrypted private key?)"); ssl_die(); @@ -1016,10 +1244,82 @@ static void ssl_init_proxy_certs(server_rec *s, } } - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(02207) "loaded %d client certs for SSL proxy", ncerts); pkp->certs = sk; + + + if (!pkp->ca_cert_file || !store) { + return; + } + + /* Load all of the CA certs and construct a chain */ + pkp->ca_certs = (STACK_OF(X509) **) apr_pcalloc(p, ncerts * sizeof(sk)); + sctx = X509_STORE_CTX_new(); + + if (!sctx) { + ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02208) + "SSL proxy client cert initialization failed"); + ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s); + ssl_die(); + } + + X509_STORE_load_locations(store, pkp->ca_cert_file, NULL); + + for (n = 0; n < ncerts; n++) { + int i; + + X509_INFO *inf = sk_X509_INFO_value(pkp->certs, n); + X509_STORE_CTX_init(sctx, store, inf->x509, NULL); + + /* Attempt to verify the client cert */ + if (X509_verify_cert(sctx) != 1) { + int err = X509_STORE_CTX_get_error(sctx); + ssl_log_xerror(SSLLOG_MARK, APLOG_WARNING, 0, ptemp, s, inf->x509, + APLOGNO(02270) "SSL proxy client cert chain " + "verification failed: %s :", + X509_verify_cert_error_string(err)); + } + + /* Clear X509_verify_cert errors */ + ERR_clear_error(); + + /* Obtain a copy of the verified chain */ + chain = X509_STORE_CTX_get1_chain(sctx); + + if (chain != NULL) { + /* Discard end entity cert from the chain */ + X509_free(sk_X509_shift(chain)); + + if ((i = sk_X509_num(chain)) > 0) { + /* Store the chain for later use */ + pkp->ca_certs[n] = chain; + } + else { + /* Discard empty chain */ + sk_X509_pop_free(chain, X509_free); + pkp->ca_certs[n] = NULL; + } + + ssl_log_xerror(SSLLOG_MARK, APLOG_DEBUG, 0, ptemp, s, inf->x509, + APLOGNO(02271) + "loaded %i intermediate CA%s for cert %i: ", + i, i == 1 ? "" : "s", n); + if (i > 0) { + int j; + for (j = 0; j < i; j++) { + ssl_log_xerror(SSLLOG_MARK, APLOG_DEBUG, 0, ptemp, s, + sk_X509_value(chain, j), "%i:", j); + } + } + } + + /* get ready for next X509_STORE_CTX_init */ + X509_STORE_CTX_cleanup(sctx); + } + + X509_STORE_CTX_free(sctx); } static void ssl_init_proxy_ctx(server_rec *s, @@ -1042,6 +1342,10 @@ static void ssl_init_server_ctx(server_rec *s, ssl_init_ctx(s, p, ptemp, sc->server); ssl_init_server_certs(s, p, ptemp, sc->server); + +#ifdef HAVE_TLS_SESSION_TICKETS + ssl_init_ticket_key(s, p, ptemp, sc->server); +#endif } /* @@ -1055,8 +1359,8 @@ void ssl_init_ConfigureServer(server_rec *s, /* Initialize the server if SSL is enabled or optional. */ if ((sc->enabled == SSL_ENABLED_TRUE) || (sc->enabled == SSL_ENABLED_OPTIONAL)) { - ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, - "Configuring server for SSL protocol"); + ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, APLOGNO(01914) + "Configuring server %s for SSL protocol", sc->vhost_id); ssl_init_server_ctx(s, p, ptemp, sc); } @@ -1084,7 +1388,7 @@ void ssl_init_CheckServers(server_rec *base_server, apr_pool_t *p) if ((sc->enabled == SSL_ENABLED_TRUE) && (s->port == DEFAULT_HTTP_PORT)) { ap_log_error(APLOG_MARK, APLOG_WARNING, 0, - base_server, + base_server, APLOGNO(01915) "Init: (%s) You configured HTTPS(%d) " "on the standard HTTP(%d) port!", ssl_util_vhostid(p, s), @@ -1093,7 +1397,7 @@ void ssl_init_CheckServers(server_rec *base_server, apr_pool_t *p) if ((sc->enabled == SSL_ENABLED_FALSE) && (s->port == DEFAULT_HTTPS_PORT)) { ap_log_error(APLOG_MARK, APLOG_WARNING, 0, - base_server, + base_server, APLOGNO(01916) "Init: (%s) You configured HTTP(%d) " "on the standard HTTPS(%d) port!", ssl_util_vhostid(p, s), @@ -1123,11 +1427,11 @@ void ssl_init_CheckServers(server_rec *base_server, apr_pool_t *p) klen = strlen(key); if ((ps = (server_rec *)apr_hash_get(table, key, klen))) { - ap_log_error(APLOG_MARK, + ap_log_error(APLOG_MARK, #ifdef OPENSSL_NO_TLSEXT - APLOG_WARNING, + APLOG_WARNING, #else - APLOG_DEBUG, + APLOG_DEBUG, #endif 0, base_server, @@ -1151,7 +1455,7 @@ void ssl_init_CheckServers(server_rec *base_server, apr_pool_t *p) } if (conflict) { - ap_log_error(APLOG_MARK, APLOG_WARNING, 0, base_server, + ap_log_error(APLOG_MARK, APLOG_WARNING, 0, base_server, APLOGNO(01917) #ifdef OPENSSL_NO_TLSEXT "Init: You should not use name-based " "virtual hosts in conjunction with SSL!!"); @@ -1163,39 +1467,32 @@ void ssl_init_CheckServers(server_rec *base_server, apr_pool_t *p) } } -#ifdef SSLC_VERSION_NUMBER -static int ssl_init_FindCAList_X509NameCmp(char **a, char **b) -{ - return(X509_NAME_cmp((void*)*a, (void*)*b)); -} -#else -static int ssl_init_FindCAList_X509NameCmp(const X509_NAME * const *a, +static int ssl_init_FindCAList_X509NameCmp(const X509_NAME * const *a, const X509_NAME * const *b) { return(X509_NAME_cmp(*a, *b)); } -#endif static void ssl_init_PushCAList(STACK_OF(X509_NAME) *ca_list, - server_rec *s, const char *file) + server_rec *s, apr_pool_t *ptemp, + const char *file) { int n; STACK_OF(X509_NAME) *sk; sk = (STACK_OF(X509_NAME) *) - SSL_load_client_CA_file(MODSSL_PCHAR_CAST file); + SSL_load_client_CA_file(file); if (!sk) { return; } for (n = 0; n < sk_X509_NAME_num(sk); n++) { - char name_buf[256]; X509_NAME *name = sk_X509_NAME_value(sk, n); - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(02209) "CA certificate: %s", - X509_NAME_oneline(name, name_buf, sizeof(name_buf))); + SSL_X509_NAME_to_string(ptemp, name, 0)); /* * note that SSL_load_client_CA_file() checks for duplicates, @@ -1233,7 +1530,16 @@ STACK_OF(X509_NAME) *ssl_init_FindCAList(server_rec *s, * Process CA certificate bundle file */ if (ca_file) { - ssl_init_PushCAList(ca_list, s, ca_file); + ssl_init_PushCAList(ca_list, s, ptemp, ca_file); + /* + * If ca_list is still empty after trying to load ca_file + * then the file failed to load, and users should hear about that. + */ + if (sk_X509_NAME_num(ca_list) == 0) { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(02210) + "Failed to load SSLCACertificateFile: %s", ca_file); + ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, s); + } } /* @@ -1246,7 +1552,7 @@ STACK_OF(X509_NAME) *ssl_init_FindCAList(server_rec *s, apr_status_t rv; if ((rv = apr_dir_open(&dir, ca_path, ptemp)) != APR_SUCCESS) { - ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, + ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s, APLOGNO(02211) "Failed to open Certificate Path `%s'", ca_path); ssl_die(); @@ -1258,7 +1564,7 @@ STACK_OF(X509_NAME) *ssl_init_FindCAList(server_rec *s, continue; /* don't try to load directories */ } file = apr_pstrcat(ptemp, ca_path, "/", direntry.name, NULL); - ssl_init_PushCAList(ca_list, s, file); + ssl_init_PushCAList(ca_list, s, ptemp, file); } apr_dir_close(dir); @@ -1282,6 +1588,9 @@ void ssl_init_Child(apr_pool_t *p, server_rec *s) /* open the mutex lockfile */ ssl_mutex_reinit(s, p); +#ifdef HAVE_OCSP_STAPLING + ssl_stapling_mutex_reinit(s, p); +#endif } #define MODSSL_CFG_ITEM_FREE(func, item) \ @@ -1292,8 +1601,6 @@ void ssl_init_Child(apr_pool_t *p, server_rec *s) static void ssl_init_ctx_cleanup(modssl_ctx_t *mctx) { - MODSSL_CFG_ITEM_FREE(X509_STORE_free, mctx->crl); - MODSSL_CFG_ITEM_FREE(SSL_CTX_free, mctx->ssl_ctx); } diff --git a/modules/ssl/ssl_engine_io.c b/modules/ssl/ssl_engine_io.c index e2d33909..2ffe21f4 100644 --- a/modules/ssl/ssl_engine_io.c +++ b/modules/ssl/ssl_engine_io.c @@ -102,17 +102,13 @@ typedef struct { BIO *pbioWrite; ap_filter_t *pInputFilter; ap_filter_t *pOutputFilter; - int nobuffer; /* non-zero to prevent buffering */ SSLConnRec *config; } ssl_filter_ctx_t; typedef struct { ssl_filter_ctx_t *filter_ctx; conn_rec *c; - apr_bucket_brigade *bb; - apr_size_t length; - char buffer[AP_IOBUFSIZE]; - apr_size_t blen; + apr_bucket_brigade *bb; /* Brigade used as a buffer. */ apr_status_t rc; } bio_filter_out_ctx_t; @@ -124,35 +120,15 @@ static bio_filter_out_ctx_t *bio_filter_out_ctx_new(ssl_filter_ctx_t *filter_ctx outctx->filter_ctx = filter_ctx; outctx->c = c; outctx->bb = apr_brigade_create(c->pool, c->bucket_alloc); - outctx->blen = 0; - outctx->length = 0; return outctx; } -static int bio_filter_out_flush(BIO *bio) +/* Pass an output brigade down the filter stack; returns 1 on success + * or -1 on failure. */ +static int bio_filter_out_pass(bio_filter_out_ctx_t *outctx) { - bio_filter_out_ctx_t *outctx = (bio_filter_out_ctx_t *)(bio->ptr); - apr_bucket *e; - - if (!(outctx->blen || outctx->length)) { - outctx->rc = APR_SUCCESS; - return 1; - } - - if (outctx->blen) { - e = apr_bucket_transient_create(outctx->buffer, outctx->blen, - outctx->bb->bucket_alloc); - /* we filled this buffer first so add it to the - * head of the brigade - */ - APR_BRIGADE_INSERT_HEAD(outctx->bb, e); - outctx->blen = 0; - } - - outctx->length = 0; - e = apr_bucket_flush_create(outctx->bb->bucket_alloc); - APR_BRIGADE_INSERT_TAIL(outctx->bb, e); + AP_DEBUG_ASSERT(!APR_BRIGADE_EMPTY(outctx->bb)); outctx->rc = ap_pass_brigade(outctx->filter_ctx->pOutputFilter->next, outctx->bb); @@ -163,6 +139,21 @@ static int bio_filter_out_flush(BIO *bio) return (outctx->rc == APR_SUCCESS) ? 1 : -1; } +/* Send a FLUSH bucket down the output filter stack; returns 1 on + * success, -1 on failure. */ +static int bio_filter_out_flush(BIO *bio) +{ + bio_filter_out_ctx_t *outctx = (bio_filter_out_ctx_t *)(bio->ptr); + apr_bucket *e; + + AP_DEBUG_ASSERT(APR_BRIGADE_EMPTY(outctx->bb)); + + e = apr_bucket_flush_create(outctx->bb->bucket_alloc); + APR_BRIGADE_INSERT_TAIL(outctx->bb, e); + + return bio_filter_out_pass(outctx); +} + static int bio_filter_create(BIO *bio) { bio->shutdown = 1; @@ -194,45 +185,27 @@ static int bio_filter_out_read(BIO *bio, char *out, int outl) static int bio_filter_out_write(BIO *bio, const char *in, int inl) { bio_filter_out_ctx_t *outctx = (bio_filter_out_ctx_t *)(bio->ptr); - + apr_bucket *e; + /* Abort early if the client has initiated a renegotiation. */ if (outctx->filter_ctx->config->reneg_state == RENEG_ABORT) { outctx->rc = APR_ECONNABORTED; return -1; } - + /* when handshaking we'll have a small number of bytes. * max size SSL will pass us here is about 16k. * (16413 bytes to be exact) */ BIO_clear_retry_flags(bio); - if (!outctx->length && (inl + outctx->blen < sizeof(outctx->buffer)) && - !outctx->filter_ctx->nobuffer) { - /* the first two SSL_writes (of 1024 and 261 bytes) - * need to be in the same packet (vec[0].iov_base) - */ - /* XXX: could use apr_brigade_write() to make code look cleaner - * but this way we avoid the malloc(APR_BUCKET_BUFF_SIZE) - * and free() of it later - */ - memcpy(&outctx->buffer[outctx->blen], in, inl); - outctx->blen += inl; - } - else { - /* pass along the encrypted data - * need to flush since we're using SSL's malloc-ed buffer - * which will be overwritten once we leave here - */ - apr_bucket *bucket = apr_bucket_transient_create(in, inl, - outctx->bb->bucket_alloc); - - outctx->length += inl; - APR_BRIGADE_INSERT_TAIL(outctx->bb, bucket); + /* Use a transient bucket for the output data - any downstream + * filter must setaside if necessary. */ + e = apr_bucket_transient_create(in, inl, outctx->bb->bucket_alloc); + APR_BRIGADE_INSERT_TAIL(outctx->bb, e); - if (bio_filter_out_flush(bio) < 0) { - return -1; - } + if (bio_filter_out_pass(outctx) < 0) { + return -1; } return inl; @@ -241,39 +214,27 @@ static int bio_filter_out_write(BIO *bio, const char *in, int inl) static long bio_filter_out_ctrl(BIO *bio, int cmd, long num, void *ptr) { long ret = 1; - char **pptr; - bio_filter_out_ctx_t *outctx = (bio_filter_out_ctx_t *)(bio->ptr); switch (cmd) { - case BIO_CTRL_RESET: - outctx->blen = outctx->length = 0; - break; - case BIO_CTRL_EOF: - ret = (long)((outctx->blen + outctx->length) == 0); - break; - case BIO_C_SET_BUF_MEM_EOF_RETURN: - outctx->blen = outctx->length = (apr_size_t)num; + case BIO_CTRL_RESET: + case BIO_CTRL_EOF: + case BIO_C_SET_BUF_MEM_EOF_RETURN: + ap_log_cerror(APLOG_MARK, APLOG_TRACE4, 0, outctx->c, + "output bio: unhandled control %d", cmd); + ret = 0; break; - case BIO_CTRL_INFO: - ret = (long)(outctx->blen + outctx->length); - if (ptr) { - pptr = (char **)ptr; - *pptr = (char *)&(outctx->buffer[0]); - } + case BIO_CTRL_WPENDING: + case BIO_CTRL_PENDING: + case BIO_CTRL_INFO: + ret = 0; break; - case BIO_CTRL_GET_CLOSE: + case BIO_CTRL_GET_CLOSE: ret = (long)bio->shutdown; break; case BIO_CTRL_SET_CLOSE: bio->shutdown = (int)num; break; - case BIO_CTRL_WPENDING: - ret = 0L; - break; - case BIO_CTRL_PENDING: - ret = (long)(outctx->blen + outctx->length); - break; case BIO_CTRL_FLUSH: ret = bio_filter_out_flush(bio); break; @@ -316,9 +277,7 @@ static BIO_METHOD bio_filter_out_method = { bio_filter_out_ctrl, bio_filter_create, bio_filter_destroy, -#ifdef OPENSSL_VERSION_NUMBER - NULL /* sslc does not have the callback_ctrl field */ -#endif + NULL }; typedef struct { @@ -570,9 +529,7 @@ static BIO_METHOD bio_filter_in_method = { NULL, /* ctrl is never called */ bio_filter_create, bio_filter_destroy, -#ifdef OPENSSL_VERSION_NUMBER - NULL /* sslc does not have the callback_ctrl field */ -#endif + NULL }; @@ -680,7 +637,7 @@ static apr_status_t ssl_io_input_read(bio_filter_in_ctx_t *inctx, * data from network filter. * * (This is usually the case when the client forces an SSL - * renegotation which is handled implicitly by OpenSSL.) + * renegotiation which is handled implicitly by OpenSSL.) */ inctx->rc = APR_EAGAIN; @@ -707,7 +664,7 @@ static apr_status_t ssl_io_input_read(bio_filter_in_ctx_t *inctx, continue; /* Blocking and nothing yet? Try again. */ } else { - ap_log_cerror(APLOG_MARK, APLOG_INFO, inctx->rc, c, + ap_log_cerror(APLOG_MARK, APLOG_INFO, inctx->rc, c, APLOGNO(01991) "SSL input filter read failed."); } } @@ -715,9 +672,9 @@ static apr_status_t ssl_io_input_read(bio_filter_in_ctx_t *inctx, /* * Log SSL errors and any unexpected conditions. */ - ap_log_cerror(APLOG_MARK, APLOG_INFO, inctx->rc, c, + ap_log_cerror(APLOG_MARK, APLOG_INFO, inctx->rc, c, APLOGNO(01992) "SSL library error %d reading data", ssl_err); - ssl_log_ssl_error(APLOG_MARK, APLOG_INFO, mySrvFromConn(c)); + ssl_log_ssl_error(SSLLOG_MARK, APLOG_INFO, mySrvFromConn(c)); } if (inctx->rc == APR_SUCCESS) { @@ -729,6 +686,9 @@ static apr_status_t ssl_io_input_read(bio_filter_in_ctx_t *inctx, return inctx->rc; } +/* Read a line of input from the SSL input layer into buffer BUF of + * length *LEN; updating *len to reflect the length of the line + * including the LF character. */ static apr_status_t ssl_io_input_getline(bio_filter_in_ctx_t *inctx, char *buf, apr_size_t *len) @@ -811,21 +771,21 @@ static apr_status_t ssl_filter_write(ap_filter_t *f, * data at the network filter. * * (This is usually the case when the client forces an SSL - * renegotation which is handled implicitly by OpenSSL.) + * renegotiation which is handled implicitly by OpenSSL.) */ outctx->rc = APR_EAGAIN; } else if (ssl_err == SSL_ERROR_SYSCALL) { - ap_log_cerror(APLOG_MARK, APLOG_INFO, outctx->rc, c, + ap_log_cerror(APLOG_MARK, APLOG_INFO, outctx->rc, c, APLOGNO(01993) "SSL output filter write failed."); } else /* if (ssl_err == SSL_ERROR_SSL) */ { /* * Log SSL errors */ - ap_log_cerror(APLOG_MARK, APLOG_INFO, outctx->rc, c, + ap_log_cerror(APLOG_MARK, APLOG_INFO, outctx->rc, c, APLOGNO(01994) "SSL library error %d writing data", ssl_err); - ssl_log_ssl_error(APLOG_MARK, APLOG_INFO, mySrvFromConn(c)); + ssl_log_ssl_error(SSLLOG_MARK, APLOG_INFO, mySrvFromConn(c)); } if (outctx->rc == APR_SUCCESS) { outctx->rc = APR_EGENERAL; @@ -840,7 +800,7 @@ static apr_status_t ssl_filter_write(ap_filter_t *f, reason = "likely due to failed renegotiation"; } - ap_log_cerror(APLOG_MARK, APLOG_INFO, outctx->rc, c, + ap_log_cerror(APLOG_MARK, APLOG_INFO, outctx->rc, c, APLOGNO(01995) "failed to write %" APR_SSIZE_T_FMT " of %" APR_SIZE_T_FMT " bytes (%s)", len - (apr_size_t)res, len, reason); @@ -865,6 +825,14 @@ static apr_status_t ssl_filter_write(ap_filter_t *f, sizeof(HTTP_ON_HTTPS_PORT) - 1, \ alloc) +/* Custom apr_status_t error code, used when a plain HTTP request is + * recevied on an SSL port. */ +#define MODSSL_ERROR_HTTP_ON_HTTPS (APR_OS_START_USERERR + 0) + +/* Custom apr_status_t error code, used when the proxy cannot + * establish an outgoing SSL connection. */ +#define MODSSL_ERROR_BAD_GATEWAY (APR_OS_START_USERERR + 1) + static void ssl_io_filter_disable(SSLConnRec *sslconn, ap_filter_t *f) { bio_filter_in_ctx_t *inctx = f->ctx; @@ -882,12 +850,12 @@ static apr_status_t ssl_io_filter_error(ap_filter_t *f, apr_bucket *bucket; switch (status) { - case HTTP_BAD_REQUEST: + case MODSSL_ERROR_HTTP_ON_HTTPS: /* log the situation */ - ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, f->c, + ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, f->c, APLOGNO(01996) "SSL handshake failed: HTTP spoken on HTTPS port; " "trying to send HTML error page"); - ssl_log_ssl_error(APLOG_MARK, APLOG_INFO, sslconn->server); + ssl_log_ssl_error(SSLLOG_MARK, APLOG_INFO, sslconn->server); sslconn->non_ssl_request = 1; ssl_io_filter_disable(sslconn, f); @@ -896,7 +864,15 @@ static apr_status_t ssl_io_filter_error(ap_filter_t *f, bucket = HTTP_ON_HTTPS_PORT_BUCKET(f->c->bucket_alloc); break; - default: + case MODSSL_ERROR_BAD_GATEWAY: + bucket = ap_bucket_error_create(HTTP_BAD_REQUEST, NULL, + f->c->pool, + f->c->bucket_alloc); + ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, f->c, APLOGNO(01997) + "SSL handshake failed: sending 502"); + break; + + default: return status; } @@ -909,23 +885,25 @@ static apr_status_t ssl_io_filter_error(ap_filter_t *f, static const char ssl_io_filter[] = "SSL/TLS Filter"; static const char ssl_io_buffer[] = "SSL/TLS Buffer"; +static const char ssl_io_coalesce[] = "SSL/TLS Coalescing Filter"; /* * Close the SSL part of the socket connection * (called immediately _before_ the socket is closed) * or called with */ -static apr_status_t ssl_filter_io_shutdown(ssl_filter_ctx_t *filter_ctx, - conn_rec *c, - int abortive) +static void ssl_filter_io_shutdown(ssl_filter_ctx_t *filter_ctx, + conn_rec *c, int abortive) { SSL *ssl = filter_ctx->pssl; const char *type = ""; SSLConnRec *sslconn = myConnConfig(c); int shutdown_type; + int loglevel = APLOG_DEBUG; + const char *logno; if (!ssl) { - return APR_SUCCESS; + return; } /* @@ -967,6 +945,8 @@ static apr_status_t ssl_filter_io_shutdown(ssl_filter_ctx_t *filter_ctx, if (abortive) { shutdown_type = SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN; type = "abortive"; + logno = APLOGNO(01998); + loglevel = APLOG_INFO; } else switch (sslconn->shutdown_type) { case SSL_SHUTDOWN_TYPE_UNCLEAN: @@ -974,12 +954,14 @@ static apr_status_t ssl_filter_io_shutdown(ssl_filter_ctx_t *filter_ctx, (violates the SSL/TLS standard!) */ shutdown_type = SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN; type = "unclean"; + logno = APLOGNO(01999); break; case SSL_SHUTDOWN_TYPE_ACCURATE: /* send close notify and wait for clients close notify (standard compliant, but usually causes connection hangs) */ shutdown_type = 0; type = "accurate"; + logno = APLOGNO(02000); break; default: /* @@ -990,6 +972,7 @@ static apr_status_t ssl_filter_io_shutdown(ssl_filter_ctx_t *filter_ctx, (standard compliant and safe, so it's the DEFAULT!) */ shutdown_type = SSL_RECEIVED_SHUTDOWN; type = "standard"; + logno = APLOGNO(02001); break; } @@ -997,11 +980,12 @@ static apr_status_t ssl_filter_io_shutdown(ssl_filter_ctx_t *filter_ctx, SSL_smart_shutdown(ssl); /* and finally log the fact that we've closed the connection */ - if (mySrvFromConn(c)->loglevel >= APLOG_INFO) { - ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, c, - "Connection closed to child %ld with %s shutdown " - "(server %s)", - c->id, type, ssl_util_vhostid(c->pool, mySrvFromConn(c))); + if (APLOG_CS_IS_LEVEL(c, mySrvFromConn(c), loglevel)) { + ap_log_cserror(APLOG_MARK, loglevel, 0, c, mySrvFromConn(c), + "%sConnection closed to child %ld with %s shutdown " + "(server %s)", + logno, c->id, type, + ssl_util_vhostid(c->pool, mySrvFromConn(c))); } /* deallocate the SSL connection */ @@ -1017,8 +1001,6 @@ static apr_status_t ssl_filter_io_shutdown(ssl_filter_ctx_t *filter_ctx, /* prevent any further I/O */ c->aborted = 1; } - - return APR_SUCCESS; } static apr_status_t ssl_io_filter_cleanup(void *data) @@ -1043,7 +1025,10 @@ static apr_status_t ssl_io_filter_cleanup(void *data) * Adv. if conn_rec * can be accepted is we can hook this function using the * ap_hook_process_connection hook. */ -static int ssl_io_filter_connect(ssl_filter_ctx_t *filter_ctx) + +/* Perform the SSL handshake (whether in client or server mode), if + * necessary, for the given connection. */ +static apr_status_t ssl_io_filter_handshake(ssl_filter_ctx_t *filter_ctx) { conn_rec *c = (conn_rec *)SSL_get_app_data(filter_ctx->pssl); SSLConnRec *sslconn = myConnConfig(c); @@ -1060,59 +1045,87 @@ static int ssl_io_filter_connect(ssl_filter_ctx_t *filter_ctx) server = sslconn->server; if (sslconn->is_proxy) { - const char *hostname_note; - +#ifndef OPENSSL_NO_TLSEXT + apr_ipsubnet_t *ip; +#endif + const char *hostname_note = apr_table_get(c->notes, + "proxy-request-hostname"); sc = mySrvConfig(server); + +#ifndef OPENSSL_NO_TLSEXT + /* + * Enable SNI for backend requests. Make sure we don't do it for + * pure SSLv3 connections, and also prevent IP addresses + * from being included in the SNI extension. (OpenSSL would simply + * pass them on, but RFC 6066 is quite clear on this: "Literal + * IPv4 and IPv6 addresses are not permitted".) + */ + if (hostname_note && + sc->proxy->protocol != SSL_PROTOCOL_SSLV3 && + apr_ipsubnet_create(&ip, hostname_note, NULL, + c->pool) != APR_SUCCESS) { + if (SSL_set_tlsext_host_name(filter_ctx->pssl, hostname_note)) { + ap_log_cerror(APLOG_MARK, APLOG_TRACE3, 0, c, + "SNI extension for SSL Proxy request set to '%s'", + hostname_note); + } else { + ap_log_cerror(APLOG_MARK, APLOG_WARNING, 0, c, APLOGNO(02002) + "Failed to set SNI extension for SSL Proxy " + "request to '%s'", hostname_note); + ssl_log_ssl_error(SSLLOG_MARK, APLOG_WARNING, server); + } + } +#endif + if ((n = SSL_connect(filter_ctx->pssl)) <= 0) { - ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, c, + ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, c, APLOGNO(02003) "SSL Proxy connect failed"); - ssl_log_ssl_error(APLOG_MARK, APLOG_INFO, server); + ssl_log_ssl_error(SSLLOG_MARK, APLOG_INFO, server); /* ensure that the SSL structures etc are freed, etc: */ ssl_filter_io_shutdown(filter_ctx, c, 1); - apr_table_set(c->notes, "SSL_connect_rv", "err"); - return HTTP_BAD_GATEWAY; + apr_table_setn(c->notes, "SSL_connect_rv", "err"); + return MODSSL_ERROR_BAD_GATEWAY; } - if (sc->proxy_ssl_check_peer_expire == SSL_ENABLED_TRUE) { + if (sc->proxy_ssl_check_peer_expire != SSL_ENABLED_FALSE) { cert = SSL_get_peer_certificate(filter_ctx->pssl); if (!cert || (X509_cmp_current_time( X509_get_notBefore(cert)) >= 0) || (X509_cmp_current_time( X509_get_notAfter(cert)) <= 0)) { - ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, c, + ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, c, APLOGNO(02004) "SSL Proxy: Peer certificate is expired"); if (cert) { X509_free(cert); } /* ensure that the SSL structures etc are freed, etc: */ ssl_filter_io_shutdown(filter_ctx, c, 1); - apr_table_set(c->notes, "SSL_connect_rv", "err"); + apr_table_setn(c->notes, "SSL_connect_rv", "err"); return HTTP_BAD_GATEWAY; } X509_free(cert); } - if ((sc->proxy_ssl_check_peer_cn == SSL_ENABLED_TRUE) - && ((hostname_note = - apr_table_get(c->notes, "proxy-request-hostname")) != NULL)) { + if ((sc->proxy_ssl_check_peer_cn != SSL_ENABLED_FALSE) && + hostname_note) { const char *hostname; hostname = ssl_var_lookup(NULL, server, c, NULL, "SSL_CLIENT_S_DN_CN"); apr_table_unset(c->notes, "proxy-request-hostname"); if (strcasecmp(hostname, hostname_note)) { - ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, c, + ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, c, APLOGNO(02005) "SSL Proxy: Peer certificate CN mismatch:" " Certificate CN: %s Requested hostname: %s", hostname, hostname_note); /* ensure that the SSL structures etc are freed, etc: */ ssl_filter_io_shutdown(filter_ctx, c, 1); - apr_table_set(c->notes, "SSL_connect_rv", "err"); + apr_table_setn(c->notes, "SSL_connect_rv", "err"); return HTTP_BAD_GATEWAY; } } - apr_table_set(c->notes, "SSL_connect_rv", "ok"); + apr_table_setn(c->notes, "SSL_connect_rv", "ok"); return APR_SUCCESS; } @@ -1130,7 +1143,7 @@ static int ssl_io_filter_connect(ssl_filter_ctx_t *filter_ctx) * was transferred. That's not a real error and can occur * sporadically with some clients. */ - ap_log_cerror(APLOG_MARK, APLOG_INFO, rc, c, + ap_log_cerror(APLOG_MARK, APLOG_INFO, rc, c, APLOGNO(02006) "SSL handshake stopped: connection was closed"); } else if (ssl_err == SSL_ERROR_WANT_READ) { @@ -1140,7 +1153,7 @@ static int ssl_io_filter_connect(ssl_filter_ctx_t *filter_ctx) * TBD. */ outctx->rc = APR_EAGAIN; - return SSL_ERROR_WANT_READ; + return APR_EAGAIN; } else if (ERR_GET_LIB(ERR_peek_error()) == ERR_LIB_SSL && ERR_GET_REASON(ERR_peek_error()) == SSL_R_HTTP_REQUEST) { @@ -1150,10 +1163,10 @@ static int ssl_io_filter_connect(ssl_filter_ctx_t *filter_ctx) * ssl_io_filter_error will disable the ssl filters when it * sees this status code. */ - return HTTP_BAD_REQUEST; + return MODSSL_ERROR_HTTP_ON_HTTPS; } else if (ssl_err == SSL_ERROR_SYSCALL) { - ap_log_cerror(APLOG_MARK, APLOG_INFO, rc, c, + ap_log_cerror(APLOG_MARK, APLOG_DEBUG, rc, c, APLOGNO(02007) "SSL handshake interrupted by system " "[Hint: Stop button pressed in browser?!]"); } @@ -1161,18 +1174,19 @@ static int ssl_io_filter_connect(ssl_filter_ctx_t *filter_ctx) /* * Log SSL errors and any unexpected conditions. */ - ap_log_cerror(APLOG_MARK, APLOG_INFO, rc, c, + ap_log_cerror(APLOG_MARK, APLOG_INFO, rc, c, APLOGNO(02008) "SSL library error %d in handshake " "(server %s)", ssl_err, ssl_util_vhostid(c->pool, server)); - ssl_log_ssl_error(APLOG_MARK, APLOG_INFO, server); + ssl_log_ssl_error(SSLLOG_MARK, APLOG_INFO, server); } if (inctx->rc == APR_SUCCESS) { inctx->rc = APR_EGENERAL; } - return ssl_filter_io_shutdown(filter_ctx, c, 1); + ssl_filter_io_shutdown(filter_ctx, c, 1); + return inctx->rc; } sc = mySrvConfig(sslconn->server); @@ -1195,24 +1209,25 @@ static int ssl_io_filter_connect(ssl_filter_ctx_t *filter_ctx) * optional_no_ca doesn't appear to work as advertised * in 1.x */ - ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, c, + ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, c, APLOGNO(02009) "SSL client authentication failed, " "accepting certificate based on " "\"SSLVerifyClient optional_no_ca\" " "configuration"); - ssl_log_ssl_error(APLOG_MARK, APLOG_INFO, server); + ssl_log_ssl_error(SSLLOG_MARK, APLOG_INFO, server); } else { const char *error = sslconn->verify_error ? sslconn->verify_error : X509_verify_cert_error_string(verify_result); - ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, c, + ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, c, APLOGNO(02010) "SSL client authentication failed: %s", error ? error : "unknown"); - ssl_log_ssl_error(APLOG_MARK, APLOG_INFO, server); + ssl_log_ssl_error(SSLLOG_MARK, APLOG_INFO, server); - return ssl_filter_io_shutdown(filter_ctx, c, 1); + ssl_filter_io_shutdown(filter_ctx, c, 1); + return APR_ECONNABORTED; } } @@ -1234,94 +1249,16 @@ static int ssl_io_filter_connect(ssl_filter_ctx_t *filter_ctx) if ((sc->server->auth.verify_mode == SSL_CVERIFY_REQUIRE) && !sslconn->client_cert) { - ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, c, + ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, c, APLOGNO(02011) "No acceptable peer certificate available"); - return ssl_filter_io_shutdown(filter_ctx, c, 1); + ssl_filter_io_shutdown(filter_ctx, c, 1); + return APR_ECONNABORTED; } return APR_SUCCESS; } -#define SWITCH_STATUS_LINE "HTTP/1.1 101 Switching Protocols" -#define UPGRADE_HEADER "Upgrade: TLS/1.0, HTTP/1.1" -#define CONNECTION_HEADER "Connection: Upgrade" - -static apr_status_t ssl_io_filter_Upgrade(ap_filter_t *f, - apr_bucket_brigade *bb) -{ - const char *upgrade; - apr_bucket_brigade *upgradebb; - request_rec *r = f->r; - SSLConnRec *sslconn; - apr_status_t rv; - apr_bucket *b; - SSL *ssl; - - /* Just remove the filter, if it doesn't work the first time, it won't - * work at all for this request. - */ - ap_remove_output_filter(f); - - /* No need to ensure that this is a server with optional SSL, the filter - * is only inserted if that is true. - */ - - upgrade = apr_table_get(r->headers_in, "Upgrade"); - if (upgrade == NULL - || strcmp(ap_getword(r->pool, &upgrade, ','), "TLS/1.0")) { - /* "Upgrade: TLS/1.0, ..." header not found, don't do Upgrade */ - return ap_pass_brigade(f->next, bb); - } - - apr_table_unset(r->headers_out, "Upgrade"); - - /* Send the interim 101 response. */ - upgradebb = apr_brigade_create(r->pool, f->c->bucket_alloc); - - ap_fputstrs(f->next, upgradebb, SWITCH_STATUS_LINE, CRLF, - UPGRADE_HEADER, CRLF, CONNECTION_HEADER, CRLF, CRLF, NULL); - - b = apr_bucket_flush_create(f->c->bucket_alloc); - APR_BRIGADE_INSERT_TAIL(upgradebb, b); - - rv = ap_pass_brigade(f->next, upgradebb); - if (rv) { - ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, - "could not send interim 101 Upgrade response"); - return AP_FILTER_ERROR; - } - - ssl_init_ssl_connection(f->c); - - ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, - "Awaiting re-negotiation handshake"); - - sslconn = myConnConfig(f->c); - ssl = sslconn->ssl; - - /* XXX: Should replace SSL_set_state with SSL_renegotiate(ssl); - * However, this causes failures in perl-framework currently, - * perhaps pre-test if we have already negotiated? - */ - SSL_set_accept_state(ssl); - SSL_do_handshake(ssl); - - if (SSL_get_state(ssl) != SSL_ST_OK) { - ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, - "TLS Upgrade handshake failed: " - "Not accepted by client!?"); - - return AP_FILTER_ERROR; - } - - /* Now that we have initialized the ssl connection which added the ssl_io_filter, - pass the brigade off to the connection based output filters so that the - request can complete encrypted */ - return ap_pass_brigade(f->c->output_filters, bb); - -} - static apr_status_t ssl_io_filter_input(ap_filter_t *f, apr_bucket_brigade *bb, ap_input_mode_t mode, @@ -1330,8 +1267,8 @@ static apr_status_t ssl_io_filter_input(ap_filter_t *f, { apr_status_t status; bio_filter_in_ctx_t *inctx = f->ctx; - - apr_size_t len = sizeof(inctx->buffer); + const char *start = inctx->buffer; /* start of block to return */ + apr_size_t len = sizeof(inctx->buffer); /* length of block to return */ int is_init = (mode == AP_MODE_INIT); if (f->c->aborted) { @@ -1357,12 +1294,12 @@ static apr_status_t ssl_io_filter_input(ap_filter_t *f, inctx->mode = mode; inctx->block = block; - /* XXX: we could actually move ssl_io_filter_connect to an + /* XXX: we could actually move ssl_io_filter_handshake to an * ap_hook_process_connection but would still need to call it for * AP_MODE_INIT for protocols that may upgrade the connection * rather than have SSLEngine On configured. */ - if ((status = ssl_io_filter_connect(inctx->filter_ctx)) != APR_SUCCESS) { + if ((status = ssl_io_filter_handshake(inctx->filter_ctx)) != APR_SUCCESS) { return ssl_io_filter_error(f, bb, status); } @@ -1383,7 +1320,25 @@ static apr_status_t ssl_io_filter_input(ap_filter_t *f, status = ssl_io_input_read(inctx, inctx->buffer, &len); } else if (inctx->mode == AP_MODE_GETLINE) { - status = ssl_io_input_getline(inctx, inctx->buffer, &len); + const char *pos; + + /* Satisfy the read directly out of the buffer if possible; + * invoking ssl_io_input_getline will mean the entire buffer + * is copied once (unnecessarily) for each GETLINE call. */ + if (inctx->cbuf.length + && (pos = memchr(inctx->cbuf.value, APR_ASCII_LF, + inctx->cbuf.length)) != NULL) { + start = inctx->cbuf.value; + len = 1 + pos - start; /* +1 to include LF */ + /* Buffer contents now consumed. */ + inctx->cbuf.value += len; + inctx->cbuf.length -= len; + status = APR_SUCCESS; + } + else { + /* Otherwise fall back to the hard way. */ + status = ssl_io_input_getline(inctx, inctx->buffer, &len); + } } else { /* We have no idea what you are talking about, so return an error. */ @@ -1405,13 +1360,156 @@ static apr_status_t ssl_io_filter_input(ap_filter_t *f, /* Create a transient bucket out of the decrypted data. */ if (len > 0) { apr_bucket *bucket = - apr_bucket_transient_create(inctx->buffer, len, f->c->bucket_alloc); + apr_bucket_transient_create(start, len, f->c->bucket_alloc); APR_BRIGADE_INSERT_TAIL(bb, bucket); } return APR_SUCCESS; } + +/* ssl_io_filter_output() produces one SSL/TLS message per bucket + * passed down the output filter stack. This results in a high + * overhead (network packets) for any output comprising many small + * buckets. SSI page applied through the HTTP chunk filter, for + * example, may produce many brigades containing small buckets - + * [chunk-size CRLF] [chunk-data] [CRLF]. + * + * The coalescing filter merges many small buckets into larger buckets + * where possible, allowing the SSL I/O output filter to handle them + * more efficiently. */ + +#define COALESCE_BYTES (2048) + +struct coalesce_ctx { + char buffer[COALESCE_BYTES]; + apr_size_t bytes; /* number of bytes of buffer used. */ +}; + +static apr_status_t ssl_io_filter_coalesce(ap_filter_t *f, + apr_bucket_brigade *bb) +{ + apr_bucket *e, *last = NULL; + apr_size_t bytes = 0; + struct coalesce_ctx *ctx = f->ctx; + unsigned count = 0; + + /* The brigade consists of zero-or-more small data buckets which + * can be coalesced (the prefix), followed by the remainder of the + * brigade. + * + * Find the last bucket - if any - of that prefix. count gives + * the number of buckets in the prefix. The "prefix" must contain + * only data buckets with known length, and must be of a total + * size which fits into the buffer. + * + * N.B.: The process here could be repeated throughout the brigade + * (coalesce any run of consecutive data buckets) but this would + * add significant complexity, particularly to memory + * management. */ + for (e = APR_BRIGADE_FIRST(bb); + e != APR_BRIGADE_SENTINEL(bb) + && !APR_BUCKET_IS_METADATA(e) + && e->length != (apr_size_t)-1 + && e->length < COALESCE_BYTES + && (bytes + e->length) < COALESCE_BYTES + && (ctx == NULL + || bytes + ctx->bytes + e->length < COALESCE_BYTES); + e = APR_BUCKET_NEXT(e)) { + last = e; + if (e->length) count++; /* don't count zero-length buckets */ + bytes += e->length; + } + + /* Coalesce the prefix, if: + * a) more than one bucket is found to coalesce, or + * b) the brigade contains only a single data bucket, or + * c) + */ + if (bytes > 0 + && (count > 1 + || (count == 1 && APR_BUCKET_NEXT(last) == APR_BRIGADE_SENTINEL(bb)))) { + /* If coalescing some bytes, ensure a context has been + * created. */ + if (!ctx) { + f->ctx = ctx = apr_palloc(f->c->pool, sizeof *ctx); + ctx->bytes = 0; + } + + ap_log_cerror(APLOG_MARK, APLOG_TRACE4, 0, f->c, + "coalesce: have %" APR_SIZE_T_FMT " bytes, " + "adding %" APR_SIZE_T_FMT " more", ctx->bytes, bytes); + + /* Iterate through the prefix segment. For non-fatal errors + * in this loop it is safe to break out and fall back to the + * normal path of sending the buffer + remaining buckets in + * brigade. */ + e = APR_BRIGADE_FIRST(bb); + while (e != last) { + apr_size_t len; + const char *data; + apr_bucket *next; + + if (APR_BUCKET_IS_METADATA(e) + || e->length == (apr_size_t)-1) { + ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, f->c, APLOGNO(02012) + "unexpected bucket type during coalesce"); + break; /* non-fatal error; break out */ + } + + if (e->length) { + apr_status_t rv; + + /* A blocking read should be fine here for a + * known-length data bucket, rather than the usual + * non-block/flush/block. */ + rv = apr_bucket_read(e, &data, &len, APR_BLOCK_READ); + if (rv) { + ap_log_cerror(APLOG_MARK, APLOG_ERR, rv, f->c, APLOGNO(02013) + "coalesce failed to read from data bucket"); + return AP_FILTER_ERROR; + } + + /* Be paranoid. */ + if (len > sizeof ctx->buffer + || (len + ctx->bytes > sizeof ctx->buffer)) { + ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, f->c, APLOGNO(02014) + "unexpected coalesced bucket data length"); + break; /* non-fatal error; break out */ + } + + memcpy(ctx->buffer + ctx->bytes, data, len); + ctx->bytes += len; + } + + next = APR_BUCKET_NEXT(e); + apr_bucket_delete(e); + e = next; + } + } + + if (APR_BRIGADE_EMPTY(bb)) { + /* If the brigade is now empty, our work here is done. */ + return APR_SUCCESS; + } + + /* If anything remains in the brigade, it must now be passed down + * the filter stack, first prepending anything that has been + * coalesced. */ + if (ctx && ctx->bytes) { + apr_bucket *e; + + ap_log_cerror(APLOG_MARK, APLOG_TRACE4, 0, f->c, + "coalesce: passing on %" APR_SIZE_T_FMT " bytes", ctx->bytes); + + e = apr_bucket_transient_create(ctx->buffer, ctx->bytes, bb->bucket_alloc); + APR_BRIGADE_INSERT_HEAD(bb, e); + ctx->bytes = 0; /* buffer now emptied. */ + } + + return ap_pass_brigade(f->next, bb); +} + static apr_status_t ssl_io_filter_output(ap_filter_t *f, apr_bucket_brigade *bb) { @@ -1441,7 +1539,7 @@ static apr_status_t ssl_io_filter_output(ap_filter_t *f, inctx->mode = AP_MODE_READBYTES; inctx->block = APR_BLOCK_READ; - if ((status = ssl_io_filter_connect(filter_ctx)) != APR_SUCCESS) { + if ((status = ssl_io_filter_handshake(filter_ctx)) != APR_SUCCESS) { return ssl_io_filter_error(f, bb, status); } @@ -1478,16 +1576,9 @@ static apr_status_t ssl_io_filter_output(ap_filter_t *f, } } else if (AP_BUCKET_IS_EOC(bucket)) { - /* The special "EOC" bucket means a shutdown is needed; - * - turn off buffering in bio_filter_out_write - * - issue the SSL_shutdown - */ - filter_ctx->nobuffer = 1; - status = ssl_filter_io_shutdown(filter_ctx, f->c, 0); - if (status != APR_SUCCESS) { - ap_log_cerror(APLOG_MARK, APLOG_INFO, status, f->c, - "SSL filter error shutting down I/O"); - } + /* The EOC bucket indicates connection closure, so SSL + * shutdown must now be performed. */ + ssl_filter_io_shutdown(filter_ctx, f->c, 0); if ((status = ap_pass_brigade(f->next, bb)) != APR_SUCCESS) { return status; } @@ -1530,7 +1621,6 @@ static apr_status_t ssl_io_filter_output(ap_filter_t *f, struct modssl_buffer_ctx { apr_bucket_brigade *bb; - apr_pool_t *pool; }; int ssl_io_buffer_fill(request_rec *r, apr_size_t maxlen) @@ -1545,13 +1635,12 @@ int ssl_io_buffer_fill(request_rec *r, apr_size_t maxlen) * containing a setaside pool and a brigade which constrain the * lifetime of the buffered data. */ ctx = apr_palloc(r->pool, sizeof *ctx); - apr_pool_create(&ctx->pool, r->pool); - ctx->bb = apr_brigade_create(ctx->pool, c->bucket_alloc); + ctx->bb = apr_brigade_create(r->pool, c->bucket_alloc); /* ... and a temporary brigade. */ tempb = apr_brigade_create(r->pool, c->bucket_alloc); - ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, "filling buffer, max size " + ap_log_cerror(APLOG_MARK, APLOG_TRACE4, 0, c, "filling buffer, max size " "%" APR_SIZE_T_FMT " bytes", maxlen); do { @@ -1566,7 +1655,7 @@ int ssl_io_buffer_fill(request_rec *r, apr_size_t maxlen) rv = ap_get_brigade(r->proto_input_filters, tempb, AP_MODE_READBYTES, APR_BLOCK_READ, 8192); if (rv) { - ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, + ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(02015) "could not read request body for SSL buffer"); return HTTP_INTERNAL_SERVER_ERROR; } @@ -1585,16 +1674,16 @@ int ssl_io_buffer_fill(request_rec *r, apr_size_t maxlen) } else if (!APR_BUCKET_IS_METADATA(e)) { rv = apr_bucket_read(e, &data, &len, APR_BLOCK_READ); if (rv != APR_SUCCESS) { - ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, + ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(02016) "could not read bucket for SSL buffer"); return HTTP_INTERNAL_SERVER_ERROR; } total += len; } - rv = apr_bucket_setaside(e, ctx->pool); + rv = apr_bucket_setaside(e, r->pool); if (rv != APR_SUCCESS) { - ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, + ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(02017) "could not setaside bucket for SSL buffer"); return HTTP_INTERNAL_SERVER_ERROR; } @@ -1603,14 +1692,14 @@ int ssl_io_buffer_fill(request_rec *r, apr_size_t maxlen) APR_BRIGADE_INSERT_TAIL(ctx->bb, e); } - ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, + ap_log_cerror(APLOG_MARK, APLOG_TRACE4, 0, c, "total of %" APR_OFF_T_FMT " bytes in buffer, eos=%d", total, eos); /* Fail if this exceeds the maximum buffer size. */ if (total > maxlen) { - ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, - "request body exceeds maximum size (%" APR_SIZE_T_FMT + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02018) + "request body exceeds maximum size (%" APR_SIZE_T_FMT ") for SSL buffer", maxlen); return HTTP_REQUEST_ENTITY_TOO_LARGE; } @@ -1621,7 +1710,7 @@ int ssl_io_buffer_fill(request_rec *r, apr_size_t maxlen) /* After consuming all protocol-level input, remove all protocol-level * filters. It should strictly only be necessary to remove filters - * at exactly ftype == AP_FTYPE_PROTOCOL, since this filter will + * at exactly ftype == AP_FTYPE_PROTOCOL, since this filter will * precede all > AP_FTYPE_PROTOCOL anyway. */ while (r->proto_input_filters->frec->ftype < AP_FTYPE_CONNECTION) { ap_remove_input_filter(r->proto_input_filters); @@ -1647,7 +1736,7 @@ static apr_status_t ssl_io_filter_buffer(ap_filter_t *f, struct modssl_buffer_ctx *ctx = f->ctx; apr_status_t rv; - ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, f->c, + ap_log_cerror(APLOG_MARK, APLOG_TRACE4, 0, f->c, "read from buffered SSL brigade, mode %d, " "%" APR_OFF_T_FMT " bytes", mode, bytes); @@ -1675,7 +1764,7 @@ static apr_status_t ssl_io_filter_buffer(ap_filter_t *f, /* Partition the buffered brigade. */ rv = apr_brigade_partition(ctx->bb, bytes, &e); if (rv && rv != APR_INCOMPLETE) { - ap_log_cerror(APLOG_MARK, APLOG_ERR, rv, f->c, + ap_log_cerror(APLOG_MARK, APLOG_ERR, rv, f->c, APLOGNO(02019) "could not partition buffered SSL brigade"); ap_remove_input_filter(f); return rv; @@ -1705,7 +1794,7 @@ static apr_status_t ssl_io_filter_buffer(ap_filter_t *f, rv = apr_brigade_split_line(bb, ctx->bb, block, bytes); if (rv) { - ap_log_cerror(APLOG_MARK, APLOG_ERR, rv, f->c, + ap_log_cerror(APLOG_MARK, APLOG_ERR, rv, f->c, APLOGNO(02020) "could not split line from buffered SSL brigade"); ap_remove_input_filter(f); return rv; @@ -1722,7 +1811,7 @@ static apr_status_t ssl_io_filter_buffer(ap_filter_t *f, APR_BRIGADE_INSERT_TAIL(bb, e); } - ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, f->c, + ap_log_cerror(APLOG_MARK, APLOG_TRACE4, 0, f->c, "buffered SSL brigade exhausted"); /* Note that the filter must *not* be removed here; it may be * invoked again, see comment above. */ @@ -1731,14 +1820,17 @@ static apr_status_t ssl_io_filter_buffer(ap_filter_t *f, return APR_SUCCESS; } +/* The request_rec pointer is passed in here only to ensure that the + * filter chain is modified correctly when doing a TLS upgrade. It + * must *not* be used otherwise. */ static void ssl_io_input_add_filter(ssl_filter_ctx_t *filter_ctx, conn_rec *c, - SSL *ssl) + request_rec *r, SSL *ssl) { bio_filter_in_ctx_t *inctx; inctx = apr_palloc(c->pool, sizeof(*inctx)); - filter_ctx->pInputFilter = ap_add_input_filter(ssl_io_filter, inctx, NULL, c); + filter_ctx->pInputFilter = ap_add_input_filter(ssl_io_filter, inctx, r, c); filter_ctx->pbioRead = BIO_new(&bio_filter_in_method); filter_ctx->pbioRead->ptr = (void *)inctx; @@ -1755,7 +1847,10 @@ static void ssl_io_input_add_filter(ssl_filter_ctx_t *filter_ctx, conn_rec *c, inctx->filter_ctx = filter_ctx; } -void ssl_io_filter_init(conn_rec *c, SSL *ssl) +/* The request_rec pointer is passed in here only to ensure that the + * filter chain is modified correctly when doing a TLS upgrade. It + * must *not* be used otherwise. */ +void ssl_io_filter_init(conn_rec *c, request_rec *r, SSL *ssl) { ssl_filter_ctx_t *filter_ctx; @@ -1763,17 +1858,18 @@ void ssl_io_filter_init(conn_rec *c, SSL *ssl) filter_ctx->config = myConnConfig(c); - filter_ctx->nobuffer = 0; + ap_add_output_filter(ssl_io_coalesce, NULL, r, c); + filter_ctx->pOutputFilter = ap_add_output_filter(ssl_io_filter, - filter_ctx, NULL, c); + filter_ctx, r, c); filter_ctx->pbioWrite = BIO_new(&bio_filter_out_method); filter_ctx->pbioWrite->ptr = (void *)bio_filter_out_ctx_new(filter_ctx, c); /* We insert a clogging input filter. Let the core know. */ c->clogging_input_filters = 1; - - ssl_io_input_add_filter(filter_ctx, c, ssl); + + ssl_io_input_add_filter(filter_ctx, c, r, ssl); SSL_set_bio(ssl, filter_ctx->pbioRead, filter_ctx->pbioWrite); filter_ctx->pssl = ssl; @@ -1781,7 +1877,7 @@ void ssl_io_filter_init(conn_rec *c, SSL *ssl) apr_pool_cleanup_register(c->pool, (void*)filter_ctx, ssl_io_filter_cleanup, apr_pool_cleanup_null); - if (c->base_server->loglevel >= APLOG_DEBUG) { + if (APLOG_CS_IS_LEVEL(c, mySrvFromConn(c), APLOG_TRACE4)) { BIO_set_callback(SSL_get_rbio(ssl), ssl_io_data_cb); BIO_set_callback_arg(SSL_get_rbio(ssl), (void *)ssl); } @@ -1791,12 +1887,8 @@ void ssl_io_filter_init(conn_rec *c, SSL *ssl) void ssl_io_filter_register(apr_pool_t *p) { - /* This filter MUST be after the HTTP_HEADER filter, but it also must be - * a resource-level filter so it has the request_rec. - */ - ap_register_output_filter ("UPGRADE_FILTER", ssl_io_filter_Upgrade, NULL, AP_FTYPE_PROTOCOL + 5); - ap_register_input_filter (ssl_io_filter, ssl_io_filter_input, NULL, AP_FTYPE_CONNECTION + 5); + ap_register_output_filter (ssl_io_coalesce, ssl_io_filter_coalesce, NULL, AP_FTYPE_CONNECTION + 4); ap_register_output_filter (ssl_io_filter, ssl_io_filter_output, NULL, AP_FTYPE_CONNECTION + 5); ap_register_input_filter (ssl_io_buffer, ssl_io_filter_buffer, NULL, AP_FTYPE_PROTOCOL); @@ -1813,7 +1905,7 @@ void ssl_io_filter_register(apr_pool_t *p) #define DUMP_WIDTH 16 static void ssl_io_data_dump(server_rec *srvr, - MODSSL_BIO_CB_ARG_TYPE *s, + const char *s, long len) { char buf[256]; @@ -1827,19 +1919,19 @@ static void ssl_io_data_dump(server_rec *srvr, rows = (len / DUMP_WIDTH); if ((rows * DUMP_WIDTH) < len) rows++; - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, srvr, + ap_log_error(APLOG_MARK, APLOG_TRACE7, 0, srvr, "+-------------------------------------------------------------------------+"); for(i = 0 ; i< rows; i++) { #if APR_CHARSET_EBCDIC char ebcdic_text[DUMP_WIDTH]; - /* Determine how many bytes we are going to process in this row. */ j = DUMP_WIDTH; if ((i * DUMP_WIDTH + j) > len) j = len % DUMP_WIDTH; - if (j == 0) j = DUMP_WIDTH; - memcpy(ebcdic_text, (char *)(s) + i * DUMP_WIDTH, j); + if (j == 0) + j = DUMP_WIDTH; + memcpy(ebcdic_text,(char *)(s) + i * DUMP_WIDTH, j); ap_xlate_proto_from_ascii(ebcdic_text, j); -#endif +#endif /* APR_CHARSET_EBCDIC */ apr_snprintf(tmp, sizeof(tmp), "| %04x: ", i * DUMP_WIDTH); apr_cpystrn(buf, tmp, sizeof(buf)); for (j = 0; j < DUMP_WIDTH; j++) { @@ -1857,28 +1949,28 @@ static void ssl_io_data_dump(server_rec *srvr, apr_cpystrn(buf+strlen(buf), " ", sizeof(buf)-strlen(buf)); else { ch = ((unsigned char)*((char *)(s) + i * DUMP_WIDTH + j)) & 0xff; -#if APR_CHARSET_EBCDIC - apr_snprintf(tmp, sizeof(tmp), "%c", ((ch >= 0x20 /*' '*/) && (ch <= 0x7e /*'~'*/)) ? ebcdic_text[j] : '.'); -#else +#if APR_CHARSET_EBCDIC + apr_snprintf(tmp, sizeof(tmp), "%c", (ch >= 0x20 && ch <= 0x7F) ? ebcdic_text[j] : '.'); +#else /* APR_CHARSET_EBCDIC */ apr_snprintf(tmp, sizeof(tmp), "%c", ((ch >= ' ') && (ch <= '~')) ? ch : '.'); -#endif +#endif /* APR_CHARSET_EBCDIC */ apr_cpystrn(buf+strlen(buf), tmp, sizeof(buf)-strlen(buf)); } } apr_cpystrn(buf+strlen(buf), " |", sizeof(buf)-strlen(buf)); - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, srvr, + ap_log_error(APLOG_MARK, APLOG_TRACE7, 0, srvr, "%s", buf); } if (trunc > 0) - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, srvr, + ap_log_error(APLOG_MARK, APLOG_TRACE7, 0, srvr, "| %04ld - <SPACES/NULS>", len + trunc); - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, srvr, + ap_log_error(APLOG_MARK, APLOG_TRACE7, 0, srvr, "+-------------------------------------------------------------------------+"); return; } long ssl_io_data_cb(BIO *bio, int cmd, - MODSSL_BIO_CB_ARG_TYPE *argp, + const char *argp, int argi, long argl, long rc) { SSL *ssl; @@ -1894,18 +1986,18 @@ long ssl_io_data_cb(BIO *bio, int cmd, if ( cmd == (BIO_CB_WRITE|BIO_CB_RETURN) || cmd == (BIO_CB_READ |BIO_CB_RETURN) ) { if (rc >= 0) { - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, + ap_log_cserror(APLOG_MARK, APLOG_TRACE4, 0, c, s, "%s: %s %ld/%d bytes %s BIO#%pp [mem: %pp] %s", SSL_LIBRARY_NAME, (cmd == (BIO_CB_WRITE|BIO_CB_RETURN) ? "write" : "read"), rc, argi, (cmd == (BIO_CB_WRITE|BIO_CB_RETURN) ? "to" : "from"), bio, argp, (argp != NULL ? "(BIO dump follows)" : "(Oops, no memory buffer?)")); - if (argp != NULL) + if ((argp != NULL) && APLOG_CS_IS_LEVEL(c, s, APLOG_TRACE7)) ssl_io_data_dump(s, argp, rc); } else { - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, + ap_log_cserror(APLOG_MARK, APLOG_TRACE4, 0, c, s, "%s: I/O error, %d bytes expected to %s on BIO#%pp [mem: %pp]", SSL_LIBRARY_NAME, argi, (cmd == (BIO_CB_WRITE|BIO_CB_RETURN) ? "write" : "read"), diff --git a/modules/ssl/ssl_engine_kernel.c b/modules/ssl/ssl_engine_kernel.c index 33f97bd9..a4703933 100644 --- a/modules/ssl/ssl_engine_kernel.c +++ b/modules/ssl/ssl_engine_kernel.c @@ -29,32 +29,85 @@ time I was too famous.'' -- Unknown */ #include "ssl_private.h" +#include "util_md5.h" static void ssl_configure_env(request_rec *r, SSLConnRec *sslconn); #ifndef OPENSSL_NO_TLSEXT static int ssl_find_vhost(void *servername, conn_rec *c, server_rec *s); #endif +#define SWITCH_STATUS_LINE "HTTP/1.1 101 Switching Protocols" +#define UPGRADE_HEADER "Upgrade: TLS/1.0, HTTP/1.1" +#define CONNECTION_HEADER "Connection: Upgrade" + +/* Perform an upgrade-to-TLS for the given request, per RFC 2817. */ +static apr_status_t upgrade_connection(request_rec *r) +{ + struct conn_rec *conn = r->connection; + apr_bucket_brigade *bb; + SSLConnRec *sslconn; + apr_status_t rv; + SSL *ssl; + + ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(02028) + "upgrading connection to TLS"); + + bb = apr_brigade_create(r->pool, conn->bucket_alloc); + + rv = ap_fputstrs(conn->output_filters, bb, SWITCH_STATUS_LINE, CRLF, + UPGRADE_HEADER, CRLF, CONNECTION_HEADER, CRLF, CRLF, NULL); + if (rv == APR_SUCCESS) { + APR_BRIGADE_INSERT_TAIL(bb, + apr_bucket_flush_create(conn->bucket_alloc)); + rv = ap_pass_brigade(conn->output_filters, bb); + } + + if (rv) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02029) + "failed to send 101 interim response for connection " + "upgrade"); + return rv; + } + + ssl_init_ssl_connection(conn, r); + + sslconn = myConnConfig(conn); + ssl = sslconn->ssl; + + /* Perform initial SSL handshake. */ + SSL_set_accept_state(ssl); + SSL_do_handshake(ssl); + + if (SSL_get_state(ssl) != SSL_ST_OK) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02030) + "TLS upgrade handshake failed: not accepted by client!?"); + + return APR_ECONNABORTED; + } + + return APR_SUCCESS; +} + /* Perform a speculative (and non-blocking) read from the connection * filters for the given request, to determine whether there is any * pending data to read. Return non-zero if there is, else zero. */ -static int has_buffered_data(request_rec *r) +static int has_buffered_data(request_rec *r) { apr_bucket_brigade *bb; apr_off_t len; apr_status_t rv; int result; - + bb = apr_brigade_create(r->pool, r->connection->bucket_alloc); - + rv = ap_get_brigade(r->connection->input_filters, bb, AP_MODE_SPECULATIVE, - APR_NONBLOCK_READ, 1); + APR_NONBLOCK_READ, 1); result = rv == APR_SUCCESS && apr_brigade_length(bb, 1, &len) == APR_SUCCESS && len > 0; - + apr_brigade_destroy(bb); - + return result; } @@ -63,12 +116,26 @@ static int has_buffered_data(request_rec *r) */ int ssl_hook_ReadReq(request_rec *r) { - SSLConnRec *sslconn = myConnConfig(r->connection); + SSLSrvConfigRec *sc = mySrvConfig(r->server); + SSLConnRec *sslconn; + const char *upgrade; #ifndef OPENSSL_NO_TLSEXT const char *servername; #endif SSL *ssl; + /* Perform TLS upgrade here if "SSLEngine optional" is configured, + * SSL is not already set up for this connection, and the client + * has sent a suitable Upgrade header. */ + if (sc->enabled == SSL_ENABLED_OPTIONAL && !myConnConfig(r->connection) + && (upgrade = apr_table_get(r->headers_in, "Upgrade")) != NULL + && ap_find_token(r->pool, upgrade, "TLS/1.0")) { + if (upgrade_connection(r)) { + return HTTP_INTERNAL_SERVER_ERROR; + } + } + + sslconn = myConnConfig(r->connection); if (!sslconn) { return DECLINED; } @@ -85,7 +152,7 @@ int ssl_hook_ReadReq(request_rec *r) thisurl = ap_escape_html(r->pool, apr_psprintf(r->pool, "https://%s%s/", - ap_get_server_name(r), + ap_get_server_name_for_url(r), thisport)); errmsg = apr_psprintf(r->pool, @@ -127,7 +194,7 @@ int ssl_hook_ReadReq(request_rec *r) * with either no hostname or a different hostname. */ if (!r->hostname) { - ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, + ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, APLOGNO(02031) "Hostname %s provided via SNI, but no hostname" " provided in HTTP request", servername); return HTTP_BAD_REQUEST; @@ -136,15 +203,14 @@ int ssl_hook_ReadReq(request_rec *r) if (rv != APR_SUCCESS || scope_id) { return HTTP_BAD_REQUEST; } - if (strcmp(host, servername)) { - ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, + if (strcasecmp(host, servername)) { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, APLOGNO(02032) "Hostname %s provided via SNI and hostname %s provided" " via HTTP are different", servername, host); return HTTP_BAD_REQUEST; } } - else if ((((mySrvConfig(r->server))->strict_sni_vhost_check - == SSL_ENABLED_TRUE) + else if (((sc->strict_sni_vhost_check == SSL_ENABLED_TRUE) || (mySrvConfig(sslconn->server))->strict_sni_vhost_check == SSL_ENABLED_TRUE) && r->connection->vhost_lookup_data) { @@ -155,7 +221,7 @@ int ssl_hook_ReadReq(request_rec *r) * server config we used for handshaking or in our current server. * This should avoid insecure configuration by accident. */ - ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, + ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, APLOGNO(02033) "No hostname was provided via SNI for a name based" " virtual host"); return HTTP_FORBIDDEN; @@ -166,8 +232,8 @@ int ssl_hook_ReadReq(request_rec *r) /* * Log information about incoming HTTPS requests */ - if (r->server->loglevel >= APLOG_INFO && ap_is_initial_req(r)) { - ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server, + if (APLOGrinfo(r) && ap_is_initial_req(r)) { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02034) "%s HTTPS request received for child %ld (server %s)", (r->connection->keepalives <= 0 ? "Initial (No.1)" : @@ -237,7 +303,6 @@ int ssl_hook_Access(request_rec *r) SSL_CTX *ctx = NULL; apr_array_header_t *requires; ssl_require_t *ssl_requires; - char *cp; int ok, i; BOOL renegotiate = FALSE, renegotiate_quick = FALSE; X509 *cert; @@ -266,7 +331,7 @@ int ssl_hook_Access(request_rec *r) return HTTP_UPGRADE_REQUIRED; } - ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02219) "access to %s failed, reason: %s", r->filename, "SSL connection required"); @@ -343,13 +408,13 @@ int ssl_hook_Access(request_rec *r) /* configure new state */ if ((dc->szCipherSuite || sc->server->auth.cipher_suite) && - !modssl_set_cipher_list(ssl, dc->szCipherSuite ? - dc->szCipherSuite : - sc->server->auth.cipher_suite)) { - ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, + !SSL_set_cipher_list(ssl, dc->szCipherSuite ? + dc->szCipherSuite : + sc->server->auth.cipher_suite)) { + ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(02253) "Unable to reconfigure (per-directory) " "permitted SSL ciphers"); - ssl_log_ssl_error(APLOG_MARK, APLOG_ERR, r->server); + ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, r->server); if (cipher_list_old) { sk_SSL_CIPHER_free(cipher_list_old); @@ -418,7 +483,7 @@ int ssl_hook_Access(request_rec *r) } #endif /* tracing */ - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02220) "Reconfigured cipher suite will force renegotiation"); } } @@ -435,7 +500,7 @@ int ssl_hook_Access(request_rec *r) * currently active/remembered verify depth (because this means more * restriction on the certificate chain). */ - n = sslconn->verify_depth ? + n = (sslconn->verify_depth != UNSET) ? sslconn->verify_depth : (mySrvConfig(handshakeserver))->server->auth.verify_depth; /* determine the new depth */ @@ -443,7 +508,7 @@ int ssl_hook_Access(request_rec *r) dc->nVerifyDepth : sc->server->auth.verify_depth; if (sslconn->verify_depth < n) { renegotiate = TRUE; - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02254) "Reduced client verification depth will force " "renegotiation"); } @@ -459,7 +524,7 @@ int ssl_hook_Access(request_rec *r) * Additionally the following optimization is possible here: When the * currently active verify type is "none" but a client certificate is * already known/present, it's enough to manually force a client - * verification but at least skip the I/O-intensive renegotation + * verification but at least skip the I/O-intensive renegotiation * handshake. */ if ((dc->nVerifyClient != SSL_CVERIFY_UNSET) || @@ -482,7 +547,7 @@ int ssl_hook_Access(request_rec *r) verify |= SSL_VERIFY_PEER; } - modssl_set_verify(ssl, verify, ssl_callback_SSLVerify); + SSL_set_verify(ssl, verify, ssl_callback_SSLVerify); SSL_set_verify_result(ssl, X509_V_OK); /* determine whether we've to force a renegotiation */ @@ -507,7 +572,7 @@ int ssl_hook_Access(request_rec *r) X509_free(peercert); } - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02255) "Changed client verification type will force " "%srenegotiation", renegotiate_quick ? "quick " : ""); @@ -537,12 +602,12 @@ int ssl_hook_Access(request_rec *r) if (MODSSL_CFG_CA_NE(ca_cert_file, sc, hssc) || MODSSL_CFG_CA_NE(ca_cert_path, sc, hssc)) { if (verify & SSL_VERIFY_FAIL_IF_NO_PEER_CERT) { - ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, + ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(02256) "Non-default virtual host with SSLVerify set to " "'require' and VirtualHost-specific CA certificate " "list is only available to clients with TLS server " "name indication (SNI) support"); - modssl_set_verify(ssl, verify_old, NULL); + SSL_set_verify(ssl, verify_old, NULL); return HTTP_FORBIDDEN; } else /* let it pass, possibly with an "incorrect" peer cert, @@ -554,67 +619,6 @@ int ssl_hook_Access(request_rec *r) } } - /* - * override SSLCACertificateFile & SSLCACertificatePath - * This is only enabled if the SSL_set_cert_store() function - * is available in the ssl library. the 1.x based mod_ssl - * used SSL_CTX_set_cert_store which is not thread safe. - */ - -#ifdef HAVE_SSL_SET_CERT_STORE - /* - * check if per-dir and per-server config field are not the same. - * if f is defined in per-dir and not defined in per-server - * or f is defined in both but not the equal ... - */ -#define MODSSL_CFG_NE(f) \ - (dc->f && (!sc->f || (sc->f && strNE(dc->f, sc->f)))) - -#define MODSSL_CFG_CA(f) \ - (dc->f ? dc->f : sc->f) - - if (MODSSL_CFG_NE(szCACertificateFile) || - MODSSL_CFG_NE(szCACertificatePath)) - { - STACK_OF(X509_NAME) *ca_list; - const char *ca_file = MODSSL_CFG_CA(szCACertificateFile); - const char *ca_path = MODSSL_CFG_CA(szCACertificatePath); - - cert_store = X509_STORE_new(); - - if (!X509_STORE_load_locations(cert_store, ca_file, ca_path)) { - ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, - "Unable to reconfigure verify locations " - "for client authentication"); - ssl_log_ssl_error(APLOG_MARK, APLOG_ERR, r->server); - - X509_STORE_free(cert_store); - - return HTTP_FORBIDDEN; - } - - /* SSL_free will free cert_store */ - SSL_set_cert_store(ssl, cert_store); - - if (!(ca_list = ssl_init_FindCAList(r->server, r->pool, - ca_file, ca_path))) - { - ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, - "Unable to determine list of available " - "CA certificates for client authentication"); - - return HTTP_FORBIDDEN; - } - - SSL_set_client_CA_list(ssl, ca_list); - renegotiate = TRUE; - - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, - "Changed client verification locations will force " - "renegotiation"); - } -#endif /* HAVE_SSL_SET_CERT_STORE */ - /* If a renegotiation is now required for this location, and the * request includes a message body (and the client has not * requested a "100 Continue" response), then the client will be @@ -648,7 +652,7 @@ int ssl_hook_Access(request_rec *r) } if (rv) { - ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02257) "could not buffer message body to allow " "SSL renegotiation to proceed"); return rv; @@ -660,7 +664,7 @@ int ssl_hook_Access(request_rec *r) */ if (renegotiate) { /* - * Now we force the SSL renegotation by sending the Hello Request + * Now we force the SSL renegotiation by sending the Hello Request * message to the client. Here we have to do a workaround: Actually * OpenSSL returns immediately after sending the Hello Request (the * intent AFAIK is because the SSL/TLS protocol says it's not a must @@ -670,14 +674,14 @@ int ssl_hook_Access(request_rec *r) * here because it resets too much of the connection. So we set the * state explicitly and continue the handshake manually. */ - ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, + ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(02221) "Requesting connection re-negotiation"); if (renegotiate_quick) { STACK_OF(X509) *cert_stack; /* perform just a manual re-verification of the peer */ - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02258) "Performing quick renegotiation: " "just re-verifying the peer"); @@ -692,11 +696,11 @@ int ssl_hook_Access(request_rec *r) * we put it back here for the purpose of quick_renegotiation. */ cert_stack = sk_X509_new_null(); - sk_X509_push(cert_stack, MODSSL_PCHAR_CAST cert); + sk_X509_push(cert_stack, cert); } if (!cert_stack || (sk_X509_num(cert_stack) == 0)) { - ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02222) "Cannot find peer certificate chain"); return HTTP_FORBIDDEN; @@ -705,7 +709,7 @@ int ssl_hook_Access(request_rec *r) if (!(cert_store || (cert_store = SSL_CTX_get_cert_store(ctx)))) { - ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02223) "Cannot find certificate storage"); return HTTP_FORBIDDEN; @@ -726,10 +730,10 @@ int ssl_hook_Access(request_rec *r) SSL_get_ex_data_X509_STORE_CTX_idx(), (char *)ssl); - if (!modssl_X509_verify_cert(&cert_store_ctx)) { - ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, + if (!X509_verify_cert(&cert_store_ctx)) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02224) "Re-negotiation verification step failed"); - ssl_log_ssl_error(APLOG_MARK, APLOG_ERR, r->server); + ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, r->server); } SSL_set_verify_result(ssl, cert_store_ctx.error); @@ -753,7 +757,7 @@ int ssl_hook_Access(request_rec *r) * discarded. Legimately pipelined HTTP requests will be * retried anyway with this approach. */ if (has_buffered_data(r)) { - ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02259) "insecure SSL re-negotiation required, but " "a pipelined request is present; keepalive " "disabled"); @@ -761,11 +765,11 @@ int ssl_hook_Access(request_rec *r) } /* Perform a full renegotiation. */ - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02260) "Performing full renegotiation: complete handshake " "protocol (%s support secure renegotiation)", #if defined(SSL_get_secure_renegotiation_support) - SSL_get_secure_renegotiation_support(ssl) ? + SSL_get_secure_renegotiation_support(ssl) ? "client does" : "client does not" #else "server does not" @@ -779,37 +783,37 @@ int ssl_hook_Access(request_rec *r) /* Toggle the renegotiation state to allow the new * handshake to proceed. */ sslconn->reneg_state = RENEG_ALLOW; - + SSL_renegotiate(ssl); SSL_do_handshake(ssl); if (SSL_get_state(ssl) != SSL_ST_OK) { - ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02225) "Re-negotiation request failed"); - ssl_log_ssl_error(APLOG_MARK, APLOG_ERR, r->server); + ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, r->server); - r->connection->aborted = 1; + r->connection->keepalive = AP_CONN_CLOSE; return HTTP_FORBIDDEN; } - ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, + ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(02226) "Awaiting re-negotiation handshake"); - /* XXX: Should replace SSL_set_state with SSL_renegotiate(ssl); + /* XXX: Should replace setting ssl->state with SSL_renegotiate(ssl); * However, this causes failures in perl-framework currently, * perhaps pre-test if we have already negotiated? */ - SSL_set_state(ssl, SSL_ST_ACCEPT); + ssl->state = SSL_ST_ACCEPT; SSL_do_handshake(ssl); sslconn->reneg_state = RENEG_REJECT; if (SSL_get_state(ssl) != SSL_ST_OK) { - ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02261) "Re-negotiation handshake failed: " "Not accepted by client!?"); - r->connection->aborted = 1; + r->connection->keepalive = AP_CONN_CLOSE; return HTTP_FORBIDDEN; } } @@ -834,7 +838,7 @@ int ssl_hook_Access(request_rec *r) (sc->server->auth.verify_mode == SSL_CVERIFY_REQUIRE)); if (do_verify && (SSL_get_verify_result(ssl) != X509_V_OK)) { - ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02262) "Re-negotiation handshake failed: " "Client verification failed"); @@ -843,7 +847,7 @@ int ssl_hook_Access(request_rec *r) if (do_verify) { if ((peercert = SSL_get_peer_certificate(ssl)) == NULL) { - ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02263) "Re-negotiation handshake failed: " "Client certificate missing"); @@ -860,7 +864,7 @@ int ssl_hook_Access(request_rec *r) if (cipher_list) { cipher = SSL_get_current_cipher(ssl); if (sk_SSL_CIPHER_find(cipher_list, cipher) < 0) { - ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02264) "SSL cipher suite not renegotiated: " "access to %s denied using cipher %s", r->filename, @@ -882,6 +886,9 @@ int ssl_hook_Access(request_rec *r) r, (char *)dc->szUserName); if (val && val[0]) r->user = val; + else + ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(02227) + "Failed to set r->user to '%s'", dc->szUserName); } /* @@ -892,17 +899,14 @@ int ssl_hook_Access(request_rec *r) for (i = 0; i < requires->nelts; i++) { ssl_require_t *req = &ssl_requires[i]; - ok = ssl_expr_exec(r, req->mpExpr); + const char *errstring; + ok = ap_expr_exec(r, req->mpExpr, &errstring); if (ok < 0) { - cp = apr_psprintf(r->pool, - "Failed to execute " - "SSL requirement expression: %s", - ssl_expr_get_error()); - - ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, - "access to %s failed, reason: %s", - r->filename, cp); + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02265) + "access to %s failed, reason: Failed to execute " + "SSL requirement expression: %s", + r->filename, errstring); /* remember forbidden access for strict require option */ apr_table_setn(r->notes, "ssl-access-forbidden", "1"); @@ -911,19 +915,18 @@ int ssl_hook_Access(request_rec *r) } if (ok != 1) { - ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, + ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(02266) "Access to %s denied for %s " "(requirement expression not fulfilled)", - r->filename, r->connection->remote_ip); + r->filename, r->useragent_ip); - ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, + ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(02228) "Failed expression: %s", req->cpExpr); - ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02229) "access to %s failed, reason: %s", r->filename, - "SSL requirement expression not fulfilled " - "(see SSL logfile for more details)"); + "SSL requirement expression not fulfilled"); /* remember forbidden access for strict require option */ apr_table_setn(r->notes, "ssl-access-forbidden", "1"); @@ -994,7 +997,7 @@ int ssl_hook_UserCheck(request_rec *r) password = auth_line; if ((username[0] == '/') && strEQ(password, "password")) { - ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02035) "Encountered FakeBasicAuth spoof: %s", username); return HTTP_FORBIDDEN; } @@ -1019,7 +1022,7 @@ int ssl_hook_UserCheck(request_rec *r) X509_NAME *name = X509_get_subject_name(sslconn->client_cert); char *cp = X509_NAME_oneline(name, NULL, 0); sslconn->client_dn = apr_pstrdup(r->connection->pool, cp); - modssl_free(cp); + OPENSSL_free(cp); } clientdn = (char *)sslconn->client_dn; @@ -1040,9 +1043,9 @@ int ssl_hook_UserCheck(request_rec *r) apr_pstrcat(r->pool, clientdn, ":password", NULL)), NULL); - apr_table_set(r->headers_in, "Authorization", auth_line); + apr_table_setn(r->headers_in, "Authorization", auth_line); - ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, + ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(02036) "Faking HTTP Basic Auth header: \"Authorization: %s\"", auth_line); @@ -1100,6 +1103,7 @@ static const char *ssl_hook_Fixup_vars[] = { "SSL_SERVER_A_KEY", "SSL_SERVER_A_SIG", "SSL_SESSION_ID", + "SSL_SESSION_RESUMED", NULL }; @@ -1117,8 +1121,13 @@ int ssl_hook_Fixup(request_rec *r) SSL *ssl; int i; - if (sc->enabled == SSL_ENABLED_OPTIONAL && !(sslconn && sslconn->ssl)) { + /* If "SSLEngine optional" is configured, this is not an SSL + * connection, and this isn't a subrequest, send an Upgrade + * response header. */ + if (sc->enabled == SSL_ENABLED_OPTIONAL && !(sslconn && sslconn->ssl) + && !r->main) { apr_table_setn(r->headers_out, "Upgrade", "TLS/1.0, HTTP/1.1"); + apr_table_mergen(r->headers_out, "Connection", "upgrade"); } /* @@ -1182,7 +1191,7 @@ int ssl_hook_Fixup(request_rec *r) #ifdef SSL_get_secure_renegotiation_support - apr_table_setn(r->notes, "ssl-secure-reneg", + apr_table_setn(r->notes, "ssl-secure-reneg", SSL_get_secure_renegotiation_support(ssl) ? "1" : "0"); #endif @@ -1191,6 +1200,87 @@ int ssl_hook_Fixup(request_rec *r) /* _________________________________________________________________ ** +** Authz providers for use with mod_authz_core +** _________________________________________________________________ +*/ + +static authz_status ssl_authz_require_ssl_check(request_rec *r, + const char *require_line, + const void *parsed) +{ + SSLConnRec *sslconn = myConnConfig(r->connection); + SSL *ssl = sslconn ? sslconn->ssl : NULL; + + if (ssl) + return AUTHZ_GRANTED; + else + return AUTHZ_DENIED; +} + +static const char *ssl_authz_require_ssl_parse(cmd_parms *cmd, + const char *require_line, + const void **parsed) +{ + if (require_line && require_line[0]) + return "'Require ssl' does not take arguments"; + + return NULL; +} + +const authz_provider ssl_authz_provider_require_ssl = +{ + &ssl_authz_require_ssl_check, + &ssl_authz_require_ssl_parse, +}; + +static authz_status ssl_authz_verify_client_check(request_rec *r, + const char *require_line, + const void *parsed) +{ + SSLConnRec *sslconn = myConnConfig(r->connection); + SSL *ssl = sslconn ? sslconn->ssl : NULL; + + if (!ssl) + return AUTHZ_DENIED; + + if (sslconn->verify_error == NULL && + sslconn->verify_info == NULL && + SSL_get_verify_result(ssl) == X509_V_OK) + { + X509 *xs = SSL_get_peer_certificate(ssl); + + if (xs) { + X509_free(xs); + return AUTHZ_GRANTED; + } + else { + X509_free(xs); + } + } + + return AUTHZ_DENIED; +} + +static const char *ssl_authz_verify_client_parse(cmd_parms *cmd, + const char *require_line, + const void **parsed) +{ + if (require_line && require_line[0]) + return "'Require ssl-verify-client' does not take arguments"; + + return NULL; +} + +const authz_provider ssl_authz_provider_verify_client = +{ + &ssl_authz_verify_client_check, + &ssl_authz_verify_client_parse, +}; + + + +/* _________________________________________________________________ +** ** OpenSSL Callback Functions ** _________________________________________________________________ */ @@ -1239,7 +1329,7 @@ RSA *ssl_callback_TmpRSA(SSL *ssl, int export, int keylen) SSLModConfigRec *mc = myModConfigFromConn(c); int idx; - ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, + ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, c, "handing out temporary %d bit RSA key", keylen); /* doesn't matter if export flag is on, @@ -1271,7 +1361,7 @@ DH *ssl_callback_TmpDH(SSL *ssl, int export, int keylen) SSLModConfigRec *mc = myModConfigFromConn(c); int idx; - ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, + ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, c, "handing out temporary %d bit DH key", keylen); switch (keylen) { @@ -1287,6 +1377,31 @@ DH *ssl_callback_TmpDH(SSL *ssl, int export, int keylen) return (DH *)mc->pTmpKeys[idx]; } +#ifndef OPENSSL_NO_EC +EC_KEY *ssl_callback_TmpECDH(SSL *ssl, int export, int keylen) +{ + conn_rec *c = (conn_rec *)SSL_get_app_data(ssl); + static EC_KEY *ecdh = NULL; + static int init = 0; + + /* XXX Uses 256-bit key for now. TODO: support other sizes. */ + ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, c, + "handing out temporary 256 bit ECC key"); + + if (init == 0) { + ecdh = EC_KEY_new(); + if (ecdh != NULL) { + /* ecdh->group = EC_GROUP_new_by_nid(NID_secp160r2); */ + EC_KEY_set_group(ecdh, + EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1)); + } + init = 1; + } + + return ecdh; +} +#endif + /* * This OpenSSL callback function is called when OpenSSL * does client authentication and verifies the certificate chain. @@ -1313,26 +1428,13 @@ int ssl_callback_SSLVerify(int ok, X509_STORE_CTX *ctx) /* * Log verification information */ - if (s->loglevel >= APLOG_DEBUG) { - X509 *cert = X509_STORE_CTX_get_current_cert(ctx); - char *sname = X509_NAME_oneline(X509_get_subject_name(cert), NULL, 0); - char *iname = X509_NAME_oneline(X509_get_issuer_name(cert), NULL, 0); - - ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, conn, - "Certificate Verification: " - "depth: %d, subject: %s, issuer: %s", - errdepth, - sname ? sname : "-unknown-", - iname ? iname : "-unknown-"); - - if (sname) { - modssl_free(sname); - } - - if (iname) { - modssl_free(iname); - } - } + ssl_log_cxerror(SSLLOG_MARK, APLOG_DEBUG, 0, conn, + X509_STORE_CTX_get_current_cert(ctx), APLOGNO(02275) + "Certificate Verification, depth %d, " + "CRL checking mode: %s", errdepth, + mctx->crl_check_mode == SSL_CRLCHECK_CHAIN ? + "chain" : (mctx->crl_check_mode == SSL_CRLCHECK_LEAF ? + "leaf" : "none")); /* * Check for optionally acceptable non-verifiable issuer situation @@ -1356,7 +1458,7 @@ int ssl_callback_SSLVerify(int ok, X509_STORE_CTX *ctx) if (ssl_verify_error_is_optional(errnum) && (verify == SSL_CVERIFY_OPTIONAL_NO_CA)) { - ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, conn, + ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, conn, APLOGNO(02037) "Certificate Verification: Verifiable Issuer is " "configured as optional, therefore we're accepting " "the certificate"); @@ -1366,21 +1468,60 @@ int ssl_callback_SSLVerify(int ok, X509_STORE_CTX *ctx) } /* - * Additionally perform CRL-based revocation checks + * Expired certificates vs. "expired" CRLs: by default, OpenSSL + * turns X509_V_ERR_CRL_HAS_EXPIRED into a "certificate_expired(45)" + * SSL alert, but that's not really the message we should convey to the + * peer (at the very least, it's confusing, and in many cases, it's also + * inaccurate, as the certificate itself may very well not have expired + * yet). We set the X509_STORE_CTX error to something which OpenSSL's + * s3_both.c:ssl_verify_alarm_type() maps to SSL_AD_CERTIFICATE_UNKNOWN, + * i.e. the peer will receive a "certificate_unknown(46)" alert. + * We do not touch errnum, though, so that later on we will still log + * the "real" error, as returned by OpenSSL. */ - if (ok) { - if (!(ok = ssl_callback_SSLVerify_CRL(ok, ctx, conn))) { - errnum = X509_STORE_CTX_get_error(ctx); + if (!ok && errnum == X509_V_ERR_CRL_HAS_EXPIRED) { + X509_STORE_CTX_set_error(ctx, -1); + } + +#ifndef OPENSSL_NO_OCSP + /* + * Perform OCSP-based revocation checks + */ + if (ok && sc->server->ocsp_enabled) { + /* If there was an optional verification error, it's not + * possible to perform OCSP validation since the issuer may be + * missing/untrusted. Fail in that case. */ + if (ssl_verify_error_is_optional(errnum)) { + X509_STORE_CTX_set_error(ctx, X509_V_ERR_APPLICATION_VERIFICATION); + errnum = X509_V_ERR_APPLICATION_VERIFICATION; + ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, conn, APLOGNO(02038) + "cannot perform OCSP validation for cert " + "if issuer has not been verified " + "(optional_no_ca configured)"); + ok = FALSE; + } else { + ok = modssl_verify_ocsp(ctx, sc, s, conn, conn->pool); + if (!ok) { + errnum = X509_STORE_CTX_get_error(ctx); + } } } +#endif /* * If we already know it's not ok, log the real reason */ if (!ok) { - ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, conn, - "Certificate Verification: Error (%d): %s", - errnum, X509_verify_cert_error_string(errnum)); + if (APLOGcinfo(conn)) { + ssl_log_cxerror(SSLLOG_MARK, APLOG_INFO, 0, conn, + X509_STORE_CTX_get_current_cert(ctx), APLOGNO(02276) + "Certificate Verification: Error (%d): %s", + errnum, X509_verify_cert_error_string(errnum)); + } else { + ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, conn, APLOGNO(02039) + "Certificate Verification: Error (%d): %s", + errnum, X509_verify_cert_error_string(errnum)); + } if (sslconn->client_cert) { X509_free(sslconn->client_cert); @@ -1401,7 +1542,7 @@ int ssl_callback_SSLVerify(int ok, X509_STORE_CTX *ctx) } if (errdepth > depth) { - ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, conn, + ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, conn, APLOGNO(02040) "Certificate Verification: Certificate Chain too long " "(chain has %d certificates, but maximum allowed are " "only %d)", @@ -1419,220 +1560,16 @@ int ssl_callback_SSLVerify(int ok, X509_STORE_CTX *ctx) return ok; } -int ssl_callback_SSLVerify_CRL(int ok, X509_STORE_CTX *ctx, conn_rec *c) -{ - SSL *ssl = X509_STORE_CTX_get_ex_data(ctx, - SSL_get_ex_data_X509_STORE_CTX_idx()); - request_rec *r = (request_rec *)SSL_get_app_data2(ssl); - server_rec *s = r ? r->server : mySrvFromConn(c); - SSLSrvConfigRec *sc = mySrvConfig(s); - SSLConnRec *sslconn = myConnConfig(c); - modssl_ctx_t *mctx = myCtxConfig(sslconn, sc); - X509_OBJECT obj; - X509_NAME *subject, *issuer; - X509 *cert; - X509_CRL *crl; - EVP_PKEY *pubkey; - int i, n, rc; - - /* - * Unless a revocation store for CRLs was created we - * cannot do any CRL-based verification, of course. - */ - if (!mctx->crl) { - return ok; - } - - /* - * Determine certificate ingredients in advance - */ - cert = X509_STORE_CTX_get_current_cert(ctx); - subject = X509_get_subject_name(cert); - issuer = X509_get_issuer_name(cert); - - /* - * OpenSSL provides the general mechanism to deal with CRLs but does not - * use them automatically when verifying certificates, so we do it - * explicitly here. We will check the CRL for the currently checked - * certificate, if there is such a CRL in the store. - * - * We come through this procedure for each certificate in the certificate - * chain, starting with the root-CA's certificate. At each step we've to - * both verify the signature on the CRL (to make sure it's a valid CRL) - * and it's revocation list (to make sure the current certificate isn't - * revoked). But because to check the signature on the CRL we need the - * public key of the issuing CA certificate (which was already processed - * one round before), we've a little problem. But we can both solve it and - * at the same time optimize the processing by using the following - * verification scheme (idea and code snippets borrowed from the GLOBUS - * project): - * - * 1. We'll check the signature of a CRL in each step when we find a CRL - * through the _subject_ name of the current certificate. This CRL - * itself will be needed the first time in the next round, of course. - * But we do the signature processing one round before this where the - * public key of the CA is available. - * - * 2. We'll check the revocation list of a CRL in each step when - * we find a CRL through the _issuer_ name of the current certificate. - * This CRLs signature was then already verified one round before. - * - * This verification scheme allows a CA to revoke its own certificate as - * well, of course. - */ - - /* - * Try to retrieve a CRL corresponding to the _subject_ of - * the current certificate in order to verify it's integrity. - */ - memset((char *)&obj, 0, sizeof(obj)); - rc = SSL_X509_STORE_lookup(mctx->crl, - X509_LU_CRL, subject, &obj); - crl = obj.data.crl; - - if ((rc > 0) && crl) { - /* - * Log information about CRL - * (A little bit complicated because of ASN.1 and BIOs...) - */ - if (s->loglevel >= APLOG_DEBUG) { - char buff[512]; /* should be plenty */ - BIO *bio = BIO_new(BIO_s_mem()); - - BIO_printf(bio, "CA CRL: Issuer: "); - X509_NAME_print(bio, issuer, 0); - - BIO_printf(bio, ", lastUpdate: "); - ASN1_UTCTIME_print(bio, X509_CRL_get_lastUpdate(crl)); - - BIO_printf(bio, ", nextUpdate: "); - ASN1_UTCTIME_print(bio, X509_CRL_get_nextUpdate(crl)); - - n = BIO_read(bio, buff, sizeof(buff) - 1); - buff[n] = '\0'; - - BIO_free(bio); - - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "%s", buff); - } - - /* - * Verify the signature on this CRL - */ - pubkey = X509_get_pubkey(cert); - rc = X509_CRL_verify(crl, pubkey); -#ifdef OPENSSL_VERSION_NUMBER - /* Only refcounted in OpenSSL */ - if (pubkey) - EVP_PKEY_free(pubkey); -#endif - if (rc <= 0) { - ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, - "Invalid signature on CRL"); - - X509_STORE_CTX_set_error(ctx, X509_V_ERR_CRL_SIGNATURE_FAILURE); - X509_OBJECT_free_contents(&obj); - return FALSE; - } - - /* - * Check date of CRL to make sure it's not expired - */ - i = X509_cmp_current_time(X509_CRL_get_nextUpdate(crl)); - - if (i == 0) { - ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, - "Found CRL has invalid nextUpdate field"); - - X509_STORE_CTX_set_error(ctx, - X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD); - X509_OBJECT_free_contents(&obj); - - return FALSE; - } - - if (i < 0) { - ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, - "Found CRL is expired - " - "revoking all certificates until you get updated CRL"); - - X509_STORE_CTX_set_error(ctx, X509_V_ERR_CRL_HAS_EXPIRED); - X509_OBJECT_free_contents(&obj); - - return FALSE; - } - - X509_OBJECT_free_contents(&obj); - } - - /* - * Try to retrieve a CRL corresponding to the _issuer_ of - * the current certificate in order to check for revocation. - */ - memset((char *)&obj, 0, sizeof(obj)); - rc = SSL_X509_STORE_lookup(mctx->crl, - X509_LU_CRL, issuer, &obj); - - crl = obj.data.crl; - if ((rc > 0) && crl) { - /* - * Check if the current certificate is revoked by this CRL - */ - n = sk_X509_REVOKED_num(X509_CRL_get_REVOKED(crl)); - - for (i = 0; i < n; i++) { - X509_REVOKED *revoked = - sk_X509_REVOKED_value(X509_CRL_get_REVOKED(crl), i); - - ASN1_INTEGER *sn = X509_REVOKED_get_serialNumber(revoked); - - if (!ASN1_INTEGER_cmp(sn, X509_get_serialNumber(cert))) { - if (s->loglevel >= APLOG_DEBUG) { - char *cp = X509_NAME_oneline(issuer, NULL, 0); - long serial = ASN1_INTEGER_get(sn); - - ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, - "Certificate with serial %ld (0x%lX) " - "revoked per CRL from issuer %s", - serial, serial, cp); - modssl_free(cp); - } - - X509_STORE_CTX_set_error(ctx, X509_V_ERR_CERT_REVOKED); - X509_OBJECT_free_contents(&obj); - - return FALSE; - } - } - - X509_OBJECT_free_contents(&obj); - } - - return ok; -} - #define SSLPROXY_CERT_CB_LOG_FMT \ "Proxy client certificate callback: (%s) " -static void modssl_proxy_info_log(server_rec *s, +static void modssl_proxy_info_log(conn_rec *c, X509_INFO *info, const char *msg) { - SSLSrvConfigRec *sc = mySrvConfig(s); - char name_buf[256]; - X509_NAME *name; - char *dn; - - if (s->loglevel < APLOG_DEBUG) { - return; - } - - name = X509_get_subject_name(info->x509); - dn = X509_NAME_oneline(name, name_buf, sizeof(name_buf)); - - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, - SSLPROXY_CERT_CB_LOG_FMT "%s, sending %s", - sc->vhost_id, msg, dn ? dn : "-uknown-"); + ssl_log_cxerror(SSLLOG_MARK, APLOG_DEBUG, 0, c, info->x509, APLOGNO(02277) + SSLPROXY_CERT_CB_LOG_FMT "%s, sending", + (mySrvConfigFromConn(c))->vhost_id, msg); } /* @@ -1642,27 +1579,30 @@ static void modssl_proxy_info_log(server_rec *s, */ #define modssl_set_cert_info(info, cert, pkey) \ *cert = info->x509; \ - X509_reference_inc(*cert); \ + CRYPTO_add(&(*cert)->references, +1, CRYPTO_LOCK_X509); \ *pkey = info->x_pkey->dec_pkey; \ - EVP_PKEY_reference_inc(*pkey) + CRYPTO_add(&(*pkey)->references, +1, CRYPTO_LOCK_X509_PKEY) -int ssl_callback_proxy_cert(SSL *ssl, MODSSL_CLIENT_CERT_CB_ARG_TYPE **x509, EVP_PKEY **pkey) +int ssl_callback_proxy_cert(SSL *ssl, X509 **x509, EVP_PKEY **pkey) { conn_rec *c = (conn_rec *)SSL_get_app_data(ssl); server_rec *s = mySrvFromConn(c); SSLSrvConfigRec *sc = mySrvConfig(s); - X509_NAME *ca_name, *issuer; + X509_NAME *ca_name, *issuer, *ca_issuer; X509_INFO *info; + X509 *ca_cert; STACK_OF(X509_NAME) *ca_list; STACK_OF(X509_INFO) *certs = sc->proxy->pkp->certs; - int i, j; + STACK_OF(X509) *ca_certs; + STACK_OF(X509) **ca_cert_chains; + int i, j, k; - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(02267) SSLPROXY_CERT_CB_LOG_FMT "entered", sc->vhost_id); if (!certs || (sk_X509_INFO_num(certs) <= 0)) { - ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, + ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(02268) SSLPROXY_CERT_CB_LOG_FMT "downstream server wanted client certificate " "but none are configured", sc->vhost_id); @@ -1678,13 +1618,14 @@ int ssl_callback_proxy_cert(SSL *ssl, MODSSL_CLIENT_CERT_CB_ARG_TYPE **x509, EVP */ info = sk_X509_INFO_value(certs, 0); - modssl_proxy_info_log(s, info, "no acceptable CA list"); + modssl_proxy_info_log(c, info, APLOGNO(02278) "no acceptable CA list"); modssl_set_cert_info(info, x509, pkey); return TRUE; } + ca_cert_chains = sc->proxy->pkp->ca_certs; for (i = 0; i < sk_X509_NAME_num(ca_list); i++) { ca_name = sk_X509_NAME_value(ca_list, i); @@ -1692,17 +1633,40 @@ int ssl_callback_proxy_cert(SSL *ssl, MODSSL_CLIENT_CERT_CB_ARG_TYPE **x509, EVP info = sk_X509_INFO_value(certs, j); issuer = X509_get_issuer_name(info->x509); + /* Search certs (by issuer name) one by one*/ if (X509_NAME_cmp(issuer, ca_name) == 0) { - modssl_proxy_info_log(s, info, "found acceptable cert"); + modssl_proxy_info_log(c, info, APLOGNO(02279) + "found acceptable cert"); modssl_set_cert_info(info, x509, pkey); return TRUE; } - } + + if (ca_cert_chains) { + /* + * Failed to find direct issuer - search intermediates + * (by issuer name), if provided. + */ + ca_certs = ca_cert_chains[j]; + for (k = 0; k < sk_X509_num(ca_certs); k++) { + ca_cert = sk_X509_value(ca_certs, k); + ca_issuer = X509_get_issuer_name(ca_cert); + + if(X509_NAME_cmp(ca_issuer, ca_name) == 0 ) { + modssl_proxy_info_log(c, info, APLOGNO(02280) + "found acceptable cert by intermediate CA"); + + modssl_set_cert_info(info, x509, pkey); + + return TRUE; + } + } /* end loop through chained certs */ + } + } /* end loop through available certs */ } - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(02269) SSLPROXY_CERT_CB_LOG_FMT "no client certificate found!?", sc->vhost_id); @@ -1720,7 +1684,7 @@ static void ssl_session_log(server_rec *s, char buf[SSL_SESSION_ID_STRING_LEN]; char timeout_str[56] = {'\0'}; - if (s->loglevel < APLOG_DEBUG) { + if (!APLOGdebug(s)) { return; } @@ -1729,7 +1693,7 @@ static void ssl_session_log(server_rec *s, "timeout=%lds ", (timeout - time(NULL))); } - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, + ap_log_error(APLOG_MARK, APLOG_TRACE2, 0, s, "Inter-Process Session Cache: " "request=%s status=%s id=%s %s(session %s)", request, status, @@ -1764,12 +1728,13 @@ int ssl_callback_NewSessionCacheEntry(SSL *ssl, SSL_SESSION *session) * Store the SSL_SESSION in the inter-process cache with the * same expire time, so it expires automatically there, too. */ - id = SSL_SESSION_get_session_id(session); - idlen = SSL_SESSION_get_session_id_length(session); - - timeout += modssl_session_get_time(session); + id = session->session_id; + idlen = session->session_id_length; - rc = ssl_scache_store(s, id, idlen, timeout, session); + rc = ssl_scache_store(s, id, idlen, + apr_time_from_sec(SSL_SESSION_get_time(session) + + timeout), + session, conn->pool); ssl_session_log(s, "SET", id, idlen, rc == TRUE ? "OK" : "BAD", @@ -1801,7 +1766,7 @@ SSL_SESSION *ssl_callback_GetSessionCacheEntry(SSL *ssl, /* * Try to retrieve the SSL_SESSION from the inter-process cache */ - session = ssl_scache_retrieve(s, id, idlen); + session = ssl_scache_retrieve(s, id, idlen, conn->pool); ssl_session_log(s, "GET", id, idlen, session ? "FOUND" : "MISSED", @@ -1844,10 +1809,11 @@ void ssl_callback_DelSessionCacheEntry(SSL_CTX *ctx, /* * Remove the SSL_SESSION from the inter-process cache */ - id = SSL_SESSION_get_session_id(session); - idlen = SSL_SESSION_get_session_id_length(session); + id = session->session_id; + idlen = session->session_id_length; - ssl_scache_remove(s, id, idlen); + /* TODO: Do we need a temp pool here, or are we always shutting down? */ + ssl_scache_remove(s, id, idlen, sc->mc->pPool); ssl_session_log(s, "REM", id, idlen, "OK", "dead", 0); @@ -1856,70 +1822,70 @@ void ssl_callback_DelSessionCacheEntry(SSL_CTX *ctx, } /* Dump debugginfo trace to the log file. */ -static void log_tracing_state(MODSSL_INFO_CB_ARG_TYPE ssl, conn_rec *c, +static void log_tracing_state(const SSL *ssl, conn_rec *c, server_rec *s, int where, int rc) { /* * create the various trace messages */ if (where & SSL_CB_HANDSHAKE_START) { - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, - "%s: Handshake: start", SSL_LIBRARY_NAME); + ap_log_cerror(APLOG_MARK, APLOG_TRACE3, 0, c, + "%s: Handshake: start", SSL_LIBRARY_NAME); } else if (where & SSL_CB_HANDSHAKE_DONE) { - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, - "%s: Handshake: done", SSL_LIBRARY_NAME); + ap_log_cerror(APLOG_MARK, APLOG_TRACE3, 0, c, + "%s: Handshake: done", SSL_LIBRARY_NAME); } else if (where & SSL_CB_LOOP) { - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, - "%s: Loop: %s", - SSL_LIBRARY_NAME, SSL_state_string_long(ssl)); + ap_log_cerror(APLOG_MARK, APLOG_TRACE3, 0, c, + "%s: Loop: %s", + SSL_LIBRARY_NAME, SSL_state_string_long(ssl)); } else if (where & SSL_CB_READ) { - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, - "%s: Read: %s", - SSL_LIBRARY_NAME, SSL_state_string_long(ssl)); + ap_log_cerror(APLOG_MARK, APLOG_TRACE3, 0, c, + "%s: Read: %s", + SSL_LIBRARY_NAME, SSL_state_string_long(ssl)); } else if (where & SSL_CB_WRITE) { - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, - "%s: Write: %s", - SSL_LIBRARY_NAME, SSL_state_string_long(ssl)); + ap_log_cerror(APLOG_MARK, APLOG_TRACE3, 0, c, + "%s: Write: %s", + SSL_LIBRARY_NAME, SSL_state_string_long(ssl)); } else if (where & SSL_CB_ALERT) { char *str = (where & SSL_CB_READ) ? "read" : "write"; - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, - "%s: Alert: %s:%s:%s", - SSL_LIBRARY_NAME, str, - SSL_alert_type_string_long(rc), - SSL_alert_desc_string_long(rc)); + ap_log_cerror(APLOG_MARK, APLOG_TRACE3, 0, c, + "%s: Alert: %s:%s:%s", + SSL_LIBRARY_NAME, str, + SSL_alert_type_string_long(rc), + SSL_alert_desc_string_long(rc)); } else if (where & SSL_CB_EXIT) { if (rc == 0) { - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, - "%s: Exit: failed in %s", - SSL_LIBRARY_NAME, SSL_state_string_long(ssl)); + ap_log_cerror(APLOG_MARK, APLOG_TRACE3, 0, c, + "%s: Exit: failed in %s", + SSL_LIBRARY_NAME, SSL_state_string_long(ssl)); } else if (rc < 0) { - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, - "%s: Exit: error in %s", - SSL_LIBRARY_NAME, SSL_state_string_long(ssl)); + ap_log_cerror(APLOG_MARK, APLOG_TRACE3, 0, c, + "%s: Exit: error in %s", + SSL_LIBRARY_NAME, SSL_state_string_long(ssl)); } } /* - * Because SSL renegotations can happen at any time (not only after + * Because SSL renegotiations can happen at any time (not only after * SSL_accept()), the best way to log the current connection details is * right after a finished handshake. */ if (where & SSL_CB_HANDSHAKE_DONE) { - ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, - "Connection: Client IP: %s, Protocol: %s, " - "Cipher: %s (%s/%s bits)", - ssl_var_lookup(NULL, s, c, NULL, "REMOTE_ADDR"), - ssl_var_lookup(NULL, s, c, NULL, "SSL_PROTOCOL"), - ssl_var_lookup(NULL, s, c, NULL, "SSL_CIPHER"), - ssl_var_lookup(NULL, s, c, NULL, "SSL_CIPHER_USEKEYSIZE"), - ssl_var_lookup(NULL, s, c, NULL, "SSL_CIPHER_ALGKEYSIZE")); + ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(02041) + "Connection: Client IP: %s, Protocol: %s, " + "Cipher: %s (%s/%s bits)", + ssl_var_lookup(NULL, s, c, NULL, "REMOTE_ADDR"), + ssl_var_lookup(NULL, s, c, NULL, "SSL_PROTOCOL"), + ssl_var_lookup(NULL, s, c, NULL, "SSL_CIPHER"), + ssl_var_lookup(NULL, s, c, NULL, "SSL_CIPHER_USEKEYSIZE"), + ssl_var_lookup(NULL, s, c, NULL, "SSL_CIPHER_ALGKEYSIZE")); } } @@ -1929,7 +1895,7 @@ static void log_tracing_state(MODSSL_INFO_CB_ARG_TYPE ssl, conn_rec *c, * client-initiated renegotiations, and for dumping everything to the * log. */ -void ssl_callback_Info(MODSSL_INFO_CB_ARG_TYPE ssl, int where, int rc) +void ssl_callback_Info(const SSL *ssl, int where, int rc) { conn_rec *c; server_rec *s; @@ -1948,12 +1914,12 @@ void ssl_callback_Info(MODSSL_INFO_CB_ARG_TYPE ssl, int where, int rc) * state machine and move to ABORT if a Client Hello is being * read. */ if ((where & SSL_CB_ACCEPT_LOOP) && scr->reneg_state == RENEG_REJECT) { - int state = SSL_get_state(ssl); - - if (state == SSL3_ST_SR_CLNT_HELLO_A + int state = SSL_get_state((SSL *)ssl); + + if (state == SSL3_ST_SR_CLNT_HELLO_A || state == SSL23_ST_SR_CLNT_HELLO_A) { scr->reneg_state = RENEG_ABORT; - ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, + ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(02042) "rejecting client initiated renegotiation"); } } @@ -1964,7 +1930,7 @@ void ssl_callback_Info(MODSSL_INFO_CB_ARG_TYPE ssl, int where, int rc) } s = mySrvFromConn(c); - if (s && s->loglevel >= APLOG_DEBUG) { + if (s && APLOGdebug(s)) { log_tracing_state(ssl, c, s, where, rc); } } @@ -1984,13 +1950,13 @@ int ssl_callback_ServerNameIndication(SSL *ssl, int *al, modssl_ctx_t *mctx) if (c) { if (ap_vhost_iterate_given_conn(c, ssl_find_vhost, (void *)servername)) { - ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, + ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(02043) "SSL virtual host for servername %s found", servername); return SSL_TLSEXT_ERR_OK; } else { - ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, + ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(02044) "No matching SSL virtual host for servername " "%s found (using default/first virtual host)", servername); @@ -2007,7 +1973,7 @@ int ssl_callback_ServerNameIndication(SSL *ssl, int *al, modssl_ctx_t *mctx) * or one of the ServerAliases matches the supplied name (to be used * with ap_vhost_iterate_given_conn()) */ -static int ssl_find_vhost(void *servername, conn_rec *c, server_rec *s) +static int ssl_find_vhost(void *servername, conn_rec *c, server_rec *s) { SSLSrvConfigRec *sc; SSL *ssl; @@ -2021,7 +1987,7 @@ static int ssl_find_vhost(void *servername, conn_rec *c, server_rec *s) found = TRUE; } - /* + /* * if not matched yet, check ServerAlias entries * (adapted from vhost.c:matches_aliases()) */ @@ -2081,6 +2047,23 @@ static int ssl_find_vhost(void *servername, conn_rec *c, server_rec *s) } /* + * Adjust the session id context. ssl_init_ssl_connection() + * always picks the configuration of the first vhost when + * calling SSL_new(), but we want to tie the session to the + * vhost we have just switched to. Again, we have to make sure + * that we're not overwriting a session id context which was + * possibly set in ssl_hook_Access(), before triggering + * a renegotation. + */ + if (SSL_num_renegotiations(ssl) == 0) { + unsigned char *sid_ctx = + (unsigned char *)ap_md5_binary(c->pool, + (unsigned char *)sc->vhost_id, + sc->vhost_id_len); + SSL_set_session_id_context(ssl, sid_ctx, APR_MD5_DIGESTSIZE*2); + } + + /* * Save the found server into our SSLConnRec for later * retrieval */ @@ -2090,10 +2073,10 @@ static int ssl_find_vhost(void *servername, conn_rec *c, server_rec *s) * There is one special filter callback, which is set * very early depending on the base_server's log level. * If this is not the first vhost we're now selecting - * (and the first vhost doesn't use APLOG_DEBUG), then + * (and the first vhost doesn't use APLOG_TRACE4), then * we need to set that callback here. */ - if (s->loglevel >= APLOG_DEBUG) { + if (APLOGtrace4(s)) { BIO_set_callback(SSL_get_rbio(ssl), ssl_io_data_cb); BIO_set_callback_arg(SSL_get_rbio(ssl), (void *)ssl); } @@ -2104,3 +2087,73 @@ static int ssl_find_vhost(void *servername, conn_rec *c, server_rec *s) return 0; } #endif + +#ifdef HAVE_TLS_SESSION_TICKETS +/* + * This callback function is executed when OpenSSL needs a key for encrypting/ + * decrypting a TLS session ticket (RFC 5077) and a ticket key file has been + * configured through SSLSessionTicketKeyFile. + */ +int ssl_callback_SessionTicket(SSL *ssl, + unsigned char *keyname, + unsigned char *iv, + EVP_CIPHER_CTX *cipher_ctx, + HMAC_CTX *hctx, + int mode) +{ + conn_rec *c = (conn_rec *)SSL_get_app_data(ssl); + server_rec *s = mySrvFromConn(c); + SSLSrvConfigRec *sc = mySrvConfig(s); + SSLConnRec *sslconn = myConnConfig(c); + modssl_ctx_t *mctx = myCtxConfig(sslconn, sc); + modssl_ticket_key_t *ticket_key = mctx->ticket_key; + + if (mode == 1) { + /* + * OpenSSL is asking for a key for encrypting a ticket, + * see s3_srvr.c:ssl3_send_newsession_ticket() + */ + + if (ticket_key == NULL) { + /* should never happen, but better safe than sorry */ + return -1; + } + + memcpy(keyname, ticket_key->key_name, 16); + RAND_pseudo_bytes(iv, EVP_MAX_IV_LENGTH); + EVP_EncryptInit_ex(cipher_ctx, EVP_aes_128_cbc(), NULL, + ticket_key->aes_key, iv); + HMAC_Init_ex(hctx, ticket_key->hmac_secret, 16, tlsext_tick_md(), NULL); + + ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(02289) + "TLS session ticket key for %s successfully set, " + "creating new session ticket", sc->vhost_id); + + return 0; + } + else if (mode == 0) { + /* + * OpenSSL is asking for the decryption key, + * see t1_lib.c:tls_decrypt_ticket() + */ + + /* check key name */ + if (ticket_key == NULL || memcmp(keyname, ticket_key->key_name, 16)) { + return 0; + } + + EVP_DecryptInit_ex(cipher_ctx, EVP_aes_128_cbc(), NULL, + ticket_key->aes_key, iv); + HMAC_Init_ex(hctx, ticket_key->hmac_secret, 16, tlsext_tick_md(), NULL); + + ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(02290) + "TLS session ticket key for %s successfully set, " + "decrypting existing session ticket", sc->vhost_id); + + return 1; + } + + /* OpenSSL is not expected to call us with modes other than 1 or 0 */ + return -1; +} +#endif diff --git a/modules/ssl/ssl_engine_log.c b/modules/ssl/ssl_engine_log.c index 883274bf..31861ca7 100644 --- a/modules/ssl/ssl_engine_log.c +++ b/modules/ssl/ssl_engine_log.c @@ -79,23 +79,155 @@ void ssl_die(void) void ssl_log_ssl_error(const char *file, int line, int level, server_rec *s) { unsigned long e; + const char *data; + int flags; - while ((e = ERR_get_error())) { + while ((e = ERR_peek_error_line_data(NULL, NULL, &data, &flags))) { const char *annotation; char err[256]; + if (!(flags & ERR_TXT_STRING)) { + data = NULL; + } + ERR_error_string_n(e, err, sizeof err); annotation = ssl_log_annotation(err); - if (annotation) { - ap_log_error(file, line, level, 0, s, - "SSL Library Error: %lu %s %s", - e, err, annotation); - } - else { - ap_log_error(file, line, level, 0, s, - "SSL Library Error: %lu %s", - e, err); + ap_log_error(file, line, APLOG_MODULE_INDEX, level, 0, s, + "SSL Library Error: %s%s%s%s%s%s", + /* %s */ + err, + /* %s%s%s */ + data ? " (" : "", data ? data : "", data ? ")" : "", + /* %s%s */ + annotation ? " -- " : "", + annotation ? annotation : ""); + + /* Pop the error off the stack: */ + ERR_get_error(); + } +} + +static void ssl_log_cert_error(const char *file, int line, int level, + apr_status_t rv, const server_rec *s, + const conn_rec *c, const request_rec *r, + apr_pool_t *p, X509 *cert, const char *format, + va_list ap) +{ + char buf[HUGE_STRING_LEN]; + int msglen, n; + char *name; + + apr_vsnprintf(buf, sizeof buf, format, ap); + + msglen = strlen(buf); + + if (cert) { + BIO *bio = BIO_new(BIO_s_mem()); + + if (bio) { + /* + * Limit the maximum length of the subject and issuer DN strings + * in the log message. 300 characters should always be sufficient + * for holding both the timestamp, module name, pid etc. stuff + * at the beginning of the line and the trailing information about + * serial, notbefore and notafter. + */ + int maxdnlen = (HUGE_STRING_LEN - msglen - 300) / 2; + + BIO_puts(bio, " [subject: "); + name = SSL_X509_NAME_to_string(p, X509_get_subject_name(cert), + maxdnlen); + if (!strIsEmpty(name)) { + BIO_puts(bio, name); + } else { + BIO_puts(bio, "-empty-"); + } + + BIO_puts(bio, " / issuer: "); + name = SSL_X509_NAME_to_string(p, X509_get_issuer_name(cert), + maxdnlen); + if (!strIsEmpty(name)) { + BIO_puts(bio, name); + } else { + BIO_puts(bio, "-empty-"); + } + + BIO_puts(bio, " / serial: "); + if (i2a_ASN1_INTEGER(bio, X509_get_serialNumber(cert)) == -1) + BIO_puts(bio, "(ERROR)"); + + BIO_puts(bio, " / notbefore: "); + ASN1_TIME_print(bio, X509_get_notBefore(cert)); + + BIO_puts(bio, " / notafter: "); + ASN1_TIME_print(bio, X509_get_notAfter(cert)); + + BIO_puts(bio, "]"); + + n = BIO_read(bio, buf + msglen, sizeof buf - msglen - 1); + if (n > 0) + buf[msglen + n] = '\0'; + + BIO_free(bio); } } + else { + apr_snprintf(buf + msglen, sizeof buf - msglen, + " [certificate: -not available-]"); + } + + if (r) { + ap_log_rerror(file, line, APLOG_MODULE_INDEX, level, rv, r, "%s", buf); + } + else if (c) { + ap_log_cerror(file, line, APLOG_MODULE_INDEX, level, rv, c, "%s", buf); + } + else if (s) { + ap_log_error(file, line, APLOG_MODULE_INDEX, level, rv, s, "%s", buf); + } + +} + +/* + * Wrappers for ap_log_error/ap_log_cerror/ap_log_rerror which log additional + * details of the X509 cert. For ssl_log_xerror, a pool needs to be passed in + * as well (for temporary allocation of the cert's subject/issuer name strings, + * in the other cases we use the connection and request pool, respectively). + */ +void ssl_log_xerror(const char *file, int line, int level, apr_status_t rv, + apr_pool_t *ptemp, server_rec *s, X509 *cert, + const char *fmt, ...) +{ + if (APLOG_IS_LEVEL(s,level)) { + va_list ap; + va_start(ap, fmt); + ssl_log_cert_error(file, line, level, rv, s, NULL, NULL, ptemp, + cert, fmt, ap); + va_end(ap); + } +} + +void ssl_log_cxerror(const char *file, int line, int level, apr_status_t rv, + conn_rec *c, X509 *cert, const char *fmt, ...) +{ + if (APLOG_IS_LEVEL(mySrvFromConn(c),level)) { + va_list ap; + va_start(ap, fmt); + ssl_log_cert_error(file, line, level, rv, NULL, c, NULL, c->pool, + cert, fmt, ap); + va_end(ap); + } +} + +void ssl_log_rxerror(const char *file, int line, int level, apr_status_t rv, + request_rec *r, X509 *cert, const char *fmt, ...) +{ + if (APLOG_R_IS_LEVEL(r,level)) { + va_list ap; + va_start(ap, fmt); + ssl_log_cert_error(file, line, level, rv, NULL, NULL, r, r->pool, + cert, fmt, ap); + va_end(ap); + } } diff --git a/modules/ssl/ssl_engine_mutex.c b/modules/ssl/ssl_engine_mutex.c index bbcd92ad..e915a163 100644 --- a/modules/ssl/ssl_engine_mutex.c +++ b/modules/ssl/ssl_engine_mutex.c @@ -30,43 +30,29 @@ #include "ssl_private.h" -#ifdef AP_NEED_SET_MUTEX_PERMS -#include "unixd.h" -#endif - int ssl_mutex_init(server_rec *s, apr_pool_t *p) { SSLModConfigRec *mc = myModConfig(s); apr_status_t rv; - if (mc->nMutexMode == SSL_MUTEXMODE_NONE) + /* A mutex is only needed if a session cache is configured, and + * the provider used is not internally multi-process/thread + * safe. */ + if (!mc->sesscache + || (mc->sesscache->flags & AP_SOCACHE_FLAG_NOTMPSAFE) == 0) { return TRUE; + } if (mc->pMutex) { return TRUE; } - if ((rv = apr_global_mutex_create(&mc->pMutex, mc->szMutexFile, - mc->nMutexMech, s->process->pool)) + + if ((rv = ap_global_mutex_create(&mc->pMutex, NULL, SSL_CACHE_MUTEX_TYPE, + NULL, s, s->process->pool, 0)) != APR_SUCCESS) { - if (mc->szMutexFile) - ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, - "Cannot create SSLMutex with file `%s'", - mc->szMutexFile); - else - ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, - "Cannot create SSLMutex"); return FALSE; } -#ifdef AP_NEED_SET_MUTEX_PERMS - rv = unixd_set_global_mutex_perms(mc->pMutex); - if (rv != APR_SUCCESS) { - ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, - "Could not set permissions on ssl_mutex; check User " - "and Group directives"); - return FALSE; - } -#endif return TRUE; } @@ -74,19 +60,24 @@ int ssl_mutex_reinit(server_rec *s, apr_pool_t *p) { SSLModConfigRec *mc = myModConfig(s); apr_status_t rv; + const char *lockfile; - if (mc->nMutexMode == SSL_MUTEXMODE_NONE) + if (mc->pMutex == NULL || !mc->sesscache + || (mc->sesscache->flags & AP_SOCACHE_FLAG_NOTMPSAFE) == 0) { return TRUE; + } + lockfile = apr_global_mutex_lockfile(mc->pMutex); if ((rv = apr_global_mutex_child_init(&mc->pMutex, - mc->szMutexFile, p)) != APR_SUCCESS) { - if (mc->szMutexFile) - ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, - "Cannot reinit SSLMutex with file `%s'", - mc->szMutexFile); + lockfile, + p)) != APR_SUCCESS) { + if (lockfile) + ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO(02024) + "Cannot reinit %s mutex with file `%s'", + SSL_CACHE_MUTEX_TYPE, lockfile); else - ap_log_error(APLOG_MARK, APLOG_WARNING, rv, s, - "Cannot reinit SSLMutex"); + ap_log_error(APLOG_MARK, APLOG_WARNING, rv, s, APLOGNO(02025) + "Cannot reinit %s mutex", SSL_CACHE_MUTEX_TYPE); return FALSE; } return TRUE; @@ -97,10 +88,8 @@ int ssl_mutex_on(server_rec *s) SSLModConfigRec *mc = myModConfig(s); apr_status_t rv; - if (mc->nMutexMode == SSL_MUTEXMODE_NONE) - return TRUE; if ((rv = apr_global_mutex_lock(mc->pMutex)) != APR_SUCCESS) { - ap_log_error(APLOG_MARK, APLOG_WARNING, rv, s, + ap_log_error(APLOG_MARK, APLOG_WARNING, rv, s, APLOGNO(02026) "Failed to acquire SSL session cache lock"); return FALSE; } @@ -112,10 +101,8 @@ int ssl_mutex_off(server_rec *s) SSLModConfigRec *mc = myModConfig(s); apr_status_t rv; - if (mc->nMutexMode == SSL_MUTEXMODE_NONE) - return TRUE; if ((rv = apr_global_mutex_unlock(mc->pMutex)) != APR_SUCCESS) { - ap_log_error(APLOG_MARK, APLOG_WARNING, rv, s, + ap_log_error(APLOG_MARK, APLOG_WARNING, rv, s, APLOGNO(02027) "Failed to release SSL session cache lock"); return FALSE; } diff --git a/modules/ssl/ssl_engine_ocsp.c b/modules/ssl/ssl_engine_ocsp.c new file mode 100644 index 00000000..90da5c27 --- /dev/null +++ b/modules/ssl/ssl_engine_ocsp.c @@ -0,0 +1,297 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ssl_private.h" + +#ifndef OPENSSL_NO_OCSP +#include "apr_base64.h" + +/* Return the responder URI specified in the given certificate, or + * NULL if none specified. */ +static const char *extract_responder_uri(X509 *cert, apr_pool_t *pool) +{ + STACK_OF(ACCESS_DESCRIPTION) *values; + char *result = NULL; + int j; + + values = X509_get_ext_d2i(cert, NID_info_access, NULL, NULL); + if (!values) { + return NULL; + } + + for (j = 0; j < sk_ACCESS_DESCRIPTION_num(values) && !result; j++) { + ACCESS_DESCRIPTION *value = sk_ACCESS_DESCRIPTION_value(values, j); + + /* Name found in extension, and is a URI: */ + if (OBJ_obj2nid(value->method) == NID_ad_OCSP + && value->location->type == GEN_URI) { + result = apr_pstrdup(pool, + (char *)value->location->d.uniformResourceIdentifier->data); + } + } + + AUTHORITY_INFO_ACCESS_free(values); + + return result; +} + +/* Return the responder URI object which should be used in the given + * configuration for the given certificate, or NULL if none can be + * determined. */ +static apr_uri_t *determine_responder_uri(SSLSrvConfigRec *sc, X509 *cert, + conn_rec *c, apr_pool_t *p) +{ + apr_uri_t *u = apr_palloc(p, sizeof *u); + const char *s; + apr_status_t rv; + + /* Use default responder URL if forced by configuration, else use + * certificate-specified responder, falling back to default if + * necessary and possible. */ + if (sc->server->ocsp_force_default) { + s = sc->server->ocsp_responder; + } + else { + s = extract_responder_uri(cert, p); + + if (s == NULL && sc->server->ocsp_responder) { + s = sc->server->ocsp_responder; + } + } + + if (s == NULL) { + ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(01918) + "no OCSP responder specified in certificate and " + "no default configured"); + return NULL; + } + + rv = apr_uri_parse(p, s, u); + if (rv || !u->hostname) { + ap_log_cerror(APLOG_MARK, APLOG_DEBUG, rv, c, APLOGNO(01919) + "failed to parse OCSP responder URI '%s'", s); + return NULL; + } + + if (strcasecmp(u->scheme, "http") != 0) { + ap_log_cerror(APLOG_MARK, APLOG_DEBUG, rv, c, APLOGNO(01920) + "cannot handle OCSP responder URI '%s'", s); + return NULL; + } + + if (!u->port) { + u->port = apr_uri_port_of_scheme(u->scheme); + } + + return u; +} + +/* Create an OCSP request for the given certificate; returning the + * certificate ID in *certid and *issuer on success. Returns the + * request object on success, or NULL on error. */ +static OCSP_REQUEST *create_request(X509_STORE_CTX *ctx, X509 *cert, + OCSP_CERTID **certid, + server_rec *s, apr_pool_t *p) +{ + OCSP_REQUEST *req = OCSP_REQUEST_new(); + + *certid = OCSP_cert_to_id(NULL, cert, ctx->current_issuer); + if (!*certid || !OCSP_request_add0_id(req, *certid)) { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(01921) + "could not retrieve certificate id"); + ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, s); + return NULL; + } + + OCSP_request_add1_nonce(req, 0, -1); + + return req; +} + +/* Verify the OCSP status of given certificate. Returns + * V_OCSP_CERTSTATUS_* result code. */ +static int verify_ocsp_status(X509 *cert, X509_STORE_CTX *ctx, conn_rec *c, + SSLSrvConfigRec *sc, server_rec *s, + apr_pool_t *pool) +{ + int rc = V_OCSP_CERTSTATUS_GOOD; + OCSP_RESPONSE *response = NULL; + OCSP_BASICRESP *basicResponse = NULL; + OCSP_REQUEST *request = NULL; + OCSP_CERTID *certID = NULL; + apr_uri_t *ruri; + + ruri = determine_responder_uri(sc, cert, c, pool); + if (!ruri) { + return V_OCSP_CERTSTATUS_UNKNOWN; + } + + request = create_request(ctx, cert, &certID, s, pool); + if (request) { + apr_interval_time_t to = sc->server->ocsp_responder_timeout == UNSET ? + apr_time_from_sec(DEFAULT_OCSP_TIMEOUT) : + sc->server->ocsp_responder_timeout; + response = modssl_dispatch_ocsp_request(ruri, to, request, c, pool); + } + + if (!request || !response) { + rc = V_OCSP_CERTSTATUS_UNKNOWN; + } + + if (rc == V_OCSP_CERTSTATUS_GOOD) { + int r = OCSP_response_status(response); + + if (r != OCSP_RESPONSE_STATUS_SUCCESSFUL) { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(01922) + "OCSP response not successful: %d", rc); + rc = V_OCSP_CERTSTATUS_UNKNOWN; + } + } + + if (rc == V_OCSP_CERTSTATUS_GOOD) { + basicResponse = OCSP_response_get1_basic(response); + if (!basicResponse) { + ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(01923) + "could not retrieve OCSP basic response"); + ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, s); + rc = V_OCSP_CERTSTATUS_UNKNOWN; + } + } + + if (rc == V_OCSP_CERTSTATUS_GOOD) { + if (OCSP_check_nonce(request, basicResponse) != 1) { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(01924) + "Bad OCSP responder answer (bad nonce)"); + rc = V_OCSP_CERTSTATUS_UNKNOWN; + } + } + + if (rc == V_OCSP_CERTSTATUS_GOOD) { + /* TODO: allow flags configuration. */ + if (OCSP_basic_verify(basicResponse, NULL, ctx->ctx, 0) != 1) { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(01925) + "failed to verify the OCSP response"); + ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, s); + rc = V_OCSP_CERTSTATUS_UNKNOWN; + } + } + + if (rc == V_OCSP_CERTSTATUS_GOOD) { + int reason = -1, status; + ASN1_GENERALIZEDTIME *thisup = NULL, *nextup = NULL; + + rc = OCSP_resp_find_status(basicResponse, certID, &status, + &reason, NULL, &thisup, &nextup); + if (rc != 1) { + ssl_log_cxerror(SSLLOG_MARK, APLOG_ERR, 0, c, cert, APLOGNO(02272) + "failed to retrieve OCSP response status"); + ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, s); + rc = V_OCSP_CERTSTATUS_UNKNOWN; + } + else { + rc = status; + } + + /* Check whether the response is inside the defined validity + * period; otherwise fail. */ + if (rc != V_OCSP_CERTSTATUS_UNKNOWN) { + long resptime_skew = sc->server->ocsp_resptime_skew == UNSET ? + DEFAULT_OCSP_MAX_SKEW : sc->server->ocsp_resptime_skew; + /* oscp_resp_maxage can be passed verbatim - UNSET (-1) means + * that responses can be of any age as long as nextup is in the + * future. */ + int vrc = OCSP_check_validity(thisup, nextup, resptime_skew, + sc->server->ocsp_resp_maxage); + if (vrc != 1) { + ssl_log_cxerror(SSLLOG_MARK, APLOG_ERR, 0, c, cert, APLOGNO(02273) + "OCSP response outside validity period"); + ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, s); + rc = V_OCSP_CERTSTATUS_UNKNOWN; + } + } + + { + int level = + (status == V_OCSP_CERTSTATUS_GOOD) ? APLOG_INFO : APLOG_ERR; + const char *result = + status == V_OCSP_CERTSTATUS_GOOD ? "good" : + (status == V_OCSP_CERTSTATUS_REVOKED ? "revoked" : "unknown"); + + ssl_log_cxerror(SSLLOG_MARK, level, 0, c, cert, + "OCSP validation completed, " + "certificate status: %s (%d, %d)", + result, status, reason); + } + } + + if (request) OCSP_REQUEST_free(request); + if (response) OCSP_RESPONSE_free(response); + if (basicResponse) OCSP_BASICRESP_free(basicResponse); + /* certID is freed when the request is freed */ + + return rc; +} + +int modssl_verify_ocsp(X509_STORE_CTX *ctx, SSLSrvConfigRec *sc, + server_rec *s, conn_rec *c, apr_pool_t *pool) +{ + X509 *cert = X509_STORE_CTX_get_current_cert(ctx); + apr_pool_t *vpool; + int rv; + + if (!cert) { + /* starting with OpenSSL 1.0, X509_STORE_CTX_get_current_cert() + * may yield NULL. Return early, but leave the ctx error as is. */ + ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, c, + "No cert available to check with OCSP"); + return 1; + } + else if (cert->valid && X509_check_issued(cert,cert) == X509_V_OK) { + /* don't do OCSP checking for valid self-issued certs */ + ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, c, + "Skipping OCSP check for valid self-issued cert"); + X509_STORE_CTX_set_error(ctx, X509_V_OK); + return 1; + } + + /* Create a temporary pool to constrain memory use (the passed-in + * pool may be e.g. a connection pool). */ + apr_pool_create(&vpool, pool); + + rv = verify_ocsp_status(cert, ctx, c, sc, s, vpool); + + apr_pool_destroy(vpool); + + /* Propagate the verification status back to the passed-in + * context. */ + switch (rv) { + case V_OCSP_CERTSTATUS_GOOD: + X509_STORE_CTX_set_error(ctx, X509_V_OK); + break; + + case V_OCSP_CERTSTATUS_REVOKED: + X509_STORE_CTX_set_error(ctx, X509_V_ERR_CERT_REVOKED); + break; + + case V_OCSP_CERTSTATUS_UNKNOWN: + /* correct error code for application errors? */ + X509_STORE_CTX_set_error(ctx, X509_V_ERR_APPLICATION_VERIFICATION); + break; + } + + return rv == V_OCSP_CERTSTATUS_GOOD; +} +#endif /* HAVE_OCSP */ diff --git a/modules/ssl/ssl_engine_pphrase.c b/modules/ssl/ssl_engine_pphrase.c index dc49eff6..b12cdacd 100644 --- a/modules/ssl/ssl_engine_pphrase.c +++ b/modules/ssl/ssl_engine_pphrase.c @@ -109,11 +109,7 @@ static apr_file_t *readtty = NULL; */ static server_rec *ssl_pphrase_server_rec = NULL; -#ifdef SSLC_VERSION_NUMBER -int ssl_pphrase_Handle_CB(char *, int, int); -#else int ssl_pphrase_Handle_CB(char *, int, int, void *); -#endif static char *pphrase_array_get(apr_array_header_t *arr, int idx) { @@ -132,6 +128,13 @@ static void pphrase_array_clear(apr_array_header_t *arr) arr->nelts = 0; } +/* Abandon all hope, ye who read this code. Don't believe the name: + * "passphrase handling" is really a peripheral (if complex) concern; + * the core purpose of this function to load into memory all + * configured certs and key from files. The private key handling in + * here should be split out into a separate function for improved + * readability. The myCtxVarGet abomination can be thrown away with + * SSLC support, vastly simplifying the code. */ void ssl_pphrase_Handle(server_rec *s, apr_pool_t *p) { SSLModConfigRec *mc = myModConfig(s); @@ -157,9 +160,7 @@ void ssl_pphrase_Handle(server_rec *s, apr_pool_t *p) int i, j; ssl_algo_t algoCert, algoKey, at; char *an; - char *cp; apr_time_t pkey_mtime = 0; - int isterm = 1; apr_status_t rv; /* * Start with a fresh pass phrase array @@ -173,43 +174,70 @@ void ssl_pphrase_Handle(server_rec *s, apr_pool_t *p) */ for (pServ = s; pServ != NULL; pServ = pServ->next) { sc = mySrvConfig(pServ); - - if (!sc->enabled) + cpVHostID = ssl_util_vhostid(p, pServ); + if (!sc->enabled) { + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, pServ, APLOGNO(02199) + "SSL not enabled on vhost %s, skipping SSL setup", + cpVHostID); continue; + } - cpVHostID = ssl_util_vhostid(p, pServ); - ap_log_error(APLOG_MARK, APLOG_INFO, 0, pServ, - "Loading certificate & private key of SSL-aware server"); + ap_log_error(APLOG_MARK, APLOG_INFO, 0, pServ, APLOGNO(02200) + "Loading certificate & private key of SSL-aware server '%s'", + cpVHostID); /* * Read in server certificate(s): This is the easy part * because this file isn't encrypted in any way. */ - if (sc->server->pks->cert_files[0] == NULL) { - ap_log_error(APLOG_MARK, APLOG_ERR, 0, pServ, + if (sc->server->pks->cert_files[0] == NULL + && sc->server->pkcs7 == NULL) { + ap_log_error(APLOG_MARK, APLOG_EMERG, 0, pServ, APLOGNO(02240) "Server should be SSL-aware but has no certificate " "configured [Hint: SSLCertificateFile] (%s:%d)", pServ->defn_name, pServ->defn_line_number); ssl_die(); } + + /* Bitmasks for all key algorithms configured for this server; + * initialize to zero. */ algoCert = SSL_ALGO_UNKNOWN; algoKey = SSL_ALGO_UNKNOWN; - for (i = 0, j = 0; i < SSL_AIDX_MAX && sc->server->pks->cert_files[i] != NULL; i++) { - apr_cpystrn(szPath, sc->server->pks->cert_files[i], sizeof(szPath)); - if ((rv = exists_and_readable(szPath, p, NULL)) != APR_SUCCESS) { - ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, - "Init: Can't open server certificate file %s", + /* Iterate through configured certificate files for this + * server. */ + for (i = 0, j = 0; i < SSL_AIDX_MAX + && (sc->server->pks->cert_files[i] != NULL + || sc->server->pkcs7); i++) { + const char *key_id; + int using_cache = 0; + + if (sc->server->pkcs7) { + STACK_OF(X509) *certs = ssl_read_pkcs7(pServ, + sc->server->pkcs7); + pX509Cert = sk_X509_value(certs, 0); + i = SSL_AIDX_MAX; + } else { + apr_cpystrn(szPath, sc->server->pks->cert_files[i], + sizeof(szPath)); + if ((rv = exists_and_readable(szPath, p, NULL)) + != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s, APLOGNO(02201) + "Init: Can't open server certificate file %s", + szPath); + ssl_die(); + } + if ((pX509Cert = SSL_read_X509(szPath, NULL, NULL)) == NULL) { + ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02241) + "Init: Unable to read server certificate from" + " file %s", szPath); + ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s); + ssl_die(); + } + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(02202) + "Init: Read server certificate from '%s'", szPath); - ssl_die(); } - if ((pX509Cert = SSL_read_X509(szPath, NULL, NULL)) == NULL) { - ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, - "Init: Unable to read server certificate from file %s", szPath); - ssl_log_ssl_error(APLOG_MARK, APLOG_ERR, s); - ssl_die(); - } - /* * check algorithm type of certificate and make * sure only one certificate per type is used. @@ -217,14 +245,19 @@ void ssl_pphrase_Handle(server_rec *s, apr_pool_t *p) at = ssl_util_algotypeof(pX509Cert, NULL); an = ssl_util_algotypestr(at); if (algoCert & at) { - ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, + ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02242) "Init: Multiple %s server certificates not " "allowed", an); - ssl_log_ssl_error(APLOG_MARK, APLOG_ERR, s); + ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s); ssl_die(); } algoCert |= at; + /* Determine the hash key used for this (vhost, algo-type) + * pair used to index both the mc->tPrivateKey and + * mc->tPublicCert tables: */ + key_id = asn1_table_vhost_key(mc, p, cpVHostID, an); + /* * Insert the certificate into global module configuration to let it * survive the processing between the 1st Apache API init round (where @@ -232,9 +265,8 @@ void ssl_pphrase_Handle(server_rec *s, apr_pool_t *p) * certificate is actually used to configure mod_ssl's per-server * configuration structures). */ - cp = asn1_table_vhost_key(mc, p, cpVHostID, an); length = i2d_X509(pX509Cert, NULL); - ucp = ssl_asn1_table_set(mc->tPublicCert, cp, length); + ucp = ssl_asn1_table_set(mc->tPublicCert, key_id, length); (void)i2d_X509(pX509Cert, &ucp); /* 2nd arg increments */ /* @@ -293,7 +325,7 @@ void ssl_pphrase_Handle(server_rec *s, apr_pool_t *p) */ if ((rv = exists_and_readable(szPath, p, &pkey_mtime)) != APR_SUCCESS ) { - ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, + ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s, APLOGNO(02243) "Init: Can't open server private key file " "%s",szPath); ssl_die(); @@ -320,22 +352,17 @@ void ssl_pphrase_Handle(server_rec *s, apr_pool_t *p) * are used to give a better idea as to what failed. */ if (pkey_mtime) { - int i; - - for (i=0; i < SSL_AIDX_MAX; i++) { - const char *key_id = - ssl_asn1_table_keyfmt(p, cpVHostID, i); - ssl_asn1_t *asn1 = - ssl_asn1_table_get(mc->tPrivateKey, key_id); - - if (asn1 && (asn1->source_mtime == pkey_mtime)) { - ap_log_error(APLOG_MARK, APLOG_INFO, - 0, pServ, - "%s reusing existing " - "%s private key on restart", - cpVHostID, ssl_asn1_keystr(i)); - return; - } + ssl_asn1_t *asn1 = + ssl_asn1_table_get(mc->tPrivateKey, key_id); + + if (asn1 && (asn1->source_mtime == pkey_mtime)) { + ap_log_error(APLOG_MARK, APLOG_INFO, + 0, pServ, APLOGNO(02244) + "%s reusing existing " + "%s private key on restart", + cpVHostID, ssl_asn1_keystr(i)); + using_cache = 1; + break; } } @@ -394,7 +421,7 @@ void ssl_pphrase_Handle(server_rec *s, apr_pool_t *p) } #ifdef WIN32 if (sc->server->pphrase_dialog_type == SSL_PPTYPE_BUILTIN) { - ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, + ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02245) "Init: SSLPassPhraseDialog builtin is not " "supported on Win32 (key file " "%s)", szPath); @@ -407,19 +434,19 @@ void ssl_pphrase_Handle(server_rec *s, apr_pool_t *p) */ if (cpPassPhraseCur == NULL) { if (nPassPhraseDialogCur && pkey_mtime && - !(isterm = isatty(fileno(stdout)))) /* XXX: apr_isatty() */ + !isatty(fileno(stdout))) /* XXX: apr_isatty() */ { ap_log_error(APLOG_MARK, APLOG_ERR, 0, - pServ, + pServ, APLOGNO(02246) "Init: Unable to read pass phrase " "[Hint: key introduced or changed " "before restart?]"); - ssl_log_ssl_error(APLOG_MARK, APLOG_ERR, pServ); + ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, pServ); } else { ap_log_error(APLOG_MARK, APLOG_ERR, 0, - pServ, "Init: Private key not found"); - ssl_log_ssl_error(APLOG_MARK, APLOG_ERR, pServ); + pServ, APLOGNO(02203) "Init: Private key not found"); + ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, pServ); } if (writetty) { apr_file_printf(writetty, "Apache:mod_ssl:Error: Private key not found.\n"); @@ -427,9 +454,10 @@ void ssl_pphrase_Handle(server_rec *s, apr_pool_t *p) } } else { - ap_log_error(APLOG_MARK, APLOG_ERR, 0, - pServ, "Init: Pass phrase incorrect"); - ssl_log_ssl_error(APLOG_MARK, APLOG_ERR, pServ); + ap_log_error(APLOG_MARK, APLOG_EMERG, 0, pServ, APLOGNO(02204) + "Init: Pass phrase incorrect for key of %s", + cpVHostID); + ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, pServ); if (writetty) { apr_file_printf(writetty, "Apache:mod_ssl:Error: Pass phrase incorrect.\n"); @@ -439,12 +467,18 @@ void ssl_pphrase_Handle(server_rec *s, apr_pool_t *p) ssl_die(); } + /* If a cached private key was found, nothing more to do + * here; loop through to the next configured cert for this + * vhost. */ + if (using_cache) + continue; + if (pPrivateKey == NULL) { - ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, + ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02247) "Init: Unable to read server private key from " "file %s [Hint: Perhaps it is in a separate file? " " See SSLCertificateKeyFile]", szPath); - ssl_log_ssl_error(APLOG_MARK, APLOG_ERR, s); + ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s); ssl_die(); } @@ -455,10 +489,10 @@ void ssl_pphrase_Handle(server_rec *s, apr_pool_t *p) at = ssl_util_algotypeof(NULL, pPrivateKey); an = ssl_util_algotypestr(at); if (algoKey & at) { - ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, + ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02248) "Init: Multiple %s server private keys not " "allowed", an); - ssl_log_ssl_error(APLOG_MARK, APLOG_ERR, s); + ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s); ssl_die(); } algoKey |= at; @@ -467,20 +501,20 @@ void ssl_pphrase_Handle(server_rec *s, apr_pool_t *p) * Log the type of reading */ if (nPassPhraseDialogCur == 0) { - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, pServ, + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, pServ, APLOGNO(02249) "unencrypted %s private key - pass phrase not " "required", an); } else { if (cpPassPhraseCur != NULL) { ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, - pServ, + pServ, APLOGNO(02250) "encrypted %s private key - pass phrase " "requested", an); } else { ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, - pServ, + pServ, APLOGNO(02251) "encrypted %s private key - pass phrase" " reused", an); } @@ -501,14 +535,13 @@ void ssl_pphrase_Handle(server_rec *s, apr_pool_t *p) * because the SSL library uses static variables inside a * RSA structure which do not survive DSO reloads!) */ - cp = asn1_table_vhost_key(mc, p, cpVHostID, an); length = i2d_PrivateKey(pPrivateKey, NULL); - ucp = ssl_asn1_table_set(mc->tPrivateKey, cp, length); + ucp = ssl_asn1_table_set(mc->tPrivateKey, key_id, length); (void)i2d_PrivateKey(pPrivateKey, &ucp); /* 2nd arg increments */ if (nPassPhraseDialogCur != 0) { /* remember mtime of encrypted keys */ - asn1 = ssl_asn1_table_get(mc->tPrivateKey, cp); + asn1 = ssl_asn1_table_get(mc->tPrivateKey, key_id); asn1->source_mtime = pkey_mtime; } @@ -536,7 +569,7 @@ void ssl_pphrase_Handle(server_rec *s, apr_pool_t *p) */ if (aPassPhrase->nelts) { pphrase_array_clear(aPassPhrase); - ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, + ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, APLOGNO(02205) "Init: Wiped out the queried pass phrases from memory"); } @@ -612,14 +645,8 @@ static int pipe_get_passwd_cb(char *buf, int length, char *prompt, int verify) return 0; } -#ifdef SSLC_VERSION_NUMBER -int ssl_pphrase_Handle_CB(char *buf, int bufsize, int verify) -{ - void *srv = ssl_pphrase_server_rec; -#else int ssl_pphrase_Handle_CB(char *buf, int bufsize, int verify, void *srv) { -#endif SSLModConfigRec *mc; server_rec *s; apr_pool_t *p; @@ -674,12 +701,12 @@ int ssl_pphrase_Handle_CB(char *buf, int bufsize, int verify, void *srv) if (sc->server->pphrase_dialog_type == SSL_PPTYPE_PIPE) { if (!readtty) { - ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, + ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, APLOGNO(01965) "Init: Creating pass phrase dialog pipe child " "'%s'", sc->server->pphrase_dialog_path); if (ssl_pipe_child_create(p, sc->server->pphrase_dialog_path) != APR_SUCCESS) { - ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, + ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(01966) "Init: Failed to create pass phrase pipe '%s'", sc->server->pphrase_dialog_path); PEMerr(PEM_F_DEF_CALLBACK,PEM_R_PROBLEMS_GETTING_PASSWORD); @@ -687,7 +714,7 @@ int ssl_pphrase_Handle_CB(char *buf, int bufsize, int verify, void *srv) return (-1); } } - ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, + ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, APLOGNO(01967) "Init: Requesting pass phrase via piped dialog"); } else { /* sc->server->pphrase_dialog_type == SSL_PPTYPE_BUILTIN */ @@ -704,7 +731,7 @@ int ssl_pphrase_Handle_CB(char *buf, int bufsize, int verify, void *srv) */ apr_file_open_stdout(&writetty, p); - ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, + ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, APLOGNO(01968) "Init: Requesting pass phrase via builtin terminal " "dialog"); #endif @@ -717,8 +744,8 @@ int ssl_pphrase_Handle_CB(char *buf, int bufsize, int verify, void *srv) * something... */ if (*pnPassPhraseDialog == 1) { - apr_file_printf(writetty, "%s mod_ssl/%s (Pass Phrase Dialog)\n", - AP_SERVER_BASEVERSION, MOD_SSL_VERSION); + apr_file_printf(writetty, "%s mod_ssl (Pass Phrase Dialog)\n", + AP_SERVER_BASEVERSION); apr_file_printf(writetty, "Some of your private key files are encrypted for security reasons.\n"); apr_file_printf(writetty, "In order to read them you have to provide the pass phrases.\n"); } @@ -763,7 +790,7 @@ int ssl_pphrase_Handle_CB(char *buf, int bufsize, int verify, void *srv) const char **argv = apr_palloc(p, sizeof(char *) * 4); char *result; - ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, + ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, APLOGNO(01969) "Init: Requesting pass phrase from dialog filter " "program (%s)", cmd); @@ -783,7 +810,7 @@ int ssl_pphrase_Handle_CB(char *buf, int bufsize, int verify, void *srv) *cppPassPhraseCur = apr_pstrdup(p, buf); /* - * And return it's length to OpenSSL... + * And return its length to OpenSSL... */ return (len); } diff --git a/modules/ssl/ssl_engine_rand.c b/modules/ssl/ssl_engine_rand.c index a3c0fc5b..df25d8fd 100644 --- a/modules/ssl/ssl_engine_rand.c +++ b/modules/ssl/ssl_engine_rand.c @@ -45,19 +45,17 @@ int ssl_rand_seed(server_rec *s, apr_pool_t *p, ssl_rsctx_t nCtx, char *prefix) ssl_randseed_t *pRandSeeds; ssl_randseed_t *pRandSeed; unsigned char stackdata[256]; - int nReq, nDone; + int nDone; apr_file_t *fp; int i, n, l; mc = myModConfig(s); - nReq = 0; nDone = 0; apRandSeed = mc->aRandSeed; pRandSeeds = (ssl_randseed_t *)apRandSeed->elts; for (i = 0; i < apRandSeed->nelts; i++) { pRandSeed = &pRandSeeds[i]; if (pRandSeed->nCtx == nCtx) { - nReq += pRandSeed->nBytes; if (pRandSeed->nSrc == SSL_RSSRC_FILE) { /* * seed in contents of an external file @@ -83,7 +81,6 @@ int ssl_rand_seed(server_rec *s, apr_pool_t *p, ssl_rsctx_t nCtx, char *prefix) nDone += ssl_rand_feedfp(p, fp, pRandSeed->nBytes); ssl_util_ppclose(s, p, fp); } -#ifdef HAVE_SSL_RAND_EGD else if (pRandSeed->nSrc == SSL_RSSRC_EGD) { /* * seed in contents provided by the external @@ -93,7 +90,6 @@ int ssl_rand_seed(server_rec *s, apr_pool_t *p, ssl_rsctx_t nCtx, char *prefix) continue; nDone += n; } -#endif else if (pRandSeed->nSrc == SSL_RSSRC_BUILTIN) { struct { time_t t; @@ -124,11 +120,11 @@ int ssl_rand_seed(server_rec *s, apr_pool_t *p, ssl_rsctx_t nCtx, char *prefix) } } } - ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, + ap_log_error(APLOG_MARK, APLOG_TRACE2, 0, s, "%sSeeding PRNG with %d bytes of entropy", prefix, nDone); if (RAND_status() == 0) - ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, + ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(01990) "%sPRNG still contains insufficient entropy!", prefix); return nDone; diff --git a/modules/ssl/ssl_engine_vars.c b/modules/ssl/ssl_engine_vars.c index 83cff2c1..3815cd43 100644 --- a/modules/ssl/ssl_engine_vars.c +++ b/modules/ssl/ssl_engine_vars.c @@ -29,6 +29,7 @@ -- Unknown */ #include "ssl_private.h" #include "mod_ssl.h" +#include "ap_expr.h" #include "apr_time.h" @@ -38,11 +39,11 @@ ** _________________________________________________________________ */ -static char *ssl_var_lookup_ssl(apr_pool_t *p, conn_rec *c, char *var); -static char *ssl_var_lookup_ssl_cert(apr_pool_t *p, X509 *xs, char *var); +static char *ssl_var_lookup_ssl(apr_pool_t *p, conn_rec *c, request_rec *r, char *var); +static char *ssl_var_lookup_ssl_cert(apr_pool_t *p, request_rec *r, X509 *xs, char *var); static char *ssl_var_lookup_ssl_cert_dn(apr_pool_t *p, X509_NAME *xsname, char *var); -static char *ssl_var_lookup_ssl_cert_valid(apr_pool_t *p, ASN1_UTCTIME *tm); -static char *ssl_var_lookup_ssl_cert_remain(apr_pool_t *p, ASN1_UTCTIME *tm); +static char *ssl_var_lookup_ssl_cert_valid(apr_pool_t *p, ASN1_TIME *tm); +static char *ssl_var_lookup_ssl_cert_remain(apr_pool_t *p, ASN1_TIME *tm); static char *ssl_var_lookup_ssl_cert_serial(apr_pool_t *p, X509 *xs); static char *ssl_var_lookup_ssl_cert_chain(apr_pool_t *p, STACK_OF(X509) *sk, char *var); static char *ssl_var_lookup_ssl_cert_PEM(apr_pool_t *p, X509 *xs); @@ -58,17 +59,56 @@ static int ssl_is_https(conn_rec *c) return sslconn && sslconn->ssl; } -static const char var_interface[] = "mod_ssl/" MOD_SSL_VERSION; +static const char var_interface[] = "mod_ssl/" AP_SERVER_BASEREVISION; static char var_library_interface[] = SSL_LIBRARY_TEXT; static char *var_library = NULL; +static apr_array_header_t *expr_peer_ext_list_fn(ap_expr_eval_ctx_t *ctx, + const void *dummy, + const char *arg) +{ + return ssl_ext_list(ctx->p, ctx->c, 1, arg); +} + +static const char *expr_var_fn(ap_expr_eval_ctx_t *ctx, const void *data) +{ + char *var = (char *)data; + return ssl_var_lookup_ssl(ctx->p, ctx->c, ctx->r, var); +} + +static int ssl_expr_lookup(ap_expr_lookup_parms *parms) +{ + switch (parms->type) { + case AP_EXPR_FUNC_VAR: + /* for now, we just handle everything that starts with SSL_, but + * register our hook as APR_HOOK_LAST + * XXX: This can be optimized + */ + if (strcEQn(parms->name, "SSL_", 4)) { + *parms->func = expr_var_fn; + *parms->data = parms->name + 4; + return OK; + } + break; + case AP_EXPR_FUNC_LIST: + if (strcEQ(parms->name, "PeerExtList")) { + *parms->func = expr_peer_ext_list_fn; + *parms->data = "PeerExtList"; + return OK; + } + break; + } + return DECLINED; +} + + void ssl_var_register(apr_pool_t *p) { char *cp, *cp2; APR_REGISTER_OPTIONAL_FN(ssl_is_https); APR_REGISTER_OPTIONAL_FN(ssl_var_lookup); - APR_REGISTER_OPTIONAL_FN(ssl_ext_lookup); + APR_REGISTER_OPTIONAL_FN(ssl_ext_list); /* Perform once-per-process library version determination: */ var_library = apr_pstrdup(p, SSL_LIBRARY_DYNTEXT); @@ -84,6 +124,8 @@ void ssl_var_register(apr_pool_t *p) if ((cp2 = strchr(cp, ' ')) != NULL) *cp2 = NUL; } + + ap_hook_expr_lookup(ssl_expr_lookup, NULL, NULL, APR_HOOK_MIDDLE); } /* This function must remain safe to use for a non-SSL connection. */ @@ -145,6 +187,8 @@ char *ssl_var_lookup(apr_pool_t *p, server_rec *s, conn_rec *c, request_rec *r, result = r->uri; else if (strcEQ(var, "REQUEST_FILENAME")) result = r->filename; + else if (strcEQ(var, "REMOTE_ADDR")) + result = r->useragent_ip; else if (strcEQ(var, "REMOTE_HOST")) result = ap_get_remote_host(r->connection, r->per_dir_config, REMOTE_NAME, NULL); @@ -161,7 +205,7 @@ char *ssl_var_lookup(apr_pool_t *p, server_rec *s, conn_rec *c, request_rec *r, if (strcEQ(var, "SERVER_ADMIN")) result = r->server->server_admin; else if (strcEQ(var, "SERVER_NAME")) - result = ap_get_server_name(r); + result = ap_get_server_name_for_url(r); else if (strcEQ(var, "SERVER_PORT")) result = apr_psprintf(p, "%u", ap_get_server_port(r)); else if (strcEQ(var, "SERVER_PROTOCOL")) @@ -183,6 +227,11 @@ char *ssl_var_lookup(apr_pool_t *p, server_rec *s, conn_rec *c, request_rec *r, result = r->ap_auth_type; else if (strcEQ(var, "THE_REQUEST")) result = r->the_request; + else if (strlen(var) > 4 && strcEQn(var, "ENV:", 4)) { + result = apr_table_get(r->notes, var+4); + if (result == NULL) + result = apr_table_get(r->subprocess_env, var+4); + } break; } } @@ -194,9 +243,7 @@ char *ssl_var_lookup(apr_pool_t *p, server_rec *s, conn_rec *c, request_rec *r, SSLConnRec *sslconn = myConnConfig(c); if (strlen(var) > 4 && strcEQn(var, "SSL_", 4) && sslconn && sslconn->ssl) - result = ssl_var_lookup_ssl(p, c, var+4); - else if (strcEQ(var, "REMOTE_ADDR")) - result = c->remote_ip; + result = ssl_var_lookup_ssl(p, c, r, var+4); else if (strcEQ(var, "HTTPS")) { if (sslconn && sslconn->ssl) result = "on"; @@ -255,11 +302,7 @@ char *ssl_var_lookup(apr_pool_t *p, server_rec *s, conn_rec *c, request_rec *r, } /* all other env-variables from the parent Apache process */ else if (strlen(var) > 4 && strcEQn(var, "ENV:", 4)) { - result = apr_table_get(r->notes, var+4); - if (result == NULL) - result = apr_table_get(r->subprocess_env, var+4); - if (result == NULL) - result = getenv(var+4); + result = getenv(var+4); } } @@ -270,7 +313,8 @@ char *ssl_var_lookup(apr_pool_t *p, server_rec *s, conn_rec *c, request_rec *r, return (char *)result; } -static char *ssl_var_lookup_ssl(apr_pool_t *p, conn_rec *c, char *var) +static char *ssl_var_lookup_ssl(apr_pool_t *p, conn_rec *c, request_rec *r, + char *var) { SSLConnRec *sslconn = myConnConfig(c); char *result; @@ -292,11 +336,17 @@ static char *ssl_var_lookup_ssl(apr_pool_t *p, conn_rec *c, char *var) SSL_SESSION *pSession = SSL_get_session(ssl); if (pSession) { result = apr_pstrdup(p, SSL_SESSION_id2sz( - SSL_SESSION_get_session_id(pSession), - SSL_SESSION_get_session_id_length(pSession), + pSession->session_id, + pSession->session_id_length, buf, sizeof(buf))); } } + else if(ssl != NULL && strcEQ(var, "SESSION_RESUMED")) { + if (SSL_session_reused(ssl) == 1) + result = "Resumed"; + else + result = "Initial"; + } else if (ssl != NULL && strlen(var) >= 6 && strcEQn(var, "CIPHER", 6)) { result = ssl_var_lookup_ssl_cipher(p, c, var+6); } @@ -309,13 +359,17 @@ static char *ssl_var_lookup_ssl(apr_pool_t *p, conn_rec *c, char *var) } else if (ssl != NULL && strlen(var) > 7 && strcEQn(var, "CLIENT_", 7)) { if ((xs = SSL_get_peer_certificate(ssl)) != NULL) { - result = ssl_var_lookup_ssl_cert(p, xs, var+7); + result = ssl_var_lookup_ssl_cert(p, r, xs, var+7); X509_free(xs); } } else if (ssl != NULL && strlen(var) > 7 && strcEQn(var, "SERVER_", 7)) { - if ((xs = SSL_get_certificate(ssl)) != NULL) - result = ssl_var_lookup_ssl_cert(p, xs, var+7); + if ((xs = SSL_get_certificate(ssl)) != NULL) { + result = ssl_var_lookup_ssl_cert(p, r, xs, var+7); + /* SSL_get_certificate is different from SSL_get_peer_certificate. + * No need to X509_free(xs). + */ + } } else if (ssl != NULL && strcEQ(var, "COMPRESS_METHOD")) { result = ssl_var_lookup_ssl_compress_meth(ssl); @@ -332,18 +386,51 @@ static char *ssl_var_lookup_ssl(apr_pool_t *p, conn_rec *c, char *var) flag = SSL_get_secure_renegotiation_support(ssl); #endif result = apr_pstrdup(p, flag ? "true" : "false"); - } + } return result; } -static char *ssl_var_lookup_ssl_cert(apr_pool_t *p, X509 *xs, char *var) +static char *ssl_var_lookup_ssl_cert_dn_oneline(apr_pool_t *p, request_rec *r, + X509_NAME *xsname) +{ + char *result = NULL; + SSLDirConfigRec *dc; + int legacy_format = 0; + if (r) { + dc = myDirConfig(r); + legacy_format = dc->nOptions & SSL_OPT_LEGACYDNFORMAT; + } + if (legacy_format) { + char *cp = X509_NAME_oneline(xsname, NULL, 0); + result = apr_pstrdup(p, cp); + OPENSSL_free(cp); + } + else { + BIO* bio; + int n; + unsigned long flags = XN_FLAG_RFC2253 & ~ASN1_STRFLGS_ESC_MSB; + if ((bio = BIO_new(BIO_s_mem())) == NULL) + return NULL; + X509_NAME_print_ex(bio, xsname, 0, flags); + n = BIO_pending(bio); + if (n > 0) { + result = apr_palloc(p, n+1); + n = BIO_read(bio, result, n); + result[n] = NUL; + } + BIO_free(bio); + } + return result; +} + +static char *ssl_var_lookup_ssl_cert(apr_pool_t *p, request_rec *r, X509 *xs, + char *var) { char *result; BOOL resdup; X509_NAME *xsname; int nid; - char *cp; result = NULL; resdup = TRUE; @@ -365,38 +452,34 @@ static char *ssl_var_lookup_ssl_cert(apr_pool_t *p, X509 *xs, char *var) result = ssl_var_lookup_ssl_cert_remain(p, X509_get_notAfter(xs)); resdup = FALSE; } - else if (strcEQ(var, "S_DN")) { - xsname = X509_get_subject_name(xs); - cp = X509_NAME_oneline(xsname, NULL, 0); - result = apr_pstrdup(p, cp); - modssl_free(cp); - resdup = FALSE; - } - else if (strlen(var) > 5 && strcEQn(var, "S_DN_", 5)) { - xsname = X509_get_subject_name(xs); - result = ssl_var_lookup_ssl_cert_dn(p, xsname, var+5); - resdup = FALSE; - } - else if (strcEQ(var, "I_DN")) { - xsname = X509_get_issuer_name(xs); - cp = X509_NAME_oneline(xsname, NULL, 0); - result = apr_pstrdup(p, cp); - modssl_free(cp); + else if (*var && strcEQ(var+1, "_DN")) { + if (*var == 'S') + xsname = X509_get_subject_name(xs); + else if (*var == 'I') + xsname = X509_get_issuer_name(xs); + else + return NULL; + result = ssl_var_lookup_ssl_cert_dn_oneline(p, r, xsname); resdup = FALSE; } - else if (strlen(var) > 5 && strcEQn(var, "I_DN_", 5)) { - xsname = X509_get_issuer_name(xs); + else if (strlen(var) > 5 && strcEQn(var+1, "_DN_", 4)) { + if (*var == 'S') + xsname = X509_get_subject_name(xs); + else if (*var == 'I') + xsname = X509_get_issuer_name(xs); + else + return NULL; result = ssl_var_lookup_ssl_cert_dn(p, xsname, var+5); resdup = FALSE; } else if (strcEQ(var, "A_SIG")) { - nid = OBJ_obj2nid((ASN1_OBJECT *)X509_get_signature_algorithm(xs)); + nid = OBJ_obj2nid((ASN1_OBJECT *)(xs->cert_info->signature->algorithm)); result = apr_pstrdup(p, (nid == NID_undef) ? "UNKNOWN" : OBJ_nid2ln(nid)); resdup = FALSE; } else if (strcEQ(var, "A_KEY")) { - nid = OBJ_obj2nid((ASN1_OBJECT *)X509_get_key_algorithm(xs)); + nid = OBJ_obj2nid((ASN1_OBJECT *)(xs->cert_info->key->algor->algorithm)); result = apr_pstrdup(p, (nid == NID_undef) ? "UNKNOWN" : OBJ_nid2ln(nid)); resdup = FALSE; @@ -431,7 +514,7 @@ static const struct { { "S", NID_surname, 1 }, { "D", NID_description, 1 }, #ifdef NID_userId - { "UID", NID_x500UniqueIdentifier, 1 }, + { "UID", NID_userId, 1 }, #endif { "Email", NID_pkcs9_emailAddress, 1 }, { NULL, 0, 0 } @@ -459,21 +542,15 @@ static char *ssl_var_lookup_ssl_cert_dn(apr_pool_t *p, X509_NAME *xsname, char * if (strEQn(var, ssl_var_lookup_ssl_cert_dn_rec[i].name, varlen) && strlen(ssl_var_lookup_ssl_cert_dn_rec[i].name) == varlen) { for (j = 0; j < sk_X509_NAME_ENTRY_num((STACK_OF(X509_NAME_ENTRY) *) - X509_NAME_get_entries(xsname)); + xsname->entries); j++) { xsne = sk_X509_NAME_ENTRY_value((STACK_OF(X509_NAME_ENTRY) *) - X509_NAME_get_entries(xsname), j); + xsname->entries, j); n =OBJ_obj2nid((ASN1_OBJECT *)X509_NAME_ENTRY_get_object(xsne)); if (n == ssl_var_lookup_ssl_cert_dn_rec[i].nid && idx-- == 0) { - unsigned char *data = X509_NAME_ENTRY_get_data_ptr(xsne); - /* cast needed from unsigned char to char */ - result = apr_pstrmemdup(p, (char *)data, - X509_NAME_ENTRY_get_data_len(xsne)); -#if APR_CHARSET_EBCDIC - ap_xlate_proto_from_ascii(result, X509_NAME_ENTRY_get_data_len(xsne)); -#endif /* APR_CHARSET_EBCDIC */ + result = SSL_X509_NAME_ENTRY_to_string(p, xsne); break; } } @@ -483,7 +560,7 @@ static char *ssl_var_lookup_ssl_cert_dn(apr_pool_t *p, X509_NAME *xsname, char * return result; } -static char *ssl_var_lookup_ssl_cert_valid(apr_pool_t *p, ASN1_UTCTIME *tm) +static char *ssl_var_lookup_ssl_cert_valid(apr_pool_t *p, ASN1_TIME *tm) { char *result; BIO* bio; @@ -491,7 +568,7 @@ static char *ssl_var_lookup_ssl_cert_valid(apr_pool_t *p, ASN1_UTCTIME *tm) if ((bio = BIO_new(BIO_s_mem())) == NULL) return NULL; - ASN1_UTCTIME_print(bio, tm); + ASN1_TIME_print(bio, tm); n = BIO_pending(bio); result = apr_pcalloc(p, n+1); n = BIO_read(bio, result, n); @@ -504,27 +581,36 @@ static char *ssl_var_lookup_ssl_cert_valid(apr_pool_t *p, ASN1_UTCTIME *tm) /* Return a string giving the number of days remaining until 'tm', or * "0" if this can't be determined. */ -static char *ssl_var_lookup_ssl_cert_remain(apr_pool_t *p, ASN1_UTCTIME *tm) +static char *ssl_var_lookup_ssl_cert_remain(apr_pool_t *p, ASN1_TIME *tm) { apr_time_t then, now = apr_time_now(); apr_time_exp_t exp = {0}; long diff; + unsigned char *dp; - /* Fail if the time isn't a valid ASN.1 UTCTIME; RFC3280 mandates + /* Fail if the time isn't a valid ASN.1 TIME; RFC3280 mandates * that the seconds digits are present even though ASN.1 * doesn't. */ - if (tm->length < 11 || !ASN1_UTCTIME_check(tm)) { + if ((tm->type == V_ASN1_UTCTIME && tm->length < 11) || + (tm->type == V_ASN1_GENERALIZEDTIME && tm->length < 13) || + !ASN1_TIME_check(tm)) { return apr_pstrdup(p, "0"); } - exp.tm_year = DIGIT2NUM(tm->data); - exp.tm_mon = DIGIT2NUM(tm->data + 2) - 1; - exp.tm_mday = DIGIT2NUM(tm->data + 4) + 1; - exp.tm_hour = DIGIT2NUM(tm->data + 6); - exp.tm_min = DIGIT2NUM(tm->data + 8); - exp.tm_sec = DIGIT2NUM(tm->data + 10); + if (tm->type == V_ASN1_UTCTIME) { + exp.tm_year = DIGIT2NUM(tm->data); + if (exp.tm_year <= 50) exp.tm_year += 100; + dp = tm->data + 2; + } else { + exp.tm_year = DIGIT2NUM(tm->data) * 100 + DIGIT2NUM(tm->data + 2) - 1900; + dp = tm->data + 4; + } - if (exp.tm_year <= 50) exp.tm_year += 100; + exp.tm_mon = DIGIT2NUM(dp) - 1; + exp.tm_mday = DIGIT2NUM(dp + 2) + 1; + exp.tm_hour = DIGIT2NUM(dp + 4); + exp.tm_min = DIGIT2NUM(dp + 6); + exp.tm_sec = DIGIT2NUM(dp + 8); if (apr_time_exp_gmt_get(&then, &exp) != APR_SUCCESS) { return apr_pstrdup(p, "0"); @@ -616,7 +702,8 @@ static char *ssl_var_lookup_ssl_cert_verify(apr_pool_t *p, conn_rec *c) result = "GENEROUS"; else /* client verification failed */ - result = apr_psprintf(p, "FAILED:%s", verr); + result = apr_psprintf(p, "FAILED:%s", + verr ? verr : X509_verify_cert_error_string(vrc)); if (xs) X509_free(xs); @@ -685,14 +772,14 @@ static char *ssl_var_lookup_ssl_version(apr_pool_t *p, char *var) /* Add each RDN in 'xn' to the table 't' where the NID is present in * 'nids', using key prefix 'pfx'. */ -static void extract_dn(apr_table_t *t, apr_hash_t *nids, const char *pfx, +static void extract_dn(apr_table_t *t, apr_hash_t *nids, const char *pfx, X509_NAME *xn, apr_pool_t *p) { - STACK_OF(X509_NAME_ENTRY) *ents = X509_NAME_get_entries(xn); + STACK_OF(X509_NAME_ENTRY) *ents = xn->entries; X509_NAME_ENTRY *xsne; apr_hash_t *count; int i, nid; - + /* Hash of (int) NID -> (int *) counter to count each time an RDN * with the given NID has been seen. */ count = apr_hash_make(p); @@ -709,7 +796,6 @@ static void extract_dn(apr_table_t *t, apr_hash_t *nids, const char *pfx, tag = apr_hash_get(nids, &nid, sizeof nid); if (tag) { - unsigned char *data = X509_NAME_ENTRY_get_data_ptr(xsne); const char *key; int *dup; char *value; @@ -726,13 +812,7 @@ static void extract_dn(apr_table_t *t, apr_hash_t *nids, const char *pfx, apr_hash_set(count, &nid, sizeof nid, dup); key = apr_pstrcat(p, pfx, tag, NULL); } - - /* cast needed from 'unsigned char *' to 'char *' */ - value = apr_pstrmemdup(p, (char *)data, - X509_NAME_ENTRY_get_data_len(xsne)); -#if APR_CHARSET_EBCDIC - ap_xlate_proto_from_ascii(value, X509_NAME_ENTRY_get_data_len(xsne)); -#endif /* APR_CHARSET_EBCDIC */ + value = SSL_X509_NAME_ENTRY_to_string(p, xsne); apr_table_setn(t, key, value); } } @@ -754,7 +834,7 @@ void modssl_var_extract_dns(apr_table_t *t, SSL *ssl, apr_pool_t *p) ssl_var_lookup_ssl_cert_dn_rec[n].name); } } - + /* Extract the server cert DNS -- note that the refcount does NOT * increase: */ xs = SSL_get_certificate(ssl); @@ -762,7 +842,7 @@ void modssl_var_extract_dns(apr_table_t *t, SSL *ssl, apr_pool_t *p) extract_dn(t, nids, "SSL_SERVER_S_DN_", X509_get_subject_name(xs), p); extract_dn(t, nids, "SSL_SERVER_I_DN_", X509_get_issuer_name(xs), p); } - + /* Extract the client cert DNs -- note that the refcount DOES * increase: */ xs = SSL_get_peer_certificate(ssl); @@ -773,23 +853,50 @@ void modssl_var_extract_dns(apr_table_t *t, SSL *ssl, apr_pool_t *p) } } -const char *ssl_ext_lookup(apr_pool_t *p, conn_rec *c, int peer, - const char *oidnum) +/* For an extension type which OpenSSL does not recognize, attempt to + * parse the extension type as a primitive string. This will fail for + * any structured extension type per the docs. Returns non-zero on + * success and writes the string to the given bio. */ +static int dump_extn_value(BIO *bio, ASN1_OCTET_STRING *str) +{ + MODSSL_D2I_ASN1_type_bytes_CONST unsigned char *pp = str->data; + ASN1_STRING *ret = ASN1_STRING_new(); + int rv = 0; + + /* This allows UTF8String, IA5String, VisibleString, or BMPString; + * conversion to UTF-8 is forced. */ + if (d2i_DISPLAYTEXT(&ret, &pp, str->length)) { + ASN1_STRING_print_ex(bio, ret, ASN1_STRFLGS_UTF8_CONVERT); + rv = 1; + } + + ASN1_STRING_free(ret); + return rv; +} + +apr_array_header_t *ssl_ext_list(apr_pool_t *p, conn_rec *c, int peer, + const char *extension) { SSLConnRec *sslconn = myConnConfig(c); - SSL *ssl; + SSL *ssl = NULL; + apr_array_header_t *array = NULL; X509 *xs = NULL; - ASN1_OBJECT *oid; + ASN1_OBJECT *oid = NULL; int count = 0, j; - char *result = NULL; - if (!sslconn || !sslconn->ssl) { + if (!sslconn || !sslconn->ssl || !extension) { return NULL; } ssl = sslconn->ssl; - oid = OBJ_txt2obj(oidnum, 1); + /* We accept the "extension" string to be converted as + * a long name (nsComment), short name (DN) or + * numeric OID (1.2.3.4). + */ + oid = OBJ_txt2obj(extension, 0); if (!oid) { + ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(01970) + "could not parse OID '%s'", extension); ERR_clear_error(); return NULL; } @@ -800,38 +907,54 @@ const char *ssl_ext_lookup(apr_pool_t *p, conn_rec *c, int peer, } count = X509_get_ext_count(xs); - + /* Create an array large enough to accomodate every extension. This is + * likely overkill, but safe. + */ + array = apr_array_make(p, count, sizeof(char *)); for (j = 0; j < count; j++) { X509_EXTENSION *ext = X509_get_ext(xs, j); if (OBJ_cmp(ext->object, oid) == 0) { BIO *bio = BIO_new(BIO_s_mem()); - if (X509V3_EXT_print(bio, ext, 0, 0) == 1) { + /* We want to obtain a string representation of the extensions + * value and add it to the array we're building. + * X509V3_EXT_print() doesn't know about all the possible + * data types, but the value is stored as an ASN1_OCTET_STRING + * allowing us a fallback in case of X509V3_EXT_print + * not knowing how to handle the data. + */ + if (X509V3_EXT_print(bio, ext, 0, 0) == 1 || + dump_extn_value(bio, X509_EXTENSION_get_data(ext)) == 1) { BUF_MEM *buf; - + char **ptr = apr_array_push(array); BIO_get_mem_ptr(bio, &buf); - result = apr_pstrmemdup(p, buf->data, buf->length); + *ptr = apr_pstrmemdup(p, buf->data, buf->length); + } else { + ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(01971) + "Found an extension '%s', but failed to " + "create a string from it", extension); } - BIO_vfree(bio); - break; } } + if (array->nelts == 0) + array = NULL; + if (peer) { /* only SSL_get_peer_certificate raises the refcount */ X509_free(xs); } + ASN1_OBJECT_free(oid); ERR_clear_error(); - return result; + return array; } static char *ssl_var_lookup_ssl_compress_meth(SSL *ssl) { char *result = "NULL"; -#ifdef OPENSSL_VERSION_NUMBER #if (OPENSSL_VERSION_NUMBER >= 0x00908000) SSL_SESSION *pSession = SSL_get_session(ssl); @@ -857,7 +980,6 @@ static char *ssl_var_lookup_ssl_compress_meth(SSL *ssl) } } #endif -#endif return result; } @@ -932,3 +1054,4 @@ static const char *ssl_var_log_handler_x(request_rec *r, char *a) return result; } + diff --git a/modules/ssl/ssl_expr.c b/modules/ssl/ssl_expr.c deleted file mode 100644 index da57e228..00000000 --- a/modules/ssl/ssl_expr.c +++ /dev/null @@ -1,82 +0,0 @@ -/* Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* _ _ - * _ __ ___ ___ __| | ___ ___| | mod_ssl - * | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL - * | | | | | | (_) | (_| | \__ \__ \ | - * |_| |_| |_|\___/ \__,_|___|___/___/_| - * |_____| - * ssl_expr.c - * Expression Handling - */ - /* ``It is hard to fly with - the eagles when you work - with the turkeys.'' - -- Unknown */ -#include "ssl_private.h" - -/* _________________________________________________________________ -** -** Expression Handling -** _________________________________________________________________ -*/ - -ssl_expr_info_type ssl_expr_info; -char *ssl_expr_error; - -ssl_expr *ssl_expr_comp(apr_pool_t *p, char *expr) -{ - ssl_expr_info.pool = p; - ssl_expr_info.inputbuf = expr; - ssl_expr_info.inputlen = strlen(expr); - ssl_expr_info.inputptr = ssl_expr_info.inputbuf; - ssl_expr_info.expr = FALSE; - - ssl_expr_error = NULL; - if (ssl_expr_yyparse()) - return NULL; - return ssl_expr_info.expr; -} - -char *ssl_expr_get_error(void) -{ - if (ssl_expr_error == NULL) - return ""; - return ssl_expr_error; -} - -ssl_expr *ssl_expr_make(ssl_expr_node_op op, void *a1, void *a2) -{ - ssl_expr *node; - - node = (ssl_expr *)apr_palloc(ssl_expr_info.pool, sizeof(ssl_expr)); - node->node_op = op; - node->node_arg1 = (char *)a1; - node->node_arg2 = (char *)a2; - return node; -} - -int ssl_expr_exec(request_rec *r, ssl_expr *expr) -{ - BOOL rc; - - rc = ssl_expr_eval(r, expr); - if (ssl_expr_error != NULL) - return (-1); - else - return (rc ? 1 : 0); -} diff --git a/modules/ssl/ssl_expr.h b/modules/ssl/ssl_expr.h deleted file mode 100644 index 0a1526db..00000000 --- a/modules/ssl/ssl_expr.h +++ /dev/null @@ -1,113 +0,0 @@ -/* Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @verbatim - _ _ - _ __ ___ ___ __| | ___ ___| | mod_ssl - | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL - | | | | | | (_) | (_| | \__ \__ \ | - |_| |_| |_|\___/ \__,_|___|___/___/_| - |_____| - @endverbatim - * @file ssl_expr.h - * @brief Expression Handling (Header). - * ``May all your PUSHes be POPed.'' - * - * @defgroup MOD_SSL_EXPR Expression Handling - * @ingroup MOD_SSL - * @{ - */ - -#ifndef __SSL_EXPR_H__ -#define __SSL_EXPR_H__ - -#ifndef FALSE -#define FALSE 0 -#endif - -#ifndef TRUE -#define TRUE !FALSE -#endif - -#ifndef YY_NULL -#define YY_NULL 0 -#endif - -#ifndef MIN -#define MIN(a,b) (((a)<(b))?(a):(b)) -#endif - -#ifndef BOOL -#define BOOL unsigned int -#endif - -#ifndef NULL -#define NULL (void *)0 -#endif - -#ifndef NUL -#define NUL '\0' -#endif - -#ifndef YYDEBUG -#define YYDEBUG 0 -#endif - -typedef enum { - op_NOP, op_ListElement, op_OidListElement, - op_True, op_False, op_Not, op_Or, op_And, op_Comp, - op_EQ, op_NE, op_LT, op_LE, op_GT, op_GE, op_IN, op_REG, op_NRE, - op_Digit, op_String, op_Regex, op_Var, op_Func -} ssl_expr_node_op; - -typedef struct { - ssl_expr_node_op node_op; - void *node_arg1; - void *node_arg2; - apr_pool_t *p; -} ssl_expr_node; - -typedef ssl_expr_node ssl_expr; - -typedef struct { - apr_pool_t *pool; - char *inputbuf; - int inputlen; - char *inputptr; - ssl_expr *expr; -} ssl_expr_info_type; - -extern ssl_expr_info_type ssl_expr_info; -extern char *ssl_expr_error; - -#define yylval ssl_expr_yylval -#define yyerror ssl_expr_yyerror -#define yyinput ssl_expr_yyinput - -extern int ssl_expr_yyparse(void); -extern int ssl_expr_yyerror(char *); -extern int ssl_expr_yylex(void); - -extern ssl_expr *ssl_expr_comp(apr_pool_t *, char *); -extern int ssl_expr_exec(request_rec *, ssl_expr *); -extern char *ssl_expr_get_error(void); -extern ssl_expr *ssl_expr_make(ssl_expr_node_op, void *, void *); -extern BOOL ssl_expr_eval(request_rec *, ssl_expr *); - -#endif /* __SSL_EXPR_H__ */ -/** @} */ - diff --git a/modules/ssl/ssl_expr_eval.c b/modules/ssl/ssl_expr_eval.c deleted file mode 100644 index f9d6f5ec..00000000 --- a/modules/ssl/ssl_expr_eval.c +++ /dev/null @@ -1,345 +0,0 @@ -/* Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* _ _ - * _ __ ___ ___ __| | ___ ___| | mod_ssl - * | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL - * | | | | | | (_) | (_| | \__ \__ \ | - * |_| |_| |_|\___/ \__,_|___|___/___/_| - * |_____| - * ssl_expr_eval.c - * Expression Evaluation - */ - /* ``Make love, - not software!'' - -- Unknown */ -#include "ssl_private.h" - -/* _________________________________________________________________ -** -** Expression Evaluation -** _________________________________________________________________ -*/ - -static BOOL ssl_expr_eval_comp(request_rec *, ssl_expr *); -static char *ssl_expr_eval_word(request_rec *, ssl_expr *); -static BOOL ssl_expr_eval_oid(request_rec *r, const char *word, const char *oidstr); -static char *ssl_expr_eval_func_file(request_rec *, char *); -static int ssl_expr_eval_strcmplex(char *, char *); - -BOOL ssl_expr_eval(request_rec *r, ssl_expr *node) -{ - switch (node->node_op) { - case op_True: { - return TRUE; - } - case op_False: { - return FALSE; - } - case op_Not: { - ssl_expr *e = (ssl_expr *)node->node_arg1; - return (!ssl_expr_eval(r, e)); - } - case op_Or: { - ssl_expr *e1 = (ssl_expr *)node->node_arg1; - ssl_expr *e2 = (ssl_expr *)node->node_arg2; - return (ssl_expr_eval(r, e1) || ssl_expr_eval(r, e2)); - } - case op_And: { - ssl_expr *e1 = (ssl_expr *)node->node_arg1; - ssl_expr *e2 = (ssl_expr *)node->node_arg2; - return (ssl_expr_eval(r, e1) && ssl_expr_eval(r, e2)); - } - case op_Comp: { - ssl_expr *e = (ssl_expr *)node->node_arg1; - return ssl_expr_eval_comp(r, e); - } - default: { - ssl_expr_error = "Internal evaluation error: Unknown expression node"; - return FALSE; - } - } -} - -static BOOL ssl_expr_eval_comp(request_rec *r, ssl_expr *node) -{ - switch (node->node_op) { - case op_EQ: { - ssl_expr *e1 = (ssl_expr *)node->node_arg1; - ssl_expr *e2 = (ssl_expr *)node->node_arg2; - return (strcmp(ssl_expr_eval_word(r, e1), ssl_expr_eval_word(r, e2)) == 0); - } - case op_NE: { - ssl_expr *e1 = (ssl_expr *)node->node_arg1; - ssl_expr *e2 = (ssl_expr *)node->node_arg2; - return (strcmp(ssl_expr_eval_word(r, e1), ssl_expr_eval_word(r, e2)) != 0); - } - case op_LT: { - ssl_expr *e1 = (ssl_expr *)node->node_arg1; - ssl_expr *e2 = (ssl_expr *)node->node_arg2; - return (ssl_expr_eval_strcmplex(ssl_expr_eval_word(r, e1), ssl_expr_eval_word(r, e2)) < 0); - } - case op_LE: { - ssl_expr *e1 = (ssl_expr *)node->node_arg1; - ssl_expr *e2 = (ssl_expr *)node->node_arg2; - return (ssl_expr_eval_strcmplex(ssl_expr_eval_word(r, e1), ssl_expr_eval_word(r, e2)) <= 0); - } - case op_GT: { - ssl_expr *e1 = (ssl_expr *)node->node_arg1; - ssl_expr *e2 = (ssl_expr *)node->node_arg2; - return (ssl_expr_eval_strcmplex(ssl_expr_eval_word(r, e1), ssl_expr_eval_word(r, e2)) > 0); - } - case op_GE: { - ssl_expr *e1 = (ssl_expr *)node->node_arg1; - ssl_expr *e2 = (ssl_expr *)node->node_arg2; - return (ssl_expr_eval_strcmplex(ssl_expr_eval_word(r, e1), ssl_expr_eval_word(r, e2)) >= 0); - } - case op_IN: { - ssl_expr *e1 = (ssl_expr *)node->node_arg1; - ssl_expr *e2 = (ssl_expr *)node->node_arg2; - ssl_expr *e3; - char *w1 = ssl_expr_eval_word(r, e1); - BOOL found = FALSE; - do { - ssl_expr_node_op op = e2->node_op; - e3 = (ssl_expr *)e2->node_arg1; - e2 = (ssl_expr *)e2->node_arg2; - - if (op == op_OidListElement) { - char *w3 = ssl_expr_eval_word(r, e3); - - found = ssl_expr_eval_oid(r, w1, w3); - - /* There will be no more nodes on the list, so the result is authoritative */ - break; - } - - if (strcmp(w1, ssl_expr_eval_word(r, e3)) == 0) { - found = TRUE; - break; - } - } while (e2 != NULL); - return found; - } - case op_REG: { - ssl_expr *e1; - ssl_expr *e2; - char *word; - ap_regex_t *regex; - - e1 = (ssl_expr *)node->node_arg1; - e2 = (ssl_expr *)node->node_arg2; - word = ssl_expr_eval_word(r, e1); - regex = (ap_regex_t *)(e2->node_arg1); - return (ap_regexec(regex, word, 0, NULL, 0) == 0); - } - case op_NRE: { - ssl_expr *e1; - ssl_expr *e2; - char *word; - ap_regex_t *regex; - - e1 = (ssl_expr *)node->node_arg1; - e2 = (ssl_expr *)node->node_arg2; - word = ssl_expr_eval_word(r, e1); - regex = (ap_regex_t *)(e2->node_arg1); - return !(ap_regexec(regex, word, 0, NULL, 0) == 0); - } - default: { - ssl_expr_error = "Internal evaluation error: Unknown expression node"; - return FALSE; - } - } -} - -static char *ssl_expr_eval_word(request_rec *r, ssl_expr *node) -{ - switch (node->node_op) { - case op_Digit: { - char *string = (char *)node->node_arg1; - return string; - } - case op_String: { - char *string = (char *)node->node_arg1; - return string; - } - case op_Var: { - char *var = (char *)node->node_arg1; - char *val = ssl_var_lookup(r->pool, r->server, r->connection, r, var); - return (val == NULL ? "" : val); - } - case op_Func: { - char *name = (char *)node->node_arg1; - ssl_expr *args = (ssl_expr *)node->node_arg2; - if (strEQ(name, "file")) - return ssl_expr_eval_func_file(r, (char *)(args->node_arg1)); - else { - ssl_expr_error = "Internal evaluation error: Unknown function name"; - return ""; - } - } - default: { - ssl_expr_error = "Internal evaluation error: Unknown expression node"; - return FALSE; - } - } -} - -#define NUM_OID_ELTS 8 /* start with 8 oid slots, resize when needed */ - -apr_array_header_t *ssl_extlist_by_oid(request_rec *r, const char *oidstr) -{ - int count = 0, j; - X509 *xs = NULL; - ASN1_OBJECT *oid; - apr_array_header_t *val_array; - SSLConnRec *sslconn = myConnConfig(r->connection); - - /* trivia */ - if (oidstr == NULL || sslconn == NULL || sslconn->ssl == NULL) - return NULL; - - /* Determine the oid we are looking for */ - if ((oid = OBJ_txt2obj(oidstr, 1)) == NULL) { - ERR_clear_error(); - return NULL; - } - - /* are there any extensions in the cert? */ - if ((xs = SSL_get_peer_certificate(sslconn->ssl)) == NULL || - (count = X509_get_ext_count(xs)) == 0) { - return NULL; - } - - val_array = apr_array_make(r->pool, NUM_OID_ELTS, sizeof(char *)); - - /* Loop over all extensions, extract the desired oids */ - for (j = 0; j < count; j++) { - X509_EXTENSION *ext = X509_get_ext(xs, j); - - if (OBJ_cmp(ext->object, oid) == 0) { - BIO *bio = BIO_new(BIO_s_mem()); - - if (X509V3_EXT_print(bio, ext, 0, 0) == 1) { - BUF_MEM *buf; - char **new = apr_array_push(val_array); - - BIO_get_mem_ptr(bio, &buf); - - *new = apr_pstrmemdup(r->pool, buf->data, buf->length); - } - - BIO_vfree(bio); - } - } - - X509_free(xs); - ERR_clear_error(); - - if (val_array->nelts == 0) - return NULL; - else - return val_array; -} - -static BOOL ssl_expr_eval_oid(request_rec *r, const char *word, const char *oidstr) -{ - int j; - BOOL result = FALSE; - apr_array_header_t *oid_array; - char **oid_value; - - if (NULL == (oid_array = ssl_extlist_by_oid(r, oidstr))) { - return FALSE; - } - - oid_value = (char **) oid_array->elts; - for (j = 0; j < oid_array->nelts; j++) { - if (strcmp(word, oid_value[j]) == 0) { - result = TRUE; - break; - } - } - return result; -} - - -static char *ssl_expr_eval_func_file(request_rec *r, char *filename) -{ - apr_file_t *fp; - char *buf; - apr_off_t offset; - apr_size_t len; - apr_finfo_t finfo; - - if (apr_file_open(&fp, filename, APR_READ|APR_BUFFERED, - APR_OS_DEFAULT, r->pool) != APR_SUCCESS) { - ssl_expr_error = "Cannot open file"; - return ""; - } - apr_file_info_get(&finfo, APR_FINFO_SIZE, fp); - if ((finfo.size + 1) != ((apr_size_t)finfo.size + 1)) { - ssl_expr_error = "Huge file cannot be read"; - apr_file_close(fp); - return ""; - } - len = (apr_size_t)finfo.size; - if (len == 0) { - buf = (char *)apr_palloc(r->pool, sizeof(char) * 1); - *buf = NUL; - } - else { - if ((buf = (char *)apr_palloc(r->pool, sizeof(char)*(len+1))) == NULL) { - ssl_expr_error = "Cannot allocate memory"; - apr_file_close(fp); - return ""; - } - offset = 0; - apr_file_seek(fp, APR_SET, &offset); - if (apr_file_read(fp, buf, &len) != APR_SUCCESS) { - ssl_expr_error = "Cannot read from file"; - apr_file_close(fp); - return ""; - } - buf[len] = NUL; - } - apr_file_close(fp); - return buf; -} - -/* a variant of strcmp(3) which works correctly also for number strings */ -static int ssl_expr_eval_strcmplex(char *cpNum1, char *cpNum2) -{ - int i, n1, n2; - - if (cpNum1 == NULL) - return -1; - if (cpNum2 == NULL) - return +1; - n1 = strlen(cpNum1); - n2 = strlen(cpNum2); - if (n1 > n2) - return 1; - if (n1 < n2) - return -1; - for (i = 0; i < n1; i++) { - if (cpNum1[i] > cpNum2[i]) - return 1; - if (cpNum1[i] < cpNum2[i]) - return -1; - } - return 0; -} diff --git a/modules/ssl/ssl_expr_parse.c b/modules/ssl/ssl_expr_parse.c deleted file mode 100644 index 90475937..00000000 --- a/modules/ssl/ssl_expr_parse.c +++ /dev/null @@ -1,618 +0,0 @@ -#ifndef lint -static char const -ssl_expr_yyrcsid[] = "$FreeBSD: src/usr.bin/yacc/skeleton.c,v 1.28.2.1 2001/07/19 05:46:39 peter Exp $"; -#endif -#include <stdlib.h> -#define YYBYACC 1 -#define YYMAJOR 1 -#define YYMINOR 9 -#define YYLEX ssl_expr_yylex() -#define YYEMPTY -1 -#define ssl_expr_yyclearin (ssl_expr_yychar=(YYEMPTY)) -#define ssl_expr_yyerrok (ssl_expr_yyerrflag=0) -#define YYRECOVERING() (ssl_expr_yyerrflag!=0) -#if defined(__cplusplus) || __STDC__ -static int ssl_expr_yygrowstack(void); -#else -static int ssl_expr_yygrowstack(); -#endif -#define YYPREFIX "ssl_expr_yy" -#line 36 "ssl_expr_parse.y" -#include "ssl_private.h" -#line 39 "ssl_expr_parse.y" -typedef union { - char *cpVal; - ssl_expr *exVal; -} YYSTYPE; -#line 28 "y.tab.c" -#define YYERRCODE 256 -#define T_TRUE 257 -#define T_FALSE 258 -#define T_DIGIT 259 -#define T_ID 260 -#define T_STRING 261 -#define T_REGEX 262 -#define T_REGEX_I 263 -#define T_FUNC_FILE 264 -#define T_OP_EQ 265 -#define T_OP_NE 266 -#define T_OP_LT 267 -#define T_OP_LE 268 -#define T_OP_GT 269 -#define T_OP_GE 270 -#define T_OP_REG 271 -#define T_OP_NRE 272 -#define T_OP_IN 273 -#define T_OP_OID 274 -#define T_OP_OR 275 -#define T_OP_AND 276 -#define T_OP_NOT 277 -const short ssl_expr_yylhs[] = { -1, - 0, 1, 1, 1, 1, 1, 1, 1, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 6, 6, 5, - 5, 7, 7, 7, 7, 4, 4, 3, -}; -const short ssl_expr_yylen[] = { 2, - 1, 1, 1, 2, 3, 3, 1, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 4, 3, 1, - 3, 1, 1, 4, 1, 1, 1, 4, -}; -const short ssl_expr_yydefred[] = { 0, - 2, 3, 22, 23, 0, 0, 0, 0, 0, 0, - 7, 25, 0, 0, 4, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, - 0, 0, 6, 9, 10, 11, 12, 13, 14, 26, - 27, 16, 17, 0, 0, 15, 28, 24, 0, 0, - 20, 0, 19, 0, 18, 21, -}; -const short ssl_expr_yydgoto[] = { 9, - 10, 11, 12, 42, 50, 46, 13, -}; -const short ssl_expr_yysindex[] = { -37, - 0, 0, 0, 0, -16, -37, -37, -92, 0, -248, - 0, 0, -250, -228, 0, -39, -226, -37, -37, -33, - -33, -33, -33, -33, -33, -233, -233, -118, -6, 0, - -88, -238, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, -1, -33, 0, 0, 0, -33, -38, - 0, 2, 0, -33, 0, 0, -}; -const short ssl_expr_yyrindex[] = { 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, -}; -const short ssl_expr_yygindex[] = { 0, - 7, 0, 0, 17, 0, 0, -13, -}; -#define YYTABLESIZE 276 -const short ssl_expr_yytable[] = { 8, - 5, 30, 7, 8, 45, 54, 34, 35, 36, 37, - 38, 39, 15, 16, 20, 21, 22, 23, 24, 25, - 26, 27, 28, 14, 32, 33, 18, 19, 40, 41, - 17, 51, 29, 31, 47, 52, 48, 19, 49, 1, - 56, 5, 55, 43, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 53, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 44, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, - 2, 3, 0, 4, 0, 3, 5, 4, 0, 0, - 5, 0, 0, 0, 0, 18, 19, 0, 0, 6, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 5, -}; -const short ssl_expr_yycheck[] = { 37, - 0, 41, 40, 37, 123, 44, 20, 21, 22, 23, - 24, 25, 6, 7, 265, 266, 267, 268, 269, 270, - 271, 272, 273, 40, 18, 19, 275, 276, 262, 263, - 123, 45, 261, 260, 41, 49, 125, 276, 40, 0, - 54, 41, 41, 27, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 125, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 274, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 257, - 258, 259, -1, 261, -1, 259, 264, 261, -1, -1, - 264, -1, -1, -1, -1, 275, 276, -1, -1, 277, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 275, -}; -#define YYFINAL 9 -#ifndef YYDEBUG -#define YYDEBUG 0 -#endif -#define YYMAXTOKEN 277 -#if YYDEBUG -const char * const ssl_expr_yyname[] = { -"end-of-file",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,"'%'",0,0,"'('","')'",0,0,"','",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"'{'",0,"'}'",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"T_TRUE", -"T_FALSE","T_DIGIT","T_ID","T_STRING","T_REGEX","T_REGEX_I","T_FUNC_FILE", -"T_OP_EQ","T_OP_NE","T_OP_LT","T_OP_LE","T_OP_GT","T_OP_GE","T_OP_REG", -"T_OP_NRE","T_OP_IN","T_OP_OID","T_OP_OR","T_OP_AND","T_OP_NOT", -}; -const char * const ssl_expr_yyrule[] = { -"$accept : root", -"root : expr", -"expr : T_TRUE", -"expr : T_FALSE", -"expr : T_OP_NOT expr", -"expr : expr T_OP_OR expr", -"expr : expr T_OP_AND expr", -"expr : comparison", -"expr : '(' expr ')'", -"comparison : word T_OP_EQ word", -"comparison : word T_OP_NE word", -"comparison : word T_OP_LT word", -"comparison : word T_OP_LE word", -"comparison : word T_OP_GT word", -"comparison : word T_OP_GE word", -"comparison : word T_OP_IN wordlist", -"comparison : word T_OP_REG regex", -"comparison : word T_OP_NRE regex", -"wordlist : T_OP_OID '(' word ')'", -"wordlist : '{' words '}'", -"words : word", -"words : words ',' word", -"word : T_DIGIT", -"word : T_STRING", -"word : '%' '{' T_ID '}'", -"word : funccall", -"regex : T_REGEX", -"regex : T_REGEX_I", -"funccall : T_FUNC_FILE '(' T_STRING ')'", -}; -#endif -#if YYDEBUG -#include <stdio.h> -#endif -#ifdef YYSTACKSIZE -#undef YYMAXDEPTH -#define YYMAXDEPTH YYSTACKSIZE -#else -#ifdef YYMAXDEPTH -#define YYSTACKSIZE YYMAXDEPTH -#else -#define YYSTACKSIZE 10000 -#define YYMAXDEPTH 10000 -#endif -#endif -#define YYINITSTACKSIZE 200 -int ssl_expr_yydebug; -int ssl_expr_yynerrs; -int ssl_expr_yyerrflag; -int ssl_expr_yychar; -short *ssl_expr_yyssp; -YYSTYPE *ssl_expr_yyvsp; -YYSTYPE ssl_expr_yyval; -YYSTYPE ssl_expr_yylval; -short *ssl_expr_yyss; -short *ssl_expr_yysslim; -YYSTYPE *ssl_expr_yyvs; -int ssl_expr_yystacksize; -#line 148 "ssl_expr_parse.y" - -int ssl_expr_yyerror(char *s) -{ - ssl_expr_error = s; - return 2; -} - -#line 237 "y.tab.c" -/* allocate initial stack or double stack size, up to YYMAXDEPTH */ -static int ssl_expr_yygrowstack() -{ - int newsize, i; - short *newss; - YYSTYPE *newvs; - - if ((newsize = ssl_expr_yystacksize) == 0) - newsize = YYINITSTACKSIZE; - else if (newsize >= YYMAXDEPTH) - return -1; - else if ((newsize *= 2) > YYMAXDEPTH) - newsize = YYMAXDEPTH; - i = ssl_expr_yyssp - ssl_expr_yyss; - newss = ssl_expr_yyss ? (short *)realloc(ssl_expr_yyss, newsize * sizeof *newss) : - (short *)malloc(newsize * sizeof *newss); - if (newss == NULL) - return -1; - ssl_expr_yyss = newss; - ssl_expr_yyssp = newss + i; - newvs = ssl_expr_yyvs ? (YYSTYPE *)realloc(ssl_expr_yyvs, newsize * sizeof *newvs) : - (YYSTYPE *)malloc(newsize * sizeof *newvs); - if (newvs == NULL) - return -1; - ssl_expr_yyvs = newvs; - ssl_expr_yyvsp = newvs + i; - ssl_expr_yystacksize = newsize; - ssl_expr_yysslim = ssl_expr_yyss + newsize - 1; - return 0; -} - -#define YYABORT goto ssl_expr_yyabort -#define YYREJECT goto ssl_expr_yyabort -#define YYACCEPT goto ssl_expr_yyaccept -#define YYERROR goto ssl_expr_yyerrlab - -#ifndef YYPARSE_PARAM -#if defined(__cplusplus) || __STDC__ -#define YYPARSE_PARAM_ARG void -#define YYPARSE_PARAM_DECL -#else /* ! ANSI-C/C++ */ -#define YYPARSE_PARAM_ARG -#define YYPARSE_PARAM_DECL -#endif /* ANSI-C/C++ */ -#else /* YYPARSE_PARAM */ -#ifndef YYPARSE_PARAM_TYPE -#define YYPARSE_PARAM_TYPE void * -#endif -#if defined(__cplusplus) || __STDC__ -#define YYPARSE_PARAM_ARG YYPARSE_PARAM_TYPE YYPARSE_PARAM -#define YYPARSE_PARAM_DECL -#else /* ! ANSI-C/C++ */ -#define YYPARSE_PARAM_ARG YYPARSE_PARAM -#define YYPARSE_PARAM_DECL YYPARSE_PARAM_TYPE YYPARSE_PARAM; -#endif /* ANSI-C/C++ */ -#endif /* ! YYPARSE_PARAM */ - -int -ssl_expr_yyparse (YYPARSE_PARAM_ARG) - YYPARSE_PARAM_DECL -{ - register int ssl_expr_yym, ssl_expr_yyn, ssl_expr_yystate; -#if YYDEBUG - register const char *ssl_expr_yys; - - if ((ssl_expr_yys = getenv("YYDEBUG"))) - { - ssl_expr_yyn = *ssl_expr_yys; - if (ssl_expr_yyn >= '0' && ssl_expr_yyn <= '9') - ssl_expr_yydebug = ssl_expr_yyn - '0'; - } -#endif - - ssl_expr_yynerrs = 0; - ssl_expr_yyerrflag = 0; - ssl_expr_yychar = (-1); - - if (ssl_expr_yyss == NULL && ssl_expr_yygrowstack()) goto ssl_expr_yyoverflow; - ssl_expr_yyssp = ssl_expr_yyss; - ssl_expr_yyvsp = ssl_expr_yyvs; - *ssl_expr_yyssp = ssl_expr_yystate = 0; - -ssl_expr_yyloop: - if ((ssl_expr_yyn = ssl_expr_yydefred[ssl_expr_yystate])) goto ssl_expr_yyreduce; - if (ssl_expr_yychar < 0) - { - if ((ssl_expr_yychar = ssl_expr_yylex()) < 0) ssl_expr_yychar = 0; -#if YYDEBUG - if (ssl_expr_yydebug) - { - ssl_expr_yys = 0; - if (ssl_expr_yychar <= YYMAXTOKEN) ssl_expr_yys = ssl_expr_yyname[ssl_expr_yychar]; - if (!ssl_expr_yys) ssl_expr_yys = "illegal-symbol"; - printf("%sdebug: state %d, reading %d (%s)\n", - YYPREFIX, ssl_expr_yystate, ssl_expr_yychar, ssl_expr_yys); - } -#endif - } - if ((ssl_expr_yyn = ssl_expr_yysindex[ssl_expr_yystate]) && (ssl_expr_yyn += ssl_expr_yychar) >= 0 && - ssl_expr_yyn <= YYTABLESIZE && ssl_expr_yycheck[ssl_expr_yyn] == ssl_expr_yychar) - { -#if YYDEBUG - if (ssl_expr_yydebug) - printf("%sdebug: state %d, shifting to state %d\n", - YYPREFIX, ssl_expr_yystate, ssl_expr_yytable[ssl_expr_yyn]); -#endif - if (ssl_expr_yyssp >= ssl_expr_yysslim && ssl_expr_yygrowstack()) - { - goto ssl_expr_yyoverflow; - } - *++ssl_expr_yyssp = ssl_expr_yystate = ssl_expr_yytable[ssl_expr_yyn]; - *++ssl_expr_yyvsp = ssl_expr_yylval; - ssl_expr_yychar = (-1); - if (ssl_expr_yyerrflag > 0) --ssl_expr_yyerrflag; - goto ssl_expr_yyloop; - } - if ((ssl_expr_yyn = ssl_expr_yyrindex[ssl_expr_yystate]) && (ssl_expr_yyn += ssl_expr_yychar) >= 0 && - ssl_expr_yyn <= YYTABLESIZE && ssl_expr_yycheck[ssl_expr_yyn] == ssl_expr_yychar) - { - ssl_expr_yyn = ssl_expr_yytable[ssl_expr_yyn]; - goto ssl_expr_yyreduce; - } - if (ssl_expr_yyerrflag) goto ssl_expr_yyinrecovery; -#if defined(lint) || defined(__GNUC__) - goto ssl_expr_yynewerror; -#endif -ssl_expr_yynewerror: - ssl_expr_yyerror("syntax error"); -#if defined(lint) || defined(__GNUC__) - goto ssl_expr_yyerrlab; -#endif -ssl_expr_yyerrlab: - ++ssl_expr_yynerrs; -ssl_expr_yyinrecovery: - if (ssl_expr_yyerrflag < 3) - { - ssl_expr_yyerrflag = 3; - for (;;) - { - if ((ssl_expr_yyn = ssl_expr_yysindex[*ssl_expr_yyssp]) && (ssl_expr_yyn += YYERRCODE) >= 0 && - ssl_expr_yyn <= YYTABLESIZE && ssl_expr_yycheck[ssl_expr_yyn] == YYERRCODE) - { -#if YYDEBUG - if (ssl_expr_yydebug) - printf("%sdebug: state %d, error recovery shifting\ - to state %d\n", YYPREFIX, *ssl_expr_yyssp, ssl_expr_yytable[ssl_expr_yyn]); -#endif - if (ssl_expr_yyssp >= ssl_expr_yysslim && ssl_expr_yygrowstack()) - { - goto ssl_expr_yyoverflow; - } - *++ssl_expr_yyssp = ssl_expr_yystate = ssl_expr_yytable[ssl_expr_yyn]; - *++ssl_expr_yyvsp = ssl_expr_yylval; - goto ssl_expr_yyloop; - } - else - { -#if YYDEBUG - if (ssl_expr_yydebug) - printf("%sdebug: error recovery discarding state %d\n", - YYPREFIX, *ssl_expr_yyssp); -#endif - if (ssl_expr_yyssp <= ssl_expr_yyss) goto ssl_expr_yyabort; - --ssl_expr_yyssp; - --ssl_expr_yyvsp; - } - } - } - else - { - if (ssl_expr_yychar == 0) goto ssl_expr_yyabort; -#if YYDEBUG - if (ssl_expr_yydebug) - { - ssl_expr_yys = 0; - if (ssl_expr_yychar <= YYMAXTOKEN) ssl_expr_yys = ssl_expr_yyname[ssl_expr_yychar]; - if (!ssl_expr_yys) ssl_expr_yys = "illegal-symbol"; - printf("%sdebug: state %d, error recovery discards token %d (%s)\n", - YYPREFIX, ssl_expr_yystate, ssl_expr_yychar, ssl_expr_yys); - } -#endif - ssl_expr_yychar = (-1); - goto ssl_expr_yyloop; - } -ssl_expr_yyreduce: -#if YYDEBUG - if (ssl_expr_yydebug) - printf("%sdebug: state %d, reducing by rule %d (%s)\n", - YYPREFIX, ssl_expr_yystate, ssl_expr_yyn, ssl_expr_yyrule[ssl_expr_yyn]); -#endif - ssl_expr_yym = ssl_expr_yylen[ssl_expr_yyn]; - ssl_expr_yyval = ssl_expr_yyvsp[1-ssl_expr_yym]; - switch (ssl_expr_yyn) - { -case 1: -#line 84 "ssl_expr_parse.y" -{ ssl_expr_info.expr = ssl_expr_yyvsp[0].exVal; } -break; -case 2: -#line 87 "ssl_expr_parse.y" -{ ssl_expr_yyval.exVal = ssl_expr_make(op_True, NULL, NULL); } -break; -case 3: -#line 88 "ssl_expr_parse.y" -{ ssl_expr_yyval.exVal = ssl_expr_make(op_False, NULL, NULL); } -break; -case 4: -#line 89 "ssl_expr_parse.y" -{ ssl_expr_yyval.exVal = ssl_expr_make(op_Not, ssl_expr_yyvsp[0].exVal, NULL); } -break; -case 5: -#line 90 "ssl_expr_parse.y" -{ ssl_expr_yyval.exVal = ssl_expr_make(op_Or, ssl_expr_yyvsp[-2].exVal, ssl_expr_yyvsp[0].exVal); } -break; -case 6: -#line 91 "ssl_expr_parse.y" -{ ssl_expr_yyval.exVal = ssl_expr_make(op_And, ssl_expr_yyvsp[-2].exVal, ssl_expr_yyvsp[0].exVal); } -break; -case 7: -#line 92 "ssl_expr_parse.y" -{ ssl_expr_yyval.exVal = ssl_expr_make(op_Comp, ssl_expr_yyvsp[0].exVal, NULL); } -break; -case 8: -#line 93 "ssl_expr_parse.y" -{ ssl_expr_yyval.exVal = ssl_expr_yyvsp[-1].exVal; } -break; -case 9: -#line 96 "ssl_expr_parse.y" -{ ssl_expr_yyval.exVal = ssl_expr_make(op_EQ, ssl_expr_yyvsp[-2].exVal, ssl_expr_yyvsp[0].exVal); } -break; -case 10: -#line 97 "ssl_expr_parse.y" -{ ssl_expr_yyval.exVal = ssl_expr_make(op_NE, ssl_expr_yyvsp[-2].exVal, ssl_expr_yyvsp[0].exVal); } -break; -case 11: -#line 98 "ssl_expr_parse.y" -{ ssl_expr_yyval.exVal = ssl_expr_make(op_LT, ssl_expr_yyvsp[-2].exVal, ssl_expr_yyvsp[0].exVal); } -break; -case 12: -#line 99 "ssl_expr_parse.y" -{ ssl_expr_yyval.exVal = ssl_expr_make(op_LE, ssl_expr_yyvsp[-2].exVal, ssl_expr_yyvsp[0].exVal); } -break; -case 13: -#line 100 "ssl_expr_parse.y" -{ ssl_expr_yyval.exVal = ssl_expr_make(op_GT, ssl_expr_yyvsp[-2].exVal, ssl_expr_yyvsp[0].exVal); } -break; -case 14: -#line 101 "ssl_expr_parse.y" -{ ssl_expr_yyval.exVal = ssl_expr_make(op_GE, ssl_expr_yyvsp[-2].exVal, ssl_expr_yyvsp[0].exVal); } -break; -case 15: -#line 102 "ssl_expr_parse.y" -{ ssl_expr_yyval.exVal = ssl_expr_make(op_IN, ssl_expr_yyvsp[-2].exVal, ssl_expr_yyvsp[0].exVal); } -break; -case 16: -#line 103 "ssl_expr_parse.y" -{ ssl_expr_yyval.exVal = ssl_expr_make(op_REG, ssl_expr_yyvsp[-2].exVal, ssl_expr_yyvsp[0].exVal); } -break; -case 17: -#line 104 "ssl_expr_parse.y" -{ ssl_expr_yyval.exVal = ssl_expr_make(op_NRE, ssl_expr_yyvsp[-2].exVal, ssl_expr_yyvsp[0].exVal); } -break; -case 18: -#line 107 "ssl_expr_parse.y" -{ ssl_expr_yyval.exVal = ssl_expr_make(op_OidListElement, ssl_expr_yyvsp[-1].exVal, NULL); } -break; -case 19: -#line 108 "ssl_expr_parse.y" -{ ssl_expr_yyval.exVal = ssl_expr_yyvsp[-1].exVal ; } -break; -case 20: -#line 111 "ssl_expr_parse.y" -{ ssl_expr_yyval.exVal = ssl_expr_make(op_ListElement, ssl_expr_yyvsp[0].exVal, NULL); } -break; -case 21: -#line 112 "ssl_expr_parse.y" -{ ssl_expr_yyval.exVal = ssl_expr_make(op_ListElement, ssl_expr_yyvsp[0].exVal, ssl_expr_yyvsp[-2].exVal); } -break; -case 22: -#line 115 "ssl_expr_parse.y" -{ ssl_expr_yyval.exVal = ssl_expr_make(op_Digit, ssl_expr_yyvsp[0].cpVal, NULL); } -break; -case 23: -#line 116 "ssl_expr_parse.y" -{ ssl_expr_yyval.exVal = ssl_expr_make(op_String, ssl_expr_yyvsp[0].cpVal, NULL); } -break; -case 24: -#line 117 "ssl_expr_parse.y" -{ ssl_expr_yyval.exVal = ssl_expr_make(op_Var, ssl_expr_yyvsp[-1].cpVal, NULL); } -break; -case 25: -#line 118 "ssl_expr_parse.y" -{ ssl_expr_yyval.exVal = ssl_expr_yyvsp[0].exVal; } -break; -case 26: -#line 121 "ssl_expr_parse.y" -{ - ap_regex_t *regex; - if ((regex = ap_pregcomp(ssl_expr_info.pool, ssl_expr_yyvsp[0].cpVal, - AP_REG_EXTENDED|AP_REG_NOSUB)) == NULL) { - ssl_expr_error = "Failed to compile regular expression"; - YYERROR; - } - ssl_expr_yyval.exVal = ssl_expr_make(op_Regex, regex, NULL); - } -break; -case 27: -#line 130 "ssl_expr_parse.y" -{ - ap_regex_t *regex; - if ((regex = ap_pregcomp(ssl_expr_info.pool, ssl_expr_yyvsp[0].cpVal, - AP_REG_EXTENDED|AP_REG_NOSUB|AP_REG_ICASE)) == NULL) { - ssl_expr_error = "Failed to compile regular expression"; - YYERROR; - } - ssl_expr_yyval.exVal = ssl_expr_make(op_Regex, regex, NULL); - } -break; -case 28: -#line 141 "ssl_expr_parse.y" -{ - ssl_expr *args = ssl_expr_make(op_ListElement, ssl_expr_yyvsp[-1].cpVal, NULL); - ssl_expr_yyval.exVal = ssl_expr_make(op_Func, "file", args); - } -break; -#line 563 "y.tab.c" - } - ssl_expr_yyssp -= ssl_expr_yym; - ssl_expr_yystate = *ssl_expr_yyssp; - ssl_expr_yyvsp -= ssl_expr_yym; - ssl_expr_yym = ssl_expr_yylhs[ssl_expr_yyn]; - if (ssl_expr_yystate == 0 && ssl_expr_yym == 0) - { -#if YYDEBUG - if (ssl_expr_yydebug) - printf("%sdebug: after reduction, shifting from state 0 to\ - state %d\n", YYPREFIX, YYFINAL); -#endif - ssl_expr_yystate = YYFINAL; - *++ssl_expr_yyssp = YYFINAL; - *++ssl_expr_yyvsp = ssl_expr_yyval; - if (ssl_expr_yychar < 0) - { - if ((ssl_expr_yychar = ssl_expr_yylex()) < 0) ssl_expr_yychar = 0; -#if YYDEBUG - if (ssl_expr_yydebug) - { - ssl_expr_yys = 0; - if (ssl_expr_yychar <= YYMAXTOKEN) ssl_expr_yys = ssl_expr_yyname[ssl_expr_yychar]; - if (!ssl_expr_yys) ssl_expr_yys = "illegal-symbol"; - printf("%sdebug: state %d, reading %d (%s)\n", - YYPREFIX, YYFINAL, ssl_expr_yychar, ssl_expr_yys); - } -#endif - } - if (ssl_expr_yychar == 0) goto ssl_expr_yyaccept; - goto ssl_expr_yyloop; - } - if ((ssl_expr_yyn = ssl_expr_yygindex[ssl_expr_yym]) && (ssl_expr_yyn += ssl_expr_yystate) >= 0 && - ssl_expr_yyn <= YYTABLESIZE && ssl_expr_yycheck[ssl_expr_yyn] == ssl_expr_yystate) - ssl_expr_yystate = ssl_expr_yytable[ssl_expr_yyn]; - else - ssl_expr_yystate = ssl_expr_yydgoto[ssl_expr_yym]; -#if YYDEBUG - if (ssl_expr_yydebug) - printf("%sdebug: after reduction, shifting from state %d \ -to state %d\n", YYPREFIX, *ssl_expr_yyssp, ssl_expr_yystate); -#endif - if (ssl_expr_yyssp >= ssl_expr_yysslim && ssl_expr_yygrowstack()) - { - goto ssl_expr_yyoverflow; - } - *++ssl_expr_yyssp = ssl_expr_yystate; - *++ssl_expr_yyvsp = ssl_expr_yyval; - goto ssl_expr_yyloop; -ssl_expr_yyoverflow: - ssl_expr_yyerror("yacc stack overflow"); -ssl_expr_yyabort: - return (1); -ssl_expr_yyaccept: - return (0); -} diff --git a/modules/ssl/ssl_expr_parse.h b/modules/ssl/ssl_expr_parse.h deleted file mode 100644 index 66952eb1..00000000 --- a/modules/ssl/ssl_expr_parse.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef YYERRCODE -#define YYERRCODE 256 -#endif - -#define T_TRUE 257 -#define T_FALSE 258 -#define T_DIGIT 259 -#define T_ID 260 -#define T_STRING 261 -#define T_REGEX 262 -#define T_REGEX_I 263 -#define T_FUNC_FILE 264 -#define T_OP_EQ 265 -#define T_OP_NE 266 -#define T_OP_LT 267 -#define T_OP_LE 268 -#define T_OP_GT 269 -#define T_OP_GE 270 -#define T_OP_REG 271 -#define T_OP_NRE 272 -#define T_OP_IN 273 -#define T_OP_OID 274 -#define T_OP_OR 275 -#define T_OP_AND 276 -#define T_OP_NOT 277 -typedef union { - char *cpVal; - ssl_expr *exVal; -} YYSTYPE; -extern YYSTYPE ssl_expr_yylval; diff --git a/modules/ssl/ssl_expr_parse.y b/modules/ssl/ssl_expr_parse.y deleted file mode 100644 index a30fc8e7..00000000 --- a/modules/ssl/ssl_expr_parse.y +++ /dev/null @@ -1,154 +0,0 @@ -/* Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* _ _ - * _ __ ___ ___ __| | ___ ___| | - * | '_ ` _ \ / _ \ / _` | / __/ __| | - * | | | | | | (_) | (_| | \__ \__ \ | mod_ssl - Apache Interface to OpenSSL - * |_| |_| |_|\___/ \__,_|___|___/___/_| http://www.modssl.org/ - * |_____| - * ssl_expr_parse.y - * Expression LR(1) Parser - */ - /* ``What you see is all you get.'' - -- Brian Kernighan */ - -/* _________________________________________________________________ -** -** Expression Parser -** _________________________________________________________________ -*/ - -%{ -#include "ssl_private.h" -%} - -%union { - char *cpVal; - ssl_expr *exVal; -} - -%token T_TRUE -%token T_FALSE - -%token <cpVal> T_DIGIT -%token <cpVal> T_ID -%token <cpVal> T_STRING -%token <cpVal> T_REGEX -%token <cpVal> T_REGEX_I - -%token T_FUNC_FILE - -%token T_OP_EQ -%token T_OP_NE -%token T_OP_LT -%token T_OP_LE -%token T_OP_GT -%token T_OP_GE -%token T_OP_REG -%token T_OP_NRE -%token T_OP_IN -%token T_OP_OID - -%token T_OP_OR -%token T_OP_AND -%token T_OP_NOT - -%left T_OP_OR -%left T_OP_AND -%left T_OP_NOT - -%type <exVal> expr -%type <exVal> comparison -%type <exVal> funccall -%type <exVal> regex -%type <exVal> words -%type <exVal> wordlist -%type <exVal> word - -%% - -root : expr { ssl_expr_info.expr = $1; } - ; - -expr : T_TRUE { $$ = ssl_expr_make(op_True, NULL, NULL); } - | T_FALSE { $$ = ssl_expr_make(op_False, NULL, NULL); } - | T_OP_NOT expr { $$ = ssl_expr_make(op_Not, $2, NULL); } - | expr T_OP_OR expr { $$ = ssl_expr_make(op_Or, $1, $3); } - | expr T_OP_AND expr { $$ = ssl_expr_make(op_And, $1, $3); } - | comparison { $$ = ssl_expr_make(op_Comp, $1, NULL); } - | '(' expr ')' { $$ = $2; } - ; - -comparison: word T_OP_EQ word { $$ = ssl_expr_make(op_EQ, $1, $3); } - | word T_OP_NE word { $$ = ssl_expr_make(op_NE, $1, $3); } - | word T_OP_LT word { $$ = ssl_expr_make(op_LT, $1, $3); } - | word T_OP_LE word { $$ = ssl_expr_make(op_LE, $1, $3); } - | word T_OP_GT word { $$ = ssl_expr_make(op_GT, $1, $3); } - | word T_OP_GE word { $$ = ssl_expr_make(op_GE, $1, $3); } - | word T_OP_IN wordlist { $$ = ssl_expr_make(op_IN, $1, $3); } - | word T_OP_REG regex { $$ = ssl_expr_make(op_REG, $1, $3); } - | word T_OP_NRE regex { $$ = ssl_expr_make(op_NRE, $1, $3); } - ; - -wordlist : T_OP_OID '(' word ')' { $$ = ssl_expr_make(op_OidListElement, $3, NULL); } - | '{' words '}' { $$ = $2 ; } - ; - -words : word { $$ = ssl_expr_make(op_ListElement, $1, NULL); } - | words ',' word { $$ = ssl_expr_make(op_ListElement, $3, $1); } - ; - -word : T_DIGIT { $$ = ssl_expr_make(op_Digit, $1, NULL); } - | T_STRING { $$ = ssl_expr_make(op_String, $1, NULL); } - | '%' '{' T_ID '}' { $$ = ssl_expr_make(op_Var, $3, NULL); } - | funccall { $$ = $1; } - ; - -regex : T_REGEX { - ap_regex_t *regex; - if ((regex = ap_pregcomp(ssl_expr_info.pool, $1, - AP_REG_EXTENDED|AP_REG_NOSUB)) == NULL) { - ssl_expr_error = "Failed to compile regular expression"; - YYERROR; - } - $$ = ssl_expr_make(op_Regex, regex, NULL); - } - | T_REGEX_I { - ap_regex_t *regex; - if ((regex = ap_pregcomp(ssl_expr_info.pool, $1, - AP_REG_EXTENDED|AP_REG_NOSUB|AP_REG_ICASE)) == NULL) { - ssl_expr_error = "Failed to compile regular expression"; - YYERROR; - } - $$ = ssl_expr_make(op_Regex, regex, NULL); - } - ; - -funccall : T_FUNC_FILE '(' T_STRING ')' { - ssl_expr *args = ssl_expr_make(op_ListElement, $3, NULL); - $$ = ssl_expr_make(op_Func, "file", args); - } - ; - -%% - -int yyerror(char *s) -{ - ssl_expr_error = s; - return 2; -} - diff --git a/modules/ssl/ssl_expr_scan.c b/modules/ssl/ssl_expr_scan.c deleted file mode 100644 index 278eba40..00000000 --- a/modules/ssl/ssl_expr_scan.c +++ /dev/null @@ -1,1975 +0,0 @@ -#define yy_create_buffer ssl_expr_yy_create_buffer -#define yy_delete_buffer ssl_expr_yy_delete_buffer -#define yy_scan_buffer ssl_expr_yy_scan_buffer -#define yy_scan_string ssl_expr_yy_scan_string -#define yy_scan_bytes ssl_expr_yy_scan_bytes -#define yy_flex_debug ssl_expr_yy_flex_debug -#define yy_init_buffer ssl_expr_yy_init_buffer -#define yy_flush_buffer ssl_expr_yy_flush_buffer -#define yy_load_buffer_state ssl_expr_yy_load_buffer_state -#define yy_switch_to_buffer ssl_expr_yy_switch_to_buffer -#define yyin ssl_expr_yyin -#define yyleng ssl_expr_yyleng -#define yylex ssl_expr_yylex -#define yyout ssl_expr_yyout -#define yyrestart ssl_expr_yyrestart -#define yytext ssl_expr_yytext - -/* A lexical scanner generated by flex */ - -/* Scanner skeleton version: - * $FreeBSD: src/usr.bin/lex/flex.skl,v 1.4 1999/10/27 07:56:44 obrien Exp $ - */ - -#define FLEX_SCANNER -#define YY_FLEX_MAJOR_VERSION 2 -#define YY_FLEX_MINOR_VERSION 5 - -#include <stdio.h> - - -/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */ -#ifdef c_plusplus -#ifndef __cplusplus -#define __cplusplus -#endif -#endif - - -#ifdef __cplusplus - -#include <stdlib.h> -#include <unistd.h> - -/* Use prototypes in function declarations. */ -#define YY_USE_PROTOS - -/* The "const" storage-class-modifier is valid. */ -#define YY_USE_CONST - -#else /* ! __cplusplus */ - -#if __STDC__ - -#define YY_USE_PROTOS -#define YY_USE_CONST - -#endif /* __STDC__ */ -#endif /* ! __cplusplus */ - -#ifdef __TURBOC__ - #pragma warn -rch - #pragma warn -use -#include <io.h> -#include <stdlib.h> -#define YY_USE_CONST -#define YY_USE_PROTOS -#endif - -#ifdef YY_USE_CONST -#define yyconst const -#else -#define yyconst -#endif - - -#ifdef YY_USE_PROTOS -#define YY_PROTO(proto) proto -#else -#define YY_PROTO(proto) () -#endif - -/* Returned upon end-of-file. */ -#define YY_NULL 0 - -/* Promotes a possibly negative, possibly signed char to an unsigned - * integer for use as an array index. If the signed char is negative, - * we want to instead treat it as an 8-bit unsigned char, hence the - * double cast. - */ -#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) - -/* Enter a start condition. This macro really ought to take a parameter, - * but we do it the disgusting crufty way forced on us by the ()-less - * definition of BEGIN. - */ -#define BEGIN yy_start = 1 + 2 * - -/* Translate the current start state into a value that can be later handed - * to BEGIN to return to the state. The YYSTATE alias is for lex - * compatibility. - */ -#define YY_START ((yy_start - 1) / 2) -#define YYSTATE YY_START - -/* Action number for EOF rule of a given start state. */ -#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) - -/* Special action meaning "start processing a new file". */ -#define YY_NEW_FILE yyrestart( yyin ) - -#define YY_END_OF_BUFFER_CHAR 0 - -/* Size of default input buffer. */ -#define YY_BUF_SIZE 16384 - -typedef struct yy_buffer_state *YY_BUFFER_STATE; - -extern int yyleng; -extern FILE *yyin, *yyout; - -#define EOB_ACT_CONTINUE_SCAN 0 -#define EOB_ACT_END_OF_FILE 1 -#define EOB_ACT_LAST_MATCH 2 - -/* The funky do-while in the following #define is used to turn the definition - * int a single C statement (which needs a semi-colon terminator). This - * avoids problems with code like: - * - * if ( condition_holds ) - * yyless( 5 ); - * else - * do_something_else(); - * - * Prior to using the do-while the compiler would get upset at the - * "else" because it interpreted the "if" statement as being all - * done when it reached the ';' after the yyless() call. - */ - -/* Return all but the first 'n' matched characters back to the input stream. */ - -#define yyless(n) \ - do \ - { \ - /* Undo effects of setting up yytext. */ \ - *yy_cp = yy_hold_char; \ - YY_RESTORE_YY_MORE_OFFSET \ - yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \ - YY_DO_BEFORE_ACTION; /* set up yytext again */ \ - } \ - while ( 0 ) - -#define unput(c) yyunput( c, yytext_ptr ) - -/* The following is because we cannot portably get our hands on size_t - * (without autoconf's help, which isn't available because we want - * flex-generated scanners to compile on their own). - */ -typedef unsigned int yy_size_t; - - -struct yy_buffer_state - { - FILE *yy_input_file; - - char *yy_ch_buf; /* input buffer */ - char *yy_buf_pos; /* current position in input buffer */ - - /* Size of input buffer in bytes, not including room for EOB - * characters. - */ - yy_size_t yy_buf_size; - - /* Number of characters read into yy_ch_buf, not including EOB - * characters. - */ - int yy_n_chars; - - /* Whether we "own" the buffer - i.e., we know we created it, - * and can realloc() it to grow it, and should free() it to - * delete it. - */ - int yy_is_our_buffer; - - /* Whether this is an "interactive" input source; if so, and - * if we're using stdio for input, then we want to use getc() - * instead of fread(), to make sure we stop fetching input after - * each newline. - */ - int yy_is_interactive; - - /* Whether we're considered to be at the beginning of a line. - * If so, '^' rules will be active on the next match, otherwise - * not. - */ - int yy_at_bol; - - /* Whether to try to fill the input buffer when we reach the - * end of it. - */ - int yy_fill_buffer; - - int yy_buffer_status; -#define YY_BUFFER_NEW 0 -#define YY_BUFFER_NORMAL 1 - /* When an EOF's been seen but there's still some text to process - * then we mark the buffer as YY_EOF_PENDING, to indicate that we - * shouldn't try reading from the input source any more. We might - * still have a bunch of tokens to match, though, because of - * possible backing-up. - * - * When we actually see the EOF, we change the status to "new" - * (via yyrestart()), so that the user can continue scanning by - * just pointing yyin at a new input file. - */ -#define YY_BUFFER_EOF_PENDING 2 - }; - -static YY_BUFFER_STATE yy_current_buffer = 0; - -/* We provide macros for accessing buffer states in case in the - * future we want to put the buffer states in a more general - * "scanner state". - */ -#define YY_CURRENT_BUFFER yy_current_buffer - - -/* yy_hold_char holds the character lost when yytext is formed. */ -static char yy_hold_char; - -static int yy_n_chars; /* number of characters read into yy_ch_buf */ - - -int yyleng; - -/* Points to current character in buffer. */ -static char *yy_c_buf_p = (char *) 0; -static int yy_init = 1; /* whether we need to initialize */ -static int yy_start = 0; /* start state number */ - -/* Flag which is used to allow yywrap()'s to do buffer switches - * instead of setting up a fresh yyin. A bit of a hack ... - */ -static int yy_did_buffer_switch_on_eof; - -void yyrestart YY_PROTO(( FILE *input_file )); - -void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer )); -void yy_load_buffer_state YY_PROTO(( void )); -YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size )); -void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b )); -void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file )); -void yy_flush_buffer YY_PROTO(( YY_BUFFER_STATE b )); -#define YY_FLUSH_BUFFER yy_flush_buffer( yy_current_buffer ) - -YY_BUFFER_STATE yy_scan_buffer YY_PROTO(( char *base, yy_size_t size )); -YY_BUFFER_STATE yy_scan_string YY_PROTO(( yyconst char *yy_str )); -YY_BUFFER_STATE yy_scan_bytes YY_PROTO(( yyconst char *bytes, int len )); - -static void *yy_flex_alloc YY_PROTO(( yy_size_t )); -static void *yy_flex_realloc YY_PROTO(( void *, yy_size_t )); -static void yy_flex_free YY_PROTO(( void * )); - -#define yy_new_buffer yy_create_buffer - -#define yy_set_interactive(is_interactive) \ - { \ - if ( ! yy_current_buffer ) \ - yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ - yy_current_buffer->yy_is_interactive = is_interactive; \ - } - -#define yy_set_bol(at_bol) \ - { \ - if ( ! yy_current_buffer ) \ - yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ - yy_current_buffer->yy_at_bol = at_bol; \ - } - -#define YY_AT_BOL() (yy_current_buffer->yy_at_bol) - - -#define yywrap() 1 -#define YY_SKIP_YYWRAP -typedef unsigned char YY_CHAR; -FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0; -typedef int yy_state_type; -extern char *yytext; -#define yytext_ptr yytext - -static yy_state_type yy_get_previous_state YY_PROTO(( void )); -static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state )); -static int yy_get_next_buffer YY_PROTO(( void )); -static void yy_fatal_error YY_PROTO(( yyconst char msg[] )); - -/* Done after the current pattern has been matched and before the - * corresponding action - sets up yytext. - */ -#define YY_DO_BEFORE_ACTION \ - yytext_ptr = yy_bp; \ - yyleng = (int) (yy_cp - yy_bp); \ - yy_hold_char = *yy_cp; \ - *yy_cp = '\0'; \ - yy_c_buf_p = yy_cp; - -#define YY_NUM_RULES 47 -#define YY_END_OF_BUFFER 48 -static yyconst short int yy_accept[89] = - { 0, - 0, 0, 0, 0, 0, 0, 0, 0, 48, 46, - 1, 38, 2, 46, 44, 24, 46, 28, 45, 45, - 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, - 46, 13, 4, 3, 14, 16, 18, 17, 1, 22, - 32, 34, 44, 26, 20, 31, 30, 45, 45, 45, - 19, 45, 45, 29, 27, 39, 25, 23, 15, 15, - 21, 45, 35, 45, 36, 13, 12, 5, 6, 10, - 11, 7, 8, 9, 40, 33, 45, 45, 37, 45, - 5, 6, 45, 41, 42, 5, 43, 0 - } ; - -static yyconst int yy_ec[256] = - { 0, - 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 2, 4, 5, 1, 1, 1, 6, 1, 1, - 1, 1, 1, 1, 7, 1, 1, 8, 8, 8, - 8, 8, 8, 8, 8, 9, 9, 7, 1, 10, - 11, 12, 1, 1, 13, 13, 13, 14, 13, 13, - 13, 13, 15, 13, 13, 13, 13, 13, 16, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 1, 17, 1, 1, 7, 1, 18, 19, 13, 20, - - 21, 22, 23, 13, 24, 13, 13, 25, 26, 27, - 28, 13, 29, 30, 31, 32, 33, 13, 13, 13, - 13, 13, 1, 34, 1, 35, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1 - } ; - -static yyconst int yy_meta[36] = - { 0, - 1, 1, 2, 1, 3, 1, 4, 4, 4, 1, - 1, 1, 4, 4, 4, 4, 3, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 1, 1 - } ; - -static yyconst short int yy_base[96] = - { 0, - 0, 0, 33, 34, 0, 0, 88, 87, 110, 154, - 38, 31, 154, 103, 35, 97, 34, 96, 0, 31, - 75, 72, 29, 27, 73, 28, 69, 33, 48, 69, - 64, 0, 154, 154, 97, 154, 154, 154, 54, 154, - 154, 154, 56, 154, 154, 154, 154, 0, 38, 77, - 0, 71, 70, 0, 0, 0, 0, 0, 154, 0, - 0, 62, 0, 60, 154, 0, 154, 59, 68, 154, - 154, 154, 154, 154, 0, 0, 61, 70, 0, 69, - 74, 76, 68, 0, 0, 79, 0, 154, 129, 133, - 137, 58, 141, 145, 149 - - } ; - -static yyconst short int yy_def[96] = - { 0, - 88, 1, 89, 89, 90, 90, 91, 91, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 92, 92, - 92, 92, 92, 92, 92, 92, 93, 92, 92, 92, - 88, 94, 88, 88, 95, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 92, 92, 92, - 92, 92, 92, 92, 92, 92, 92, 92, 88, 92, - 92, 92, 92, 92, 88, 94, 88, 88, 88, 88, - 88, 88, 88, 88, 92, 92, 92, 92, 92, 92, - 88, 88, 92, 92, 92, 88, 92, 0, 88, 88, - 88, 88, 88, 88, 88 - - } ; - -static yyconst short int yy_nxt[190] = - { 0, - 10, 11, 11, 12, 13, 14, 10, 15, 15, 16, - 17, 18, 19, 19, 19, 20, 10, 21, 19, 19, - 22, 23, 24, 25, 26, 27, 28, 29, 19, 19, - 19, 30, 19, 31, 10, 33, 33, 34, 34, 39, - 39, 40, 43, 43, 45, 49, 52, 54, 57, 35, - 35, 75, 53, 61, 49, 39, 39, 75, 55, 58, - 62, 48, 49, 43, 43, 41, 81, 82, 46, 59, - 59, 49, 59, 59, 59, 82, 82, 63, 59, 59, - 59, 86, 82, 82, 82, 59, 82, 82, 87, 85, - 84, 83, 80, 79, 78, 77, 76, 65, 64, 56, - - 51, 50, 59, 59, 68, 69, 47, 44, 42, 88, - 38, 38, 88, 88, 88, 70, 88, 88, 71, 88, - 88, 88, 88, 72, 88, 88, 73, 88, 74, 32, - 32, 32, 32, 36, 36, 36, 36, 37, 37, 37, - 37, 60, 88, 60, 60, 66, 88, 88, 66, 67, - 67, 67, 67, 9, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88 - } ; - -static yyconst short int yy_chk[190] = - { 0, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 3, 4, 3, 4, 11, - 11, 12, 15, 15, 17, 20, 23, 24, 26, 3, - 4, 49, 23, 28, 20, 39, 39, 49, 24, 26, - 28, 92, 29, 43, 43, 12, 68, 68, 17, 27, - 27, 29, 27, 27, 27, 69, 69, 29, 27, 27, - 27, 81, 81, 82, 82, 27, 86, 86, 83, 80, - 78, 77, 64, 62, 53, 52, 50, 31, 30, 25, - - 22, 21, 27, 27, 35, 35, 18, 16, 14, 9, - 8, 7, 0, 0, 0, 35, 0, 0, 35, 0, - 0, 0, 0, 35, 0, 0, 35, 0, 35, 89, - 89, 89, 89, 90, 90, 90, 90, 91, 91, 91, - 91, 93, 0, 93, 93, 94, 0, 0, 94, 95, - 95, 95, 95, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88 - } ; - -static yy_state_type yy_last_accepting_state; -static char *yy_last_accepting_cpos; - -/* The intent behind this definition is that it'll catch - * any uses of REJECT which flex missed. - */ -#define REJECT reject_used_but_not_detected -#define yymore() yymore_used_but_not_detected -#define YY_MORE_ADJ 0 -#define YY_RESTORE_YY_MORE_OFFSET -char *yytext; -#line 1 "ssl_expr_scan.l" -#define INITIAL 0 -/* Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* _ _ - * _ __ ___ ___ __| | ___ ___| | - * | '_ ` _ \ / _ \ / _` | / __/ __| | - * | | | | | | (_) | (_| | \__ \__ \ | mod_ssl - Apache Interface to OpenSSL - * |_| |_| |_|\___/ \__,_|___|___/___/_| http://www.modssl.org/ - * |_____| - * ssl_expr_scan.l - * Expression Scanner - */ -/* ``Killing for peace is -like fucking for virginity.'' --- Unknown */ -/* _________________________________________________________________ -** -** Expression Scanner -** _________________________________________________________________ -*/ -#line 37 "ssl_expr_scan.l" -#include "ssl_private.h" - -#include "ssl_expr_parse.h" - -#define YY_NO_UNPUT 1 -int yyinput(char *buf, int max_size); - -#undef YY_INPUT -#define YY_INPUT(buf,result,max_size) \ - (result = yyinput(buf, max_size)) - -#define MAX_STR_LEN 2048 -/* %option stack */ -#define YY_NEVER_INTERACTIVE 1 -#define str 1 - -#define regex 2 -#define regex_flags 3 - -#line 505 "lex.ssl_expr_yy.c" - -/* Macros after this point can all be overridden by user definitions in - * section 1. - */ - -#ifndef YY_SKIP_YYWRAP -#ifdef __cplusplus -extern "C" int yywrap YY_PROTO(( void )); -#else -extern int yywrap YY_PROTO(( void )); -#endif -#endif - -#ifndef YY_NO_UNPUT -static void yyunput YY_PROTO(( int c, char *buf_ptr )); -#endif - -#ifndef yytext_ptr -static void yy_flex_strncpy YY_PROTO(( char *, yyconst char *, int )); -#endif - -#ifdef YY_NEED_STRLEN -static int yy_flex_strlen YY_PROTO(( yyconst char * )); -#endif - -#ifndef YY_NO_INPUT -#ifdef __cplusplus -static int yyinput YY_PROTO(( void )); -#else -static int input YY_PROTO(( void )); -#endif -#endif - -#if YY_STACK_USED -static int yy_start_stack_ptr = 0; -static int yy_start_stack_depth = 0; -static int *yy_start_stack = 0; -#ifndef YY_NO_PUSH_STATE -static void yy_push_state YY_PROTO(( int new_state )); -#endif -#ifndef YY_NO_POP_STATE -static void yy_pop_state YY_PROTO(( void )); -#endif -#ifndef YY_NO_TOP_STATE -static int yy_top_state YY_PROTO(( void )); -#endif - -#else -#define YY_NO_PUSH_STATE 1 -#define YY_NO_POP_STATE 1 -#define YY_NO_TOP_STATE 1 -#endif - -#ifdef YY_MALLOC_DECL -YY_MALLOC_DECL -#else -#if __STDC__ -#ifndef __cplusplus -#include <stdlib.h> -#endif -#else -/* Just try to get by without declaring the routines. This will fail - * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int) - * or sizeof(void*) != sizeof(int). - */ -#endif -#endif - -/* Amount of stuff to slurp up with each read. */ -#ifndef YY_READ_BUF_SIZE -#define YY_READ_BUF_SIZE 8192 -#endif - -/* Copy whatever the last rule matched to the standard output. */ - -#ifndef ECHO -/* This used to be an fputs(), but since the string might contain NUL's, - * we now use fwrite(). - */ -#define ECHO (void) fwrite( yytext, yyleng, 1, yyout ) -#endif - -/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, - * is returned in "result". - */ -#ifndef YY_INPUT -#define YY_INPUT(buf,result,max_size) \ - if ( yy_current_buffer->yy_is_interactive ) \ - { \ - int c = '*', n; \ - for ( n = 0; n < max_size && \ - (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ - buf[n] = (char) c; \ - if ( c == '\n' ) \ - buf[n++] = (char) c; \ - if ( c == EOF && ferror( yyin ) ) \ - YY_FATAL_ERROR( "input in flex scanner failed" ); \ - result = n; \ - } \ - else if ( ((result = fread( buf, 1, max_size, yyin )) == 0) \ - && ferror( yyin ) ) \ - YY_FATAL_ERROR( "input in flex scanner failed" ); -#endif - -/* No semi-colon after return; correct usage is to write "yyterminate();" - - * we don't want an extra ';' after the "return" because that will cause - * some compilers to complain about unreachable statements. - */ -#ifndef yyterminate -#define yyterminate() return YY_NULL -#endif - -/* Number of entries by which start-condition stack grows. */ -#ifndef YY_START_STACK_INCR -#define YY_START_STACK_INCR 25 -#endif - -/* Report a fatal error. */ -#ifndef YY_FATAL_ERROR -#define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) -#endif - -/* Default declaration of generated scanner - a define so the user can - * easily add parameters. - */ -#ifndef YY_DECL -#define YY_DECL int yylex YY_PROTO(( void )) -#endif - -/* Code executed at the beginning of each rule, after yytext and yyleng - * have been set up. - */ -#ifndef YY_USER_ACTION -#define YY_USER_ACTION -#endif - -/* Code executed at the end of each rule. */ -#ifndef YY_BREAK -#define YY_BREAK break; -#endif - -#define YY_RULE_SETUP \ - YY_USER_ACTION - -YY_DECL - { - register yy_state_type yy_current_state; - register char *yy_cp, *yy_bp; - register int yy_act; - -#line 58 "ssl_expr_scan.l" - - - char caStr[MAX_STR_LEN]; - char *cpStr = NULL; - char caRegex[MAX_STR_LEN]; - char *cpRegex = NULL; - char cRegexDel = NUL; - - /* - * Whitespaces - */ -#line 668 "lex.ssl_expr_yy.c" - - if ( yy_init ) - { - yy_init = 0; - -#ifdef YY_USER_INIT - YY_USER_INIT; -#endif - - if ( ! yy_start ) - yy_start = 1; /* first start state */ - - if ( ! yyin ) - yyin = stdin; - - if ( ! yyout ) - yyout = stdout; - - if ( ! yy_current_buffer ) - yy_current_buffer = - yy_create_buffer( yyin, YY_BUF_SIZE ); - - yy_load_buffer_state(); - } - - while ( 1 ) /* loops until end-of-file is reached */ - { - yy_cp = yy_c_buf_p; - - /* Support of yytext. */ - *yy_cp = yy_hold_char; - - /* yy_bp points to the position in yy_ch_buf of the start of - * the current run. - */ - yy_bp = yy_cp; - - yy_current_state = yy_start; -yy_match: - do - { - register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; - if ( yy_accept[yy_current_state] ) - { - yy_last_accepting_state = yy_current_state; - yy_last_accepting_cpos = yy_cp; - } - while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) - { - yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 89 ) - yy_c = yy_meta[(unsigned int) yy_c]; - } - yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; - ++yy_cp; - } - while ( yy_current_state != 88 ); - yy_cp = yy_last_accepting_cpos; - yy_current_state = yy_last_accepting_state; - -yy_find_action: - yy_act = yy_accept[yy_current_state]; - - YY_DO_BEFORE_ACTION; - - -do_action: /* This label is used only to access EOF actions. */ - - - switch ( yy_act ) - { /* beginning of action switch */ - case 0: /* must back up */ - /* undo the effects of YY_DO_BEFORE_ACTION */ - *yy_cp = yy_hold_char; - yy_cp = yy_last_accepting_cpos; - yy_current_state = yy_last_accepting_state; - goto yy_find_action; - -case 1: -YY_RULE_SETUP -#line 69 "ssl_expr_scan.l" -{ - /* NOP */ -} - YY_BREAK -/* - * C-style strings ("...") - */ -case 2: -YY_RULE_SETUP -#line 76 "ssl_expr_scan.l" -{ - cpStr = caStr; - BEGIN(str); -} - YY_BREAK -case 3: -YY_RULE_SETUP -#line 80 "ssl_expr_scan.l" -{ - BEGIN(INITIAL); - *cpStr = NUL; - yylval.cpVal = apr_pstrdup(ssl_expr_info.pool, caStr); - return T_STRING; -} - YY_BREAK -case 4: -YY_RULE_SETUP -#line 86 "ssl_expr_scan.l" -{ - yyerror("Unterminated string"); -} - YY_BREAK -case 5: -YY_RULE_SETUP -#line 89 "ssl_expr_scan.l" -{ - int result; - - (void)sscanf(yytext+1, "%o", &result); - if (result > 0xff) - yyerror("Escape sequence out of bound"); - else - *cpStr++ = result; -} - YY_BREAK -case 6: -YY_RULE_SETUP -#line 98 "ssl_expr_scan.l" -{ - yyerror("Bad escape sequence"); -} - YY_BREAK -case 7: -YY_RULE_SETUP -#line 101 "ssl_expr_scan.l" -{ *cpStr++ = '\n'; } - YY_BREAK -case 8: -YY_RULE_SETUP -#line 102 "ssl_expr_scan.l" -{ *cpStr++ = '\r'; } - YY_BREAK -case 9: -YY_RULE_SETUP -#line 103 "ssl_expr_scan.l" -{ *cpStr++ = '\t'; } - YY_BREAK -case 10: -YY_RULE_SETUP -#line 104 "ssl_expr_scan.l" -{ *cpStr++ = '\b'; } - YY_BREAK -case 11: -YY_RULE_SETUP -#line 105 "ssl_expr_scan.l" -{ *cpStr++ = '\f'; } - YY_BREAK -case 12: -YY_RULE_SETUP -#line 106 "ssl_expr_scan.l" -{ - *cpStr++ = yytext[1]; -} - YY_BREAK -case 13: -YY_RULE_SETUP -#line 109 "ssl_expr_scan.l" -{ - char *cp = yytext; - while (*cp != NUL) - *cpStr++ = *cp++; -} - YY_BREAK -case 14: -YY_RULE_SETUP -#line 114 "ssl_expr_scan.l" -{ - *cpStr++ = yytext[1]; -} - YY_BREAK -/* - * Regular Expression - */ -case 15: -YY_RULE_SETUP -#line 121 "ssl_expr_scan.l" -{ - cRegexDel = yytext[1]; - cpRegex = caRegex; - BEGIN(regex); -} - YY_BREAK -case 16: -YY_RULE_SETUP -#line 126 "ssl_expr_scan.l" -{ - if (yytext[0] == cRegexDel) { - *cpRegex = NUL; - BEGIN(regex_flags); - } - else { - *cpRegex++ = yytext[0]; - } -} - YY_BREAK -case 17: -YY_RULE_SETUP -#line 135 "ssl_expr_scan.l" -{ - yylval.cpVal = apr_pstrdup(ssl_expr_info.pool, caRegex); - BEGIN(INITIAL); - return T_REGEX_I; -} - YY_BREAK -case 18: -YY_RULE_SETUP -#line 140 "ssl_expr_scan.l" -{ - yylval.cpVal = apr_pstrdup(ssl_expr_info.pool, caRegex); - yyless(0); - BEGIN(INITIAL); - return T_REGEX; -} - YY_BREAK -case YY_STATE_EOF(regex_flags): -#line 146 "ssl_expr_scan.l" -{ - yylval.cpVal = apr_pstrdup(ssl_expr_info.pool, caRegex); - BEGIN(INITIAL); - return T_REGEX; -} - YY_BREAK -/* - * Operators - */ -case 19: -YY_RULE_SETUP -#line 155 "ssl_expr_scan.l" -{ return T_OP_EQ; } - YY_BREAK -case 20: -YY_RULE_SETUP -#line 156 "ssl_expr_scan.l" -{ return T_OP_EQ; } - YY_BREAK -case 21: -YY_RULE_SETUP -#line 157 "ssl_expr_scan.l" -{ return T_OP_NE; } - YY_BREAK -case 22: -YY_RULE_SETUP -#line 158 "ssl_expr_scan.l" -{ return T_OP_NE; } - YY_BREAK -case 23: -YY_RULE_SETUP -#line 159 "ssl_expr_scan.l" -{ return T_OP_LT; } - YY_BREAK -case 24: -YY_RULE_SETUP -#line 160 "ssl_expr_scan.l" -{ return T_OP_LT; } - YY_BREAK -case 25: -YY_RULE_SETUP -#line 161 "ssl_expr_scan.l" -{ return T_OP_LE; } - YY_BREAK -case 26: -YY_RULE_SETUP -#line 162 "ssl_expr_scan.l" -{ return T_OP_LE; } - YY_BREAK -case 27: -YY_RULE_SETUP -#line 163 "ssl_expr_scan.l" -{ return T_OP_GT; } - YY_BREAK -case 28: -YY_RULE_SETUP -#line 164 "ssl_expr_scan.l" -{ return T_OP_GT; } - YY_BREAK -case 29: -YY_RULE_SETUP -#line 165 "ssl_expr_scan.l" -{ return T_OP_GE; } - YY_BREAK -case 30: -YY_RULE_SETUP -#line 166 "ssl_expr_scan.l" -{ return T_OP_GE; } - YY_BREAK -case 31: -YY_RULE_SETUP -#line 167 "ssl_expr_scan.l" -{ return T_OP_REG; } - YY_BREAK -case 32: -YY_RULE_SETUP -#line 168 "ssl_expr_scan.l" -{ return T_OP_NRE; } - YY_BREAK -case 33: -YY_RULE_SETUP -#line 169 "ssl_expr_scan.l" -{ return T_OP_AND; } - YY_BREAK -case 34: -YY_RULE_SETUP -#line 170 "ssl_expr_scan.l" -{ return T_OP_AND; } - YY_BREAK -case 35: -YY_RULE_SETUP -#line 171 "ssl_expr_scan.l" -{ return T_OP_OR; } - YY_BREAK -case 36: -YY_RULE_SETUP -#line 172 "ssl_expr_scan.l" -{ return T_OP_OR; } - YY_BREAK -case 37: -YY_RULE_SETUP -#line 173 "ssl_expr_scan.l" -{ return T_OP_NOT; } - YY_BREAK -case 38: -YY_RULE_SETUP -#line 174 "ssl_expr_scan.l" -{ return T_OP_NOT; } - YY_BREAK -case 39: -YY_RULE_SETUP -#line 175 "ssl_expr_scan.l" -{ return T_OP_IN; } - YY_BREAK -case 40: -YY_RULE_SETUP -#line 176 "ssl_expr_scan.l" -{ return T_OP_OID; } - YY_BREAK -/* - * Functions - */ -case 41: -YY_RULE_SETUP -#line 181 "ssl_expr_scan.l" -{ return T_FUNC_FILE; } - YY_BREAK -/* - * Specials - */ -case 42: -YY_RULE_SETUP -#line 186 "ssl_expr_scan.l" -{ return T_TRUE; } - YY_BREAK -case 43: -YY_RULE_SETUP -#line 187 "ssl_expr_scan.l" -{ return T_FALSE; } - YY_BREAK -/* - * Digits - */ -case 44: -YY_RULE_SETUP -#line 192 "ssl_expr_scan.l" -{ - yylval.cpVal = apr_pstrdup(ssl_expr_info.pool, yytext); - return T_DIGIT; -} - YY_BREAK -/* - * Identifiers - */ -case 45: -YY_RULE_SETUP -#line 200 "ssl_expr_scan.l" -{ - yylval.cpVal = apr_pstrdup(ssl_expr_info.pool, yytext); - return T_ID; -} - YY_BREAK -/* - * Anything else is returned as is... - */ -case 46: -YY_RULE_SETUP -#line 208 "ssl_expr_scan.l" -{ - return yytext[0]; -} - YY_BREAK -case 47: -YY_RULE_SETUP -#line 212 "ssl_expr_scan.l" -YY_FATAL_ERROR( "flex scanner jammed" ); - YY_BREAK -#line 1073 "lex.ssl_expr_yy.c" -case YY_STATE_EOF(INITIAL): -case YY_STATE_EOF(str): -case YY_STATE_EOF(regex): - yyterminate(); - - case YY_END_OF_BUFFER: - { - /* Amount of text matched not including the EOB char. */ - int yy_amount_of_matched_text = (int) (yy_cp - yytext_ptr) - 1; - - /* Undo the effects of YY_DO_BEFORE_ACTION. */ - *yy_cp = yy_hold_char; - YY_RESTORE_YY_MORE_OFFSET - - if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW ) - { - /* We're scanning a new file or input source. It's - * possible that this happened because the user - * just pointed yyin at a new source and called - * yylex(). If so, then we have to assure - * consistency between yy_current_buffer and our - * globals. Here is the right place to do so, because - * this is the first action (other than possibly a - * back-up) that will match for the new input source. - */ - yy_n_chars = yy_current_buffer->yy_n_chars; - yy_current_buffer->yy_input_file = yyin; - yy_current_buffer->yy_buffer_status = YY_BUFFER_NORMAL; - } - - /* Note that here we test for yy_c_buf_p "<=" to the position - * of the first EOB in the buffer, since yy_c_buf_p will - * already have been incremented past the NUL character - * (since all states make transitions on EOB to the - * end-of-buffer state). Contrast this with the test - * in input(). - */ - if ( yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars] ) - { /* This was really a NUL. */ - yy_state_type yy_next_state; - - yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text; - - yy_current_state = yy_get_previous_state(); - - /* Okay, we're now positioned to make the NUL - * transition. We couldn't have - * yy_get_previous_state() go ahead and do it - * for us because it doesn't know how to deal - * with the possibility of jamming (and we don't - * want to build jamming into it because then it - * will run more slowly). - */ - - yy_next_state = yy_try_NUL_trans( yy_current_state ); - - yy_bp = yytext_ptr + YY_MORE_ADJ; - - if ( yy_next_state ) - { - /* Consume the NUL. */ - yy_cp = ++yy_c_buf_p; - yy_current_state = yy_next_state; - goto yy_match; - } - - else - { - yy_cp = yy_last_accepting_cpos; - yy_current_state = yy_last_accepting_state; - goto yy_find_action; - } - } - - else switch ( yy_get_next_buffer() ) - { - case EOB_ACT_END_OF_FILE: - { - yy_did_buffer_switch_on_eof = 0; - - if ( yywrap() ) - { - /* Note: because we've taken care in - * yy_get_next_buffer() to have set up - * yytext, we can now set up - * yy_c_buf_p so that if some total - * hoser (like flex itself) wants to - * call the scanner after we return the - * YY_NULL, it'll still work - another - * YY_NULL will get returned. - */ - yy_c_buf_p = yytext_ptr + YY_MORE_ADJ; - - yy_act = YY_STATE_EOF(YY_START); - goto do_action; - } - - else - { - if ( ! yy_did_buffer_switch_on_eof ) - YY_NEW_FILE; - } - break; - } - - case EOB_ACT_CONTINUE_SCAN: - yy_c_buf_p = - yytext_ptr + yy_amount_of_matched_text; - - yy_current_state = yy_get_previous_state(); - - yy_cp = yy_c_buf_p; - yy_bp = yytext_ptr + YY_MORE_ADJ; - goto yy_match; - - case EOB_ACT_LAST_MATCH: - yy_c_buf_p = - &yy_current_buffer->yy_ch_buf[yy_n_chars]; - - yy_current_state = yy_get_previous_state(); - - yy_cp = yy_c_buf_p; - yy_bp = yytext_ptr + YY_MORE_ADJ; - goto yy_find_action; - } - break; - } - - default: - YY_FATAL_ERROR( - "fatal flex scanner internal error--no action found" ); - } /* end of action switch */ - } /* end of scanning one token */ - } /* end of yylex */ - - -/* yy_get_next_buffer - try to read in a new buffer - * - * Returns a code representing an action: - * EOB_ACT_LAST_MATCH - - * EOB_ACT_CONTINUE_SCAN - continue scanning from current position - * EOB_ACT_END_OF_FILE - end of file - */ - -static int yy_get_next_buffer() - { - register char *dest = yy_current_buffer->yy_ch_buf; - register char *source = yytext_ptr; - register int number_to_move, i; - int ret_val; - - if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] ) - YY_FATAL_ERROR( - "fatal flex scanner internal error--end of buffer missed" ); - - if ( yy_current_buffer->yy_fill_buffer == 0 ) - { /* Don't try to fill the buffer, so this is an EOF. */ - if ( yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1 ) - { - /* We matched a single character, the EOB, so - * treat this as a final EOF. - */ - return EOB_ACT_END_OF_FILE; - } - - else - { - /* We matched some text prior to the EOB, first - * process it. - */ - return EOB_ACT_LAST_MATCH; - } - } - - /* Try to read more data. */ - - /* First move last chars to start of buffer. */ - number_to_move = (int) (yy_c_buf_p - yytext_ptr) - 1; - - for ( i = 0; i < number_to_move; ++i ) - *(dest++) = *(source++); - - if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_EOF_PENDING ) - /* don't do the read, it's not guaranteed to return an EOF, - * just force an EOF - */ - yy_current_buffer->yy_n_chars = yy_n_chars = 0; - - else - { - int num_to_read = - yy_current_buffer->yy_buf_size - number_to_move - 1; - - while ( num_to_read <= 0 ) - { /* Not enough room in the buffer - grow it. */ -#ifdef YY_USES_REJECT - YY_FATAL_ERROR( -"input buffer overflow, can't enlarge buffer because scanner uses REJECT" ); -#else - - /* just a shorter name for the current buffer */ - YY_BUFFER_STATE b = yy_current_buffer; - - int yy_c_buf_p_offset = - (int) (yy_c_buf_p - b->yy_ch_buf); - - if ( b->yy_is_our_buffer ) - { - int new_size = b->yy_buf_size * 2; - - if ( new_size <= 0 ) - b->yy_buf_size += b->yy_buf_size / 8; - else - b->yy_buf_size *= 2; - - b->yy_ch_buf = (char *) - /* Include room in for 2 EOB chars. */ - yy_flex_realloc( (void *) b->yy_ch_buf, - b->yy_buf_size + 2 ); - } - else - /* Can't grow it, we don't own it. */ - b->yy_ch_buf = 0; - - if ( ! b->yy_ch_buf ) - YY_FATAL_ERROR( - "fatal error - scanner input buffer overflow" ); - - yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset]; - - num_to_read = yy_current_buffer->yy_buf_size - - number_to_move - 1; -#endif - } - - if ( num_to_read > YY_READ_BUF_SIZE ) - num_to_read = YY_READ_BUF_SIZE; - - /* Read in more data. */ - YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]), - yy_n_chars, num_to_read ); - - yy_current_buffer->yy_n_chars = yy_n_chars; - } - - if ( yy_n_chars == 0 ) - { - if ( number_to_move == YY_MORE_ADJ ) - { - ret_val = EOB_ACT_END_OF_FILE; - yyrestart( yyin ); - } - - else - { - ret_val = EOB_ACT_LAST_MATCH; - yy_current_buffer->yy_buffer_status = - YY_BUFFER_EOF_PENDING; - } - } - - else - ret_val = EOB_ACT_CONTINUE_SCAN; - - yy_n_chars += number_to_move; - yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR; - yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR; - - yytext_ptr = &yy_current_buffer->yy_ch_buf[0]; - - return ret_val; - } - - -/* yy_get_previous_state - get the state just before the EOB char was reached */ - -static yy_state_type yy_get_previous_state() - { - register yy_state_type yy_current_state; - register char *yy_cp; - - yy_current_state = yy_start; - - for ( yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp ) - { - register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); - if ( yy_accept[yy_current_state] ) - { - yy_last_accepting_state = yy_current_state; - yy_last_accepting_cpos = yy_cp; - } - while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) - { - yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 89 ) - yy_c = yy_meta[(unsigned int) yy_c]; - } - yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; - } - - return yy_current_state; - } - - -/* yy_try_NUL_trans - try to make a transition on the NUL character - * - * synopsis - * next_state = yy_try_NUL_trans( current_state ); - */ - -#ifdef YY_USE_PROTOS -static yy_state_type yy_try_NUL_trans( yy_state_type yy_current_state ) -#else -static yy_state_type yy_try_NUL_trans( yy_current_state ) -yy_state_type yy_current_state; -#endif - { - register int yy_is_jam; - register char *yy_cp = yy_c_buf_p; - - register YY_CHAR yy_c = 1; - if ( yy_accept[yy_current_state] ) - { - yy_last_accepting_state = yy_current_state; - yy_last_accepting_cpos = yy_cp; - } - while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) - { - yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 89 ) - yy_c = yy_meta[(unsigned int) yy_c]; - } - yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; - yy_is_jam = (yy_current_state == 88); - - return yy_is_jam ? 0 : yy_current_state; - } - - -#ifndef YY_NO_UNPUT -#ifdef YY_USE_PROTOS -static void yyunput( int c, register char *yy_bp ) -#else -static void yyunput( c, yy_bp ) -int c; -register char *yy_bp; -#endif - { - register char *yy_cp = yy_c_buf_p; - - /* undo effects of setting up yytext */ - *yy_cp = yy_hold_char; - - if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) - { /* need to shift things up to make room */ - /* +2 for EOB chars. */ - register int number_to_move = yy_n_chars + 2; - register char *dest = &yy_current_buffer->yy_ch_buf[ - yy_current_buffer->yy_buf_size + 2]; - register char *source = - &yy_current_buffer->yy_ch_buf[number_to_move]; - - while ( source > yy_current_buffer->yy_ch_buf ) - *--dest = *--source; - - yy_cp += (int) (dest - source); - yy_bp += (int) (dest - source); - yy_current_buffer->yy_n_chars = - yy_n_chars = yy_current_buffer->yy_buf_size; - - if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) - YY_FATAL_ERROR( "flex scanner push-back overflow" ); - } - - *--yy_cp = (char) c; - - - yytext_ptr = yy_bp; - yy_hold_char = *yy_cp; - yy_c_buf_p = yy_cp; - } -#endif /* ifndef YY_NO_UNPUT */ - - -#ifdef __cplusplus -static int yyinput() -#else -static int input() -#endif - { - int c; - - *yy_c_buf_p = yy_hold_char; - - if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR ) - { - /* yy_c_buf_p now points to the character we want to return. - * If this occurs *before* the EOB characters, then it's a - * valid NUL; if not, then we've hit the end of the buffer. - */ - if ( yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars] ) - /* This was really a NUL. */ - *yy_c_buf_p = '\0'; - - else - { /* need more input */ - int offset = yy_c_buf_p - yytext_ptr; - ++yy_c_buf_p; - - switch ( yy_get_next_buffer() ) - { - case EOB_ACT_LAST_MATCH: - /* This happens because yy_g_n_b() - * sees that we've accumulated a - * token and flags that we need to - * try matching the token before - * proceeding. But for input(), - * there's no matching to consider. - * So convert the EOB_ACT_LAST_MATCH - * to EOB_ACT_END_OF_FILE. - */ - - /* Reset buffer status. */ - yyrestart( yyin ); - - /* fall through */ - - case EOB_ACT_END_OF_FILE: - { - if ( yywrap() ) - return EOF; - - if ( ! yy_did_buffer_switch_on_eof ) - YY_NEW_FILE; -#ifdef __cplusplus - return yyinput(); -#else - return input(); -#endif - } - - case EOB_ACT_CONTINUE_SCAN: - yy_c_buf_p = yytext_ptr + offset; - break; - } - } - } - - c = *(unsigned char *) yy_c_buf_p; /* cast for 8-bit char's */ - *yy_c_buf_p = '\0'; /* preserve yytext */ - yy_hold_char = *++yy_c_buf_p; - - - return c; - } - - -#ifdef YY_USE_PROTOS -void yyrestart( FILE *input_file ) -#else -void yyrestart( input_file ) -FILE *input_file; -#endif - { - if ( ! yy_current_buffer ) - yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); - - yy_init_buffer( yy_current_buffer, input_file ); - yy_load_buffer_state(); - } - - -#ifdef YY_USE_PROTOS -void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer ) -#else -void yy_switch_to_buffer( new_buffer ) -YY_BUFFER_STATE new_buffer; -#endif - { - if ( yy_current_buffer == new_buffer ) - return; - - if ( yy_current_buffer ) - { - /* Flush out information for old buffer. */ - *yy_c_buf_p = yy_hold_char; - yy_current_buffer->yy_buf_pos = yy_c_buf_p; - yy_current_buffer->yy_n_chars = yy_n_chars; - } - - yy_current_buffer = new_buffer; - yy_load_buffer_state(); - - /* We don't actually know whether we did this switch during - * EOF (yywrap()) processing, but the only time this flag - * is looked at is after yywrap() is called, so it's safe - * to go ahead and always set it. - */ - yy_did_buffer_switch_on_eof = 1; - } - - -#ifdef YY_USE_PROTOS -void yy_load_buffer_state( void ) -#else -void yy_load_buffer_state() -#endif - { - yy_n_chars = yy_current_buffer->yy_n_chars; - yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos; - yyin = yy_current_buffer->yy_input_file; - yy_hold_char = *yy_c_buf_p; - } - - -#ifdef YY_USE_PROTOS -YY_BUFFER_STATE yy_create_buffer( FILE *file, int size ) -#else -YY_BUFFER_STATE yy_create_buffer( file, size ) -FILE *file; -int size; -#endif - { - YY_BUFFER_STATE b; - - b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); - if ( ! b ) - YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); - - b->yy_buf_size = size; - - /* yy_ch_buf has to be 2 characters longer than the size given because - * we need to put in 2 end-of-buffer characters. - */ - b->yy_ch_buf = (char *) yy_flex_alloc( b->yy_buf_size + 2 ); - if ( ! b->yy_ch_buf ) - YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); - - b->yy_is_our_buffer = 1; - - yy_init_buffer( b, file ); - - return b; - } - - -#ifdef YY_USE_PROTOS -void yy_delete_buffer( YY_BUFFER_STATE b ) -#else -void yy_delete_buffer( b ) -YY_BUFFER_STATE b; -#endif - { - if ( ! b ) - return; - - if ( b == yy_current_buffer ) - yy_current_buffer = (YY_BUFFER_STATE) 0; - - if ( b->yy_is_our_buffer ) - yy_flex_free( (void *) b->yy_ch_buf ); - - yy_flex_free( (void *) b ); - } - - -#ifndef YY_ALWAYS_INTERACTIVE -#ifndef YY_NEVER_INTERACTIVE -extern int isatty YY_PROTO(( int )); -#endif -#endif - -#ifdef YY_USE_PROTOS -void yy_init_buffer( YY_BUFFER_STATE b, FILE *file ) -#else -void yy_init_buffer( b, file ) -YY_BUFFER_STATE b; -FILE *file; -#endif - - - { - yy_flush_buffer( b ); - - b->yy_input_file = file; - b->yy_fill_buffer = 1; - -#if YY_ALWAYS_INTERACTIVE - b->yy_is_interactive = 1; -#else -#if YY_NEVER_INTERACTIVE - b->yy_is_interactive = 0; -#else - b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; -#endif -#endif - } - - -#ifdef YY_USE_PROTOS -void yy_flush_buffer( YY_BUFFER_STATE b ) -#else -void yy_flush_buffer( b ) -YY_BUFFER_STATE b; -#endif - - { - if ( ! b ) - return; - - b->yy_n_chars = 0; - - /* We always need two end-of-buffer characters. The first causes - * a transition to the end-of-buffer state. The second causes - * a jam in that state. - */ - b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; - b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; - - b->yy_buf_pos = &b->yy_ch_buf[0]; - - b->yy_at_bol = 1; - b->yy_buffer_status = YY_BUFFER_NEW; - - if ( b == yy_current_buffer ) - yy_load_buffer_state(); - } - - -#ifndef YY_NO_SCAN_BUFFER -#ifdef YY_USE_PROTOS -YY_BUFFER_STATE yy_scan_buffer( char *base, yy_size_t size ) -#else -YY_BUFFER_STATE yy_scan_buffer( base, size ) -char *base; -yy_size_t size; -#endif - { - YY_BUFFER_STATE b; - - if ( size < 2 || - base[size-2] != YY_END_OF_BUFFER_CHAR || - base[size-1] != YY_END_OF_BUFFER_CHAR ) - /* They forgot to leave room for the EOB's. */ - return 0; - - b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); - if ( ! b ) - YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); - - b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ - b->yy_buf_pos = b->yy_ch_buf = base; - b->yy_is_our_buffer = 0; - b->yy_input_file = 0; - b->yy_n_chars = b->yy_buf_size; - b->yy_is_interactive = 0; - b->yy_at_bol = 1; - b->yy_fill_buffer = 0; - b->yy_buffer_status = YY_BUFFER_NEW; - - yy_switch_to_buffer( b ); - - return b; - } -#endif - - -#ifndef YY_NO_SCAN_STRING -#ifdef YY_USE_PROTOS -YY_BUFFER_STATE yy_scan_string( yyconst char *yy_str ) -#else -YY_BUFFER_STATE yy_scan_string( yy_str ) -yyconst char *yy_str; -#endif - { - int len; - for ( len = 0; yy_str[len]; ++len ) - ; - - return yy_scan_bytes( yy_str, len ); - } -#endif - - -#ifndef YY_NO_SCAN_BYTES -#ifdef YY_USE_PROTOS -YY_BUFFER_STATE yy_scan_bytes( yyconst char *bytes, int len ) -#else -YY_BUFFER_STATE yy_scan_bytes( bytes, len ) -yyconst char *bytes; -int len; -#endif - { - YY_BUFFER_STATE b; - char *buf; - yy_size_t n; - int i; - - /* Get memory for full buffer, including space for trailing EOB's. */ - n = len + 2; - buf = (char *) yy_flex_alloc( n ); - if ( ! buf ) - YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); - - for ( i = 0; i < len; ++i ) - buf[i] = bytes[i]; - - buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR; - - b = yy_scan_buffer( buf, n ); - if ( ! b ) - YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); - - /* It's okay to grow etc. this buffer, and we should throw it - * away when we're done. - */ - b->yy_is_our_buffer = 1; - - return b; - } -#endif - - -#ifndef YY_NO_PUSH_STATE -#ifdef YY_USE_PROTOS -static void yy_push_state( int new_state ) -#else -static void yy_push_state( new_state ) -int new_state; -#endif - { - if ( yy_start_stack_ptr >= yy_start_stack_depth ) - { - yy_size_t new_size; - - yy_start_stack_depth += YY_START_STACK_INCR; - new_size = yy_start_stack_depth * sizeof( int ); - - if ( ! yy_start_stack ) - yy_start_stack = (int *) yy_flex_alloc( new_size ); - - else - yy_start_stack = (int *) yy_flex_realloc( - (void *) yy_start_stack, new_size ); - - if ( ! yy_start_stack ) - YY_FATAL_ERROR( - "out of memory expanding start-condition stack" ); - } - - yy_start_stack[yy_start_stack_ptr++] = YY_START; - - BEGIN(new_state); - } -#endif - - -#ifndef YY_NO_POP_STATE -static void yy_pop_state() - { - if ( --yy_start_stack_ptr < 0 ) - YY_FATAL_ERROR( "start-condition stack underflow" ); - - BEGIN(yy_start_stack[yy_start_stack_ptr]); - } -#endif - - -#ifndef YY_NO_TOP_STATE -static int yy_top_state() - { - return yy_start_stack[yy_start_stack_ptr - 1]; - } -#endif - -#ifndef YY_EXIT_FAILURE -#define YY_EXIT_FAILURE 2 -#endif - -#ifdef YY_USE_PROTOS -static void yy_fatal_error( yyconst char msg[] ) -#else -static void yy_fatal_error( msg ) -char msg[]; -#endif - { - (void) fprintf( stderr, "%s\n", msg ); - exit( YY_EXIT_FAILURE ); - } - - - -/* Redefine yyless() so it works in section 3 code. */ - -#undef yyless -#define yyless(n) \ - do \ - { \ - /* Undo effects of setting up yytext. */ \ - yytext[yyleng] = yy_hold_char; \ - yy_c_buf_p = yytext + n; \ - yy_hold_char = *yy_c_buf_p; \ - *yy_c_buf_p = '\0'; \ - yyleng = n; \ - } \ - while ( 0 ) - - -/* Internal utility routines. */ - -#ifndef yytext_ptr -#ifdef YY_USE_PROTOS -static void yy_flex_strncpy( char *s1, yyconst char *s2, int n ) -#else -static void yy_flex_strncpy( s1, s2, n ) -char *s1; -yyconst char *s2; -int n; -#endif - { - register int i; - for ( i = 0; i < n; ++i ) - s1[i] = s2[i]; - } -#endif - -#ifdef YY_NEED_STRLEN -#ifdef YY_USE_PROTOS -static int yy_flex_strlen( yyconst char *s ) -#else -static int yy_flex_strlen( s ) -yyconst char *s; -#endif - { - register int n; - for ( n = 0; s[n]; ++n ) - ; - - return n; - } -#endif - - -#ifdef YY_USE_PROTOS -static void *yy_flex_alloc( yy_size_t size ) -#else -static void *yy_flex_alloc( size ) -yy_size_t size; -#endif - { - return (void *) malloc( size ); - } - -#ifdef YY_USE_PROTOS -static void *yy_flex_realloc( void *ptr, yy_size_t size ) -#else -static void *yy_flex_realloc( ptr, size ) -void *ptr; -yy_size_t size; -#endif - { - /* The cast to (char *) in the following accommodates both - * implementations that use char* generic pointers, and those - * that use void* generic pointers. It works with the latter - * because both ANSI C and C++ allow castless assignment from - * any pointer type to void*, and deal with argument conversions - * as though doing an assignment. - */ - return (void *) realloc( (char *) ptr, size ); - } - -#ifdef YY_USE_PROTOS -static void yy_flex_free( void *ptr ) -#else -static void yy_flex_free( ptr ) -void *ptr; -#endif - { - free( ptr ); - } - -#if YY_MAIN -int main() - { - yylex(); - return 0; - } -#endif -#line 212 "ssl_expr_scan.l" - - -int yyinput(char *buf, int max_size) -{ - int n; - - if ((n = MIN(max_size, ssl_expr_info.inputbuf - + ssl_expr_info.inputlen - - ssl_expr_info.inputptr)) <= 0) - return YY_NULL; - memcpy(buf, ssl_expr_info.inputptr, n); - ssl_expr_info.inputptr += n; - return n; -} - diff --git a/modules/ssl/ssl_expr_scan.l b/modules/ssl/ssl_expr_scan.l deleted file mode 100644 index 6c720523..00000000 --- a/modules/ssl/ssl_expr_scan.l +++ /dev/null @@ -1,226 +0,0 @@ -/* Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* _ _ - * _ __ ___ ___ __| | ___ ___| | - * | '_ ` _ \ / _ \ / _` | / __/ __| | - * | | | | | | (_) | (_| | \__ \__ \ | mod_ssl - Apache Interface to OpenSSL - * |_| |_| |_|\___/ \__,_|___|___/___/_| http://www.modssl.org/ - * |_____| - * ssl_expr_scan.l - * Expression Scanner - */ - /* ``Killing for peace is - like fucking for virginity.'' - -- Unknown */ - -/* _________________________________________________________________ -** -** Expression Scanner -** _________________________________________________________________ -*/ - -%{ -#include "ssl_private.h" - -#include "ssl_expr_parse.h" - -#define YY_NO_UNPUT 1 -int yyinput(char *buf, int max_size); - -#undef YY_INPUT -#define YY_INPUT(buf,result,max_size) \ - (result = yyinput(buf, max_size)) - -#define MAX_STR_LEN 2048 -%} - -%pointer -/* %option stack */ -%option never-interactive -%option noyywrap -%x str -%x regex regex_flags - -%% - - char caStr[MAX_STR_LEN]; - char *cpStr = NULL; - char caRegex[MAX_STR_LEN]; - char *cpRegex = NULL; - char cRegexDel = NUL; - - /* - * Whitespaces - */ -[ \t\n]+ { - /* NOP */ -} - - /* - * C-style strings ("...") - */ -\" { - cpStr = caStr; - BEGIN(str); -} -<str>\" { - BEGIN(INITIAL); - *cpStr = NUL; - yylval.cpVal = apr_pstrdup(ssl_expr_info.pool, caStr); - return T_STRING; -} -<str>\n { - yyerror("Unterminated string"); -} -<str>\\[0-7]{1,3} { - int result; - - (void)sscanf(yytext+1, "%o", &result); - if (result > 0xff) - yyerror("Escape sequence out of bound"); - else - *cpStr++ = result; -} -<str>\\[0-9]+ { - yyerror("Bad escape sequence"); -} -<str>\\n { *cpStr++ = '\n'; } -<str>\\r { *cpStr++ = '\r'; } -<str>\\t { *cpStr++ = '\t'; } -<str>\\b { *cpStr++ = '\b'; } -<str>\\f { *cpStr++ = '\f'; } -<str>\\(.|\n) { - *cpStr++ = yytext[1]; -} -<str>[^\\\n\"]+ { - char *cp = yytext; - while (*cp != NUL) - *cpStr++ = *cp++; -} -<str>. { - *cpStr++ = yytext[1]; -} - - /* - * Regular Expression - */ -"m". { - cRegexDel = yytext[1]; - cpRegex = caRegex; - BEGIN(regex); -} -<regex>.|\n { - if (yytext[0] == cRegexDel) { - *cpRegex = NUL; - BEGIN(regex_flags); - } - else { - *cpRegex++ = yytext[0]; - } -} -<regex_flags>i { - yylval.cpVal = apr_pstrdup(ssl_expr_info.pool, caRegex); - BEGIN(INITIAL); - return T_REGEX_I; -} -<regex_flags>.|\n { - yylval.cpVal = apr_pstrdup(ssl_expr_info.pool, caRegex); - yyless(0); - BEGIN(INITIAL); - return T_REGEX; -} -<regex_flags><<EOF>> { - yylval.cpVal = apr_pstrdup(ssl_expr_info.pool, caRegex); - BEGIN(INITIAL); - return T_REGEX; -} - - /* - * Operators - */ -"eq" { return T_OP_EQ; } -"==" { return T_OP_EQ; } -"ne" { return T_OP_NE; } -"!=" { return T_OP_NE; } -"lt" { return T_OP_LT; } -"<" { return T_OP_LT; } -"le" { return T_OP_LE; } -"<=" { return T_OP_LE; } -"gt" { return T_OP_GT; } -">" { return T_OP_GT; } -"ge" { return T_OP_GE; } -">=" { return T_OP_GE; } -"=~" { return T_OP_REG; } -"!~" { return T_OP_NRE; } -"and" { return T_OP_AND; } -"&&" { return T_OP_AND; } -"or" { return T_OP_OR; } -"||" { return T_OP_OR; } -"not" { return T_OP_NOT; } -"!" { return T_OP_NOT; } -"in" { return T_OP_IN; } -[Oo][Ii][Dd] { return T_OP_OID; } - - /* - * Functions - */ -"file" { return T_FUNC_FILE; } - - /* - * Specials - */ -"true" { return T_TRUE; } -"false" { return T_FALSE; } - - /* - * Digits - */ -[0-9]+ { - yylval.cpVal = apr_pstrdup(ssl_expr_info.pool, yytext); - return T_DIGIT; -} - - /* - * Identifiers - */ -[a-zA-Z][a-zA-Z0-9_:-]* { - yylval.cpVal = apr_pstrdup(ssl_expr_info.pool, yytext); - return T_ID; -} - - /* - * Anything else is returned as is... - */ -.|\n { - return yytext[0]; -} - -%% - -int yyinput(char *buf, int max_size) -{ - int n; - - if ((n = MIN(max_size, ssl_expr_info.inputbuf - + ssl_expr_info.inputlen - - ssl_expr_info.inputptr)) <= 0) - return YY_NULL; - memcpy(buf, ssl_expr_info.inputptr, n); - ssl_expr_info.inputptr += n; - return n; -} - diff --git a/modules/ssl/ssl_private.h b/modules/ssl/ssl_private.h index 15deb8f1..0ed6e254 100644 --- a/modules/ssl/ssl_private.h +++ b/modules/ssl/ssl_private.h @@ -18,7 +18,7 @@ #define SSL_PRIVATE_H /** - * @file ssl_private.h + * @file ssl_private.h * @brief Internal interfaces private to mod_ssl. * * @defgroup MOD_SSL_PRIVATE Private @@ -39,47 +39,146 @@ #include "util_script.h" #include "util_filter.h" #include "util_ebcdic.h" -#include "mpm.h" +#include "util_mutex.h" #include "apr.h" #include "apr_strings.h" #define APR_WANT_STRFUNC +#define APR_WANT_MEMFUNC #include "apr_want.h" #include "apr_tables.h" #include "apr_lib.h" #include "apr_fnmatch.h" #include "apr_strings.h" -#include "apr_dbm.h" -#include "apr_rmm.h" -#include "apr_shm.h" #include "apr_global_mutex.h" #include "apr_optional.h" +#include "ap_socache.h" +#include "mod_auth.h" -#define MOD_SSL_VERSION AP_SERVER_BASEREVISION - -/** mod_ssl headers */ -#include "ssl_toolkit_compat.h" -#include "ssl_expr.h" -#include "ssl_util_ssl.h" - -/** The #ifdef macros are only defined AFTER including the above +/* The #ifdef macros are only defined AFTER including the above * therefore we cannot include these system files at the top :-( */ +#ifdef APR_HAVE_STDLIB_H +#include <stdlib.h> +#endif #if APR_HAVE_SYS_TIME_H #include <sys/time.h> #endif #if APR_HAVE_UNISTD_H -#include <unistd.h> /** needed for STDIN_FILENO et.al., at least on FreeBSD */ +#include <unistd.h> /* needed for STDIN_FILENO et.al., at least on FreeBSD */ #endif -/** - * Provide reasonable default for some defines - */ #ifndef FALSE -#define FALSE (0) +#define FALSE 0 #endif + #ifndef TRUE -#define TRUE (!FALSE) +#define TRUE !FALSE +#endif + +#ifndef BOOL +#define BOOL unsigned int +#endif + +#include "ap_expr.h" + +/* OpenSSL headers */ +#include <openssl/ssl.h> +#include <openssl/err.h> +#include <openssl/x509.h> +#include <openssl/pem.h> +#include <openssl/crypto.h> +#include <openssl/evp.h> +#include <openssl/rand.h> +#include <openssl/x509v3.h> +#include <openssl/x509_vfy.h> +#include <openssl/ocsp.h> + +/* Avoid tripping over an engine build installed globally and detected + * when the user points at an explicit non-engine flavor of OpenSSL + */ +#if defined(HAVE_OPENSSL_ENGINE_H) && defined(HAVE_ENGINE_INIT) +#include <openssl/engine.h> #endif + +#if (OPENSSL_VERSION_NUMBER < 0x0090700f) +#error mod_ssl requires OpenSSL 0.9.7 or later +#endif + +/* ...shifting sands of OpenSSL... */ +#if (OPENSSL_VERSION_NUMBER >= 0x0090707f) +#define MODSSL_D2I_SSL_SESSION_CONST const +#else +#define MODSSL_D2I_SSL_SESSION_CONST +#endif + +#if (OPENSSL_VERSION_NUMBER >= 0x00908000) +#define HAVE_GENERATE_EX +#define MODSSL_D2I_ASN1_type_bytes_CONST const +#define MODSSL_D2I_PrivateKey_CONST const +#define MODSSL_D2I_X509_CONST const +#else +#define MODSSL_D2I_ASN1_type_bytes_CONST +#define MODSSL_D2I_PrivateKey_CONST +#define MODSSL_D2I_X509_CONST +#endif + +#if OPENSSL_VERSION_NUMBER >= 0x00908080 && !defined(OPENSSL_NO_OCSP) \ + && !defined(OPENSSL_NO_TLSEXT) +#define HAVE_OCSP_STAPLING +#if (OPENSSL_VERSION_NUMBER < 0x10000000) +#define sk_OPENSSL_STRING_pop sk_pop +#endif +#endif + +#if (OPENSSL_VERSION_NUMBER >= 0x009080a0) && defined(OPENSSL_FIPS) +#define HAVE_FIPS +#endif + +#if (OPENSSL_VERSION_NUMBER >= 0x10000000) +#define MODSSL_SSL_CIPHER_CONST const +#define MODSSL_SSL_METHOD_CONST const +#else +#define MODSSL_SSL_CIPHER_CONST +#define MODSSL_SSL_METHOD_CONST +/* ECC support came along in OpenSSL 1.0.0 */ +#define OPENSSL_NO_EC +#endif + +#ifndef PEM_F_DEF_CALLBACK +#ifdef PEM_F_PEM_DEF_CALLBACK +/** In OpenSSL 0.9.8 PEM_F_DEF_CALLBACK was renamed */ +#define PEM_F_DEF_CALLBACK PEM_F_PEM_DEF_CALLBACK +#endif +#endif + +#ifndef OPENSSL_NO_TLSEXT +#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME +#define OPENSSL_NO_TLSEXT +#endif +#endif + +#ifndef OPENSSL_NO_TLSEXT +#ifdef SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB +#define HAVE_TLS_SESSION_TICKETS +#define TLSEXT_TICKET_KEY_LEN 48 +#ifndef tlsext_tick_md +#ifdef OPENSSL_NO_SHA256 +#define tlsext_tick_md EVP_sha1 +#else +#define tlsext_tick_md EVP_sha256 +#endif +#endif +#endif +#endif + +/* mod_ssl headers */ +#include "ssl_util_ssl.h" + +APLOG_USE_MODULE(ssl); + +/* + * Provide reasonable default for some defines + */ #ifndef PFALSE #define PFALSE ((void *)FALSE) #endif @@ -100,9 +199,6 @@ /** * Provide reasonable defines for some types */ -#ifndef BOOL -#define BOOL unsigned int -#endif #ifndef UCHAR #define UCHAR unsigned char #endif @@ -149,27 +245,14 @@ ap_set_module_config(c->conn_config, &ssl_module, val) #define DEFAULT_RENEG_BUFFER_SIZE (128 * 1024) #endif -/** - * Support for MM library - */ -#define SSL_MM_FILE_MODE ( APR_UREAD | APR_UWRITE | APR_GREAD | APR_WREAD ) - -/** - * Support for DBM library - */ -#define SSL_DBM_FILE_MODE ( APR_UREAD | APR_UWRITE | APR_GREAD | APR_WREAD ) - -#if !defined(SSL_DBM_FILE_SUFFIX_DIR) && !defined(SSL_DBM_FILE_SUFFIX_PAG) -#if defined(DBM_SUFFIX) -#define SSL_DBM_FILE_SUFFIX_DIR DBM_SUFFIX -#define SSL_DBM_FILE_SUFFIX_PAG DBM_SUFFIX -#elif defined(__FreeBSD__) || (defined(DB_LOCK) && defined(DB_SHMEM)) -#define SSL_DBM_FILE_SUFFIX_DIR ".db" -#define SSL_DBM_FILE_SUFFIX_PAG ".db" -#else -#define SSL_DBM_FILE_SUFFIX_DIR ".dir" -#define SSL_DBM_FILE_SUFFIX_PAG ".pag" +/* Default for OCSP response validity */ +#ifndef DEFAULT_OCSP_MAX_SKEW +#define DEFAULT_OCSP_MAX_SKEW (60 * 5) #endif + +/* Default timeout for OCSP queries */ +#ifndef DEFAULT_OCSP_TIMEOUT +#define DEFAULT_OCSP_TIMEOUT 10 #endif /** @@ -181,11 +264,21 @@ typedef int ssl_algo_t; #define SSL_ALGO_UNKNOWN (0) #define SSL_ALGO_RSA (1<<0) #define SSL_ALGO_DSA (1<<1) +#ifndef OPENSSL_NO_EC +#define SSL_ALGO_ECC (1<<2) +#define SSL_ALGO_ALL (SSL_ALGO_RSA|SSL_ALGO_DSA|SSL_ALGO_ECC) +#else #define SSL_ALGO_ALL (SSL_ALGO_RSA|SSL_ALGO_DSA) +#endif #define SSL_AIDX_RSA (0) #define SSL_AIDX_DSA (1) +#ifndef OPENSSL_NO_EC +#define SSL_AIDX_ECC (2) +#define SSL_AIDX_MAX (3) +#else #define SSL_AIDX_MAX (2) +#endif /** @@ -208,7 +301,7 @@ typedef int ssl_algo_t; #define SSL_OPT_FAKEBASICAUTH (1<<4) #define SSL_OPT_STRICTREQUIRE (1<<5) #define SSL_OPT_OPTRENEGOTIATE (1<<6) -#define SSL_OPT_ALL (SSL_OPT_STDENVVARS|SSL_OPT_EXPORTCERTDATA|SSL_OPT_FAKEBASICAUTH|SSL_OPT_STRICTREQUIRE|SSL_OPT_OPTRENEGOTIATE) +#define SSL_OPT_LEGACYDNFORMAT (1<<7) typedef int ssl_opt_t; /** @@ -218,11 +311,7 @@ typedef int ssl_opt_t; #define SSL_PROTOCOL_SSLV2 (1<<0) #define SSL_PROTOCOL_SSLV3 (1<<1) #define SSL_PROTOCOL_TLSV1 (1<<2) -#ifndef OPENSSL_NO_SSL2 -#define SSL_PROTOCOL_ALL (SSL_PROTOCOL_SSLV2|SSL_PROTOCOL_SSLV3|SSL_PROTOCOL_TLSV1) -#else #define SSL_PROTOCOL_ALL (SSL_PROTOCOL_SSLV3|SSL_PROTOCOL_TLSV1) -#endif typedef int ssl_proto_t; /** @@ -239,10 +328,6 @@ typedef enum { #define SSL_VERIFY_PEER_STRICT \ (SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT) -#ifndef X509_V_ERR_CERT_UNTRUSTED -#define X509_V_ERR_CERT_UNTRUSTED 27 -#endif - #define ssl_verify_error_is_optional(errnum) \ ((errnum == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT) \ || (errnum == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN) \ @@ -251,13 +336,23 @@ typedef enum { || (errnum == X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE)) /** + * CRL checking modes + */ +typedef enum { + SSL_CRLCHECK_UNSET = UNSET, + SSL_CRLCHECK_NONE = 0, + SSL_CRLCHECK_LEAF = 1, + SSL_CRLCHECK_CHAIN = 2 +} ssl_crlcheck_t; + +/** * Define the SSL pass phrase dialog types */ typedef enum { SSL_PPTYPE_UNSET = UNSET, SSL_PPTYPE_BUILTIN = 0, SSL_PPTYPE_FILTER = 1, - SSL_PPTYPE_PIPE = 2 + SSL_PPTYPE_PIPE = 2 } ssl_pphrase_t; /** @@ -270,42 +365,21 @@ typedef enum { typedef unsigned int ssl_pathcheck_t; /** - * Define the SSL session cache modes and structures - */ -typedef enum { - SSL_SCMODE_UNSET = UNSET, - SSL_SCMODE_NONE = 0, - SSL_SCMODE_DBM = 1, - SSL_SCMODE_SHMCB = 3, - SSL_SCMODE_DC = 4, - SSL_SCMODE_NONE_NOT_NULL = 5 -} ssl_scmode_t; - -/** - * Define the SSL mutex modes - */ -typedef enum { - SSL_MUTEXMODE_UNSET = UNSET, - SSL_MUTEXMODE_NONE = 0, - SSL_MUTEXMODE_USED = 1 -} ssl_mutexmode_t; - -/** * Define the SSL enabled state */ typedef enum { SSL_ENABLED_UNSET = UNSET, SSL_ENABLED_FALSE = 0, SSL_ENABLED_TRUE = 1, - SSL_ENABLED_OPTIONAL = 3 + SSL_ENABLED_OPTIONAL = 3 } ssl_enabled_t; /** * Define the SSL requirement structure */ typedef struct { - char *cpExpr; - ssl_expr *mpExpr; + char *cpExpr; + ap_expr_info_t *mpExpr; } ssl_require_t; /** @@ -364,7 +438,7 @@ typedef struct { /* Track the handshake/renegotiation state for the connection so * that all client-initiated renegotiations can be rejected, as a * partial fix for CVE-2009-3555. */ - enum { + enum { RENEG_INIT = 0, /* Before initial handshake */ RENEG_REJECT, /* After initial handshake; any client-initiated * renegotiation should be rejected */ @@ -373,45 +447,93 @@ typedef struct { RENEG_ABORT /* Renegotiation initiated by client, abort the * connection */ } reneg_state; - + server_rec *server; } SSLConnRec; +/* BIG FAT WARNING: SSLModConfigRec has unusual memory lifetime: it is + * allocated out of the "process" pool and only a single such + * structure is created and used for the lifetime of the process. + * (The process pool is s->process->pool and is stored in the .pPool + * field.) Most members of this structure are likewise allocated out + * of the process pool, but notably sesscache and sesscache_context + * are not. + * + * The structure is treated as mostly immutable after a single config + * parse has completed; the post_config hook (ssl_init_Module) flips + * the bFixed flag to true and subsequent invocations of the config + * callbacks hence do nothing. + * + * This odd lifetime strategy is used so that encrypted private keys + * can be decrypted once at startup and continue to be used across + * subsequent server reloads where the interactive password prompt is + * not possible. + + * It is really an ABI nightmare waiting to happen since DSOs are + * reloaded across restarts, and nothing prevents the struct type + * changing across such reloads, yet the cached structure will be + * assumed to match regardless. + * + * This should really be fixed using a smaller structure which only + * stores that which is absolutely necessary (the private keys, maybe + * the random seed), and have that structure be strictly ABI-versioned + * for safety. + */ typedef struct { pid_t pid; apr_pool_t *pPool; BOOL bFixed; - int nSessionCacheMode; - char *szSessionCacheDataFile; - int nSessionCacheDataSize; - apr_shm_t *pSessionCacheDataMM; - apr_rmm_t *pSessionCacheDataRMM; - void *tSessionCacheDataTable; - ssl_mutexmode_t nMutexMode; - apr_lockmech_e nMutexMech; - const char *szMutexFile; + + /* OpenSSL SSL_SESS_CACHE_* flags: */ + long sesscache_mode; + + /* The configured provider, and associated private data + * structure. */ + const ap_socache_provider_t *sesscache; + ap_socache_instance_t *sesscache_context; + apr_global_mutex_t *pMutex; apr_array_header_t *aRandSeed; apr_hash_t *tVHostKeys; void *pTmpKeys[SSL_TMP_KEY_MAX]; + + /* Two hash tables of pointers to ssl_asn1_t structures. The + * structures are used to store certificates and private keys + * respectively, in raw DER format (serialized OpenSSL X509 and + * PrivateKey structures). The tables are indexed by (vhost-id, + * algorithm type) using the function ssl_asn1_table_keyfmt(); for + * example the string "vhost.example.com:443:RSA". */ apr_hash_t *tPublicCert; apr_hash_t *tPrivateKey; + #if defined(HAVE_OPENSSL_ENGINE_H) && defined(HAVE_ENGINE_INIT) const char *szCryptoDevice; #endif + +#ifdef HAVE_OCSP_STAPLING + const ap_socache_provider_t *stapling_cache; + ap_socache_instance_t *stapling_cache_context; + apr_global_mutex_t *stapling_mutex; +#endif + struct { void *pV1, *pV2, *pV3, *pV4, *pV5, *pV6, *pV7, *pV8, *pV9, *pV10; } rCtx; } SSLModConfigRec; -/** public cert/private key */ +/** Structure representing configured filenames for certs and keys for + * a given vhost, and the corresponding in-memory structures once the + * files are parsed. */ typedef struct { - /** - * server only has 1-2 certs/keys - * 1 RSA and/or 1 DSA - */ + /* Lists of configured certs and keys for this server; from index + * 0 up to SSL_AIDX_MAX-1 or the first NULL pointer. Note that + * these arrays are NOT indexed by algorithm type, they are simply + * unordered lists. */ const char *cert_files[SSL_AIDX_MAX]; const char *key_files[SSL_AIDX_MAX]; + /* Loaded certs and keys; these arrays ARE indexed by the + * algorithm type, i.e. keys[SSL_AIDX_RSA] maps to the RSA + * private key. */ X509 *certs[SSL_AIDX_MAX]; EVP_PKEY *keys[SSL_AIDX_MAX]; @@ -425,7 +547,11 @@ typedef struct { /** proxy can have any number of cert/key pairs */ const char *cert_file; const char *cert_path; - STACK_OF(X509_INFO) *certs; + const char *ca_cert_file; + STACK_OF(X509_INFO) *certs; /* Contains End Entity certs */ + STACK_OF(X509) **ca_certs; /* Contains ONLY chain certs for + * each item in certs. + * (ptr to array of ptrs) */ } modssl_pk_proxy_t; /** stuff related to authentication that can also be per-dir */ @@ -441,6 +567,15 @@ typedef struct { ssl_verify_t verify_mode; } modssl_auth_ctx_t; +#ifdef HAVE_TLS_SESSION_TICKETS +typedef struct { + const char *file_path; + unsigned char key_name[16]; + unsigned char hmac_secret[16]; + unsigned char aes_key[16]; +} modssl_ticket_key_t; +#endif + typedef struct SSLSrvConfigRec SSLSrvConfigRec; typedef struct { @@ -451,6 +586,10 @@ typedef struct { modssl_pk_server_t *pks; modssl_pk_proxy_t *pkp; +#ifdef HAVE_TLS_SESSION_TICKETS + modssl_ticket_key_t *ticket_key; +#endif + ssl_proto_t protocol; /** config for handling encrypted keys */ @@ -458,13 +597,36 @@ typedef struct { const char *pphrase_dialog_path; const char *cert_chain; + const char *pkcs7; /** certificate revocation list */ - const char *crl_path; - const char *crl_file; - X509_STORE *crl; + const char *crl_path; + const char *crl_file; + ssl_crlcheck_t crl_check_mode; + +#ifdef HAVE_OCSP_STAPLING + /** OCSP stapling options */ + BOOL stapling_enabled; + long stapling_resptime_skew; + long stapling_resp_maxage; + int stapling_cache_timeout; + BOOL stapling_return_errors; + BOOL stapling_fake_trylater; + int stapling_errcache_timeout; + apr_interval_time_t stapling_responder_timeout; + const char *stapling_force_url; +#endif modssl_auth_ctx_t auth; + + BOOL ocsp_enabled; /* true if OCSP verification enabled */ + BOOL ocsp_force_default; /* true if the default responder URL is + * used regardless of per-cert URL */ + const char *ocsp_responder; /* default responder URL */ + long ocsp_resptime_skew; + long ocsp_resp_maxage; + apr_interval_time_t ocsp_responder_timeout; + } modssl_ctx_t; struct SSLSrvConfigRec { @@ -490,7 +652,7 @@ struct SSLSrvConfigRec { /** * Define the mod_ssl per-directory configuration structure - * (i.e. the local configuration for all <Directory> + * (i.e. the local configuration for all <Directory> * and .htaccess contexts) */ typedef struct { @@ -515,9 +677,6 @@ typedef struct { /** API glue structures */ extern module AP_MODULE_DECLARE_DATA ssl_module; -/** "global" stuff */ -extern const char ssl_valid_ssl_mutex_string[]; - /** configuration handling */ SSLModConfigRec *ssl_config_global_create(server_rec *); void ssl_config_global_fix(SSLModConfigRec *); @@ -526,7 +685,6 @@ void *ssl_config_server_create(apr_pool_t *, server_rec *); void *ssl_config_server_merge(apr_pool_t *, void *, void *); void *ssl_config_perdir_create(apr_pool_t *, char *); void *ssl_config_perdir_merge(apr_pool_t *, void *, void *); -const char *ssl_cmd_SSLMutex(cmd_parms *, void *, const char *); const char *ssl_cmd_SSLPassPhraseDialog(cmd_parms *, void *, const char *); const char *ssl_cmd_SSLCryptoDevice(cmd_parms *, void *, const char *); const char *ssl_cmd_SSLRandomSeed(cmd_parms *, void *, const char *, const char *, const char *); @@ -535,12 +693,14 @@ const char *ssl_cmd_SSLCipherSuite(cmd_parms *, void *, const char *); const char *ssl_cmd_SSLCertificateFile(cmd_parms *, void *, const char *); const char *ssl_cmd_SSLCertificateKeyFile(cmd_parms *, void *, const char *); const char *ssl_cmd_SSLCertificateChainFile(cmd_parms *, void *, const char *); +const char *ssl_cmd_SSLPKCS7CertificateFile(cmd_parms *, void *, const char *); const char *ssl_cmd_SSLCACertificatePath(cmd_parms *, void *, const char *); const char *ssl_cmd_SSLCACertificateFile(cmd_parms *, void *, const char *); const char *ssl_cmd_SSLCADNRequestPath(cmd_parms *, void *, const char *); const char *ssl_cmd_SSLCADNRequestFile(cmd_parms *, void *, const char *); const char *ssl_cmd_SSLCARevocationPath(cmd_parms *, void *, const char *); const char *ssl_cmd_SSLCARevocationFile(cmd_parms *, void *, const char *); +const char *ssl_cmd_SSLCARevocationCheck(cmd_parms *, void *, const char *); const char *ssl_cmd_SSLHonorCipherOrder(cmd_parms *cmd, void *dcfg, int flag); const char *ssl_cmd_SSLVerifyClient(cmd_parms *, void *, const char *); const char *ssl_cmd_SSLVerifyDepth(cmd_parms *, void *, const char *); @@ -564,11 +724,23 @@ const char *ssl_cmd_SSLProxyCACertificatePath(cmd_parms *, void *, const char * const char *ssl_cmd_SSLProxyCACertificateFile(cmd_parms *, void *, const char *); const char *ssl_cmd_SSLProxyCARevocationPath(cmd_parms *, void *, const char *); const char *ssl_cmd_SSLProxyCARevocationFile(cmd_parms *, void *, const char *); +const char *ssl_cmd_SSLProxyCARevocationCheck(cmd_parms *, void *, const char *); const char *ssl_cmd_SSLProxyMachineCertificatePath(cmd_parms *, void *, const char *); const char *ssl_cmd_SSLProxyMachineCertificateFile(cmd_parms *, void *, const char *); +const char *ssl_cmd_SSLProxyMachineCertificateChainFile(cmd_parms *, void *, const char *); +#ifdef HAVE_TLS_SESSION_TICKETS +const char *ssl_cmd_SSLSessionTicketKeyFile(cmd_parms *cmd, void *dcfg, const char *arg); +#endif const char *ssl_cmd_SSLProxyCheckPeerExpire(cmd_parms *cmd, void *dcfg, int flag); const char *ssl_cmd_SSLProxyCheckPeerCN(cmd_parms *cmd, void *dcfg, int flag); +const char *ssl_cmd_SSLOCSPOverrideResponder(cmd_parms *cmd, void *dcfg, int flag); +const char *ssl_cmd_SSLOCSPDefaultResponder(cmd_parms *cmd, void *dcfg, const char *arg); +const char *ssl_cmd_SSLOCSPResponseTimeSkew(cmd_parms *cmd, void *dcfg, const char *arg); +const char *ssl_cmd_SSLOCSPResponseMaxAge(cmd_parms *cmd, void *dcfg, const char *arg); +const char *ssl_cmd_SSLOCSPResponderTimeout(cmd_parms *cmd, void *dcfg, const char *arg); +const char *ssl_cmd_SSLOCSPEnable(cmd_parms *cmd, void *dcfg, int flag); + const char *ssl_cmd_SSLFIPS(cmd_parms *cmd, void *dcfg, int flag); /** module initialization */ @@ -576,7 +748,7 @@ int ssl_init_Module(apr_pool_t *, apr_pool_t *, apr_pool_t *, server_re void ssl_init_Engine(server_rec *, apr_pool_t *); void ssl_init_ConfigureServer(server_rec *, apr_pool_t *, apr_pool_t *, SSLSrvConfigRec *); void ssl_init_CheckServers(server_rec *, apr_pool_t *); -STACK_OF(X509_NAME) +STACK_OF(X509_NAME) *ssl_init_FindCAList(server_rec *, apr_pool_t *, const char *, const char *); void ssl_init_Child(apr_pool_t *, server_rec *); apr_status_t ssl_init_ModuleKill(void *data); @@ -590,64 +762,72 @@ int ssl_hook_ReadReq(request_rec *); int ssl_hook_Upgrade(request_rec *); void ssl_hook_ConfigTest(apr_pool_t *pconf, server_rec *s); +/** Apache authz provisders */ +extern const authz_provider ssl_authz_provider_require_ssl; +extern const authz_provider ssl_authz_provider_verify_client; + /** OpenSSL callbacks */ RSA *ssl_callback_TmpRSA(SSL *, int, int); DH *ssl_callback_TmpDH(SSL *, int, int); +#ifndef OPENSSL_NO_EC +EC_KEY *ssl_callback_TmpECDH(SSL *, int, int); +#endif int ssl_callback_SSLVerify(int, X509_STORE_CTX *); int ssl_callback_SSLVerify_CRL(int, X509_STORE_CTX *, conn_rec *); -int ssl_callback_proxy_cert(SSL *ssl, MODSSL_CLIENT_CERT_CB_ARG_TYPE **x509, EVP_PKEY **pkey); +int ssl_callback_proxy_cert(SSL *ssl, X509 **x509, EVP_PKEY **pkey); int ssl_callback_NewSessionCacheEntry(SSL *, SSL_SESSION *); SSL_SESSION *ssl_callback_GetSessionCacheEntry(SSL *, unsigned char *, int, int *); void ssl_callback_DelSessionCacheEntry(SSL_CTX *, SSL_SESSION *); -void ssl_callback_Info(MODSSL_INFO_CB_ARG_TYPE, int, int); +void ssl_callback_Info(const SSL *, int, int); #ifndef OPENSSL_NO_TLSEXT int ssl_callback_ServerNameIndication(SSL *, int *, modssl_ctx_t *); #endif +#ifdef HAVE_TLS_SESSION_TICKETS +int ssl_callback_SessionTicket(SSL *, unsigned char *, unsigned char *, + EVP_CIPHER_CTX *, HMAC_CTX *, int); +#endif /** Session Cache Support */ void ssl_scache_init(server_rec *, apr_pool_t *); void ssl_scache_status_register(apr_pool_t *p); void ssl_scache_kill(server_rec *); -BOOL ssl_scache_store(server_rec *, UCHAR *, int, time_t, SSL_SESSION *); -SSL_SESSION *ssl_scache_retrieve(server_rec *, UCHAR *, int); -void ssl_scache_remove(server_rec *, UCHAR *, int); - -char *ssl_scache_id2sz(UCHAR *, int); -void ssl_scache_dbm_init(server_rec *, apr_pool_t *); -void ssl_scache_dbm_kill(server_rec *); -BOOL ssl_scache_dbm_store(server_rec *, UCHAR *, int, time_t, SSL_SESSION *); -SSL_SESSION *ssl_scache_dbm_retrieve(server_rec *, UCHAR *, int); -void ssl_scache_dbm_remove(server_rec *, UCHAR *, int); -void ssl_scache_dbm_status(request_rec *r, int flags, apr_pool_t *pool); - -void ssl_scache_shmcb_init(server_rec *, apr_pool_t *); -void ssl_scache_shmcb_kill(server_rec *); -BOOL ssl_scache_shmcb_store(server_rec *, UCHAR *, int, time_t, SSL_SESSION *); -SSL_SESSION *ssl_scache_shmcb_retrieve(server_rec *, UCHAR *, int); -void ssl_scache_shmcb_remove(server_rec *, UCHAR *, int); -void ssl_scache_shmcb_status(request_rec *r, int flags, apr_pool_t *pool); - -void ssl_scache_dc_init(server_rec *, apr_pool_t *); -void ssl_scache_dc_kill(server_rec *); -BOOL ssl_scache_dc_store(server_rec *, UCHAR *, int, time_t, SSL_SESSION *); -SSL_SESSION *ssl_scache_dc_retrieve(server_rec *, UCHAR *, int); -void ssl_scache_dc_remove(server_rec *, UCHAR *, int); -void ssl_scache_dc_status(request_rec *r, int flags, apr_pool_t *pool); +BOOL ssl_scache_store(server_rec *, UCHAR *, int, + apr_time_t, SSL_SESSION *, apr_pool_t *); +SSL_SESSION *ssl_scache_retrieve(server_rec *, UCHAR *, int, apr_pool_t *); +void ssl_scache_remove(server_rec *, UCHAR *, int, + apr_pool_t *); /** Proxy Support */ int ssl_proxy_enable(conn_rec *c); int ssl_engine_disable(conn_rec *c); +/** OCSP Stapling Support */ +#ifdef HAVE_OCSP_STAPLING +const char *ssl_cmd_SSLStaplingCache(cmd_parms *, void *, const char *); +const char *ssl_cmd_SSLUseStapling(cmd_parms *, void *, int); +const char *ssl_cmd_SSLStaplingResponseTimeSkew(cmd_parms *, void *, const char *); +const char *ssl_cmd_SSLStaplingResponseMaxAge(cmd_parms *, void *, const char *); +const char *ssl_cmd_SSLStaplingStandardCacheTimeout(cmd_parms *, void *, const char *); +const char *ssl_cmd_SSLStaplingErrorCacheTimeout(cmd_parms *, void *, const char *); +const char *ssl_cmd_SSLStaplingReturnResponderErrors(cmd_parms *, void *, int); +const char *ssl_cmd_SSLStaplingFakeTryLater(cmd_parms *, void *, int); +const char *ssl_cmd_SSLStaplingResponderTimeout(cmd_parms *, void *, const char *); +const char *ssl_cmd_SSLStaplingForceURL(cmd_parms *, void *, const char *); +void modssl_init_stapling(server_rec *, apr_pool_t *, apr_pool_t *, modssl_ctx_t *); +void ssl_stapling_ex_init(void); +int ssl_stapling_init_cert(server_rec *s, modssl_ctx_t *mctx, X509 *x); +#endif + /** I/O */ -void ssl_io_filter_init(conn_rec *, SSL *); +void ssl_io_filter_init(conn_rec *, request_rec *r, SSL *); void ssl_io_filter_register(apr_pool_t *); -long ssl_io_data_cb(BIO *, int, MODSSL_BIO_CB_ARG_TYPE *, int, long, long); +long ssl_io_data_cb(BIO *, int, const char *, int, long, long); /* ssl_io_buffer_fill fills the setaside buffering of the HTTP request * to allow an SSL renegotiation to take place. */ int ssl_io_buffer_fill(request_rec *r, apr_size_t maxlen); -/* PRNG */ +/** PRNG */ int ssl_rand_seed(server_rec *, apr_pool_t *, ssl_rsctx_t, char *); /** Utility Functions */ @@ -658,10 +838,10 @@ void ssl_util_ppclose(server_rec *, apr_pool_t *, apr_file_t *); char *ssl_util_readfilter(server_rec *, apr_pool_t *, const char *, const char * const *); BOOL ssl_util_path_check(ssl_pathcheck_t, const char *, apr_pool_t *); -ssl_algo_t ssl_util_algotypeof(X509 *, EVP_PKEY *); +ssl_algo_t ssl_util_algotypeof(X509 *, EVP_PKEY *); char *ssl_util_algotypestr(ssl_algo_t); void ssl_util_thread_setup(apr_pool_t *); -int ssl_init_ssl_connection(conn_rec *c); +int ssl_init_ssl_connection(conn_rec *c, request_rec *r); /** Pass Phrase Support */ void ssl_pphrase_Handle(server_rec *, apr_pool_t *); @@ -685,24 +865,53 @@ const char *ssl_asn1_keystr(int keytype); const char *ssl_asn1_table_keyfmt(apr_pool_t *p, const char *id, int keytype); + +STACK_OF(X509) *ssl_read_pkcs7(server_rec *s, const char *pkcs7); + /** Mutex Support */ int ssl_mutex_init(server_rec *, apr_pool_t *); int ssl_mutex_reinit(server_rec *, apr_pool_t *); int ssl_mutex_on(server_rec *); int ssl_mutex_off(server_rec *); +int ssl_stapling_mutex_reinit(server_rec *, apr_pool_t *); + +/* mutex type names for Mutex directive */ +#define SSL_CACHE_MUTEX_TYPE "ssl-cache" +#define SSL_STAPLING_MUTEX_TYPE "ssl-stapling" + /** Logfile Support */ void ssl_die(void); void ssl_log_ssl_error(const char *, int, int, server_rec *); +/* ssl_log_xerror, ssl_log_cxerror and ssl_log_rxerror are wrappers for the + * respective ap_log_*error functions and take a certificate as an + * additional argument (whose details are appended to the log message). + * The other arguments are interpreted exactly as with their ap_log_*error + * counterparts. */ +void ssl_log_xerror(const char *file, int line, int level, + apr_status_t rv, apr_pool_t *p, server_rec *s, + X509 *cert, const char *format, ...) + __attribute__((format(printf,8,9))); + +void ssl_log_cxerror(const char *file, int line, int level, + apr_status_t rv, conn_rec *c, X509 *cert, + const char *format, ...) + __attribute__((format(printf,7,8))); + +void ssl_log_rxerror(const char *file, int line, int level, + apr_status_t rv, request_rec *r, X509 *cert, + const char *format, ...) + __attribute__((format(printf,7,8))); + +#define SSLLOG_MARK __FILE__,__LINE__ + /** Variables */ /* Register variables for the lifetime of the process pool 'p'. */ void ssl_var_register(apr_pool_t *p); char *ssl_var_lookup(apr_pool_t *, server_rec *, conn_rec *, request_rec *, char *); -const char *ssl_ext_lookup(apr_pool_t *p, conn_rec *c, int peer, const char *oid); - -extern apr_array_header_t *ssl_extlist_by_oid(request_rec *r, const char *oidstr); +apr_array_header_t *ssl_ext_list(apr_pool_t *p, conn_rec *c, int peer, const char *extension); void ssl_var_log_config_register(apr_pool_t *p); @@ -710,7 +919,22 @@ void ssl_var_log_config_register(apr_pool_t *p); * allocating from 'p': */ void modssl_var_extract_dns(apr_table_t *t, SSL *ssl, apr_pool_t *p); -#define APR_SHM_MAXSIZE (64 * 1024 * 1024) +#ifndef OPENSSL_NO_OCSP +/* Perform OCSP validation of the current cert in the given context. + * Returns non-zero on success or zero on failure. On failure, the + * context error code is set. */ +int modssl_verify_ocsp(X509_STORE_CTX *ctx, SSLSrvConfigRec *sc, + server_rec *s, conn_rec *c, apr_pool_t *pool); + +/* OCSP helper interface; dispatches the given OCSP request to the + * responder at the given URI. Returns the decoded OCSP response + * object, or NULL on error (in which case, errors will have been + * logged). Pool 'p' is used for temporary allocations. */ +OCSP_RESPONSE *modssl_dispatch_ocsp_request(const apr_uri_t *uri, + apr_interval_time_t timeout, + OCSP_REQUEST *request, + conn_rec *c, apr_pool_t *p); +#endif #endif /* SSL_PRIVATE_H */ /** @} */ diff --git a/modules/ssl/ssl_scache.c b/modules/ssl/ssl_scache.c index c85e4f19..2c8d1bc8 100644 --- a/modules/ssl/ssl_scache.c +++ b/modules/ssl/ssl_scache.c @@ -40,36 +40,55 @@ void ssl_scache_init(server_rec *s, apr_pool_t *p) { SSLModConfigRec *mc = myModConfig(s); + apr_status_t rv; + struct ap_socache_hints hints; + + /* The very first invocation of this function will be the + * post_config invocation during server startup; do nothing for + * this first (and only the first) time through, since the pool + * will be immediately cleared anyway. For every subsequent + * invocation, initialize the configured cache. */ + if (ap_state_query(AP_SQ_MAIN_STATE) == AP_SQ_MS_CREATE_PRE_CONFIG) + return; + +#ifdef HAVE_OCSP_STAPLING + if (mc->stapling_cache) { + memset(&hints, 0, sizeof hints); + hints.avg_obj_size = 1500; + hints.avg_id_len = 20; + hints.expiry_interval = 300; + + rv = mc->stapling_cache->init(mc->stapling_cache_context, + "mod_ssl-stapling", &hints, s, p); + if (rv) { + ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(01872) + "Could not initialize stapling cache. Exiting."); + ssl_die(); + } + } +#endif /* * Warn the user that he should use the session cache. * But we can operate without it, of course. */ - if (mc->nSessionCacheMode == SSL_SCMODE_UNSET) { - ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, + if (mc->sesscache == NULL) { + ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(01873) "Init: Session Cache is not configured " "[hint: SSLSessionCache]"); - mc->nSessionCacheMode = SSL_SCMODE_NONE; return; } - if (mc->nSessionCacheMode == SSL_SCMODE_DBM) - ssl_scache_dbm_init(s, p); -#ifdef HAVE_DISTCACHE - else if (mc->nSessionCacheMode == SSL_SCMODE_DC) - ssl_scache_dc_init(s, p); -#endif - else if (mc->nSessionCacheMode == SSL_SCMODE_SHMCB) { - void *data; - const char *userdata_key = "ssl_scache_init"; - - apr_pool_userdata_get(&data, userdata_key, s->process->pool); - if (!data) { - apr_pool_userdata_set((const void *)1, userdata_key, - apr_pool_cleanup_null, s->process->pool); - return; - } - ssl_scache_shmcb_init(s, p); + memset(&hints, 0, sizeof hints); + hints.avg_obj_size = 150; + hints.avg_id_len = 30; + hints.expiry_interval = 30; + + rv = mc->sesscache->init(mc->sesscache_context, "mod_ssl-session", &hints, s, p); + if (rv) { + ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(01874) + "Could not initialize session cache. Exiting."); + ssl_die(); } } @@ -77,62 +96,95 @@ void ssl_scache_kill(server_rec *s) { SSLModConfigRec *mc = myModConfig(s); - if (mc->nSessionCacheMode == SSL_SCMODE_DBM) - ssl_scache_dbm_kill(s); - else if (mc->nSessionCacheMode == SSL_SCMODE_SHMCB) - ssl_scache_shmcb_kill(s); -#ifdef HAVE_DISTCACHE - else if (mc->nSessionCacheMode == SSL_SCMODE_DC) - ssl_scache_dc_kill(s); + if (mc->sesscache) { + mc->sesscache->destroy(mc->sesscache_context, s); + } + +#ifdef HAVE_OCSP_STAPLING + if (mc->stapling_cache) { + mc->stapling_cache->destroy(mc->stapling_cache_context, s); + } #endif - return; + } -BOOL ssl_scache_store(server_rec *s, UCHAR *id, int idlen, time_t expiry, SSL_SESSION *sess) +BOOL ssl_scache_store(server_rec *s, UCHAR *id, int idlen, + apr_time_t expiry, SSL_SESSION *sess, + apr_pool_t *p) { SSLModConfigRec *mc = myModConfig(s); - BOOL rv = FALSE; - - if (mc->nSessionCacheMode == SSL_SCMODE_DBM) - rv = ssl_scache_dbm_store(s, id, idlen, expiry, sess); - else if (mc->nSessionCacheMode == SSL_SCMODE_SHMCB) - rv = ssl_scache_shmcb_store(s, id, idlen, expiry, sess); -#ifdef HAVE_DISTCACHE - else if (mc->nSessionCacheMode == SSL_SCMODE_DC) - rv = ssl_scache_dc_store(s, id, idlen, expiry, sess); -#endif - return rv; + unsigned char encoded[SSL_SESSION_MAX_DER], *ptr; + unsigned int len; + apr_status_t rv; + + /* Serialise the session. */ + len = i2d_SSL_SESSION(sess, NULL); + if (len > sizeof encoded) { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(01875) + "session is too big (%u bytes)", len); + return FALSE; + } + + ptr = encoded; + len = i2d_SSL_SESSION(sess, &ptr); + + if (mc->sesscache->flags & AP_SOCACHE_FLAG_NOTMPSAFE) { + ssl_mutex_on(s); + } + + rv = mc->sesscache->store(mc->sesscache_context, s, id, idlen, + expiry, encoded, len, p); + + if (mc->sesscache->flags & AP_SOCACHE_FLAG_NOTMPSAFE) { + ssl_mutex_off(s); + } + + return rv == APR_SUCCESS ? TRUE : FALSE; } -SSL_SESSION *ssl_scache_retrieve(server_rec *s, UCHAR *id, int idlen) +SSL_SESSION *ssl_scache_retrieve(server_rec *s, UCHAR *id, int idlen, + apr_pool_t *p) { SSLModConfigRec *mc = myModConfig(s); - SSL_SESSION *sess = NULL; - - if (mc->nSessionCacheMode == SSL_SCMODE_DBM) - sess = ssl_scache_dbm_retrieve(s, id, idlen); - else if (mc->nSessionCacheMode == SSL_SCMODE_SHMCB) - sess = ssl_scache_shmcb_retrieve(s, id, idlen); -#ifdef HAVE_DISTCACHE - else if (mc->nSessionCacheMode == SSL_SCMODE_DC) - sess = ssl_scache_dc_retrieve(s, id, idlen); -#endif - return sess; + unsigned char dest[SSL_SESSION_MAX_DER]; + unsigned int destlen = SSL_SESSION_MAX_DER; + MODSSL_D2I_SSL_SESSION_CONST unsigned char *ptr; + apr_status_t rv; + + if (mc->sesscache->flags & AP_SOCACHE_FLAG_NOTMPSAFE) { + ssl_mutex_on(s); + } + + rv = mc->sesscache->retrieve(mc->sesscache_context, s, id, idlen, + dest, &destlen, p); + + if (mc->sesscache->flags & AP_SOCACHE_FLAG_NOTMPSAFE) { + ssl_mutex_off(s); + } + + if (rv != APR_SUCCESS) { + return NULL; + } + + ptr = dest; + + return d2i_SSL_SESSION(NULL, &ptr, destlen); } -void ssl_scache_remove(server_rec *s, UCHAR *id, int idlen) +void ssl_scache_remove(server_rec *s, UCHAR *id, int idlen, + apr_pool_t *p) { SSLModConfigRec *mc = myModConfig(s); - if (mc->nSessionCacheMode == SSL_SCMODE_DBM) - ssl_scache_dbm_remove(s, id, idlen); - else if (mc->nSessionCacheMode == SSL_SCMODE_SHMCB) - ssl_scache_shmcb_remove(s, id, idlen); -#ifdef HAVE_DISTCACHE - else if (mc->nSessionCacheMode == SSL_SCMODE_DC) - ssl_scache_dc_remove(s, id, idlen); -#endif - return; + if (mc->sesscache->flags & AP_SOCACHE_FLAG_NOTMPSAFE) { + ssl_mutex_on(s); + } + + mc->sesscache->remove(mc->sesscache_context, s, id, idlen, p); + + if (mc->sesscache->flags & AP_SOCACHE_FLAG_NOTMPSAFE) { + ssl_mutex_off(s); + } } /* _________________________________________________________________ @@ -142,9 +194,9 @@ void ssl_scache_remove(server_rec *s, UCHAR *id, int idlen) */ static int ssl_ext_status_hook(request_rec *r, int flags) { - SSLSrvConfigRec *sc = mySrvConfig(r->server); + SSLModConfigRec *mc = myModConfig(r->server); - if (sc == NULL || flags & AP_STATUS_SHORT) + if (mc == NULL || flags & AP_STATUS_SHORT || mc->sesscache == NULL) return OK; ap_rputs("<hr>\n", r); @@ -154,14 +206,15 @@ static int ssl_ext_status_hook(request_rec *r, int flags) ap_rputs("</td></tr>\n", r); ap_rputs("<tr><td bgcolor=\"#ffffff\">\n", r); - if (sc->mc->nSessionCacheMode == SSL_SCMODE_DBM) - ssl_scache_dbm_status(r, flags, r->pool); - else if (sc->mc->nSessionCacheMode == SSL_SCMODE_SHMCB) - ssl_scache_shmcb_status(r, flags, r->pool); -#ifdef HAVE_DISTCACHE - else if (sc->mc->nSessionCacheMode == SSL_SCMODE_DC) - ssl_scache_dc_status(r, flags, r->pool); -#endif + if (mc->sesscache->flags & AP_SOCACHE_FLAG_NOTMPSAFE) { + ssl_mutex_on(r->server); + } + + mc->sesscache->status(mc->sesscache_context, r, flags); + + if (mc->sesscache->flags & AP_SOCACHE_FLAG_NOTMPSAFE) { + ssl_mutex_off(r->server); + } ap_rputs("</td></tr>\n", r); ap_rputs("</table>\n", r); diff --git a/modules/ssl/ssl_scache_dbm.c b/modules/ssl/ssl_scache_dbm.c deleted file mode 100644 index cdcce9d8..00000000 --- a/modules/ssl/ssl_scache_dbm.c +++ /dev/null @@ -1,464 +0,0 @@ -/* Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* _ _ - * _ __ ___ ___ __| | ___ ___| | mod_ssl - * | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL - * | | | | | | (_) | (_| | \__ \__ \ | - * |_| |_| |_|\___/ \__,_|___|___/___/_| - * |_____| - * ssl_scache_dbm.c - * Session Cache via DBM - */ - -#include "ssl_private.h" - -static void ssl_scache_dbm_expire(server_rec *s); - -void ssl_scache_dbm_init(server_rec *s, apr_pool_t *p) -{ - SSLModConfigRec *mc = myModConfig(s); - apr_dbm_t *dbm; - apr_status_t rv; - - /* for the DBM we need the data file */ - if (mc->szSessionCacheDataFile == NULL) { - ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, - "SSLSessionCache required"); - ssl_die(); - } - - /* open it once to create it and to make sure it _can_ be created */ - ssl_mutex_on(s); - if ((rv = apr_dbm_open(&dbm, mc->szSessionCacheDataFile, - APR_DBM_RWCREATE, SSL_DBM_FILE_MODE, mc->pPool)) != APR_SUCCESS) { - ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, - "Cannot create SSLSessionCache DBM file `%s'", - mc->szSessionCacheDataFile); - ssl_mutex_off(s); - return; - } - apr_dbm_close(dbm); - -#if !defined(OS2) && !defined(WIN32) && !defined(BEOS) && !defined(NETWARE) - /* - * We have to make sure the Apache child processes have access to - * the DBM file. But because there are brain-dead platforms where we - * cannot exactly determine the suffixes we try all possibilities. - */ - if (geteuid() == 0 /* is superuser */) { - chown(mc->szSessionCacheDataFile, unixd_config.user_id, -1 /* no gid change */); - if (chown(apr_pstrcat(p, mc->szSessionCacheDataFile, SSL_DBM_FILE_SUFFIX_DIR, NULL), - unixd_config.user_id, -1) == -1) { - if (chown(apr_pstrcat(p, mc->szSessionCacheDataFile, ".db", NULL), - unixd_config.user_id, -1) == -1) - chown(apr_pstrcat(p, mc->szSessionCacheDataFile, ".dir", NULL), - unixd_config.user_id, -1); - } - if (chown(apr_pstrcat(p, mc->szSessionCacheDataFile, SSL_DBM_FILE_SUFFIX_PAG, NULL), - unixd_config.user_id, -1) == -1) { - if (chown(apr_pstrcat(p, mc->szSessionCacheDataFile, ".db", NULL), - unixd_config.user_id, -1) == -1) - chown(apr_pstrcat(p, mc->szSessionCacheDataFile, ".pag", NULL), - unixd_config.user_id, -1); - } - } -#endif - ssl_mutex_off(s); - ssl_scache_dbm_expire(s); - return; -} - -void ssl_scache_dbm_kill(server_rec *s) -{ - SSLModConfigRec *mc = myModConfig(s); - apr_pool_t *p; - - apr_pool_create_ex(&p, mc->pPool, NULL, NULL); - if (p != NULL) { - /* the correct way */ - unlink(apr_pstrcat(p, mc->szSessionCacheDataFile, SSL_DBM_FILE_SUFFIX_DIR, NULL)); - unlink(apr_pstrcat(p, mc->szSessionCacheDataFile, SSL_DBM_FILE_SUFFIX_PAG, NULL)); - /* the additional ways to be sure */ - unlink(apr_pstrcat(p, mc->szSessionCacheDataFile, ".dir", NULL)); - unlink(apr_pstrcat(p, mc->szSessionCacheDataFile, ".pag", NULL)); - unlink(apr_pstrcat(p, mc->szSessionCacheDataFile, ".db", NULL)); - unlink(mc->szSessionCacheDataFile); - apr_pool_destroy(p); - } - return; -} - -BOOL ssl_scache_dbm_store(server_rec *s, UCHAR *id, int idlen, time_t expiry, SSL_SESSION *sess) -{ - SSLModConfigRec *mc = myModConfig(s); - apr_dbm_t *dbm; - apr_datum_t dbmkey; - apr_datum_t dbmval; - UCHAR ucaData[SSL_SESSION_MAX_DER]; - int nData; - UCHAR *ucp; - apr_status_t rv; - - /* streamline session data */ - if ((nData = i2d_SSL_SESSION(sess, NULL)) > sizeof(ucaData)) { - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, - "streamline session data size too large: %d > " - "%" APR_SIZE_T_FMT, - nData, sizeof(ucaData)); - return FALSE; - } - ucp = ucaData; - i2d_SSL_SESSION(sess, &ucp); - - /* be careful: do not try to store too much bytes in a DBM file! */ -#ifdef PAIRMAX - if ((idlen + nData) >= PAIRMAX) { - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, - "data size too large for DBM session cache: %d >= %d", - (idlen + nData), PAIRMAX); - return FALSE; - } -#else - if ((idlen + nData) >= 950 /* at least less than approx. 1KB */) { - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, - "data size too large for DBM session cache: %d >= %d", - (idlen + nData), 950); - return FALSE; - } -#endif - - /* create DBM key */ - dbmkey.dptr = (char *)id; - dbmkey.dsize = idlen; - - /* create DBM value */ - dbmval.dsize = sizeof(time_t) + nData; - dbmval.dptr = (char *)malloc(dbmval.dsize); - if (dbmval.dptr == NULL) { - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, - "malloc error creating DBM value"); - return FALSE; - } - memcpy((char *)dbmval.dptr, &expiry, sizeof(time_t)); - memcpy((char *)dbmval.dptr+sizeof(time_t), ucaData, nData); - - /* and store it to the DBM file */ - ssl_mutex_on(s); - if ((rv = apr_dbm_open(&dbm, mc->szSessionCacheDataFile, - APR_DBM_RWCREATE, SSL_DBM_FILE_MODE, mc->pPool)) != APR_SUCCESS) { - ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, - "Cannot open SSLSessionCache DBM file `%s' for writing " - "(store)", - mc->szSessionCacheDataFile); - ssl_mutex_off(s); - free(dbmval.dptr); - return FALSE; - } - if ((rv = apr_dbm_store(dbm, dbmkey, dbmval)) != APR_SUCCESS) { - ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, - "Cannot store SSL session to DBM file `%s'", - mc->szSessionCacheDataFile); - apr_dbm_close(dbm); - ssl_mutex_off(s); - free(dbmval.dptr); - return FALSE; - } - apr_dbm_close(dbm); - ssl_mutex_off(s); - - /* free temporary buffers */ - free(dbmval.dptr); - - /* allow the regular expiring to occur */ - ssl_scache_dbm_expire(s); - - return TRUE; -} - -SSL_SESSION *ssl_scache_dbm_retrieve(server_rec *s, UCHAR *id, int idlen) -{ - SSLModConfigRec *mc = myModConfig(s); - apr_dbm_t *dbm; - apr_datum_t dbmkey; - apr_datum_t dbmval; - SSL_SESSION *sess = NULL; - MODSSL_D2I_SSL_SESSION_CONST unsigned char *ucpData; - int nData; - time_t expiry; - time_t now; - apr_status_t rc; - - /* allow the regular expiring to occur */ - ssl_scache_dbm_expire(s); - - /* create DBM key and values */ - dbmkey.dptr = (char *)id; - dbmkey.dsize = idlen; - - /* and fetch it from the DBM file - * XXX: Should we open the dbm against r->pool so the cleanup will - * do the apr_dbm_close? This would make the code a bit cleaner. - */ - ssl_mutex_on(s); - if ((rc = apr_dbm_open(&dbm, mc->szSessionCacheDataFile, - APR_DBM_RWCREATE, SSL_DBM_FILE_MODE, mc->pPool)) != APR_SUCCESS) { - ap_log_error(APLOG_MARK, APLOG_ERR, rc, s, - "Cannot open SSLSessionCache DBM file `%s' for reading " - "(fetch)", - mc->szSessionCacheDataFile); - ssl_mutex_off(s); - return NULL; - } - rc = apr_dbm_fetch(dbm, dbmkey, &dbmval); - if (rc != APR_SUCCESS) { - apr_dbm_close(dbm); - ssl_mutex_off(s); - return NULL; - } - if (dbmval.dptr == NULL || dbmval.dsize <= sizeof(time_t)) { - apr_dbm_close(dbm); - ssl_mutex_off(s); - return NULL; - } - - /* parse resulting data */ - nData = dbmval.dsize-sizeof(time_t); - ucpData = malloc(nData); - if (ucpData == NULL) { - apr_dbm_close(dbm); - ssl_mutex_off(s); - return NULL; - } - /* Cast needed, ucpData may be const */ - memcpy((unsigned char *)ucpData, - (char *)dbmval.dptr + sizeof(time_t), nData); - memcpy(&expiry, dbmval.dptr, sizeof(time_t)); - - apr_dbm_close(dbm); - ssl_mutex_off(s); - - /* make sure the stuff is still not expired */ - now = time(NULL); - if (expiry <= now) { - ssl_scache_dbm_remove(s, id, idlen); - return NULL; - } - - /* unstreamed SSL_SESSION */ - sess = d2i_SSL_SESSION(NULL, &ucpData, nData); - - return sess; -} - -void ssl_scache_dbm_remove(server_rec *s, UCHAR *id, int idlen) -{ - SSLModConfigRec *mc = myModConfig(s); - apr_dbm_t *dbm; - apr_datum_t dbmkey; - apr_status_t rv; - - /* create DBM key and values */ - dbmkey.dptr = (char *)id; - dbmkey.dsize = idlen; - - /* and delete it from the DBM file */ - ssl_mutex_on(s); - if ((rv = apr_dbm_open(&dbm, mc->szSessionCacheDataFile, - APR_DBM_RWCREATE, SSL_DBM_FILE_MODE, mc->pPool)) != APR_SUCCESS) { - ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, - "Cannot open SSLSessionCache DBM file `%s' for writing " - "(delete)", - mc->szSessionCacheDataFile); - ssl_mutex_off(s); - return; - } - apr_dbm_delete(dbm, dbmkey); - apr_dbm_close(dbm); - ssl_mutex_off(s); - - return; -} - -static void ssl_scache_dbm_expire(server_rec *s) -{ - SSLModConfigRec *mc = myModConfig(s); - SSLSrvConfigRec *sc = mySrvConfig(s); - static time_t tLast = 0; - apr_dbm_t *dbm; - apr_datum_t dbmkey; - apr_datum_t dbmval; - apr_pool_t *p; - time_t tExpiresAt; - int nElements = 0; - int nDeleted = 0; - int bDelete; - apr_datum_t *keylist; - int keyidx; - int i; - time_t tNow; - apr_status_t rv; - - /* - * make sure the expiration for still not-accessed session - * cache entries is done only from time to time - */ - tNow = time(NULL); - if (tNow < tLast+sc->session_cache_timeout) - return; - tLast = tNow; - - /* - * Here we have to be very carefully: Not all DBM libraries are - * smart enough to allow one to iterate over the elements and at the - * same time delete expired ones. Some of them get totally crazy - * while others have no problems. So we have to do it the slower but - * more safe way: we first iterate over all elements and remember - * those which have to be expired. Then in a second pass we delete - * all those expired elements. Additionally we reopen the DBM file - * to be really safe in state. - */ - -#define KEYMAX 1024 - - ssl_mutex_on(s); - for (;;) { - /* allocate the key array in a memory sub pool */ - apr_pool_create_ex(&p, mc->pPool, NULL, NULL); - if (p == NULL) - break; - if ((keylist = apr_palloc(p, sizeof(dbmkey)*KEYMAX)) == NULL) { - apr_pool_destroy(p); - break; - } - - /* pass 1: scan DBM database */ - keyidx = 0; - if ((rv = apr_dbm_open(&dbm, mc->szSessionCacheDataFile, - APR_DBM_RWCREATE,SSL_DBM_FILE_MODE, - p)) != APR_SUCCESS) { - ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, - "Cannot open SSLSessionCache DBM file `%s' for " - "scanning", - mc->szSessionCacheDataFile); - apr_pool_destroy(p); - break; - } - apr_dbm_firstkey(dbm, &dbmkey); - while (dbmkey.dptr != NULL) { - nElements++; - bDelete = FALSE; - apr_dbm_fetch(dbm, dbmkey, &dbmval); - if (dbmval.dsize <= sizeof(time_t) || dbmval.dptr == NULL) - bDelete = TRUE; - else { - memcpy(&tExpiresAt, dbmval.dptr, sizeof(time_t)); - if (tExpiresAt <= tNow) - bDelete = TRUE; - } - if (bDelete) { - if ((keylist[keyidx].dptr = apr_pmemdup(p, dbmkey.dptr, dbmkey.dsize)) != NULL) { - keylist[keyidx].dsize = dbmkey.dsize; - keyidx++; - if (keyidx == KEYMAX) - break; - } - } - apr_dbm_nextkey(dbm, &dbmkey); - } - apr_dbm_close(dbm); - - /* pass 2: delete expired elements */ - if (apr_dbm_open(&dbm, mc->szSessionCacheDataFile, - APR_DBM_RWCREATE,SSL_DBM_FILE_MODE, p) != APR_SUCCESS) { - ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, - "Cannot re-open SSLSessionCache DBM file `%s' for " - "expiring", - mc->szSessionCacheDataFile); - apr_pool_destroy(p); - break; - } - for (i = 0; i < keyidx; i++) { - apr_dbm_delete(dbm, keylist[i]); - nDeleted++; - } - apr_dbm_close(dbm); - - /* destroy temporary pool */ - apr_pool_destroy(p); - - if (keyidx < KEYMAX) - break; - } - ssl_mutex_off(s); - - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, - "Inter-Process Session Cache (DBM) Expiry: " - "old: %d, new: %d, removed: %d", - nElements, nElements-nDeleted, nDeleted); - return; -} - -void ssl_scache_dbm_status(request_rec *r, int flags, apr_pool_t *p) -{ - SSLModConfigRec *mc = myModConfig(r->server); - apr_dbm_t *dbm; - apr_datum_t dbmkey; - apr_datum_t dbmval; - int nElem; - int nSize; - int nAverage; - apr_status_t rv; - - nElem = 0; - nSize = 0; - ssl_mutex_on(r->server); - /* - * XXX - Check what pool is to be used - TBD - */ - if ((rv = apr_dbm_open(&dbm, mc->szSessionCacheDataFile, - APR_DBM_RWCREATE, SSL_DBM_FILE_MODE, - mc->pPool)) != APR_SUCCESS) { - ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, - "Cannot open SSLSessionCache DBM file `%s' for status " - "retrival", - mc->szSessionCacheDataFile); - ssl_mutex_off(r->server); - return; - } - /* - * XXX - Check the return value of apr_dbm_firstkey, apr_dbm_fetch - TBD - */ - apr_dbm_firstkey(dbm, &dbmkey); - for ( ; dbmkey.dptr != NULL; apr_dbm_nextkey(dbm, &dbmkey)) { - apr_dbm_fetch(dbm, dbmkey, &dbmval); - if (dbmval.dptr == NULL) - continue; - nElem += 1; - nSize += dbmval.dsize; - } - apr_dbm_close(dbm); - ssl_mutex_off(r->server); - if (nSize > 0 && nElem > 0) - nAverage = nSize / nElem; - else - nAverage = 0; - ap_rprintf(r, "cache type: <b>DBM</b>, maximum size: <b>unlimited</b><br>"); - ap_rprintf(r, "current sessions: <b>%d</b>, current size: <b>%d</b> bytes<br>", nElem, nSize); - ap_rprintf(r, "average session size: <b>%d</b> bytes<br>", nAverage); - return; -} - diff --git a/modules/ssl/ssl_scache_dc.c b/modules/ssl/ssl_scache_dc.c deleted file mode 100644 index b03b0dea..00000000 --- a/modules/ssl/ssl_scache_dc.c +++ /dev/null @@ -1,177 +0,0 @@ -/* Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* _ _ - * _ __ ___ ___ __| | ___ ___| | mod_ssl - * | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL - * | | | | | | (_) | (_| | \__ \__ \ | - * |_| |_| |_|\___/ \__,_|___|___/___/_| - * |_____| - * ssl_scache_dc.c - * Distributed Session Cache (client support) - */ - -#include "ssl_private.h" - -/* Only build this code if it's enabled at configure-time. */ -#ifdef HAVE_DISTCACHE - -#include "distcache/dc_client.h" - -#if !defined(DISTCACHE_CLIENT_API) || (DISTCACHE_CLIENT_API < 0x0001) -#error "You must compile with a more recent version of the distcache-base package" -#endif - -/* - * This cache implementation allows modssl to access 'distcache' servers (or - * proxies) to facilitate distributed session caching. It is based on code - * released as open source by Cryptographic Appliances Inc, and was developed by - * Geoff Thorpe, Steve Robb, and Chris Zimmerman. - */ - -/* -** -** High-Level "handlers" as per ssl_scache.c -** -*/ - -void ssl_scache_dc_init(server_rec *s, apr_pool_t *p) -{ - DC_CTX *ctx; - SSLModConfigRec *mc = myModConfig(s); - /* - * Create a session context - */ - if (mc->szSessionCacheDataFile == NULL) { - ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "SSLSessionCache required"); - ssl_die(); - } -#if 0 - /* If a "persistent connection" mode of operation is preferred, you *must* - * also use the PIDCHECK flag to ensure fork()'d processes don't interlace - * comms on the same connection as each other. */ -#define SESSION_CTX_FLAGS SESSION_CTX_FLAG_PERSISTENT | \ - SESSION_CTX_FLAG_PERSISTENT_PIDCHECK | \ - SESSION_CTX_FLAG_PERSISTENT_RETRY | \ - SESSION_CTX_FLAG_PERSISTENT_LATE -#else - /* This mode of operation will open a temporary connection to the 'target' - * for each cache operation - this makes it safe against fork() - * automatically. This mode is preferred when running a local proxy (over - * unix domain sockets) because overhead is negligable and it reduces the - * performance/stability danger of file-descriptor bloatage. */ -#define SESSION_CTX_FLAGS 0 -#endif - ctx = DC_CTX_new(mc->szSessionCacheDataFile, SESSION_CTX_FLAGS); - if (!ctx) { - ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "distributed scache failed to obtain context"); - ssl_die(); - } - ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, "distributed scache context initialised"); - /* - * Success ... - */ - mc->tSessionCacheDataTable = ctx; - return; -} - -void ssl_scache_dc_kill(server_rec *s) -{ - SSLModConfigRec *mc = myModConfig(s); - - if (mc->tSessionCacheDataTable) - DC_CTX_free(mc->tSessionCacheDataTable); - mc->tSessionCacheDataTable = NULL; -} - -BOOL ssl_scache_dc_store(server_rec *s, UCHAR *id, int idlen, - time_t timeout, SSL_SESSION * pSession) -{ - unsigned char der[SSL_SESSION_MAX_DER]; - int der_len; - unsigned char *pder = der; - SSLModConfigRec *mc = myModConfig(s); - DC_CTX *ctx = mc->tSessionCacheDataTable; - - /* Serialise the SSL_SESSION object */ - if ((der_len = i2d_SSL_SESSION(pSession, NULL)) > SSL_SESSION_MAX_DER) - return FALSE; - i2d_SSL_SESSION(pSession, &pder); - /* !@#$%^ - why do we deal with *absolute* time anyway??? */ - timeout -= time(NULL); - /* Send the serialised session to the distributed cache context */ - if (!DC_CTX_add_session(ctx, id, idlen, der, der_len, - (unsigned long)timeout * 1000)) { - ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "distributed scache 'add_session' failed"); - return FALSE; - } - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "distributed scache 'add_session' successful"); - return TRUE; -} - -SSL_SESSION *ssl_scache_dc_retrieve(server_rec *s, UCHAR *id, int idlen) -{ - unsigned char der[SSL_SESSION_MAX_DER]; - unsigned int der_len; - SSL_SESSION *pSession; - MODSSL_D2I_SSL_SESSION_CONST unsigned char *pder = der; - SSLModConfigRec *mc = myModConfig(s); - DC_CTX *ctx = mc->tSessionCacheDataTable; - - /* Retrieve any corresponding session from the distributed cache context */ - if (!DC_CTX_get_session(ctx, id, idlen, der, SSL_SESSION_MAX_DER, - &der_len)) { - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "distributed scache 'get_session' MISS"); - return NULL; - } - if (der_len > SSL_SESSION_MAX_DER) { - ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "distributed scache 'get_session' OVERFLOW"); - return NULL; - } - pSession = d2i_SSL_SESSION(NULL, &pder, der_len); - if (!pSession) { - ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "distributed scache 'get_session' CORRUPT"); - return NULL; - } - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "distributed scache 'get_session' HIT"); - return pSession; -} - -void ssl_scache_dc_remove(server_rec *s, UCHAR *id, int idlen) -{ - SSLModConfigRec *mc = myModConfig(s); - DC_CTX *ctx = mc->tSessionCacheDataTable; - - /* Remove any corresponding session from the distributed cache context */ - if (!DC_CTX_remove_session(ctx, id, idlen)) { - ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "distributed scache 'remove_session' MISS"); - } else { - ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "distributed scache 'remove_session' HIT"); - } -} - -void ssl_scache_dc_status(request_rec *r, int flags, apr_pool_t *pool) -{ - SSLModConfigRec *mc = myModConfig(r->server); - - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, - "distributed scache 'ssl_scache_dc_status'"); - ap_rprintf(r, "cache type: <b>DC (Distributed Cache)</b>, " - " target: <b>%s</b><br>", mc->szSessionCacheDataFile); -} - -#endif - diff --git a/modules/ssl/ssl_scache_shmcb.c b/modules/ssl/ssl_scache_shmcb.c deleted file mode 100644 index e778db04..00000000 --- a/modules/ssl/ssl_scache_shmcb.c +++ /dev/null @@ -1,769 +0,0 @@ -/* Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* _ _ - * _ __ ___ ___ __| | ___ ___| | mod_ssl - * | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL - * | | | | | | (_) | (_| | \__ \__ \ | - * |_| |_| |_|\___/ \__,_|___|___/___/_| - * |_____| - * ssl_scache_shmcb.c - * Session Cache via Shared Memory (Cyclic Buffer Variant) - */ - -#include "ssl_private.h" - -/* - * This shared memory based SSL session cache implementation was - * originally written by Geoff Thorpe <geoff geoffthorpe.net> for C2Net - * Europe as a contribution to Ralf Engelschall's mod_ssl project. - * - * Since rewritten by GT to not use alignment-fudging memcpys and reduce - * complexity. - */ - -/* - * Header structure - the start of the shared-mem segment - */ -typedef struct { - /* Stats for cache operations */ - unsigned long stat_stores; - unsigned long stat_expiries; - unsigned long stat_scrolled; - unsigned long stat_retrieves_hit; - unsigned long stat_retrieves_miss; - unsigned long stat_removes_hit; - unsigned long stat_removes_miss; - /* Number of subcaches */ - unsigned int subcache_num; - /* How many indexes each subcache's queue has */ - unsigned int index_num; - /* How large each subcache is, including the queue and data */ - unsigned int subcache_size; - /* How far into each subcache the data area is (optimisation) */ - unsigned int subcache_data_offset; - /* How large the data area in each subcache is (optimisation) */ - unsigned int subcache_data_size; -} SHMCBHeader; - -/* - * Subcache structure - the start of each subcache, followed by - * indexes then data - */ -typedef struct { - /* The start position and length of the cyclic buffer of indexes */ - unsigned int idx_pos, idx_used; - /* Same for the data area */ - unsigned int data_pos, data_used; -} SHMCBSubcache; - -/* - * Index structure - each subcache has an array of these - */ -typedef struct { - /* absolute time this entry expires */ - time_t expires; - /* location within the subcache's data area */ - unsigned int data_pos; - /* size (most logic ignores this, we keep it only to minimise memcpy) */ - unsigned int data_used; - /* Optimisation to prevent ASN decoding unless a match is likely */ - unsigned char s_id2; - /* Used to mark explicitly-removed sessions */ - unsigned char removed; -} SHMCBIndex; - - -/* The SHM data segment is of fixed size and stores data as follows. - * - * [ SHMCBHeader | Subcaches ] - * - * The SHMCBHeader header structure stores metadata concerning the - * cache and the contained subcaches. - * - * Subcaches is a hash table of header->subcache_num SHMCBSubcache - * structures. The hash table is indexed by SHMCB_MASK(id). Each - * SHMCBSubcache structure has a fixed size (header->subcache_size), - * which is determined at creation time, and looks like the following: - * - * [ SHMCBSubcache | Indexes | Data ] - * - * Each subcache is prefixed by the SHMCBSubcache structure. - * - * The subcache's "Data" segment is a single cyclic data buffer, of - * total size header->subcache_data_size; data inside is referenced - * using byte offsets. The offset marking the beginning of the cyclic - * buffer is subcache->data_pos the buffer's length is - * subcache->data_used. - * - * "Indexes" is an array of header->index_num SHMCBIndex structures, - * which is used as a cyclic queue; subcache->idx_pos gives the array - * index of the first in use, subcache->idx_used gives the number in - * use. Both ->idx_* values have a range of [0, header->index_num) - * - * Each in-use SHMCBIndex structure represents a single SSL session. - */ - -/* This macro takes a pointer to the header and a zero-based index and returns - * a pointer to the corresponding subcache. */ -#define SHMCB_SUBCACHE(pHeader, num) \ - (SHMCBSubcache *)(((unsigned char *)(pHeader)) + \ - sizeof(SHMCBHeader) + \ - (num) * ((pHeader)->subcache_size)) - -/* This macro takes a pointer to the header and a session id and returns a - * pointer to the corresponding subcache. */ -#define SHMCB_MASK(pHeader, id) \ - SHMCB_SUBCACHE((pHeader), *(id) & ((pHeader)->subcache_num - 1)) - -/* This macro takes the same params as the last, generating two outputs for use - * in ap_log_error(...). */ -#define SHMCB_MASK_DBG(pHeader, id) \ - *(id), (*(id) & ((pHeader)->subcache_num - 1)) - -/* This macro takes a pointer to a subcache and a zero-based index and returns - * a pointer to the corresponding SHMCBIndex. */ -#define SHMCB_INDEX(pSubcache, num) \ - ((SHMCBIndex *)(((unsigned char *)pSubcache) + \ - sizeof(SHMCBSubcache)) + num) - -/* This macro takes a pointer to the header and a subcache and returns a - * pointer to the corresponding data area. */ -#define SHMCB_DATA(pHeader, pSubcache) \ - ((unsigned char *)(pSubcache) + (pHeader)->subcache_data_offset) - -/* - * Cyclic functions - assists in "wrap-around"/modulo logic - */ - -/* Addition modulo 'mod' */ -#define SHMCB_CYCLIC_INCREMENT(val,inc,mod) \ - (((val) + (inc)) % (mod)) - -/* Subtraction (or "distance between") modulo 'mod' */ -#define SHMCB_CYCLIC_SPACE(val1,val2,mod) \ - ((val2) >= (val1) ? ((val2) - (val1)) : \ - ((val2) + (mod) - (val1))) - -/* A "normal-to-cyclic" memcpy. */ -static void shmcb_cyclic_ntoc_memcpy(unsigned int buf_size, unsigned char *data, - unsigned int dest_offset, unsigned char *src, - unsigned int src_len) -{ - if (dest_offset + src_len < buf_size) - /* It be copied all in one go */ - memcpy(data + dest_offset, src, src_len); - else { - /* Copy the two splits */ - memcpy(data + dest_offset, src, buf_size - dest_offset); - memcpy(data, src + buf_size - dest_offset, - src_len + dest_offset - buf_size); - } -} - -/* A "cyclic-to-normal" memcpy. */ -static void shmcb_cyclic_cton_memcpy(unsigned int buf_size, unsigned char *dest, - unsigned char *data, unsigned int src_offset, - unsigned int src_len) -{ - if (src_offset + src_len < buf_size) - /* It be copied all in one go */ - memcpy(dest, data + src_offset, src_len); - else { - /* Copy the two splits */ - memcpy(dest, data + src_offset, buf_size - src_offset); - memcpy(dest + buf_size - src_offset, data, - src_len + src_offset - buf_size); - } -} - -/* Prototypes for low-level subcache operations */ -static void shmcb_subcache_expire(server_rec *, SHMCBHeader *, SHMCBSubcache *); -static BOOL shmcb_subcache_store(server_rec *, SHMCBHeader *, SHMCBSubcache *, - UCHAR *, unsigned int, UCHAR *, time_t); -static SSL_SESSION *shmcb_subcache_retrieve(server_rec *, SHMCBHeader *, SHMCBSubcache *, - UCHAR *, unsigned int); -static BOOL shmcb_subcache_remove(server_rec *, SHMCBHeader *, SHMCBSubcache *, - UCHAR *, unsigned int); - -/* - * High-Level "handlers" as per ssl_scache.c - * subcache internals are deferred to shmcb_subcache_*** functions lower down - */ - -void ssl_scache_shmcb_init(server_rec *s, apr_pool_t *p) -{ - SSLModConfigRec *mc = myModConfig(s); - void *shm_segment; - apr_size_t shm_segsize; - apr_status_t rv; - SHMCBHeader *header; - unsigned int num_subcache, num_idx, loop; - - /* Create shared memory segment */ - if (mc->szSessionCacheDataFile == NULL) { - ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, - "SSLSessionCache required"); - ssl_die(); - } - - /* Use anonymous shm by default, fall back on name-based. */ - rv = apr_shm_create(&(mc->pSessionCacheDataMM), - mc->nSessionCacheDataSize, - NULL, mc->pPool); - if (APR_STATUS_IS_ENOTIMPL(rv)) { - /* For a name-based segment, remove it first in case of a - * previous unclean shutdown. */ - apr_shm_remove(mc->szSessionCacheDataFile, mc->pPool); - - rv = apr_shm_create(&(mc->pSessionCacheDataMM), - mc->nSessionCacheDataSize, - mc->szSessionCacheDataFile, - mc->pPool); - } - - if (rv != APR_SUCCESS) { - ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, - "could not allocate shared memory for shmcb " - "session cache"); - ssl_die(); - } - - shm_segment = apr_shm_baseaddr_get(mc->pSessionCacheDataMM); - shm_segsize = apr_shm_size_get(mc->pSessionCacheDataMM); - if (shm_segsize < (5 * sizeof(SHMCBHeader))) { - /* the segment is ridiculously small, bail out */ - ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, - "shared memory segment too small"); - ssl_die(); - } - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, - "shmcb_init allocated %" APR_SIZE_T_FMT - " bytes of shared memory", - shm_segsize); - /* Discount the header */ - shm_segsize -= sizeof(SHMCBHeader); - /* Select the number of subcaches to create and how many indexes each - * should contain based on the size of the memory (the header has already - * been subtracted). Typical non-client-auth sslv3/tlsv1 sessions are - * around 150 bytes, so erring to division by 120 helps ensure we would - * exhaust data storage before index storage (except sslv2, where it's - * *slightly* the other way). From there, we select the number of subcaches - * to be a power of two, such that the number of indexes per subcache at - * least twice the number of subcaches. */ - num_idx = (shm_segsize) / 120; - num_subcache = 256; - while ((num_idx / num_subcache) < (2 * num_subcache)) - num_subcache /= 2; - num_idx /= num_subcache; - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, - "for %" APR_SIZE_T_FMT " bytes (%" APR_SIZE_T_FMT - " including header), recommending %u subcaches, " - "%u indexes each", shm_segsize, - shm_segsize + sizeof(SHMCBHeader), num_subcache, num_idx); - if (num_idx < 5) { - /* we're still too small, bail out */ - ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, - "shared memory segment too small"); - ssl_die(); - } - /* OK, we're sorted */ - header = shm_segment; - header->stat_stores = 0; - header->stat_expiries = 0; - header->stat_scrolled = 0; - header->stat_retrieves_hit = 0; - header->stat_retrieves_miss = 0; - header->stat_removes_hit = 0; - header->stat_removes_miss = 0; - header->subcache_num = num_subcache; - /* Convert the subcache size (in bytes) to a value that is suitable for - * structure alignment on the host platform, by rounding down if necessary. - * This assumes that sizeof(unsigned long) provides an appropriate - * alignment unit. */ - header->subcache_size = ((size_t)(shm_segsize / num_subcache) & - ~(size_t)(sizeof(unsigned long) - 1)); - header->subcache_data_offset = sizeof(SHMCBSubcache) + - num_idx * sizeof(SHMCBIndex); - header->subcache_data_size = header->subcache_size - - header->subcache_data_offset; - header->index_num = num_idx; - - /* Output trace info */ - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, - "shmcb_init_memory choices follow"); - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, - "subcache_num = %u", header->subcache_num); - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, - "subcache_size = %u", header->subcache_size); - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, - "subcache_data_offset = %u", header->subcache_data_offset); - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, - "subcache_data_size = %u", header->subcache_data_size); - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, - "index_num = %u", header->index_num); - /* The header is done, make the caches empty */ - for (loop = 0; loop < header->subcache_num; loop++) { - SHMCBSubcache *subcache = SHMCB_SUBCACHE(header, loop); - subcache->idx_pos = subcache->idx_used = 0; - subcache->data_pos = subcache->data_used = 0; - } - ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, - "Shared memory session cache initialised"); - /* Success ... */ - mc->tSessionCacheDataTable = shm_segment; -} - -void ssl_scache_shmcb_kill(server_rec *s) -{ - SSLModConfigRec *mc = myModConfig(s); - - if (mc->pSessionCacheDataMM != NULL) { - apr_shm_destroy(mc->pSessionCacheDataMM); - mc->pSessionCacheDataMM = NULL; - } - return; -} - -BOOL ssl_scache_shmcb_store(server_rec *s, UCHAR *id, int idlen, - time_t timeout, SSL_SESSION * pSession) -{ - SSLModConfigRec *mc = myModConfig(s); - BOOL to_return = FALSE; - unsigned char encoded[SSL_SESSION_MAX_DER]; - unsigned char *ptr_encoded; - unsigned int len_encoded; - SHMCBHeader *header = mc->tSessionCacheDataTable; - SHMCBSubcache *subcache = SHMCB_MASK(header, id); - - ssl_mutex_on(s); - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, - "ssl_scache_shmcb_store (0x%02x -> subcache %d)", - SHMCB_MASK_DBG(header, id)); - if (idlen < 4) { - ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "unusably short session_id provided " - "(%u bytes)", idlen); - goto done; - } - /* Serialise the session. */ - len_encoded = i2d_SSL_SESSION(pSession, NULL); - if (len_encoded > SSL_SESSION_MAX_DER) { - ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, - "session is too big (%u bytes)", len_encoded); - goto done; - } - ptr_encoded = encoded; - len_encoded = i2d_SSL_SESSION(pSession, &ptr_encoded); - if (!shmcb_subcache_store(s, header, subcache, encoded, - len_encoded, id, timeout)) { - ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, - "can't store a session!"); - goto done; - } - header->stat_stores++; - to_return = TRUE; - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, - "leaving ssl_scache_shmcb_store successfully"); -done: - ssl_mutex_off(s); - return to_return; -} - -SSL_SESSION *ssl_scache_shmcb_retrieve(server_rec *s, UCHAR *id, int idlen) -{ - SSLModConfigRec *mc = myModConfig(s); - SSL_SESSION *pSession = NULL; - SHMCBHeader *header = mc->tSessionCacheDataTable; - SHMCBSubcache *subcache = SHMCB_MASK(header, id); - - ssl_mutex_on(s); - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, - "ssl_scache_shmcb_retrieve (0x%02x -> subcache %d)", - SHMCB_MASK_DBG(header, id)); - if (idlen < 4) { - ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "unusably short session_id provided " - "(%u bytes)", idlen); - goto done; - } - /* Get the session corresponding to the session_id or NULL if it doesn't - * exist (or is flagged as "removed"). */ - pSession = shmcb_subcache_retrieve(s, header, subcache, id, idlen); - if (pSession) - header->stat_retrieves_hit++; - else - header->stat_retrieves_miss++; - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, - "leaving ssl_scache_shmcb_retrieve successfully"); -done: - ssl_mutex_off(s); - return pSession; -} - -void ssl_scache_shmcb_remove(server_rec *s, UCHAR *id, int idlen) -{ - SSLModConfigRec *mc = myModConfig(s); - SHMCBHeader *header = mc->tSessionCacheDataTable; - SHMCBSubcache *subcache = SHMCB_MASK(header, id); - - ssl_mutex_on(s); - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, - "ssl_scache_shmcb_remove (0x%02x -> subcache %d)", - SHMCB_MASK_DBG(header, id)); - if (idlen < 4) { - ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "unusably short session_id provided " - "(%u bytes)", idlen); - goto done; - } - if (shmcb_subcache_remove(s, header, subcache, id, idlen)) - header->stat_removes_hit++; - else - header->stat_removes_miss++; - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, - "leaving ssl_scache_shmcb_remove successfully"); -done: - ssl_mutex_off(s); -} - -void ssl_scache_shmcb_status(request_rec *r, int flags, apr_pool_t *p) -{ - server_rec *s = r->server; - SSLModConfigRec *mc = myModConfig(s); - void *shm_segment = apr_shm_baseaddr_get(mc->pSessionCacheDataMM); - SHMCBHeader *header = shm_segment; - unsigned int loop, total = 0, cache_total = 0, non_empty_subcaches = 0; - time_t idx_expiry, min_expiry = 0, max_expiry = 0, average_expiry = 0; - time_t now = time(NULL); - double expiry_total = 0; - int index_pct, cache_pct; - - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "inside shmcb_status"); - /* Perform the iteration inside the mutex to avoid corruption or invalid - * pointer arithmetic. The rest of our logic uses read-only header data so - * doesn't need the lock. */ - ssl_mutex_on(s); - /* Iterate over the subcaches */ - for (loop = 0; loop < header->subcache_num; loop++) { - SHMCBSubcache *subcache = SHMCB_SUBCACHE(header, loop); - shmcb_subcache_expire(s, header, subcache); - total += subcache->idx_used; - cache_total += subcache->data_used; - if (subcache->idx_used) { - SHMCBIndex *idx = SHMCB_INDEX(subcache, subcache->idx_pos); - non_empty_subcaches++; - idx_expiry = idx->expires; - expiry_total += (double)idx_expiry; - max_expiry = ((idx_expiry > max_expiry) ? idx_expiry : max_expiry); - if (!min_expiry) - min_expiry = idx_expiry; - else - min_expiry = ((idx_expiry < min_expiry) ? idx_expiry : min_expiry); - } - } - ssl_mutex_off(s); - index_pct = (100 * total) / (header->index_num * - header->subcache_num); - cache_pct = (100 * cache_total) / (header->subcache_data_size * - header->subcache_num); - /* Generate HTML */ - ap_rprintf(r, "cache type: <b>SHMCB</b>, shared memory: <b>%d</b> " - "bytes, current sessions: <b>%d</b><br>", - mc->nSessionCacheDataSize, total); - ap_rprintf(r, "subcaches: <b>%d</b>, indexes per subcache: <b>%d</b><br>", - header->subcache_num, header->index_num); - if (non_empty_subcaches) { - average_expiry = (time_t)(expiry_total / (double)non_empty_subcaches); - ap_rprintf(r, "time left on oldest entries' SSL sessions: "); - if (now < average_expiry) - ap_rprintf(r, "avg: <b>%d</b> seconds, (range: %d...%d)<br>", - (int)(average_expiry - now), - (int)(min_expiry - now), - (int)(max_expiry - now)); - else - ap_rprintf(r, "expiry_threshold: <b>Calculation error!</b><br>"); - } - - ap_rprintf(r, "index usage: <b>%d%%</b>, cache usage: <b>%d%%</b><br>", - index_pct, cache_pct); - ap_rprintf(r, "total sessions stored since starting: <b>%lu</b><br>", - header->stat_stores); - ap_rprintf(r, "total sessions expired since starting: <b>%lu</b><br>", - header->stat_expiries); - ap_rprintf(r, "total (pre-expiry) sessions scrolled out of the cache: " - "<b>%lu</b><br>", header->stat_scrolled); - ap_rprintf(r, "total retrieves since starting: <b>%lu</b> hit, " - "<b>%lu</b> miss<br>", header->stat_retrieves_hit, - header->stat_retrieves_miss); - ap_rprintf(r, "total removes since starting: <b>%lu</b> hit, " - "<b>%lu</b> miss<br>", header->stat_removes_hit, - header->stat_removes_miss); - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "leaving shmcb_status"); -} - -/* - * Subcache-level cache operations - */ - -static void shmcb_subcache_expire(server_rec *s, SHMCBHeader *header, - SHMCBSubcache *subcache) -{ - time_t now = time(NULL); - unsigned int loop = 0; - unsigned int new_idx_pos = subcache->idx_pos; - SHMCBIndex *idx = NULL; - - while (loop < subcache->idx_used) { - idx = SHMCB_INDEX(subcache, new_idx_pos); - if (idx->expires > now) - /* it hasn't expired yet, we're done iterating */ - break; - loop++; - new_idx_pos = SHMCB_CYCLIC_INCREMENT(new_idx_pos, 1, header->index_num); - } - if (!loop) - /* Nothing to do */ - return; - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, - "will be expiring %u sessions", loop); - if (loop == subcache->idx_used) { - /* We're expiring everything, piece of cake */ - subcache->idx_used = 0; - subcache->data_used = 0; - } else { - /* There remain other indexes, so we can use idx to adjust 'data' */ - unsigned int diff = SHMCB_CYCLIC_SPACE(subcache->data_pos, - idx->data_pos, - header->subcache_data_size); - /* Adjust the indexes */ - subcache->idx_used -= loop; - subcache->idx_pos = new_idx_pos; - /* Adjust the data area */ - subcache->data_used -= diff; - subcache->data_pos = idx->data_pos; - } - header->stat_expiries += loop; - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, - "we now have %u sessions", subcache->idx_used); -} - -static BOOL shmcb_subcache_store(server_rec *s, SHMCBHeader *header, - SHMCBSubcache *subcache, - UCHAR *data, unsigned int data_len, - UCHAR *id, time_t expiry) -{ - unsigned int new_offset, new_idx; - SHMCBIndex *idx; - - /* Sanity check the input */ - if ((data_len > header->subcache_data_size) || (data_len > SSL_SESSION_MAX_DER)) { - ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, - "inserting session larger (%d) than subcache data area (%d)", - data_len, header->subcache_data_size); - return FALSE; - } - - /* If there are entries to expire, ditch them first. */ - shmcb_subcache_expire(s, header, subcache); - - /* Loop until there is enough space to insert */ - if (header->subcache_data_size - subcache->data_used < data_len - || subcache->idx_used == header->index_num) { - unsigned int loop = 0; - - idx = SHMCB_INDEX(subcache, subcache->idx_pos); - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, - "about to force-expire, subcache: idx_used=%d, " - "data_used=%d", subcache->idx_used, subcache->data_used); - do { - SHMCBIndex *idx2; - - /* Adjust the indexes by one */ - subcache->idx_pos = SHMCB_CYCLIC_INCREMENT(subcache->idx_pos, 1, - header->index_num); - subcache->idx_used--; - if (!subcache->idx_used) { - /* There's nothing left */ - subcache->data_used = 0; - break; - } - /* Adjust the data */ - idx2 = SHMCB_INDEX(subcache, subcache->idx_pos); - subcache->data_used -= SHMCB_CYCLIC_SPACE(idx->data_pos, idx2->data_pos, - header->subcache_data_size); - subcache->data_pos = idx2->data_pos; - /* Stats */ - header->stat_scrolled++; - /* Loop admin */ - idx = idx2; - loop++; - } while (header->subcache_data_size - subcache->data_used < data_len); - - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, - "finished force-expire, subcache: idx_used=%d, " - "data_used=%d", subcache->idx_used, subcache->data_used); - } - - /* HERE WE ASSUME THAT THE NEW SESSION SHOULD GO ON THE END! I'M NOT - * CHECKING WHETHER IT SHOULD BE GENUINELY "INSERTED" SOMEWHERE. - * - * We either fix that, or find out at a "higher" (read "mod_ssl") - * level whether it is possible to have distinct session caches for - * any attempted tomfoolery to do with different session timeouts. - * Knowing in advance that we can have a cache-wide constant timeout - * would make this stuff *MUCH* more efficient. Mind you, it's very - * efficient right now because I'm ignoring this problem!!! - */ - /* Insert the data */ - new_offset = SHMCB_CYCLIC_INCREMENT(subcache->data_pos, subcache->data_used, - header->subcache_data_size); - shmcb_cyclic_ntoc_memcpy(header->subcache_data_size, - SHMCB_DATA(header, subcache), new_offset, - data, data_len); - subcache->data_used += data_len; - /* Insert the index */ - new_idx = SHMCB_CYCLIC_INCREMENT(subcache->idx_pos, subcache->idx_used, - header->index_num); - idx = SHMCB_INDEX(subcache, new_idx); - idx->expires = expiry; - idx->data_pos = new_offset; - idx->data_used = data_len; - idx->s_id2 = id[1]; - idx->removed = 0; - subcache->idx_used++; - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, - "insert happened at idx=%d, data=%d", new_idx, new_offset); - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, - "finished insert, subcache: idx_pos/idx_used=%d/%d, " - "data_pos/data_used=%d/%d", - subcache->idx_pos, subcache->idx_used, - subcache->data_pos, subcache->data_used); - return TRUE; -} - -static SSL_SESSION *shmcb_subcache_retrieve(server_rec *s, SHMCBHeader *header, - SHMCBSubcache *subcache, UCHAR *id, - unsigned int idlen) -{ - unsigned int pos; - unsigned int loop = 0; - - /* If there are entries to expire, ditch them first. */ - shmcb_subcache_expire(s, header, subcache); - pos = subcache->idx_pos; - - while (loop < subcache->idx_used) { - SHMCBIndex *idx = SHMCB_INDEX(subcache, pos); - - /* Only consider 'idx' if; - * (a) the s_id2 byte matches - * (b) the "removed" flag isn't set. - */ - if ((idx->s_id2 == id[1]) && !idx->removed) { - SSL_SESSION *pSession; - unsigned char *s_id; - unsigned int s_idlen; - unsigned char tempasn[SSL_SESSION_MAX_DER]; - MODSSL_D2I_SSL_SESSION_CONST unsigned char *ptr = tempasn; - - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, - "possible match at idx=%d, data=%d", pos, idx->data_pos); - /* Copy the data */ - shmcb_cyclic_cton_memcpy(header->subcache_data_size, - tempasn, SHMCB_DATA(header, subcache), - idx->data_pos, idx->data_used); - /* Decode the session */ - pSession = d2i_SSL_SESSION(NULL, &ptr, idx->data_used); - if (!pSession) { - ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, - "shmcb_subcache_retrieve internal error"); - return NULL; - } - s_id = SSL_SESSION_get_session_id(pSession); - s_idlen = SSL_SESSION_get_session_id_length(pSession); - if (s_idlen == idlen && memcmp(s_id, id, idlen) == 0) { - /* Found the matching session */ - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, - "shmcb_subcache_retrieve returning matching session"); - return pSession; - } - SSL_SESSION_free(pSession); - } - /* Increment */ - loop++; - pos = SHMCB_CYCLIC_INCREMENT(pos, 1, header->index_num); - } - - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, - "shmcb_subcache_retrieve found no match"); - return NULL; -} - -static BOOL shmcb_subcache_remove(server_rec *s, SHMCBHeader *header, - SHMCBSubcache *subcache, - UCHAR *id, unsigned int idlen) -{ - unsigned int pos; - unsigned int loop = 0; - BOOL to_return = FALSE; - - /* Unlike the others, we don't do an expire-run first. This is to keep - * consistent statistics where a "remove" operation may actually be the - * higher layer spotting an expiry issue prior to us. Our caller is - * handling stats, so a failure return would be inconsistent if the - * intended session was in fact removed by an expiry run. */ - - pos = subcache->idx_pos; - while (!to_return && (loop < subcache->idx_used)) { - SHMCBIndex *idx = SHMCB_INDEX(subcache, pos); - /* Only consider 'idx' if the s_id2 byte matches and it's not already - * removed - easiest way to avoid costly ASN decodings. */ - if ((idx->s_id2 == id[1]) && !idx->removed) { - SSL_SESSION *pSession; - unsigned char *s_id; - unsigned int s_idlen; - unsigned char tempasn[SSL_SESSION_MAX_DER]; - MODSSL_D2I_SSL_SESSION_CONST unsigned char *ptr = tempasn; - - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, - "possible match at idx=%d, data=%d", pos, idx->data_pos); - /* Copy the data */ - shmcb_cyclic_cton_memcpy(header->subcache_data_size, - tempasn, SHMCB_DATA(header, subcache), - idx->data_pos, idx->data_used); - /* Decode the session */ - pSession = d2i_SSL_SESSION(NULL, &ptr, idx->data_used); - if (!pSession) { - ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, - "shmcb_subcache_remove internal error"); - return FALSE; - } - s_id = SSL_SESSION_get_session_id(pSession); - s_idlen = SSL_SESSION_get_session_id_length(pSession); - if (s_idlen == idlen && memcmp(s_id, id, idlen) == 0) { - /* Found the matching session, remove it quietly. */ - idx->removed = 1; - to_return = TRUE; - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, - "shmcb_subcache_remove removing matching session"); - } - SSL_SESSION_free(pSession); - } - /* Increment */ - loop++; - pos = SHMCB_CYCLIC_INCREMENT(pos, 1, header->index_num); - } - - return to_return; -} diff --git a/modules/ssl/ssl_toolkit_compat.h b/modules/ssl/ssl_toolkit_compat.h deleted file mode 100644 index 369516b2..00000000 --- a/modules/ssl/ssl_toolkit_compat.h +++ /dev/null @@ -1,281 +0,0 @@ -/* Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef SSL_TOOLKIT_COMPAT_H -#define SSL_TOOLKIT_COMPAT_H - -/** - * @file ssl_toolkit_compat.h - * @brief this header file provides a compatiblity layer - * between OpenSSL and RSA sslc - * - * @defgroup MOD_SSL_TOOLKIT Toolkit - * @ingroup MOD_SSL - * @{ - */ - -#ifdef HAVE_OPENSSL - -/** OpenSSL headers */ -#include <openssl/ssl.h> -#include <openssl/err.h> -#include <openssl/x509.h> -#include <openssl/pem.h> -#include <openssl/crypto.h> -#include <openssl/evp.h> -#include <openssl/rand.h> -#include <openssl/x509v3.h> -/** Avoid tripping over an engine build installed globally and detected - * when the user points at an explicit non-engine flavor of OpenSSL - */ -#if defined(HAVE_OPENSSL_ENGINE_H) && defined(HAVE_ENGINE_INIT) -#include <openssl/engine.h> -#endif - -/** - * rsa sslc uses incomplete types for most structures - * so we macroize for OpenSSL those which cannot be dereferenced - * using the same sames as the sslc functions - */ - -#define EVP_PKEY_key_type(k) (EVP_PKEY_type(k->type)) - -#define X509_NAME_get_entries(xs) (xs->entries) -#define X509_REVOKED_get_serialNumber(xs) (xs->serialNumber) - -#define X509_get_signature_algorithm(xs) (xs->cert_info->signature->algorithm) -#define X509_get_key_algorithm(xs) (xs->cert_info->key->algor->algorithm) - -#define X509_NAME_ENTRY_get_data_ptr(xs) (xs->value->data) -#define X509_NAME_ENTRY_get_data_len(xs) (xs->value->length) - -#define SSL_CTX_get_extra_certs(ctx) (ctx->extra_certs) -#define SSL_CTX_set_extra_certs(ctx,value) {ctx->extra_certs = value;} - -#define SSL_CIPHER_get_name(s) (s->name) -#define SSL_CIPHER_get_valid(s) (s->valid) - -#define SSL_SESSION_get_session_id(s) (s->session_id) -#define SSL_SESSION_get_session_id_length(s) (s->session_id_length) - -/** - * Support for retrieving/overriding states - */ -#ifndef SSL_get_state -#define SSL_get_state(ssl) SSL_state(ssl) -#endif - -#define SSL_set_state(ssl,val) (ssl)->state = val - -#define MODSSL_BIO_CB_ARG_TYPE const char -#define MODSSL_CRYPTO_CB_ARG_TYPE const char -#if (OPENSSL_VERSION_NUMBER < 0x00907000) -# define MODSSL_INFO_CB_ARG_TYPE SSL* -#else -# define MODSSL_INFO_CB_ARG_TYPE const SSL* -#endif -#define MODSSL_CLIENT_CERT_CB_ARG_TYPE X509 -#define MODSSL_PCHAR_CAST - -/** ...shifting sands of openssl... */ -#if (OPENSSL_VERSION_NUMBER >= 0x0090707f) -# define MODSSL_D2I_SSL_SESSION_CONST const -# define MODSSL_SSL_CIPHER_CONST const -#else -# define MODSSL_D2I_SSL_SESSION_CONST -# define MODSSL_SSL_CIPHER_CONST -#endif - -#if (OPENSSL_VERSION_NUMBER >= 0x00908000) -# define MODSSL_D2I_PrivateKey_CONST const -# define MODSSL_D2I_X509_CONST const -#else -# define MODSSL_D2I_PrivateKey_CONST -# define MODSSL_D2I_X509_CONST -#endif - -#if (OPENSSL_VERSION_NUMBER >= 0x00909000) -# define MODSSL_SSL_METHOD_CONST const -#else -# define MODSSL_SSL_METHOD_CONST -#endif - -#define modssl_X509_verify_cert X509_verify_cert - -typedef int (modssl_read_bio_cb_fn)(char*,int,int,void*); - -#if (OPENSSL_VERSION_NUMBER < 0x00904000) -#define modssl_PEM_read_bio_X509(b, x, cb, arg) PEM_read_bio_X509(b, x, cb) -#else -#define modssl_PEM_read_bio_X509(b, x, cb, arg) PEM_read_bio_X509(b, x, cb, arg) -#endif - -#define modssl_PEM_X509_INFO_read_bio PEM_X509_INFO_read_bio - -#define modssl_PEM_read_bio_PrivateKey PEM_read_bio_PrivateKey - -#define modssl_set_cipher_list SSL_set_cipher_list - -#define modssl_free OPENSSL_free - -#define EVP_PKEY_reference_inc(pkey) \ - CRYPTO_add(&((pkey)->references), +1, CRYPTO_LOCK_X509_PKEY) - -#define X509_reference_inc(cert) \ - CRYPTO_add(&((cert)->references), +1, CRYPTO_LOCK_X509) - -#define HAVE_SSL_RAND_EGD /* since 9.5.1 */ - -#define HAVE_SSL_X509V3_EXT_d2i - -#if (OPENSSL_VERSION_NUMBER >= 0x009080a0) && defined(OPENSSL_FIPS) -#define HAVE_FIPS -#endif - -#ifndef PEM_F_DEF_CALLBACK -#ifdef PEM_F_PEM_DEF_CALLBACK -/** In OpenSSL 0.9.8 PEM_F_DEF_CALLBACK was renamed */ -#define PEM_F_DEF_CALLBACK PEM_F_PEM_DEF_CALLBACK -#endif -#endif - -#elif defined(HAVE_SSLC) - -#include <bio.h> -#include <ssl.h> -#include <err.h> -#include <x509.h> -#include <pem.h> -#include <evp.h> -#include <objects.h> -#include <sslc.h> - -/** sslc does not support this function, OpenSSL has since 9.5.1 */ -#define RAND_status() 1 - -/** sslc names this function a bit differently */ -#define CRYPTO_num_locks() CRYPTO_get_num_locks() - -#ifndef STACK_OF -#define STACK_OF(type) STACK -#endif - -#define MODSSL_BIO_CB_ARG_TYPE char -#define MODSSL_CRYPTO_CB_ARG_TYPE char -#define MODSSL_INFO_CB_ARG_TYPE SSL* -#define MODSSL_CLIENT_CERT_CB_ARG_TYPE void -#define MODSSL_PCHAR_CAST (char *) -#define MODSSL_D2I_SSL_SESSION_CONST -#define MODSSL_D2I_PrivateKey_CONST -#define MODSSL_D2I_X509_CONST - -typedef int (modssl_read_bio_cb_fn)(char*,int,int); - -#define modssl_X509_verify_cert(c) X509_verify_cert(c, NULL) - -#define modssl_PEM_read_bio_X509(b, x, cb, arg) \ - PEM_read_bio_X509(b, x, cb) - -#define modssl_PEM_X509_INFO_read_bio(b, x, cb, arg)\ - PEM_X509_INFO_read_bio(b, x, cb) - -#define modssl_PEM_read_bio_PrivateKey(b, k, cb, arg) \ - PEM_read_bio_PrivateKey(b, k, cb) - -#ifndef HAVE_SSL_SET_STATE -#define SSL_set_state(ssl, state) /** XXX: should throw an error */ -#endif - -#define modssl_set_cipher_list(ssl, l) \ - SSL_set_cipher_list(ssl, (char *)l) - -#define modssl_free free - -#ifndef PEM_F_DEF_CALLBACK -#define PEM_F_DEF_CALLBACK PEM_F_DEF_CB -#endif - -#if SSLC_VERSION_NUMBER < 0x2000 - -#define X509_STORE_CTX_set_depth(st, d) -#define X509_CRL_get_lastUpdate(x) ((x)->crl->lastUpdate) -#define X509_CRL_get_nextUpdate(x) ((x)->crl->nextUpdate) -#define X509_CRL_get_REVOKED(x) ((x)->crl->revoked) -#define X509_REVOKED_get_serialNumber(xs) (xs->serialNumber) - -#define modssl_set_verify(ssl, verify, cb) \ - SSL_set_verify(ssl, verify) - -#else /** SSLC_VERSION_NUMBER >= 0x2000 */ - -#define CRYPTO_malloc_init R_malloc_init - -#define EVP_cleanup() - -#endif /** SSLC_VERSION_NUMBER >= 0x2000 */ - -typedef void (*modssl_popfree_fn)(char *data); - -#define sk_SSL_CIPHER_dup sk_dup -#define sk_SSL_CIPHER_find(st, data) sk_find(st, (void *)data) -#define sk_SSL_CIPHER_free sk_free -#define sk_SSL_CIPHER_num sk_num -#define sk_SSL_CIPHER_value (SSL_CIPHER *)sk_value -#define sk_X509_num sk_num -#define sk_X509_push sk_push -#define sk_X509_pop_free(st, free) sk_pop_free((STACK*)(st), (modssl_popfree_fn)(free)) -#define sk_X509_value (X509 *)sk_value -#define sk_X509_INFO_free sk_free -#define sk_X509_INFO_pop_free(st, free) sk_pop_free((STACK*)(st), (modssl_popfree_fn)(free)) -#define sk_X509_INFO_num sk_num -#define sk_X509_INFO_new_null sk_new_null -#define sk_X509_INFO_value (X509_INFO *)sk_value -#define sk_X509_NAME_find(st, data) sk_find(st, (void *)data) -#define sk_X509_NAME_free sk_free -#define sk_X509_NAME_new sk_new -#define sk_X509_NAME_num sk_num -#define sk_X509_NAME_push(st, data) sk_push(st, (void *)data) -#define sk_X509_NAME_value (X509_NAME *)sk_value -#define sk_X509_NAME_ENTRY_num sk_num -#define sk_X509_NAME_ENTRY_value (X509_NAME_ENTRY *)sk_value -#define sk_X509_NAME_set_cmp_func sk_set_cmp_func -#define sk_X509_REVOKED_num sk_num -#define sk_X509_REVOKED_value (X509_REVOKED *)sk_value - -#else /** ! HAVE_OPENSSL && ! HAVE_SSLC */ - -#error "Unrecognized SSL Toolkit!" - -#endif /* ! HAVE_OPENSSL && ! HAVE_SSLC */ - -#ifndef modssl_set_verify -#define modssl_set_verify(ssl, verify, cb) \ - SSL_set_verify(ssl, verify, cb) -#endif - -#ifndef SSL_SESS_CACHE_NO_INTERNAL -#define SSL_SESS_CACHE_NO_INTERNAL SSL_SESS_CACHE_NO_INTERNAL_LOOKUP -#endif - -#ifndef OPENSSL_NO_TLSEXT -#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME -#define OPENSSL_NO_TLSEXT -#endif -#endif - -#endif /* SSL_TOOLKIT_COMPAT_H */ - -/** @} */ diff --git a/modules/ssl/ssl_util.c b/modules/ssl/ssl_util.c index e4387e61..6b5a7de6 100644 --- a/modules/ssl/ssl_util.c +++ b/modules/ssl/ssl_util.c @@ -125,6 +125,8 @@ BOOL ssl_util_path_check(ssl_pathcheck_t pcm, const char *path, apr_pool_t *p) if (pcm & SSL_PCM_EXISTS && apr_stat(&finfo, path, APR_FINFO_TYPE|APR_FINFO_SIZE, p) != 0) return FALSE; + AP_DEBUG_ASSERT((pcm & SSL_PCM_EXISTS) || + !(pcm & (SSL_PCM_ISREG|SSL_PCM_ISDIR|SSL_PCM_ISNONZERO))); if (pcm & SSL_PCM_ISREG && finfo.filetype != APR_REG) return FALSE; if (pcm & SSL_PCM_ISDIR && finfo.filetype != APR_DIR) @@ -143,22 +145,24 @@ ssl_algo_t ssl_util_algotypeof(X509 *pCert, EVP_PKEY *pKey) if (pCert != NULL) pFreeKey = pKey = X509_get_pubkey(pCert); if (pKey != NULL) { - switch (EVP_PKEY_key_type(pKey)) { + switch (EVP_PKEY_type(pKey->type)) { case EVP_PKEY_RSA: t = SSL_ALGO_RSA; break; case EVP_PKEY_DSA: t = SSL_ALGO_DSA; break; +#ifndef OPENSSL_NO_EC + case EVP_PKEY_EC: + t = SSL_ALGO_ECC; + break; +#endif default: break; } } -#ifdef OPENSSL_VERSION_NUMBER - /* Only refcounted in OpenSSL */ if (pFreeKey != NULL) EVP_PKEY_free(pFreeKey); -#endif return t; } @@ -174,6 +178,11 @@ char *ssl_util_algotypestr(ssl_algo_t t) case SSL_ALGO_DSA: cp = "DSA"; break; +#ifndef OPENSSL_NO_EC + case SSL_ALGO_ECC: + cp = "ECC"; + break; +#endif default: break; } @@ -206,14 +215,14 @@ unsigned char *ssl_asn1_table_set(apr_hash_t *table, } } else { - asn1 = malloc(sizeof(*asn1)); + asn1 = ap_malloc(sizeof(*asn1)); asn1->source_mtime = 0; /* used as a note for encrypted private keys */ asn1->cpData = NULL; } asn1->nData = length; if (!asn1->cpData) { - asn1->cpData = malloc(length); + asn1->cpData = ap_malloc(length); } apr_hash_set(table, key, klen, asn1); @@ -245,7 +254,11 @@ void ssl_asn1_table_unset(apr_hash_t *table, apr_hash_set(table, key, klen, NULL); } +#ifndef OPENSSL_NO_EC +static const char *ssl_asn1_key_types[] = {"RSA", "DSA", "ECC"}; +#else static const char *ssl_asn1_key_types[] = {"RSA", "DSA"}; +#endif const char *ssl_asn1_keystr(int keytype) { @@ -265,6 +278,56 @@ const char *ssl_asn1_table_keyfmt(apr_pool_t *p, return apr_pstrcat(p, id, ":", keystr, NULL); } +STACK_OF(X509) *ssl_read_pkcs7(server_rec *s, const char *pkcs7) +{ + PKCS7 *p7; + STACK_OF(X509) *certs = NULL; + FILE *f; + + f = fopen(pkcs7, "r"); + if (!f) { + ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02212) "Can't open %s", pkcs7); + ssl_die(); + } + + p7 = PEM_read_PKCS7(f, NULL, NULL, NULL); + if (!p7) { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(02274) + "Can't read PKCS7 object %s", pkcs7); + ssl_log_ssl_error(SSLLOG_MARK, APLOG_CRIT, s); + exit(1); + } + + switch (OBJ_obj2nid(p7->type)) { + case NID_pkcs7_signed: + certs = p7->d.sign->cert; + p7->d.sign->cert = NULL; + PKCS7_free(p7); + break; + + case NID_pkcs7_signedAndEnveloped: + certs = p7->d.signed_and_enveloped->cert; + p7->d.signed_and_enveloped->cert = NULL; + PKCS7_free(p7); + break; + + default: + ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02213) + "Don't understand PKCS7 file %s", pkcs7); + ssl_die(); + } + + if (!certs) { + ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02214) + "No certificates in %s", pkcs7); + ssl_die(); + } + + fclose(f); + + return certs; +} + #if APR_HAS_THREADS /* @@ -274,18 +337,8 @@ const char *ssl_asn1_table_keyfmt(apr_pool_t *p, static apr_thread_mutex_t **lock_cs; static int lock_num_locks; -#ifdef HAVE_SSLC -#if SSLC_VERSION_NUMBER >= 0x2000 -static int ssl_util_thr_lock(int mode, int type, - char *file, int line) -#else -static void ssl_util_thr_lock(int mode, int type, - char *file, int line) -#endif -#else static void ssl_util_thr_lock(int mode, int type, const char *file, int line) -#endif { if (type < lock_num_locks) { if (mode & CRYPTO_LOCK) { @@ -294,21 +347,13 @@ static void ssl_util_thr_lock(int mode, int type, else { apr_thread_mutex_unlock(lock_cs[type]); } -#ifdef HAVE_SSLC -#if SSLC_VERSION_NUMBER >= 0x2000 - return 1; - } - else { - return -1; -#endif -#endif } } /* Dynamic lock structure */ struct CRYPTO_dynlock_value { apr_pool_t *pool; - const char* file; + const char* file; int line; apr_thread_mutex_t *mutex; }; @@ -319,45 +364,45 @@ apr_pool_t *dynlockpool = NULL; /* * Dynamic lock creation callback */ -static struct CRYPTO_dynlock_value *ssl_dyn_create_function(const char *file, +static struct CRYPTO_dynlock_value *ssl_dyn_create_function(const char *file, int line) { struct CRYPTO_dynlock_value *value; apr_pool_t *p; apr_status_t rv; - /* + /* * We need a pool to allocate our mutex. Since we can't clear * allocated memory from a pool, create a subpool that we can blow - * away in the destruction callback. + * away in the destruction callback. */ rv = apr_pool_create(&p, dynlockpool); if (rv != APR_SUCCESS) { - ap_log_perror(file, line, APLOG_ERR, rv, dynlockpool, - "Failed to create subpool for dynamic lock"); + ap_log_perror(file, line, APLOG_MODULE_INDEX, APLOG_ERR, rv, dynlockpool, + APLOGNO(02183) "Failed to create subpool for dynamic lock"); return NULL; } - ap_log_perror(file, line, APLOG_DEBUG, 0, p, + ap_log_perror(file, line, APLOG_MODULE_INDEX, APLOG_TRACE1, 0, p, "Creating dynamic lock"); - - value = (struct CRYPTO_dynlock_value *)apr_palloc(p, + + value = (struct CRYPTO_dynlock_value *)apr_palloc(p, sizeof(struct CRYPTO_dynlock_value)); if (!value) { - ap_log_perror(file, line, APLOG_ERR, 0, p, - "Failed to allocate dynamic lock structure"); + ap_log_perror(file, line, APLOG_MODULE_INDEX, APLOG_ERR, 0, p, + APLOGNO(02185) "Failed to allocate dynamic lock structure"); return NULL; } - + value->pool = p; /* Keep our own copy of the place from which we were created, using our own pool. */ value->file = apr_pstrdup(p, file); value->line = line; - rv = apr_thread_mutex_create(&(value->mutex), APR_THREAD_MUTEX_DEFAULT, + rv = apr_thread_mutex_create(&(value->mutex), APR_THREAD_MUTEX_DEFAULT, p); if (rv != APR_SUCCESS) { - ap_log_perror(file, line, APLOG_ERR, rv, p, + ap_log_perror(file, line, APLOG_MODULE_INDEX, APLOG_ERR, rv, p, APLOGNO(02186) "Failed to create thread mutex for dynamic lock"); apr_pool_destroy(p); return NULL; @@ -375,17 +420,17 @@ static void ssl_dyn_lock_function(int mode, struct CRYPTO_dynlock_value *l, apr_status_t rv; if (mode & CRYPTO_LOCK) { - ap_log_perror(file, line, APLOG_DEBUG, 0, l->pool, + ap_log_perror(file, line, APLOG_MODULE_INDEX, APLOG_TRACE3, 0, l->pool, "Acquiring mutex %s:%d", l->file, l->line); rv = apr_thread_mutex_lock(l->mutex); - ap_log_perror(file, line, APLOG_DEBUG, rv, l->pool, + ap_log_perror(file, line, APLOG_MODULE_INDEX, APLOG_TRACE3, rv, l->pool, "Mutex %s:%d acquired!", l->file, l->line); } else { - ap_log_perror(file, line, APLOG_DEBUG, 0, l->pool, + ap_log_perror(file, line, APLOG_MODULE_INDEX, APLOG_TRACE3, 0, l->pool, "Releasing mutex %s:%d", l->file, l->line); rv = apr_thread_mutex_unlock(l->mutex); - ap_log_perror(file, line, APLOG_DEBUG, rv, l->pool, + ap_log_perror(file, line, APLOG_MODULE_INDEX, APLOG_TRACE3, rv, l->pool, "Mutex %s:%d released!", l->file, l->line); } } @@ -393,18 +438,18 @@ static void ssl_dyn_lock_function(int mode, struct CRYPTO_dynlock_value *l, /* * Dynamic lock destruction callback */ -static void ssl_dyn_destroy_function(struct CRYPTO_dynlock_value *l, +static void ssl_dyn_destroy_function(struct CRYPTO_dynlock_value *l, const char *file, int line) { apr_status_t rv; - ap_log_perror(file, line, APLOG_DEBUG, 0, l->pool, + ap_log_perror(file, line, APLOG_MODULE_INDEX, APLOG_TRACE1, 0, l->pool, "Destroying dynamic lock %s:%d", l->file, l->line); rv = apr_thread_mutex_destroy(l->mutex); if (rv != APR_SUCCESS) { - ap_log_perror(file, line, APLOG_ERR, rv, l->pool, - "Failed to destroy mutex for dynamic lock %s:%d", - l->file, l->line); + ap_log_perror(file, line, APLOG_MODULE_INDEX, APLOG_ERR, rv, l->pool, + APLOGNO(02192) "Failed to destroy mutex for dynamic " + "lock %s:%d", l->file, l->line); } /* Trust that whomever owned the CRYPTO_dynlock_value we were @@ -435,11 +480,11 @@ static apr_status_t ssl_util_thread_cleanup(void *data) { CRYPTO_set_locking_callback(NULL); CRYPTO_set_id_callback(NULL); - + CRYPTO_set_dynlock_create_callback(NULL); CRYPTO_set_dynlock_lock_callback(NULL); CRYPTO_set_dynlock_destroy_callback(NULL); - + dynlockpool = NULL; /* Let the registered mutex cleanups do their own thing @@ -461,9 +506,9 @@ void ssl_util_thread_setup(apr_pool_t *p) CRYPTO_set_id_callback(ssl_util_thr_id); CRYPTO_set_locking_callback(ssl_util_thr_lock); - + /* Set up dynamic locking scaffolding for OpenSSL to use at its - * convenience. + * convenience. */ dynlockpool = p; CRYPTO_set_dynlock_create_callback(ssl_dyn_create_function); diff --git a/modules/ssl/ssl_util_ocsp.c b/modules/ssl/ssl_util_ocsp.c new file mode 100644 index 00000000..94ef4cd0 --- /dev/null +++ b/modules/ssl/ssl_util_ocsp.c @@ -0,0 +1,308 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* This file implements an OCSP client including a toy HTTP/1.0 + * client. Once httpd depends on a real HTTP client library, most of + * this can be thrown away. */ + +#include "ssl_private.h" + +#ifndef OPENSSL_NO_OCSP + +#include "apr_buckets.h" +#include "apr_uri.h" + +/* Serialize an OCSP request which will be sent to the responder at + * given URI to a memory BIO object, which is returned. */ +static BIO *serialize_request(OCSP_REQUEST *req, const apr_uri_t *uri) +{ + BIO *bio; + int len; + + len = i2d_OCSP_REQUEST(req, NULL); + + bio = BIO_new(BIO_s_mem()); + + BIO_printf(bio, "POST %s%s%s HTTP/1.0\r\n" + "Host: %s:%d\r\n" + "Content-Type: application/ocsp-request\r\n" + "Content-Length: %d\r\n" + "\r\n", + uri->path ? uri->path : "/", + uri->query ? "?" : "", uri->query ? uri->query : "", + uri->hostname, uri->port, len); + + if (i2d_OCSP_REQUEST_bio(bio, req) != 1) { + BIO_free(bio); + return NULL; + } + + return bio; +} + +/* Send the OCSP request serialized into BIO 'request' to the + * responder at given server given by URI. Returns socket object or + * NULL on error. */ +static apr_socket_t *send_request(BIO *request, const apr_uri_t *uri, + apr_interval_time_t timeout, + conn_rec *c, apr_pool_t *p) +{ + apr_status_t rv; + apr_sockaddr_t *sa; + apr_socket_t *sd; + char buf[HUGE_STRING_LEN]; + int len; + + rv = apr_sockaddr_info_get(&sa, uri->hostname, APR_UNSPEC, uri->port, 0, p); + if (rv) { + ap_log_cerror(APLOG_MARK, APLOG_ERR, rv, c, APLOGNO(01972) + "could not resolve address of OCSP responder %s", + uri->hostinfo); + return NULL; + } + + /* establish a connection to the OCSP responder */ + ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(01973) + "connecting to OCSP responder '%s'", uri->hostinfo); + + /* Cycle through address until a connect() succeeds. */ + for (; sa; sa = sa->next) { + rv = apr_socket_create(&sd, sa->family, SOCK_STREAM, APR_PROTO_TCP, p); + if (rv == APR_SUCCESS) { + apr_socket_timeout_set(sd, timeout); + + rv = apr_socket_connect(sd, sa); + if (rv == APR_SUCCESS) { + break; + } + apr_socket_close(sd); + } + } + + if (sa == NULL) { + ap_log_cerror(APLOG_MARK, APLOG_ERR, rv, c, APLOGNO(01974) + "could not connect to OCSP responder '%s'", + uri->hostinfo); + apr_socket_close(sd); + return NULL; + } + + /* send the request and get a response */ + ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(01975) + "sending request to OCSP responder"); + + while ((len = BIO_read(request, buf, sizeof buf)) > 0) { + char *wbuf = buf; + apr_size_t remain = len; + + do { + apr_size_t wlen = remain; + + rv = apr_socket_send(sd, wbuf, &wlen); + wbuf += remain; + remain -= wlen; + } while (rv == APR_SUCCESS && remain > 0); + + if (rv) { + apr_socket_close(sd); + ap_log_cerror(APLOG_MARK, APLOG_ERR, rv, c, APLOGNO(01976) + "failed to send request to OCSP responder '%s'", + uri->hostinfo); + return NULL; + } + } + + return sd; +} + +/* Return a pool-allocated NUL-terminated line, with CRLF stripped, + * read from brigade 'bbin' using 'bbout' as temporary storage. */ +static char *get_line(apr_bucket_brigade *bbout, apr_bucket_brigade *bbin, + conn_rec *c, apr_pool_t *p) +{ + apr_status_t rv; + apr_size_t len; + char *line; + + apr_brigade_cleanup(bbout); + + rv = apr_brigade_split_line(bbout, bbin, APR_BLOCK_READ, 8192); + if (rv) { + ap_log_cerror(APLOG_MARK, APLOG_ERR, rv, c, APLOGNO(01977) + "failed reading line from OCSP server"); + return NULL; + } + + rv = apr_brigade_pflatten(bbout, &line, &len, p); + if (rv) { + ap_log_cerror(APLOG_MARK, APLOG_ERR, rv, c, APLOGNO(01978) + "failed reading line from OCSP server"); + return NULL; + } + + if (len && line[len-1] != APR_ASCII_LF) { + ap_log_cerror(APLOG_MARK, APLOG_ERR, rv, c, APLOGNO(01979) + "response header line too long from OCSP server"); + return NULL; + } + + line[len-1] = '\0'; + if (len > 1 && line[len-2] == APR_ASCII_CR) { + line[len-2] = '\0'; + } + + return line; +} + +/* Maximum values to prevent eating RAM forever. */ +#define MAX_HEADERS (256) +#define MAX_CONTENT (2048 * 1024) + +/* Read the OCSP response from the socket 'sd', using temporary memory + * BIO 'bio', and return the decoded OCSP response object, or NULL on + * error. */ +static OCSP_RESPONSE *read_response(apr_socket_t *sd, BIO *bio, conn_rec *c, + apr_pool_t *p) +{ + apr_bucket_brigade *bb, *tmpbb; + OCSP_RESPONSE *response; + char *line; + apr_size_t count; + apr_int64_t code; + + /* Using brigades for response parsing is much simpler than using + * apr_socket_* directly. */ + bb = apr_brigade_create(p, c->bucket_alloc); + tmpbb = apr_brigade_create(p, c->bucket_alloc); + APR_BRIGADE_INSERT_TAIL(bb, apr_bucket_socket_create(sd, c->bucket_alloc)); + + line = get_line(tmpbb, bb, c, p); + if (!line || strncmp(line, "HTTP/", 5) + || (line = ap_strchr(line, ' ')) == NULL + || (code = apr_atoi64(++line)) < 200 || code > 299) { + ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(01980) + "bad response from OCSP server: %s", + line ? line : "(none)"); + return NULL; + } + + /* Read till end of headers; don't have to even bother parsing the + * Content-Length since the server is obliged to close the + * connection after the response anyway for HTTP/1.0. */ + count = 0; + while ((line = get_line(tmpbb, bb, c, p)) != NULL && line[0] + && ++count < MAX_HEADERS) { + ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(01981) + "OCSP response header: %s", line); + } + + if (count == MAX_HEADERS) { + ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(01982) + "could not read response headers from OCSP server, " + "exceeded maximum count (%u)", MAX_HEADERS); + return NULL; + } + else if (!line) { + ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(01983) + "could not read response header from OCSP server"); + return NULL; + } + + /* Read the response body into the memory BIO. */ + count = 0; + while (!APR_BRIGADE_EMPTY(bb)) { + const char *data; + apr_size_t len; + apr_status_t rv; + apr_bucket *e = APR_BRIGADE_FIRST(bb); + + rv = apr_bucket_read(e, &data, &len, APR_BLOCK_READ); + if (rv == APR_EOF || (rv == APR_SUCCESS && len == 0)) { + ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(01984) + "OCSP response: got EOF"); + break; + } + if (rv != APR_SUCCESS) { + ap_log_cerror(APLOG_MARK, APLOG_ERR, rv, c, APLOGNO(01985) + "error reading response from OCSP server"); + return NULL; + } + count += len; + if (count > MAX_CONTENT) { + ap_log_cerror(APLOG_MARK, APLOG_ERR, rv, c, APLOGNO(01986) + "OCSP response size exceeds %u byte limit", + MAX_CONTENT); + return NULL; + } + ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(01987) + "OCSP response: got %" APR_SIZE_T_FMT + " bytes, %" APR_SIZE_T_FMT " total", len, count); + + BIO_write(bio, data, (int)len); + apr_bucket_delete(e); + } + + apr_brigade_destroy(bb); + apr_brigade_destroy(tmpbb); + + /* Finally decode the OCSP response from what's stored in the + * bio. */ + response = d2i_OCSP_RESPONSE_bio(bio, NULL); + if (response == NULL) { + ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(01988) + "failed to decode OCSP response data"); + ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, mySrvFromConn(c)); + } + + return response; +} + +OCSP_RESPONSE *modssl_dispatch_ocsp_request(const apr_uri_t *uri, + apr_interval_time_t timeout, + OCSP_REQUEST *request, + conn_rec *c, apr_pool_t *p) +{ + OCSP_RESPONSE *response = NULL; + apr_socket_t *sd; + BIO *bio; + + bio = serialize_request(request, uri); + if (bio == NULL) { + ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(01989) + "could not serialize OCSP request"); + ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, mySrvFromConn(c)); + return NULL; + } + + sd = send_request(bio, uri, timeout, c, p); + if (sd == NULL) { + /* Errors already logged. */ + BIO_free(bio); + return NULL; + } + + /* Clear the BIO contents, ready for the response. */ + (void)BIO_reset(bio); + + response = read_response(sd, bio, c, p); + + apr_socket_close(sd); + BIO_free(bio); + + return response; +} + +#endif /* HAVE_OCSP */ diff --git a/modules/ssl/ssl_util_ssl.c b/modules/ssl/ssl_util_ssl.c index a06b6504..5022d0da 100644 --- a/modules/ssl/ssl_util_ssl.c +++ b/modules/ssl/ssl_util_ssl.c @@ -74,7 +74,7 @@ void SSL_set_app_data2(SSL *ssl, void *arg) ** _________________________________________________________________ */ -X509 *SSL_read_X509(char* filename, X509 **x509, modssl_read_bio_cb_fn *cb) +X509 *SSL_read_X509(char* filename, X509 **x509, pem_password_cb *cb) { X509 *rc; BIO *bioS; @@ -83,7 +83,7 @@ X509 *SSL_read_X509(char* filename, X509 **x509, modssl_read_bio_cb_fn *cb) /* 1. try PEM (= DER+Base64+headers) */ if ((bioS=BIO_new_file(filename, "r")) == NULL) return NULL; - rc = modssl_PEM_read_bio_X509 (bioS, x509, cb, NULL); + rc = PEM_read_bio_X509 (bioS, x509, cb, NULL); BIO_free(bioS); if (rc == NULL) { @@ -115,17 +115,7 @@ X509 *SSL_read_X509(char* filename, X509 **x509, modssl_read_bio_cb_fn *cb) return rc; } -#if SSL_LIBRARY_VERSION <= 0x00904100 -static EVP_PKEY *d2i_PrivateKey_bio(BIO *bio, EVP_PKEY **key) -{ - return ((EVP_PKEY *)ASN1_d2i_bio( - (char *(*)())EVP_PKEY_new, - (char *(*)())d2i_PrivateKey, - (bio), (unsigned char **)(key))); -} -#endif - -EVP_PKEY *SSL_read_PrivateKey(char* filename, EVP_PKEY **key, modssl_read_bio_cb_fn *cb, void *s) +EVP_PKEY *SSL_read_PrivateKey(char* filename, EVP_PKEY **key, pem_password_cb *cb, void *s) { EVP_PKEY *rc; BIO *bioS; @@ -134,7 +124,7 @@ EVP_PKEY *SSL_read_PrivateKey(char* filename, EVP_PKEY **key, modssl_read_bio_cb /* 1. try PEM (= DER+Base64+headers) */ if ((bioS=BIO_new_file(filename, "r")) == NULL) return NULL; - rc = modssl_PEM_read_bio_PrivateKey(bioS, key, cb, s); + rc = PEM_read_bio_PrivateKey(bioS, key, cb, s); BIO_free(bioS); if (rc == NULL) { @@ -194,55 +184,6 @@ int SSL_smart_shutdown(SSL *ssl) /* _________________________________________________________________ ** -** Certificate Revocation List (CRL) Storage -** _________________________________________________________________ -*/ - -X509_STORE *SSL_X509_STORE_create(char *cpFile, char *cpPath) -{ - X509_STORE *pStore; - X509_LOOKUP *pLookup; - int rv = 1; - - ERR_clear_error(); - - if (cpFile == NULL && cpPath == NULL) - return NULL; - if ((pStore = X509_STORE_new()) == NULL) - return NULL; - if (cpFile != NULL) { - pLookup = X509_STORE_add_lookup(pStore, X509_LOOKUP_file()); - if (pLookup == NULL) { - X509_STORE_free(pStore); - return NULL; - } - rv = X509_LOOKUP_load_file(pLookup, cpFile, X509_FILETYPE_PEM); - } - if (cpPath != NULL && rv == 1) { - pLookup = X509_STORE_add_lookup(pStore, X509_LOOKUP_hash_dir()); - if (pLookup == NULL) { - X509_STORE_free(pStore); - return NULL; - } - rv = X509_LOOKUP_add_dir(pLookup, cpPath, X509_FILETYPE_PEM); - } - return rv == 1 ? pStore : NULL; -} - -int SSL_X509_STORE_lookup(X509_STORE *pStore, int nType, - X509_NAME *pName, X509_OBJECT *pObj) -{ - X509_STORE_CTX pStoreCtx; - int rc; - - X509_STORE_CTX_init(&pStoreCtx, pStore, NULL, NULL); - rc = X509_STORE_get_by_subject(&pStoreCtx, nType, pName, pObj); - X509_STORE_CTX_cleanup(&pStoreCtx); - return rc; -} - -/* _________________________________________________________________ -** ** Cipher Suite Spec String Creation ** _________________________________________________________________ */ @@ -275,7 +216,7 @@ char *SSL_make_ciphersuite(apr_pool_t *p, SSL *ssl) memcpy(cp, SSL_CIPHER_get_name(c), l); cp += l; *cp++ = '/'; - *cp++ = (SSL_CIPHER_get_valid(c) == 1 ? '1' : '0'); + *cp++ = (c->valid == 1 ? '1' : '0'); *cp++ = ':'; } *(cp-1) = NUL; @@ -291,50 +232,35 @@ char *SSL_make_ciphersuite(apr_pool_t *p, SSL *ssl) /* check whether cert contains extended key usage with a SGC tag */ BOOL SSL_X509_isSGC(X509 *cert) { -#ifdef HAVE_SSL_X509V3_EXT_d2i - X509_EXTENSION *ext; int ext_nid; EXTENDED_KEY_USAGE *sk; BOOL is_sgc; - int idx; int i; is_sgc = FALSE; - idx = X509_get_ext_by_NID(cert, NID_ext_key_usage, -1); - if (idx >= 0) { - ext = X509_get_ext(cert, idx); - if ((sk = (EXTENDED_KEY_USAGE *)X509V3_EXT_d2i(ext)) != NULL) { - for (i = 0; i < sk_ASN1_OBJECT_num(sk); i++) { - ext_nid = OBJ_obj2nid((ASN1_OBJECT *)sk_ASN1_OBJECT_value(sk, i)); - if (ext_nid == NID_ms_sgc || ext_nid == NID_ns_sgc) { - is_sgc = TRUE; - break; - } + sk = X509_get_ext_d2i(cert, NID_ext_key_usage, NULL, NULL); + if (sk) { + for (i = 0; i < sk_ASN1_OBJECT_num(sk); i++) { + ext_nid = OBJ_obj2nid(sk_ASN1_OBJECT_value(sk, i)); + if (ext_nid == NID_ms_sgc || ext_nid == NID_ns_sgc) { + is_sgc = TRUE; + break; } } + EXTENDED_KEY_USAGE_free(sk); } return is_sgc; -#else - return FALSE; -#endif } /* retrieve basic constraints ingredients */ BOOL SSL_X509_getBC(X509 *cert, int *ca, int *pathlen) { -#ifdef HAVE_SSL_X509V3_EXT_d2i - X509_EXTENSION *ext; BASIC_CONSTRAINTS *bc; - int idx; BIGNUM *bn = NULL; char *cp; - if ((idx = X509_get_ext_by_NID(cert, NID_basic_constraints, -1)) < 0) - return FALSE; - ext = X509_get_ext(cert, idx); - if (ext == NULL) - return FALSE; - if ((bc = (BASIC_CONSTRAINTS *)X509V3_EXT_d2i(ext)) == NULL) + bc = X509_get_ext_d2i(cert, NID_basic_constraints, NULL, NULL); + if (bc == NULL) return FALSE; *ca = bc->ca; *pathlen = -1 /* unlimited */; @@ -349,37 +275,108 @@ BOOL SSL_X509_getBC(X509 *cert, int *ca, int *pathlen) } BASIC_CONSTRAINTS_free(bc); return TRUE; -#else - return FALSE; -#endif } -/* retrieve subject CommonName of certificate */ -BOOL SSL_X509_getCN(apr_pool_t *p, X509 *xs, char **cppCN) +/* convert a NAME_ENTRY to UTF8 string */ +char *SSL_X509_NAME_ENTRY_to_string(apr_pool_t *p, X509_NAME_ENTRY *xsne) +{ + char *result = NULL; + BIO* bio; + int len; + + if ((bio = BIO_new(BIO_s_mem())) == NULL) + return NULL; + ASN1_STRING_print_ex(bio, X509_NAME_ENTRY_get_data(xsne), + ASN1_STRFLGS_ESC_CTRL|ASN1_STRFLGS_UTF8_CONVERT); + len = BIO_pending(bio); + result = apr_palloc(p, len+1); + len = BIO_read(bio, result, len); + result[len] = NUL; + BIO_free(bio); + ap_xlate_proto_from_ascii(result, len); + return result; +} + +/* + * convert an X509_NAME to an RFC 2253 formatted string, optionally truncated + * to maxlen characters (specify a maxlen of 0 for no length limit) + */ +char *SSL_X509_NAME_to_string(apr_pool_t *p, X509_NAME *dn, unsigned int maxlen) { - X509_NAME *xsn; - X509_NAME_ENTRY *xsne; - int i, nid; - unsigned char *data_ptr; - int data_len; - - xsn = X509_get_subject_name(xs); - for (i = 0; i < sk_X509_NAME_ENTRY_num((STACK_OF(X509_NAME_ENTRY) *) - X509_NAME_get_entries(xsn)); i++) { - xsne = sk_X509_NAME_ENTRY_value((STACK_OF(X509_NAME_ENTRY) *) - X509_NAME_get_entries(xsn), i); - nid = OBJ_obj2nid((ASN1_OBJECT *)X509_NAME_ENTRY_get_object(xsne)); - if (nid == NID_commonName) { - data_ptr = X509_NAME_ENTRY_get_data_ptr(xsne); - data_len = X509_NAME_ENTRY_get_data_len(xsne); - *cppCN = apr_palloc(p, data_len+1); - apr_cpystrn(*cppCN, (char *)data_ptr, data_len+1); - (*cppCN)[data_len] = NUL; - ap_xlate_proto_from_ascii(*cppCN, data_len); - return TRUE; + char *result = NULL; + BIO *bio; + int len; + + if ((bio = BIO_new(BIO_s_mem())) == NULL) + return NULL; + X509_NAME_print_ex(bio, dn, 0, XN_FLAG_RFC2253); + len = BIO_pending(bio); + if (len > 0) { + result = apr_palloc(p, maxlen ? maxlen+1 : len+1); + if (maxlen && maxlen < len) { + len = BIO_read(bio, result, maxlen); + if (maxlen > 2) { + /* insert trailing ellipsis if there's enough space */ + apr_snprintf(result + maxlen - 3, 4, "..."); + } + } else { + len = BIO_read(bio, result, len); } + result[len] = NUL; + } + BIO_free(bio); + + return result; +} + +/* return an array of (RFC 6125 coined) DNS-IDs and CN-IDs in a certificate */ +BOOL SSL_X509_getIDs(apr_pool_t *p, X509 *x509, apr_array_header_t **ids) +{ + STACK_OF(GENERAL_NAME) *names; + BIO *bio; + X509_NAME *subj; + char **cpp; + int i, n; + + if (!x509 || !(*ids = apr_array_make(p, 0, sizeof(char *)))) { + *ids = NULL; + return FALSE; + } + + /* First, the DNS-IDs (dNSName entries in the subjectAltName extension) */ + if ((names = X509_get_ext_d2i(x509, NID_subject_alt_name, NULL, NULL)) && + (bio = BIO_new(BIO_s_mem()))) { + GENERAL_NAME *name; + + for (i = 0; i < sk_GENERAL_NAME_num(names); i++) { + name = sk_GENERAL_NAME_value(names, i); + if (name->type == GEN_DNS) { + ASN1_STRING_print_ex(bio, name->d.ia5, ASN1_STRFLGS_ESC_CTRL| + ASN1_STRFLGS_UTF8_CONVERT); + n = BIO_pending(bio); + if (n > 0) { + cpp = (char **)apr_array_push(*ids); + *cpp = apr_palloc(p, n+1); + n = BIO_read(bio, *cpp, n); + (*cpp)[n] = NUL; + } + } + } + BIO_free(bio); } - return FALSE; + + if (names) + sk_GENERAL_NAME_free(names); + + /* Second, the CN-IDs (commonName attributes in the subject DN) */ + subj = X509_get_subject_name(x509); + i = -1; + while ((i = X509_NAME_get_index_by_NID(subj, NID_commonName, i)) != -1) { + cpp = (char **)apr_array_push(*ids); + *cpp = SSL_X509_NAME_ENTRY_to_string(p, X509_NAME_get_entry(subj, i)); + } + + return apr_is_empty_array(*ids) ? FALSE : TRUE; } /* _________________________________________________________________ @@ -398,14 +395,14 @@ BOOL SSL_X509_INFO_load_file(apr_pool_t *ptemp, return FALSE; } - if (BIO_read_filename(in, MODSSL_PCHAR_CAST filename) <= 0) { + if (BIO_read_filename(in, filename) <= 0) { BIO_free(in); return FALSE; } ERR_clear_error(); - modssl_PEM_X509_INFO_read_bio(in, sk, NULL, NULL); + PEM_X509_INFO_read_bio(in, sk, NULL, NULL); BIO_free(in); @@ -461,7 +458,7 @@ BOOL SSL_X509_INFO_load_path(apr_pool_t *ptemp, * should be sent to the peer in the SSL Certificate message. */ int SSL_CTX_use_certificate_chain( - SSL_CTX *ctx, char *file, int skipfirst, modssl_read_bio_cb_fn *cb) + SSL_CTX *ctx, char *file, int skipfirst, pem_password_cb *cb) { BIO *bio; X509 *x509; @@ -477,21 +474,21 @@ int SSL_CTX_use_certificate_chain( } /* optionally skip a leading server certificate */ if (skipfirst) { - if ((x509 = modssl_PEM_read_bio_X509(bio, NULL, cb, NULL)) == NULL) { + if ((x509 = PEM_read_bio_X509(bio, NULL, cb, NULL)) == NULL) { BIO_free(bio); return -1; } X509_free(x509); } /* free a perhaps already configured extra chain */ - extra_certs=SSL_CTX_get_extra_certs(ctx); + extra_certs = ctx->extra_certs; if (extra_certs != NULL) { sk_X509_pop_free((STACK_OF(X509) *)extra_certs, X509_free); - SSL_CTX_set_extra_certs(ctx,NULL); + ctx->extra_certs = NULL; } /* create new extra chain by loading the certs */ n = 0; - while ((x509 = modssl_PEM_read_bio_X509(bio, NULL, cb, NULL)) != NULL) { + while ((x509 = PEM_read_bio_X509(bio, NULL, cb, NULL)) != NULL) { if (!SSL_CTX_add_extra_chain_cert(ctx, x509)) { X509_free(x509); BIO_free(bio); @@ -532,44 +529,3 @@ char *SSL_SESSION_id2sz(unsigned char *id, int idlen, *cp = NUL; return str; } - -/* sslc+OpenSSL compat */ - -int modssl_session_get_time(SSL_SESSION *session) -{ -#ifdef OPENSSL_VERSION_NUMBER - return SSL_SESSION_get_time(session); -#else /* assume sslc */ - CRYPTO_TIME_T ct; - SSL_SESSION_get_time(session, &ct); - return CRYPTO_time_to_int(&ct); -#endif -} - -#ifndef SSLC_VERSION_NUMBER -#define SSLC_VERSION_NUMBER 0x0000 -#endif - -DH *modssl_dh_configure(unsigned char *p, int plen, - unsigned char *g, int glen) -{ - DH *dh; - - if (!(dh = DH_new())) { - return NULL; - } - -#if defined(OPENSSL_VERSION_NUMBER) || (SSLC_VERSION_NUMBER < 0x2000) - dh->p = BN_bin2bn(p, plen, NULL); - dh->g = BN_bin2bn(g, glen, NULL); - if (!(dh->p && dh->g)) { - DH_free(dh); - return NULL; - } -#else - R_EITEMS_add(dh->data, PK_TYPE_DH, PK_DH_P, 0, p, plen, R_EITEMS_PF_COPY); - R_EITEMS_add(dh->data, PK_TYPE_DH, PK_DH_G, 0, g, glen, R_EITEMS_PF_COPY); -#endif - - return dh; -} diff --git a/modules/ssl/ssl_util_ssl.h b/modules/ssl/ssl_util_ssl.h index 04bcbdc2..db2a2e30 100644 --- a/modules/ssl/ssl_util_ssl.h +++ b/modules/ssl/ssl_util_ssl.h @@ -35,30 +35,13 @@ #define __SSL_UTIL_SSL_H__ /** - * Determine SSL library version number + * SSL library version number */ -#define SSL_NIBBLE(x,n) ((x >> (n * 4)) & 0xF) -#ifdef OPENSSL_VERSION_NUMBER #define SSL_LIBRARY_VERSION OPENSSL_VERSION_NUMBER #define SSL_LIBRARY_NAME "OpenSSL" #define SSL_LIBRARY_TEXT OPENSSL_VERSION_TEXT #define SSL_LIBRARY_DYNTEXT SSLeay_version(SSLEAY_VERSION) -#elif defined(SSLC_VERSION_NUMBER) -#define SSL_LIBRARY_VERSION SSLC_VERSION_NUMBER -#define SSL_LIBRARY_NAME "SSL-C" -#define SSL_LIBRARY_TEXT { 'S', 'S', 'L', '-', 'C', ' ', \ - '0' + SSL_NIBBLE(SSLC_VERSION_NUMBER,3), '.', \ - '0' + SSL_NIBBLE(SSLC_VERSION_NUMBER,2), '.', \ - '0' + SSL_NIBBLE(SSLC_VERSION_NUMBER,1), '.', \ - '0' + SSL_NIBBLE(SSLC_VERSION_NUMBER,0), 0 } -#define SSL_LIBRARY_DYNTEXT SSLC_library_info(SSLC_INFO_VERSION) -#elif !defined(SSL_LIBRARY_VERSION) -#define SSL_LIBRARY_VERSION 0x0000 -#define SSL_LIBRARY_NAME "OtherSSL" -#define SSL_LIBRARY_TEXT "OtherSSL 0.0.0 00 XXX 0000" -#define SSL_LIBRARY_DYNTEXT "OtherSSL 0.0.0 00 XXX 0000" -#endif /** * Maximum length of a DER encoded session. @@ -71,32 +54,26 @@ #define SSL_SESSION_ID_STRING_LEN \ ((SSL_MAX_SSL_SESSION_ID_LENGTH + 1) * 2) -/** +/** * Additional Functions */ void SSL_init_app_data2_idx(void); void *SSL_get_app_data2(SSL *); void SSL_set_app_data2(SSL *, void *); -X509 *SSL_read_X509(char *, X509 **, modssl_read_bio_cb_fn *); -EVP_PKEY *SSL_read_PrivateKey(char *, EVP_PKEY **, modssl_read_bio_cb_fn *, void *); +X509 *SSL_read_X509(char *, X509 **, pem_password_cb *); +EVP_PKEY *SSL_read_PrivateKey(char *, EVP_PKEY **, pem_password_cb *, void *); int SSL_smart_shutdown(SSL *ssl); -X509_STORE *SSL_X509_STORE_create(char *, char *); -int SSL_X509_STORE_lookup(X509_STORE *, int, X509_NAME *, X509_OBJECT *); char *SSL_make_ciphersuite(apr_pool_t *, SSL *); BOOL SSL_X509_isSGC(X509 *); BOOL SSL_X509_getBC(X509 *, int *, int *); -BOOL SSL_X509_getCN(apr_pool_t *, X509 *, char **); +char *SSL_X509_NAME_ENTRY_to_string(apr_pool_t *p, X509_NAME_ENTRY *xsne); +char *SSL_X509_NAME_to_string(apr_pool_t *, X509_NAME *, unsigned int); +BOOL SSL_X509_getIDs(apr_pool_t *, X509 *, apr_array_header_t **); BOOL SSL_X509_INFO_load_file(apr_pool_t *, STACK_OF(X509_INFO) *, const char *); BOOL SSL_X509_INFO_load_path(apr_pool_t *, STACK_OF(X509_INFO) *, const char *); -int SSL_CTX_use_certificate_chain(SSL_CTX *, char *, int, modssl_read_bio_cb_fn *); +int SSL_CTX_use_certificate_chain(SSL_CTX *, char *, int, pem_password_cb *); char *SSL_SESSION_id2sz(unsigned char *, int, char *, int); -/** util functions for OpenSSL+sslc compat */ -int modssl_session_get_time(SSL_SESSION *session); - -DH *modssl_dh_configure(unsigned char *p, int plen, - unsigned char *g, int glen); - #endif /* __SSL_UTIL_SSL_H__ */ /** @} */ diff --git a/modules/ssl/ssl_util_stapling.c b/modules/ssl/ssl_util_stapling.c new file mode 100644 index 00000000..941fb285 --- /dev/null +++ b/modules/ssl/ssl_util_stapling.c @@ -0,0 +1,688 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* _ _ + * _ __ ___ ___ __| | ___ ___| | mod_ssl + * | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL + * | | | | | | (_) | (_| | \__ \__ \ | + * |_| |_| |_|\___/ \__,_|___|___/___/_| + * |_____| + * ssl_stapling.c + * OCSP Stapling Support + */ + /* ``Where's the spoons? + Where's the spoons? + Where's the bloody spoons?'' + -- Alexei Sayle */ + +#include "ssl_private.h" +#include "ap_mpm.h" +#include "apr_thread_mutex.h" + +#ifdef HAVE_OCSP_STAPLING + +/** + * Maxiumum OCSP stapling response size. This should be the response for a + * single certificate and will typically include the responder certificate chain + * so 10K should be more than enough. + * + */ + +#define MAX_STAPLING_DER 10240 + +/* Cached info stored in certificate ex_info. */ +typedef struct { + /* Index in session cache SHA1 hash of certificate */ + UCHAR idx[20]; + /* Certificate ID for OCSP requests or NULL if ID cannot be determined */ + OCSP_CERTID *cid; + /* Responder details */ + char *uri; +} certinfo; + +static void certinfo_free(void *parent, void *ptr, CRYPTO_EX_DATA *ad, + int idx, long argl, void *argp) +{ + certinfo *cinf = ptr; + + if (!cinf) + return; + if (cinf->uri) + OPENSSL_free(cinf->uri); + OPENSSL_free(cinf); +} + +static int stapling_ex_idx = -1; + +void ssl_stapling_ex_init(void) +{ + if (stapling_ex_idx != -1) + return; + stapling_ex_idx = X509_get_ex_new_index(0, "X509 cached OCSP info", 0, 0, + certinfo_free); +} + +static X509 *stapling_get_issuer(modssl_ctx_t *mctx, X509 *x) +{ + X509 *issuer = NULL; + int i; + X509_STORE *st = SSL_CTX_get_cert_store(mctx->ssl_ctx); + X509_STORE_CTX inctx; + + for (i = 0; i < sk_X509_num(mctx->ssl_ctx->extra_certs); i++) { + issuer = sk_X509_value(mctx->ssl_ctx->extra_certs, i); + if (X509_check_issued(issuer, x) == X509_V_OK) { + CRYPTO_add(&issuer->references, 1, CRYPTO_LOCK_X509); + return issuer; + } + } + + if (!X509_STORE_CTX_init(&inctx, st, NULL, NULL)) + return 0; + if (X509_STORE_CTX_get1_issuer(&issuer, &inctx, x) <= 0) + issuer = NULL; + X509_STORE_CTX_cleanup(&inctx); + return issuer; + +} + +int ssl_stapling_init_cert(server_rec *s, modssl_ctx_t *mctx, X509 *x) +{ + certinfo *cinf; + X509 *issuer = NULL; + STACK_OF(OPENSSL_STRING) *aia = NULL; + + if (x == NULL) + return 0; + cinf = X509_get_ex_data(x, stapling_ex_idx); + if (cinf) { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(02215) + "ssl_stapling_init_cert: certificate already initialized!"); + return 0; + } + cinf = OPENSSL_malloc(sizeof(certinfo)); + if (!cinf) { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(02216) + "ssl_stapling_init_cert: error allocating memory!"); + return 0; + } + cinf->cid = NULL; + cinf->uri = NULL; + X509_set_ex_data(x, stapling_ex_idx, cinf); + + issuer = stapling_get_issuer(mctx, x); + + if (issuer == NULL) { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(02217) + "ssl_stapling_init_cert: Can't retrieve issuer certificate!"); + return 0; + } + + cinf->cid = OCSP_cert_to_id(NULL, x, issuer); + X509_free(issuer); + if (!cinf->cid) + return 0; + X509_digest(x, EVP_sha1(), cinf->idx, NULL); + + aia = X509_get1_ocsp(x); + if (aia) + cinf->uri = sk_OPENSSL_STRING_pop(aia); + if (!cinf->uri && !mctx->stapling_force_url) { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(02218) + "ssl_stapling_init_cert: no responder URL"); + } + if (aia) + X509_email_free(aia); + return 1; +} + +static certinfo *stapling_get_cert_info(server_rec *s, modssl_ctx_t *mctx, + SSL *ssl) +{ + certinfo *cinf; + X509 *x; + x = SSL_get_certificate(ssl); + if (x == NULL) + return NULL; + cinf = X509_get_ex_data(x, stapling_ex_idx); + if (cinf && cinf->cid) + return cinf; + ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, APLOGNO(01926) + "stapling_get_cert_info: stapling not supported for certificate"); + return NULL; +} + +/* + * OCSP response caching code. The response is preceded by a flag value + * which indicates whether the response was invalid when it was stored. + * the purpose of this flag is to avoid repeated queries to a server + * which has given an invalid response while allowing a response which + * has subsequently become invalid to be retried immediately. + * + * The key for the cache is the hash of the certificate the response + * is for. + */ +static BOOL stapling_cache_response(server_rec *s, modssl_ctx_t *mctx, + OCSP_RESPONSE *rsp, certinfo *cinf, + BOOL ok, apr_pool_t *pool) +{ + SSLModConfigRec *mc = myModConfig(s); + unsigned char resp_der[MAX_STAPLING_DER]; + unsigned char *p; + int resp_derlen; + BOOL rv; + apr_time_t expiry; + + resp_derlen = i2d_OCSP_RESPONSE(rsp, NULL) + 1; + + if (resp_derlen <= 0) { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(01927) + "OCSP stapling response encode error??"); + return FALSE; + } + + if (resp_derlen > sizeof resp_der) { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(01928) + "OCSP stapling response too big (%u bytes)", resp_derlen); + return FALSE; + } + + p = resp_der; + + /* TODO: potential optimization; _timeout members as apr_interval_time_t */ + if (ok == TRUE) { + *p++ = 1; + expiry = apr_time_from_sec(mctx->stapling_cache_timeout); + } + else { + *p++ = 0; + expiry = apr_time_from_sec(mctx->stapling_errcache_timeout); + } + + expiry += apr_time_now(); + + i2d_OCSP_RESPONSE(rsp, &p); + + rv = mc->stapling_cache->store(mc->stapling_cache_context, s, + cinf->idx, sizeof(cinf->idx), + expiry, resp_der, resp_derlen, pool); + if (rv != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(01929) + "stapling_cache_response: OCSP response session store error!"); + return FALSE; + } + + return TRUE; +} + +static BOOL stapling_get_cached_response(server_rec *s, OCSP_RESPONSE **prsp, + BOOL *pok, certinfo *cinf, + apr_pool_t *pool) +{ + SSLModConfigRec *mc = myModConfig(s); + apr_status_t rv; + OCSP_RESPONSE *rsp; + unsigned char resp_der[MAX_STAPLING_DER]; + const unsigned char *p; + unsigned int resp_derlen = MAX_STAPLING_DER; + + rv = mc->stapling_cache->retrieve(mc->stapling_cache_context, s, + cinf->idx, sizeof(cinf->idx), + resp_der, &resp_derlen, pool); + if (rv != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(01930) + "stapling_get_cached_response: cache miss"); + return TRUE; + } + if (resp_derlen <= 1) { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(01931) + "stapling_get_cached_response: response length invalid??"); + return TRUE; + } + p = resp_der; + if (pok) { + if (*p) + *pok = TRUE; + else + *pok = FALSE; + } + p++; + resp_derlen--; + rsp = d2i_OCSP_RESPONSE(NULL, &p, resp_derlen); + if (!rsp) { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(01932) + "stapling_get_cached_response: response parse error??"); + return TRUE; + } + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(01933) + "stapling_get_cached_response: cache hit"); + + *prsp = rsp; + + return TRUE; +} + +static int stapling_set_response(SSL *ssl, OCSP_RESPONSE *rsp) +{ + int rspderlen; + unsigned char *rspder = NULL; + + rspderlen = i2d_OCSP_RESPONSE(rsp, &rspder); + if (rspderlen <= 0) + return 0; + SSL_set_tlsext_status_ocsp_resp(ssl, rspder, rspderlen); + return 1; +} + +static int stapling_check_response(server_rec *s, modssl_ctx_t *mctx, + certinfo *cinf, OCSP_RESPONSE *rsp, + BOOL *pok) +{ + int status, reason; + OCSP_BASICRESP *bs = NULL; + ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd; + int response_status = OCSP_response_status(rsp); + + if (pok) + *pok = FALSE; + /* Check to see if response is an error. If so we automatically accept + * it because it would have expired from the cache if it was time to + * retry. + */ + if (response_status != OCSP_RESPONSE_STATUS_SUCCESSFUL) { + if (mctx->stapling_return_errors) + return SSL_TLSEXT_ERR_OK; + else + return SSL_TLSEXT_ERR_NOACK; + } + + bs = OCSP_response_get1_basic(rsp); + if (bs == NULL) { + /* If we can't parse response just pass it to client */ + ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(01934) + "stapling_check_response: Error Parsing Response!"); + return SSL_TLSEXT_ERR_OK; + } + + if (!OCSP_resp_find_status(bs, cinf->cid, &status, &reason, &rev, + &thisupd, &nextupd)) { + /* If ID not present just pass back to client */ + ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(01935) + "stapling_check_response: certificate ID not present in response!"); + } + else { + if (OCSP_check_validity(thisupd, nextupd, + mctx->stapling_resptime_skew, + mctx->stapling_resp_maxage)) { + if (pok) + *pok = TRUE; + } + else { + /* If pok is not NULL response was direct from a responder and + * the times should be valide. If pok is NULL the response was + * retrieved from cache and it is expected to subsequently expire + */ + if (pok) { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(01936) + "stapling_check_response: response times invalid"); + } + else { + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(01937) + "stapling_check_response: cached response expired"); + } + + OCSP_BASICRESP_free(bs); + return SSL_TLSEXT_ERR_NOACK; + } + } + + OCSP_BASICRESP_free(bs); + + return SSL_TLSEXT_ERR_OK; +} + +static BOOL stapling_renew_response(server_rec *s, modssl_ctx_t *mctx, SSL *ssl, + certinfo *cinf, OCSP_RESPONSE **prsp, + apr_pool_t *pool) +{ + conn_rec *conn = (conn_rec *)SSL_get_app_data(ssl); + apr_pool_t *vpool; + OCSP_REQUEST *req = NULL; + OCSP_CERTID *id = NULL; + STACK_OF(X509_EXTENSION) *exts; + int i; + BOOL ok = FALSE; + BOOL rv = TRUE; + const char *ocspuri; + apr_uri_t uri; + + *prsp = NULL; + /* Build up OCSP query from server certificate info */ + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(01938) + "stapling_renew_response: querying responder"); + + req = OCSP_REQUEST_new(); + if (!req) + goto err; + id = OCSP_CERTID_dup(cinf->cid); + if (!id) + goto err; + if (!OCSP_request_add0_id(req, id)) + goto err; + id = NULL; + /* Add any extensions to the request */ + SSL_get_tlsext_status_exts(ssl, &exts); + for (i = 0; i < sk_X509_EXTENSION_num(exts); i++) { + X509_EXTENSION *ext = sk_X509_EXTENSION_value(exts, i); + if (!OCSP_REQUEST_add_ext(req, ext, -1)) + goto err; + } + + if (mctx->stapling_force_url) + ocspuri = mctx->stapling_force_url; + else + ocspuri = cinf->uri; + + /* Create a temporary pool to constrain memory use */ + apr_pool_create(&vpool, conn->pool); + + ok = apr_uri_parse(vpool, ocspuri, &uri); + if (ok != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(01939) + "stapling_renew_response: Error parsing uri %s", + ocspuri); + rv = FALSE; + goto done; + } + else if (strcmp(uri.scheme, "http")) { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(01940) + "stapling_renew_response: Unsupported uri %s", ocspuri); + rv = FALSE; + goto done; + } + + if (!uri.port) { + uri.port = apr_uri_port_of_scheme(uri.scheme); + } + + *prsp = modssl_dispatch_ocsp_request(&uri, mctx->stapling_responder_timeout, + req, conn, vpool); + + apr_pool_destroy(vpool); + + if (!*prsp) { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(01941) + "stapling_renew_response: responder error"); + if (mctx->stapling_fake_trylater) { + *prsp = OCSP_response_create(OCSP_RESPONSE_STATUS_TRYLATER, NULL); + } + else { + goto done; + } + } + else { + int response_status = OCSP_response_status(*prsp); + + if (response_status == OCSP_RESPONSE_STATUS_SUCCESSFUL) { + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(01942) + "stapling_renew_response: query response received"); + stapling_check_response(s, mctx, cinf, *prsp, &ok); + if (ok == FALSE) { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(01943) + "stapling_renew_response: error in retreived response!"); + } + } + else { + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(01944) + "stapling_renew_response: responder error %s", + OCSP_response_status_str(response_status)); + } + } + if (stapling_cache_response(s, mctx, *prsp, cinf, ok, pool) == FALSE) { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(01945) + "stapling_renew_response: error caching response!"); + } + +done: + if (id) + OCSP_CERTID_free(id); + if (req) + OCSP_REQUEST_free(req); + return rv; +err: + rv = FALSE; + goto done; +} + +/* + * SSLStaplingMutex operations. Similar to SSL mutex except a mutex is + * mandatory if stapling is enabled. + */ +static int ssl_stapling_mutex_init(server_rec *s, apr_pool_t *p) +{ + SSLModConfigRec *mc = myModConfig(s); + SSLSrvConfigRec *sc = mySrvConfig(s); + apr_status_t rv; + + if (mc->stapling_mutex || sc->server->stapling_enabled != TRUE) { + return TRUE; + } + + if ((rv = ap_global_mutex_create(&mc->stapling_mutex, NULL, + SSL_STAPLING_MUTEX_TYPE, NULL, s, + s->process->pool, 0)) != APR_SUCCESS) { + return FALSE; + } + + return TRUE; +} + +int ssl_stapling_mutex_reinit(server_rec *s, apr_pool_t *p) +{ + SSLModConfigRec *mc = myModConfig(s); + apr_status_t rv; + const char *lockfile; + + if (mc->stapling_mutex == NULL) { + return TRUE; + } + + lockfile = apr_global_mutex_lockfile(mc->stapling_mutex); + if ((rv = apr_global_mutex_child_init(&mc->stapling_mutex, + lockfile, p)) != APR_SUCCESS) { + if (lockfile) { + ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO(01946) + "Cannot reinit %s mutex with file `%s'", + SSL_STAPLING_MUTEX_TYPE, lockfile); + } + else { + ap_log_error(APLOG_MARK, APLOG_WARNING, rv, s, APLOGNO(01947) + "Cannot reinit %s mutex", SSL_STAPLING_MUTEX_TYPE); + } + return FALSE; + } + return TRUE; +} + +static int stapling_mutex_on(server_rec *s) +{ + SSLModConfigRec *mc = myModConfig(s); + apr_status_t rv; + + if ((rv = apr_global_mutex_lock(mc->stapling_mutex)) != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_WARNING, rv, s, APLOGNO(01948) + "Failed to acquire OCSP stapling lock"); + return FALSE; + } + return TRUE; +} + +static int stapling_mutex_off(server_rec *s) +{ + SSLModConfigRec *mc = myModConfig(s); + apr_status_t rv; + + if ((rv = apr_global_mutex_unlock(mc->stapling_mutex)) != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_WARNING, rv, s, APLOGNO(01949) + "Failed to release OCSP stapling lock"); + return FALSE; + } + return TRUE; +} + +/* Certificate Status callback. This is called when a client includes a + * certificate status request extension. + * + * Check for cached responses in session cache. If valid send back to + * client. If absent or no longer valid query responder and update + * cache. */ +static int stapling_cb(SSL *ssl, void *arg) +{ + conn_rec *conn = (conn_rec *)SSL_get_app_data(ssl); + server_rec *s = mySrvFromConn(conn); + SSLSrvConfigRec *sc = mySrvConfig(s); + SSLConnRec *sslconn = myConnConfig(conn); + modssl_ctx_t *mctx = myCtxConfig(sslconn, sc); + certinfo *cinf = NULL; + OCSP_RESPONSE *rsp = NULL; + int rv; + BOOL ok; + + if (sc->server->stapling_enabled != TRUE) { + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(01950) + "stapling_cb: OCSP Stapling disabled"); + return SSL_TLSEXT_ERR_NOACK; + } + + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(01951) + "stapling_cb: OCSP Stapling callback called"); + + cinf = stapling_get_cert_info(s, mctx, ssl); + if (cinf == NULL) { + return SSL_TLSEXT_ERR_NOACK; + } + + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(01952) + "stapling_cb: retrieved cached certificate data"); + + /* Check to see if we already have a response for this certificate */ + stapling_mutex_on(s); + + rv = stapling_get_cached_response(s, &rsp, &ok, cinf, conn->pool); + if (rv == FALSE) { + stapling_mutex_off(s); + return SSL_TLSEXT_ERR_ALERT_FATAL; + } + + if (rsp) { + /* see if response is acceptable */ + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(01953) + "stapling_cb: retrieved cached response"); + rv = stapling_check_response(s, mctx, cinf, rsp, NULL); + if (rv == SSL_TLSEXT_ERR_ALERT_FATAL) { + OCSP_RESPONSE_free(rsp); + stapling_mutex_off(s); + return SSL_TLSEXT_ERR_ALERT_FATAL; + } + else if (rv == SSL_TLSEXT_ERR_NOACK) { + /* Error in response. If this error was not present when it was + * stored (i.e. response no longer valid) then it can be + * renewed straight away. + * + * If the error *was* present at the time it was stored then we + * don't renew the response straight away we just wait for the + * cached response to expire. + */ + if (ok) { + OCSP_RESPONSE_free(rsp); + rsp = NULL; + } + else if (!mctx->stapling_return_errors) { + OCSP_RESPONSE_free(rsp); + stapling_mutex_off(s); + return SSL_TLSEXT_ERR_NOACK; + } + } + } + + if (rsp == NULL) { + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(01954) + "stapling_cb: renewing cached response"); + rv = stapling_renew_response(s, mctx, ssl, cinf, &rsp, conn->pool); + + if (rv == FALSE) { + stapling_mutex_off(s); + ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(01955) + "stapling_cb: fatal error"); + return SSL_TLSEXT_ERR_ALERT_FATAL; + } + } + stapling_mutex_off(s); + + if (rsp) { + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(01956) + "stapling_cb: setting response"); + if (!stapling_set_response(ssl, rsp)) + return SSL_TLSEXT_ERR_ALERT_FATAL; + return SSL_TLSEXT_ERR_OK; + } + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(01957) + "stapling_cb: no response available"); + + return SSL_TLSEXT_ERR_NOACK; + +} + +void modssl_init_stapling(server_rec *s, apr_pool_t *p, apr_pool_t *ptemp, + modssl_ctx_t *mctx) +{ + SSL_CTX *ctx = mctx->ssl_ctx; + SSLModConfigRec *mc = myModConfig(s); + + if (mc->stapling_cache == NULL) { + ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(01958) + "SSLStapling: no stapling cache available"); + ssl_die(); + } + if (ssl_stapling_mutex_init(s, ptemp) == FALSE) { + ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(01959) + "SSLStapling: cannot initialise stapling mutex"); + ssl_die(); + } + /* Set some default values for parameters if they are not set */ + if (mctx->stapling_resptime_skew == UNSET) { + mctx->stapling_resptime_skew = 60 * 5; + } + if (mctx->stapling_cache_timeout == UNSET) { + mctx->stapling_cache_timeout = 3600; + } + if (mctx->stapling_return_errors == UNSET) { + mctx->stapling_return_errors = TRUE; + } + if (mctx->stapling_fake_trylater == UNSET) { + mctx->stapling_fake_trylater = TRUE; + } + if (mctx->stapling_errcache_timeout == UNSET) { + mctx->stapling_errcache_timeout = 600; + } + if (mctx->stapling_responder_timeout == UNSET) { + mctx->stapling_responder_timeout = 10 * APR_USEC_PER_SEC; + } + SSL_CTX_set_tlsext_status_cb(ctx, stapling_cb); + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(01960) "OCSP stapling initialized"); +} + +#endif |
