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