[Pkg-fedora-ds-maintainers] [libapache2-mod-nss] 43/156: Add proxy support to mod_nss. Most of the changes are related to adding new configuration directives. For the others we need to initialize an NSS socket differently whether we will be acting as a client or a server.

Timo Aaltonen tjaalton-guest at moszumanska.debian.org
Wed Jul 2 13:55:25 UTC 2014


This is an automated email from the git hooks/post-receive script.

tjaalton-guest pushed a commit to branch master
in repository libapache2-mod-nss.

commit bbde2f3f569b0b483b2ba8ce0cf5b43092f210ff
Author: rcritten <>
Date:   Thu Sep 29 19:35:44 2005 +0000

    Add proxy support to mod_nss. Most of the changes are related to
    adding new configuration directives. For the others we need to
    initialize an NSS socket differently whether we will be acting as a
    client or a server.
---
 docs/mod_nss.html   | 174 +++++++++++++++++++++++++++++++++++++++++-----------
 mod_nss.c           | 129 ++++++++++++++++++++++++++++----------
 mod_nss.h           |  14 ++++-
 nss_engine_config.c |  71 +++++++++++++++++++--
 nss_engine_init.c   | 107 ++++++++++++++++++++++----------
 5 files changed, 385 insertions(+), 110 deletions(-)

diff --git a/docs/mod_nss.html b/docs/mod_nss.html
index 8d38d47..7d6f5f1 100644
--- a/docs/mod_nss.html
+++ b/docs/mod_nss.html
@@ -1,4 +1,6 @@
 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
 <!--
  Copyright 2001-2005 The Apache Software Foundation
 
@@ -13,8 +15,6 @@
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
 -->
-<html>
-<head>
   <meta content="text/html; charset=ISO-8859-1"
  http-equiv="content-type">
   <title>mod_nss</title>
@@ -32,25 +32,18 @@
 <a href="#Environment">Environment Variables</a><br>
 <a href="#Database_Management">Database Management</a><br>
 <a href="#SSLv2">Why is SSLv2 disabled?</a><br>
-<br>
+<a href="#FAQ">Frequently Asked Questions</a><br>
 <h1><a name="Introduction"></a>Introduction</h1>
 The <a href="http://www.modssl.org/">mod_ssl</a> package was
 created in April 1998 by <a href="mailto:rse at engelschall.com">Ralf S.
 Engelschall</a> and was originally derived from the <a
  href="http://www.apache-ssl.org/">Apache-SSL</a> package developed by <a
- href="mailto:ben at algroup.co.uk">Ben Laurie</a>. It stays under a
-BSD-style
-license which is equivalent to the license used by <a
- href="http://www.apache.org/">The Apache Group</a> for the Apache
-webserver
-itself. This means, in short, that you are free to use it both for
-commercial
-and non-commercial purposes as long as you retain the authors'
-copyright
-notices and give the proper credit.
-<br>
-<br>
-mod_nss is based directly on the mod_ssl package from Apache
+ href="mailto:ben at algroup.co.uk">Ben Laurie</a>. It is licensed under
+the <a href="http://www.apache.org/licenses/" class="external"
+ title="http://www.apache.org/licenses/" rel="nofollow">Apache 2.0
+license</a><span class="urlexpansion">.<br>
+<br>
+</span>mod_nss is based directly on the mod_ssl package from Apache
 2.0.54.  It is a conversion from using OpenSSL calls to using <a
  href="http://www.mozilla.org/projects/security/pki/nss/">NSS</a>
 calls instead.<br>
@@ -94,6 +87,20 @@ PATH/include, etc.<br>
       </td>
     </tr>
     <tr>
+      <td style="vertical-align: top;">--with-nss-inc=PATH<br>
+      </td>
+      <td style="vertical-align: top;">The file system path to the NSS
+include directory (e.g. /usr/local/include/nss3)<br>
+      </td>
+    </tr>
+    <tr>
+      <td style="vertical-align: top;">--with-nss-lib=PATH<br>
+      </td>
+      <td style="vertical-align: top;">The file system path to the NSS
+lib directory (e.g. /usr/local/lib)<br>
+      </td>
+    </tr>
+    <tr>
       <td style="vertical-align: top;">--with-nspr=[PATH]<br>
       </td>
       <td style="vertical-align: top;">The file system path of the NSPR
@@ -101,6 +108,20 @@ installation. The assumption is that this has the layout of: PATH/lib,
 PATH/include, etc.</td>
     </tr>
     <tr>
+      <td style="vertical-align: top;">--with-nspr-inc=PATH<br>
+      </td>
+      <td style="vertical-align: top;">The file system path to the NSPR
+include directory (e.g. /usr/local/include/nspr4)<br>
+      </td>
+    </tr>
+    <tr>
+      <td style="vertical-align: top;">--with-nspr-lib=PATH<br>
+      </td>
+      <td style="vertical-align: top;">The file system path to the NSPR
+lib directory (e.g. /usr/local/lib)<br>
+      </td>
+    </tr>
+    <tr>
       <td style="vertical-align: top;">--with-apxs=[PATH]<br>
       </td>
       <td style="vertical-align: top;">The location of the apxs binary
