From 2c550346512bc3dec27c9329f4902663759e4b65 Mon Sep 17 00:00:00 2001 From: Noriko Hosoi Date: Thu, 11 Sep 2014 11:46:51 -0700 Subject: [PATCH 4/7] Ticket #47838 - harden the list of ciphers available by default Description: 1. Introducing a new attribute allowWeakCipher in "cn=encryption,cn=config". allowWeakCipher: [on | off] on -- allows weak ciphers. Default setting for user specified ciphers. off -- rejects weak ciphers. Default setting for +all and default. 2. allowWeakCipher is applied only to the user specified cipher suites such as "nsSSL3Ciphers: +rsa_rc4_128_md5". If allowWeakCipher is enabled and the user specified cipher is weak, SSL alert is logged in the error log: SSL alert: Cipher rsa_rc4_128_md5 is weak. It is enabled since allowWeakCipher is "on" (default setting for the backward compatibility). We strongly recommend to set it to "off". Please replace the value of allowWeakCipher with "off" in the encryption config entry cn=encryption, cn=config and restart the server. 3. If specified cipher suite is not supported, ignore the cipher suite and continue setting ciphers. https://fedorahosted.org/389/ticket/47838 Reviewed by rmeggins@redhat.com (Thank you, Rich!!) (cherry picked from commit 5f3c87e1380e56d76d4a4bef3af07633a8589891) (cherry picked from commit 58cb12a7b8cf938c5a4b920c4a1ad1da02fecdb8) --- ldap/schema/01core389.ldif | 3 +- ldap/servers/slapd/ssl.c | 262 +++++++++++++++++++++++++++------------------ 2 files changed, 162 insertions(+), 103 deletions(-) diff --git a/ldap/schema/01core389.ldif b/ldap/schema/01core389.ldif index 1b8a70b..c7aec70 100644 --- a/ldap/schema/01core389.ldif +++ b/ldap/schema/01core389.ldif @@ -128,6 +128,7 @@ attributeTypes: ( nsSSL3SessionTimeout-oid NAME 'nsSSL3SessionTimeout' DESC 'Net attributeTypes: ( nsSSL2Ciphers-oid NAME 'nsSSL2Ciphers' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'Netscape' ) attributeTypes: ( nsSSL3Ciphers-oid NAME 'nsSSL3Ciphers' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'Netscape' ) attributeTypes: ( nsSSLSupportedCiphers-oid NAME 'nsSSLSupportedCiphers' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'Netscape' ) +attributeTypes: ( allowWeakCipher-oid NAME 'allowWeakCipher' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'Netscape' ) attributeTypes: ( nsSSLToken-oid NAME 'nsSSLToken' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'Netscape' ) 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' ) @@ -316,7 +317,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 $ sslVersionMin $ sslVersionMax $ nsSSLSessionTimeout $ nsSSL3SessionTimeout $ nsSSLClientAuth $ nsSSL2Ciphers $ nsSSL3Ciphers $ nsSSLSupportedCiphers) X-ORIGIN 'Netscape' ) +objectClasses: ( nsEncryptionConfig-oid NAME 'nsEncryptionConfig' DESC 'Netscape defined objectclass' SUP top MUST ( cn ) MAY ( nsCertfile $ nsKeyfile $ nsSSL2 $ nsSSL3 $ nsTLS1 $ sslVersionMin $ sslVersionMax $ nsSSLSessionTimeout $ nsSSL3SessionTimeout $ nsSSLClientAuth $ nsSSL2Ciphers $ nsSSL3Ciphers $ nsSSLSupportedCiphers $ allowWeakCipher) X-ORIGIN 'Netscape' ) objectClasses: ( nsEncryptionModule-oid NAME 'nsEncryptionModule' DESC 'Netscape defined objectclass' SUP top MUST ( cn ) MAY ( nsSSLToken $ nsSSLPersonalityssl $ nsSSLActivation ) 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 1a21df0..03b5904 100644 --- a/ldap/servers/slapd/ssl.c +++ b/ldap/servers/slapd/ssl.c @@ -119,7 +119,21 @@ static char * configDN = "cn=encryption,cn=config"; #define FILE_PATHSEP '/' /* ----------------------- Multiple cipher support ------------------------ */ - +/* cipher set flags */ +#define CIPHER_SET_ALL 0x1 +#define CIPHER_SET_NONE 0x0 +#define CIPHER_SET_DEFAULT 0x2 +#define CIPHER_SET_CORE (CIPHER_SET_ALL|CIPHER_SET_DEFAULT|CIPHER_SET_NONE) +#define CIPHER_SET_ALLOWWEAKCIPHER 0x10 /* can be or'ed with other CIPHER_SET flags */ + +#define CIPHER_SET_ISDEFAULT(flag) \ + ((((flag)&CIPHER_SET_CORE) == CIPHER_SET_DEFAULT) ? PR_TRUE : PR_FALSE) +#define CIPHER_SET_ISALL(flag) \ + ((((flag)&CIPHER_SET_CORE) == CIPHER_SET_ALL) ? PR_TRUE : PR_FALSE) +#define CIPHER_SET_ALLOWSWEAKCIPHER(flag) \ + (((flag)&CIPHER_SET_ALLOWWEAKCIPHER) ? PR_TRUE : PR_FALSE) +#define CIPHER_SET_DISABLE_ALLOWSWEAKCIPHER(flag) \ + ((flag)&~CIPHER_SET_ALLOWWEAKCIPHER) /* flags */ #define CIPHER_IS_DEFAULT 0x1 @@ -158,7 +172,7 @@ static lookup_cipher _lookup_cipher[] = { {"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_des_sha", "SSL_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"}, @@ -339,21 +353,20 @@ _conf_init_ciphers() 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 + * flag: CIPHER_SET_ALL -- enable all + * CIPHER_SET_NONE -- disable all + * CIPHER_SET_DEFAULT -- set default ciphers + * CIPHER_SET_ALLOW_WEAKCIPHER -- allow weak ciphers (can be or'ed with the ather CIPHER_SET flags) */ 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 setdefault = CIPHER_SET_ISDEFAULT(flag); + PRBool enabled = CIPHER_SET_ISALL(flag); + PRBool allowweakcipher = CIPHER_SET_ALLOWSWEAKCIPHER(flag); PRBool setme = PR_FALSE; const PRUint16 *implementedCiphers = SSL_GetImplementedCiphers(); @@ -361,8 +374,9 @@ _conf_setallciphers(int flag, char ***suplist, char ***unsuplist) for (x = 0; implementedCiphers && (x < SSL_NumImplementedCiphers); x++) { if (_conf_ciphers[x].flags & CIPHER_IS_DEFAULT) { + /* certainly, not the first time. */ setme = PR_TRUE; - } else { + } else if (setdefault) { /* * SSL_CipherPrefGetDefault * If the application has not previously set the default preference, @@ -375,15 +389,16 @@ _conf_setallciphers(int flag, char ***suplist, char ***unsuplist) _conf_ciphers[x].name); continue; } - if (_conf_ciphers[x].flags & CIPHER_IS_WEAK) { + if (!allowweakcipher && (_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; + if (!allowweakcipher && (_conf_ciphers[x].flags & CIPHER_IS_WEAK)) { + setme = PR_FALSE; + } else { + setme = PR_TRUE; + } } else { setme = PR_FALSE; } @@ -433,7 +448,7 @@ _conf_dumpciphers() } char * -_conf_setciphers(char *ciphers) +_conf_setciphers(char *ciphers, int flags) { char *t, err[MAGNUS_ERROR_LEN]; int x, i, active; @@ -445,7 +460,7 @@ _conf_setciphers(char *ciphers) /* #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); + _conf_setallciphers((CIPHER_SET_DEFAULT|CIPHER_SET_DISABLE_ALLOWSWEAKCIPHER(flags)), NULL, NULL); slapd_SSL_warn("Security Initialization: Enabling default cipher set."); _conf_dumpciphers(); return NULL; @@ -458,11 +473,11 @@ _conf_setciphers(char *ciphers) * set of ciphers in the table. Right now there is no support for this * from the console */ - _conf_setallciphers(CIPHER_SET_ALL, &suplist, NULL); + _conf_setallciphers(CIPHER_SET_ALL|CIPHER_SET_DISABLE_ALLOWSWEAKCIPHER(flags), &suplist, NULL); } else { /* If "+all" is not in nsSSL3Ciphers value, disable all first, * then enable specified ciphers. */ - _conf_setallciphers(0 /* disabled */, NULL, NULL); + _conf_setallciphers(CIPHER_SET_NONE /* disabled */, NULL, NULL); } t = ciphers; @@ -482,12 +497,28 @@ _conf_setciphers(char *ciphers) if( (t = strchr(ciphers, ',')) ) *t++ = '\0'; - if(strcasecmp(ciphers, "all")) { /* if not all */ + 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(!PL_strcasecmp(ciphers, _conf_ciphers[x].name)) { + for (x = 0; _conf_ciphers[x].name; x++) { + if (!PL_strcasecmp(ciphers, _conf_ciphers[x].name)) { + if (_conf_ciphers[x].flags & CIPHER_IS_WEAK) { + if (CIPHER_SET_ALLOWSWEAKCIPHER(flags)) { + slapd_SSL_warn("Cipher %s is weak. It is enabled since allowWeakCipher is \"on\" " + "(default setting for the backward compatibility). " + "We strongly recommend to set it to \"off\". " + "Please replace the value of allowWeakCipher with \"off\" in " + "the encryption config entry cn=encryption,cn=config and " + "restart the server.", ciphers); + } else { + /* if the cipher is weak and we don't allow weak cipher, + disable it. */ + enabled = PR_FALSE; + } + } if (enabled) { + /* if the cipher is not weak or we allow weak cipher, + check fips. */ enabled = cipher_check_fips(x, NULL, &unsuplist); } SSL_CipherPrefSetDefault(_conf_ciphers[x].num, enabled); @@ -499,14 +530,33 @@ _conf_setciphers(char *ciphers) 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; + slapd_SSL_warn("Cipher suite %s is not available in NSS %d.%d. Ignoring %s", + ciphers, NSS_VMAJOR, NSS_VMINOR, ciphers); + continue; } 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); + if (_conf_ciphers[x].flags & CIPHER_IS_WEAK) { + if (CIPHER_SET_ALLOWSWEAKCIPHER(flags)) { + slapd_SSL_warn("Cipher %s is weak. " + "It is enabled since allowWeakCipher is \"on\" " + "(default setting for the backward compatibility). " + "We strongly recommend to set it to \"off\". " + "Please replace the value of allowWeakCipher with \"off\" in " + "the encryption config entry cn=encryption,cn=config and " + "restart the server.", ciphers); + } else { + /* if the cipher is weak and we don't allow weak cipher, + disable it. */ + enabled = PR_FALSE; + } + } + if (enabled) { + /* if the cipher is not weak or we allow weak cipher, + check fips. */ + enabled = cipher_check_fips(x, NULL, &unsuplist); + } } SSL_CipherPrefSetDefault(_conf_ciphers[x].num, enabled); break; @@ -1008,6 +1058,7 @@ slapd_ssl_init() int rv = 0; PK11SlotInfo *slot; Slapi_Entry *entry = NULL; + int allowweakcipher = CIPHER_SET_ALLOWWEAKCIPHER; /* Get general information */ @@ -1017,21 +1068,21 @@ slapd_ssl_init() ciphers = slapi_entry_attr_get_charptr( entry, "nsssl3ciphers" ); /* We are currently using the value of sslSessionTimeout - for ssl3SessionTimeout, see SSL_ConfigServerSessionIDCache() */ + for ssl3SessionTimeout, see SSL_ConfigServerSessionIDCache() */ /* Note from Tom Weinstein on the meaning of the timeout: Timeouts are in seconds. '0' means use the default, which is - 24hrs for SSL3 and 100 seconds for SSL2. + 24hrs for SSL3 and 100 seconds for SSL2. */ if(!val) { errorCode = PR_GetError(); slapd_SSL_warn("Security Initialization: Failed to retrieve SSL " "configuration information (" - SLAPI_COMPONENT_NAME_NSPR " error %d - %s): " - "nssslSessionTimeout: %s ", - errorCode, slapd_pr_strerror(errorCode), - (val ? "found" : "not found")); + SLAPI_COMPONENT_NAME_NSPR " error %d - %s): " + "nssslSessionTimeout: %s ", + errorCode, slapd_pr_strerror(errorCode), + (val ? "found" : "not found")); slapi_ch_free((void **) &val); slapi_ch_free((void **) &ciphers); freeConfigEntry( &entry ); @@ -1042,79 +1093,86 @@ slapd_ssl_init() slapi_ch_free((void **) &val); if (svrcore_setup()) { - freeConfigEntry( &entry ); - return -1; + freeConfigEntry( &entry ); + return -1; } - if((family_list = getChildren(configDN))) { - char **family; - char *token; - char *activation; + val = slapi_entry_attr_get_charptr(entry, "allowWeakCipher"); + if (val && (!PL_strcasecmp(val, "off") || !PL_strcasecmp(val, "false") || + !PL_strcmp(val, "0") || !PL_strcasecmp(val, "no"))) { + allowweakcipher = 0; + } + slapi_ch_free((void **) &val); + + if ((family_list = getChildren(configDN))) { + char **family; + char *token; + char *activation; - for (family = family_list; *family; family++) { + for (family = family_list; *family; family++) { - token = NULL; - activation = NULL; + token = NULL; + activation = NULL; - freeConfigEntry( &entry ); + freeConfigEntry( &entry ); - getConfigEntry( *family, &entry ); - if ( entry == NULL ) { - continue; - } + getConfigEntry( *family, &entry ); + if ( entry == NULL ) { + continue; + } - activation = slapi_entry_attr_get_charptr( entry, "nssslactivation" ); - if((!activation) || (!PL_strcasecmp(activation, "off"))) { - /* this family was turned off, goto next */ - slapi_ch_free((void **) &activation); - continue; - } + activation = slapi_entry_attr_get_charptr( entry, "nssslactivation" ); + if((!activation) || (!PL_strcasecmp(activation, "off"))) { + /* this family was turned off, goto next */ + slapi_ch_free((void **) &activation); + continue; + } - slapi_ch_free((void **) &activation); - - token = slapi_entry_attr_get_charptr( entry, "nsssltoken" ); - if( token ) { - if( !PL_strcasecmp(token, "internal") || - !PL_strcasecmp(token, "internal (software)")) - slot = slapd_pk11_getInternalKeySlot(); - else - slot = slapd_pk11_findSlotByName(token); - } else { - errorCode = PR_GetError(); - slapd_SSL_warn("Security Initialization: Unable to get token (" - SLAPI_COMPONENT_NAME_NSPR " error %d - %s)", - errorCode, slapd_pr_strerror(errorCode)); - freeChildren(family_list); - freeConfigEntry( &entry ); - return -1; - } + slapi_ch_free((void **) &activation); - slapi_ch_free((void **) &token); + token = slapi_entry_attr_get_charptr( entry, "nsssltoken" ); + if ( token ) { + if (!PL_strcasecmp(token, "internal") || + !PL_strcasecmp(token, "internal (software)")) { + slot = slapd_pk11_getInternalKeySlot(); + } else { + slot = slapd_pk11_findSlotByName(token); + } + } else { + errorCode = PR_GetError(); + slapd_SSL_warn("Security Initialization: Unable to get token (" + SLAPI_COMPONENT_NAME_NSPR " error %d - %s)", + errorCode, slapd_pr_strerror(errorCode)); + freeChildren(family_list); + freeConfigEntry( &entry ); + return -1; + } - if (!slot) { - errorCode = PR_GetError(); - slapd_SSL_warn("Security Initialization: Unable to find slot (" - SLAPI_COMPONENT_NAME_NSPR " error %d - %s)", - errorCode, slapd_pr_strerror(errorCode)); - freeChildren(family_list); - freeConfigEntry( &entry ); - return -1; - } - /* authenticate */ - if(slapd_pk11_authenticate(slot, PR_TRUE, NULL) != SECSuccess) - { - errorCode = PR_GetError(); - slapd_SSL_warn("Security Initialization: Unable to authenticate (" - SLAPI_COMPONENT_NAME_NSPR " error %d - %s)", - errorCode, slapd_pr_strerror(errorCode)); - freeChildren(family_list); - freeConfigEntry( &entry ); - return -1; - } - } - freeChildren( family_list ); + slapi_ch_free((void **) &token); + + if (!slot) { + errorCode = PR_GetError(); + slapd_SSL_warn("Security Initialization: Unable to find slot (" + SLAPI_COMPONENT_NAME_NSPR " error %d - %s)", + errorCode, slapd_pr_strerror(errorCode)); + freeChildren(family_list); + freeConfigEntry( &entry ); + return -1; + } + /* authenticate */ + if (slapd_pk11_authenticate(slot, PR_TRUE, NULL) != SECSuccess) { + errorCode = PR_GetError(); + slapd_SSL_warn("Security Initialization: Unable to authenticate (" + SLAPI_COMPONENT_NAME_NSPR " error %d - %s)", + errorCode, slapd_pr_strerror(errorCode)); + freeChildren(family_list); + freeConfigEntry( &entry ); + return -1; + } + } + freeChildren( family_list ); + freeConfigEntry( &entry ); } - freeConfigEntry( &entry ); /* ugaston- Cipher preferences must be set before any sslSocket is created * for such sockets to take preferences into account. @@ -1126,13 +1184,13 @@ slapd_ssl_init() PL_strncpyz(cipher_string, ciphers, sizeof(cipher_string)); slapi_ch_free((void **) &ciphers); - if( NULL != (val = _conf_setciphers(cipher_string)) ) { - errorCode = PR_GetError(); - slapd_SSL_warn("Security Initialization: Failed to set SSL cipher " - "preference information: %s (" SLAPI_COMPONENT_NAME_NSPR " error %d - %s)", - val, errorCode, slapd_pr_strerror(errorCode)); - rv = 3; - slapi_ch_free((void **) &val); + if ( NULL != (val = _conf_setciphers(cipher_string, allowweakcipher)) ) { + errorCode = PR_GetError(); + slapd_SSL_warn("Security Initialization: Failed to set SSL cipher " + "preference information: %s (" SLAPI_COMPONENT_NAME_NSPR " error %d - %s)", + val, errorCode, slapd_pr_strerror(errorCode)); + rv = 3; + slapi_ch_free((void **) &val); } freeConfigEntry( &entry ); -- 1.9.3