From 223df5cf69b190490e0574cf567d8cb7eff82752 Mon Sep 17 00:00:00 2001 From: Graham Leggett Date: Tue, 13 Feb 2018 23:43:36 +0000 Subject: [PATCH] mod_proxy, mod_ssl: Handle SSLProxy* directives in sections, allowing per backend TLS configuration. trunk patch: http://svn.apache.org/r1740928 http://svn.apache.org/r1740960 http://svn.apache.org/r1740967 http://svn.apache.org/r1740987 http://svn.apache.org/r1740998 http://svn.apache.org/r1742697 http://svn.apache.org/r1756976 http://svn.apache.org/r1781313 http://svn.apache.org/r1812193 2.4.x patch: https://svn.apache.org/repos/asf/httpd/httpd/patches/2.4.x/httpd-2.4.x-r1740928_and_co-v6.patch +1: ylavic, icing, minfrin git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1824187 13f79535-47bb-0310-9956-ffa450edef68 --- CHANGES | 3 + STATUS | 14 -- docs/manual/mod/mod_ssl.xml | 79 +++++---- docs/manual/style/lang/en.xml | 1 + docs/manual/style/latex/quickreference.xsl | 4 + docs/manual/style/latex/synopsis.xsl | 3 + docs/manual/style/xsl/quickreference.xsl | 14 ++ docs/manual/style/xsl/synopsis.xsl | 3 + include/ap_mmn.h | 8 +- include/http_config.h | 9 +- modules/generators/mod_suexec.c | 2 +- modules/http/http_core.c | 6 +- modules/http2/h2_h2.c | 2 - modules/http2/mod_proxy_http2.c | 6 +- modules/mappers/mod_alias.c | 2 +- modules/proxy/mod_proxy.c | 71 +++++++- modules/proxy/mod_proxy.h | 36 +++- modules/proxy/mod_proxy_connect.c | 2 +- modules/proxy/mod_proxy_ftp.c | 4 +- modules/proxy/mod_proxy_http.c | 4 +- modules/proxy/mod_proxy_wstunnel.c | 7 +- modules/proxy/proxy_util.c | 28 ++- modules/ssl/mod_ssl.c | 187 ++++++++++++-------- modules/ssl/mod_ssl.h | 9 +- modules/ssl/ssl_engine_config.c | 188 ++++++++++++--------- modules/ssl/ssl_engine_init.c | 157 +++++++++++------ modules/ssl/ssl_engine_io.c | 14 +- modules/ssl/ssl_engine_kernel.c | 8 +- modules/ssl/ssl_private.h | 52 +++--- server/config.c | 5 + server/core.c | 42 ++--- 31 files changed, 619 insertions(+), 351 deletions(-) diff --git a/CHANGES b/CHANGES index 20f54e70f2..28fcfc9629 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,9 @@ -*- coding: utf-8 -*- Changes with Apache 2.4.30 + *) mod_proxy, mod_ssl: Handle SSLProxy* directives in sections, + allowing per backend TLS configuration. [Yann Ylavic] + *) mod_proxy_uwsgi: Add in UWSGI proxy (sub)module. [Roberto De Ioris, Jim Jagielski] diff --git a/STATUS b/STATUS index 77c8b2c1f8..6d84a1acbd 100644 --- a/STATUS +++ b/STATUS @@ -119,20 +119,6 @@ RELEASE SHOWSTOPPERS: PATCHES ACCEPTED TO BACKPORT FROM TRUNK: [ start all new proposals below, under PATCHES PROPOSED. ] - *) mod_proxy, mod_ssl: Handle SSLProxy* directives in sections, - allowing per backend TLS configuration. - trunk patch: http://svn.apache.org/r1740928 - http://svn.apache.org/r1740960 - http://svn.apache.org/r1740967 - http://svn.apache.org/r1740987 - http://svn.apache.org/r1740998 - http://svn.apache.org/r1742697 - http://svn.apache.org/r1756976 - http://svn.apache.org/r1781313 - http://svn.apache.org/r1812193 - 2.4.x patch: https://svn.apache.org/repos/asf/httpd/httpd/patches/2.4.x/httpd-2.4.x-r1740928_and_co-v6.patch - +1: ylavic, icing, minfrin - PATCHES PROPOSED TO BACKPORT FROM TRUNK: [ New proposals should be added at the end of the list ] diff --git a/docs/manual/mod/mod_ssl.xml b/docs/manual/mod/mod_ssl.xml index 8ef2f76c93..3d484f0a76 100644 --- a/docs/manual/mod/mod_ssl.xml +++ b/docs/manual/mod/mod_ssl.xml @@ -1740,7 +1740,8 @@ SSLStrictSNIVHostCheck on SSLProxyMachineCertificatePath Directory of PEM-encoded client certificates and keys to be used by the proxy SSLProxyMachineCertificatePath directory -server config +server config virtual host +proxy section

@@ -1767,7 +1768,8 @@ SSLProxyMachineCertificatePath "/usr/local/apache2/conf/proxy.crt/" SSLProxyMachineCertificateFile File of concatenated PEM-encoded client certificates and keys to be used by the proxy SSLProxyMachineCertificateFile filename -server config +server config virtual host +proxy section

@@ -1794,7 +1796,8 @@ SSLProxyMachineCertificateFile "/usr/local/apache2/conf/ssl.crt/proxy.pem" SSLProxyMachineCertificateChainFile File of concatenated PEM-encoded CA certificates to be used by the proxy for choosing a certificate SSLProxyMachineCertificateChainFile filename -server config +server config virtual host +proxy section

@@ -1826,8 +1829,9 @@ SSLProxyMachineCertificateChainFile "/usr/local/apache2/conf/ssl.crt/proxyCA.pem Type of remote server Certificate verification SSLProxyVerify level SSLProxyVerify none -server config -virtual host +server config virtual host +proxy section +Not applicable @@ -1866,8 +1870,9 @@ SSLProxyVerify require Certificate verification SSLProxyVerifyDepth number SSLProxyVerifyDepth 1 -server config -virtual host +server config virtual host +proxy section +Not applicable

@@ -1895,8 +1900,9 @@ SSLProxyVerifyDepth 10 SSLProxyCheckPeerExpire on|off SSLProxyCheckPeerExpire on -server config -virtual host +server config virtual host +proxy section +Not applicable

@@ -1918,8 +1924,9 @@ SSLProxyCheckPeerExpire on SSLProxyCheckPeerCN on|off SSLProxyCheckPeerCN on -server config -virtual host +server config virtual host +proxy section +Not applicable

@@ -1962,8 +1969,9 @@ SSLProxyCheckPeerName off SSLProxyCheckPeerName on|off SSLProxyCheckPeerName on -server config -virtual host +server config virtual host +proxy section +Not applicable Apache HTTP Server 2.4.5 and later @@ -2001,8 +2009,9 @@ improvements. SSL Proxy Engine Operation Switch SSLProxyEngine on|off SSLProxyEngine off -server config -virtual host +server config virtual host +proxy section +Not applicable

@@ -2035,9 +2044,9 @@ server to proxy SSL/TLS requests.

Configure usable SSL protocol flavors for proxy usage SSLProxyProtocol [+|-]protocol ... SSLProxyProtocol all -SSLv3 (up to 2.4.16: all) -server config -virtual host -Options +server config virtual host +proxy section +Not applicable @@ -2057,11 +2066,10 @@ for additional information. proxy handshake SSLProxyCipherSuite cipher-spec SSLProxyCipherSuite ALL:!ADH:RC4+RSA:+HIGH:+MEDIUM:+LOW:+EXP -server config -virtual host -directory -.htaccess -AuthConfig +server config virtual host +proxy section +Not applicable +

Equivalent to SSLCipherSuite, but for the proxy connection. @@ -2075,8 +2083,9 @@ for additional information.

Directory of PEM-encoded CA Certificates for Remote Server Auth SSLProxyCACertificatePath directory-path -server config -virtual host +server config virtual host +proxy section +Not applicable

@@ -2102,8 +2111,9 @@ SSLProxyCACertificatePath "/usr/local/apache2/conf/ssl.crt/" File of concatenated PEM-encoded CA Certificates for Remote Server Auth SSLProxyCACertificateFile file-path -server config -virtual host +server config virtual host +proxy section +Not applicable

@@ -2126,8 +2136,9 @@ SSLProxyCACertificateFile "/usr/local/apache2/conf/ssl.crt/ca-bundle-remote-serv Directory of PEM-encoded CA CRLs for Remote Server Auth SSLProxyCARevocationPath directory-path -server config -virtual host +server config virtual host +proxy section +Not applicable

@@ -2153,8 +2164,9 @@ SSLProxyCARevocationPath "/usr/local/apache2/conf/ssl.crl/" File of concatenated PEM-encoded CA CRLs for Remote Server Auth SSLProxyCARevocationFile file-path -server config -virtual host +server config virtual host +proxy section +Not applicable

@@ -2178,8 +2190,9 @@ SSLProxyCARevocationFile "/usr/local/apache2/conf/ssl.crl/ca-bundle-remote-serve Enable CRL-based revocation checking for Remote Server Auth SSLProxyCARevocationCheck chain|leaf|none SSLProxyCARevocationCheck none -server config -virtual host +server config virtual host +proxy section +Not applicable