@@ -117,7 +138,7 @@ tells us where the APR include files and libraries are located<br>
 </table>
 <br>
  If --with-nss or --with-nspr are not passed configure will look
-for the mozilla-[nss|nspr]-devel packages and use the libraries with
+for the [nss|nspr]-devel packages and use the libraries with
 that if found.<br>
 <br>
  It is strongly recommended that the mozilla.org version be used.<br>
@@ -371,12 +392,12 @@ limited to those that are FIPS-certified. Any non-FIPS that are
 included in the NSSCipherSuite entry are automatically disabled.
 The allowable ciphers are:<br>
 <ul>
-<li>rsa_3des_sha</li>
-<li>rsa_des_sha</li>
-<li>fips_3des_sha</li>
-<li>fips_des_sha</li>
-<li>rsa_des_56_sha</li>
-<li>fortezza</li>
+  <li>rsa_3des_sha</li>
+  <li>rsa_des_sha</li>
+  <li>fips_3des_sha</li>
+  <li>fips_des_sha</li>
+  <li>rsa_des_56_sha</li>
+  <li>fortezza</li>
 </ul>
 <span style="font-weight: bold;"><br>
 </span>FIPS is disabled by default.<br>
@@ -404,7 +425,8 @@ Example</span><br style="font-weight: bold;">
 A space-separated list of the SSL ciphers used, with the prefix <code>+</code>
 to enable or <code>-</code> to disable.<br>
 <br>
-All ciphers are disabled by default. The SSLv2 ciphers cannot be enabled because
+All ciphers are disabled by default. The SSLv2 ciphers cannot be
+enabled because
 <a href="#SSLv2">SSLv2</a> is not allowed in mod_nss.<br>
 <br>
 Available ciphers are:<br>
@@ -622,7 +644,7 @@ be enclosed in double quotes.<br>
 <code>NSSNickname Server-Cert</code><br>
 <code>NSSNickname "This contains a space"</code><br>
 <br>
-NSSEnforceValidCerts<br>
+<big><big>NSSEnforceValidCerts</big></big><br>
 <br>
 By default mod_nss will not start up if the server
 certificate is not valid. This means that if the certificate has
@@ -636,7 +658,7 @@ not recommended.<br>
 <br>
 <code>NSSEnforceValidCerts on</code><br>
 <br>
-NSSVerifyClient<br>
+<big><big>NSSVerifyClient</big></big><br>
 <br>
 Determines whether Client Certificate
 Authentication will be requested or required. This may be set in a
@@ -646,18 +668,17 @@ per-directry context an SSL renogitation is required and a certificate
 requested from the client.<br>
 <br>
 Available options are:<br>
-
 <ul>
   <li><code>none</code>: no client certificate
 is required or requested<br>
-    </li>
-  <li>code>optional</code>: a client
+  </li>
+  <li>code>optional: a client
 certificate is requested but if one is not available, the connection
 may continue.<br>
-    </li>
+  </li>
   <li><code>require</code>: a valid client
 certificate is required for the connection to continue.<br>
-    </li>
+  </li>
 </ul>
 The mod_ssl option <code>option_no_ca</code>
 is not supported.<br>
@@ -732,7 +753,45 @@ Provides a regular expression-based access-control mechanism. Access
 may be restricted (or allowed) based on any number of variables such as
 components of the client certificate, the remote IP address, etc.<br>
 <br>
-<code>NSSRequire</code><br>
+<span style="font-weight: bold;">Example</span><br>
+<br>
+<code>NSSRequire<br>
+</code><br>
+<big><big>NSSProxyEngine</big></big><br>
+<br>
+Enables or disables mod_nss HTTPS support for mod_proxy.<br>
+<br>
+<span style="font-weight: bold;">Example</span><br>
+<br>
+<code>NSSProxyEngine on</code><br>
+<br>
+<big><big>NSSProxyProtocol</big></big><br>
+<br>
+Specifies the SSL protocols that may be used in proxy connections. The
+syntax is identical to NSSProtocol.<br>
+<br>
+<span style="font-weight: bold;">Example</span><br>
+<br>
+<code>NSSProxyProtocol SSLv3<br>
+</code><br>
+<big><big>NSSProxyCipherSuite</big></big><br>
+<br>
+Specifies the SSL ciphers available for proxy connections. They syntax
+is identical to NSSCipherSuite.<br>
+<br>
+<span style="font-weight: bold;">Example</span><br>
+<br>
+<code>NSSProxyCipherSuite
++rsa_3des_sha,-rsa_null_md5,-rsa_null_sha,+rsa_rc4_128_md5</code><br>
+<br>
+<big><big>NSSProxyNickname</big></big><br>
+<br>
+The nickname of the client certificate to send if the remote server
+requests client authentication.<br>
+<br>
+<span style="font-weight: bold;">Example</span><br>
+<br>
+<code>NSSProxyNickname beta</code><br>
 <h1><a name="Environment"></a>Environment Variables</h1>
 Quite a few environment variables (for CGI and SSI) may be set
 depending on the NSSOptions configuration. It can be expensive to set
