diff options
Diffstat (limited to 'modules/ssl')
-rw-r--r-- | modules/ssl/mod_ssl.c | 8 | ||||
-rw-r--r-- | modules/ssl/ssl_engine_config.c | 161 | ||||
-rw-r--r-- | modules/ssl/ssl_engine_init.c | 773 | ||||
-rw-r--r-- | modules/ssl/ssl_engine_kernel.c | 89 | ||||
-rw-r--r-- | modules/ssl/ssl_engine_log.c | 10 | ||||
-rw-r--r-- | modules/ssl/ssl_engine_pphrase.c | 726 | ||||
-rw-r--r-- | modules/ssl/ssl_private.h | 111 | ||||
-rw-r--r-- | modules/ssl/ssl_scache.c | 12 | ||||
-rw-r--r-- | modules/ssl/ssl_util.c | 130 | ||||
-rw-r--r-- | modules/ssl/ssl_util_ocsp.c | 1 | ||||
-rw-r--r-- | modules/ssl/ssl_util_ssl.c | 68 | ||||
-rw-r--r-- | modules/ssl/ssl_util_ssl.h | 4 | ||||
-rw-r--r-- | modules/ssl/ssl_util_stapling.c | 10 |
13 files changed, 869 insertions, 1234 deletions
diff --git a/modules/ssl/mod_ssl.c b/modules/ssl/mod_ssl.c index f0499405..6e632a38 100644 --- a/modules/ssl/mod_ssl.c +++ b/modules/ssl/mod_ssl.c @@ -91,9 +91,6 @@ static const command_rec ssl_config_cmds[] = { SSL_CMD_SRV(CertificateChainFile, TAKE1, "SSL Server CA Certificate Chain file " "('/path/to/file' - PEM encoded)") - SSL_CMD_SRV(PKCS7CertificateFile, TAKE1, - "PKCS#7 file containing server certificate and chain" - " certificates ('/path/to/file' - PEM encoded)") #ifdef HAVE_TLS_SESSION_TICKETS SSL_CMD_SRV(SessionTicketKeyFile, TAKE1, "TLS session ticket encryption/decryption key file (RFC 5077) " @@ -266,6 +263,11 @@ static const command_rec ssl_config_cmds[] = { "SSL stapling option to Force the OCSP Stapling URL") #endif +#ifdef HAVE_SSL_CONF_CMD + SSL_CMD_SRV(OpenSSLConfCmd, TAKE2, + "OpenSSL configuration command") +#endif + /* Deprecated directives. */ AP_INIT_RAW_ARGS("SSLLog", ap_set_deprecated, NULL, OR_ALL, "SSLLog directive is no longer supported - use ErrorLog."), diff --git a/modules/ssl/ssl_engine_config.c b/modules/ssl/ssl_engine_config.c index f519151e..2dda6a95 100644 --- a/modules/ssl/ssl_engine_config.c +++ b/modules/ssl/ssl_engine_config.c @@ -66,7 +66,6 @@ SSLModConfigRec *ssl_config_global_create(server_rec *s) sizeof(ssl_randseed_t)); mc->tVHostKeys = apr_hash_make(pool); mc->tPrivateKey = apr_hash_make(pool); - mc->tPublicCert = apr_hash_make(pool); #if defined(HAVE_OPENSSL_ENGINE_H) && defined(HAVE_ENGINE_INIT) mc->szCryptoDevice = NULL; #endif @@ -98,7 +97,7 @@ BOOL ssl_config_global_isfixed(SSLModConfigRec *mc) ** _________________________________________________________________ */ -static void modssl_ctx_init(modssl_ctx_t *mctx) +static void modssl_ctx_init(modssl_ctx_t *mctx, apr_pool_t *p) { mctx->sc = NULL; /* set during module init */ @@ -116,7 +115,6 @@ static void modssl_ctx_init(modssl_ctx_t *mctx) mctx->pphrase_dialog_type = SSL_PPTYPE_UNSET; mctx->pphrase_dialog_path = NULL; - mctx->pkcs7 = NULL; mctx->cert_chain = NULL; mctx->crl_path = NULL; @@ -153,6 +151,13 @@ static void modssl_ctx_init(modssl_ctx_t *mctx) mctx->srp_unknown_user_seed = NULL; mctx->srp_vbase = NULL; #endif +#ifdef HAVE_SSL_CONF_CMD + mctx->ssl_ctx_config = SSL_CONF_CTX_new(); + SSL_CONF_CTX_set_flags(mctx->ssl_ctx_config, SSL_CONF_FLAG_FILE); + SSL_CONF_CTX_set_flags(mctx->ssl_ctx_config, SSL_CONF_FLAG_SERVER); + SSL_CONF_CTX_set_flags(mctx->ssl_ctx_config, SSL_CONF_FLAG_CERTIFICATE); + mctx->ssl_ctx_param = apr_array_make(p, 5, sizeof(ssl_ctx_param_t)); +#endif } static void modssl_ctx_init_proxy(SSLSrvConfigRec *sc, @@ -162,7 +167,7 @@ static void modssl_ctx_init_proxy(SSLSrvConfigRec *sc, mctx = sc->proxy = apr_palloc(p, sizeof(*sc->proxy)); - modssl_ctx_init(mctx); + modssl_ctx_init(mctx, p); mctx->pkp = apr_palloc(p, sizeof(*mctx->pkp)); @@ -180,11 +185,12 @@ static void modssl_ctx_init_server(SSLSrvConfigRec *sc, mctx = sc->server = apr_palloc(p, sizeof(*sc->server)); - modssl_ctx_init(mctx); + modssl_ctx_init(mctx, p); mctx->pks = apr_pcalloc(p, sizeof(*mctx->pks)); - /* mctx->pks->... certs/keys are set during module init */ + mctx->pks->cert_files = apr_array_make(p, 3, sizeof(char *)); + mctx->pks->key_files = apr_array_make(p, 3, sizeof(char *)); #ifdef HAVE_TLS_SESSION_TICKETS mctx->ticket_key = apr_pcalloc(p, sizeof(*mctx->ticket_key)); @@ -241,7 +247,8 @@ void *ssl_config_server_create(apr_pool_t *p, server_rec *s) #define cfgMergeBool(el) cfgMerge(el, UNSET) #define cfgMergeInt(el) cfgMerge(el, UNSET) -static void modssl_ctx_cfg_merge(modssl_ctx_t *base, +static void modssl_ctx_cfg_merge(apr_pool_t *p, + modssl_ctx_t *base, modssl_ctx_t *add, modssl_ctx_t *mrg) { @@ -284,31 +291,33 @@ static void modssl_ctx_cfg_merge(modssl_ctx_t *base, cfgMergeString(srp_vfile); cfgMergeString(srp_unknown_user_seed); #endif + +#ifdef HAVE_SSL_CONF_CMD + cfgMergeArray(ssl_ctx_param); +#endif } -static void modssl_ctx_cfg_merge_proxy(modssl_ctx_t *base, +static void modssl_ctx_cfg_merge_proxy(apr_pool_t *p, + modssl_ctx_t *base, modssl_ctx_t *add, modssl_ctx_t *mrg) { - modssl_ctx_cfg_merge(base, add, mrg); + modssl_ctx_cfg_merge(p, base, add, mrg); cfgMergeString(pkp->cert_file); cfgMergeString(pkp->cert_path); cfgMergeString(pkp->ca_cert_file); } -static void modssl_ctx_cfg_merge_server(modssl_ctx_t *base, +static void modssl_ctx_cfg_merge_server(apr_pool_t *p, + modssl_ctx_t *base, modssl_ctx_t *add, modssl_ctx_t *mrg) { - int i; + modssl_ctx_cfg_merge(p, base, add, mrg); - modssl_ctx_cfg_merge(base, add, mrg); - - for (i = 0; i < SSL_AIDX_MAX; i++) { - cfgMergeString(pks->cert_files[i]); - cfgMergeString(pks->key_files[i]); - } + cfgMergeArray(pks->cert_files); + cfgMergeArray(pks->key_files); cfgMergeString(pks->ca_name_path); cfgMergeString(pks->ca_name_file); @@ -346,9 +355,9 @@ void *ssl_config_server_merge(apr_pool_t *p, void *basev, void *addv) cfgMergeBool(compression); #endif - modssl_ctx_cfg_merge_proxy(base->proxy, add->proxy, mrg->proxy); + modssl_ctx_cfg_merge_proxy(p, base->proxy, add->proxy, mrg->proxy); - modssl_ctx_cfg_merge_server(base->server, add->server, mrg->server); + modssl_ctx_cfg_merge_server(p, base->server, add->server, mrg->server); return mrg; } @@ -707,7 +716,7 @@ const char *ssl_cmd_SSLHonorCipherOrder(cmd_parms *cmd, void *dcfg, int flag) sc->cipher_server_pref = flag?TRUE:FALSE; return NULL; #else - return "SSLHonorCiperOrder unsupported; not implemented by the SSL library"; + return "SSLHonorCipherOrder unsupported; not implemented by the SSL library"; #endif } @@ -745,56 +754,20 @@ static const char *ssl_cmd_check_dir(cmd_parms *parms, } -#define SSL_AIDX_CERTS 1 -#define SSL_AIDX_KEYS 2 - -static const char *ssl_cmd_check_aidx_max(cmd_parms *parms, - const char *arg, - int idx) -{ - SSLSrvConfigRec *sc = mySrvConfig(parms->server); - const char *err, *desc=NULL, **files=NULL; - int i; - - if ((err = ssl_cmd_check_file(parms, &arg))) { - return err; - } - - switch (idx) { - case SSL_AIDX_CERTS: - desc = "certificates"; - files = sc->server->pks->cert_files; - break; - case SSL_AIDX_KEYS: - desc = "private keys"; - files = sc->server->pks->key_files; - break; - } - - for (i = 0; i < SSL_AIDX_MAX; i++) { - if (!files[i]) { - files[i] = arg; - return NULL; - } - } - - return apr_psprintf(parms->pool, - "%s: only up to %d " - "different %s per virtual host allowed", - parms->cmd->name, SSL_AIDX_MAX, desc); -} - const char *ssl_cmd_SSLCertificateFile(cmd_parms *cmd, void *dcfg, const char *arg) { - + SSLSrvConfigRec *sc = mySrvConfig(cmd->server); const char *err; - if ((err = ssl_cmd_check_aidx_max(cmd, arg, SSL_AIDX_CERTS))) { + if ((err = ssl_cmd_check_file(cmd, &arg))) { return err; } + *(const char **)apr_array_push(sc->server->pks->cert_files) = + apr_pstrdup(cmd->pool, arg); + return NULL; } @@ -802,19 +775,6 @@ const char *ssl_cmd_SSLCertificateKeyFile(cmd_parms *cmd, void *dcfg, const char *arg) { - const char *err; - - if ((err = ssl_cmd_check_aidx_max(cmd, arg, SSL_AIDX_KEYS))) { - return err; - } - - return NULL; -} - -const char *ssl_cmd_SSLCertificateChainFile(cmd_parms *cmd, - void *dcfg, - const char *arg) -{ SSLSrvConfigRec *sc = mySrvConfig(cmd->server); const char *err; @@ -822,23 +782,30 @@ const char *ssl_cmd_SSLCertificateChainFile(cmd_parms *cmd, return err; } - sc->server->cert_chain = arg; + *(const char **)apr_array_push(sc->server->pks->key_files) = + apr_pstrdup(cmd->pool, arg); return NULL; } -const char *ssl_cmd_SSLPKCS7CertificateFile(cmd_parms *cmd, +const char *ssl_cmd_SSLCertificateChainFile(cmd_parms *cmd, void *dcfg, const char *arg) { SSLSrvConfigRec *sc = mySrvConfig(cmd->server); const char *err; + ap_log_error(APLOG_MARK, APLOG_WARNING|APLOG_STARTUP, 0, cmd->server, + APLOGNO(02559) + "The SSLCertificateChainFile directive (%s:%d) is deprecated, " + "SSLCertificateFile should be used instead", + cmd->directive->filename, cmd->directive->line_num); + if ((err = ssl_cmd_check_file(cmd, &arg))) { return err; } - sc->server->pkcs7 = arg; + sc->server->cert_chain = arg; return NULL; } @@ -1808,6 +1775,38 @@ const char *ssl_cmd_SSLStaplingForceURL(cmd_parms *cmd, void *dcfg, #endif /* HAVE_OCSP_STAPLING */ +#ifdef HAVE_SSL_CONF_CMD +const char *ssl_cmd_SSLOpenSSLConfCmd(cmd_parms *cmd, void *dcfg, + const char *arg1, const char *arg2) +{ + SSLSrvConfigRec *sc = mySrvConfig(cmd->server); + SSL_CONF_CTX *cctx = sc->server->ssl_ctx_config; + int value_type = SSL_CONF_cmd_value_type(cctx, arg1); + const char *err; + ssl_ctx_param_t *param; + + if (value_type == SSL_CONF_TYPE_UNKNOWN) { + return apr_psprintf(cmd->pool, + "'%s': invalid OpenSSL configuration command", + arg1); + } + + if (value_type == SSL_CONF_TYPE_FILE) { + if ((err = ssl_cmd_check_file(cmd, &arg2))) + return err; + } + else if (value_type == SSL_CONF_TYPE_DIR) { + if ((err = ssl_cmd_check_dir(cmd, &arg2))) + return err; + } + + param = apr_array_push(sc->server->ssl_ctx_param); + param->name = arg1; + param->value = arg2; + return NULL; +} +#endif + #ifdef HAVE_SRP const char *ssl_cmd_SSLSRPVerifierFile(cmd_parms *cmd, void *dcfg, @@ -1852,8 +1851,12 @@ void ssl_hook_ConfigTest(apr_pool_t *pconf, server_rec *s) modssl_pk_server_t *const pks = sc->server->pks; int i; - for (i = 0; (i < SSL_AIDX_MAX) && pks->cert_files[i]; i++) { - apr_file_printf(out, " %s\n", pks->cert_files[i]); + for (i = 0; (i < pks->cert_files->nelts) && + APR_ARRAY_IDX(pks->cert_files, i, const char *); + i++) { + apr_file_printf(out, " %s\n", + APR_ARRAY_IDX(pks->cert_files, + i, const char *)); } } diff --git a/modules/ssl/ssl_engine_init.c b/modules/ssl/ssl_engine_init.c index f6e010de..21c68a1a 100644 --- a/modules/ssl/ssl_engine_init.c +++ b/modules/ssl/ssl_engine_init.c @@ -59,13 +59,15 @@ static void ssl_add_version_components(apr_pool_t *p, /* * Per-module initialization */ -int ssl_init_Module(apr_pool_t *p, apr_pool_t *plog, - apr_pool_t *ptemp, - server_rec *base_server) +apr_status_t ssl_init_Module(apr_pool_t *p, apr_pool_t *plog, + apr_pool_t *ptemp, + server_rec *base_server) { SSLModConfigRec *mc = myModConfig(base_server); SSLSrvConfigRec *sc; server_rec *s; + apr_status_t rv; + apr_array_header_t *pphrases; if (SSLeay() < SSL_LIBRARY_VERSION) { ap_log_error(APLOG_MARK, APLOG_WARNING, 0, base_server, APLOGNO(01882) @@ -152,7 +154,9 @@ int ssl_init_Module(apr_pool_t *p, apr_pool_t *plog, * SSL external crypto device ("engine") support */ #if defined(HAVE_OPENSSL_ENGINE_H) && defined(HAVE_ENGINE_INIT) - ssl_init_Engine(base_server, p); + if ((rv = ssl_init_Engine(base_server, p)) != APR_SUCCESS) { + return rv; + } #endif ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, APLOGNO(01883) @@ -175,7 +179,7 @@ int ssl_init_Module(apr_pool_t *p, apr_pool_t *plog, else { ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(01885) "FIPS mode failed"); ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s); - ssl_die(s); + return ssl_die(s); } } } @@ -186,14 +190,6 @@ int ssl_init_Module(apr_pool_t *p, apr_pool_t *plog, #endif /* - * read server private keys/public certs into memory. - * decrypting any encrypted keys via configured SSLPassPhraseDialogs - * anything that needs to live longer than ptemp needs to also survive - * restarts, in which case they'll live inside s->process->pool. - */ - ssl_pphrase_Handle(base_server, ptemp); - - /* * initialize the mutex handling */ if (!ssl_mutex_init(base_server, p)) { @@ -206,7 +202,11 @@ int ssl_init_Module(apr_pool_t *p, apr_pool_t *plog, /* * initialize session caching */ - ssl_scache_init(base_server, p); + if ((rv = ssl_scache_init(base_server, p)) != APR_SUCCESS) { + return rv; + } + + pphrases = apr_array_make(ptemp, 2, sizeof(char *)); /* * initialize servers @@ -225,13 +225,25 @@ int ssl_init_Module(apr_pool_t *p, apr_pool_t *plog, /* * Read the server certificate and key */ - ssl_init_ConfigureServer(s, p, ptemp, sc); + if ((rv = ssl_init_ConfigureServer(s, p, ptemp, sc, pphrases)) + != APR_SUCCESS) { + return rv; + } + } + + if (pphrases->nelts > 0) { + memset(pphrases->elts, 0, pphrases->elt_size * pphrases->nelts); + pphrases->nelts = 0; + ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, APLOGNO(02560) + "Init: Wiped out the queried pass phrases from memory"); } /* * Configuration consistency checks */ - ssl_init_CheckServers(base_server, ptemp); + if ((rv = ssl_init_CheckServers(base_server, ptemp)) != APR_SUCCESS) { + return rv; + } /* * Announce mod_ssl and SSL library in HTTP Server field @@ -249,7 +261,7 @@ int ssl_init_Module(apr_pool_t *p, apr_pool_t *plog, * a hardware accellerator card for crypto operations. */ #if defined(HAVE_OPENSSL_ENGINE_H) && defined(HAVE_ENGINE_INIT) -void ssl_init_Engine(server_rec *s, apr_pool_t *p) +apr_status_t ssl_init_Engine(server_rec *s, apr_pool_t *p) { SSLModConfigRec *mc = myModConfig(s); ENGINE *e; @@ -260,7 +272,7 @@ void ssl_init_Engine(server_rec *s, apr_pool_t *p) "Init: Failed to load Crypto Device API `%s'", mc->szCryptoDevice); ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s); - ssl_die(s); + return ssl_die(s); } if (strEQ(mc->szCryptoDevice, "chil")) { @@ -272,7 +284,7 @@ void ssl_init_Engine(server_rec *s, apr_pool_t *p) "Init: Failed to enable Crypto Device API `%s'", mc->szCryptoDevice); ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s); - ssl_die(s); + return ssl_die(s); } ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, APLOGNO(01890) "Init: loaded Crypto Device API `%s'", @@ -280,47 +292,19 @@ void ssl_init_Engine(server_rec *s, apr_pool_t *p) ENGINE_free(e); } -} -#endif -static void ssl_init_server_check(server_rec *s, - apr_pool_t *p, - apr_pool_t *ptemp, - modssl_ctx_t *mctx) -{ - /* - * check for important parameters and the - * possibility that the user forgot to set them. - */ - if (!mctx->pks->cert_files[0] && !mctx->pkcs7) { - ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(01891) - "No SSL Certificate set [hint: SSLCertificateFile]"); - ssl_die(s); - } - - /* - * Check for problematic re-initializations - */ - if (mctx->pks->certs[SSL_AIDX_RSA] || - mctx->pks->certs[SSL_AIDX_DSA] -#ifdef HAVE_ECC - || mctx->pks->certs[SSL_AIDX_ECC] -#endif - ) - { - ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(01892) - "Illegal attempt to re-initialise SSL for server " - "(SSLEngine On should go in the VirtualHost, not in global scope.)"); - ssl_die(s); - } + return APR_SUCCESS; } +#endif #ifdef HAVE_TLSEXT -static void ssl_init_ctx_tls_extensions(server_rec *s, - apr_pool_t *p, - apr_pool_t *ptemp, - modssl_ctx_t *mctx) +static apr_status_t ssl_init_ctx_tls_extensions(server_rec *s, + apr_pool_t *p, + apr_pool_t *ptemp, + modssl_ctx_t *mctx) { + apr_status_t rv; + /* * Configure TLS extensions support */ @@ -337,7 +321,7 @@ static void ssl_init_ctx_tls_extensions(server_rec *s, "Unable to initialize TLS servername extension " "callback (incompatible OpenSSL version?)"); ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s); - ssl_die(s); + return ssl_die(s); } #ifdef HAVE_OCSP_STAPLING @@ -345,7 +329,9 @@ static void ssl_init_ctx_tls_extensions(server_rec *s, * OCSP Stapling support, status_request extension */ if ((mctx->pkp == FALSE) && (mctx->stapling_enabled == TRUE)) { - modssl_init_stapling(s, p, ptemp, mctx); + if ((rv = modssl_init_stapling(s, p, ptemp, mctx)) != APR_SUCCESS) { + return rv; + } } #endif @@ -364,7 +350,7 @@ static void ssl_init_ctx_tls_extensions(server_rec *s, "[%s seed]", mctx->srp_unknown_user_seed ? "with" : "without"); ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s); - ssl_die(s); + return ssl_die(s); } err = SRP_VBASE_init(mctx->srp_vbase, mctx->srp_vfile); @@ -372,7 +358,7 @@ static void ssl_init_ctx_tls_extensions(server_rec *s, ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02310) "Unable to load SRP verifier file [error %d]", err); ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s); - ssl_die(s); + return ssl_die(s); } SSL_CTX_set_srp_username_callback(mctx->ssl_ctx, @@ -380,13 +366,14 @@ static void ssl_init_ctx_tls_extensions(server_rec *s, SSL_CTX_set_srp_cb_arg(mctx->ssl_ctx, mctx); } #endif + return APR_SUCCESS; } #endif -static void ssl_init_ctx_protocol(server_rec *s, - apr_pool_t *p, - apr_pool_t *ptemp, - modssl_ctx_t *mctx) +static apr_status_t ssl_init_ctx_protocol(server_rec *s, + apr_pool_t *p, + apr_pool_t *ptemp, + modssl_ctx_t *mctx) { SSL_CTX *ctx = NULL; MODSSL_SSL_METHOD_CONST SSL_METHOD *method = NULL; @@ -400,7 +387,7 @@ static void ssl_init_ctx_protocol(server_rec *s, if (protocol == SSL_PROTOCOL_NONE) { ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02231) "No SSL protocols available [hint: SSLProtocol]"); - ssl_die(s); + return ssl_die(s); } cp = apr_pstrcat(p, @@ -517,6 +504,8 @@ static void ssl_init_ctx_protocol(server_rec *s, if (ap_max_mem_free != APR_ALLOCATOR_MAX_FREE_UNLIMITED) SSL_CTX_set_mode(ctx, SSL_MODE_RELEASE_BUFFERS); #endif + + return APR_SUCCESS; } static void ssl_init_ctx_session_cache(server_rec *s, @@ -548,10 +537,10 @@ static void ssl_init_ctx_callbacks(server_rec *s, SSL_CTX_set_info_callback(ctx, ssl_callback_Info); } -static void ssl_init_ctx_verify(server_rec *s, - apr_pool_t *p, - apr_pool_t *ptemp, - modssl_ctx_t *mctx) +static apr_status_t ssl_init_ctx_verify(server_rec *s, + apr_pool_t *p, + apr_pool_t *ptemp, + modssl_ctx_t *mctx) { SSL_CTX *ctx = mctx->ssl_ctx; @@ -596,7 +585,7 @@ static void ssl_init_ctx_verify(server_rec *s, "Unable to configure verify locations " "for client authentication"); ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s); - ssl_die(s); + return ssl_die(s); } if (mctx->pks && (mctx->pks->ca_name_file || mctx->pks->ca_name_path)) { @@ -611,7 +600,7 @@ static void ssl_init_ctx_verify(server_rec *s, ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(01896) "Unable to determine list of acceptable " "CA certificates for client authentication"); - ssl_die(s); + return ssl_die(s); } SSL_CTX_set_client_CA_list(ctx, ca_list); @@ -631,12 +620,14 @@ static void ssl_init_ctx_verify(server_rec *s, "verification!? [Hint: SSLCACertificate*]"); } } + + return APR_SUCCESS; } -static void ssl_init_ctx_cipher_suite(server_rec *s, - apr_pool_t *p, - apr_pool_t *ptemp, - modssl_ctx_t *mctx) +static apr_status_t ssl_init_ctx_cipher_suite(server_rec *s, + apr_pool_t *p, + apr_pool_t *ptemp, + modssl_ctx_t *mctx) { SSL_CTX *ctx = mctx->ssl_ctx; const char *suite; @@ -658,14 +649,16 @@ static void ssl_init_ctx_cipher_suite(server_rec *s, ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(01898) "Unable to configure permitted SSL ciphers"); ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s); - ssl_die(s); + return ssl_die(s); } + + return APR_SUCCESS; } -static void ssl_init_ctx_crl(server_rec *s, - apr_pool_t *p, - apr_pool_t *ptemp, - modssl_ctx_t *mctx) +static apr_status_t ssl_init_ctx_crl(server_rec *s, + apr_pool_t *p, + apr_pool_t *ptemp, + modssl_ctx_t *mctx) { X509_STORE *store = SSL_CTX_get_cert_store(mctx->ssl_ctx); unsigned long crlflags = 0; @@ -682,9 +675,9 @@ static void ssl_init_ctx_crl(server_rec *s, "Host %s: CRL checking has been enabled, but " "neither %sCARevocationFile nor %sCARevocationPath " "is configured", mctx->sc->vhost_id, cfgp, cfgp); - ssl_die(s); + return ssl_die(s); } - return; + return APR_SUCCESS; } ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(01900) @@ -696,7 +689,7 @@ static void ssl_init_ctx_crl(server_rec *s, "Host %s: unable to configure X.509 CRL storage " "for certificate revocation", mctx->sc->vhost_id); ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s); - ssl_die(s); + return ssl_die(s); } switch (mctx->crl_check_mode) { @@ -718,39 +711,19 @@ static void ssl_init_ctx_crl(server_rec *s, "but CRL checking (%sCARevocationCheck) is not " "enabled", mctx->sc->vhost_id, cfgp); } -} -static void ssl_init_ctx_pkcs7_cert_chain(server_rec *s, modssl_ctx_t *mctx) -{ - STACK_OF(X509) *certs = ssl_read_pkcs7(s, mctx->pkcs7); - int n; - STACK_OF(X509) *extra_certs = NULL; - -#ifdef OPENSSL_NO_SSL_INTERN - SSL_CTX_get_extra_chain_certs(mctx->ssl_ctx, &extra_certs); -#else - extra_certs = mctx->ssl_ctx->extra_certs; -#endif - - if (!extra_certs) - for (n = 1; n < sk_X509_num(certs); ++n) - SSL_CTX_add_extra_chain_cert(mctx->ssl_ctx, sk_X509_value(certs, n)); + return APR_SUCCESS; } -static void ssl_init_ctx_cert_chain(server_rec *s, - apr_pool_t *p, - apr_pool_t *ptemp, - modssl_ctx_t *mctx) +static apr_status_t ssl_init_ctx_cert_chain(server_rec *s, + apr_pool_t *p, + apr_pool_t *ptemp, + modssl_ctx_t *mctx) { BOOL skip_first = FALSE; int i, n; const char *chain = mctx->cert_chain; - if (mctx->pkcs7) { - ssl_init_ctx_pkcs7_cert_chain(s, mctx); - return; - } - /* * Optionally configure extra server certificate chain certificates. * This is usually done by OpenSSL automatically when one of the @@ -766,11 +739,12 @@ static void ssl_init_ctx_cert_chain(server_rec *s, * used only for the server certificate chain. */ if (!chain) { - return; + return APR_SUCCESS; } - for (i = 0; (i < SSL_AIDX_MAX) && mctx->pks->cert_files[i]; i++) { - if (strEQ(mctx->pks->cert_files[i], chain)) { + for (i = 0; (i < mctx->pks->cert_files->nelts) && + APR_ARRAY_IDX(mctx->pks->cert_files, i, const char *); i++) { + if (strEQ(APR_ARRAY_IDX(mctx->pks->cert_files, i, const char *), chain)) { skip_first = TRUE; break; } @@ -782,155 +756,64 @@ static void ssl_init_ctx_cert_chain(server_rec *s, if (n < 0) { ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(01903) "Failed to configure CA certificate chain!"); - ssl_die(s); + return ssl_die(s); } ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(01904) "Configuring server certificate chain " "(%d CA certificate%s)", n, n == 1 ? "" : "s"); -} - -static void ssl_init_ctx(server_rec *s, - apr_pool_t *p, - apr_pool_t *ptemp, - modssl_ctx_t *mctx) -{ - ssl_init_ctx_protocol(s, p, ptemp, mctx); - - ssl_init_ctx_session_cache(s, p, ptemp, mctx); - - ssl_init_ctx_callbacks(s, p, ptemp, mctx); - - ssl_init_ctx_verify(s, p, ptemp, mctx); - ssl_init_ctx_cipher_suite(s, p, ptemp, mctx); - - ssl_init_ctx_crl(s, p, ptemp, mctx); - - if (mctx->pks) { - /* XXX: proxy support? */ - ssl_init_ctx_cert_chain(s, p, ptemp, mctx); -#ifdef HAVE_TLSEXT - ssl_init_ctx_tls_extensions(s, p, ptemp, mctx); -#endif - } + return APR_SUCCESS; } -static int ssl_server_import_cert(server_rec *s, - modssl_ctx_t *mctx, - const char *id, - int idx) +static apr_status_t ssl_init_ctx(server_rec *s, + apr_pool_t *p, + apr_pool_t *ptemp, + modssl_ctx_t *mctx) { - SSLModConfigRec *mc = myModConfig(s); - ssl_asn1_t *asn1; - const unsigned char *ptr; - const char *type = ssl_asn1_keystr(idx); - X509 *cert; - - if (!(asn1 = ssl_asn1_table_get(mc->tPublicCert, id))) { - return FALSE; - } - - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(02232) - "Configuring %s server certificate", type); + apr_status_t rv; - ptr = asn1->cpData; - if (!(cert = d2i_X509(NULL, &ptr, asn1->nData))) { - ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02233) - "Unable to import %s server certificate", type); - ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s); - ssl_die(s); + if ((rv = ssl_init_ctx_protocol(s, p, ptemp, mctx)) != APR_SUCCESS) { + return rv; } - if (SSL_CTX_use_certificate(mctx->ssl_ctx, cert) <= 0) { - ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02234) - "Unable to configure %s server certificate", type); - ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s); - ssl_die(s); - } - -#ifdef HAVE_OCSP_STAPLING - if ((mctx->pkp == FALSE) && (mctx->stapling_enabled == TRUE)) { - if (!ssl_stapling_init_cert(s, mctx, cert)) { - ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(02235) - "Unable to configure server certificate for stapling"); - } - } -#endif - - mctx->pks->certs[idx] = cert; - - return TRUE; -} - -static int ssl_server_import_key(server_rec *s, - modssl_ctx_t *mctx, - const char *id, - int idx) -{ - SSLModConfigRec *mc = myModConfig(s); - ssl_asn1_t *asn1; - const unsigned char *ptr; - const char *type = ssl_asn1_keystr(idx); - int pkey_type; - EVP_PKEY *pkey; + ssl_init_ctx_session_cache(s, p, ptemp, mctx); -#ifdef HAVE_ECC - if (idx == SSL_AIDX_ECC) - pkey_type = EVP_PKEY_EC; - else -#endif - pkey_type = (idx == SSL_AIDX_RSA) ? EVP_PKEY_RSA : EVP_PKEY_DSA; + ssl_init_ctx_callbacks(s, p, ptemp, mctx); - if (!(asn1 = ssl_asn1_table_get(mc->tPrivateKey, id))) { - return FALSE; + if ((rv = ssl_init_ctx_verify(s, p, ptemp, mctx)) != APR_SUCCESS) { + return rv; } - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(02236) - "Configuring %s server private key", type); - - ptr = asn1->cpData; - if (!(pkey = d2i_PrivateKey(pkey_type, NULL, &ptr, asn1->nData))) - { - ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02237) - "Unable to import %s server private key", type); - ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s); - ssl_die(s); + if ((rv = ssl_init_ctx_cipher_suite(s, p, ptemp, mctx)) != APR_SUCCESS) { + return rv; } - if (SSL_CTX_use_PrivateKey(mctx->ssl_ctx, pkey) <= 0) { - ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02238) - "Unable to configure %s server private key", type); - ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s); - ssl_die(s); + if ((rv = ssl_init_ctx_crl(s, p, ptemp, mctx)) != APR_SUCCESS) { + return rv; } - /* - * XXX: wonder if this is still needed, this is old todo doc. - * (see http://www.psy.uq.edu.au/~ftp/Crypto/ssleay/TODO.html) - */ - if ((pkey_type == EVP_PKEY_DSA) && mctx->pks->certs[idx]) { - EVP_PKEY *pubkey = X509_get_pubkey(mctx->pks->certs[idx]); - - if (pubkey && EVP_PKEY_missing_parameters(pubkey)) { - EVP_PKEY_copy_parameters(pubkey, pkey); - ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(02239) - "Copying DSA parameters from private key to certificate"); - ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, s); - EVP_PKEY_free(pubkey); + if (mctx->pks) { + /* XXX: proxy support? */ + if ((rv = ssl_init_ctx_cert_chain(s, p, ptemp, mctx)) != APR_SUCCESS) { + return rv; } +#ifdef HAVE_TLSEXT + if ((rv = ssl_init_ctx_tls_extensions(s, p, ptemp, mctx)) != + APR_SUCCESS) { + return rv; + } +#endif } - mctx->pks->keys[idx] = pkey; - - return TRUE; + return APR_SUCCESS; } static void ssl_check_public_cert(server_rec *s, apr_pool_t *ptemp, X509 *cert, - int type) + const char *key_id) { int is_ca, pathlen; @@ -942,141 +825,228 @@ static void ssl_check_public_cert(server_rec *s, * Some information about the certificate(s) */ - if (SSL_X509_isSGC(cert)) { - ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, APLOGNO(01905) - "%s server certificate enables " - "Server Gated Cryptography (SGC)", - ssl_asn1_keystr(type)); - } - if (SSL_X509_getBC(cert, &is_ca, &pathlen)) { if (is_ca) { ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(01906) "%s server certificate is a CA certificate " - "(BasicConstraints: CA == TRUE !?)", - ssl_asn1_keystr(type)); + "(BasicConstraints: CA == TRUE !?)", key_id); } if (pathlen > 0) { ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(01907) "%s server certificate is not a leaf certificate " "(BasicConstraints: pathlen == %d > 0 !?)", - ssl_asn1_keystr(type), pathlen); + key_id, pathlen); } } if (SSL_X509_match_name(ptemp, cert, (const char *)s->server_hostname, TRUE, s) == FALSE) { ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(01909) - "%s certificate configured for %s does NOT include " - "an ID which matches the server name", - ssl_asn1_keystr(type), (mySrvConfig(s))->vhost_id); + "%s server certificate does NOT include an ID " + "which matches the server name", key_id); } } -static void ssl_init_server_certs(server_rec *s, - apr_pool_t *p, - apr_pool_t *ptemp, - modssl_ctx_t *mctx) +/* prevent OpenSSL from showing its "Enter PEM pass phrase:" prompt */ +static int ssl_no_passwd_prompt_cb(char *buf, int size, int rwflag, + void *userdata) { + return 0; +} + +static apr_status_t ssl_init_server_certs(server_rec *s, + apr_pool_t *p, + apr_pool_t *ptemp, + modssl_ctx_t *mctx, + apr_array_header_t *pphrases) { - const char *rsa_id, *dsa_id; + SSLModConfigRec *mc = myModConfig(s); + const char *vhost_id = mctx->sc->vhost_id, *key_id, *certfile, *keyfile; + int i; + X509 *cert; + DH *dhparams; #ifdef HAVE_ECC - const char *ecc_id; EC_GROUP *ecparams; int nid; EC_KEY *eckey; #endif - const char *vhost_id = mctx->sc->vhost_id; - int i; - int have_rsa, have_dsa; - DH *dhparams; -#ifdef HAVE_ECC - int have_ecc; +#ifndef HAVE_SSL_CONF_CMD + SSL *ssl; #endif - rsa_id = ssl_asn1_table_keyfmt(ptemp, vhost_id, SSL_AIDX_RSA); - dsa_id = ssl_asn1_table_keyfmt(ptemp, vhost_id, SSL_AIDX_DSA); -#ifdef HAVE_ECC - ecc_id = ssl_asn1_table_keyfmt(ptemp, vhost_id, SSL_AIDX_ECC); -#endif + /* no OpenSSL default prompts for any of the SSL_CTX_use_* calls, please */ + SSL_CTX_set_default_passwd_cb(mctx->ssl_ctx, ssl_no_passwd_prompt_cb); + + /* Iterate over the SSLCertificateFile array */ + for (i = 0; (i < mctx->pks->cert_files->nelts) && + (certfile = APR_ARRAY_IDX(mctx->pks->cert_files, i, + const char *)); + i++) { + key_id = apr_psprintf(ptemp, "%s:%d", vhost_id, i); + + /* first the certificate (public key) */ + if (mctx->cert_chain) { + if ((SSL_CTX_use_certificate_file(mctx->ssl_ctx, certfile, + SSL_FILETYPE_PEM) < 1)) { + ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02561) + "Failed to configure certificate %s, check %s", + key_id, certfile); + ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s); + return APR_EGENERAL; + } + } else { + if ((SSL_CTX_use_certificate_chain_file(mctx->ssl_ctx, + certfile) < 1)) { + ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02562) + "Failed to configure certificate %s (with chain)," + " check %s", key_id, certfile); + ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s); + return APR_EGENERAL; + } + } - have_rsa = ssl_server_import_cert(s, mctx, rsa_id, SSL_AIDX_RSA); - have_dsa = ssl_server_import_cert(s, mctx, dsa_id, SSL_AIDX_DSA); -#ifdef HAVE_ECC - have_ecc = ssl_server_import_cert(s, mctx, ecc_id, SSL_AIDX_ECC); -#endif + /* and second, the private key */ + keyfile = APR_ARRAY_IDX(mctx->pks->key_files, i, const char *); + if (keyfile == NULL) + keyfile = certfile; - if (!(have_rsa || have_dsa -#ifdef HAVE_ECC - || have_ecc + ERR_clear_error(); + + if ((SSL_CTX_use_PrivateKey_file(mctx->ssl_ctx, keyfile, + SSL_FILETYPE_PEM) < 1) && + (ERR_GET_FUNC(ERR_peek_last_error()) + != X509_F_X509_CHECK_PRIVATE_KEY)) { + ssl_asn1_t *asn1; + EVP_PKEY *pkey; + const unsigned char *ptr; + + ERR_clear_error(); + + /* perhaps it's an encrypted private key, so try again */ + ssl_load_encrypted_pkey(s, ptemp, i, keyfile, &pphrases); + + if (!(asn1 = ssl_asn1_table_get(mc->tPrivateKey, key_id)) || + !(ptr = asn1->cpData) || + !(pkey = d2i_AutoPrivateKey(NULL, &ptr, asn1->nData)) || + (SSL_CTX_use_PrivateKey(mctx->ssl_ctx, pkey) < 1)) { + ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02564) + "Failed to configure encrypted (?) private key %s," + " check %s", key_id, keyfile); + ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s); + return APR_EGENERAL; + } + } + + if (SSL_CTX_check_private_key(mctx->ssl_ctx) < 1) { + ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02565) + "Certificate and private key %s from %s and %s " + "do not match", key_id, certfile, keyfile); + return APR_EGENERAL; + } + +#ifdef HAVE_SSL_CONF_CMD + /* + * workaround for those OpenSSL versions where SSL_CTX_get0_certificate + * is not yet available: create an SSL struct which we dispose of + * as soon as we no longer need access to the cert. (Strictly speaking, + * SSL_CTX_get0_certificate does not depend on the SSL_CONF stuff, + * but there's no reliable way to check for its existence, so we + * assume that if SSL_CONF is available, it's OpenSSL 1.0.2 or later, + * and SSL_CTX_get0_certificate is implemented.) + */ + if (!(cert = SSL_CTX_get0_certificate(mctx->ssl_ctx))) { +#else + ssl = SSL_new(mctx->ssl_ctx); + if (ssl) { + /* Workaround bug in SSL_get_certificate in OpenSSL 0.9.8y */ + SSL_set_connect_state(ssl); + cert = SSL_get_certificate(ssl); + } + if (!ssl || !cert) { #endif -)) { - ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(01910) - "Oops, no " KEYTYPES " server certificate found " - "for '%s:%d'?!", s->server_hostname, s->port); - ssl_die(s); - } + ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(02566) + "Unable to retrieve certificate %s", key_id); +#ifndef HAVE_SSL_CONF_CMD + if (ssl) + SSL_free(ssl); +#endif + return APR_EGENERAL; + } - for (i = 0; i < SSL_AIDX_MAX; i++) { - ssl_check_public_cert(s, ptemp, mctx->pks->certs[i], i); - } + /* warn about potential cert issues */ + ssl_check_public_cert(s, ptemp, cert, key_id); - have_rsa = ssl_server_import_key(s, mctx, rsa_id, SSL_AIDX_RSA); - have_dsa = ssl_server_import_key(s, mctx, dsa_id, SSL_AIDX_DSA); -#ifdef HAVE_ECC - have_ecc = ssl_server_import_key(s, mctx, ecc_id, SSL_AIDX_ECC); +#if defined(HAVE_OCSP_STAPLING) && !defined(SSL_CTRL_SET_CURRENT_CERT) + /* + * OpenSSL up to 1.0.1: configure stapling as we go. In 1.0.2 + * and later, there's SSL_CTX_set_current_cert, which allows + * iterating over all certs in an SSL_CTX (including those possibly + * loaded via SSLOpenSSLConfCmd Certificate), so for 1.0.2 and + * later, we defer to the code in ssl_init_server_ctx. + */ + if ((mctx->stapling_enabled == TRUE) && + !ssl_stapling_init_cert(s, mctx, cert)) { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(02567) + "Unable to configure certificate %s for stapling", + key_id); + } #endif - if (!(have_rsa || have_dsa -#ifdef HAVE_ECC - || have_ecc +#ifndef HAVE_SSL_CONF_CMD + SSL_free(ssl); #endif - )) { - ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(01911) - "Oops, no " KEYTYPES " server private key found?!"); - ssl_die(s); + + ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, APLOGNO(02568) + "Certificate and private key %s configured from %s and %s", + key_id, certfile, keyfile); } /* * Try to read DH parameters from the (first) SSLCertificateFile */ - if ((mctx->pks->cert_files[0] != NULL) && - (dhparams = ssl_dh_GetParamFromFile(mctx->pks->cert_files[0]))) { + if ((certfile = APR_ARRAY_IDX(mctx->pks->cert_files, 0, const char *)) && + (dhparams = ssl_dh_GetParamFromFile(certfile))) { SSL_CTX_set_tmp_dh(mctx->ssl_ctx, dhparams); ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(02540) "Custom DH parameters (%d bits) for %s loaded from %s", - BN_num_bits(dhparams->p), vhost_id, - mctx->pks->cert_files[0]); + BN_num_bits(dhparams->p), vhost_id, certfile); } #ifdef HAVE_ECC /* * Similarly, try to read the ECDH curve name from SSLCertificateFile... */ - if ((mctx->pks->cert_files[0] != NULL) && - (ecparams = ssl_ec_GetParamFromFile(mctx->pks->cert_files[0])) && + if ((certfile != NULL) && + (ecparams = ssl_ec_GetParamFromFile(certfile)) && (nid = EC_GROUP_get_curve_name(ecparams)) && (eckey = EC_KEY_new_by_curve_name(nid))) { SSL_CTX_set_tmp_ecdh(mctx->ssl_ctx, eckey); ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(02541) "ECDH curve %s for %s specified in %s", - OBJ_nid2sn(nid), vhost_id, mctx->pks->cert_files[0]); + OBJ_nid2sn(nid), vhost_id, certfile); } /* - * ...otherwise, configure NIST P-256 (required to enable ECDHE) + * ...otherwise, enable auto curve selection (OpenSSL 1.0.2 and later) + * or configure NIST P-256 (required to enable ECDHE for earlier versions) */ else { +#if defined(SSL_CTX_set_ecdh_auto) + SSL_CTX_set_ecdh_auto(mctx->ssl_ctx, 1); +#else SSL_CTX_set_tmp_ecdh(mctx->ssl_ctx, EC_KEY_new_by_curve_name(NID_X9_62_prime256v1)); +#endif } #endif + + return APR_SUCCESS; } #ifdef HAVE_TLS_SESSION_TICKETS -static void ssl_init_ticket_key(server_rec *s, - apr_pool_t *p, - apr_pool_t *ptemp, - modssl_ctx_t *mctx) +static apr_status_t ssl_init_ticket_key(server_rec *s, + apr_pool_t *p, + apr_pool_t *ptemp, + modssl_ctx_t *mctx) { apr_status_t rv; apr_file_t *fp; @@ -1086,7 +1056,7 @@ static void ssl_init_ticket_key(server_rec *s, modssl_ticket_key_t *ticket_key = mctx->ticket_key; if (!ticket_key->file_path) { - return; + return APR_SUCCESS; } path = ap_server_root_relative(p, ticket_key->file_path); @@ -1098,7 +1068,7 @@ static void ssl_init_ticket_key(server_rec *s, ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02286) "Failed to open ticket key file %s: (%d) %pm", path, rv, &rv); - ssl_die(s); + return ssl_die(s); } rv = apr_file_read_full(fp, &buf[0], TLSEXT_TICKET_KEY_LEN, &len); @@ -1107,7 +1077,7 @@ static void ssl_init_ticket_key(server_rec *s, ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02287) "Failed to read %d bytes from %s: (%d) %pm", TLSEXT_TICKET_KEY_LEN, path, rv, &rv); - ssl_die(s); + return ssl_die(s); } memcpy(ticket_key->key_name, buf, 16); @@ -1120,19 +1090,21 @@ static void ssl_init_ticket_key(server_rec *s, "Unable to initialize TLS session ticket key callback " "(incompatible OpenSSL version?)"); ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s); - ssl_die(s); + return ssl_die(s); } ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, APLOGNO(02288) "TLS session ticket key for %s successfully loaded from %s", (mySrvConfig(s))->vhost_id, path); + + return APR_SUCCESS; } #endif -static void ssl_init_proxy_certs(server_rec *s, - apr_pool_t *p, - apr_pool_t *ptemp, - modssl_ctx_t *mctx) +static apr_status_t ssl_init_proxy_certs(server_rec *s, + apr_pool_t *p, + apr_pool_t *ptemp, + modssl_ctx_t *mctx) { int n, ncerts = 0; STACK_OF(X509_INFO) *sk; @@ -1145,7 +1117,7 @@ static void ssl_init_proxy_certs(server_rec *s, ssl_callback_proxy_cert); if (!(pkp->cert_file || pkp->cert_path)) { - return; + return APR_SUCCESS; } sk = sk_X509_INFO_new_null(); @@ -1162,7 +1134,7 @@ static void ssl_init_proxy_certs(server_rec *s, sk_X509_INFO_free(sk); ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(02206) "no client certs found for SSL proxy"); - return; + return APR_SUCCESS; } /* Check that all client certs have got certificates and private @@ -1176,8 +1148,7 @@ static void ssl_init_proxy_certs(server_rec *s, ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, APLOGNO(02252) "incomplete client cert configured for SSL proxy " "(missing or encrypted private key?)"); - ssl_die(s); - return; + return ssl_die(s); } if (X509_check_private_key(inf->x509, inf->x_pkey->dec_pkey) != 1) { @@ -1185,8 +1156,7 @@ static void ssl_init_proxy_certs(server_rec *s, APLOGNO(02326) "proxy client certificate and " "private key do not match"); ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, s); - ssl_die(s); - return; + return ssl_die(s); } } @@ -1197,7 +1167,7 @@ static void ssl_init_proxy_certs(server_rec *s, if (!pkp->ca_cert_file || !store) { - return; + return APR_SUCCESS; } /* If SSLProxyMachineCertificateChainFile is configured, load all @@ -1212,7 +1182,7 @@ static void ssl_init_proxy_certs(server_rec *s, ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02208) "SSL proxy client cert initialization failed"); ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s); - ssl_die(s); + return ssl_die(s); } X509_STORE_load_locations(store, pkp->ca_cert_file, NULL); @@ -1270,56 +1240,162 @@ static void ssl_init_proxy_certs(server_rec *s, } X509_STORE_CTX_free(sctx); + + return APR_SUCCESS; } -static void ssl_init_proxy_ctx(server_rec *s, - apr_pool_t *p, - apr_pool_t *ptemp, - SSLSrvConfigRec *sc) +static apr_status_t ssl_init_proxy_ctx(server_rec *s, + apr_pool_t *p, + apr_pool_t *ptemp, + SSLSrvConfigRec *sc) { - ssl_init_ctx(s, p, ptemp, sc->proxy); + apr_status_t rv; + + if ((rv = ssl_init_ctx(s, p, ptemp, sc->proxy)) != APR_SUCCESS) { + return rv; + } + + if ((rv = ssl_init_proxy_certs(s, p, ptemp, sc->proxy)) != APR_SUCCESS) { + return rv; + } - ssl_init_proxy_certs(s, p, ptemp, sc->proxy); + return APR_SUCCESS; } -static void ssl_init_server_ctx(server_rec *s, - apr_pool_t *p, - apr_pool_t *ptemp, - SSLSrvConfigRec *sc) +static apr_status_t ssl_init_server_ctx(server_rec *s, + apr_pool_t *p, + apr_pool_t *ptemp, + SSLSrvConfigRec *sc, + apr_array_header_t *pphrases) { - ssl_init_server_check(s, p, ptemp, sc->server); + apr_status_t rv; +#ifdef HAVE_SSL_CONF_CMD + ssl_ctx_param_t *param = (ssl_ctx_param_t *)sc->server->ssl_ctx_param->elts; + SSL_CONF_CTX *cctx = sc->server->ssl_ctx_config; + int i; +#endif - ssl_init_ctx(s, p, ptemp, sc->server); + /* + * Check for problematic re-initializations + */ + if (sc->server->ssl_ctx) { + ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02569) + "Illegal attempt to re-initialise SSL for server " + "(SSLEngine On should go in the VirtualHost, not in global scope.)"); + return APR_EGENERAL; + } - ssl_init_server_certs(s, p, ptemp, sc->server); + if ((rv = ssl_init_ctx(s, p, ptemp, sc->server)) != APR_SUCCESS) { + return rv; + } + + if ((rv = ssl_init_server_certs(s, p, ptemp, sc->server, pphrases)) + != APR_SUCCESS) { + return rv; + } + +#ifdef HAVE_SSL_CONF_CMD + SSL_CONF_CTX_set_ssl_ctx(cctx, sc->server->ssl_ctx); + for (i = 0; i < sc->server->ssl_ctx_param->nelts; i++, param++) { + ERR_clear_error(); + if (SSL_CONF_cmd(cctx, param->name, param->value) <= 0) { + ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02407) + "\"SSLOpenSSLConfCmd %s %s\" failed for %s", + param->name, param->value, sc->vhost_id); + ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s); + return ssl_die(s); + } else { + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(02556) + "\"SSLOpenSSLConfCmd %s %s\" applied to %s", + param->name, param->value, sc->vhost_id); + } + } + + if (SSL_CONF_CTX_finish(cctx) == 0) { + ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02547) + "SSL_CONF_CTX_finish() failed"); + SSL_CONF_CTX_free(cctx); + ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s); + return ssl_die(s); + } + SSL_CONF_CTX_free(cctx); +#endif + + if (SSL_CTX_check_private_key(sc->server->ssl_ctx) != 1) { + ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02572) + "Failed to configure at least one certificate and key " + "for %s", sc->vhost_id); + ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s); + return ssl_die(s); + } + +#if defined(HAVE_OCSP_STAPLING) && defined(SSL_CTRL_SET_CURRENT_CERT) + /* + * OpenSSL 1.0.2 and later allows iterating over all SSL_CTX certs + * by means of SSL_CTX_set_current_cert. Enabling stapling at this + * (late) point makes sure that we catch both certificates loaded + * via SSLCertificateFile and SSLOpenSSLConfCmd Certificate. + */ + if (sc->server->stapling_enabled == TRUE) { + X509 *cert; + int i = 0; + int ret = SSL_CTX_set_current_cert(sc->server->ssl_ctx, + SSL_CERT_SET_FIRST); + while (ret) { + cert = SSL_CTX_get0_certificate(sc->server->ssl_ctx); + if (!cert || !ssl_stapling_init_cert(s, sc->server, cert)) { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(02604) + "Unable to configure certificate %s:%d " + "for stapling", sc->vhost_id, i); + } + ret = SSL_CTX_set_current_cert(sc->server->ssl_ctx, + SSL_CERT_SET_NEXT); + i++; + } + } +#endif #ifdef HAVE_TLS_SESSION_TICKETS - ssl_init_ticket_key(s, p, ptemp, sc->server); + if ((rv = ssl_init_ticket_key(s, p, ptemp, sc->server)) != APR_SUCCESS) { + return rv; + } #endif + + return APR_SUCCESS; } /* * Configure a particular server */ -void ssl_init_ConfigureServer(server_rec *s, - apr_pool_t *p, - apr_pool_t *ptemp, - SSLSrvConfigRec *sc) +apr_status_t ssl_init_ConfigureServer(server_rec *s, + apr_pool_t *p, + apr_pool_t *ptemp, + SSLSrvConfigRec *sc, + apr_array_header_t *pphrases) { + apr_status_t rv; + /* Initialize the server if SSL is enabled or optional. */ if ((sc->enabled == SSL_ENABLED_TRUE) || (sc->enabled == SSL_ENABLED_OPTIONAL)) { ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, APLOGNO(01914) "Configuring server %s for SSL protocol", sc->vhost_id); - ssl_init_server_ctx(s, p, ptemp, sc); + if ((rv = ssl_init_server_ctx(s, p, ptemp, sc, pphrases)) + != APR_SUCCESS) { + return rv; + } } if (sc->proxy_enabled) { - ssl_init_proxy_ctx(s, p, ptemp, sc); + if ((rv = ssl_init_proxy_ctx(s, p, ptemp, sc)) != APR_SUCCESS) { + return rv; + } } + + return APR_SUCCESS; } -void ssl_init_CheckServers(server_rec *base_server, apr_pool_t *p) +apr_status_t ssl_init_CheckServers(server_rec *base_server, apr_pool_t *p) { server_rec *s, *ps; SSLSrvConfigRec *sc; @@ -1412,6 +1488,8 @@ void ssl_init_CheckServers(server_rec *base_server, apr_pool_t *p) "support (RFC 4366)"); #endif } + + return APR_SUCCESS; } static int ssl_init_FindCAList_X509NameCmp(const X509_NAME * const *a, @@ -1502,7 +1580,8 @@ STACK_OF(X509_NAME) *ssl_init_FindCAList(server_rec *s, ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s, APLOGNO(02211) "Failed to open Certificate Path `%s'", ca_path); - ssl_die(s); + sk_X509_NAME_pop_free(ca_list, X509_NAME_free); + return NULL; } while ((apr_dir_read(&direntry, finfo_flags, dir)) == APR_SUCCESS) { @@ -1579,21 +1658,6 @@ static void ssl_init_ctx_cleanup_proxy(modssl_ctx_t *mctx) } } -static void ssl_init_ctx_cleanup_server(modssl_ctx_t *mctx) -{ - int i; - - ssl_init_ctx_cleanup(mctx); - - for (i=0; i < SSL_AIDX_MAX; i++) { - MODSSL_CFG_ITEM_FREE(X509_free, - mctx->pks->certs[i]); - - MODSSL_CFG_ITEM_FREE(EVP_PKEY_free, - mctx->pks->keys[i]); - } -} - apr_status_t ssl_init_ModuleKill(void *data) { SSLSrvConfigRec *sc; @@ -1614,9 +1678,8 @@ apr_status_t ssl_init_ModuleKill(void *data) ssl_init_ctx_cleanup_proxy(sc->proxy); - ssl_init_ctx_cleanup_server(sc->server); + ssl_init_ctx_cleanup(sc->server); } return APR_SUCCESS; } - diff --git a/modules/ssl/ssl_engine_kernel.c b/modules/ssl/ssl_engine_kernel.c index 6d93ac99..c60f0a6c 100644 --- a/modules/ssl/ssl_engine_kernel.c +++ b/modules/ssl/ssl_engine_kernel.c @@ -163,48 +163,59 @@ int ssl_hook_ReadReq(request_rec *r) return DECLINED; } #ifdef HAVE_TLSEXT - if ((servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name))) { - char *host, *scope_id; - apr_port_t port; - apr_status_t rv; - - /* - * The SNI extension supplied a hostname. So don't accept requests - * with either no hostname or a different hostname. - */ - if (!r->hostname) { - ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, APLOGNO(02031) - "Hostname %s provided via SNI, but no hostname" - " provided in HTTP request", servername); - return HTTP_BAD_REQUEST; - } - rv = apr_parse_addr_port(&host, &scope_id, &port, r->hostname, r->pool); - if (rv != APR_SUCCESS || scope_id) { - return HTTP_BAD_REQUEST; + if (r->proxyreq != PROXYREQ_PROXY) { + if ((servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name))) { + char *host, *scope_id; + apr_port_t port; + apr_status_t rv; + + /* + * The SNI extension supplied a hostname. So don't accept requests + * with either no hostname or a different hostname as this could + * cause us to end up in a different virtual host as the one that + * was used for the handshake causing different SSL parameters to + * be applied as SSLProtocol, SSLCACertificateFile/Path and + * SSLCADNRequestFile/Path cannot be renegotioated (SSLCA* due + * to current limitiations in Openssl, see + * http://mail-archives.apache.org/mod_mbox/httpd-dev/200806.mbox/%3C48592955.2090303@velox.ch%3E + * and + * http://mail-archives.apache.org/mod_mbox/httpd-dev/201312.mbox/%3CCAKQ1sVNpOrdiBm-UPw1hEdSN7YQXRRjeaT-MCWbW_7mN%3DuFiOw%40mail.gmail.com%3E + * ) + */ + if (!r->hostname) { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, APLOGNO(02031) + "Hostname %s provided via SNI, but no hostname" + " provided in HTTP request", servername); + return HTTP_BAD_REQUEST; + } + rv = apr_parse_addr_port(&host, &scope_id, &port, r->hostname, r->pool); + if (rv != APR_SUCCESS || scope_id) { + return HTTP_BAD_REQUEST; + } + if (strcasecmp(host, servername)) { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, APLOGNO(02032) + "Hostname %s provided via SNI and hostname %s provided" + " via HTTP are different", servername, host); + return HTTP_BAD_REQUEST; + } } - if (strcasecmp(host, servername)) { - ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, APLOGNO(02032) - "Hostname %s provided via SNI and hostname %s provided" - " via HTTP are different", servername, host); - return HTTP_BAD_REQUEST; + else if (((sc->strict_sni_vhost_check == SSL_ENABLED_TRUE) + || (mySrvConfig(sslconn->server))->strict_sni_vhost_check + == SSL_ENABLED_TRUE) + && r->connection->vhost_lookup_data) { + /* + * We are using a name based configuration here, but no hostname was + * provided via SNI. Don't allow that if are requested to do strict + * checking. Check wether this strict checking was setup either in the + * server config we used for handshaking or in our current server. + * This should avoid insecure configuration by accident. + */ + ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, APLOGNO(02033) + "No hostname was provided via SNI for a name based" + " virtual host"); + return HTTP_FORBIDDEN; } } - else if (((sc->strict_sni_vhost_check == SSL_ENABLED_TRUE) - || (mySrvConfig(sslconn->server))->strict_sni_vhost_check - == SSL_ENABLED_TRUE) - && r->connection->vhost_lookup_data) { - /* - * We are using a name based configuration here, but no hostname was - * provided via SNI. Don't allow that if are requested to do strict - * checking. Check wether this strict checking was setup either in the - * server config we used for handshaking or in our current server. - * This should avoid insecure configuration by accident. - */ - ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, APLOGNO(02033) - "No hostname was provided via SNI for a name based" - " virtual host"); - return HTTP_FORBIDDEN; - } #endif SSL_set_app_data2(ssl, r); diff --git a/modules/ssl/ssl_engine_log.c b/modules/ssl/ssl_engine_log.c index 3f6d6edc..2c87638f 100644 --- a/modules/ssl/ssl_engine_log.c +++ b/modules/ssl/ssl_engine_log.c @@ -63,7 +63,7 @@ static const char *ssl_log_annotation(const char *error) return ssl_log_annotate[i].cpAnnotation; } -void ssl_die(server_rec *s) +apr_status_t ssl_die(server_rec *s) { if (s != NULL && s->is_virtual && s->error_fname != NULL) ap_log_error(APLOG_MARK, APLOG_EMERG, 0, NULL, APLOGNO(02311) @@ -75,13 +75,7 @@ void ssl_die(server_rec *s) ap_log_error(APLOG_MARK, APLOG_EMERG, 0, NULL, APLOGNO(02312) "Fatal error initialising mod_ssl, exiting."); - /* - * This is used for fatal errors and here - * it is common module practice to really - * exit from the complete program. - * XXX: The config hooks should return errors instead of calling exit(). - */ - exit(1); + return APR_EGENERAL; } /* diff --git a/modules/ssl/ssl_engine_pphrase.c b/modules/ssl/ssl_engine_pphrase.c index ca8e130f..df81d121 100644 --- a/modules/ssl/ssl_engine_pphrase.c +++ b/modules/ssl/ssl_engine_pphrase.c @@ -30,11 +30,25 @@ -- Clifford Stoll */ #include "ssl_private.h" +typedef struct { + server_rec *s; + apr_pool_t *p; + apr_array_header_t *aPassPhrase; + int nPassPhraseCur; + char *cpPassPhraseCur; + int nPassPhraseDialog; + int nPassPhraseDialogCur; + BOOL bPassPhraseDialogOnce; + const char *key_id; + const char *pkey_file; +} pphrase_cb_arg_t; + /* * Return true if the named file exists and is readable */ -static apr_status_t exists_and_readable(char *fname, apr_pool_t *pool, apr_time_t *mtime) +static apr_status_t exists_and_readable(const char *fname, apr_pool_t *pool, + apr_time_t *mtime) { apr_status_t stat; apr_finfo_t sbuf; @@ -73,11 +87,11 @@ static apr_status_t exists_and_readable(char *fname, apr_pool_t *pool, apr_time_ * since apr_array_push() will apr_alloc arr->nalloc * 2 elts, * leaving the original arr->elts to waste. */ -static char *asn1_table_vhost_key(SSLModConfigRec *mc, apr_pool_t *p, - char *id, char *an) +static const char *asn1_table_vhost_key(SSLModConfigRec *mc, apr_pool_t *p, + const char *id, int i) { /* 'p' pool used here is cleared on restarts (or sooner) */ - char *key = apr_psprintf(p, "%s:%s", id, an); + char *key = apr_psprintf(p, "%s:%d", id, i); void *keyptr = apr_hash_get(mc->tVHostKeys, key, APR_HASH_KEY_STRING); @@ -103,12 +117,6 @@ static char *asn1_table_vhost_key(SSLModConfigRec *mc, apr_pool_t *p, static apr_file_t *writetty = NULL; static apr_file_t *readtty = NULL; -/* - * sslc has a nasty flaw where its - * PEM_read_bio_PrivateKey does not take a callback arg. - */ -static server_rec *ssl_pphrase_server_rec = NULL; - int ssl_pphrase_Handle_CB(char *, int, int, void *); static char *pphrase_array_get(apr_array_header_t *arr, int idx) @@ -120,458 +128,260 @@ static char *pphrase_array_get(apr_array_header_t *arr, int idx) return ((char **)arr->elts)[idx]; } -static void pphrase_array_clear(apr_array_header_t *arr) -{ - if (arr->nelts > 0) { - memset(arr->elts, 0, arr->elt_size * arr->nelts); - } - arr->nelts = 0; -} - -/* Abandon all hope, ye who read this code. Don't believe the name: - * "passphrase handling" is really a peripheral (if complex) concern; - * the core purpose of this function to load into memory all - * configured certs and key from files. The private key handling in - * here should be split out into a separate function for improved - * readability. The myCtxVarGet abomination can be thrown away with - * SSLC support, vastly simplifying the code. */ -void ssl_pphrase_Handle(server_rec *s, apr_pool_t *p) +apr_status_t ssl_load_encrypted_pkey(server_rec *s, apr_pool_t *p, int idx, + const char *pkey_file, + apr_array_header_t **pphrases) { SSLModConfigRec *mc = myModConfig(s); - SSLSrvConfigRec *sc; - server_rec *pServ; - char *cpVHostID; - char szPath[MAX_STRING_LEN]; - EVP_PKEY *pPrivateKey; + SSLSrvConfigRec *sc = mySrvConfig(s); + const char *key_id = asn1_table_vhost_key(mc, p, sc->vhost_id, idx); + EVP_PKEY *pPrivateKey = NULL; ssl_asn1_t *asn1; unsigned char *ucp; long int length; - X509 *pX509Cert; BOOL bReadable; - apr_array_header_t *aPassPhrase; - int nPassPhrase; - int nPassPhraseCur; - char *cpPassPhraseCur; - int nPassPhraseRetry; - int nPassPhraseDialog; - int nPassPhraseDialogCur; - BOOL bPassPhraseDialogOnce; - char **cpp; - int i, j; - ssl_algo_t algoCert, algoKey, at; - char *an; + int nPassPhrase = (*pphrases)->nelts; + int nPassPhraseRetry = 0; apr_time_t pkey_mtime = 0; apr_status_t rv; - /* - * Start with a fresh pass phrase array - */ - aPassPhrase = apr_array_make(p, 2, sizeof(char *)); - nPassPhrase = 0; - nPassPhraseDialog = 0; + pphrase_cb_arg_t ppcb_arg; + + if (!pkey_file) { + ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02573) + "Init: No private key specified for %s", key_id); + return ssl_die(s); + } + else if ((rv = exists_and_readable(pkey_file, p, &pkey_mtime)) + != APR_SUCCESS ) { + ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s, APLOGNO(02574) + "Init: Can't open server private key file %s", pkey_file); + return ssl_die(s); + } + + ppcb_arg.s = s; + ppcb_arg.p = p; + ppcb_arg.aPassPhrase = *pphrases; + ppcb_arg.nPassPhraseCur = 0; + ppcb_arg.cpPassPhraseCur = NULL; + ppcb_arg.nPassPhraseDialog = 0; + ppcb_arg.nPassPhraseDialogCur = 0; + ppcb_arg.bPassPhraseDialogOnce = TRUE; + ppcb_arg.key_id = key_id; + ppcb_arg.pkey_file = pkey_file; /* - * Walk through all configured servers + * if the private key is encrypted and SSLPassPhraseDialog + * is configured to "builtin" it isn't possible to prompt for + * a password after httpd has detached from the tty. + * in this case if we already have a private key and the + * file name/mtime hasn't changed, then reuse the existing key. + * we also reuse existing private keys that were encrypted for + * exec: and pipe: dialogs to minimize chances to snoop the + * password. that and pipe: dialogs might prompt the user + * for password, which on win32 for example could happen 4 + * times at startup. twice for each child and twice within + * each since apache "restarts itself" on startup. + * of course this will not work for the builtin dialog if + * the server was started without LoadModule ssl_module + * configured, then restarted with it configured. + * but we fall through with a chance of success if the key + * is not encrypted or can be handled via exec or pipe dialog. + * and in the case of fallthrough, pkey_mtime and isatty() + * are used to give a better idea as to what failed. */ - for (pServ = s; pServ != NULL; pServ = pServ->next) { - sc = mySrvConfig(pServ); - cpVHostID = ssl_util_vhostid(p, pServ); - if (!sc->enabled) { - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, pServ, APLOGNO(02199) - "SSL not enabled on vhost %s, skipping SSL setup", - cpVHostID); - continue; + if (pkey_mtime) { + ssl_asn1_t *asn1 = ssl_asn1_table_get(mc->tPrivateKey, key_id); + if (asn1 && (asn1->source_mtime == pkey_mtime)) { + ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, APLOGNO(02575) + "Reusing existing private key from %s on restart", + ppcb_arg.pkey_file); + return APR_SUCCESS; } + } - ap_log_error(APLOG_MARK, APLOG_INFO, 0, pServ, APLOGNO(02200) - "Loading certificate & private key of SSL-aware server '%s'", - cpVHostID); + ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, APLOGNO(02576) + "Attempting to load encrypted (?) private key %s", key_id); + for (;;) { /* - * Read in server certificate(s): This is the easy part - * because this file isn't encrypted in any way. + * Try to read the private key file with the help of + * the callback function which serves the pass + * phrases to OpenSSL */ - if (sc->server->pks->cert_files[0] == NULL - && sc->server->pkcs7 == NULL) { - ap_log_error(APLOG_MARK, APLOG_EMERG, 0, pServ, APLOGNO(02240) - "Server should be SSL-aware but has no certificate " - "configured [Hint: SSLCertificateFile] (%s:%d)", - pServ->defn_name, pServ->defn_line_number); - ssl_die(pServ); - } - - /* Bitmasks for all key algorithms configured for this server; - * initialize to zero. */ - algoCert = SSL_ALGO_UNKNOWN; - algoKey = SSL_ALGO_UNKNOWN; - - /* Iterate through configured certificate files for this - * server. */ - for (i = 0, j = 0; i < SSL_AIDX_MAX - && (sc->server->pks->cert_files[i] != NULL - || sc->server->pkcs7); i++) { - const char *key_id; - int using_cache = 0; - - if (sc->server->pkcs7) { - STACK_OF(X509) *certs = ssl_read_pkcs7(pServ, - sc->server->pkcs7); - pX509Cert = sk_X509_value(certs, 0); - i = SSL_AIDX_MAX; - } else { - apr_cpystrn(szPath, sc->server->pks->cert_files[i], - sizeof(szPath)); - if ((rv = exists_and_readable(szPath, p, NULL)) - != APR_SUCCESS) { - ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s, APLOGNO(02201) - "Init: Can't open server certificate file %s", - szPath); - ssl_die(s); - } - if ((pX509Cert = SSL_read_X509(szPath, NULL, NULL)) == NULL) { - ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02241) - "Init: Unable to read server certificate from" - " file %s", szPath); - ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s); - ssl_die(s); - } - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(02202) - "Init: Read server certificate from '%s'", - szPath); - } - /* - * check algorithm type of certificate and make - * sure only one certificate per type is used. - */ - at = ssl_util_algotypeof(pX509Cert, NULL); - an = ssl_util_algotypestr(at); - if (algoCert & at) { - ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02242) - "Init: Multiple %s server certificates not " - "allowed", an); - ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s); - ssl_die(s); - } - algoCert |= at; - - /* Determine the hash key used for this (vhost, algo-type) - * pair used to index both the mc->tPrivateKey and - * mc->tPublicCert tables: */ - key_id = asn1_table_vhost_key(mc, p, cpVHostID, an); - /* - * Insert the certificate into global module configuration to let it - * survive the processing between the 1st Apache API init round (where - * we operate here) and the 2nd Apache init round (where the - * certificate is actually used to configure mod_ssl's per-server - * configuration structures). - */ - length = i2d_X509(pX509Cert, NULL); - ucp = ssl_asn1_table_set(mc->tPublicCert, key_id, length); - (void)i2d_X509(pX509Cert, &ucp); /* 2nd arg increments */ + ppcb_arg.cpPassPhraseCur = NULL; - /* - * Free the X509 structure - */ - X509_free(pX509Cert); - - /* - * Read in the private key: This is the non-trivial part, because the - * key is typically encrypted, so a pass phrase dialog has to be used - * to request it from the user (or it has to be alternatively gathered - * from a dialog program). The important point here is that ISPs - * usually have hundrets of virtual servers configured and a lot of - * them use SSL, so really we have to minimize the pass phrase - * dialogs. - * - * The idea is this: When N virtual hosts are configured and all of - * them use encrypted private keys with different pass phrases, we - * have no chance and have to pop up N pass phrase dialogs. But - * usually the admin is clever enough and uses the same pass phrase - * for more private key files (typically he even uses one single pass - * phrase for all). When this is the case we can minimize the dialogs - * by trying to re-use already known/entered pass phrases. - */ - if (sc->server->pks->key_files[j] != NULL) - apr_cpystrn(szPath, sc->server->pks->key_files[j++], sizeof(szPath)); + /* Ensure that the error stack is empty; some SSL + * functions will fail spuriously if the error stack + * is not empty. */ + ERR_clear_error(); - /* - * Try to read the private key file with the help of - * the callback function which serves the pass - * phrases to OpenSSL - */ - myCtxVarSet(mc, 1, pServ); - myCtxVarSet(mc, 2, p); - myCtxVarSet(mc, 3, aPassPhrase); - myCtxVarSet(mc, 4, &nPassPhraseCur); - myCtxVarSet(mc, 5, &cpPassPhraseCur); - myCtxVarSet(mc, 6, cpVHostID); - myCtxVarSet(mc, 7, an); - myCtxVarSet(mc, 8, &nPassPhraseDialog); - myCtxVarSet(mc, 9, &nPassPhraseDialogCur); - myCtxVarSet(mc, 10, &bPassPhraseDialogOnce); - - nPassPhraseCur = 0; - nPassPhraseRetry = 0; - nPassPhraseDialogCur = 0; - bPassPhraseDialogOnce = TRUE; - - pPrivateKey = NULL; - - for (;;) { - /* - * Try to read the private key file with the help of - * the callback function which serves the pass - * phrases to OpenSSL - */ - if ((rv = exists_and_readable(szPath, p, - &pkey_mtime)) != APR_SUCCESS ) { - ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s, APLOGNO(02243) - "Init: Can't open server private key file " - "%s",szPath); - ssl_die(s); - } + bReadable = ((pPrivateKey = SSL_read_PrivateKey(ppcb_arg.pkey_file, + NULL, ssl_pphrase_Handle_CB, &ppcb_arg)) != NULL ? + TRUE : FALSE); - /* - * if the private key is encrypted and SSLPassPhraseDialog - * is configured to "builtin" it isn't possible to prompt for - * a password after httpd has detached from the tty. - * in this case if we already have a private key and the - * file name/mtime hasn't changed, then reuse the existing key. - * we also reuse existing private keys that were encrypted for - * exec: and pipe: dialogs to minimize chances to snoop the - * password. that and pipe: dialogs might prompt the user - * for password, which on win32 for example could happen 4 - * times at startup. twice for each child and twice within - * each since apache "restarts itself" on startup. - * of course this will not work for the builtin dialog if - * the server was started without LoadModule ssl_module - * configured, then restarted with it configured. - * but we fall through with a chance of success if the key - * is not encrypted or can be handled via exec or pipe dialog. - * and in the case of fallthrough, pkey_mtime and isatty() - * are used to give a better idea as to what failed. - */ - if (pkey_mtime) { - ssl_asn1_t *asn1 = - ssl_asn1_table_get(mc->tPrivateKey, key_id); - - if (asn1 && (asn1->source_mtime == pkey_mtime)) { - ap_log_error(APLOG_MARK, APLOG_INFO, - 0, pServ, APLOGNO(02244) - "%s reusing existing " - "%s private key on restart", - cpVHostID, ssl_asn1_keystr(i)); - using_cache = 1; - break; - } - } + /* + * when the private key file now was readable, + * it's fine and we go out of the loop + */ + if (bReadable) + break; - cpPassPhraseCur = NULL; - ssl_pphrase_server_rec = s; /* to make up for sslc flaw */ - - /* Ensure that the error stack is empty; some SSL - * functions will fail spuriously if the error stack - * is not empty. */ - ERR_clear_error(); - - bReadable = ((pPrivateKey = SSL_read_PrivateKey(szPath, NULL, - ssl_pphrase_Handle_CB, s)) != NULL ? TRUE : FALSE); - - /* - * when the private key file now was readable, - * it's fine and we go out of the loop - */ - if (bReadable) - break; - - /* - * when we have more remembered pass phrases - * try to reuse these first. - */ - if (nPassPhraseCur < nPassPhrase) { - nPassPhraseCur++; - continue; - } + /* + * when we have more remembered pass phrases + * try to reuse these first. + */ + if (ppcb_arg.nPassPhraseCur < nPassPhrase) { + ppcb_arg.nPassPhraseCur++; + continue; + } - /* - * else it's not readable and we have no more - * remembered pass phrases. Then this has to mean - * that the callback function popped up the dialog - * but a wrong pass phrase was entered. We give the - * user (but not the dialog program) a few more - * chances... - */ + /* + * else it's not readable and we have no more + * remembered pass phrases. Then this has to mean + * that the callback function popped up the dialog + * but a wrong pass phrase was entered. We give the + * user (but not the dialog program) a few more + * chances... + */ #ifndef WIN32 - if ((sc->server->pphrase_dialog_type == SSL_PPTYPE_BUILTIN - || sc->server->pphrase_dialog_type == SSL_PPTYPE_PIPE) + if ((sc->server->pphrase_dialog_type == SSL_PPTYPE_BUILTIN + || sc->server->pphrase_dialog_type == SSL_PPTYPE_PIPE) #else - if (sc->server->pphrase_dialog_type == SSL_PPTYPE_PIPE + if (sc->server->pphrase_dialog_type == SSL_PPTYPE_PIPE #endif - && cpPassPhraseCur != NULL - && nPassPhraseRetry < BUILTIN_DIALOG_RETRIES ) { - apr_file_printf(writetty, "Apache:mod_ssl:Error: Pass phrase incorrect " - "(%d more retr%s permitted).\n", - (BUILTIN_DIALOG_RETRIES-nPassPhraseRetry), - (BUILTIN_DIALOG_RETRIES-nPassPhraseRetry) == 1 ? "y" : "ies"); - nPassPhraseRetry++; - if (nPassPhraseRetry > BUILTIN_DIALOG_BACKOFF) - apr_sleep((nPassPhraseRetry-BUILTIN_DIALOG_BACKOFF) - * 5 * APR_USEC_PER_SEC); - continue; - } + && ppcb_arg.cpPassPhraseCur != NULL + && nPassPhraseRetry < BUILTIN_DIALOG_RETRIES ) { + apr_file_printf(writetty, "Apache:mod_ssl:Error: Pass phrase incorrect " + "(%d more retr%s permitted).\n", + (BUILTIN_DIALOG_RETRIES-nPassPhraseRetry), + (BUILTIN_DIALOG_RETRIES-nPassPhraseRetry) == 1 ? "y" : "ies"); + nPassPhraseRetry++; + if (nPassPhraseRetry > BUILTIN_DIALOG_BACKOFF) + apr_sleep((nPassPhraseRetry-BUILTIN_DIALOG_BACKOFF) + * 5 * APR_USEC_PER_SEC); + continue; + } #ifdef WIN32 - if (sc->server->pphrase_dialog_type == SSL_PPTYPE_BUILTIN) { - ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02245) - "Init: SSLPassPhraseDialog builtin is not " - "supported on Win32 (key file " - "%s)", szPath); - ssl_die(s); - } + if (sc->server->pphrase_dialog_type == SSL_PPTYPE_BUILTIN) { + ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02577) + "Init: SSLPassPhraseDialog builtin is not " + "supported on Win32 (key file " + "%s)", ppcb_arg.pkey_file); + return ssl_die(s); + } #endif /* WIN32 */ - /* - * Ok, anything else now means a fatal error. - */ - if (cpPassPhraseCur == NULL) { - if (nPassPhraseDialogCur && pkey_mtime && - !isatty(fileno(stdout))) /* XXX: apr_isatty() */ - { - ap_log_error(APLOG_MARK, APLOG_ERR, 0, - pServ, APLOGNO(02246) - "Init: Unable to read pass phrase " - "[Hint: key introduced or changed " - "before restart?]"); - ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, pServ); - } - else { - ap_log_error(APLOG_MARK, APLOG_ERR, 0, - pServ, APLOGNO(02203) "Init: Private key not found"); - ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, pServ); - } - if (writetty) { - apr_file_printf(writetty, "Apache:mod_ssl:Error: Private key not found.\n"); - apr_file_printf(writetty, "**Stopped\n"); - } - } - else { - ap_log_error(APLOG_MARK, APLOG_EMERG, 0, pServ, APLOGNO(02204) - "Init: Pass phrase incorrect for key of %s", - cpVHostID); - ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, pServ); - - if (writetty) { - apr_file_printf(writetty, "Apache:mod_ssl:Error: Pass phrase incorrect.\n"); - apr_file_printf(writetty, "**Stopped\n"); - } - } - ssl_die(pServ); - } - - /* If a cached private key was found, nothing more to do - * here; loop through to the next configured cert for this - * vhost. */ - if (using_cache) - continue; - - if (pPrivateKey == NULL) { - ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02247) - "Init: Unable to read server private key from " - "file %s [Hint: Perhaps it is in a separate file? " - " See SSLCertificateKeyFile]", szPath); - ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s); - ssl_die(s); - } - - /* - * check algorithm type of private key and make - * sure only one private key per type is used. - */ - at = ssl_util_algotypeof(NULL, pPrivateKey); - an = ssl_util_algotypestr(at); - if (algoKey & at) { - ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02248) - "Init: Multiple %s server private keys not " - "allowed", an); - ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s); - ssl_die(s); - } - algoKey |= at; - - /* - * Log the type of reading - */ - if (nPassPhraseDialogCur == 0) { - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, pServ, APLOGNO(02249) - "unencrypted %s private key - pass phrase not " - "required", an); + /* + * Ok, anything else now means a fatal error. + */ + if (ppcb_arg.cpPassPhraseCur == NULL) { + if (ppcb_arg.nPassPhraseDialogCur && pkey_mtime && + !isatty(fileno(stdout))) /* XXX: apr_isatty() */ + { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, + s, APLOGNO(02578) + "Init: Unable to read pass phrase " + "[Hint: key introduced or changed " + "before restart?]"); + ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, s); } else { - if (cpPassPhraseCur != NULL) { - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, - pServ, APLOGNO(02250) - "encrypted %s private key - pass phrase " - "requested", an); - } - else { - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, - pServ, APLOGNO(02251) - "encrypted %s private key - pass phrase" - " reused", an); - } + ap_log_error(APLOG_MARK, APLOG_ERR, 0, + s, APLOGNO(02579) "Init: Private key not found"); + ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, s); } - - /* - * Ok, when we have one more pass phrase store it - */ - if (cpPassPhraseCur != NULL) { - cpp = (char **)apr_array_push(aPassPhrase); - *cpp = cpPassPhraseCur; - nPassPhrase++; + if (writetty) { + apr_file_printf(writetty, "Apache:mod_ssl:Error: Private key not found.\n"); + apr_file_printf(writetty, "**Stopped\n"); } - - /* - * Insert private key into the global module configuration - * (we convert it to a stand-alone DER byte sequence - * because the SSL library uses static variables inside a - * RSA structure which do not survive DSO reloads!) - */ - length = i2d_PrivateKey(pPrivateKey, NULL); - ucp = ssl_asn1_table_set(mc->tPrivateKey, key_id, length); - (void)i2d_PrivateKey(pPrivateKey, &ucp); /* 2nd arg increments */ - - if (nPassPhraseDialogCur != 0) { - /* remember mtime of encrypted keys */ - asn1 = ssl_asn1_table_get(mc->tPrivateKey, key_id); - asn1->source_mtime = pkey_mtime; + } + else { + ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02580) + "Init: Pass phrase incorrect for key %s", + key_id); + ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s); + + if (writetty) { + apr_file_printf(writetty, "Apache:mod_ssl:Error: Pass phrase incorrect.\n"); + apr_file_printf(writetty, "**Stopped\n"); } + } + return ssl_die(s); + } - /* - * Free the private key structure - */ - EVP_PKEY_free(pPrivateKey); + if (pPrivateKey == NULL) { + ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02581) + "Init: Unable to read server private key from file %s", + ppcb_arg.pkey_file); + ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s); + return ssl_die(s); + } + + /* + * Log the type of reading + */ + if (ppcb_arg.nPassPhraseDialogCur == 0) { + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(02582) + "unencrypted %s private key - pass phrase not " + "required", key_id); + } + else { + if (ppcb_arg.cpPassPhraseCur != NULL) { + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, + s, APLOGNO(02583) + "encrypted %s private key - pass phrase " + "requested", key_id); + } + else { + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, + s, APLOGNO(02584) + "encrypted %s private key - pass phrase" + " reused", key_id); } } /* + * Ok, when we have one more pass phrase store it + */ + if (ppcb_arg.cpPassPhraseCur != NULL) { + *(const char **)apr_array_push(ppcb_arg.aPassPhrase) = + ppcb_arg.cpPassPhraseCur; + nPassPhrase++; + } + + /* + * Insert private key into the global module configuration + * (we convert it to a stand-alone DER byte sequence + * because the SSL library uses static variables inside a + * RSA structure which do not survive DSO reloads!) + */ + length = i2d_PrivateKey(pPrivateKey, NULL); + ucp = ssl_asn1_table_set(mc->tPrivateKey, key_id, length); + (void)i2d_PrivateKey(pPrivateKey, &ucp); /* 2nd arg increments */ + + if (ppcb_arg.nPassPhraseDialogCur != 0) { + /* remember mtime of encrypted keys */ + asn1 = ssl_asn1_table_get(mc->tPrivateKey, key_id); + asn1->source_mtime = pkey_mtime; + } + + /* + * Free the private key structure + */ + EVP_PKEY_free(pPrivateKey); + + /* * Let the user know when we're successful. */ - if (nPassPhraseDialog > 0) { + if ((ppcb_arg.nPassPhraseDialog > 0) && + (ppcb_arg.cpPassPhraseCur != NULL)) { if (writetty) { apr_file_printf(writetty, "\n" "OK: Pass Phrase Dialog successful.\n"); } } - /* - * Wipe out the used memory from the - * pass phrase array and then deallocate it - */ - if (aPassPhrase->nelts) { - pphrase_array_clear(aPassPhrase); - ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, APLOGNO(02205) - "Init: Wiped out the queried pass phrases from memory"); - } - /* Close the pipes if they were opened */ if (readtty) { @@ -579,7 +389,8 @@ void ssl_pphrase_Handle(server_rec *s, apr_pool_t *p) apr_file_close(writetty); readtty = writetty = NULL; } - return; + + return APR_SUCCESS; } static apr_status_t ssl_pipe_child_create(apr_pool_t *p, const char *progname) @@ -646,45 +457,19 @@ static int pipe_get_passwd_cb(char *buf, int length, char *prompt, int verify) int ssl_pphrase_Handle_CB(char *buf, int bufsize, int verify, void *srv) { - SSLModConfigRec *mc; - server_rec *s; - apr_pool_t *p; - apr_array_header_t *aPassPhrase; - SSLSrvConfigRec *sc; - int *pnPassPhraseCur; - char **cppPassPhraseCur; - char *cpVHostID; - char *cpAlgoType; - int *pnPassPhraseDialog; - int *pnPassPhraseDialogCur; - BOOL *pbPassPhraseDialogOnce; + pphrase_cb_arg_t *ppcb_arg = (pphrase_cb_arg_t *)srv; + SSLSrvConfigRec *sc = mySrvConfig(ppcb_arg->s); char *cpp; int len = -1; - mc = myModConfig((server_rec *)srv); - - /* - * Reconnect to the context of ssl_phrase_Handle() - */ - s = myCtxVarGet(mc, 1, server_rec *); - p = myCtxVarGet(mc, 2, apr_pool_t *); - aPassPhrase = myCtxVarGet(mc, 3, apr_array_header_t *); - pnPassPhraseCur = myCtxVarGet(mc, 4, int *); - cppPassPhraseCur = myCtxVarGet(mc, 5, char **); - cpVHostID = myCtxVarGet(mc, 6, char *); - cpAlgoType = myCtxVarGet(mc, 7, char *); - pnPassPhraseDialog = myCtxVarGet(mc, 8, int *); - pnPassPhraseDialogCur = myCtxVarGet(mc, 9, int *); - pbPassPhraseDialogOnce = myCtxVarGet(mc, 10, BOOL *); - sc = mySrvConfig(s); - - (*pnPassPhraseDialog)++; - (*pnPassPhraseDialogCur)++; + ppcb_arg->nPassPhraseDialog++; + ppcb_arg->nPassPhraseDialogCur++; /* * When remembered pass phrases are available use them... */ - if ((cpp = pphrase_array_get(aPassPhrase, *pnPassPhraseCur)) != NULL) { + if ((cpp = pphrase_array_get(ppcb_arg->aPassPhrase, + ppcb_arg->nPassPhraseCur)) != NULL) { apr_cpystrn(buf, cpp, bufsize); len = strlen(buf); return len; @@ -700,25 +485,29 @@ int ssl_pphrase_Handle_CB(char *buf, int bufsize, int verify, void *srv) if (sc->server->pphrase_dialog_type == SSL_PPTYPE_PIPE) { if (!readtty) { - ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, APLOGNO(01965) + ap_log_error(APLOG_MARK, APLOG_INFO, 0, ppcb_arg->s, + APLOGNO(01965) "Init: Creating pass phrase dialog pipe child " "'%s'", sc->server->pphrase_dialog_path); - if (ssl_pipe_child_create(p, sc->server->pphrase_dialog_path) + if (ssl_pipe_child_create(ppcb_arg->p, + sc->server->pphrase_dialog_path) != APR_SUCCESS) { - ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(01966) + ap_log_error(APLOG_MARK, APLOG_ERR, 0, ppcb_arg->s, + APLOGNO(01966) "Init: Failed to create pass phrase pipe '%s'", sc->server->pphrase_dialog_path); - PEMerr(PEM_F_PEM_DEF_CALLBACK,PEM_R_PROBLEMS_GETTING_PASSWORD); + PEMerr(PEM_F_PEM_DEF_CALLBACK, + PEM_R_PROBLEMS_GETTING_PASSWORD); memset(buf, 0, (unsigned int)bufsize); return (-1); } } - ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, APLOGNO(01967) + ap_log_error(APLOG_MARK, APLOG_INFO, 0, ppcb_arg->s, APLOGNO(01967) "Init: Requesting pass phrase via piped dialog"); } else { /* sc->server->pphrase_dialog_type == SSL_PPTYPE_BUILTIN */ #ifdef WIN32 - PEMerr(PEM_F_PEM_DEF_CALLBACK,PEM_R_PROBLEMS_GETTING_PASSWORD); + PEMerr(PEM_F_PEM_DEF_CALLBACK, PEM_R_PROBLEMS_GETTING_PASSWORD); memset(buf, 0, (unsigned int)bufsize); return (-1); #else @@ -728,9 +517,9 @@ int ssl_pphrase_Handle_CB(char *buf, int bufsize, int verify, void *srv) * we print the prompt to stdout before EVP_read_pw_string turns * off tty echo */ - apr_file_open_stdout(&writetty, p); + apr_file_open_stdout(&writetty, ppcb_arg->p); - ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, APLOGNO(01968) + ap_log_error(APLOG_MARK, APLOG_INFO, 0, ppcb_arg->s, APLOGNO(01968) "Init: Requesting pass phrase via builtin terminal " "dialog"); #endif @@ -742,16 +531,17 @@ int ssl_pphrase_Handle_CB(char *buf, int bufsize, int verify, void *srv) * this terminal dialog and why to the hell he has to enter * something... */ - if (*pnPassPhraseDialog == 1) { + if (ppcb_arg->nPassPhraseDialog == 1) { apr_file_printf(writetty, "%s mod_ssl (Pass Phrase Dialog)\n", AP_SERVER_BASEVERSION); apr_file_printf(writetty, "Some of your private key files are encrypted for security reasons.\n"); apr_file_printf(writetty, "In order to read them you have to provide the pass phrases.\n"); } - if (*pbPassPhraseDialogOnce) { - *pbPassPhraseDialogOnce = FALSE; + if (ppcb_arg->bPassPhraseDialogOnce) { + ppcb_arg->bPassPhraseDialogOnce = FALSE; apr_file_printf(writetty, "\n"); - apr_file_printf(writetty, "Server %s (%s)\n", cpVHostID, cpAlgoType); + apr_file_printf(writetty, "Private key %s (%s)\n", + ppcb_arg->key_id, ppcb_arg->pkey_file); } /* @@ -786,19 +576,18 @@ int ssl_pphrase_Handle_CB(char *buf, int bufsize, int verify, void *srv) */ else if (sc->server->pphrase_dialog_type == SSL_PPTYPE_FILTER) { const char *cmd = sc->server->pphrase_dialog_path; - const char **argv = apr_palloc(p, sizeof(char *) * 4); + const char **argv = apr_palloc(ppcb_arg->p, sizeof(char *) * 3); char *result; - ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, APLOGNO(01969) + ap_log_error(APLOG_MARK, APLOG_INFO, 0, ppcb_arg->s, APLOGNO(01969) "Init: Requesting pass phrase from dialog filter " "program (%s)", cmd); argv[0] = cmd; - argv[1] = cpVHostID; - argv[2] = cpAlgoType; - argv[3] = NULL; + argv[1] = ppcb_arg->key_id; + argv[2] = NULL; - result = ssl_util_readfilter(s, p, cmd, argv); + result = ssl_util_readfilter(ppcb_arg->s, ppcb_arg->p, cmd, argv); apr_cpystrn(buf, result, bufsize); len = strlen(buf); } @@ -806,11 +595,10 @@ int ssl_pphrase_Handle_CB(char *buf, int bufsize, int verify, void *srv) /* * Ok, we now have the pass phrase, so give it back */ - *cppPassPhraseCur = apr_pstrdup(p, buf); + ppcb_arg->cpPassPhraseCur = apr_pstrdup(ppcb_arg->p, buf); /* * And return its length to OpenSSL... */ return (len); } - diff --git a/modules/ssl/ssl_private.h b/modules/ssl/ssl_private.h index 4ea924f3..516d7e65 100644 --- a/modules/ssl/ssl_private.h +++ b/modules/ssl/ssl_private.h @@ -131,6 +131,10 @@ #define HAVE_TLSV1_X #endif +#if defined(SSL_CONF_FLAG_FILE) +#define HAVE_SSL_CONF_CMD +#endif + /** * The following features all depend on TLS extension support. * Within this block, check again for features (not version numbers). @@ -232,9 +236,6 @@ ap_set_module_config(c->conn_config, &ssl_module, val) #define mySrvConfigFromConn(c) mySrvConfig(mySrvFromConn(c)) #define myModConfigFromConn(c) myModConfig(mySrvFromConn(c)) -#define myCtxVarSet(mc,num,val) mc->rCtx.pV##num = val -#define myCtxVarGet(mc,num,type) (type)(mc->rCtx.pV##num) - /** * Defaults for the configuration */ @@ -258,31 +259,6 @@ ap_set_module_config(c->conn_config, &ssl_module, val) #endif /** - * Define the certificate algorithm types - */ - -typedef int ssl_algo_t; - -#define SSL_ALGO_UNKNOWN (0) -#define SSL_ALGO_RSA (1<<0) -#define SSL_ALGO_DSA (1<<1) -#ifdef HAVE_ECC -#define SSL_ALGO_ECC (1<<2) -#define SSL_ALGO_ALL (SSL_ALGO_RSA|SSL_ALGO_DSA|SSL_ALGO_ECC) -#else -#define SSL_ALGO_ALL (SSL_ALGO_RSA|SSL_ALGO_DSA) -#endif - -#define SSL_AIDX_RSA (0) -#define SSL_AIDX_DSA (1) -#ifdef HAVE_ECC -#define SSL_AIDX_ECC (2) -#define SSL_AIDX_MAX (3) -#else -#define SSL_AIDX_MAX (2) -#endif - -/** * Define the SSL options */ #define SSL_OPT_NONE (0) @@ -498,13 +474,10 @@ typedef struct { apr_array_header_t *aRandSeed; apr_hash_t *tVHostKeys; - /* Two hash tables of pointers to ssl_asn1_t structures. The - * structures are used to store certificates and private keys - * respectively, in raw DER format (serialized OpenSSL X509 and - * PrivateKey structures). The tables are indexed by (vhost-id, - * algorithm type) using the function ssl_asn1_table_keyfmt(); for - * example the string "vhost.example.com:443:RSA". */ - apr_hash_t *tPublicCert; + /* A hash table of pointers to ssl_asn1_t structures. The structures + * are used to store private keys in raw DER format (serialized OpenSSL + * PrivateKey structures). The table is indexed by (vhost-id, + * index), for example the string "vhost.example.com:443:0". */ apr_hash_t *tPrivateKey; #if defined(HAVE_OPENSSL_ENGINE_H) && defined(HAVE_ENGINE_INIT) @@ -516,27 +489,14 @@ typedef struct { ap_socache_instance_t *stapling_cache_context; apr_global_mutex_t *stapling_mutex; #endif - - struct { - void *pV1, *pV2, *pV3, *pV4, *pV5, *pV6, *pV7, *pV8, *pV9, *pV10; - } rCtx; } SSLModConfigRec; /** Structure representing configured filenames for certs and keys for - * a given vhost, and the corresponding in-memory structures once the - * files are parsed. */ + * a given vhost */ typedef struct { - /* Lists of configured certs and keys for this server; from index - * 0 up to SSL_AIDX_MAX-1 or the first NULL pointer. Note that - * these arrays are NOT indexed by algorithm type, they are simply - * unordered lists. */ - const char *cert_files[SSL_AIDX_MAX]; - const char *key_files[SSL_AIDX_MAX]; - /* Loaded certs and keys; these arrays ARE indexed by the - * algorithm type, i.e. keys[SSL_AIDX_RSA] maps to the RSA - * private key. */ - X509 *certs[SSL_AIDX_MAX]; - EVP_PKEY *keys[SSL_AIDX_MAX]; + /* Lists of configured certs and keys for this server */ + apr_array_header_t *cert_files; + apr_array_header_t *key_files; /** Certificates which specify the set of CA names which should be * sent in the CertificateRequest message: */ @@ -577,6 +537,13 @@ typedef struct { } modssl_ticket_key_t; #endif +#ifdef HAVE_SSL_CONF_CMD +typedef struct { + const char *name; + const char *value; +} ssl_ctx_param_t; +#endif + typedef struct SSLSrvConfigRec SSLSrvConfigRec; typedef struct { @@ -598,7 +565,6 @@ typedef struct { const char *pphrase_dialog_path; const char *cert_chain; - const char *pkcs7; /** certificate revocation list */ const char *crl_path; @@ -633,7 +599,10 @@ typedef struct { long ocsp_resptime_skew; long ocsp_resp_maxage; apr_interval_time_t ocsp_responder_timeout; - +#ifdef HAVE_SSL_CONF_CMD + SSL_CONF_CTX *ssl_ctx_config; /* Configuration context */ + apr_array_header_t *ssl_ctx_param; /* parameters to pass to SSL_CTX */ +#endif } modssl_ctx_t; struct SSLSrvConfigRec { @@ -704,7 +673,6 @@ const char *ssl_cmd_SSLCipherSuite(cmd_parms *, void *, const char *); const char *ssl_cmd_SSLCertificateFile(cmd_parms *, void *, const char *); const char *ssl_cmd_SSLCertificateKeyFile(cmd_parms *, void *, const char *); const char *ssl_cmd_SSLCertificateChainFile(cmd_parms *, void *, const char *); -const char *ssl_cmd_SSLPKCS7CertificateFile(cmd_parms *, void *, const char *); const char *ssl_cmd_SSLCACertificatePath(cmd_parms *, void *, const char *); const char *ssl_cmd_SSLCACertificateFile(cmd_parms *, void *, const char *); const char *ssl_cmd_SSLCADNRequestPath(cmd_parms *, void *, const char *); @@ -754,6 +722,10 @@ const char *ssl_cmd_SSLOCSPResponseMaxAge(cmd_parms *cmd, void *dcfg, const char const char *ssl_cmd_SSLOCSPResponderTimeout(cmd_parms *cmd, void *dcfg, const char *arg); const char *ssl_cmd_SSLOCSPEnable(cmd_parms *cmd, void *dcfg, int flag); +#ifdef HAVE_SSL_CONF_CMD +const char *ssl_cmd_SSLOpenSSLConfCmd(cmd_parms *cmd, void *dcfg, const char *arg1, const char *arg2); +#endif + #ifdef HAVE_SRP const char *ssl_cmd_SSLSRPVerifierFile(cmd_parms *cmd, void *dcfg, const char *arg); const char *ssl_cmd_SSLSRPUnknownUserSeed(cmd_parms *cmd, void *dcfg, const char *arg); @@ -762,10 +734,11 @@ const char *ssl_cmd_SSLSRPUnknownUserSeed(cmd_parms *cmd, void *dcfg, const char const char *ssl_cmd_SSLFIPS(cmd_parms *cmd, void *dcfg, int flag); /** module initialization */ -int ssl_init_Module(apr_pool_t *, apr_pool_t *, apr_pool_t *, server_rec *); -void ssl_init_Engine(server_rec *, apr_pool_t *); -void ssl_init_ConfigureServer(server_rec *, apr_pool_t *, apr_pool_t *, SSLSrvConfigRec *); -void ssl_init_CheckServers(server_rec *, apr_pool_t *); +apr_status_t ssl_init_Module(apr_pool_t *, apr_pool_t *, apr_pool_t *, server_rec *); +apr_status_t ssl_init_Engine(server_rec *, apr_pool_t *); +apr_status_t ssl_init_ConfigureServer(server_rec *, apr_pool_t *, apr_pool_t *, SSLSrvConfigRec *, + apr_array_header_t *); +apr_status_t ssl_init_CheckServers(server_rec *, apr_pool_t *); STACK_OF(X509_NAME) *ssl_init_FindCAList(server_rec *, apr_pool_t *, const char *, const char *); void ssl_init_Child(apr_pool_t *, server_rec *); @@ -802,7 +775,7 @@ int ssl_callback_SessionTicket(SSL *, unsigned char *, unsigned char *, #endif /** Session Cache Support */ -void ssl_scache_init(server_rec *, apr_pool_t *); +apr_status_t ssl_scache_init(server_rec *, apr_pool_t *); void ssl_scache_status_register(apr_pool_t *p); void ssl_scache_kill(server_rec *); BOOL ssl_scache_store(server_rec *, UCHAR *, int, @@ -827,7 +800,7 @@ const char *ssl_cmd_SSLStaplingReturnResponderErrors(cmd_parms *, void *, int); const char *ssl_cmd_SSLStaplingFakeTryLater(cmd_parms *, void *, int); const char *ssl_cmd_SSLStaplingResponderTimeout(cmd_parms *, void *, const char *); const char *ssl_cmd_SSLStaplingForceURL(cmd_parms *, void *, const char *); -void modssl_init_stapling(server_rec *, apr_pool_t *, apr_pool_t *, modssl_ctx_t *); +apr_status_t modssl_init_stapling(server_rec *, apr_pool_t *, apr_pool_t *, modssl_ctx_t *); void ssl_stapling_ex_init(void); int ssl_stapling_init_cert(server_rec *s, modssl_ctx_t *mctx, X509 *x); #endif @@ -855,13 +828,12 @@ void ssl_util_ppclose(server_rec *, apr_pool_t *, apr_file_t *); char *ssl_util_readfilter(server_rec *, apr_pool_t *, const char *, const char * const *); BOOL ssl_util_path_check(ssl_pathcheck_t, const char *, apr_pool_t *); -ssl_algo_t ssl_util_algotypeof(X509 *, EVP_PKEY *); -char *ssl_util_algotypestr(ssl_algo_t); void ssl_util_thread_setup(apr_pool_t *); int ssl_init_ssl_connection(conn_rec *c, request_rec *r); /** Pass Phrase Support */ -void ssl_pphrase_Handle(server_rec *, apr_pool_t *); +apr_status_t ssl_load_encrypted_pkey(server_rec *, apr_pool_t *, int, + const char *, apr_array_header_t **); /** Diffie-Hellman Parameter Support */ DH *ssl_dh_GetParamFromFile(const char *); @@ -879,14 +851,6 @@ ssl_asn1_t *ssl_asn1_table_get(apr_hash_t *table, void ssl_asn1_table_unset(apr_hash_t *table, const char *key); -const char *ssl_asn1_keystr(int keytype); - -const char *ssl_asn1_table_keyfmt(apr_pool_t *p, - const char *id, - int keytype); - -STACK_OF(X509) *ssl_read_pkcs7(server_rec *s, const char *pkcs7); - /** Mutex Support */ int ssl_mutex_init(server_rec *, apr_pool_t *); int ssl_mutex_reinit(server_rec *, apr_pool_t *); @@ -899,8 +863,9 @@ int ssl_stapling_mutex_reinit(server_rec *, apr_pool_t *); #define SSL_CACHE_MUTEX_TYPE "ssl-cache" #define SSL_STAPLING_MUTEX_TYPE "ssl-stapling" +apr_status_t ssl_die(server_rec *); + /** Logfile Support */ -void ssl_die(server_rec *); void ssl_log_ssl_error(const char *, int, int, server_rec *); /* ssl_log_xerror, ssl_log_cxerror and ssl_log_rxerror are wrappers for the diff --git a/modules/ssl/ssl_scache.c b/modules/ssl/ssl_scache.c index bfed6e7c..01f72546 100644 --- a/modules/ssl/ssl_scache.c +++ b/modules/ssl/ssl_scache.c @@ -37,7 +37,7 @@ ** _________________________________________________________________ */ -void ssl_scache_init(server_rec *s, apr_pool_t *p) +apr_status_t ssl_scache_init(server_rec *s, apr_pool_t *p) { SSLModConfigRec *mc = myModConfig(s); apr_status_t rv; @@ -49,7 +49,7 @@ void ssl_scache_init(server_rec *s, apr_pool_t *p) * will be immediately cleared anyway. For every subsequent * invocation, initialize the configured cache. */ if (ap_state_query(AP_SQ_MAIN_STATE) == AP_SQ_MS_CREATE_PRE_CONFIG) - return; + return APR_SUCCESS; #ifdef HAVE_OCSP_STAPLING if (mc->stapling_cache) { @@ -63,7 +63,7 @@ void ssl_scache_init(server_rec *s, apr_pool_t *p) if (rv) { ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(01872) "Could not initialize stapling cache. Exiting."); - ssl_die(s); + return ssl_die(s); } } #endif @@ -76,7 +76,7 @@ void ssl_scache_init(server_rec *s, apr_pool_t *p) ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(01873) "Init: Session Cache is not configured " "[hint: SSLSessionCache]"); - return; + return APR_SUCCESS; } memset(&hints, 0, sizeof hints); @@ -88,8 +88,10 @@ void ssl_scache_init(server_rec *s, apr_pool_t *p) if (rv) { ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(01874) "Could not initialize session cache. Exiting."); - ssl_die(s); + return ssl_die(s); } + + return APR_SUCCESS; } void ssl_scache_kill(server_rec *s) diff --git a/modules/ssl/ssl_util.c b/modules/ssl/ssl_util.c index d2122784..476aa0b6 100644 --- a/modules/ssl/ssl_util.c +++ b/modules/ssl/ssl_util.c @@ -135,61 +135,8 @@ BOOL ssl_util_path_check(ssl_pathcheck_t pcm, const char *path, apr_pool_t *p) return TRUE; } -ssl_algo_t ssl_util_algotypeof(X509 *pCert, EVP_PKEY *pKey) -{ - ssl_algo_t t; - EVP_PKEY *pFreeKey = NULL; - - t = SSL_ALGO_UNKNOWN; - if (pCert != NULL) - pFreeKey = pKey = X509_get_pubkey(pCert); - if (pKey != NULL) { - switch (EVP_PKEY_type(pKey->type)) { - case EVP_PKEY_RSA: - t = SSL_ALGO_RSA; - break; - case EVP_PKEY_DSA: - t = SSL_ALGO_DSA; - break; -#ifdef HAVE_ECC - case EVP_PKEY_EC: - t = SSL_ALGO_ECC; - break; -#endif - default: - break; - } - } - if (pFreeKey != NULL) - EVP_PKEY_free(pFreeKey); - return t; -} - -char *ssl_util_algotypestr(ssl_algo_t t) -{ - char *cp; - - cp = "UNKNOWN"; - switch (t) { - case SSL_ALGO_RSA: - cp = "RSA"; - break; - case SSL_ALGO_DSA: - cp = "DSA"; - break; -#ifdef HAVE_ECC - case SSL_ALGO_ECC: - cp = "ECC"; - break; -#endif - default: - break; - } - return cp; -} - /* - * certain key and cert data needs to survive restarts, + * certain key data needs to survive restarts, * which are stored in the user data table of s->process->pool. * to prevent "leaking" of this data, we use malloc/free * rather than apr_palloc and these wrappers to help make sure @@ -253,81 +200,6 @@ void ssl_asn1_table_unset(apr_hash_t *table, apr_hash_set(table, key, klen, NULL); } -#ifdef HAVE_ECC -static const char *ssl_asn1_key_types[] = {"RSA", "DSA", "ECC"}; -#else -static const char *ssl_asn1_key_types[] = {"RSA", "DSA"}; -#endif - -const char *ssl_asn1_keystr(int keytype) -{ - if (keytype >= SSL_AIDX_MAX) { - return NULL; - } - - return ssl_asn1_key_types[keytype]; -} - -const char *ssl_asn1_table_keyfmt(apr_pool_t *p, - const char *id, - int keytype) -{ - const char *keystr = ssl_asn1_keystr(keytype); - - return apr_pstrcat(p, id, ":", keystr, NULL); -} - -STACK_OF(X509) *ssl_read_pkcs7(server_rec *s, const char *pkcs7) -{ - PKCS7 *p7; - STACK_OF(X509) *certs = NULL; - FILE *f; - - f = fopen(pkcs7, "r"); - if (!f) { - ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02212) "Can't open %s", pkcs7); - ssl_die(s); - } - - p7 = PEM_read_PKCS7(f, NULL, NULL, NULL); - if (!p7) { - ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(02274) - "Can't read PKCS7 object %s", pkcs7); - ssl_log_ssl_error(SSLLOG_MARK, APLOG_CRIT, s); - exit(1); - } - - switch (OBJ_obj2nid(p7->type)) { - case NID_pkcs7_signed: - certs = p7->d.sign->cert; - p7->d.sign->cert = NULL; - PKCS7_free(p7); - break; - - case NID_pkcs7_signedAndEnveloped: - certs = p7->d.signed_and_enveloped->cert; - p7->d.signed_and_enveloped->cert = NULL; - PKCS7_free(p7); - break; - - default: - ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02213) - "Don't understand PKCS7 file %s", pkcs7); - ssl_die(s); - } - - if (!certs) { - ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02214) - "No certificates in %s", pkcs7); - ssl_die(s); - } - - fclose(f); - - return certs; -} - - #if APR_HAS_THREADS /* * To ensure thread-safetyness in OpenSSL - work in progress diff --git a/modules/ssl/ssl_util_ocsp.c b/modules/ssl/ssl_util_ocsp.c index 757df05f..90160405 100644 --- a/modules/ssl/ssl_util_ocsp.c +++ b/modules/ssl/ssl_util_ocsp.c @@ -96,7 +96,6 @@ static apr_socket_t *send_request(BIO *request, const apr_uri_t *uri, ap_log_cerror(APLOG_MARK, APLOG_ERR, rv, c, APLOGNO(01974) "could not connect to OCSP responder '%s'", uri->hostinfo); - apr_socket_close(sd); return NULL; } diff --git a/modules/ssl/ssl_util_ssl.c b/modules/ssl/ssl_util_ssl.c index 9f4cfa2c..0bf37768 100644 --- a/modules/ssl/ssl_util_ssl.c +++ b/modules/ssl/ssl_util_ssl.c @@ -70,52 +70,11 @@ void SSL_set_app_data2(SSL *ssl, void *arg) /* _________________________________________________________________ ** -** High-Level Certificate / Private Key Loading +** High-Level Private Key Loading ** _________________________________________________________________ */ -X509 *SSL_read_X509(char* filename, X509 **x509, pem_password_cb *cb) -{ - X509 *rc; - BIO *bioS; - BIO *bioF; - - /* 1. try PEM (= DER+Base64+headers) */ - if ((bioS=BIO_new_file(filename, "r")) == NULL) - return NULL; - rc = PEM_read_bio_X509 (bioS, x509, cb, NULL); - BIO_free(bioS); - - if (rc == NULL) { - /* 2. try DER+Base64 */ - if ((bioS=BIO_new_file(filename, "r")) == NULL) - return NULL; - - if ((bioF = BIO_new(BIO_f_base64())) == NULL) { - BIO_free(bioS); - return NULL; - } - bioS = BIO_push(bioF, bioS); - rc = d2i_X509_bio(bioS, NULL); - BIO_free_all(bioS); - - if (rc == NULL) { - /* 3. try plain DER */ - if ((bioS=BIO_new_file(filename, "r")) == NULL) - return NULL; - rc = d2i_X509_bio(bioS, NULL); - BIO_free(bioS); - } - } - if (rc != NULL && x509 != NULL) { - if (*x509 != NULL) - X509_free(*x509); - *x509 = rc; - } - return rc; -} - -EVP_PKEY *SSL_read_PrivateKey(char* filename, EVP_PKEY **key, pem_password_cb *cb, void *s) +EVP_PKEY *SSL_read_PrivateKey(const char* filename, EVP_PKEY **key, pem_password_cb *cb, void *s) { EVP_PKEY *rc; BIO *bioS; @@ -188,29 +147,6 @@ int SSL_smart_shutdown(SSL *ssl) ** _________________________________________________________________ */ -/* check whether cert contains extended key usage with a SGC tag */ -BOOL SSL_X509_isSGC(X509 *cert) -{ - int ext_nid; - EXTENDED_KEY_USAGE *sk; - BOOL is_sgc; - int i; - - is_sgc = FALSE; - sk = X509_get_ext_d2i(cert, NID_ext_key_usage, NULL, NULL); - if (sk) { - for (i = 0; i < sk_ASN1_OBJECT_num(sk); i++) { - ext_nid = OBJ_obj2nid(sk_ASN1_OBJECT_value(sk, i)); - if (ext_nid == NID_ms_sgc || ext_nid == NID_ns_sgc) { - is_sgc = TRUE; - break; - } - } - EXTENDED_KEY_USAGE_free(sk); - } - return is_sgc; -} - /* retrieve basic constraints ingredients */ BOOL SSL_X509_getBC(X509 *cert, int *ca, int *pathlen) { diff --git a/modules/ssl/ssl_util_ssl.h b/modules/ssl/ssl_util_ssl.h index 4b882db2..6f6873b4 100644 --- a/modules/ssl/ssl_util_ssl.h +++ b/modules/ssl/ssl_util_ssl.h @@ -60,10 +60,8 @@ void SSL_init_app_data2_idx(void); void *SSL_get_app_data2(SSL *); void SSL_set_app_data2(SSL *, void *); -X509 *SSL_read_X509(char *, X509 **, pem_password_cb *); -EVP_PKEY *SSL_read_PrivateKey(char *, EVP_PKEY **, pem_password_cb *, void *); +EVP_PKEY *SSL_read_PrivateKey(const char *, EVP_PKEY **, pem_password_cb *, void *); int SSL_smart_shutdown(SSL *ssl); -BOOL SSL_X509_isSGC(X509 *); BOOL SSL_X509_getBC(X509 *, int *, int *); char *SSL_X509_NAME_ENTRY_to_string(apr_pool_t *p, X509_NAME_ENTRY *xsne); char *SSL_X509_NAME_to_string(apr_pool_t *, X509_NAME *, int); diff --git a/modules/ssl/ssl_util_stapling.c b/modules/ssl/ssl_util_stapling.c index 0387cf92..7633648c 100644 --- a/modules/ssl/ssl_util_stapling.c +++ b/modules/ssl/ssl_util_stapling.c @@ -653,8 +653,8 @@ static int stapling_cb(SSL *ssl, void *arg) } -void modssl_init_stapling(server_rec *s, apr_pool_t *p, apr_pool_t *ptemp, - modssl_ctx_t *mctx) +apr_status_t modssl_init_stapling(server_rec *s, apr_pool_t *p, + apr_pool_t *ptemp, modssl_ctx_t *mctx) { SSL_CTX *ctx = mctx->ssl_ctx; SSLModConfigRec *mc = myModConfig(s); @@ -662,12 +662,12 @@ void modssl_init_stapling(server_rec *s, apr_pool_t *p, apr_pool_t *ptemp, if (mc->stapling_cache == NULL) { ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(01958) "SSLStapling: no stapling cache available"); - ssl_die(s); + return ssl_die(s); } if (ssl_stapling_mutex_init(s, ptemp) == FALSE) { ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(01959) "SSLStapling: cannot initialise stapling mutex"); - ssl_die(s); + return ssl_die(s); } /* Set some default values for parameters if they are not set */ if (mctx->stapling_resptime_skew == UNSET) { @@ -690,6 +690,8 @@ void modssl_init_stapling(server_rec *s, apr_pool_t *p, apr_pool_t *ptemp, } SSL_CTX_set_tlsext_status_cb(ctx, stapling_cb); ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(01960) "OCSP stapling initialized"); + + return APR_SUCCESS; } #endif |