On Tue, Apr 19, 2016 at 9:36 PM, Yann Ylavic <ylavic....@gmail.com> wrote: > > What changed is: > 1. SSLProxy* directives are now per directory (restricted to > Server/VirtualHost and <Proxy>), so all the internal struct members > have been move from SSLSrvConfigRec to SSLDirConfigRec; > 2. The merge happens from main server to VirtualHosts (if any) to > <Proxy> sections (if any), as usual; > 3. The proxies SSL_CTX are still created once at startup, in the > post_config hook, by retrieving all the dc->proxy and initializing > them (the one associated with the server_rec and the ones of the > <Proxy> sections, with the help of a new mod_proxy optional function: > ap_proxy_get_sections_configs()); > 4. At runtime, the new ssl_proxy_{enable,disable}_ex() optional > functions are used by mod_proxy to indicate the per dir (proxy > worker's) configuration to mod_ssl.
I did even more testing with this new (attached) patch and it works for me. > > Feedbacks and more testing welcome :) Let me known if it's suitable for trunk...
Index: include/http_config.h =================================================================== --- include/http_config.h (revision 1740086) +++ include/http_config.h (working copy) @@ -923,9 +923,10 @@ AP_DECLARE(const char *) ap_check_cmd_context(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 */ -/** 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 NOT_IN_PROXY 0x40 /**< Forbidden in <Proxy> */ +/** Forbidden in <Directory>/<Location>/<Files><If><Proxy>*/ +#define NOT_IN_DIR_LOC_FILE (NOT_IN_DIRECTORY|NOT_IN_LOCATION|NOT_IN_FILES|NOT_IN_PROXY) +/** Forbidden in <VirtualHost>/<Limit>/<Directory>/<Location>/<Files>/<If><Proxy>*/ #define GLOBAL_ONLY (NOT_IN_VIRTUALHOST|NOT_IN_LIMIT|NOT_IN_DIR_LOC_FILE) /** @} */ Index: modules/http2/h2_h2.c =================================================================== --- modules/http2/h2_h2.c (revision 1740086) +++ modules/http2/h2_h2.c (working copy) @@ -56,7 +56,6 @@ const char *H2_MAGIC_TOKEN = "PRI * HTTP/2.0\r\n\r /******************************************************************************* * 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; @@ -441,7 +440,6 @@ apr_status_t h2_h2_init(apr_pool_t *pool, server_r { (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); Index: modules/http2/mod_proxy_http2.c =================================================================== --- modules/http2/mod_proxy_http2.c (revision 1740086) +++ modules/http2/mod_proxy_http2.c (working copy) @@ -563,9 +563,9 @@ run_connect: "setup new connection: is_ssl=%d %s %s %s", ctx->p_conn->is_ssl, ctx->p_conn->ssl_hostname, locurl, ctx->p_conn->hostname); - 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) { goto cleanup; } Index: modules/proxy/mod_proxy.c =================================================================== --- modules/proxy/mod_proxy.c (revision 1740086) +++ modules/proxy/mod_proxy.c (working copy) @@ -26,6 +26,10 @@ #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_proxy_enable_ex, + (conn_rec *, ap_conf_vector_t *)); +APR_DECLARE_OPTIONAL_FN(int, ssl_proxy_disable_ex, + (conn_rec *, ap_conf_vector_t *)); APR_DECLARE_OPTIONAL_FN(int, ssl_is_https, (conn_rec *)); APR_DECLARE_OPTIONAL_FN(char *, ssl_var_lookup, (apr_pool_t *, server_rec *, @@ -2313,6 +2317,9 @@ static const char *add_member(cmd_parms *cmd, void "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; @@ -2427,6 +2434,13 @@ static void ap_add_per_proxy_conf(server_rec *s, a *new_space = dir_config; } +static apr_array_header_t *ap_proxy_get_sections_configs(server_rec *s) +{ + proxy_server_conf *sconf = ap_get_module_config(s->module_config, + &proxy_module); + return sconf->sec_proxy; +} + static const char *proxysection(cmd_parms *cmd, void *mconfig, const char *arg) { const char *errmsg; @@ -2521,6 +2535,9 @@ static const char *proxysection(cmd_parms *cmd, vo 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, @@ -2544,6 +2561,9 @@ static const char *proxysection(cmd_parms *cmd, vo "altogether with the same worker name ", "(", worker->s->name, ")", NULL); } + if (!worker->section_config) { + worker->section_config = new_dir_conf; + } } if (worker == NULL && balancer == NULL) { return apr_pstrcat(cmd->pool, thiscmd->name, @@ -2651,6 +2671,8 @@ 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_proxy_enable_ex) *proxy_ssl_enable_ex = NULL; +static APR_OPTIONAL_FN_TYPE(ssl_proxy_disable_ex) *proxy_ssl_disable_ex = 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; @@ -2676,6 +2698,34 @@ PROXY_DECLARE(int) ap_proxy_ssl_disable(conn_rec * return 0; } +PROXY_DECLARE(int) ap_proxy_ssl_enable_ex(conn_rec *c, + ap_conf_vector_t *per_dir_config) +{ + /* + * if c == NULL just check if the optional function was imported + * else run the optional function so ssl filters are inserted + */ + if (proxy_ssl_enable_ex) { + return c ? proxy_ssl_enable_ex(c, per_dir_config) : 1; + } + + return ap_proxy_ssl_enable(c); +} + +PROXY_DECLARE(int) ap_proxy_ssl_disable_ex(conn_rec *c, + ap_conf_vector_t *per_dir_config) +{ + /* + * if c == NULL just check if the optional function was imported + * else run the optional function so ssl filters are inserted + */ + if (proxy_ssl_disable_ex) { + return c ? proxy_ssl_disable_ex(c, per_dir_config) : 1; + } + + return ap_proxy_ssl_disable(c); +} + PROXY_DECLARE(int) ap_proxy_conn_is_https(conn_rec *c) { if (proxy_is_https) { @@ -2710,6 +2760,8 @@ static int proxy_post_config(apr_pool_t *pconf, ap proxy_ssl_enable = APR_RETRIEVE_OPTIONAL_FN(ssl_proxy_enable); proxy_ssl_disable = APR_RETRIEVE_OPTIONAL_FN(ssl_engine_disable); + proxy_ssl_enable_ex = APR_RETRIEVE_OPTIONAL_FN(ssl_proxy_enable_ex); + proxy_ssl_disable_ex = APR_RETRIEVE_OPTIONAL_FN(ssl_proxy_disable_ex); 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); @@ -2955,6 +3007,8 @@ static void register_hooks(apr_pool_t *p) /* child init handling */ ap_hook_child_init(child_init, aszPred, NULL, APR_HOOK_MIDDLE); + APR_REGISTER_OPTIONAL_FN(ap_proxy_get_sections_configs); + /* register optional functions within proxy_util.c */ proxy_util_register_hooks(p); } Index: modules/proxy/mod_proxy.h =================================================================== --- modules/proxy/mod_proxy.h (revision 1740086) +++ modules/proxy/mod_proxy.h (working copy) @@ -459,6 +459,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; /* Per <Proxy>-section config */ }; /* default to health check every 30 seconds */ @@ -523,6 +524,7 @@ struct proxy_balancer { unsigned int failontimeout_set:1; unsigned int growth_set:1; unsigned int lbmethod_set:1; + ap_conf_vector_t *section_config; /* Per <Proxy>-section config */ }; struct proxy_balancer_method { @@ -664,6 +666,10 @@ PROXY_DECLARE(apr_status_t) ap_proxy_ssl_connectio 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_enable_ex(conn_rec *c, + ap_conf_vector_t *per_dir_config); +PROXY_DECLARE(int) ap_proxy_ssl_disable_ex(conn_rec *c, + ap_conf_vector_t *per_dir_config); 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); @@ -991,7 +997,7 @@ PROXY_DECLARE(apr_status_t) ap_proxy_connect_uds(a * 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 @@ -1002,6 +1008,18 @@ PROXY_DECLARE(int) ap_proxy_connection_create(cons 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. * @param conn proxy connection @@ -1226,5 +1244,8 @@ PROXY_DECLARE(apr_status_t) ap_proxy_transfer_betw extern module PROXY_DECLARE_DATA proxy_module; +APR_DECLARE_OPTIONAL_FN(apr_array_header_t *, ap_proxy_get_sections_configs, + (server_rec *s)); + #endif /*MOD_PROXY_H*/ /** @} */ Index: modules/proxy/mod_proxy_connect.c =================================================================== --- modules/proxy/mod_proxy_connect.c (revision 1740086) +++ modules/proxy/mod_proxy_connect.c (working copy) @@ -299,7 +299,7 @@ static int proxy_connect_handler(request_rec *r, p apr_socket_close(sock); return HTTP_INTERNAL_SERVER_ERROR; } - ap_proxy_ssl_disable(backconn); + ap_proxy_ssl_disable_ex(backconn, r->per_dir_config); rc = ap_run_pre_connection(backconn, sock); if (rc != OK && rc != DONE) { backconn->aborted = 1; Index: modules/proxy/mod_proxy_ftp.c =================================================================== --- modules/proxy/mod_proxy_ftp.c (revision 1740086) +++ modules/proxy/mod_proxy_ftp.c (working copy) @@ -1189,7 +1189,7 @@ static int proxy_ftp_handler(request_rec *r, proxy } 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; @@ -2035,7 +2035,7 @@ static int proxy_ftp_handler(request_rec *r, proxy * 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_disable_ex(data, r->per_dir_config); /* set up the connection filters */ rc = ap_run_pre_connection(data, data_sock); if (rc != OK && rc != DONE) { Index: modules/proxy/mod_proxy_http.c =================================================================== --- modules/proxy/mod_proxy_http.c (revision 1740086) +++ modules/proxy/mod_proxy_http.c (working copy) @@ -2083,8 +2083,8 @@ static int proxy_http_handler(request_rec *r, prox /* Step Three: Create conn_rec */ backconn = backend->connection; if (!backconn) { - 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; backconn = backend->connection; Index: modules/proxy/mod_proxy_wstunnel.c =================================================================== --- modules/proxy/mod_proxy_wstunnel.c (revision 1740086) +++ modules/proxy/mod_proxy_wstunnel.c (working copy) @@ -447,7 +447,6 @@ static int proxy_wstunnel_handler(request_rec *r, proxy_conn_rec *backend = NULL; const char *upgrade; char *scheme; - conn_rec *c = r->connection; apr_pool_t *p = r->pool; char *locurl = url; apr_uri_t *uri; @@ -504,7 +503,7 @@ static int proxy_wstunnel_handler(request_rec *r, /* Step Three: Create conn_rec */ if (!backend->connection) { - status = ap_proxy_connection_create(scheme, backend, c, r->server); + status = ap_proxy_connection_create_ex(scheme, backend, r); if (status != OK) { goto cleanup; } Index: modules/proxy/proxy_util.c =================================================================== --- modules/proxy/proxy_util.c (revision 1740086) +++ modules/proxy/proxy_util.c (working copy) @@ -2982,11 +2982,12 @@ static apr_status_t connection_shutdown(void *thec } -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; @@ -3020,7 +3021,7 @@ static apr_status_t connection_shutdown(void *thec /* For ssl connection to backend */ if (conn->is_ssl) { - if (!ap_proxy_ssl_enable(conn->connection)) { + if (!ap_proxy_ssl_enable_ex(conn->connection, per_dir_config)) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(00961) "%s: failed to enable ssl support " "for %pI (%s)", proxy_function, @@ -3030,7 +3031,7 @@ static apr_status_t connection_shutdown(void *thec } else { /* TODO: See if this will break FTP */ - ap_proxy_ssl_disable(conn->connection); + ap_proxy_ssl_disable_ex(conn->connection, per_dir_config); } ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(00962) @@ -3062,6 +3063,21 @@ static apr_status_t connection_shutdown(void *thec 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) { /* Index: modules/ssl/mod_ssl.c =================================================================== --- modules/ssl/mod_ssl.c (revision 1740086) +++ modules/ssl/mod_ssl.c (working copy) @@ -175,50 +175,50 @@ static const command_rec ssl_config_cmds[] = { /* * Proxy configuration for remote SSL connections */ - SSL_CMD_SRV(ProxyEngine, FLAG, + SSL_CMD_ALL(ProxyEngine, FLAG, "SSL switch for the proxy protocol engine " "('on', 'off')") - SSL_CMD_SRV(ProxyProtocol, RAW_ARGS, + SSL_CMD_ALL(ProxyProtocol, RAW_ARGS, "SSL Proxy: enable or disable SSL protocol flavors " "('[+-][" SSL_PROTOCOLS "] ...' - see manual)") - SSL_CMD_SRV(ProxyCipherSuite, TAKE1, + SSL_CMD_ALL(ProxyCipherSuite, TAKE1, "SSL Proxy: colon-delimited list of permitted SSL ciphers " "('XXX:...:XXX' - see manual)") - SSL_CMD_SRV(ProxyVerify, TAKE1, + SSL_CMD_ALL(ProxyVerify, TAKE1, "SSL Proxy: whether to verify the remote certificate " "('on' or 'off')") - SSL_CMD_SRV(ProxyVerifyDepth, TAKE1, + SSL_CMD_ALL(ProxyVerifyDepth, TAKE1, "SSL Proxy: maximum certificate verification depth " "('N' - number of intermediate certificates)") - SSL_CMD_SRV(ProxyCACertificateFile, TAKE1, + SSL_CMD_ALL(ProxyCACertificateFile, TAKE1, "SSL Proxy: file containing server certificates " "('/path/to/file' - PEM encoded certificates)") - SSL_CMD_SRV(ProxyCACertificatePath, TAKE1, + SSL_CMD_ALL(ProxyCACertificatePath, TAKE1, "SSL Proxy: directory containing server certificates " "('/path/to/dir' - contains PEM encoded certificates)") - SSL_CMD_SRV(ProxyCARevocationPath, TAKE1, + SSL_CMD_ALL(ProxyCARevocationPath, TAKE1, "SSL Proxy: CA Certificate Revocation List (CRL) path " "('/path/to/dir' - contains PEM encoded files)") - SSL_CMD_SRV(ProxyCARevocationFile, TAKE1, + SSL_CMD_ALL(ProxyCARevocationFile, TAKE1, "SSL Proxy: CA Certificate Revocation List (CRL) file " "('/path/to/file' - PEM encoded)") - SSL_CMD_SRV(ProxyCARevocationCheck, RAW_ARGS, + SSL_CMD_ALL(ProxyCARevocationCheck, RAW_ARGS, "SSL Proxy: CA Certificate Revocation List (CRL) checking mode") - SSL_CMD_SRV(ProxyMachineCertificateFile, TAKE1, + SSL_CMD_ALL(ProxyMachineCertificateFile, TAKE1, "SSL Proxy: file containing client certificates " "('/path/to/file' - PEM encoded certificates)") - SSL_CMD_SRV(ProxyMachineCertificatePath, TAKE1, + SSL_CMD_ALL(ProxyMachineCertificatePath, TAKE1, "SSL Proxy: directory containing client certificates " "('/path/to/dir' - contains PEM encoded certificates)") - SSL_CMD_SRV(ProxyMachineCertificateChainFile, TAKE1, + SSL_CMD_ALL(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_ALL(ProxyCheckPeerExpire, FLAG, "SSL Proxy: check the peer certificate's expiration date") - SSL_CMD_SRV(ProxyCheckPeerCN, FLAG, + SSL_CMD_ALL(ProxyCheckPeerCN, FLAG, "SSL Proxy: check the peer certificate's CN") - SSL_CMD_SRV(ProxyCheckPeerName, FLAG, + SSL_CMD_ALL(ProxyCheckPeerName, FLAG, "SSL Proxy: check the peer certificate's name " "(must be present in subjectAltName extension or CN") @@ -403,8 +403,21 @@ static int ssl_hook_pre_config(apr_pool_t *pconf, return OK; } -static SSLConnRec *ssl_init_connection_ctx(conn_rec *c) +static SSLDirConfigRec *ssl_get_dir_config(conn_rec *c, + ap_conf_vector_t *per_dir_config) { + if (per_dir_config) { + return ap_get_module_config(per_dir_config, &ssl_module); + } + else { + return ap_get_module_config(c->base_server->lookup_defaults, + &ssl_module); + } +} + +static SSLConnRec *ssl_init_connection_ctx(conn_rec *c, + ap_conf_vector_t *per_dir_config) +{ SSLConnRec *sslconn = myConnConfig(c); SSLSrvConfigRec *sc; @@ -418,6 +431,7 @@ static int ssl_hook_pre_config(apr_pool_t *pconf, sslconn->verify_depth = UNSET; sc = mySrvConfig(c->base_server); sslconn->cipher_suite = sc->server->auth.cipher_suite; + sslconn->dc = ssl_get_dir_config(c, per_dir_config); myConnConfigSet(c, sslconn); @@ -424,63 +438,64 @@ static int ssl_hook_pre_config(apr_pool_t *pconf, return sslconn; } -static int ssl_proxy_enable(conn_rec *c) +static int ssl_proxy_enable_ex(conn_rec *c, ap_conf_vector_t *per_dir_config) { - SSLSrvConfigRec *sc; + SSLConnRec *sslconn = ssl_init_connection_ctx(c, per_dir_config); - SSLConnRec *sslconn = ssl_init_connection_ctx(c); - sc = mySrvConfig(sslconn->server); + sslconn->is_proxy = 1; - if (!sc->proxy_enabled) { + if (!sslconn->dc->proxy_enabled) { + 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; + return 0; } - sslconn->is_proxy = 1; sslconn->disabled = 0; return 1; } -static int ssl_engine_disable(conn_rec *c) +static int ssl_proxy_disable_ex(conn_rec *c, ap_conf_vector_t *per_dir_config) { - SSLSrvConfigRec *sc; + SSLDirConfigRec *dc = ssl_get_dir_config(c, per_dir_config); + SSLConnRec *sslconn; - SSLConnRec *sslconn = myConnConfig(c); - - if (sslconn) { - sc = mySrvConfig(sslconn->server); - } - else { - sc = mySrvConfig(c->base_server); - } - if (sc->enabled == SSL_ENABLED_FALSE) { + if (!dc->proxy_enabled) { return 0; } - sslconn = ssl_init_connection_ctx(c); - + sslconn = ssl_init_connection_ctx(c, per_dir_config); sslconn->disabled = 1; return 1; } +static int ssl_proxy_enable(conn_rec *c) +{ + return ssl_proxy_enable_ex(c, NULL); +} + +static int ssl_engine_disable(conn_rec *c) +{ + return ssl_proxy_disable_ex(c, NULL); +} + 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); - } + sslconn = ssl_init_connection_ctx(c, r ? r->per_dir_config : NULL); server = sslconn->server; sc = mySrvConfig(server); @@ -489,7 +504,7 @@ int ssl_init_ssl_connection(conn_rec *c, request_r */ ssl_rand_seed(server, c->pool, SSL_RSCTX_CONNECT, ""); - mctx = sslconn->is_proxy ? sc->proxy : sc->server; + mctx = myCtxConfig(sslconn, sc); /* * Create a new SSL connection with the configured server SSL context and @@ -584,7 +599,7 @@ static int ssl_hook_pre_connection(conn_rec *c, vo * Create SSL context */ if (!sslconn) { - sslconn = ssl_init_connection_ctx(c); + sslconn = ssl_init_connection_ctx(c, NULL); } if (sslconn->disabled) { @@ -657,6 +672,8 @@ static void ssl_register_hooks(apr_pool_t *p) APR_REGISTER_OPTIONAL_FN(ssl_proxy_enable); APR_REGISTER_OPTIONAL_FN(ssl_engine_disable); + APR_REGISTER_OPTIONAL_FN(ssl_proxy_enable_ex); + APR_REGISTER_OPTIONAL_FN(ssl_proxy_disable_ex); ap_register_auth_provider(p, AUTHZ_PROVIDER_GROUP, "ssl", AUTHZ_PROVIDER_VERSION, @@ -667,7 +684,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 = { Index: modules/ssl/mod_ssl.h =================================================================== --- modules/ssl/mod_ssl.h (revision 1740086) +++ modules/ssl/mod_ssl.h (working copy) @@ -85,13 +85,16 @@ APR_DECLARE_OPTIONAL_FN(apr_status_t, ssl_get_tls_ (apr_pool_t *p, conn_rec *c, const char *type, unsigned char **buf, apr_size_t *size)); -/** 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,disable}[_dir]() and ssl_engine_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_proxy_enable_ex, + (conn_rec *c, ap_conf_vector_t *dir_config)); +APR_DECLARE_OPTIONAL_FN(int, ssl_proxy_disable_ex, + (conn_rec *c, ap_conf_vector_t *dir_config)); #endif /* __MOD_SSL_H__ */ /** @} */ Index: modules/ssl/ssl_engine_config.c =================================================================== --- modules/ssl/ssl_engine_config.c (revision 1740086) +++ modules/ssl/ssl_engine_config.c (working copy) @@ -162,24 +162,10 @@ static void modssl_ctx_init(modssl_ctx_t *mctx, ap 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, @@ -207,15 +193,11 @@ static SSLSrvConfigRec *ssl_config_server_new(apr_ 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 @@ -227,8 +209,6 @@ static SSLSrvConfigRec *ssl_config_server_new(apr_ #endif sc->session_tickets = UNSET; - modssl_ctx_init_proxy(sc, p); - modssl_ctx_init_server(sc, p); return sc; @@ -252,6 +232,10 @@ void *ssl_config_server_create(apr_pool_t *p, serv #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, @@ -309,18 +293,6 @@ static void modssl_ctx_cfg_merge(apr_pool_t *p, #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); -} - static void modssl_ctx_cfg_merge_server(apr_pool_t *p, modssl_ctx_t *base, modssl_ctx_t *add, @@ -339,9 +311,6 @@ static void modssl_ctx_cfg_merge_server(apr_pool_t #endif } -/* - * Merge per-server SSL configurations - */ void *ssl_config_server_merge(apr_pool_t *p, void *basev, void *addv) { SSLSrvConfigRec *base = (SSLSrvConfigRec *)basev; @@ -350,13 +319,9 @@ void *ssl_config_server_merge(apr_pool_t *p, void 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 @@ -368,8 +333,6 @@ void *ssl_config_server_merge(apr_pool_t *p, void #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; @@ -378,6 +341,25 @@ void *ssl_config_server_merge(apr_pool_t *p, void /* * 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)); @@ -392,12 +374,14 @@ void *ssl_config_perdir_create(apr_pool_t *p, char 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; } @@ -404,6 +388,23 @@ void *ssl_config_perdir_create(apr_pool_t *p, char /* * 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); + + cfgMergeBool(ssl_check_peer_cn); + cfgMergeBool(ssl_check_peer_name); + cfgMergeBool(ssl_check_peer_expire); +} + void *ssl_config_perdir_merge(apr_pool_t *p, void *basev, void *addv) { SSLDirConfigRec *base = (SSLDirConfigRec *)basev; @@ -431,19 +432,43 @@ void *ssl_config_perdir_merge(apr_pool_t *p, void cfgMerge(nVerifyClient, SSL_CVERIFY_UNSET); cfgMergeInt(nVerifyDepth); - cfgMergeString(szCACertificatePath); - cfgMergeString(szCACertificateFile); cfgMergeString(szUserName); cfgMergeInt(nRenegBufferSize); + 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 */ +#define SERVER_OR_PROXY_ONLY (NOT_IN_DIR_LOC_FILE & ~NOT_IN_PROXY) + const char *ssl_cmd_SSLPassPhraseDialog(cmd_parms *cmd, void *dcfg, const char *arg) @@ -1393,10 +1418,15 @@ 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; + const char *err; - sc->proxy_enabled = flag ? TRUE : FALSE; + if ((err = ap_check_cmd_context(cmd, SERVER_OR_PROXY_ONLY))) { + return err; + } + dc->proxy_enabled = flag ? TRUE : FALSE; + return NULL; } @@ -1404,10 +1434,15 @@ const char *ssl_cmd_SSLProxyProtocol(cmd_parms *cm void *dcfg, const char *arg) { - SSLSrvConfigRec *sc = mySrvConfig(cmd->server); + SSLDirConfigRec *dc = (SSLDirConfigRec *)dcfg; + const char *err; - sc->proxy->protocol_set = 1; - return ssl_cmd_protocol_parse(cmd, arg, &sc->proxy->protocol); + if ((err = ap_check_cmd_context(cmd, SERVER_OR_PROXY_ONLY))) { + return err; + } + + dc->proxy->protocol_set = 1; + return ssl_cmd_protocol_parse(cmd, arg, &dc->proxy->protocol); } const char *ssl_cmd_SSLProxyCipherSuite(cmd_parms *cmd, @@ -1414,13 +1449,16 @@ const char *ssl_cmd_SSLProxyCipherSuite(cmd_parms void *dcfg, const char *arg) { - SSLSrvConfigRec *sc = mySrvConfig(cmd->server); + SSLDirConfigRec *dc = (SSLDirConfigRec *)dcfg; + const char *err; + if ((err = ap_check_cmd_context(cmd, SERVER_OR_PROXY_ONLY))) { + return err; + } + /* 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; } @@ -1428,16 +1466,16 @@ const char *ssl_cmd_SSLProxyVerify(cmd_parms *cmd, void *dcfg, const char *arg) { - SSLSrvConfigRec *sc = mySrvConfig(cmd->server); + SSLDirConfigRec *dc = (SSLDirConfigRec *)dcfg; ssl_verify_t mode; const char *err; - if ((err = ssl_cmd_verify_parse(cmd, arg, &mode))) { + if ((err = ap_check_cmd_context(cmd, SERVER_OR_PROXY_ONLY)) || + (err = ssl_cmd_verify_parse(cmd, arg, &mode))) { return err; } - sc->proxy->auth.verify_mode = mode; - + dc->proxy->auth.verify_mode = mode; return NULL; } @@ -1445,16 +1483,16 @@ const char *ssl_cmd_SSLProxyVerifyDepth(cmd_parms void *dcfg, const char *arg) { - SSLSrvConfigRec *sc = mySrvConfig(cmd->server); + SSLDirConfigRec *dc = (SSLDirConfigRec *)dcfg; int depth; const char *err; - if ((err = ssl_cmd_verify_depth_parse(cmd, arg, &depth))) { + if ((err = ap_check_cmd_context(cmd, SERVER_OR_PROXY_ONLY)) || + (err = ssl_cmd_verify_depth_parse(cmd, arg, &depth))) { return err; } - sc->proxy->auth.verify_depth = depth; - + dc->proxy->auth.verify_depth = depth; return NULL; } @@ -1462,15 +1500,15 @@ const char *ssl_cmd_SSLProxyCACertificateFile(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))) { + if ((err = ap_check_cmd_context(cmd, SERVER_OR_PROXY_ONLY)) || + (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; } @@ -1478,15 +1516,15 @@ const char *ssl_cmd_SSLProxyCACertificatePath(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))) { + if ((err = ap_check_cmd_context(cmd, SERVER_OR_PROXY_ONLY)) || + (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; } @@ -1494,15 +1532,15 @@ const char *ssl_cmd_SSLProxyCARevocationPath(cmd_p 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))) { + if ((err = ap_check_cmd_context(cmd, SERVER_OR_PROXY_ONLY)) || + (err = ssl_cmd_check_dir(cmd, &arg))) { return err; } - sc->proxy->crl_path = arg; - + dc->proxy->crl_path = arg; return NULL; } @@ -1510,15 +1548,15 @@ const char *ssl_cmd_SSLProxyCARevocationFile(cmd_p 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))) { + if ((err = ap_check_cmd_context(cmd, SERVER_OR_PROXY_ONLY)) || + (err = ssl_cmd_check_file(cmd, &arg))) { return err; } - sc->proxy->crl_file = arg; - + dc->proxy->crl_file = arg; return NULL; } @@ -1526,9 +1564,14 @@ const char *ssl_cmd_SSLProxyCARevocationCheck(cmd_ void *dcfg, const char *arg) { - SSLSrvConfigRec *sc = mySrvConfig(cmd->server); + SSLDirConfigRec *dc = (SSLDirConfigRec *)dcfg; + const char *err; - return ssl_cmd_crlcheck_parse(cmd, arg, &sc->proxy->crl_check_mask); + if ((err = ap_check_cmd_context(cmd, SERVER_OR_PROXY_ONLY))) { + return err; + } + + return ssl_cmd_crlcheck_parse(cmd, arg, &dc->proxy->crl_check_mask); } const char *ssl_cmd_SSLProxyMachineCertificateFile(cmd_parms *cmd, @@ -1535,15 +1578,15 @@ const char *ssl_cmd_SSLProxyMachineCertificateFile 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))) { + if ((err = ap_check_cmd_context(cmd, SERVER_OR_PROXY_ONLY)) || + (err = ssl_cmd_check_file(cmd, &arg))) { return err; } - sc->proxy->pkp->cert_file = arg; - + dc->proxy->pkp->cert_file = arg; return NULL; } @@ -1551,15 +1594,15 @@ const char *ssl_cmd_SSLProxyMachineCertificatePath 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))) { + if ((err = ap_check_cmd_context(cmd, SERVER_OR_PROXY_ONLY)) || + (err = ssl_cmd_check_dir(cmd, &arg))) { return err; } - sc->proxy->pkp->cert_path = arg; - + dc->proxy->pkp->cert_path = arg; return NULL; } @@ -1567,15 +1610,15 @@ const char *ssl_cmd_SSLProxyMachineCertificateChai 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))) { + if ((err = ap_check_cmd_context(cmd, SERVER_OR_PROXY_ONLY)) || + (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; } @@ -1674,28 +1717,40 @@ const char *ssl_cmd_SSLOCSPProxyURL(cmd_parms *cmd const char *ssl_cmd_SSLProxyCheckPeerExpire(cmd_parms *cmd, void *dcfg, int flag) { - SSLSrvConfigRec *sc = mySrvConfig(cmd->server); + SSLDirConfigRec *dc = (SSLDirConfigRec *)dcfg; + const char *err; - sc->proxy_ssl_check_peer_expire = flag ? SSL_ENABLED_TRUE : SSL_ENABLED_FALSE; + if ((err = ap_check_cmd_context(cmd, SERVER_OR_PROXY_ONLY))) { + return err; + } + 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; + const char *err; - sc->proxy_ssl_check_peer_cn = flag ? SSL_ENABLED_TRUE : SSL_ENABLED_FALSE; + if ((err = ap_check_cmd_context(cmd, SERVER_OR_PROXY_ONLY))) { + return err; + } + 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; + const char *err; - sc->proxy_ssl_check_peer_name = flag ? SSL_ENABLED_TRUE : SSL_ENABLED_FALSE; + if ((err = ap_check_cmd_context(cmd, SERVER_OR_PROXY_ONLY))) { + return err; + } + dc->proxy->ssl_check_peer_name = flag ? TRUE : FALSE; return NULL; } Index: modules/ssl/ssl_engine_init.c =================================================================== --- modules/ssl/ssl_engine_init.c (revision 1740086) +++ modules/ssl/ssl_engine_init.c (working copy) @@ -31,6 +31,8 @@ #include "mod_ssl_openssl.h" #include "mpm_common.h" +#include "mod_proxy.h" /* for optional ap_proxy_get_sections_configs() */ + static apr_status_t ssl_init_ca_cert_path(server_rec *, apr_pool_t *, const char *, STACK_OF(X509_NAME) *, STACK_OF(X509_INFO) *); @@ -38,6 +40,9 @@ APR_IMPLEMENT_OPTIONAL_HOOK_RUN_ALL(ssl, SSL, int, (server_rec *s,apr_pool_t *p,int is_proxy,SSL_CTX *ctx), (s,p,is_proxy,ctx), OK, DECLINED) +static APR_OPTIONAL_FN_TYPE(ap_proxy_get_sections_configs) + *ssl_proxy_get_sections_configs = NULL; + /* _________________________________________________________________ ** ** Module Initialization @@ -218,10 +223,6 @@ apr_status_t ssl_init_Module(apr_pool_t *p, apr_po sc->server->sc = sc; } - if (sc->proxy) { - sc->proxy->sc = sc; - } - /* * Create the server host:port string because we need it a lot */ @@ -241,9 +242,6 @@ apr_status_t ssl_init_Module(apr_pool_t *p, apr_po 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; @@ -330,6 +328,9 @@ apr_status_t ssl_init_Module(apr_pool_t *p, apr_po ap_log_error(APLOG_MARK, APLOG_INFO, 0, base_server, APLOGNO(01887) "Init: Initializing (virtual) servers for SSL"); + ssl_proxy_get_sections_configs = + APR_RETRIEVE_OPTIONAL_FN(ap_proxy_get_sections_configs); + for (s = base_server; s; s = s->next) { sc = mySrvConfig(s); /* @@ -362,6 +363,9 @@ apr_status_t ssl_init_Module(apr_pool_t *p, apr_po } for (s = base_server; s; s = s->next) { + SSLDirConfigRec *sdc = ap_get_module_config(s->lookup_defaults, + &ssl_module); + apr_array_header_t *proxy_configs; sc = mySrvConfig(s); if (sc->enabled == SSL_ENABLED_TRUE || sc->enabled == SSL_ENABLED_OPTIONAL) { @@ -369,11 +373,31 @@ apr_status_t ssl_init_Module(apr_pool_t *p, apr_po 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; } } + + if (ssl_proxy_get_sections_configs && + (proxy_configs = ssl_proxy_get_sections_configs(s))) { + ap_conf_vector_t **proxy_config = + (ap_conf_vector_t **)proxy_configs->elts; + int i; + + for (i = 0; i < proxy_configs->nelts; ++i) { + SSLDirConfigRec *pdc = ap_get_module_config(proxy_config[i], + &ssl_module); + if (pdc && pdc->proxy_enabled) { + rv = ssl_run_init_server(s, p, 1, pdc->proxy->ssl_ctx); + if (rv != APR_SUCCESS) { + return rv; + } + } + } + } } /* @@ -1565,18 +1589,65 @@ static apr_status_t ssl_init_proxy_certs(server_re 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) { + 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; } @@ -1698,6 +1769,9 @@ apr_status_t ssl_init_ConfigureServer(server_rec * SSLSrvConfigRec *sc, apr_array_header_t *pphrases) { + SSLDirConfigRec *sdc = ap_get_module_config(s->lookup_defaults, + &ssl_module); + apr_array_header_t *proxy_configs; apr_status_t rv; /* Initialize the server if SSL is enabled or optional. @@ -1711,12 +1785,41 @@ apr_status_t ssl_init_ConfigureServer(server_rec * } } - 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; + if (ssl_proxy_get_sections_configs && + (proxy_configs = ssl_proxy_get_sections_configs(s))) { + ap_conf_vector_t **proxy_config = + (ap_conf_vector_t **)proxy_configs->elts; + int i; + + for (i = 0; i < proxy_configs->nelts; ++i) { + SSLDirConfigRec *pdc = ap_get_module_config(proxy_config[i], + &ssl_module); + if (pdc) { + pdc->proxy->sc = sc; + ssl_config_proxy_merge(p, sdc, pdc); + if (pdc->proxy_enabled) { + rv = ssl_init_proxy_ctx(s, p, ptemp, pdc->proxy); + if (rv != APR_SUCCESS) { + return rv; + } + } + pdc->proxy_post_config = 1; + } + } + } + return APR_SUCCESS; } @@ -1954,45 +2057,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; @@ -2011,8 +2075,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); } Index: modules/ssl/ssl_engine_io.c =================================================================== --- modules/ssl/ssl_engine_io.c (revision 1740086) +++ modules/ssl/ssl_engine_io.c (working copy) @@ -1191,7 +1191,9 @@ static apr_status_t ssl_io_filter_handshake(ssl_fi #endif BOOL proxy_ssl_check_peer_ok = TRUE; int post_handshake_rc = OK; + SSLDirConfigRec *dc; + dc = sslconn->dc; sc = mySrvConfig(server); #ifdef HAVE_TLSEXT @@ -1239,7 +1241,7 @@ static apr_status_t ssl_io_filter_handshake(ssl_fi */ 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) { @@ -1268,7 +1270,7 @@ static apr_status_t ssl_io_filter_handshake(ssl_fi 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) @@ -1279,7 +1281,7 @@ static apr_status_t ssl_io_filter_handshake(ssl_fi "SSL Proxy: Peer certificate is expired"); } } - if ((sc->proxy_ssl_check_peer_name != SSL_ENABLED_FALSE) && + if ((dc->proxy->ssl_check_peer_name != FALSE) && hostname_note) { apr_table_unset(c->notes, "proxy-request-hostname"); if (!cert @@ -1291,7 +1293,7 @@ static apr_status_t ssl_io_filter_handshake(ssl_fi "for hostname %s", hostname_note); } } - else if ((sc->proxy_ssl_check_peer_cn != SSL_ENABLED_FALSE) && + else if ((dc->proxy->ssl_check_peer_cn != FALSE) && hostname_note) { const char *hostname; int match = 0; Index: modules/ssl/ssl_engine_kernel.c =================================================================== --- modules/ssl/ssl_engine_kernel.c (revision 1740086) +++ modules/ssl/ssl_engine_kernel.c (working copy) @@ -1566,8 +1566,8 @@ int ssl_callback_SSLVerify(int ok, X509_STORE_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; @@ -1759,11 +1759,13 @@ int ssl_callback_proxy_cert(SSL *ssl, X509 **x509, conn_rec *c = (conn_rec *)SSL_get_app_data(ssl); server_rec *s = mySrvFromConn(c); SSLSrvConfigRec *sc = mySrvConfig(s); + SSLConnRec *sslconn = myConnConfig(c); + SSLDirConfigRec *dc = sslconn->dc; 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; @@ -1772,6 +1774,7 @@ int ssl_callback_proxy_cert(SSL *ssl, X509 **x509, 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 @@ -1796,7 +1799,7 @@ int ssl_callback_proxy_cert(SSL *ssl, X509 **x509, 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); Index: modules/ssl/ssl_private.h =================================================================== --- modules/ssl/ssl_private.h (revision 1740086) +++ modules/ssl/ssl_private.h (working copy) @@ -259,14 +259,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)) @@ -437,6 +441,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, @@ -475,6 +482,7 @@ typedef struct { } reneg_state; server_rec *server; + SSLDirConfigRec *dc; const char *cipher_suite; /* cipher suite used in last reneg */ } SSLConnRec; @@ -595,8 +603,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; @@ -658,12 +664,15 @@ 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; @@ -670,10 +679,6 @@ struct SSLSrvConfigRec { 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 @@ -691,7 +696,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; @@ -700,12 +705,14 @@ struct SSLSrvConfigRec { 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 */ @@ -721,6 +728,8 @@ void *ssl_config_server_create(apr_pool_t * 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 *); Index: server/core.c =================================================================== --- server/core.c (revision 1740086) +++ server/core.c (working copy) @@ -1312,7 +1312,10 @@ AP_DECLARE(const char *) ap_check_cmd_context(cmd_ || (found = find_parent(cmd->directive, "<FilesMatch")) || (found = find_parent(cmd->directive, "<If")) || (found = find_parent(cmd->directive, "<ElseIf")) - || (found = find_parent(cmd->directive, "<Else"))))) { + || (found = find_parent(cmd->directive, "<Else")))) + || ((forbidden & NOT_IN_PROXY) + && ((found = find_parent(cmd->directive, "<Proxy")) + || (found = find_parent(cmd->directive, "<ProxyMatch"))))) { return apr_pstrcat(cmd->pool, cmd->cmd->name, gt, " cannot occur within ", found->directive, "> section", NULL);