@@ -1121,10 +1180,53 @@ have NSS validate it:<br>
 <code>% certutil -V -n Server-Cert -u V -d .<br>
 certutil: certificate is valid</code><br>
 <h1><a name="SSLv2"></a>Why is SSLv2 disabled?</h1>
-All major browsers (Firefox, Internet Explorer, Mozilla, Netscape, Opera, and
-Safari) support SSL 3 and TLS so there is no need for a web server to support
+All major browsers (Firefox, Internet Explorer, Mozilla, Netscape,
+Opera, and
+Safari) support SSL 3 and TLS so there is no need for a web server to
+support
 SSL 2. There are some known attacks against SSL 2 that are handled by
-SSL 3/TLS. SSL2 also doesn't support useful features like client authentication.
-<br>
+SSL 3/TLS. SSL2 also doesn't support useful features like client
+authentication.
+<br>
+<h1><a name="FAQ"></a>Frequently Asked Questions</h1>
+Q. Does mod_nss support mod_proxy?<br>
+<br>
+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 <a
+ href="http://issues.apache.org/bugzilla/show_bug.cgi?id=36468">36468</a>.
+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.<br>
+<br>
+You also have to change the SSL functions that mod_proxy looks to use.
+You'll need to apply this patch:<br>
+<br>
+<code>1038,1039c1038,1039<br>
+< APR_DECLARE_OPTIONAL_FN(int, ssl_proxy_enable, (conn_rec *));<br>
+< APR_DECLARE_OPTIONAL_FN(int, ssl_engine_disable, (conn_rec *));<br>
+---<br>
+> APR_DECLARE_OPTIONAL_FN(int, nss_proxy_enable, (conn_rec *));<br>
+> APR_DECLARE_OPTIONAL_FN(int, nss_engine_disable, (conn_rec *));<br>
+1041,1042c1041,1042<br>
+< static APR_OPTIONAL_FN_TYPE(ssl_proxy_enable) *proxy_ssl_enable =
+NULL;<br>
+< static APR_OPTIONAL_FN_TYPE(ssl_engine_disable) *proxy_ssl_disable
+= NULL;<br>
+---<br>
+> static APR_OPTIONAL_FN_TYPE(nss_proxy_enable) *proxy_ssl_enable =
+NULL;<br>
+> static APR_OPTIONAL_FN_TYPE(nss_engine_disable) *proxy_ssl_disable
+= NULL;<br>
+1069,1070c1069,1070<br>
+<     proxy_ssl_enable =
+APR_RETRIEVE_OPTIONAL_FN(ssl_proxy_enable);<br>
+<     proxy_ssl_disable =
+APR_RETRIEVE_OPTIONAL_FN(ssl_engine_disable);<br>
+---<br>
+>     proxy_ssl_enable =
+APR_RETRIEVE_OPTIONAL_FN(nss_proxy_enable);<br>
+>     proxy_ssl_disable =
+APR_RETRIEVE_OPTIONAL_FN(nss_engine_disable);<br>
+</code><br>
 </body>
 </html>
diff --git a/mod_nss.c b/mod_nss.c
index e546680..2dd2f3c 100644
--- a/mod_nss.c
+++ b/mod_nss.c
@@ -15,6 +15,7 @@
 
 #include "mod_nss.h"
 #include <assert.h>
+#include "sslerr.h"
 
 /*
  *  the table of configuration directives we provide
@@ -101,7 +102,6 @@ static const command_rec nss_config_cmds[] = {
     SSL_CMD_DIR(Require, AUTHCFG, RAW_ARGS,
                "Require a boolean expression to evaluate to true for granting access" 
                "(arbitrary complex boolean expression - see manual)")
-#ifdef PROXY
     /* 
      * Proxy configuration for remote SSL connections
      */
