diff --git a/pki-core-post-re-base.patch b/pki-core-post-re-base.patch new file mode 100644 index 0000000..b2cded9 --- /dev/null +++ b/pki-core-post-re-base.patch @@ -0,0 +1,5567 @@ +From e897fbd1b37d16d60858717f74e09952a45693d2 Mon Sep 17 00:00:00 2001 +From: "Endi S. Dewata" +Date: Sat, 25 Jun 2016 00:14:11 +0200 +Subject: Fixed problem reading HSM password from password file. + +A new method get_token_password() has been added into PKIInstance +Python class in order to read the token password correctly from +password.conf. If the token is an internal token, it will read the +'internal' password. If it is an HSM it will read the password for +'hardware-'. + +The codes that call the get_password() to get token password have +been modified to use get_token_password() instead. + +https://fedorahosted.org/pki/ticket/2384 +--- + base/server/python/pki/server/__init__.py | 59 +++++++++++++++++++------- + base/server/python/pki/server/cli/instance.py | 4 +- + base/server/python/pki/server/cli/subsystem.py | 11 ++--- + 3 files changed, 50 insertions(+), 24 deletions(-) + +diff --git a/base/server/python/pki/server/__init__.py b/base/server/python/pki/server/__init__.py +index bf705fd..454408f 100644 +--- a/base/server/python/pki/server/__init__.py ++++ b/base/server/python/pki/server/__init__.py +@@ -186,9 +186,11 @@ class PKISubsystem(object): + cert = self.get_subsystem_cert(cert_id) + nickname = cert['nickname'] + token = cert['token'] +- if token == 'Internal Key Storage Token': +- token = 'internal' +- nssdb_password = self.instance.get_password(token) ++ ++ if token and token.lower() in ['internal', 'internal key storage token']: ++ token = None ++ ++ nssdb_password = self.instance.get_token_password(token) + + tmpdir = tempfile.mkdtemp() + +@@ -204,7 +206,7 @@ class PKISubsystem(object): + '-C', nssdb_password_file + ] + +- if token and token != 'internal': ++ if token: + cmd.extend(['--token', token]) + + cmd.extend([ +@@ -234,9 +236,11 @@ class PKISubsystem(object): + cert = self.get_subsystem_cert('subsystem') + nickname = cert['nickname'] + token = cert['token'] +- if token == 'Internal Key Storage Token': +- token = 'internal' +- nssdb_password = self.instance.get_password(token) ++ ++ if token and token.lower() in ['internal', 'internal key storage token']: ++ token = None ++ ++ nssdb_password = self.instance.get_token_password(token) + + tmpdir = tempfile.mkdtemp() + +@@ -252,7 +256,7 @@ class PKISubsystem(object): + '-C', nssdb_password_file + ] + +- if token and token != 'internal': ++ if token: + cmd.extend(['--token', token]) + + cmd.extend([ +@@ -271,7 +275,7 @@ class PKISubsystem(object): + '-C', nssdb_password_file + ] + +- if token and token != 'internal': ++ if token: + cmd.extend(['--token', token]) + + cmd.extend([ +@@ -359,7 +363,8 @@ class PKISubsystem(object): + connection.set_credentials( + client_cert_nickname=self.config[ + '%s.ldapauth.clientCertNickname' % name], +- nssdb_password=self.instance.get_password('internal') ++ # TODO: remove hard-coded token name ++ nssdb_password=self.instance.get_token_password('internal') + ) + + else: +@@ -543,19 +548,41 @@ class PKIInstance(object): + return external_certs + + def get_password(self, name): ++ ++ # find password (e.g. internaldb, replicationdb) in password.conf + if name in self.passwords: + return self.passwords[name] + ++ # prompt for password if not found + password = getpass.getpass(prompt='Enter password for %s: ' % name) + self.passwords[name] = password + + return password + ++ def get_token_password(self, token='internal'): ++ ++ # determine the password name for the token ++ if token.lower() in ['internal', 'internal key storage token']: ++ name = 'internal' ++ ++ else: ++ name = 'hardware-%s' % token ++ ++ # find password in password.conf ++ if name in self.passwords: ++ return self.passwords[name] ++ ++ # prompt for password if not found ++ password = getpass.getpass(prompt='Enter password for %s: ' % token) ++ self.passwords[name] = password ++ ++ return password ++ + def open_nssdb(self, token='internal'): + return pki.nssdb.NSSDatabase( + directory=self.nssdb_dir, + token=token, +- password=self.get_password(token)) ++ password=self.get_token_password(token)) + + def external_cert_exists(self, nickname, token): + for cert in self.external_certs: +@@ -588,9 +615,11 @@ class PKIInstance(object): + for cert in self.external_certs: + nickname = cert.nickname + token = cert.token +- if token == 'Internal Key Storage Token': +- token = 'internal' +- nssdb_password = self.get_password(token) ++ ++ if token and token.lower() in ['internal', 'internal key storage token']: ++ token = None ++ ++ nssdb_password = self.get_token_password(token) + + tmpdir = tempfile.mkdtemp() + +@@ -606,7 +635,7 @@ class PKIInstance(object): + '-C', nssdb_password_file + ] + +- if token and token != 'internal': ++ if token: + cmd.extend(['--token', token]) + + cmd.extend([ +diff --git a/base/server/python/pki/server/cli/instance.py b/base/server/python/pki/server/cli/instance.py +index 6e336e1..4a5a3b3 100644 +--- a/base/server/python/pki/server/cli/instance.py ++++ b/base/server/python/pki/server/cli/instance.py +@@ -679,7 +679,7 @@ class InstanceExternalCertAddCLI(pki.cli.CLI): + instance_name) + + def import_certs(self, instance, cert_file, nickname, token, trust_args): +- password = instance.get_password(token) ++ password = instance.get_token_password(token) + certdb = pki.nssdb.NSSDatabase( + directory=instance.nssdb_dir, + password=password, +@@ -762,7 +762,7 @@ class InstanceExternalCertDeleteCLI(pki.cli.CLI): + instance_name) + + def remove_cert(self, instance, nickname, token): +- password = instance.get_password(token) ++ password = instance.get_token_password(token) + certdb = pki.nssdb.NSSDatabase( + directory=instance.nssdb_dir, + password=password, +diff --git a/base/server/python/pki/server/cli/subsystem.py b/base/server/python/pki/server/cli/subsystem.py +index c92ed16..615b55e 100644 +--- a/base/server/python/pki/server/cli/subsystem.py ++++ b/base/server/python/pki/server/cli/subsystem.py +@@ -843,14 +843,11 @@ class SubsystemCertValidateCLI(pki.cli.CLI): + + print(' Token: %s' % token) + +- if token == 'Internal Key Storage Token': +- token = 'internal' ++ if token and token.lower() in ['internal', 'internal key storage token']: ++ token = None + + # get token password and store in temporary file +- if token == 'internal': +- passwd = instance.get_password('internal') +- else: +- passwd = instance.get_password("hardware-%s" % token) ++ passwd = instance.get_token_password(token) + + pwfile_handle, pwfile_path = mkstemp() + os.write(pwfile_handle, passwd) +@@ -860,7 +857,7 @@ class SubsystemCertValidateCLI(pki.cli.CLI): + cmd = ['pki', '-d', instance.nssdb_dir, + '-C', pwfile_path ] + +- if token != 'internal': ++ if token: + cmd.extend(['--token', token]) + + cmd.extend(['client-cert-validate', +-- +2.5.5 + + +From f0ab1c3d8bcd084ffe611e954b2d4f548f64cfd2 Mon Sep 17 00:00:00 2001 +From: Amol Kahat +Date: Tue, 21 Jun 2016 12:47:23 +0530 +Subject: Fixes pki-server subsystem-* --help options. + +Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1340718 +--- + base/server/python/pki/server/cli/subsystem.py | 155 +++++++++++++------------ + 1 file changed, 81 insertions(+), 74 deletions(-) + +diff --git a/base/server/python/pki/server/cli/subsystem.py b/base/server/python/pki/server/cli/subsystem.py +index 615b55e..45f5be9 100644 +--- a/base/server/python/pki/server/cli/subsystem.py ++++ b/base/server/python/pki/server/cli/subsystem.py +@@ -90,7 +90,7 @@ class SubsystemFindCLI(pki.cli.CLI): + self.set_verbose(True) + + elif o == '--help': +- self.print_help() ++ self.usage() + sys.exit() + + else: +@@ -138,12 +138,6 @@ class SubsystemShowCLI(pki.cli.CLI): + self.usage() + sys.exit(1) + +- if len(args) != 1: +- print('ERROR: missing subsystem ID') +- self.usage() +- sys.exit(1) +- +- subsystem_name = args[0] + instance_name = 'pki-tomcat' + + for o, a in opts: +@@ -154,7 +148,7 @@ class SubsystemShowCLI(pki.cli.CLI): + self.set_verbose(True) + + elif o == '--help': +- self.print_help() ++ self.usage() + sys.exit() + + else: +@@ -162,6 +156,13 @@ class SubsystemShowCLI(pki.cli.CLI): + self.usage() + sys.exit(1) + ++ if len(args) != 1: ++ print('ERROR: missing subsystem ID') ++ self.usage() ++ sys.exit(1) ++ ++ subsystem_name = args[0] ++ + instance = pki.server.PKIInstance(instance_name) + instance.load() + +@@ -195,12 +196,6 @@ class SubsystemEnableCLI(pki.cli.CLI): + self.usage() + sys.exit(1) + +- if len(args) != 1: +- print('ERROR: missing subsystem ID') +- self.usage() +- sys.exit(1) +- +- subsystem_name = args[0] + instance_name = 'pki-tomcat' + + for o, a in opts: +@@ -211,7 +206,7 @@ class SubsystemEnableCLI(pki.cli.CLI): + self.set_verbose(True) + + elif o == '--help': +- self.print_help() ++ self.usage() + sys.exit() + + else: +@@ -219,6 +214,13 @@ class SubsystemEnableCLI(pki.cli.CLI): + self.usage() + sys.exit(1) + ++ if len(args) != 1: ++ print('ERROR: missing subsystem ID') ++ self.usage() ++ sys.exit(1) ++ ++ subsystem_name = args[0] ++ + instance = pki.server.PKIInstance(instance_name) + instance.load() + +@@ -257,12 +259,6 @@ class SubsystemDisableCLI(pki.cli.CLI): + self.usage() + sys.exit(1) + +- if len(args) != 1: +- print('ERROR: missing subsystem ID') +- self.usage() +- sys.exit(1) +- +- subsystem_name = args[0] + instance_name = 'pki-tomcat' + + for o, a in opts: +@@ -273,7 +269,7 @@ class SubsystemDisableCLI(pki.cli.CLI): + self.set_verbose(True) + + elif o == '--help': +- self.print_help() ++ self.usage() + sys.exit() + + else: +@@ -281,6 +277,13 @@ class SubsystemDisableCLI(pki.cli.CLI): + self.usage() + sys.exit(1) + ++ if len(args) != 1: ++ print('ERROR: missing subsystem ID') ++ self.usage() ++ sys.exit(1) ++ ++ subsystem_name = args[0] ++ + instance = pki.server.PKIInstance(instance_name) + instance.load() + +@@ -342,12 +345,6 @@ class SubsystemCertFindCLI(pki.cli.CLI): + self.print_help() + sys.exit(1) + +- if len(args) != 1: +- print('ERROR: missing subsystem ID') +- self.print_help() +- sys.exit(1) +- +- subsystem_name = args[0] + instance_name = 'pki-tomcat' + show_all = False + +@@ -370,6 +367,13 @@ class SubsystemCertFindCLI(pki.cli.CLI): + self.print_help() + sys.exit(1) + ++ if len(args) != 1: ++ print('ERROR: missing subsystem ID') ++ self.print_help() ++ sys.exit(1) ++ ++ subsystem_name = args[0] ++ + instance = pki.server.PKIInstance(instance_name) + instance.load() + +@@ -414,18 +418,6 @@ class SubsystemCertShowCLI(pki.cli.CLI): + self.usage() + sys.exit(1) + +- if len(args) < 1: +- print('ERROR: missing subsystem ID') +- self.usage() +- sys.exit(1) +- +- if len(args) < 2: +- print('ERROR: missing cert ID') +- self.usage() +- sys.exit(1) +- +- subsystem_name = args[0] +- cert_id = args[1] + instance_name = 'pki-tomcat' + + for o, a in opts: +@@ -436,7 +428,7 @@ class SubsystemCertShowCLI(pki.cli.CLI): + self.set_verbose(True) + + elif o == '--help': +- self.print_help() ++ self.usage() + sys.exit() + + else: +@@ -444,6 +436,20 @@ class SubsystemCertShowCLI(pki.cli.CLI): + self.usage() + sys.exit(1) + ++ if len(args) < 1: ++ print('ERROR: missing subsystem ID') ++ self.usage() ++ sys.exit(1) ++ ++ ++ if len(args) < 2: ++ print('ERROR: missing cert ID') ++ self.usage() ++ sys.exit(1) ++ ++ subsystem_name = args[0] ++ cert_id = args[1] ++ + instance = pki.server.PKIInstance(instance_name) + instance.load() + +@@ -491,13 +497,6 @@ class SubsystemCertExportCLI(pki.cli.CLI): + self.print_help() + sys.exit(1) + +- if len(args) < 1: +- print('ERROR: missing subsystem ID') +- self.print_help() +- sys.exit(1) +- +- subsystem_name = args[0] +- + instance_name = 'pki-tomcat' + cert_file = None + csr_file = None +@@ -556,6 +555,13 @@ class SubsystemCertExportCLI(pki.cli.CLI): + self.print_help() + sys.exit(1) + ++ if len(args) < 1: ++ print('ERROR: missing subsystem ID') ++ self.print_help() ++ sys.exit(1) ++ ++ subsystem_name = args[0] ++ + if not (cert_file or csr_file or pkcs12_file): + print('ERROR: missing output file') + self.print_help() +@@ -646,18 +652,6 @@ class SubsystemCertUpdateCLI(pki.cli.CLI): + self.usage() + sys.exit(1) + +- if len(args) < 1: +- print('ERROR: missing subsystem ID') +- self.usage() +- sys.exit(1) +- +- if len(args) < 2: +- print('ERROR: missing cert ID') +- self.usage() +- sys.exit(1) +- +- subsystem_name = args[0] +- cert_id = args[1] + instance_name = 'pki-tomcat' + + for o, a in opts: +@@ -668,7 +662,7 @@ class SubsystemCertUpdateCLI(pki.cli.CLI): + self.set_verbose(True) + + elif o == '--help': +- self.print_help() ++ self.usage() + sys.exit() + + else: +@@ -676,6 +670,19 @@ class SubsystemCertUpdateCLI(pki.cli.CLI): + self.usage() + sys.exit(1) + ++ if len(args) < 1: ++ print('ERROR: missing subsystem ID') ++ self.usage() ++ sys.exit(1) ++ ++ if len(args) < 2: ++ print('ERROR: missing cert ID') ++ self.usage() ++ sys.exit(1) ++ ++ subsystem_name = args[0] ++ cert_id = args[1] ++ + instance = pki.server.PKIInstance(instance_name) + instance.load() + +@@ -745,18 +752,6 @@ class SubsystemCertValidateCLI(pki.cli.CLI): + self.usage() + sys.exit(1) + +- if len(args) < 1: +- print('ERROR: missing subsystem ID') +- self.usage() +- sys.exit(1) +- +- subsystem_name = args[0] +- +- if len(args) >=2: +- cert_id = args[1] +- else: +- cert_id = None +- + instance_name = 'pki-tomcat' + + for o, a in opts: +@@ -767,7 +762,7 @@ class SubsystemCertValidateCLI(pki.cli.CLI): + self.set_verbose(True) + + elif o == '--help': +- self.print_help() ++ self.usage() + sys.exit() + + else: +@@ -775,6 +770,18 @@ class SubsystemCertValidateCLI(pki.cli.CLI): + self.usage() + sys.exit(1) + ++ if len(args) < 1: ++ print('ERROR: missing subsystem ID') ++ self.usage() ++ sys.exit(1) ++ ++ subsystem_name = args[0] ++ ++ if len(args) >=2: ++ cert_id = args[1] ++ else: ++ cert_id = None ++ + instance = pki.server.PKIInstance(instance_name) + instance.load() + +-- +2.5.5 + + +From 7e1ffced6b91b28a0fcbb65df5087220be0b6c68 Mon Sep 17 00:00:00 2001 +From: Amol Kahat +Date: Tue, 21 Jun 2016 13:20:59 +0530 +Subject: Fixes: Invalid instance exception issue. + +Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1348433 +--- + base/server/python/pki/server/cli/instance.py | 40 +++++++++++++++++++++++++-- + 1 file changed, 37 insertions(+), 3 deletions(-) + +diff --git a/base/server/python/pki/server/cli/instance.py b/base/server/python/pki/server/cli/instance.py +index 4a5a3b3..b69519d 100644 +--- a/base/server/python/pki/server/cli/instance.py ++++ b/base/server/python/pki/server/cli/instance.py +@@ -157,6 +157,11 @@ class InstanceCertExportCLI(pki.cli.CLI): + sys.exit(1) + + instance = pki.server.PKIInstance(instance_name) ++ ++ if not instance.is_valid(): ++ print('ERROR: Invalid instance %s.' % instance_name) ++ sys.exit(1) ++ + instance.load() + + if not pkcs12_password and not pkcs12_password_file: +@@ -282,6 +287,11 @@ class InstanceShowCLI(pki.cli.CLI): + instance_name = args[0] + + instance = pki.server.PKIInstance(instance_name) ++ ++ if not instance.is_valid(): ++ print('ERROR: Invalid instance %s.' % instance_name) ++ sys.exit(1) ++ + instance.load() + + InstanceCLI.print_instance(instance) +@@ -333,7 +343,7 @@ class InstanceStartCLI(pki.cli.CLI): + instance = pki.server.PKIInstance(instance_name) + + if not instance.is_valid(): +- self.print_message('%s instance not found' % instance_name) ++ print('ERROR: Invalid instance %s.' % instance_name) + sys.exit(1) + + if instance.is_active(): +@@ -392,7 +402,7 @@ class InstanceStopCLI(pki.cli.CLI): + instance = pki.server.PKIInstance(instance_name) + + if not instance.is_valid(): +- self.print_message('%s instance not found' % instance_name) ++ print('ERROR: Invalid instance %s.' % instance_name) + sys.exit(1) + + if not instance.is_active(): +@@ -470,6 +480,11 @@ class InstanceMigrateCLI(pki.cli.CLI): + module.set_debug(self.debug) + + instance = pki.server.PKIInstance(instance_name) ++ ++ if not instance.is_valid(): ++ print('ERROR: Invalid instance %s.' % instance_name) ++ sys.exit(1) ++ + instance.load() + + module.migrate( # pylint: disable=no-member,maybe-no-member +@@ -526,8 +541,12 @@ class InstanceNuxwdogEnableCLI(pki.cli.CLI): + module.set_verbose(self.verbose) + + instance = pki.server.PKIInstance(instance_name) +- instance.load() + ++ if not instance.is_valid(): ++ print('ERROR: Invalid instance %s.' % instance_name) ++ sys.exit(1) ++ ++ instance.load() + module.enable_nuxwdog( # pylint: disable=no-member,maybe-no-member + instance) + +@@ -580,6 +599,11 @@ class InstanceNuxwdogDisableCLI(pki.cli.CLI): + module.set_verbose(self.verbose) + + instance = pki.server.PKIInstance(instance_name) ++ ++ if not instance.is_valid(): ++ print('ERROR: Invalid instance %s.' % instance_name) ++ sys.exit(1) ++ + instance.load() + + module.disable_nuxwdog( +@@ -664,6 +688,11 @@ class InstanceExternalCertAddCLI(pki.cli.CLI): + sys.exit(1) + + instance = pki.server.PKIInstance(instance_name) ++ ++ if not instance.is_valid(): ++ print('ERROR: Invalid instance %s.' % instance_name) ++ sys.exit(1) ++ + instance.load() + + if instance.external_cert_exists(nickname, token): +@@ -753,6 +782,11 @@ class InstanceExternalCertDeleteCLI(pki.cli.CLI): + sys.exit(1) + + instance = pki.server.PKIInstance(instance_name) ++ ++ if not instance.is_valid(): ++ print('ERROR: Invalid instance %s.' % instance_name) ++ sys.exit(1) ++ + instance.load() + + self.remove_cert(instance, nickname, token) +-- +2.5.5 + + +From 66223629c5d8e74be9f5a59734ab091b081435bc Mon Sep 17 00:00:00 2001 +From: Christina Fu +Date: Tue, 28 Jun 2016 11:28:42 -0700 +Subject: Ticket #1308 [RFE] Provide ability to perform off-card key generation + for non-encryption token keys This is the patch to add missing serverKeygen + params for non-encryption certs. By default it is disabled. + +--- + base/tps/shared/conf/CS.cfg | 43 +++++++++++++++++++++++++++++++++++-------- + 1 file changed, 35 insertions(+), 8 deletions(-) + +diff --git a/base/tps/shared/conf/CS.cfg b/base/tps/shared/conf/CS.cfg +index f552a54..258d5a7 100644 +--- a/base/tps/shared/conf/CS.cfg ++++ b/base/tps/shared/conf/CS.cfg +@@ -332,6 +332,9 @@ op.enroll.delegateIEtoken.keyGen.authentication.recovery.keyCompromise.scheme=Ge + op.enroll.delegateIEtoken.keyGen.authentication.recovery.onHold.revokeCert=false + op.enroll.delegateIEtoken.keyGen.authentication.recovery.onHold.revokeCert.reason=6 + op.enroll.delegateIEtoken.keyGen.authentication.recovery.onHold.scheme=GenerateNewKey ++op.enroll.delegateIEtoken.keyGen.authentication.serverKeygen.archive=false ++op.enroll.delegateIEtoken.keyGen.authentication.serverKeygen.drm.conn=kra1 ++op.enroll.delegateIEtoken.keyGen.authentication.serverKeygen.enable=false + op.enroll.delegateIEtoken.keyGen.encryption.ca.conn=ca1 + op.enroll.delegateIEtoken.keyGen.encryption.private.keyCapabilities.decrypt=true + op.enroll.delegateIEtoken.keyGen.encryption.private.keyCapabilities.derive=false +@@ -359,7 +362,7 @@ op.enroll.delegateIEtoken.keyGen.encryption.public.keyCapabilities.verifyRecover + op.enroll.delegateIEtoken.keyGen.encryption.public.keyCapabilities.wrap=true + op.enroll.delegateIEtoken.keyGen.encryption.serverKeygen.archive=true + op.enroll.delegateIEtoken.keyGen.encryption.serverKeygen.drm.conn=kra1 +-op.enroll.delegateIEtoken.keyGen.encryption.serverKeygen.enable=true ++op.enroll.delegateIEtoken.keyGen.encryption.serverKeygen.enable=[SERVER_KEYGEN] + op.enroll.delegateIEtoken.keyGen.keyType.num=1 + op.enroll.delegateIEtoken.keyGen.keyType.value.0=authentication + op.enroll.delegateIEtoken.keyGen.recovery.destroyed.keyType.num=1 +@@ -501,6 +504,9 @@ op.enroll.delegateISEtoken.keyGen.authentication.recovery.keyCompromise.scheme=G + op.enroll.delegateISEtoken.keyGen.authentication.recovery.onHold.revokeCert=false + op.enroll.delegateISEtoken.keyGen.authentication.recovery.onHold.revokeCert.reason=6 + op.enroll.delegateISEtoken.keyGen.authentication.recovery.onHold.scheme=GenerateNewKey ++op.enroll.delegateISEtoken.keyGen.authentication.serverKeygen.archive=false ++op.enroll.delegateISEtoken.keyGen.authentication.serverKeygen.drm.conn=kra1 ++op.enroll.delegateISEtoken.keyGen.authentication.serverKeygen.enable=false + op.enroll.delegateISEtoken.keyGen.encryption.SANpattern=$auth.mail$,$auth.exec-edipi$.$auth.exec-pcc$@EXAMPLE.com + op.enroll.delegateISEtoken.keyGen.encryption._000=######################################### + op.enroll.delegateISEtoken.keyGen.encryption._001=# encryption cert/keys are "recovered" for this profile +@@ -556,7 +562,7 @@ op.enroll.delegateISEtoken.keyGen.encryption.recovery.onHold.revokeCert.reason=6 + op.enroll.delegateISEtoken.keyGen.encryption.recovery.onHold.scheme=GenerateNewKey + op.enroll.delegateISEtoken.keyGen.encryption.serverKeygen.archive=true + op.enroll.delegateISEtoken.keyGen.encryption.serverKeygen.drm.conn=kra1 +-op.enroll.delegateISEtoken.keyGen.encryption.serverKeygen.enable=true ++op.enroll.delegateISEtoken.keyGen.encryption.serverKeygen.enable=[SERVER_KEYGEN] + op.enroll.delegateISEtoken.keyGen.keyType.num=2 + op.enroll.delegateISEtoken.keyGen.keyType.value.0=signing + op.enroll.delegateISEtoken.keyGen.keyType.value.1=authentication +@@ -618,6 +624,9 @@ op.enroll.delegateISEtoken.keyGen.signing.recovery.keyCompromise.scheme=Generate + op.enroll.delegateISEtoken.keyGen.signing.recovery.onHold.revokeCert=false + op.enroll.delegateISEtoken.keyGen.signing.recovery.onHold.revokeCert.reason=6 + op.enroll.delegateISEtoken.keyGen.signing.recovery.onHold.scheme=GenerateNewKey ++op.enroll.delegateISEtoken.keyGen.signing.serverKeygen.archive=false ++op.enroll.delegateISEtoken.keyGen.signing.serverKeygen.drm.conn=kra1 ++op.enroll.delegateISEtoken.keyGen.signing.serverKeygen.enable=false + op.enroll.delegateISEtoken.keyGen.tokenName=$auth.cn$ + op.enroll.delegateISEtoken.loginRequest.enable=true + op.enroll.delegateISEtoken.pinReset.enable=true +@@ -736,12 +745,12 @@ op.enroll.externalRegAddToToken.keyGen.encryption.public.keyCapabilities.wrap=tr + op.enroll.externalRegAddToToken.keyGen.encryption.recovery.destroyed.revokeCert=false + op.enroll.externalRegAddToToken.keyGen.encryption.recovery.keyCompromise.revokeCert=false + op.enroll.externalRegAddToToken.keyGen.encryption.recovery.onHold.revokeCert=false +-op.enroll.externalRegAddToToken.keyGen.signing.recovery.destroyed.revokeCert=false +-op.enroll.externalRegAddToToken.keyGen.signing.recovery.keyCompromise.revokeCert=false +-op.enroll.externalRegAddToToken.keyGen.signing.recovery.onHold.revokeCert=false ++op.enroll.externalRegAddToToken.keyGen.encryption.recovery.destroyed.revokeCert=false ++op.enroll.externalRegAddToToken.keyGen.encryption.recovery.keyCompromise.revokeCert=false ++op.enroll.externalRegAddToToken.keyGen.encryption.recovery.onHold.revokeCert=false + op.enroll.externalRegAddToToken.keyGen.encryption.serverKeygen.archive=true + op.enroll.externalRegAddToToken.keyGen.encryption.serverKeygen.drm.conn=kra1 +-op.enroll.externalRegAddToToken.keyGen.encryption.serverKeygen.enable=true ++op.enroll.externalRegAddToToken.keyGen.encryption.serverKeygen.enable=[SERVER_KEYGEN] + op.enroll.externalRegAddToToken.keyGen.tokenName=$auth.cn$ + op.enroll.externalRegAddToToken.loginRequest.enable=true + op.enroll.externalRegAddToToken.pkcs11obj.compress.enable=true +@@ -894,6 +903,9 @@ op.enroll.soKey.keyGen.signing.recovery.keyCompromise.scheme=GenerateNewKey + op.enroll.soKey.keyGen.signing.recovery.onHold.revokeCert.reason=6 + op.enroll.soKey.keyGen.signing.recovery.onHold.revokeCert=true + op.enroll.soKey.keyGen.signing.recovery.onHold.scheme=GenerateNewKey ++op.enroll.soKey.keyGen.signing.serverKeygen.archive=false ++op.enroll.soKey.keyGen.signing.serverKeygen.drm.conn=kra1 ++op.enroll.soKey.keyGen.signing.serverKeygen.enable=false + op.enroll.soKey.keyGen.tokenName=$auth.cn$ + op.enroll.soKey.loginRequest.enable=true + op.enroll.soKey.pinReset.enable=true +@@ -948,6 +960,9 @@ op.enroll.soKeyTemporary.keyGen.auth.public.keyCapabilities.unwrap=false + op.enroll.soKeyTemporary.keyGen.auth.public.keyCapabilities.verifyRecover=true + op.enroll.soKeyTemporary.keyGen.auth.public.keyCapabilities.verify=true + op.enroll.soKeyTemporary.keyGen.auth.public.keyCapabilities.wrap=false ++op.enroll.soKeyTemporary.keyGen.auth.serverKeygen.archive=false ++op.enroll.soKeyTemporary.keyGen.auth.serverKeygen.drm.conn=kra1 ++op.enroll.soKeyTemporary.keyGen.auth.serverKeygen.enable=false + op.enroll.soKeyTemporary.keyGen.auth.publicKeyNumber=1 + op.enroll.soKeyTemporary.keyGen.encryption.ca.conn=ca1 + op.enroll.soKeyTemporary.keyGen.encryption.ca.profileId=caTempTokenUserEncryptionKeyEnrollment +@@ -992,7 +1007,7 @@ op.enroll.soKeyTemporary.keyGen.encryption.recovery.onHold.revokeCert=true + op.enroll.soKeyTemporary.keyGen.encryption.recovery.onHold.scheme=RecoverLast + op.enroll.soKeyTemporary.keyGen.encryption.serverKeygen.archive=true + op.enroll.soKeyTemporary.keyGen.encryption.serverKeygen.drm.conn=kra1 +-op.enroll.soKeyTemporary.keyGen.encryption.serverKeygen.enable=true ++op.enroll.soKeyTemporary.keyGen.encryption.serverKeygen.enable=[SERVER_KEYGEN] + op.enroll.soKeyTemporary.keyGen.keyType.num=3 + op.enroll.soKeyTemporary.keyGen.keyType.value.0=auth + op.enroll.soKeyTemporary.keyGen.keyType.value.1=signing +@@ -1041,6 +1056,9 @@ op.enroll.soKeyTemporary.keyGen.signing.publicKeyNumber=3 + op.enroll.soKeyTemporary.keyGen.signing.recovery.onHold.revokeCert.reason=0 + op.enroll.soKeyTemporary.keyGen.signing.recovery.onHold.revokeCert=true + op.enroll.soKeyTemporary.keyGen.signing.recovery.onHold.scheme=GenerateNewKey ++op.enroll.soKeyTemporary.keyGen.signing.serverKeygen.archive=false ++op.enroll.soKeyTemporary.keyGen.signing.serverKeygen.drm.conn=kra1 ++op.enroll.soKeyTemporary.keyGen.signing.serverKeygen.enable=false + op.enroll.soKeyTemporary.keyGen.tokenName=$auth.cn$ (Temporary) + op.enroll.soKeyTemporary.loginRequest.enable=true + op.enroll.soKeyTemporary.pinReset.enable=true +@@ -1187,6 +1205,9 @@ op.enroll.userKey.keyGen.signing.recovery.keyCompromise.scheme=GenerateNewKey + op.enroll.userKey.keyGen.signing.recovery.onHold.revokeCert.reason=6 + op.enroll.userKey.keyGen.signing.recovery.onHold.revokeCert=true + op.enroll.userKey.keyGen.signing.recovery.onHold.scheme=GenerateNewKey ++op.enroll.userKey.keyGen.signing.serverKeygen.archive=false ++op.enroll.userKey.keyGen.signing.serverKeygen.drm.conn=kra1 ++op.enroll.userKey.keyGen.signing.serverKeygen.enable=false + op.enroll.userKey.keyGen.tokenName=$auth.cn$ + op.enroll.userKey.loginRequest.enable=true + op.enroll.userKey.pinReset.enable=true +@@ -1255,6 +1276,9 @@ op.enroll.userKeyTemporary.keyGen.auth.public.keyCapabilities.verifyRecover=true + op.enroll.userKeyTemporary.keyGen.auth.public.keyCapabilities.verify=true + op.enroll.userKeyTemporary.keyGen.auth.public.keyCapabilities.wrap=false + op.enroll.userKeyTemporary.keyGen.auth.publicKeyNumber=1 ++op.enroll.userKeyTemporary.keyGen.auth.serverKeygen.archive=false ++op.enroll.userKeyTemporary.keyGen.auth.serverKeygen.drm.conn=kra1 ++op.enroll.userKeyTemporary.keyGen.auth.serverKeygen.enable=false + op.enroll.userKeyTemporary.keyGen.encryption.ca.conn=ca1 + op.enroll.userKeyTemporary.keyGen.encryption.ca.profileId=caTempTokenUserEncryptionKeyEnrollment + op.enroll.userKeyTemporary.keyGen.encryption.certAttrId=c2 +@@ -1298,7 +1322,7 @@ op.enroll.userKeyTemporary.keyGen.encryption.recovery.onHold.revokeCert=true + op.enroll.userKeyTemporary.keyGen.encryption.recovery.onHold.scheme=RecoverLast + op.enroll.userKeyTemporary.keyGen.encryption.serverKeygen.archive=true + op.enroll.userKeyTemporary.keyGen.encryption.serverKeygen.drm.conn=kra1 +-op.enroll.userKeyTemporary.keyGen.encryption.serverKeygen.enable=true ++op.enroll.userKeyTemporary.keyGen.encryption.serverKeygen.enable=[SERVER_KEYGEN] + op.enroll.userKeyTemporary.keyGen.keyType.num=3 + op.enroll.userKeyTemporary.keyGen.keyType.value.0=auth + op.enroll.userKeyTemporary.keyGen.keyType.value.1=signing +@@ -1347,6 +1371,9 @@ op.enroll.userKeyTemporary.keyGen.signing.publicKeyNumber=3 + op.enroll.userKeyTemporary.keyGen.signing.recovery.onHold.revokeCert.reason=0 + op.enroll.userKeyTemporary.keyGen.signing.recovery.onHold.revokeCert=true + op.enroll.userKeyTemporary.keyGen.signing.recovery.onHold.scheme=GenerateNewKey ++op.enroll.userKeyTemporary.keyGen.signing.serverKeygen.archive=false ++op.enroll.userKeyTemporary.keyGen.signing.serverKeygen.drm.conn=kra1 ++op.enroll.userKeyTemporary.keyGen.signing.serverKeygen.enable=false + op.enroll.userKeyTemporary.keyGen.tokenName=$auth.cn$ (Temporary) + op.enroll.userKeyTemporary.loginRequest.enable=true + op.enroll.userKeyTemporary.pinReset.enable=true +-- +2.5.5 + + +From 8598a68ac954d1020f4e0063e257a20512961567 Mon Sep 17 00:00:00 2001 +From: "Endi S. Dewata" +Date: Tue, 21 Jun 2016 18:39:25 +0200 +Subject: Fixed KRA cloning issue. + +The pki pkcs12-import CLI has been modified not to import +certificates that already exist in the NSS database unless +specifically requested with the --overwrite parameter. This +will avoid changing the trust flags of the CA signing +certificate during KRA cloning. + +The some other classes have been modified to provide better +debugging information. + +https://fedorahosted.org/pki/ticket/2374 +--- + base/common/python/pki/cli/pkcs12.py | 19 +++++++++++++- + base/common/python/pki/nssdb.py | 22 ++++++++++++---- + .../netscape/cmstools/pkcs12/PKCS12ImportCLI.java | 6 +++-- + .../cms/servlet/csadmin/ConfigurationUtils.java | 29 ++++++++++++++++++++-- + .../cmscore/ldapconn/LdapJssSSLSocketFactory.java | 18 ++++++++------ + .../src/netscape/security/pkcs/PKCS12Util.java | 21 +++++++++++----- + 6 files changed, 91 insertions(+), 24 deletions(-) + +diff --git a/base/common/python/pki/cli/pkcs12.py b/base/common/python/pki/cli/pkcs12.py +index a7c32cc..3fcea35 100644 +--- a/base/common/python/pki/cli/pkcs12.py ++++ b/base/common/python/pki/cli/pkcs12.py +@@ -55,6 +55,7 @@ class PKCS12ImportCLI(pki.cli.CLI): + print(' --no-trust-flags Do not include trust flags') + print(' --no-user-certs Do not import user certificates') + print(' --no-ca-certs Do not import CA certificates') ++ print(' --overwrite Overwrite existing certificates') + print(' -v, --verbose Run in verbose mode.') + print(' --debug Run in debug mode.') + print(' --help Show help message.') +@@ -65,7 +66,7 @@ class PKCS12ImportCLI(pki.cli.CLI): + try: + opts, _ = getopt.gnu_getopt(args, 'v', [ + 'pkcs12-file=', 'pkcs12-password=', 'pkcs12-password-file=', +- 'no-trust-flags', 'no-user-certs', 'no-ca-certs', ++ 'no-trust-flags', 'no-user-certs', 'no-ca-certs', 'overwrite', + 'verbose', 'debug', 'help']) + + except getopt.GetoptError as e: +@@ -79,6 +80,7 @@ class PKCS12ImportCLI(pki.cli.CLI): + no_trust_flags = False + import_user_certs = True + import_ca_certs = True ++ overwrite = False + debug = False + + for o, a in opts: +@@ -100,6 +102,9 @@ class PKCS12ImportCLI(pki.cli.CLI): + elif o == '--no-ca-certs': + import_ca_certs = False + ++ elif o == '--overwrite': ++ overwrite = True ++ + elif o in ('-v', '--verbose'): + self.set_verbose(True) + +@@ -221,6 +226,15 @@ class PKCS12ImportCLI(pki.cli.CLI): + cert_id = cert_info['id'] + nickname = cert_info['nickname'] + ++ cert = nssdb.get_cert(nickname) ++ ++ if cert: ++ if not overwrite: ++ print('WARNING: cert %s already exists' % nickname) ++ continue ++ ++ nssdb.remove_cert(nickname) ++ + if 'trust_flags' in cert_info: + trust_flags = cert_info['trust_flags'] + else: +@@ -292,6 +306,9 @@ class PKCS12ImportCLI(pki.cli.CLI): + if no_trust_flags: + cmd.extend(['--no-trust-flags']) + ++ if overwrite: ++ cmd.extend(['--overwrite']) ++ + if self.verbose: + cmd.extend(['--verbose']) + +diff --git a/base/common/python/pki/nssdb.py b/base/common/python/pki/nssdb.py +index 0c27c3f..f563fd8 100644 +--- a/base/common/python/pki/nssdb.py ++++ b/base/common/python/pki/nssdb.py +@@ -423,12 +423,20 @@ class NSSDatabase(object): + output_format_option + ]) + +- cert_data = subprocess.check_output(cmd) ++ try: ++ cert_data = subprocess.check_output(cmd) ++ ++ if output_format == 'base64': ++ cert_data = base64.b64encode(cert_data) + +- if output_format == 'base64': +- cert_data = base64.b64encode(cert_data) ++ return cert_data + +- return cert_data ++ except subprocess.CalledProcessError: ++ # All certutil errors return the same code (i.e. 255). ++ # For now assume it was caused by missing certificate. ++ # TODO: Check error message. If it's caused by other ++ # issue, throw exception. ++ return None + + def remove_cert(self, nickname): + +@@ -576,7 +584,8 @@ class NSSDatabase(object): + pkcs12_password=None, + pkcs12_password_file=None, + no_user_certs=False, +- no_ca_certs=False): ++ no_ca_certs=False, ++ overwrite=False): + + tmpdir = tempfile.mkdtemp() + +@@ -613,6 +622,9 @@ class NSSDatabase(object): + if no_ca_certs: + cmd.extend(['--no-ca-certs']) + ++ if overwrite: ++ cmd.extend(['--overwrite']) ++ + subprocess.check_call(cmd) + + finally: +diff --git a/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12ImportCLI.java b/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12ImportCLI.java +index ae574d3..862fffb 100644 +--- a/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12ImportCLI.java ++++ b/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12ImportCLI.java +@@ -61,6 +61,7 @@ public class PKCS12ImportCLI extends CLI { + options.addOption(option); + + options.addOption(null, "no-trust-flags", false, "Do not include trust flags"); ++ options.addOption(null, "overwrite", false, "Overwrite existing certificates"); + + options.addOption("v", "verbose", false, "Run in verbose mode."); + options.addOption(null, "debug", false, "Run in debug mode."); +@@ -125,6 +126,7 @@ public class PKCS12ImportCLI extends CLI { + Password password = new Password(passwordString.toCharArray()); + + boolean trustFlagsEnabled = !cmd.hasOption("no-trust-flags"); ++ boolean overwrite = cmd.hasOption("overwrite"); + + try { + PKCS12Util util = new PKCS12Util(); +@@ -134,12 +136,12 @@ public class PKCS12ImportCLI extends CLI { + + if (nicknames.length == 0) { + // store all certificates +- util.storeIntoNSS(pkcs12); ++ util.storeIntoNSS(pkcs12, overwrite); + + } else { + // load specified certificates + for (String nickname : nicknames) { +- util.storeCertIntoNSS(pkcs12, nickname); ++ util.storeCertIntoNSS(pkcs12, nickname, overwrite); + } + } + +diff --git a/base/server/cms/src/com/netscape/cms/servlet/csadmin/ConfigurationUtils.java b/base/server/cms/src/com/netscape/cms/servlet/csadmin/ConfigurationUtils.java +index 2da4e48..308f3e7 100644 +--- a/base/server/cms/src/com/netscape/cms/servlet/csadmin/ConfigurationUtils.java ++++ b/base/server/cms/src/com/netscape/cms/servlet/csadmin/ConfigurationUtils.java +@@ -686,6 +686,7 @@ public class ConfigurationUtils { + public static boolean updateConfigEntries(String hostname, int port, boolean https, + String servlet, MultivaluedMap content, IConfigStore config) + throws Exception { ++ + CMS.debug("updateConfigEntries start"); + String c = post(hostname, port, https, servlet, content, null, null); + +@@ -704,6 +705,7 @@ public class ConfigurationUtils { + + cstype = config.getString("cs.type", ""); + ++ CMS.debug("Master's configuration:"); + Document doc = parser.getDocument(); + NodeList list = doc.getElementsByTagName("name"); + int len = list.getLength(); +@@ -711,9 +713,12 @@ public class ConfigurationUtils { + Node n = list.item(i); + NodeList nn = n.getChildNodes(); + String name = nn.item(0).getNodeValue(); ++ CMS.debug(" - " + name); ++ + Node parent = n.getParentNode(); + nn = parent.getChildNodes(); + int len1 = nn.getLength(); ++ + String v = ""; + for (int j = 0; j < len1; j++) { + Node nv = nn.item(j); +@@ -729,33 +734,43 @@ public class ConfigurationUtils { + if (name.equals("internaldb.basedn")) { + config.putString(name, v); + config.putString("preop.internaldb.master.basedn", v); ++ + } else if (name.startsWith("internaldb")) { + config.putString(name.replaceFirst("internaldb", "preop.internaldb.master"), v); ++ + } else if (name.equals("instanceId")) { + config.putString("preop.master.instanceId", v); ++ + } else if (name.equals("cloning.signing.nickname")) { + config.putString("preop.master.signing.nickname", v); + config.putString("preop.cert.signing.nickname", v); ++ + } else if (name.equals("cloning.ocsp_signing.nickname")) { + config.putString("preop.master.ocsp_signing.nickname", v); + config.putString("preop.cert.ocsp_signing.nickname", v); ++ + } else if (name.equals("cloning.subsystem.nickname")) { + config.putString("preop.master.subsystem.nickname", v); + config.putString("preop.cert.subsystem.nickname", v); ++ + } else if (name.equals("cloning.transport.nickname")) { + config.putString("preop.master.transport.nickname", v); + config.putString("kra.transportUnit.nickName", v); + config.putString("preop.cert.transport.nickname", v); ++ + } else if (name.equals("cloning.storage.nickname")) { + config.putString("preop.master.storage.nickname", v); + config.putString("kra.storageUnit.nickName", v); + config.putString("preop.cert.storage.nickname", v); ++ + } else if (name.equals("cloning.audit_signing.nickname")) { + config.putString("preop.master.audit_signing.nickname", v); + config.putString("preop.cert.audit_signing.nickname", v); + config.putString(name, v); ++ + } else if (name.startsWith("cloning.ca")) { + config.putString(name.replaceFirst("cloning", "preop"), v); ++ + } else if (name.equals("cloning.signing.keyalgorithm")) { + config.putString(name.replaceFirst("cloning", "preop.cert"), v); + if (cstype.equals("CA")) { +@@ -767,13 +782,16 @@ public class ConfigurationUtils { + } else if (name.equals("cloning.transport.keyalgorithm")) { + config.putString(name.replaceFirst("cloning", "preop.cert"), v); + config.putString("kra.transportUnit.signingAlgorithm", v); ++ + } else if (name.equals("cloning.ocsp_signing.keyalgorithm")) { + config.putString(name.replaceFirst("cloning", "preop.cert"), v); + if (cstype.equals("CA")) { + config.putString("ca.ocsp_signing.defaultSigningAlgorithm", v); + } ++ + } else if (name.startsWith("cloning")) { + config.putString(name.replaceFirst("cloning", "preop.cert"), v); ++ + } else { + config.putString(name, v); + } +@@ -1183,12 +1201,15 @@ public class ConfigurationUtils { + return org.mozilla.jss.crypto.PrivateKey.Type.RSA; + } + +- public static boolean isCASigningCert(String name) { ++ public static boolean isCASigningCert(String name) throws EBaseException { + IConfigStore cs = CMS.getConfigStore(); + try { + String nickname = cs.getString("preop.master.signing.nickname"); ++ CMS.debug("Property preop.master.signing.nickname: " + nickname); + if (nickname.equals(name)) return true; +- } catch(Exception e) { ++ ++ } catch (EPropertyNotFound e) { ++ CMS.debug("Property preop.master.signing.nickname not found -> cert " + name + " is not CA signing cert"); + // nickname may not exist if this is not cloning a CA + }; + +@@ -1245,6 +1266,8 @@ public class ConfigurationUtils { + IConfigStore cs = CMS.getConfigStore(); + String certList = cs.getString("preop.cert.list", ""); + StringTokenizer st = new StringTokenizer(certList, ","); ++ ++ CMS.debug("Master certs:"); + while (st.hasMoreTokens()) { + String s = st.nextToken(); + if (s.equals("sslserver")) +@@ -1256,7 +1279,9 @@ public class ConfigurationUtils { + name = "preop.cert." + s + ".dn"; + String dn = cs.getString(name); + list.add(dn); ++ CMS.debug(" - " + name + ": " + dn); + } ++ + return list; + } + +diff --git a/base/server/cmscore/src/com/netscape/cmscore/ldapconn/LdapJssSSLSocketFactory.java b/base/server/cmscore/src/com/netscape/cmscore/ldapconn/LdapJssSSLSocketFactory.java +index 720882a..182812c 100644 +--- a/base/server/cmscore/src/com/netscape/cmscore/ldapconn/LdapJssSSLSocketFactory.java ++++ b/base/server/cmscore/src/com/netscape/cmscore/ldapconn/LdapJssSSLSocketFactory.java +@@ -21,9 +21,6 @@ import java.io.IOException; + import java.net.Socket; + import java.net.UnknownHostException; + +-import netscape.ldap.LDAPException; +-import netscape.ldap.LDAPSSLSocketFactoryExt; +- + import org.mozilla.jss.ssl.SSLHandshakeCompletedEvent; + import org.mozilla.jss.ssl.SSLHandshakeCompletedListener; + import org.mozilla.jss.ssl.SSLSocket; +@@ -31,6 +28,9 @@ import org.mozilla.jss.ssl.SSLSocket; + import com.netscape.certsrv.apps.CMS; + import com.netscape.certsrv.logging.ILogger; + ++import netscape.ldap.LDAPException; ++import netscape.ldap.LDAPSSLSocketFactoryExt; ++ + /** + * Uses HCL ssl socket. + * +@@ -65,17 +65,18 @@ public class LdapJssSSLSocketFactory implements LDAPSSLSocketFactoryExt { + + if (mClientAuthCertNickname != null) { + mClientAuth = true; +- CMS.debug( +- "LdapJssSSLSocket set client auth cert nickname" + +- mClientAuthCertNickname); ++ CMS.debug("LdapJssSSLSocket: set client auth cert nickname " + ++ mClientAuthCertNickname); + s.setClientCertNickname(mClientAuthCertNickname); + } + s.forceHandshake(); ++ + } catch (UnknownHostException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSCORE_LDAPCONN_UNKNOWN_HOST")); + throw new LDAPException( +- "Cannot Create JSS SSL Socket - Unknown host"); ++ "Cannot Create JSS SSL Socket - Unknown host: " + e); ++ + } catch (IOException e) { + if (s != null) { + try { +@@ -85,8 +86,9 @@ public class LdapJssSSLSocketFactory implements LDAPSSLSocketFactoryExt { + } + } + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_LDAPCONN_IO_ERROR", e.toString())); +- throw new LDAPException("IO Error creating JSS SSL Socket"); ++ throw new LDAPException("IO Error creating JSS SSL Socket: " + e); + } ++ + return s; + } + +diff --git a/base/util/src/netscape/security/pkcs/PKCS12Util.java b/base/util/src/netscape/security/pkcs/PKCS12Util.java +index b1b0f07..178a861 100644 +--- a/base/util/src/netscape/security/pkcs/PKCS12Util.java ++++ b/base/util/src/netscape/security/pkcs/PKCS12Util.java +@@ -635,14 +635,23 @@ public class PKCS12Util { + wrapper.unwrapPrivate(encpkey, getPrivateKeyType(publicKey), publicKey); + } + +- public void storeCertIntoNSS(PKCS12 pkcs12, PKCS12CertInfo certInfo) throws Exception { ++ public void storeCertIntoNSS(PKCS12 pkcs12, PKCS12CertInfo certInfo, boolean overwrite) throws Exception { + + CryptoManager cm = CryptoManager.getInstance(); ++ CryptoToken ct = cm.getInternalKeyStorageToken(); ++ CryptoStore store = ct.getCryptoStore(); + +- X509Certificate cert; + BigInteger id = certInfo.getID(); + PKCS12KeyInfo keyInfo = pkcs12.getKeyInfoByID(id); + ++ for (X509Certificate cert : cm.findCertsByNickname(certInfo.nickname)) { ++ if (!overwrite) { ++ return; ++ } ++ store.deleteCert(cert); ++ } ++ ++ X509Certificate cert; + if (keyInfo != null) { // cert has key + logger.fine("Importing user key for " + certInfo.nickname); + importKey(pkcs12, keyInfo); +@@ -660,19 +669,19 @@ public class PKCS12Util { + setTrustFlags(cert, certInfo.trustFlags); + } + +- public void storeCertIntoNSS(PKCS12 pkcs12, String nickname) throws Exception { ++ public void storeCertIntoNSS(PKCS12 pkcs12, String nickname, boolean overwrite) throws Exception { + Collection certInfos = pkcs12.getCertInfosByNickname(nickname); + for (PKCS12CertInfo certInfo : certInfos) { +- storeCertIntoNSS(pkcs12, certInfo); ++ storeCertIntoNSS(pkcs12, certInfo, overwrite); + } + } + +- public void storeIntoNSS(PKCS12 pkcs12) throws Exception { ++ public void storeIntoNSS(PKCS12 pkcs12, boolean overwrite) throws Exception { + + logger.info("Storing data into NSS database"); + + for (PKCS12CertInfo certInfo : pkcs12.getCertInfos()) { +- storeCertIntoNSS(pkcs12, certInfo); ++ storeCertIntoNSS(pkcs12, certInfo, overwrite); + } + } + } +-- +2.5.5 + + +From 00ac032c8995756f5bfdaab5a7f6ae441ac7dda3 Mon Sep 17 00:00:00 2001 +From: Matthew Harmsen +Date: Fri, 24 Jun 2016 14:39:59 -0600 +Subject: Normalize default softokn name + +- PKI TRAC Ticket #2311 - When pki_token_name=Internal, + consider normalizing it to "internal" +--- + base/server/python/pki/server/deployment/pkiparser.py | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/base/server/python/pki/server/deployment/pkiparser.py b/base/server/python/pki/server/deployment/pkiparser.py +index b1fc213..dc5d7f6 100644 +--- a/base/server/python/pki/server/deployment/pkiparser.py ++++ b/base/server/python/pki/server/deployment/pkiparser.py +@@ -1181,6 +1181,11 @@ class PKIConfigParser: + # self.mdict['pki_clone_pkcs12_path'] + # self.mdict['pki_clone_uri'] + # self.mdict['pki_security_domain_https_port'] ++ # ++ # The following variables are established via the specified PKI ++ # deployment configuration file and potentially "normalized" ++ # below: ++ # + # self.mdict['pki_token_name'] + # + # The following variables are established via the specified PKI +@@ -1191,6 +1196,11 @@ class PKIConfigParser: + # self.mdict['pki_issuing_ca'] + # + ++ # if the case insensitive softokn name is the 'default' value ++ if (self.mdict['pki_token_name'].lower() == "internal"): ++ # always normalize 'default' softokn name ++ self.mdict['pki_token_name'] = "internal" ++ + # if security domain user is not defined + if not len(self.mdict['pki_security_domain_user']): + +-- +2.5.5 + + +From 659c90869a27871eda27fd730d00b0499873dae2 Mon Sep 17 00:00:00 2001 +From: Christina Fu +Date: Tue, 28 Jun 2016 18:00:03 -0700 +Subject: Ticket 2389 Installation: subsystem certs could have notAfter beyond + CA signing cert in case of external or existing CA + +This patch implements validity check on the notAfter value of the certInfo +and adjusts it to that of the CA's notAfter if exceeding +--- + .../netscape/cms/profile/def/ValidityDefault.java | 23 ++++++++++++++++++++++ + .../com/netscape/cms/servlet/csadmin/CertUtil.java | 3 +++ + 2 files changed, 26 insertions(+) + +diff --git a/base/server/cms/src/com/netscape/cms/profile/def/ValidityDefault.java b/base/server/cms/src/com/netscape/cms/profile/def/ValidityDefault.java +index 634d070..21ec8ea 100644 +--- a/base/server/cms/src/com/netscape/cms/profile/def/ValidityDefault.java ++++ b/base/server/cms/src/com/netscape/cms/profile/def/ValidityDefault.java +@@ -26,6 +26,7 @@ import java.util.Locale; + + import com.netscape.certsrv.apps.CMS; + import com.netscape.certsrv.base.IConfigStore; ++import com.netscape.certsrv.ca.ICertificateAuthority; + import com.netscape.certsrv.profile.EProfileException; + import com.netscape.certsrv.profile.IProfile; + import com.netscape.certsrv.property.Descriptor; +@@ -34,6 +35,7 @@ import com.netscape.certsrv.property.IDescriptor; + import com.netscape.certsrv.request.IRequest; + + import netscape.security.x509.CertificateValidity; ++import netscape.security.x509.X509CertImpl; + import netscape.security.x509.X509CertInfo; + + /** +@@ -301,6 +303,27 @@ public class ValidityDefault extends EnrollDefault { + Date notAfter = date.getTime(); + CMS.debug("ValidityDefault: not after: " + notAfter); + ++ // check and fix notAfter if needed ++ // installAdjustValidity is set during installation if needed ++ boolean adjustValidity = ++ request.getExtDataInBoolean("installAdjustValidity", false); ++ if (adjustValidity) { ++ CMS.debug("ValidityDefault: populate: adjustValidity is true"); ++ ICertificateAuthority ca = (ICertificateAuthority) ++ CMS.getSubsystem(CMS.SUBSYSTEM_CA); ++ try { ++ X509CertImpl caCert = ca.getCACert(); ++ Date caNotAfter = caCert.getNotAfter(); ++ if (notAfter.after(caNotAfter)) { ++ notAfter = caNotAfter; ++ CMS.debug("ValidityDefault: populate: resetting notAfter to caNotAfter"); ++ } ++ } catch (Exception e) { ++ throw new EProfileException( ++ "Unable to get ca certificate: " + e.getMessage(), e); ++ } ++ } ++ + CertificateValidity validity = + new CertificateValidity(notBefore, notAfter); + +diff --git a/base/server/cms/src/com/netscape/cms/servlet/csadmin/CertUtil.java b/base/server/cms/src/com/netscape/cms/servlet/csadmin/CertUtil.java +index 774ff94..495e4c0 100644 +--- a/base/server/cms/src/com/netscape/cms/servlet/csadmin/CertUtil.java ++++ b/base/server/cms/src/com/netscape/cms/servlet/csadmin/CertUtil.java +@@ -535,6 +535,9 @@ public class CertUtil { + CMS.debug("Creating local request exception:" + e.toString()); + } + ++ // installAdjustValidity tells ValidityDefault to adjust the ++ // notAfter value to that of the CA's signing cert if needed ++ req.setExtData("installAdjustValidity", "true"); + processor.populate(req, info); + + PrivateKey caPrik = null; +-- +2.5.5 + + +From 63a58cf51ef2982e8a35eff1f98dd42453e5681e Mon Sep 17 00:00:00 2001 +From: Christina Fu +Date: Thu, 30 Jun 2016 14:03:24 -0700 +Subject: Ticket #1306 config params: Add granularity to token termination in + TPS + +This patch adds the missing configuration parameters that go with the +original bug. The code would take on defaults when these parameters are +missing, but putting them in the CS.cfg would make it easier for the +administrators. +--- + base/tps/shared/conf/CS.cfg | 123 ++++++++++++++++++++++++++++++++++++++++++-- + 1 file changed, 119 insertions(+), 4 deletions(-) + +diff --git a/base/tps/shared/conf/CS.cfg b/base/tps/shared/conf/CS.cfg +index 258d5a7..4f2b391 100644 +--- a/base/tps/shared/conf/CS.cfg ++++ b/base/tps/shared/conf/CS.cfg +@@ -265,7 +265,20 @@ op.enroll._000=######################################### + op.enroll._001=# TPS Profiles + op.enroll._002=# - Operations + op.enroll._003=# - operation; enroll,pinReset,format +-op.enroll._004=######################################### ++op.enroll._004=# ++op.enroll._005=# Revocation Reasons (revokeCert.reason) according to RFC 5280 ++op.enroll._006=# unspecified (0) ++op.enroll._007=# keyCompromise (1) ++op.enroll._008=# CACompromise (2) ++op.enroll._009=# affiliationChanged (3) ++op.enroll._010=# superseded (4) ++op.enroll._011=# cessationOfOperation (5) ++op.enroll._012=# certificateHold (6) ++op.enroll._013=# removeFromCRL (8) ++op.enroll._014=# privilegeWithdrawn (9) ++op.enroll._015=# AACompromise (10) ++op.enroll._016=# ++op.enroll._017=######################################### + op.enroll.delegateIEtoken._000=######################################### + op.enroll.delegateIEtoken._001=# Enrollment for externalReg + op.enroll.delegateIEtoken._002=# ID, Encryption +@@ -326,12 +339,23 @@ op.enroll.delegateIEtoken.keyGen.authentication.publicKeyNumber=7 + op.enroll.delegateIEtoken.keyGen.authentication.recovery.destroyed.revokeCert=false + op.enroll.delegateIEtoken.keyGen.authentication.recovery.destroyed.revokeCert.reason=0 + op.enroll.delegateIEtoken.keyGen.authentication.recovery.destroyed.scheme=GenerateNewKey ++op.enroll.delegateIEtoken.keyGen.authentication.recovery.destroyed.holdRevocationUntilLastCredential=false ++op.enroll.delegateIEtoken.keyGen.authentication.recovery.destroyed.revokeExpiredCerts=false + op.enroll.delegateIEtoken.keyGen.authentication.recovery.keyCompromise.revokeCert=false + op.enroll.delegateIEtoken.keyGen.authentication.recovery.keyCompromise.revokeCert.reason=1 + op.enroll.delegateIEtoken.keyGen.authentication.recovery.keyCompromise.scheme=GenerateNewKey ++op.enroll.delegateIEtoken.keyGen.authentication.recovery.keyCompromise.holdRevocationUntilLastCredential=false ++op.enroll.delegateIEtoken.keyGen.authentication.recovery.keyCompromise.revokeExpiredCerts=false ++op.enroll.delegateIEtoken.keyGen.authentication.recovery.terminated.revokeCert=true ++op.enroll.delegateIEtoken.keyGen.authentication.recovery.terminated.revokeCert.reason=1 ++op.enroll.delegateIEtoken.keyGen.authentication.recovery.terminated.scheme=GenerateNewKey ++op.enroll.delegateIEtoken.keyGen.authentication.recovery.terminated.holdRevocationUntilLastCredential=false ++op.enroll.delegateIEtoken.keyGen.authentication.recovery.terminated.revokeExpiredCerts=false + op.enroll.delegateIEtoken.keyGen.authentication.recovery.onHold.revokeCert=false + op.enroll.delegateIEtoken.keyGen.authentication.recovery.onHold.revokeCert.reason=6 + op.enroll.delegateIEtoken.keyGen.authentication.recovery.onHold.scheme=GenerateNewKey ++op.enroll.delegateIEtoken.keyGen.authentication.recovery.onHold.holdRevocationUntilLastCredential=false ++op.enroll.delegateIEtoken.keyGen.authentication.recovery.onHold.revokeExpiredCerts=false + op.enroll.delegateIEtoken.keyGen.authentication.serverKeygen.archive=false + op.enroll.delegateIEtoken.keyGen.authentication.serverKeygen.drm.conn=kra1 + op.enroll.delegateIEtoken.keyGen.authentication.serverKeygen.enable=false +@@ -498,12 +522,23 @@ op.enroll.delegateISEtoken.keyGen.authentication.publicKeyNumber=7 + op.enroll.delegateISEtoken.keyGen.authentication.recovery.destroyed.revokeCert=false + op.enroll.delegateISEtoken.keyGen.authentication.recovery.destroyed.revokeCert.reason=0 + op.enroll.delegateISEtoken.keyGen.authentication.recovery.destroyed.scheme=GenerateNewKey ++op.enroll.delegateISEtoken.keyGen.authentication.recovery.destroyed.holdRevocationUntilLastCredential=false ++op.enroll.delegateISEtoken.keyGen.authentication.recovery.destroyed.revokeExpiredCerts=false + op.enroll.delegateISEtoken.keyGen.authentication.recovery.keyCompromise.revokeCert=false + op.enroll.delegateISEtoken.keyGen.authentication.recovery.keyCompromise.revokeCert.reason=1 + op.enroll.delegateISEtoken.keyGen.authentication.recovery.keyCompromise.scheme=GenerateNewKey ++op.enroll.delegateISEtoken.keyGen.authentication.recovery.keyCompromise.holdRevocationUntilLastCredential=false ++op.enroll.delegateISEtoken.keyGen.authentication.recovery.keyCompromise.revokeExpiredCerts=false ++op.enroll.delegateISEtoken.keyGen.authentication.recovery.terminated.revokeCert=true ++op.enroll.delegateISEtoken.keyGen.authentication.recovery.terminated.revokeCert.reason=1 ++op.enroll.delegateISEtoken.keyGen.authentication.recovery.terminated.scheme=GenerateNewKey ++op.enroll.delegateISEtoken.keyGen.authentication.recovery.terminated.holdRevocationUntilLastCredential=false ++op.enroll.delegateISEtoken.keyGen.authentication.recovery.terminated.revokeExpiredCerts=false + op.enroll.delegateISEtoken.keyGen.authentication.recovery.onHold.revokeCert=false + op.enroll.delegateISEtoken.keyGen.authentication.recovery.onHold.revokeCert.reason=6 + op.enroll.delegateISEtoken.keyGen.authentication.recovery.onHold.scheme=GenerateNewKey ++op.enroll.delegateISEtoken.keyGen.authentication.recovery.onHold.holdRevocationUntilLastCredential=false ++op.enroll.delegateISEtoken.keyGen.authentication.recovery.onHold.revokeExpiredCerts=false + op.enroll.delegateISEtoken.keyGen.authentication.serverKeygen.archive=false + op.enroll.delegateISEtoken.keyGen.authentication.serverKeygen.drm.conn=kra1 + op.enroll.delegateISEtoken.keyGen.authentication.serverKeygen.enable=false +@@ -554,12 +589,23 @@ op.enroll.delegateISEtoken.keyGen.encryption.publicKeyNumber=5 + op.enroll.delegateISEtoken.keyGen.encryption.recovery.destroyed.revokeCert=false + op.enroll.delegateISEtoken.keyGen.encryption.recovery.destroyed.revokeCert.reason=0 + op.enroll.delegateISEtoken.keyGen.encryption.recovery.destroyed.scheme=RecoverLast ++op.enroll.delegateISEtoken.keyGen.encryption.recovery.destroyed.holdRevocationUntilLastCredential=false ++op.enroll.delegateISEtoken.keyGen.encryption.recovery.destroyed.revokeExpiredCerts=false + op.enroll.delegateISEtoken.keyGen.encryption.recovery.keyCompromise.revokeCert=false + op.enroll.delegateISEtoken.keyGen.encryption.recovery.keyCompromise.revokeCert.reason=1 + op.enroll.delegateISEtoken.keyGen.encryption.recovery.keyCompromise.scheme=GenerateNewKey ++op.enroll.delegateISEtoken.keyGen.encryption.recovery.keyCompromise.holdRevocationUntilLastCredential=false ++op.enroll.delegateISEtoken.keyGen.encryption.recovery.keyCompromise.revokeExpiredCerts=false ++op.enroll.delegateISEtoken.keyGen.encryption.recovery.terminated.revokeCert=true ++op.enroll.delegateISEtoken.keyGen.encryption.recovery.terminated.revokeCert.reason=1 ++op.enroll.delegateISEtoken.keyGen.encryption.recovery.terminated.scheme=GenerateNewKey ++op.enroll.delegateISEtoken.keyGen.encryption.recovery.terminated.holdRevocationUntilLastCredential=false ++op.enroll.delegateISEtoken.keyGen.encryption.recovery.terminated.revokeExpiredCerts=false + op.enroll.delegateISEtoken.keyGen.encryption.recovery.onHold.revokeCert=false + op.enroll.delegateISEtoken.keyGen.encryption.recovery.onHold.revokeCert.reason=6 + op.enroll.delegateISEtoken.keyGen.encryption.recovery.onHold.scheme=GenerateNewKey ++op.enroll.delegateISEtoken.keyGen.encryption.recovery.onHold.holdRevocationUntilLastCredential=false ++op.enroll.delegateISEtoken.keyGen.encryption.recovery.onHold.revokeExpiredCerts=false + op.enroll.delegateISEtoken.keyGen.encryption.serverKeygen.archive=true + op.enroll.delegateISEtoken.keyGen.encryption.serverKeygen.drm.conn=kra1 + op.enroll.delegateISEtoken.keyGen.encryption.serverKeygen.enable=[SERVER_KEYGEN] +@@ -618,12 +664,23 @@ op.enroll.delegateISEtoken.keyGen.signing.publicKeyNumber=3 + op.enroll.delegateISEtoken.keyGen.signing.recovery.destroyed.revokeCert=false + op.enroll.delegateISEtoken.keyGen.signing.recovery.destroyed.revokeCert.reason=0 + op.enroll.delegateISEtoken.keyGen.signing.recovery.destroyed.scheme=GenerateNewKey ++op.enroll.delegateISEtoken.keyGen.signing.recovery.destroyed.holdRevocationUntilLastCredential=false ++op.enroll.delegateISEtoken.keyGen.signing.recovery.destroyed.revokeExpiredCerts=false + op.enroll.delegateISEtoken.keyGen.signing.recovery.keyCompromise.revokeCert=false + op.enroll.delegateISEtoken.keyGen.signing.recovery.keyCompromise.revokeCert.reason=1 + op.enroll.delegateISEtoken.keyGen.signing.recovery.keyCompromise.scheme=GenerateNewKey ++op.enroll.delegateISEtoken.keyGen.signing.recovery.keyCompromise.holdRevocationUntilLastCredential=false ++op.enroll.delegateISEtoken.keyGen.signing.recovery.keyCompromise.revokeExpiredCerts=false ++op.enroll.delegateISEtoken.keyGen.signing.recovery.terminated.revokeCert=true ++op.enroll.delegateISEtoken.keyGen.signing.recovery.terminated.revokeCert.reason=1 ++op.enroll.delegateISEtoken.keyGen.signing.recovery.terminated.scheme=GenerateNewKey ++op.enroll.delegateISEtoken.keyGen.signing.recovery.terminated.holdRevocationUntilLastCredential=false ++op.enroll.delegateISEtoken.keyGen.signing.recovery.terminated.revokeExpiredCerts=false + op.enroll.delegateISEtoken.keyGen.signing.recovery.onHold.revokeCert=false + op.enroll.delegateISEtoken.keyGen.signing.recovery.onHold.revokeCert.reason=6 + op.enroll.delegateISEtoken.keyGen.signing.recovery.onHold.scheme=GenerateNewKey ++op.enroll.delegateISEtoken.keyGen.signing.recovery.onHold.holdRevocationUntilLastCredential=false ++op.enroll.delegateISEtoken.keyGen.signing.recovery.onHold.revokeExpiredCerts=false + op.enroll.delegateISEtoken.keyGen.signing.serverKeygen.archive=false + op.enroll.delegateISEtoken.keyGen.signing.serverKeygen.drm.conn=kra1 + op.enroll.delegateISEtoken.keyGen.signing.serverKeygen.enable=false +@@ -743,11 +800,25 @@ op.enroll.externalRegAddToToken.keyGen.encryption.public.keyCapabilities.verify= + op.enroll.externalRegAddToToken.keyGen.encryption.public.keyCapabilities.verifyRecover=false + op.enroll.externalRegAddToToken.keyGen.encryption.public.keyCapabilities.wrap=true + op.enroll.externalRegAddToToken.keyGen.encryption.recovery.destroyed.revokeCert=false ++op.enroll.externalRegAddToToken.keyGen.encryption.recovery.destroyed.revokeCert.reason=0 ++op.enroll.externalRegAddToToken.keyGen.encryption.recovery.destroyed.scheme=GenerateNewKey ++op.enroll.externalRegAddToToken.keyGen.encryption.recovery.destroyed.holdRevocationUntilLastCredential=false ++op.enroll.externalRegAddToToken.keyGen.encryption.recovery.destroyed.revokeExpiredCerts=false + op.enroll.externalRegAddToToken.keyGen.encryption.recovery.keyCompromise.revokeCert=false ++op.enroll.externalRegAddToToken.keyGen.encryption.recovery.keyCompromise.revokeCert.reason=1 ++op.enroll.externalRegAddToToken.keyGen.encryption.recovery.keyCompromise.scheme=GenerateNewKey ++op.enroll.externalRegAddToToken.keyGen.encryption.recovery.keyCompromise.holdRevocationUntilLastCredential=false ++op.enroll.externalRegAddToToken.keyGen.encryption.recovery.keyCompromise.revokeExpiredCerts=false ++op.enroll.externalRegAddToToken.keyGen.encryption.recovery.terminated.revokeCert=true ++op.enroll.externalRegAddToToken.keyGen.encryption.recovery.terminated.revokeCert.reason=1 ++op.enroll.externalRegAddToToken.keyGen.encryption.recovery.terminated.scheme=GenerateNewKey ++op.enroll.externalRegAddToToken.keyGen.encryption.recovery.terminated.holdRevocationUntilLastCredential=false ++op.enroll.externalRegAddToToken.keyGen.encryption.recovery.terminated.revokeExpiredCerts=false + op.enroll.externalRegAddToToken.keyGen.encryption.recovery.onHold.revokeCert=false +-op.enroll.externalRegAddToToken.keyGen.encryption.recovery.destroyed.revokeCert=false +-op.enroll.externalRegAddToToken.keyGen.encryption.recovery.keyCompromise.revokeCert=false +-op.enroll.externalRegAddToToken.keyGen.encryption.recovery.onHold.revokeCert=false ++op.enroll.externalRegAddToToken.keyGen.encryption.recovery.onHold.revokeCert.reason=6 ++op.enroll.externalRegAddToToken.keyGen.encryption.recovery.onHold.scheme=GenerateNewKey ++op.enroll.externalRegAddToToken.keyGen.encryption.recovery.onHold.holdRevocationUntilLastCredential=false ++op.enroll.externalRegAddToToken.keyGen.encryption.recovery.onHold.revokeExpiredCerts=false + op.enroll.externalRegAddToToken.keyGen.encryption.serverKeygen.archive=true + op.enroll.externalRegAddToToken.keyGen.encryption.serverKeygen.drm.conn=kra1 + op.enroll.externalRegAddToToken.keyGen.encryption.serverKeygen.enable=[SERVER_KEYGEN] +@@ -835,12 +906,23 @@ op.enroll.soKey.keyGen.encryption.publicKeyNumber=5 + op.enroll.soKey.keyGen.encryption.recovery.destroyed.revokeCert=false + op.enroll.soKey.keyGen.encryption.recovery.destroyed.revokeCert.reason=0 + op.enroll.soKey.keyGen.encryption.recovery.destroyed.scheme=RecoverLast ++op.enroll.soKey.keyGen.encryption.recovery.destroyed.holdRevocationUntilLastCredential=false ++op.enroll.soKey.keyGen.encryption.recovery.destroyed.revokeExpiredCerts=false + op.enroll.soKey.keyGen.encryption.recovery.keyCompromise.revokeCert.reason=1 + op.enroll.soKey.keyGen.encryption.recovery.keyCompromise.revokeCert=true + op.enroll.soKey.keyGen.encryption.recovery.keyCompromise.scheme=GenerateNewKey ++op.enroll.soKey.keyGen.encryption.recovery.keyCompromise.holdRevocationUntilLastCredential=false ++op.enroll.soKey.keyGen.encryption.recovery.keyCompromise.revokeExpiredCerts=false ++op.enroll.soKey.keyGen.encryption.recovery.terminated.revokeCert.reason=1 ++op.enroll.soKey.keyGen.encryption.recovery.terminated.revokeCert=true ++op.enroll.soKey.keyGen.encryption.recovery.terminated.scheme=GenerateNewKey ++op.enroll.soKey.keyGen.encryption.recovery.terminated.holdRevocationUntilLastCredential=false ++op.enroll.soKey.keyGen.encryption.recovery.terminated.revokeExpiredCerts=false + op.enroll.soKey.keyGen.encryption.recovery.onHold.revokeCert.reason=6 + op.enroll.soKey.keyGen.encryption.recovery.onHold.revokeCert=true + op.enroll.soKey.keyGen.encryption.recovery.onHold.scheme=GenerateNewKey ++op.enroll.soKey.keyGen.encryption.recovery.onHold.holdRevocationUntilLastCredential=false ++op.enroll.soKey.keyGen.encryption.recovery.onHold.revokeExpiredCerts=false + op.enroll.soKey.keyGen.encryption.serverKeygen.archive=true + op.enroll.soKey.keyGen.encryption.serverKeygen.drm.conn=kra1 + op.enroll.soKey.keyGen.encryption.serverKeygen.enable=[SERVER_KEYGEN] +@@ -897,12 +979,23 @@ op.enroll.soKey.keyGen.signing.publicKeyNumber=3 + op.enroll.soKey.keyGen.signing.recovery.destroyed.revokeCert.reason=0 + op.enroll.soKey.keyGen.signing.recovery.destroyed.revokeCert=true + op.enroll.soKey.keyGen.signing.recovery.destroyed.scheme=GenerateNewKey ++op.enroll.soKey.keyGen.signing.recovery.destroyed.holdRevocationUntilLastCredential=false ++op.enroll.soKey.keyGen.signing.recovery.destroyed.revokeExpiredCerts=false + op.enroll.soKey.keyGen.signing.recovery.keyCompromise.revokeCert.reason=1 + op.enroll.soKey.keyGen.signing.recovery.keyCompromise.revokeCert=true + op.enroll.soKey.keyGen.signing.recovery.keyCompromise.scheme=GenerateNewKey ++op.enroll.soKey.keyGen.signing.recovery.keyCompromise.holdRevocationUntilLastCredential=false ++op.enroll.soKey.keyGen.signing.recovery.keyCompromise.revokeExpiredCerts=false ++op.enroll.soKey.keyGen.signing.recovery.terminated.revokeCert.reason=1 ++op.enroll.soKey.keyGen.signing.recovery.terminated.revokeCert=true ++op.enroll.soKey.keyGen.signing.recovery.terminated.scheme=GenerateNewKey ++op.enroll.soKey.keyGen.signing.recovery.terminated.holdRevocationUntilLastCredential=false ++op.enroll.soKey.keyGen.signing.recovery.terminated.revokeExpiredCerts=false + op.enroll.soKey.keyGen.signing.recovery.onHold.revokeCert.reason=6 + op.enroll.soKey.keyGen.signing.recovery.onHold.revokeCert=true + op.enroll.soKey.keyGen.signing.recovery.onHold.scheme=GenerateNewKey ++op.enroll.soKey.keyGen.signing.recovery.onHold.holdRevocationUntilLastCredential=false ++op.enroll.soKey.keyGen.signing.recovery.onHold.revokeExpiredCerts=false + op.enroll.soKey.keyGen.signing.serverKeygen.archive=false + op.enroll.soKey.keyGen.signing.serverKeygen.drm.conn=kra1 + op.enroll.soKey.keyGen.signing.serverKeygen.enable=false +@@ -1137,12 +1230,23 @@ op.enroll.userKey.keyGen.encryption.publicKeyNumber=5 + op.enroll.userKey.keyGen.encryption.recovery.destroyed.revokeCert=false + op.enroll.userKey.keyGen.encryption.recovery.destroyed.revokeCert.reason=0 + op.enroll.userKey.keyGen.encryption.recovery.destroyed.scheme=RecoverLast ++op.enroll.userKey.keyGen.encryption.recovery.destroyed.holdRevocationUntilLastCredential=false ++op.enroll.userKey.keyGen.encryption.recovery.destroyed.revokeExpiredCerts=false + op.enroll.userKey.keyGen.encryption.recovery.keyCompromise.revokeCert.reason=1 + op.enroll.userKey.keyGen.encryption.recovery.keyCompromise.revokeCert=true + op.enroll.userKey.keyGen.encryption.recovery.keyCompromise.scheme=GenerateNewKey ++op.enroll.userKey.keyGen.encryption.recovery.keyCompromise.holdRevocationUntilLastCredential=false ++op.enroll.userKey.keyGen.encryption.recovery.keyCompromise.revokeExpiredCerts=false ++op.enroll.userKey.keyGen.encryption.recovery.terminated.revokeCert.reason=1 ++op.enroll.userKey.keyGen.encryption.recovery.terminated.revokeCert=true ++op.enroll.userKey.keyGen.encryption.recovery.terminated.scheme=GenerateNewKey ++op.enroll.userKey.keyGen.encryption.recovery.terminated.holdRevocationUntilLastCredential=false ++op.enroll.userKey.keyGen.encryption.recovery.terminated.revokeExpiredCerts=false + op.enroll.userKey.keyGen.encryption.recovery.onHold.revokeCert.reason=6 + op.enroll.userKey.keyGen.encryption.recovery.onHold.revokeCert=true + op.enroll.userKey.keyGen.encryption.recovery.onHold.scheme=GenerateNewKey ++op.enroll.userKey.keyGen.encryption.recovery.onHold.holdRevocationUntilLastCredential=false ++op.enroll.userKey.keyGen.encryption.recovery.onHold.revokeExpiredCerts=false + op.enroll.userKey.keyGen.encryption.serverKeygen.archive=true + op.enroll.userKey.keyGen.encryption.serverKeygen.drm.conn=kra1 + op.enroll.userKey.keyGen.encryption.serverKeygen.enable=[SERVER_KEYGEN] +@@ -1199,12 +1303,23 @@ op.enroll.userKey.keyGen.signing.publicKeyNumber=3 + op.enroll.userKey.keyGen.signing.recovery.destroyed.revokeCert.reason=0 + op.enroll.userKey.keyGen.signing.recovery.destroyed.revokeCert=true + op.enroll.userKey.keyGen.signing.recovery.destroyed.scheme=GenerateNewKey ++op.enroll.userKey.keyGen.signing.recovery.destroyed.holdRevocationUntilLastCredential=false ++op.enroll.userKey.keyGen.signing.recovery.destroyed.revokeExpiredCerts=false + op.enroll.userKey.keyGen.signing.recovery.keyCompromise.revokeCert.reason=1 + op.enroll.userKey.keyGen.signing.recovery.keyCompromise.revokeCert=true + op.enroll.userKey.keyGen.signing.recovery.keyCompromise.scheme=GenerateNewKey ++op.enroll.userKey.keyGen.signing.recovery.keyCompromise.holdRevocationUntilLastCredential=false ++op.enroll.userKey.keyGen.signing.recovery.keyCompromise.revokeExpiredCerts=false ++op.enroll.userKey.keyGen.signing.recovery.terminated.revokeCert.reason=1 ++op.enroll.userKey.keyGen.signing.recovery.terminated.revokeCert=true ++op.enroll.userKey.keyGen.signing.recovery.terminated.scheme=GenerateNewKey ++op.enroll.userKey.keyGen.signing.recovery.terminated.holdRevocationUntilLastCredential=false ++op.enroll.userKey.keyGen.signing.recovery.terminated.revokeExpiredCerts=false + op.enroll.userKey.keyGen.signing.recovery.onHold.revokeCert.reason=6 + op.enroll.userKey.keyGen.signing.recovery.onHold.revokeCert=true + op.enroll.userKey.keyGen.signing.recovery.onHold.scheme=GenerateNewKey ++op.enroll.userKey.keyGen.signing.recovery.onHold.holdRevocationUntilLastCredential=false ++op.enroll.userKey.keyGen.signing.recovery.onHold.revokeExpiredCerts=false + op.enroll.userKey.keyGen.signing.serverKeygen.archive=false + op.enroll.userKey.keyGen.signing.serverKeygen.drm.conn=kra1 + op.enroll.userKey.keyGen.signing.serverKeygen.enable=false +-- +2.5.5 + + +From e326cd2f06bd651cdd87646eea94622e18cec28d Mon Sep 17 00:00:00 2001 +From: Jack Magne +Date: Fri, 24 Jun 2016 11:02:35 -0700 +Subject: Add ability to disallow TPS to enroll a single user on multiple + tokens. + +This patch will install a check during the early portion of the enrollment +process check a configurable policy whether or not a user should be allowed +to have more that one active token. + +This check will take place only for brand new tokens not seen before. +The check will prevent the enrollment to proceed and will exit before the system +has a chance to add this new token to the TPS tokendb. + +The behavior will be configurable for the the external reg and not external reg scenarios +as follows: + +tokendb.nonExternalReg.allowMultiActiveTokensUser=false +tokendb.enroll.externalReg.allowMultiActiveTokensUser=false +--- + base/tps/shared/conf/CS.cfg | 3 + + .../org/dogtagpki/server/tps/engine/TPSEngine.java | 3 + + .../server/tps/processor/TPSEnrollProcessor.java | 100 +++++++++++++++------ + 3 files changed, 80 insertions(+), 26 deletions(-) + +diff --git a/base/tps/shared/conf/CS.cfg b/base/tps/shared/conf/CS.cfg +index 4f2b391..a8499a2 100644 +--- a/base/tps/shared/conf/CS.cfg ++++ b/base/tps/shared/conf/CS.cfg +@@ -2169,6 +2169,9 @@ tokendb.ssl=false + tokendb.templateDir=[PKI_INSTANCE_PATH]/docroot/tus + tokendb.userBaseDN=[TOKENDB_ROOT] + tokendb.userDeleteTemplate=userDelete.template ++tokendb.nonExternalReg.allowMultiActiveTokensUser=false ++tokendb.externalReg.allowMultiActiveTokensUser=false ++ + tps._000=######################################## + tps._001=# For verifying system certificates + tps._002=# tps.cert.list=sslserver,subsystem,audit_signing +diff --git a/base/tps/src/org/dogtagpki/server/tps/engine/TPSEngine.java b/base/tps/src/org/dogtagpki/server/tps/engine/TPSEngine.java +index a5fbc3b..93edfde 100644 +--- a/base/tps/src/org/dogtagpki/server/tps/engine/TPSEngine.java ++++ b/base/tps/src/org/dogtagpki/server/tps/engine/TPSEngine.java +@@ -91,6 +91,7 @@ public class TPSEngine { + public static final String CFG_ERROR_PREFIX = "logging.error"; + public static final String CFG_DEBUG_PREFIX = "logging.debug"; + public static final String CFG_SELFTEST_PREFIX = "selftests.container.logger"; ++ public static final String CFG_TOKENDB = "tokendb"; + public static final String CFG_TOKENDB_ALLOWED_TRANSITIONS = "tokendb.allowedTransitions"; + public static final String CFG_OPERATIONS_ALLOWED_TRANSITIONS = "tps.operations.allowedTransitions"; + +@@ -153,6 +154,7 @@ public class TPSEngine { + + public static final String CFG_EXTERNAL_REG = "externalReg"; + public static final String CFG_ER_DELEGATION = "delegation"; ++ public static final String CFG_NON_EXTERNAL_REG = "nonExternalReg"; + + /* misc values */ + +@@ -192,6 +194,7 @@ public class TPSEngine { + public static final String ENROLL_MODE_ENROLLMENT = ENROLL_OP; + public static final String ENROLL_MODE_RECOVERY = RECOVERY_OP; + public static final String ERNOLL_MODE_RENEWAL = RENEWAL_OP; ++ public static final String CFG_ALLOW_MULTI_TOKENS_USER = "allowMultiActiveTokensUser"; + + public void init() { + //ToDo +diff --git a/base/tps/src/org/dogtagpki/server/tps/processor/TPSEnrollProcessor.java b/base/tps/src/org/dogtagpki/server/tps/processor/TPSEnrollProcessor.java +index 6240ea6..9d42546 100644 +--- a/base/tps/src/org/dogtagpki/server/tps/processor/TPSEnrollProcessor.java ++++ b/base/tps/src/org/dogtagpki/server/tps/processor/TPSEnrollProcessor.java +@@ -14,6 +14,11 @@ import java.util.Map; + import java.util.Random; + import java.util.zip.DataFormatException; + ++import netscape.security.provider.RSAPublicKey; ++//import org.mozilla.jss.pkcs11.PK11ECPublicKey; ++import netscape.security.util.BigInt; ++import netscape.security.x509.X509CertImpl; ++ + import org.dogtagpki.server.tps.TPSSession; + import org.dogtagpki.server.tps.TPSSubsystem; + import org.dogtagpki.server.tps.TPSTokenPolicy; +@@ -53,6 +58,8 @@ import org.mozilla.jss.pkcs11.PK11PubKey; + import org.mozilla.jss.pkcs11.PK11RSAPublicKey; + import org.mozilla.jss.pkix.primitive.SubjectPublicKeyInfo; + ++import sun.security.pkcs11.wrapper.PKCS11Constants; ++ + import com.netscape.certsrv.apps.CMS; + import com.netscape.certsrv.base.EBaseException; + import com.netscape.certsrv.base.EPropertyNotFound; +@@ -60,12 +67,6 @@ import com.netscape.certsrv.base.IConfigStore; + import com.netscape.certsrv.tps.token.TokenStatus; + import com.netscape.cmsutil.util.Utils; + +-import netscape.security.provider.RSAPublicKey; +-//import org.mozilla.jss.pkcs11.PK11ECPublicKey; +-import netscape.security.util.BigInt; +-import netscape.security.x509.X509CertImpl; +-import sun.security.pkcs11.wrapper.PKCS11Constants; +- + public class TPSEnrollProcessor extends TPSProcessor { + + public TPSEnrollProcessor(TPSSession session) { +@@ -329,6 +330,24 @@ public class TPSEnrollProcessor extends TPSProcessor { + if (!isExternalReg) + checkAndAuthenticateUser(appletInfo, getSelectedTokenType()); + ++ //Do this here after all authentication has taken place, so we have a (userid) ++ ++ boolean allowMultiTokens = checkAllowMultiActiveTokensUser(isExternalReg); ++ ++ if (isTokenPresent == false && allowMultiTokens == false) { ++ boolean alreadyHasActiveToken = checkUserAlreadyHasActiveToken(userid); ++ ++ if (alreadyHasActiveToken == true) { ++ //We don't allow the user to have more than one active token, nip it in the bud right now ++ //If this token is brand new and not known to the system ++ ++ throw new TPSException(method ++ + " User already has an active token when trying to enroll this new token!", ++ TPSStatus.STATUS_ERROR_HAS_AT_LEAST_ONE_ACTIVE_TOKEN); ++ } ++ ++ } ++ + if (do_force_format) { + //We will skip the auth step inside of format + format(true); +@@ -1030,22 +1049,9 @@ public class TPSEnrollProcessor extends TPSProcessor { + } else { + CMS.debug(method + ": There are multiple token entries for user " + + userid); +- try { +- // this is assuming that the user can only have one single active token +- // TODO: for future, maybe should allow multiple active tokens +- tps.tdb.tdbHasActiveToken(userid); + +- } catch (Exception e1) { +- /* +- * user has no active token, need to find a token to recover from +- * there are no other active tokens for this user +- */ + isRecover = true; + continue; // TODO: or break? +- } +- logMsg = method + ": user already has an active token"; +- CMS.debug(logMsg); +- throw new TPSException(logMsg, TPSStatus.STATUS_ERROR_HAS_AT_LEAST_ONE_ACTIVE_TOKEN); + } + + } else if (tokenRecord.getTokenStatus() == TokenStatus.ACTIVE) { +@@ -1070,17 +1076,10 @@ public class TPSEnrollProcessor extends TPSProcessor { + throw new TPSException(logMsg, TPSStatus.STATUS_ERROR_UNUSABLE_TOKEN_KEYCOMPROMISE); + + } else if (tokenRecord.getTokenStatus() == TokenStatus.SUSPENDED) { +- try { +- tps.tdb.tdbHasActiveToken(userid); +- logMsg = "user already has an active token"; +- CMS.debug(method + ": " + logMsg); +- throw new TPSException(logMsg, TPSStatus.STATUS_ERROR_HAS_AT_LEAST_ONE_ACTIVE_TOKEN); + +- } catch (Exception e2) { + logMsg = "User needs to contact administrator to report lost token (it should be put on Hold)."; + CMS.debug(method + ": " + logMsg); + break; +- } + + } else if (tokenRecord.getTokenStatus() == TokenStatus.DAMAGED) { + logMsg = "This destroyed lost case should not be executed because the token is so damaged. It should not get here"; +@@ -3559,6 +3558,55 @@ public class TPSEnrollProcessor extends TPSProcessor { + audit(auditMessage); + } + ++ private boolean checkUserAlreadyHasActiveToken(String userid) { ++ ++ String method = "TPSEnrollProcessor.checkUserAlreadyHasActiveToken: "; ++ boolean result = false; ++ ++ TPSSubsystem tps = (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID); ++ try { ++ tps.tdb.tdbHasActiveToken(userid); ++ result = true; ++ ++ } catch (Exception e) { ++ result = false; ++ } ++ ++ CMS.debug(method + " user: " + userid + " has a token already: " + result); ++ ++ return result; ++ } ++ ++ private boolean checkAllowMultiActiveTokensUser(boolean isExternalReg) { ++ boolean allow = true; ++ ++ String method = "TPSEnrollProcessor.checkAllowMultiActiveTokensUser: "; ++ IConfigStore configStore = CMS.getConfigStore(); ++ ++ String scheme = null; ++ ++ if (isExternalReg == true) { ++ scheme = TPSEngine.CFG_EXTERNAL_REG; ++ } else { ++ scheme = TPSEngine.CFG_NON_EXTERNAL_REG; ++ } ++ ++ String allowMultiConfig = TPSEngine.CFG_TOKENDB + "." + scheme + "." ++ + TPSEngine.CFG_ALLOW_MULTI_TOKENS_USER; ++ ++ CMS.debug(method + " trying config: " + allowMultiConfig); ++ ++ try { ++ allow = configStore.getBoolean(allowMultiConfig, false); ++ } catch (EBaseException e) { ++ allow = false; ++ } ++ ++ CMS.debug(method + "returning allow: " + allow); ++ ++ return allow; ++ } ++ + public static void main(String[] args) { + } + +-- +2.5.5 + + +From d86a514800483edf3310c4bde6c8b5bd56b074bc Mon Sep 17 00:00:00 2001 +From: Matthew Harmsen +Date: Wed, 29 Jun 2016 20:51:03 -0600 +Subject: Separate PKI Instances versus Shared PKI Instances + +- PKI TRAC Ticket #1607 - [MAN] man pkispawn has inadequate description for + shared vs non shared tomcat instance installation +--- + base/server/man/man8/pkispawn.8 | 360 +++++++++++++++++++++++++++++++++++----- + 1 file changed, 318 insertions(+), 42 deletions(-) + +diff --git a/base/server/man/man8/pkispawn.8 b/base/server/man/man8/pkispawn.8 +index fa601fc..3ad6fdb 100644 +--- a/base/server/man/man8/pkispawn.8 ++++ b/base/server/man/man8/pkispawn.8 +@@ -92,6 +92,37 @@ Displays verbose information about the installation. This flag can be provided + .B pkispawn -h + for details. + ++.SH SEPARATE VERSUS SHARED INSTANCES ++.IP ++.SS Separate PKI instances: ++.BR ++.PP ++As described above, this version of Certificate System continues to support separate PKI instances for all subsystems. ++.PP ++Separate PKI instances run as a single Java-based Apache Tomcat instance, contain a single PKI subsystem (CA, KRA, OCSP, TKS, or TPS), and must utilize unique ports if co-located on the same physical machine or virtual machine (VM). ++.PP ++.SS Shared PKI instances: ++.BR ++.PP ++Additionally, this version of Certificate System introduces the notion of a shared PKI instance. ++.PP ++Shared PKI instances also run as a single Java-based Apache Tomcat instance, but may contain any combination of up to one of each type of PKI subsystem: ++.IP ++.nf ++CA ++TKS ++CA, KRA ++CA, OCSP ++TKS, TPS ++CA, KRA, TKS, TPS ++CA, KRA, OCSP, TKS, TPS ++etc. ++.fi ++.PP ++Shared PKI instances allow all of their subsystems contained within that instance to share the same ports, and must utilize unique ports if more than one shared PKI instance is co-located on the same physical machine or VM. ++.PP ++Semantically, a shared PKI instance that contains a single PKI subsystem is identical to a separate PKI instance. ++ + .SH INTERACTIVE MODE + .PP + If no options are specified, pkispawn will provide an interactive menu to +@@ -319,17 +350,46 @@ For all PKI subsystems including the CA, ECC is not supported for the correspond + .SS Installing a KRA, OCSP, TKS, or TPS in a shared instance + .BR + .PP +-To install a KRA, OCSP, TKS, or TPS in the same instance used by the CA execute ++For this example, assume that a new CA instance has been installed by ++executing the following command: ++.IP ++\x'-1'\fBpkispawn \-s CA \-f myconfig.txt\fR ++.PP ++where \fImyconfig.txt\fP contains the following text: ++.IP ++.nf ++[DEFAULT] ++pki_admin_password=\fISecret123\fP ++pki_client_pkcs12_password=\fISecret123\fP ++pki_ds_password=\fISecret123\fP ++# Optionally keep client databases ++pki_client_database_purge=False ++.if + ++.PP ++To install a shared KRA in the same instance used by the CA execute + the following command: +- + .IP +-\x'-1'\fBpkispawn \-s \-f myconfig.txt\fR +- ++\x'-1'\fBpkispawn \-s KRA \-f myconfig.txt\fR + .PP +-where subsystem is KRA, OCSP, TKS, or TPS, and \fImyconfig.txt\fP contains the +-following text: ++where \fImyconfig.txt\fP contains the following text: ++.IP ++.nf ++[DEFAULT] ++pki_admin_password=\fISecret123\fP ++pki_client_database_password=\fISecret123\fP ++pki_client_pkcs12_password=\fISecret123\fP ++pki_ds_password=\fISecret123\fP ++pki_security_domain_password=\fISecret123\fP ++.if + ++.PP ++To install a shared OCSP in the same instance used by the CA execute ++the following command: ++.IP ++\x'-1'\fBpkispawn \-s OCSP \-f myconfig.txt\fR ++.PP ++where \fImyconfig.txt\fP contains the following text: + .IP + .nf + [DEFAULT] +@@ -338,21 +398,74 @@ pki_client_database_password=\fISecret123\fP + pki_client_pkcs12_password=\fISecret123\fP + pki_ds_password=\fISecret123\fP + pki_security_domain_password=\fISecret123\fP +-.fi ++.if + + .PP +-The \fBpki_security_domain_password\fP is the admin password of the CA +-installed in the same instance. This command should be run after a CA is +-installed. This installs another subsystem within the same instance using the +-certificate generated for the CA administrator for the subsystem's +-administrator. This allows a user to access both subsystems on the browser +-with a single administrator certificate. To access the new subsystem's +-functionality, simply point the browser to https://:8443 and click +-the relevant top-level links. ++To install a shared TKS in the same instance used by the CA execute ++the following command: ++.IP ++\x'-1'\fBpkispawn \-s TKS \-f myconfig.txt\fR ++.PP ++where \fImyconfig.txt\fP contains the following text: ++.IP ++.nf ++[DEFAULT] ++pki_admin_password=\fISecret123\fP ++pki_client_database_password=\fISecret123\fP ++pki_client_pkcs12_password=\fISecret123\fP ++pki_ds_password=\fISecret123\fP ++pki_security_domain_password=\fISecret123\fP ++.if + + .PP +-To install TPS in a shared instance the following section must be added to +-\fImyconfig.txt\fP: ++To install a shared TPS in the same instance used by the CA execute ++the following command: ++.IP ++\x'-1'\fBpkispawn \-s TPS \-f myconfig.txt\fR ++.PP ++where \fImyconfig.txt\fP contains the following text: ++.IP ++.nf ++[DEFAULT] ++pki_admin_password=\fISecret123\fP ++pki_client_database_password=\fISecret123\fP ++pki_client_pkcs12_password=\fISecret123\fP ++pki_ds_password=\fISecret123\fP ++pki_security_domain_password=\fISecret123\fP ++[TPS] ++# Shared TPS instances optionally utilize their shared KRA ++# for server-side keygen ++pki_enable_server_side_keygen=True ++pki_authdb_basedn=\fIdc=example,dc=com\fP ++.if ++ ++.TP ++\fBNote:\fP ++For this particular example, the computed default values for a ++PKI instance name including its ports, URLs, machine names, etc. ++were utilized as defined in \fI/etc/pki/default.cfg\fP. Each ++subsystem in this example will reside under the ++\fI/var/lib/pki/pki-tomcat\fP instance housed within their own ++\fIca\fP, \fIkra\fP, \fIocsp\fP, \fItks\fP, and \fItps\fP ++subdirectories, utilizing the same default port values of ++8080 (http), 8443 (https), 8009 (ajp), 8005 (tomcat), using the ++same computed hostname and URL information, and sharing a single ++common PKI Administrator Certificate. ++ ++.PP ++The \fBpki_security_domain_password\fP is the admin password of the ++CA installed in the same instance. This command should be run after ++a CA is installed. This installs another subsystem within the same ++instance using the certificate generated for the CA administrator ++for the subsystem's administrator. This allows a user to access ++both subsystems on the browser with a single administrator ++certificate. To access the new subsystem's functionality, simply ++point the browser to https://:8443 and click the ++relevant top-level links. ++ ++.PP ++To install TPS in a shared instance the following section must be ++added to \fImyconfig.txt\fP: + + .IP + .nf +@@ -385,16 +498,110 @@ installed in the same instance. + .SS Installing a KRA, OCSP, TKS, or TPS in a separate instance + .BR + .PP +-To install a KRA, OCSP, TKS, or TPS with a remote a CA execute the following +-command: ++For this example, assume that a new CA instance has been installed by executing the following command: ++.IP ++\x'-1'\fBpkispawn \-s CA \-f myconfig.txt\fR ++.PP ++where \fImyconfig.txt\fP contains the following text: ++.IP ++.nf ++[DEFAULT] ++pki_admin_password=\fISecret123\fP ++pki_client_pkcs12_password=\fISecret123\fP ++pki_ds_password=\fISecret123\fP ++# Optionally keep client databases ++pki_client_database_purge=False ++# Separated CA instance name and ports ++pki_instance_name=\fIpki-ca\fP ++pki_http_port=\fI18080\fP ++pki_https_port=\fI18443\fP ++# This Separated CA instance will be its own security domain ++pki_security_domain_https_port=\fI18443\fP ++[Tomcat] ++# Separated CA Tomcat ports ++pki_ajp_port=\fI18009\fP ++pki_tomcat_server_port=\fI18005\fP ++.if + ++.PP ++To install a separate KRA which connects to this remote CA execute ++the following command: + .IP +-\x'-1'\fBpkispawn \-s \-f myconfig.txt\fR ++\x'-1'\fBpkispawn \-s KRA \-f myconfig.txt\fR ++.PP ++where \fImyconfig.txt\fP contains the following text: ++.IP ++.nf ++[DEFAULT] ++pki_admin_password=\fISecret123\fP ++pki_client_database_password=\fISecret123\fP ++pki_client_pkcs12_password=\fISecret123\fP ++pki_ds_password=\fISecret123\fP ++pki_security_domain_password=\fISecret123\fP ++# Optionally keep client databases ++pki_client_database_purge=False ++# Separated KRA instance name and ports ++pki_instance_name=\fIpki-kra\fP ++pki_http_port=\fI28080\fP ++pki_https_port=\fI28443\fP ++# Separated KRA instance security domain references ++pki_issuing_ca=\fIhttps://pki.example.com:18443\fP ++pki_security_domain_hostname=\fIpki.example.com\fP ++pki_security_domain_https_port=\fI18443\fP ++pki_security_domain_user=caadmin ++[Tomcat] ++# Separated KRA Tomcat ports ++pki_ajp_port=\fI28009\fP ++pki_tomcat_server_port=\fI28005\fP ++[KRA] ++# A Separated KRA instance requires its own ++# PKI Administrator Certificate ++pki_import_admin_cert=False ++.if + + .PP +-where subsystem is KRA, OCSP, TKS, or TPS, and \fImyconfig.txt\fP contains the +-following text: ++To install a separate OCSP which connects to this remote CA execute ++the following command: ++.IP ++\x'-1'\fBpkispawn \-s OCSP \-f myconfig.txt\fR ++.PP ++where \fImyconfig.txt\fP contains the following text: ++.IP ++.nf ++[DEFAULT] ++pki_admin_password=\fISecret123\fP ++pki_client_database_password=\fISecret123\fP ++pki_client_pkcs12_password=\fISecret123\fP ++pki_ds_password=\fISecret123\fP ++pki_security_domain_password=\fISecret123\fP ++# Optionally keep client databases ++pki_client_database_purge=False ++# Separated OCSP instance name and ports ++pki_instance_name=\fIpki-ocsp\fP ++pki_http_port=\fI29080\fP ++pki_https_port=\fI29443\fP ++# Separated OCSP instance security domain references ++pki_issuing_ca=\fIhttps://pki.example.com:18443\fP ++pki_security_domain_hostname=\fIpki.example.com\fP ++pki_security_domain_https_port=\fI18443\fP ++pki_security_domain_user=caadmin ++[Tomcat] ++# Separated OCSP Tomcat ports ++pki_ajp_port=\fI29009\fP ++pki_tomcat_server_port=\fI29005\fP ++[OCSP] ++# A Separated OCSP instance requires its own ++# PKI Administrator Certificate ++pki_import_admin_cert=False ++.if + ++.PP ++To install a separate TKS which connects to this remote CA execute ++the following command: ++.IP ++\x'-1'\fBpkispawn \-s TKS \-f myconfig.txt\fR ++.PP ++where \fImyconfig.txt\fP contains the following text: + .IP + .nf + [DEFAULT] +@@ -403,37 +610,106 @@ pki_client_database_password=\fISecret123\fP + pki_client_pkcs12_password=\fISecret123\fP + pki_ds_password=\fISecret123\fP + pki_security_domain_password=\fISecret123\fP +-pki_security_domain_hostname= +-pki_security_domain_https_port= ++# Optionally keep client databases ++pki_client_database_purge=False ++# Separated TKS instance name and ports ++pki_instance_name=\fIpki-tks\fP ++pki_http_port=\fI30080\fP ++pki_https_port=\fI30443\fP ++# Separated TKS instance security domain references ++pki_issuing_ca=\fIhttps://pki.example.com:18443\fP ++pki_security_domain_hostname=\fIpki.example.com\fP ++pki_security_domain_https_port=\fI18443\fP + pki_security_domain_user=caadmin +-pki_issuing_ca=https://: ++[Tomcat] ++# Separated TKS Tomcat ports ++pki_ajp_port=\fI30009\fP ++pki_tomcat_server_port=\fI30005\fP ++[TKS] ++# A Separated TKS instance requires its own ++# PKI Administrator Certificate ++pki_import_admin_cert=False ++.if + +-[KRA/OCSP/TKS/TPS] ++.PP ++To install a separate TPS which connects to this remote CA execute ++the following command: ++.IP ++\x'-1'\fBpkispawn \-s TPS \-f myconfig.txt\fR ++.PP ++where \fImyconfig.txt\fP contains the following text: ++.IP ++.nf ++[DEFAULT] ++pki_admin_password=\fISecret123\fP ++pki_client_database_password=\fISecret123\fP ++pki_client_pkcs12_password=\fISecret123\fP ++pki_ds_password=\fISecret123\fP ++pki_security_domain_password=\fISecret123\fP ++# Optionally keep client databases ++pki_client_database_purge=False ++# Separated TPS instance name and ports ++pki_instance_name=\fIpki-tps\fP ++pki_http_port=\fI31080\fP ++pki_https_port=\fI31443\fP ++# Separated TPS instance security domain references ++pki_issuing_ca=\fIhttps://pki.example.com:18443\fP ++pki_security_domain_hostname=\fIpki.example.com\fP ++pki_security_domain_https_port=\fI18443\fP ++pki_security_domain_user=caadmin ++[Tomcat] ++# Separated TPS Tomcat ports ++pki_ajp_port=\fI31009\fP ++pki_tomcat_server_port=\fI31005\fP ++[TPS] ++# Separated TPS instances require specifying a remote CA ++pki_ca_uri=\fIhttps://pki.example.com:18443\fP ++# Separated TPS instances optionally utilize a remote KRA ++# for server-side keygen ++pki_kra_uri=\fIhttps://pki.example.com:28443\fP ++pki_enable_server_side_keygen=True ++pki_authdb_basedn=\fIdc=example,dc=com\fP ++# Separated TPS instances require specifying a remote TKS ++pki_tks_uri=\fIhttps://pki.example.com:30443\fP ++pki_import_shared_secret=True ++# A Separated TPS instance requires its own ++# PKI Administrator Certificate + pki_import_admin_cert=False +-.fi ++.if ++ ++.TP ++\fBNote:\fP ++For this particular example, besides passwords, sample ++values were also utilized for PKI instance names, ports, ++URLs, machine names, etc. Under no circumstances should ++these demonstrative values be construed to be required ++literal values. + + .PP +-A remote CA is one where the CA resides in another Certificate Server instance, +-either on the local machine or a remote machine. In this case, +-\fImyconfig.txt\fP must specify the connection information for the remote CA +-and the information about the security domain (the trusted collection of +-subsystems within an instance). ++A remote CA is one where the CA resides in another ++Certificate Server instance, either on the local machine ++or a remote machine. In this case, \fImyconfig.txt\fP must ++specify the connection information for the remote CA and the ++information about the security domain (the trusted collection ++of subsystems within an instance). + + .PP +-The subsystem section is [KRA], [OCSP], [TKS], or [TPS]. This example assumes +-that the specified CA hosts the security domain. The CA must be running and +-accessible. ++The subsystem section is [KRA], [OCSP], [TKS], or [TPS]. ++This example assumes that the specified CA hosts the security ++domain. The CA must be running and accessible. + + .PP +-A new administrator certificate is generated for the new subsystem and stored +-in a PKCS #12 file in \fI$HOME/.dogtag/pki-tomcat\fP. ++A new administrator certificate is generated for the new ++subsystem and stored in a PKCS #12 file ++in \fI$HOME/.dogtag/\fP. + + .PP +-As in a shared instance, to install TPS in a separate instance the +-authentication database must be specified in the [TPS] section, and optionally +-the server-side key generation can be enabled. If the CA, KRA, or TKS +-subsystems required by TPS are running on a remote instance the following +-parameters must be added into the [TPS] section to specify their locations: ++As in a shared instance, to install TPS in a separate instance ++the authentication database must be specified in the [TPS] section, ++and optionally the server-side key generation can be enabled. ++If the CA, KRA, or TKS subsystems required by TPS are running ++on a remote instance the following parameters must be added into ++the [TPS] section to specify their locations: + + .IP + .nf +-- +2.5.5 + + +From f0ad71e8a4fbae665a6b4875cce5b82895ad74f0 Mon Sep 17 00:00:00 2001 +From: Christina Fu +Date: Thu, 30 Jun 2016 15:01:42 -0700 +Subject: Bugzilla #1203407 tomcatjss: missing ciphers + +This patch removes references to the ciphers currently unsupported by NSS: + TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 + TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 +--- + base/server/python/pki/server/deployment/pkiparser.py | 3 --- + base/server/share/conf/ciphers.info | 4 ++-- + base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java | 4 ---- + 3 files changed, 2 insertions(+), 9 deletions(-) + +diff --git a/base/server/python/pki/server/deployment/pkiparser.py b/base/server/python/pki/server/deployment/pkiparser.py +index dc5d7f6..d940e2c 100644 +--- a/base/server/python/pki/server/deployment/pkiparser.py ++++ b/base/server/python/pki/server/deployment/pkiparser.py +@@ -971,7 +971,6 @@ class PKIConfigParser: + "-TLS_ECDH_RSA_WITH_AES_128_CBC_SHA," + \ + "-TLS_ECDH_RSA_WITH_AES_256_CBC_SHA," + \ + "-TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA," + \ +- "-TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256," + \ + "+TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA," + \ + "-TLS_RSA_WITH_3DES_EDE_CBC_SHA," + \ + "-TLS_RSA_WITH_AES_128_CBC_SHA," + \ +@@ -1006,8 +1005,6 @@ class PKIConfigParser: + "-TLS_ECDH_RSA_WITH_AES_128_CBC_SHA," + \ + "-TLS_ECDH_RSA_WITH_AES_256_CBC_SHA," + \ + "-TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA," + \ +- "-TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256," + \ +- "-TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256," +\ + "-TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA," + \ + "-TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA," + \ + "-TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA," + \ +diff --git a/base/server/share/conf/ciphers.info b/base/server/share/conf/ciphers.info +index 69aaeaa..71face5 100644 +--- a/base/server/share/conf/ciphers.info ++++ b/base/server/share/conf/ciphers.info +@@ -67,8 +67,8 @@ + # + ## + # For RSA servers: +- sslRangeCiphers="-TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,-TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,-TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA,-TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,-TLS_ECDH_RSA_WITH_AES_256_CBC_SHA,-TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA,-TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256,-TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256,-TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,-TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,-TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,-TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,-TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,-TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,-TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA,-TLS_DHE_DSS_WITH_AES_128_CBC_SHA,-TLS_DHE_DSS_WITH_AES_256_CBC_SHA,-TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA,-TLS_DHE_RSA_WITH_AES_128_CBC_SHA,-TLS_DHE_RSA_WITH_AES_256_CBC_SHA,-TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,-TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,-TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,-TLS_DHE_DSS_WITH_AES_128_GCM_SHA256,-TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,-TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,-TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,-TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,-TLS_RSA_WITH_AES_128_CBC_SHA256,-TLS_RSA_WITH_AES_256_CBC_SHA256,-TLS_RSA_WITH_AES_128_GCM_SHA256,+TLS_RSA_WITH_3DES_EDE_CBC_SHA,+TLS_RSA_WITH_AES_128_CBC_SHA,+TLS_RSA_WITH_AES_256_CBC_SHA" ++ sslRangeCiphers="-TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,-TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,-TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA,-TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,-TLS_ECDH_RSA_WITH_AES_256_CBC_SHA,-TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA,-TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,-TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,-TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,-TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,-TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,-TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,-TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA,-TLS_DHE_DSS_WITH_AES_128_CBC_SHA,-TLS_DHE_DSS_WITH_AES_256_CBC_SHA,-TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA,-TLS_DHE_RSA_WITH_AES_128_CBC_SHA,-TLS_DHE_RSA_WITH_AES_256_CBC_SHA,-TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,-TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,-TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,-TLS_DHE_DSS_WITH_AES_128_GCM_SHA256,-TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,-TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,-TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,-TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,-TLS_RSA_WITH_AES_128_CBC_SHA256,-TLS_RSA_WITH_AES_256_CBC_SHA256,-TLS_RSA_WITH_AES_128_GCM_SHA256,+TLS_RSA_WITH_3DES_EDE_CBC_SHA,+TLS_RSA_WITH_AES_128_CBC_SHA,+TLS_RSA_WITH_AES_256_CBC_SHA" + # + # + # For ECC servers: +- sslRangeCiphers="-TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,-TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,-TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA,-TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,-TLS_ECDH_RSA_WITH_AES_256_CBC_SHA,-TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA,-TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256,+TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,-TLS_RSA_WITH_3DES_EDE_CBC_SHA,-TLS_RSA_WITH_AES_128_CBC_SHA,+TLS_RSA_WITH_AES_256_CBC_SHA,+TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,+TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,-TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,-TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,-TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA,-TLS_DHE_DSS_WITH_AES_128_CBC_SHA,-TLS_DHE_DSS_WITH_AES_256_CBC_SHA,-TLS_DHE_DSS_WITH_AES_128_GCM_SHA256,-TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA,-TLS_DHE_RSA_WITH_AES_128_CBC_SHA,-TLS_DHE_RSA_WITH_AES_256_CBC_SHA,-TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,-TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,-TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,-TLS_RSA_WITH_AES_128_CBC_SHA256,+TLS_RSA_WITH_AES_256_CBC_SHA256,-TLS_RSA_WITH_AES_128_GCM_SHA256,+TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,+TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,-TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,-TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,-TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256" ++ sslRangeCiphers="-TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,-TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,-TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA,-TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,-TLS_ECDH_RSA_WITH_AES_256_CBC_SHA,-TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA,+TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,-TLS_RSA_WITH_3DES_EDE_CBC_SHA,-TLS_RSA_WITH_AES_128_CBC_SHA,+TLS_RSA_WITH_AES_256_CBC_SHA,+TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,+TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,-TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,-TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,-TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA,-TLS_DHE_DSS_WITH_AES_128_CBC_SHA,-TLS_DHE_DSS_WITH_AES_256_CBC_SHA,-TLS_DHE_DSS_WITH_AES_128_GCM_SHA256,-TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA,-TLS_DHE_RSA_WITH_AES_128_CBC_SHA,-TLS_DHE_RSA_WITH_AES_256_CBC_SHA,-TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,-TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,-TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,-TLS_RSA_WITH_AES_128_CBC_SHA256,+TLS_RSA_WITH_AES_256_CBC_SHA256,-TLS_RSA_WITH_AES_128_GCM_SHA256,+TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,+TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,-TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,-TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,-TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256" +diff --git a/base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java b/base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java +index 979b047..4a2558b 100644 +--- a/base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java ++++ b/base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java +@@ -879,12 +879,8 @@ public class CryptoUtil { + SSLSocket.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256); + cipherMap.put("TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", + SSLSocket.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256); +- cipherMap.put("TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256", +- SSLSocket.TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256); + cipherMap.put("TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", + SSLSocket.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256); +- cipherMap.put("TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256", +- SSLSocket.TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256); + + } + +-- +2.5.5 + + +From 097e116c8557e7bee170bc2764c2e000bd49d4c9 Mon Sep 17 00:00:00 2001 +From: Abhijeet Kasurde +Date: Wed, 29 Jun 2016 14:44:45 +0530 +Subject: Added condition to verify instance id in db-schema-upgrade + +Fixes : https://bugzilla.redhat.com/show_bug.cgi?id=1351096 +--- + base/server/python/pki/server/cli/db.py | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/base/server/python/pki/server/cli/db.py b/base/server/python/pki/server/cli/db.py +index c643182..5915417 100644 +--- a/base/server/python/pki/server/cli/db.py ++++ b/base/server/python/pki/server/cli/db.py +@@ -95,7 +95,11 @@ class DBSchemaUpgrade(pki.cli.CLI): + sys.exit(1) + + instance = pki.server.PKIInstance(instance_name) ++ if not instance.is_valid(): ++ print("ERROR: Instance name '%s' not found" % instance) ++ sys.exit(1) + instance.load() ++ + self.update_schema(instance, bind_dn, bind_password) + + self.print_message('Upgrade complete') +-- +2.5.5 + + +From 1913ff38f04dd27641f23cb76b13cb4806720946 Mon Sep 17 00:00:00 2001 +From: Abhijeet Kasurde +Date: Wed, 29 Jun 2016 18:06:12 +0530 +Subject: Added fix for checking ldapmodify return code in db-schema-upgrade + +Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1349769 +--- + base/server/python/pki/server/cli/db.py | 12 +++++++----- + 1 file changed, 7 insertions(+), 5 deletions(-) + +diff --git a/base/server/python/pki/server/cli/db.py b/base/server/python/pki/server/cli/db.py +index 5915417..6555e40 100644 +--- a/base/server/python/pki/server/cli/db.py ++++ b/base/server/python/pki/server/cli/db.py +@@ -100,7 +100,12 @@ class DBSchemaUpgrade(pki.cli.CLI): + sys.exit(1) + instance.load() + +- self.update_schema(instance, bind_dn, bind_password) ++ try: ++ self.update_schema(instance, bind_dn, bind_password) ++ ++ except subprocess.CalledProcessError as e: ++ print("ERROR: " + e.output) ++ sys.exit(e.returncode) + + self.print_message('Upgrade complete') + +@@ -122,10 +127,7 @@ class DBSchemaUpgrade(pki.cli.CLI): + if secure.lower() == "true": + cmd.append('-Z') + +- try: +- subprocess.check_output(cmd) +- except subprocess.CalledProcessError as e: +- print('ldapmodify returns {}: {}'.format(e.returncode, e.output)) ++ subprocess.check_output(cmd, stderr=subprocess.STDOUT) + + + class DBUpgrade(pki.cli.CLI): +-- +2.5.5 + + +From 99a93af1ca5cce26d625ce7cee07dab4a890f1be Mon Sep 17 00:00:00 2001 +From: Abhijeet Kasurde +Date: Thu, 30 Jun 2016 15:18:24 +0530 +Subject: Added condition for checking instance id in kra commands + +Partially Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1351295 +--- + base/java-tools/bin/pki | 5 ++--- + base/server/python/pki/server/__init__.py | 2 +- + base/server/python/pki/server/cli/kra.py | 23 +++++++++++++++++++++-- + base/server/sbin/pki-server | 13 ++++++++++++- + 4 files changed, 36 insertions(+), 7 deletions(-) + +diff --git a/base/java-tools/bin/pki b/base/java-tools/bin/pki +index c917083..6104a5f 100644 +--- a/base/java-tools/bin/pki ++++ b/base/java-tools/bin/pki +@@ -261,7 +261,6 @@ if __name__ == '__main__': + + except subprocess.CalledProcessError as e: + if cli.verbose: +- print('ERROR: %s' % e) +- elif cli.debug: + traceback.print_exc() +- exit(e.returncode) ++ print('ERROR: %s' % e) ++ sys.exit(e.returncode) +diff --git a/base/server/python/pki/server/__init__.py b/base/server/python/pki/server/__init__.py +index 454408f..87303cd 100644 +--- a/base/server/python/pki/server/__init__.py ++++ b/base/server/python/pki/server/__init__.py +@@ -562,7 +562,7 @@ class PKIInstance(object): + def get_token_password(self, token='internal'): + + # determine the password name for the token +- if token.lower() in ['internal', 'internal key storage token']: ++ if not token or token.lower() in ['internal', 'internal key storage token']: + name = 'internal' + + else: +diff --git a/base/server/python/pki/server/cli/kra.py b/base/server/python/pki/server/cli/kra.py +index b4f0df4..676d1f5 100644 +--- a/base/server/python/pki/server/cli/kra.py ++++ b/base/server/python/pki/server/cli/kra.py +@@ -132,9 +132,15 @@ class KRAClonePrepareCLI(pki.cli.CLI): + sys.exit(1) + + instance = pki.server.PKIInstance(instance_name) ++ if not instance.is_valid(): ++ print('ERROR: Invalid instance %s.' % instance_name) ++ sys.exit(1) + instance.load() + + subsystem = instance.get_subsystem('kra') ++ if not subsystem: ++ print('ERROR: No KRA subsystem in instance %s.' % instance_name) ++ sys.exit(1) + + tmpdir = tempfile.mkdtemp() + +@@ -151,6 +157,7 @@ class KRAClonePrepareCLI(pki.cli.CLI): + 'storage', pkcs12_file, pkcs12_password_file) + subsystem.export_system_cert( + 'audit_signing', pkcs12_file, pkcs12_password_file) ++ + instance.export_external_certs(pkcs12_file, pkcs12_password_file) + + finally: +@@ -235,12 +242,15 @@ class KRADBVLVFindCLI(pki.cli.CLI): + sys.exit(1) + + instance = pki.server.PKIInstance(instance_name) ++ if not instance.is_valid(): ++ print('ERROR: Invalid instance %s.' % instance_name) ++ sys.exit(1) + instance.load() + + subsystem = instance.get_subsystem('kra') +- + if not subsystem: +- raise Exception('Subsystem not found') ++ print('ERROR: No KRA subsystem in instance %s.' % instance_name) ++ sys.exit(1) + + self.find_vlv(subsystem, bind_dn, bind_password) + +@@ -347,6 +357,9 @@ class KRADBVLVAddCLI(pki.cli.CLI): + sys.exit(1) + + instance = pki.server.PKIInstance(instance_name) ++ if not instance.is_valid(): ++ print('ERROR: Invalid instance %s.' % instance_name) ++ sys.exit(1) + instance.load() + self.add_vlv(instance, bind_dn, bind_password) + +@@ -442,6 +455,9 @@ class KRADBVLVDeleteCLI(pki.cli.CLI): + sys.exit(1) + + instance = pki.server.PKIInstance(instance_name) ++ if not instance.is_valid(): ++ print('ERROR: Invalid instance %s.' % instance_name) ++ sys.exit(1) + instance.load() + self.delete_vlv(instance, bind_dn, bind_password) + +@@ -557,6 +573,9 @@ class KRADBVLVReindexCLI(pki.cli.CLI): + sys.exit(1) + + instance = pki.server.PKIInstance(instance_name) ++ if not instance.is_valid(): ++ print('ERROR: Invalid instance %s.' % instance_name) ++ sys.exit(1) + instance.load() + self.reindex_vlv(instance, bind_dn, bind_password) + +diff --git a/base/server/sbin/pki-server b/base/server/sbin/pki-server +index cd00de0..cea62b7 100644 +--- a/base/server/sbin/pki-server ++++ b/base/server/sbin/pki-server +@@ -22,7 +22,9 @@ + from __future__ import absolute_import + from __future__ import print_function + import getopt ++import subprocess + import sys ++import traceback + + import pki.cli + import pki.server.cli.ca +@@ -103,5 +105,14 @@ class PKIServerCLI(pki.cli.CLI): + + + if __name__ == '__main__': ++ + cli = PKIServerCLI() +- cli.execute(sys.argv) ++ ++ try: ++ cli.execute(sys.argv) ++ ++ except subprocess.CalledProcessError as e: ++ if cli.verbose: ++ traceback.print_exc() ++ print('ERROR: %s' % e) ++ sys.exit(e.returncode) +-- +2.5.5 + + +From 8e40b74dc5d314912c65722b4284cab0ffbffbcc Mon Sep 17 00:00:00 2001 +From: Abhijeet Kasurde +Date: Thu, 30 Jun 2016 16:53:36 +0530 +Subject: Updated notification message for kra-db-vlv-del command + +Partially fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1351295 +--- + base/server/python/pki/server/cli/kra.py | 28 ++++++++++++++++------------ + 1 file changed, 16 insertions(+), 12 deletions(-) + +diff --git a/base/server/python/pki/server/cli/kra.py b/base/server/python/pki/server/cli/kra.py +index 676d1f5..17611a8 100644 +--- a/base/server/python/pki/server/cli/kra.py ++++ b/base/server/python/pki/server/cli/kra.py +@@ -455,28 +455,34 @@ class KRADBVLVDeleteCLI(pki.cli.CLI): + sys.exit(1) + + instance = pki.server.PKIInstance(instance_name) ++ + if not instance.is_valid(): + print('ERROR: Invalid instance %s.' % instance_name) + sys.exit(1) ++ + instance.load() +- self.delete_vlv(instance, bind_dn, bind_password) + +- def delete_vlv(self, instance, bind_dn, bind_password): + subsystem = instance.get_subsystem('kra') ++ + if not subsystem: +- if self.verbose: +- print('modify_kra_vlv: No KRA subsystem available. ' +- 'Skipping ...') +- return ++ print('ERROR: No KRA subsystem in instance %s.' % instance_name) ++ sys.exit(1) ++ ++ self.delete_vlv(subsystem, bind_dn, bind_password) ++ ++ print('KRA VLVs deleted from the database for ' + instance_name) ++ ++ def delete_vlv(self, subsystem, bind_dn, bind_password): ++ + database = subsystem.config['internaldb.database'] + + if self.out_file: + with open(self.out_file, "w") as f: + for vlv in KRA_VLVS: +- dn = ("cn=" + vlv + '-' + instance.name + ++ dn = ("cn=" + vlv + '-' + subsystem.instance.name + + ',cn=' + database + + ',cn=ldbm database, cn=plugins, cn=config') +- index_dn = ("cn=" + vlv + '-' + instance.name + ++ index_dn = ("cn=" + vlv + '-' + subsystem.instance.name + + "Index," + dn) + f.write('dn: ' + index_dn + '\n') + f.write('changetype: delete' + '\n') +@@ -491,9 +497,9 @@ class KRADBVLVDeleteCLI(pki.cli.CLI): + bind_password=bind_password) + try: + for vlv in KRA_VLVS: +- dn = ("cn=" + vlv + '-' + instance.name + ',cn=' + database + ++ dn = ("cn=" + vlv + '-' + subsystem.instance.name + ',cn=' + database + + ',cn=ldbm database, cn=plugins, cn=config') +- index_dn = "cn=" + vlv + '-' + instance.name + "Index," + dn ++ index_dn = "cn=" + vlv + '-' + subsystem.instance.name + "Index," + dn + + try: + conn.ldap.delete_s(index_dn) +@@ -508,8 +514,6 @@ class KRADBVLVDeleteCLI(pki.cli.CLI): + finally: + conn.close() + +- print('KRA VLVs deleted from the database for ' + instance.name) +- + + class KRADBVLVReindexCLI(pki.cli.CLI): + +-- +2.5.5 + + +From c7f9e6c4e0711dfafc81d201dcfadee3e0efa335 Mon Sep 17 00:00:00 2001 +From: Fraser Tweedale +Date: Fri, 1 Jul 2016 10:25:15 +1000 +Subject: Respond 400 if lightweight CA cert issuance fails + +If certificate issuance fails during lightweight CA creation (e.g. +due to a profile constraint violation such as Subject DN not +matching pattern) the API responds with status 500. + +Raise BadRequestDataException if cert issuance fails in a way that +indicates bad or invalid CSR data, and catch it to respond with +status 400. + +Also do some drive-by exception chaining. + +Fixes: https://fedorahosted.org/pki/ticket/2388 +--- + base/ca/src/com/netscape/ca/CertificateAuthority.java | 18 +++++++++++++++--- + .../org/dogtagpki/server/ca/rest/AuthorityService.java | 3 ++- + 2 files changed, 17 insertions(+), 4 deletions(-) + +diff --git a/base/ca/src/com/netscape/ca/CertificateAuthority.java b/base/ca/src/com/netscape/ca/CertificateAuthority.java +index e501380..502ab18 100644 +--- a/base/ca/src/com/netscape/ca/CertificateAuthority.java ++++ b/base/ca/src/com/netscape/ca/CertificateAuthority.java +@@ -74,6 +74,7 @@ import org.mozilla.jss.pkix.primitive.Name; + import com.netscape.certsrv.apps.CMS; + import com.netscape.certsrv.authentication.IAuthToken; + import com.netscape.certsrv.authority.ICertAuthority; ++import com.netscape.certsrv.base.BadRequestDataException; + import com.netscape.certsrv.base.EBaseException; + import com.netscape.certsrv.base.EPropertyNotFound; + import com.netscape.certsrv.base.IConfigStore; +@@ -2680,8 +2681,16 @@ public class CertificateAuthority + if (result != null && !result.equals(IRequest.RES_SUCCESS)) + throw new EBaseException("createSubCA: certificate request submission resulted in error: " + result); + RequestStatus requestStatus = request.getRequestStatus(); +- if (requestStatus != RequestStatus.COMPLETE) +- throw new EBaseException("createSubCA: certificate request did not complete; status: " + requestStatus); ++ if (requestStatus != RequestStatus.COMPLETE) { ++ // The request did not complete. Inference: something ++ // incorrect in the request (e.g. profile constraint ++ // violated). ++ String msg = "Failed to issue CA certificate. Final status: " + requestStatus + "."; ++ String errorMsg = request.getExtDataInString(IRequest.ERROR); ++ if (errorMsg != null) ++ msg += " Additional info: " + errorMsg; ++ throw new BadRequestDataException(msg); ++ } + + // Add certificate to nssdb + cert = request.getExtDataInCert(IEnrollProfile.REQUEST_ISSUED_CERT); +@@ -2697,7 +2706,10 @@ public class CertificateAuthority + // log this error. + CMS.debug("Error deleting new authority entry after failure during certificate generation: " + e2); + } +- throw new ECAException("Error creating lightweight CA certificate: " + e); ++ if (e instanceof BadRequestDataException) ++ throw (BadRequestDataException) e; // re-throw ++ else ++ throw new ECAException("Error creating lightweight CA certificate: " + e, e); + } + + CertificateAuthority ca = new CertificateAuthority( +diff --git a/base/ca/src/org/dogtagpki/server/ca/rest/AuthorityService.java b/base/ca/src/org/dogtagpki/server/ca/rest/AuthorityService.java +index 5ecabac..7bca10f 100644 +--- a/base/ca/src/org/dogtagpki/server/ca/rest/AuthorityService.java ++++ b/base/ca/src/org/dogtagpki/server/ca/rest/AuthorityService.java +@@ -38,6 +38,7 @@ import javax.ws.rs.core.UriInfo; + import com.netscape.certsrv.apps.CMS; + import com.netscape.certsrv.authority.AuthorityData; + import com.netscape.certsrv.authority.AuthorityResource; ++import com.netscape.certsrv.base.BadRequestDataException; + import com.netscape.certsrv.base.BadRequestException; + import com.netscape.certsrv.base.ConflictingOperationException; + import com.netscape.certsrv.base.EBaseException; +@@ -207,7 +208,7 @@ public class AuthorityService extends PKIService implements AuthorityResource { + audit(ILogger.SUCCESS, OpDef.OP_ADD, + subCA.getAuthorityID().toString(), auditParams); + return createOKResponse(readAuthorityData(subCA)); +- } catch (IllegalArgumentException e) { ++ } catch (IllegalArgumentException | BadRequestDataException e) { + throw new BadRequestException(e.toString()); + } catch (CANotFoundException e) { + throw new ResourceNotFoundException(e.toString()); +-- +2.5.5 + + +From ca8edcd504ab81dbc30547c3c59a51fe98ff21cf Mon Sep 17 00:00:00 2001 +From: Fraser Tweedale +Date: Mon, 27 Jun 2016 15:04:44 +1000 +Subject: AuthInfoAccess: use default OCSP URI if configured + +The AuthInfoAccessExtDefault profile component constructs an OCSP +URI based on the current host and port, if no URI is explicitly +configured in the profile. + +Update the component to look in CS.cfg for the "ca.defaultOcspUri" +config, and use its value if present. If not present, the old +behaviour prevails. + +Also add the 'pki_default_ocsp_uri' pkispawn config to add the +config during instance creation, so that the value will be used for +the CA and system certificates. + +Fixes: https://fedorahosted.org/pki/ticket/2387 +--- + .../src/com/netscape/cms/profile/def/AuthInfoAccessExtDefault.java | 5 +++-- + base/server/etc/default.cfg | 5 +++++ + base/server/python/pki/server/deployment/scriptlets/configuration.py | 5 +++++ + 3 files changed, 13 insertions(+), 2 deletions(-) + +diff --git a/base/server/cms/src/com/netscape/cms/profile/def/AuthInfoAccessExtDefault.java b/base/server/cms/src/com/netscape/cms/profile/def/AuthInfoAccessExtDefault.java +index 36818a9..1190f28 100644 +--- a/base/server/cms/src/com/netscape/cms/profile/def/AuthInfoAccessExtDefault.java ++++ b/base/server/cms/src/com/netscape/cms/profile/def/AuthInfoAccessExtDefault.java +@@ -430,9 +430,10 @@ public class AuthInfoAccessExtDefault extends EnrollExtDefault { + if (method.equals("1.3.6.1.5.5.7.48.1")) { + String hostname = CMS.getEENonSSLHost(); + String port = CMS.getEENonSSLPort(); ++ String uri = ""; + if (hostname != null && port != null) +- // location = "http://"+hostname+":"+port+"/ocsp/ee/ocsp"; +- location = "http://" + hostname + ":" + port + "/ca/ocsp"; ++ uri = "http://" + hostname + ":" + port + "/ca/ocsp"; ++ location = CMS.getConfigStore().getString("ca.defaultOcspUri", uri); + } + } + +diff --git a/base/server/etc/default.cfg b/base/server/etc/default.cfg +index aa97e1f..edd2632 100644 +--- a/base/server/etc/default.cfg ++++ b/base/server/etc/default.cfg +@@ -417,6 +417,11 @@ pki_ds_hostname=%(pki_hostname)s + pki_subsystem_name=CA %(pki_hostname)s %(pki_https_port)s + pki_share_db=False + ++# Default OCSP URI added by AuthInfoAccessExtDefault if the profile ++# config is blank. If both are blank, the value is constructed ++# based on the CMS hostname and port. ++pki_default_ocsp_uri= ++ + # Paths + # These are used in the processing of pkispawn and are not supposed + # to be overwritten by user configuration files. +diff --git a/base/server/python/pki/server/deployment/scriptlets/configuration.py b/base/server/python/pki/server/deployment/scriptlets/configuration.py +index b8505dd..64ee4e5 100644 +--- a/base/server/python/pki/server/deployment/scriptlets/configuration.py ++++ b/base/server/python/pki/server/deployment/scriptlets/configuration.py +@@ -87,6 +87,11 @@ class PkiScriptlet(pkiscriptlet.AbstractBasePkiScriptlet): + subsystem = instance.get_subsystem( + deployer.mdict['pki_subsystem'].lower()) + ++ ocsp_uri = deployer.mdict.get('pki_default_ocsp_uri') ++ if ocsp_uri: ++ subsystem.config['ca.defaultOcspUri'] = ocsp_uri ++ subsystem.save() ++ + token = deployer.mdict['pki_token_name'] + nssdb = instance.open_nssdb(token) + +-- +2.5.5 + + +From 2dea243d51765e3a8f01f7680592143c842921ce Mon Sep 17 00:00:00 2001 +From: Fraser Tweedale +Date: Wed, 22 Jun 2016 13:34:01 +1000 +Subject: Add profiles container to LDAP if missing + +CMS startup was changed a while back to wait for +LDAPProfileSubsystem initialisation, while LDAPProfileSubsystem +initialisation waits for all known profiles to be loaded by the LDAP +persistent search thread. If the ou=certificateProfiles container +object does not exist, startup hangs. + +This can cause a race condition in FreeIPA upgrade. FreeIPA +switches the Dogtag instance to the LDAPProfileSubsystem and +restarts it. The restart fails because the container object does +not get added until after the restart. + +Update LDAPProfileSubsystem to add the container object itself, if +it is missing, before commencing the persistent search. + +Fixes: https://fedorahosted.org/pki/ticket/2285 +--- + .../cmscore/profile/LDAPProfileSubsystem.java | 19 +++++++++++++++++++ + 1 file changed, 19 insertions(+) + +diff --git a/base/server/cmscore/src/com/netscape/cmscore/profile/LDAPProfileSubsystem.java b/base/server/cmscore/src/com/netscape/cmscore/profile/LDAPProfileSubsystem.java +index 28b34cd..6dea1a0 100644 +--- a/base/server/cmscore/src/com/netscape/cmscore/profile/LDAPProfileSubsystem.java ++++ b/base/server/cmscore/src/com/netscape/cmscore/profile/LDAPProfileSubsystem.java +@@ -27,6 +27,7 @@ import java.util.TreeSet; + import java.util.concurrent.CountDownLatch; + + import netscape.ldap.LDAPAttribute; ++import netscape.ldap.LDAPAttributeSet; + import netscape.ldap.LDAPConnection; + import netscape.ldap.LDAPDN; + import netscape.ldap.LDAPEntry; +@@ -400,6 +401,23 @@ public class LDAPProfileSubsystem + initialLoadDone.countDown(); + } + ++ private void ensureProfilesOU(LDAPConnection conn) throws LDAPException { ++ try { ++ conn.search(dn, LDAPConnection.SCOPE_BASE, "(objectclass=*)", null, false); ++ } catch (LDAPException e) { ++ if (e.getLDAPResultCode() == LDAPException.NO_SUCH_OBJECT) { ++ CMS.debug("Adding LDAP certificate profiles container"); ++ LDAPAttribute[] attrs = { ++ new LDAPAttribute("objectClass", "organizationalUnit"), ++ new LDAPAttribute("ou", "certificateProfiles") ++ }; ++ LDAPAttributeSet attrSet = new LDAPAttributeSet(attrs); ++ LDAPEntry entry = new LDAPEntry(dn, attrSet); ++ conn.add(entry); ++ } ++ } ++ } ++ + public void run() { + int op = LDAPPersistSearchControl.ADD + | LDAPPersistSearchControl.MODIFY +@@ -416,6 +434,7 @@ public class LDAPProfileSubsystem + forgetAllProfiles(); + try { + conn = dbFactory.getConn(); ++ ensureProfilesOU(conn); + LDAPSearchConstraints cons = conn.getSearchConstraints(); + cons.setServerControls(persistCtrl); + cons.setBatchSize(1); +-- +2.5.5 + + +From 943e8231fc77ed0ccb6ed34b71817a6d3927d3e5 Mon Sep 17 00:00:00 2001 +From: "Endi S. Dewata" +Date: Fri, 1 Jul 2016 03:54:58 +0200 +Subject: Removed excessive error message in pki CLI. + +A recent change in the pki CLI caused excessive error message in +normal usage. The change has been reverted. + +https://fedorahosted.org/pki/ticket/2390 +--- + base/java-tools/bin/pki | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/base/java-tools/bin/pki b/base/java-tools/bin/pki +index 6104a5f..c1ba34e 100644 +--- a/base/java-tools/bin/pki ++++ b/base/java-tools/bin/pki +@@ -261,6 +261,7 @@ if __name__ == '__main__': + + except subprocess.CalledProcessError as e: + if cli.verbose: ++ print('ERROR: %s' % e) ++ elif cli.debug: + traceback.print_exc() +- print('ERROR: %s' % e) + sys.exit(e.returncode) +-- +2.5.5 + + +From 67bbdc5edd1404f89e638037599b4231f50490f8 Mon Sep 17 00:00:00 2001 +From: "Endi S. Dewata" +Date: Wed, 29 Jun 2016 17:13:20 +0200 +Subject: Fixed pki-server subsystem-cert-update. + +The pki-server subsystem-cert-update is supposed to restore the +system certificate data and requests into CS.cfg. The command was +broken since the CASubsystem class that contains the code to find +the certificate requests from database was not loaded correctly. +To fix the problem the CASubsystem class has been moved into the +pki/server/__init__.py. + +All pki-server subsystem-* commands have been modified to check +the validity of the instance. + +An option has been added to the pki-server subsystem-cert-show +command to display the data and request of a particular system +certificate. + +The redundant output of the pki-server subsystem-cert-update has +been removed. The updated certificate data and request can be +obtained using the pki-server subsystem-cert-show command. + +https://fedorahosted.org/pki/ticket/2385 +--- + base/server/python/pki/server/__init__.py | 67 +++++++++++++++++++ + base/server/python/pki/server/ca.py | 91 -------------------------- + base/server/python/pki/server/cli/subsystem.py | 58 ++++++++++++++-- + 3 files changed, 120 insertions(+), 96 deletions(-) + delete mode 100644 base/server/python/pki/server/ca.py + +diff --git a/base/server/python/pki/server/__init__.py b/base/server/python/pki/server/__init__.py +index 87303cd..03bb225 100644 +--- a/base/server/python/pki/server/__init__.py ++++ b/base/server/python/pki/server/__init__.py +@@ -25,6 +25,7 @@ import getpass + import grp + import io + import ldap ++import ldap.filter + import operator + import os + import pwd +@@ -389,6 +390,72 @@ class PKISubsystem(object): + return str(self.instance) + '/' + self.name + + ++class CASubsystem(PKISubsystem): ++ ++ def __init__(self, instance): ++ super(CASubsystem, self).__init__(instance, 'ca') ++ ++ def find_cert_requests(self, cert=None): ++ ++ base_dn = self.config['internaldb.basedn'] ++ ++ if cert: ++ escaped_value = ldap.filter.escape_filter_chars(cert) ++ search_filter = '(extdata-req--005fissued--005fcert=%s)' % escaped_value ++ ++ else: ++ search_filter = '(objectClass=*)' ++ ++ con = self.open_database() ++ ++ entries = con.ldap.search_s( ++ 'ou=ca,ou=requests,%s' % base_dn, ++ ldap.SCOPE_ONELEVEL, ++ search_filter, ++ None) ++ ++ con.close() ++ ++ requests = [] ++ for entry in entries: ++ requests.append(self.create_request_object(entry)) ++ ++ return requests ++ ++ def get_cert_requests(self, request_id): ++ ++ base_dn = self.config['internaldb.basedn'] ++ ++ con = self.open_database() ++ ++ entries = con.ldap.search_s( ++ 'cn=%s,ou=ca,ou=requests,%s' % (request_id, base_dn), ++ ldap.SCOPE_BASE, ++ '(objectClass=*)', ++ None) ++ ++ con.close() ++ ++ entry = entries[0] ++ return self.create_request_object(entry) ++ ++ def create_request_object(self, entry): ++ ++ attrs = entry[1] ++ ++ request = {} ++ request['id'] = attrs['cn'][0] ++ request['type'] = attrs['requestType'][0] ++ request['status'] = attrs['requestState'][0] ++ request['request'] = attrs['extdata-cert--005frequest'][0] ++ ++ return request ++ ++ ++# register CASubsystem ++SUBSYSTEM_CLASSES['ca'] = CASubsystem ++ ++ + class ExternalCert(object): + + def __init__(self, nickname=None, token=None): +diff --git a/base/server/python/pki/server/ca.py b/base/server/python/pki/server/ca.py +deleted file mode 100644 +index afb281c..0000000 +--- a/base/server/python/pki/server/ca.py ++++ /dev/null +@@ -1,91 +0,0 @@ +-# Authors: +-# Endi S. Dewata +-# +-# This program is free software; you can redistribute it and/or modify +-# it under the terms of the GNU General Public License as published by +-# the Free Software Foundation; version 2 of the License. +-# +-# This program is distributed in the hope that it will be useful, +-# but WITHOUT ANY WARRANTY; without even the implied warranty of +-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-# GNU General Public License for more details. +-# +-# You should have received a copy of the GNU General Public License along +-# with this program; if not, write to the Free Software Foundation, Inc., +-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Copyright (C) 2015 Red Hat, Inc. +-# All rights reserved. +-# +- +-from __future__ import absolute_import +-import ldap +-import ldap.filter +- +-import pki +-import pki.server +- +- +-class CASubsystem(pki.server.PKISubsystem): +- +- def __init__(self, instance): +- super(CASubsystem, self).__init__(instance, 'ca') +- +- def find_cert_requests(self, cert=None): +- +- base_dn = self.config['internaldb.basedn'] +- +- if cert: +- escaped_value = ldap.filter.escape_filter_chars(cert) +- search_filter = '(extdata-req--005fissued--005fcert=%s)' % escaped_value +- +- else: +- search_filter = '(objectClass=*)' +- +- con = self.open_database() +- +- entries = con.ldap.search_s( +- 'ou=ca,ou=requests,%s' % base_dn, +- ldap.SCOPE_ONELEVEL, +- search_filter, +- None) +- +- con.close() +- +- requests = [] +- for entry in entries: +- requests.append(self.create_request_object(entry)) +- +- return requests +- +- def get_cert_requests(self, request_id): +- +- base_dn = self.config['internaldb.basedn'] +- +- con = self.open_database() +- +- entries = con.ldap.search_s( +- 'cn=%s,ou=ca,ou=requests,%s' % (request_id, base_dn), +- ldap.SCOPE_BASE, +- '(objectClass=*)', +- None) +- +- con.close() +- +- entry = entries[0] +- return self.create_request_object(entry) +- +- def create_request_object(self, entry): +- +- attrs = entry[1] +- +- request = {} +- request['id'] = attrs['cn'][0] +- request['type'] = attrs['requestType'][0] +- request['status'] = attrs['requestState'][0] +- request['request'] = attrs['extdata-cert--005frequest'][0] +- +- return request +- +- +-pki.server.SUBSYSTEM_CLASSES['ca'] = CASubsystem +diff --git a/base/server/python/pki/server/cli/subsystem.py b/base/server/python/pki/server/cli/subsystem.py +index 45f5be9..49215cf 100644 +--- a/base/server/python/pki/server/cli/subsystem.py ++++ b/base/server/python/pki/server/cli/subsystem.py +@@ -99,6 +99,11 @@ class SubsystemFindCLI(pki.cli.CLI): + sys.exit(1) + + instance = pki.server.PKIInstance(instance_name) ++ ++ if not instance.is_valid(): ++ print('ERROR: Invalid instance %s.' % instance_name) ++ sys.exit(1) ++ + instance.load() + + self.print_message('%s entries matched' % len(instance.subsystems)) +@@ -164,6 +169,11 @@ class SubsystemShowCLI(pki.cli.CLI): + subsystem_name = args[0] + + instance = pki.server.PKIInstance(instance_name) ++ ++ if not instance.is_valid(): ++ print('ERROR: Invalid instance %s.' % instance_name) ++ sys.exit(1) ++ + instance.load() + + subsystem = instance.get_subsystem(subsystem_name) +@@ -222,6 +232,11 @@ class SubsystemEnableCLI(pki.cli.CLI): + subsystem_name = args[0] + + instance = pki.server.PKIInstance(instance_name) ++ ++ if not instance.is_valid(): ++ print('ERROR: Invalid instance %s.' % instance_name) ++ sys.exit(1) ++ + instance.load() + + subsystem = instance.get_subsystem(subsystem_name) +@@ -285,6 +300,11 @@ class SubsystemDisableCLI(pki.cli.CLI): + subsystem_name = args[0] + + instance = pki.server.PKIInstance(instance_name) ++ ++ if not instance.is_valid(): ++ print('ERROR: Invalid instance %s.' % instance_name) ++ sys.exit(1) ++ + instance.load() + + subsystem = instance.get_subsystem(subsystem_name) +@@ -375,6 +395,11 @@ class SubsystemCertFindCLI(pki.cli.CLI): + subsystem_name = args[0] + + instance = pki.server.PKIInstance(instance_name) ++ ++ if not instance.is_valid(): ++ print('ERROR: Invalid instance %s.' % instance_name) ++ sys.exit(1) ++ + instance.load() + + subsystem = instance.get_subsystem(subsystem_name) +@@ -402,6 +427,7 @@ class SubsystemCertShowCLI(pki.cli.CLI): + print('Usage: pki-server subsystem-cert-show [OPTIONS] ') + print() + print(' -i, --instance Instance ID (default: pki-tomcat).') ++ print(' --show-all Show all attributes.') + print(' -v, --verbose Run in verbose mode.') + print(' --help Show help message.') + print() +@@ -410,7 +436,7 @@ class SubsystemCertShowCLI(pki.cli.CLI): + + try: + opts, args = getopt.gnu_getopt(argv, 'i:v', [ +- 'instance=', ++ 'instance=', 'show-all', + 'verbose', 'help']) + + except getopt.GetoptError as e: +@@ -419,11 +445,15 @@ class SubsystemCertShowCLI(pki.cli.CLI): + sys.exit(1) + + instance_name = 'pki-tomcat' ++ show_all = False + + for o, a in opts: + if o in ('-i', '--instance'): + instance_name = a + ++ elif o == '--show-all': ++ show_all = True ++ + elif o in ('-v', '--verbose'): + self.set_verbose(True) + +@@ -451,12 +481,17 @@ class SubsystemCertShowCLI(pki.cli.CLI): + cert_id = args[1] + + instance = pki.server.PKIInstance(instance_name) ++ ++ if not instance.is_valid(): ++ print('ERROR: Invalid instance %s.' % instance_name) ++ sys.exit(1) ++ + instance.load() + + subsystem = instance.get_subsystem(subsystem_name) +- subsystem_cert = subsystem.get_subsystem_cert(cert_id) ++ cert = subsystem.get_subsystem_cert(cert_id) + +- SubsystemCertCLI.print_subsystem_cert(subsystem_cert) ++ SubsystemCertCLI.print_subsystem_cert(cert, show_all) + + + class SubsystemCertExportCLI(pki.cli.CLI): +@@ -568,6 +603,11 @@ class SubsystemCertExportCLI(pki.cli.CLI): + sys.exit(1) + + instance = pki.server.PKIInstance(instance_name) ++ ++ if not instance.is_valid(): ++ print('ERROR: Invalid instance %s.' % instance_name) ++ sys.exit(1) ++ + instance.load() + + subsystem = instance.get_subsystem(subsystem_name) +@@ -684,6 +724,11 @@ class SubsystemCertUpdateCLI(pki.cli.CLI): + cert_id = args[1] + + instance = pki.server.PKIInstance(instance_name) ++ ++ if not instance.is_valid(): ++ print('ERROR: Invalid instance %s.' % instance_name) ++ sys.exit(1) ++ + instance.load() + + subsystem = instance.get_subsystem(subsystem_name) +@@ -723,8 +768,6 @@ class SubsystemCertUpdateCLI(pki.cli.CLI): + + self.print_message('Updated "%s" subsystem certificate' % cert_id) + +- SubsystemCertCLI.print_subsystem_cert(subsystem_cert) +- + + class SubsystemCertValidateCLI(pki.cli.CLI): + +@@ -783,6 +826,11 @@ class SubsystemCertValidateCLI(pki.cli.CLI): + cert_id = None + + instance = pki.server.PKIInstance(instance_name) ++ ++ if not instance.is_valid(): ++ print('ERROR: Invalid instance %s.' % instance_name) ++ sys.exit(1) ++ + instance.load() + + subsystem = instance.get_subsystem(subsystem_name) +-- +2.5.5 + + +From f8310a4ff306d28cf25ec71693a2e89c5323564d Mon Sep 17 00:00:00 2001 +From: "Endi S. Dewata" +Date: Fri, 1 Jul 2016 03:26:23 +0200 +Subject: Added instance and subsystem validation for pki-server ca-* commands. + +The pki-server ca-* commands have been modified to validate +the instance and the CA subsystem before proceeding with the +operation. + +The usage() methods and invocations have been renamed into +print_help() for consistency. + +https://fedorahosted.org/pki/ticket/2364 +--- + base/server/python/pki/server/cli/ca.py | 44 +++++++++++++++++++++++++++------ + 1 file changed, 37 insertions(+), 7 deletions(-) + +diff --git a/base/server/python/pki/server/cli/ca.py b/base/server/python/pki/server/cli/ca.py +index dbf8239..1d1c00f 100644 +--- a/base/server/python/pki/server/cli/ca.py ++++ b/base/server/python/pki/server/cli/ca.py +@@ -129,9 +129,16 @@ class CACertChainExportCLI(pki.cli.CLI): + sys.exit(1) + + instance = pki.server.PKIInstance(instance_name) ++ if not instance.is_valid(): ++ print('ERROR: Invalid instance %s.' % instance_name) ++ sys.exit(1) ++ + instance.load() + + subsystem = instance.get_subsystem('ca') ++ if not subsystem: ++ print('ERROR: No CA subsystem in instance %s.' % instance_name) ++ sys.exit(1) + + tmpdir = tempfile.mkdtemp() + +@@ -171,7 +178,7 @@ class CACertRequestFindCLI(pki.cli.CLI): + super(CACertRequestFindCLI, self).__init__( + 'find', 'Find CA certificate requests') + +- def usage(self): ++ def print_help(self): + print('Usage: pki-server ca-cert-request-find [OPTIONS]') + print() + print(' -i, --instance Instance ID (default: pki-tomcat).') +@@ -190,7 +197,7 @@ class CACertRequestFindCLI(pki.cli.CLI): + + except getopt.GetoptError as e: + print('ERROR: ' + str(e)) +- self.usage() ++ self.print_help() + sys.exit(1) + + instance_name = 'pki-tomcat' +@@ -216,13 +223,21 @@ class CACertRequestFindCLI(pki.cli.CLI): + + else: + print('ERROR: unknown option ' + o) +- self.usage() ++ self.print_help() + sys.exit(1) + + instance = pki.server.PKIInstance(instance_name) ++ if not instance.is_valid(): ++ print('ERROR: Invalid instance %s.' % instance_name) ++ sys.exit(1) ++ + instance.load() + + subsystem = instance.get_subsystem('ca') ++ if not subsystem: ++ print('ERROR: No CA subsystem in instance %s.' % instance_name) ++ sys.exit(1) ++ + results = subsystem.find_cert_requests(cert=cert) + + self.print_message('%s entries matched' % len(results)) +@@ -243,7 +258,7 @@ class CACertRequestShowCLI(pki.cli.CLI): + super(CACertRequestShowCLI, self).__init__( + 'show', 'Show CA certificate request') + +- def usage(self): ++ def print_help(self): + print('Usage: pki-server ca-cert-request-show [OPTIONS]') + print() + print(' -i, --instance Instance ID (default: pki-tomcat).') +@@ -260,12 +275,12 @@ class CACertRequestShowCLI(pki.cli.CLI): + + except getopt.GetoptError as e: + print('ERROR: ' + str(e)) +- self.usage() ++ self.print_help() + sys.exit(1) + + if len(args) != 1: + print('ERROR: missing request ID') +- self.usage() ++ self.print_help() + sys.exit(1) + + request_id = args[0] +@@ -288,13 +303,21 @@ class CACertRequestShowCLI(pki.cli.CLI): + + else: + print('ERROR: unknown option ' + o) +- self.usage() ++ self.print_help() + sys.exit(1) + + instance = pki.server.PKIInstance(instance_name) ++ if not instance.is_valid(): ++ print('ERROR: Invalid instance %s.' % instance_name) ++ sys.exit(1) ++ + instance.load() + + subsystem = instance.get_subsystem('ca') ++ if not subsystem: ++ print('ERROR: No CA subsystem in instance %s.' % instance_name) ++ sys.exit(1) ++ + request = subsystem.get_cert_requests(request_id) + + if output_file: +@@ -384,9 +407,16 @@ class CAClonePrepareCLI(pki.cli.CLI): + sys.exit(1) + + instance = pki.server.PKIInstance(instance_name) ++ if not instance.is_valid(): ++ print('ERROR: Invalid instance %s.' % instance_name) ++ sys.exit(1) ++ + instance.load() + + subsystem = instance.get_subsystem('ca') ++ if not subsystem: ++ print('ERROR: No CA subsystem in instance %s.' % instance_name) ++ sys.exit(1) + + tmpdir = tempfile.mkdtemp() + +-- +2.5.5 + + +From e81cf4e11ca86562b27548d469fa606a072da23b Mon Sep 17 00:00:00 2001 +From: Abhijeet Kasurde +Date: Fri, 1 Jul 2016 10:05:05 +0530 +Subject: Updated notification message for kra-db-vlv* command + +Partially Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1351295 +--- + base/server/python/pki/server/cli/kra.py | 38 +++++++++++++++++++------------- + 1 file changed, 23 insertions(+), 15 deletions(-) + +diff --git a/base/server/python/pki/server/cli/kra.py b/base/server/python/pki/server/cli/kra.py +index 17611a8..5c9111d 100644 +--- a/base/server/python/pki/server/cli/kra.py ++++ b/base/server/python/pki/server/cli/kra.py +@@ -361,19 +361,28 @@ class KRADBVLVAddCLI(pki.cli.CLI): + print('ERROR: Invalid instance %s.' % instance_name) + sys.exit(1) + instance.load() +- self.add_vlv(instance, bind_dn, bind_password) + +- def add_vlv(self, instance, bind_dn, bind_password): + subsystem = instance.get_subsystem('kra') + if not subsystem: +- print('No KRA subsystem available.') +- return ++ print('ERROR: No KRA subsystem in instance %s.' % instance_name) ++ sys.exit(1) + + if self.out_file: + subsystem.customize_file(KRA_VLV_PATH, self.out_file) + print('KRA VLVs written to ' + self.out_file) + return + ++ try: ++ self.add_vlv(subsystem, bind_dn, bind_password) ++ ++ print('KRA VLVs added to the database for ' + instance_name) ++ ++ except ldap.LDAPError as e: ++ print("ERROR: " + e.message['desc']) ++ sys.exit(1) ++ ++ def add_vlv(self, subsystem, bind_dn, bind_password): ++ + ldif_file = tempfile.NamedTemporaryFile(delete=False) + subsystem.customize_file(KRA_VLV_PATH, ldif_file.name) + +@@ -386,12 +395,11 @@ class KRADBVLVAddCLI(pki.cli.CLI): + for dn, entry in parser.all_records: + add_modlist = ldap.modlist.addModlist(entry) + conn.ldap.add_s(dn, add_modlist) ++ + finally: + os.unlink(ldif_file.name) + conn.close() + +- print('KRA VLVs added to the database for ' + instance.name) +- + + class KRADBVLVDeleteCLI(pki.cli.CLI): + +@@ -581,28 +589,30 @@ class KRADBVLVReindexCLI(pki.cli.CLI): + print('ERROR: Invalid instance %s.' % instance_name) + sys.exit(1) + instance.load() +- self.reindex_vlv(instance, bind_dn, bind_password) + +- def reindex_vlv(self, instance, bind_dn, bind_password): + subsystem = instance.get_subsystem('kra') + if not subsystem: +- if self.verbose: +- print('reindex_vlv: No KRA subsystem available. ' +- 'Skipping ...') +- return ++ print('ERROR: No KRA subsystem in instance %s.' % instance_name) ++ sys.exit(1) + + if self.out_file: + subsystem.customize_file(KRA_VLV_TASKS_PATH, self.out_file) + print('KRA VLV reindex task written to ' + self.out_file) + return + ++ self.reindex_vlv(subsystem, bind_dn, bind_password) ++ ++ print('KRA VLV reindex completed for ' + instance_name) ++ ++ def reindex_vlv(self, subsystem, bind_dn, bind_password): ++ + ldif_file = tempfile.NamedTemporaryFile(delete=False) + subsystem.customize_file(KRA_VLV_TASKS_PATH, ldif_file.name) + + conn = subsystem.open_database(bind_dn=bind_dn, + bind_password=bind_password) + +- print('Initiating KRA VLV reindex for ' + instance.name) ++ print('Initiating KRA VLV reindex for ' + subsystem.instance.name) + + try: + parser = ldif.LDIFRecordList(open(ldif_file.name, "rb")) +@@ -630,5 +640,3 @@ class KRADBVLVReindexCLI(pki.cli.CLI): + finally: + os.unlink(ldif_file.name) + conn.close() +- +- print('KRA VLV reindex completed for ' + instance.name) +-- +2.5.5 + + +From a646c1b6e67a5c4d105208254fa3288cdbd86c6e Mon Sep 17 00:00:00 2001 +From: Abhijeet Kasurde +Date: Fri, 1 Jul 2016 10:23:53 +0530 +Subject: Updated notification message for OCSP subsystem command + +Partially fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1351295 +--- + base/server/python/pki/server/cli/ocsp.py | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/base/server/python/pki/server/cli/ocsp.py b/base/server/python/pki/server/cli/ocsp.py +index c32e8de..246f593 100644 +--- a/base/server/python/pki/server/cli/ocsp.py ++++ b/base/server/python/pki/server/cli/ocsp.py +@@ -118,9 +118,15 @@ class OCSPClonePrepareCLI(pki.cli.CLI): + sys.exit(1) + + instance = pki.server.PKIInstance(instance_name) ++ if not instance.is_valid(): ++ print('ERROR: Invalid instance %s.' % instance_name) ++ sys.exit(1) + instance.load() + + subsystem = instance.get_subsystem('ocsp') ++ if not subsystem: ++ print("ERROR: No OCSP subsystem in instance %s." % instance_name) ++ sys.exit(1) + + tmpdir = tempfile.mkdtemp() + +-- +2.5.5 + + +From ab8655ca693ddf5afc0579db42cfbea61e8fee89 Mon Sep 17 00:00:00 2001 +From: Abhijeet Kasurde +Date: Fri, 1 Jul 2016 10:31:32 +0530 +Subject: Updated notification message for TKS subsystem command + +Partially fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1351295 +--- + base/server/python/pki/server/cli/tks.py | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/base/server/python/pki/server/cli/tks.py b/base/server/python/pki/server/cli/tks.py +index 0bcf748..2c4157a 100644 +--- a/base/server/python/pki/server/cli/tks.py ++++ b/base/server/python/pki/server/cli/tks.py +@@ -118,9 +118,16 @@ class TKSClonePrepareCLI(pki.cli.CLI): + sys.exit(1) + + instance = pki.server.PKIInstance(instance_name) ++ if not instance.is_valid(): ++ print('ERROR: Invalid instance %s.' % instance_name) ++ sys.exit(1) ++ + instance.load() + + subsystem = instance.get_subsystem('tks') ++ if not subsystem: ++ print("ERROR: No TKS subsystem in instance %s." % instance_name) ++ sys.exit(1) + + tmpdir = tempfile.mkdtemp() + +-- +2.5.5 + + +From eb0f8d0f1e9d396efb071c6432aa22ff0a39d613 Mon Sep 17 00:00:00 2001 +From: Abhijeet Kasurde +Date: Fri, 1 Jul 2016 10:35:21 +0530 +Subject: Updated notification message for TPS subsystem command + +Partially fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1351295 +--- + base/server/python/pki/server/cli/tps.py | 34 ++++++++++++++++++++++++-------- + 1 file changed, 26 insertions(+), 8 deletions(-) + +diff --git a/base/server/python/pki/server/cli/tps.py b/base/server/python/pki/server/cli/tps.py +index 63da341..1f71b8e 100644 +--- a/base/server/python/pki/server/cli/tps.py ++++ b/base/server/python/pki/server/cli/tps.py +@@ -127,9 +127,15 @@ class TPSClonePrepareCLI(pki.cli.CLI): + sys.exit(1) + + instance = pki.server.PKIInstance(instance_name) ++ if not instance.is_valid(): ++ print('ERROR: Invalid instance %s.' % instance_name) ++ sys.exit(1) + instance.load() + + subsystem = instance.get_subsystem('tps') ++ if not subsystem: ++ print("ERROR: No TPS subsystem in instance %s." % instance_name) ++ sys.exit(1) + + tmpdir = tempfile.mkdtemp() + +@@ -228,12 +234,15 @@ class TPSDBVLVFindCLI(pki.cli.CLI): + sys.exit(1) + + instance = pki.server.PKIInstance(instance_name) ++ if not instance.is_valid(): ++ print('ERROR: Invalid instance %s.' % instance_name) ++ sys.exit(1) + instance.load() + + subsystem = instance.get_subsystem('tps') +- + if not subsystem: +- raise Exception('Subsystem not found') ++ print("ERROR: No TPS subsystem in instance %s." % instance_name) ++ sys.exit(1) + + self.find_vlv(subsystem, bind_dn, bind_password) + +@@ -340,12 +349,15 @@ class TPSDBVLVAddCLI(pki.cli.CLI): + sys.exit(1) + + instance = pki.server.PKIInstance(instance_name) ++ if not instance.is_valid(): ++ print('ERROR: Invalid instance %s.' % instance_name) ++ sys.exit(1) + instance.load() + + subsystem = instance.get_subsystem('tps') +- + if not subsystem: +- raise Exception('Subsystem not found') ++ print("ERROR: No TPS subsystem in instance %s." % instance_name) ++ sys.exit(1) + + if out_file: + self.generate_ldif(subsystem, out_file) +@@ -450,12 +462,15 @@ class TPSDBVLVDeleteCLI(pki.cli.CLI): + sys.exit(1) + + instance = pki.server.PKIInstance(instance_name) ++ if not instance.is_valid(): ++ print('ERROR: Invalid instance %s.' % instance_name) ++ sys.exit(1) + instance.load() + + subsystem = instance.get_subsystem('tps') +- + if not subsystem: +- raise Exception('Subsystem not found') ++ print("ERROR: No TPS subsystem in instance %s." % instance_name) ++ sys.exit(1) + + if out_file: + self.generate_ldif(subsystem, out_file) +@@ -582,12 +597,15 @@ class TPSDBVLVReindexCLI(pki.cli.CLI): + sys.exit(1) + + instance = pki.server.PKIInstance(instance_name) ++ if not instance.is_valid(): ++ print('ERROR: Invalid instance %s.' % instance_name) ++ sys.exit(1) + instance.load() + + subsystem = instance.get_subsystem('tps') +- + if not subsystem: +- raise Exception('Subsystem not found') ++ print("ERROR: No TPS subsystem in instance %s." % instance_name) ++ sys.exit(1) + + if out_file: + self.generate_ldif(subsystem, out_file) +-- +2.5.5 + + +From aef84ae829bf2645937363ee3e61f002c2682869 Mon Sep 17 00:00:00 2001 +From: Abhijeet Kasurde +Date: Fri, 1 Jul 2016 15:08:09 +0530 +Subject: Updated notification message for DB subsystem command + +Partially fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1351295 +--- + base/server/python/pki/server/cli/db.py | 20 +++++++++++++++----- + 1 file changed, 15 insertions(+), 5 deletions(-) + +diff --git a/base/server/python/pki/server/cli/db.py b/base/server/python/pki/server/cli/db.py +index 6555e40..cc768da 100644 +--- a/base/server/python/pki/server/cli/db.py ++++ b/base/server/python/pki/server/cli/db.py +@@ -25,6 +25,7 @@ import ldap + import nss.nss as nss + import subprocess + import sys ++import getpass + + import pki.cli + +@@ -96,12 +97,19 @@ class DBSchemaUpgrade(pki.cli.CLI): + + instance = pki.server.PKIInstance(instance_name) + if not instance.is_valid(): +- print("ERROR: Instance name '%s' not found" % instance) ++ print("ERROR: Invalid instance %s." % instance_name) + sys.exit(1) + instance.load() + ++ if not instance.subsystems: ++ print("ERROR: No subsystem in instance %s." % instance_name) ++ sys.exit(1) ++ ++ if not bind_password: ++ bind_password = getpass.getpass(prompt='Enter password: ') ++ + try: +- self.update_schema(instance, bind_dn, bind_password) ++ self.update_schema(instance.subsystems[0], bind_dn, bind_password) + + except subprocess.CalledProcessError as e: + print("ERROR: " + e.output) +@@ -109,9 +117,8 @@ class DBSchemaUpgrade(pki.cli.CLI): + + self.print_message('Upgrade complete') + +- def update_schema(self, instance, bind_dn, bind_password): ++ def update_schema(self, subsystem, bind_dn, bind_password): + # TODO(alee) re-implement this using open_database +- subsystem = instance.subsystems[0] + host = subsystem.config['internaldb.ldapconn.host'] + port = subsystem.config['internaldb.ldapconn.port'] + secure = subsystem.config['internaldb.ldapconn.secureConn'] +@@ -174,11 +181,14 @@ class DBUpgrade(pki.cli.CLI): + nss.nss_init_nodb() + + instance = pki.server.PKIInstance(instance_name) ++ if not instance.is_valid(): ++ print("ERROR: Invalid instance %s." % instance_name) ++ sys.exit(1) + instance.load() + + subsystem = instance.get_subsystem('ca') + if not subsystem: +- print('ERROR: missing subsystem ca') ++ print('ERROR: No CA subsystem in instance %s.' + instance_name) + sys.exit(1) + + base_dn = subsystem.config['internaldb.basedn'] +-- +2.5.5 + + +From 17e86cc2c5dde2f45f4ceef5bedb6e05062866e1 Mon Sep 17 00:00:00 2001 +From: Matthew Harmsen +Date: Fri, 1 Jul 2016 14:45:57 -0600 +Subject: Add HSM information + +- PKI TRAC Ticket #1405 - Add additional HSM details to 'pki_default.cfg' & + 'pkispawn' man pages +--- + base/server/man/man5/pki_default.cfg.5 | 8 +- + base/server/man/man8/pkispawn.8 | 173 +++++++++++++++++++++++++++++++++ + 2 files changed, 180 insertions(+), 1 deletion(-) + +diff --git a/base/server/man/man5/pki_default.cfg.5 b/base/server/man/man5/pki_default.cfg.5 +index 550e2aa..aaf7b53 100644 +--- a/base/server/man/man5/pki_default.cfg.5 ++++ b/base/server/man/man5/pki_default.cfg.5 +@@ -184,7 +184,10 @@ Location for the PKCS #12 file containing the administrative user's certificate + .B pki_backup_keys, pki_backup_password + .IP + Set to True to back up the subsystem certificates and keys to a PKCS #12 file. This file will be located in \fI/var/lib/pki//alias\fP. pki_backup_password is the password of the PKCS#12 file. +- ++.TP ++\fBImportant:\fP ++Since HSM keys are stored in the HSM (hardware), they cannot be backed up to a PKCS #12 file (software). Therefore, if \fBpki_hsm_enable\fP is set to True, \fBpki_backup_keys\fP should be set to False and \fBpki_backup_password\fP should be left unset (the default values in \fB/etc/pki/default.cfg\fP). Failure to do so will result in \fBpkispawn\fP reporting this error and exiting. ++ + .SS CLIENT DIRECTORY PARAMETERS + .TP + .B pki_client_dir +@@ -295,6 +298,9 @@ Installs a clone, rather than original, subsystem. + .IP + Location and password of the PKCS #12 file containing the system certificates for the master subsystem being cloned. This file should be readable by the user that the Certificate Server is running as (default of pkiuser), and have the correct selinux context (pki_tomcat_cert_t). This can be achieved by placing the file in \fI/var/lib/pki//alias\fP. + .TP ++\fBImportant:\fP ++Since HSM keys are stored in the HSM (hardware), they cannot be copied to a PKCS #12 file (software). For the case of clones using an HSM, this means that the HSM keys must be shared between the master and its clones. Therefore, if \fBpki_hsm_enable\fP is set to True, both \fBpki_clone_pkcs12_path\fP and \fBpki_clone_pkcs12_password\fP should be left unset (the default values in \fB/etc/pki/default.cfg\fP). Failure to do so will result in \fBpkispawn\fP reporting this error and exiting. ++.TP + .B pki_clone_setup_replication + .IP + Defaults to True. If set to False, the installer does not set up replication agreements from the master to the clone as part of the subsystem configuration. In this case, it is expected that the top level suffix already exists, and that the data has already been replicated. This option is useful if you want to use other tools to create and manage your replication topology, or if the baseDN is already replicated as part of a top-level suffix. +diff --git a/base/server/man/man8/pkispawn.8 b/base/server/man/man8/pkispawn.8 +index 3ad6fdb..3678cff 100644 +--- a/base/server/man/man8/pkispawn.8 ++++ b/base/server/man/man8/pkispawn.8 +@@ -756,6 +756,179 @@ conn.tks1.tksSharedSymKeyName=sharedSecret + .PP + Finally, restart the TPS instance. + ++.SS Installing a CA, KRA, OCSP, TKS, or TPS using a Hardware Security Module (HSM) ++.BR ++.PP ++This section provides sample \fBmyconfig.txt\fP files when an HSM is being utilized in a shared PKI instance. ++ ++.PP ++For this example, assume that a new CA instance has been installed by ++executing the following command: ++.IP ++\x'-1'\fBpkispawn \-s CA \-f myconfig.txt\fR ++.PP ++where \fImyconfig.txt\fP contains the following text: ++.IP ++.nf ++[DEFAULT] ++pki_admin_password=\fISecret123\fP ++pki_client_pkcs12_password=\fISecret123\fP ++pki_ds_password=\fISecret123\fP ++# Optionally keep client databases ++pki_client_database_purge=False ++# Provide HSM parameters ++pki_hsm_enable=True ++pki_hsm_libfile= ++pki_hsm_modulename= ++pki_token_name= ++pki_token_password= ++# Provide PKI-specific HSM token names ++pki_audit_signing_token= ++pki_ssl_server_token= ++pki_subsystem_token= ++[CA] ++# Provide CA-specific HSM token names ++pki_ca_signing_token= ++pki_ocsp_signing_token= ++.if ++ ++.PP ++To install a shared KRA in the same instance used by the CA execute ++the following command: ++.IP ++\x'-1'\fBpkispawn \-s KRA \-f myconfig.txt\fR ++.PP ++where \fImyconfig.txt\fP contains the following text: ++.IP ++.nf ++[DEFAULT] ++pki_admin_password=\fISecret123\fP ++pki_client_database_password=\fISecret123\fP ++pki_client_pkcs12_password=\fISecret123\fP ++pki_ds_password=\fISecret123\fP ++pki_security_domain_password=\fISecret123\fP ++# Provide HSM parameters ++pki_hsm_enable=True ++pki_hsm_libfile= ++pki_hsm_modulename= ++pki_token_name= ++pki_token_password= ++# Provide PKI-specific HSM token names ++pki_audit_signing_token= ++pki_ssl_server_token= ++pki_subsystem_token= ++[KRA] ++# Provide KRA-specific HSM token names ++pki_storage_token= ++pki_transport_token= ++.if ++ ++.PP ++To install a shared OCSP in the same instance used by the CA execute ++the following command: ++.IP ++\x'-1'\fBpkispawn \-s OCSP \-f myconfig.txt\fR ++.PP ++where \fImyconfig.txt\fP contains the following text: ++.IP ++.nf ++[DEFAULT] ++pki_admin_password=\fISecret123\fP ++pki_client_database_password=\fISecret123\fP ++pki_client_pkcs12_password=\fISecret123\fP ++pki_ds_password=\fISecret123\fP ++pki_security_domain_password=\fISecret123\fP ++# Provide HSM parameters ++pki_hsm_enable=True ++pki_hsm_libfile= ++pki_hsm_modulename= ++pki_token_name= ++pki_token_password= ++# Provide PKI-specific HSM token names ++pki_audit_signing_token= ++pki_ssl_server_token= ++pki_subsystem_token= ++[OCSP] ++# Provide OCSP-specific HSM token names ++pki_ocsp_signing_token= ++.if ++ ++.PP ++To install a shared TKS in the same instance used by the CA execute ++the following command: ++.IP ++\x'-1'\fBpkispawn \-s TKS \-f myconfig.txt\fR ++.PP ++where \fImyconfig.txt\fP contains the following text: ++.IP ++.nf ++[DEFAULT] ++pki_admin_password=\fISecret123\fP ++pki_client_database_password=\fISecret123\fP ++pki_client_pkcs12_password=\fISecret123\fP ++pki_ds_password=\fISecret123\fP ++pki_security_domain_password=\fISecret123\fP ++# Provide HSM parameters ++pki_hsm_enable=True ++pki_hsm_libfile= ++pki_hsm_modulename= ++pki_token_name= ++pki_token_password= ++# Provide PKI-specific HSM token names ++pki_audit_signing_token= ++pki_ssl_server_token= ++pki_subsystem_token= ++.if ++ ++.PP ++To install a shared TPS in the same instance used by the CA execute ++the following command: ++.IP ++\x'-1'\fBpkispawn \-s TPS \-f myconfig.txt\fR ++.PP ++where \fImyconfig.txt\fP contains the following text: ++.IP ++.nf ++[DEFAULT] ++pki_admin_password=\fISecret123\fP ++pki_client_database_password=\fISecret123\fP ++pki_client_pkcs12_password=\fISecret123\fP ++pki_ds_password=\fISecret123\fP ++pki_security_domain_password=\fISecret123\fP ++# Provide HSM parameters ++pki_hsm_enable=True ++pki_hsm_libfile= ++pki_hsm_modulename= ++pki_token_name= ++pki_token_password= ++# Provide PKI-specific HSM token names ++pki_audit_signing_token= ++pki_ssl_server_token= ++pki_subsystem_token= ++[TPS] ++# Shared TPS instances optionally utilize their shared KRA ++# for server-side keygen ++pki_enable_server_side_keygen=True ++pki_authdb_basedn=\fIdc=example,dc=com\fP ++.if ++ ++.TP ++\fBImportant:\fP ++Since HSM keys are stored in the HSM (hardware), they cannot be ++backed up, moved, or copied to a PKCS #12 file (software). ++For example, if \fBpki_hsm_enable\fP is set to True, ++\fBpki_backup_keys\fP should be set to False and ++\fBpki_backup_password\fP should be left unset (the default ++values in \fB/etc/pki/default.cfg\fP). Similarly, for the case ++of clones using an HSM, this means that the HSM keys must be ++shared between the master and its clones. Therefore, if ++\fBpki_hsm_enable\fP is set to True, both ++\fBpki_clone_pkcs12_path\fP and \fBpki_clone_pkcs12_password\fP ++should be left unset (the default values in ++\fB/etc/pki/default.cfg\fP). Failure to comply with these rules ++will result in \fBpkispawn\fP reporting an appropriate error and ++exiting. ++ + .SS Installing a CA clone + .BR + .PP +-- +2.5.5 + + +From cfab57d057c7ada71ea9c360c278249d14e018d9 Mon Sep 17 00:00:00 2001 +From: Jack Magne +Date: Fri, 24 Jun 2016 17:04:15 -0700 +Subject: Generting Symmetric key fails with key-generate when --usages verify + is passed + +Ticket #1114 + +Minor adjustment to the man page for the key management commands to say +which usages are appropriate for sym keys and those appropriate for asym keys. + +t +--- + base/java-tools/man/man1/pki-key.1 | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/base/java-tools/man/man1/pki-key.1 b/base/java-tools/man/man1/pki-key.1 +index 30ac909..669ab86 100644 +--- a/base/java-tools/man/man1/pki-key.1 ++++ b/base/java-tools/man/man1/pki-key.1 +@@ -329,7 +329,9 @@ Following is the description of the various parameters in the key retrieval temp + -- clientKeyID - Client specified unique key identifier + -- keyAlgorithm - Algorithm to be used to generate key (AES/DES/DES3/DESede/RC2/RC4) + -- keySize - Value for the size of the key to be generated. +- -- keyUsage - usages of the generated key(wrap,unwrap,sign,verify,encrypt,decrypt) ++ -- keyUsage - usages of the generated key ++ useful for Symmetric Keys (DES3,AES,etc) (wrap,unwrap,encrypt,decrypt) ++ useful for Asymmetric Keys (RSA, EC,etc) (wrap,unwrap,encrypt,decrypt,sign,verify,sign_recover,verify_recover) + + To create a key generation request using the template file: + +-- +2.5.5 + + +From 0f056221d096a30307834265ecd1c527087bb0f7 Mon Sep 17 00:00:00 2001 +From: Jack Magne +Date: Mon, 13 Jun 2016 11:27:59 -0700 +Subject: Separated TPS does not automatically receive shared secret from + remote TKS. + +Support to allow the TPS to do the following: + +1. Request that the TKS creates a shared secret with the proper ID, pointing to the TPS. +2. Have the TKS securely return the shared secret back to the TPS during the end of configuration. +3. The TPS then imports the wrapped shared secret into it's own internal NSS db permanenty and. +4. Given a name that is mapped to the TPS's id string. + +Additional fixes: + +1. The TKS was modified to actually be able to use multiple shared secrets registered by +multiple TPS instances. + +Caveat: + +At this point if the same remote TPS instance is created over and over again, the TPS's user +in the TKS will accumulate "userCert" attributes, making the exportation of teh shared secret +not functional. At this point we need to assume that the TPS user has ONE "userCert" registered +at this time. +--- + .../src/com/netscape/certsrv/key/KeyData.java | 21 +- + .../cms/servlet/csadmin/ConfigurationUtils.java | 247 ++++++++++++--------- + .../cms/servlet/tks/SecureChannelProtocol.java | 3 +- + .../com/netscape/cms/servlet/tks/TokenServlet.java | 26 ++- + base/server/man/man8/pkispawn.8 | 11 +- + .../server/tks/rest/TPSConnectorService.java | 147 +++++++++--- + .../server/tps/processor/TPSProcessor.java | 8 +- + .../server/tps/rest/TPSInstallerService.java | 12 +- + .../com/netscape/cmsutil/crypto/CryptoUtil.java | 157 +++++++++---- + 9 files changed, 435 insertions(+), 197 deletions(-) + +diff --git a/base/common/src/com/netscape/certsrv/key/KeyData.java b/base/common/src/com/netscape/certsrv/key/KeyData.java +index 6da4d38..e31cfb3 100644 +--- a/base/common/src/com/netscape/certsrv/key/KeyData.java ++++ b/base/common/src/com/netscape/certsrv/key/KeyData.java +@@ -48,7 +48,11 @@ public class KeyData { + @XmlElement + Integer size; + +- String privateData; ++ @XmlElement ++ String additionalWrappedPrivateData; ++ // Optionally used for importing a shared secret from TKS to TPS ++ // Will contain wrapped shared secret data. ++ // Can be used for anything in other scenarios + + public KeyData() { + // required for JAXB (defaults) +@@ -68,6 +72,15 @@ public class KeyData { + this.wrappedPrivateData = wrappedPrivateData; + } + ++ public String getAdditionalWrappedPrivateData() { ++ return additionalWrappedPrivateData; ++ } ++ ++ ++ public void setAdditionalWrappedPrivateData(String additionalWrappedPrivateData) { ++ this.additionalWrappedPrivateData = additionalWrappedPrivateData; ++ } ++ + /** + * @return the nonceData + */ +@@ -126,11 +139,5 @@ public class KeyData { + this.size = size; + } + +- public String getPrivateData() { +- return privateData; +- } + +- public void setPrivateData(String privateData) { +- this.privateData = privateData; +- } + } +diff --git a/base/server/cms/src/com/netscape/cms/servlet/csadmin/ConfigurationUtils.java b/base/server/cms/src/com/netscape/cms/servlet/csadmin/ConfigurationUtils.java +index 308f3e7..ab5e4d6 100644 +--- a/base/server/cms/src/com/netscape/cms/servlet/csadmin/ConfigurationUtils.java ++++ b/base/server/cms/src/com/netscape/cms/servlet/csadmin/ConfigurationUtils.java +@@ -15,7 +15,7 @@ + // (C) 2012 Red Hat, Inc. + // All rights reserved. + // --- END COPYRIGHT BLOCK --- +- package com.netscape.cms.servlet.csadmin; ++package com.netscape.cms.servlet.csadmin; + + import java.io.BufferedReader; + import java.io.ByteArrayInputStream; +@@ -58,6 +58,34 @@ import javax.ws.rs.core.MultivaluedMap; + import javax.ws.rs.core.Response; + import javax.xml.parsers.ParserConfigurationException; + ++import netscape.ldap.LDAPAttribute; ++import netscape.ldap.LDAPAttributeSet; ++import netscape.ldap.LDAPConnection; ++import netscape.ldap.LDAPDN; ++import netscape.ldap.LDAPEntry; ++import netscape.ldap.LDAPException; ++import netscape.ldap.LDAPModification; ++import netscape.ldap.LDAPSearchConstraints; ++import netscape.ldap.LDAPSearchResults; ++import netscape.ldap.LDAPv3; ++import netscape.security.pkcs.ContentInfo; ++import netscape.security.pkcs.PKCS10; ++import netscape.security.pkcs.PKCS12; ++import netscape.security.pkcs.PKCS12Util; ++import netscape.security.pkcs.PKCS7; ++import netscape.security.pkcs.SignerInfo; ++import netscape.security.util.DerOutputStream; ++import netscape.security.util.ObjectIdentifier; ++import netscape.security.x509.AlgorithmId; ++import netscape.security.x509.BasicConstraintsExtension; ++import netscape.security.x509.CertificateChain; ++import netscape.security.x509.Extension; ++import netscape.security.x509.Extensions; ++import netscape.security.x509.KeyUsageExtension; ++import netscape.security.x509.X500Name; ++import netscape.security.x509.X509CertImpl; ++import netscape.security.x509.X509Key; ++ + import org.apache.commons.lang.StringUtils; + import org.apache.velocity.context.Context; + import org.mozilla.jss.CryptoManager; +@@ -149,36 +177,9 @@ import com.netscape.certsrv.usrgrp.IUGSubsystem; + import com.netscape.certsrv.usrgrp.IUser; + import com.netscape.cmsutil.crypto.CryptoUtil; + import com.netscape.cmsutil.ldap.LDAPUtil; ++import com.netscape.cmsutil.util.Utils; + import com.netscape.cmsutil.xml.XMLObject; + +-import netscape.ldap.LDAPAttribute; +-import netscape.ldap.LDAPAttributeSet; +-import netscape.ldap.LDAPConnection; +-import netscape.ldap.LDAPDN; +-import netscape.ldap.LDAPEntry; +-import netscape.ldap.LDAPException; +-import netscape.ldap.LDAPModification; +-import netscape.ldap.LDAPSearchConstraints; +-import netscape.ldap.LDAPSearchResults; +-import netscape.ldap.LDAPv3; +-import netscape.security.pkcs.ContentInfo; +-import netscape.security.pkcs.PKCS10; +-import netscape.security.pkcs.PKCS12; +-import netscape.security.pkcs.PKCS12Util; +-import netscape.security.pkcs.PKCS7; +-import netscape.security.pkcs.SignerInfo; +-import netscape.security.util.DerOutputStream; +-import netscape.security.util.ObjectIdentifier; +-import netscape.security.x509.AlgorithmId; +-import netscape.security.x509.BasicConstraintsExtension; +-import netscape.security.x509.CertificateChain; +-import netscape.security.x509.Extension; +-import netscape.security.x509.Extensions; +-import netscape.security.x509.KeyUsageExtension; +-import netscape.security.x509.X500Name; +-import netscape.security.x509.X509CertImpl; +-import netscape.security.x509.X509Key; +- + /** + * Utility class for functions to be used by the RESTful installer. + * +@@ -377,7 +378,7 @@ public class ConfigurationUtils { + if (eqPos != -1) { + String name = line.substring(0, eqPos).trim(); + String tempval = line.substring(eqPos + 1).trim(); +- String value = tempval.replaceAll("(^\")|(\";$)",""); ++ String value = tempval.replaceAll("(^\")|(\";$)", ""); + + if (name.equals(header)) { + return value; +@@ -634,7 +635,7 @@ public class ConfigurationUtils { + throw new IOException("The server you want to contact is not available"); + } + +- CMS.debug("content from admin interface ="+ c); ++ CMS.debug("content from admin interface =" + c); + // when the admin servlet is unavailable, we return a badly formatted error page + // in that case, this will throw an exception and be passed into the catch block. + parser = new XMLObject(new ByteArrayInputStream(c.getBytes())); +@@ -685,8 +686,7 @@ public class ConfigurationUtils { + + public static boolean updateConfigEntries(String hostname, int port, boolean https, + String servlet, MultivaluedMap content, IConfigStore config) +- throws Exception { +- ++ throws Exception { + CMS.debug("updateConfigEntries start"); + String c = post(hostname, port, https, servlet, content, null, null); + +@@ -892,7 +892,8 @@ public class ConfigurationUtils { + // pkeyinfo_v stores private key (PrivateKeyInfo) and subject DN (String) + Vector pkeyinfo_v = new Vector(); + pkeyinfo_v.addElement(pkeyinfo); +- if (subjectDN != null) pkeyinfo_v.addElement(subjectDN); ++ if (subjectDN != null) ++ pkeyinfo_v.addElement(subjectDN); + + pkeyinfo_collection.addElement(pkeyinfo_v); + +@@ -941,7 +942,8 @@ public class ConfigurationUtils { + // cert_v stores certificate (byte[]) and nickname (String) + Vector cert_v = new Vector(); + cert_v.addElement(x509cert); +- if (nickname != null) cert_v.addElement(nickname); ++ if (nickname != null) ++ cert_v.addElement(nickname); + + cert_collection.addElement(cert_v); + } +@@ -992,10 +994,11 @@ public class ConfigurationUtils { + public static void importKeyCert( + Vector> pkeyinfo_collection, + Vector> cert_collection +- ) throws IOException, CertificateException, TokenException, +- NoSuchAlgorithmException, InvalidKeyException, InvalidAlgorithmParameterException, IllegalStateException, +- IllegalBlockSizeException, BadPaddingException, NotInitializedException, NicknameConflictException, +- UserCertConflictException, NoSuchItemOnTokenException, EPropertyNotFound, EBaseException { ++ ) throws IOException, CertificateException, TokenException, ++ NoSuchAlgorithmException, InvalidKeyException, InvalidAlgorithmParameterException, ++ IllegalStateException, ++ IllegalBlockSizeException, BadPaddingException, NotInitializedException, NicknameConflictException, ++ UserCertConflictException, NoSuchItemOnTokenException, EPropertyNotFound, EBaseException { + + CMS.debug("ConfigurationUtils.importKeyCert()"); + CryptoManager cm = CryptoManager.getInstance(); +@@ -1069,7 +1072,7 @@ public class ConfigurationUtils { + String name = (String) cert_v.elementAt(1); + CMS.debug("- Certificate: " + name); + +- if (! masterList.contains(name)) { ++ if (!masterList.contains(name)) { + CMS.debug(" Certificate not in master list, ignore certificate"); + continue; + } +@@ -1160,10 +1163,11 @@ public class ConfigurationUtils { + return true; + try { + X500Name xname = new X500Name(nickname); +- for (String key: masterList) { ++ for (String key : masterList) { + try { + X500Name xkey = new X500Name(key); +- if (xkey.equals(xname)) return true; ++ if (xkey.equals(xname)) ++ return true; + } catch (IOException e) { + // xkey not an X500Name + } +@@ -1216,10 +1220,12 @@ public class ConfigurationUtils { + return false; + } + ++ + public static boolean isAuditSigningCert(String name) throws EPropertyNotFound, EBaseException { + IConfigStore cs = CMS.getConfigStore(); + String nickname = cs.getString("preop.master.audit_signing.nickname"); +- if (nickname.equals(name)) return true; ++ if (nickname.equals(name)) ++ return true; + return false; + } + +@@ -1271,7 +1277,7 @@ public class ConfigurationUtils { + while (st.hasMoreTokens()) { + String s = st.nextToken(); + if (s.equals("sslserver")) +- continue; ++ continue; + String name = "preop.master." + s + ".nickname"; + String nickname = cs.getString(name); + list.add(nickname); +@@ -1293,14 +1299,16 @@ public class ConfigurationUtils { + X509CertImpl impl = null; + impl = new X509CertImpl(b); + Principal subjectdn = impl.getSubjectDN(); +- if (LDAPDN.equals(subjectdn.toString(), nickname)) return b; ++ if (LDAPDN.equals(subjectdn.toString(), nickname)) ++ return b; + } + return null; + } + + public static void releaseConnection(LDAPConnection conn) { + try { +- if (conn != null) conn.disconnect(); ++ if (conn != null) ++ conn.disconnect(); + } catch (LDAPException e) { + CMS.debug(e); + CMS.debug("releaseConnection: " + e); +@@ -1551,14 +1559,15 @@ public class ConfigurationUtils { + LDAPSearchResults res = conn.search( + "cn=mapping tree, cn=config", LDAPConnection.SCOPE_ONE, + "nsslapd-backend=" + LDAPUtil.escapeFilter(database), +- null, false, (LDAPSearchConstraints)null); ++ null, false, (LDAPSearchConstraints) null); + + while (res.hasMoreElements()) { + LDAPEntry entry = res.next(); + + LDAPAttribute cn = entry.getAttribute("cn"); + String dn = cn.getStringValueArray()[0]; +- if (LDAPDN.equals(baseDN, dn)) continue; ++ if (LDAPDN.equals(baseDN, dn)) ++ continue; + + CMS.debug("confirmMappings: Database " + database + " is used by " + dn + "."); + throw new EBaseException("The database (" + database + ") is used by another base DN. " + +@@ -1646,12 +1655,12 @@ public class ConfigurationUtils { + + private static void checkParentExists(String baseDN, LDAPConnection conn) throws EBaseException { + String[] dns = LDAPDN.explodeDN(baseDN, false); +- if (dns.length == 1 ) { ++ if (dns.length == 1) { + CMS.debug("checkParentExists: no parent in baseDN: " + baseDN); + throw new EBaseException("Invalid BaseDN. No parent DN in " + baseDN); + } + String parentDN = Arrays.toString(Arrays.copyOfRange(dns, 1, dns.length)); +- parentDN = parentDN.substring(1,parentDN.length() -1); ++ parentDN = parentDN.substring(1, parentDN.length() - 1); + try { + CMS.debug("checkParentExists: Checking parent " + parentDN + "."); + conn.read(parentDN); +@@ -1666,11 +1675,13 @@ public class ConfigurationUtils { + } + } + +- public static void importLDIFS(String param, LDAPConnection conn) throws EPropertyNotFound, IOException, EBaseException { ++ public static void importLDIFS(String param, LDAPConnection conn) throws EPropertyNotFound, IOException, ++ EBaseException { + importLDIFS(param, conn, true); + } + +- public static void importLDIFS(String param, LDAPConnection conn, boolean suppressErrors) throws IOException, EPropertyNotFound, ++ public static void importLDIFS(String param, LDAPConnection conn, boolean suppressErrors) throws IOException, ++ EPropertyNotFound, + EBaseException { + IConfigStore cs = CMS.getConfigStore(); + +@@ -1764,7 +1775,7 @@ public class ConfigurationUtils { + try { + LDAPSearchResults res = conn.search( + dn, LDAPConnection.SCOPE_BASE, "objectclass=*", +- null, true, (LDAPSearchConstraints)null); ++ null, true, (LDAPSearchConstraints) null); + deleteEntries(res, conn, excludedDNs); + + } catch (LDAPException e) { +@@ -1777,14 +1788,15 @@ public class ConfigurationUtils { + } + } + +- public static void deleteEntries(LDAPSearchResults res, LDAPConnection conn, String[] excludedDNs) throws LDAPException { ++ public static void deleteEntries(LDAPSearchResults res, LDAPConnection conn, String[] excludedDNs) ++ throws LDAPException { + while (res.hasMoreElements()) { + LDAPEntry entry = res.next(); + String dn = entry.getDN(); + + LDAPSearchResults res1 = conn.search( + dn, 1, "objectclass=*", +- null, true, (LDAPSearchConstraints)null); ++ null, true, (LDAPSearchConstraints) null); + deleteEntries(res1, conn, excludedDNs); + deleteEntry(conn, dn, excludedDNs); + } +@@ -1792,7 +1804,8 @@ public class ConfigurationUtils { + + public static void deleteEntry(LDAPConnection conn, String dn, String[] excludedDNs) throws LDAPException { + for (String excludedDN : excludedDNs) { +- if (!LDAPDN.equals(dn, excludedDN)) continue; ++ if (!LDAPDN.equals(dn, excludedDN)) ++ continue; + + CMS.debug("deleteEntry: entry with this dn " + dn + " is not deleted."); + return; +@@ -1997,7 +2010,7 @@ public class ConfigurationUtils { + + String status = replicationStatus(replicadn, masterConn, masterAgreementName); + if (!status.startsWith("0 ")) { +- CMS.debug("setupReplication: consumer initialization failed. " +status); ++ CMS.debug("setupReplication: consumer initialization failed. " + status); + throw new IOException("consumer initialization failed. " + status); + } + +@@ -2015,7 +2028,7 @@ public class ConfigurationUtils { + releaseConnection(masterConn); + releaseConnection(replicaConn); + } +-} ++ } + + public static void createReplicationManager(LDAPConnection conn, String bindUser, String pwd) + throws LDAPException { +@@ -2277,7 +2290,8 @@ public class ConfigurationUtils { + CMS.reinit(IUGSubsystem.ID); + } + +- public static void setExternalCACert(String certStr, String subsystem, IConfigStore config, Cert certObj) throws Exception { ++ public static void setExternalCACert(String certStr, String subsystem, IConfigStore config, Cert certObj) ++ throws Exception { + certStr = CryptoUtil.stripCertBrackets(certStr.trim()); + certStr = CryptoUtil.normalizeCertStr(certStr); + config.putString(subsystem + ".external_ca.cert", certStr); +@@ -2365,7 +2379,8 @@ public class ConfigurationUtils { + String sslType = "ECDHE"; + try { + sslType = config.getString(PCERT_PREFIX + ct + "ec.type", "ECDHE"); +- } catch (Exception e) {} ++ } catch (Exception e) { ++ } + + // ECDHE needs "SIGN" but no "DERIVE" + org.mozilla.jss.crypto.KeyPairGeneratorSpi.Usage usages_mask[] = { +@@ -2380,13 +2395,15 @@ public class ConfigurationUtils { + + do { + if (ct.equals("sslserver") && sslType.equalsIgnoreCase("ECDH")) { +- CMS.debug("ConfigurationUtils: createECCKeypair: sslserver cert for ECDH. Make sure server.xml is set " + +- "properly with -TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,+TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA"); ++ CMS.debug("ConfigurationUtils: createECCKeypair: sslserver cert for ECDH. Make sure server.xml is set " ++ + ++ "properly with -TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,+TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA"); + pair = CryptoUtil.generateECCKeyPair(token, curveName, null, ECDH_usages_mask); + } else { + if (ct.equals("sslserver")) { +- CMS.debug("ConfigurationUtils: createECCKeypair: sslserver cert for ECDHE. Make sure server.xml is set " + +- "properly with +TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,-TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA"); ++ CMS.debug("ConfigurationUtils: createECCKeypair: sslserver cert for ECDHE. Make sure server.xml is set " ++ + ++ "properly with +TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,-TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA"); + } + pair = CryptoUtil.generateECCKeyPair(token, curveName, null, usages_mask); + } +@@ -2443,7 +2460,8 @@ public class ConfigurationUtils { + setSigningAlgorithm(ct, keyAlgo, config); + } + +- public static void setSigningAlgorithm(String ct, String keyAlgo, IConfigStore config) throws EPropertyNotFound, EBaseException { ++ public static void setSigningAlgorithm(String ct, String keyAlgo, IConfigStore config) throws EPropertyNotFound, ++ EBaseException { + String systemType = config.getString("cs.type"); + if (systemType.equalsIgnoreCase("CA")) { + if (ct.equals("signing")) { +@@ -2523,16 +2541,16 @@ public class ConfigurationUtils { + // retrieve and store original 'CS.cfg' entries + preop_ca_type = config.getString("preop.ca.type", ""); + preop_cert_signing_type = config.getString("preop.cert.signing.type", ""); +- preop_cert_signing_profile = config.getString("preop.cert.signing.profile",""); ++ preop_cert_signing_profile = config.getString("preop.cert.signing.profile", ""); + preop_cert_sslserver_type = config.getString("preop.cert.sslserver.type", ""); +- preop_cert_sslserver_profile = config.getString("preop.cert.sslserver.profile",""); ++ preop_cert_sslserver_profile = config.getString("preop.cert.sslserver.profile", ""); + + // add/modify 'CS.cfg' entries + config.putString("preop.ca.type", "sdca"); + config.putString("preop.cert.signing.type", "remote"); +- config.putString("preop.cert.signing.profile","caInstallCACert"); ++ config.putString("preop.cert.signing.profile", "caInstallCACert"); + config.putString("preop.cert.sslserver.type", "remote"); +- config.putString("preop.cert.sslserver.profile","caInternalAuthServerCert"); ++ config.putString("preop.cert.sslserver.profile", "caInternalAuthServerCert"); + + // store original caType + original_caType = caType; +@@ -2568,7 +2586,7 @@ public class ConfigurationUtils { + if (standalone) { + // Treat standalone subsystem the same as "otherca" + config.putString(subsystem + "." + certTag + ".cert", +- "...paste certificate here..."); ++ "...paste certificate here..."); + + } else { + String sd_hostname = config.getString("securitydomain.host", ""); +@@ -2594,8 +2612,8 @@ public class ConfigurationUtils { + try { + if (sign_clone_sslserver_cert_using_master) { + CMS.debug("ConfigurationUtils: For this Cloned CA, always use its Master CA to generate " + +- "the 'sslserver' certificate to avoid any changes which may have been " + +- "made to the X500Name directory string encoding order."); ++ "the 'sslserver' certificate to avoid any changes which may have been " + ++ "made to the X500Name directory string encoding order."); + ca_hostname = config.getString("preop.master.hostname", ""); + ca_port = config.getInteger("preop.master.httpsport", -1); + } else { +@@ -2607,12 +2625,12 @@ public class ConfigurationUtils { + + String sslserver_extension = ""; + Boolean injectSAN = config.getBoolean( +- "service.injectSAN", false); +- CMS.debug("ConfigurationUtils: injectSAN="+injectSAN); ++ "service.injectSAN", false); ++ CMS.debug("ConfigurationUtils: injectSAN=" + injectSAN); + if (certTag.equals("sslserver") && +- injectSAN == true) { ++ injectSAN == true) { + sslserver_extension = +- CertUtil.buildSANSSLserverURLExtension(config); ++ CertUtil.buildSANSSLserverURLExtension(config); + } + + MultivaluedMap content = new MultivaluedHashMap(); +@@ -3115,7 +3133,8 @@ public class ConfigurationUtils { + IConfigStore config = CMS.getConfigStore(); + + boolean enable = config.getBoolean(PCERT_PREFIX + certTag + ".enable", true); +- if (!enable) return 0; ++ if (!enable) ++ return 0; + + CMS.debug("handleCerts(): for cert tag '" + cert.getCertTag() + "' using cert type '" + cert.getType() + "'"); + String b64 = cert.getCert(); +@@ -3131,7 +3150,8 @@ public class ConfigurationUtils { + } + + if (findCertificate(tokenname, nickname)) { +- if (!certTag.equals("sslserver")) return 0; ++ if (!certTag.equals("sslserver")) ++ return 0; + } + X509CertImpl impl = CertUtil.createLocalCert(config, x509key, + PCERT_PREFIX, certTag, cert.getType(), null); +@@ -3156,7 +3176,8 @@ public class ConfigurationUtils { + CMS.debug("handleCerts(): cert imported for certTag '" + certTag + "'"); + } catch (Exception ee) { + CMS.debug(ee); +- CMS.debug("handleCerts(): import certificate for certTag=" + certTag + " Exception: " + ee.toString()); ++ CMS.debug("handleCerts(): import certificate for certTag=" + certTag + " Exception: " ++ + ee.toString()); + } + } + } else if (cert.getType().equals("remote")) { +@@ -3216,7 +3237,7 @@ public class ConfigurationUtils { + CMS.debug("handleCerts(): import certificate successfully, certTag=" + certTag); + } catch (Exception ee) { + ee.printStackTrace(); +- CMS.debug("handleCerts: import certificate for certTag=" + certTag + " Exception: "+ ee.toString()); ++ CMS.debug("handleCerts: import certificate for certTag=" + certTag + " Exception: " + ee.toString()); + } + + } else { +@@ -3268,7 +3289,8 @@ public class ConfigurationUtils { + + public static void setCertPermissions(String tag) throws EBaseException, NotInitializedException, + ObjectNotFoundException, TokenException { +- if (tag.equals("signing") || tag.equals("external_signing")) return; ++ if (tag.equals("signing") || tag.equals("external_signing")) ++ return; + + IConfigStore cs = CMS.getConfigStore(); + String nickname = cs.getString("preop.cert." + tag + ".nickname", ""); +@@ -3327,7 +3349,6 @@ public class ConfigurationUtils { + return true; + } + +- + public static boolean findBootstrapServerCert() throws EBaseException, NotInitializedException, TokenException { + IConfigStore cs = CMS.getConfigStore(); + +@@ -3342,7 +3363,8 @@ public class ConfigurationUtils { + } + Principal issuerDN = cert.getIssuerDN(); + Principal subjectDN = cert.getSubjectDN(); +- if (issuerDN.equals(subjectDN)) return true; ++ if (issuerDN.equals(subjectDN)) ++ return true; + + return false; + } +@@ -3473,7 +3495,8 @@ public class ConfigurationUtils { + } + + public static byte[] addCertBag(X509Certificate x509cert, String nickname, +- SEQUENCE safeContents) throws CertificateEncodingException, NoSuchAlgorithmException, CharConversionException { ++ SEQUENCE safeContents) throws CertificateEncodingException, NoSuchAlgorithmException, ++ CharConversionException { + byte[] localKeyId = null; + + ASN1Value cert = new OCTET_STRING(x509cert.getEncoded()); +@@ -3636,49 +3659,56 @@ public class ConfigurationUtils { + if (select.equals("new")) { + group = system.getGroupFromName("Security Domain Administrators"); + if (group != null && !group.isMember(uid)) { +- CMS.debug("ConfigurationUtils: createAdmin: add user '" + uid + "' to group 'Security Domain Administrators'"); ++ CMS.debug("ConfigurationUtils: createAdmin: add user '" + uid ++ + "' to group 'Security Domain Administrators'"); + group.addMemberName(uid); + system.modifyGroup(group); + } + + group = system.getGroupFromName("Enterprise CA Administrators"); + if (group != null && !group.isMember(uid)) { +- CMS.debug("ConfigurationUtils: createAdmin: add user '" + uid + "' to group 'Enterprise CA Administrators'"); ++ CMS.debug("ConfigurationUtils: createAdmin: add user '" + uid ++ + "' to group 'Enterprise CA Administrators'"); + group.addMemberName(uid); + system.modifyGroup(group); + } + + group = system.getGroupFromName("Enterprise KRA Administrators"); + if (group != null && !group.isMember(uid)) { +- CMS.debug("ConfigurationUtils: createAdmin: add user '" + uid + "' to group 'Enterprise KRA Administrators'"); ++ CMS.debug("ConfigurationUtils: createAdmin: add user '" + uid ++ + "' to group 'Enterprise KRA Administrators'"); + group.addMemberName(uid); + system.modifyGroup(group); + } + + group = system.getGroupFromName("Enterprise RA Administrators"); + if (group != null && !group.isMember(uid)) { +- CMS.debug("ConfigurationUtils: createAdmin: add user '" + uid + "' to group 'Enterprise RA Administrators'"); ++ CMS.debug("ConfigurationUtils: createAdmin: add user '" + uid ++ + "' to group 'Enterprise RA Administrators'"); + group.addMemberName(uid); + system.modifyGroup(group); + } + + group = system.getGroupFromName("Enterprise TKS Administrators"); + if (group != null && !group.isMember(uid)) { +- CMS.debug("ConfigurationUtils: createAdmin: add user '" + uid + "' to group 'Enterprise TKS Administrators'"); ++ CMS.debug("ConfigurationUtils: createAdmin: add user '" + uid ++ + "' to group 'Enterprise TKS Administrators'"); + group.addMemberName(uid); + system.modifyGroup(group); + } + + group = system.getGroupFromName("Enterprise OCSP Administrators"); + if (group != null && !group.isMember(uid)) { +- CMS.debug("ConfigurationUtils: createAdmin: add user '" + uid + "' to group 'Enterprise OCSP Administrators'"); ++ CMS.debug("ConfigurationUtils: createAdmin: add user '" + uid ++ + "' to group 'Enterprise OCSP Administrators'"); + group.addMemberName(uid); + system.modifyGroup(group); + } + + group = system.getGroupFromName("Enterprise TPS Administrators"); + if (group != null && !group.isMember(uid)) { +- CMS.debug("ConfigurationUtils: createAdmin: add user '" + uid + "' to group 'Enterprise TPS Administrators'"); ++ CMS.debug("ConfigurationUtils: createAdmin: add user '" + uid ++ + "' to group 'Enterprise TPS Administrators'"); + group.addMemberName(uid); + system.modifyGroup(group); + } +@@ -3833,7 +3863,7 @@ public class ConfigurationUtils { + CMS.debug("Cloning a domain master"); + } + +- String url = "/ca/admin/ca/updateDomainXML"; ++ String url = "/ca/admin/ca/updateDomainXML"; + + MultivaluedMap content = new MultivaluedHashMap(); + content.putSingle("list", type + "List"); +@@ -3862,7 +3892,7 @@ public class ConfigurationUtils { + CMS.debug("Unable to access admin interface: " + e); + + CMS.debug("Update security domain using agent interface"); +- url = "/ca/agent/ca/updateDomainXML"; ++ url = "/ca/agent/ca/updateDomainXML"; + updateDomainXML(sd_host, sd_agent_port, true, url, content, true); + } + +@@ -3903,7 +3933,7 @@ public class ConfigurationUtils { + + public static void updateDomainXML(String hostname, int port, boolean https, + String servlet, MultivaluedMap content, boolean useClientAuth) +- throws Exception { ++ throws Exception { + + CMS.debug("ConfigurationUtils: updateDomainXML start hostname=" + hostname + " port=" + port); + +@@ -4047,7 +4077,7 @@ public class ConfigurationUtils { + try { + CMS.debug("setupClientAuthUser: Adding cert to user: " + id); + system.addUserCert(user); +- } catch(ConflictingOperationException e) { ++ } catch (ConflictingOperationException e) { + // ignore exception + CMS.debug("setupClientAuthUser: Cert already added: " + e); + } +@@ -4121,7 +4151,9 @@ public class ConfigurationUtils { + } + + public static void getSharedSecret(String tksHost, int tksPort, boolean importKey) throws EPropertyNotFound, +- EBaseException, URISyntaxException { ++ EBaseException, URISyntaxException, InvalidKeyException, NoSuchAlgorithmException, ++ InvalidAlgorithmParameterException, NotInitializedException, TokenException, ObjectNotFoundException, ++ IOException { + IConfigStore cs = CMS.getConfigStore(); + String host = cs.getString("service.machineName"); + String port = cs.getString("service.securePort"); +@@ -4140,6 +4172,8 @@ public class ConfigurationUtils { + + PKIClient client = new PKIClient(config, null); + ++ CMS.debug("In ConfigurationUtils.getSharedSecret! importKey: " + importKey); ++ + // Ignore the "UNTRUSTED_ISSUER" and "CA_CERT_INVALID" validity status + // during PKI instance creation since we are using an untrusted temporary CA cert. + client.addIgnoredCertStatus(SSLCertificateApprovalCallback.ValidityStatus.UNTRUSTED_ISSUER); +@@ -4156,6 +4190,9 @@ public class ConfigurationUtils { + // no connector exists + data = null; + } ++ ++ ++ // The connId or data.getID will be the id of the shared secret + KeyData keyData = null; + if (data == null) { + data = tpsConnectorClient.createConnector(host, port); +@@ -4171,14 +4208,24 @@ public class ConfigurationUtils { + } + accountClient.logout(); + ++ String nick = "TPS-" + host + "-" + port + " sharedSecret"; ++ + if (importKey) { +- // TODO - we need code here to import the key into the tps certdb ++ CMS.debug("getSharedSecret: About to attempt to import shared secret key."); ++ byte[] sessionKeyData = Utils.base64decode(keyData.getWrappedPrivateData()); ++ byte[] sharedSecretData = Utils.base64decode(keyData.getAdditionalWrappedPrivateData()); ++ ++ try { ++ CryptoUtil.importSharedSecret(sessionKeyData, sharedSecretData, dbNick, nick); ++ } catch (Exception e) { ++ CMS.debug("getSharedSecret()): WARNING, Failed to automatically import shared secret. Please follow the manual procedure." + e.toString()); ++ } + // this is not needed if we are using a shared database with + // the tks. + } + + // store the new nick in CS.cfg +- String nick = "TPS-" + host + "-" + port + " sharedSecret"; ++ + cs.putString("conn.tks1.tksSharedSymKeyName", nick); + cs.commit(false); + } +@@ -4388,7 +4435,7 @@ public class ConfigurationUtils { + + if (status.equals(SUCCESS)) { + CMS.debug("registerUser: Successfully added user " + uid + " to " + targetURI + +- " using " + targetURL); ++ " using " + targetURL); + + } else if (status.equals(AUTH_FAILURE)) { + throw new EAuthException(AUTH_FAILURE); +@@ -4500,7 +4547,6 @@ public class ConfigurationUtils { + cs.putString("auths.instance.ldap1.ldap.ldapconn.secureConn", secureConn); + } + +- + public static void updateNextRanges() throws EBaseException, LDAPException { + IConfigStore cs = CMS.getConfigStore(); + +@@ -4541,6 +4587,7 @@ public class ConfigurationUtils { + + /** + * save variables needed for cloning and remove preops ++ * + * @throws EBaseException + */ + public static void removePreopConfigEntries() throws EBaseException { +diff --git a/base/server/cms/src/com/netscape/cms/servlet/tks/SecureChannelProtocol.java b/base/server/cms/src/com/netscape/cms/servlet/tks/SecureChannelProtocol.java +index 7dab140..9593816 100644 +--- a/base/server/cms/src/com/netscape/cms/servlet/tks/SecureChannelProtocol.java ++++ b/base/server/cms/src/com/netscape/cms/servlet/tks/SecureChannelProtocol.java +@@ -418,7 +418,8 @@ public class SecureChannelProtocol { + String method = "SecureChannelProtocol.getSharedSecretKeyName:"; + CMS.debug(method + " Entering..."); + +- if (name != null && SecureChannelProtocol.sharedSecretKeyName == null) { ++ // No longer cache the secret name, there could be a different one for each incoming TPS connection. ++ if (name != null) { + SecureChannelProtocol.sharedSecretKeyName = name; + } + +diff --git a/base/server/cms/src/com/netscape/cms/servlet/tks/TokenServlet.java b/base/server/cms/src/com/netscape/cms/servlet/tks/TokenServlet.java +index ab2ade9..9c143fd 100644 +--- a/base/server/cms/src/com/netscape/cms/servlet/tks/TokenServlet.java ++++ b/base/server/cms/src/com/netscape/cms/servlet/tks/TokenServlet.java +@@ -70,6 +70,7 @@ public class TokenServlet extends CMSServlet { + public static int ERROR = 1; + String mKeyNickName = null; + String mNewKeyNickName = null; ++ String mCurrentUID = null; + IPrettyPrintFormat pp = CMS.getPrettyPrintFormat(":"); + + private final static String LOGGING_SIGNED_AUDIT_COMPUTE_SESSION_KEY_REQUEST = +@@ -951,8 +952,6 @@ public class TokenServlet extends CMSServlet { + + transportKeyName = getSharedSecretName(sconfig); + +- CMS.debug("TokenServlet: ComputeSessionKey(): tksSharedSymKeyName: " + transportKeyName); +- + String rcard_challenge = req.getParameter(IRemoteRequest.TOKEN_CARD_CHALLENGE); + String rhost_challenge = req.getParameter(IRemoteRequest.TOKEN_HOST_CHALLENGE); + String rKeyInfo = req.getParameter(IRemoteRequest.TOKEN_KEYINFO); +@@ -1537,13 +1536,32 @@ public class TokenServlet extends CMSServlet { + + if (useNewNames) { + String tpsList = cs.getString("tps.list", ""); ++ String firstSharedSecretName = null; + if (!tpsList.isEmpty()) { + for (String tpsID : tpsList.split(",")) { + String sharedSecretName = cs.getString("tps." + tpsID + ".nickname", ""); ++ ++ // This one will be a fall back in case we can't get a specific one ++ if (firstSharedSecretName == null) { ++ firstSharedSecretName = sharedSecretName; ++ } ++ + if (!sharedSecretName.isEmpty()) { +- return sharedSecretName; ++ if (mCurrentUID != null) { ++ String csUid = cs.getString("tps." + tpsID + ".userid", ""); ++ ++ if (mCurrentUID.equalsIgnoreCase(csUid)) { ++ CMS.debug("TokenServlet.getSharedSecretName: found a match of the user id! " + csUid); ++ return sharedSecretName; ++ } ++ } + } + } ++ ++ if (firstSharedSecretName != null) { ++ //Return the first in the list if we couldn't isolate one ++ return firstSharedSecretName; ++ } + } + CMS.debug("getSharedSecretName: no shared secret has been configured"); + throw new EBaseException("No shared secret has been configured"); +@@ -2351,6 +2369,8 @@ public class TokenServlet extends CMSServlet { + IAuthToken authToken = authenticate(cmsReq); + AuthzToken authzToken = null; + ++ mCurrentUID = (String) authToken.get(IAuthToken.UID) ; ++ + try { + authzToken = authorize(mAclMethod, authToken, + mAuthzResourceName, "execute"); +diff --git a/base/server/man/man8/pkispawn.8 b/base/server/man/man8/pkispawn.8 +index 3678cff..40ec7f0 100644 +--- a/base/server/man/man8/pkispawn.8 ++++ b/base/server/man/man8/pkispawn.8 +@@ -719,10 +719,15 @@ pki_tks_uri=\fIhttps://:\fP + .fi + + .PP +-If TPS and TKS are installed on separate instances the shared secret key needs +-to be generated manually in TKS, then manually imported into TPS. ++If TPS and TKS are installed on separate instances the shared secret key ++should be imported over the wire between the TKS and TPS automatically. + +-Generate the shared secret key in TKS with the following command: ++If the automated procedure fails for any unlikely reason the following ++manual procedure will serve as a fallback. The key needs to be created ++on the TKS side and imported into the TPS side in this case. ++ ++ ++Generate the shared secret key (if needed) in TKS with the following command: + + .IP + tkstool -T -d /var/lib/pki/pki-tomcat/alias -n sharedSecret +diff --git a/base/tks/src/org/dogtagpki/server/tks/rest/TPSConnectorService.java b/base/tks/src/org/dogtagpki/server/tks/rest/TPSConnectorService.java +index bc655d6..a2d18f1 100644 +--- a/base/tks/src/org/dogtagpki/server/tks/rest/TPSConnectorService.java ++++ b/base/tks/src/org/dogtagpki/server/tks/rest/TPSConnectorService.java +@@ -1,5 +1,6 @@ + package org.dogtagpki.server.tks.rest; + ++import java.io.CharConversionException; + import java.io.IOException; + import java.net.URI; + import java.security.InvalidAlgorithmParameterException; +@@ -10,6 +11,7 @@ import java.security.cert.X509Certificate; + import java.util.Arrays; + import java.util.Collection; + import java.util.Iterator; ++import java.util.List; + import java.util.TreeSet; + + import javax.servlet.http.HttpServletRequest; +@@ -20,8 +22,13 @@ import javax.ws.rs.core.UriInfo; + import org.apache.commons.lang.ArrayUtils; + import org.apache.commons.lang.StringUtils; + import org.jboss.resteasy.plugins.providers.atom.Link; ++import org.mozilla.jss.CryptoManager; + import org.mozilla.jss.CryptoManager.NotInitializedException; ++import org.mozilla.jss.crypto.CryptoToken; + import org.mozilla.jss.crypto.InvalidKeyFormatException; ++import org.mozilla.jss.crypto.KeyGenAlgorithm; ++import org.mozilla.jss.crypto.KeyGenerator; ++import org.mozilla.jss.crypto.SymmetricKey; + import org.mozilla.jss.crypto.TokenException; + + import com.netscape.certsrv.apps.CMS; +@@ -60,30 +67,32 @@ public class TPSConnectorService extends PKIService implements TPSConnectorResou + public Response findConnectors(Integer start, Integer size) { + try { + String tpsList = cs.getString(TPS_LIST, ""); +- Iterator entries = Arrays.asList(StringUtils.split(tpsList,",")).iterator(); ++ Iterator entries = Arrays.asList(StringUtils.split(tpsList, ",")).iterator(); + + TPSConnectorCollection response = new TPSConnectorCollection(); + int i = 0; + + // skip to the start of the page +- for ( ; i 0) { +- URI uri = uriInfo.getRequestUriBuilder().replaceQueryParam("start", Math.max(start-size, 0)).build(); ++ URI uri = uriInfo.getRequestUriBuilder().replaceQueryParam("start", Math.max(start - size, 0)).build(); + response.addLink(new Link("prev", uri)); + } + +- if (start+size < i) { +- URI uri = uriInfo.getRequestUriBuilder().replaceQueryParam("start", start+size).build(); ++ if (start + size < i) { ++ URI uri = uriInfo.getRequestUriBuilder().replaceQueryParam("start", start + size).build(); + response.addLink(new Link("next", uri)); + } + +@@ -114,7 +123,8 @@ public class TPSConnectorService extends PKIService implements TPSConnectorResou + + public TPSConnectorData getConnectorData(String id) { + +- if (id == null) throw new BadRequestException("TPS connector ID is null."); ++ if (id == null) ++ throw new BadRequestException("TPS connector ID is null."); + + try { + if (!connectorExists(id)) +@@ -131,8 +141,10 @@ public class TPSConnectorService extends PKIService implements TPSConnectorResou + @Override + public Response getConnector(String host, String port) { + +- if (host == null) throw new BadRequestException("TPS connector host is null."); +- if (port == null) throw new BadRequestException("TPS connector port is null."); ++ if (host == null) ++ throw new BadRequestException("TPS connector host is null."); ++ if (port == null) ++ throw new BadRequestException("TPS connector port is null."); + + try { + String id = getConnectorID(host, port); +@@ -151,8 +163,10 @@ public class TPSConnectorService extends PKIService implements TPSConnectorResou + @Override + public Response createConnector(String tpsHost, String tpsPort) { + +- if (tpsHost == null) throw new BadRequestException("TPS connector host is null."); +- if (tpsPort == null) throw new BadRequestException("TPS connector port is null."); ++ if (tpsHost == null) ++ throw new BadRequestException("TPS connector host is null."); ++ if (tpsPort == null) ++ throw new BadRequestException("TPS connector port is null."); + + try { + String id = getConnectorID(tpsHost, tpsPort); +@@ -245,7 +259,8 @@ public class TPSConnectorService extends PKIService implements TPSConnectorResou + if (StringUtils.isEmpty(id)) + throw new BadRequestException("Attempt to delete TPS connection with null or empty id"); + +- if (!connectorExists(id)) return createNoContentResponse(); ++ if (!connectorExists(id)) ++ return createNoContentResponse(); + + deleteSharedSecret(id); + cs.removeSubStore("tps." + id); +@@ -263,8 +278,10 @@ public class TPSConnectorService extends PKIService implements TPSConnectorResou + @Override + public Response deleteConnector(String host, String port) { + +- if (host == null) throw new BadRequestException("TPS connector host is null."); +- if (port == null) throw new BadRequestException("TPS connector port is null."); ++ if (host == null) ++ throw new BadRequestException("TPS connector host is null."); ++ if (port == null) ++ throw new BadRequestException("TPS connector port is null."); + + String id; + try { +@@ -281,7 +298,10 @@ public class TPSConnectorService extends PKIService implements TPSConnectorResou + @Override + public Response createSharedSecret(String id) { + +- if (id == null) throw new BadRequestException("TPS connector ID is null."); ++ CMS.debug("TPSConnectorService.createSharedSecret.id: " + id); ++ ++ if (id == null) ++ throw new BadRequestException("TPS connector ID is null."); + + try { + if (!connectorExists(id)) { +@@ -293,9 +313,13 @@ public class TPSConnectorService extends PKIService implements TPSConnectorResou + + // get user cert + IUser user = userGroupManager.getUser(userid); ++ ++ CMS.debug("TPSConnectorService.createSharedSecret.userid: " + userid); + X509Certificate[] certs = user.getX509Certificates(); + + String nickname = userid + " sharedSecret"; ++ ++ CMS.debug("TPSConnectorService.createSharedSecret. nickname: " + nickname); + if (CryptoUtil.sharedSecretExists(nickname)) { + throw new BadRequestException("Shared secret already exists"); + } +@@ -305,9 +329,21 @@ public class TPSConnectorService extends PKIService implements TPSConnectorResou + cs.putString("tps." + id + ".nickname", nickname); + cs.commit(true); + +- byte[] wrappedKey = CryptoUtil.exportSharedSecret(nickname, certs[0]); ++ //Create des3 session sym key to wrap the shared secret. ++ SymmetricKey tempKey = createDes3SessionKeyOnInternal(); ++ ++ if (tempKey == null) { ++ return createNoContentResponse(); ++ } ++ ++ List listWrappedKeys = CryptoUtil.exportSharedSecret(nickname, certs[0], tempKey); ++ ++ byte[] wrappedSessionKey = listWrappedKeys.get(0); ++ byte[] wrappedSharedSecret = listWrappedKeys.get(1); ++ + KeyData keyData = new KeyData(); +- keyData.setWrappedPrivateData(Utils.base64encode(wrappedKey)); ++ keyData.setWrappedPrivateData(Utils.base64encode(wrappedSessionKey)); ++ keyData.setAdditionalWrappedPrivateData(Utils.base64encode(wrappedSharedSecret)); + + return createOKResponse(keyData); + +@@ -341,7 +377,8 @@ public class TPSConnectorService extends PKIService implements TPSConnectorResou + @Override + public Response replaceSharedSecret(String id) { + +- if (id == null) throw new BadRequestException("TPS connector ID is null."); ++ if (id == null) ++ throw new BadRequestException("TPS connector ID is null."); + + try { + if (!connectorExists(id)) { +@@ -362,9 +399,22 @@ public class TPSConnectorService extends PKIService implements TPSConnectorResou + + CryptoUtil.deleteSharedSecret(nickname); + CryptoUtil.createSharedSecret(nickname); +- byte[] wrappedKey = CryptoUtil.exportSharedSecret(nickname, certs[0]); ++ ++ //Create des3 session sym key to wrap the shared secret. ++ SymmetricKey tempKey = createDes3SessionKeyOnInternal(); ++ ++ if (tempKey == null) { ++ return createNoContentResponse(); ++ } ++ ++ List listWrappedKeys = CryptoUtil.exportSharedSecret(nickname,certs[0], tempKey); ++ ++ byte[] wrappedSessionKey = listWrappedKeys.get(0); ++ byte[] wrappedSharedSecret = listWrappedKeys.get(1); ++ + KeyData keyData = new KeyData(); +- keyData.setWrappedPrivateData(Utils.base64encode(wrappedKey)); ++ keyData.setWrappedPrivateData(Utils.base64encode(wrappedSessionKey)); ++ keyData.setAdditionalWrappedPrivateData(Utils.base64encode(wrappedSharedSecret)); + + return createOKResponse(keyData); + +@@ -380,7 +430,8 @@ public class TPSConnectorService extends PKIService implements TPSConnectorResou + @Override + public Response deleteSharedSecret(String id) { + +- if (id == null) throw new BadRequestException("TPS connector ID is null."); ++ if (id == null) ++ throw new BadRequestException("TPS connector ID is null."); + + try { + if (!connectorExists(id)) { +@@ -415,8 +466,10 @@ public class TPSConnectorService extends PKIService implements TPSConnectorResou + @Override + public Response getSharedSecret(String id) { + +- if (id == null) throw new BadRequestException("TPS connector ID is null."); ++ if (id == null) ++ throw new BadRequestException("TPS connector ID is null."); + ++ CMS.debug("TPSConnectorServlet.getSharedSecret: id : " + id); + try { + if (!connectorExists(id)) { + throw new ResourceNotFoundException("TPS connection does not exist"); +@@ -434,9 +487,20 @@ public class TPSConnectorService extends PKIService implements TPSConnectorResou + IUser user = userGroupManager.getUser(userid); + X509Certificate[] certs = user.getX509Certificates(); + +- byte[] wrappedKey = CryptoUtil.exportSharedSecret(nickname, certs[0]); ++ //Create des3 session sym key to wrap the shared secrt. ++ SymmetricKey tempKey = createDes3SessionKeyOnInternal(); ++ ++ if (tempKey == null) { ++ return createNoContentResponse(); ++ } ++ ++ List listWrappedKeys = CryptoUtil.exportSharedSecret(nickname, certs[0], tempKey); ++ byte[] wrappedSessionKey = listWrappedKeys.get(0); ++ byte[] wrappedSharedSecret = listWrappedKeys.get(1); ++ + KeyData keyData = new KeyData(); +- keyData.setWrappedPrivateData(Utils.base64encode(wrappedKey)); ++ keyData.setWrappedPrivateData(Utils.base64encode(wrappedSessionKey)); ++ keyData.setAdditionalWrappedPrivateData(Utils.base64encode(wrappedSharedSecret)); + + return createOKResponse(keyData); + +@@ -456,7 +520,7 @@ public class TPSConnectorService extends PKIService implements TPSConnectorResou + + private String getConnectorID(String host, String port) throws EBaseException { + String tpsList = cs.getString(TPS_LIST, ""); +- for (String tpsID : StringUtils.split(tpsList,",")) { ++ for (String tpsID : StringUtils.split(tpsList, ",")) { + TPSConnectorData data = createTPSConnectorData(tpsID); + if (data.getHost().equals(host) && data.getPort().equals(port)) + return tpsID; +@@ -486,7 +550,36 @@ public class TPSConnectorService extends PKIService implements TPSConnectorResou + sorted.addAll(Arrays.asList(StringUtils.split(tpsList, ","))); + + int index = 0; +- while (sorted.contains(Integer.toString(index))) index++; ++ while (sorted.contains(Integer.toString(index))) ++ index++; + return Integer.toString(index); + } ++ ++ private SymmetricKey createDes3SessionKeyOnInternal() throws EBaseException { ++ ++ SymmetricKey tempKey = null; ++ try { ++ CryptoManager cm = CryptoManager.getInstance(); ++ CryptoToken token = cm.getInternalKeyStorageToken(); ++ KeyGenerator kg = token.getKeyGenerator(KeyGenAlgorithm.DES3); ++ ++ SymmetricKey.Usage usages[] = new SymmetricKey.Usage[4]; ++ usages[0] = SymmetricKey.Usage.WRAP; ++ usages[1] = SymmetricKey.Usage.UNWRAP; ++ usages[2] = SymmetricKey.Usage.ENCRYPT; ++ usages[3] = SymmetricKey.Usage.DECRYPT; ++ ++ kg.setKeyUsages(usages); ++ kg.temporaryKeys(true); ++ tempKey = kg.generate(); ++ } catch (NoSuchAlgorithmException | TokenException | IllegalStateException | CharConversionException ++ | NotInitializedException e) { ++ CMS.debug("TPSConnectorService.createDes3SesisonKeyOnInternal: Can't generate temporary session key."); ++ ++ throw new EBaseException(e); ++ } ++ ++ return tempKey; ++ } ++ + } +diff --git a/base/tps/src/org/dogtagpki/server/tps/processor/TPSProcessor.java b/base/tps/src/org/dogtagpki/server/tps/processor/TPSProcessor.java +index ff64208..94e6497 100644 +--- a/base/tps/src/org/dogtagpki/server/tps/processor/TPSProcessor.java ++++ b/base/tps/src/org/dogtagpki/server/tps/processor/TPSProcessor.java +@@ -33,6 +33,8 @@ import java.util.List; + import java.util.Map; + import java.util.Set; + ++import netscape.security.x509.RevocationReason; ++ + import org.dogtagpki.server.tps.TPSSession; + import org.dogtagpki.server.tps.TPSSubsystem; + import org.dogtagpki.server.tps.authentication.AuthUIParameter; +@@ -96,8 +98,6 @@ import com.netscape.certsrv.tps.token.TokenStatus; + import com.netscape.cms.servlet.tks.SecureChannelProtocol; + import com.netscape.symkey.SessionKey; + +-import netscape.security.x509.RevocationReason; +- + public class TPSProcessor { + + public static final int RESULT_NO_ERROR = 0; +@@ -686,9 +686,6 @@ public class TPSProcessor { + sessionKey = (PK11SymKey) protocol.unwrapWrappedSymKeyOnToken(token, sharedSecret, sessionKeyWrapped.toBytesArray(), false); + + +- +- +- + if (sessionKey == null) { + CMS.debug("TPSProcessor.generateSecureChannel: Can't extract session key!"); + throw new TPSException("TPSProcessor.generateSecureChannel: Can't extract session key!", +@@ -708,7 +705,6 @@ public class TPSProcessor { + TPSStatus.STATUS_ERROR_SECURE_CHANNEL); + } + +- //CMS.debug("TPSProcessor.generateSecureChannel: retrieved enc session key: " + encSessionKey); + CMS.debug("TPSProcessor.generateSecureChannel: retrieved enc session key"); + + TPSBuffer drmDesKey = null; +diff --git a/base/tps/src/org/dogtagpki/server/tps/rest/TPSInstallerService.java b/base/tps/src/org/dogtagpki/server/tps/rest/TPSInstallerService.java +index dab80e4..068293e 100644 +--- a/base/tps/src/org/dogtagpki/server/tps/rest/TPSInstallerService.java ++++ b/base/tps/src/org/dogtagpki/server/tps/rest/TPSInstallerService.java +@@ -142,11 +142,21 @@ public class TPSInstallerService extends SystemConfigService { + ConfigurationUtils.exportTransportCert(secdomainURI, tksURI, transportCert); + } + ++ String doImportStr = request.getImportSharedSecret(); ++ CMS.debug("finalizeConfiguration: importSharedSecret:" + doImportStr); + // generate shared secret from the tks ++ ++ boolean doImport = false; ++ ++ if("true".equalsIgnoreCase(doImportStr)) { ++ CMS.debug("finalizeConfiguration: importSharedSecret: importSharedSecret is true."); ++ doImport = true; ++ } ++ + ConfigurationUtils.getSharedSecret( + tksURI.getHost(), + tksURI.getPort(), +- Boolean.getBoolean(request.getImportSharedSecret())); ++ doImport); + + } catch (URISyntaxException e) { + throw new BadRequestException("Invalid URI for CA, TKS or KRA"); +diff --git a/base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java b/base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java +index 4a2558b..9cabdc5 100644 +--- a/base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java ++++ b/base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java +@@ -47,7 +47,32 @@ import java.util.Random; + import java.util.StringTokenizer; + import java.util.Vector; + +-import javax.crypto.SecretKey; ++import netscape.security.pkcs.PKCS10; ++import netscape.security.pkcs.PKCS10Attribute; ++import netscape.security.pkcs.PKCS10Attributes; ++import netscape.security.pkcs.PKCS7; ++import netscape.security.pkcs.PKCS9Attribute; ++import netscape.security.util.BigInt; ++import netscape.security.util.DerInputStream; ++import netscape.security.util.DerOutputStream; ++import netscape.security.util.DerValue; ++import netscape.security.util.ObjectIdentifier; ++import netscape.security.x509.AlgorithmId; ++import netscape.security.x509.CertificateAlgorithmId; ++import netscape.security.x509.CertificateChain; ++import netscape.security.x509.CertificateExtensions; ++import netscape.security.x509.CertificateIssuerName; ++import netscape.security.x509.CertificateSerialNumber; ++import netscape.security.x509.CertificateSubjectName; ++import netscape.security.x509.CertificateValidity; ++import netscape.security.x509.CertificateVersion; ++import netscape.security.x509.CertificateX509Key; ++import netscape.security.x509.Extensions; ++import netscape.security.x509.X500Name; ++import netscape.security.x509.X500Signer; ++import netscape.security.x509.X509CertImpl; ++import netscape.security.x509.X509CertInfo; ++import netscape.security.x509.X509Key; + + import org.mozilla.jss.CryptoManager; + import org.mozilla.jss.CryptoManager.NotInitializedException; +@@ -82,7 +107,6 @@ import org.mozilla.jss.crypto.NoSuchItemOnTokenException; + import org.mozilla.jss.crypto.ObjectNotFoundException; + import org.mozilla.jss.crypto.PBEAlgorithm; + import org.mozilla.jss.crypto.PrivateKey; +-import org.mozilla.jss.crypto.SecretKeyFacade; + import org.mozilla.jss.crypto.Signature; + import org.mozilla.jss.crypto.SignatureAlgorithm; + import org.mozilla.jss.crypto.SymmetricKey; +@@ -108,33 +132,6 @@ import org.mozilla.jss.util.Password; + import com.netscape.cmsutil.util.Cert; + import com.netscape.cmsutil.util.Utils; + +-import netscape.security.pkcs.PKCS10; +-import netscape.security.pkcs.PKCS10Attribute; +-import netscape.security.pkcs.PKCS10Attributes; +-import netscape.security.pkcs.PKCS7; +-import netscape.security.pkcs.PKCS9Attribute; +-import netscape.security.util.BigInt; +-import netscape.security.util.DerInputStream; +-import netscape.security.util.DerOutputStream; +-import netscape.security.util.DerValue; +-import netscape.security.util.ObjectIdentifier; +-import netscape.security.x509.AlgorithmId; +-import netscape.security.x509.CertificateAlgorithmId; +-import netscape.security.x509.CertificateChain; +-import netscape.security.x509.CertificateExtensions; +-import netscape.security.x509.CertificateIssuerName; +-import netscape.security.x509.CertificateSerialNumber; +-import netscape.security.x509.CertificateSubjectName; +-import netscape.security.x509.CertificateValidity; +-import netscape.security.x509.CertificateVersion; +-import netscape.security.x509.CertificateX509Key; +-import netscape.security.x509.Extensions; +-import netscape.security.x509.X500Name; +-import netscape.security.x509.X500Signer; +-import netscape.security.x509.X509CertImpl; +-import netscape.security.x509.X509CertInfo; +-import netscape.security.x509.X509Key; +- + @SuppressWarnings("serial") + public class CryptoUtil { + +@@ -2072,55 +2069,117 @@ public class CryptoUtil { + km.deleteUniqueNamedKey(nickname); + } + +- public static byte[] exportSharedSecret(String nickname, java.security.cert.X509Certificate wrappingCert) ++ // Return a list of two wrapped keys: first element: temp DES3 key wrapped by cert , second element: shared secret wrapped by temp DES3 key ++ public static List exportSharedSecret(String nickname, java.security.cert.X509Certificate wrappingCert,SymmetricKey wrappingKey) + throws NotInitializedException, TokenException, IOException, NoSuchAlgorithmException, InvalidKeyException, + InvalidAlgorithmParameterException, InvalidKeyFormatException { + CryptoManager cm = CryptoManager.getInstance(); + CryptoToken token = cm.getInternalKeyStorageToken(); ++ ++ List listWrappedKeys = new ArrayList(); ++ ++ + KeyManager km = new KeyManager(token); + if (!km.uniqueNamedKeyExists(nickname)) { + throw new IOException("Shared secret " + nickname + " does not exist"); + } +- SecretKey skey = km.lookupUniqueNamedKey(EncryptionAlgorithm.DES3_ECB, nickname); ++ ++ SymmetricKey sharedSecretKey = null; ++ ++ try { ++ sharedSecretKey = getSymKeyByName(token, nickname); ++ } catch (Exception e) { ++ sharedSecretKey = null; ++ } ++ ++ if (sharedSecretKey == null) { ++ throw new IOException("Shared secret " + nickname + " does not exist"); ++ } + + KeyWrapper keyWrap = token.getKeyWrapper(KeyWrapAlgorithm.RSA); + PublicKey pub = wrappingCert.getPublicKey(); + PK11PubKey pubK = PK11PubKey.fromSPKI(pub.getEncoded()); + keyWrap.initWrap(pubK, null); +- byte[] wrappedKey = keyWrap.wrap(((SecretKeyFacade) skey).key); +- return wrappedKey; ++ ++ //Wrap the temp DES3 key with the cert ++ byte[] wrappedKey = keyWrap.wrap(wrappingKey); ++ ++ listWrappedKeys.add(wrappedKey); ++ //Use the DES3 key to wrap the shared secret ++ ++ KeyWrapper keyWrapSharedSecret = token.getKeyWrapper(KeyWrapAlgorithm.DES3_ECB); ++ keyWrapSharedSecret.initWrap(wrappingKey,null); ++ ++ byte[] wrappedSharedSecret = keyWrapSharedSecret.wrap(sharedSecretKey); ++ ++ listWrappedKeys.add(wrappedSharedSecret); ++ ++ if(listWrappedKeys.size() != 2) { ++ throw new IOException("Can't write out shared secret data to export for nickname: " + nickname); ++ } ++ ++ return listWrappedKeys; + } + +- /* +- public static void importSharedSecret(KeyData data) throws EBaseException, NotInitializedException, TokenException, ++ ++ public static void importSharedSecret(byte[] wrappedSessionKey,byte[] wrappedSharedSecret,String subsystemCertNickname,String sharedSecretNickname) throws Exception, NotInitializedException, TokenException, + NoSuchAlgorithmException, ObjectNotFoundException, InvalidKeyException, InvalidAlgorithmParameterException, + IOException { +- byte[] wrappedKey = Utils.base64decode(data.getWrappedPrivateData()); +- +- IConfigStore cs = CMS.getConfigStore(); +- String subsystemNick = cs.getString("tps.cert.subsystem.nickname"); +- String keyNick = cs.getString("conn.tks1.tksSharedSymKeyName", "sharedSecret"); + + CryptoManager cm = CryptoManager.getInstance(); + CryptoToken token = cm.getInternalKeyStorageToken(); ++ + KeyManager km = new KeyManager(token); + +- if (km.uniqueNamedKeyExists(keyNick)) { +- throw new IOException("Shared secret " + keyNick + " already exists"); ++ if (km.uniqueNamedKeyExists(sharedSecretNickname)) { ++ throw new IOException("Shared secret " + sharedSecretNickname + " already exists"); + } + ++ //Unwrap session key ++ + KeyWrapper keyWrap = token.getKeyWrapper(KeyWrapAlgorithm.RSA); +- X509Certificate cert = cm.findCertByNickname(subsystemNick); ++ X509Certificate cert = cm.findCertByNickname(subsystemCertNickname); + PrivateKey subsystemPrivateKey = cm.findPrivKeyByCert(cert); + keyWrap.initUnwrap(subsystemPrivateKey, null); + +- @SuppressWarnings("unused") +- SymmetricKey unwrapped = keyWrap.unwrapSymmetric(wrappedKey, SymmetricKey.DES, +- SymmetricKey.Usage.DECRYPT, 0); ++ SymmetricKey unwrappedSessionKey = keyWrap.unwrapSymmetric(wrappedSessionKey, SymmetricKey.DES3, ++ 0); ++ ++ SymmetricKey unwrappedSharedSecret = null; ++ ++ //Unwrap shared secret permanently with session key ++ ++ KeyWrapper sharedSecretWrap = token.getKeyWrapper(KeyWrapAlgorithm.DES3_ECB); ++ sharedSecretWrap.initUnwrap(unwrappedSessionKey,null); ++ unwrappedSharedSecret = sharedSecretWrap.unwrapSymmetricPerm(wrappedSharedSecret,SymmetricKey.DES3,0 ); ++ unwrappedSharedSecret.setNickName(sharedSecretNickname); ++ } + +- // TODO - I have a key - now what to do with it? +- // need to somehow import/label the symkey +- }*/ ++ public static SymmetricKey getSymKeyByName(CryptoToken token, String name) throws Exception { ++ ++ String method = "CryptoUtil.getSymKeyByName:"; ++ if (token == null || name == null) { ++ throw new Exception(method + "Invalid input data!"); ++ } ++ SymmetricKey[] keys; ++ ++ try { ++ keys = token.getCryptoStore().getSymmetricKeys(); ++ } catch (TokenException e) { ++ throw new Exception(method + "Can't get the list of symmetric keys!"); ++ } ++ int len = keys.length; ++ for (int i = 0; i < len; i++) { ++ SymmetricKey cur = keys[i]; ++ if (cur != null) { ++ if (name.equals(cur.getNickName())) { ++ return cur; ++ } ++ } ++ } ++ ++ return null; ++ } + + public static String[] getECcurves() { + return ecCurves; +-- +2.5.5 + diff --git a/pki-core.spec b/pki-core.spec index 39d01d2..cfa83c7 100644 --- a/pki-core.spec +++ b/pki-core.spec @@ -58,7 +58,7 @@ Name: pki-core Version: 10.3.3 -Release: 2%{?dist} +Release: 3%{?dist} Summary: Certificate System - PKI Core Components URL: http://pki.fedoraproject.org/ License: GPLv2 @@ -67,6 +67,7 @@ Group: System Environment/Daemons BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) BuildRequires: cmake >= 2.8.9-1 +BuildRequires: gcc-c++ BuildRequires: zip BuildRequires: java-1.8.0-openjdk-devel BuildRequires: redhat-rpm-config @@ -198,6 +199,8 @@ Source0: http://pki.fedoraproject.org/pki/sources/%{name}/%{version}/%{ ## pki-core-10.3.3-2 Patch1: pki-core-Fix-build-on-Fedora-25.patch +## pki-core-10.3.3-3 +Patch2: pki-core-post-re-base.patch # Obtain version phase number (e. g. - used by "alpha", "beta", etc.) # @@ -779,6 +782,7 @@ This package is a part of the PKI Core used by the Certificate System. %prep %setup -q -n %{name}-%{version}%{?prerel} %patch1 -p1 +%patch2 -p1 %clean %{__rm} -rf %{buildroot} @@ -1192,6 +1196,49 @@ systemctl daemon-reload %endif # %{with server} %changelog +* Tue Jul 5 2016 Dogtag Team 10.3.3-3 +- PKI TRAC Ticket #691 - [MAN] pki-server man pages (mharmsen) +- PKI TRAC Ticket #1114 - [MAN] Generting Symmetric key fails with + key-generate when --usages verify is passed (jmagne) +- PKI TRAC Ticket #1306 - [RFE] Add granularity to token termination in TPS + (cfu) +- PKI TRAC Ticket #1308 - [RFE] Provide ability to perform off-card key + generation for non-encryption token keys (cfu) +- PKI TRAC Ticket #1405 - [MAN] Add additional HSM details to + 'pki_default.cfg' & 'pkispawn' man pages (mharmsen) +- PKI TRAC Ticket #1607 - [MAN] man pkispawn has inadequate description for + shared vs non shared tomcat instance installation (mharmsen) +- PKI TRAC Ticket #1664 - [BUG] Add ability to disallow TPS to enroll a single + user on multiple tokens. (jmagne) +- PKI TRAC Ticket #1711 - CLI :: pki-server ca-cert-request-find throws + IOError (edewata, ftweedal) +- PKI TRAC Ticket #2285 - freeipa fails to start correctly after pki-core + update on upgraded system (ftweedal) +- PKI TRAC Ticket #2311 - When pki_token_name=Internal, consider normalizing + it to "internal" (mharmsen) +- PKI TRAC Ticket #2349 - Separated TPS does not automatically receive shared + secret from remote TKS (jmagne) +- PKI TRAC Ticket #2364 - CLI :: pki-server ca-cert-request-show throws + attribute error (ftweedal) +- PKI TRAC Ticket #2368 - pki-server subsystem subcommands throws error with + --help option (edewata) +- PKI TRAC Ticket #2374 - KRA cloning overwrites CA signing certificate trust + flags (edewata) +- PKI TRAC Ticket #2380 - Pki-server instance commands throws exception while + specifying invalid parameters. (edewata) +- PKI TRAC Ticket #2384 - CA installation with HSM prompts for HSM password + during silent installation (edewata) +- PKI TRAC Ticket #2385 - Upgraded CA lacks ca.sslserver.certreq in CS.cfg + (ftweedal) +- PKI TRAC Ticket #2387 - Add config for default OCSP URI if none given + (ftweedal) +- PKI TRAC Ticket #2388 - CA creation responds 500 if certificate issuance + fails (ftweedal) +- PKI TRAC Ticket #2389 - Installation: subsystem certs could have notAfter + beyond CA signing cert in case of external or existing CA (cfu) +- PKI TRAC Ticket #2390 - Dogtag 10.3.4: Miscellaneous Enhancements + (akasurde, edewata) + * Thu Jun 30 2016 Dogtag Team 10.3.3-2 - PKI TRAC Ticket #2373 - Fedora 25: RestEasy 3.0.6 ==> 3.0.17 breaks pki-core (ftweedal)