]> granicus.if.org Git - apache/blob - modules/ssl/mod_ssl.c
* modules/ssl/ssl_engine_vars.c (ssl_var_register): Take a pool
[apache] / modules / ssl / mod_ssl.c
1 /* Licensed to the Apache Software Foundation (ASF) under one or more
2  * contributor license agreements.  See the NOTICE file distributed with
3  * this work for additional information regarding copyright ownership.
4  * The ASF licenses this file to You under the Apache License, Version 2.0
5  * (the "License"); you may not use this file except in compliance with
6  * the License.  You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 /*                      _             _
18  *  _ __ ___   ___   __| |    ___ ___| |  mod_ssl
19  * | '_ ` _ \ / _ \ / _` |   / __/ __| |  Apache Interface to OpenSSL
20  * | | | | | | (_) | (_| |   \__ \__ \ |
21  * |_| |_| |_|\___/ \__,_|___|___/___/_|
22  *                      |_____|
23  *  mod_ssl.c
24  *  Apache API interface structures
25  */
26
27 #include "ssl_private.h"
28 #include "mod_ssl.h"
29 #include "util_md5.h"
30 #include "util_mutex.h"
31 #include <assert.h>
32
33 /*
34  *  the table of configuration directives we provide
35  */
36
37 #define SSL_CMD_ALL(name, args, desc) \
38         AP_INIT_##args("SSL"#name, ssl_cmd_SSL##name, \
39                        NULL, RSRC_CONF|OR_AUTHCFG, desc),
40
41 #define SSL_CMD_SRV(name, args, desc) \
42         AP_INIT_##args("SSL"#name, ssl_cmd_SSL##name, \
43                        NULL, RSRC_CONF, desc),
44
45 #define SSL_CMD_DIR(name, type, args, desc) \
46         AP_INIT_##args("SSL"#name, ssl_cmd_SSL##name, \
47                        NULL, OR_##type, desc),
48
49 #define AP_END_CMD { NULL }
50
51 static const command_rec ssl_config_cmds[] = {
52     /*
53      * Global (main-server) context configuration directives
54      */
55     SSL_CMD_SRV(Mutex, TAKE1, AP_ALL_AVAILABLE_MUTEXES_STRING)
56     SSL_CMD_SRV(PassPhraseDialog, TAKE1,
57                 "SSL dialog mechanism for the pass phrase query "
58                 "(`builtin', `|/path/to/pipe_program`, "
59                 "or `exec:/path/to/cgi_program')")
60     SSL_CMD_SRV(SessionCache, TAKE1,
61                 "SSL Session Cache storage "
62                 "(`none', `nonenotnull', `dbm:/path/to/file')")
63 #if defined(HAVE_OPENSSL_ENGINE_H) && defined(HAVE_ENGINE_INIT)
64     SSL_CMD_SRV(CryptoDevice, TAKE1,
65                 "SSL external Crypto Device usage "
66                 "(`builtin', `...')")
67 #endif
68     SSL_CMD_SRV(RandomSeed, TAKE23,
69                 "SSL Pseudo Random Number Generator (PRNG) seeding source "
70                 "(`startup|connect builtin|file:/path|exec:/path [bytes]')")
71
72     /*
73      * Per-server context configuration directives
74      */
75     SSL_CMD_SRV(Engine, TAKE1,
76                 "SSL switch for the protocol engine "
77                 "(`on', `off')")
78     SSL_CMD_ALL(CipherSuite, TAKE1,
79                 "Colon-delimited list of permitted SSL Ciphers "
80                 "(`XXX:...:XXX' - see manual)")
81     SSL_CMD_SRV(CertificateFile, TAKE1,
82                 "SSL Server Certificate file "
83                 "(`/path/to/file' - PEM or DER encoded)")
84     SSL_CMD_SRV(CertificateKeyFile, TAKE1,
85                 "SSL Server Private Key file "
86                 "(`/path/to/file' - PEM or DER encoded)")
87     SSL_CMD_SRV(CertificateChainFile, TAKE1,
88                 "SSL Server CA Certificate Chain file "
89                 "(`/path/to/file' - PEM encoded)")
90     SSL_CMD_SRV(PKCS7CertificateFile, TAKE1,
91                 "PKCS#7 file containing server certificate and chain"
92                 " certificates (`/path/to/file' - PEM encoded)")
93     SSL_CMD_ALL(CACertificatePath, TAKE1,
94                 "SSL CA Certificate path "
95                 "(`/path/to/dir' - contains PEM encoded files)")
96     SSL_CMD_ALL(CACertificateFile, TAKE1,
97                 "SSL CA Certificate file "
98                 "(`/path/to/file' - PEM encoded)")
99     SSL_CMD_SRV(CADNRequestPath, TAKE1,
100                 "SSL CA Distinguished Name path "
101                 "(`/path/to/dir' - symlink hashes to PEM of acceptable CA names to request)")
102     SSL_CMD_SRV(CADNRequestFile, TAKE1,
103                 "SSL CA Distinguished Name file "
104                 "(`/path/to/file' - PEM encoded to derive acceptable CA names to request)")
105     SSL_CMD_SRV(CARevocationPath, TAKE1,
106                 "SSL CA Certificate Revocation List (CRL) path "
107                 "(`/path/to/dir' - contains PEM encoded files)")
108     SSL_CMD_SRV(CARevocationFile, TAKE1,
109                 "SSL CA Certificate Revocation List (CRL) file "
110                 "(`/path/to/file' - PEM encoded)")
111     SSL_CMD_ALL(VerifyClient, TAKE1,
112                 "SSL Client verify type "
113                 "(`none', `optional', `require', `optional_no_ca')")
114     SSL_CMD_ALL(VerifyDepth, TAKE1,
115                 "SSL Client verify depth "
116                 "(`N' - number of intermediate certificates)")
117     SSL_CMD_SRV(SessionCacheTimeout, TAKE1,
118                 "SSL Session Cache object lifetime "
119                 "(`N' - number of seconds)")
120     SSL_CMD_SRV(Protocol, RAW_ARGS,
121                 "Enable or disable various SSL protocols"
122                 "(`[+-][SSLv2|SSLv3|TLSv1] ...' - see manual)")
123     SSL_CMD_SRV(HonorCipherOrder, FLAG,
124                 "Use the server's cipher ordering preference")
125     SSL_CMD_ALL(UserName, TAKE1,
126                 "Set user name to SSL variable value")
127     SSL_CMD_SRV(LogLevelDebugDump, TAKE1,
128                 "Include I/O Dump when LogLevel is set to Debug "
129                 "([ None (default) | IO (not bytes) | Bytes ])")
130
131     /*
132      * Proxy configuration for remote SSL connections
133      */
134     SSL_CMD_SRV(ProxyEngine, FLAG,
135                 "SSL switch for the proxy protocol engine "
136                 "(`on', `off')")
137     SSL_CMD_SRV(ProxyProtocol, RAW_ARGS,
138                "SSL Proxy: enable or disable SSL protocol flavors "
139                "(`[+-][SSLv2|SSLv3|TLSv1] ...' - see manual)")
140     SSL_CMD_SRV(ProxyCipherSuite, TAKE1,
141                "SSL Proxy: colon-delimited list of permitted SSL ciphers "
142                "(`XXX:...:XXX' - see manual)")
143     SSL_CMD_SRV(ProxyVerify, TAKE1,
144                "SSL Proxy: whether to verify the remote certificate "
145                "(`on' or `off')")
146     SSL_CMD_SRV(ProxyVerifyDepth, TAKE1,
147                "SSL Proxy: maximum certificate verification depth "
148                "(`N' - number of intermediate certificates)")
149     SSL_CMD_SRV(ProxyCACertificateFile, TAKE1,
150                "SSL Proxy: file containing server certificates "
151                "(`/path/to/file' - PEM encoded certificates)")
152     SSL_CMD_SRV(ProxyCACertificatePath, TAKE1,
153                "SSL Proxy: directory containing server certificates "
154                "(`/path/to/dir' - contains PEM encoded certificates)")
155     SSL_CMD_SRV(ProxyCARevocationPath, TAKE1,
156                 "SSL Proxy: CA Certificate Revocation List (CRL) path "
157                 "(`/path/to/dir' - contains PEM encoded files)")
158     SSL_CMD_SRV(ProxyCARevocationFile, TAKE1,
159                 "SSL Proxy: CA Certificate Revocation List (CRL) file "
160                 "(`/path/to/file' - PEM encoded)")
161     SSL_CMD_SRV(ProxyMachineCertificateFile, TAKE1,
162                "SSL Proxy: file containing client certificates "
163                "(`/path/to/file' - PEM encoded certificates)")
164     SSL_CMD_SRV(ProxyMachineCertificatePath, TAKE1,
165                "SSL Proxy: directory containing client certificates "
166                "(`/path/to/dir' - contains PEM encoded certificates)")
167
168     /*
169      * Per-directory context configuration directives
170      */
171     SSL_CMD_DIR(Options, OPTIONS, RAW_ARGS,
172                "Set one or more options to configure the SSL engine"
173                "(`[+-]option[=value] ...' - see manual)")
174     SSL_CMD_DIR(RequireSSL, AUTHCFG, NO_ARGS,
175                "Require the SSL protocol for the per-directory context "
176                "(no arguments)")
177     SSL_CMD_DIR(Require, AUTHCFG, RAW_ARGS,
178                "Require a boolean expression to evaluate to true for granting access"
179                "(arbitrary complex boolean expression - see manual)")
180
181     /* Deprecated directives. */
182     AP_INIT_RAW_ARGS("SSLLog", ap_set_deprecated, NULL, OR_ALL,
183       "SSLLog directive is no longer supported - use ErrorLog."),
184     AP_INIT_RAW_ARGS("SSLLogLevel", ap_set_deprecated, NULL, OR_ALL,
185       "SSLLogLevel directive is no longer supported - use LogLevel."),
186
187     AP_END_CMD
188 };
189
190 /*
191  *  the various processing hooks
192  */
193 static apr_status_t ssl_cleanup_pre_config(void *data)
194 {
195     /*
196      * Try to kill the internals of the SSL library.
197      */
198 #ifdef HAVE_OPENSSL
199 #if OPENSSL_VERSION_NUMBER >= 0x00907001
200     /* Corresponds to OPENSSL_load_builtin_modules():
201      * XXX: borrowed from apps.h, but why not CONF_modules_free()
202      * which also invokes CONF_modules_finish()?
203      */
204     CONF_modules_unload(1);
205 #endif
206 #endif
207     /* Corresponds to SSL_library_init: */
208     EVP_cleanup();
209 #if HAVE_ENGINE_LOAD_BUILTIN_ENGINES
210     ENGINE_cleanup();
211 #endif
212 #ifdef HAVE_OPENSSL
213 #if OPENSSL_VERSION_NUMBER >= 0x00907001
214     CRYPTO_cleanup_all_ex_data();
215 #endif
216 #endif
217     ERR_remove_state(0);
218
219     /* Don't call ERR_free_strings here; ERR_load_*_strings only
220      * actually load the error strings once per process due to static
221      * variable abuse in OpenSSL. */
222
223     /*
224      * TODO: determine somewhere we can safely shove out diagnostics
225      *       (when enabled) at this late stage in the game:
226      * CRYPTO_mem_leaks_fp(stderr);
227      */
228     return APR_SUCCESS;
229 }
230
231 static int ssl_hook_pre_config(apr_pool_t *pconf,
232                                apr_pool_t *plog,
233                                apr_pool_t *ptemp)
234 {
235     /* We must register the library in full, to ensure our configuration
236      * code can successfully test the SSL environment.
237      */
238     CRYPTO_malloc_init();
239 #ifdef HAVE_OPENSSL
240     ERR_load_crypto_strings();
241 #endif
242     SSL_load_error_strings();
243     SSL_library_init();
244 #if HAVE_ENGINE_LOAD_BUILTIN_ENGINES
245     ENGINE_load_builtin_engines();
246 #endif
247 #ifdef HAVE_OPENSSL
248     OpenSSL_add_all_algorithms();
249 #if OPENSSL_VERSION_NUMBER >= 0x00907001
250     OPENSSL_load_builtin_modules();
251 #endif
252 #endif
253
254     /*
255      * Let us cleanup the ssl library when the module is unloaded
256      */
257     apr_pool_cleanup_register(pconf, NULL, ssl_cleanup_pre_config,
258                                            apr_pool_cleanup_null);
259
260     /* Register us to handle mod_log_config %c/%x variables */
261     ssl_var_log_config_register(pconf);
262
263     /* Register to handle mod_status status page generation */
264     ssl_scache_status_register(pconf);
265
266     return OK;
267 }
268
269 static SSLConnRec *ssl_init_connection_ctx(conn_rec *c)
270 {
271     SSLConnRec *sslconn = myConnConfig(c);
272
273     if (sslconn) {
274         return sslconn;
275     }
276
277     sslconn = apr_pcalloc(c->pool, sizeof(*sslconn));
278
279     myConnConfigSet(c, sslconn);
280
281     return sslconn;
282 }
283
284 int ssl_proxy_enable(conn_rec *c)
285 {
286     SSLSrvConfigRec *sc = mySrvConfig(c->base_server);
287
288     SSLConnRec *sslconn = ssl_init_connection_ctx(c);
289
290     if (!sc->proxy_enabled) {
291         ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c,
292                       "SSL Proxy requested for %s but not enabled "
293                       "[Hint: SSLProxyEngine]", sc->vhost_id);
294
295         return 0;
296     }
297
298     sslconn->is_proxy = 1;
299     sslconn->disabled = 0;
300
301     return 1;
302 }
303
304 int ssl_engine_disable(conn_rec *c)
305 {
306     SSLSrvConfigRec *sc = mySrvConfig(c->base_server);
307
308     SSLConnRec *sslconn;
309
310     if (sc->enabled == SSL_ENABLED_FALSE) {
311         return 0;
312     }
313
314     sslconn = ssl_init_connection_ctx(c);
315
316     sslconn->disabled = 1;
317
318     return 1;
319 }
320
321 int ssl_init_ssl_connection(conn_rec *c)
322 {
323     SSLSrvConfigRec *sc = mySrvConfig(c->base_server);
324     SSL *ssl;
325     SSLConnRec *sslconn = myConnConfig(c);
326     char *vhost_md5;
327     modssl_ctx_t *mctx;
328
329     /*
330      * Seed the Pseudo Random Number Generator (PRNG)
331      */
332     ssl_rand_seed(c->base_server, c->pool, SSL_RSCTX_CONNECT, "");
333
334     if (!sslconn) {
335         sslconn = ssl_init_connection_ctx(c);
336     }
337
338     mctx = sslconn->is_proxy ? sc->proxy : sc->server;
339
340     /*
341      * Create a new SSL connection with the configured server SSL context and
342      * attach this to the socket. Additionally we register this attachment
343      * so we can detach later.
344      */
345     if (!(ssl = SSL_new(mctx->ssl_ctx))) {
346         ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c,
347                       "Unable to create a new SSL connection from the SSL "
348                       "context");
349         ssl_log_ssl_error(APLOG_MARK, APLOG_ERR, c->base_server);
350
351         c->aborted = 1;
352
353         return DECLINED; /* XXX */
354     }
355
356     vhost_md5 = ap_md5_binary(c->pool, (unsigned char *)sc->vhost_id,
357                               sc->vhost_id_len);
358
359     if (!SSL_set_session_id_context(ssl, (unsigned char *)vhost_md5,
360                                     APR_MD5_DIGESTSIZE*2))
361     {
362         ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c,
363                       "Unable to set session id context to `%s'", vhost_md5);
364         ssl_log_ssl_error(APLOG_MARK, APLOG_ERR, c->base_server);
365
366         c->aborted = 1;
367
368         return DECLINED; /* XXX */
369     }
370
371     SSL_set_app_data(ssl, c);
372     SSL_set_app_data2(ssl, NULL); /* will be request_rec */
373
374     sslconn->ssl = ssl;
375
376     /*
377      *  Configure callbacks for SSL connection
378      */
379     SSL_set_tmp_rsa_callback(ssl, ssl_callback_TmpRSA);
380     SSL_set_tmp_dh_callback(ssl,  ssl_callback_TmpDH);
381
382     SSL_set_verify_result(ssl, X509_V_OK);
383
384     ssl_io_filter_init(c, ssl);
385
386     return APR_SUCCESS;
387 }
388
389 static const char *ssl_hook_http_scheme(const request_rec *r)
390 {
391     SSLSrvConfigRec *sc = mySrvConfig(r->server);
392
393     if (sc->enabled == SSL_ENABLED_FALSE || sc->enabled == SSL_ENABLED_OPTIONAL) {
394         return NULL;
395     }
396
397     return "https";
398 }
399
400 static apr_port_t ssl_hook_default_port(const request_rec *r)
401 {
402     SSLSrvConfigRec *sc = mySrvConfig(r->server);
403
404     if (sc->enabled == SSL_ENABLED_FALSE || sc->enabled == SSL_ENABLED_OPTIONAL) {
405         return 0;
406     }
407
408     return 443;
409 }
410
411 static int ssl_hook_pre_connection(conn_rec *c, void *csd)
412 {
413     SSLSrvConfigRec *sc = mySrvConfig(c->base_server);
414     SSLConnRec *sslconn = myConnConfig(c);
415
416     /*
417      * Immediately stop processing if SSL is disabled for this connection
418      */
419     if (!(sc && (sc->enabled == SSL_ENABLED_TRUE ||
420                  (sslconn && sslconn->is_proxy))))
421     {
422         return DECLINED;
423     }
424
425     /*
426      * Create SSL context
427      */
428     if (!sslconn) {
429         sslconn = ssl_init_connection_ctx(c);
430     }
431
432     if (sslconn->disabled) {
433         return DECLINED;
434     }
435
436     /*
437      * Remember the connection information for
438      * later access inside callback functions
439      */
440
441     ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, c,
442                   "Connection to child %ld established "
443                   "(server %s)", c->id, sc->vhost_id);
444
445     return ssl_init_ssl_connection(c);
446 }
447
448
449 static void ssl_hook_Insert_Filter(request_rec *r)
450 {
451     SSLSrvConfigRec *sc = mySrvConfig(r->server);
452
453     if (sc->enabled == SSL_ENABLED_OPTIONAL) {
454         ap_add_output_filter("UPGRADE_FILTER", NULL, r, r->connection);
455     }
456 }
457
458 /*
459  *  the module registration phase
460  */
461
462 static void ssl_register_hooks(apr_pool_t *p)
463 {
464     /* ssl_hook_ReadReq needs to use the BrowserMatch settings so must
465      * run after mod_setenvif's post_read_request hook. */
466     static const char *pre_prr[] = { "mod_setenvif.c", NULL };
467
468     ssl_io_filter_register(p);
469
470     ap_hook_pre_connection(ssl_hook_pre_connection,NULL,NULL, APR_HOOK_MIDDLE);
471     ap_hook_test_config   (ssl_hook_ConfigTest,    NULL,NULL, APR_HOOK_MIDDLE);
472     ap_hook_post_config   (ssl_init_Module,        NULL,NULL, APR_HOOK_MIDDLE);
473     ap_hook_http_scheme   (ssl_hook_http_scheme,   NULL,NULL, APR_HOOK_MIDDLE);
474     ap_hook_default_port  (ssl_hook_default_port,  NULL,NULL, APR_HOOK_MIDDLE);
475     ap_hook_pre_config    (ssl_hook_pre_config,    NULL,NULL, APR_HOOK_MIDDLE);
476     ap_hook_child_init    (ssl_init_Child,         NULL,NULL, APR_HOOK_MIDDLE);
477     ap_hook_check_user_id (ssl_hook_UserCheck,     NULL,NULL, APR_HOOK_FIRST);
478     ap_hook_fixups        (ssl_hook_Fixup,         NULL,NULL, APR_HOOK_MIDDLE);
479     ap_hook_access_checker(ssl_hook_Access,        NULL,NULL, APR_HOOK_MIDDLE);
480     ap_hook_auth_checker  (ssl_hook_Auth,          NULL,NULL, APR_HOOK_MIDDLE);
481     ap_hook_post_read_request(ssl_hook_ReadReq, pre_prr,NULL, APR_HOOK_MIDDLE);
482     ap_hook_insert_filter (ssl_hook_Insert_Filter, NULL,NULL, APR_HOOK_MIDDLE);
483 /*    ap_hook_handler       (ssl_hook_Upgrade,       NULL,NULL, APR_HOOK_MIDDLE); */
484
485     ssl_var_register(p);
486
487     APR_REGISTER_OPTIONAL_FN(ssl_proxy_enable);
488     APR_REGISTER_OPTIONAL_FN(ssl_engine_disable);
489 }
490
491 module AP_MODULE_DECLARE_DATA ssl_module = {
492     STANDARD20_MODULE_STUFF,
493     ssl_config_perdir_create,   /* create per-dir    config structures */
494     ssl_config_perdir_merge,    /* merge  per-dir    config structures */
495     ssl_config_server_create,   /* create per-server config structures */
496     ssl_config_server_merge,    /* merge  per-server config structures */
497     ssl_config_cmds,            /* table of configuration directives   */
498     ssl_register_hooks          /* register hooks */
499 };