mod_proxy now sets the requested remote host name. Use this to compare to the CN value of the peer certificate and reject the request if they do not match (and we are have NSSProxyCheckPeerCN set to on). diff -u --recursive mod_nss-1.0.8.orig/docs/mod_nss.html mod_nss-1.0.8/docs/mod_nss.html --- mod_nss-1.0.8.orig/docs/mod_nss.html 2006-09-05 10:58:56.000000000 -0400 +++ mod_nss-1.0.8/docs/mod_nss.html 2010-05-13 11:25:42.000000000 -0400 @@ -1028,7 +1028,21 @@
Example

-NSSProxyNickname beta
+NSSProxyNickname beta
+
+
NSSProxyCheckPeerCN
+
+Compare the CN value of the peer certificate with the hostname being +requested. If this is set to on, the default, then the request will +fail if they do not match. If this is set to off then this comparison +is not done. Note that this test is your only protection against a +man-in-the-middle attack so leaving this as on is strongly recommended.
+
+Example
+
+NSSProcyCheckPeerCN +on
+

Environment Variables

Quite a few environment variables (for CGI and SSI) may be set depending on the NSSOptions configuration. It can be expensive to set @@ -1435,42 +1449,9 @@

Frequently Asked Questions

Q. Does mod_nss support mod_proxy?

-A. In order to use the mod_nss proxy support you will need to build -your own mod_proxy by applying a patch found in bug 36468. -The patch is needed so we can compare the hostname contained in the -remote certificate with the hostname you meant to visit. This prevents -man-in-the-middle attacks.
-
-You also have to change the SSL functions that mod_proxy looks to use. -You'll need to apply this patch:
-
-1038,1039c1038,1039
-< APR_DECLARE_OPTIONAL_FN(int, ssl_proxy_enable, (conn_rec *));
-< APR_DECLARE_OPTIONAL_FN(int, ssl_engine_disable, (conn_rec *));
----
-> APR_DECLARE_OPTIONAL_FN(int, nss_proxy_enable, (conn_rec *));
-> APR_DECLARE_OPTIONAL_FN(int, nss_engine_disable, (conn_rec *));
-1041,1042c1041,1042
-< static APR_OPTIONAL_FN_TYPE(ssl_proxy_enable) *proxy_ssl_enable = -NULL;
-< static APR_OPTIONAL_FN_TYPE(ssl_engine_disable) *proxy_ssl_disable -= NULL;
----
-> static APR_OPTIONAL_FN_TYPE(nss_proxy_enable) *proxy_ssl_enable = -NULL;
-> static APR_OPTIONAL_FN_TYPE(nss_engine_disable) *proxy_ssl_disable -= NULL;
-1069,1070c1069,1070
-<     proxy_ssl_enable = -APR_RETRIEVE_OPTIONAL_FN(ssl_proxy_enable);
-<     proxy_ssl_disable = -APR_RETRIEVE_OPTIONAL_FN(ssl_engine_disable);
----
->     proxy_ssl_enable = -APR_RETRIEVE_OPTIONAL_FN(nss_proxy_enable);
->     proxy_ssl_disable = -APR_RETRIEVE_OPTIONAL_FN(nss_engine_disable);
-