@@ -114,31 +114,11 @@ static const command_rec nss_config_cmds[] = {
     SSL_CMD_SRV(ProxyCipherSuite, TAKE1,
                "SSL Proxy: colon-delimited list of permitted SSL ciphers "
                "(`XXX:...:XXX' - see manual)")
-    SSL_CMD_SRV(ProxyVerify, TAKE1,
-               "SSL Proxy: whether to verify the remote certificate "
-               "(`on' or `off')")
-    SSL_CMD_SRV(ProxyVerifyDepth, TAKE1,
-               "SSL Proxy: maximum certificate verification depth "
-               "(`N' - number of intermediate certificates)")
-    SSL_CMD_SRV(ProxyCACertificateFile, TAKE1,
-               "SSL Proxy: file containing server certificates "
-               "(`/path/to/file' - PEM encoded certificates)")
-    SSL_CMD_SRV(ProxyCACertificatePath, TAKE1,
-               "SSL Proxy: directory containing server certificates "
-               "(`/path/to/dir' - contains PEM encoded certificates)")
-    SSL_CMD_SRV(ProxyCARevocationPath, TAKE1,
-                "SSL Proxy: CA Certificate Revocation List (CRL) path "
-                "(`/path/to/dir' - contains PEM encoded files)")
-    SSL_CMD_SRV(ProxyCARevocationFile, TAKE1,
-                "SSL Proxy: CA Certificate Revocation List (CRL) file "
-                "(`/path/to/file' - PEM encoded)")
-    SSL_CMD_SRV(ProxyMachineCertificateFile, TAKE1,
-               "SSL Proxy: file containing client certificates "
-               "(`/path/to/file' - PEM encoded certificates)")
-    SSL_CMD_SRV(ProxyMachineCertificatePath, TAKE1,
-               "SSL Proxy: directory containing client certificates "
-               "(`/path/to/dir' - contains PEM encoded certificates)")
+    SSL_CMD_SRV(ProxyNickname, TAKE1,
+               "SSL Proxy: client certificate Nickname to be for proxy connections "
+               "(`nickname')")
 
+#ifdef IGNORE
     /* Deprecated directives. */
     AP_INIT_RAW_ARGS("NSSLog", ap_set_deprecated, NULL, OR_ALL, 
       "SSLLog directive is no longer supported - use ErrorLog."),
@@ -183,7 +163,6 @@ static SSLConnRec *nss_init_connection_ctx(conn_rec *c)
     return sslconn;
 }
 
-#ifdef PROXY
 int nss_proxy_enable(conn_rec *c)
 {
     SSLSrvConfigRec *sc = mySrvConfig(c->base_server);
@@ -193,7 +172,7 @@ int nss_proxy_enable(conn_rec *c)
     if (!sc->proxy_enabled) {
         ap_log_error(APLOG_MARK, APLOG_ERR, 0, c->base_server,
                      "SSL Proxy requested for %s but not enabled "
-                     "[Hint: SSLProxyEngine]", sc->vhost_id);
+                     "[Hint: NSSProxyEngine]", sc->vhost_id);
 
         return 0;
     }
@@ -203,7 +182,6 @@ int nss_proxy_enable(conn_rec *c)
 
     return 1;
 }
-#endif
 
 int nss_engine_disable(conn_rec *c)
 {
@@ -222,6 +200,76 @@ int nss_engine_disable(conn_rec *c)
     return 1;
 }
 
+/* Callback for an incoming certificate that is not valid */
+
+SECStatus NSSBadCertHandler(void *arg, PRFileDesc * socket)
+{
+    conn_rec *c = (conn_rec *)arg;
+    PRErrorCode err = PR_GetError();
+    SECStatus rv = SECFailure;
+    CERTCertificate *peerCert = SSL_PeerCertificate(socket);
+                                                                                
+    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);
+                    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, rv);
+                    PORT_Free(remote);
+                }
+            } 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.");
+            }
+            break;
+        default:
+            ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
+                "Bad remote server certificate.", err);
+            nss_log_nss_error(APLOG_MARK, APLOG_ERR, NULL);
+            break;
+    }
+    return rv;
+}
+
+/* Callback to pull the client certificate upon server request */
+
+static SECStatus NSSGetClientAuthData(void *arg, PRFileDesc *socket,
+                                    CERTDistNames *caNames,
+                                    CERTCertificate **pRetCert,/*return */
+                                    SECKEYPrivateKey **pRetKey)
+{
+    CERTCertificate *               cert;
+    SECKEYPrivateKey *              privKey;
+    void *                          proto_win = NULL;
+    SECStatus                       rv = SECFailure;
+    char *                          localNickName = (char *)arg;
+
+    proto_win = SSL_RevealPinArg(socket);
+
+    if (localNickName) {
+        cert = CERT_FindUserCertByUsage(CERT_GetDefaultCertDB(),
+                                    localNickName, certUsageSSLClient,
+                                    PR_FALSE, proto_win);
+        if (cert) {
+            privKey = PK11_FindKeyByAnyCert(cert, proto_win);
+            if (privKey) {
+                rv = SECSuccess;
+            } else {
+                CERT_DestroyCertificate(cert);
+            }
+        } 
+
+        if (rv == SECSuccess) {
+            *pRetCert = cert;
+            *pRetKey  = privKey;
+        }
+    }
+
+    return rv;
+}
+
 static int nss_hook_pre_connection(conn_rec *c, void *csd)
 {
     SSLSrvConfigRec *sc = mySrvConfig(c->base_server);
@@ -285,7 +333,28 @@ static int nss_hook_pre_connection(conn_rec *c, void *csd)
 
     nss_io_filter_init(c, ssl);
 
-    SSL_ResetHandshake(ssl, PR_TRUE);
+    SSL_ResetHandshake(ssl, mctx->as_server);
+
+    /* If we are doing a client connection, set our own bad certificate
+     * handler and register the nickname we want to use in case client
+     * authentication is requested.
+     */
+    if (!mctx->as_server) {
+        if (SSL_BadCertHook(ssl, (SSLBadCertHandler) NSSBadCertHandler, c) != SECSuccess)
+        {
+            /* errors are reported in the certificate handler */
+            return DECLINED;
+        }
+        if (mctx->nickname) {
+            if (SSL_GetClientAuthDataHook(ssl, NSSGetClientAuthData,
+                                          (void*)mctx->nickname) != SECSuccess)
+            {
+                ap_log_error(APLOG_MARK, APLOG_ERR, 0, c->base_server,
+                    "Unable to register client authentication callback");
+                return DECLINED;
+            }
+        }
+    }
 
     return APR_SUCCESS;
 }
