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