289 lines
9.9 KiB
C
289 lines
9.9 KiB
C
/* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed with
|
|
* this work for additional information regarding copyright ownership.
|
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
|
* (the "License"); you may not use this file except in compliance with
|
|
* the License. You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
#include <assert.h>
|
|
#include <apr_optional.h>
|
|
#include <apr_strings.h>
|
|
|
|
#include <mpm_common.h>
|
|
#include <httpd.h>
|
|
#include <http_core.h>
|
|
#include <http_connection.h>
|
|
#include <http_log.h>
|
|
#include <http_protocol.h>
|
|
#include <http_ssl.h>
|
|
#include <http_request.h>
|
|
#include <ap_socache.h>
|
|
|
|
#include <rustls.h>
|
|
|
|
#include "mod_tls.h"
|
|
#include "tls_conf.h"
|
|
#include "tls_core.h"
|
|
#include "tls_cache.h"
|
|
#include "tls_proto.h"
|
|
#include "tls_filter.h"
|
|
#include "tls_var.h"
|
|
#include "tls_version.h"
|
|
|
|
#include "mod_proxy.h"
|
|
|
|
static void tls_hooks(apr_pool_t *pool);
|
|
|
|
AP_DECLARE_MODULE(tls) = {
|
|
STANDARD20_MODULE_STUFF,
|
|
tls_conf_create_dir, /* create per dir config */
|
|
tls_conf_merge_dir, /* merge per dir config */
|
|
tls_conf_create_svr, /* create per server config */
|
|
tls_conf_merge_svr, /* merge per server config (inheritance) */
|
|
tls_conf_cmds, /* command handlers */
|
|
tls_hooks,
|
|
#if defined(AP_MODULE_FLAG_NONE)
|
|
AP_MODULE_FLAG_ALWAYS_MERGE
|
|
#endif
|
|
};
|
|
|
|
static const char* crustls_version(apr_pool_t *p)
|
|
{
|
|
struct rustls_str rversion;
|
|
|
|
rversion = rustls_version();
|
|
return apr_pstrndup(p, rversion.data, rversion.len);
|
|
}
|
|
|
|
static int tls_pre_config(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp)
|
|
{
|
|
tls_proto_pre_config(pconf, ptemp);
|
|
tls_cache_pre_config(pconf, plog, ptemp);
|
|
return OK;
|
|
}
|
|
|
|
static apr_status_t tls_post_config(apr_pool_t *p, apr_pool_t *plog,
|
|
apr_pool_t *ptemp, server_rec *s)
|
|
{
|
|
const char *tls_init_key = "mod_tls_init_counter";
|
|
tls_conf_server_t *sc;
|
|
void *data = NULL;
|
|
|
|
(void)plog;
|
|
sc = tls_conf_server_get(s);
|
|
assert(sc);
|
|
assert(sc->global);
|
|
sc->global->module_version = "mod_tls/" MOD_TLS_VERSION;
|
|
sc->global->crustls_version = crustls_version(p);
|
|
|
|
apr_pool_userdata_get(&data, tls_init_key, s->process->pool);
|
|
if (data == NULL) {
|
|
/* At the first start, httpd makes a config check dry run
|
|
* to see if the config is ok in principle.
|
|
*/
|
|
ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, s, "post config dry run");
|
|
apr_pool_userdata_set((const void *)1, tls_init_key,
|
|
apr_pool_cleanup_null, s->process->pool);
|
|
}
|
|
else {
|
|
ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, APLOGNO(10365)
|
|
"%s (%s), initializing...",
|
|
sc->global->module_version,
|
|
sc->global->crustls_version);
|
|
}
|
|
|
|
return tls_core_init(p, ptemp, s);
|
|
}
|
|
|
|
static apr_status_t tls_post_proxy_config(
|
|
apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s)
|
|
{
|
|
tls_conf_server_t *sc = tls_conf_server_get(s);
|
|
(void)plog;
|
|
sc->global->mod_proxy_post_config_done = 1;
|
|
return tls_core_init(p, ptemp, s);
|
|
}
|
|
|
|
#if AP_MODULE_MAGIC_AT_LEAST(20120211, 109)
|
|
static int tls_ssl_outgoing(conn_rec *c, ap_conf_vector_t *dir_conf, int enable_ssl)
|
|
{
|
|
/* we are not handling proxy connections - for now */
|
|
tls_core_conn_bind(c, dir_conf);
|
|
if (enable_ssl && tls_core_setup_outgoing(c) == OK) {
|
|
ap_log_error(APLOG_MARK, APLOG_TRACE2, 0, c->base_server,
|
|
"accepted ssl_bind_outgoing(enable=%d) for %s",
|
|
enable_ssl, c->base_server->server_hostname);
|
|
return OK;
|
|
}
|
|
tls_core_conn_disable(c);
|
|
ap_log_error(APLOG_MARK, APLOG_TRACE2, 0, c->base_server,
|
|
"declined ssl_bind_outgoing(enable=%d) for %s",
|
|
enable_ssl, c->base_server->server_hostname);
|
|
return DECLINED;
|
|
}
|
|
|
|
#else /* #if AP_MODULE_MAGIC_AT_LEAST(20120211, 109) */
|
|
|
|
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));
|
|
static APR_OPTIONAL_FN_TYPE(ssl_engine_set) *module_ssl_engine_set;
|
|
|
|
static int ssl_engine_set(
|
|
conn_rec *c, ap_conf_vector_t *dir_conf, int proxy, int enable)
|
|
{
|
|
ap_log_error(APLOG_MARK, APLOG_TRACE3, 0, c->base_server,
|
|
"ssl_engine_set(proxy=%d, enable=%d) for %s",
|
|
proxy, enable, c->base_server->server_hostname);
|
|
tls_core_conn_bind(c, dir_conf);
|
|
if (enable && tls_core_setup_outgoing(c) == OK) {
|
|
if (module_ssl_engine_set) {
|
|
module_ssl_engine_set(c, dir_conf, proxy, 0);
|
|
}
|
|
return 1;
|
|
}
|
|
if (proxy || !enable) {
|
|
/* we are not handling proxy connections - for now */
|
|
tls_core_conn_disable(c);
|
|
}
|
|
if (module_ssl_engine_set) {
|
|
return module_ssl_engine_set(c, dir_conf, proxy, enable);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int ssl_proxy_enable(conn_rec *c)
|
|
{
|
|
return ssl_engine_set(c, NULL, 1, 1);
|
|
}
|
|
|
|
static int ssl_engine_disable(conn_rec *c)
|
|
{
|
|
return ssl_engine_set(c, NULL, 0, 0);
|
|
}
|
|
|
|
static apr_status_t tls_post_config_proxy_ssl(
|
|
apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s)
|
|
{
|
|
if (1) {
|
|
const char *tls_init_key = "mod_tls_proxy_ssl_counter";
|
|
void *data = NULL;
|
|
APR_OPTIONAL_FN_TYPE(ssl_engine_set) *fn_ssl_engine_set;
|
|
|
|
(void)p;
|
|
(void)plog;
|
|
(void)ptemp;
|
|
apr_pool_userdata_get(&data, tls_init_key, s->process->pool);
|
|
if (data == NULL) {
|
|
/* At the first start, httpd makes a config check dry run
|
|
* to see if the config is ok in principle.
|
|
*/
|
|
apr_pool_userdata_set((const void *)1, tls_init_key,
|
|
apr_pool_cleanup_null, s->process->pool);
|
|
return APR_SUCCESS;
|
|
}
|
|
|
|
/* mod_ssl (if so loaded, has registered its optional functions.
|
|
* When mod_proxy runs in post-config, it looks up those functions and uses
|
|
* them to manipulate SSL status for backend connections.
|
|
* We provide our own implementations to avoid becoming active on such
|
|
* connections for now.
|
|
* */
|
|
fn_ssl_engine_set = APR_RETRIEVE_OPTIONAL_FN(ssl_engine_set);
|
|
module_ssl_engine_set = (fn_ssl_engine_set
|
|
&& fn_ssl_engine_set != ssl_engine_set)? fn_ssl_engine_set : NULL;
|
|
APR_REGISTER_OPTIONAL_FN(ssl_engine_set);
|
|
APR_REGISTER_OPTIONAL_FN(ssl_proxy_enable);
|
|
APR_REGISTER_OPTIONAL_FN(ssl_engine_disable);
|
|
}
|
|
return APR_SUCCESS;
|
|
}
|
|
#endif /* #if AP_MODULE_MAGIC_AT_LEAST(20120211, 109) */
|
|
|
|
static void tls_init_child(apr_pool_t *p, server_rec *s)
|
|
{
|
|
tls_cache_init_child(p, s);
|
|
}
|
|
|
|
static int hook_pre_connection(conn_rec *c, void *csd)
|
|
{
|
|
(void)csd; /* mpm specific socket data, not used */
|
|
|
|
/* are we on a primary connection? */
|
|
if (c->master) return DECLINED;
|
|
|
|
/* Decide connection TLS stats and install our
|
|
* input/output filters for handling TLS/application data
|
|
* if enabled.
|
|
*/
|
|
return tls_filter_pre_conn_init(c);
|
|
}
|
|
|
|
static int hook_connection(conn_rec* c)
|
|
{
|
|
tls_filter_conn_init(c);
|
|
/* we do *not* take over. we are not processing requests. */
|
|
return DECLINED;
|
|
}
|
|
|
|
static const char *tls_hook_http_scheme(const request_rec *r)
|
|
{
|
|
return (tls_conn_check_ssl(r->connection) == OK)? "https" : NULL;
|
|
}
|
|
|
|
static apr_port_t tls_hook_default_port(const request_rec *r)
|
|
{
|
|
return (tls_conn_check_ssl(r->connection) == OK) ? 443 : 0;
|
|
}
|
|
|
|
static const char* const mod_http2[] = { "mod_http2.c", NULL};
|
|
|
|
static void tls_hooks(apr_pool_t *pool)
|
|
{
|
|
/* If our request check denies further processing, certain things
|
|
* need to be in place for the response to be correctly generated. */
|
|
static const char *dep_req_check[] = { "mod_setenvif.c", NULL };
|
|
static const char *dep_proxy[] = { "mod_proxy.c", NULL };
|
|
|
|
ap_log_perror(APLOG_MARK, APLOG_TRACE1, 0, pool, "installing hooks");
|
|
tls_filter_register(pool);
|
|
|
|
ap_hook_pre_config(tls_pre_config, NULL,NULL, APR_HOOK_MIDDLE);
|
|
/* run post-config hooks one before, one after mod_proxy, as the
|
|
* mod_proxy's own one calls us in its "section_post_config" hook. */
|
|
ap_hook_post_config(tls_post_config, NULL, dep_proxy, APR_HOOK_MIDDLE);
|
|
APR_OPTIONAL_HOOK(proxy, section_post_config,
|
|
tls_proxy_section_post_config, NULL, NULL,
|
|
APR_HOOK_MIDDLE);
|
|
ap_hook_post_config(tls_post_proxy_config, dep_proxy, NULL, APR_HOOK_MIDDLE);
|
|
ap_hook_child_init(tls_init_child, NULL,NULL, APR_HOOK_MIDDLE);
|
|
/* connection things */
|
|
ap_hook_pre_connection(hook_pre_connection, NULL, NULL, APR_HOOK_MIDDLE);
|
|
ap_hook_process_connection(hook_connection, NULL, mod_http2, APR_HOOK_MIDDLE);
|
|
/* request things */
|
|
ap_hook_default_port(tls_hook_default_port, NULL,NULL, APR_HOOK_MIDDLE);
|
|
ap_hook_http_scheme(tls_hook_http_scheme, NULL,NULL, APR_HOOK_MIDDLE);
|
|
ap_hook_post_read_request(tls_core_request_check, dep_req_check, NULL, APR_HOOK_MIDDLE);
|
|
ap_hook_fixups(tls_var_request_fixup, NULL,NULL, APR_HOOK_MIDDLE);
|
|
|
|
ap_hook_ssl_conn_is_ssl(tls_conn_check_ssl, NULL, NULL, APR_HOOK_MIDDLE);
|
|
ap_hook_ssl_var_lookup(tls_var_lookup, NULL, NULL, APR_HOOK_MIDDLE);
|
|
|
|
#if AP_MODULE_MAGIC_AT_LEAST(20120211, 109)
|
|
ap_hook_ssl_bind_outgoing(tls_ssl_outgoing, NULL, NULL, APR_HOOK_MIDDLE);
|
|
#else
|
|
ap_hook_post_config(tls_post_config_proxy_ssl, NULL, dep_proxy, APR_HOOK_MIDDLE);
|
|
#endif
|
|
|
|
}
|