mirror of
https://github.com/apache/httpd.git
synced 2025-08-08 15:02:10 +03:00
* Add SSLProxyCheckPeerExpire and SSLProxyCheckPeerCN directives to enable
stricter checking of remote server certificates. (docs/manual/mod/mod_ssl.xml) Documentation of SSLProxyCheckPeerExpire and SSLProxyCheckPeerCN. (modules/proxy/mod_proxy_http.c) Set the hostname of the request URL as note on the connection. (modules/ssl/ssl_private.h) Add proxy_ssl_check_peer_expire and proxy_ssl_check_peer_cn fields to the SSLSrvConfigRec. (modules/ssl/ssl_engine_config.c) Directives stuff for SSLProxyCheckPeerExpire and SSLProxyCheckPeerCN. (modules/ssl/ssl_engine_io.c) Check whether the remote servers certificate is expired / if there is a mismatch between the requested hostanme and the remote server certificates CN field. Be able to parse ASN1 times. (modules/ssl/mod_ssl.c) Directives stuff for SSLProxyCheckPeerExpire and SSLProxyCheckPeerCN. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@760866 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
4
CHANGES
4
CHANGES
@@ -2,6 +2,10 @@
|
||||
|
||||
Changes with Apache 2.3.3
|
||||
|
||||
*) mod_ssl: Add SSLProxyCheckPeerExpire and SSLProxyCheckPeerCN directives
|
||||
to enable stricter checking of remote server certificates.
|
||||
[Ruediger Pluem]
|
||||
|
||||
*) ab: Fix a 100% CPU loop on platforms where a failed non-blocking connect
|
||||
returns EINPROGRESS and a subsequent poll() returns only POLLERR.
|
||||
Observed on HP-UX. [Eric Covener]
|
||||
|
@@ -1501,6 +1501,48 @@ SSLProxyVerifyDepth 10
|
||||
</usage>
|
||||
</directivesynopsis>
|
||||
|
||||
<directivesynopsis>
|
||||
<name>SSLProxyCheckPeerExpire</name>
|
||||
<description>Whether to check if remote server certificate is expired
|
||||
</description>
|
||||
<syntax>SSLProxyCheckPeerExpire on|off|optional</syntax>
|
||||
<default>SSLProxyCheckPeerExpire off</default>
|
||||
<contextlist><context>server config</context>
|
||||
<context>virtual host</context></contextlist>
|
||||
|
||||
<usage>
|
||||
<p>
|
||||
This directive sets whether it is checked if the remote server certificate
|
||||
is expired or not. If the check fails a 502 status code (Bad Gateway) is
|
||||
sent.
|
||||
</p>
|
||||
<example><title>Example</title>
|
||||
SSLProxyCheckPeerExpire on
|
||||
</example>
|
||||
</usage>
|
||||
</directivesynopsis>
|
||||
|
||||
<directivesynopsis>
|
||||
<name>SSLProxyCheckPeerCN</name>
|
||||
<description>Whether to check the remote server certificates CN field
|
||||
</description>
|
||||
<syntax>SSLProxyCheckPeerCN on|off|optional</syntax>
|
||||
<default>SSLProxyCheckPeerCN off</default>
|
||||
<contextlist><context>server config</context>
|
||||
<context>virtual host</context></contextlist>
|
||||
|
||||
<usage>
|
||||
<p>
|
||||
This directive sets whether the remote server certificates CN field is
|
||||
compared against the hostname of the request URL. If both are not equal
|
||||
a 502 status code (Bad Gateway) is sent.
|
||||
</p>
|
||||
<example><title>Example</title>
|
||||
SSLProxyCheckPeerCN on
|
||||
</example>
|
||||
</usage>
|
||||
</directivesynopsis>
|
||||
|
||||
<directivesynopsis>
|
||||
<name>SSLProxyEngine</name>
|
||||
<description>SSL Proxy Engine Operation Switch</description>
|
||||
|
@@ -1964,6 +1964,15 @@ static int proxy_http_handler(request_rec *r, proxy_worker *worker,
|
||||
if ((status = ap_proxy_connection_create(proxy_function, backend,
|
||||
c, r->server)) != OK)
|
||||
goto cleanup;
|
||||
/*
|
||||
* On SSL connections set a note on the connection what CN is
|
||||
* requested, such that mod_ssl can check if it is requested to do
|
||||
* so.
|
||||
*/
|
||||
if (is_ssl) {
|
||||
apr_table_set(backend->connection->notes, "proxy-request-hostname",
|
||||
uri->hostname);
|
||||
}
|
||||
}
|
||||
|
||||
/* Step Four: Send the Request */
|
||||
|
@@ -166,6 +166,10 @@ static const command_rec ssl_config_cmds[] = {
|
||||
SSL_CMD_SRV(ProxyMachineCertificatePath, TAKE1,
|
||||
"SSL Proxy: directory containing client certificates "
|
||||
"(`/path/to/dir' - contains PEM encoded certificates)")
|
||||
SSL_CMD_SRV(ProxyCheckPeerExpire, FLAG,
|
||||
"SSL Proxy: check the peers certificate expiration date")
|
||||
SSL_CMD_SRV(ProxyCheckPeerCN, FLAG,
|
||||
"SSL Proxy: check the peers certificate CN")
|
||||
|
||||
/*
|
||||
* Per-directory context configuration directives
|
||||
|
@@ -173,6 +173,8 @@ static SSLSrvConfigRec *ssl_config_server_new(apr_pool_t *p)
|
||||
sc->session_cache_timeout = UNSET;
|
||||
sc->cipher_server_pref = UNSET;
|
||||
sc->ssl_log_level = SSL_LOG_UNSET;
|
||||
sc->proxy_ssl_check_peer_expire = SSL_ENABLED_UNSET;
|
||||
sc->proxy_ssl_check_peer_cn = SSL_ENABLED_UNSET;
|
||||
|
||||
modssl_ctx_init_proxy(sc, p);
|
||||
|
||||
@@ -266,6 +268,8 @@ void *ssl_config_server_merge(apr_pool_t *p, void *basev, void *addv)
|
||||
cfgMergeInt(session_cache_timeout);
|
||||
cfgMergeBool(cipher_server_pref);
|
||||
cfgMerge(ssl_log_level, SSL_LOG_UNSET);
|
||||
cfgMerge(proxy_ssl_check_peer_expire, SSL_ENABLED_UNSET);
|
||||
cfgMerge(proxy_ssl_check_peer_cn, SSL_ENABLED_UNSET);
|
||||
|
||||
modssl_ctx_cfg_merge_proxy(base->proxy, add->proxy, mrg->proxy);
|
||||
|
||||
@@ -1418,6 +1422,24 @@ const char *ssl_cmd_SSLOCSPDefaultResponder(cmd_parms *cmd, void *dcfg, const ch
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *ssl_cmd_SSLProxyCheckPeerExpire(cmd_parms *cmd, void *dcfg, int flag)
|
||||
{
|
||||
SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
|
||||
|
||||
sc->proxy_ssl_check_peer_expire = flag ? SSL_ENABLED_TRUE : SSL_ENABLED_FALSE;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *ssl_cmd_SSLProxyCheckPeerCN(cmd_parms *cmd, void *dcfg, int flag)
|
||||
{
|
||||
SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
|
||||
|
||||
sc->proxy_ssl_check_peer_cn = flag ? SSL_ENABLED_TRUE : SSL_ENABLED_FALSE;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void ssl_hook_ConfigTest(apr_pool_t *pconf, server_rec *s)
|
||||
{
|
||||
if (!ap_exists_config_define("DUMP_CERTS")) {
|
||||
|
@@ -28,6 +28,7 @@
|
||||
core keeps dumping.''
|
||||
-- Unknown */
|
||||
#include "ssl_private.h"
|
||||
#include "apr_date.h"
|
||||
|
||||
/* _________________________________________________________________
|
||||
**
|
||||
@@ -1033,6 +1034,31 @@ static apr_status_t ssl_io_filter_cleanup(void *data)
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse an ASN1time string as returned by ASN1_UTCTIME_print into an
|
||||
* apr_time_t.
|
||||
*/
|
||||
static apr_time_t parseASN1time(apr_pool_t *p, const char *asn1time)
|
||||
{
|
||||
char *asctime;
|
||||
|
||||
/*
|
||||
* Little bit ugly hack:
|
||||
* The ASN1time looks very similar to the asctime format which can be
|
||||
* parsed by apr_date_parse_rfc:
|
||||
* It misses the weekday at the beginning (which is ignored by
|
||||
* apr_date_parse_rfc anyway) and it has a GMT at the end which
|
||||
* does not into the asctime pattern. So add a dummy "Sun " before
|
||||
* the ASN1time and remove the GMT string at the end.
|
||||
*/
|
||||
asctime = apr_pstrcat(p, "Sun ", asn1time, NULL);
|
||||
if (strlen(asctime) < 25) {
|
||||
return APR_DATE_BAD;
|
||||
}
|
||||
asctime[24] = '\0';
|
||||
return apr_date_parse_rfc(asctime);
|
||||
}
|
||||
|
||||
/*
|
||||
* The hook is NOT registered with ap_hook_process_connection. Instead, it is
|
||||
* called manually from the churn () before it tries to read any data.
|
||||
@@ -1060,6 +1086,9 @@ static apr_status_t ssl_io_filter_handshake(ssl_filter_ctx_t *filter_ctx)
|
||||
|
||||
server = mySrvFromConn(c);
|
||||
if (sslconn->is_proxy) {
|
||||
const char *hostname_note;
|
||||
|
||||
sc = mySrvConfig(sslconn->server);
|
||||
if ((n = SSL_connect(filter_ctx->pssl)) <= 0) {
|
||||
ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, c,
|
||||
"SSL Proxy connect failed");
|
||||
@@ -1069,6 +1098,47 @@ static apr_status_t ssl_io_filter_handshake(ssl_filter_ctx_t *filter_ctx)
|
||||
return MODSSL_ERROR_BAD_GATEWAY;
|
||||
}
|
||||
|
||||
if (sc->proxy_ssl_check_peer_expire == SSL_ENABLED_TRUE) {
|
||||
apr_time_t start_time;
|
||||
apr_time_t end_time;
|
||||
apr_time_t now;
|
||||
|
||||
start_time = parseASN1time(c->pool,
|
||||
ssl_var_lookup(NULL, c->base_server,
|
||||
c, NULL,
|
||||
"SSL_CLIENT_V_START"));
|
||||
end_time = parseASN1time(c->pool,
|
||||
ssl_var_lookup(NULL, c->base_server,
|
||||
c, NULL,
|
||||
"SSL_CLIENT_V_END"));
|
||||
now = apr_time_now();
|
||||
if ((now > end_time) || (now < start_time)) {
|
||||
ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, c,
|
||||
"SSL Proxy: Peer certificate is expired");
|
||||
/* ensure that the SSL structures etc are freed, etc: */
|
||||
ssl_filter_io_shutdown(filter_ctx, c, 1);
|
||||
return HTTP_BAD_GATEWAY;
|
||||
}
|
||||
}
|
||||
if ((sc->proxy_ssl_check_peer_cn == SSL_ENABLED_TRUE)
|
||||
&& ((hostname_note =
|
||||
apr_table_get(c->notes, "proxy-request-hostname")) != NULL)) {
|
||||
const char *hostname;
|
||||
|
||||
hostname = ssl_var_lookup(NULL, c->base_server, c, NULL,
|
||||
"SSL_CLIENT_S_DN_CN");
|
||||
apr_table_unset(c->notes, "proxy-request-hostname");
|
||||
if (strcasecmp(hostname, hostname_note)) {
|
||||
ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, c,
|
||||
"SSL Proxy: Peer certificate CN mismatch:"
|
||||
" Certificate CN: %s Requested hostname: %s",
|
||||
hostname, hostname_note);
|
||||
/* ensure that the SSL structures etc are freed, etc: */
|
||||
ssl_filter_io_shutdown(filter_ctx, c, 1);
|
||||
return HTTP_BAD_GATEWAY;
|
||||
}
|
||||
}
|
||||
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
|
||||
|
@@ -477,6 +477,8 @@ struct SSLSrvConfigRec {
|
||||
modssl_ctx_t *server;
|
||||
modssl_ctx_t *proxy;
|
||||
ssl_log_level_e ssl_log_level;
|
||||
ssl_enabled_t proxy_ssl_check_peer_expire;
|
||||
ssl_enabled_t proxy_ssl_check_peer_cn;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -554,6 +556,8 @@ const char *ssl_cmd_SSLProxyCARevocationPath(cmd_parms *, void *, const char *)
|
||||
const char *ssl_cmd_SSLProxyCARevocationFile(cmd_parms *, void *, const char *);
|
||||
const char *ssl_cmd_SSLProxyMachineCertificatePath(cmd_parms *, void *, const char *);
|
||||
const char *ssl_cmd_SSLProxyMachineCertificateFile(cmd_parms *, void *, const char *);
|
||||
const char *ssl_cmd_SSLProxyCheckPeerExpire(cmd_parms *cmd, void *dcfg, int flag);
|
||||
const char *ssl_cmd_SSLProxyCheckPeerCN(cmd_parms *cmd, void *dcfg, int flag);
|
||||
|
||||
const char *ssl_cmd_SSLOCSPOverrideResponder(cmd_parms *cmd, void *dcfg, int flag);
|
||||
const char *ssl_cmd_SSLOCSPDefaultResponder(cmd_parms *cmd, void *dcfg, const char *arg);
|
||||
|
Reference in New Issue
Block a user