On Thu, 27 Aug 2015 14:36:06 -0400
"Cohen, Laurence" <[email protected]> wrote:

Hi Laurence,

> Hi,
> 
> I'm trying to set up an nss.conf to use while we are doing maintenance
> which will point all ssl traffic to a file called maintenance.html
> which simply states that we are doing maintenance on the server.  The
> rewrite.conf we have set up is working fine for port 80 traffic, but
> the nss.conf is not working.
> 
> Here are the errors I'm getting.  BTW, we are using a self signed cert
> because this is our test system.  I figured this would cause an info
> or at most a warning message, but not an error message.
> 
> [Thu Aug 27 13:38:00 2015] [info] Connection to child 0 established
> (server jamie-web1:443, client "Server IP")
> [Thu Aug 27 13:38:00 2015] [info] Connection to child 7 established
> (server jamie-web1:443, client "Server IP")
> [Thu Aug 27 13:38:00 2015] [info] SSL input filter read failed.
> [Thu Aug 27 13:38:00 2015] [error] SSL Library Error: -12195 Peer
> does not recognize and trust the CA that issued your certificate
> [Thu Aug 27 13:38:00 2015] [info] Connection to child 7 closed (server
> jamie-web1.novetta.com:443, client Server IP)
> [Thu Aug 27 13:38:00 2015] [info] SSL library error -8172 writing data
> [Thu Aug 27 13:38:00 2015] [info] SSL Library Error: -8172
> Certificate is signed by an untrusted issuer
> [Thu Aug 27 13:38:00 2015] [error] (20014)Internal error: proxy: pass
> request body failed to 10.3.238.21:443 (jamie-web1)
> [Thu Aug 27 13:38:00 2015] [error] proxy: pass request body failed to
> Server IP:443 (jamie-web1) from Server IP ()
> [Thu Aug 27 13:38:00 2015] [info] Connection to child 1 closed (server
> jamie-web1:443, client "Workstation IP")
> 

I suppose that this problem is with CA certificate on remote server:

You have two possible solution:

1. add CA from remote server to your certificate database at PROXY
server
2. build mod_nss with a patch from this email


PS: I have already worked on a similar problem for our customer. 

Have nice day

Standa 

> This is the nss.conf I'm using.
> 
> Listen 443
> 
> AddType application/x-x509-ca-cert .crt
> AddType application/x-pkcs7-crl    .crl
> 
> NSSPassPhraseDialog file:/etc/httpd/.password.conf
> #NSSPassPhraseDialog  builtin
> 
> NSSPassPhraseHelper /usr/sbin/nss_pcache
> 
> NSSSessionCacheSize 10000
> NSSSessionCacheTimeout 100
> NSSSession3CacheTimeout 86400
> 
> 
> NSSRandomSeed startup builtin
> 
> 
> <VirtualHost _default_:443>
> 
> DocumentRoot "/var/www/docroot"
> NSSProxyCheckPeerCN Off
> NSSEngine on
> NSSProxyEngine on
> NSSEnforceValidCerts off
> NSSRenegotiation on
> NSSRequireSafeNegotiation on
> 
> NSSCipherSuite
> +rsa_3des_sha,-rsa_des_sha,-rsa_rc4_40_md5,-rsa_rc2_40_md5,-rsa_null_md5,-rsa_null_sha,+fips_3des_sha,-fips_des_sha,-fortezza,-fortezza_rc4_128_sha,-fortezza_null,-rsa_des_56_sha,-rsa_rc4_56_sha,+rsa_aes_128_sha,+rsa_aes_256_sha
> 
> NSSProxyCipherSuite
> +rsa_3des_sha,-rsa_des_sha,-rsa_rc4_40_md5,-rsa_rc2_40_md5,-rsa_null_md5,-rsa_null_sha,+fips_3des_sha,-fips_des_sha,-fortezza,-fortezza_rc4_128_sha,-fortezza_null,-rsa_des_56_sha,-rsa_rc4_56_sha,+rsa_aes_128_sha,+rsa_aes_256_sha
> 
> NSSProtocol TLSv1
> NSSNickname Server-Cert
> NSSCertificateDatabase /etc/httpd/alias
> NSSFIPS on
> NSSOCSP off
> 
> ProxyPreserveHost On
> 
> 
> <Location />
> #SSLRenegBufferSize 52430000
>       NSSVerifyClient optional
>       NSSOptions +ExportCertData +StdEnvVars
>       ProxyPass https://jamie-web1/maintenance.html
>       ProxyPassReverse https://jamie-web1/maintenance.html
> </Location>
> 
> <Files ~ "\.(cgi|shtml|phtml|php3?)$">
>     NSSOptions +StdEnvVars
> </Files>
> <Directory "/var/www/cgi-bin">
>     NSSOptions +StdEnvVars
> </Directory>
> 
> 
> # initialize the SSL headers to a blank value to avoid http header
> forgeries RequestHeader set SSL_CLIENT_CERT ""
> RequestHeader set SSL_CIPHER ""
> RequestHeader set SSL_SESSION_ID ""
> RequestHeader set SSL_CIPHER_USEKEYSIZE ""
> 
> RequestHeader set SSL_CLIENT_CERT "%{SSL_CLIENT_CERT}s"
> RequestHeader set SSL_CIPHER "%{SSL_CIPHER}s"
> RequestHeader set SSL_SESSION_ID "%{SSL_SESSION_ID}s"
> RequestHeader set SSL_CIPHER_USEKEYSIZE "%{SSL_CIPHER_USEKEYSIZE}s"
> 
> CustomLog /var/log/httpd/ssl_request_log "%t %h %{SSL_CLIENT_CERT}x
> %{SSL_CLIENT_S_DN}x %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"
> 
> 
> ErrorLog /etc/httpd/logs/error_log
> TransferLog /etc/httpd/logs/access_log
> LogLevel info
> 
> </VirtualHost>
> 
> If anyone can help I'd appreciate it.
> 
> Thanks,
> 
> Larry Cohen