+A. Yes but you need to make sure that mod_ssl is not loaded. mod_proxy +provides a single interface for SSL providers and mod_nss defers to +mod_ssl +if it is loaded. diff -u --recursive mod_nss-1.0.8.orig/mod_nss.c mod_nss-1.0.8/mod_nss.c --- mod_nss-1.0.8.orig/mod_nss.c 2010-05-13 11:24:49.000000000 -0400 +++ mod_nss-1.0.8/mod_nss.c 2010-05-13 11:25:42.000000000 -0400 @@ -142,6 +142,8 @@ SSL_CMD_SRV(ProxyNickname, TAKE1, "SSL Proxy: client certificate Nickname to be for proxy connections " "(`nickname')") + SSL_CMD_SRV(ProxyCheckPeerCN, FLAG, + "SSL Proxy: check the peers certificate CN") #ifdef IGNORE /* Deprecated directives. */ @@ -238,23 +240,30 @@ SECStatus NSSBadCertHandler(void *arg, PRFileDesc * socket) { conn_rec *c = (conn_rec *)arg; + SSLSrvConfigRec *sc = mySrvConfig(c->base_server); PRErrorCode err = PR_GetError(); SECStatus rv = SECFailure; CERTCertificate *peerCert = SSL_PeerCertificate(socket); + const char *hostname_note; switch (err) { case SSL_ERROR_BAD_CERT_DOMAIN: - if (c->remote_host != NULL) { - rv = CERT_VerifyCertName(peerCert, c->remote_host); - if (rv != SECSuccess) { - char *remote = CERT_GetCommonName(&peerCert->subject); + if (sc->proxy_ssl_check_peer_cn == TRUE) { + if ((hostname_note = apr_table_get(c->notes, "proxy-request-hostname")) != NULL) { + apr_table_unset(c->notes, "proxy-request-hostname"); + rv = CERT_VerifyCertName(peerCert, hostname_note); + if (rv != SECSuccess) { + char *remote = CERT_GetCommonName(&peerCert->subject); + ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, + "SSL Proxy: Possible man-in-the-middle attack. The remove server is %s, we expected %s", remote, hostname_note); + PORT_Free(remote); + } + } else { ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, - "SSL Proxy: Possible man-in-the-middle attack. The remove server is %s, we expected %s", remote, c->remote_host); - PORT_Free(remote); + "SSL Proxy: I don't have the name of the host we're supposed to connect to so I can't verify that we are connecting to who we think we should be. Giving up."); } } else { - ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, - "SSL Proxy: I don't have the name of the host we're supposed to connect to so I can't verify that we are connecting to who we think we should be. Giving up. Hint: See Apache bug 36468."); + rv = SECSuccess; } break; default: diff -u --recursive mod_nss-1.0.8.orig/mod_nss.h mod_nss-1.0.8/mod_nss.h --- mod_nss-1.0.8.orig/mod_nss.h 2010-05-13 11:24:49.000000000 -0400 +++ mod_nss-1.0.8/mod_nss.h 2010-05-13 11:25:42.000000000 -0400 @@ -306,6 +306,7 @@ int vhost_id_len; modnss_ctx_t *server; modnss_ctx_t *proxy; + BOOL proxy_ssl_check_peer_cn; }; /* @@ -410,6 +411,7 @@ const char *nss_cmd_NSSProxyProtocol(cmd_parms *, void *, const char *); const char *nss_cmd_NSSProxyCipherSuite(cmd_parms *, void *, const char *); const char *nss_cmd_NSSProxyNickname(cmd_parms *cmd, void *dcfg, const char *arg); +const char *nss_cmd_NSSProxyCheckPeerCN(cmd_parms *cmd, void *dcfg, int flag); /* module initialization */ int nss_init_Module(apr_pool_t *, apr_pool_t *, apr_pool_t *, server_rec *); diff -u --recursive mod_nss-1.0.8.orig/nss_engine_config.c mod_nss-1.0.8/nss_engine_config.c --- mod_nss-1.0.8.orig/nss_engine_config.c 2010-05-13 11:24:49.000000000 -0400 +++ mod_nss-1.0.8/nss_engine_config.c 2010-05-13 11:25:42.000000000 -0400 @@ -140,6 +140,7 @@ sc->vhost_id_len = 0; /* set during module init */ sc->proxy = NULL; sc->server = NULL; + sc->proxy_ssl_check_peer_cn = TRUE; modnss_ctx_init_proxy(sc, p); @@ -214,6 +215,7 @@ cfgMergeBool(fips); cfgMergeBool(enabled); cfgMergeBool(proxy_enabled); + cfgMergeBool(proxy_ssl_check_peer_cn); modnss_ctx_cfg_merge_proxy(base->proxy, add->proxy, mrg->proxy); @@ -544,6 +546,15 @@ return NULL; } +const char *nss_cmd_NSSProxyCheckPeerCN(cmd_parms *cmd, void *dcfg, int flag) +{ + SSLSrvConfigRec *sc = mySrvConfig(cmd->server); + + sc->proxy_ssl_check_peer_cn = flag ? TRUE : FALSE; + + return NULL; +} + const char *nss_cmd_NSSEnforceValidCerts(cmd_parms *cmd, void *dcfg, int flag)