summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog6
-rw-r--r--Makefile.am13
-rw-r--r--docs/mod_nss.html317
-rw-r--r--mod_nss.h20
-rw-r--r--nss_engine_cipher.c322
-rw-r--r--nss_engine_cipher.h90
-rw-r--r--nss_engine_init.c129
-rw-r--r--nss_engine_kernel.c1
-rwxr-xr-xtest/createinstance.sh1
-rwxr-xr-xtest/setup.sh3
-rw-r--r--test/suite1.tmpl10
-rw-r--r--test/test.py6
-rw-r--r--test/test_cipher.py162
-rw-r--r--test/test_util.py36
-rw-r--r--test_cipher.c97
15 files changed, 946 insertions, 267 deletions
diff --git a/ChangeLog b/ChangeLog
index e5ca948..152af15 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,10 @@
2014-11-12 Rob Crittenden <rcritten@redhat.com>
+ * Add compatability for mod_ssl-style cipher definitions (#862938)
+ * Add Camelia ciphers
+ * Remove Fortezza ciphers
+ * Add TLSv1.2-specific ciphers
+
+2014-11-12 Rob Crittenden <rcritten@redhat.com>
* Initialize ciphers to all disabled before renegotiation
(#1165408)
diff --git a/Makefile.am b/Makefile.am
index fbfa62d..376bb2c 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -3,10 +3,14 @@ VERSION = 1.0.10
## This is the shared library to be built
lib_LTLIBRARIES = libmodnss.la
-bin_PROGRAMS = nss_pcache
+bin_PROGRAMS = nss_pcache test_cipher
nss_pcache_SOURCES = nss_pcache.c
+test_cipher_SOURCES = test_cipher.c
+test_cipher_LDADD = .libs/nss_engine_cipher.o
+test_cipher_CFLAGS = $(AM_CFLAGS) $(CFLAGS) $(EXTRA_CPPFLAGS)
+
man8_MANS = \
gencert.8 \
nss_pcache.8 \
@@ -16,7 +20,7 @@ install-data-hook:
@for i in $(man8_MANS) ; do gzip -f $(DESTDIR)$(man8dir)/$$i ; done
## Define the source file for the module
-libmodnss_la_SOURCES = mod_nss.c nss_engine_config.c nss_engine_init.c nss_engine_io.c nss_engine_kernel.c nss_engine_log.c nss_engine_pphrase.c nss_engine_vars.c nss_expr.c nss_expr_eval.c nss_expr_parse.y nss_expr_scan.l nss_util.c nss_engine_rand.c
+libmodnss_la_SOURCES = mod_nss.c nss_engine_config.c nss_engine_init.c nss_engine_io.c nss_engine_kernel.c nss_engine_log.c nss_engine_pphrase.c nss_engine_vars.c nss_expr.c nss_expr_eval.c nss_expr_parse.y nss_expr_scan.l nss_util.c nss_engine_rand.c nss_engine_cipher.c
libmodnss_la_LDFLAGS = -module -avoid-version
## Set the includes and libraries needed
@@ -99,12 +103,13 @@ EXTRA_DIST = *.h *.8 LICENSE test docs
check:
cd test; \
rm -rf work; \
+ nosetests -v test_cipher.py; \
./setup.sh; \
- nosetests -v; \
+ nosetests -v test.py; \
sleep 5; \
rm -rf work; \
./setup.sh sql:; \
- DBPREFIX=sql: nosetests -v; \
+ DBPREFIX=sql: nosetests -v test.py; \
cd ..
.PHONY: all test clean
diff --git a/docs/mod_nss.html b/docs/mod_nss.html
index 93499e5..052a464 100644
--- a/docs/mod_nss.html
+++ b/docs/mod_nss.html
@@ -1,6 +1,5 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-<html>
-<head>
+<html><head>
<!--
Copyright 2001-2005 The Apache Software Foundation
@@ -15,7 +14,7 @@
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
-->
- <meta content="text/html; charset=ISO-8859-1" http-equiv="content-type">
+ <meta content="text/html; charset=windows-1252" http-equiv="content-type">
<title>mod_nss</title>
</head>
@@ -38,11 +37,8 @@
<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@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@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
+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@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
@@ -54,8 +50,7 @@ calls instead.<br>
Refer to the README file included with the distribution.<br>
<br>
To build you'll need <a href="http://www.mozilla.org/projects/nspr/">NSPR</a>
-4.4.1 or above and <a
- href="http://www.mozilla.org/projects/security/pki/nss/">NSS</a> 3.9.2
+4.4.1 or above and <a href="http://www.mozilla.org/projects/security/pki/nss/">NSS</a> 3.9.2
or above.
It may work with earlier versions but these are recommended (or
tested). These can be retrieved from <a href="http://www.mozilla.org/">http://www.mozilla.org/</a>.
@@ -64,14 +59,11 @@ installed in the same parent directory (e.g. /opt/nspr,
/usr/local/nspr, etc). It will look in this parent for include/ and
lib/, etc.<br>
<br>
-To build with ECC support you need <a
- href="http://www.mozilla.org/projects/nspr/">NSPR</a> 4.6.2 or higher
+To build with ECC support you need <a href="http://www.mozilla.org/projects/nspr/">NSPR</a> 4.6.2 or higher
and <a href="http://www.mozilla.org/projects/security/pki/nss/">NSS</a>
3.11.2 or higher.<br>
<br>
-You will also need the <a
- href="http://www.mozilla.org/projects/security/pki/nss/">NSS</a> and <a
- href="http://www.mozilla.org/projects/nspr/">NSPR</a> directories in
+You will also need the <a href="http://www.mozilla.org/projects/security/pki/nss/">NSS</a> and <a href="http://www.mozilla.org/projects/nspr/">NSPR</a> directories in
your library search
path (either /etc/ld.so.conf or LD_LIBRARY_PATH) to link and run the
module.<br>
@@ -79,8 +71,7 @@ module.<br>
Run the configure script. The following mod_nss-specific options are
available:<br>
<br>
-<table style="width: 100%; text-align: left;" border="0" cellpadding="2"
- cellspacing="2">
+<table style="width: 100%; text-align: left;" cellpadding="2" cellspacing="2" border="0">
<tbody>
<tr>
<td style="vertical-align: top; font-weight: bold;">Option<br>
@@ -211,8 +202,7 @@ bother with the details.<br>
The certificate database password is httptest.<br>
<br>
A sample run is:<br>
-<pre>
-# mkdir /etc/httpd/nss
+<pre># mkdir /etc/httpd/nss
# ./gencert /etc/httpd/nss
#####################################################################
@@ -229,12 +219,18 @@ Generating key. This may take a few moments...
[ Lots of output removed ]
</pre>
You should now have the following files:<br>
-<pre>
-/etc/httpd/nss/cert8.db
-/etc/httpd/nss/key3db
+<pre>/etc/httpd/nss/cert8.db
+/etc/httpd/nss/key3.db
/etc/httpd/nss/secmod.db
</pre>
These 3 files make up an NSS certificate database.<br>
+<br>
+If you have a sql: prefix on the path, like sql:/etc/httpd/nss, then it
+will generate an SQLite NSS database consisting of the following files:<br>
+<pre>/etc/httpd/nss/cert9.db
+/etc/httpd/nss/key4.db
+/etc/httpd/nss/pkcs11.txt</pre>
+
<h1><a name="Startup"></a>Server Startup</h1>
Starting a mod_nss server is no different than starting a mod_ssl
@@ -461,17 +457,32 @@ enabled protocols to TLSv1.2, TLSv1.1 and TLS v1.0 and disables all ciphers
but the FIPS ones. You may still select which ciphers you would like
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>
+The allowable ciphers are (with ecc-enabled set):<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>
-</ul>
-<br>
-FIPS is disabled by default.<br>
+<li>rsa_aes_128_sha</li>
+<li>rsa_aes_256_sha</li>
+<li>aes_128_sha_256</li>
+<li>aes_256_sha_256</li>
+<li>rsa_aes_128_gcm_sha_256</li>
+<li>fips_3des_sha</li>
+<li>ecdh_ecdsa_3des_sha</li>
+<li>ecdh_ecdsa_aes_128_sha</li>
+<li>ecdh_ecdsa_aes_256_sha</li>
+<li>ecdhe_ecdsa_3des_sha</li>
+<li>ecdhe_ecdsa_aes_128_sha</li>
+<li>ecdhe_ecdsa_aes_256_sha</li>
+<li>ecdh_rsa_3des_sha</li>
+<li>ecdh_rsa_aes_128_sha</li>
+<li>ecdh_rsa_aes_256_sha</li>
+<li>ecdhe_rsa_3des_sha</li>
+<li>ecdhe_rsa_aes_128_sha</li>
+<li>ecdhe_rsa_aes_256_sha</li>
+<li>ecdhe_ecdsa_aes_128_sha_256</li>
+<li>ecdhe_rsa_aes_128_sha_256</li>
+<li>ecdhe_ecdsa_aes_128_gcm_sha_256</li>
+<li>ecdhe_rsa_aes_128_gcm_sha_256</li>
+</ul>FIPS is disabled by default.<br>
<br><span style="font-weight: bold;">
Example</span><br>
<br>
@@ -479,8 +490,7 @@ Example</span><br>
<br>
<big><big>NSSOCSP</big></big><br>
<br>
-Enables or disables <a
- href="http://www.ietf.org/rfc/rfc2560.txt?number=2560">OCSP</a>
+Enables or disables <a href="http://www.ietf.org/rfc/rfc2560.txt?number=2560">OCSP</a>
(Online Certificate Status Protocol). This allows the server to check
the validity of a client certificate before accepting it.<br>
<br>
@@ -492,17 +502,27 @@ Example</span><br>
<br>
<big><big>NSSCipherSuite<br>
</big></big><br>
-A space-separated list of the SSL ciphers used, with the prefix <code>+</code>
-to enable or <code>-</code> to disable.<br>
+There are two options for configuring the available ciphers. mod_nss
+provides its own cipher list, a space-separated list of the SSL ciphers
+used, with the prefix <code>+</code>
+to enable or <code>-</code> to disable, using the Cipher Name value in the tables below.<br>
+<br>
+Alternatively the mod_nss-style cipher definitions may be used, <a href="http://httpd.apache.org/docs/2.4/mod/mod_ssl.html#sslciphersuite">http://httpd.apache.org/docs/2.4/mod/mod_ssl.html#sslciphersuite</a>.
+ The support options are: ALL, COMPLEMENTOFALL, DEFAULT, RSA, EDH, NULL,
+ eNULL, AES, 3DES, DES, RC4, MD5, SHA, SHA1, SHA256, SSLv3, TLSv1,
+TLSv12, HIGH, MEDIUM, LOW, EXPORT, EXPORT40 and EXPORT56.<br>
+<br>
+If a cipher string value contains a colon it is considered a mod_ssl-style cipher string.<br>
+<br>
+If a cipher string value contains a comma it is considered a mod_nss-style cipher string.<br>
+<br>
+If it contains neither then mod_nss first tries to apply OpenSSL ciphers then NSS ciphers.<br>
<br>
-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>
+All ciphers are disabled by default. <br>
<br>
Available ciphers are:<br>
<br>
-<table style="width: 70%; text-align: left;" border="1" cellpadding="2"
- cellspacing="2">
+<table style="width: 70%; text-align: left;" cellpadding="2" cellspacing="2" border="1">
<tbody>
<tr>
<td style="vertical-align: top; font-weight: bold;">Cipher Name<br>
@@ -515,77 +535,59 @@ Available ciphers are:<br>
<tr>
<td style="vertical-align: top;">rsa_3des_sha<br>
</td>
- <td style="vertical-align: top;">SSL_RSA_WITH_3DES_EDE_CBC_SHA<br>
- </td>
+ <td style="vertical-align: top;">TLS_RSA_WITH_3DES_EDE_CBC_SHA<br>
+</td>
<td style="vertical-align: top;">SSLv3/TLSv1.0/TLSv1.1/TLSv1.2<br>
</td>
</tr>
<tr>
<td style="vertical-align: top;">rsa_des_sha<br>
</td>
- <td style="vertical-align: top;">SSL_RSA_WITH_DES_CBC_SHA<br>
+ <td style="vertical-align: top;">TLS_RSA_WITH_DES_CBC_SHA<br>
</td>
<td style="vertical-align: top;">SSLv3/TLSv1.0/TLSv1.1/TLSv1.2</td>
</tr>
<tr>
<td style="vertical-align: top;">rsa_null_md5<br>
</td>
- <td style="vertical-align: top;">SSL_RSA_WITH_NULL_MD5<br>
+ <td style="vertical-align: top;">TLS_RSA_WITH_NULL_MD5<br>
</td>
<td style="vertical-align: top;">SSLv3/TLSv1.0/TLSv1.1/TLSv1.2</td>
</tr>
<tr>
<td style="vertical-align: top;">rsa_null_sha<br>
</td>
- <td style="vertical-align: top;">SSL_RSA_WITH_NULL_SHA<br>
+ <td style="vertical-align: top;">TLS_RSA_WITH_NULL_SHA<br>
</td>
<td style="vertical-align: top;">SSLv3/TLSv1.0/TLSv1.1/TLSv1.2</td>
</tr>
<tr>
<td style="vertical-align: top;">rsa_rc2_40_md5</td>
- <td style="vertical-align: top;">SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5<br>
+ <td style="vertical-align: top;">TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5<br>
</td>
<td style="vertical-align: top;">SSLv3/TLSv1.0/TLSv1.1/TLSv1.2</td>
</tr>
<tr>
<td style="vertical-align: top;">rsa_rc4_128_md5</td>
- <td style="vertical-align: top;">SSL_RSA_WITH_RC4_128_MD5<br>
+ <td style="vertical-align: top;">TLS_RSA_WITH_RC4_128_MD5<br>
</td>
<td style="vertical-align: top;">SSLv3/TLSv1.0/TLSv1.1/TLSv1.2</td>
</tr>
<tr>
<td style="vertical-align: top;">rsa_rc4_128_sha</td>
- <td style="vertical-align: top;">SSL_RSA_WITH_RC4_128_SHA<br>
+ <td style="vertical-align: top;">TLS_RSA_WITH_RC4_128_SHA<br>
</td>
<td style="vertical-align: top;">SSLv3/TLSv1.0/TLSv1.1/TLSv1.2</td>
</tr>
<tr>
<td style="vertical-align: top;">rsa_rc4_40_md5</td>
- <td style="vertical-align: top;">SSL_RSA_EXPORT_WITH_RC4_40_MD5<br>
- </td>
- <td style="vertical-align: top;">SSLv3/TLSv1.0/TLSv1.1/TLSv1.2</td>
- </tr>
- <tr>
- <td style="vertical-align: top;">fortezza<br>
- </td>
- <td style="vertical-align: top;">SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA<br>
- </td>
- <td style="vertical-align: top;">SSLv3/TLSv1.0/TLSv1.1/TLSv1.2</td>
- </tr>
- <tr>
- <td style="vertical-align: top;">fortezza_rc4_128_sha<br>
- </td>
- <td style="vertical-align: top;">SSL_FORTEZZA_DMS_WITH_RC4_128_SHA<br>
- </td>
- <td style="vertical-align: top;">SSLv3/TLSv1.0/TLSv1.1/TLSv1.2</td>
- </tr>
- <tr>
- <td style="vertical-align: top;">fortezza_null<br>
- </td>
- <td style="vertical-align: top;">SSL_FORTEZZA_DMS_WITH_NULL_SHA<br>
+ <td style="vertical-align: top;">TLS_RSA_EXPORT_WITH_RC4_40_MD5<br>
</td>
<td style="vertical-align: top;">SSLv3/TLSv1.0/TLSv1.1/TLSv1.2</td>
</tr>
+
+
+
<tr>
<td style="vertical-align: top;">fips_des_sha<br>
</td>
@@ -625,13 +627,56 @@ Available ciphers are:<br>
<td style="vertical-align: top;">TLS_RSA_WITH_AES_256_CBC_SHA<br>
</td>
<td style="vertical-align: top;">SSLv3/TLSv1.0/TLSv1.1/TLSv1.2</td>
- </tr>
+ </tr><tr>
+ <td valign="top">camelia_128_sha<br>
+ </td>
+ <td valign="top">TLS_RSA_WITH_CAMELLIA_128_CBC_SHA<br>
+ </td>
+ <td valign="top">SSLv3/TLSv1.0/TLSv1.1/TLSv1.2</td>
+</tr>
+<tr>
+ <td valign="top">camelia_256_sha<br>
+ </td>
+ <td valign="top">TLS_RSA_WITH_CAMELLIA_256_CBC_SHA<br>
+ </td>
+ <td valign="top">SSLv3/TLSv1.0/TLSv1.1/TLSv1.2</td>
+</tr>
+<tr>
+ <td valign="top">null_sha_256<br>
+ </td>
+ <td valign="top">TLS_RSA_WITH_NULL_SHA256<br>
+ </td>
+ <td valign="top">TLSv1.2<br>
+ </td>
+</tr>
+<tr>
+ <td valign="top">aes_128_sha_256<br>
+ </td>
+ <td valign="top">TLS_RSA_WITH_AES_128_CBC_SHA256<br>
+ </td>
+ <td valign="top">TLSv1.2</td>
+</tr>
+<tr>
+ <td valign="top">aes_256_sha_256<br>
+ </td>
+ <td valign="top">TLS_RSA_WITH_AES_256_CBC_SHA256<br>
+ </td>
+ <td valign="top">TLSv1.2</td>
+</tr>
+<tr>
+ <td valign="top">rsa_aes_128_gcm_sha_256<br>
+ </td>
+ <td valign="top">TLS_RSA_WITH_AES_128_GCM_SHA256<br>
+ </td>
+ <td valign="top">TLSv1.2</td>
+</tr>
+
</tbody>
</table>
<br>
Additionally there are a number of ECC ciphers:<br>
<br>
-<table style="width: 70%;" border="1" cellpadding="2" cellspacing="2">
+<table style="width: 70%;" cellpadding="2" cellspacing="2" border="1">
<tbody>
<tr>
<td style="vertical-align: top; font-weight: bold;">Cipher Name<br>
@@ -765,16 +810,48 @@ Additionally there are a number of ECC ciphers:<br>
<td>ecdh_anon_aes_256_sha</td>
<td>TLS_ECDH_anon_WITH_AES_256_CBC_SHA</td>
<td>TLSv1.0/TLSv1.1/TLSv1.2</td>
- </tr>
+ </tr><tr>
+ <td valign="top">ecdhe_ecdsa_aes_128_sha_256<br>
+ </td>
+ <td valign="top">TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256<br>
+ </td>
+ <td valign="top">TLSv1.2</td>
+</tr>
+<tr>
+ <td valign="top">ecdhe_rsa_aes_128_sha_256<br>
+ </td>
+ <td valign="top">TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256<br>
+ </td>
+ <td valign="top">TLSv1.2</td>
+</tr>
+<tr>
+ <td valign="top">ecdhe_ecdsa_aes_128_gcm_sha_256<br>
+ </td>
+ <td valign="top">TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256<br>
+ </td>
+ <td valign="top">TLSv1.2</td>
+</tr>
+<tr>
+ <td valign="top">ecdhe_rsa_aes_128_gcm_sha_256<br>
+ </td>
+ <td valign="top">TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256<br>
+ </td>
+ <td valign="top">TLSv1.2</td>
+</tr>
+
</tbody>
</table>
<br>
<span style="font-weight: bold;">Example</span><br>
<br>
<code>NSSCipherSuite
-+rsa_3des_sha,-rsa_des_56_sha,+rsa_des_sha,-rsa_null_md5,-rsa_null_sha,-rsa_rc2_40_md5,+rsa_rc4_128_md5,-rsa_rc4_128_sha,<br>
--rsa_rc4_40_md5,-rsa_rc4_56_sha,-fortezza,-fortezza_rc4_128_sha,-fortezza_null,-fips_des_sha,<br>
-+fips_3des_sha,-rsa_aes_128_sha,-rsa_aes_256_sha</code><br>
++rsa_3des_sha,-rsa_des_56_sha,+rsa_des_sha,-rsa_null_md5,-rsa_null_sha,-rsa_rc2_40_md5,+rsa_rc4_128_md5,-rsa_rc4_128_sha,-rsa_rc4_40_md5,-rsa_rc4_56_sha,-fips_des_sha, +fips_3des_sha,-rsa_aes_128_sha,-rsa_aes_256_sha</code><br>
+<br>
+<code>NSSCipherSuite ALL</code><br>
+<br>
+<code>NSSCipherSuite </code><code>rsa_3des_sha</code><br>
+<br>
+<code>NSSCipherSuite RC4-SHA</code><br>
<br>
<big><big>NSSProtocol<br>
</big></big><br>
@@ -804,7 +881,7 @@ and the maximum allowed protocols based upon these entries allowing for the
inclusion of every protocol in-between. For example, if only SSLv3 and TLSv1.1
are specified, SSLv3, TLSv1.0, and TLSv1.1 will all be allowed, as NSS utilizes
protocol ranges to accept all protocols inclusively
-(TLS 1.1 -> TLS 1.0 -> SSL 3.0), and does not allow exclusion of any protocols
+(TLS 1.1 -&gt; TLS 1.0 -&gt; SSL 3.0), and does not allow exclusion of any protocols
in the middle of a range (e. g. - TLS 1.0).<br>
<br>
Finally, NSS will always automatically negotiate the use of the strongest
@@ -931,8 +1008,7 @@ very strong ciphers in particular directories.<br>
All options are disabled by default.<br>
<br>
Example:<br>
-<pre>
-NSSOptions +FakeBasicAuth
+<pre>NSSOptions +FakeBasicAuth
&lt;Files ~ "\.(cgi|shtml)$"&gt;
NSSOptions +StdEnvVars
&lt;Files&gt;
@@ -1015,8 +1091,7 @@ variables along with the option used to set them.<br>
<div style="text-align: center;">
<h3>Always Set</h3>
</div>
-<table style="width: 100%; text-align: left;" border="1" cellpadding="2"
- cellspacing="2">
+<table style="width: 100%; text-align: left;" cellpadding="2" cellspacing="2" border="1">
<tbody>
<tr>
<td style="vertical-align: top; font-weight: bold; width: 45%;">Name<br>
@@ -1038,8 +1113,7 @@ used<br>
<h3>+StdEnvVars<br>
</h3>
</div>
-<table style="width: 100%; text-align: left;" border="1" cellpadding="2"
- cellspacing="2">
+<table style="width: 100%; text-align: left;" cellpadding="2" cellspacing="2" border="1">
<tbody>
<tr>
<td style="vertical-align: top; font-weight: bold; width: 45%;">Name<br>
@@ -1233,8 +1307,7 @@ of the server key</td>
<br>
<h3 style="text-align: center;">+ExportCertData<br>
</h3>
-<table style="width: 100%; text-align: left;" border="1" cellpadding="2"
- cellspacing="2">
+<table style="width: 100%; text-align: left;" cellpadding="2" cellspacing="2" border="1">
<tbody>
<tr>
<td style="vertical-align: top; font-weight: bold; width: 45%;">Name<br>
@@ -1271,14 +1344,13 @@ itself).<br>
<h1><a name="Database_Management"></a>Database Management</h1>
NSS stores it's certificates and keys in a set of files referred to as
the "certificate database." The files by default (with NSS 3.x) are
-named cert8.db, key3.db and secmod.db. See the NSS documentation at <a
- href="http://www.mozilla.org/projects/security/pki/nss/">http://www.mozilla.org/projects/security/pki/nss/</a>
+named cert8.db, key3.db and secmod.db. See the NSS documentation at <a href="http://www.mozilla.org/projects/security/pki/nss/">http://www.mozilla.org/projects/security/pki/nss/</a>
for more information on these specific files.<p>
By default the NSS databases use the Berkeley Database format (cert8 and
key3). To use the sqlite format (cert9 and key4) either include sql: in
all references to the database (-d sql:/path/to/database) or
<code>export NSS_DEFAULT_DB_TYPE="sql"</code>.
-<p>
+</p><p>
For more details see
<a href="https://wiki.mozilla.org/NSS_Shared_DB">https://wiki.mozilla.org/NSS_Shared_DB</a><br>
<br>
@@ -1288,8 +1360,7 @@ Several NSS tools are available for managing certificates, keys,
PKCS#11 modules and CRLs. These come with the NSS distribution. Here is
a brief overview:<br>
<br>
-<table style="width: 100%; text-align: left;" border="1" cellpadding="2"
- cellspacing="2">
+<table style="width: 100%; text-align: left;" cellpadding="2" cellspacing="2" border="1">
<tbody>
<tr>
<td style="vertical-align: top;"><span style="font-weight: bold;">Tool</span><br>
@@ -1334,8 +1405,7 @@ method of referring to certificates. All of these commands use the -d
option to specify the database location. The default is ~/.netscape and
is probably not what you want.<br>
<br>
-<table style="width: 100%; text-align: left;" border="1" cellpadding="2"
- cellspacing="2">
+<table style="width: 100%; text-align: left;" cellpadding="2" cellspacing="2" border="1">
<tbody>
<tr>
<td style="vertical-align: top;"><span style="font-weight: bold;">Description</span><br>
@@ -1382,7 +1452,7 @@ Import-Me -d [path]<br>
</tbody>
</table>
<br>
-<h2>Importing OpenSSL Certificates</h2>
+</p><h2>Importing OpenSSL Certificates</h2>
If you have existing OpenSSL certificates you can import them into an
NSS certificate database.<br>
<br>
@@ -1435,8 +1505,7 @@ mod_ssl if it is loaded.<br>
<ul>
<code>
# certutil -L -d /etc/httpd/alias<br>
-<pre>
-Certificate Nickname Trust Attributes
+<pre>Certificate Nickname Trust Attributes
SSL,S/MIME,JAR/XPI
cacert CTu,Cu,Cu
@@ -1445,11 +1514,13 @@ alpha u,pu,u
</pre>
</code>
<table>
-<tr>
+<tbody><tr>
<td valign="top"><b>NOTE:&nbsp;&nbsp; </b></td>
-<td valign="top">For actual deployments, the administrator should setup their own NSS security databases (e. g. - replace the default mod_nss NSS security databases located in <code>/etc/httpd/alias</code>), populate them with the appropriate certificates set with the proper trust attributes, and apply any changes necessary to the <code>/etc/httpd/conf.d/nss.conf</code> file such that mod_nss uses these NSS security databases.</td>
+<td valign="top">For actual deployments, the administrator should setup
+their own NSS security databases (e. g. - replace the default mod_nss
+NSS security databases located in <code>/etc/httpd/alias</code>), populate them with the appropriate certificates set with the proper trust attributes, and apply any changes necessary to the <code>/etc/httpd/conf.d/nss.conf</code> file such that mod_nss uses these NSS security databases.</td>
</tr>
-</table>
+</tbody></table>
<br>
</ul>
4. Use <code>certutil</code> to apply a password to the NSS security databases configured in step 3 above:<br>
@@ -1485,11 +1556,17 @@ with:<br>
<br>
<ul>
<table>
-<tr>
+<tbody><tr>
<td valign="top"><b>NOTE:&nbsp;&nbsp; </b></td>
-<td valign="top">Whenever <code>httpd</code> is invoked as a service/systemd process, the <code>NSSPassPhraseDialog builtin</code> parameter must be changed to point to a file URL in order to allow mod_nss to work with the Apache web server. This is because the mod_nss test for issuing the password prompt <code>Please enter password for "internal" token:</code> on the command line is only displayed when the command <code>isatty(fileno(stdin))</code> is set to 'true', and when the command is entered from this type of invocation the value is 'false'. In order to see the prompt, one can set the <code>NSSPassPhraseDialog builtin</code> parameter and invoke <code>httpd -D FOREGROUND</code> from the command line.</td>
+<td valign="top">Whenever <code>httpd</code> is invoked as a service/systemd process, the <code>NSSPassPhraseDialog builtin</code>
+ parameter must be changed to point to a file URL in order to allow
+mod_nss to work with the Apache web server. This is because the mod_nss
+ test for issuing the password prompt <code>Please enter password for "internal" token:</code> on the command line is only displayed when the command <code>isatty(fileno(stdin))</code>
+ is set to 'true', and when the command is entered from this type of
+invocation the value is 'false'. In order to see the prompt, one can
+set the <code>NSSPassPhraseDialog builtin</code> parameter and invoke <code>httpd -D FOREGROUND</code> from the command line.</td>
</tr>
-</table>
+</tbody></table>
</ul>
<br>
If the SSL Server Certificate contained in the NSS security database is an RSA certificate, make certain that the <code>NSSNickname</code> parameter is uncommented and matches the nickname displayed in step 3 above:<br>
@@ -1540,8 +1617,7 @@ Apply the appropriate ownership and permissions to the <code>/etc/httpd/password
Redirecting to /bin/systemctl restart httpd.service<br>
</code>
<code>
-<pre>
-# service httpd status
+<pre># service httpd status
Redirecting to /bin/systemctl status httpd.service
httpd.service - The Apache HTTP Server
Loaded: loaded (/usr/lib/systemd/system/httpd.service; disabled)
@@ -1574,8 +1650,7 @@ Nov 27 15:25:48 server.example.com systemd[1]: Started The Apache HTTP Server.
<ul>
<code>
# certutil -L -d /etc/httpd/alias<br>
-<pre>
-Certificate Nickname Trust Attributes
+<pre>Certificate Nickname Trust Attributes
SSL,S/MIME,JAR/XPI
cacert CTu,Cu,Cu
@@ -1584,11 +1659,13 @@ alpha u,pu,u
</pre>
</code>
<table>
-<tr>
+<tbody><tr>
<td valign="top"><b>NOTE:&nbsp;&nbsp; </b></td>
-<td valign="top">For actual deployments, the administrator should setup their own NSS security databases (e. g. - replace the default mod_nss NSS security databases located in <code>/etc/httpd/alias</code>), populate them with the appropriate certificates set with the proper trust attributes, and apply any changes necessary to the <code>/etc/httpd/conf.d/nss.conf</code> file such that mod_nss uses these NSS security databases.</td>
+<td valign="top">For actual deployments, the administrator should setup
+their own NSS security databases (e. g. - replace the default mod_nss
+NSS security databases located in <code>/etc/httpd/alias</code>), populate them with the appropriate certificates set with the proper trust attributes, and apply any changes necessary to the <code>/etc/httpd/conf.d/nss.conf</code> file such that mod_nss uses these NSS security databases.</td>
</tr>
-</table>
+</tbody></table>
<br>
</ul>
4. Use <code>certutil</code> to apply a password to the NSS security databases configured in step 3 above:<br>
@@ -1624,11 +1701,17 @@ with:<br>
<br>
<ul>
<table>
-<tr>
+<tbody><tr>
<td valign="top"><b>NOTE:&nbsp;&nbsp; </b></td>
-<td valign="top">Whenever <code>httpd</code> is invoked as a service/systemd process, the <code>NSSPassPhraseDialog builtin</code> parameter must be changed to point to a file URL in order to allow mod_nss to work with the Apache web server. This is because the mod_nss test for issuing the password prompt <code>Please enter password for "NSS FIPS 140-2 Certificate DB" token:</code> on the command line is only displayed when the command <code>isatty(fileno(stdin))</code> is set to 'true', and when the command is entered from this type of invocation the value is 'false'. In order to see the prompt, one can set the <code>NSSPassPhraseDialog builtin</code> parameter and invoke <code>httpd -D FOREGROUND</code> from the command line.</td>
+<td valign="top">Whenever <code>httpd</code> is invoked as a service/systemd process, the <code>NSSPassPhraseDialog builtin</code>
+ parameter must be changed to point to a file URL in order to allow
+mod_nss to work with the Apache web server. This is because the mod_nss
+ test for issuing the password prompt <code>Please enter password for "NSS FIPS 140-2 Certificate DB" token:</code> on the command line is only displayed when the command <code>isatty(fileno(stdin))</code>
+ is set to 'true', and when the command is entered from this type of
+invocation the value is 'false'. In order to see the prompt, one can
+set the <code>NSSPassPhraseDialog builtin</code> parameter and invoke <code>httpd -D FOREGROUND</code> from the command line.</td>
</tr>
-</table>
+</tbody></table>
</ul>
<br>
To enable FIPS mode for mod_nss, add the following parameter:
@@ -1666,11 +1749,11 @@ Add:<br>
Replacing '&lt;password&gt;' with the password that was applied to the NSS security databases in step 4 above.<br>
<br>
<table>
-<tr>
+<tbody><tr>
<td valign="top"><b>IMPORTANT:&nbsp;&nbsp; </b></td>
<td valign="top">Notice that since the NSS FIPS software token is being used, the contents of the <code>/etc/httpd/password.conf</code> file references the password for the NSS FIPS software token (<code>NSS FIPS 140-2 Certificate DB:&lt;password&gt;</code>) rather than the NSS internal software token (<code>internal:&lt;password&gt;</code>).</td>
</tr>
-</table>
+</tbody></table>
</ul>
<br>
Apply the appropriate ownership and permissions to the <code>/etc/httpd/password.conf</code> file:<br>
@@ -1695,8 +1778,7 @@ Apply the appropriate ownership and permissions to the <code>/etc/httpd/password
Redirecting to /bin/systemctl restart httpd.service<br>
</code>
<code>
-<pre>
-# service httpd status
+<pre># service httpd status
Redirecting to /bin/systemctl status httpd.service
httpd.service - The Apache HTTP Server
Loaded: loaded (/usr/lib/systemd/system/httpd.service; disabled)
@@ -1716,5 +1798,6 @@ Nov 27 16:26:07 server.example.com systemd[1]: Started The Apache HTTP Server.
</code>
</ul>
</ul>
-</body>
-</html>
+
+
+</body></html>
diff --git a/mod_nss.h b/mod_nss.h
index cea31fd..e219ad2 100644
--- a/mod_nss.h
+++ b/mod_nss.h
@@ -331,15 +331,8 @@ typedef struct {
} SSLDirConfigRec;
/*
- * Cipher definitions
+ * for cipher definitions see nss_engine_cipher.h
*/
-typedef struct
-{
- const char *name;
- int num;
- int fortezza_only;
- PRInt32 version; /* protocol version valid for this cipher */
-} cipher_properties;
/* Compatibility between Apache 2.0.x and 2.2.x. The numeric version of
* the version first appeared in Apache 2.0.56-dev. I picked 2.0.55 as it
@@ -359,15 +352,6 @@ typedef struct regex_t ap_regex_t;
#define AP_REG_ICASE REG_ICASE
#endif
-enum sslversion { SSL2=1, SSL3=2, TLS=4};
-
-/* the table itself is defined in nss_engine_init.c */
-#ifdef NSS_ENABLE_ECC
-#define ciphernum 42
-#else
-#define ciphernum 17
-#endif
-
/*
* function prototypes
*/
@@ -425,7 +409,7 @@ void nss_init_Child(apr_pool_t *, server_rec *);
void nss_init_ConfigureServer(server_rec *, apr_pool_t *, apr_pool_t *, SSLSrvConfigRec *, const CERTCertList*);
apr_status_t nss_init_ModuleKill(void *data);
apr_status_t nss_init_ChildKill(void *data);
-int nss_parse_ciphers(server_rec *s, char *ciphers, PRBool cipher_list[ciphernum]);
+/* int nss_parse_ciphers(server_rec *s, char *ciphers, PRBool cipher_list[ciphernum]); */
/* Apache API hooks */
int nss_hook_UserCheck(request_rec *r);
diff --git a/nss_engine_cipher.c b/nss_engine_cipher.c
new file mode 100644
index 0000000..9110d57
--- /dev/null
+++ b/nss_engine_cipher.c
@@ -0,0 +1,322 @@
+/* Copyright 2001-2004 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "mod_nss.h"
+#include "nss_engine_cipher.h"
+#include <string.h>
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sslproto.h>
+
+/* ciphernum is defined in nss_engine_cipher.h */
+cipher_properties ciphers_def[ciphernum] =
+{
+ {"rsa_null_md5", TLS_RSA_WITH_NULL_MD5, "NULL-MD5", SSL_kRSA|SSL_aRSA|SSL_eNULL|SSL_MD5, SSLV3, SSL_STRONG_NONE, 0, 0},
+ {"rsa_null_sha", TLS_RSA_WITH_NULL_SHA, "NULL-SHA", SSL_kRSA|SSL_aRSA|SSL_eNULL|SSL_SHA1, SSLV3, SSL_STRONG_NONE, 0, 0},
+ {"rsa_rc4_40_md5", TLS_RSA_EXPORT_WITH_RC4_40_MD5, "EXP-RC4-MD5", SSL_kRSA|SSL_aRSA|SSL_RC4|SSL_MD5, SSLV3, SSL_EXPORT40, 40, 128},
+ {"rsa_rc4_128_md5", TLS_RSA_WITH_RC4_128_MD5, "RC4-MD5", SSL_kRSA|SSL_aRSA|SSL_RC4|SSL_MD5, SSLV3, SSL_MEDIUM, 128, 128},
+ {"rsa_rc4_128_sha", TLS_RSA_WITH_RC4_128_SHA, "RC4-SHA", SSL_kRSA|SSL_aRSA|SSL_RC4|SSL_SHA1, SSLV3, SSL_MEDIUM, 128, 128},
+ {"rsa_rc2_40_md5", TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5, "EXP-RC2-CBC-MD5", SSL_kRSA|SSL_aRSA|SSL_RC2|SSL_MD5, SSLV3, SSL_EXPORT40, 40, 128},
+ {"rsa_des_sha", TLS_RSA_WITH_DES_CBC_SHA, "DES-CBC-SHA", SSL_kRSA|SSL_aRSA|SSL_DES|SSL_SHA1, SSLV3, SSL_LOW, 56, 56},
+ {"rsa_3des_sha", TLS_RSA_WITH_3DES_EDE_CBC_SHA, "DES-CBC3-SHA", SSL_kRSA|SSL_aRSA|SSL_3DES|SSL_SHA1, SSLV3, SSL_HIGH, 112, 168},
+ {"rsa_aes_128_sha", TLS_RSA_WITH_AES_128_CBC_SHA, "AES128-SHA", SSL_kRSA|SSL_aRSA|SSL_AES128|SSL_SHA1, TLSV1, SSL_HIGH, 128, 128},
+ {"rsa_aes_256_sha", TLS_RSA_WITH_AES_256_CBC_SHA, "AES256-SHA256", SSL_kRSA|SSL_aRSA|SSL_AES256|SSL_SHA1, TLSV1, SSL_HIGH, 256, 256},
+ {"null_sha_256", TLS_RSA_WITH_NULL_SHA256, "NULL-SHA256", SSL_kRSA|SSL_aRSA|SSL_eNULL|SSL_SHA256, TLSV1_2, SSL_STRONG_NONE, 0, 0},
+ {"aes_128_sha_256", TLS_RSA_WITH_AES_128_CBC_SHA256, "AES128-SHA256", SSL_kRSA|SSL_aRSA|SSL_AES128|SSL_SHA256, TLSV1_2, SSL_HIGH, 128, 128},
+ {"aes_256_sha_256", TLS_RSA_WITH_AES_256_CBC_SHA256, "AES256-SHA256", SSL_kRSA|SSL_aRSA|SSL_AES256|SSL_SHA256, TLSV1_2, SSL_HIGH, 256, 256},
+ {"camelia_128_sha", TLS_RSA_WITH_CAMELLIA_128_CBC_SHA, "CAMELLIA128-SHA", SSL_kRSA|SSL_aRSA|SSL_CAMELLIA128|SSL_SHA1, TLSV1, SSL_HIGH, 128, 128},
+ {"rsa_des_56_sha", TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA, "EXP1024-DES-CBC-SHA", SSL_kRSA|SSL_aRSA|SSL_DES|SSL_SHA1, TLSV1, SSL_EXPORT56, 56, 56},
+ {"rsa_rc4_56_sha", TLS_RSA_EXPORT1024_WITH_RC4_56_SHA, "EXP1024-RC4-SHA", SSL_kRSA|SSL_aRSA|SSL_RC4|SSL_SHA1, TLSV1, SSL_EXPORT56, 56, 128},
+ {"camelia_256_sha", TLS_RSA_WITH_CAMELLIA_256_CBC_SHA, "CAMELLIA256-SHA", SSL_kRSA|SSL_aRSA|SSL_CAMELLIA256|SSL_SHA1, TLSV1, SSL_HIGH, 256, 256},
+ {"rsa_aes_128_gcm_sha_256", TLS_RSA_WITH_AES_128_GCM_SHA256, "AES128-GCM-SHA256", SSL_kRSA|SSL_aRSA|SSL_AES128GCM|SSL_AEAD, TLSV1_2, SSL_HIGH, 128, 128},
+ {"fips_3des_sha", SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA, "FIPS-DES-CBC3-SHA", SSL_kRSA|SSL_aRSA|SSL_3DES|SSL_SHA1, SSLV3, SSL_HIGH, 112, 168},
+ {"fips_des_sha", SSL_RSA_FIPS_WITH_DES_CBC_SHA, "FIPS-DES-CBC-SHA", SSL_kRSA|SSL_aRSA|SSL_DES|SSL_SHA1, SSLV3, SSL_LOW, 56, 56},
+#ifdef NSS_ENABLE_ECC
+ {"ecdh_ecdsa_null_sha", TLS_ECDH_ECDSA_WITH_NULL_SHA, "ECDH-ECDSA-NULL-SHA", SSL_kECDHe|SSL_aECDH|SSL_eNULL|SSL_SHA1, TLSV1, SSL_STRONG_NONE, 0, 0},
+ {"ecdh_ecdsa_rc4_128_sha", TLS_ECDH_ECDSA_WITH_RC4_128_SHA, "ECDH-ECDSA-RC4-SHA", SSL_kECDHe|SSL_aECDH|SSL_RC4|SSL_SHA1, TLSV1, SSL_MEDIUM, 128, 128},
+ {"ecdh_ecdsa_3des_sha", TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, "ECDH-ECDSA-DES-CBC3-SHA", SSL_kECDHe|SSL_aECDH|SSL_3DES|SSL_SHA1, TLSV1, SSL_HIGH, 112, 168},
+ {"ecdh_ecdsa_aes_128_sha", TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, "ECDH-ECDSA-AES128-SHA", SSL_kECDHe|SSL_aECDH|SSL_AES128|SSL_SHA1, TLSV1, SSL_HIGH, 128, 128},
+ {"ecdh_ecdsa_aes_256_sha", TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, "ECDH-ECDSA-AES256-SHA", SSL_kECDHe|SSL_aECDH|SSL_AES256|SSL_SHA1, TLSV1, SSL_HIGH, 256, 256},
+ {"ecdhe_ecdsa_null_sha", TLS_ECDHE_ECDSA_WITH_NULL_SHA, "ECDHE-ECDSA-NULL-SHA", SSL_kEECDH|SSL_aECDSA|SSL_eNULL|SSL_SHA1, TLSV1, SSL_STRONG_NONE, 0, 0},
+ {"ecdhe_ecdsa_rc4_128_sha", TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, "ECDHE-ECDSA-RC4-SHA", SSL_kEECDH|SSL_aECDSA|SSL_RC4|SSL_SHA1, TLSV1, SSL_MEDIUM, 128, 128},
+ {"ecdhe_ecdsa_3des_sha", TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, "ECDHE-ECDSA-DES-CBC3-SHA", SSL_kEECDH|SSL_aECDSA|SSL_3DES|SSL_SHA1, TLSV1, SSL_HIGH, 112, 168},
+ {"ecdhe_ecdsa_aes_128_sha", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, "ECDHE-ECDSA-AES128-SHA", SSL_kEECDH|SSL_aECDSA|SSL_AES128|SSL_SHA1, TLSV1, SSL_HIGH, 128, 128},
+ {"ecdhe_ecdsa_aes_256_sha", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, "ECDHE-ECDSA-AES256-SHA", SSL_kEECDH|SSL_aECDSA|SSL_AES256|SSL_SHA1, TLSV1, SSL_HIGH, 256, 256},
+ {"ecdh_rsa_null_sha", TLS_ECDH_RSA_WITH_NULL_SHA, "ECDH-RSA-NULL-SHA", SSL_kECDHr|SSL_aECDH|SSL_eNULL|SSL_SHA1, TLSV1, SSL_STRONG_NONE, 0, 0},
+ {"ecdh_rsa_128_sha", TLS_ECDH_RSA_WITH_RC4_128_SHA, "ECDH-RSA-RC4-SHA", SSL_kECDHr|SSL_aECDH|SSL_RC4|SSL_SHA1, TLSV1, SSL_MEDIUM, 128, 128},
+ {"ecdh_rsa_3des_sha", TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, "ECDH-RSA-DES-CBC3-SHA", SSL_kECDHr|SSL_aECDH|SSL_3DES|SSL_SHA1, TLSV1, SSL_HIGH, 112, 168},
+ {"ecdh_rsa_aes_128_sha", TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, "ECDH-RSA-AES128-SHA", SSL_kECDHr|SSL_aECDH|SSL_AES128|SSL_SHA1, TLSV1, SSL_HIGH, 128, 128},
+ {"ecdh_rsa_aes_256_sha", TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, "ECDH-RSA-AES256-SHA", SSL_kECDHr|SSL_aECDH|SSL_AES256|SSL_SHA1, TLSV1, SSL_HIGH, 256, 256},
+ {"ecdhe_rsa_null", TLS_ECDHE_RSA_WITH_NULL_SHA, "ECDHE-RSA-NULL-SHA", SSL_kEECDH|SSL_aRSA|SSL_eNULL|SSL_SHA1, TLSV1, SSL_STRONG_NONE, 0, 0},
+ {"ecdhe_rsa_rc4_128_sha", TLS_ECDHE_RSA_WITH_RC4_128_SHA, "ECDHE-RSA-RC4-SHA", SSL_kEECDH|SSL_aRSA|SSL_RC4|SSL_SHA1, TLSV1, SSL_MEDIUM, 128, 128},
+ {"ecdhe_rsa_3des_sha", TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, "ECDHE-RSA-DES-CBC3-SHA", SSL_kEECDH|SSL_aRSA|SSL_3DES|SSL_SHA1, TLSV1, SSL_HIGH, 112, 168},
+ {"ecdhe_rsa_aes_128_sha", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, "ECDHE-RSA-AES128-SHA", SSL_kEECDH|SSL_aRSA|SSL_AES128|SSL_SHA1, TLSV1, SSL_HIGH, 128, 128},
+ {"ecdhe_rsa_aes_256_sha", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, "ECDHE-RSA-AES256-SHA", SSL_kEECDH|SSL_aRSA|SSL_AES256|SSL_SHA1, TLSV1, SSL_HIGH, 256, 256},
+ {"ecdh_anon_null_sha", TLS_ECDH_anon_WITH_NULL_SHA, "AECDH-NULL-SHA", SSL_kEECDH|SSL_aNULL|SSL_eNULL|SSL_SHA1, TLSV1, SSL_STRONG_NONE, 0, 0},
+ {"ecdh_anon_rc4_128sha", TLS_ECDH_anon_WITH_RC4_128_SHA, "AECDH-RC4-SHA", SSL_kEECDH|SSL_aNULL|SSL_RC4|SSL_SHA1, TLSV1, SSL_MEDIUM, 128, 128},
+ {"ecdh_anon_3des_sha", TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA, "AECDH-DES-CBC3-SHA", SSL_kEECDH|SSL_aNULL|SSL_3DES|SSL_SHA1, TLSV1, SSL_HIGH, 112, 168},
+ {"ecdh_anon_aes_128_sha", TLS_ECDH_anon_WITH_AES_128_CBC_SHA, "AECDH-AES128-SHA", SSL_kEECDH|SSL_aNULL|SSL_AES128|SSL_SHA1, TLSV1, SSL_HIGH, 128, 128},
+ {"ecdh_anon_aes_256_sha", TLS_ECDH_anon_WITH_AES_256_CBC_SHA, "AECDH-AES256-SHA", SSL_kEECDH|SSL_aNULL|SSL_AES256|SSL_SHA1, TLSV1, SSL_HIGH, 256, 256},
+ {"ecdhe_ecdsa_aes_128_sha_256", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, "ECDHE-ECDSA-AES128-SHA256", SSL_kEECDH|SSL_aECDSA|SSL_AES128|SSL_SHA256, TLSV1_2, SSL_HIGH, 128, 128},
+ {"ecdhe_rsa_aes_128_sha_256", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, "ECDHE-RSA-AES128-SHA256", SSL_kEECDH|SSL_aRSA|SSL_AES128|SSL_SHA256, TLSV1_2, SSL_HIGH, 128, 128},
+ {"ecdhe_ecdsa_aes_128_gcm_sha_256", TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, "ECDHE-ECDSA-AES128-GCM-SHA256", SSL_kEECDH|SSL_aECDSA|SSL_AES128GCM|SSL_AEAD, TLSV1_2, SSL_HIGH, 128, 128},
+ {"ecdhe_rsa_aes_128_gcm_sha_256", TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, "ECDHE-RSA-AES128-GCM-SHA256", SSL_kEECDH|SSL_aRSA|SSL_AES128GCM|SSL_AEAD, TLSV1_2, SSL_HIGH, 128, 128},
+#endif
+};
+
+static int parse_nss_ciphers(server_rec *s, char *ciphers, PRBool cipher_list[ciphernum]);
+static int parse_openssl_ciphers(server_rec *s, char *ciphers, PRBool cipher_list[ciphernum]);
+
+int countciphers(PRBool cipher_state[ciphernum], int version) {
+ int ciphercount = 0;
+ int i = ciphernum;
+
+ for (i = 0; i < ciphernum; i++)
+ {
+ if ((cipher_state[i] == PR_TRUE) &&
+ (ciphers_def[i].version & version)) {
+ ciphercount++;
+ }
+ }
+
+ return ciphercount;
+}
+
+
+int nss_parse_ciphers(server_rec *s, char *ciphers, PRBool cipher_list[ciphernum])
+{
+ int rv = 0;
+
+ /* If the string has a colon we use the OpenSSL style. If it has a
+ * comma then NSS. If it has neither we try both. */
+ if (strchr(ciphers, ':')) {
+ rv = parse_openssl_ciphers(s, ciphers, cipher_list);
+ } else if (strchr(ciphers, ',')) {
+ rv = parse_nss_ciphers(s, ciphers, cipher_list);
+ } else {
+ rv = parse_openssl_ciphers(s, ciphers, cipher_list);
+ if (0 == countciphers(cipher_list, SSLV3|TLSV1|TLSV1_2)) {
+ rv = parse_nss_ciphers(s, ciphers, cipher_list);
+ }
+ }
+
+ return rv;
+}
+
+
+static int parse_openssl_ciphers(server_rec *s, char *ciphers, PRBool cipher_list[ciphernum])
+{
+ char * cipher;
+ int i, action;
+
+ cipher = ciphers;
+ while (ciphers && (strlen(ciphers)))
+ {
+ while ((*cipher) && (isspace(*cipher)))
+ ++cipher;
+
+ action = 1;
+ switch(*cipher)
+ {
+ case '+': /* Add something */
+ action = 1;
+ cipher++;
+ break;
+ case '-': /* Subtract something */
+ action = 0;
+ cipher++;
+ break;
+ case '!': /* Disable something */
+ action = -1;
+ cipher++;
+ break;
+ default:
+ /* do nothing */
+ break;
+ }
+
+ if ((ciphers = strchr(cipher, ':'))) {
+ *ciphers++ = '\0';
+ }
+
+ if (!strcmp(cipher, "ALL")) {
+ for (i=0; i<ciphernum; i++) {
+ if (!(ciphers_def[i].attr & SSL_eNULL))
+ if (cipher_list[i] != -1)
+ cipher_list[i] = action;
+ }
+ } else if (!strcmp(cipher, "COMPLEMENTOFALL")) {
+ for (i=0; i<ciphernum; i++) {
+ if ((ciphers_def[i].attr & SSL_eNULL))
+ if (cipher_list[i] != -1)
+ cipher_list[i] = action;
+ }
+ } else if (!strcmp(cipher, "DEFAULT")) {
+ for (i=0; i < ciphernum; i++) {
+ if (cipher_list[i] != -1)
+ SSL_CipherPrefGetDefault(ciphers_def[i].num,
+ &cipher_list[i]);
+ }
+ } else {
+ int mask = 0;
+ int strength = 0;
+ int protocol = 0;
+ char *c;
+
+ c = cipher;
+ while (c && (strlen(c))) {
+
+ if ((c = strchr(cipher, '+'))) {
+ *c++ = '\0';
+ }
+
+ if (!strcmp(cipher, "RSA")) {
+ mask |= SSL_RSA;
+ } else if (!strcmp(cipher, "EDH")) {
+ mask |= SSL_EDH;
+ } else if ((!strcmp(cipher, "NULL")) || (!strcmp(cipher, "eNULL"))) {
+ mask |= SSL_eNULL;
+ } else if (!strcmp(cipher, "AES")) {
+ mask |= SSL_AES;
+ } else if (!strcmp(cipher, "3DES")) {
+ mask |= SSL_3DES;
+ } else if (!strcmp(cipher, "DES")) {
+ mask |= SSL_DES;
+ } else if (!strcmp(cipher, "RC4")) {
+ mask |= SSL_RC4;
+ } else if (!strcmp(cipher, "RC2")) {
+ mask |= SSL_RC2;
+ } else if (!strcmp(cipher, "MD5")) {
+ mask |= SSL_MD5;
+ } else if ((!strcmp(cipher, "SHA")) || (!strcmp(cipher, "SHA1"))) {
+ mask |= SSL_SHA1;
+ } else if (!strcmp(cipher, "SHA256")) {
+ mask |= SSL_SHA256;
+ } else if (!strcmp(cipher, "SSLv2")) {
+ /* no-op */
+ } else if (!strcmp(cipher, "SSLv3")) {
+ protocol |= SSLV3;
+ } else if (!strcmp(cipher, "TLSv1")) {
+ protocol |= TLSV1;
+ } else if (!strcmp(cipher, "TLSv12")) {
+ protocol |= TLSV1_2;
+ } else if (!strcmp(cipher, "HIGH")) {
+ strength |= SSL_HIGH;
+ } else if (!strcmp(cipher, "MEDIUM")) {
+ strength |= SSL_MEDIUM;
+ } else if (!strcmp(cipher, "LOW")) {
+ strength |= SSL_LOW;
+ } else if ((!strcmp(cipher, "EXPORT")) || (!strcmp(cipher, "EXP"))) {
+ strength |= SSL_EXPORT40|SSL_EXPORT56;
+ } else if (!strcmp(cipher, "EXPORT40")) {
+ strength |= SSL_EXPORT40;
+ } else if (!strcmp(cipher, "EXPORT56")) {
+ strength |= SSL_EXPORT56;
+ }
+
+ if (c)
+ cipher = c;
+
+ } /* while */
+
+ /* If we have a mask, apply it. If not then perhaps they provided
+ * a specific cipher to enable.
+ */
+ if (mask || strength || protocol)
+ for (i=0; i<ciphernum; i++) {
+ if (((ciphers_def[i].attr & mask) ||
+ (ciphers_def[i].strength & strength) ||
+ (ciphers_def[i].version & protocol)) &&
+ (cipher_list[i] != -1)) {
+ /* Enable the NULL ciphers only if explicity
+ * requested */
+ if (ciphers_def[i].attr & SSL_eNULL) {
+ if (mask & SSL_eNULL)
+ cipher_list[i] = action;
+ } else
+ cipher_list[i] = action;
+ }
+ }
+ else {
+ for (i=0; i<ciphernum; i++) {
+ if (!strcmp(ciphers_def[i].openssl_name, cipher) &&
+ cipher_list[i] != -1)
+ cipher_list[i] = action;
+ }
+ }
+ }
+
+ if (ciphers)
+ cipher = ciphers;
+
+ }
+ return 0;
+}
+
+
+static int parse_nss_ciphers(server_rec *s, char *ciphers, PRBool cipher_list[ciphernum])
+{
+ char * cipher;
+ PRBool found;
+ int i, active;
+
+ cipher = ciphers;
+
+ while (ciphers && (strlen(ciphers)))
+ {
+ while ((*cipher) && (isspace(*cipher)))
+ ++cipher;
+
+ switch(*cipher++)
+ {
+ case '+':
+ active = PR_TRUE;
+ break;
+ case '-':
+ active = PR_FALSE;
+ break;
+ default:
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, s,
+ "invalid cipher string %s. Format is +cipher1,-cipher2...", cipher - 1);
+ return -1;
+ }
+
+ if ((ciphers = strchr(cipher, ','))) {
+ *ciphers++ = '\0';
+ }
+
+ found = PR_FALSE;
+
+ for (i = 0; i < ciphernum; i++)
+ {
+ if (!strcasecmp(cipher, ciphers_def[i].name)) {
+ cipher_list[i] = active;
+ found = PR_TRUE;
+ break;
+ }
+ }
+
+ if (found == PR_FALSE) {
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, s,
+ "Unknown cipher %s\n", cipher);
+ }
+
+ if (ciphers) {
+ cipher = ciphers;
+ }
+ }
+
+ return 0;
+}
diff --git a/nss_engine_cipher.h b/nss_engine_cipher.h
new file mode 100644
index 0000000..f0c12f1
--- /dev/null
+++ b/nss_engine_cipher.h
@@ -0,0 +1,90 @@
+/* Copyright 2001-2004 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Cipher definitions
+ */
+typedef struct
+{
+ const char *name; /* The mod_nss cipher name */
+ PRInt32 num; /* The cipher id */
+ const char *openssl_name; /* The OpenSSL cipher name */
+ PRInt32 attr; /* cipher attributes: algorithms, etc */
+ PRInt32 version; /* protocol version valid for this cipher */
+ PRInt32 strength; /* LOW, MEDIUM, HIGH */
+ PRInt32 bits; /* bits of strength */
+ PRInt32 alg_bits; /* bits of the algorithm */
+} cipher_properties;
+
+/* OpenSSL-compatible cipher attributes */
+#define SSL_kRSA 0x00000001L
+#define SSL_aRSA 0x00000002L
+#define SSL_aDSS 0x00000004L
+#define SSL_DSS SSL_aDSS
+#define SSL_eNULL 0x00000008L
+#define SSL_DES 0x00000010L
+#define SSL_3DES 0x00000020L
+#define SSL_RC4 0x00000040L
+#define SSL_RC2 0x00000080L
+#define SSL_MD5 0x00000200L
+#define SSL_SHA1 0x00000400L
+#define SSL_SHA SSL_SHA1
+#define SSL_RSA (SSL_kRSA|SSL_aRSA)
+#define SSL_kEDH 0x00000800L
+#define SSL_EDH (SSL_kEDH)
+#define SSL_aNULL 0x00001000L
+#define SSL_kECDHe 0x00002000L
+#define SSL_aECDH 0x00004000L
+#define SSL_aECDSA 0x00008000L
+#define SSL_kECDHr 0x00010000L
+#define SSL_kEECDH 0x00020000L
+
+/* cipher strength */
+#define SSL_STRONG_NONE 0x00000001L
+#define SSL_NULL 0x00000002L
+#define SSL_EXPORT40 0x00000004L
+#define SSL_EXPORT56 0x00000008L
+#define SSL_LOW 0x00000010L
+#define SSL_MEDIUM 0x00000020L
+#define SSL_HIGH 0x00000040L
+
+#define SSL_AES128 0x00004000L
+#define SSL_AES256 0x00008000L
+#define SSL_CAMELLIA128 0x00010000L
+#define SSL_CAMELLIA256 0x00020000L
+#define SSL_AES128GCM 0x00040000L
+#define SSL_AES256GCM 0x00080000L
+#define SSL_SHA256 0x00100000L
+#define SSL_AEAD 0x00200000L
+
+#define SSL_AES (SSL_AES128|SSL_AES256|SSL_AES128GCM|SSL_AES256GCM)
+#define SSL_CAMELLIA (SSL_CAMELLIA128|SSL_CAMELLIA256)
+
+/* Protocols */
+#define SSLV2 0x00000001L
+#define SSLV3 0x00000002L
+#define TLSV1 SSLV3
+#define TLSV1_2 0x00000004L
+
+/* the table itself is defined in nss_engine_cipher.c */
+#ifdef NSS_ENABLE_ECC
+#define ciphernum 49
+#else
+#define ciphernum 20
+#endif
+
+/* function prototypes */
+int nss_parse_ciphers(server_rec *s, char *ciphers, PRBool cipher_list[ciphernum]);
+int countciphers(PRBool cipher_state[ciphernum], int version);
diff --git a/nss_engine_init.c b/nss_engine_init.c
index 4259cfb..a81fdfd 100644
--- a/nss_engine_init.c
+++ b/nss_engine_init.c
@@ -14,6 +14,7 @@
*/
#include "mod_nss.h"
+#include "nss_engine_cipher.h"
#include "apr_thread_proc.h"
#include "mpm_common.h"
#include "secmod.h"
@@ -34,57 +35,7 @@ SECStatus nss_AuthCertificate(void *arg, PRFileDesc *socket, PRBool checksig, PR
*/
char* INTERNAL_TOKEN_NAME = "internal ";
-cipher_properties ciphers_def[ciphernum] =
-{
- /* SSL3/TLS cipher suites */
- {"rsa_rc4_128_md5", SSL_RSA_WITH_RC4_128_MD5, 0, SSL3 | TLS},
- {"rsa_rc4_128_sha", SSL_RSA_WITH_RC4_128_SHA, 0, SSL3 | TLS},
- {"rsa_3des_sha", SSL_RSA_WITH_3DES_EDE_CBC_SHA, 0, SSL3 | TLS},
- {"rsa_des_sha", SSL_RSA_WITH_DES_CBC_SHA, 0, SSL3 | TLS},
- {"rsa_rc4_40_md5", SSL_RSA_EXPORT_WITH_RC4_40_MD5, 0, SSL3 | TLS},
- {"rsa_rc2_40_md5", SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5, 0, SSL3 | TLS},
- {"rsa_null_md5", SSL_RSA_WITH_NULL_MD5, 0, SSL3 | TLS},
- {"rsa_null_sha", SSL_RSA_WITH_NULL_SHA, 0, SSL3 | TLS},
- {"fips_3des_sha", SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA, 0, SSL3 | TLS},
- {"fips_des_sha", SSL_RSA_FIPS_WITH_DES_CBC_SHA, 0, SSL3 | TLS},
- {"fortezza", SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA, 1, SSL3 | TLS},
- {"fortezza_rc4_128_sha", SSL_FORTEZZA_DMS_WITH_RC4_128_SHA, 1, SSL3 | TLS},
- {"fortezza_null", SSL_FORTEZZA_DMS_WITH_NULL_SHA, 1, SSL3 | TLS},
- /* TLS 1.0: Exportable 56-bit Cipher Suites. */
- {"rsa_des_56_sha", TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA, 0, SSL3 | TLS},
- {"rsa_rc4_56_sha", TLS_RSA_EXPORT1024_WITH_RC4_56_SHA, 0, SSL3 | TLS},
- /* AES ciphers.*/
- {"rsa_aes_128_sha", TLS_RSA_WITH_AES_128_CBC_SHA, 0, SSL3 | TLS},
- {"rsa_aes_256_sha", TLS_RSA_WITH_AES_256_CBC_SHA, 0, SSL3 | TLS},
-#ifdef NSS_ENABLE_ECC
- /* ECC ciphers.*/
- {"ecdh_ecdsa_null_sha", TLS_ECDH_ECDSA_WITH_NULL_SHA, 0, TLS},
- {"ecdh_ecdsa_rc4_128_sha", TLS_ECDH_ECDSA_WITH_RC4_128_SHA, 0, TLS},
- {"ecdh_ecdsa_3des_sha", TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, 0, TLS},
- {"ecdh_ecdsa_aes_128_sha", TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, 0, TLS},
- {"ecdh_ecdsa_aes_256_sha", TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, 0, TLS},
- {"ecdhe_ecdsa_null_sha", TLS_ECDHE_ECDSA_WITH_NULL_SHA, 0, TLS},
- {"ecdhe_ecdsa_rc4_128_sha", TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, 0, TLS},
- {"ecdhe_ecdsa_3des_sha", TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, 0, TLS},
- {"ecdhe_ecdsa_aes_128_sha", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, 0, TLS},
- {"ecdhe_ecdsa_aes_256_sha", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, 0, TLS},
- {"ecdh_rsa_null_sha", TLS_ECDH_RSA_WITH_NULL_SHA, 0, TLS},
- {"ecdh_rsa_128_sha", TLS_ECDH_RSA_WITH_RC4_128_SHA, 0, TLS},
- {"ecdh_rsa_3des_sha", TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, 0, TLS},
- {"ecdh_rsa_aes_128_sha", TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, 0, TLS},
- {"ecdh_rsa_aes_256_sha", TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, 0, TLS},
- {"ecdhe_rsa_null", TLS_ECDHE_RSA_WITH_NULL_SHA, 0, TLS},
- {"ecdhe_rsa_rc4_128_sha", TLS_ECDHE_RSA_WITH_RC4_128_SHA, 0, TLS},
- {"ecdhe_rsa_3des_sha", TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, 0, TLS},
- {"ecdhe_rsa_aes_128_sha", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, 0, TLS},
- {"ecdhe_rsa_aes_256_sha", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, 0, TLS},
- {"ecdh_anon_null_sha", TLS_ECDH_anon_WITH_NULL_SHA, 0, TLS},
- {"ecdh_anon_rc4_128sha", TLS_ECDH_anon_WITH_RC4_128_SHA, 0, TLS},
- {"ecdh_anon_3des_sha", TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA, 0, TLS},
- {"ecdh_anon_aes_128_sha", TLS_ECDH_anon_WITH_AES_128_CBC_SHA, 0, TLS},
- {"ecdh_anon_aes_256_sha", TLS_ECDH_anon_WITH_AES_256_CBC_SHA, 0, TLS},
-#endif
-};
+extern cipher_properties ciphers_def[];
static char *version_components[] = {
"SSL_VERSION_PRODUCT",
@@ -337,7 +288,7 @@ int nss_init_Module(apr_pool_t *p, apr_pool_t *plog,
/* We still need to pass in a legal value to
* SSL_ConfigMPServerSIDCache() and SSL_ConfigServerSessionIDCache()
- * /
+ */
mc->session_cache_timeout = 0; /* use NSS default */
}
@@ -869,21 +820,6 @@ static void nss_init_ctx_verify(server_rec *s,
}
}
-static int countciphers(PRBool cipher_state[ciphernum], int version) {
- int ciphercount = 0;
- int i;
-
- for (i = 0; i < ciphernum; i++)
- {
- if ((cipher_state[i] == PR_TRUE) &&
- (ciphers_def[i].version & version)) {
- ciphercount++;
- }
- }
-
- return ciphercount;
-}
-
static void nss_init_ctx_cipher_suite(server_rec *s,
apr_pool_t *p,
apr_pool_t *ptemp,
@@ -1025,14 +961,14 @@ static void nss_init_ctx_cipher_suite(server_rec *s,
}
}
- if (mctx->ssl3 && countciphers(cipher_state, SSL3) == 0) {
+ if (mctx->ssl3 && countciphers(cipher_state, SSLV3) == 0) {
ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
"%s: SSL3 is enabled but no SSL3 ciphers are enabled.",
cipher_suite_marker);
nss_die();
}
- if (mctx->tls && countciphers(cipher_state, TLS) == 0) {
+ if (mctx->tls && countciphers(cipher_state, TLSV1|TLSV1_2) == 0) {
ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
"%s: TLS is enabled but no TLS ciphers are enabled.",
cipher_suite_marker);
@@ -1651,58 +1587,3 @@ SECStatus NSSHandshakeCallback(PRFileDesc *socket, void *arg)
{
return SECSuccess;
}
-
-int nss_parse_ciphers(server_rec *s, char *ciphers, PRBool cipher_list[ciphernum])
-{
- char * cipher;
- PRBool found, active;
- int i;
-
- cipher = ciphers;
-
- while (ciphers && (strlen(ciphers)))
- {
- while ((*cipher) && (isspace(*cipher)))
- ++cipher;
-
- switch(*cipher++)
- {
- case '+':
- active = PR_TRUE;
- break;
- case '-':
- active = PR_FALSE;
- break;
- default:
- ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
- "invalid cipher string %s. Format is +cipher1,-cipher2...", cipher - 1);
- return -1;
- }
-
- if ((ciphers = strchr(cipher, ','))) {
- *ciphers++ = '\0';
- }
-
- found = PR_FALSE;
-
- for (i = 0; i < ciphernum; i++)
- {
- if (!strcasecmp(cipher, ciphers_def[i].name)) {
- cipher_list[i] = active;
- found = PR_TRUE;
- break;
- }
- }
-
- if (found == PR_FALSE) {
- ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
- "Unknown cipher %s", cipher);
- }
-
- if (ciphers) {
- cipher = ciphers;
- }
- }
-
- return 0;
-}
diff --git a/nss_engine_kernel.c b/nss_engine_kernel.c
index 4addb39..337ca67 100644
--- a/nss_engine_kernel.c
+++ b/nss_engine_kernel.c
@@ -13,6 +13,7 @@
* limitations under the License.
*/
#include "mod_nss.h"
+#include "nss_engine_cipher.h"
#include "secerr.h"
static void HandshakeDone(PRFileDesc *fd, void *doneflag);
diff --git a/test/createinstance.sh b/test/createinstance.sh
index fac0a7d..c3b7260 100755
--- a/test/createinstance.sh
+++ b/test/createinstance.sh
@@ -24,6 +24,7 @@ mkdir lib
# Create the content
mkdir content/rc4_cipher
+mkdir content/openssl_rc4_cipher
mkdir content/acl
mkdir content/protocolssl2
mkdir content/protocolssl3
diff --git a/test/setup.sh b/test/setup.sh
index b1e3371..487a5f5 100755
--- a/test/setup.sh
+++ b/test/setup.sh
@@ -24,7 +24,8 @@ fi
cp ../.libs/libmodnss.so ${test_root}/lib
cp ../nss_pcache ${test_root}/bin
-bash ../gencert ${DBPREFIX}${test_root}/alias
+echo "Generating a new certificate database..."
+bash ../gencert ${DBPREFIX}${test_root}/alias > /dev/null 2>&1
echo internal:httptest > ${test_root}/conf/password.conf
# Export the CA cert
diff --git a/test/suite1.tmpl b/test/suite1.tmpl
index 233894c..eb2a16c 100644
--- a/test/suite1.tmpl
+++ b/test/suite1.tmpl
@@ -19,7 +19,7 @@ NSSFIPS off
NSSOCSP off
NSSRenegotiation on
-NSSCipherSuite +rc4,+rc4export,+rc2,+rc2export,+des,+desede3,-fortezza,-fortezza_rc4_128_sha,-fortezza_null,+rsa_rc4_128_md5,+rsa_3des_sha,+rsa_des_sha,+rsa_rc4_40_md5,+rsa_rc2_40_md5,+rsa_null_md5,+rsa_des_56_sha,+rsa_rc4_56_sha,+rsa_aes_128_sha,+rsa_aes_256_sha,+fips_des_sha,+fips_3des_sha
+NSSCipherSuite +rsa_rc4_128_md5,+rsa_3des_sha,+rsa_des_sha,+rsa_rc4_40_md5,+rsa_rc2_40_md5,+rsa_null_md5,+rsa_des_56_sha,+rsa_rc4_56_sha,+rsa_aes_128_sha,+rsa_aes_256_sha
NSSProtocol SSLv3,TLSv1.0
@@ -32,7 +32,11 @@ NSSVerifyClient none
NSSUserName SSL_CLIENT_S_DN_UID
<Location "/rc4_cipher">
- NSSCipherSuite -rc4,-rc4export,-rc2,-rc2export,-des,-desede3,-fortezza,-fortezza_rc4_128_sha,-fortezza_null,+rsa_rc4_128_md5,-rsa_3des_sha,-rsa_des_sha,-rsa_rc4_40_md5,-rsa_rc2_40_md5,-rsa_null_md5,-rsa_des_56_sha,-rsa_rc4_56_sha,-rsa_aes_128_sha,-rsa_aes_256_sha,-fips_des_sha,-fips_3des_sha,-ecdhe_rsa_rc4_128_sha,-ecdhe_rsa_aes_128_sha,-rsa_rc4_128_sha
+ NSSCipherSuite +rsa_rc4_128_md5
+</Location>
+
+<Location "/openssl_rc4_cipher">
+ NSSCipherSuite RC4-SHA
</Location>
<Location "/acl/aclS01.html">
@@ -93,7 +97,7 @@ NSSFIPS off
NSSOCSP off
NSSRenegotiation on
-NSSCipherSuite +rc4,+rc4export,+rc2,+rc2export,+des,+desede3,-fortezza,-fortezza_rc4_128_sha,-fortezza_null,+rsa_rc4_128_md5,+rsa_3des_sha,+rsa_des_sha,+rsa_rc4_40_md5,+rsa_rc2_40_md5,+rsa_null_md5,+rsa_des_56_sha,+rsa_rc4_56_sha,+rsa_aes_128_sha,+rsa_aes_256_sha,+fips_des_sha,+fips_3des_sha
+NSSCipherSuite +rsa_rc4_128_md5,+rsa_3des_sha,+rsa_des_sha,+rsa_rc4_40_md5,+rsa_rc2_40_md5,+rsa_null_md5,+rsa_des_56_sha,+rsa_rc4_56_sha,+rsa_aes_128_sha,+rsa_aes_256_sha
NSSProtocol TLSv1.2
diff --git a/test/test.py b/test/test.py
index 75f3b0c..ee8d95b 100644
--- a/test/test.py
+++ b/test/test.py
@@ -63,6 +63,12 @@ class test_suite1(Declarative):
),
dict(
+ desc='server-side OpenSSL-style RC4 cipher check',
+ request=('/openssl_rc4_cipher/', {'ciphers': 'ALL'}),
+ expected=200,
+ ),
+
+ dict(
desc='Basic client auth, no certificate',
request=('/acl/aclS01.html', {}),
expected=requests.exceptions.SSLError(),
diff --git a/test/test_cipher.py b/test/test_cipher.py
new file mode 100644
index 0000000..429d086
--- /dev/null
+++ b/test/test_cipher.py
@@ -0,0 +1,162 @@
+from test_config import Declarative
+from test_util import run, assert_equal
+import os
+import nose
+from nose.tools import make_decorator
+
+# As of now there are 47 ciphers including ECC
+WITH_ECC=47
+
+cwd = os.getcwd()
+srcdir = os.path.dirname(cwd)
+exe = "%s/test_cipher" % srcdir
+
+ciphernum = 0
+
+class test_ciphers(object):
+ @classmethod
+ def setUpClass(cls):
+ (out, err, rc) = run([exe, "--count"])
+ assert rc == 0
+ cls.ciphernum = int(out)
+
+ def test_RC4(self):
+ (out, err, rc) = run([exe, "RC4"])
+ assert rc == 0
+ if self.ciphernum < WITH_ECC:
+ assert_equal(out, 'rsa_rc4_40_md5, rsa_rc4_128_md5, rsa_rc4_128_sha, rsa_rc4_56_sha')
+ else:
+ assert_equal(out, 'rsa_rc4_40_md5, rsa_rc4_128_md5, rsa_rc4_128_sha, rsa_rc4_56_sha, ecdh_ecdsa_rc4_128_sha, ecdhe_ecdsa_rc4_128_sha, ecdh_rsa_128_sha, ecdhe_rsa_rc4_128_sha, ecdh_anon_rc4_128sha')
+
+ def test_AES(self):
+ (out, err, rc) = run([exe, "AES"])
+ assert rc == 0
+ if self.ciphernum < WITH_ECC:
+ assert_equal(out, 'rsa_aes_128_sha, rsa_aes_256_sha, aes_128_sha_256, aes_256_sha_256, rsa_aes_128_gcm_sha_256')
+ else:
+ assert_equal(out, 'rsa_aes_128_sha, rsa_aes_256_sha, aes_128_sha_256, aes_256_sha_256, rsa_aes_128_gcm_sha_256, ecdh_ecdsa_rc4_128_sha, ecdh_ecdsa_3des_sha, ecdh_ecdsa_aes_128_sha, ecdh_ecdsa_aes_256_sha, ecdhe_ecdsa_rc4_128_sha, ecdhe_ecdsa_3des_sha, ecdhe_ecdsa_aes_128_sha, ecdhe_ecdsa_aes_256_sha, ecdh_rsa_128_sha, ecdh_rsa_3des_sha, ecdh_rsa_aes_128_sha, ecdh_rsa_aes_256_sha, ecdhe_rsa_aes_128_sha, ecdhe_rsa_aes_256_sha, ecdh_anon_aes_128_sha, ecdh_anon_aes_256_sha, ecdhe_ecdsa_aes_128_sha_256, ecdhe_rsa_aes_128_sha_256, ecdhe_ecdsa_aes_128_gcm_sha_256, ecdhe_rsa_aes_128_gcm_sha_256')
+
+
+ def test_ALL(self):
+ (out, err, rc) = run([exe, "ALL"])
+ assert rc == 0
+ if self.ciphernum < WITH_ECC:
+ 'rsa_rc4_40_md5, rsa_rc4_128_md5, rsa_rc4_128_sha, rsa_rc2_40_md5, rsa_des_sha, rsa_3des_sha, rsa_aes_128_sha, rsa_aes_256_sha, aes_128_sha_256, aes_256_sha_256, camelia_128_sha, rsa_des_56_sha, rsa_rc4_56_sha, camelia_256_sha, rsa_aes_128_gcm_sha_256'
+ else:
+ assert_equal(out, 'rsa_rc4_40_md5, rsa_rc4_128_md5, rsa_rc4_128_sha, rsa_rc2_40_md5, rsa_des_sha, rsa_3des_sha, rsa_aes_128_sha, rsa_aes_256_sha, aes_128_sha_256, aes_256_sha_256, camelia_128_sha, rsa_des_56_sha, rsa_rc4_56_sha, camelia_256_sha, rsa_aes_128_gcm_sha_256, fips_3des_sha, fips_des_sha, ecdh_ecdsa_rc4_128_sha, ecdh_ecdsa_3des_sha, ecdh_ecdsa_aes_128_sha, ecdh_ecdsa_aes_256_sha, ecdhe_ecdsa_rc4_128_sha, ecdhe_ecdsa_3des_sha, ecdhe_ecdsa_aes_128_sha, ecdhe_ecdsa_aes_256_sha, ecdh_rsa_128_sha, ecdh_rsa_3des_sha, ecdh_rsa_aes_128_sha, ecdh_rsa_aes_256_sha, ecdhe_rsa_rc4_128_sha, ecdhe_rsa_3des_sha, ecdhe_rsa_aes_128_sha, ecdhe_rsa_aes_256_sha, ecdh_anon_rc4_128sha, ecdh_anon_3des_sha, ecdh_anon_aes_128_sha, ecdh_anon_aes_256_sha, ecdhe_ecdsa_aes_128_sha_256, ecdhe_rsa_aes_128_sha_256, ecdhe_ecdsa_aes_128_gcm_sha_256, ecdhe_rsa_aes_128_gcm_sha_256')
+
+ def test_ALL_no_AES(self):
+ (out, err, rc) = run([exe, "ALL:-AES"])
+ assert rc == 0
+ if self.ciphernum < WITH_ECC:
+ assert_equal(out, 'rsa_rc4_40_md5, rsa_rc4_128_md5, rsa_rc4_128_sha, rsa_rc2_40_md5, rsa_des_sha, rsa_3des_sha, camelia_128_sha, rsa_des_56_sha, rsa_rc4_56_sha, camelia_256_sha, fips_3des_sha, fips_des_sha')
+ else:
+ assert_equal(out, 'rsa_rc4_40_md5, rsa_rc4_128_md5, rsa_rc4_128_sha, rsa_rc2_40_md5, rsa_des_sha, rsa_3des_sha, camelia_128_sha, rsa_des_56_sha, rsa_rc4_56_sha, camelia_256_sha, fips_3des_sha, fips_des_sha, ecdhe_rsa_rc4_128_sha, ecdhe_rsa_3des_sha, ecdh_anon_rc4_128sha, ecdh_anon_3des_sha')
+
+ def test_SSLv3(self):
+ (out, err, rc) = run([exe, "SSLv3"])
+ assert rc == 0
+ if self.ciphernum < WITH_ECC:
+ assert_equal(out, 'rsa_rc4_40_md5, rsa_rc4_128_md5, rsa_rc4_128_sha, rsa_rc2_40_md5, rsa_des_sha, rsa_3des_sha, rsa_aes_128_sha, rsa_aes_256_sha, camelia_128_sha, rsa_des_56_sha, rsa_rc4_56_sha, camelia_256_sha, fips_3des_sha, fips_des_sha')
+ else:
+ assert_equal(out, 'rsa_rc4_40_md5, rsa_rc4_128_md5, rsa_rc4_128_sha, rsa_rc2_40_md5, rsa_des_sha, rsa_3des_sha, rsa_aes_128_sha, rsa_aes_256_sha, camelia_128_sha, rsa_des_56_sha, rsa_rc4_56_sha, camelia_256_sha, fips_3des_sha, fips_des_sha, ecdh_ecdsa_rc4_128_sha, ecdh_ecdsa_3des_sha, ecdh_ecdsa_aes_128_sha, ecdh_ecdsa_aes_256_sha, ecdhe_ecdsa_rc4_128_sha, ecdhe_ecdsa_3des_sha, ecdhe_ecdsa_aes_128_sha, ecdhe_ecdsa_aes_256_sha, ecdh_rsa_128_sha, ecdh_rsa_3des_sha, ecdh_rsa_aes_128_sha, ecdh_rsa_aes_256_sha, ecdhe_rsa_rc4_128_sha, ecdhe_rsa_3des_sha, ecdhe_rsa_aes_128_sha, ecdhe_rsa_aes_256_sha, ecdh_anon_rc4_128sha, ecdh_anon_3des_sha, ecdh_anon_aes_128_sha, ecdh_anon_aes_256_sha')
+
+ def test_SSLv3_equals_TLSv1(self):
+ (out, err, rc) = run([exe, "SSLv3"])
+ (out2, err2, rc2) = run([exe, "TLSv1"])
+ assert rc == 0
+ assert rc2 == 0
+ assert_equal(out, out2)
+
+ def test_TLSv12(self):
+ if self.ciphernum < WITH_ECC:
+ raise nose.SkipTest('ECC disabled')
+ (out, err, rc) = run([exe, "TLSv12"])
+ assert rc == 0
+ assert_equal(out, 'aes_128_sha_256, aes_256_sha_256, rsa_aes_128_gcm_sha_256, ecdhe_ecdsa_aes_128_sha_256, ecdhe_rsa_aes_128_sha_256, ecdhe_ecdsa_aes_128_gcm_sha_256, ecdhe_rsa_aes_128_gcm_sha_256')
+
+ def test_NULL(self):
+ (out, err, rc) = run([exe, "NULL"])
+ assert rc == 0
+ if self.ciphernum < WITH_ECC:
+ assert_equal(out, 'rsa_null_md5, rsa_null_sha, null_sha_256')
+ else:
+ assert_equal(out, 'rsa_null_md5, rsa_null_sha, null_sha_256, ecdh_ecdsa_null_sha, ecdhe_ecdsa_null_sha, ecdh_rsa_null_sha, ecdhe_rsa_null, ecdh_anon_null_sha')
+
+ def test_nss_rsa_rc4_128(self):
+ (out, err, rc) = run([exe, "+rsa_rc4_128_md5,+rsa_rc4_128_sha"])
+ assert rc == 0
+ assert_equal(out, 'rsa_rc4_128_md5, rsa_rc4_128_sha')
+
+ def test_openssl_cipher(self):
+ (out, err, rc) = run([exe, "DES-CBC3-SHA"])
+ assert rc == 0
+ assert_equal(out, 'rsa_3des_sha')
+
+ def test_openssl_cipherlist(self):
+ (out, err, rc) = run([exe, "DES-CBC3-SHA:RC4-SHA"])
+ assert rc == 0
+ assert_equal(out, 'rsa_rc4_128_sha, rsa_3des_sha')
+
+ def test_EXP(self):
+ (out, err, rc) = run([exe, "EXP"])
+ assert rc == 0
+ assert_equal(out, 'rsa_rc4_40_md5, rsa_rc2_40_md5, rsa_des_56_sha, rsa_rc4_56_sha')
+
+ def test_MD5(self):
+ (out, err, rc) = run([exe, "MD5"])
+ assert rc == 0
+ assert_equal(out, 'rsa_rc4_40_md5, rsa_rc4_128_md5, rsa_rc2_40_md5')
+
+ def test_SHA(self):
+ (out, err, rc) = run([exe, "SHA"])
+ assert rc == 0
+ if self.ciphernum < WITH_ECC:
+ assert_equal(out, 'rsa_rc4_128_sha, rsa_des_sha, rsa_3des_sha, rsa_aes_128_sha, rsa_aes_256_sha, camelia_128_sha, rsa_des_56_sha, rsa_rc4_56_sha, camelia_256_sha, fips_3des_sha, fips_des_sha')
+ else:
+ assert_equal(out, 'rsa_rc4_128_sha, rsa_des_sha, rsa_3des_sha, rsa_aes_128_sha, rsa_aes_256_sha, camelia_128_sha, rsa_des_56_sha, rsa_rc4_56_sha, camelia_256_sha, fips_3des_sha, fips_des_sha, ecdh_ecdsa_rc4_128_sha, ecdh_ecdsa_3des_sha, ecdh_ecdsa_aes_128_sha, ecdh_ecdsa_aes_256_sha, ecdhe_ecdsa_rc4_128_sha, ecdhe_ecdsa_3des_sha, ecdhe_ecdsa_aes_128_sha, ecdhe_ecdsa_aes_256_sha, ecdh_rsa_128_sha, ecdh_rsa_3des_sha, ecdh_rsa_aes_128_sha, ecdh_rsa_aes_256_sha, ecdhe_rsa_rc4_128_sha, ecdhe_rsa_3des_sha, ecdhe_rsa_aes_128_sha, ecdhe_rsa_aes_256_sha, ecdh_anon_rc4_128sha, ecdh_anon_3des_sha, ecdh_anon_aes_128_sha, ecdh_anon_aes_256_sha')
+
+ def test_SHA256(self):
+ (out, err, rc) = run([exe, "SHA256"])
+ assert rc == 0
+ if self.ciphernum < WITH_ECC:
+ assert_equal(out, 'aes_128_sha_256, aes_256_sha_256')
+ else:
+ assert_equal(out, 'aes_128_sha_256, aes_256_sha_256, ecdhe_ecdsa_aes_128_sha_256, ecdhe_rsa_aes_128_sha_256')
+
+ def test_SHA_MD5_minus_AES(self):
+ (out, err, rc) = run([exe, "SHA:MD5:-AES"])
+ assert rc == 0
+ if self.ciphernum < WITH_ECC:
+ assert_equal(out, 'rsa_rc4_40_md5, rsa_rc4_128_md5, rsa_rc4_128_sha, rsa_rc2_40_md5, rsa_des_sha, rsa_3des_sha, camelia_128_sha, rsa_des_56_sha, rsa_rc4_56_sha, camelia_256_sha, fips_3des_sha, fips_des_sha')
+ else:
+ assert_equal(out, 'rsa_rc4_40_md5, rsa_rc4_128_md5, rsa_rc4_128_sha, rsa_rc2_40_md5, rsa_des_sha, rsa_3des_sha, camelia_128_sha, rsa_des_56_sha, rsa_rc4_56_sha, camelia_256_sha, fips_3des_sha, fips_des_sha, ecdhe_rsa_rc4_128_sha, ecdhe_rsa_3des_sha, ecdh_anon_rc4_128sha, ecdh_anon_3des_sha')
+
+ def test_SHA_MD5_not_AES_HIGH(self):
+ (out, err, rc) = run([exe, "!AES:SHA:MD5"])
+ assert rc == 0
+ if self.ciphernum < WITH_ECC:
+ assert_equal(out, 'rsa_rc4_40_md5, rsa_rc4_128_md5, rsa_rc4_128_sha, rsa_rc2_40_md5, rsa_des_sha, rsa_3des_sha, camelia_128_sha, rsa_des_56_sha, rsa_rc4_56_sha, camelia_256_sha, fips_3des_sha, fips_des_sha')
+ else:
+ assert_equal(out, 'rsa_rc4_40_md5, rsa_rc4_128_md5, rsa_rc4_128_sha, rsa_rc2_40_md5, rsa_des_sha, rsa_3des_sha, camelia_128_sha, rsa_des_56_sha, rsa_rc4_56_sha, camelia_256_sha, fips_3des_sha, fips_des_sha, ecdhe_rsa_rc4_128_sha, ecdhe_rsa_3des_sha, ecdh_anon_rc4_128sha, ecdh_anon_3des_sha')
+
+ def test_nss_subtraction(self):
+ (out, err, rc) = run([exe, "+rsa_rc4_128_md5,+rsa_rc4_128_sha,-rsa_rc4_128_md5"])
+ assert rc == 0
+ assert_equal(out, 'rsa_rc4_128_sha')
+
+ # As long as at least one is valid, things are ok
+ def test_nss_unknown(self):
+ (out, err, rc) = run([exe, "+rsa_rc4_128_md5,+unknown"])
+ assert rc == 0
+ assert_equal(out, 'rsa_rc4_128_md5')
+
+ def test_nss_single(self):
+ (out, err, rc) = run([exe, "+aes_128_sha_256"])
+ assert rc == 0
+ assert_equal(out, 'aes_128_sha_256')
+
+ def test_invalid_format(self):
+ (out, err, rc) = run([exe, "none"])
+ assert rc == 1
+ assert_equal(err, 'nss_engine_cipher.c:292, invalid cipher string none. Format is +cipher1,-cipher2...Unable to parse cipher list')
diff --git a/test/test_util.py b/test/test_util.py
index f01d43a..050e1dc 100644
--- a/test/test_util.py
+++ b/test/test_util.py
@@ -1,5 +1,6 @@
import socket
import time
+import subprocess
def host_port_open(host, port, socket_type=socket.SOCK_STREAM, socket_timeout=None):
for res in socket.getaddrinfo(host, port, socket.AF_UNSPEC, socket_type):
@@ -50,3 +51,38 @@ def wait_for_open_ports(host, ports, timeout=0):
raise socket.timeout()
time.sleep(1)
+def shell_quote(string):
+ return "'" + string.replace("'", "'\\''") + "'"
+
+def run(args):
+ """
+ Execute a command and return stdin, stdout and the process return code.
+
+ :param args: List of arguments for the command
+ """
+ p_in = None
+ p_out = None
+
+ p_out = subprocess.PIPE
+ p_err = subprocess.PIPE
+
+ arg_string = ' '.join(shell_quote(a) for a in args)
+
+ try:
+ p = subprocess.Popen(args, stdout=p_out, stderr=p_err,
+ close_fds=True)
+ stdout,stderr = p.communicate(None)
+ except KeyboardInterrupt:
+ p.wait()
+ raise
+
+ return (stdout, stderr, p.returncode)
+
+
+def assert_equal(got, expected):
+ if got.strip() != expected.strip():
+ raise AssertionError(
+ "assert_deepequal: expected != got. " \
+ "expected = %r got = %r" %
+ (expected, got)
+ )
diff --git a/test_cipher.c b/test_cipher.c
new file mode 100644
index 0000000..91d112b
--- /dev/null
+++ b/test_cipher.c
@@ -0,0 +1,97 @@
+/* Copyright 2001-2004 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <sslproto.h>
+
+/* Fake a few Apache and NSPR data types and definitions */
+typedef char server_rec;
+typedef int PRBool;
+typedef int PRInt32;
+
+#define PR_FALSE 0
+#define PR_TRUE 1
+
+#include <nss_engine_cipher.h>
+
+extern cipher_properties ciphers_def[];
+
+/* An Apache-like error logger */
+int ap_log_error_(const char *fn, int line, int module_index,
+ int level, int status,
+ const server_rec *s, char *fmt, ...)
+{
+ char out[1024];
+ va_list args;
+
+ va_start(args, fmt);
+ vsprintf(out, fmt, args);
+ fprintf(stderr,"%s:%d, %s", fn, line, out);
+ va_end(args);
+
+ return 0;
+}
+
+#define ap_log_error_ ap_log_error
+
+int main(int argc, char ** argv)
+{
+ int rv=0;
+ int i;
+ char *ciphers;
+ PRBool ciphers_list[ciphernum];
+
+ if (argc != 2) {
+ fprintf(stderr, "Usage: test_cipher [--count] <cipher_list>\n");
+ exit(1);
+ }
+
+ if (!strcmp(argv[1], "--count")) {
+ fprintf(stdout, "%d\n", ciphernum);
+ exit(0);
+ }
+
+ for (i=0; i<ciphernum; i++)
+ {
+ ciphers_list[i] = PR_FALSE;
+ }
+
+ ciphers = strdup(argv[1]);
+ if (nss_parse_ciphers(NULL, ciphers, ciphers_list) < 0) {
+ fprintf(stderr, "Unable to parse cipher list\n");
+ rv = 1;
+ }
+ free(ciphers);
+
+ /* Done parsing, print the results, if any */
+ if (rv == 0)
+ {
+ char output[1024 * 10];
+
+ for (i = 0; i < ciphernum; i++)
+ {
+ if (ciphers_list[i] == 1) {
+ strncat(output, ciphers_def[i].name, sizeof(output));
+ strncat(output, ", ", sizeof(output));
+ }
+ }
+ output[strlen(output) - 2] = '\0';
+ fprintf(stdout, "%s\n", output);
+ }
+
+ return rv;
+}