@@ -335,9 +404,7 @@ static void nss_register_hooks(apr_pool_t *p)
 
     nss_var_register();
 
-#ifdef PROXY
     APR_REGISTER_OPTIONAL_FN(nss_proxy_enable);
-#endif
     APR_REGISTER_OPTIONAL_FN(nss_engine_disable);
 }
 
diff --git a/mod_nss.h b/mod_nss.h
index eb452cb..a2a4bef 100644
--- a/mod_nss.h
+++ b/mod_nss.h
@@ -238,6 +238,8 @@ typedef struct {
     
     char *cipherSuite;
 
+    int as_server;
+
     int ssl2;
     int ssl3;
     int tls;
@@ -278,9 +280,7 @@ typedef struct {
     int                 nOptionsAdd;
     int                 nOptionsDel;
     const char         *szCipherSuite;
-    nss_verify_t   nVerifyClient;
-    const char         *szCACertificatePath;
-    const char         *szCACertificateFile;
+    nss_verify_t        nVerifyClient;
     const char         *szUserName;
 } SSLDirConfigRec;
 
@@ -333,6 +333,11 @@ const char *nss_cmd_NSSOptions(cmd_parms *, void *, const char *);
 const char *nss_cmd_NSSRequireSSL(cmd_parms *cmd, void *dcfg);
 const char  *nss_cmd_NSSRequire(cmd_parms *, void *, const char *);
 
+const char *nss_cmd_NSSProxyEngine(cmd_parms *cmd, void *dcfg, int flag);
+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);
+
 /*  module initialization  */
 int  nss_init_Module(apr_pool_t *, apr_pool_t *, apr_pool_t *, server_rec *);
 void nss_init_Child(apr_pool_t *, server_rec *);
