# HG changeset patch
# User John Dennis <jdennis@redhat.com>
# Date 1434146324 14400
# Fri Jun 12 17:58:44 2015 -0400
# Node ID 6096d0660e2abefcee12e502fed029663d435c54
# Parent a5e07e90e9c8cb08c5fb46eba16bdb43b94d67c3
Some unit tests fail in FIPS mode
Resolves bug
https://bugzilla.redhat.com/show_bug.cgi?id=1194349
Essentially there were 2 problems:
1. The DB password 'db_passwd' was not complex enough for FIPS
changing it to 'DB_passwd' with upper case was sufficient.
Also changed the pkcs password 'pk12_passwd' to 'PK12_passwd'
2. NSS adds a random salt in FIPS mode for the PKCS12 operations.
The presence of this salt was causing a comparision to fail,
the exact salt is insignificant to the operation of the test
so it was stripped out prior to comparision.
At the same time setup_certs.py was augmented to accept a --fips
parameter to put the DB into fips mode and setup_certs.py also
now reports the status of the system FIPS mode and DB FIPS mode in
addtion to the existing info displayed at its conclusion.
diff --git a/test/setup_certs.py b/test/setup_certs.py
--- a/test/setup_certs.py
+++ b/test/setup_certs.py
@@ -4,6 +4,7 @@
import atexit
import logging
import os
+import re
import shutil
import subprocess
import sys
@@ -11,6 +12,12 @@
import tempfile
#-------------------------------------------------------------------------------
+logger = None
+
+FIPS_SWITCH_FAILED_ERR = 11
+FIPS_ALREADY_ON_ERR = 12
+FIPS_ALREADY_OFF_ERR = 13
+
class CmdError(Exception):
def __init__(self, cmd_args, returncode, message=None, stdout=None, stderr=None):
@@ -41,7 +48,7 @@
returncode = p.returncode
if returncode != 0:
raise CmdError(cmd_args, returncode,
- 'failed %s' % (', '.join(cmd_args)),
+ 'failed %s' % (' '.join(cmd_args)),
stdout, stderr)
return stdout, stderr
except OSError as e:
@@ -319,9 +326,75 @@
run_cmd(cmd_args)
return name
+def parse_fips_enabled(string):
+ if re.search('FIPS mode disabled', string):
+ return False
+ if re.search('FIPS mode enabled', string):
+ return True
+ raise ValueError('unknown fips enabled string: "%s"' % string)
+
+def get_system_fips_enabled():
+ fips_path = '/proc/sys/crypto/fips_enabled'
+
+ try:
+ with open(fips_path) as f:
+ data = f.read()
+ except Exception as e:
+ logger.warning("Unable to determine system FIPS mode: %s" % e)
+ data = '0'
+
+ value = int(data)
+ if value:
+ return True
+ else:
+ return False
+
+
+def get_db_fips_enabled(db_name):
+ cmd_args = ['/usr/bin/modutil',
+ '-dbdir', db_name, # NSS database
+ '-chkfips', 'true', # enable/disable fips
+ ]
+
+ try:
+ stdout, stderr = run_cmd(cmd_args)
+ return parse_fips_enabled(stdout)
+ except CmdError as e:
+ if e.returncode == FIPS_SWITCH_FAILED_ERR:
+ return parse_fips_enabled(e.stdout)
+ else:
+ raise
+
+def set_fips_mode(options):
+ if options.fips:
+ state = 'true'
+ else:
+ if get_system_fips_enabled():
+ logger.warning("System FIPS enabled, cannot disable FIPS")
+ return
+ state = 'false'
+
+ logging.info('setting fips: %s', state)
+
+ cmd_args = ['/usr/bin/modutil',
+ '-dbdir', options.db_name, # NSS database
+ '-fips', state, # enable/disable fips
+ '-force'
+ ]
+
+ try:
+ stdout, stderr = run_cmd(cmd_args)
+ except CmdError as e:
+ if options.fips and e.returncode == FIPS_ALREADY_ON_ERR:
+ pass
+ elif not options.fips and e.returncode == FIPS_ALREADY_OFF_ERR:
+ pass
+ else:
+ raise
#-------------------------------------------------------------------------------
def setup_certs(args):
+ global logger
# --- cmd ---
parser = argparse.ArgumentParser(description='create certs for testing',
@@ -393,6 +466,9 @@
parser.add_argument('--serial-file', dest='serial_file',
help='name of file used to track next serial number')
+ parser.add_argument('--db-fips', action='store_true',
+ help='enable FIPS mode on NSS Database')
+
parser.set_defaults(verbose = False,
debug = False,
quiet = False,
@@ -402,7 +478,7 @@
hostname = os.uname()[1],
db_type = 'sql',
db_dir = 'pki',
- db_passwd = 'db_passwd',
+ db_passwd = 'DB_passwd',
ca_subject = 'CN=Test CA',
ca_nickname = 'test_ca',
server_subject = 'CN=${hostname}',
@@ -416,6 +492,7 @@
valid_months = 12,
ca_path_len = 2,
serial_file = '${db_dir}/serial',
+ fips = False,
)
@@ -468,6 +545,7 @@
try:
create_database(options)
+ set_fips_mode(options)
cert_nicknames.append(create_ca_cert(options))
cert_nicknames.append(create_server_cert(options))
cert_nicknames.append(create_client_cert(options))
@@ -488,6 +566,8 @@
logging.info('---------- Summary ----------')
logging.info('NSS database name="%s", password="%s"',
options.db_name, options.db_passwd)
+ logging.info('system FIPS mode=%s', get_system_fips_enabled());
+ logging.info('DB FIPS mode=%s', get_db_fips_enabled(options.db_name));
logging.info('CA nickname="%s", CA subject="%s"',
options.ca_nickname, options.ca_subject)
logging.info('server nickname="%s", server subject="%s"',
diff --git a/test/test_client_server.py b/test/test_client_server.py
--- a/test/test_client_server.py
+++ b/test/test_client_server.py
@@ -22,7 +22,7 @@
verbose = False
info = False
-password = 'db_passwd'
+password = 'DB_passwd'
use_ssl = True
client_cert_action = NO_CLIENT_CERT
db_name = 'sql:pki'
diff --git a/test/test_pkcs12.py b/test/test_pkcs12.py
--- a/test/test_pkcs12.py
+++ b/test/test_pkcs12.py
@@ -15,8 +15,8 @@
verbose = False
db_name = 'sql:pki'
-db_passwd = 'db_passwd'
-pk12_passwd = 'pk12_passwd'
+db_passwd = 'DB_passwd'
+pk12_passwd = 'PK12_passwd'
cert_nickname = 'test_user'
pk12_filename = '%s.p12' % cert_nickname
@@ -115,6 +115,9 @@
raise ValueError('Could not file Key section in pk12 listing')
return text[match.start(0):]
+def strip_salt_from_pk12_listing(text):
+ return re.sub(r'\s+Salt:\s*\n.*', '', text)
+
#-------------------------------------------------------------------------------
def load_tests(loader, tests, pattern):
@@ -206,9 +209,11 @@
pk12_listing = list_pk12(pk12_filename)
pk12_listing = strip_key_from_pk12_listing(pk12_listing)
+ pk12_listing = strip_salt_from_pk12_listing(pk12_listing)
exported_pk12_listing = list_pk12(exported_pk12_filename)
exported_pk12_listing = strip_key_from_pk12_listing(exported_pk12_listing)
+ exported_pk12_listing = strip_salt_from_pk12_listing(exported_pk12_listing)
self.assertEqual(pk12_listing, exported_pk12_listing)