Index: mod_nss-1.0.8/nss_engine_init.c
===================================================================
--- mod_nss-1.0.8.orig/nss_engine_init.c
+++ mod_nss-1.0.8/nss_engine_init.c
@@ -23,7 +23,6 @@
 #include "keyhi.h"
 #include "cert.h"
 
-static SECStatus ownBadCertHandler(void *arg, PRFileDesc * socket);
 static SECStatus ownHandshakeCallback(PRFileDesc * socket, void *arg);
 static SECStatus NSSHandshakeCallback(PRFileDesc *socket, void *arg);
 static CERTCertificate* FindServerCertFromNickname(const char* name, const CERTCertList* clist);
@@ -862,7 +861,7 @@ static void nss_init_ctx_callbacks(serve
         nss_log_nss_error(APLOG_MARK, APLOG_ERR, s);
         nss_die();
     }
-    if (SSL_BadCertHook(mctx->model, (SSLBadCertHandler) ownBadCertHandler, NULL) != SECSuccess) {
+    if (SSL_BadCertHook(mctx->model, (SSLBadCertHandler) NSSBadCertHandler, NULL) != SECSuccess) {
         ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
                 "SSL_BadCertHook failed");
         nss_log_nss_error(APLOG_MARK, APLOG_ERR, s);
@@ -1287,7 +1286,7 @@ static void nss_init_certificate(server_
 		"SSL_SNISocketConfigHook failed");
 	    nss_log_nss_error(APLOG_MARK, APLOG_ERR, s);
 	    nss_die();
-	    }
+    }
 }
 
 
@@ -1554,25 +1553,6 @@ apr_status_t nss_init_ChildKill(void *da
 }
 
 /*
- * This callback is used when the incoming cert is not valid.
- * It should return SECSuccess to accept the cert anyway, SECFailure
- * to reject. In this case we always reject.
- */
-SECStatus ownBadCertHandler(void *arg, PRFileDesc * socket)
-{
-    PRErrorCode err = PR_GetError();
-
-    switch (err) {
-        default:
-            ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
-                "Bad remote server certificate: %d", err);
-            nss_log_nss_error(APLOG_MARK, APLOG_ERR, NULL);
-            return SECFailure;
-            break;
-    }
-}
-
-/*
  * Called by SSL to inform application that the handshake is
  * complete. This function is mostly used on the server side of an SSL
  * connection, although it is provided for a client as well.
Index: mod_nss-1.0.8/mod_nss.c
===================================================================
--- mod_nss-1.0.8.orig/mod_nss.c
+++ mod_nss-1.0.8/mod_nss.c
@@ -16,6 +16,7 @@
 #include "mod_nss.h"
 #include <assert.h>
 #include "sslerr.h"
+#include "secerr.h"
 
 /*
  *  the table of configuration directives we provide
@@ -147,6 +148,8 @@ static const command_rec nss_config_cmds
                "(`nickname')")
     SSL_CMD_SRV(ProxyCheckPeerCN, FLAG,
                 "SSL Proxy: check the peers certificate CN")
+    SSL_CMD_SRV(ProxyCheckPeerCA, FLAG,
+                "SSL Proxy: check the peers certificate CA")
 
 #ifdef IGNORE
     /* Deprecated directives. */