@@ -363,8 +368,11 @@ APR_DECLARE_OPTIONAL_FN(char *, nss_var_lookup,
 APR_DECLARE_OPTIONAL_FN(int, nss_is_https, (conn_rec *));
 
 /* Proxy Support */
+int nss_proxy_enable(conn_rec *c);
 int nss_engine_disable(conn_rec *c);
 
+APR_DECLARE_OPTIONAL_FN(int, nss_proxy_enable, (conn_rec *));
+
 APR_DECLARE_OPTIONAL_FN(int, nss_engine_disable, (conn_rec *));
 
 /* I/O */
diff --git a/nss_engine_config.c b/nss_engine_config.c
index 9eb0cea..a13cdab 100644
--- a/nss_engine_config.c
+++ b/nss_engine_config.c
@@ -69,6 +69,8 @@ static void modnss_ctx_init(modnss_ctx_t *mctx)
 {
     mctx->sc                  = NULL; /* set during module init */
 
+    mctx->as_server           = PR_TRUE;
+
     mctx->ssl2                = PR_FALSE;
     mctx->ssl3                = PR_FALSE;
     mctx->tls                 = PR_FALSE;
@@ -87,6 +89,18 @@ static void modnss_ctx_init(modnss_ctx_t *mctx)
 
 }
 
+static void modnss_ctx_init_proxy(SSLSrvConfigRec *sc,
+                                  apr_pool_t *p)
+{
+    modnss_ctx_t *mctx;
+
+    mctx = sc->proxy = apr_palloc(p, sizeof(*sc->proxy));
+
+    modnss_ctx_init(mctx);
+
+    mctx->as_server = PR_FALSE;
+}
+
 static void modnss_ctx_init_server(SSLSrvConfigRec *sc,
                                    apr_pool_t *p)
 {
@@ -95,6 +109,8 @@ static void modnss_ctx_init_server(SSLSrvConfigRec *sc,
     mctx = sc->server = apr_palloc(p, sizeof(*sc->server));
 
     modnss_ctx_init(mctx);
+
+    mctx->as_server = PR_TRUE;
 }
 
 static SSLSrvConfigRec *nss_config_server_new(apr_pool_t *p)
@@ -111,9 +127,7 @@ static SSLSrvConfigRec *nss_config_server_new(apr_pool_t *p)
     sc->proxy                       = NULL;
     sc->server                      = NULL;
 
-#ifdef PROXY
     modnss_ctx_init_proxy(sc, p);
-#endif
 
     modnss_ctx_init_server(sc, p);
 
@@ -149,6 +163,13 @@ static void modnss_ctx_cfg_merge(modnss_ctx_t *base,
     cfgMerge(enforce, PR_TRUE);
 }
 
+static void modnss_ctx_cfg_merge_proxy(modnss_ctx_t *base,
+                                       modnss_ctx_t *add,
+                                       modnss_ctx_t *mrg)
+{
+    modnss_ctx_cfg_merge(base, add, mrg);
+}
+
 static void modnss_ctx_cfg_merge_server(modnss_ctx_t *base,
                                         modnss_ctx_t *add,
                                         modnss_ctx_t *mrg)
@@ -170,9 +191,7 @@ void *nss_config_server_merge(apr_pool_t *p, void *basev, void *addv) {
     cfgMergeBool(enabled);
     cfgMergeBool(proxy_enabled);
 
-#ifdef PROXY 
     modnss_ctx_cfg_merge_proxy(base->proxy, add->proxy, mrg->proxy);
-#endif
 
     modnss_ctx_cfg_merge_server(base->server, add->server, mrg->server);
 
@@ -270,7 +289,7 @@ const char *nss_cmd_NSSEngine(cmd_parms *cmd, void *dcfg, int flag)
 const char *nss_cmd_NSSFIPS(cmd_parms *cmd, void *dcfg, int flag)
 {
     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
-
+    
     sc->fips = flag ? TRUE : FALSE;
  
     return NULL;
@@ -281,7 +300,7 @@ const char *nss_cmd_NSSOCSP(cmd_parms *cmd, void *dcfg, int flag)
     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
 
     sc->ocsp = flag ? TRUE : FALSE;
- 
+
     return NULL;
 }
 
@@ -395,6 +414,46 @@ const char *nss_cmd_NSSNickname(cmd_parms *cmd,
     return NULL;
 }
 
+const char *nss_cmd_NSSProxyEngine(cmd_parms *cmd, void *dcfg, int flag)
+{
+    SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
+ 
+    sc->proxy_enabled = flag ? TRUE : FALSE;
+
+    return NULL;
+}
+ 
+const char *nss_cmd_NSSProxyProtocol(cmd_parms *cmd,
+                                     void *dcfg,
+                                     const char *arg)
+{
+    SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
+
+    sc->proxy->auth.protocols = arg;
+}
+
+const char *nss_cmd_NSSProxyCipherSuite(cmd_parms *cmd,
+                                        void *dcfg,
+                                        const char *arg)
+{
+    SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
+ 
+    sc->proxy->auth.cipher_suite = arg;
+ 
+    return NULL;
+}
+ 
+const char *nss_cmd_NSSProxyNickname(cmd_parms *cmd,
+                                void *dcfg,
+                                const char *arg)
+{
+    SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
+
+    sc->proxy->nickname = arg;
+
+    return NULL;
+}
+
 const char *nss_cmd_NSSEnforceValidCerts(cmd_parms *cmd,
                                          void *dcfg,
                                          int flag)
diff --git a/nss_engine_init.c b/nss_engine_init.c
index 78fb56c..7eda971 100644
--- a/nss_engine_init.c
+++ b/nss_engine_init.c
@@ -16,7 +16,9 @@
 #include "mod_nss.h"
 #include "apr_thread_proc.h"
 #include "ap_mpm.h"
-#include <secmod.h>
+#include "secmod.h"
+#include "sslerr.h"
+#include "pk11func.h"
 
 static SECStatus ownBadCertHandler(void *arg, PRFileDesc * socket);
 static SECStatus ownHandshakeCallback(PRFileDesc * socket, void *arg);
@@ -111,6 +113,7 @@ static void nss_init_SSLLibrary(server_rec *s, int sslenabled, int fipsenabled,
     SSLModConfigRec *mc = myModConfig(s);
     SSLSrvConfigRec *sc; 
     int forked = 0;
+    char cwd[PATH_MAX];
 
     sc = mySrvConfig(s);
 
@@ -172,8 +175,14 @@ static void nss_init_SSLLibrary(server_rec *s, int sslenabled, int fipsenabled,
     /* Set the PKCS #11 strings for the internal token. */
     PK11_ConfigurePKCS11(NULL,NULL,NULL, INTERNAL_TOKEN_NAME, NULL, NULL,NULL,NULL,8,1);
 
+    /* We need to be in the same directory as libnssckbi.so to load the
+     * root certificates properly.
+     */
+    getcwd(cwd, PATH_MAX);
+    chdir(mc->pCertificateDatabase);
     /* Initialize NSS and open the certificate database read-only. */
     rv = NSS_Initialize(mc->pCertificateDatabase, mc->pDBPrefix, mc->pDBPrefix, "secmod.db", NSS_INIT_READONLY);
+    chdir(cwd);
 
     /* Assuming everything is ok so far, check the cert database password(s). */
     if (sslenabled && (rv != SECSuccess)) {
@@ -287,11 +296,9 @@ int nss_init_Module(apr_pool_t *p, apr_pool_t *plog,
             sc->server->sc = sc;
         }
 
-#ifdef PROXY
         if (sc->proxy) {
             sc->proxy->sc = sc;
         }
-#endif
 
         /*
          * Create the server host:port string because we need it a lot
@@ -366,8 +373,8 @@ int nss_init_Module(apr_pool_t *p, apr_pool_t *plog,
 
 
     /*
-     *  Announce mod_ssl and SSL library in HTTP Server field
-     *  as ``mod_ssl/X.X.X OpenSSL/X.X.X''
+     *  Announce mod_nss and SSL library in HTTP Server field
+     *  as ``mod_nss/X.X.X NSS/X.X.X''
      */
     nss_add_version_components(p, base_server);
 
@@ -391,20 +398,28 @@ static void nss_init_ctx_socket(server_rec *s,
         nss_die();
     }
 
-    if (SSL_OptionSet(mctx->model, SSL_HANDSHAKE_AS_SERVER, PR_TRUE)
+    if (SSL_OptionSet(mctx->model, SSL_HANDSHAKE_AS_SERVER, mctx->as_server)
             != SECSuccess) {
         ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
                 "Unable to set SSL server handshake mode.");
         nss_log_nss_error(APLOG_MARK, APLOG_ERR, s);
         nss_die();
     }
-    if (SSL_OptionSet(mctx->model, SSL_HANDSHAKE_AS_CLIENT, PR_FALSE)
+    if (SSL_OptionSet(mctx->model, SSL_HANDSHAKE_AS_CLIENT, !mctx->as_server)
             != SECSuccess) {
         ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
-                "Unable to disable handshake as client");
+                "Unable to set handshake as client");
         nss_log_nss_error(APLOG_MARK, APLOG_ERR, s);
         nss_die();
     }
+    if (!mctx->as_server) {
+        if ((SSL_OptionSet(mctx->model, SSL_NO_CACHE, PR_TRUE)) != SECSuccess) {
+            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
+                    "Unable to disable SSL client caching");
+            nss_log_nss_error(APLOG_MARK, APLOG_ERR, s);
+            nss_die();
+        }
+    }
 }
 
 static void nss_init_ctx_protocol(server_rec *s,
@@ -622,7 +637,8 @@ static void nss_init_ctx_cipher_suite(server_rec *s,
         ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
                  "FIPS mode enabled, permitted SSL ciphers are: [%s]",
                  fipsciphers);
-    } 
+    }
+
     ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
                 "Configuring permitted SSL ciphers [%s]",
                  suite);
@@ -666,7 +682,7 @@ static void nss_init_ctx_cipher_suite(server_rec *s,
                 ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
                     "Cipher %s is enabled but this is not a FIPS cipher, disabling.", ciphers_def[i].name);
                 cipher_state[i] = PR_FALSE;
-            }   
+            }
         }
     }
 
