summaryrefslogtreecommitdiffstats
path: root/modules/tls/mod_tls.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--modules/tls/mod_tls.c288
1 files changed, 288 insertions, 0 deletions
diff --git a/modules/tls/mod_tls.c b/modules/tls/mod_tls.c
new file mode 100644
index 0000000..9d79521
--- /dev/null
+++ b/modules/tls/mod_tls.c
@@ -0,0 +1,288 @@
+/* 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
+
+}