dirsrvtests/tickets/ticket47838_test.py | 552 ++++++++++++++++++++++++++++++++
ldap/servers/slapd/ssl.c | 401 +++++++++++++++--------
2 files changed, 823 insertions(+), 130 deletions(-)
New commits:
commit 03df340d4aacd6074700e3c5945e785965f2ae51
Author: Noriko Hosoi <nhosoi(a)redhat.com>
Date: Thu Aug 7 15:05:56 2014 -0700
Ticket 47838 - CI test: add test case for ticket 47838
Description: harden the list of ciphers available by default
Test Case 1 - Check the ciphers availability for "+all"
Test Case 2 - Check the ciphers availability for
"+rsa_aes_128_sha,+rsa_aes_256_sha"
Test Case 3 - Check the ciphers availability for "-all"
Test Case 4 - Check no nssSSL3Chiphers (default setting)
Test Case 5 - Check default nssSSL3Chiphers (default setting)
Test Case 6 - Check nssSSL3Chiphers: +all,-rsa_rc4_128_md5
Test Case 7 - Check nssSSL3Chiphers: -all,+rsa_rc4_128_md5
Test Case 8 - Check no nssSSL3Chiphers (default setting) with no errorlog-level
Test Case 9 - Check nssSSL3Chiphers: long list using the NSS Cipher Suite name
diff --git a/dirsrvtests/tickets/ticket47838_test.py
b/dirsrvtests/tickets/ticket47838_test.py
new file mode 100644
index 0000000..dedd61d
--- /dev/null
+++ b/dirsrvtests/tickets/ticket47838_test.py
@@ -0,0 +1,552 @@
+import os
+import sys
+import time
+import ldap
+import logging
+import socket
+import pytest
+import shutil
+from lib389 import DirSrv, Entry, tools
+from lib389 import DirSrvTools
+from lib389.tools import DirSrvTools
+from lib389._constants import *
+from lib389.properties import *
+from constants import *
+
+log = logging.getLogger(__name__)
+
+installation_prefix = None
+
+CONFIG_DN = 'cn=config'
+ENCRYPTION_DN = 'cn=encryption,%s' % CONFIG_DN
+RSA = 'RSA'
+RSA_DN = 'cn=%s,%s' % (RSA, ENCRYPTION_DN)
+LDAPSPORT = '10636'
+SERVERCERT = 'Server-Cert'
+plus_all_ecount = 0
+plus_all_dcount = 0
+
+class TopologyStandalone(object):
+ def __init__(self, standalone):
+ standalone.open()
+ self.standalone = standalone
+
+(a)pytest.fixture(scope="module")
+def topology(request):
+ '''
+ This fixture is used to standalone topology for the 'module'.
+ At the beginning, It may exists a standalone instance.
+ It may also exists a backup for the standalone instance.
+
+ Principle:
+ If standalone instance exists:
+ restart it
+ If backup of standalone exists:
+ create/rebind to standalone
+
+ restore standalone instance from backup
+ else:
+ Cleanup everything
+ remove instance
+ remove backup
+ Create instance
+ Create backup
+ '''
+ global installation_prefix
+
+ if installation_prefix:
+ args_instance[SER_DEPLOYED_DIR] = installation_prefix
+
+ standalone = DirSrv(verbose=False)
+
+ # Args for the standalone instance
+ args_instance[SER_HOST] = HOST_STANDALONE
+ args_instance[SER_PORT] = PORT_STANDALONE
+ args_instance[SER_SERVERID_PROP] = SERVERID_STANDALONE
+ args_standalone = args_instance.copy()
+ standalone.allocate(args_standalone)
+
+ # Get the status of the backups
+ backup_standalone = standalone.checkBackupFS()
+
+ # Get the status of the instance and restart it if it exists
+ instance_standalone = standalone.exists()
+ if instance_standalone:
+ # assuming the instance is already stopped, just wait 5 sec max
+ standalone.stop(timeout=5)
+ try:
+ standalone.start(timeout=10)
+ except ldap.SERVER_DOWN:
+ pass
+
+ if backup_standalone:
+ # The backup exist, assuming it is correct
+ # we just re-init the instance with it
+ if not instance_standalone:
+ standalone.create()
+ # Used to retrieve configuration information (dbdir, confdir...)
+ standalone.open()
+
+ # restore standalone instance from backup
+ standalone.stop(timeout=10)
+ standalone.restoreFS(backup_standalone)
+ standalone.start(timeout=10)
+
+ else:
+ # We should be here only in two conditions
+ # - This is the first time a test involve standalone instance
+ # - Something weird happened (instance/backup destroyed)
+ # so we discard everything and recreate all
+
+ # Remove the backup. So even if we have a specific backup file
+ # (e.g backup_standalone) we clear backup that an instance may have created
+ if backup_standalone:
+ standalone.clearBackupFS()
+
+ # Remove the instance
+ if instance_standalone:
+ standalone.delete()
+
+ # Create the instance
+ standalone.create()
+
+ # Used to retrieve configuration information (dbdir, confdir...)
+ standalone.open()
+
+ # Time to create the backups
+ standalone.stop(timeout=10)
+ standalone.backupfile = standalone.backupFS()
+ standalone.start(timeout=10)
+
+ # clear the tmp directory
+ standalone.clearTmpDir(__file__)
+
+ #
+ # Here we have standalone instance up and running
+ # Either coming from a backup recovery
+ # or from a fresh (re)init
+ # Time to return the topology
+ return TopologyStandalone(standalone)
+
+def _header(topology, label):
+
topology.standalone.log.info("\n\n###############################################")
+ topology.standalone.log.info("#######")
+ topology.standalone.log.info("####### %s" % label)
+ topology.standalone.log.info("#######")
+
topology.standalone.log.info("###############################################")
+
+def test_ticket47838_init(topology):
+ """
+ Generate self signed cert and import it to the DS cert db.
+ Enable SSL
+ """
+ _header(topology, 'Testing Ticket 47838 - harden the list of ciphers available by
default')
+
+ conf_dir = topology.standalone.confdir
+
+ log.info("\n######################### Checking existing certs
######################\n")
+ os.system('certutil -L -d %s -n "CA certificate"' % conf_dir)
+ os.system('certutil -L -d %s -n "%s"' % (conf_dir, SERVERCERT))
+
+ log.info("\n######################### Create a password file
######################\n")
+ pwdfile = '%s/pwdfile.txt' % (conf_dir)
+ opasswd = os.popen("(ps -ef ; w ) | sha1sum | awk '{print $1}'",
"r")
+ passwd = opasswd.readline()
+ pwdfd = open(pwdfile, "w")
+ pwdfd.write(passwd)
+ pwdfd.close()
+
+ log.info("\n######################### Create a noise file
######################\n")
+ noisefile = '%s/noise.txt' % (conf_dir)
+ noise = os.popen("(w ; ps -ef ; date ) | sha1sum | awk '{print
$1}'", "r")
+ noisewdfd = open(noisefile, "w")
+ noisewdfd.write(noise.readline())
+ noisewdfd.close()
+
+ log.info("\n######################### Create key3.db and cert8.db database
######################\n")
+ os.system("ls %s" % pwdfile)
+ os.system("cat %s" % pwdfile)
+ os.system('certutil -N -d %s -f %s' % (conf_dir, pwdfile))
+
+ log.info("\n######################### Creating encryption key for CA
######################\n")
+ os.system('certutil -G -d %s -z %s -f %s' % (conf_dir, noisefile, pwdfile))
+
+ log.info("\n######################### Creating self-signed CA certificate
######################\n")
+ os.system('( echo y ; echo ; echo y ) | certutil -S -n "CA certificate"
-s "cn=CAcert" -x -t "CT,," -m 1000 -v 120 -d %s -z %s -f %s -2' %
(conf_dir, noisefile, pwdfile))
+
+ log.info("\n######################### Exporting the CA certificate to cacert.asc
######################\n")
+ cafile = '%s/cacert.asc' % conf_dir
+ catxt = os.popen('certutil -L -d %s -n "CA certificate" -a' %
conf_dir)
+ cafd = open(cafile, "w")
+ while True:
+ line = catxt.readline()
+ if (line == ''):
+ break
+ cafd.write(line)
+ cafd.close()
+
+ log.info("\n######################### Generate the server certificate
######################\n")
+ ohostname = os.popen('hostname --fqdn', "r")
+ myhostname = ohostname.readline()
+ os.system('certutil -S -n "%s" -s "cn=%s,ou=389 Directory
Server" -c "CA certificate" -t "u,u,u" -m 1001 -v 120 -d %s -z %s
-f %s' % (SERVERCERT, myhostname.rstrip(), conf_dir, noisefile, pwdfile))
+
+ log.info("\n######################### create the pin file
######################\n")
+ pinfile = '%s/pin.txt' % (conf_dir)
+ pintxt = 'Internal (Software) Token:%s' % passwd
+ pinfd = open(pinfile, "w")
+ pinfd.write(pintxt)
+ pinfd.close()
+
+ log.info("\n######################### enable SSL in the directory server with
all ciphers ######################\n")
+ topology.standalone.simple_bind_s(DN_DM, PASSWORD)
+ topology.standalone.modify_s(ENCRYPTION_DN, [(ldap.MOD_REPLACE, 'nsSSL3',
'on'),
+ (ldap.MOD_REPLACE,
'nsSSLClientAuth', 'allowed'),
+ (ldap.MOD_REPLACE,
'nsSSL3Ciphers', '+all')])
+
+ topology.standalone.modify_s(CONFIG_DN, [(ldap.MOD_REPLACE,
'nsslapd-security', 'on'),
+ (ldap.MOD_REPLACE,
'nsslapd-ssl-check-hostname', 'off'),
+ (ldap.MOD_REPLACE,
'nsslapd-secureport', LDAPSPORT)])
+
+ topology.standalone.add_s(Entry((RSA_DN, {'objectclass': "top
nsEncryptionModule".split(),
+ 'cn': RSA,
+ 'nsSSLPersonalitySSL': SERVERCERT,
+ 'nsSSLToken': 'internal
(software)',
+ 'nsSSLActivation':
'on'})))
+
+def test_ticket47838_run_0(topology):
+ """
+ Check nsSSL3Ciphers: +all
+ All ciphers are enabled except null.
+ """
+ _header(topology, 'Test Case 1 - Check the ciphers availability for
"+all"')
+
+ topology.standalone.simple_bind_s(DN_DM, PASSWORD)
+ topology.standalone.modify_s(CONFIG_DN, [(ldap.MOD_REPLACE,
'nsslapd-errorlog-level', '64')])
+
+ log.info("\n######################### Restarting the server
######################\n")
+ topology.standalone.restart(timeout=120)
+
+ enabled = os.popen('egrep "SSL alert:" %s | egrep enabled | wc -l'
% topology.standalone.errlog)
+ disabled = os.popen('egrep "SSL alert:" %s | egrep disabled | wc
-l' % topology.standalone.errlog)
+ ecount = int(enabled.readline().rstrip())
+ dcount = int(disabled.readline().rstrip())
+
+ log.info("Enabled ciphers: %d" % ecount)
+ log.info("Disabled ciphers: %d" % dcount)
+ assert ecount >= 60
+ assert dcount <= 7
+ global plus_all_ecount
+ global plus_all_dcount
+ plus_all_ecount = ecount
+ plus_all_dcount = dcount
+ weak = os.popen('egrep "SSL alert:" %s | egrep "WEAK CIPHER"
| wc -l' % topology.standalone.errlog)
+ wcount = int(weak.readline().rstrip())
+ log.info("Weak ciphers: %d" % wcount)
+ assert wcount <= 29
+
+def test_ticket47838_run_1(topology):
+ """
+ Check nsSSL3Ciphers: +rsa_aes_128_sha,+rsa_aes_256_sha
+ rsa_aes_128_sha, tls_rsa_aes_128_sha, rsa_aes_256_sha, tls_rsa_aes_256_sha are
enabled.
+ """
+ _header(topology, 'Test Case 2 - Check the ciphers availability for
"+rsa_aes_128_sha,+rsa_aes_256_sha"')
+
+ topology.standalone.simple_bind_s(DN_DM, PASSWORD)
+ topology.standalone.modify_s(ENCRYPTION_DN, [(ldap.MOD_REPLACE,
'nsSSL3Ciphers', '+rsa_aes_128_sha,+rsa_aes_256_sha')])
+
+ log.info("\n######################### Restarting the server
######################\n")
+ topology.standalone.stop(timeout=10)
+ os.system('mv %s %s.47838_0' % (topology.standalone.errlog,
topology.standalone.errlog))
+ os.system('touch %s' % (topology.standalone.errlog))
+ topology.standalone.start(timeout=120)
+
+ enabled = os.popen('egrep "SSL alert:" %s | egrep enabled | wc -l'
% topology.standalone.errlog)
+ disabled = os.popen('egrep "SSL alert:" %s | egrep disabled | wc
-l' % topology.standalone.errlog)
+ ecount = int(enabled.readline().rstrip())
+ dcount = int(disabled.readline().rstrip())
+
+ log.info("Enabled ciphers: %d" % ecount)
+ log.info("Disabled ciphers: %d" % dcount)
+ global plus_all_ecount
+ global plus_all_dcount
+ assert ecount == 2
+ assert dcount == (plus_all_ecount + plus_all_dcount - ecount)
+
+def test_ticket47838_run_2(topology):
+ """
+ Check nsSSL3Ciphers: -all
+ All ciphers are disabled.
+ """
+ _header(topology, 'Test Case 3 - Check the ciphers availability for
"-all"')
+
+ topology.standalone.simple_bind_s(DN_DM, PASSWORD)
+ topology.standalone.modify_s(ENCRYPTION_DN, [(ldap.MOD_REPLACE,
'nsSSL3Ciphers', '-all')])
+
+ log.info("\n######################### Restarting the server
######################\n")
+ topology.standalone.stop(timeout=10)
+ os.system('mv %s %s.47838_1' % (topology.standalone.errlog,
topology.standalone.errlog))
+ os.system('touch %s' % (topology.standalone.errlog))
+ topology.standalone.start(timeout=120)
+
+ enabled = os.popen('egrep "SSL alert:" %s | egrep enabled | wc -l'
% topology.standalone.errlog)
+ disabled = os.popen('egrep "SSL alert:" %s | egrep disabled | wc
-l' % topology.standalone.errlog)
+ ecount = int(enabled.readline().rstrip())
+ dcount = int(disabled.readline().rstrip())
+
+ log.info("Enabled ciphers: %d" % ecount)
+ log.info("Disabled ciphers: %d" % dcount)
+ global plus_all_ecount
+ global plus_all_dcount
+ assert ecount == 0
+ assert dcount == (plus_all_ecount + plus_all_dcount)
+
+def test_ticket47838_run_3(topology):
+ """
+ Check no nsSSL3Ciphers
+ Default ciphers are enabled.
+ """
+ _header(topology, 'Test Case 4 - Check no nssSSL3Chiphers (default
setting)')
+
+ topology.standalone.simple_bind_s(DN_DM, PASSWORD)
+ topology.standalone.modify_s(ENCRYPTION_DN, [(ldap.MOD_DELETE,
'nsSSL3Ciphers', '-all')])
+
+ log.info("\n######################### Restarting the server
######################\n")
+ topology.standalone.stop(timeout=10)
+ os.system('mv %s %s.47838_2' % (topology.standalone.errlog,
topology.standalone.errlog))
+ os.system('touch %s' % (topology.standalone.errlog))
+ topology.standalone.start(timeout=120)
+
+ enabled = os.popen('egrep "SSL alert:" %s | egrep enabled | wc -l'
% topology.standalone.errlog)
+ disabled = os.popen('egrep "SSL alert:" %s | egrep disabled | wc
-l' % topology.standalone.errlog)
+ ecount = int(enabled.readline().rstrip())
+ dcount = int(disabled.readline().rstrip())
+
+ log.info("Enabled ciphers: %d" % ecount)
+ log.info("Disabled ciphers: %d" % dcount)
+ global plus_all_ecount
+ global plus_all_dcount
+ assert ecount == 12
+ assert dcount == (plus_all_ecount + plus_all_dcount - ecount)
+ weak = os.popen('egrep "SSL alert:" %s | egrep enabled | egrep
"WEAK CIPHER" | wc -l' % topology.standalone.errlog)
+ wcount = int(weak.readline().rstrip())
+ log.info("Weak ciphers in the default setting: %d" % wcount)
+ assert wcount == 0
+
+def test_ticket47838_run_4(topology):
+ """
+ Check nsSSL3Ciphers: default
+ Default ciphers are enabled.
+ """
+ _header(topology, 'Test Case 5 - Check default nssSSL3Chiphers (default
setting)')
+
+ topology.standalone.simple_bind_s(DN_DM, PASSWORD)
+ topology.standalone.modify_s(ENCRYPTION_DN, [(ldap.MOD_REPLACE,
'nsSSL3Ciphers', 'default')])
+
+ log.info("\n######################### Restarting the server
######################\n")
+ topology.standalone.stop(timeout=10)
+ os.system('mv %s %s.47838_3' % (topology.standalone.errlog,
topology.standalone.errlog))
+ os.system('touch %s' % (topology.standalone.errlog))
+ topology.standalone.start(timeout=120)
+
+ enabled = os.popen('egrep "SSL alert:" %s | egrep enabled | wc -l'
% topology.standalone.errlog)
+ disabled = os.popen('egrep "SSL alert:" %s | egrep disabled | wc
-l' % topology.standalone.errlog)
+ ecount = int(enabled.readline().rstrip())
+ dcount = int(disabled.readline().rstrip())
+
+ log.info("Enabled ciphers: %d" % ecount)
+ log.info("Disabled ciphers: %d" % dcount)
+ global plus_all_ecount
+ global plus_all_dcount
+ assert ecount == 12
+ assert dcount == (plus_all_ecount + plus_all_dcount - ecount)
+ weak = os.popen('egrep "SSL alert:" %s | egrep enabled | egrep
"WEAK CIPHER" | wc -l' % topology.standalone.errlog)
+ wcount = int(weak.readline().rstrip())
+ log.info("Weak ciphers in the default setting: %d" % wcount)
+ assert wcount == 0
+
+def test_ticket47838_run_5(topology):
+ """
+ Check nssSSL3Chiphers: +all,-rsa_rc4_128_md5
+ All ciphers are disabled.
+ """
+ _header(topology, 'Test Case 6 - Check nssSSL3Chiphers:
+all,-rsa_rc4_128_md5')
+
+ topology.standalone.simple_bind_s(DN_DM, PASSWORD)
+ topology.standalone.modify_s(ENCRYPTION_DN, [(ldap.MOD_REPLACE,
'nsSSL3Ciphers', '+all,-rsa_rc4_128_md5')])
+
+ log.info("\n######################### Restarting the server
######################\n")
+ topology.standalone.stop(timeout=10)
+ os.system('mv %s %s.47838_4' % (topology.standalone.errlog,
topology.standalone.errlog))
+ os.system('touch %s' % (topology.standalone.errlog))
+ topology.standalone.start(timeout=120)
+
+ enabled = os.popen('egrep "SSL alert:" %s | egrep enabled | wc -l'
% topology.standalone.errlog)
+ disabled = os.popen('egrep "SSL alert:" %s | egrep disabled | wc
-l' % topology.standalone.errlog)
+ ecount = int(enabled.readline().rstrip())
+ dcount = int(disabled.readline().rstrip())
+
+ log.info("Enabled ciphers: %d" % ecount)
+ log.info("Disabled ciphers: %d" % dcount)
+ global plus_all_ecount
+ global plus_all_dcount
+ assert ecount == (plus_all_ecount - 1)
+ assert dcount == (plus_all_dcount + 1)
+
+def test_ticket47838_run_6(topology):
+ """
+ Check nssSSL3Chiphers: -all,+rsa_rc4_128_md5
+ All ciphers are disabled.
+ """
+ _header(topology, 'Test Case 7 - Check nssSSL3Chiphers:
-all,+rsa_rc4_128_md5')
+
+ topology.standalone.simple_bind_s(DN_DM, PASSWORD)
+ topology.standalone.modify_s(ENCRYPTION_DN, [(ldap.MOD_REPLACE,
'nsSSL3Ciphers', '-all,+rsa_rc4_128_md5')])
+
+ log.info("\n######################### Restarting the server
######################\n")
+ topology.standalone.stop(timeout=10)
+ os.system('mv %s %s.47838_5' % (topology.standalone.errlog,
topology.standalone.errlog))
+ os.system('touch %s' % (topology.standalone.errlog))
+ topology.standalone.start(timeout=120)
+
+ enabled = os.popen('egrep "SSL alert:" %s | egrep enabled | wc -l'
% topology.standalone.errlog)
+ disabled = os.popen('egrep "SSL alert:" %s | egrep disabled | wc
-l' % topology.standalone.errlog)
+ ecount = int(enabled.readline().rstrip())
+ dcount = int(disabled.readline().rstrip())
+
+ log.info("Enabled ciphers: %d" % ecount)
+ log.info("Disabled ciphers: %d" % dcount)
+ global plus_all_ecount
+ global plus_all_dcount
+ assert ecount == 1
+ assert dcount == (plus_all_ecount + plus_all_dcount - ecount)
+
+def test_ticket47838_run_7(topology):
+ """
+ Check no nsSSL3Ciphers
+ Default ciphers are enabled.
+ """
+ _header(topology, 'Test Case 8 - Check no nssSSL3Chiphers (default setting) with
no errorlog-level')
+
+ topology.standalone.simple_bind_s(DN_DM, PASSWORD)
+ topology.standalone.modify_s(ENCRYPTION_DN, [(ldap.MOD_REPLACE,
'nsSSL3Ciphers', None)])
+ topology.standalone.modify_s(CONFIG_DN, [(ldap.MOD_REPLACE,
'nsslapd-errorlog-level', None)])
+
+ log.info("\n######################### Restarting the server
######################\n")
+ topology.standalone.stop(timeout=10)
+ os.system('mv %s %s.47838_6' % (topology.standalone.errlog,
topology.standalone.errlog))
+ os.system('touch %s' % (topology.standalone.errlog))
+ topology.standalone.start(timeout=120)
+
+ enabled = os.popen('egrep "SSL alert:" %s | egrep enabled | wc -l'
% topology.standalone.errlog)
+ disabled = os.popen('egrep "SSL alert:" %s | egrep disabled | wc
-l' % topology.standalone.errlog)
+ ecount = int(enabled.readline().rstrip())
+ dcount = int(disabled.readline().rstrip())
+
+ log.info("Enabled ciphers: %d" % ecount)
+ log.info("Disabled ciphers: %d" % dcount)
+ assert ecount == 12
+ assert dcount == 0
+ weak = os.popen('egrep "SSL alert:" %s | egrep enabled | egrep
"WEAK CIPHER" | wc -l' % topology.standalone.errlog)
+ wcount = int(weak.readline().rstrip())
+ log.info("Weak ciphers in the default setting: %d" % wcount)
+ assert wcount == 0
+
+def test_ticket47838_run_8(topology):
+ """
+ Check nssSSL3Chiphers: -TLS_RSA_WITH_NULL_MD5,+TLS_RSA_WITH_RC4_128_MD5,
+ +TLS_RSA_EXPORT_WITH_RC4_40_MD5,+TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5,
+ +TLS_DHE_RSA_WITH_DES_CBC_SHA,+SSL_RSA_FIPS_WITH_DES_CBC_SHA,
+ +TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA,+SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA,
+ +TLS_RSA_EXPORT1024_WITH_RC4_56_SHA,+TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA,
+ -SSL_CK_RC4_128_WITH_MD5,-SSL_CK_RC4_128_EXPORT40_WITH_MD5,
+ -SSL_CK_RC2_128_CBC_WITH_MD5,-SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5,
+ -SSL_CK_DES_64_CBC_WITH_MD5,-SSL_CK_DES_192_EDE3_CBC_WITH_MD5
+ """
+ _header(topology, 'Test Case 9 - Check nssSSL3Chiphers: long list using the NSS
Cipher Suite name')
+
+ topology.standalone.simple_bind_s(DN_DM, PASSWORD)
+ topology.standalone.modify_s(ENCRYPTION_DN, [(ldap.MOD_REPLACE,
'nsSSL3Ciphers',
+
'-TLS_RSA_WITH_NULL_MD5,+TLS_RSA_WITH_RC4_128_MD5,+TLS_RSA_EXPORT_WITH_RC4_40_MD5,+TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5,+TLS_DHE_RSA_WITH_DES_CBC_SHA,+SSL_RSA_FIPS_WITH_DES_CBC_SHA,+TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA,+SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA,+TLS_RSA_EXPORT1024_WITH_RC4_56_SHA,+TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA,-SSL_CK_RC4_128_WITH_MD5,-SSL_CK_RC4_128_EXPORT40_WITH_MD5,-SSL_CK_RC2_128_CBC_WITH_MD5,-SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5,-SSL_CK_DES_64_CBC_WITH_MD5,-SSL_CK_DES_192_EDE3_CBC_WITH_MD5')])
+
+ log.info("\n######################### Restarting the server
######################\n")
+ topology.standalone.stop(timeout=10)
+ os.system('mv %s %s.47838_7' % (topology.standalone.errlog,
topology.standalone.errlog))
+ os.system('touch %s' % (topology.standalone.errlog))
+ topology.standalone.start(timeout=120)
+
+ enabled = os.popen('egrep "SSL alert:" %s | egrep enabled | wc -l'
% topology.standalone.errlog)
+ disabled = os.popen('egrep "SSL alert:" %s | egrep disabled | wc
-l' % topology.standalone.errlog)
+ ecount = int(enabled.readline().rstrip())
+ dcount = int(disabled.readline().rstrip())
+
+ log.info("Enabled ciphers: %d" % ecount)
+ log.info("Disabled ciphers: %d" % dcount)
+ global plus_all_ecount
+ global plus_all_dcount
+ assert ecount == 9
+ assert dcount == 0
+ weak = os.popen('egrep "SSL alert:" %s | egrep enabled | egrep
"WEAK CIPHER" | wc -l' % topology.standalone.errlog)
+ wcount = int(weak.readline().rstrip())
+ log.info("Weak ciphers in the default setting: %d" % wcount)
+
+def test_ticket47838_run_9(topology):
+ """
+ NOTE: Currently, this test case is commented out since if the server fails to start,
+ it repeatedly restarted.
+ Check nssSSL3Chiphers: all <== invalid value
+ All ciphers are disabled.
+ """
+ _header(topology, 'Test Case 10 - Check nssSSL3Chiphers: all, which is
invalid')
+
+ topology.standalone.simple_bind_s(DN_DM, PASSWORD)
+ topology.standalone.modify_s(ENCRYPTION_DN, [(ldap.MOD_REPLACE,
'nsSSL3Ciphers', 'all')])
+
+ log.info("\n######################### Restarting the server
######################\n")
+ topology.standalone.stop(timeout=10)
+ os.system('mv %s %s.47838_7' % (topology.standalone.errlog,
topology.standalone.errlog))
+ os.system('touch %s' % (topology.standalone.errlog))
+ topology.standalone.start(timeout=120)
+
+ errmsg = os.popen('egrep "SSL alert:" %s | egrep "invalid
ciphers"' % topology.standalone.errlog)
+ if errmsg != "":
+ log.info("Expected error message:")
+ log.info("%s" % errmsg)
+ else:
+ log.info("Expected error message was not found")
+ assert False
+
+ topology.standalone.log.info("ticket47838 was successfully verified.");
+
+def test_ticket47838_final(topology):
+ topology.standalone.simple_bind_s(DN_DM, PASSWORD)
+ topology.standalone.stop(timeout=10)
+
+def run_isolated():
+ '''
+ run_isolated is used to run these test cases independently of a test scheduler
(xunit, py.test..)
+ To run isolated without py.test, you need to
+ - edit this file and comment '(a)pytest.fixture' line before
'topology' function.
+ - set the installation prefix
+ - run this program
+ '''
+ global installation_prefix
+ installation_prefix = None
+
+ topo = topology(True)
+ test_ticket47838_init(topo)
+
+ test_ticket47838_run_0(topo)
+ test_ticket47838_run_1(topo)
+ test_ticket47838_run_2(topo)
+ test_ticket47838_run_3(topo)
+ test_ticket47838_run_4(topo)
+ test_ticket47838_run_5(topo)
+ test_ticket47838_run_6(topo)
+ test_ticket47838_run_7(topo)
+ test_ticket47838_run_8(topo)
+ # test_ticket47838_run_9(topo)
+
+ test_ticket47838_final(topo)
+
+if __name__ == '__main__':
+ run_isolated()
commit 13c0d2f7b7850676042fe05c917a7d498135324f
Author: Noriko Hosoi <nhosoi(a)redhat.com>
Date: Thu Aug 7 11:53:55 2014 -0700
Ticket #47838 - harden the list of ciphers available by default
Description:
Directory Server used to maintain the supported cipher suite list.
This patch abandons the table and retrieve the list dynamically
from NSS using its API SSL_GetImplementedCiphers.
We still keeps a lookup table _lookup_cipher to find out a name
defined in NSS from the old cipher name for the backward compatibility.
E.g. "rc4" --> "SSL_CK_RC4_128_WITH_MD5".
Changes on the value of nsSSL3Ciphers:
. If "+all" is included in the value of nsSSL3Ciphers, enable all
ciphers first, then disable specified ciphers starting with "-".
Otherwise (without "+all"), disable all the ciphers first, then
enable specified ciphers starting with "+".
. Introduced a keyword "default" for nsSSL3Ciphers. If the config
attribute nsSSL3Ciphers does not exist, the value is empty or the
value is "default", the default cipher set is enabled.
The enabled ciphers are logged in the error log as follows:
[..] - SSL alert: Configured NSS Ciphers
[..] - SSL alert: TLS_RSA_WITH_AES_128_GCM_SHA256: enabled
[..] - SSL alert: TLS_RSA_WITH_AES_128_CBC_SHA: enabled
If specified ciphers are weak or very weak, the cipher is logged
with (WEAK CIPHER) or (MUST BE DISABLED) as follows:
[..] - SSL alert: Configured NSS Ciphers
[..] - SSL alert: TLS_DHE_DSS_WITH_DES_CBC_SHA: disabled, (WEAK CIPHER)
[..] - SSL alert: TLS_RSA_WITH_NULL_SHA: disabled, (MUST BE DISABLED)
To log all the available ciphers, set log level to CONFIG
(SLAPI_LOG_CONFIG). Then, all the ciphers are logged.
See also
http://directory.fedoraproject.org/wiki/NSS_Ciphers
https://fedorahosted.org/389/ticket/47838
Reviewed by rmeggins(a)redhat.com (Thank you, Rich!!)
diff --git a/ldap/servers/slapd/ssl.c b/ldap/servers/slapd/ssl.c
index 8dc39d2..cf9643f 100644
--- a/ldap/servers/slapd/ssl.c
+++ b/ldap/servers/slapd/ssl.c
@@ -121,68 +121,90 @@ static char * configDN = "cn=encryption,cn=config";
/* ----------------------- Multiple cipher support ------------------------ */
+/* flags */
+#define CIPHER_IS_DEFAULT 0x1
+#define CIPHER_MUST_BE_DISABLED 0x2
+#define CIPHER_IS_WEAK 0x4
+#define CIPHER_IS_DEPRECATED 0x8
static char **cipher_names = NULL;
typedef struct {
- char *version;
char *name;
int num;
+ int flags;
} cipherstruct;
-
-static cipherstruct _conf_ciphers[] = {
- {"SSL3","rc4", SSL_EN_RC4_128_WITH_MD5},
- {"SSL3","rc4export", SSL_EN_RC4_128_EXPORT40_WITH_MD5},
- {"SSL3","rc2", SSL_EN_RC2_128_CBC_WITH_MD5},
- {"SSL3","rc2export", SSL_EN_RC2_128_CBC_EXPORT40_WITH_MD5},
- /*{"idea", SSL_EN_IDEA_128_CBC_WITH_MD5}, */
- {"SSL3","des", SSL_EN_DES_64_CBC_WITH_MD5},
- {"SSL3","desede3", SSL_EN_DES_192_EDE3_CBC_WITH_MD5},
- {"SSL3","rsa_rc4_128_md5", SSL_RSA_WITH_RC4_128_MD5},
- {"SSL3","rsa_rc4_128_sha", SSL_RSA_WITH_RC4_128_SHA},
- {"SSL3","rsa_3des_sha", SSL_RSA_WITH_3DES_EDE_CBC_SHA},
- {"SSL3","rsa_des_sha", SSL_RSA_WITH_DES_CBC_SHA},
- {"SSL3","rsa_fips_3des_sha",
SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA},
- {"SSL3","fips_3des_sha", SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA}, /*
ditto */
- {"SSL3","rsa_fips_des_sha", SSL_RSA_FIPS_WITH_DES_CBC_SHA},
- {"SSL3","fips_des_sha", SSL_RSA_FIPS_WITH_DES_CBC_SHA}, /* ditto
*/
- {"SSL3","rsa_rc4_40_md5", SSL_RSA_EXPORT_WITH_RC4_40_MD5},
- {"SSL3","rsa_rc2_40_md5", SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5},
- {"SSL3","rsa_null_md5", SSL_RSA_WITH_NULL_MD5}, /* disabled by
default */
- {"SSL3","rsa_null_sha", SSL_RSA_WITH_NULL_SHA}, /* disabled by
default */
- {"TLS","tls_rsa_export1024_with_rc4_56_sha",
TLS_RSA_EXPORT1024_WITH_RC4_56_SHA},
- {"TLS","rsa_rc4_56_sha", TLS_RSA_EXPORT1024_WITH_RC4_56_SHA}, /*
ditto */
- {"TLS","tls_rsa_export1024_with_des_cbc_sha",
TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA},
- {"TLS","rsa_des_56_sha", TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA}, /*
ditto */
- {"SSL3","fortezza", SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA}, /*
deprecated */
- {"SSL3","fortezza_rc4_128_sha",
SSL_FORTEZZA_DMS_WITH_RC4_128_SHA}, /* deprecated */
- {"SSL3","fortezza_null", SSL_FORTEZZA_DMS_WITH_NULL_SHA}, /*
deprecated */
-
- /*{"SSL3","dhe_dss_40_sha",
SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA}, */
- {"SSL3","dhe_dss_des_sha", SSL_DHE_DSS_WITH_DES_CBC_SHA},
- {"SSL3","dhe_dss_3des_sha", SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA},
- /*{"SSL3","dhe_rsa_40_sha",
SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA}, */
- {"SSL3","dhe_rsa_des_sha", SSL_DHE_RSA_WITH_DES_CBC_SHA},
- {"SSL3","dhe_rsa_3des_sha", SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA},
-
- {"TLS","tls_rsa_aes_128_sha", TLS_RSA_WITH_AES_128_CBC_SHA},
- {"TLS","rsa_aes_128_sha", TLS_RSA_WITH_AES_128_CBC_SHA}, /* ditto
*/
- {"TLS","tls_dhe_dss_aes_128_sha",
TLS_DHE_DSS_WITH_AES_128_CBC_SHA},
- {"TLS","tls_dhe_rsa_aes_128_sha",
TLS_DHE_RSA_WITH_AES_128_CBC_SHA},
-
- {"TLS","tls_rsa_aes_256_sha", TLS_RSA_WITH_AES_256_CBC_SHA},
- {"TLS","rsa_aes_256_sha", TLS_RSA_WITH_AES_256_CBC_SHA}, /* ditto
*/
- {"TLS","tls_dhe_dss_aes_256_sha",
TLS_DHE_DSS_WITH_AES_256_CBC_SHA},
- {"TLS","tls_dhe_rsa_aes_256_sha",
TLS_DHE_RSA_WITH_AES_256_CBC_SHA},
- /*{"TLS","tls_dhe_dss_1024_des_sha",
TLS_DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA}, */
- {"TLS","tls_dhe_dss_1024_rc4_sha",
TLS_RSA_EXPORT1024_WITH_RC4_56_SHA},
- {"TLS","tls_dhe_dss_rc4_128_sha", TLS_DHE_DSS_WITH_RC4_128_SHA},
+static cipherstruct *_conf_ciphers = NULL;
+static void _conf_init_ciphers();
+/*
+ * This lookup table is for supporting the old cipher name.
+ * Once swtiching to the NSS cipherSuiteName is done,
+ * this lookup_cipher table can be removed.
+ */
+typedef struct {
+ char *alias;
+ char *name;
+} lookup_cipher;
+static lookup_cipher _lookup_cipher[] = {
+ {"rc4",
"SSL_CK_RC4_128_WITH_MD5"},
+ {"rc4export",
"SSL_CK_RC4_128_EXPORT40_WITH_MD5"},
+ {"rc2",
"SSL_CK_RC2_128_CBC_WITH_MD5"},
+ {"rc2export",
"SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5"},
+ /*{"idea",
"SSL_EN_IDEA_128_CBC_WITH_MD5"}, */
+ {"des",
"SSL_CK_DES_64_CBC_WITH_MD5"},
+ {"desede3",
"SSL_CK_DES_192_EDE3_CBC_WITH_MD5"},
+ {"rsa_rc4_128_md5",
"TLS_RSA_WITH_RC4_128_MD5"},
+ {"rsa_rc4_128_sha",
"TLS_RSA_WITH_RC4_128_SHA"},
+ {"rsa_3des_sha",
"TLS_RSA_WITH_3DES_EDE_CBC_SHA"},
+ {"tls_rsa_3des_sha",
"TLS_RSA_WITH_3DES_EDE_CBC_SHA"},
+ {"rsa_fips_3des_sha",
"SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA"},
+ {"fips_3des_sha",
"SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA"},
+ {"rsa_des_sha",
"TLS_RSA_WITH_DES_CBC_SHA"},
+ {"rsa_fips_des_sha",
"SSL_RSA_FIPS_WITH_DES_CBC_SHA"},
+ {"fips_des_sha",
"SSL_RSA_FIPS_WITH_DES_CBC_SHA"}, /* ditto */
+ {"rsa_rc4_40_md5",
"TLS_RSA_EXPORT_WITH_RC4_40_MD5"},
+ {"tls_rsa_rc4_40_md5",
"TLS_RSA_EXPORT_WITH_RC4_40_MD5"},
+ {"rsa_rc2_40_md5",
"TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5"},
+ {"tls_rsa_rc2_40_md5",
"TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5"},
+ {"rsa_null_md5", "TLS_RSA_WITH_NULL_MD5"},
/* disabled by default */
+ {"rsa_null_sha", "TLS_RSA_WITH_NULL_SHA"},
/* disabled by default */
+ {"tls_rsa_export1024_with_rc4_56_sha",
"TLS_RSA_EXPORT1024_WITH_RC4_56_SHA"},
+ {"rsa_rc4_56_sha",
"TLS_RSA_EXPORT1024_WITH_RC4_56_SHA"}, /* ditto */
+ {"tls_rsa_export1024_with_des_cbc_sha",
"TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA"},
+ {"rsa_des_56_sha",
"TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA"}, /* ditto */
+ {"fortezza", ""}, /* deprecated */
+ {"fortezza_rc4_128_sha", ""}, /* deprecated */
+ {"fortezza_null", ""}, /* deprecated */
+
+ /*{"dhe_dss_40_sha", SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA, 0}, */
+ {"dhe_dss_des_sha",
"TLS_DHE_DSS_WITH_DES_CBC_SHA"},
+ {"dhe_dss_3des_sha",
"TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA"},
+ {"dhe_rsa_40_sha",
"TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA"},
+ {"dhe_rsa_des_sha",
"TLS_DHE_RSA_WITH_DES_CBC_SHA"},
+ {"dhe_rsa_3des_sha",
"TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA"},
+
+ {"tls_rsa_aes_128_sha",
"TLS_RSA_WITH_AES_128_CBC_SHA"},
+ {"rsa_aes_128_sha",
"TLS_RSA_WITH_AES_128_CBC_SHA"}, /* ditto */
+ {"tls_dh_dss_aes_128_sha", ""}, /* deprecated */
+ {"tls_dh_rsa_aes_128_sha", ""}, /* deprecated */
+ {"tls_dhe_dss_aes_128_sha",
"TLS_DHE_DSS_WITH_AES_128_CBC_SHA"},
+ {"tls_dhe_rsa_aes_128_sha",
"TLS_DHE_RSA_WITH_AES_128_CBC_SHA"},
+
+ {"tls_rsa_aes_256_sha",
"TLS_RSA_WITH_AES_256_CBC_SHA"},
+ {"rsa_aes_256_sha",
"TLS_RSA_WITH_AES_256_CBC_SHA"}, /* ditto */
+ {"tls_dss_aes_256_sha", ""}, /* deprecated */
+ {"tls_rsa_aes_256_sha", ""}, /* deprecated */
+ {"tls_dhe_dss_aes_256_sha",
"TLS_DHE_DSS_WITH_AES_256_CBC_SHA"},
+ {"tls_dhe_rsa_aes_256_sha",
"TLS_DHE_RSA_WITH_AES_256_CBC_SHA"},
+ /*{"tls_dhe_dss_1024_des_sha", ""}, */
+ {"tls_dhe_dss_1024_rc4_sha",
"TLS_RSA_EXPORT1024_WITH_RC4_56_SHA"},
+ {"tls_dhe_dss_rc4_128_sha",
"TLS_DHE_DSS_WITH_RC4_128_SHA"},
#if defined(NSS_TLS12)
/* New in NSS 3.15 */
- {"TLS","tls_rsa_aes_128_gcm_sha",
TLS_RSA_WITH_AES_128_GCM_SHA256},
- {"TLS","tls_dhe_rsa_aes_128_gcm_sha",
TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
- {"TLS","tls_dhe_dss_aes_128_gcm_sha",
TLS_DHE_DSS_WITH_AES_128_GCM_SHA256},
+ {"tls_rsa_aes_128_gcm_sha",
"TLS_RSA_WITH_AES_128_GCM_SHA256"},
+ {"tls_dhe_rsa_aes_128_gcm_sha",
"TLS_DHE_RSA_WITH_AES_128_GCM_SHA256"},
+ {"tls_dhe_dss_aes_128_gcm_sha", NULL}, /* not available */
#endif
- {NULL, NULL, 0}
+ {NULL, NULL}
};
static void
@@ -217,17 +239,24 @@ char ** getSupportedCiphers()
{
SSLCipherSuiteInfo info;
char *sep = "::";
- int number_of_ciphers = sizeof (_conf_ciphers) /sizeof(cipherstruct);
+ int number_of_ciphers = SSL_NumImplementedCiphers;
int i;
int idx = 0;
PRBool isFIPS = slapd_pk11_isFIPS();
- if (cipher_names == NULL ) {
- cipher_names = (char **) slapi_ch_calloc ((number_of_ciphers +1 ) , sizeof(char *));
+
+ _conf_init_ciphers();
+
+ if ((cipher_names == NULL) && (_conf_ciphers)) {
+ cipher_names = (char **)slapi_ch_calloc((number_of_ciphers + 1), sizeof(char *));
for (i = 0 ; _conf_ciphers[i].name != NULL; i++ ) {
SSL_GetCipherSuiteInfo((PRUint16)_conf_ciphers[i].num,&info,sizeof(info));
/* only support FIPS approved ciphers in FIPS mode */
if (!isFIPS || info.isFIPS) {
- cipher_names[idx++] =
PR_smprintf("%s%s%s%s%s%s%s%s%d",_conf_ciphers[i].version,sep,_conf_ciphers[i].name,sep,info.symCipherName,sep,info.macAlgorithmName,sep,info.symKeyBits);
+ cipher_names[idx++] = PR_smprintf("%s%s%s%s%s%s%d",
+ _conf_ciphers[i].name,sep,
+ info.symCipherName,sep,
+ info.macAlgorithmName,sep,
+ info.symKeyBits);
}
}
cipher_names[idx] = NULL;
@@ -240,7 +269,7 @@ cipher_check_fips(int idx, char ***suplist, char ***unsuplist)
{
PRBool rc = PR_TRUE;
- if (slapd_pk11_isFIPS()) {
+ if (_conf_ciphers && slapd_pk11_isFIPS()) {
SSLCipherSuiteInfo info;
if (SECFailure == SSL_GetCipherSuiteInfo((PRUint16)_conf_ciphers[idx].num,
&info, sizeof info)) {
@@ -273,24 +302,94 @@ cipher_check_fips(int idx, char ***suplist, char ***unsuplist)
return rc;
}
-void
-_conf_setallciphers(int active, char ***suplist, char ***unsuplist)
+static void
+_conf_init_ciphers()
{
int x;
+ SECStatus rc;
+ SSLCipherSuiteInfo info;
+ const PRUint16 *implementedCiphers = SSL_GetImplementedCiphers();
+
+ /* Initialize _conf_ciphers */
+ if (_conf_ciphers) {
+ return;
+ }
+ _conf_ciphers = (cipherstruct *)slapi_ch_calloc(SSL_NumImplementedCiphers + 1,
sizeof(cipherstruct));
- /* MLM - change: Because null_md5 is NOT encrypted at all, force
- * them to activate it by name. */
- for(x = 0; _conf_ciphers[x].name; x++) {
- PRBool enabled = active ? PR_TRUE : PR_FALSE;
- if(active && (!strcmp(_conf_ciphers[x].name, "rsa_null_md5")
||
- !strcmp(_conf_ciphers[x].name, "rsa_null_sha")))
- {
+ for (x = 0; implementedCiphers && (x < SSL_NumImplementedCiphers); x++) {
+ rc = SSL_GetCipherSuiteInfo(implementedCiphers[x], &info, sizeof info);
+ if (SECFailure == rc) {
+ slapi_log_error(SLAPI_LOG_FATAL, "SSL Initialization",
+ "Warning: failed to get the cipher suite info of cipher
ID %d\n",
+ implementedCiphers[x]);
continue;
}
- if (enabled) {
- enabled = cipher_check_fips(x, suplist, unsuplist);
+ if (!_conf_ciphers[x].num) { /* initialize each cipher */
+ _conf_ciphers[x].name = slapi_ch_strdup(info.cipherSuiteName);
+ _conf_ciphers[x].num = implementedCiphers[x];
+ if (info.symCipher == ssl_calg_null) {
+ _conf_ciphers[x].flags |= CIPHER_MUST_BE_DISABLED;
+ } else {
+ _conf_ciphers[x].flags |= info.isExportable?CIPHER_IS_WEAK:
+ (info.symCipher <
ssl_calg_3des)?CIPHER_IS_WEAK:
+ (info.effectiveKeyBits <
128)?CIPHER_IS_WEAK:0;
+ }
}
- SSL_CipherPrefSetDefault(_conf_ciphers[x].num, enabled);
+ }
+ return;
+}
+
+#define CIPHER_SET_ALL 1
+#define CIPHER_SET_NONE 0
+#define CIPHER_SET_DEFAULT 2
+/*
+ * flag: 1 -- enable all
+ * 0 -- disable all
+ * 2 -- set default ciphers
+ */
+static void
+_conf_setallciphers(int flag, char ***suplist, char ***unsuplist)
+{
+ int x;
+ SECStatus rc;
+ PRBool setdefault = (flag == CIPHER_SET_DEFAULT) ? PR_TRUE : PR_FALSE;
+ PRBool enabled = (flag == CIPHER_SET_ALL) ? PR_TRUE : PR_FALSE;
+ PRBool setme;
+ const PRUint16 *implementedCiphers = SSL_GetImplementedCiphers();
+ SSLCipherSuiteInfo info;
+
+ _conf_init_ciphers();
+
+ for (x = 0; implementedCiphers && (x < SSL_NumImplementedCiphers); x++) {
+ if (!(_conf_ciphers[x].flags & CIPHER_IS_DEFAULT)) {
+ /*
+ * SSL_CipherPrefGetDefault
+ * If the application has not previously set the default preference,
+ * SSL_CipherPrefGetDefault returns the factory setting.
+ */
+ rc = SSL_CipherPrefGetDefault(_conf_ciphers[x].num, &setme);
+ if (SECFailure == rc) {
+ slapi_log_error(SLAPI_LOG_FATAL, "SSL Initialization",
+ "Warning: failed to get the default state of cipher %s\n",
+ _conf_ciphers[x].name);
+ continue;
+ }
+ if (_conf_ciphers[x].flags & CIPHER_IS_WEAK) {
+ setme = PR_FALSE;
+ }
+ _conf_ciphers[x].flags |= setme?CIPHER_IS_DEFAULT:0;
+ }
+ if (setdefault) {
+ /* Use the NSS default settings */
+ } else if (enabled && !(_conf_ciphers[x].flags &
CIPHER_MUST_BE_DISABLED)) {
+ setme = PR_TRUE;
+ } else {
+ setme = PR_FALSE;
+ }
+ if (setme) {
+ setme = cipher_check_fips(x, suplist, unsuplist);
+ }
+ SSL_CipherPrefSetDefault(_conf_ciphers[x].num, setme);
}
}
@@ -309,40 +408,61 @@ charray2str(char **ary, const char *delim)
return str;
}
+void
+_conf_dumpciphers()
+{
+ int x;
+ PRBool enabled;
+ /* {"SSL3","rc4", SSL_EN_RC4_128_WITH_MD5}, */
+ slapd_SSL_warn("Configured NSS Ciphers");
+ for (x = 0; _conf_ciphers[x].name; x++) {
+ SSL_CipherPrefGetDefault(_conf_ciphers[x].num, &enabled);
+ if (enabled) {
+ slapd_SSL_warn("\t%s: enabled%s%s%s", _conf_ciphers[x].name,
+ (_conf_ciphers[x].flags&CIPHER_IS_WEAK)?", (WEAK
CIPHER)":"",
+ (_conf_ciphers[x].flags&CIPHER_IS_DEPRECATED)?",
(DEPRECATED)":"",
+ (_conf_ciphers[x].flags&CIPHER_MUST_BE_DISABLED)?",
(MUST BE DISABLED)":"");
+ } else if (slapi_is_loglevel_set(SLAPI_LOG_CONFIG)) {
+ slapd_SSL_warn("\t%s: disabled%s%s%s", _conf_ciphers[x].name,
+ (_conf_ciphers[x].flags&CIPHER_IS_WEAK)?", (WEAK
CIPHER)":"",
+ (_conf_ciphers[x].flags&CIPHER_IS_DEPRECATED)?",
(DEPRECATED)":"",
+ (_conf_ciphers[x].flags&CIPHER_MUST_BE_DISABLED)?",
(MUST BE DISABLED)":"");
+ }
+ }
+}
+
char *
_conf_setciphers(char *ciphers)
{
char *t, err[MAGNUS_ERROR_LEN];
- int x, active;
+ int x, i, active;
char *raw = ciphers;
char **suplist = NULL;
char **unsuplist = NULL;
-
- /* Default is to activate all of them */
- if(!ciphers || ciphers[0] == '\0') {
- _conf_setallciphers(1, &suplist, NULL);
- if (suplist && *suplist) {
- if (slapi_is_loglevel_set(SLAPI_LOG_CONFIG)) {
- char *str = charray2str(suplist, ",");
- slapd_SSL_warn("Security Initialization: FIPS mode is enabled - only
the following "
- "cipher suites are approved for FIPS: [%s] - "
- "all other cipher suites are disabled - if "
- "you want to use other cipher suites, you must use
modutil to "
- "disable FIPS in the internal token.",
- str ? str : "(none)");
- slapi_ch_free_string(&str);
- }
- }
- slapi_ch_free((void **)&suplist); /* strings inside are static */
+ int lookup;
+
+ /* #47838: harden the list of ciphers available by default */
+ /* Default is to activate all of them ==> none of them*/
+ if (!ciphers || (ciphers[0] == '\0') || !PL_strcasecmp(ciphers,
"default")) {
+ _conf_setallciphers(CIPHER_SET_DEFAULT, NULL, NULL);
+ slapd_SSL_warn("Security Initialization: Enabling default cipher
set.");
+ _conf_dumpciphers();
return NULL;
}
- /*
- * Enable all the ciphers by default and the following while loop would
- * disable the user disabled ones. This is needed because we added a new
- * set of ciphers in the table. Right now there is no support for this
- * from the console
- */
- _conf_setallciphers(1, &suplist, NULL);
+
+ if (PL_strcasestr(ciphers, "+all")) {
+ /*
+ * Enable all the ciphers if "+all" and the following while loop would
+ * disable the user disabled ones. This is needed because we added a new
+ * set of ciphers in the table. Right now there is no support for this
+ * from the console
+ */
+ _conf_setallciphers(CIPHER_SET_ALL, &suplist, NULL);
+ } else {
+ /* If "+all" is not in nsSSL3Ciphers value, disable all first,
+ * then enable specified ciphers. */
+ _conf_setallciphers(0 /* disabled */, NULL, NULL);
+ }
t = ciphers;
while(t) {
@@ -354,24 +474,45 @@ _conf_setciphers(char *ciphers)
case '-':
active = 0; break;
default:
- PR_snprintf(err, sizeof(err), "invalid ciphers <%s>: format is "
- "+cipher1,-cipher2...", raw);
+ PR_snprintf(err, sizeof(err), "invalid ciphers <%s>: format is
"
+ "+cipher1,-cipher2...", raw);
return slapi_ch_strdup(err);
}
if( (t = strchr(ciphers, ',')) )
*t++ = '\0';
- if(!strcasecmp(ciphers, "all"))
- _conf_setallciphers(active, NULL, NULL);
- else {
+ if(strcasecmp(ciphers, "all")) { /* if not all */
+ PRBool enabled = active ? PR_TRUE : PR_FALSE;
+ lookup = 1;
for(x = 0; _conf_ciphers[x].name; x++) {
- if(!strcasecmp(ciphers, _conf_ciphers[x].name)) {
- PRBool enabled = active ? PR_TRUE : PR_FALSE;
- if (enabled) {
- enabled = cipher_check_fips(x, NULL, &unsuplist);
- }
- SSL_CipherPrefSetDefault(_conf_ciphers[x].num, enabled);
- break;
+ if(!PL_strcasecmp(ciphers, _conf_ciphers[x].name)) {
+ if (enabled) {
+ enabled = cipher_check_fips(x, NULL, &unsuplist);
+ }
+ SSL_CipherPrefSetDefault(_conf_ciphers[x].num, enabled);
+ lookup = 0;
+ break;
+ }
+ }
+ if (lookup) { /* lookup with old cipher name and get NSS cipherSuiteName */
+ for (i = 0; _lookup_cipher[i].alias; i++) {
+ if (!PL_strcasecmp(ciphers, _lookup_cipher[i].alias)) {
+ if (!_lookup_cipher[i].name[0]) {
+ slapd_SSL_warn("Cipher suite %s is not available in NSS
%d.%d",
+ ciphers, NSS_VMAJOR, NSS_VMINOR);
+ break;
+ }
+ for (x = 0; _conf_ciphers[x].name; x++) {
+ if (!PL_strcasecmp(_lookup_cipher[i].name,
_conf_ciphers[x].name)) {
+ if (enabled) {
+ enabled = cipher_check_fips(x, NULL,
&unsuplist);
+ }
+ SSL_CipherPrefSetDefault(_conf_ciphers[x].num, enabled);
+ break;
+ }
+ }
+ break;
+ }
}
}
if(!_conf_ciphers[x].name) {
@@ -399,6 +540,8 @@ _conf_setciphers(char *ciphers)
slapi_ch_free((void **)&suplist); /* strings inside are static */
slapi_ch_free((void **)&unsuplist); /* strings inside are static */
+
+ _conf_dumpciphers();
return NULL;
}
@@ -855,7 +998,8 @@ svrcore_setup()
* on a secure port.
*/
int
-slapd_ssl_init() {
+slapd_ssl_init()
+{
PRErrorCode errorCode;
char ** family_list;
char *val = NULL;
@@ -919,7 +1063,7 @@ slapd_ssl_init() {
}
activation = slapi_entry_attr_get_charptr( entry, "nssslactivation" );
- if((!activation) || (!strcasecmp(activation, "off"))) {
+ if((!activation) || (!PL_strcasecmp(activation, "off"))) {
/* this family was turned off, goto next */
slapi_ch_free((void **) &activation);
continue;
@@ -929,8 +1073,8 @@ slapd_ssl_init() {
token = slapi_entry_attr_get_charptr( entry, "nsssltoken" );
if( token ) {
- if( !strcasecmp(token, "internal") ||
- !strcasecmp(token, "internal (software)"))
+ if( !PL_strcasecmp(token, "internal") ||
+ !PL_strcasecmp(token, "internal (software)"))
slot = slapd_pk11_getInternalKeySlot();
else
slot = slapd_pk11_findSlotByName(token);
@@ -977,7 +1121,7 @@ slapd_ssl_init() {
/* Step Three.5: Set SSL cipher preferences */
*cipher_string = 0;
- if(ciphers && (*ciphers) && strcmp(ciphers, "blank"))
+ if(ciphers && (*ciphers) && PL_strcmp(ciphers, "blank"))
PL_strncpyz(cipher_string, ciphers, sizeof(cipher_string));
slapi_ch_free((void **) &ciphers);
@@ -991,19 +1135,16 @@ slapd_ssl_init() {
}
freeConfigEntry( &entry );
-
-
+
/* Introduce a way of knowing whether slapd_ssl_init has
* already been executed. */
_security_library_initialized = 1;
-
- if ( rv != 0 )
- return rv;
-
+ if ( rv != 0 ) {
+ return rv;
+ }
return 0;
-
}
#if !defined(NSS_TLS10) /* NSS_TLS11 or newer */
@@ -1307,7 +1448,7 @@ slapd_ssl_init2(PRFileDesc **fd, int startTLS)
}
activation = slapi_entry_attr_get_charptr( e, "nssslactivation" );
- if((!activation) || (!strcasecmp(activation, "off"))) {
+ if((!activation) || (!PL_strcasecmp(activation, "off"))) {
/* this family was turned off, goto next */
slapi_ch_free((void **) &activation);
freeConfigEntry( &e );
@@ -1319,8 +1460,8 @@ slapd_ssl_init2(PRFileDesc **fd, int startTLS)
token = slapi_entry_attr_get_charptr( e, "nsssltoken" );
personality = slapi_entry_attr_get_charptr( e,
"nssslpersonalityssl" );
if( token && personality ) {
- if( !strcasecmp(token, "internal") ||
- !strcasecmp(token, "internal (software)") )
+ if( !PL_strcasecmp(token, "internal") ||
+ !PL_strcasecmp(token, "internal (software)") )
PL_strncpyz(cert_name, personality, sizeof(cert_name));
else
/* external PKCS #11 token - attach token name */
@@ -1538,9 +1679,9 @@ slapd_ssl_init2(PRFileDesc **fd, int startTLS)
if ( e != NULL ) {
val = slapi_entry_attr_get_charptr( e, "nsSSL3" );
if ( val ) {
- if ( !strcasecmp( val, "off" ) ) {
+ if ( !PL_strcasecmp( val, "off" ) ) {
enableSSL3 = PR_FALSE;
- } else if ( !strcasecmp( val, "on" ) ) {
+ } else if ( !PL_strcasecmp( val, "on" ) ) {
enableSSL3 = PR_TRUE;
} else {
enableSSL3 = slapi_entry_attr_get_bool( e, "nsSSL3" );
@@ -1557,9 +1698,9 @@ slapd_ssl_init2(PRFileDesc **fd, int startTLS)
slapi_ch_free_string( &val );
val = slapi_entry_attr_get_charptr( e, "nsTLS1" );
if ( val ) {
- if ( !strcasecmp( val, "off" ) ) {
+ if ( !PL_strcasecmp( val, "off" ) ) {
enableTLS1 = PR_FALSE;
- } else if ( !strcasecmp( val, "on" ) ) {
+ } else if ( !PL_strcasecmp( val, "on" ) ) {
enableTLS1 = PR_TRUE;
} else {
enableTLS1 = slapi_entry_attr_get_bool( e, "nsTLS1" );
@@ -1718,7 +1859,7 @@ slapd_SSL_client_auth (LDAP* ld)
}
activation = slapi_entry_attr_get_charptr( entry, "nssslactivation"
);
- if((!activation) || (!strcasecmp(activation, "off"))) {
+ if((!activation) || (!PL_strcasecmp(activation, "off"))) {
/* this family was turned off, goto next */
slapi_ch_free((void **) &activation);
freeConfigEntry( &entry );
@@ -1729,7 +1870,7 @@ slapd_SSL_client_auth (LDAP* ld)
personality = slapi_entry_attr_get_charptr( entry,
"nssslpersonalityssl" );
cipher = slapi_entry_attr_get_charptr( entry, "cn" );
- if ( cipher && !strcasecmp(cipher, "RSA" )) {
+ if ( cipher && !PL_strcasecmp(cipher, "RSA" )) {
char *ssltoken;
/* If there already is a token name, use it */
@@ -1742,8 +1883,8 @@ slapd_SSL_client_auth (LDAP* ld)
ssltoken = slapi_entry_attr_get_charptr( entry, "nsssltoken" );
if( ssltoken && personality ) {
- if( !strcasecmp(ssltoken, "internal") ||
- !strcasecmp(ssltoken, "internal (software)") ) {
+ if( !PL_strcasecmp(ssltoken, "internal") ||
+ !PL_strcasecmp(ssltoken, "internal (software)") ) {
/* Translate config internal name to more
* readable form. Certificate name is just