diff --git a/docs/manual/style/lang/en.xml b/docs/manual/style/lang/en.xml index 4671515297..4e97a89091 100644 --- a/docs/manual/style/lang/en.xml +++ b/docs/manual/style/lang/en.xml @@ -97,6 +97,7 @@ virtual host directory .htaccess + proxy section Directives diff --git a/docs/manual/style/latex/quickreference.xsl b/docs/manual/style/latex/quickreference.xsl index fc9c2bd828..3c3e48e6aa 100644 --- a/docs/manual/style/latex/quickreference.xsl +++ b/docs/manual/style/latex/quickreference.xsl @@ -105,6 +105,10 @@ [normalize-space(.)='.htaccess']"> + + + & + + + unknown context: diff --git a/docs/manual/style/xsl/quickreference.xsl b/docs/manual/style/xsl/quickreference.xsl index dcaa590fdc..84cf20d502 100644 --- a/docs/manual/style/xsl/quickreference.xsl +++ b/docs/manual/style/xsl/quickreference.xsl @@ -117,6 +117,16 @@ select="$message[@id='htaccess']"/> &lf; + + + + + + + + &lf; &lf; @@ -349,6 +359,10 @@ [normalize-space(.)='.htaccess']"> + + + diff --git a/docs/manual/style/xsl/synopsis.xsl b/docs/manual/style/xsl/synopsis.xsl index 56800a2bd9..0bcbe2c924 100644 --- a/docs/manual/style/xsl/synopsis.xsl +++ b/docs/manual/style/xsl/synopsis.xsl @@ -626,6 +626,9 @@ + + + unknown context: diff --git a/include/ap_mmn.h b/include/ap_mmn.h index 379b877611..da093a0f1b 100644 --- a/include/ap_mmn.h +++ b/include/ap_mmn.h @@ -499,6 +499,12 @@ * 20120211.69 (2.4.30-dev) Add ap_update_sb_handle() * 20120211.70 (2.4.30-dev) Add flags field to module_struct and function * ap_get_module_flags() + * 20120211.71 (2.4.30-dev) Add optional proxy_{hook,run}_section_post_config(), + * ap_proxy_connection_create_ex() and section_config + * to struct proxy_{worker,balancer} in mod_proxy.h, + * and optional ssl_engine_set() to mod_ssl.h. + * 20120211.72 (2.4.30-dev) Add NOT_IN_DIR_CONTEXT replacing NOT_IN_DIR_LOC_FILE + * semantics */ #define MODULE_MAGIC_COOKIE 0x41503234UL /* "AP24" */ @@ -506,7 +512,7 @@ #ifndef MODULE_MAGIC_NUMBER_MAJOR #define MODULE_MAGIC_NUMBER_MAJOR 20120211 #endif -#define MODULE_MAGIC_NUMBER_MINOR 70 /* 0...n */ +#define MODULE_MAGIC_NUMBER_MINOR 72 /* 0...n */ /** * Determine if the server's current MODULE_MAGIC_NUMBER is at least a diff --git a/include/http_config.h b/include/http_config.h index f3e88a8b8c..9600dd3d62 100644 --- a/include/http_config.h +++ b/include/http_config.h @@ -249,6 +249,8 @@ struct command_struct { #define NONFATAL_UNKNOWN 1024 /* Unrecognised directive */ #define NONFATAL_ALL (NONFATAL_OVERRIDE|NONFATAL_UNKNOWN) +#define PROXY_CONF 2048 /**< *.conf inside <Proxy> only */ + /** this directive can be placed anywhere */ #define OR_ALL (OR_LIMIT|OR_OPTIONS|OR_FILEINFO|OR_AUTHCFG|OR_INDEXES) @@ -944,10 +946,13 @@ AP_DECLARE(const char *) ap_check_cmd_context(cmd_parms *cmd, #define NOT_IN_LOCATION 0x08 /**< Forbidden in <Location> */ #define NOT_IN_FILES 0x10 /**< Forbidden in <Files> or <If>*/ #define NOT_IN_HTACCESS 0x20 /**< Forbidden in .htaccess files */ +#define NOT_IN_PROXY 0x40 /**< Forbidden in <Proxy> */ /** Forbidden in <Directory>/<Location>/<Files><If>*/ #define NOT_IN_DIR_LOC_FILE (NOT_IN_DIRECTORY|NOT_IN_LOCATION|NOT_IN_FILES) -/** Forbidden in <VirtualHost>/<Limit>/<Directory>/<Location>/<Files>/<If> */ -#define GLOBAL_ONLY (NOT_IN_VIRTUALHOST|NOT_IN_LIMIT|NOT_IN_DIR_LOC_FILE) +/** Forbidden in <Directory>/<Location>/<Files><If><Proxy>*/ +#define NOT_IN_DIR_CONTEXT (NOT_IN_LIMIT|NOT_IN_DIR_LOC_FILE|NOT_IN_PROXY) +/** Forbidden in <VirtualHost>/<Limit>/<Directory>/<Location>/<Files>/<If><Proxy>*/ +#define GLOBAL_ONLY (NOT_IN_VIRTUALHOST|NOT_IN_DIR_CONTEXT) /** @} */ diff --git a/modules/generators/mod_suexec.c b/modules/generators/mod_suexec.c index 75e96404c0..a71b0a8597 100644 --- a/modules/generators/mod_suexec.c +++ b/modules/generators/mod_suexec.c @@ -59,7 +59,7 @@ static const char *set_suexec_ugid(cmd_parms *cmd, void *mconfig, const char *uid, const char *gid) { suexec_config_t *cfg = (suexec_config_t *) mconfig; - const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE); + const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_CONTEXT); if (err != NULL) { return err; diff --git a/modules/http/http_core.c b/modules/http/http_core.c index f395bcc445..ccc3f141f4 100644 --- a/modules/http/http_core.c +++ b/modules/http/http_core.c @@ -52,7 +52,7 @@ static const char *set_keep_alive_timeout(cmd_parms *cmd, void *dummy, const char *arg) { apr_interval_time_t timeout; - const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE); + const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_CONTEXT); if (err != NULL) { return err; } @@ -78,7 +78,7 @@ static const char *set_keep_alive_timeout(cmd_parms *cmd, void *dummy, static const char *set_keep_alive(cmd_parms *cmd, void *dummy, int arg) { - const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE); + const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_CONTEXT); if (err != NULL) { return err; } @@ -90,7 +90,7 @@ static const char *set_keep_alive(cmd_parms *cmd, void *dummy, static const char *set_keep_alive_max(cmd_parms *cmd, void *dummy, const char *arg) { - const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE); + const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_CONTEXT); if (err != NULL) { return err; } diff --git a/modules/http2/h2_h2.c b/modules/http2/h2_h2.c index 6f9284b1da..f5fda0a00b 100644 --- a/modules/http2/h2_h2.c +++ b/modules/http2/h2_h2.c @@ -60,7 +60,6 @@ const char *H2_MAGIC_TOKEN = "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"; /******************************************************************************* * The optional mod_ssl functions we need. */ -static APR_OPTIONAL_FN_TYPE(ssl_engine_disable) *opt_ssl_engine_disable; static APR_OPTIONAL_FN_TYPE(ssl_is_https) *opt_ssl_is_https; static APR_OPTIONAL_FN_TYPE(ssl_var_lookup) *opt_ssl_var_lookup; @@ -446,7 +445,6 @@ apr_status_t h2_h2_init(apr_pool_t *pool, server_rec *s) { (void)pool; ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, s, "h2_h2, child_init"); - opt_ssl_engine_disable = APR_RETRIEVE_OPTIONAL_FN(ssl_engine_disable); opt_ssl_is_https = APR_RETRIEVE_OPTIONAL_FN(ssl_is_https); opt_ssl_var_lookup = APR_RETRIEVE_OPTIONAL_FN(ssl_var_lookup); diff --git a/modules/http2/mod_proxy_http2.c b/modules/http2/mod_proxy_http2.c index 07e91ae516..a7e0dcd7f6 100644 --- a/modules/http2/mod_proxy_http2.c +++ b/modules/http2/mod_proxy_http2.c @@ -580,9 +580,9 @@ run_connect: /* Step Three: Create conn_rec for the socket we have open now. */ if (!ctx->p_conn->connection) { - if ((status = ap_proxy_connection_create(ctx->proxy_func, ctx->p_conn, - ctx->owner, - ctx->server)) != OK) { + status = ap_proxy_connection_create_ex(ctx->proxy_func, + ctx->p_conn, ctx->rbase); + if (status != OK) { ap_log_cerror(APLOG_MARK, APLOG_DEBUG, status, ctx->owner, APLOGNO(03353) "setup new connection: is_ssl=%d %s %s %s", ctx->p_conn->is_ssl, ctx->p_conn->ssl_hostname, diff --git a/modules/mappers/mod_alias.c b/modules/mappers/mod_alias.c index 22a90aa80c..79d58d8263 100644 --- a/modules/mappers/mod_alias.c +++ b/modules/mappers/mod_alias.c @@ -131,7 +131,7 @@ static const char *add_alias_internal(cmd_parms *cmd, void *dummy, /* XXX: real can NOT be relative to DocumentRoot here... compat bug. */ - const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE); + const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_CONTEXT); if (err != NULL) { return err; diff --git a/modules/proxy/mod_proxy.c b/modules/proxy/mod_proxy.c index d7f79cf062..544611299a 100644 --- a/modules/proxy/mod_proxy.c +++ b/modules/proxy/mod_proxy.c @@ -26,6 +26,9 @@ #else APR_DECLARE_OPTIONAL_FN(int, ssl_proxy_enable, (conn_rec *)); APR_DECLARE_OPTIONAL_FN(int, ssl_engine_disable, (conn_rec *)); +APR_DECLARE_OPTIONAL_FN(int, ssl_engine_set, (conn_rec *, + ap_conf_vector_t *, + int proxy, int enable)); APR_DECLARE_OPTIONAL_FN(int, ssl_is_https, (conn_rec *)); APR_DECLARE_OPTIONAL_FN(char *, ssl_var_lookup, (apr_pool_t *, server_rec *, @@ -811,7 +814,7 @@ static int proxy_walk(request_rec *r) { proxy_server_conf *sconf = ap_get_module_config(r->server->module_config, &proxy_module); - ap_conf_vector_t *per_dir_defaults = r->server->lookup_defaults; + ap_conf_vector_t *per_dir_defaults = r->per_dir_config; ap_conf_vector_t **sec_proxy = (ap_conf_vector_t **) sconf->sec_proxy->elts; ap_conf_vector_t *entry_config; proxy_dir_conf *entry_proxy; @@ -2235,6 +2238,9 @@ static const char *add_member(cmd_parms *cmd, void *dummy, const char *arg) "Sharing worker '%s' instead of creating new worker '%s'", ap_proxy_worker_name(cmd->pool, worker), name); } + if (!worker->section_config) { + worker->section_config = balancer->section_config; + } arr = apr_table_elts(params); elts = (const apr_table_entry_t *)arr->elts; @@ -2363,7 +2369,7 @@ static const char *proxysection(cmd_parms *cmd, void *mconfig, const char *arg) proxy_balancer *balancer = NULL; proxy_worker *worker = NULL; - const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE); + const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_CONTEXT); proxy_server_conf *sconf = (proxy_server_conf *) ap_get_module_config(cmd->server->module_config, &proxy_module); @@ -2386,7 +2392,7 @@ static const char *proxysection(cmd_parms *cmd, void *mconfig, const char *arg) } cmd->path = ap_getword_conf(cmd->pool, &arg); - cmd->override = OR_ALL|ACCESS_CONF; + cmd->override = OR_ALL|ACCESS_CONF|PROXY_CONF; if (!strncasecmp(cmd->path, "proxy:", 6)) cmd->path += 6; @@ -2441,6 +2447,9 @@ static const char *proxysection(cmd_parms *cmd, void *mconfig, const char *arg) return apr_pstrcat(cmd->temp_pool, thiscmd->name, " ", err, NULL); } + if (!balancer->section_config) { + balancer->section_config = new_dir_conf; + } } else { worker = ap_proxy_get_worker(cmd->temp_pool, NULL, sconf, @@ -2452,6 +2461,9 @@ static const char *proxysection(cmd_parms *cmd, void *mconfig, const char *arg) return apr_pstrcat(cmd->temp_pool, thiscmd->name, " ", err, NULL); } + if (!worker->section_config) { + worker->section_config = new_dir_conf; + } } if (worker == NULL && balancer == NULL) { return apr_pstrcat(cmd->pool, thiscmd->name, @@ -2559,6 +2571,7 @@ static const command_rec proxy_cmds[] = static APR_OPTIONAL_FN_TYPE(ssl_proxy_enable) *proxy_ssl_enable = NULL; static APR_OPTIONAL_FN_TYPE(ssl_engine_disable) *proxy_ssl_disable = NULL; +static APR_OPTIONAL_FN_TYPE(ssl_engine_set) *proxy_ssl_engine = NULL; static APR_OPTIONAL_FN_TYPE(ssl_is_https) *proxy_is_https = NULL; static APR_OPTIONAL_FN_TYPE(ssl_var_lookup) *proxy_ssl_val = NULL; @@ -2584,6 +2597,30 @@ PROXY_DECLARE(int) ap_proxy_ssl_disable(conn_rec *c) return 0; } +PROXY_DECLARE(int) ap_proxy_ssl_engine(conn_rec *c, + ap_conf_vector_t *per_dir_config, + int enable) +{ + /* + * if c == NULL just check if the optional function was imported + * else run the optional function so ssl filters are inserted + */ + if (proxy_ssl_engine) { + return c ? proxy_ssl_engine(c, per_dir_config, 1, enable) : 1; + } + + if (!per_dir_config) { + if (enable) { + return ap_proxy_ssl_enable(c); + } + else { + return ap_proxy_ssl_disable(c); + } + } + + return 0; +} + PROXY_DECLARE(int) ap_proxy_conn_is_https(conn_rec *c) { if (proxy_is_https) { @@ -2606,10 +2643,11 @@ PROXY_DECLARE(const char *) ap_proxy_ssl_val(apr_pool_t *p, server_rec *s, } static int proxy_post_config(apr_pool_t *pconf, apr_pool_t *plog, - apr_pool_t *ptemp, server_rec *s) + apr_pool_t *ptemp, server_rec *main_s) { + server_rec *s = main_s; apr_status_t rv = ap_global_mutex_create(&proxy_mutex, NULL, - proxy_id, NULL, s, pconf, 0); + proxy_id, NULL, s, pconf, 0); if (rv != APR_SUCCESS) { ap_log_perror(APLOG_MARK, APLOG_CRIT, rv, plog, APLOGNO(02478) "failed to create %s mutex", proxy_id); @@ -2618,11 +2656,28 @@ static int proxy_post_config(apr_pool_t *pconf, apr_pool_t *plog, proxy_ssl_enable = APR_RETRIEVE_OPTIONAL_FN(ssl_proxy_enable); proxy_ssl_disable = APR_RETRIEVE_OPTIONAL_FN(ssl_engine_disable); + proxy_ssl_engine = APR_RETRIEVE_OPTIONAL_FN(ssl_engine_set); proxy_is_https = APR_RETRIEVE_OPTIONAL_FN(ssl_is_https); proxy_ssl_val = APR_RETRIEVE_OPTIONAL_FN(ssl_var_lookup); ap_proxy_strmatch_path = apr_strmatch_precompile(pconf, "path=", 0); ap_proxy_strmatch_domain = apr_strmatch_precompile(pconf, "domain=", 0); + for (; s; s = s->next) { + int rc, i; + proxy_server_conf *sconf = + ap_get_module_config(s->module_config, &proxy_module); + ap_conf_vector_t **sections = + (ap_conf_vector_t **)sconf->sec_proxy->elts; + + for (i = 0; i < sconf->sec_proxy->nelts; ++i) { + rc = proxy_run_section_post_config(pconf, ptemp, plog, + s, sections[i]); + if (rc != OK && rc != DECLINED) { + return rc; + } + } + } + return OK; } @@ -2907,6 +2962,12 @@ APR_IMPLEMENT_EXTERNAL_HOOK_RUN_FIRST(proxy, PROXY, int, post_request, request_rec *r, proxy_server_conf *conf),(worker, balancer,r,conf),DECLINED) +APR_IMPLEMENT_OPTIONAL_HOOK_RUN_ALL(proxy, PROXY, int, section_post_config, + (apr_pool_t *p, apr_pool_t *plog, + apr_pool_t *ptemp, server_rec *s, + ap_conf_vector_t *section_config), + (p, ptemp, plog, s, section_config), + OK, DECLINED) APR_IMPLEMENT_OPTIONAL_HOOK_RUN_ALL(proxy, PROXY, int, fixups, (request_rec *r), (r), OK, DECLINED) diff --git a/modules/proxy/mod_proxy.h b/modules/proxy/mod_proxy.h index 4f31bed389..1708c5c4f2 100644 --- a/modules/proxy/mod_proxy.h +++ b/modules/proxy/mod_proxy.h @@ -457,6 +457,7 @@ struct proxy_worker { proxy_balancer *balancer; /* which balancer am I in? */ apr_thread_mutex_t *tmutex; /* Thread lock for updating address cache */ void *context; /* general purpose storage */ + ap_conf_vector_t *section_config; /* -section wherein defined */ }; /* default to health check every 30 seconds */ @@ -513,6 +514,7 @@ struct proxy_balancer { void *context; /* general purpose storage */ proxy_balancer_shared *s; /* Shared data */ int failontimeout; /* Whether to mark a member in Err if IO timeout occurs */ + ap_conf_vector_t *section_config; /* -section wherein defined */ }; struct proxy_balancer_method { @@ -574,15 +576,22 @@ APR_DECLARE_OPTIONAL_FN(const char *, set_worker_hc_param, (apr_pool_t *, server_rec *, proxy_worker *, const char *, const char *, void *)); -APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, scheme_handler, (request_rec *r, - proxy_worker *worker, proxy_server_conf *conf, char *url, - const char *proxyhost, apr_port_t proxyport)) -APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, canon_handler, (request_rec *r, - char *url)) +APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, section_post_config, + (apr_pool_t *p, apr_pool_t *plog, + apr_pool_t *ptemp, server_rec *s, + ap_conf_vector_t *section_config)) + +APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, scheme_handler, + (request_rec *r, proxy_worker *worker, + proxy_server_conf *conf, char *url, + const char *proxyhost, apr_port_t proxyport)) +APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, canon_handler, + (request_rec *r, char *url)) APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, create_req, (request_rec *r, request_rec *pr)) APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, fixups, (request_rec *r)) + /** * pre request hook. * It will return the most suitable worker at the moment @@ -643,6 +652,9 @@ PROXY_DECLARE(apr_status_t) ap_proxy_ssl_connection_cleanup(proxy_conn_rec *conn request_rec *r); PROXY_DECLARE(int) ap_proxy_ssl_enable(conn_rec *c); PROXY_DECLARE(int) ap_proxy_ssl_disable(conn_rec *c); +PROXY_DECLARE(int) ap_proxy_ssl_engine(conn_rec *c, + ap_conf_vector_t *per_dir_config, + int enable); PROXY_DECLARE(int) ap_proxy_conn_is_https(conn_rec *c); PROXY_DECLARE(const char *) ap_proxy_ssl_val(apr_pool_t *p, server_rec *s, conn_rec *c, request_rec *r, const char *var); @@ -974,7 +986,7 @@ PROXY_DECLARE(apr_status_t) ap_proxy_connect_uds(apr_socket_t *sock, * Make a connection record for backend connection * @param proxy_function calling proxy scheme (http, ajp, ...) * @param conn acquired connection - * @param c client connection record + * @param c client connection record (unused, deprecated) * @param s current server record * @return OK or HTTP_XXX error * @note The function will return immediately if conn->connection @@ -984,6 +996,18 @@ PROXY_DECLARE(int) ap_proxy_connection_create(const char *proxy_function, proxy_conn_rec *conn, conn_rec *c, server_rec *s); +/** + * Make a connection record for backend connection, using request dir config + * @param proxy_function calling proxy scheme (http, ajp, ...) + * @param conn acquired connection + * @param r current request record + * @return OK or HTTP_XXX error + * @note The function will return immediately if conn->connection + * is already set, + */ +PROXY_DECLARE(int) ap_proxy_connection_create_ex(const char *proxy_function, + proxy_conn_rec *conn, + request_rec *r); /** * Determine if proxy connection can potentially be reused at the * end of this request. diff --git a/modules/proxy/mod_proxy_connect.c b/modules/proxy/mod_proxy_connect.c index 1984342a37..7be6a6a50e 100644 --- a/modules/proxy/mod_proxy_connect.c +++ b/modules/proxy/mod_proxy_connect.c @@ -299,7 +299,7 @@ static int proxy_connect_handler(request_rec *r, proxy_worker *worker, apr_socket_close(sock); return HTTP_INTERNAL_SERVER_ERROR; } - ap_proxy_ssl_disable(backconn); + ap_proxy_ssl_engine(backconn, r->per_dir_config, 0); rc = ap_run_pre_connection(backconn, sock); if (rc != OK && rc != DONE) { backconn->aborted = 1; diff --git a/modules/proxy/mod_proxy_ftp.c b/modules/proxy/mod_proxy_ftp.c index 104736b242..4a10987b4d 100644 --- a/modules/proxy/mod_proxy_ftp.c +++ b/modules/proxy/mod_proxy_ftp.c @@ -1181,7 +1181,7 @@ static int proxy_ftp_handler(request_rec *r, proxy_worker *worker, } if (!backend->connection) { - status = ap_proxy_connection_create("FTP", backend, c, r->server); + status = ap_proxy_connection_create_ex("FTP", backend, r); if (status != OK) { proxy_ftp_cleanup(r, backend); return status; @@ -1967,7 +1967,7 @@ static int proxy_ftp_handler(request_rec *r, proxy_worker *worker, * We do not do SSL over the data connection, even if the virtual host we * are in might have SSL enabled */ - ap_proxy_ssl_disable(data); + ap_proxy_ssl_engine(data, r->per_dir_config, 0); /* set up the connection filters */ rc = ap_run_pre_connection(data, data_sock); if (rc != OK && rc != DONE) { diff --git a/modules/proxy/mod_proxy_http.c b/modules/proxy/mod_proxy_http.c index d343aa7be7..a5bfa77364 100644 --- a/modules/proxy/mod_proxy_http.c +++ b/modules/proxy/mod_proxy_http.c @@ -1948,8 +1948,8 @@ static int proxy_http_handler(request_rec *r, proxy_worker *worker, /* Step Three: Create conn_rec */ if (!backend->connection) { - if ((status = ap_proxy_connection_create(proxy_function, backend, - c, r->server)) != OK) + if ((status = ap_proxy_connection_create_ex(proxy_function, + backend, r)) != OK) break; /* * On SSL connections set a note on the connection what CN is diff --git a/modules/proxy/mod_proxy_wstunnel.c b/modules/proxy/mod_proxy_wstunnel.c index c9949e25a2..9dda010dbc 100644 --- a/modules/proxy/mod_proxy_wstunnel.c +++ b/modules/proxy/mod_proxy_wstunnel.c @@ -285,7 +285,6 @@ static int proxy_wstunnel_handler(request_rec *r, proxy_worker *worker, proxy_conn_rec *backend = NULL; char *scheme; int retry; - conn_rec *c = r->connection; apr_pool_t *p = r->pool; apr_uri_t *uri; int is_ssl = 0; @@ -352,11 +351,13 @@ static int proxy_wstunnel_handler(request_rec *r, proxy_worker *worker, status = HTTP_SERVICE_UNAVAILABLE; break; } + /* Step Three: Create conn_rec */ if (!backend->connection) { - if ((status = ap_proxy_connection_create(scheme, backend, - c, r->server)) != OK) + status = ap_proxy_connection_create_ex(scheme, backend, r); + if (status != OK) { break; + } } backend->close = 1; /* must be after ap_proxy_determine_connection */ diff --git a/modules/proxy/proxy_util.c b/modules/proxy/proxy_util.c index b61d56fd4e..7b4cb09e08 100644 --- a/modules/proxy/proxy_util.c +++ b/modules/proxy/proxy_util.c @@ -2997,11 +2997,12 @@ static apr_status_t connection_shutdown(void *theconn) } -PROXY_DECLARE(int) ap_proxy_connection_create(const char *proxy_function, - proxy_conn_rec *conn, - conn_rec *c, - server_rec *s) +static int proxy_connection_create(const char *proxy_function, + proxy_conn_rec *conn, + request_rec *r, server_rec *s) { + ap_conf_vector_t *per_dir_config = (r) ? r->per_dir_config + : conn->worker->section_config; apr_sockaddr_t *backend_addr = conn->addr; int rc; apr_interval_time_t current_timeout; @@ -3036,7 +3037,7 @@ PROXY_DECLARE(int) ap_proxy_connection_create(const char *proxy_function, /* For ssl connection to backend */ if (conn->is_ssl) { - if (!ap_proxy_ssl_enable(conn->connection)) { + if (!ap_proxy_ssl_engine(conn->connection, per_dir_config, 1)) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(00961) "%s: failed to enable ssl support " "for %pI (%s)", proxy_function, @@ -3046,7 +3047,7 @@ PROXY_DECLARE(int) ap_proxy_connection_create(const char *proxy_function, } else { /* TODO: See if this will break FTP */ - ap_proxy_ssl_disable(conn->connection); + ap_proxy_ssl_engine(conn->connection, per_dir_config, 0); } ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(00962) @@ -3078,6 +3079,21 @@ PROXY_DECLARE(int) ap_proxy_connection_create(const char *proxy_function, return OK; } +PROXY_DECLARE(int) ap_proxy_connection_create_ex(const char *proxy_function, + proxy_conn_rec *conn, + request_rec *r) +{ + return proxy_connection_create(proxy_function, conn, r, r->server); +} + +PROXY_DECLARE(int) ap_proxy_connection_create(const char *proxy_function, + proxy_conn_rec *conn, + conn_rec *c, server_rec *s) +{ + (void) c; /* unused */ + return proxy_connection_create(proxy_function, conn, NULL, s); +} + int ap_proxy_lb_workers(void) { /* diff --git a/modules/ssl/mod_ssl.c b/modules/ssl/mod_ssl.c index 7eea7ce5cc..48d64cb624 100644 --- a/modules/ssl/mod_ssl.c +++ b/modules/ssl/mod_ssl.c @@ -32,6 +32,8 @@ #include "ap_provider.h" #include "http_config.h" +#include "mod_proxy.h" /* for proxy_hook_section_post_config() */ + #include static int modssl_running_statically = 0; @@ -52,6 +54,10 @@ APR_IMPLEMENT_OPTIONAL_HOOK_RUN_ALL(ssl, SSL, int, pre_handshake, AP_INIT_##args("SSL"#name, ssl_cmd_SSL##name, \ NULL, RSRC_CONF, desc), +#define SSL_CMD_PXY(name, args, desc) \ + AP_INIT_##args("SSL"#name, ssl_cmd_SSL##name, \ + NULL, RSRC_CONF|PROXY_CONF, desc), + #define SSL_CMD_DIR(name, type, args, desc) \ AP_INIT_##args("SSL"#name, ssl_cmd_SSL##name, \ NULL, OR_##type, desc), @@ -173,50 +179,50 @@ static const command_rec ssl_config_cmds[] = { /* * Proxy configuration for remote SSL connections */ - SSL_CMD_SRV(ProxyEngine, FLAG, + SSL_CMD_PXY(ProxyEngine, FLAG, "SSL switch for the proxy protocol engine " "('on', 'off')") - SSL_CMD_SRV(ProxyProtocol, RAW_ARGS, + SSL_CMD_PXY(ProxyProtocol, RAW_ARGS, "SSL Proxy: enable or disable SSL protocol flavors " "('[+-][" SSL_PROTOCOLS "] ...' - see manual)") - SSL_CMD_SRV(ProxyCipherSuite, TAKE1, + SSL_CMD_PXY(ProxyCipherSuite, TAKE1, "SSL Proxy: colon-delimited list of permitted SSL ciphers " "('XXX:...:XXX' - see manual)") - SSL_CMD_SRV(ProxyVerify, TAKE1, + SSL_CMD_PXY(ProxyVerify, TAKE1, "SSL Proxy: whether to verify the remote certificate " "('on' or 'off')") - SSL_CMD_SRV(ProxyVerifyDepth, TAKE1, + SSL_CMD_PXY(ProxyVerifyDepth, TAKE1, "SSL Proxy: maximum certificate verification depth " "('N' - number of intermediate certificates)") - SSL_CMD_SRV(ProxyCACertificateFile, TAKE1, + SSL_CMD_PXY(ProxyCACertificateFile, TAKE1, "SSL Proxy: file containing server certificates " "('/path/to/file' - PEM encoded certificates)") - SSL_CMD_SRV(ProxyCACertificatePath, TAKE1, + SSL_CMD_PXY(ProxyCACertificatePath, TAKE1, "SSL Proxy: directory containing server certificates " "('/path/to/dir' - contains PEM encoded certificates)") - SSL_CMD_SRV(ProxyCARevocationPath, TAKE1, + SSL_CMD_PXY(ProxyCARevocationPath, TAKE1, "SSL Proxy: CA Certificate Revocation List (CRL) path " "('/path/to/dir' - contains PEM encoded files)") - SSL_CMD_SRV(ProxyCARevocationFile, TAKE1, + SSL_CMD_PXY(ProxyCARevocationFile, TAKE1, "SSL Proxy: CA Certificate Revocation List (CRL) file " "('/path/to/file' - PEM encoded)") - SSL_CMD_SRV(ProxyCARevocationCheck, RAW_ARGS, + SSL_CMD_PXY(ProxyCARevocationCheck, RAW_ARGS, "SSL Proxy: CA Certificate Revocation List (CRL) checking mode") - SSL_CMD_SRV(ProxyMachineCertificateFile, TAKE1, + SSL_CMD_PXY(ProxyMachineCertificateFile, TAKE1, "SSL Proxy: file containing client certificates " "('/path/to/file' - PEM encoded certificates)") - SSL_CMD_SRV(ProxyMachineCertificatePath, TAKE1, + SSL_CMD_PXY(ProxyMachineCertificatePath, TAKE1, "SSL Proxy: directory containing client certificates " "('/path/to/dir' - contains PEM encoded certificates)") - SSL_CMD_SRV(ProxyMachineCertificateChainFile, TAKE1, + SSL_CMD_PXY(ProxyMachineCertificateChainFile, TAKE1, "SSL Proxy: file containing issuing certificates " "of the client certificate " "(`/path/to/file' - PEM encoded certificates)") - SSL_CMD_SRV(ProxyCheckPeerExpire, FLAG, + SSL_CMD_PXY(ProxyCheckPeerExpire, FLAG, "SSL Proxy: check the peer certificate's expiration date") - SSL_CMD_SRV(ProxyCheckPeerCN, FLAG, + SSL_CMD_PXY(ProxyCheckPeerCN, FLAG, "SSL Proxy: check the peer certificate's CN") - SSL_CMD_SRV(ProxyCheckPeerName, FLAG, + SSL_CMD_PXY(ProxyCheckPeerName, FLAG, "SSL Proxy: check the peer certificate's name " "(must be present in subjectAltName extension or CN") @@ -438,7 +444,8 @@ static int ssl_hook_pre_config(apr_pool_t *pconf, return OK; } -static SSLConnRec *ssl_init_connection_ctx(conn_rec *c) +static SSLConnRec *ssl_init_connection_ctx(conn_rec *c, + ap_conf_vector_t *per_dir_config) { SSLConnRec *sslconn = myConnConfig(c); SSLSrvConfigRec *sc; @@ -449,6 +456,14 @@ static SSLConnRec *ssl_init_connection_ctx(conn_rec *c) sslconn = apr_pcalloc(c->pool, sizeof(*sslconn)); + if (per_dir_config) { + sslconn->dc = ap_get_module_config(per_dir_config, &ssl_module); + } + else { + sslconn->dc = ap_get_module_config(c->base_server->lookup_defaults, + &ssl_module); + } + sslconn->server = c->base_server; sslconn->verify_depth = UNSET; sc = mySrvConfig(c->base_server); @@ -459,72 +474,101 @@ static SSLConnRec *ssl_init_connection_ctx(conn_rec *c) return sslconn; } -int ssl_proxy_enable(conn_rec *c) +static int ssl_engine_status(conn_rec *c, SSLConnRec *sslconn) { - SSLSrvConfigRec *sc; - - SSLConnRec *sslconn = ssl_init_connection_ctx(c); - sc = mySrvConfig(sslconn->server); - - if (!sc->proxy_enabled) { - ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(01961) - "SSL Proxy requested for %s but not enabled " - "[Hint: SSLProxyEngine]", sc->vhost_id); - - return 0; + if (c->master) { + return DECLINED; } - - sslconn->is_proxy = 1; - sslconn->disabled = 0; - - return 1; + if (sslconn) { + if (sslconn->disabled) { + return SUSPENDED; + } + if (sslconn->is_proxy) { + if (!sslconn->dc->proxy_enabled) { + return DECLINED; + } + } + else { + if (mySrvConfig(sslconn->server)->enabled != SSL_ENABLED_TRUE) { + return DECLINED; + } + } + } + else { + if (mySrvConfig(c->base_server)->enabled != SSL_ENABLED_TRUE) { + return DECLINED; + } + } + return OK; } -int ssl_engine_disable(conn_rec *c) +static int ssl_engine_set(conn_rec *c, + ap_conf_vector_t *per_dir_config, + int proxy, int enable) { - SSLSrvConfigRec *sc; - - SSLConnRec *sslconn = myConnConfig(c); - - if (sslconn) { - sc = mySrvConfig(sslconn->server); + SSLConnRec *sslconn; + int status; + + if (proxy) { + sslconn = ssl_init_connection_ctx(c, per_dir_config); + sslconn->is_proxy = 1; } else { - sc = mySrvConfig(c->base_server); + sslconn = myConnConfig(c); } - if (sc->enabled == SSL_ENABLED_FALSE) { - return 0; + + status = ssl_engine_status(c, sslconn); + + if (proxy && status == DECLINED) { + if (enable) { + SSLSrvConfigRec *sc = mySrvConfig(sslconn->server); + ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(01961) + "SSL Proxy requested for %s but not enabled " + "[Hint: SSLProxyEngine]", sc->vhost_id); + } + sslconn->disabled = 1; + } + else if (sslconn) { + sslconn->disabled = !enable; } - sslconn = ssl_init_connection_ctx(c); + return status != DECLINED; +} - sslconn->disabled = 1; +static int ssl_proxy_enable(conn_rec *c) +{ + return ssl_engine_set(c, NULL, 1, 1); +} - return 1; +static int ssl_engine_disable(conn_rec *c) +{ + return ssl_engine_set(c, NULL, 0, 0); } int ssl_init_ssl_connection(conn_rec *c, request_rec *r) { SSLSrvConfigRec *sc; SSL *ssl; - SSLConnRec *sslconn = myConnConfig(c); + SSLConnRec *sslconn; char *vhost_md5; int rc; modssl_ctx_t *mctx; server_rec *server; - if (!sslconn) { - sslconn = ssl_init_connection_ctx(c); - } + /* + * Create or retrieve SSL context + */ + sslconn = ssl_init_connection_ctx(c, r ? r->per_dir_config : NULL); server = sslconn->server; sc = mySrvConfig(server); /* * Seed the Pseudo Random Number Generator (PRNG) */ - ssl_rand_seed(server, c->pool, SSL_RSCTX_CONNECT, ""); + ssl_rand_seed(server, c->pool, SSL_RSCTX_CONNECT, + sslconn->is_proxy ? "Proxy: " : "Server: "); - mctx = sslconn->is_proxy ? sc->proxy : sc->server; + mctx = myCtxConfig(sslconn, sc); /* * Create a new SSL connection with the configured server SSL context and @@ -596,34 +640,21 @@ static apr_port_t ssl_hook_default_port(const request_rec *r) static int ssl_hook_pre_connection(conn_rec *c, void *csd) { - SSLSrvConfigRec *sc; SSLConnRec *sslconn = myConnConfig(c); - if (sslconn) { - sc = mySrvConfig(sslconn->server); - } - else { - sc = mySrvConfig(c->base_server); - } /* * Immediately stop processing if SSL is disabled for this connection */ - if (c->master || !(sc && (sc->enabled == SSL_ENABLED_TRUE || - (sslconn && sslconn->is_proxy)))) - { + if (ssl_engine_status(c, sslconn) != OK) { return DECLINED; } - /* - * Create SSL context - */ - if (!sslconn) { - sslconn = ssl_init_connection_ctx(c); + if (sslconn) { + sc = mySrvConfig(sslconn->server); } - - if (sslconn->disabled) { - return DECLINED; + else { + sc = mySrvConfig(c->base_server); } /* @@ -667,6 +698,12 @@ static void ssl_register_hooks(apr_pool_t *p) /* ssl_hook_ReadReq needs to use the BrowserMatch settings so must * run after mod_setenvif's post_read_request hook. */ static const char *pre_prr[] = { "mod_setenvif.c", NULL }; + /* The ssl_init_Module post_config hook should run before mod_proxy's + * for the ssl proxy main configs to be merged with vhosts' before being + * themselves merged with mod_proxy's in proxy_hook_section_post_config. + */ + static const char *b_pc[] = { "mod_proxy.c", NULL}; + ssl_io_filter_register(p); @@ -674,7 +711,7 @@ static void ssl_register_hooks(apr_pool_t *p) ap_hook_process_connection(ssl_hook_process_connection, NULL, NULL, APR_HOOK_MIDDLE); ap_hook_test_config (ssl_hook_ConfigTest, NULL,NULL, APR_HOOK_MIDDLE); - ap_hook_post_config (ssl_init_Module, NULL,NULL, APR_HOOK_MIDDLE); + ap_hook_post_config (ssl_init_Module, NULL,b_pc, APR_HOOK_MIDDLE); ap_hook_http_scheme (ssl_hook_http_scheme, NULL,NULL, APR_HOOK_MIDDLE); 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); @@ -688,10 +725,15 @@ static void ssl_register_hooks(apr_pool_t *p) AP_AUTH_INTERNAL_PER_CONF); ap_hook_post_read_request(ssl_hook_ReadReq, pre_prr,NULL, APR_HOOK_MIDDLE); + APR_OPTIONAL_HOOK(proxy, section_post_config, + ssl_proxy_section_post_config, 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_engine_set); ap_register_auth_provider(p, AUTHZ_PROVIDER_GROUP, "ssl", AUTHZ_PROVIDER_VERSION, @@ -702,7 +744,6 @@ static void ssl_register_hooks(apr_pool_t *p) 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.h b/modules/ssl/mod_ssl.h index db8ffafd2e..24a65a0abe 100644 --- a/modules/ssl/mod_ssl.h +++ b/modules/ssl/mod_ssl.h @@ -27,6 +27,7 @@ #define __MOD_SSL_H__ #include "httpd.h" +#include "http_config.h" #include "apr_optional.h" /* Create a set of SSL_DECLARE(type), SSL_DECLARE_NONSTD(type) and @@ -76,13 +77,15 @@ APR_DECLARE_OPTIONAL_FN(apr_array_header_t *, ssl_ext_list, * is using SSL/TLS. */ APR_DECLARE_OPTIONAL_FN(int, ssl_is_https, (conn_rec *)); -/** The ssl_proxy_enable() and ssl_engine_disable() optional functions - * are used by mod_proxy to enable use of SSL for outgoing +/** The ssl_proxy_enable() and ssl_engine_{set,disable}() optional + * functions are used by mod_proxy to enable use of SSL for outgoing * connections. */ APR_DECLARE_OPTIONAL_FN(int, ssl_proxy_enable, (conn_rec *)); - APR_DECLARE_OPTIONAL_FN(int, ssl_engine_disable, (conn_rec *)); +APR_DECLARE_OPTIONAL_FN(int, ssl_engine_set, (conn_rec *, + ap_conf_vector_t *, + int proxy, int enable)); #endif /* __MOD_SSL_H__ */ /** @} */ diff --git a/modules/ssl/ssl_engine_config.c b/modules/ssl/ssl_engine_config.c index 78d058cb16..104d84a141 100644 --- a/modules/ssl/ssl_engine_config.c +++ b/modules/ssl/ssl_engine_config.c @@ -180,24 +180,10 @@ static void modssl_ctx_init(modssl_ctx_t *mctx, apr_pool_t *p) SSL_CONF_CTX_set_flags(mctx->ssl_ctx_config, SSL_CONF_FLAG_CERTIFICATE); mctx->ssl_ctx_param = apr_array_make(p, 5, sizeof(ssl_ctx_param_t)); #endif -} - -static void modssl_ctx_init_proxy(SSLSrvConfigRec *sc, - apr_pool_t *p) -{ - modssl_ctx_t *mctx; - - mctx = sc->proxy = apr_palloc(p, sizeof(*sc->proxy)); - - modssl_ctx_init(mctx, p); - - mctx->pkp = apr_palloc(p, sizeof(*mctx->pkp)); - 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; + mctx->ssl_check_peer_cn = UNSET; + mctx->ssl_check_peer_name = UNSET; + mctx->ssl_check_peer_expire = UNSET; } static void modssl_ctx_init_server(SSLSrvConfigRec *sc, @@ -225,15 +211,11 @@ static SSLSrvConfigRec *ssl_config_server_new(apr_pool_t *p) sc->mc = NULL; sc->enabled = SSL_ENABLED_UNSET; - sc->proxy_enabled = UNSET; sc->vhost_id = NULL; /* set during module init */ sc->vhost_id_len = 0; /* set during module init */ sc->session_cache_timeout = UNSET; sc->cipher_server_pref = UNSET; sc->insecure_reneg = UNSET; - sc->proxy_ssl_check_peer_expire = SSL_ENABLED_UNSET; - sc->proxy_ssl_check_peer_cn = SSL_ENABLED_UNSET; - sc->proxy_ssl_check_peer_name = SSL_ENABLED_UNSET; #ifdef HAVE_TLSEXT sc->strict_sni_vhost_check = SSL_ENABLED_UNSET; #endif @@ -245,8 +227,6 @@ static SSLSrvConfigRec *ssl_config_server_new(apr_pool_t *p) #endif sc->session_tickets = UNSET; - modssl_ctx_init_proxy(sc, p); - modssl_ctx_init_server(sc, p); return sc; @@ -270,6 +250,10 @@ void *ssl_config_server_create(apr_pool_t *p, server_rec *s) #define cfgMergeBool(el) cfgMerge(el, UNSET) #define cfgMergeInt(el) cfgMerge(el, UNSET) +/* + * Merge per-server SSL configurations + */ + static void modssl_ctx_cfg_merge(apr_pool_t *p, modssl_ctx_t *base, modssl_ctx_t *add, @@ -331,18 +315,10 @@ static void modssl_ctx_cfg_merge(apr_pool_t *p, #ifdef HAVE_SSL_CONF_CMD cfgMergeArray(ssl_ctx_param); #endif -} -static void modssl_ctx_cfg_merge_proxy(apr_pool_t *p, - modssl_ctx_t *base, - modssl_ctx_t *add, - modssl_ctx_t *mrg) -{ - modssl_ctx_cfg_merge(p, base, add, mrg); - - cfgMergeString(pkp->cert_file); - cfgMergeString(pkp->cert_path); - cfgMergeString(pkp->ca_cert_file); + cfgMergeBool(ssl_check_peer_cn); + cfgMergeBool(ssl_check_peer_name); + cfgMergeBool(ssl_check_peer_expire); } static void modssl_ctx_cfg_merge_certkeys_array(apr_pool_t *p, @@ -401,9 +377,6 @@ static void modssl_ctx_cfg_merge_server(apr_pool_t *p, #endif } -/* - * Merge per-server SSL configurations - */ void *ssl_config_server_merge(apr_pool_t *p, void *basev, void *addv) { SSLSrvConfigRec *base = (SSLSrvConfigRec *)basev; @@ -412,13 +385,9 @@ void *ssl_config_server_merge(apr_pool_t *p, void *basev, void *addv) cfgMerge(mc, NULL); cfgMerge(enabled, SSL_ENABLED_UNSET); - cfgMergeBool(proxy_enabled); cfgMergeInt(session_cache_timeout); cfgMergeBool(cipher_server_pref); cfgMergeBool(insecure_reneg); - cfgMerge(proxy_ssl_check_peer_expire, SSL_ENABLED_UNSET); - cfgMerge(proxy_ssl_check_peer_cn, SSL_ENABLED_UNSET); - cfgMerge(proxy_ssl_check_peer_name, SSL_ENABLED_UNSET); #ifdef HAVE_TLSEXT cfgMerge(strict_sni_vhost_check, SSL_ENABLED_UNSET); #endif @@ -430,8 +399,6 @@ void *ssl_config_server_merge(apr_pool_t *p, void *basev, void *addv) #endif cfgMergeBool(session_tickets); - modssl_ctx_cfg_merge_proxy(p, base->proxy, add->proxy, mrg->proxy); - modssl_ctx_cfg_merge_server(p, base->server, add->server, mrg->server); return mrg; @@ -440,6 +407,25 @@ void *ssl_config_server_merge(apr_pool_t *p, void *basev, void *addv) /* * Create per-directory SSL configuration */ + +static void modssl_ctx_init_proxy(SSLDirConfigRec *dc, + apr_pool_t *p) +{ + modssl_ctx_t *mctx; + + mctx = dc->proxy = apr_palloc(p, sizeof(*dc->proxy)); + + modssl_ctx_init(mctx, p); + + mctx->pkp = apr_palloc(p, sizeof(*mctx->pkp)); + + 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; +} + void *ssl_config_perdir_create(apr_pool_t *p, char *dir) { SSLDirConfigRec *dc = apr_palloc(p, sizeof(*dc)); @@ -454,18 +440,33 @@ void *ssl_config_perdir_create(apr_pool_t *p, char *dir) dc->nVerifyClient = SSL_CVERIFY_UNSET; dc->nVerifyDepth = UNSET; - dc->szCACertificatePath = NULL; - dc->szCACertificateFile = NULL; dc->szUserName = NULL; dc->nRenegBufferSize = UNSET; + dc->proxy_enabled = UNSET; + modssl_ctx_init_proxy(dc, p); + dc->proxy_post_config = FALSE; + return dc; } /* * Merge per-directory SSL configurations */ + +static void modssl_ctx_cfg_merge_proxy(apr_pool_t *p, + modssl_ctx_t *base, + modssl_ctx_t *add, + modssl_ctx_t *mrg) +{ + modssl_ctx_cfg_merge(p, base, add, mrg); + + cfgMergeString(pkp->cert_file); + cfgMergeString(pkp->cert_path); + cfgMergeString(pkp->ca_cert_file); +} + void *ssl_config_perdir_merge(apr_pool_t *p, void *basev, void *addv) { SSLDirConfigRec *base = (SSLDirConfigRec *)basev; @@ -493,15 +494,38 @@ void *ssl_config_perdir_merge(apr_pool_t *p, void *basev, void *addv) cfgMerge(nVerifyClient, SSL_CVERIFY_UNSET); cfgMergeInt(nVerifyDepth); - cfgMergeString(szCACertificatePath); - cfgMergeString(szCACertificateFile); cfgMergeString(szUserName); cfgMergeInt(nRenegBufferSize); + mrg->proxy_post_config = add->proxy_post_config; + if (!add->proxy_post_config) { + cfgMergeBool(proxy_enabled); + modssl_ctx_init_proxy(mrg, p); + modssl_ctx_cfg_merge_proxy(p, base->proxy, add->proxy, mrg->proxy); + } + else { + /* post_config hook has already merged and initialized the + * proxy context, use it. + */ + mrg->proxy_enabled = add->proxy_enabled; + mrg->proxy = add->proxy; + } + return mrg; } +/* Simply merge conf with base into conf, no third party. */ +void ssl_config_proxy_merge(apr_pool_t *p, + SSLDirConfigRec *base, + SSLDirConfigRec *conf) +{ + if (conf->proxy_enabled == UNSET) { + conf->proxy_enabled = base->proxy_enabled; + } + modssl_ctx_cfg_merge_proxy(p, base->proxy, conf->proxy, conf->proxy); +} + /* * Configuration functions for particular directives */ @@ -1110,7 +1134,7 @@ const char *ssl_cmd_SSLVerifyClient(cmd_parms *cmd, { SSLDirConfigRec *dc = (SSLDirConfigRec *)dcfg; SSLSrvConfigRec *sc = mySrvConfig(cmd->server); - ssl_verify_t mode; + ssl_verify_t mode = SSL_CVERIFY_NONE; const char *err; if ((err = ssl_cmd_verify_parse(cmd, arg, &mode))) { @@ -1455,9 +1479,9 @@ const char *ssl_cmd_SSLProtocol(cmd_parms *cmd, const char *ssl_cmd_SSLProxyEngine(cmd_parms *cmd, void *dcfg, int flag) { - SSLSrvConfigRec *sc = mySrvConfig(cmd->server); + SSLDirConfigRec *dc = (SSLDirConfigRec *)dcfg; - sc->proxy_enabled = flag ? TRUE : FALSE; + dc->proxy_enabled = flag ? TRUE : FALSE; return NULL; } @@ -1466,22 +1490,22 @@ const char *ssl_cmd_SSLProxyProtocol(cmd_parms *cmd, void *dcfg, const char *arg) { - SSLSrvConfigRec *sc = mySrvConfig(cmd->server); + SSLDirConfigRec *dc = (SSLDirConfigRec *)dcfg; - sc->proxy->protocol_set = 1; - return ssl_cmd_protocol_parse(cmd, arg, &sc->proxy->protocol); + dc->proxy->protocol_set = 1; + return ssl_cmd_protocol_parse(cmd, arg, &dc->proxy->protocol); } const char *ssl_cmd_SSLProxyCipherSuite(cmd_parms *cmd, void *dcfg, const char *arg) { - SSLSrvConfigRec *sc = mySrvConfig(cmd->server); + SSLDirConfigRec *dc = (SSLDirConfigRec *)dcfg; /* always disable null and export ciphers */ arg = apr_pstrcat(cmd->pool, arg, ":!aNULL:!eNULL:!EXP", NULL); - sc->proxy->auth.cipher_suite = arg; + dc->proxy->auth.cipher_suite = arg; return NULL; } @@ -1490,15 +1514,15 @@ const char *ssl_cmd_SSLProxyVerify(cmd_parms *cmd, void *dcfg, const char *arg) { - SSLSrvConfigRec *sc = mySrvConfig(cmd->server); - ssl_verify_t mode; + SSLDirConfigRec *dc = (SSLDirConfigRec *)dcfg; + ssl_verify_t mode = SSL_CVERIFY_NONE; const char *err; if ((err = ssl_cmd_verify_parse(cmd, arg, &mode))) { return err; } - sc->proxy->auth.verify_mode = mode; + dc->proxy->auth.verify_mode = mode; return NULL; } @@ -1507,7 +1531,7 @@ const char *ssl_cmd_SSLProxyVerifyDepth(cmd_parms *cmd, void *dcfg, const char *arg) { - SSLSrvConfigRec *sc = mySrvConfig(cmd->server); + SSLDirConfigRec *dc = (SSLDirConfigRec *)dcfg; int depth; const char *err; @@ -1515,7 +1539,7 @@ const char *ssl_cmd_SSLProxyVerifyDepth(cmd_parms *cmd, return err; } - sc->proxy->auth.verify_depth = depth; + dc->proxy->auth.verify_depth = depth; return NULL; } @@ -1524,14 +1548,14 @@ const char *ssl_cmd_SSLProxyCACertificateFile(cmd_parms *cmd, void *dcfg, const char *arg) { - SSLSrvConfigRec *sc = mySrvConfig(cmd->server); + SSLDirConfigRec *dc = (SSLDirConfigRec *)dcfg; const char *err; if ((err = ssl_cmd_check_file(cmd, &arg))) { return err; } - sc->proxy->auth.ca_cert_file = arg; + dc->proxy->auth.ca_cert_file = arg; return NULL; } @@ -1540,14 +1564,14 @@ const char *ssl_cmd_SSLProxyCACertificatePath(cmd_parms *cmd, void *dcfg, const char *arg) { - SSLSrvConfigRec *sc = mySrvConfig(cmd->server); + SSLDirConfigRec *dc = (SSLDirConfigRec *)dcfg; const char *err; if ((err = ssl_cmd_check_dir(cmd, &arg))) { return err; } - sc->proxy->auth.ca_cert_path = arg; + dc->proxy->auth.ca_cert_path = arg; return NULL; } @@ -1556,14 +1580,14 @@ const char *ssl_cmd_SSLProxyCARevocationPath(cmd_parms *cmd, void *dcfg, const char *arg) { - SSLSrvConfigRec *sc = mySrvConfig(cmd->server); + SSLDirConfigRec *dc = (SSLDirConfigRec *)dcfg; const char *err; if ((err = ssl_cmd_check_dir(cmd, &arg))) { return err; } - sc->proxy->crl_path = arg; + dc->proxy->crl_path = arg; return NULL; } @@ -1572,14 +1596,14 @@ const char *ssl_cmd_SSLProxyCARevocationFile(cmd_parms *cmd, void *dcfg, const char *arg) { - SSLSrvConfigRec *sc = mySrvConfig(cmd->server); + SSLDirConfigRec *dc = (SSLDirConfigRec *)dcfg; const char *err; if ((err = ssl_cmd_check_file(cmd, &arg))) { return err; } - sc->proxy->crl_file = arg; + dc->proxy->crl_file = arg; return NULL; } @@ -1588,23 +1612,23 @@ const char *ssl_cmd_SSLProxyCARevocationCheck(cmd_parms *cmd, void *dcfg, const char *arg) { - SSLSrvConfigRec *sc = mySrvConfig(cmd->server); + SSLDirConfigRec *dc = (SSLDirConfigRec *)dcfg; - return ssl_cmd_crlcheck_parse(cmd, arg, &sc->proxy->crl_check_mask); + return ssl_cmd_crlcheck_parse(cmd, arg, &dc->proxy->crl_check_mask); } const char *ssl_cmd_SSLProxyMachineCertificateFile(cmd_parms *cmd, void *dcfg, const char *arg) { - SSLSrvConfigRec *sc = mySrvConfig(cmd->server); + SSLDirConfigRec *dc = (SSLDirConfigRec *)dcfg; const char *err; if ((err = ssl_cmd_check_file(cmd, &arg))) { return err; } - sc->proxy->pkp->cert_file = arg; + dc->proxy->pkp->cert_file = arg; return NULL; } @@ -1613,14 +1637,14 @@ const char *ssl_cmd_SSLProxyMachineCertificatePath(cmd_parms *cmd, void *dcfg, const char *arg) { - SSLSrvConfigRec *sc = mySrvConfig(cmd->server); + SSLDirConfigRec *dc = (SSLDirConfigRec *)dcfg; const char *err; if ((err = ssl_cmd_check_dir(cmd, &arg))) { return err; } - sc->proxy->pkp->cert_path = arg; + dc->proxy->pkp->cert_path = arg; return NULL; } @@ -1629,14 +1653,14 @@ const char *ssl_cmd_SSLProxyMachineCertificateChainFile(cmd_parms *cmd, void *dcfg, const char *arg) { - SSLSrvConfigRec *sc = mySrvConfig(cmd->server); + SSLDirConfigRec *dc = (SSLDirConfigRec *)dcfg; const char *err; if ((err = ssl_cmd_check_file(cmd, &arg))) { return err; } - sc->proxy->pkp->ca_cert_file = arg; + dc->proxy->pkp->ca_cert_file = arg; return NULL; } @@ -1746,27 +1770,27 @@ const char *ssl_cmd_SSLOCSPNoVerify(cmd_parms *cmd, void *dcfg, int flag) const char *ssl_cmd_SSLProxyCheckPeerExpire(cmd_parms *cmd, void *dcfg, int flag) { - SSLSrvConfigRec *sc = mySrvConfig(cmd->server); + SSLDirConfigRec *dc = (SSLDirConfigRec *)dcfg; - sc->proxy_ssl_check_peer_expire = flag ? SSL_ENABLED_TRUE : SSL_ENABLED_FALSE; + dc->proxy->ssl_check_peer_expire = flag ? TRUE : FALSE; return NULL; } const char *ssl_cmd_SSLProxyCheckPeerCN(cmd_parms *cmd, void *dcfg, int flag) { - SSLSrvConfigRec *sc = mySrvConfig(cmd->server); + SSLDirConfigRec *dc = (SSLDirConfigRec *)dcfg; - sc->proxy_ssl_check_peer_cn = flag ? SSL_ENABLED_TRUE : SSL_ENABLED_FALSE; + dc->proxy->ssl_check_peer_cn = flag ? TRUE : FALSE; return NULL; } const char *ssl_cmd_SSLProxyCheckPeerName(cmd_parms *cmd, void *dcfg, int flag) { - SSLSrvConfigRec *sc = mySrvConfig(cmd->server); + SSLDirConfigRec *dc = (SSLDirConfigRec *)dcfg; - sc->proxy_ssl_check_peer_name = flag ? SSL_ENABLED_TRUE : SSL_ENABLED_FALSE; + dc->proxy->ssl_check_peer_name = flag ? TRUE : FALSE; return NULL; } diff --git a/modules/ssl/ssl_engine_init.c b/modules/ssl/ssl_engine_init.c index 2c26564126..a3a74f474c 100644 --- a/modules/ssl/ssl_engine_init.c +++ b/modules/ssl/ssl_engine_init.c @@ -244,10 +244,6 @@ apr_status_t ssl_init_Module(apr_pool_t *p, apr_pool_t *plog, sc->server->sc = sc; } - if (sc->proxy) { - sc->proxy->sc = sc; - } - /* * Create the server host:port string because we need it a lot */ @@ -274,9 +270,6 @@ apr_status_t ssl_init_Module(apr_pool_t *p, apr_pool_t *plog, if (sc->enabled == SSL_ENABLED_UNSET) { sc->enabled = SSL_ENABLED_FALSE; } - if (sc->proxy_enabled == UNSET) { - sc->proxy_enabled = FALSE; - } if (sc->session_cache_timeout == UNSET) { sc->session_cache_timeout = SSL_SESSION_CACHE_TIMEOUT; @@ -393,15 +386,19 @@ apr_status_t ssl_init_Module(apr_pool_t *p, apr_pool_t *plog, } for (s = base_server; s; s = s->next) { - sc = mySrvConfig(s); + SSLDirConfigRec *sdc = ap_get_module_config(s->lookup_defaults, + &ssl_module); + sc = mySrvConfig(s); if (sc->enabled == SSL_ENABLED_TRUE || sc->enabled == SSL_ENABLED_OPTIONAL) { if ((rv = ssl_run_init_server(s, p, 0, sc->server->ssl_ctx)) != APR_SUCCESS) { return rv; } } - else if (sc->proxy_enabled == SSL_ENABLED_TRUE) { - if ((rv = ssl_run_init_server(s, p, 1, sc->proxy->ssl_ctx)) != APR_SUCCESS) { + + if (sdc->proxy_enabled) { + rv = ssl_run_init_server(s, p, 1, sdc->proxy->ssl_ctx); + if (rv != APR_SUCCESS) { return rv; } } @@ -1601,18 +1598,70 @@ static apr_status_t ssl_init_proxy_certs(server_rec *s, return APR_SUCCESS; } +#define MODSSL_CFG_ITEM_FREE(func, item) \ + if (item) { \ + func(item); \ + item = NULL; \ + } + +static void ssl_init_ctx_cleanup(modssl_ctx_t *mctx) +{ + MODSSL_CFG_ITEM_FREE(SSL_CTX_free, mctx->ssl_ctx); + +#ifdef HAVE_SRP + if (mctx->srp_vbase != NULL) { + SRP_VBASE_free(mctx->srp_vbase); + mctx->srp_vbase = NULL; + } +#endif +} + +static apr_status_t ssl_cleanup_proxy_ctx(void *data) +{ + modssl_ctx_t *mctx = data; + + ssl_init_ctx_cleanup(mctx); + + if (mctx->pkp->certs) { + int i = 0; + int ncerts = sk_X509_INFO_num(mctx->pkp->certs); + + if (mctx->pkp->ca_certs) { + for (i = 0; i < ncerts; i++) { + if (mctx->pkp->ca_certs[i] != NULL) { + sk_X509_pop_free(mctx->pkp->ca_certs[i], X509_free); + } + } + } + + sk_X509_INFO_pop_free(mctx->pkp->certs, X509_INFO_free); + mctx->pkp->certs = NULL; + } + + return APR_SUCCESS; +} + static apr_status_t ssl_init_proxy_ctx(server_rec *s, apr_pool_t *p, apr_pool_t *ptemp, - SSLSrvConfigRec *sc) + modssl_ctx_t *proxy) { apr_status_t rv; - if ((rv = ssl_init_ctx(s, p, ptemp, sc->proxy)) != APR_SUCCESS) { + if (proxy->ssl_ctx) { + /* Merged/initialized already */ + return APR_SUCCESS; + } + + apr_pool_cleanup_register(p, proxy, + ssl_cleanup_proxy_ctx, + apr_pool_cleanup_null); + + if ((rv = ssl_init_ctx(s, p, ptemp, proxy)) != APR_SUCCESS) { return rv; } - if ((rv = ssl_init_proxy_certs(s, p, ptemp, sc->proxy)) != APR_SUCCESS) { + if ((rv = ssl_init_proxy_certs(s, p, ptemp, proxy)) != APR_SUCCESS) { return rv; } @@ -1780,6 +1829,8 @@ apr_status_t ssl_init_ConfigureServer(server_rec *s, SSLSrvConfigRec *sc, apr_array_header_t *pphrases) { + SSLDirConfigRec *sdc = ap_get_module_config(s->lookup_defaults, + &ssl_module); apr_status_t rv; /* Initialize the server if SSL is enabled or optional. @@ -1799,11 +1850,17 @@ apr_status_t ssl_init_ConfigureServer(server_rec *s, } - if (sc->proxy_enabled) { - if ((rv = ssl_init_proxy_ctx(s, p, ptemp, sc)) != APR_SUCCESS) { + sdc->proxy->sc = sc; + if (sdc->proxy_enabled == TRUE) { + rv = ssl_init_proxy_ctx(s, p, ptemp, sdc->proxy); + if (rv != APR_SUCCESS) { return rv; } } + else { + sdc->proxy_enabled = FALSE; + } + sdc->proxy_post_config = 1; return APR_SUCCESS; } @@ -1898,6 +1955,35 @@ apr_status_t ssl_init_CheckServers(server_rec *base_server, apr_pool_t *p) return APR_SUCCESS; } +int ssl_proxy_section_post_config(apr_pool_t *p, apr_pool_t *plog, + apr_pool_t *ptemp, server_rec *s, + ap_conf_vector_t *section_config) +{ + SSLDirConfigRec *sdc = ap_get_module_config(s->lookup_defaults, + &ssl_module); + SSLDirConfigRec *pdc = ap_get_module_config(section_config, + &ssl_module); + if (pdc) { + pdc->proxy->sc = mySrvConfig(s); + ssl_config_proxy_merge(p, sdc, pdc); + if (pdc->proxy_enabled) { + apr_status_t rv; + + rv = ssl_init_proxy_ctx(s, p, ptemp, pdc->proxy); + if (rv != APR_SUCCESS) { + return !OK; + } + + rv = ssl_run_init_server(s, p, 1, pdc->proxy->ssl_ctx); + if (rv != APR_SUCCESS) { + return !OK; + } + } + pdc->proxy_post_config = 1; + } + return OK; +} + static int ssl_init_FindCAList_X509NameCmp(const X509_NAME * const *a, const X509_NAME * const *b) { @@ -2025,45 +2111,6 @@ void ssl_init_Child(apr_pool_t *p, server_rec *s) #endif } -#define MODSSL_CFG_ITEM_FREE(func, item) \ - if (item) { \ - func(item); \ - item = NULL; \ - } - -static void ssl_init_ctx_cleanup(modssl_ctx_t *mctx) -{ - MODSSL_CFG_ITEM_FREE(SSL_CTX_free, mctx->ssl_ctx); - -#ifdef HAVE_SRP - if (mctx->srp_vbase != NULL) { - SRP_VBASE_free(mctx->srp_vbase); - mctx->srp_vbase = NULL; - } -#endif -} - -static void ssl_init_ctx_cleanup_proxy(modssl_ctx_t *mctx) -{ - ssl_init_ctx_cleanup(mctx); - - if (mctx->pkp->certs) { - int i = 0; - int ncerts = sk_X509_INFO_num(mctx->pkp->certs); - - if (mctx->pkp->ca_certs) { - for (i = 0; i < ncerts; i++) { - if (mctx->pkp->ca_certs[i] != NULL) { - sk_X509_pop_free(mctx->pkp->ca_certs[i], X509_free); - } - } - } - - sk_X509_INFO_pop_free(mctx->pkp->certs, X509_INFO_free); - mctx->pkp->certs = NULL; - } -} - apr_status_t ssl_init_ModuleKill(void *data) { SSLSrvConfigRec *sc; @@ -2082,8 +2129,6 @@ apr_status_t ssl_init_ModuleKill(void *data) for (s = base_server; s; s = s->next) { sc = mySrvConfig(s); - ssl_init_ctx_cleanup_proxy(sc->proxy); - ssl_init_ctx_cleanup(sc->server); /* Not Sure but possibly clear X509 trusted cert file */ diff --git a/modules/ssl/ssl_engine_io.c b/modules/ssl/ssl_engine_io.c index d5ebac9bcb..1a47b0e982 100644 --- a/modules/ssl/ssl_engine_io.c +++ b/modules/ssl/ssl_engine_io.c @@ -1170,7 +1170,9 @@ static apr_status_t ssl_io_filter_handshake(ssl_filter_ctx_t *filter_ctx) "proxy-request-hostname"); BOOL proxy_ssl_check_peer_ok = TRUE; int post_handshake_rc = OK; + SSLDirConfigRec *dc; + dc = sslconn->dc; sc = mySrvConfig(server); #ifdef HAVE_TLSEXT @@ -1218,7 +1220,7 @@ static apr_status_t ssl_io_filter_handshake(ssl_filter_ctx_t *filter_ctx) */ if (hostname_note && #ifndef OPENSSL_NO_SSL3 - sc->proxy->protocol != SSL_PROTOCOL_SSLV3 && + dc->proxy->protocol != SSL_PROTOCOL_SSLV3 && #endif apr_ipsubnet_create(&ip, hostname_note, NULL, c->pool) != APR_SUCCESS) { @@ -1247,7 +1249,7 @@ static apr_status_t ssl_io_filter_handshake(ssl_filter_ctx_t *filter_ctx) cert = SSL_get_peer_certificate(filter_ctx->pssl); - if (sc->proxy_ssl_check_peer_expire != SSL_ENABLED_FALSE) { + if (dc->proxy->ssl_check_peer_expire != FALSE) { if (!cert || (X509_cmp_current_time( X509_get_notBefore(cert)) >= 0) @@ -1258,9 +1260,9 @@ static apr_status_t ssl_io_filter_handshake(ssl_filter_ctx_t *filter_ctx) "SSL Proxy: Peer certificate is expired"); } } - if ((sc->proxy_ssl_check_peer_name != SSL_ENABLED_FALSE) && - ((sc->proxy_ssl_check_peer_cn != SSL_ENABLED_FALSE) || - (sc->proxy_ssl_check_peer_name == SSL_ENABLED_TRUE)) && + if ((dc->proxy->ssl_check_peer_name != FALSE) && + ((dc->proxy->ssl_check_peer_cn != FALSE) || + (dc->proxy->ssl_check_peer_name == TRUE)) && hostname_note) { apr_table_unset(c->notes, "proxy-request-hostname"); if (!cert @@ -1272,7 +1274,7 @@ static apr_status_t ssl_io_filter_handshake(ssl_filter_ctx_t *filter_ctx) "for hostname %s", hostname_note); } } - else if ((sc->proxy_ssl_check_peer_cn == SSL_ENABLED_TRUE) && + else if ((dc->proxy->ssl_check_peer_cn == TRUE) && hostname_note) { const char *hostname; int match = 0; diff --git a/modules/ssl/ssl_engine_kernel.c b/modules/ssl/ssl_engine_kernel.c index b22f8c125a..0da9b45c95 100644 --- a/modules/ssl/ssl_engine_kernel.c +++ b/modules/ssl/ssl_engine_kernel.c @@ -1568,8 +1568,8 @@ int ssl_callback_SSLVerify(int ok, X509_STORE_CTX *ctx) server_rec *s = r ? r->server : mySrvFromConn(conn); SSLSrvConfigRec *sc = mySrvConfig(s); - SSLDirConfigRec *dc = r ? myDirConfig(r) : NULL; SSLConnRec *sslconn = myConnConfig(conn); + SSLDirConfigRec *dc = r ? myDirConfig(r) : sslconn->dc; modssl_ctx_t *mctx = myCtxConfig(sslconn, sc); int crl_check_mode = mctx->crl_check_mask & ~SSL_CRLCHECK_FLAGS; @@ -1761,11 +1761,12 @@ 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); + SSLDirConfigRec *dc = myDirConfigFromConn(c); 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; + STACK_OF(X509_INFO) *certs; STACK_OF(X509) *ca_certs; STACK_OF(X509) **ca_cert_chains; int i, j, k; @@ -1774,6 +1775,7 @@ int ssl_callback_proxy_cert(SSL *ssl, X509 **x509, EVP_PKEY **pkey) SSLPROXY_CERT_CB_LOG_FMT "entered", sc->vhost_id); + certs = (dc && dc->proxy) ? dc->proxy->pkp->certs : NULL; if (!certs || (sk_X509_INFO_num(certs) <= 0)) { ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(02268) SSLPROXY_CERT_CB_LOG_FMT @@ -1798,7 +1800,7 @@ int ssl_callback_proxy_cert(SSL *ssl, X509 **x509, EVP_PKEY **pkey) return TRUE; } - ca_cert_chains = sc->proxy->pkp->ca_certs; + ca_cert_chains = dc->proxy->pkp->ca_certs; for (i = 0; i < sk_X509_NAME_num(ca_list); i++) { ca_name = sk_X509_NAME_value(ca_list, i); diff --git a/modules/ssl/ssl_private.h b/modules/ssl/ssl_private.h index 9990f8b41e..a39569cbf7 100644 --- a/modules/ssl/ssl_private.h +++ b/modules/ssl/ssl_private.h @@ -296,14 +296,18 @@ APLOG_USE_MODULE(ssl); #define strIsEmpty(s) (s == NULL || s[0] == NUL) #define myConnConfig(c) \ -(SSLConnRec *)ap_get_module_config(c->conn_config, &ssl_module) -#define myCtxConfig(sslconn, sc) (sslconn->is_proxy ? sc->proxy : sc->server) + ((SSLConnRec *)ap_get_module_config(c->conn_config, &ssl_module)) #define myConnConfigSet(c, val) \ -ap_set_module_config(c->conn_config, &ssl_module, val) -#define mySrvConfig(srv) (SSLSrvConfigRec *)ap_get_module_config(srv->module_config, &ssl_module) -#define myDirConfig(req) (SSLDirConfigRec *)ap_get_module_config(req->per_dir_config, &ssl_module) -#define myModConfig(srv) (mySrvConfig((srv)))->mc -#define mySrvFromConn(c) (myConnConfig(c))->server + ap_set_module_config(c->conn_config, &ssl_module, val) +#define mySrvConfig(srv) \ + ((SSLSrvConfigRec *)ap_get_module_config(srv->module_config, &ssl_module)) +#define myDirConfig(req) \ + ((SSLDirConfigRec *)ap_get_module_config(req->per_dir_config, &ssl_module)) +#define myCtxConfig(sslconn, sc) \ + (sslconn->is_proxy ? sslconn->dc->proxy : sc->server) +#define myModConfig(srv) mySrvConfig((srv))->mc +#define mySrvFromConn(c) myConnConfig(c)->server +#define myDirConfigFromConn(c) myConnConfig(c)->dc #define mySrvConfigFromConn(c) mySrvConfig(mySrvFromConn(c)) #define myModConfigFromConn(c) myModConfig(mySrvFromConn(c)) @@ -484,6 +488,9 @@ typedef struct { * (i.e. the global configuration for each httpd process) */ +typedef struct SSLSrvConfigRec SSLSrvConfigRec; +typedef struct SSLDirConfigRec SSLDirConfigRec; + typedef enum { SSL_SHUTDOWN_TYPE_UNSET, SSL_SHUTDOWN_TYPE_STANDARD, @@ -522,6 +529,7 @@ typedef struct { } reneg_state; server_rec *server; + SSLDirConfigRec *dc; const char *cipher_suite; /* cipher suite used in last reneg */ int service_unavailable; /* thouugh we negotiate SSL, no requests will be served */ @@ -646,8 +654,6 @@ typedef struct { } ssl_ctx_param_t; #endif -typedef struct SSLSrvConfigRec SSLSrvConfigRec; - typedef struct { SSLSrvConfigRec *sc; /** pointer back to server config */ SSL_CTX *ssl_ctx; @@ -715,22 +721,21 @@ typedef struct { SSL_CONF_CTX *ssl_ctx_config; /* Configuration context */ apr_array_header_t *ssl_ctx_param; /* parameters to pass to SSL_CTX */ #endif + + BOOL ssl_check_peer_cn; + BOOL ssl_check_peer_name; + BOOL ssl_check_peer_expire; } modssl_ctx_t; struct SSLSrvConfigRec { SSLModConfigRec *mc; ssl_enabled_t enabled; - BOOL proxy_enabled; const char *vhost_id; int vhost_id_len; int session_cache_timeout; BOOL cipher_server_pref; BOOL insecure_reneg; modssl_ctx_t *server; - modssl_ctx_t *proxy; - ssl_enabled_t proxy_ssl_check_peer_expire; - ssl_enabled_t proxy_ssl_check_peer_cn; - ssl_enabled_t proxy_ssl_check_peer_name; #ifdef HAVE_TLSEXT ssl_enabled_t strict_sni_vhost_check; #endif @@ -748,7 +753,7 @@ struct SSLSrvConfigRec { * (i.e. the local configuration for all <Directory> * and .htaccess contexts) */ -typedef struct { +struct SSLDirConfigRec { BOOL bSSLRequired; apr_array_header_t *aRequirement; ssl_opt_t nOptions; @@ -757,11 +762,13 @@ typedef struct { const char *szCipherSuite; ssl_verify_t nVerifyClient; int nVerifyDepth; - const char *szCACertificatePath; - const char *szCACertificateFile; const char *szUserName; apr_size_t nRenegBufferSize; -} SSLDirConfigRec; + + modssl_ctx_t *proxy; + BOOL proxy_enabled; + BOOL proxy_post_config; +}; /** * function prototypes @@ -778,6 +785,8 @@ 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 *); +void ssl_config_proxy_merge(apr_pool_t *, + SSLDirConfigRec *, SSLDirConfigRec *); 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 *); @@ -860,6 +869,9 @@ apr_status_t ssl_init_Engine(server_rec *, apr_pool_t *); apr_status_t ssl_init_ConfigureServer(server_rec *, apr_pool_t *, apr_pool_t *, SSLSrvConfigRec *, apr_array_header_t *); apr_status_t ssl_init_CheckServers(server_rec *, apr_pool_t *); +int ssl_proxy_section_post_config(apr_pool_t *p, apr_pool_t *plog, + apr_pool_t *ptemp, server_rec *s, + ap_conf_vector_t *section_config); 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 *); @@ -911,10 +923,6 @@ SSL_SESSION *ssl_scache_retrieve(server_rec *, IDCONST UCHAR *, int, apr_pool_t void ssl_scache_remove(server_rec *, IDCONST 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 *); diff --git a/server/config.c b/server/config.c index 71d1d5513f..ffd26fd592 100644 --- a/server/config.c +++ b/server/config.c @@ -873,6 +873,11 @@ static const char *invoke_cmd(const command_rec *cmd, cmd_parms *parms, cmd->name); return NULL; } + else if (parms->directive && parms->directive->parent) { + return apr_pstrcat(parms->pool, cmd->name, " not allowed in ", + parms->directive->parent->directive, ">", + " context", NULL); + } else { return apr_pstrcat(parms->pool, cmd->name, " not allowed here", NULL); diff --git a/server/core.c b/server/core.c index 6516b09a05..b52e9b258a 100644 --- a/server/core.c +++ b/server/core.c @@ -1252,8 +1252,7 @@ AP_DECLARE(const char *) ap_check_cmd_context(cmd_parms *cmd, " cannot occur within section", NULL); } - if ((forbidden & (NOT_IN_LIMIT | NOT_IN_DIR_LOC_FILE)) - && cmd->limited != -1) { + if ((forbidden & NOT_IN_DIR_CONTEXT) && cmd->limited != -1) { return apr_pstrcat(cmd->pool, cmd->cmd->name, gt, " cannot occur within or " "section", NULL); @@ -1267,8 +1266,7 @@ AP_DECLARE(const char *) ap_check_cmd_context(cmd_parms *cmd, if ((forbidden & NOT_IN_DIR_LOC_FILE) == NOT_IN_DIR_LOC_FILE) { if (cmd->path != NULL) { return apr_pstrcat(cmd->pool, cmd->cmd->name, gt, - " cannot occur within " - "section", NULL); + " cannot occur within directory context", NULL); } if (cmd->cmd->req_override & EXEC_ON_READ) { /* EXEC_ON_READ must be NOT_IN_DIR_LOC_FILE, if not, it will @@ -1289,7 +1287,10 @@ AP_DECLARE(const char *) ap_check_cmd_context(cmd_parms *cmd, || (found = find_parent(cmd->directive, "directive, "directive, "directive, "directive, "directive, "directive, "pool, cmd->cmd->name, gt, " cannot occur within ", found->directive, "> section", NULL); @@ -1304,7 +1305,7 @@ static const char *set_access_name(cmd_parms *cmd, void *dummy, void *sconf = cmd->server->module_config; core_server_config *conf = ap_get_core_module_config(sconf); - const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE); + const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_CONTEXT); if (err != NULL) { return err; } @@ -1511,7 +1512,7 @@ static const char *set_gprof_dir(cmd_parms *cmd, void *dummy, const char *arg) void *sconf = cmd->server->module_config; core_server_config *conf = ap_get_core_module_config(sconf); - const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE); + const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_CONTEXT); if (err != NULL) { return err; } @@ -1547,7 +1548,7 @@ static const char *set_document_root(cmd_parms *cmd, void *dummy, void *sconf = cmd->server->module_config; core_server_config *conf = ap_get_core_module_config(sconf); - const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE); + const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_CONTEXT); if (err != NULL) { return err; } @@ -2326,7 +2327,7 @@ static const char *dirsection(cmd_parms *cmd, void *mconfig, const char *arg) ap_regex_t *r = NULL; const command_rec *thiscmd = cmd->cmd; - const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE); + const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_CONTEXT); if (err != NULL) { return err; } @@ -2427,7 +2428,7 @@ static const char *urlsection(cmd_parms *cmd, void *mconfig, const char *arg) ap_regex_t *r = NULL; const command_rec *thiscmd = cmd->cmd; ap_conf_vector_t *new_url_conf = ap_create_per_dir_config(cmd->pool); - const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE); + const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_CONTEXT); if (err != NULL) { return err; } @@ -2905,7 +2906,7 @@ AP_DECLARE(void) ap_set_server_protocol(server_rec* s, const char* proto) static const char *set_protocol(cmd_parms *cmd, void *dummy, const char *arg) { - const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE); + const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_CONTEXT); core_server_config *conf = ap_get_core_module_config(cmd->server->module_config); char* proto; @@ -2929,8 +2930,7 @@ static const char *set_server_string_slot(cmd_parms *cmd, void *dummy, int offset = (int)(long)cmd->info; char *struct_ptr = (char *)cmd->server; - const char *err = ap_check_cmd_context(cmd, - NOT_IN_DIR_LOC_FILE); + const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_CONTEXT); if (err != NULL) { return err; } @@ -2949,7 +2949,7 @@ static const char *set_server_string_slot(cmd_parms *cmd, void *dummy, static const char *server_hostname_port(cmd_parms *cmd, void *dummy, const char *arg) { - const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE); + const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_CONTEXT); const char *portstr, *part; char *scheme; int port; @@ -3053,7 +3053,7 @@ static const char *set_runtime_dir(cmd_parms *cmd, void *dummy, const char *arg) static const char *set_timeout(cmd_parms *cmd, void *dummy, const char *arg) { - const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE); + const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_CONTEXT); if (err != NULL) { return err; @@ -3108,7 +3108,7 @@ static const char *set_hostname_lookups(cmd_parms *cmd, void *d_, static const char *set_serverpath(cmd_parms *cmd, void *dummy, const char *arg) { - const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE); + const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_CONTEXT); if (err != NULL) { return err; @@ -3500,7 +3500,7 @@ static const char *set_serv_tokens(cmd_parms *cmd, void *dummy, static const char *set_limit_req_line(cmd_parms *cmd, void *dummy, const char *arg) { - const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE); + const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_CONTEXT); int lim; if (err != NULL) { @@ -3520,7 +3520,7 @@ static const char *set_limit_req_line(cmd_parms *cmd, void *dummy, static const char *set_limit_req_fieldsize(cmd_parms *cmd, void *dummy, const char *arg) { - const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE); + const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_CONTEXT); int lim; if (err != NULL) { @@ -3541,7 +3541,7 @@ static const char *set_limit_req_fieldsize(cmd_parms *cmd, void *dummy, static const char *set_limit_req_fields(cmd_parms *cmd, void *dummy, const char *arg) { - const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE); + const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_CONTEXT); int lim; if (err != NULL) { @@ -3878,7 +3878,7 @@ static const char *set_protocols(cmd_parms *cmd, void *dummy, core_server_config *conf = ap_get_core_module_config(cmd->server->module_config); const char **np; - const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE); + const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_CONTEXT); if (err) { return err; @@ -3895,7 +3895,7 @@ static const char *set_protocols_honor_order(cmd_parms *cmd, void *dummy, { core_server_config *conf = ap_get_core_module_config(cmd->server->module_config); - const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE); + const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_CONTEXT); if (err) { return err; -- 2.50.1