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 <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 50const 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 75static 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_SRV(FIPS, FLAG, 103 "Enable FIPS-140 mode " 104 "(`on', `off')") 105 SSL_CMD_SRV(AllowEmptyFragments, FLAG, 106 "Allow empty fragments " 107 "(`on', `off')") 108 SSL_CMD_ALL(CipherSuite, TAKE1, 109 "Colon-delimited list of permitted SSL Ciphers " 110 "(`XXX:...:XXX' - see manual)") 111 SSL_CMD_SRV(CertificateFile, TAKE1, 112 "SSL Server Certificate file " 113 "(`/path/to/file' - PEM or DER encoded)") 114 SSL_CMD_SRV(CertificateKeyFile, TAKE1, 115 "SSL Server Private Key file " 116 "(`/path/to/file' - PEM or DER encoded)") 117 SSL_CMD_SRV(CertificateChainFile, TAKE1, 118 "SSL Server CA Certificate Chain file " 119 "(`/path/to/file' - PEM encoded)") 120 SSL_CMD_ALL(CACertificatePath, TAKE1, 121 "SSL CA Certificate path " 122 "(`/path/to/dir' - contains PEM encoded files)") 123 SSL_CMD_ALL(CACertificateFile, TAKE1, 124 "SSL CA Certificate file " 125 "(`/path/to/file' - PEM encoded)") 126 SSL_CMD_SRV(CADNRequestPath, TAKE1, 127 "SSL CA Distinguished Name path " 128 "(`/path/to/dir' - symlink hashes to PEM of acceptable CA names to request)") 129 SSL_CMD_SRV(CADNRequestFile, TAKE1, 130 "SSL CA Distinguished Name file " 131 "(`/path/to/file' - PEM encoded to derive acceptable CA names to request)") 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#ifdef OPENSSL_NO_SSL2 148#define SSLv2_PROTO_PREFIX "" 149#else 150#define SSLv2_PROTO_PREFIX "SSLv2|" 151#endif 152#ifdef HAVE_TLSV1_X 153#define SSL_PROTOCOLS SSLv2_PROTO_PREFIX "SSLv3|TLSv1|TLSv1.1|TLSv1.2" 154#else 155#define SSL_PROTOCOLS SSLv2_PROTO_PREFIX "SSLv3|TLSv1" 156#endif 157 SSL_CMD_SRV(Protocol, RAW_ARGS, 158 "Enable or disable various SSL protocols " 159 "('[+-][" SSL_PROTOCOLS "] ...' - see manual)") 160 SSL_CMD_SRV(HonorCipherOrder, FLAG, 161 "Use the server's cipher ordering preference") 162 SSL_CMD_SRV(Compression, FLAG, 163 "Enable SSL level compression" 164 "(`on', `off')") 165 SSL_CMD_SRV(InsecureRenegotiation, FLAG, 166 "Enable support for insecure renegotiation") 167 SSL_CMD_ALL(UserName, TAKE1, 168 "Set user name to SSL variable value") 169 SSL_CMD_SRV(StrictSNIVHostCheck, FLAG, 170 "Strict SNI virtual host checking") 171 172 /* 173 * Proxy configuration for remote SSL connections 174 */ 175 SSL_CMD_SRV(ProxyEngine, FLAG, 176 "SSL switch for the proxy protocol engine " 177 "(`on', `off')") 178 SSL_CMD_SRV(ProxyProtocol, RAW_ARGS, 179 "SSL Proxy: enable or disable SSL protocol flavors " 180 "('[+-][" SSL_PROTOCOLS "] ...' - see manual)") 181 SSL_CMD_SRV(ProxyCipherSuite, TAKE1, 182 "SSL Proxy: colon-delimited list of permitted SSL ciphers " 183 "(`XXX:...:XXX' - see manual)") 184 SSL_CMD_SRV(ProxyVerify, TAKE1, 185 "SSL Proxy: whether to verify the remote certificate " 186 "(`on' or `off')") 187 SSL_CMD_SRV(ProxyVerifyDepth, TAKE1, 188 "SSL Proxy: maximum certificate verification depth " 189 "(`N' - number of intermediate certificates)") 190 SSL_CMD_SRV(ProxyCACertificateFile, TAKE1, 191 "SSL Proxy: file containing server certificates " 192 "(`/path/to/file' - PEM encoded certificates)") 193 SSL_CMD_SRV(ProxyCACertificatePath, TAKE1, 194 "SSL Proxy: directory containing server certificates " 195 "(`/path/to/dir' - contains PEM encoded certificates)") 196 SSL_CMD_SRV(ProxyCARevocationPath, TAKE1, 197 "SSL Proxy: CA Certificate Revocation List (CRL) path " 198 "(`/path/to/dir' - contains PEM encoded files)") 199 SSL_CMD_SRV(ProxyCARevocationFile, TAKE1, 200 "SSL Proxy: CA Certificate Revocation List (CRL) file " 201 "(`/path/to/file' - PEM encoded)") 202 SSL_CMD_SRV(ProxyMachineCertificateFile, TAKE1, 203 "SSL Proxy: file containing client certificates " 204 "(`/path/to/file' - PEM encoded certificates)") 205 SSL_CMD_SRV(ProxyMachineCertificatePath, TAKE1, 206 "SSL Proxy: directory containing client certificates " 207 "(`/path/to/dir' - contains PEM encoded certificates)") 208 SSL_CMD_SRV(ProxyMachineCertificateChainFile, TAKE1, 209 "SSL Proxy: file containing issuing certificates " 210 "of the client certificate " 211 "(`/path/to/file' - PEM encoded certificates)") 212 SSL_CMD_SRV(ProxyCheckPeerExpire, FLAG, 213 "SSL Proxy: check the peers certificate expiration date") 214 SSL_CMD_SRV(ProxyCheckPeerCN, FLAG, 215 "SSL Proxy: check the peers certificate CN") 216 217 /* 218 * Per-directory context configuration directives 219 */ 220 SSL_CMD_DIR(Options, OPTIONS, RAW_ARGS, 221 "Set one or more options to configure the SSL engine" 222 "(`[+-]option[=value] ...' - see manual)") 223 SSL_CMD_DIR(RequireSSL, AUTHCFG, NO_ARGS, 224 "Require the SSL protocol for the per-directory context " 225 "(no arguments)") 226 SSL_CMD_DIR(Require, AUTHCFG, RAW_ARGS, 227 "Require a boolean expression to evaluate to true for granting access" 228 "(arbitrary complex boolean expression - see manual)") 229 SSL_CMD_DIR(RenegBufferSize, AUTHCFG, TAKE1, 230 "Configure the amount of memory that will be used for buffering the " 231 "request body if a per-location SSL renegotiation is required due to " 232 "changed access control requirements") 233 234 /* Deprecated directives. */ 235 AP_INIT_RAW_ARGS("SSLLog", ap_set_deprecated, NULL, OR_ALL, 236 "SSLLog directive is no longer supported - use ErrorLog."), 237 AP_INIT_RAW_ARGS("SSLLogLevel", ap_set_deprecated, NULL, OR_ALL, 238 "SSLLogLevel directive is no longer supported - use LogLevel."), 239 240 AP_END_CMD 241}; 242 243/* 244 * the various processing hooks 245 */ 246static apr_status_t ssl_cleanup_pre_config(void *data) 247{ 248 /* 249 * Try to kill the internals of the SSL library. 250 */ 251#ifdef HAVE_OPENSSL 252#if OPENSSL_VERSION_NUMBER >= 0x00907001 253 /* Corresponds to OPENSSL_load_builtin_modules(): 254 * XXX: borrowed from apps.h, but why not CONF_modules_free() 255 * which also invokes CONF_modules_finish()? 256 */ 257 CONF_modules_unload(1); 258#endif 259#endif 260 /* Corresponds to SSL_library_init: */ 261 EVP_cleanup(); 262#if HAVE_ENGINE_LOAD_BUILTIN_ENGINES 263 ENGINE_cleanup(); 264#endif 265 ERR_remove_state(0); 266 267 /* Don't call ERR_free_strings here; ERR_load_*_strings only 268 * actually load the error strings once per process due to static 269 * variable abuse in OpenSSL. */ 270 271 /* Also don't call CRYPTO_cleanup_all_ex_data here; any registered 272 * ex_data indices may have been cached in static variables in 273 * OpenSSL; removing them may cause havoc. Notably, with OpenSSL 274 * versions >= 0.9.8f, COMP_CTX cleanups would not be run, which 275 * could result in a per-connection memory leak (!). */ 276 277 /* 278 * TODO: determine somewhere we can safely shove out diagnostics 279 * (when enabled) at this late stage in the game: 280 * CRYPTO_mem_leaks_fp(stderr); 281 */ 282 return APR_SUCCESS; 283} 284 285static int ssl_hook_pre_config(apr_pool_t *pconf, 286 apr_pool_t *plog, 287 apr_pool_t *ptemp) 288{ 289 /* We must register the library in full, to ensure our configuration 290 * code can successfully test the SSL environment. 291 */ 292 CRYPTO_malloc_init(); 293#ifdef HAVE_OPENSSL 294 ERR_load_crypto_strings(); 295#endif 296 SSL_load_error_strings(); 297 SSL_library_init(); 298#if HAVE_ENGINE_LOAD_BUILTIN_ENGINES 299 ENGINE_load_builtin_engines(); 300#endif 301#ifdef HAVE_OPENSSL 302 OpenSSL_add_all_algorithms(); 303#if OPENSSL_VERSION_NUMBER >= 0x00907001 304 OPENSSL_load_builtin_modules(); 305#endif 306#endif 307 308 /* 309 * Let us cleanup the ssl library when the module is unloaded 310 */ 311 apr_pool_cleanup_register(pconf, NULL, ssl_cleanup_pre_config, 312 apr_pool_cleanup_null); 313 314 /* Register us to handle mod_log_config %c/%x variables */ 315 ssl_var_log_config_register(pconf); 316 317 /* Register to handle mod_status status page generation */ 318 ssl_scache_status_register(pconf); 319 320 return OK; 321} 322 323static SSLConnRec *ssl_init_connection_ctx(conn_rec *c) 324{ 325 SSLConnRec *sslconn = myConnConfig(c); 326 327 if (sslconn) { 328 return sslconn; 329 } 330 331 sslconn = apr_pcalloc(c->pool, sizeof(*sslconn)); 332 333 sslconn->server = c->base_server; 334 335 myConnConfigSet(c, sslconn); 336 337 return sslconn; 338} 339 340int ssl_proxy_enable(conn_rec *c) 341{ 342 SSLSrvConfigRec *sc; 343 344 SSLConnRec *sslconn = ssl_init_connection_ctx(c); 345 sc = mySrvConfig(sslconn->server); 346 347 if (!sc->proxy_enabled) { 348 ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, 349 "SSL Proxy requested for %s but not enabled " 350 "[Hint: SSLProxyEngine]", sc->vhost_id); 351 352 return 0; 353 } 354 355 sslconn->is_proxy = 1; 356 sslconn->disabled = 0; 357 358 return 1; 359} 360 361int ssl_engine_disable(conn_rec *c) 362{ 363 SSLSrvConfigRec *sc; 364 365 SSLConnRec *sslconn = myConnConfig(c); 366 367 if (sslconn) { 368 sc = mySrvConfig(sslconn->server); 369 } 370 else { 371 sc = mySrvConfig(c->base_server); 372 } 373 if (sc->enabled == SSL_ENABLED_FALSE) { 374 return 0; 375 } 376 377 sslconn = ssl_init_connection_ctx(c); 378 379 sslconn->disabled = 1; 380 381 return 1; 382} 383 384int ssl_init_ssl_connection(conn_rec *c) 385{ 386 SSLSrvConfigRec *sc; 387 SSL *ssl; 388 SSLConnRec *sslconn = myConnConfig(c); 389 char *vhost_md5; 390 modssl_ctx_t *mctx; 391 server_rec *server; 392 393 if (!sslconn) { 394 sslconn = ssl_init_connection_ctx(c); 395 } 396 server = sslconn->server; 397 sc = mySrvConfig(server); 398 399 /* 400 * Seed the Pseudo Random Number Generator (PRNG) 401 */ 402 ssl_rand_seed(server, c->pool, SSL_RSCTX_CONNECT, ""); 403 404 mctx = sslconn->is_proxy ? sc->proxy : sc->server; 405 406 /* 407 * Create a new SSL connection with the configured server SSL context and 408 * attach this to the socket. Additionally we register this attachment 409 * so we can detach later. 410 */ 411 if (!(ssl = SSL_new(mctx->ssl_ctx))) { 412 ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, 413 "Unable to create a new SSL connection from the SSL " 414 "context"); 415 ssl_log_ssl_error(APLOG_MARK, APLOG_ERR, server); 416 417 c->aborted = 1; 418 419 return DECLINED; /* XXX */ 420 } 421 422 vhost_md5 = ap_md5_binary(c->pool, (unsigned char *)sc->vhost_id, 423 sc->vhost_id_len); 424 425 if (!SSL_set_session_id_context(ssl, (unsigned char *)vhost_md5, 426 APR_MD5_DIGESTSIZE*2)) 427 { 428 ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, 429 "Unable to set session id context to `%s'", vhost_md5); 430 ssl_log_ssl_error(APLOG_MARK, APLOG_ERR, server); 431 432 c->aborted = 1; 433 434 return DECLINED; /* XXX */ 435 } 436 437 SSL_set_app_data(ssl, c); 438 SSL_set_app_data2(ssl, NULL); /* will be request_rec */ 439 440 sslconn->ssl = ssl; 441 442 /* 443 * Configure callbacks for SSL connection 444 */ 445 SSL_set_tmp_rsa_callback(ssl, ssl_callback_TmpRSA); 446 SSL_set_tmp_dh_callback(ssl, ssl_callback_TmpDH); 447#ifndef OPENSSL_NO_EC 448 SSL_set_tmp_ecdh_callback(ssl, ssl_callback_TmpECDH); 449#endif 450 451 SSL_set_verify_result(ssl, X509_V_OK); 452 453 ssl_io_filter_init(c, ssl); 454 455 return APR_SUCCESS; 456} 457 458static const char *ssl_hook_http_scheme(const request_rec *r) 459{ 460 SSLSrvConfigRec *sc = mySrvConfig(r->server); 461 462 if (sc->enabled == SSL_ENABLED_FALSE || sc->enabled == SSL_ENABLED_OPTIONAL) { 463 return NULL; 464 } 465 466 return "https"; 467} 468 469static apr_port_t ssl_hook_default_port(const request_rec *r) 470{ 471 SSLSrvConfigRec *sc = mySrvConfig(r->server); 472 473 if (sc->enabled == SSL_ENABLED_FALSE || sc->enabled == SSL_ENABLED_OPTIONAL) { 474 return 0; 475 } 476 477 return 443; 478} 479 480static int ssl_hook_pre_connection(conn_rec *c, void *csd) 481{ 482 SSLSrvConfigRec *sc; 483 SSLConnRec *sslconn = myConnConfig(c); 484 485 if (sslconn) { 486 sc = mySrvConfig(sslconn->server); 487 } 488 else { 489 sc = mySrvConfig(c->base_server); 490 } 491 /* 492 * Immediately stop processing if SSL is disabled for this connection 493 */ 494 if (!(sc && (sc->enabled == SSL_ENABLED_TRUE || 495 (sslconn && sslconn->is_proxy)))) 496 { 497 return DECLINED; 498 } 499 500 /* 501 * Create SSL context 502 */ 503 if (!sslconn) { 504 sslconn = ssl_init_connection_ctx(c); 505 } 506 507 if (sslconn->disabled) { 508 return DECLINED; 509 } 510 511 /* 512 * Remember the connection information for 513 * later access inside callback functions 514 */ 515 516 ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, c, 517 "Connection to child %ld established " 518 "(server %s)", c->id, sc->vhost_id); 519 520 return ssl_init_ssl_connection(c); 521} 522 523 524static void ssl_hook_Insert_Filter(request_rec *r) 525{ 526 SSLSrvConfigRec *sc = mySrvConfig(r->server); 527 528 if (sc->enabled == SSL_ENABLED_OPTIONAL) { 529 ap_add_output_filter("UPGRADE_FILTER", NULL, r, r->connection); 530 } 531} 532 533/* 534 * the module registration phase 535 */ 536 537static void ssl_register_hooks(apr_pool_t *p) 538{ 539 /* ssl_hook_ReadReq needs to use the BrowserMatch settings so must 540 * run after mod_setenvif's post_read_request hook. */ 541 static const char *pre_prr[] = { "mod_setenvif.c", NULL }; 542 543 ssl_io_filter_register(p); 544 545 ap_hook_pre_connection(ssl_hook_pre_connection,NULL,NULL, APR_HOOK_MIDDLE); 546 ap_hook_test_config (ssl_hook_ConfigTest, NULL,NULL, APR_HOOK_MIDDLE); 547 ap_hook_post_config (ssl_init_Module, NULL,NULL, APR_HOOK_MIDDLE); 548 ap_hook_http_scheme (ssl_hook_http_scheme, NULL,NULL, APR_HOOK_MIDDLE); 549 ap_hook_default_port (ssl_hook_default_port, NULL,NULL, APR_HOOK_MIDDLE); 550 ap_hook_pre_config (ssl_hook_pre_config, NULL,NULL, APR_HOOK_MIDDLE); 551 ap_hook_child_init (ssl_init_Child, NULL,NULL, APR_HOOK_MIDDLE); 552 ap_hook_check_user_id (ssl_hook_UserCheck, NULL,NULL, APR_HOOK_FIRST); 553 ap_hook_fixups (ssl_hook_Fixup, NULL,NULL, APR_HOOK_MIDDLE); 554 ap_hook_access_checker(ssl_hook_Access, NULL,NULL, APR_HOOK_MIDDLE); 555 ap_hook_auth_checker (ssl_hook_Auth, NULL,NULL, APR_HOOK_MIDDLE); 556 ap_hook_post_read_request(ssl_hook_ReadReq, pre_prr,NULL, APR_HOOK_MIDDLE); 557 ap_hook_insert_filter (ssl_hook_Insert_Filter, NULL,NULL, APR_HOOK_MIDDLE); 558/* ap_hook_handler (ssl_hook_Upgrade, NULL,NULL, APR_HOOK_MIDDLE); */ 559 560 ssl_var_register(p); 561 562 APR_REGISTER_OPTIONAL_FN(ssl_proxy_enable); 563 APR_REGISTER_OPTIONAL_FN(ssl_engine_disable); 564 565 APR_REGISTER_OPTIONAL_FN(ssl_extlist_by_oid); 566} 567 568module AP_MODULE_DECLARE_DATA ssl_module = { 569 STANDARD20_MODULE_STUFF, 570 ssl_config_perdir_create, /* create per-dir config structures */ 571 ssl_config_perdir_merge, /* merge per-dir config structures */ 572 ssl_config_server_create, /* create per-server config structures */ 573 ssl_config_server_merge, /* merge per-server config structures */ 574 ssl_config_cmds, /* table of configuration directives */ 575 ssl_register_hooks /* register hooks */ 576}; 577