summaryrefslogtreecommitdiffstats
path: root/contrib
diff options
context:
space:
mode:
authorChristian Heimes <cheimes@redhat.com>2016-01-21 16:09:10 +0100
committerMartin Basti <mbasti@redhat.com>2016-02-11 10:44:29 +0100
commit5ac3a3cee534a16db86c541b9beff4939f03410e (patch)
treed0aff8d1bb1d4976e99120b01976bf1ccf293beb /contrib
parent42d364427606e39486645e4064ca16940b2f8837 (diff)
downloadfreeipa-5ac3a3cee534a16db86c541b9beff4939f03410e.tar.gz
freeipa-5ac3a3cee534a16db86c541b9beff4939f03410e.tar.xz
freeipa-5ac3a3cee534a16db86c541b9beff4939f03410e.zip
Modernize mod_nss's cipher suites
The list of supported TLS cipher suites in /etc/httpd/conf.d/nss.conf has been modernized. Insecure or less secure algorithms such as RC4, DES and 3DES are removed. Perfect forward secrecy suites with ephemeral ECDH key exchange have been added. IE 8 on Windows XP is no longer supported. The list of enabled cipher suites has been generated with the script contrib/nssciphersuite/nssciphersuite.py. TLS_RSA_WITH_AES_128_CBC_SHA256 TLS_RSA_WITH_AES_256_CBC_SHA256 TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA TLS_RSA_WITH_AES_128_GCM_SHA256 TLS_RSA_WITH_AES_128_CBC_SHA TLS_RSA_WITH_AES_256_GCM_SHA384 TLS_RSA_WITH_AES_256_CBC_SHA https://fedorahosted.org/freeipa/ticket/5589 Signed-off-by: Christian Heimes <cheimes@redhat.com> Reviewed-By: Martin Basti <mbasti@redhat.com>
Diffstat (limited to 'contrib')
-rw-r--r--contrib/nssciphersuite/README.txt36
-rwxr-xr-xcontrib/nssciphersuite/nssciphersuite.py147
2 files changed, 183 insertions, 0 deletions
diff --git a/contrib/nssciphersuite/README.txt b/contrib/nssciphersuite/README.txt
new file mode 100644
index 000000000..c36594b9b
--- /dev/null
+++ b/contrib/nssciphersuite/README.txt
@@ -0,0 +1,36 @@
+Cipher suite for mod_nss
+------------------------
+
+The nssciphersuite.py script parses mod_nss' nss_engine_cipher.c file and
+creates a list of secure cipher suites for TLS. The script filters out
+insecure, obsolete and slow ciphers according to some rules.
+
+As of January 2016 and mod_nss 1.0.12 the cipher suite list contains 14
+cipher suites for TLS 1.0, 1.1 and 1.2 for RSA and ECDSA certificates. The
+cipher suite list also supports Perfect Forward Secrecy with ephemeral ECDH
+key exchange. https://www.ssllabs.com/ gives a 'A' grade.
+
+Note:
+No suite is compatible with IE 8 and earlier on Windows XP. If you need IE 8
+support, append "+rsa_3des_sha" to enable TLS_RSA_WITH_3DES_EDE_CBC_SHA.
+
+# disabled cipher attributes: SSL_3DES, SSL_CAMELLIA, SSL_CAMELLIA128, SSL_CAMELLIA256, SSL_DES, SSL_DSS, SSL_MD5, SSL_RC2, SSL_RC4, SSL_aDSS, SSL_aNULL, SSL_eNULL, SSL_kECDHe, SSL_kECDHr, kECDH
+# weak strength: SSL_EXPORT40, SSL_EXPORT56, SSL_LOW, SSL_STRONG_NONE
+# enabled cipher suites:
+# TLS_RSA_WITH_AES_128_CBC_SHA256
+# TLS_RSA_WITH_AES_256_CBC_SHA256
+# TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
+# TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
+# TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
+# TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
+# TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
+# TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
+# TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
+# TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
+# TLS_RSA_WITH_AES_128_GCM_SHA256
+# TLS_RSA_WITH_AES_128_CBC_SHA
+# TLS_RSA_WITH_AES_256_GCM_SHA384
+# TLS_RSA_WITH_AES_256_CBC_SHA
+#
+
+NSSCipherSuite +aes_128_sha_256,+aes_256_sha_256,+ecdhe_ecdsa_aes_128_gcm_sha_256,+ecdhe_ecdsa_aes_128_sha,+ecdhe_ecdsa_aes_256_gcm_sha_384,+ecdhe_ecdsa_aes_256_sha,+ecdhe_rsa_aes_128_gcm_sha_256,+ecdhe_rsa_aes_128_sha,+ecdhe_rsa_aes_256_gcm_sha_384,+ecdhe_rsa_aes_256_sha,+rsa_aes_128_gcm_sha_256,+rsa_aes_128_sha,+rsa_aes_256_gcm_sha_384,+rsa_aes_256_sha
diff --git a/contrib/nssciphersuite/nssciphersuite.py b/contrib/nssciphersuite/nssciphersuite.py
new file mode 100755
index 000000000..dee05d470
--- /dev/null
+++ b/contrib/nssciphersuite/nssciphersuite.py
@@ -0,0 +1,147 @@
+#!/usr/bin/python3
+#
+# Authors:
+# Christian Heimes <cheimes@redhat.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Copyright (C) 2016 Red Hat, Inc.
+# All rights reserved.
+#
+"""Generate safe NSSCipherSuite stanza for mod_nss
+"""
+from __future__ import print_function
+
+import operator
+import re
+from urllib.request import urlopen # pylint: disable=no-name-in-module
+
+SOURCE = "https://git.fedorahosted.org/cgit/mod_nss.git/plain/nss_engine_cipher.c"
+
+CIPHER_RE = re.compile(
+ r'\s*\{'
+ r'\"(?P<name>\w+)\",\s*'
+ r'(?P<num>(TLS|SSL)_\w+),\s*'
+ r'\"(?P<openssl_name>[\w-]+)\",\s*'
+ r'(?P<attr>[\w|]+),\s*'
+ r'(?P<version>\w+),\s*'
+ r'(?P<strength>\w+),\s*'
+ r'(?P<bits>\d+),\s*'
+ r'(?P<alg_bits>\d+)'
+)
+
+DISABLED_CIPHERS = {
+ # ciphers without encryption or authentication
+ 'SSL_eNULL', 'SSL_aNULL',
+ # MD5 is broken
+ # SHA-1 is still required as PRF algorithm for TLSv1.0
+ 'SSL_MD5',
+ # RC2 and RC4 stream ciphers are broken.
+ 'SSL_RC2', 'SSL_RC4',
+ # DES is broken and Triple DES is too weak.
+ 'SSL_DES', 'SSL_3DES',
+ # DSA is problematic.
+ 'SSL_DSS', 'SSL_aDSS',
+ # prefer AES over Camellia.
+ 'SSL_CAMELLIA128', 'SSL_CAMELLIA256', 'SSL_CAMELLIA',
+ # non-ephemeral EC Diffie-Hellmann with fixed parameters are not
+ # used by common browser and are therefore irrelevant for HTTPS.
+ 'kECDH', 'SSL_kECDHr', 'SSL_kECDHe'
+}
+
+WEAK_STRENGTH = {
+ 'SSL_STRONG_NONE',
+ 'SSL_EXPORT40',
+ 'SSL_EXPORT56',
+ 'SSL_LOW'
+}
+
+
+def parse_nss_engine_cipher(lines, encoding='utf-8'):
+ """Parse nss_engine_cipher.c and get list of ciphers
+
+ :param lines: iterable or list of lines
+ :param encoding: default encoding
+ :return: list of cipher dicts
+ """
+ ciphers = []
+ start = False
+ for line in lines:
+ if not isinstance(line, str):
+ line = line.decode(encoding)
+
+ if line.startswith('cipher_properties'):
+ start = True
+ elif not start:
+ continue
+ elif line.startswith('};'):
+ break
+
+ mo = CIPHER_RE.match(line)
+ if not mo:
+ continue
+
+ match = mo.groupdict()
+ match['attr'] = set(match['attr'].split('|'))
+ match['bits'] = int(match['bits'])
+ match['alg_bits'] = int(match['alg_bits'])
+
+ # some cipher elemets aren't flagged
+ for algo in ['SHA256', 'SHA384']:
+ if match['num'].endswith(algo):
+ match['attr'].add('SSL_{}'.format(algo))
+
+ # cipher block chaining isn't tracked
+ if '_CBC' in match['num']:
+ match['attr'].add('SSL_CBC')
+
+ if match['attr'].intersection(DISABLED_CIPHERS):
+ match['enabled'] = False
+ elif match['strength'] in WEAK_STRENGTH:
+ match['enabled'] = False
+ else:
+ match['enabled'] = True
+
+ # EECDH + AES-CBC and large hash functions is slow and not more secure
+ if (match['attr'].issuperset({'SSL_CBC', 'SSL_kEECDH'}) and
+ match['attr'].intersection({'SSL_SHA256', 'SSL_SHA384'})):
+ match['enabled'] = False
+
+ ciphers.append(match)
+
+ ciphers.sort(key=operator.itemgetter('name'))
+ return ciphers
+
+
+def main():
+ with urlopen(SOURCE) as r:
+ ciphers = parse_nss_engine_cipher(r)
+ # with open('nss_engine_cipher.c') as f:
+ # ciphers = parse_nss_engine_cipher(f)
+
+ print("# disabled cipher attributes: {}".format(
+ ', '.join(sorted(DISABLED_CIPHERS))))
+ print("# weak strength: {}".format(', '.join(sorted(WEAK_STRENGTH))))
+ print("# enabled cipher suites:")
+ suite = []
+ for cipher in ciphers:
+ if cipher['enabled']:
+ print("# {:36}".format(cipher['num']))
+ suite.append('+{}'.format(cipher['name']))
+ print()
+ print("NSSCipherSuite {}".format(','.join(suite)))
+
+
+if __name__ == '__main__':
+ main()