summaryrefslogtreecommitdiff
path: root/modules/ssl/ssl_engine_kernel.c
diff options
context:
space:
mode:
authorArno Töll <arno@debian.org>2014-07-20 06:23:00 -1100
committerArno Töll <arno@debian.org>2014-07-20 06:23:00 -1100
commitcb35beef2a938b80c9e4b5d6a408eca437aa74db (patch)
tree87ae6e0d2b3a8ce318fe8ab559494808a451035e /modules/ssl/ssl_engine_kernel.c
parent2a463b3cd73c32ee9dcd508248d0194923f435f4 (diff)
downloadapache2-cb35beef2a938b80c9e4b5d6a408eca437aa74db.tar.gz
Imported Upstream version 2.4.10
Diffstat (limited to 'modules/ssl/ssl_engine_kernel.c')
-rw-r--r--modules/ssl/ssl_engine_kernel.c103
1 files changed, 54 insertions, 49 deletions
diff --git a/modules/ssl/ssl_engine_kernel.c b/modules/ssl/ssl_engine_kernel.c
index c60f0a6c..3f905e7b 100644
--- a/modules/ssl/ssl_engine_kernel.c
+++ b/modules/ssl/ssl_engine_kernel.c
@@ -163,7 +163,13 @@ int ssl_hook_ReadReq(request_rec *r)
return DECLINED;
}
#ifdef HAVE_TLSEXT
- if (r->proxyreq != PROXYREQ_PROXY) {
+ /*
+ * Perform SNI checks only on the initial request. In particular,
+ * if these checks detect a problem, the checks shouldn't return an
+ * error again when processing an ErrorDocument redirect for the
+ * original problem.
+ */
+ if (r->proxyreq != PROXYREQ_PROXY && ap_is_initial_req(r)) {
if ((servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name))) {
char *host, *scope_id;
apr_port_t port;
@@ -175,8 +181,8 @@ int ssl_hook_ReadReq(request_rec *r)
* 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
+ * SSLCADNRequestFile/Path cannot be renegotiated (SSLCA* due
+ * to current limitations 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
@@ -206,13 +212,17 @@ int ssl_hook_ReadReq(request_rec *r)
/*
* 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
+ * checking. Check whether this strict checking was set up 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");
+ apr_table_setn(r->notes, "error-notes",
+ "Reason: The client software did not provide a "
+ "hostname using Server Name Indication (SNI), "
+ "which is required to access this server.<br />\n");
return HTTP_FORBIDDEN;
}
}
@@ -1298,41 +1308,24 @@ const authz_provider ssl_authz_provider_verify_client =
*/
/*
- * Grab well-defined DH parameters from OpenSSL, see <openssl/bn.h>
- * (get_rfc*) for all available primes.
- */
-#define make_get_dh(rfc,size,gen) \
-static DH *get_dh##size(void) \
-{ \
- DH *dh; \
- if (!(dh = DH_new())) { \
- return NULL; \
- } \
- dh->p = get_##rfc##_prime_##size(NULL); \
- BN_dec2bn(&dh->g, #gen); \
- if (!dh->p || !dh->g) { \
- DH_free(dh); \
- return NULL; \
- } \
- return dh; \
-}
-
-/*
- * Prepare DH parameters from 1024 to 4096 bits, in 1024-bit increments
- */
-make_get_dh(rfc2409, 1024, 2)
-make_get_dh(rfc3526, 2048, 2)
-make_get_dh(rfc3526, 3072, 2)
-make_get_dh(rfc3526, 4096, 2)
-
-/*
* Hand out standard DH parameters, based on the authentication strength
*/
DH *ssl_callback_TmpDH(SSL *ssl, int export, int keylen)
{
conn_rec *c = (conn_rec *)SSL_get_app_data(ssl);
- EVP_PKEY *pkey = SSL_get_privatekey(ssl);
- int type = pkey ? EVP_PKEY_type(pkey->type) : EVP_PKEY_NONE;
+ EVP_PKEY *pkey;
+ int type;
+
+#ifdef SSL_CERT_SET_SERVER
+ /*
+ * When multiple certs/keys are configured for the SSL_CTX: make sure
+ * that we get the private key which is indeed used for the current
+ * SSL connection (available in OpenSSL 1.0.2 or later only)
+ */
+ SSL_set_current_cert(ssl, SSL_CERT_SET_SERVER);
+#endif
+ pkey = SSL_get_privatekey(ssl);
+ type = pkey ? EVP_PKEY_type(pkey->type) : EVP_PKEY_NONE;
/*
* OpenSSL will call us with either keylen == 512 or keylen == 1024
@@ -1353,14 +1346,7 @@ DH *ssl_callback_TmpDH(SSL *ssl, int export, int keylen)
ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, c,
"handing out built-in DH parameters for %d-bit authenticated connection", keylen);
- if (keylen >= 4096)
- return get_dh4096();
- else if (keylen >= 3072)
- return get_dh3072();
- else if (keylen >= 2048)
- return get_dh2048();
- else
- return get_dh1024();
+ return modssl_get_dh_params(keylen);
}
/*
@@ -1891,7 +1877,7 @@ void ssl_callback_Info(const SSL *ssl, int where, int rc)
}
}
/* If the first handshake is complete, change state to reject any
- * subsequent client-initated renegotiation. */
+ * subsequent client-initiated renegotiation. */
else if ((where & SSL_CB_HANDSHAKE_DONE) && scr->reneg_state == RENEG_INIT) {
scr->reneg_state = RENEG_REJECT;
}
@@ -1905,16 +1891,16 @@ void ssl_callback_Info(const SSL *ssl, int where, int rc)
#ifdef HAVE_TLSEXT
/*
* This callback function is executed when OpenSSL encounters an extended
- * client hello with a server name indication extension ("SNI", cf. RFC 4366).
+ * client hello with a server name indication extension ("SNI", cf. RFC 6066).
*/
int ssl_callback_ServerNameIndication(SSL *ssl, int *al, modssl_ctx_t *mctx)
{
const char *servername =
SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
+ conn_rec *c = (conn_rec *)SSL_get_app_data(ssl);
- if (servername) {
- conn_rec *c = (conn_rec *)SSL_get_app_data(ssl);
- if (c) {
+ if (c) {
+ if (servername) {
if (ap_vhost_iterate_given_conn(c, ssl_find_vhost,
(void *)servername)) {
ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(02043)
@@ -1927,9 +1913,28 @@ int ssl_callback_ServerNameIndication(SSL *ssl, int *al, modssl_ctx_t *mctx)
"No matching SSL virtual host for servername "
"%s found (using default/first virtual host)",
servername);
- return SSL_TLSEXT_ERR_ALERT_WARNING;
+ /*
+ * RFC 6066 section 3 says "It is NOT RECOMMENDED to send
+ * a warning-level unrecognized_name(112) alert, because
+ * the client's behavior in response to warning-level alerts
+ * is unpredictable."
+ *
+ * To maintain backwards compatibility in mod_ssl, we
+ * no longer send any alert (neither warning- nor fatal-level),
+ * i.e. we take the second action suggested in RFC 6066:
+ * "If the server understood the ClientHello extension but
+ * does not recognize the server name, the server SHOULD take
+ * one of two actions: either abort the handshake by sending
+ * a fatal-level unrecognized_name(112) alert or continue
+ * the handshake."
+ */
}
}
+ else {
+ ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(02645)
+ "Server name not provided via TLS extension "
+ "(using default/first virtual host)");
+ }
}
return SSL_TLSEXT_ERR_NOACK;
@@ -2020,7 +2025,7 @@ static int ssl_find_vhost(void *servername, conn_rec *c, server_rec *s)
* vhost we have just switched to. Again, we have to make sure
* that we're not overwriting a session id context which was
* possibly set in ssl_hook_Access(), before triggering
- * a renegotation.
+ * a renegotiation.
*/
if (SSL_num_renegotiations(ssl) == 0) {
unsigned char *sid_ctx =