* 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:
Ruediger Pluem
2009-04-01 12:07:47 +00:00
parent 23ac01a833
commit e468a9fae6
7 changed files with 155 additions and 0 deletions

View File

@ -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;
}