This is an automated email from the git hooks/post-receive script.
firstyear pushed a commit to branch master
in repository 389-ds-base.
commit 7c9c39e2ddd3442acdf0b18da1152ca22bf647c6
Author: Howard Johnson <merlin(a)merlinthp.org>
Date: Thu Jun 29 19:49:53 2017 +0100
Ticket 49303 - Add option to disable TLS client-initiated renegotiation
Bug Description: TLS renegotiation is a CPU-intensive process, which a
malicious client could use to consume server resources and perform a
denial of service attack. NSS defaults to allowing client-initiated
renegotiation, but has an option to disable it. It would be useful to
expose this as a DS configuration option.
Fix Description: Added a new 'nsTLSAllowClientRenegotiation' attribute
to the cn=encryption,cn=config object. This takes two values 'yes', and
'no'. If the value is 'no', renegotiation is disabled. If the value
is
'yes', is not set, or is set to an invalid value, renegotiation is
enabled.
https://pagure.io/389-ds-base/issue/49303
Author: Howard Johnson <merlin(a)merlinthp.org>
Review by: wibrown (Thanks!)
---
dirsrvtests/tests/tickets/ticket49303_test.py | 103 ++++++++++++++++++++++++++
ldap/schema/01core389.ldif | 3 +-
ldap/servers/slapd/ssl.c | 30 ++++++++
3 files changed, 135 insertions(+), 1 deletion(-)
diff --git a/dirsrvtests/tests/tickets/ticket49303_test.py
b/dirsrvtests/tests/tickets/ticket49303_test.py
new file mode 100644
index 0000000..d0a760d
--- /dev/null
+++ b/dirsrvtests/tests/tickets/ticket49303_test.py
@@ -0,0 +1,103 @@
+import time
+import logging
+import os
+import subprocess
+import pytest
+from lib389.topologies import topology_st as topo
+
+from lib389._constants import SECUREPORT_STANDALONE1, HOST_STANDALONE1
+
+DEBUGGING = os.getenv("DEBUGGING", default=False)
+if DEBUGGING:
+ logging.getLogger(__name__).setLevel(logging.DEBUG)
+else:
+ logging.getLogger(__name__).setLevel(logging.INFO)
+log = logging.getLogger(__name__)
+
+
+def try_reneg(host, port):
+ """
+ Connect to the specified host and port with openssl, and attempt to
+ initiate a renegotiation. Returns true if successful, false if not.
+ """
+
+ cmd = [
+ '/usr/bin/openssl',
+ 's_client',
+ '-connect',
+ '%s:%d' % (host, port),
+ ]
+
+ try:
+ proc = subprocess.Popen(cmd, stdout=subprocess.PIPE,
+ stdin=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+ except ValueError, e:
+ log.info("openssl failed: %s", e)
+ proc.kill()
+
+ # This 'R' command is intercepted by openssl and triggers a renegotiation
+ proc.communicate('R\n')
+
+ # We rely on openssl returning 0 if no errors occured, and 1 if any did
+ # (for example, the server rejecting renegotiation and terminating the
+ # connection)
+ return proc.returncode == 0
+
+
+def enable_ssl(server, ldapsport):
+ server.stop()
+ server.nss_ssl.reinit()
+ server.nss_ssl.create_rsa_ca()
+ server.nss_ssl.create_rsa_key_and_cert()
+ server.start()
+ server.rsa.create()
+ server.config.set('nsslapd-secureport', '%s' % ldapsport)
+ server.config.set('nsslapd-security', 'on')
+
+ time.sleep(1)
+ server.restart()
+
+
+def set_reneg(server, state):
+ server.encryption.set('nsTLSAllowClientRenegotiation', state)
+ time.sleep(1)
+ server.restart()
+
+
+def test_ticket49303(topo):
+ """
+ Test the nsTLSAllowClientRenegotiation setting.
+ """
+ sslport = SECUREPORT_STANDALONE1
+
+ log.info("Ticket 49303 - Allow disabling of SSL renegotiation")
+
+ # No value set, defaults to reneg allowed
+ enable_ssl(topo.standalone, sslport)
+ assert try_reneg(HOST_STANDALONE1, sslport) is True
+ log.info("Renegotiation allowed by default - OK")
+
+ # Turn reneg off
+ set_reneg(topo.standalone, 'off')
+ assert try_reneg(HOST_STANDALONE1, sslport) is False
+ log.info("Renegotiation disallowed - OK")
+
+ # Explicitly enable
+ set_reneg(topo.standalone, 'on')
+ assert try_reneg(HOST_STANDALONE1, sslport) is True
+ log.info("Renegotiation explicitly allowed - OK")
+
+ # Set to an invalid value, defaults to allowed
+ set_reneg(topo.standalone, 'invalid')
+ assert try_reneg(HOST_STANDALONE1, sslport) is True
+ log.info("Renegotiation allowed when option is invalid - OK")
+
+ log.info("Ticket 49303 - PASSED")
+
+
+if __name__ == '__main__':
+ # Run isolated
+ # -s for DEBUG mode
+ CURRENT_FILE = os.path.realpath(__file__)
+ pytest.main("-s %s" % CURRENT_FILE)
diff --git a/ldap/schema/01core389.ldif b/ldap/schema/01core389.ldif
index 5e5f69f..836b953 100644
--- a/ldap/schema/01core389.ldif
+++ b/ldap/schema/01core389.ldif
@@ -107,6 +107,7 @@ attributeTypes: ( nsSSLToken-oid NAME 'nsSSLToken' DESC
'Netscape defined attrib
attributeTypes: ( nsSSLPersonalitySSL-oid NAME 'nsSSLPersonalitySSL' DESC
'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN
'Netscape' )
attributeTypes: ( nsSSLActivation-oid NAME 'nsSSLActivation' DESC 'Netscape
defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN
'Netscape' )
attributeTypes: ( CACertExtractFile-oid NAME 'CACertExtractFile' DESC
'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN
'Netscape' )
+attributeTypes: ( nsTLSAllowClientRenegotiation-oid NAME
'nsTLSAllowClientRenegotiation' DESC 'Allow clients to renegotiate open TLS
connections using RFC 5746 secure renegotiation' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
X-ORIGIN 'Netscape' )
attributeTypes: ( ServerKeyExtractFile-oid NAME 'ServerKeyExtractFile' DESC
'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN
'Netscape' )
attributeTypes: ( ServerCertExtractFile-oid NAME 'ServerCertExtractFile' DESC
'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN
'Netscape' )
attributeTypes: ( 2.16.840.1.113730.3.1.2091 NAME 'nsslapd-suffix' DESC
'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 X-ORIGIN
'Netscape' )
@@ -317,7 +318,7 @@ objectClasses: ( 2.16.840.1.113730.3.2.103 NAME
'nsDS5ReplicationAgreement' DESC
objectClasses: ( 2.16.840.1.113730.3.2.39 NAME 'nsslapdConfig' DESC 'Netscape
defined objectclass' SUP top MAY ( cn ) X-ORIGIN 'Netscape Directory Server'
)
objectClasses: ( 2.16.840.1.113730.3.2.317 NAME 'nsSaslMapping' DESC
'Netscape defined objectclass' SUP top MUST ( cn $ nsSaslMapRegexString $
nsSaslMapBaseDNTemplate $ nsSaslMapFilterTemplate ) MAY ( nsSaslMapPriority ) X-ORIGIN
'Netscape Directory Server' )
objectClasses: ( 2.16.840.1.113730.3.2.43 NAME 'nsSNMP' DESC 'Netscape
defined objectclass' SUP top MUST ( cn $ nsSNMPEnabled ) MAY ( nsSNMPOrganization $
nsSNMPLocation $ nsSNMPContact $ nsSNMPDescription $ nsSNMPName $ nsSNMPMasterHost $
nsSNMPMasterPort ) X-ORIGIN 'Netscape Directory Server' )
-objectClasses: ( nsEncryptionConfig-oid NAME 'nsEncryptionConfig' DESC
'Netscape defined objectclass' SUP top MUST ( cn ) MAY ( nsCertfile $ nsKeyfile $
nsSSL2 $ nsSSL3 $ nsTLS1 $ nsTLS10 $ nsTLS11 $ nsTLS12 $ sslVersionMin $ sslVersionMax $
nsSSLSessionTimeout $ nsSSL3SessionTimeout $ nsSSLClientAuth $ nsSSL2Ciphers $
nsSSL3Ciphers $ nsSSLSupportedCiphers $ allowWeakCipher $ CACertExtractFile $
allowWeakDHParam ) X-ORIGIN 'Netscape' )
+objectClasses: ( nsEncryptionConfig-oid NAME 'nsEncryptionConfig' DESC
'Netscape defined objectclass' SUP top MUST ( cn ) MAY ( nsCertfile $ nsKeyfile $
nsSSL2 $ nsSSL3 $ nsTLS1 $ nsTLS10 $ nsTLS11 $ nsTLS12 $ sslVersionMin $ sslVersionMax $
nsSSLSessionTimeout $ nsSSL3SessionTimeout $ nsSSLClientAuth $ nsSSL2Ciphers $
nsSSL3Ciphers $ nsSSLSupportedCiphers $ allowWeakCipher $ CACertExtractFile $
allowWeakDHParam $ nsTLSAllowClientRenegotiation ) X-ORIGIN 'Netscape' )
objectClasses: ( nsEncryptionModule-oid NAME 'nsEncryptionModule' DESC
'Netscape defined objectclass' SUP top MUST ( cn ) MAY ( nsSSLToken $
nsSSLPersonalityssl $ nsSSLActivation $ ServerKeyExtractFile $ ServerCertExtractFile )
X-ORIGIN 'Netscape' )
objectClasses: ( 2.16.840.1.113730.3.2.327 NAME 'rootDNPluginConfig' DESC
'Netscape defined objectclass' SUP top MUST ( cn ) MAY ( rootdn-open-time $
rootdn-close-time $ rootdn-days-allowed $ rootdn-allow-host $ rootdn-deny-host $
rootdn-allow-ip $ rootdn-deny-ip ) X-ORIGIN 'Netscape' )
objectClasses: ( 2.16.840.1.113730.3.2.328 NAME 'nsSchemaPolicy' DESC
'Netscape defined objectclass' SUP top MAY ( cn $ schemaUpdateObjectclassAccept $
schemaUpdateObjectclassReject $ schemaUpdateAttributeAccept $ schemaUpdateAttributeReject)
X-ORIGIN 'Netscape Directory Server' )
diff --git a/ldap/servers/slapd/ssl.c b/ldap/servers/slapd/ssl.c
index 01b708d..67e4a65 100644
--- a/ldap/servers/slapd/ssl.c
+++ b/ldap/servers/slapd/ssl.c
@@ -1753,6 +1753,7 @@ slapd_ssl_init2(PRFileDesc **fd, int startTLS)
#endif
char cipher_string[1024];
int allowweakcipher = CIPHER_SET_DEFAULTWEAKCIPHER;
+ int_fast16_t renegotiation = (int_fast16_t) SSL_RENEGOTIATE_REQUIRES_XTN;
/* turn off the PKCS11 pin interactive mode */
/* wibrown 2016 */
@@ -2218,6 +2219,35 @@ slapd_ssl_init2(PRFileDesc **fd, int startTLS)
#if !defined(NSS_TLS10) /* NSS_TLS11 or newer */
}
#endif
+
+ val = NULL;
+ if (e != NULL) {
+ val = slapi_entry_attr_get_charptr(e,
"nsTLSAllowClientRenegotiation");
+ }
+ if( val ) {
+ /* We default to allowing reneg. If the option is "no",
+ * disable reneg. Else if the option isn't "yes", complain
+ * and do the default (allow reneg). */
+ if (PL_strcasecmp(val, "off") == 0) {
+ renegotiation = SSL_RENEGOTIATE_NEVER;
+ } else if (PL_strcasecmp(val, "on") == 0) {
+ renegotiation = SSL_RENEGOTIATE_REQUIRES_XTN;
+ } else {
+ slapd_SSL_warn("The value of nsTLSAllowClientRenegotiation is invalid
(should be 'on' or 'off'). Using default 'on'.");
+ renegotiation = SSL_RENEGOTIATE_REQUIRES_XTN;
+ }
+ }
+ slapi_ch_free_string(&val);
+
+ sslStatus = SSL_OptionSet(pr_sock, SSL_ENABLE_RENEGOTIATION, (PRBool)
renegotiation);
+ if (sslStatus != SECSuccess) {
+ errorCode = PR_GetError();
+ slapd_SSL_error("Failed to set SSL renegotiation on the imported "
+ "socket (" SLAPI_COMPONENT_NAME_NSPR " error %d - %s)",
+ errorCode, slapd_pr_strerror(errorCode));
+ return -1;
+ }
+
freeConfigEntry( &e );
if(( slapd_SSLclientAuth = config_get_SSLclientAuth()) != SLAPD_SSLCLIENTAUTH_OFF )
{
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.