from __future__ import absolute_import import os import pytest from ipapython.certdb import ( NSSDatabase, TRUSTED_PEER_TRUST_FLAGS, nss_supports_dbm, ) from ipapython import ipautil from ipaplatform.osinfo import osinfo CERTNICK = 'testcert' CERTSAN = 'testcert.certdb.test' if osinfo.id == 'fedora': if osinfo.version_number >= (28,): NSS_DEFAULT = 'sql' else: NSS_DEFAULT = 'dbm' else: NSS_DEFAULT = None def create_selfsigned(nssdb): # create self-signed cert + key noisefile = os.path.join(nssdb.secdir, 'noise') with open(noisefile, 'wb') as f: f.write(os.urandom(64)) try: nssdb.run_certutil([ '-S', '-x', '-z', noisefile, '-k', 'rsa', '-g', '2048', '-Z', 'SHA256', '-t', 'CTu,Cu,Cu', '-s', 'CN=testcert', '-n', CERTNICK, '-m', '365', '--extSAN', f'dns:{CERTSAN}' ]) finally: os.unlink(noisefile) @pytest.mark.skipif( not nss_supports_dbm(), reason="NSS is built without support of the legacy database(DBM)", ) def test_dbm_tmp(): with NSSDatabase(dbtype='dbm') as nssdb: assert nssdb.dbtype == 'dbm' for filename in nssdb.filenames: assert not os.path.isfile(filename) assert not nssdb.exists() nssdb.create_db() for filename in nssdb.filenames: assert os.path.isfile(filename) assert os.path.dirname(filename) == nssdb.secdir assert nssdb.exists() assert os.path.basename(nssdb.certdb) == 'cert8.db' assert nssdb.certdb in nssdb.filenames assert os.path.basename(nssdb.keydb) == 'key3.db' assert os.path.basename(nssdb.secmod) == 'secmod.db' @pytest.mark.skipif( nss_supports_dbm(), reason="NSS is built with support of the legacy database(DBM)", ) def test_dbm_raise(): with pytest.raises(ValueError) as e: NSSDatabase(dbtype="dbm") assert ( "NSS is built without support of the legacy database(DBM)" in str(e.value) ) def test_sql_tmp(): with NSSDatabase(dbtype='sql') as nssdb: assert nssdb.dbtype == 'sql' for filename in nssdb.filenames: assert not os.path.isfile(filename) assert not nssdb.exists() nssdb.create_db() for filename in nssdb.filenames: assert os.path.isfile(filename) assert os.path.dirname(filename) == nssdb.secdir assert nssdb.exists() assert os.path.basename(nssdb.certdb) == 'cert9.db' assert nssdb.certdb in nssdb.filenames assert os.path.basename(nssdb.keydb) == 'key4.db' assert os.path.basename(nssdb.secmod) == 'pkcs11.txt' @pytest.mark.skipif( not nss_supports_dbm(), reason="NSS is built without support of the legacy database(DBM)", ) def test_convert_db(): with NSSDatabase(dbtype='dbm') as nssdb: assert nssdb.dbtype == 'dbm' nssdb.create_db() assert nssdb.exists() create_selfsigned(nssdb) oldcerts = nssdb.list_certs() assert len(oldcerts) == 1 oldkeys = nssdb.list_keys() assert len(oldkeys) == 1 nssdb.convert_db() assert nssdb.exists() assert nssdb.dbtype == 'sql' newcerts = nssdb.list_certs() assert len(newcerts) == 1 assert newcerts == oldcerts newkeys = nssdb.list_keys() assert len(newkeys) == 1 assert newkeys == oldkeys for filename in nssdb.filenames: assert os.path.isfile(filename) assert os.path.dirname(filename) == nssdb.secdir assert os.path.basename(nssdb.certdb) == 'cert9.db' assert nssdb.certdb in nssdb.filenames assert os.path.basename(nssdb.keydb) == 'key4.db' assert os.path.basename(nssdb.secmod) == 'pkcs11.txt' @pytest.mark.skipif( not nss_supports_dbm(), reason="NSS is built without support of the legacy database(DBM)", ) def test_convert_db_nokey(): with NSSDatabase(dbtype='dbm') as nssdb: assert nssdb.dbtype == 'dbm' nssdb.create_db() create_selfsigned(nssdb) assert len(nssdb.list_certs()) == 1 assert len(nssdb.list_keys()) == 1 # remove key, readd cert cert = nssdb.get_cert(CERTNICK) nssdb.run_certutil(['-F', '-n', CERTNICK]) nssdb.add_cert(cert, CERTNICK, TRUSTED_PEER_TRUST_FLAGS) assert len(nssdb.list_keys()) == 0 oldcerts = nssdb.list_certs() assert len(oldcerts) == 1 nssdb.convert_db() assert nssdb.dbtype == 'sql' newcerts = nssdb.list_certs() assert len(newcerts) == 1 assert newcerts == oldcerts assert nssdb.get_cert(CERTNICK) == cert newkeys = nssdb.list_keys() assert newkeys == () for filename in nssdb.filenames: assert os.path.isfile(filename) assert os.path.dirname(filename) == nssdb.secdir old = os.path.join(nssdb.secdir, 'cert8.db') assert not os.path.isfile(old) assert os.path.isfile(old + '.migrated') assert os.path.basename(nssdb.certdb) == 'cert9.db' assert nssdb.certdb in nssdb.filenames assert os.path.basename(nssdb.keydb) == 'key4.db' assert os.path.basename(nssdb.secmod) == 'pkcs11.txt' def test_auto_db(): with NSSDatabase() as nssdb: assert nssdb.dbtype == 'auto' assert nssdb.filenames is None assert not nssdb.exists() with pytest.raises(RuntimeError): nssdb.list_certs() nssdb.create_db() assert nssdb.dbtype in ('dbm', 'sql') if NSS_DEFAULT is not None: assert nssdb.dbtype == NSS_DEFAULT assert nssdb.filenames is not None assert nssdb.exists() nssdb.list_certs() def test_delete_cert_and_key(): """Test that delete_cert + delete_key always deletes everything Test with a NSSDB that contains: - cert + key - key only - cert only - none of them """ cmd = ipautil.run(['mktemp'], capture_output=True) p12file = cmd.output.strip() try: with NSSDatabase() as nssdb: nssdb.create_db() # 1. Test delete_key_and_cert when cert + key are present # Create a NSS DB with cert + key create_selfsigned(nssdb) # Save both in a p12 file for latter use ipautil.run( [ 'pk12util', '-o', p12file, '-n', CERTNICK, '-d', nssdb.secdir, '-k', nssdb.pwd_file, '-w', nssdb.pwd_file ]) # Delete cert and key nssdb.delete_key_and_cert(CERTNICK) # make sure that everything was deleted assert len(nssdb.list_keys()) == 0 assert len(nssdb.list_certs()) == 0 # 2. Test delete_key_and_cert when only key is present # Import cert and key then remove cert import_args = [ 'pk12util', '-i', p12file, '-d', nssdb.secdir, '-k', nssdb.pwd_file, '-w', nssdb.pwd_file] ipautil.run(import_args) nssdb.delete_cert(CERTNICK) # Delete cert and key nssdb.delete_key_and_cert(CERTNICK) # make sure that everything was deleted assert len(nssdb.list_keys()) == 0 assert len(nssdb.list_certs()) == 0 # 3. Test delete_key_and_cert when only cert is present # Import cert and key then remove key ipautil.run(import_args) nssdb.delete_key_only(CERTNICK) # make sure the db contains only the cert assert len(nssdb.list_keys()) == 0 assert len(nssdb.list_certs()) == 1 # Delete cert and key when key is not present nssdb.delete_key_and_cert(CERTNICK) # make sure that everything was deleted assert len(nssdb.list_keys()) == 0 assert len(nssdb.list_certs()) == 0 # 4. Test delete_key_and_cert with a wrong nickname # Import cert and key ipautil.run(import_args) # Delete cert and key nssdb.delete_key_and_cert('wrongnick') # make sure that nothing was deleted assert len(nssdb.list_keys()) == 1 assert len(nssdb.list_certs()) == 1 finally: os.unlink(p12file) def test_check_validity(): with NSSDatabase() as nssdb: nssdb.create_db() create_selfsigned(nssdb) with pytest.raises(ValueError): nssdb.verify_ca_cert_validity(CERTNICK) nssdb.verify_server_cert_validity(CERTNICK, CERTSAN) with pytest.raises(ValueError): nssdb.verify_server_cert_validity(CERTNICK, 'invalid.example')