source: mod_gnutls/src/mod_gnutls.c @ 4aa63a4

debian/masterproxy-ticket
Last change on this file since 4aa63a4 was 4aa63a4, checked in by Fiona Klute <fiona.klute@…>, 3 years ago

Infrastructure for mod_watchdog support

Asynchronous OCSP cache updates require some kind of timed callbacks
outside of the request handling context. The watchdog module provides
this, is included in HTTPD builds by default, and the documentation
does not mention any restrictions regarding supported MPMs.

  • Property mode set to 100644
File size: 13.0 KB
Line 
1/*
2 *  Copyright 2004-2005 Paul Querna
3 *  Copyright 2008, 2014 Nikos Mavrogiannopoulos
4 *  Copyright 2011 Dash Shendy
5 *  Copyright 2015-2018 Fiona Klute
6 *
7 *  Licensed under the Apache License, Version 2.0 (the "License");
8 *  you may not use this file except in compliance with the License.
9 *  You may obtain a copy of the License at
10 *
11 *      http://www.apache.org/licenses/LICENSE-2.0
12 *
13 *  Unless required by applicable law or agreed to in writing, software
14 *  distributed under the License is distributed on an "AS IS" BASIS,
15 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 *  See the License for the specific language governing permissions and
17 *  limitations under the License.
18 */
19
20#include "mod_gnutls.h"
21#include "gnutls_ocsp.h"
22#include "gnutls_util.h"
23
24#ifdef APLOG_USE_MODULE
25APLOG_USE_MODULE(gnutls);
26#endif
27
28int ssl_engine_set(conn_rec *c,
29                   ap_conf_vector_t *dir_conf __attribute__((unused)),
30                   int proxy, int enable);
31
32#define MOD_HTTP2 "mod_http2.c"
33static const char * const mod_proxy[] = { "mod_proxy.c", NULL };
34static const char * const mod_http2[] = { MOD_HTTP2, NULL };
35
36static void gnutls_hooks(apr_pool_t * p __attribute__((unused)))
37{
38    /* Watchdog callbacks must be configured before post_config of
39     * mod_watchdog runs, or the watchdog won't be started. */
40    static const char * const post_conf_succ[] =
41        { MOD_HTTP2, "mod_watchdog.c", NULL };
42    ap_hook_post_config(mgs_hook_post_config, mod_proxy, post_conf_succ,
43                        APR_HOOK_MIDDLE);
44    /* HTTP Scheme Hook */
45    ap_hook_http_scheme(mgs_hook_http_scheme, NULL, NULL, APR_HOOK_MIDDLE);
46    /* Default Port Hook */
47    ap_hook_default_port(mgs_hook_default_port, NULL, NULL, APR_HOOK_MIDDLE);
48    /* Pre-Connect Hook */
49    ap_hook_pre_connection(mgs_hook_pre_connection, mod_http2, NULL,
50                           APR_HOOK_MIDDLE);
51    ap_hook_process_connection(mgs_hook_process_connection,
52                               NULL, mod_http2, APR_HOOK_MIDDLE);
53    /* Pre-Config Hook */
54    ap_hook_pre_config(mgs_hook_pre_config, NULL, NULL,
55                       APR_HOOK_MIDDLE);
56    /* Child-Init Hook */
57    ap_hook_child_init(mgs_hook_child_init, NULL, NULL,
58                       APR_HOOK_MIDDLE);
59    /* Authentication Hook */
60    ap_hook_access_checker(mgs_hook_authz, NULL, NULL,
61                           APR_HOOK_REALLY_FIRST);
62    /* Fixups Hook */
63    ap_hook_fixups(mgs_hook_fixups, NULL, NULL, APR_HOOK_REALLY_FIRST);
64
65    /* TODO: HTTP Upgrade Filter */
66    /* ap_register_output_filter ("UPGRADE_FILTER",
67     *          ssl_io_filter_Upgrade, NULL, AP_FTYPE_PROTOCOL + 5);
68     */
69
70    /* Input Filter */
71    ap_register_input_filter(GNUTLS_INPUT_FILTER_NAME, mgs_filter_input,
72                             NULL, AP_FTYPE_CONNECTION + 5);
73    /* Output Filter */
74    ap_register_output_filter(GNUTLS_OUTPUT_FILTER_NAME, mgs_filter_output,
75                              NULL, AP_FTYPE_CONNECTION + 5);
76
77    /* mod_proxy calls these functions */
78    APR_REGISTER_OPTIONAL_FN(ssl_proxy_enable);
79    APR_REGISTER_OPTIONAL_FN(ssl_engine_disable);
80    APR_REGISTER_OPTIONAL_FN(ssl_engine_set);
81
82    /* mod_rewrite calls this function to detect HTTPS */
83    APR_REGISTER_OPTIONAL_FN(ssl_is_https);
84    /* some modules look up TLS-related variables */
85    APR_REGISTER_OPTIONAL_FN(ssl_var_lookup);
86}
87
88
89
90/**
91 * Get the connection context, resolving to a master connection if
92 * any.
93 *
94 * @param c the connection handle
95 *
96 * @return mod_gnutls session context, might be `NULL`
97 */
98mgs_handle_t* get_effective_gnutls_ctxt(conn_rec *c)
99{
100    mgs_handle_t *ctxt = (mgs_handle_t *)
101        ap_get_module_config(c->conn_config, &gnutls_module);
102    if (!(ctxt != NULL && ctxt->enabled) && (c->master != NULL))
103    {
104        ctxt = (mgs_handle_t *)
105            ap_get_module_config(c->master->conn_config, &gnutls_module);
106    }
107    return ctxt;
108}
109
110
111
112/**
113 * mod_rewrite calls this function to fill %{HTTPS}.
114 *
115 * @param c the connection to check
116 * @return non-zero value if HTTPS is in use, zero if not
117 */
118int ssl_is_https(conn_rec *c)
119{
120    mgs_handle_t *ctxt = get_effective_gnutls_ctxt(c);
121    mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
122        ap_get_module_config(c->base_server->module_config, &gnutls_module);
123
124    if(sc->enabled == GNUTLS_ENABLED_FALSE
125       || ctxt == NULL
126       || ctxt->enabled == GNUTLS_ENABLED_FALSE)
127    {
128        /* SSL/TLS Disabled or Plain HTTP Connection Detected */
129        return 0;
130    }
131    /* Connection is Using SSL/TLS */
132    return 1;
133}
134
135
136
137/**
138 * Return variables describing the current TLS session (if any).
139 *
140 * mod_ssl doc for this function: "This function must remain safe to
141 * use for a non-SSL connection." mod_http2 uses it to check if an
142 * acceptable TLS session is used.
143 */
144char* ssl_var_lookup(apr_pool_t *p, server_rec *s __attribute__((unused)),
145                     conn_rec *c, request_rec *r, char *var)
146{
147    /*
148     * When no pool is given try to find one
149     */
150    if (p == NULL) {
151        if (r != NULL)
152            p = r->pool;
153        else if (c != NULL)
154            p = c->pool;
155        else
156            return NULL;
157    }
158
159    if (strcmp(var, "HTTPS") == 0)
160    {
161        if (c != NULL && ssl_is_https(c))
162            return "on";
163        else
164            return "off";
165    }
166
167    mgs_handle_t *ctxt = get_effective_gnutls_ctxt(c);
168
169    /* TLS parameters are empty if there is no session */
170    if (ctxt == NULL || ctxt->c == NULL)
171        return NULL;
172
173    if (strcmp(var, "SSL_PROTOCOL") == 0)
174        return apr_pstrdup(p, gnutls_protocol_get_name(gnutls_protocol_get_version(ctxt->session)));
175
176    if (strcmp(var, "SSL_CIPHER") == 0)
177        return apr_pstrdup(p, gnutls_cipher_suite_get_name(gnutls_kx_get(ctxt->session),
178                                                           gnutls_cipher_get(ctxt->session),
179                                                           gnutls_mac_get(ctxt->session)));
180
181    /* mod_ssl supports a LOT more variables */
182    ap_log_cerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, c,
183                  "unsupported variable requested: '%s'",
184                  var);
185
186    return NULL;
187}
188
189
190
191/**
192 * In Apache versions from 2.4.33 mod_proxy uses this function to set
193 * up its client connections. Note that mod_gnutls does not (yet)
194 * implement per directory configuration for such connections.
195 *
196 * @param c the connection
197 * @param dir_conf per directory configuration, unused for now
198 * @param proxy Is this a proxy connection?
199 * @param enable Should TLS be enabled on this connection?
200 *
201 * @param `true` (1) if successful, `false` (0) otherwise
202 */
203int ssl_engine_set(conn_rec *c,
204                   ap_conf_vector_t *dir_conf __attribute__((unused)),
205                   int proxy, int enable)
206{
207    mgs_handle_t *ctxt = init_gnutls_ctxt(c);
208
209    /* If TLS proxy has been requested, check if support is enabled
210     * for the server */
211    if (proxy && (ctxt->sc->proxy_enabled != GNUTLS_ENABLED_TRUE))
212    {
213        ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c,
214                      "%s: mod_proxy requested TLS proxy, but not enabled "
215                      "for %s", __func__, ctxt->sc->cert_cn);
216        return 0;
217    }
218
219    if (proxy)
220        ctxt->is_proxy = GNUTLS_ENABLED_TRUE;
221    else
222        ctxt->is_proxy = GNUTLS_ENABLED_FALSE;
223
224    if (enable)
225        ctxt->enabled = GNUTLS_ENABLED_TRUE;
226    else
227        ctxt->enabled = GNUTLS_ENABLED_FALSE;
228
229    return 1;
230}
231
232int ssl_engine_disable(conn_rec *c)
233{
234    return ssl_engine_set(c, NULL, 0, 0);
235}
236
237int ssl_proxy_enable(conn_rec *c)
238{
239    return ssl_engine_set(c, NULL, 1, 1);
240}
241
242static const command_rec mgs_config_cmds[] = {
243    AP_INIT_FLAG("GnuTLSProxyEngine", mgs_set_proxy_engine,
244    NULL,
245    RSRC_CONF | OR_AUTHCFG,
246    "Enable TLS Proxy Engine"),
247    AP_INIT_TAKE1("GnuTLSP11Module", mgs_set_p11_module,
248    NULL,
249    RSRC_CONF,
250    "Load this specific PKCS #11 provider library"),
251    AP_INIT_RAW_ARGS("GnuTLSPIN", mgs_set_pin,
252    NULL,
253    RSRC_CONF,
254    "The PIN to use in case of encrypted keys or PKCS #11 tokens."),
255    AP_INIT_RAW_ARGS("GnuTLSSRKPIN", mgs_set_srk_pin,
256    NULL,
257    RSRC_CONF,
258    "The SRK PIN to use in case of TPM keys."),
259    AP_INIT_TAKE1("GnuTLSClientVerify", mgs_set_client_verify,
260    NULL,
261    RSRC_CONF | OR_AUTHCFG,
262    "Set Verification Requirements of the Client Certificate"),
263    AP_INIT_TAKE1("GnuTLSClientVerifyMethod", mgs_set_client_verify_method,
264    NULL,
265    RSRC_CONF,
266    "Set Verification Method of the Client Certificate"),
267    AP_INIT_TAKE1("GnuTLSClientCAFile", mgs_set_client_ca_file,
268    NULL,
269    RSRC_CONF,
270    "Set the CA File to verify Client Certificates"),
271    AP_INIT_TAKE1("GnuTLSX509CAFile", mgs_set_client_ca_file,
272    NULL,
273    RSRC_CONF,
274    "Set the CA File to verify Client Certificates"),
275    AP_INIT_TAKE1("GnuTLSPGPKeyringFile", mgs_set_keyring_file,
276    NULL,
277    RSRC_CONF,
278    "Set the Keyring File to verify Client Certificates"),
279    AP_INIT_TAKE1("GnuTLSDHFile", mgs_set_dh_file,
280    NULL,
281    RSRC_CONF,
282    "Set the file to read Diffie Hellman parameters from"),
283    AP_INIT_TAKE1("GnuTLSCertificateFile", mgs_set_cert_file,
284    NULL,
285    RSRC_CONF,
286    "TLS Server X509 Certificate file"),
287    AP_INIT_TAKE1("GnuTLSKeyFile", mgs_set_key_file,
288    NULL,
289    RSRC_CONF,
290    "TLS Server X509 Private Key file"),
291    AP_INIT_TAKE1("GnuTLSX509CertificateFile", mgs_set_cert_file,
292    NULL,
293    RSRC_CONF,
294    "TLS Server X509 Certificate file"),
295    AP_INIT_TAKE1("GnuTLSX509KeyFile", mgs_set_key_file,
296    NULL,
297    RSRC_CONF,
298    "TLS Server X509 Private Key file"),
299    AP_INIT_TAKE1("GnuTLSPGPCertificateFile", mgs_set_pgpcert_file,
300    NULL,
301    RSRC_CONF,
302    "TLS Server PGP Certificate file"),
303    AP_INIT_TAKE1("GnuTLSPGPKeyFile", mgs_set_pgpkey_file,
304    NULL,
305    RSRC_CONF,
306    "TLS Server PGP Private key file"),
307#ifdef ENABLE_SRP
308    AP_INIT_TAKE1("GnuTLSSRPPasswdFile", mgs_set_srp_tpasswd_file,
309    NULL,
310    RSRC_CONF,
311    "TLS Server SRP Password Conf file"),
312    AP_INIT_TAKE1("GnuTLSSRPPasswdConfFile",
313    mgs_set_srp_tpasswd_conf_file,
314    NULL,
315    RSRC_CONF,
316    "TLS Server SRP Parameters file"),
317#endif
318    AP_INIT_TAKE1("GnuTLSCacheTimeout", mgs_set_timeout,
319    NULL,
320    RSRC_CONF,
321    "Cache Timeout"),
322    AP_INIT_TAKE12("GnuTLSCache", mgs_set_cache,
323    NULL,
324    RSRC_CONF,
325    "Cache Configuration"),
326    AP_INIT_FLAG("GnuTLSSessionTickets", mgs_set_tickets,
327    NULL,
328    RSRC_CONF,
329    "Session Tickets Configuration"),
330    AP_INIT_RAW_ARGS("GnuTLSPriorities", mgs_set_priorities,
331    NULL,
332    RSRC_CONF,
333    "The priorities to enable (ciphers, Key exchange, macs, compression)."),
334    AP_INIT_FLAG("GnuTLSEnable", mgs_set_enabled,
335    NULL,
336    RSRC_CONF,
337    "Whether this server has GnuTLS Enabled. Default: Off"),
338    AP_INIT_TAKE1("GnuTLSExportCertificates",
339    mgs_set_export_certificates_size,
340    NULL,
341    RSRC_CONF,
342    "Max size to export PEM encoded certificates to CGIs (or off to disable). Default: off"),
343    AP_INIT_TAKE1("GnuTLSProxyKeyFile", mgs_store_cred_path,
344    NULL,
345    RSRC_CONF,
346    "X509 client private file for proxy connections"),
347    AP_INIT_TAKE1("GnuTLSProxyCertificateFile", mgs_store_cred_path,
348    NULL,
349    RSRC_CONF,
350    "X509 client certificate file for proxy connections"),
351    AP_INIT_TAKE1("GnuTLSProxyCAFile", mgs_store_cred_path,
352    NULL,
353    RSRC_CONF,
354    "X509 trusted CA file for proxy connections"),
355    AP_INIT_TAKE1("GnuTLSProxyCRLFile", mgs_store_cred_path,
356    NULL,
357    RSRC_CONF,
358    "X509 CRL file for proxy connections"),
359    AP_INIT_RAW_ARGS("GnuTLSProxyPriorities", mgs_set_priorities,
360    NULL,
361    RSRC_CONF,
362    "The priorities to enable for proxy connections (ciphers, key exchange, "
363    "MACs, compression)."),
364    AP_INIT_FLAG("GnuTLSOCSPStapling", mgs_ocsp_stapling_enable,
365                 NULL, RSRC_CONF,
366                 "Enable OCSP stapling"),
367    AP_INIT_FLAG("GnuTLSOCSPCheckNonce", mgs_set_ocsp_check_nonce,
368                 NULL, RSRC_CONF,
369                 "Check nonce in OCSP responses?"),
370    AP_INIT_TAKE1("GnuTLSOCSPResponseFile", mgs_store_ocsp_response_path,
371                  NULL, RSRC_CONF,
372                  "Read OCSP response for stapling from this file instead "
373                  "of sending a request over HTTP (must be updated "
374                  "externally)"),
375    AP_INIT_TAKE1("GnuTLSOCSPCacheTimeout", mgs_set_timeout,
376                  NULL, RSRC_CONF,
377                  "Cache timeout for OCSP responses"),
378    AP_INIT_TAKE1("GnuTLSOCSPFailureTimeout", mgs_set_timeout,
379                  NULL, RSRC_CONF,
380                  "Wait this many seconds before retrying a failed OCSP "
381                  "request"),
382    AP_INIT_TAKE1("GnuTLSOCSPSocketTimeout", mgs_set_timeout,
383                  NULL, RSRC_CONF,
384                  "Socket timeout for OCSP requests"),
385#ifdef __clang__
386    /* Workaround for this clang bug:
387     * https://llvm.org/bugs/show_bug.cgi?id=21689 */
388    {},
389#else
390    { NULL },
391#endif
392};
393
394module AP_MODULE_DECLARE_DATA gnutls_module = {
395    STANDARD20_MODULE_STUFF,
396    .create_dir_config = mgs_config_dir_create,
397    .merge_dir_config = mgs_config_dir_merge,
398    .create_server_config = mgs_config_server_create,
399    .merge_server_config = mgs_config_server_merge,
400    .cmds = mgs_config_cmds,
401    .register_hooks = gnutls_hooks
402};
Note: See TracBrowser for help on using the repository browser.