@@ -258,12 +261,18 @@ static int ssl_engine_disable(conn_rec *
 SECStatus NSSBadCertHandler(void *arg, PRFileDesc * socket)
 {
     conn_rec *c = (conn_rec *)arg;
+    SECStatus rv = SECFailure;
     SSLSrvConfigRec *sc = mySrvConfig(c->base_server);
     PRErrorCode err = PR_GetError();
-    SECStatus rv = SECFailure;
-    CERTCertificate *peerCert = SSL_PeerCertificate(socket);
+    CERTCertificate *peerCert = NULL;
+    peerCert = SSL_PeerCertificate(socket);
     const char *hostname_note;
+    char *subject, *subject_cn, *issuer;
                                                                                 
+    issuer = CERT_NameToAscii(&peerCert->issuer);
+    subject = CERT_NameToAscii(&peerCert->subject);
+    subject_cn = CERT_GetCommonName(&peerCert->subject);
+
     switch (err) {
         case SSL_ERROR_BAD_CERT_DOMAIN:
             if (sc->proxy_ssl_check_peer_cn == TRUE) {
@@ -271,10 +280,8 @@ SECStatus NSSBadCertHandler(void *arg, P
                     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);
+                            "SSL Proxy: Possible man-in-the-middle attack. The remove server is %s, we expected %s", subject_cn, hostname_note);
                     }
                 } else {
                     ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
@@ -284,12 +291,34 @@ SECStatus NSSBadCertHandler(void *arg, P
                 rv = SECSuccess;
             }
             break;
+        case SEC_ERROR_CA_CERT_INVALID:
+	  if (sc->proxy_ssl_check_peer_ca == FALSE) {
+	    rv = SECSuccess;
+	  }else {
+	    ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "Issuer certificate is invalid: '%s'", issuer);
+	  }
+	  break;
+	case SEC_ERROR_UNTRUSTED_ISSUER:
+	  ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "Certificate is signed by an untrusted issuer: '%s'",  issuer);
+	  break;
+	case SEC_ERROR_EXPIRED_CERTIFICATE:
+	  ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "Remote Certificate has expired.");
+	  break;
+	case SEC_ERROR_UNKNOWN_ISSUER:
+	  ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "Peer's certificate issuer is not recognized: '%s'", issuer);
+	  break;
         default:
-            ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
-                "Bad remote server certificate: %d", err);
-            nss_log_nss_error(APLOG_MARK, APLOG_ERR, NULL);
-            break;
+	  ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
+		       "Bad remote server certificate: %d. Subject = '%s', Issuer = '%s'", err, subject, issuer);
+	  nss_log_nss_error(APLOG_MARK, APLOG_ERR, NULL);
+	  break;
     }
+
+    PR_Free(subject);
+    PR_Free(subject_cn);
+    PR_Free(issuer);
+    CERT_DestroyCertificate(peerCert);
+
     return rv;
 }
 
