2 ** _ __ ___ ___ __| | ___ ___| | mod_ssl
3 ** | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL
4 ** | | | | | | (_) | (_| | \__ \__ \ | www.modssl.org
5 ** |_| |_| |_|\___/ \__,_|___|___/___/_| ftp.modssl.org
8 ** Apache API interface structures
11 /* ====================================================================
12 * The Apache Software License, Version 1.1
14 * Copyright (c) 2000-2003 The Apache Software Foundation. All rights
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions
21 * 1. Redistributions of source code must retain the above copyright
22 * notice, this list of conditions and the following disclaimer.
24 * 2. Redistributions in binary form must reproduce the above copyright
25 * notice, this list of conditions and the following disclaimer in
26 * the documentation and/or other materials provided with the
29 * 3. The end-user documentation included with the redistribution,
30 * if any, must include the following acknowledgment:
31 * "This product includes software developed by the
32 * Apache Software Foundation (http://www.apache.org/)."
33 * Alternately, this acknowledgment may appear in the software itself,
34 * if and wherever such third-party acknowledgments normally appear.
36 * 4. The names "Apache" and "Apache Software Foundation" must
37 * not be used to endorse or promote products derived from this
38 * software without prior written permission. For written
39 * permission, please contact apache@apache.org.
41 * 5. Products derived from this software may not be called "Apache",
42 * nor may "Apache" appear in their name, without prior written
43 * permission of the Apache Software Foundation.
45 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
46 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
47 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
48 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
49 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
50 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
51 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
52 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
53 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
54 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
55 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
57 * ====================================================================
65 * the table of configuration directives we provide
68 #define SSL_CMD_ALL(name, args, desc) \
69 AP_INIT_##args("SSL"#name, ssl_cmd_SSL##name, \
70 NULL, RSRC_CONF|OR_AUTHCFG, desc),
72 #define SSL_CMD_SRV(name, args, desc) \
73 AP_INIT_##args("SSL"#name, ssl_cmd_SSL##name, \
74 NULL, RSRC_CONF, desc),
76 #define SSL_CMD_DIR(name, type, args, desc) \
77 AP_INIT_##args("SSL"#name, ssl_cmd_SSL##name, \
78 NULL, OR_##type, desc),
80 #define AP_END_CMD { NULL }
82 const char ssl_valid_ssl_mutex_string[] =
83 "Valid SSLMutex mechanisms are: `none', `default'"
84 #if APR_HAS_FLOCK_SERIALIZE
85 ", `flock:/path/to/file'"
87 #if APR_HAS_FCNTL_SERIALIZE
88 ", `fcntl:/path/to/file'"
90 #if APR_HAS_SYSVSEM_SERIALIZE && !defined(PERCHILD_MPM)
93 #if APR_HAS_POSIXSEM_SERIALIZE
96 #if APR_HAS_PROC_PTHREAD_SERIALIZE
99 #if APR_HAS_FLOCK_SERIALIZE || APR_HAS_FCNTL_SERIALIZE
100 ", `file:/path/to/file'"
102 #if (APR_HAS_SYSVSEM_SERIALIZE && !defined(PERCHILD_MPM)) || APR_HAS_POSIXSEM_SERIALIZE
107 static const command_rec ssl_config_cmds[] = {
109 * Global (main-server) context configuration directives
111 SSL_CMD_SRV(Mutex, TAKE1, ssl_valid_ssl_mutex_string)
112 SSL_CMD_SRV(PassPhraseDialog, TAKE1,
113 "SSL dialog mechanism for the pass phrase query "
114 "(`builtin', `|/path/to/pipe_program`, "
115 "or `exec:/path/to/cgi_program')")
116 SSL_CMD_SRV(SessionCache, TAKE1,
117 "SSL Session Cache storage "
118 "(`none', `dbm:/path/to/file')")
119 #if defined(HAVE_OPENSSL_ENGINE_H) && defined(HAVE_ENGINE_INIT)
120 SSL_CMD_SRV(CryptoDevice, TAKE1,
121 "SSL external Crypto Device usage "
122 "(`builtin', `...')")
124 SSL_CMD_SRV(RandomSeed, TAKE23,
125 "SSL Pseudo Random Number Generator (PRNG) seeding source "
126 "(`startup|connect builtin|file:/path|exec:/path [bytes]')")
129 * Per-server context configuration directives
131 SSL_CMD_SRV(Engine, TAKE1,
132 "SSL switch for the protocol engine "
134 SSL_CMD_ALL(CipherSuite, TAKE1,
135 "Colon-delimited list of permitted SSL Ciphers "
136 "(`XXX:...:XXX' - see manual)")
137 SSL_CMD_SRV(CertificateFile, TAKE1,
138 "SSL Server Certificate file "
139 "(`/path/to/file' - PEM or DER encoded)")
140 SSL_CMD_SRV(CertificateKeyFile, TAKE1,
141 "SSL Server Private Key file "
142 "(`/path/to/file' - PEM or DER encoded)")
143 SSL_CMD_SRV(CertificateChainFile, TAKE1,
144 "SSL Server CA Certificate Chain file "
145 "(`/path/to/file' - PEM encoded)")
146 SSL_CMD_ALL(CACertificatePath, TAKE1,
147 "SSL CA Certificate path "
148 "(`/path/to/dir' - contains PEM encoded files)")
149 SSL_CMD_ALL(CACertificateFile, TAKE1,
150 "SSL CA Certificate file "
151 "(`/path/to/file' - PEM encoded)")
152 SSL_CMD_SRV(CARevocationPath, TAKE1,
153 "SSL CA Certificate Revocation List (CRL) path "
154 "(`/path/to/dir' - contains PEM encoded files)")
155 SSL_CMD_SRV(CARevocationFile, TAKE1,
156 "SSL CA Certificate Revocation List (CRL) file "
157 "(`/path/to/file' - PEM encoded)")
158 SSL_CMD_ALL(VerifyClient, TAKE1,
159 "SSL Client verify type "
160 "(`none', `optional', `require', `optional_no_ca')")
161 SSL_CMD_ALL(VerifyDepth, TAKE1,
162 "SSL Client verify depth "
163 "(`N' - number of intermediate certificates)")
164 SSL_CMD_SRV(SessionCacheTimeout, TAKE1,
165 "SSL Session Cache object lifetime "
166 "(`N' - number of seconds)")
167 SSL_CMD_SRV(Protocol, RAW_ARGS,
168 "Enable or disable various SSL protocols"
169 "(`[+-][SSLv2|SSLv3|TLSv1] ...' - see manual)")
172 * Proxy configuration for remote SSL connections
174 SSL_CMD_SRV(ProxyEngine, FLAG,
175 "SSL switch for the proxy protocol engine "
177 SSL_CMD_SRV(ProxyProtocol, RAW_ARGS,
178 "SSL Proxy: enable or disable SSL protocol flavors "
179 "(`[+-][SSLv2|SSLv3|TLSv1] ...' - see manual)")
180 SSL_CMD_SRV(ProxyCipherSuite, TAKE1,
181 "SSL Proxy: colon-delimited list of permitted SSL ciphers "
182 "(`XXX:...:XXX' - see manual)")
183 SSL_CMD_SRV(ProxyVerify, TAKE1,
184 "SSL Proxy: whether to verify the remote certificate "
186 SSL_CMD_SRV(ProxyVerifyDepth, TAKE1,
187 "SSL Proxy: maximum certificate verification depth "
188 "(`N' - number of intermediate certificates)")
189 SSL_CMD_SRV(ProxyCACertificateFile, TAKE1,
190 "SSL Proxy: file containing server certificates "
191 "(`/path/to/file' - PEM encoded certificates)")
192 SSL_CMD_SRV(ProxyCACertificatePath, TAKE1,
193 "SSL Proxy: directory containing server certificates "
194 "(`/path/to/dir' - contains PEM encoded certificates)")
195 SSL_CMD_SRV(ProxyCARevocationPath, TAKE1,
196 "SSL Proxy: CA Certificate Revocation List (CRL) path "
197 "(`/path/to/dir' - contains PEM encoded files)")
198 SSL_CMD_SRV(ProxyCARevocationFile, TAKE1,
199 "SSL Proxy: CA Certificate Revocation List (CRL) file "
200 "(`/path/to/file' - PEM encoded)")
201 SSL_CMD_SRV(ProxyMachineCertificateFile, TAKE1,
202 "SSL Proxy: file containing client certificates "
203 "(`/path/to/file' - PEM encoded certificates)")
204 SSL_CMD_SRV(ProxyMachineCertificatePath, TAKE1,
205 "SSL Proxy: directory containing client certificates "
206 "(`/path/to/dir' - contains PEM encoded certificates)")
209 * Per-directory context configuration directives
211 SSL_CMD_DIR(Options, OPTIONS, RAW_ARGS,
212 "Set one or more options to configure the SSL engine"
213 "(`[+-]option[=value] ...' - see manual)")
214 SSL_CMD_DIR(RequireSSL, AUTHCFG, NO_ARGS,
215 "Require the SSL protocol for the per-directory context "
217 SSL_CMD_DIR(Require, AUTHCFG, RAW_ARGS,
218 "Require a boolean expression to evaluate to true for granting access"
219 "(arbitrary complex boolean expression - see manual)")
221 /* Deprecated directives. */
222 AP_INIT_RAW_ARGS("SSLLog", ap_set_deprecated, NULL, OR_ALL,
223 "SSLLog directive is no longer supported - use ErrorLog."),
224 AP_INIT_RAW_ARGS("SSLLogLevel", ap_set_deprecated, NULL, OR_ALL,
225 "SSLLogLevel directive is no longer supported - use LogLevel."),
231 * the various processing hooks
233 static apr_status_t ssl_cleanup_pre_config(void *data)
236 * Try to kill the internals of the SSL library.
239 #if OPENSSL_VERSION_NUMBER >= 0x00907001
240 /* Corresponds to OPENSSL_load_builtin_modules():
241 * XXX: borrowed from apps.h, but why not CONF_modules_free()
242 * which also invokes CONF_modules_finish()?
244 CONF_modules_unload(1);
247 /* Corresponds to SSL_library_init: */
249 #if HAVE_ENGINE_LOAD_BUILTIN_ENGINES
253 #if OPENSSL_VERSION_NUMBER >= 0x00907001
254 CRYPTO_cleanup_all_ex_data();
259 /* Don't call ERR_free_strings here; ERR_load_*_strings only
260 * actually load the error strings once per process due to static
261 * variable abuse in OpenSSL. */
264 * TODO: determine somewhere we can safely shove out diagnostics
265 * (when enabled) at this late stage in the game:
266 * CRYPTO_mem_leaks_fp(stderr);
271 static int ssl_hook_pre_config(apr_pool_t *pconf,
275 /* We must register the library in full, to ensure our configuration
276 * code can successfully test the SSL environment.
278 CRYPTO_malloc_init();
280 ERR_load_crypto_strings();
283 #if HAVE_ENGINE_LOAD_BUILTIN_ENGINES
284 ENGINE_load_builtin_engines();
287 #if OPENSSL_VERSION_NUMBER >= 0x00907001
288 OPENSSL_load_builtin_modules();
291 SSL_load_error_strings();
294 * Let us cleanup the ssl library when the module is unloaded
296 apr_pool_cleanup_register(pconf, NULL, ssl_cleanup_pre_config,
297 apr_pool_cleanup_null);
299 /* Register us to handle mod_log_config %c/%x variables */
300 ssl_var_log_config_register(pconf);
302 /* XXX: Register us to handle mod_status extensions that don't exist yet */
303 ssl_scache_status_register(pconf);
309 static SSLConnRec *ssl_init_connection_ctx(conn_rec *c)
311 SSLConnRec *sslconn = myConnConfig(c);
317 sslconn = apr_pcalloc(c->pool, sizeof(*sslconn));
319 myConnConfigSet(c, sslconn);
324 int ssl_proxy_enable(conn_rec *c)
326 SSLSrvConfigRec *sc = mySrvConfig(c->base_server);
328 SSLConnRec *sslconn = ssl_init_connection_ctx(c);
330 if (!sc->proxy_enabled) {
331 ap_log_error(APLOG_MARK, APLOG_ERR, 0, c->base_server,
332 "SSL Proxy requested for %s but not enabled "
333 "[Hint: SSLProxyEngine]", sc->vhost_id);
338 sslconn->is_proxy = 1;
339 sslconn->disabled = 0;
344 int ssl_engine_disable(conn_rec *c)
346 SSLSrvConfigRec *sc = mySrvConfig(c->base_server);
354 sslconn = ssl_init_connection_ctx(c);
356 sslconn->disabled = 1;
361 int ssl_init_ssl_connection(conn_rec *c)
363 SSLSrvConfigRec *sc = mySrvConfig(c->base_server);
365 SSLConnRec *sslconn = myConnConfig(c);
370 * Seed the Pseudo Random Number Generator (PRNG)
372 ssl_rand_seed(c->base_server, c->pool, SSL_RSCTX_CONNECT, "");
375 sslconn = ssl_init_connection_ctx(c);
378 mctx = sslconn->is_proxy ? sc->proxy : sc->server;
381 * Create a new SSL connection with the configured server SSL context and
382 * attach this to the socket. Additionally we register this attachment
383 * so we can detach later.
385 if (!(ssl = SSL_new(mctx->ssl_ctx))) {
386 ap_log_error(APLOG_MARK, APLOG_ERR, 0, c->base_server,
387 "Unable to create a new SSL connection from the SSL "
389 ssl_log_ssl_error(APLOG_MARK, APLOG_ERR, c->base_server);
393 return DECLINED; /* XXX */
396 vhost_md5 = ap_md5_binary(c->pool, (unsigned char *)sc->vhost_id,
399 if (!SSL_set_session_id_context(ssl, (unsigned char *)vhost_md5,
400 APR_MD5_DIGESTSIZE*2))
402 ap_log_error(APLOG_MARK, APLOG_ERR, 0, c->base_server,
403 "Unable to set session id context to `%s'", vhost_md5);
404 ssl_log_ssl_error(APLOG_MARK, APLOG_ERR, c->base_server);
408 return DECLINED; /* XXX */
411 SSL_set_app_data(ssl, c);
412 SSL_set_app_data2(ssl, NULL); /* will be request_rec */
417 * Configure callbacks for SSL connection
419 SSL_set_tmp_rsa_callback(ssl, ssl_callback_TmpRSA);
420 SSL_set_tmp_dh_callback(ssl, ssl_callback_TmpDH);
422 SSL_set_verify_result(ssl, X509_V_OK);
424 ssl_io_filter_init(c, ssl);
429 static const char *ssl_hook_http_method(const request_rec *r)
431 SSLSrvConfigRec *sc = mySrvConfig(r->server);
433 if (sc->enabled == FALSE) {
440 static apr_port_t ssl_hook_default_port(const request_rec *r)
442 SSLSrvConfigRec *sc = mySrvConfig(r->server);
444 if (sc->enabled == FALSE) {
451 static int ssl_hook_pre_connection(conn_rec *c, void *csd)
453 SSLSrvConfigRec *sc = mySrvConfig(c->base_server);
454 SSLConnRec *sslconn = myConnConfig(c);
457 * Immediately stop processing if SSL is disabled for this connection
459 if (!(sc && (sc->enabled == TRUE ||
460 (sslconn && sslconn->is_proxy))))
469 sslconn = ssl_init_connection_ctx(c);
472 if (sslconn->disabled) {
477 * Remember the connection information for
478 * later access inside callback functions
481 ap_log_error(APLOG_MARK, APLOG_INFO, 0, c->base_server,
482 "Connection to child %ld established "
483 "(server %s, client %s)", c->id, sc->vhost_id,
484 c->remote_ip ? c->remote_ip : "unknown");
486 return ssl_init_ssl_connection(c);
490 static void ssl_hook_Insert_Filter(request_rec *r)
492 SSLSrvConfigRec *sc = mySrvConfig(r->server);
494 if (sc->enabled == UNSET) {
495 ap_add_output_filter("UPGRADE_FILTER", NULL, r, r->connection);
500 * the module registration phase
503 static void ssl_register_hooks(apr_pool_t *p)
505 ssl_io_filter_register(p);
507 ap_hook_pre_connection(ssl_hook_pre_connection,NULL,NULL, APR_HOOK_MIDDLE);
508 ap_hook_post_config (ssl_init_Module, NULL,NULL, APR_HOOK_MIDDLE);
509 ap_hook_http_method (ssl_hook_http_method, NULL,NULL, APR_HOOK_MIDDLE);
510 ap_hook_default_port (ssl_hook_default_port, NULL,NULL, APR_HOOK_MIDDLE);
511 ap_hook_pre_config (ssl_hook_pre_config, NULL,NULL, APR_HOOK_MIDDLE);
512 ap_hook_child_init (ssl_init_Child, NULL,NULL, APR_HOOK_MIDDLE);
513 ap_hook_translate_name(ssl_hook_Translate, NULL,NULL, APR_HOOK_MIDDLE);
514 ap_hook_check_user_id (ssl_hook_UserCheck, NULL,NULL, APR_HOOK_FIRST);
515 ap_hook_fixups (ssl_hook_Fixup, NULL,NULL, APR_HOOK_MIDDLE);
516 ap_hook_access_checker(ssl_hook_Access, NULL,NULL, APR_HOOK_MIDDLE);
517 ap_hook_auth_checker (ssl_hook_Auth, NULL,NULL, APR_HOOK_MIDDLE);
518 ap_hook_post_read_request(ssl_hook_ReadReq, NULL,NULL, APR_HOOK_MIDDLE);
519 ap_hook_insert_filter (ssl_hook_Insert_Filter, NULL,NULL, APR_HOOK_MIDDLE);
520 /* ap_hook_handler (ssl_hook_Upgrade, NULL,NULL, APR_HOOK_MIDDLE); */
524 APR_REGISTER_OPTIONAL_FN(ssl_proxy_enable);
525 APR_REGISTER_OPTIONAL_FN(ssl_engine_disable);
528 module AP_MODULE_DECLARE_DATA ssl_module = {
529 STANDARD20_MODULE_STUFF,
530 ssl_config_perdir_create, /* create per-dir config structures */
531 ssl_config_perdir_merge, /* merge per-dir config structures */
532 ssl_config_server_create, /* create per-server config structures */
533 ssl_config_server_merge, /* merge per-server config structures */
534 ssl_config_cmds, /* table of configuration directives */
535 ssl_register_hooks /* register hooks */