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-2001 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, NULL, RSRC_CONF|OR_AUTHCFG, desc),
70 #define SSL_CMD_SRV(name, args, desc) \
71 AP_INIT_##args("SSL"#name, ssl_cmd_SSL##name, NULL, RSRC_CONF, desc),
72 #define SSL_CMD_DIR(name, type, args, desc) \
73 AP_INIT_##args("SSL"#name, ssl_cmd_SSL##name, NULL, OR_##type, desc),
74 #define AP_END_CMD { NULL }
76 static const command_rec ssl_config_cmds[] = {
79 * Global (main-server) context configuration directives
81 SSL_CMD_SRV(Mutex, TAKE1,
82 "SSL lock for handling internal mutual exclusions "
83 "(`none', `file:/path/to/file')")
84 SSL_CMD_SRV(PassPhraseDialog, TAKE1,
85 "SSL dialog mechanism for the pass phrase query "
86 "(`builtin', `exec:/path/to/program')")
87 SSL_CMD_SRV(SessionCache, TAKE1,
88 "SSL Session Cache storage "
89 "(`none', `dbm:/path/to/file')")
90 #ifdef SSL_EXPERIMENTAL_ENGINE
91 SSL_CMD_SRV(CryptoDevice, TAKE1,
92 "SSL external Crypto Device usage "
95 SSL_CMD_SRV(RandomSeed, TAKE23,
96 "SSL Pseudo Random Number Generator (PRNG) seeding source "
97 "(`startup|connect builtin|file:/path|exec:/path [bytes]')")
100 * Per-server context configuration directives
102 SSL_CMD_SRV(Engine, FLAG,
103 "SSL switch for the protocol engine "
105 SSL_CMD_ALL(CipherSuite, TAKE1,
106 "Colon-delimited list of permitted SSL Ciphers "
107 "(`XXX:...:XXX' - see manual)")
108 SSL_CMD_SRV(CertificateFile, TAKE1,
109 "SSL Server Certificate file "
110 "(`/path/to/file' - PEM or DER encoded)")
111 SSL_CMD_SRV(CertificateKeyFile, TAKE1,
112 "SSL Server Private Key file "
113 "(`/path/to/file' - PEM or DER encoded)")
114 SSL_CMD_SRV(CertificateChainFile, TAKE1,
115 "SSL Server CA Certificate Chain file "
116 "(`/path/to/file' - PEM encoded)")
117 #ifdef SSL_EXPERIMENTAL_PERDIRCA
118 SSL_CMD_ALL(CACertificatePath, TAKE1,
119 "SSL CA Certificate path "
120 "(`/path/to/dir' - contains PEM encoded files)")
121 SSL_CMD_ALL(CACertificateFile, TAKE1,
122 "SSL CA Certificate file "
123 "(`/path/to/file' - PEM encoded)")
125 SSL_CMD_SRV(CACertificatePath, TAKE1,
126 "SSL CA Certificate path "
127 "(`/path/to/dir' - contains PEM encoded files)")
128 SSL_CMD_SRV(CACertificateFile, TAKE1,
129 "SSL CA Certificate file "
130 "(`/path/to/file' - PEM encoded)")
132 SSL_CMD_SRV(CARevocationPath, TAKE1,
133 "SSL CA Certificate Revocation List (CRL) path "
134 "(`/path/to/dir' - contains PEM encoded files)")
135 SSL_CMD_SRV(CARevocationFile, TAKE1,
136 "SSL CA Certificate Revocation List (CRL) file "
137 "(`/path/to/file' - PEM encoded)")
138 SSL_CMD_ALL(VerifyClient, TAKE1,
139 "SSL Client verify type "
140 "(`none', `optional', `require', `optional_no_ca')")
141 SSL_CMD_ALL(VerifyDepth, TAKE1,
142 "SSL Client verify depth "
143 "(`N' - number of intermediate certificates)")
144 SSL_CMD_SRV(SessionCacheTimeout, TAKE1,
145 "SSL Session Cache object lifetime "
146 "(`N' - number of seconds)")
147 SSL_CMD_SRV(Log, TAKE1,
148 "SSL logfile for SSL-related messages "
149 "(`/path/to/file', `|/path/to/program')")
150 SSL_CMD_SRV(LogLevel, TAKE1,
151 "SSL logfile verbosity level "
152 "(`none', `error', `warn', `info', `debug')")
153 SSL_CMD_SRV(Protocol, RAW_ARGS,
154 "Enable or disable various SSL protocols"
155 "(`[+-][SSLv2|SSLv3|TLSv1] ...' - see manual)")
157 #ifdef SSL_EXPERIMENTAL_PROXY
159 * Proxy configuration for remote SSL connections
161 SSL_CMD_SRV(ProxyProtocol, RAW_ARGS,
162 "SSL Proxy: enable or disable SSL protocol flavors "
163 "(`[+-][SSLv2|SSLv3|TLSv1] ...' - see manual)")
164 SSL_CMD_SRV(ProxyCipherSuite, TAKE1,
165 "SSL Proxy: colon-delimited list of permitted SSL ciphers "
166 "(`XXX:...:XXX' - see manual)")
167 SSL_CMD_SRV(ProxyVerify, FLAG,
168 "SSL Proxy: whether to verify the remote certificate "
170 SSL_CMD_SRV(ProxyVerifyDepth, TAKE1,
171 "SSL Proxy: maximum certificate verification depth "
172 "(`N' - number of intermediate certificates)")
173 SSL_CMD_SRV(ProxyCACertificateFile, TAKE1,
174 "SSL Proxy: file containing server certificates "
175 "(`/path/to/file' - PEM encoded certificates)")
176 SSL_CMD_SRV(ProxyCACertificatePath, TAKE1,
177 "SSL Proxy: directory containing server certificates "
178 "(`/path/to/dir' - contains PEM encoded certificates)")
179 SSL_CMD_SRV(ProxyMachineCertificateFile, TAKE1,
180 "SSL Proxy: file containing client certificates "
181 "(`/path/to/file' - PEM encoded certificates)")
182 SSL_CMD_SRV(ProxyMachineCertificatePath, TAKE1,
183 "SSL Proxy: directory containing client certificates "
184 "(`/path/to/dir' - contains PEM encoded certificates)")
188 * Per-directory context configuration directives
190 SSL_CMD_DIR(Options, OPTIONS, RAW_ARGS,
191 "Set one or more options to configure the SSL engine"
192 "(`[+-]option[=value] ...' - see manual)")
193 SSL_CMD_DIR(RequireSSL, AUTHCFG, NO_ARGS,
194 "Require the SSL protocol for the per-directory context "
196 SSL_CMD_DIR(Require, AUTHCFG, RAW_ARGS,
197 "Require a boolean expression to evaluate to true for granting access"
198 "(arbitrary complex boolean expression - see manual)")
204 * the various processing hooks
207 static void ssl_hook_pre_config(
208 apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp)
210 /* Register us to handle mod_log_config %c/%x variables */
211 ssl_var_log_config_register(pconf);
213 /* XXX: Register us to handle mod_proxy extensions that don't exist yet */
214 ssl_ext_proxy_register(pconf);
215 /* XXX: Register us to handle mod_status extensions that don't exist yet */
216 ssl_scache_status_register(pconf);
220 static int ssl_hook_pre_connection(conn_rec *c)
222 SSLSrvConfigRec *sc = mySrvConfig(c->base_server);
225 unsigned char *cpVHostID;
231 apr_table_setn(c->notes, "ssl", NULL);
234 * Immediately stop processing if SSL is disabled for this connection
236 if (sc == NULL || !sc->bEnabled)
240 * Remember the connection information for
241 * later access inside callback functions
243 cpVHostID = (unsigned char *)ssl_util_vhostid(c->pool,c->base_server);
244 ssl_log(c->base_server, SSL_LOG_INFO, "Connection to child %d established "
245 "(server %s, client %s)", c->id, cpVHostID,
246 c->remote_ip != NULL ? c->remote_ip : "unknown");
249 * Seed the Pseudo Random Number Generator (PRNG)
251 ssl_rand_seed(c->base_server, c->pool, SSL_RSCTX_CONNECT, "");
254 * Create a new SSL connection with the configured server SSL context and
255 * attach this to the socket. Additionally we register this attachment
256 * so we can detach later.
258 if ((ssl = SSL_new(sc->pSSLCtx)) == NULL) {
259 ssl_log(c->base_server, SSL_LOG_ERROR|SSL_ADD_SSLERR,
260 "Unable to create a new SSL connection from the SSL context");
261 apr_table_setn(c->notes, "ssl", NULL);
263 return DECLINED; /* XXX */
266 cpVHostMD5 = ap_md5(c->pool, cpVHostID);
267 if (!SSL_set_session_id_context(ssl, (unsigned char *)cpVHostMD5,
268 strlen(cpVHostMD5))) {
269 ssl_log(c->base_server, SSL_LOG_ERROR|SSL_ADD_SSLERR,
270 "Unable to set session id context to `%s'", cpVHostMD5);
271 apr_table_setn(c->notes, "ssl", NULL);
273 return DECLINED; /* XXX */
275 SSL_set_app_data(ssl, c);
276 apctx = apr_table_make(c->pool, AP_CTX_MAX_ENTRIES);
277 apr_table_setn(apctx, "ssl::request_rec", NULL);
278 apr_table_setn(apctx, "ssl::verify::depth", AP_CTX_NUM2PTR(0));
279 SSL_set_app_data2(ssl, apctx);
281 apr_table_setn(c->notes, "ssl", (const char *)ssl);
284 * Configure callbacks for SSL connection
286 SSL_set_tmp_rsa_callback(ssl, ssl_callback_TmpRSA);
287 SSL_set_tmp_dh_callback(ssl, ssl_callback_TmpDH);
290 * Predefine some client verification results
292 apr_table_setn(c->notes, "ssl::client::dn", NULL);
293 apr_table_setn(c->notes, "ssl::verify::error", NULL);
294 apr_table_setn(c->notes, "ssl::verify::info", NULL);
295 SSL_set_verify_result(ssl, X509_V_OK);
298 * We have to manage a I/O timeout ourself, because Apache
299 * does it the first time when reading the request, but we're
300 * working some time before this happens.
302 ssl_util_setmodconfig(c->base_server, "ssl::handshake::timeout", (void *)FALSE);
304 ssl_io_filter_init(c, ssl);
309 static apr_status_t ssl_abort(SSLFilterRec *pRec, conn_rec *c)
312 * try to gracefully shutdown the connection:
313 * - send an own shutdown message (be gracefully)
314 * - don't wait for peer's shutdown message (deadloop)
315 * - kick away the SSL stuff immediately
316 * - block the socket, so Apache cannot operate any more
319 SSL_set_shutdown(pRec->pssl, SSL_RECEIVED_SHUTDOWN);
320 SSL_smart_shutdown(pRec->pssl);
321 SSL_free(pRec->pssl);
322 pRec->pssl = NULL; /* so filters know we've been shutdown */
323 apr_table_setn(c->notes, "ssl", NULL);
330 * The hook is NOT registered with ap_hook_process_connection. Instead, it is
331 * called manually from the churn () before it tries to read any data.
332 * There is some problem if I accept conn_rec *. Still investigating..
333 * Adv. if conn_rec * can be accepted is we can hook this function using the
334 * ap_hook_process_connection hook.
336 int ssl_hook_process_connection(SSLFilterRec *pRec)
341 conn_rec *c = (conn_rec*)SSL_get_app_data (pRec->pssl);
342 SSLSrvConfigRec *sc = mySrvConfig(c->base_server);
345 if (!SSL_is_init_finished(pRec->pssl))
347 if ((n = SSL_accept(pRec->pssl)) <= 0) {
349 if ((err = SSL_get_error(pRec->pssl, n)) == SSL_ERROR_ZERO_RETURN) {
351 * The case where the connection was closed before any data
352 * was transferred. That's not a real error and can occur
353 * sporadically with some clients.
355 ssl_log(c->base_server, SSL_LOG_INFO,
356 "SSL handshake stopped: connection was closed");
358 else if (err == SSL_ERROR_WANT_READ) {
360 * This is in addition to what was present earlier. It is
361 * borrowed from openssl_state_machine.c [mod_tls].
364 return SSL_ERROR_WANT_READ;
366 else if (ERR_GET_REASON(ERR_peek_error()) == SSL_R_HTTP_REQUEST) {
368 * The case where OpenSSL has recognized a HTTP request:
369 * This means the client speaks plain HTTP on our HTTPS port.
370 * Hmmmm... Punt this out of here after removing our output
373 ap_remove_output_filter(pRec->pOutputFilter);
374 return HTTP_BAD_REQUEST;
376 else if (ssl_util_getmodconfig_ssl(pRec->pssl, "ssl::handshake::timeout")
378 ssl_log(c->base_server, SSL_LOG_ERROR,
379 "SSL handshake timed out (client %s, server %s)",
380 c->remote_ip != NULL ? c->remote_ip : "unknown",
381 ssl_util_vhostid(c->pool,c->base_server));
383 else if ((SSL_get_error(pRec->pssl, n) == SSL_ERROR_SYSCALL)
384 && (errno != EINTR)) {
386 ssl_log(c->base_server,
387 SSL_LOG_ERROR|SSL_ADD_SSLERR|SSL_ADD_ERRNO,
388 "SSL handshake interrupted by system "
389 "[Hint: Stop button pressed in browser?!]");
391 ssl_log(c->base_server,
392 SSL_LOG_INFO|SSL_ADD_SSLERR|SSL_ADD_ERRNO,
393 "Spurious SSL handshake interrupt [Hint: "
394 "Usually just one of those OpenSSL confusions!?]");
398 * Ok, anything else is a fatal error
400 ssl_log(c->base_server,
401 SSL_LOG_ERROR|SSL_ADD_SSLERR|SSL_ADD_ERRNO,
402 "SSL handshake failed (server %s, client %s)",
403 ssl_util_vhostid(c->pool,c->base_server),
404 c->remote_ip != NULL ? c->remote_ip : "unknown");
406 return ssl_abort(pRec, c);
410 * Check for failed client authentication
412 verify_result = SSL_get_verify_result(pRec->pssl);
414 if (verify_result != X509_V_OK ||
415 ((cp = (char *)apr_table_get(c->notes,
416 "ssl::verify::error")) != NULL))
418 if (ssl_verify_error_is_optional(verify_result) &&
419 (sc->nVerifyClient == SSL_CVERIFY_OPTIONAL_NO_CA))
421 /* leaving this log message as an error for the moment,
422 * according to the mod_ssl docs:
423 * "level optional_no_ca is actually against the idea
424 * of authentication (but can be used to establish
425 * SSL test pages, etc.)"
426 * optional_no_ca doesn't appear to work as advertised
429 ssl_log(c->base_server, SSL_LOG_ERROR|SSL_ADD_SSLERR,
430 "SSL client authentication failed, "
431 "accepting certificate based on "
432 "\"SSLVerifyClient optional_no_ca\" configuration");
437 X509_verify_cert_error_string(verify_result);
438 ssl_log(c->base_server, SSL_LOG_ERROR|SSL_ADD_SSLERR,
439 "SSL client authentication failed: %s",
440 cp ? cp : verror ? verror : "unknown");
441 return ssl_abort(pRec, c);
446 * Remember the peer certificate's DN
448 if ((xs = SSL_get_peer_certificate(pRec->pssl)) != NULL) {
449 cp = X509_NAME_oneline(X509_get_subject_name(xs), NULL, 0);
450 apr_table_setn(c->notes,"ssl::client::dn",apr_pstrdup(c->pool, cp));
455 * Make really sure that when a peer certificate
456 * is required we really got one... (be paranoid)
458 if (sc->nVerifyClient == SSL_CVERIFY_REQUIRE
459 && apr_table_get(c->notes, "ssl::client::dn") == NULL) {
460 ssl_log(c->base_server, SSL_LOG_ERROR,
461 "No acceptable peer certificate available");
462 return ssl_abort(pRec, c);
468 static const char *ssl_hook_http_method (const request_rec *r)
470 SSLSrvConfigRec *sc = mySrvConfig(r->server);
472 if (sc->bEnabled == FALSE)
478 static apr_port_t ssl_hook_default_port (const request_rec *r)
480 SSLSrvConfigRec *sc = mySrvConfig(r->server);
482 if (sc->bEnabled == FALSE)
488 * the module registration phase
491 static void ssl_register_hooks(apr_pool_t *p)
493 ssl_io_filter_register(p);
495 ap_hook_pre_connection(ssl_hook_pre_connection,NULL,NULL, APR_HOOK_MIDDLE);
496 ap_hook_post_config (ssl_init_Module, NULL,NULL, APR_HOOK_MIDDLE);
497 ap_hook_http_method (ssl_hook_http_method, NULL,NULL, APR_HOOK_MIDDLE);
498 ap_hook_default_port (ssl_hook_default_port, NULL,NULL, APR_HOOK_MIDDLE);
499 ap_hook_handler (ssl_hook_Handler, NULL,NULL, APR_HOOK_MIDDLE);
500 ap_hook_pre_config (ssl_hook_pre_config, NULL,NULL, APR_HOOK_MIDDLE);
501 ap_hook_child_init (ssl_init_Child, NULL,NULL, APR_HOOK_MIDDLE);
502 ap_hook_translate_name(ssl_hook_Translate, NULL,NULL, APR_HOOK_MIDDLE);
503 ap_hook_check_user_id (ssl_hook_UserCheck, NULL,NULL, APR_HOOK_FIRST);
504 ap_hook_fixups (ssl_hook_Fixup, NULL,NULL, APR_HOOK_MIDDLE);
505 ap_hook_access_checker(ssl_hook_Access, NULL,NULL, APR_HOOK_MIDDLE);
506 ap_hook_auth_checker (ssl_hook_Auth, NULL,NULL, APR_HOOK_MIDDLE);
507 ap_hook_post_read_request(ssl_hook_ReadReq, NULL,NULL, APR_HOOK_MIDDLE);
512 module AP_MODULE_DECLARE_DATA ssl_module = {
513 STANDARD20_MODULE_STUFF,
514 ssl_config_perdir_create, /* create per-dir config structures */
515 ssl_config_perdir_merge, /* merge per-dir config structures */
516 ssl_config_server_create, /* create per-server config structures */
517 ssl_config_server_merge, /* merge per-server config structures */
518 ssl_config_cmds, /* table of configuration directives */
519 ssl_register_hooks /* register hooks */