@@ -400,11 +429,11 @@ static int nss_hook_pre_connection(conn_
      * authentication is requested.
      */
     if (!mctx->as_server) {
-        if (SSL_BadCertHook(ssl, (SSLBadCertHandler) NSSBadCertHandler, c) != SECSuccess)
+      if (SSL_BadCertHook(ssl, (SSLBadCertHandler) NSSBadCertHandler, c) != SECSuccess)
         {
-            /* errors are reported in the certificate handler */
-            return DECLINED;
-        }
+	  /* errors are reported in the certificate handler */
+          return DECLINED;
+	}
         if (mctx->nickname) {
             if (SSL_GetClientAuthDataHook(ssl, NSSGetClientAuthData,
                                           (void*)mctx->nickname) != SECSuccess)
Index: mod_nss-1.0.8/nss_engine_config.c
===================================================================
--- mod_nss-1.0.8.orig/nss_engine_config.c
+++ mod_nss-1.0.8/nss_engine_config.c
@@ -142,6 +142,7 @@ static SSLSrvConfigRec *nss_config_serve
     sc->proxy                       = NULL;
     sc->server                      = NULL;
     sc->proxy_ssl_check_peer_cn     = TRUE;
+    sc->proxy_ssl_check_peer_ca     = FALSE;
 
     modnss_ctx_init_proxy(sc, p);
 
@@ -218,6 +219,7 @@ void *nss_config_server_merge(apr_pool_t
     cfgMergeBool(sni);
     cfgMergeBool(proxy_enabled);
     cfgMergeBool(proxy_ssl_check_peer_cn);
+    cfgMergeBool(proxy_ssl_check_peer_ca);
 
     modnss_ctx_cfg_merge_proxy(base->proxy, add->proxy, mrg->proxy);
 
@@ -565,6 +567,15 @@ const char *nss_cmd_NSSProxyCheckPeerCN(
 
     return NULL;
 }
+
+const char *nss_cmd_NSSProxyCheckPeerCA(cmd_parms *cmd, void *dcfg, int flag)
+{
+    SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
+
+    sc->proxy_ssl_check_peer_ca = flag ? TRUE : FALSE;
+
+    return NULL;
+}
 
 const char *nss_cmd_NSSEnforceValidCerts(cmd_parms *cmd,
                                          void *dcfg,
Index: mod_nss-1.0.8/mod_nss.h
===================================================================
--- mod_nss-1.0.8.orig/mod_nss.h
+++ mod_nss-1.0.8/mod_nss.h
@@ -315,6 +315,7 @@ struct SSLSrvConfigRec {
     modnss_ctx_t    *server;
     modnss_ctx_t    *proxy;
     BOOL             proxy_ssl_check_peer_cn;
+    BOOL             proxy_ssl_check_peer_ca;
 };
 
 /*
@@ -435,6 +436,7 @@ const char *nss_cmd_NSSProxyProtocol(cmd
 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);
+const char *nss_cmd_NSSProxyCheckPeerCA(cmd_parms *cmd, void *dcfg, int flag);
 const char *set_user(cmd_parms *cmd, void *dummy, const char *arg);
 
 /*  module initialization  */
@@ -496,6 +498,9 @@ int          nss_io_buffer_fill(request_
 
 int nss_rand_seed(server_rec *s, apr_pool_t *p, ssl_rsctx_t nCtx, char *prefix);
 
+/* check certificate globally */
+SECStatus NSSBadCertHandler(void *arg, PRFileDesc * socket);
+
 /* Pass Phrase Handling */
 SECStatus nss_Init_Tokens(server_rec *s);
 
Index: mod_nss-1.0.8/docs/mod_nss.html
===================================================================
--- mod_nss-1.0.8.orig/docs/mod_nss.html
+++ mod_nss-1.0.8/docs/mod_nss.html
@@ -1127,7 +1127,8 @@ requests client authentication.<br>
 <br>
 <code>NSSProxyNickname beta<br>
 <br>
-</code><big><big>NSSProxyCheckPeerCN</big></big><br>
+</code>
+<big><big>NSSProxyCheckPeerCN</big></big><br>
 <br>
 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
@@ -1137,7 +1138,19 @@ man-in-the-middle attack so leaving this
 <br>
 <span style="font-weight: bold;">Example</span><br>
 <br>
-<span style="font-family: monospace;">NSSProcyCheckPeerCN</span><code>
+<span style="font-family: monospace;">NSSProxyCheckPeerCN</span><code>
+on<br>
+</code><br>
+<big><big>NSSProxyCheckPeerCA</big></big><br>
+<br>
+When a proxy is configured to forward requests to a remote SSL server, this
+directive can be used to check certificate authority verification of the
+remote server. When check fails then you will get
+SEC_ERROR_CA_CERT_INVALID. The default value for this variable is off.
+<br>
+<span style="font-weight: bold;">Example</span><br>
+<br>
+<span style="font-family: monospace;">NSSProxyCheckPeerCA</span><code>
 on<br>
 </code><br>
 <h1><a name="Environment"></a>Environment Variables</h1>
_______________________________________________
Mod_nss-list mailing list
[email protected]
https://www.redhat.com/mailman/listinfo/mod_nss-list

Reply via email to