ldap/servers/slapd/ssl.c | 178 ++++++++++++++++++++++++++++++++++++-----------
1 file changed, 139 insertions(+), 39 deletions(-)
New commits:
commit f290f80e90c116ab5c04171f6a833aa4fdee98e6
Author: Rich Megginson <rmeggins(a)redhat.com>
Date: Wed Jun 8 12:10:56 2011 -0600
Bug 707384 - only allow FIPS approved cipher suites in FIPS mode
https://bugzilla.redhat.com/show_bug.cgi?id=707384
Resolves: bug 707384
Bug Description: only allow FIPS approved cipher suites in FIPS mode
Reviewed by: nhosoi (Thanks!)
Branch: master
Fix Description: These changes only affect the server if FIPS mode has been
set in the internal security module, that is, if
modutil -dbdir /etc/dirsrv/slapd-myhost -chkfips true
returns
FIPS mode enabled.
1) If cn=encryption,cn=config nsSSL3Ciphers is missing or set to "+all",
the server will silently use only FIPS approved cipher suites.
2) If cn=encryption,cn=config nsSSL3Ciphers has a list of ciphers, and at
least one non-FIPS approved cipher suites is enabled, the server will log
to the errors log the list of unapproved cipher suites specified, and will
restrict the server to only the FIPS approved ciphers specified in the list.
3) The attribute nsSSLSupportedCiphers in cn=encryption,cn=config will list
only FIPS approved ciphers
4) If the CONFIG log level (64) is set, more detailed information will be
logged to the errors log about cipher config processing
Platforms tested: RHEL6 x86_64
Flag Day: no
Doc impact: no
diff --git a/ldap/servers/slapd/ssl.c b/ldap/servers/slapd/ssl.c
index 809a320..b0a3f43 100644
--- a/ldap/servers/slapd/ssl.c
+++ b/ldap/servers/slapd/ssl.c
@@ -168,35 +168,126 @@ static cipherstruct _conf_ciphers[] = {
{NULL, NULL, 0}
};
+static void
+slapd_SSL_report(int degree, char *fmt, va_list args)
+{
+ char buf[2048];
+ PR_vsnprintf( buf, sizeof(buf), fmt, args );
+ LDAPDebug( LDAP_DEBUG_ANY, "SSL %s: %s\n",
+ (degree == LOG_FAILURE) ? "failure" : "alert",
+ buf, 0 );
+}
+
+void
+slapd_SSL_error(char *fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ slapd_SSL_report(LOG_FAILURE, fmt, args);
+ va_end(args);
+}
+
+void
+slapd_SSL_warn(char *fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ slapd_SSL_report(LOG_WARN, fmt, args);
+ va_end(args);
+}
+
char ** getSupportedCiphers()
{
SSLCipherSuiteInfo info;
char *sep = "::";
int number_of_ciphers = sizeof (_conf_ciphers) /sizeof(cipherstruct);
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 *));
for (i = 0 ; _conf_ciphers[i].name != NULL; i++ ) {
SSL_GetCipherSuiteInfo((PRUint16)_conf_ciphers[i].num,&info,sizeof(info));
- cipher_names[i] =
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);
+ /* 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[i] = NULL;
+ cipher_names[idx] = NULL;
}
return cipher_names;
}
+
+static PRBool
+cipher_check_fips(int idx, char ***suplist, char ***unsuplist)
+{
+ PRBool rc = PR_TRUE;
+
+ if (slapd_pk11_isFIPS()) {
+ SSLCipherSuiteInfo info;
+ if (SECFailure == SSL_GetCipherSuiteInfo((PRUint16)_conf_ciphers[idx].num,
+ &info, sizeof info)) {
+ PRErrorCode errorCode = PR_GetError();
+ if (slapi_is_loglevel_set(SLAPI_LOG_CONFIG)) {
+ slapd_SSL_warn("Security Initialization: no information for cipher
suite [%s] "
+ "error %d - %s", _conf_ciphers[idx].name,
+ errorCode, slapd_pr_strerror(errorCode));
+ }
+ rc = PR_FALSE;
+ }
+ if (rc && !info.isFIPS) {
+ if (slapi_is_loglevel_set(SLAPI_LOG_CONFIG)) {
+ slapd_SSL_warn("Security Initialization: FIPS mode is enabled but
"
+ "cipher suite [%s] is not approved for FIPS - "
+ "the cipher suite will be disabled - if "
+ "you want to use this cipher suite, you must use
modutil to "
+ "disable FIPS in the internal token.",
+ _conf_ciphers[idx].name);
+ }
+ rc = PR_FALSE;
+ }
+ if (!rc && unsuplist && !charray_inlist(*unsuplist,
_conf_ciphers[idx].name)) {
+ charray_add(unsuplist, _conf_ciphers[idx].name);
+ }
+ if (rc && suplist && !charray_inlist(*suplist,
_conf_ciphers[idx].name)) {
+ charray_add(suplist, _conf_ciphers[idx].name);
+ }
+ }
+ return rc;
+}
+
void
-_conf_setallciphers(int active)
+_conf_setallciphers(int active, char ***suplist, char ***unsuplist)
{
int x;
/* 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"))
{
continue;
}
- SSL_CipherPrefSetDefault(_conf_ciphers[x].num, active ? PR_TRUE : PR_FALSE);
+ if (enabled) {
+ enabled = cipher_check_fips(x, suplist, unsuplist);
+ }
+ SSL_CipherPrefSetDefault(_conf_ciphers[x].num, enabled);
+ }
+}
+
+static char *
+charray2str(char **ary, const char *delim)
+{
+ char *str = NULL;
+ while (ary && *ary) {
+ if (str) {
+ str = PR_sprintf_append(str, "%s%s", delim, *ary++);
+ } else {
+ str = PR_smprintf("%s", *ary++);
+ }
}
+
+ return str;
}
char *
@@ -204,15 +295,30 @@ _conf_setciphers(char *ciphers)
{
char *t, err[MAGNUS_ERROR_LEN];
int x, active;
- char *raw = ciphers;
+ char *raw = ciphers;
+ char **suplist = NULL;
+ char **unsuplist = NULL;
/* Default is to activate all of them */
if(!ciphers || ciphers[0] == '\0') {
- _conf_setallciphers(1);
+ _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 */
return NULL;
}
/* Enable all the ciphers by default and the following while loop would disable the user
disabled ones This is needed becuase we added a new set of ciphers in the table . Right
now there is no support for this from the console */
- _conf_setallciphers(1);
+ _conf_setallciphers(1, &suplist, NULL);
t = ciphers;
while(t) {
@@ -232,22 +338,44 @@ _conf_setciphers(char *ciphers)
*t++ = '\0';
if(!strcasecmp(ciphers, "all"))
- _conf_setallciphers(active);
+ _conf_setallciphers(active, NULL, NULL);
else {
for(x = 0; _conf_ciphers[x].name; x++) {
if(!strcasecmp(ciphers, _conf_ciphers[x].name)) {
- SSL_CipherPrefSetDefault(_conf_ciphers[x].num, active ? PR_TRUE : PR_FALSE);
- break;
+ 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(!_conf_ciphers[x].name) {
PR_snprintf(err, sizeof(err), "unknown cipher %s", ciphers);
+ slapi_ch_free((void **)&suplist); /* strings inside are static */
+ slapi_ch_free((void **)&unsuplist); /* strings inside are static */
return slapi_ch_strdup(err);
}
}
if(t)
ciphers = t;
}
+ if (unsuplist && unsuplist) {
+ char *strsup = charray2str(suplist, ",");
+ char *strunsup = charray2str(unsuplist, ",");
+ slapd_SSL_warn("Security Initialization: FIPS mode is enabled - only the
following "
+ "cipher suites are approved for FIPS: [%s] - "
+ "the specified cipher suites [%s] are disabled - if "
+ "you want to use these unsupported cipher suites, you must
use modutil to "
+ "disable FIPS in the internal token.",
+ strsup ? strsup : "(none)", strunsup ? strunsup :
"(none)");
+ slapi_ch_free_string(&strsup);
+ slapi_ch_free_string(&strunsup);
+ }
+
+ slapi_ch_free((void **)&suplist); /* strings inside are static */
+ slapi_ch_free((void **)&unsuplist); /* strings inside are static */
+
return NULL;
}
@@ -270,34 +398,6 @@ SSLPLCY_Install(void)
}
-static void
-slapd_SSL_report(int degree, char *fmt, va_list args)
-{
- char buf[2048];
- PR_vsnprintf( buf, sizeof(buf), fmt, args );
- LDAPDebug( LDAP_DEBUG_ANY, "SSL %s: %s\n",
- (degree == LOG_FAILURE) ? "failure" : "alert",
- buf, 0 );
-}
-
-void
-slapd_SSL_error(char *fmt, ...)
-{
- va_list args;
- va_start(args, fmt);
- slapd_SSL_report(LOG_FAILURE, fmt, args);
- va_end(args);
-}
-
-void
-slapd_SSL_warn(char *fmt, ...)
-{
- va_list args;
- va_start(args, fmt);
- slapd_SSL_report(LOG_WARN, fmt, args);
- va_end(args);
-}
-
/**
* Get a particular entry
*/
@@ -1079,7 +1179,7 @@ int slapd_ssl_init2(PRFileDesc **fd, int startTLS)
"nsSSL3 explicitly set to on - SSLv3 is not approved
"
"for use in FIPS mode - SSLv3 will be disabled - if
"
"you want to use SSLv3, you must use modutil to
"
- "disable FIPS in the internal token.\n");
+ "disable FIPS in the internal token.");
enableSSL3 = PR_FALSE;
}
}