@@ -728,18 +744,20 @@ static void nss_init_server_certs(server_rec *s,
      * Get own certificate and private key.
      */
  
-    if (mctx->nickname == NULL) {
+    if (mctx->nickname == NULL && mctx->as_server) {
         ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
             "No certificate nickname provided.");
         nss_die();
     }
-    ap_log_error(APLOG_MARK, APLOG_INFO, 0, s,
-         "Using nickname %s.", mctx->nickname);
+
+    if (mctx->nickname != NULL)
+        ap_log_error(APLOG_MARK, APLOG_INFO, 0, s,
+             "Using nickname %s.", mctx->nickname);
 
     mctx->servercert = FindServerCertFromNickname(mctx->nickname);
 
     /* Verify the certificate chain. */
-    if (mctx->servercert != NULL) {
+    if (mctx->servercert != NULL && mctx->as_server) {
         SECCertificateUsage usage = certificateUsageSSLServer;
 
         if (CERT_VerifyCertificateNow(CERT_GetDefaultCertDB(), mctx->servercert, PR_TRUE, usage, NULL, NULL) != SECSuccess)  {
@@ -754,14 +772,14 @@ static void nss_init_server_certs(server_rec *s,
         }
     }
 
-    if (NULL == mctx->servercert)
+    if (NULL == mctx->servercert && mctx->as_server)
     {
         ap_log_error(APLOG_MARK, APLOG_INFO, 0, s,
             "Certificate not found: '%s'", mctx->nickname);
         nss_die();
     }
 
-    if (strchr(mctx->nickname, ':'))
+    if (mctx->nickname && strchr(mctx->nickname, ':'))
     {
         char* token = strdup(mctx->nickname);
         char* colon = strchr(token, ':');
@@ -786,17 +804,20 @@ static void nss_init_server_certs(server_rec *s,
         slot = PK11_GetInternalKeySlot();
     }
     
-    mctx->serverkey = PK11_FindPrivateKeyFromCert(slot, mctx->servercert, NULL);
-    PK11_FreeSlot(slot);
+    if (mctx->servercert) {
+        mctx->serverkey = PK11_FindPrivateKeyFromCert(slot, mctx->servercert, NULL);
+        PK11_FreeSlot(slot);
+    }
 
-    if (mctx->serverkey == NULL) {
+    if (mctx->as_server && mctx->serverkey == NULL) {
         ap_log_error(APLOG_MARK, APLOG_INFO, 0, s,
             "Key not found for: '%s'", mctx->nickname);
         nss_log_nss_error(APLOG_MARK, APLOG_ERR, s);
         nss_die();
     }
 
-    mctx->serverKEAType = NSS_FindCertKEAType(mctx->servercert);
+    if (mctx->as_server) {
+        mctx->serverKEAType = NSS_FindCertKEAType(mctx->servercert);
 
     /*
      * Check for certs that are expired or not yet valid and WARN about it
@@ -824,6 +845,7 @@ static void nss_init_server_certs(server_rec *s,
                 "Unhandled Certificate time type %d for: '%s'", certtimestatus, mctx->nickname);
             break;
     }
+    }
 
     secstatus = (SECStatus)SSL_SetPKCS11PinArg(mctx->model, NULL);
     if (secstatus != SECSuccess) {
@@ -832,15 +854,15 @@ static void nss_init_server_certs(server_rec *s,
         nss_die();
     }
     
-#if 1
-    secstatus = SSL_ConfigSecureServer(mctx->model, mctx->servercert, mctx->serverkey, mctx->serverKEAType);
-    if (secstatus != SECSuccess) {
-        ap_log_error(APLOG_MARK, APLOG_INFO, 0, s,
-            "SSL error configuring server: '%s'", mctx->nickname);
-        nss_log_nss_error(APLOG_MARK, APLOG_ERR, s);
-        nss_die();
+    if (mctx->as_server) {
+        secstatus = SSL_ConfigSecureServer(mctx->model, mctx->servercert, mctx->serverkey, mctx->serverKEAType);
+        if (secstatus != SECSuccess) {
+            ap_log_error(APLOG_MARK, APLOG_INFO, 0, s,
+                "SSL error configuring server: '%s'", mctx->nickname);
+            nss_log_nss_error(APLOG_MARK, APLOG_ERR, s);
+            nss_die();
+        }
     }
-#endif
 
     secstatus = (SECStatus)SSL_HandshakeCallback(mctx->model, (SSLHandshakeCallback)NSSHandshakeCallback, NULL);
     if (secstatus != SECSuccess)
@@ -852,6 +874,16 @@ static void nss_init_server_certs(server_rec *s,
     }
 }
 
+static void nss_init_proxy_ctx(server_rec *s,
+                                apr_pool_t *p,
+                                apr_pool_t *ptemp,
+                                SSLSrvConfigRec *sc)
+{
+    nss_init_ctx(s, p, ptemp, sc->proxy);
+
+    nss_init_server_certs(s, p, ptemp, sc->proxy);
+}
+
 static void nss_init_server_ctx(server_rec *s,
                                 apr_pool_t *p,
                                 apr_pool_t *ptemp,
@@ -876,11 +908,11 @@ void nss_init_ConfigureServer(server_rec *s,
         nss_init_server_ctx(s, p, ptemp, sc);
     }
 
-#ifdef PROXY
     if (sc->proxy_enabled) {
+        ap_log_error(APLOG_MARK, APLOG_INFO, 0, s,
+                     "Enabling proxy.");
         nss_init_proxy_ctx(s, p, ptemp, sc);
     }
-#endif
 }
 
 void nss_init_Child(apr_pool_t *p, server_rec *s)
@@ -936,10 +968,14 @@ SECStatus ownBadCertHandler(void *arg, PRFileDesc * socket)
 {
     PRErrorCode err = PR_GetError();
 
-    ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
-        "Bad certificate: %d", err);
-
-    return SECFailure;
+    switch (err) {
+        default:
+            ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
+                "Bad remote server certificate.", err);
+            nss_log_nss_error(APLOG_MARK, APLOG_ERR, NULL);
+            return SECFailure;
+            break;
+    }
 }
 
 /*
@@ -1028,6 +1064,9 @@ FindServerCertFromNickname(const char* name)
     PRUint32 bestCertMatchedUsage = 0;
     PRBool bestCertIsValid = PR_FALSE;
 
+    if (name == NULL)
+        return NULL;
+
     clist = PK11_ListCerts(PK11CertListUser, NULL);
 
     for (cln = CERT_LIST_HEAD(clist); !CERT_LIST_END(cln,clist);

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-fedora-ds/libapache2-mod-nss.git



More information about the Pkg-fedora-ds-maintainers mailing list