From 9813300cd16a0a3999b29666f78e7b4196f97410 Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Nov 03 2016 06:00:25 +0000 Subject: import pki-core-10.3.3-10.el7 --- diff --git a/.gitignore b/.gitignore index a8dc0a4..ec79473 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -SOURCES/pki-core-10.2.5.tar.gz +SOURCES/pki-core-10.3.3.tar.gz diff --git a/.pki-core.metadata b/.pki-core.metadata index 9993b27..a9389db 100644 --- a/.pki-core.metadata +++ b/.pki-core.metadata @@ -1 +1 @@ -05b09ee5181a3bcd7cc8bf23598fc65de3815ba7 SOURCES/pki-core-10.2.5.tar.gz +4b632673e6e3cfe391277f73bd2782f9f60de985 SOURCES/pki-core-10.3.3.tar.gz diff --git a/SOURCES/pki-core-Added-support-for-cloning-3rd-party-CA-certificates.patch b/SOURCES/pki-core-Added-support-for-cloning-3rd-party-CA-certificates.patch deleted file mode 100644 index efdfcb0..0000000 --- a/SOURCES/pki-core-Added-support-for-cloning-3rd-party-CA-certificates.patch +++ /dev/null @@ -1,5703 +0,0 @@ -From 81240024c49ae0f47d51bbd0501264399b595051 Mon Sep 17 00:00:00 2001 -From: "Endi S. Dewata" -Date: Mon, 13 Jul 2015 19:09:57 -0400 -Subject: [PATCH] Added support for cloning 3rd-party CA certificates. - -The PKCS12Export has been modified to store the trust flags of -the certificates in the PKCS #12 file such that they can be -restored when the file is imported into an NSS database. - -During cloning the installation scripts have been modified to -import the CA certificates in the PKCS #12 file separately using -certutil before the server is started. This includes the PKI CA -certificates and 3rd-party CA certificates. This step is necessary -since JSS is unable to preserve the CA certificate nicknames. - -Some pki and pki-server commands have been added to help importing -and exportng certificates and keys between PKCS #12 file and NSS -database. - -https://fedorahosted.org/pki/ticket/2022 ---- - base/common/CMakeLists.txt | 1 + - base/common/python/pki/{cli.py => cli/__init__.py} | 0 - base/common/python/pki/cli/pkcs12.py | 297 ++++++++++ - base/common/python/pki/nssdb.py | 202 ++++--- - base/common/share/etc/logging.properties | 28 + - base/common/share/etc/pki.conf | 3 + - base/java-tools/bin/pki | 318 +++++++--- - .../src/com/netscape/cmstools/PKCS12Export.java | 387 +++++-------- - .../src/com/netscape/cmstools/cli/MainCLI.java | 3 + - .../com/netscape/cmstools/pkcs12/PKCS12CLI.java | 47 ++ - .../netscape/cmstools/pkcs12/PKCS12CertAddCLI.java | 167 ++++++ - .../netscape/cmstools/pkcs12/PKCS12CertCLI.java | 59 ++ - .../cmstools/pkcs12/PKCS12CertExportCLI.java | 207 +++++++ - .../cmstools/pkcs12/PKCS12CertFindCLI.java | 162 ++++++ - .../cmstools/pkcs12/PKCS12CertRemoveCLI.java | 149 +++++ - .../netscape/cmstools/pkcs12/PKCS12ExportCLI.java | 166 ++++++ - .../netscape/cmstools/pkcs12/PKCS12ImportCLI.java | 153 +++++ - .../com/netscape/cmstools/pkcs12/PKCS12KeyCLI.java | 43 ++ - .../netscape/cmstools/pkcs12/PKCS12KeyFindCLI.java | 163 ++++++ - .../cmstools/pkcs12/PKCS12KeyRemoveCLI.java | 150 +++++ - .../templates/pki_java_command_wrapper.in | 7 +- - base/server/python/pki/server/__init__.py | 165 +++++- - base/server/python/pki/server/cli/ca.py | 205 ++++++- - base/server/python/pki/server/cli/instance.py | 98 ++++ - base/server/python/pki/server/cli/kra.py | 142 +++++ - base/server/python/pki/server/cli/ocsp.py | 140 +++++ - base/server/python/pki/server/cli/subsystem.py | 78 ++- - base/server/python/pki/server/cli/tks.py | 140 +++++ - base/server/python/pki/server/cli/tps.py | 140 +++++ - .../server/deployment/scriptlets/configuration.py | 2 +- - .../deployment/scriptlets/security_databases.py | 28 + - base/server/sbin/pki-server | 9 + - base/util/src/netscape/security/pkcs/PKCS12.java | 205 +++++++ - .../src/netscape/security/pkcs/PKCS12CertInfo.java | 65 +++ - .../src/netscape/security/pkcs/PKCS12KeyInfo.java | 56 ++ - .../src/netscape/security/pkcs/PKCS12Util.java | 642 +++++++++++++++++++++ - 36 files changed, 4375 insertions(+), 452 deletions(-) - rename base/common/python/pki/{cli.py => cli/__init__.py} (100%) - create mode 100644 base/common/python/pki/cli/pkcs12.py - create mode 100644 base/common/share/etc/logging.properties - create mode 100644 base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12CLI.java - create mode 100644 base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12CertAddCLI.java - create mode 100644 base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12CertCLI.java - create mode 100644 base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12CertExportCLI.java - create mode 100644 base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12CertFindCLI.java - create mode 100644 base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12CertRemoveCLI.java - create mode 100644 base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12ExportCLI.java - create mode 100644 base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12ImportCLI.java - create mode 100644 base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12KeyCLI.java - create mode 100644 base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12KeyFindCLI.java - create mode 100644 base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12KeyRemoveCLI.java - create mode 100644 base/server/python/pki/server/cli/kra.py - create mode 100644 base/server/python/pki/server/cli/ocsp.py - create mode 100644 base/server/python/pki/server/cli/tks.py - create mode 100644 base/server/python/pki/server/cli/tps.py - create mode 100644 base/util/src/netscape/security/pkcs/PKCS12.java - create mode 100644 base/util/src/netscape/security/pkcs/PKCS12CertInfo.java - create mode 100644 base/util/src/netscape/security/pkcs/PKCS12KeyInfo.java - create mode 100644 base/util/src/netscape/security/pkcs/PKCS12Util.java - -diff --git a/base/common/CMakeLists.txt b/base/common/CMakeLists.txt -index ee401f201429167b67348c35c9c89c3d52b3c3fd..121392512de0b4695c5508fa432bca4f18d167cf 100644 ---- a/base/common/CMakeLists.txt -+++ b/base/common/CMakeLists.txt -@@ -13,6 +13,7 @@ configure_file( - - install( - FILES -+ ${CMAKE_CURRENT_SOURCE_DIR}/share/etc/logging.properties - ${CMAKE_CURRENT_BINARY_DIR}/share/etc/pki.conf - DESTINATION - ${DATA_INSTALL_DIR}/etc/ -diff --git a/base/common/python/pki/cli.py b/base/common/python/pki/cli/__init__.py -similarity index 100% -rename from base/common/python/pki/cli.py -rename to base/common/python/pki/cli/__init__.py -diff --git a/base/common/python/pki/cli/pkcs12.py b/base/common/python/pki/cli/pkcs12.py -new file mode 100644 -index 0000000000000000000000000000000000000000..eaca3c6f886f273414c571af1ba3c4d5f508cb30 ---- /dev/null -+++ b/base/common/python/pki/cli/pkcs12.py -@@ -0,0 +1,297 @@ -+# 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) 2016 Red Hat, Inc. -+# All rights reserved. -+# -+ -+from __future__ import absolute_import -+from __future__ import print_function -+import getopt -+import os -+import re -+import shutil -+import sys -+import tempfile -+ -+import pki.cli -+import pki.nssdb -+ -+ -+class PKCS12CLI(pki.cli.CLI): -+ -+ def __init__(self): -+ super(PKCS12CLI, self).__init__( -+ 'pkcs12', 'PKCS #12 utilities') -+ -+ self.add_module(PKCS12ImportCLI()) -+ -+ -+class PKCS12ImportCLI(pki.cli.CLI): -+ -+ def __init__(self): -+ super(PKCS12ImportCLI, self).__init__( -+ 'import', 'Import PKCS #12 file into NSS database') -+ -+ def print_help(self): # flake8: noqa -+ print('Usage: pki pkcs12-import [OPTIONS]') -+ print() -+ print(' --pkcs12-file PKCS #12 file containing certificates and keys.') -+ print(' --pkcs12-password Password for the PKCS #12 file.') -+ print(' --pkcs12-password-file containing the PKCS #12 password.') -+ 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(' -v, --verbose Run in verbose mode.') -+ print(' --debug Run in debug mode.') -+ print(' --help Show help message.') -+ print() -+ -+ def execute(self, args): -+ -+ try: -+ opts, _ = getopt.gnu_getopt(args, 'v', [ -+ 'pkcs12-file=', 'pkcs12-password=', 'pkcs12-password-file=', -+ 'no-trust-flags', 'no-user-certs', 'no-ca-certs', -+ 'verbose', 'debug', 'help']) -+ -+ except getopt.GetoptError as e: -+ print('ERROR: ' + str(e)) -+ self.print_help() -+ sys.exit(1) -+ -+ pkcs12_file = None -+ pkcs12_password = None -+ password_file = None -+ no_trust_flags = False -+ import_user_certs = True -+ import_ca_certs = True -+ debug = False -+ -+ for o, a in opts: -+ if o == '--pkcs12-file': -+ pkcs12_file = a -+ -+ elif o == '--pkcs12-password': -+ pkcs12_password = a -+ -+ elif o == '--pkcs12-password-file': -+ password_file = a -+ -+ elif o == '--no-trust-flags': -+ no_trust_flags = True -+ -+ elif o == '--no-user-certs': -+ import_user_certs = False -+ -+ elif o == '--no-ca-certs': -+ import_ca_certs = False -+ -+ elif o in ('-v', '--verbose'): -+ self.set_verbose(True) -+ -+ elif o == '--debug': -+ debug = True -+ -+ elif o == '--help': -+ self.print_help() -+ sys.exit() -+ -+ else: -+ print('ERROR: unknown option ' + o) -+ self.print_help() -+ sys.exit(1) -+ -+ if not pkcs12_file: -+ print('ERROR: Missing PKCS #12 file') -+ self.print_help() -+ sys.exit(1) -+ -+ if not pkcs12_password and not password_file: -+ print('ERROR: Missing PKCS #12 password') -+ self.print_help() -+ sys.exit(1) -+ -+ main_cli = self.parent.parent -+ -+ # Due to JSS limitation, CA certificates need to be imported -+ # using certutil in order to preserve the nickname stored in -+ # the PKCS #12 file. -+ -+ if main_cli.verbose: -+ print('Getting certificate infos in PKCS #12 file') -+ -+ certs = [] -+ -+ tmpdir = tempfile.mkdtemp() -+ -+ try: -+ # find all certs in PKCS #12 file -+ output_file = os.path.join(tmpdir, 'pkcs12-cert-find.txt') -+ with open(output_file, 'wb') as f: -+ -+ cmd = ['pkcs12-cert-find'] -+ -+ if pkcs12_file: -+ cmd.extend(['--pkcs12-file', pkcs12_file]) -+ -+ if pkcs12_password: -+ cmd.extend(['--pkcs12-password', pkcs12_password]) -+ -+ if password_file: -+ cmd.extend(['--pkcs12-password-file', password_file]) -+ -+ if no_trust_flags: -+ cmd.extend(['--no-trust-flags']) -+ -+ if self.verbose: -+ cmd.extend(['--verbose']) -+ -+ if debug: -+ cmd.extend(['--debug']) -+ -+ main_cli.execute_java(cmd, stdout=f) -+ -+ # parse results -+ with open(output_file, 'r') as f: -+ -+ for line in f: -+ match = re.match(r' Certificate ID: (.*)$', line) -+ if match: -+ cert_info = {} -+ cert_info['id'] = match.group(1) -+ certs.append(cert_info) -+ continue -+ -+ match = re.match(r' Nickname: (.*)$', line) -+ if match: -+ cert_info['nickname'] = match.group(1) -+ continue -+ -+ match = re.match(r' Trust Flags: (.*)$', line) -+ if match: -+ cert_info['trust_flags'] = match.group(1) -+ continue -+ -+ match = re.match(r' Has Key: (.*)$', line) -+ if match: -+ cert_info['has_key'] = match.group(1) == 'true' -+ continue -+ -+ finally: -+ shutil.rmtree(tmpdir) -+ -+ # import CA certificates if requested -+ if import_ca_certs: -+ -+ if main_cli.verbose: -+ print('Importing CA certificates') -+ -+ tmpdir = tempfile.mkdtemp() -+ -+ try: -+ cert_file = os.path.join(tmpdir, 'ca-cert.pem') -+ -+ nssdb = pki.nssdb.NSSDatabase( -+ main_cli.database, -+ token=main_cli.token, -+ password=main_cli.password, -+ password_file=main_cli.password_file) -+ -+ for cert_info in certs: -+ -+ has_key = cert_info['has_key'] -+ if has_key: -+ continue -+ -+ cert_id = cert_info['id'] -+ nickname = cert_info['nickname'] -+ trust_flags = cert_info['trust_flags'] -+ -+ if main_cli.verbose: -+ print('Exporting %s (%s) from PKCS #12 file' % (nickname, cert_id)) -+ -+ cmd = ['pkcs12-cert-export'] -+ -+ if pkcs12_file: -+ cmd.extend(['--pkcs12-file', pkcs12_file]) -+ -+ if pkcs12_password: -+ cmd.extend(['--pkcs12-password', pkcs12_password]) -+ -+ if password_file: -+ cmd.extend(['--pkcs12-password-file', password_file]) -+ -+ cmd.extend(['--cert-file', cert_file]) -+ -+ cmd.extend(['--cert-id', cert_id]) -+ -+ if self.verbose: -+ cmd.extend(['--verbose']) -+ -+ if debug: -+ cmd.extend(['--debug']) -+ -+ main_cli.execute_java(cmd) -+ -+ if main_cli.verbose: -+ print('Importing %s' % nickname) -+ -+ nssdb.add_cert(nickname, cert_file, trust_flags) -+ -+ finally: -+ shutil.rmtree(tmpdir) -+ -+ # import user certificates if requested -+ if import_user_certs: -+ -+ if main_cli.verbose: -+ print('Importing user certificates') -+ -+ nicknames = [] -+ for cert_info in certs: -+ -+ has_key = cert_info['has_key'] -+ if not has_key: -+ continue -+ -+ nickname = cert_info['nickname'] -+ if nickname not in nicknames: -+ nicknames.append(nickname) -+ -+ cmd = ['pkcs12-import'] -+ -+ if pkcs12_file: -+ cmd.extend(['--pkcs12-file', pkcs12_file]) -+ -+ if pkcs12_password: -+ cmd.extend(['--pkcs12-password', pkcs12_password]) -+ -+ if password_file: -+ cmd.extend(['--pkcs12-password-file', password_file]) -+ -+ if no_trust_flags: -+ cmd.extend(['--no-trust-flags']) -+ -+ if self.verbose: -+ cmd.extend(['--verbose']) -+ -+ if debug: -+ cmd.extend(['--debug']) -+ -+ cmd.extend(nicknames) -+ -+ main_cli.execute_java(cmd) -diff --git a/base/common/python/pki/nssdb.py b/base/common/python/pki/nssdb.py -index 44e286853c252675bff9e25c32377aaa86f8cf18..9d276332aacb5a74b36c20406028e03a21c51b72 100644 ---- a/base/common/python/pki/nssdb.py -+++ b/base/common/python/pki/nssdb.py -@@ -18,6 +18,7 @@ - # All rights reserved. - # - -+from __future__ import absolute_import - import base64 - import os - import shutil -@@ -36,7 +37,6 @@ PKCS7_FOOTER = '-----END PKCS7-----' - - - def convert_data(data, input_format, output_format, header=None, footer=None): -- - if input_format == output_format: - return data - -@@ -46,7 +46,7 @@ def convert_data(data, input_format, output_format, header=None, footer=None): - data = data.replace('\r', '').replace('\n', '') - - # re-split the line into fixed-length lines -- lines = [data[i:i+64] for i in range(0, len(data), 64)] -+ lines = [data[i:i + 64] for i in range(0, len(data), 64)] - - # add header and footer - return '%s\n%s\n%s\n' % (header, '\n'.join(lines), footer) -@@ -67,20 +67,20 @@ def convert_data(data, input_format, output_format, header=None, footer=None): - - raise Exception('Unable to convert data from %s to %s' % (input_format, output_format)) - -+ - def convert_csr(csr_data, input_format, output_format): -- - return convert_data(csr_data, input_format, output_format, CSR_HEADER, CSR_FOOTER) - -+ - def convert_cert(cert_data, input_format, output_format): -- - return convert_data(cert_data, input_format, output_format, CERT_HEADER, CERT_FOOTER) - -+ - def convert_pkcs7(pkcs7_data, input_format, output_format): -- - return convert_data(pkcs7_data, input_format, output_format, PKCS7_HEADER, PKCS7_FOOTER) - -+ - def get_file_type(filename): -- - with open(filename, 'r') as f: - data = f.read() - -@@ -98,7 +98,11 @@ def get_file_type(filename): - - class NSSDatabase(object): - -- def __init__(self, directory, token='internal', password=None, password_file=None): -+ def __init__(self, directory=None, token=None, password=None, password_file=None): -+ -+ if not directory: -+ directory = os.path.join(os.path.expanduser("~"), '.dogtag', 'nssdb') -+ - self.directory = directory - self.token = token - -@@ -118,42 +122,44 @@ class NSSDatabase(object): - def close(self): - shutil.rmtree(self.tmpdir) - -- def add_cert(self, -- nickname, -- cert_file, -- trust_attributes=',,'): -- -+ def add_cert(self, nickname, cert_file, trust_attributes=',,'): - cmd = [ - 'certutil', - '-A', -- '-d', self.directory, -- '-h', self.token, -+ '-d', self.directory -+ ] -+ -+ if self.token: -+ cmd.extend(['-h', self.token]) -+ -+ cmd.extend([ - '-f', self.password_file, - '-n', nickname, - '-i', cert_file, - '-t', trust_attributes -- ] -+ ]) - - subprocess.check_call(cmd) - -- def modify_cert(self, -- nickname, -- trust_attributes): -- -+ def modify_cert(self, nickname, trust_attributes): - cmd = [ - 'certutil', - '-M', -- '-d', self.directory, -- '-h', self.token, -+ '-d', self.directory -+ ] -+ -+ if self.token: -+ cmd.extend(['-h', self.token]) -+ -+ cmd.extend([ - '-f', self.password_file, - '-n', nickname, - '-t', trust_attributes -- ] -+ ]) - - subprocess.check_call(cmd) - - def create_noise(self, noise_file, size=2048): -- - subprocess.check_call([ - 'openssl', - 'rand', -@@ -161,15 +167,9 @@ class NSSDatabase(object): - str(size) - ]) - -- def create_request(self, -- subject_dn, -- request_file, -- noise_file=None, -- key_type=None, -- key_size=None, -- curve=None, -- hash_alg=None): -- -+ def create_request(self, subject_dn, request_file, noise_file=None, -+ key_type=None, key_size=None, curve=None, -+ hash_alg=None): - tmpdir = tempfile.mkdtemp() - - try: -@@ -188,13 +188,18 @@ class NSSDatabase(object): - cmd = [ - 'certutil', - '-R', -- '-d', self.directory, -- '-h', self.token, -+ '-d', self.directory -+ ] -+ -+ if self.token: -+ cmd.extend(['-h', self.token]) -+ -+ cmd.extend([ - '-f', self.password_file, - '-s', subject_dn, - '-o', binary_request_file, - '-z', noise_file -- ] -+ ]) - - if key_type: - cmd.extend(['-k', key_type]) -@@ -229,19 +234,20 @@ class NSSDatabase(object): - finally: - shutil.rmtree(tmpdir) - -- def create_self_signed_ca_cert(self, -- subject_dn, -- request_file, -- cert_file, -- serial='1', -- validity=240): -+ def create_self_signed_ca_cert(self, subject_dn, request_file, cert_file, -+ serial='1', validity=240): - - cmd = [ - 'certutil', - '-C', - '-x', -- '-d', self.directory, -- '-h', self.token, -+ '-d', self.directory -+ ] -+ -+ if self.token: -+ cmd.extend(['-h', self.token]) -+ -+ cmd.extend([ - '-f', self.password_file, - '-c', subject_dn, - '-a', -@@ -254,9 +260,10 @@ class NSSDatabase(object): - '-3', - '--extSKID', - '--extAIA' -- ] -+ ]) - -- p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) -+ p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, -+ stderr=subprocess.STDOUT) - - keystroke = '' - -@@ -333,12 +340,17 @@ class NSSDatabase(object): - cmd = [ - 'certutil', - '-L', -- '-d', self.directory, -- '-h', self.token, -+ '-d', self.directory -+ ] -+ -+ if self.token: -+ cmd.extend(['-h', self.token]) -+ -+ cmd.extend([ - '-f', self.password_file, - '-n', nickname, - output_format_option -- ] -+ ]) - - cert_data = subprocess.check_output(cmd) - -@@ -352,38 +364,46 @@ class NSSDatabase(object): - cmd = [ - 'certutil', - '-D', -- '-d', self.directory, -- '-h', self.token, -+ '-d', self.directory -+ ] -+ -+ if self.token: -+ cmd.extend(['-h', self.token]) -+ -+ cmd.extend([ - '-f', self.password_file, - '-n', nickname -- ] -+ ]) - - subprocess.check_call(cmd) - -- def import_cert_chain(self, nickname, cert_chain_file, trust_attributes=None): -+ def import_cert_chain(self, nickname, cert_chain_file, -+ trust_attributes=None): - - tmpdir = tempfile.mkdtemp() - - try: - file_type = get_file_type(cert_chain_file) - -- if file_type == 'cert': # import single PEM cert -+ if file_type == 'cert': # import single PEM cert - self.add_cert( - nickname=nickname, - cert_file=cert_chain_file, - trust_attributes=trust_attributes) -- return self.get_cert( -- nickname=nickname, -- output_format='base64') -+ return ( -+ self.get_cert(nickname=nickname, output_format='base64'), -+ [nickname] -+ ) - -- elif file_type == 'pkcs7': # import PKCS #7 cert chain -- return self.import_pkcs7( -+ elif file_type == 'pkcs7': # import PKCS #7 cert chain -+ chain, nicks = self.import_pkcs7( - pkcs7_file=cert_chain_file, - nickname=nickname, - trust_attributes=trust_attributes, - output_format='base64') -+ return chain, nicks - -- else: # import PKCS #7 data without header/footer -+ else: # import PKCS #7 data without header/footer - with open(cert_chain_file, 'r') as f: - base64_data = f.read() - pkcs7_data = convert_pkcs7(base64_data, 'base64', 'pem') -@@ -392,17 +412,18 @@ class NSSDatabase(object): - with open(tmp_cert_chain_file, 'w') as f: - f.write(pkcs7_data) - -- self.import_pkcs7( -+ chain, nicks = self.import_pkcs7( - pkcs7_file=tmp_cert_chain_file, - nickname=nickname, - trust_attributes=trust_attributes) - -- return base64_data -+ return base64_data, nicks - - finally: - shutil.rmtree(tmpdir) - -- def import_pkcs7(self, pkcs7_file, nickname, trust_attributes=None, output_format='pem'): -+ def import_pkcs7(self, pkcs7_file, nickname, trust_attributes=None, -+ output_format='pem'): - - tmpdir = tempfile.mkdtemp() - -@@ -418,6 +439,7 @@ class NSSDatabase(object): - # parse PEM output into separate PEM certificates - certs = [] - lines = [] -+ nicks = [] - state = 'header' - - for line in output.splitlines(): -@@ -459,6 +481,7 @@ class NSSDatabase(object): - n = '%s #%d' % (nickname, counter) - - self.add_cert(n, cert_file, trust_attributes) -+ nicks.append(n) - - counter += 1 - -@@ -466,12 +489,16 @@ class NSSDatabase(object): - with open(pkcs7_file, 'r') as f: - data = f.read() - -- return convert_pkcs7(data, 'pem', output_format) -+ return convert_pkcs7(data, 'pem', output_format), nicks - - finally: - shutil.rmtree(tmpdir) - -- def import_pkcs12(self, pkcs12_file, pkcs12_password=None, pkcs12_password_file=None): -+ def import_pkcs12(self, pkcs12_file, -+ pkcs12_password=None, -+ pkcs12_password_file=None, -+ no_user_certs=False, -+ no_ca_certs=False): - - tmpdir = tempfile.mkdtemp() - -@@ -488,20 +515,35 @@ class NSSDatabase(object): - raise Exception('Missing PKCS #12 password') - - cmd = [ -- 'pk12util', -+ 'pki', - '-d', self.directory, -- '-h', self.token, -- '-k', self.password_file, -- '-i', pkcs12_file, -- '-w', password_file -+ '-C', self.password_file - ] - -+ if self.token: -+ cmd.extend(['--token', self.token]) -+ -+ cmd.extend([ -+ 'pkcs12-import', -+ '--pkcs12-file', pkcs12_file, -+ '--pkcs12-password-file', password_file -+ ]) -+ -+ if no_user_certs: -+ cmd.extend(['--no-user-certs']) -+ -+ if no_ca_certs: -+ cmd.extend(['--no-ca-certs']) -+ - subprocess.check_call(cmd) - - finally: - shutil.rmtree(tmpdir) - -- def export_pkcs12(self, pkcs12_file, nickname, pkcs12_password=None, pkcs12_password_file=None): -+ def export_pkcs12(self, pkcs12_file, -+ pkcs12_password=None, -+ pkcs12_password_file=None, -+ nicknames=None): - - tmpdir = tempfile.mkdtemp() - -@@ -518,14 +560,24 @@ class NSSDatabase(object): - raise Exception('Missing PKCS #12 password') - - cmd = [ -- 'pk12util', -+ 'pki', - '-d', self.directory, -- '-k', self.password_file, -- '-o', pkcs12_file, -- '-w', password_file, -- '-n', nickname -+ '-C', self.password_file - ] - -+ if self.token: -+ cmd.extend(['--token', self.token]) -+ -+ cmd.extend(['pkcs12-export']) -+ -+ cmd.extend([ -+ '--pkcs12-file', pkcs12_file, -+ '--pkcs12-password-file', password_file -+ ]) -+ -+ if nicknames: -+ cmd.extend(nicknames) -+ - subprocess.check_call(cmd) - - finally: -diff --git a/base/common/share/etc/logging.properties b/base/common/share/etc/logging.properties -new file mode 100644 -index 0000000000000000000000000000000000000000..bd5b5b627903e0daa2c8b70a0569a5cc78321765 ---- /dev/null -+++ b/base/common/share/etc/logging.properties -@@ -0,0 +1,28 @@ -+# --- BEGIN COPYRIGHT BLOCK --- -+# Copyright (C) 2016 Red Hat, Inc. -+# All rights reserved. -+# Modifications: configuration parameters -+# --- END COPYRIGHT BLOCK --- -+ -+# Licensed to the Apache Software Foundation (ASF) under one or more -+# contributor license agreements. See the NOTICE file distributed with -+# this work for additional information regarding copyright ownership. -+# The ASF licenses this file to You under the Apache License, Version 2.0 -+# (the "License"); you may not use this file except in compliance with -+# the License. You may obtain a copy of the License at -+# -+# http://www.apache.org/licenses/LICENSE-2.0 -+# -+# Unless required by applicable law or agreed to in writing, software -+# distributed under the License is distributed on an "AS IS" BASIS, -+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -+# See the License for the specific language governing permissions and -+# limitations under the License. -+ -+handlers = java.util.logging.ConsoleHandler -+ -+java.util.logging.ConsoleHandler.level = ALL -+java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter -+java.util.logging.SimpleFormatter.format = %4$s: %5$s%6$s%n -+ -+.level = WARNING -diff --git a/base/common/share/etc/pki.conf b/base/common/share/etc/pki.conf -index a43d1d6c144379d655da06f77e8b5056bc787e6a..57cb83e5a5087f4d8efea2743a1b3b7cc95c0489 100644 ---- a/base/common/share/etc/pki.conf -+++ b/base/common/share/etc/pki.conf -@@ -1,2 +1,5 @@ - # JNI jar file location - JNI_JAR_DIR=/usr/lib/java -+ -+# logging configuration location -+LOGGING_CONFIG=/usr/share/pki/etc/logging.properties -diff --git a/base/java-tools/bin/pki b/base/java-tools/bin/pki -index 152bf3f62c593aa6441a2082c33e311f583a4534..e476cfcfe0b4476820354ef1ec8a9ddfbf0f734c 100644 ---- a/base/java-tools/bin/pki -+++ b/base/java-tools/bin/pki -@@ -19,104 +19,240 @@ - # All rights reserved. - # - -+from __future__ import absolute_import -+from __future__ import print_function - import shlex - import subprocess - import sys -+import traceback - --def run_java_cli(args): -- -- # read RESTEasy library path -- value = subprocess.check_output( -- '. /etc/pki/pki.conf && echo $RESTEASY_LIB', -- shell=True) -- resteasy_lib = str(value).strip() -- -- # construct classpath -- classpath = [ -- '/usr/share/java/commons-cli.jar', -- '/usr/share/java/commons-codec.jar', -- '/usr/share/java/commons-httpclient.jar', -- '/usr/share/java/commons-io.jar', -- '/usr/share/java/commons-lang.jar', -- '/usr/share/java/commons-logging.jar', -- '/usr/share/java/httpcomponents/httpclient.jar', -- '/usr/share/java/httpcomponents/httpcore.jar', -- '/usr/share/java/jackson/jackson-core-asl.jar', -- '/usr/share/java/jackson/jackson-jaxrs.jar', -- '/usr/share/java/jackson/jackson-mapper-asl.jar', -- '/usr/share/java/jackson/jackson-mrbean.jar', -- '/usr/share/java/jackson/jackson-smile.jar', -- '/usr/share/java/jackson/jackson-xc.jar', -- '/usr/share/java/jaxb-api.jar', -- '/usr/share/java/ldapjdk.jar', -- '/usr/share/java/servlet.jar', -- resteasy_lib + '/jaxrs-api.jar', -- resteasy_lib + '/resteasy-atom-provider.jar', -- resteasy_lib + '/resteasy-client.jar', -- resteasy_lib + '/resteasy-jaxb-provider.jar', -- resteasy_lib + '/resteasy-jaxrs.jar', -- resteasy_lib + '/resteasy-jaxrs-jandex.jar', -- resteasy_lib + '/resteasy-jackson-provider.jar', -- '/usr/share/java/pki/pki-nsutil.jar', -- '/usr/share/java/pki/pki-cmsutil.jar', -- '/usr/share/java/pki/pki-certsrv.jar', -- '/usr/share/java/pki/pki-tools.jar', -- '/usr/lib64/java/jss4.jar', -- '/usr/lib/java/jss4.jar' -- ] -- -- command = [ -- 'java', -- '-cp', -- ':'.join(classpath), -- 'com.netscape.cmstools.cli.MainCLI' -- ] -- -- command.extend(args) -- -- rv = subprocess.call(command) -- exit(rv) -- -- --# pylint: disable=W0613 --def run_python_cli(args): -- -- raise Exception('Not implemented') -- -- --def main(argv): -- -- # read global options -- value = subprocess.check_output( -- '. /etc/pki/pki.conf && echo $PKI_CLI_OPTIONS', -- shell=True) -- args = shlex.split(value.strip()) -- args.extend(argv[1:]) -- -- client_type = 'java' -- -- new_args = [] -- -- # read --client-type parameter and remove it from the argument list -- i = 0 -- while i < len(args): -- if args[i] == '--client-type': -- client_type = args[i + 1] -+import pki.cli -+import pki.cli.pkcs12 -+ -+ -+PYTHON_COMMANDS = ['pkcs12-import'] -+ -+ -+class PKICLI(pki.cli.CLI): -+ -+ def __init__(self): -+ super(PKICLI, self).__init__( -+ 'pki', 'PKI command-line interface') -+ -+ self.database = None -+ self.password = None -+ self.password_file = None -+ self.token = None -+ -+ self.add_module(pki.cli.pkcs12.PKCS12CLI()) -+ -+ def get_full_module_name(self, module_name): -+ return module_name -+ -+ def print_help(self): -+ print('Usage: pki [OPTIONS]') -+ print() -+ print(' --client-type PKI client type (default: java)') -+ print(' -d Client security database location ' + -+ '(default: ~/.dogtag/nssdb)') -+ print(' -c Client security database password ' + -+ '(mutually exclusive to the -C option)') -+ print(' -C Client-side password file ' + -+ '(mutually exclusive to the -c option)') -+ print(' --token Security token name') -+ print() -+ print(' -v, --verbose Run in verbose mode.') -+ print(' --debug Show debug messages.') -+ print(' --help Show help message.') -+ print() -+ -+ super(PKICLI, self).print_help() -+ -+ def execute_java(self, args, stdout=sys.stdout): -+ -+ # read RESTEasy library path -+ value = subprocess.check_output( -+ '. /usr/share/pki/etc/pki.conf && . /etc/pki/pki.conf && echo $RESTEASY_LIB', -+ shell=True) -+ resteasy_lib = value.decode(sys.getfilesystemencoding()).strip() -+ -+ # read logging configuration path -+ value = subprocess.check_output( -+ '. /usr/share/pki/etc/pki.conf && . /etc/pki/pki.conf && echo $LOGGING_CONFIG', -+ shell=True) -+ logging_config = value.decode(sys.getfilesystemencoding()).strip() -+ -+ # construct classpath -+ classpath = [ -+ '/usr/share/java/commons-cli.jar', -+ '/usr/share/java/commons-codec.jar', -+ '/usr/share/java/commons-httpclient.jar', -+ '/usr/share/java/commons-io.jar', -+ '/usr/share/java/commons-lang.jar', -+ '/usr/share/java/commons-logging.jar', -+ '/usr/share/java/httpcomponents/httpclient.jar', -+ '/usr/share/java/httpcomponents/httpcore.jar', -+ '/usr/share/java/jackson/jackson-core-asl.jar', -+ '/usr/share/java/jackson/jackson-jaxrs.jar', -+ '/usr/share/java/jackson/jackson-mapper-asl.jar', -+ '/usr/share/java/jackson/jackson-mrbean.jar', -+ '/usr/share/java/jackson/jackson-smile.jar', -+ '/usr/share/java/jackson/jackson-xc.jar', -+ '/usr/share/java/jaxb-api.jar', -+ '/usr/share/java/ldapjdk.jar', -+ '/usr/share/java/servlet.jar', -+ resteasy_lib + '/jaxrs-api.jar', -+ resteasy_lib + '/resteasy-atom-provider.jar', -+ resteasy_lib + '/resteasy-client.jar', -+ resteasy_lib + '/resteasy-jaxb-provider.jar', -+ resteasy_lib + '/resteasy-jaxrs.jar', -+ resteasy_lib + '/resteasy-jaxrs-jandex.jar', -+ resteasy_lib + '/resteasy-jackson-provider.jar', -+ '/usr/share/java/pki/pki-nsutil.jar', -+ '/usr/share/java/pki/pki-cmsutil.jar', -+ '/usr/share/java/pki/pki-certsrv.jar', -+ '/usr/share/java/pki/pki-tools.jar', -+ '/usr/lib64/java/jss4.jar', -+ '/usr/lib/java/jss4.jar' -+ ] -+ -+ cmd = [ -+ 'java', -+ '-cp', -+ ':'.join(classpath), -+ '-Djava.util.logging.config.file=' + logging_config, -+ 'com.netscape.cmstools.cli.MainCLI' -+ ] -+ -+ # restore options for Java commands -+ -+ if self.database: -+ cmd.extend(['-d', self.database]) -+ -+ if self.password: -+ cmd.extend(['-c', self.password]) -+ -+ if self.password_file: -+ cmd.extend(['-C', self.password_file]) -+ -+ if self.token and self.token != 'internal': -+ cmd.extend(['--token', self.token]) -+ -+ cmd.extend(args) -+ -+ if self.verbose: -+ print('Java command: %s' % ' '.join(cmd)) -+ -+ subprocess.check_call(cmd, stdout=stdout) -+ -+ def execute(self, argv): -+ -+ # append global options -+ value = subprocess.check_output( -+ '. /usr/share/pki/etc/pki.conf && . /etc/pki/pki.conf && echo $PKI_CLI_OPTIONS', -+ shell=True) -+ value = value.decode(sys.getfilesystemencoding()).strip() -+ args = shlex.split(value) -+ args.extend(argv[1:]) -+ -+ client_type = 'java' -+ -+ pki_options = [] -+ command = None -+ cmd_args = [] -+ -+ # read pki options before the command -+ # remove options for Python module -+ -+ i = 0 -+ while i < len(args): -+ # if arg is a command, stop -+ if args[i][0] != '-': -+ command = args[i] -+ break -+ -+ # get database path -+ if args[i] == '-d': -+ self.database = args[i + 1] -+ pki_options.append(args[i]) -+ pki_options.append(args[i + 1]) -+ i = i + 2 -+ -+ # get database password -+ elif args[i] == '-c': -+ self.password = args[i + 1] -+ pki_options.append(args[i]) -+ pki_options.append(args[i + 1]) -+ i = i + 2 -+ -+ # get database password file path -+ elif args[i] == '-C': -+ self.password_file = args[i + 1] -+ pki_options.append(args[i]) -+ pki_options.append(args[i + 1]) -+ i = i + 2 -+ -+ # get token name -+ elif args[i] == '--token': -+ self.token = args[i + 1] -+ pki_options.append(args[i]) -+ pki_options.append(args[i + 1]) -+ i = i + 2 -+ -+ # check verbose option -+ elif args[i] == '-v' or args[i] == '--verbose': -+ self.set_verbose(True) -+ pki_options.append(args[i]) -+ i = i + 1 -+ -+ # check debug option -+ elif args[i] == '--debug': -+ self.set_verbose(True) -+ self.set_debug(True) -+ pki_options.append(args[i]) -+ i = i + 1 -+ -+ # get client type -+ elif args[i] == '--client-type': -+ client_type = args[i + 1] -+ pki_options.append(args[i]) -+ pki_options.append(args[i + 1]) -+ i = i + 2 -+ -+ else: # otherwise, save the arg for the next module -+ cmd_args.append(args[i]) -+ i = i + 1 -+ -+ # save the rest of the args -+ while i < len(args): -+ cmd_args.append(args[i]) - i = i + 1 - -+ if self.verbose: -+ print('PKI options: %s' % ' '.join(pki_options)) -+ print('PKI command: %s %s' % (command, ' '.join(cmd_args))) -+ -+ if client_type == 'python' or command in PYTHON_COMMANDS: -+ (module, module_args) = self.parse_args(cmd_args) -+ module.execute(module_args) -+ -+ elif client_type == 'java': -+ self.execute_java(cmd_args) -+ - else: -- new_args.append(args[i]) -+ raise Exception('Unsupported client type: ' + client_type) - -- i = i + 1 -- -- if client_type == 'java': -- run_java_cli(new_args) -- -- elif client_type == 'python': -- run_python_cli(new_args) -- -- else: -- raise Exception('Unsupported client type: ' + client_type) - - if __name__ == '__main__': -- main(sys.argv) -+ -+ cli = PKICLI() -+ -+ try: -+ cli.execute(sys.argv) -+ -+ except subprocess.CalledProcessError as e: -+ if cli.verbose: -+ print('ERROR: %s' % e) -+ elif cli.debug: -+ traceback.print_exc() -+ exit(e.returncode) -diff --git a/base/java-tools/src/com/netscape/cmstools/PKCS12Export.java b/base/java-tools/src/com/netscape/cmstools/PKCS12Export.java -index 9ab2f85052435b77685c42819d35942d1a8d376e..187ff766745130dd140f61fceebc6d1707088e2c 100644 ---- a/base/java-tools/src/com/netscape/cmstools/PKCS12Export.java -+++ b/base/java-tools/src/com/netscape/cmstools/PKCS12Export.java -@@ -18,40 +18,17 @@ - package com.netscape.cmstools; - - import java.io.BufferedReader; --import java.io.ByteArrayOutputStream; --import java.io.FileOutputStream; - import java.io.FileReader; --import java.io.IOException; --import java.security.MessageDigest; -+import java.util.logging.Level; -+import java.util.logging.Logger; - - import org.mozilla.jss.CryptoManager; --import org.mozilla.jss.asn1.ASN1Util; --import org.mozilla.jss.asn1.ASN1Value; --import org.mozilla.jss.asn1.BMPString; --import org.mozilla.jss.asn1.OCTET_STRING; --import org.mozilla.jss.asn1.SEQUENCE; --import org.mozilla.jss.asn1.SET; --import org.mozilla.jss.crypto.Cipher; --import org.mozilla.jss.crypto.CryptoStore; - import org.mozilla.jss.crypto.CryptoToken; --import org.mozilla.jss.crypto.EncryptionAlgorithm; --import org.mozilla.jss.crypto.IVParameterSpec; --import org.mozilla.jss.crypto.KeyGenAlgorithm; --import org.mozilla.jss.crypto.KeyGenerator; --import org.mozilla.jss.crypto.KeyWrapAlgorithm; --import org.mozilla.jss.crypto.KeyWrapper; --import org.mozilla.jss.crypto.PBEAlgorithm; --import org.mozilla.jss.crypto.SymmetricKey; --import org.mozilla.jss.crypto.X509Certificate; --import org.mozilla.jss.pkcs12.AuthenticatedSafes; --import org.mozilla.jss.pkcs12.CertBag; --import org.mozilla.jss.pkcs12.PFX; --import org.mozilla.jss.pkcs12.PasswordConverter; --import org.mozilla.jss.pkcs12.SafeBag; --import org.mozilla.jss.pkix.primitive.EncryptedPrivateKeyInfo; --import org.mozilla.jss.pkix.primitive.PrivateKeyInfo; - import org.mozilla.jss.util.Password; - -+import netscape.security.pkcs.PKCS12; -+import netscape.security.pkcs.PKCS12Util; -+ - /** - * Tool for creating PKCS12 file - * -@@ -62,262 +39,174 @@ import org.mozilla.jss.util.Password; - */ - public class PKCS12Export { - -- private static boolean debugMode = false; -+ private static Logger logger = Logger.getLogger(PKCS12Export.class.getName()); - -- private static void debug(String s) { -- if (debugMode) -- System.out.println("PKCS12Export debug: " + s); -+ String databaseDirectory; -+ String databasePasswordFilename; -+ -+ String pkcs12PasswordFilename; -+ String pkcs12OutputFilename; -+ -+ public String getDatabaseDirectory() { -+ return databaseDirectory; -+ } -+ -+ public void setDatabaseDirectory(String databaseDirectory) { -+ this.databaseDirectory = databaseDirectory; -+ } -+ public String getDatabasePasswordFilename() { -+ return databasePasswordFilename; -+ } -+ -+ public void setDatabasePasswordFilename(String databasePasswordFilename) { -+ this.databasePasswordFilename = databasePasswordFilename; -+ } -+ -+ public String getPkcs12PasswordFilename() { -+ return pkcs12PasswordFilename; -+ } -+ -+ public void setPkcs12PasswordFilename(String pkcs12PasswordFilename) { -+ this.pkcs12PasswordFilename = pkcs12PasswordFilename; -+ } -+ -+ public String getPkcs12OutputFilename() { -+ return pkcs12OutputFilename; -+ } -+ -+ public void setPkcs12OutputFilename(String pkcs12OutputFilename) { -+ this.pkcs12OutputFilename = pkcs12OutputFilename; -+ } -+ -+ public void initDatabase() throws Exception { -+ -+ logger.info("Initializing database in " + databaseDirectory); -+ -+ CryptoManager.InitializationValues vals = -+ new CryptoManager.InitializationValues( -+ databaseDirectory, "", "", "secmod.db"); -+ CryptoManager.initialize(vals); -+ -+ CryptoManager cm = CryptoManager.getInstance(); -+ CryptoToken token = cm.getInternalKeyStorageToken(); -+ -+ logger.info("Reading database password from " + databasePasswordFilename); -+ -+ String line; -+ try (BufferedReader in = new BufferedReader(new FileReader(databasePasswordFilename))) { -+ line = in.readLine(); -+ if (line == null) { -+ line = ""; -+ } -+ } -+ Password password = new Password(line.toCharArray()); -+ -+ logger.info("Logging into security token"); -+ -+ try { -+ token.login(password); -+ } finally { -+ password.clear(); -+ } -+ } -+ -+ public void exportData() throws Exception { -+ -+ logger.info("Reading PKCS #12 password from " + pkcs12PasswordFilename); -+ -+ String line; -+ try (BufferedReader in = new BufferedReader(new FileReader(pkcs12PasswordFilename))) { -+ line = in.readLine(); -+ if (line == null) { -+ line = ""; -+ } -+ } -+ Password password = new Password(line.toCharArray()); -+ -+ logger.info("Exporting NSS database into " + pkcs12OutputFilename); -+ -+ try { -+ PKCS12Util util = new PKCS12Util(); -+ PKCS12 pkcs12 = new PKCS12(); -+ util.loadFromNSS(pkcs12); -+ util.storeIntoFile(pkcs12, pkcs12OutputFilename, password); -+ -+ } finally { -+ password.clear(); -+ } - } - -- private static void printUsage() { -+ public static void printUsage() { - System.out.println( - "Usage: PKCS12Export -d -p -w -o "); -- System.out.println(""); -+ System.out.println(); - System.out.println("If you want to turn on debug, do the following:"); - System.out.println( - "Usage: PKCS12Export -debug -d -p -w -o "); - } - -- private static byte[] getEncodedKey(org.mozilla.jss.crypto.PrivateKey pkey) { -- try { -- CryptoManager cm = CryptoManager.getInstance(); -- CryptoToken token = cm.getInternalKeyStorageToken(); -- KeyGenerator kg = token.getKeyGenerator(KeyGenAlgorithm.DES3); -- SymmetricKey sk = kg.generate(); -- KeyWrapper wrapper = token.getKeyWrapper(KeyWrapAlgorithm.DES3_CBC_PAD); -- byte iv[] = { 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 }; -- IVParameterSpec param = new IVParameterSpec(iv); -- wrapper.initWrap(sk, param); -- byte[] enckey = wrapper.wrap(pkey); -- Cipher c = token.getCipherContext(EncryptionAlgorithm.DES3_CBC_PAD); -- c.initDecrypt(sk, param); -- byte[] recovered = c.doFinal(enckey); -- return recovered; -- } catch (Exception e) { -- debug("PKCS12Export getEncodedKey: Exception=" + e.toString()); -- System.exit(1); -- } -+ public static void main(String args[]) throws Exception { - -- return null; -- } -- -- private static void addKeyBag(org.mozilla.jss.crypto.PrivateKey pkey, X509Certificate x509cert, -- Password pass, byte[] localKeyId, SEQUENCE safeContents) { -- try { -- PasswordConverter passConverter = new PasswordConverter(); -- byte salt[] = { 0x01, 0x01, 0x01, 0x01 }; -- byte[] priData = getEncodedKey(pkey); -- -- PrivateKeyInfo pki = (PrivateKeyInfo) -- ASN1Util.decode(PrivateKeyInfo.getTemplate(), priData); -- ASN1Value key = EncryptedPrivateKeyInfo.createPBE( -- PBEAlgorithm.PBE_SHA1_DES3_CBC, -- pass, salt, 1, passConverter, pki); -- SET keyAttrs = createBagAttrs( -- x509cert.getSubjectDN().toString(), localKeyId); -- SafeBag keyBag = new SafeBag(SafeBag.PKCS8_SHROUDED_KEY_BAG, -- key, keyAttrs); -- safeContents.addElement(keyBag); -- } catch (Exception e) { -- debug("PKCS12Export addKeyBag: Exception=" + e.toString()); -- System.exit(1); -- } -- } -- -- private static byte[] addCertBag(X509Certificate x509cert, String nickname, -- SEQUENCE safeContents) throws IOException { -- byte[] localKeyId = null; -- try { -- ASN1Value cert = new OCTET_STRING(x509cert.getEncoded()); -- localKeyId = createLocalKeyId(x509cert); -- SET certAttrs = null; -- if (nickname != null) -- certAttrs = createBagAttrs(nickname, localKeyId); -- SafeBag certBag = new SafeBag(SafeBag.CERT_BAG, -- new CertBag(CertBag.X509_CERT_TYPE, cert), certAttrs); -- safeContents.addElement(certBag); -- } catch (Exception e) { -- debug("PKCS12Export addCertBag: " + e.toString()); -- System.exit(1); -- } -- -- return localKeyId; -- } -- -- private static byte[] createLocalKeyId(X509Certificate cert) { -- try { -- // SHA1 hash of the X509Cert der encoding -- byte certDer[] = cert.getEncoded(); -- -- MessageDigest md = MessageDigest.getInstance("SHA"); -- -- md.update(certDer); -- return md.digest(); -- } catch (Exception e) { -- debug("PKCS12Export createLocalKeyId: Exception: " + e.toString()); -- System.exit(1); -- } -- -- return null; -- } -- -- private static SET createBagAttrs(String nickName, byte localKeyId[]) -- throws IOException { -- try { -- SET attrs = new SET(); -- SEQUENCE nickNameAttr = new SEQUENCE(); -- -- nickNameAttr.addElement(SafeBag.FRIENDLY_NAME); -- SET nickNameSet = new SET(); -- -- nickNameSet.addElement(new BMPString(nickName)); -- nickNameAttr.addElement(nickNameSet); -- attrs.addElement(nickNameAttr); -- SEQUENCE localKeyAttr = new SEQUENCE(); -- -- localKeyAttr.addElement(SafeBag.LOCAL_KEY_ID); -- SET localKeySet = new SET(); -- -- localKeySet.addElement(new OCTET_STRING(localKeyId)); -- localKeyAttr.addElement(localKeySet); -- attrs.addElement(localKeyAttr); -- return attrs; -- } catch (Exception e) { -- debug("PKCS12Export createBagAttrs: Exception=" + e.toString()); -- System.exit(1); -- } -- -- return null; -- } -- -- public static void main(String args[]) { - if (args.length < 8) { - printUsage(); - System.exit(1); - } - -- String pwdfile = null; -- String dir = null; -- String pk12pwdfile = null; -- String pk12output = null; -+ boolean debug = false; -+ String databaseDirectory = null; -+ String databasePasswordFilename = null; -+ String pkcs12PasswordFilename = null; -+ String pkcs12OutputFilename = null; -+ -+ // TODO: get parameters using getopt -+ - for (int i = 0; i < args.length; i++) { - if (args[i].equals("-d")) { -- dir = args[i + 1]; -+ databaseDirectory = args[i + 1]; -+ - } else if (args[i].equals("-p")) { -- pwdfile = args[i + 1]; -+ databasePasswordFilename = args[i + 1]; -+ - } else if (args[i].equals("-s")) { - // snickname = args[i + 1]; -+ - } else if (args[i].equals("-w")) { -- pk12pwdfile = args[i + 1]; -+ pkcs12PasswordFilename = args[i + 1]; -+ - } else if (args[i].equals("-o")) { -- pk12output = args[i + 1]; -+ pkcs12OutputFilename = args[i + 1]; -+ - } else if (args[i].equals("-debug")) { -- debugMode = true; -+ debug = true; - } - } - -- debug("The directory for certdb/keydb is " + dir); -- debug("The password file for keydb is " + pwdfile); -- -- // get password -- String pwd = null; -- BufferedReader in = null; -- try { -- in = new BufferedReader(new FileReader(pwdfile)); -- pwd = in.readLine(); -- if (pwd == null) { -- pwd = ""; -- } -- } catch (Exception e) { -- debug("Failed to read the keydb password from the file. Exception: " + e.toString()); -- System.exit(1); -- } finally { -- if (in != null) { -- try { -- in.close(); -- } catch (IOException e) { -- e.printStackTrace(); -- } -- } -+ if (debug) { -+ Logger.getLogger("org.dogtagpki").setLevel(Level.FINE); -+ Logger.getLogger("com.netscape").setLevel(Level.FINE); -+ Logger.getLogger("netscape").setLevel(Level.FINE); - } -- String pk12pwd = null; - -- try { -- in = new BufferedReader(new FileReader(pk12pwdfile)); -- pk12pwd = in.readLine(); -- if (pk12pwd == null) { -- pk12pwd = ""; -- } -- } catch (Exception e) { -- debug("Failed to read the keydb password from the file. Exception: " + e.toString()); -- System.exit(1); -- } finally { -- if (in != null) { -- try { -- in.close(); -- } catch (IOException e) { -- e.printStackTrace(); -- } -- } -- } -+ // TODO: validate parameters - -- CryptoManager cm = null; - try { -- CryptoManager.InitializationValues vals = -- new CryptoManager.InitializationValues(dir, "", "", "secmod.db"); -- CryptoManager.initialize(vals); -- cm = CryptoManager.getInstance(); -- } catch (Exception e) { -- debug("Failed to initialize the certdb."); -- System.exit(1); -- } -+ PKCS12Export tool = new PKCS12Export(); -+ tool.setDatabaseDirectory(databaseDirectory); -+ tool.setDatabasePasswordFilename(databasePasswordFilename); -+ tool.setPkcs12PasswordFilename(pkcs12PasswordFilename); -+ tool.setPkcs12OutputFilename(pkcs12OutputFilename); - -- SEQUENCE encSafeContents = new SEQUENCE(); -- SEQUENCE safeContents = new SEQUENCE(); -- try { -- CryptoToken token = cm.getInternalKeyStorageToken(); -- Password pass = new Password(pwd.toCharArray()); -- token.login(pass); -- CryptoStore store = token.getCryptoStore(); -- X509Certificate[] certs = store.getCertificates(); -- debug("Number of user certificates = " + certs.length); -- Password pass12 = new Password(pk12pwd.toCharArray()); -- for (int i = 0; i < certs.length; i++) { -- String nickname = certs[i].getNickname(); -- debug("Certificate nickname = " + nickname); -- org.mozilla.jss.crypto.PrivateKey prikey = null; -- try { -- prikey = cm.findPrivKeyByCert(certs[i]); -- } catch (Exception e) { -- debug("PKCS12Export Exception: " + e.toString()); -- } -+ tool.initDatabase(); -+ tool.exportData(); - -- if (prikey == null) { -- debug("Private key is null"); -- addCertBag(certs[i], null, safeContents); -- } else { -- debug("Private key is not null"); -- byte localKeyId[] = -- addCertBag(certs[i], nickname, safeContents); -- addKeyBag(prikey, certs[i], pass12, localKeyId, encSafeContents); -- } -- } -+ System.out.println("Export complete."); - -- AuthenticatedSafes authSafes = new AuthenticatedSafes(); -- authSafes.addSafeContents(safeContents); -- authSafes.addSafeContents(encSafeContents); -- PFX pfx = new PFX(authSafes); -- pfx.computeMacData(pass12, null, 5); -- ByteArrayOutputStream bos = new ByteArrayOutputStream(); -- pfx.encode(bos); -- FileOutputStream fos = new FileOutputStream(pk12output); -- fos.write(bos.toByteArray()); -- fos.flush(); -- fos.close(); -- pass.clear(); -- pass12.clear(); - } catch (Exception e) { -- debug("PKCS12Export Exception: " + e.toString()); -+ if (debug) { -+ logger.log(Level.SEVERE, "Unable to export PKCS #12 file", e); -+ } else { -+ logger.severe("Unable to export PKCS #12 file: " + e.getMessage()); -+ } - System.exit(1); - } - } -diff --git a/base/java-tools/src/com/netscape/cmstools/cli/MainCLI.java b/base/java-tools/src/com/netscape/cmstools/cli/MainCLI.java -index 4d63d9bc12c012bc1db207f7a31a0b50cf5bc2af..1e38113ca13e6c7dc2ff7216ff8f702db5586b24 100644 ---- a/base/java-tools/src/com/netscape/cmstools/cli/MainCLI.java -+++ b/base/java-tools/src/com/netscape/cmstools/cli/MainCLI.java -@@ -46,6 +46,7 @@ import com.netscape.cmstools.cert.CertCLI; - import com.netscape.cmstools.client.ClientCLI; - import com.netscape.cmstools.group.GroupCLI; - import com.netscape.cmstools.key.KeyCLI; -+import com.netscape.cmstools.pkcs12.PKCS12CLI; - import com.netscape.cmstools.system.SecurityDomainCLI; - import com.netscape.cmstools.user.UserCLI; - -@@ -82,6 +83,8 @@ public class MainCLI extends CLI { - addModule(new TKSCLI(this)); - addModule(new TPSCLI(this)); - -+ addModule(new PKCS12CLI(this)); -+ - createOptions(); - } - -diff --git a/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12CLI.java b/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12CLI.java -new file mode 100644 -index 0000000000000000000000000000000000000000..b841ec0ee16ebdf3d3a66e1fe1fbdc0d4971b909 ---- /dev/null -+++ b/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12CLI.java -@@ -0,0 +1,47 @@ -+// --- BEGIN COPYRIGHT BLOCK --- -+// 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. -+// -+// (C) 2016 Red Hat, Inc. -+// All rights reserved. -+// --- END COPYRIGHT BLOCK --- -+ -+package com.netscape.cmstools.pkcs12; -+ -+import com.netscape.cmstools.cli.CLI; -+import com.netscape.cmstools.cli.MainCLI; -+ -+/** -+ * @author Endi S. Dewata -+ */ -+public class PKCS12CLI extends CLI { -+ -+ public PKCS12CLI(CLI parent) { -+ super("pkcs12", "PKCS #12 utilities", parent); -+ -+ addModule(new PKCS12CertCLI(this)); -+ addModule(new PKCS12ExportCLI(this)); -+ addModule(new PKCS12ImportCLI(this)); -+ addModule(new PKCS12KeyCLI(this)); -+ } -+ -+ public String getFullName() { -+ if (parent instanceof MainCLI) { -+ // do not include MainCLI's name -+ return name; -+ } else { -+ return parent.getFullName() + "-" + name; -+ } -+ } -+ -+} -diff --git a/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12CertAddCLI.java b/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12CertAddCLI.java -new file mode 100644 -index 0000000000000000000000000000000000000000..48e4907cf7c21604465cfb303c6d35edd9489f60 ---- /dev/null -+++ b/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12CertAddCLI.java -@@ -0,0 +1,167 @@ -+// --- BEGIN COPYRIGHT BLOCK --- -+// 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. -+// -+// (C) 2016 Red Hat, Inc. -+// All rights reserved. -+// --- END COPYRIGHT BLOCK --- -+ -+package com.netscape.cmstools.pkcs12; -+ -+import java.io.BufferedReader; -+import java.io.File; -+import java.io.FileReader; -+import java.util.logging.Level; -+import java.util.logging.Logger; -+ -+import org.apache.commons.cli.CommandLine; -+import org.apache.commons.cli.Option; -+import org.apache.commons.cli.ParseException; -+import org.mozilla.jss.util.Password; -+ -+import com.netscape.cmstools.cli.CLI; -+import com.netscape.cmstools.cli.MainCLI; -+ -+import netscape.security.pkcs.PKCS12; -+import netscape.security.pkcs.PKCS12Util; -+ -+/** -+ * @author Endi S. Dewata -+ */ -+public class PKCS12CertAddCLI extends CLI { -+ -+ public PKCS12CertAddCLI(PKCS12CertCLI certCLI) { -+ super("add", "Add certificate into PKCS #12 file", certCLI); -+ -+ createOptions(); -+ } -+ -+ public void printHelp() { -+ formatter.printHelp(getFullName() + " [OPTIONS...]", options); -+ } -+ -+ public void createOptions() { -+ Option option = new Option(null, "pkcs12-file", true, "PKCS #12 file"); -+ option.setArgName("path"); -+ options.addOption(option); -+ -+ option = new Option(null, "pkcs12-password", true, "PKCS #12 password"); -+ option.setArgName("password"); -+ options.addOption(option); -+ -+ option = new Option(null, "pkcs12-password-file", true, "PKCS #12 password file"); -+ option.setArgName("path"); -+ options.addOption(option); -+ -+ options.addOption(null, "new-file", false, "Create a new PKCS #12 file"); -+ options.addOption(null, "no-trust-flags", false, "Do not include trust flags"); -+ -+ options.addOption("v", "verbose", false, "Run in verbose mode."); -+ options.addOption(null, "debug", false, "Run in debug mode."); -+ options.addOption(null, "help", false, "Show help message."); -+ } -+ -+ public void execute(String[] args) throws Exception { -+ -+ CommandLine cmd = null; -+ -+ try { -+ cmd = parser.parse(options, args); -+ } catch (ParseException e) { -+ System.err.println("Error: " + e.getMessage()); -+ printHelp(); -+ System.exit(-1); -+ } -+ -+ if (cmd.hasOption("help")) { -+ printHelp(); -+ System.exit(0); -+ } -+ -+ if (cmd.hasOption("verbose")) { -+ Logger.getLogger("org.dogtagpki").setLevel(Level.INFO); -+ Logger.getLogger("com.netscape").setLevel(Level.INFO); -+ Logger.getLogger("netscape").setLevel(Level.INFO); -+ -+ } else if (cmd.hasOption("debug")) { -+ Logger.getLogger("org.dogtagpki").setLevel(Level.FINE); -+ Logger.getLogger("com.netscape").setLevel(Level.FINE); -+ Logger.getLogger("netscape").setLevel(Level.FINE); -+ } -+ -+ String[] cmdArgs = cmd.getArgs(); -+ -+ if (cmdArgs.length == 0) { -+ System.err.println("Error: Missing certificate nickname."); -+ printHelp(); -+ System.exit(-1); -+ } -+ -+ String nickname = cmdArgs[0]; -+ -+ String filename = cmd.getOptionValue("pkcs12-file"); -+ -+ if (filename == null) { -+ System.err.println("Error: Missing PKCS #12 file."); -+ printHelp(); -+ System.exit(-1); -+ } -+ -+ String passwordString = cmd.getOptionValue("pkcs12-password"); -+ -+ if (passwordString == null) { -+ -+ String passwordFile = cmd.getOptionValue("pkcs12-password-file"); -+ if (passwordFile != null) { -+ try (BufferedReader in = new BufferedReader(new FileReader(passwordFile))) { -+ passwordString = in.readLine(); -+ } -+ } -+ } -+ -+ if (passwordString == null) { -+ System.err.println("Error: Missing PKCS #12 password."); -+ printHelp(); -+ System.exit(-1); -+ } -+ -+ Password password = new Password(passwordString.toCharArray()); -+ -+ boolean newFile = cmd.hasOption("new-file"); -+ boolean includeTrustFlags = !cmd.hasOption("no-trust-flags"); -+ -+ try { -+ PKCS12Util util = new PKCS12Util(); -+ util.setTrustFlagsEnabled(includeTrustFlags); -+ -+ PKCS12 pkcs12; -+ -+ if (newFile || !new File(filename).exists()) { -+ // if new file requested or file does not exist, create a new file -+ pkcs12 = new PKCS12(); -+ -+ } else { -+ // otherwise, add into the existing file -+ pkcs12 = util.loadFromFile(filename, password); -+ } -+ -+ util.loadCertFromNSS(pkcs12, nickname); -+ util.storeIntoFile(pkcs12, filename, password); -+ -+ } finally { -+ password.clear(); -+ } -+ -+ MainCLI.printMessage("Added certificate \"" + nickname + "\""); -+ } -+} -diff --git a/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12CertCLI.java b/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12CertCLI.java -new file mode 100644 -index 0000000000000000000000000000000000000000..fe7092c00ef3e4ee202d47b479ec22caea5f36c1 ---- /dev/null -+++ b/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12CertCLI.java -@@ -0,0 +1,59 @@ -+// --- BEGIN COPYRIGHT BLOCK --- -+// 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. -+// -+// (C) 2016 Red Hat, Inc. -+// All rights reserved. -+// --- END COPYRIGHT BLOCK --- -+ -+package com.netscape.cmstools.pkcs12; -+ -+import java.math.BigInteger; -+ -+import com.netscape.certsrv.dbs.certdb.CertId; -+import com.netscape.cmstools.cli.CLI; -+ -+import netscape.security.pkcs.PKCS12; -+import netscape.security.pkcs.PKCS12CertInfo; -+ -+/** -+ * @author Endi S. Dewata -+ */ -+public class PKCS12CertCLI extends CLI { -+ -+ public PKCS12CertCLI(PKCS12CLI parent) { -+ super("cert", "PKCS #12 certificate management commands", parent); -+ -+ addModule(new PKCS12CertAddCLI(this)); -+ addModule(new PKCS12CertExportCLI(this)); -+ addModule(new PKCS12CertFindCLI(this)); -+ addModule(new PKCS12CertRemoveCLI(this)); -+ } -+ -+ public static void printCertInfo(PKCS12 pkcs12, PKCS12CertInfo certInfo) throws Exception { -+ -+ BigInteger id = certInfo.getID(); -+ System.out.println(" Certificate ID: " + id.toString(16)); -+ -+ System.out.println(" Serial Number: " + new CertId(certInfo.getCert().getSerialNumber()).toHexString()); -+ System.out.println(" Nickname: " + certInfo.getNickname()); -+ System.out.println(" Subject DN: " + certInfo.getCert().getSubjectDN()); -+ System.out.println(" Issuer DN: " + certInfo.getCert().getIssuerDN()); -+ -+ if (certInfo.getTrustFlags() != null) { -+ System.out.println(" Trust Flags: " + certInfo.getTrustFlags()); -+ } -+ -+ System.out.println(" Has Key: " + (pkcs12.getKeyInfoByID(id) != null)); -+ } -+} -diff --git a/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12CertExportCLI.java b/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12CertExportCLI.java -new file mode 100644 -index 0000000000000000000000000000000000000000..8fb526d489fea7b482e8af489879f7657f816996 ---- /dev/null -+++ b/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12CertExportCLI.java -@@ -0,0 +1,207 @@ -+// --- BEGIN COPYRIGHT BLOCK --- -+// 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. -+// -+// (C) 2016 Red Hat, Inc. -+// All rights reserved. -+// --- END COPYRIGHT BLOCK --- -+ -+package com.netscape.cmstools.pkcs12; -+ -+import java.io.BufferedReader; -+import java.io.FileOutputStream; -+import java.io.FileReader; -+import java.io.PrintStream; -+import java.math.BigInteger; -+import java.util.ArrayList; -+import java.util.Collection; -+import java.util.logging.Level; -+import java.util.logging.Logger; -+ -+import org.apache.commons.cli.CommandLine; -+import org.apache.commons.cli.Option; -+import org.apache.commons.cli.ParseException; -+import org.mozilla.jss.util.Password; -+ -+import com.netscape.cmstools.cli.CLI; -+import com.netscape.cmsutil.util.Utils; -+ -+import netscape.security.pkcs.PKCS12; -+import netscape.security.pkcs.PKCS12CertInfo; -+import netscape.security.pkcs.PKCS12Util; -+import netscape.security.x509.X509CertImpl; -+ -+/** -+ * @author Endi S. Dewata -+ */ -+public class PKCS12CertExportCLI extends CLI { -+ -+ public PKCS12CertExportCLI(PKCS12CertCLI certCLI) { -+ super("export", "Export certificate from PKCS #12 file", certCLI); -+ -+ createOptions(); -+ } -+ -+ public void printHelp() { -+ formatter.printHelp(getFullName() + " [OPTIONS...] [nickname]", options); -+ } -+ -+ public void createOptions() { -+ Option option = new Option(null, "pkcs12-file", true, "PKCS #12 file"); -+ option.setArgName("path"); -+ options.addOption(option); -+ -+ option = new Option(null, "pkcs12-password", true, "PKCS #12 password"); -+ option.setArgName("password"); -+ options.addOption(option); -+ -+ option = new Option(null, "pkcs12-password-file", true, "PKCS #12 password file"); -+ option.setArgName("path"); -+ options.addOption(option); -+ -+ option = new Option(null, "cert-file", true, "Certificate file"); -+ option.setArgName("path"); -+ options.addOption(option); -+ -+ option = new Option(null, "cert-id", true, "Certificate ID to export"); -+ option.setArgName("ID"); -+ options.addOption(option); -+ -+ options.addOption("v", "verbose", false, "Run in verbose mode."); -+ options.addOption(null, "debug", false, "Run in debug mode."); -+ options.addOption(null, "help", false, "Show help message."); -+ } -+ -+ public void execute(String[] args) throws Exception { -+ -+ CommandLine cmd = null; -+ -+ try { -+ cmd = parser.parse(options, args); -+ } catch (ParseException e) { -+ System.err.println("Error: " + e.getMessage()); -+ printHelp(); -+ System.exit(-1); -+ } -+ -+ if (cmd.hasOption("help")) { -+ printHelp(); -+ System.exit(0); -+ } -+ -+ if (cmd.hasOption("verbose")) { -+ Logger.getLogger("org.dogtagpki").setLevel(Level.INFO); -+ Logger.getLogger("com.netscape").setLevel(Level.INFO); -+ Logger.getLogger("netscape").setLevel(Level.INFO); -+ -+ } else if (cmd.hasOption("debug")) { -+ Logger.getLogger("org.dogtagpki").setLevel(Level.FINE); -+ Logger.getLogger("com.netscape").setLevel(Level.FINE); -+ Logger.getLogger("netscape").setLevel(Level.FINE); -+ } -+ -+ String[] cmdArgs = cmd.getArgs(); -+ String id = cmd.getOptionValue("cert-id"); -+ -+ if (cmdArgs.length < 1 && id == null) { -+ System.err.println("Error: Missing certificate nickname or ID."); -+ printHelp(); -+ System.exit(-1); -+ } -+ -+ if (cmdArgs.length >= 1 && id != null) { -+ System.err.println("Error: Certificate nickname and ID are mutually exclusive."); -+ printHelp(); -+ System.exit(-1); -+ } -+ -+ String nickname = null; -+ BigInteger certID = null; -+ -+ if (cmdArgs.length >= 1) { -+ nickname = cmdArgs[0]; -+ } else { -+ certID = new BigInteger(id, 16); -+ } -+ -+ String pkcs12File = cmd.getOptionValue("pkcs12-file"); -+ -+ if (pkcs12File == null) { -+ System.err.println("Error: Missing PKCS #12 file."); -+ printHelp(); -+ System.exit(-1); -+ } -+ -+ String passwordString = cmd.getOptionValue("pkcs12-password"); -+ -+ if (passwordString == null) { -+ -+ String passwordFile = cmd.getOptionValue("pkcs12-password-file"); -+ if (passwordFile != null) { -+ try (BufferedReader in = new BufferedReader(new FileReader(passwordFile))) { -+ passwordString = in.readLine(); -+ } -+ } -+ } -+ -+ if (passwordString == null) { -+ System.err.println("Error: Missing PKCS #12 password."); -+ printHelp(); -+ System.exit(-1); -+ } -+ -+ Password password = new Password(passwordString.toCharArray()); -+ -+ String certFile = cmd.getOptionValue("cert-file"); -+ -+ if (certFile == null) { -+ System.err.println("Error: Missing certificate file."); -+ printHelp(); -+ System.exit(-1); -+ } -+ -+ try { -+ PKCS12Util util = new PKCS12Util(); -+ PKCS12 pkcs12 = util.loadFromFile(pkcs12File, password); -+ -+ Collection certInfos = new ArrayList(); -+ -+ if (nickname != null) { -+ certInfos.addAll(pkcs12.getCertInfosByNickname(nickname)); -+ -+ } else { -+ PKCS12CertInfo certInfo = pkcs12.getCertInfoByID(certID); -+ if (certInfo != null) { -+ certInfos.add(certInfo); -+ } -+ } -+ -+ if (certInfos.isEmpty()) { -+ System.err.println("Error: Certificate not found."); -+ System.exit(-1); -+ } -+ -+ try (PrintStream os = new PrintStream(new FileOutputStream(certFile))) { -+ for (PKCS12CertInfo certInfo : certInfos) { -+ X509CertImpl cert = certInfo.getCert(); -+ os.println("-----BEGIN CERTIFICATE-----"); -+ os.print(Utils.base64encode(cert.getEncoded())); -+ os.println("-----END CERTIFICATE-----"); -+ } -+ } -+ -+ } finally { -+ password.clear(); -+ } -+ } -+} -diff --git a/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12CertFindCLI.java b/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12CertFindCLI.java -new file mode 100644 -index 0000000000000000000000000000000000000000..9bb4ad3ba2113e2426e8d9a250c0041647e1e562 ---- /dev/null -+++ b/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12CertFindCLI.java -@@ -0,0 +1,162 @@ -+// --- BEGIN COPYRIGHT BLOCK --- -+// 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. -+// -+// (C) 2016 Red Hat, Inc. -+// All rights reserved. -+// --- END COPYRIGHT BLOCK --- -+ -+package com.netscape.cmstools.pkcs12; -+ -+import java.io.BufferedReader; -+import java.io.FileReader; -+import java.util.Collection; -+import java.util.logging.Level; -+import java.util.logging.Logger; -+ -+import org.apache.commons.cli.CommandLine; -+import org.apache.commons.cli.Option; -+import org.apache.commons.cli.ParseException; -+import org.mozilla.jss.util.Password; -+ -+import com.netscape.cmstools.cli.CLI; -+import com.netscape.cmstools.cli.MainCLI; -+ -+import netscape.security.pkcs.PKCS12; -+import netscape.security.pkcs.PKCS12CertInfo; -+import netscape.security.pkcs.PKCS12Util; -+ -+/** -+ * @author Endi S. Dewata -+ */ -+public class PKCS12CertFindCLI extends CLI { -+ -+ public PKCS12CertFindCLI(PKCS12CertCLI certCLI) { -+ super("find", "Find certificates in PKCS #12 file", certCLI); -+ -+ createOptions(); -+ } -+ -+ public void printHelp() { -+ formatter.printHelp(getFullName() + " [OPTIONS...]", options); -+ } -+ -+ public void createOptions() { -+ Option option = new Option(null, "pkcs12-file", true, "PKCS #12 file"); -+ option.setArgName("path"); -+ options.addOption(option); -+ -+ option = new Option(null, "pkcs12-password", true, "PKCS #12 password"); -+ option.setArgName("password"); -+ options.addOption(option); -+ -+ option = new Option(null, "pkcs12-password-file", true, "PKCS #12 password file"); -+ option.setArgName("path"); -+ options.addOption(option); -+ -+ options.addOption("v", "verbose", false, "Run in verbose mode."); -+ options.addOption(null, "debug", false, "Run in debug mode."); -+ options.addOption(null, "help", false, "Show help message."); -+ } -+ -+ public void execute(String[] args) throws Exception { -+ -+ CommandLine cmd = null; -+ -+ try { -+ cmd = parser.parse(options, args); -+ } catch (ParseException e) { -+ System.err.println("Error: " + e.getMessage()); -+ printHelp(); -+ System.exit(-1); -+ } -+ -+ if (cmd.hasOption("help")) { -+ printHelp(); -+ System.exit(0); -+ } -+ -+ if (cmd.hasOption("verbose")) { -+ Logger.getLogger("org.dogtagpki").setLevel(Level.INFO); -+ Logger.getLogger("com.netscape").setLevel(Level.INFO); -+ Logger.getLogger("netscape").setLevel(Level.INFO); -+ -+ } else if (cmd.hasOption("debug")) { -+ Logger.getLogger("org.dogtagpki").setLevel(Level.FINE); -+ Logger.getLogger("com.netscape").setLevel(Level.FINE); -+ Logger.getLogger("netscape").setLevel(Level.FINE); -+ } -+ -+ String[] cmdArgs = cmd.getArgs(); -+ -+ if (cmdArgs.length != 0) { -+ System.err.println("Error: Too many arguments specified."); -+ printHelp(); -+ System.exit(-1); -+ } -+ -+ String filename = cmd.getOptionValue("pkcs12-file"); -+ -+ if (filename == null) { -+ System.err.println("Error: Missing PKCS #12 file."); -+ printHelp(); -+ System.exit(-1); -+ } -+ -+ String passwordString = cmd.getOptionValue("pkcs12-password"); -+ -+ if (passwordString == null) { -+ -+ String passwordFile = cmd.getOptionValue("pkcs12-password-file"); -+ if (passwordFile != null) { -+ try (BufferedReader in = new BufferedReader(new FileReader(passwordFile))) { -+ passwordString = in.readLine(); -+ } -+ } -+ } -+ -+ if (passwordString == null) { -+ System.err.println("Error: Missing PKCS #12 password."); -+ printHelp(); -+ System.exit(-1); -+ } -+ -+ Password password = new Password(passwordString.toCharArray()); -+ -+ PKCS12 pkcs12; -+ try { -+ PKCS12Util util = new PKCS12Util(); -+ pkcs12 = util.loadFromFile(filename, password); -+ -+ } finally { -+ password.clear(); -+ } -+ -+ Collection certInfos = pkcs12.getCertInfos(); -+ -+ MainCLI.printMessage(certInfos.size() + " entries found"); -+ if (certInfos.size() == 0) return; -+ -+ boolean first = true; -+ -+ for (PKCS12CertInfo certInfo : certInfos) { -+ if (first) { -+ first = false; -+ } else { -+ System.out.println(); -+ } -+ -+ PKCS12CertCLI.printCertInfo(pkcs12, certInfo); -+ } -+ } -+} -diff --git a/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12CertRemoveCLI.java b/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12CertRemoveCLI.java -new file mode 100644 -index 0000000000000000000000000000000000000000..8f7f11398c8fd9760ca0e709d19fd0af2a4b689b ---- /dev/null -+++ b/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12CertRemoveCLI.java -@@ -0,0 +1,149 @@ -+// --- BEGIN COPYRIGHT BLOCK --- -+// 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. -+// -+// (C) 2016 Red Hat, Inc. -+// All rights reserved. -+// --- END COPYRIGHT BLOCK --- -+ -+package com.netscape.cmstools.pkcs12; -+ -+import java.io.BufferedReader; -+import java.io.FileReader; -+import java.util.logging.Level; -+import java.util.logging.Logger; -+ -+import org.apache.commons.cli.CommandLine; -+import org.apache.commons.cli.Option; -+import org.apache.commons.cli.ParseException; -+import org.mozilla.jss.util.Password; -+ -+import com.netscape.cmstools.cli.CLI; -+import com.netscape.cmstools.cli.MainCLI; -+ -+import netscape.security.pkcs.PKCS12; -+import netscape.security.pkcs.PKCS12Util; -+ -+/** -+ * @author Endi S. Dewata -+ */ -+public class PKCS12CertRemoveCLI extends CLI { -+ -+ public PKCS12CertRemoveCLI(PKCS12CertCLI certCLI) { -+ super("del", "Remove certificate from PKCS #12 file", certCLI); -+ -+ createOptions(); -+ } -+ -+ public void printHelp() { -+ formatter.printHelp(getFullName() + " [OPTIONS...]", options); -+ } -+ -+ public void createOptions() { -+ Option option = new Option(null, "pkcs12-file", true, "PKCS #12 file"); -+ option.setArgName("path"); -+ options.addOption(option); -+ -+ option = new Option(null, "pkcs12-password", true, "PKCS #12 password"); -+ option.setArgName("password"); -+ options.addOption(option); -+ -+ option = new Option(null, "pkcs12-password-file", true, "PKCS #12 password file"); -+ option.setArgName("path"); -+ options.addOption(option); -+ -+ options.addOption("v", "verbose", false, "Run in verbose mode."); -+ options.addOption(null, "debug", false, "Run in debug mode."); -+ options.addOption(null, "help", false, "Show help message."); -+ } -+ -+ public void execute(String[] args) throws Exception { -+ -+ CommandLine cmd = null; -+ -+ try { -+ cmd = parser.parse(options, args); -+ } catch (ParseException e) { -+ System.err.println("Error: " + e.getMessage()); -+ printHelp(); -+ System.exit(-1); -+ } -+ -+ if (cmd.hasOption("help")) { -+ printHelp(); -+ System.exit(0); -+ } -+ -+ if (cmd.hasOption("verbose")) { -+ Logger.getLogger("org.dogtagpki").setLevel(Level.INFO); -+ Logger.getLogger("com.netscape").setLevel(Level.INFO); -+ Logger.getLogger("netscape").setLevel(Level.INFO); -+ -+ } else if (cmd.hasOption("debug")) { -+ Logger.getLogger("org.dogtagpki").setLevel(Level.FINE); -+ Logger.getLogger("com.netscape").setLevel(Level.FINE); -+ Logger.getLogger("netscape").setLevel(Level.FINE); -+ } -+ -+ String[] cmdArgs = cmd.getArgs(); -+ -+ if (cmdArgs.length == 0) { -+ System.err.println("Error: Missing certificate nickname."); -+ printHelp(); -+ System.exit(-1); -+ } -+ -+ String nickname = cmdArgs[0]; -+ -+ String filename = cmd.getOptionValue("pkcs12-file"); -+ -+ if (filename == null) { -+ System.err.println("Error: Missing PKCS #12 file."); -+ printHelp(); -+ System.exit(-1); -+ } -+ -+ String passwordString = cmd.getOptionValue("pkcs12-password"); -+ -+ if (passwordString == null) { -+ -+ String passwordFile = cmd.getOptionValue("pkcs12-password-file"); -+ if (passwordFile != null) { -+ try (BufferedReader in = new BufferedReader(new FileReader(passwordFile))) { -+ passwordString = in.readLine(); -+ } -+ } -+ } -+ -+ if (passwordString == null) { -+ System.err.println("Error: Missing PKCS #12 password."); -+ printHelp(); -+ System.exit(-1); -+ } -+ -+ Password password = new Password(passwordString.toCharArray()); -+ -+ try { -+ PKCS12Util util = new PKCS12Util(); -+ -+ PKCS12 pkcs12 = util.loadFromFile(filename, password); -+ pkcs12.removeCertInfoByNickname(nickname); -+ util.storeIntoFile(pkcs12, filename, password); -+ -+ } finally { -+ password.clear(); -+ } -+ -+ MainCLI.printMessage("Deleted certificate \"" + nickname + "\""); -+ } -+} -diff --git a/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12ExportCLI.java b/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12ExportCLI.java -new file mode 100644 -index 0000000000000000000000000000000000000000..d42c449b40c1b1fc97e921f9635b9e6a8a1e922b ---- /dev/null -+++ b/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12ExportCLI.java -@@ -0,0 +1,166 @@ -+// --- BEGIN COPYRIGHT BLOCK --- -+// 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. -+// -+// (C) 2016 Red Hat, Inc. -+// All rights reserved. -+// --- END COPYRIGHT BLOCK --- -+package com.netscape.cmstools.pkcs12; -+ -+import java.io.BufferedReader; -+import java.io.File; -+import java.io.FileReader; -+import java.util.logging.Level; -+import java.util.logging.Logger; -+ -+import org.apache.commons.cli.CommandLine; -+import org.apache.commons.cli.Option; -+import org.mozilla.jss.util.Password; -+ -+import com.netscape.cmstools.cli.CLI; -+import com.netscape.cmstools.cli.MainCLI; -+ -+import netscape.security.pkcs.PKCS12; -+import netscape.security.pkcs.PKCS12Util; -+ -+/** -+ * Tool for exporting NSS database into PKCS #12 file -+ */ -+public class PKCS12ExportCLI extends CLI { -+ -+ public PKCS12ExportCLI(PKCS12CLI certCLI) { -+ super("export", "Export NSS database into PKCS #12 file", certCLI); -+ -+ createOptions(); -+ } -+ -+ public void printHelp() { -+ formatter.printHelp(getFullName() + " [OPTIONS...] [nicknames...]", options); -+ } -+ -+ public void createOptions() { -+ Option option = new Option(null, "pkcs12-file", true, "PKCS #12 file"); -+ option.setArgName("path"); -+ options.addOption(option); -+ -+ option = new Option(null, "pkcs12-password", true, "PKCS #12 password"); -+ option.setArgName("password"); -+ options.addOption(option); -+ -+ option = new Option(null, "pkcs12-password-file", true, "PKCS #12 password file"); -+ option.setArgName("path"); -+ options.addOption(option); -+ -+ options.addOption(null, "new-file", false, "Create a new PKCS #12 file"); -+ options.addOption(null, "no-trust-flags", false, "Do not include trust flags"); -+ -+ options.addOption("v", "verbose", false, "Run in verbose mode."); -+ options.addOption(null, "debug", false, "Run in debug mode."); -+ options.addOption(null, "help", false, "Show help message."); -+ } -+ -+ public void execute(String[] args) throws Exception { -+ -+ CommandLine cmd = null; -+ -+ try { -+ cmd = parser.parse(options, args, true); -+ } catch (Exception e) { -+ System.err.println("Error: " + e.getMessage()); -+ printHelp(); -+ System.exit(-1); -+ } -+ -+ if (cmd.hasOption("help")) { -+ printHelp(); -+ System.exit(0); -+ } -+ -+ if (cmd.hasOption("verbose")) { -+ Logger.getLogger("org.dogtagpki").setLevel(Level.INFO); -+ Logger.getLogger("com.netscape").setLevel(Level.INFO); -+ Logger.getLogger("netscape").setLevel(Level.INFO); -+ -+ } else if (cmd.hasOption("debug")) { -+ Logger.getLogger("org.dogtagpki").setLevel(Level.FINE); -+ Logger.getLogger("com.netscape").setLevel(Level.FINE); -+ Logger.getLogger("netscape").setLevel(Level.FINE); -+ } -+ -+ String[] nicknames = cmd.getArgs(); -+ String filename = cmd.getOptionValue("pkcs12-file"); -+ -+ if (filename == null) { -+ System.err.println("Error: Missing PKCS #12 file."); -+ printHelp(); -+ System.exit(-1); -+ } -+ -+ String passwordString = cmd.getOptionValue("pkcs12-password"); -+ -+ if (passwordString == null) { -+ -+ String passwordFile = cmd.getOptionValue("pkcs12-password-file"); -+ if (passwordFile != null) { -+ try (BufferedReader in = new BufferedReader(new FileReader(passwordFile))) { -+ passwordString = in.readLine(); -+ } -+ } -+ } -+ -+ if (passwordString == null) { -+ System.err.println("Error: Missing PKCS #12 password."); -+ printHelp(); -+ System.exit(-1); -+ } -+ -+ Password password = new Password(passwordString.toCharArray()); -+ -+ boolean newFile = cmd.hasOption("new-file"); -+ boolean trustFlagsEnabled = !cmd.hasOption("no-trust-flags"); -+ -+ try { -+ PKCS12Util util = new PKCS12Util(); -+ util.setTrustFlagsEnabled(trustFlagsEnabled); -+ -+ PKCS12 pkcs12; -+ -+ if (newFile || !new File(filename).exists()) { -+ // if new file requested or file does not exist, create a new file -+ pkcs12 = new PKCS12(); -+ -+ } else { -+ // otherwise, export into the existing file -+ pkcs12 = util.loadFromFile(filename, password); -+ } -+ -+ if (nicknames.length == 0) { -+ // load all certificates -+ util.loadFromNSS(pkcs12); -+ -+ } else { -+ // load specified certificates -+ for (String nickname : nicknames) { -+ util.loadCertFromNSS(pkcs12, nickname); -+ } -+ } -+ -+ util.storeIntoFile(pkcs12, filename, password); -+ -+ } finally { -+ password.clear(); -+ } -+ -+ MainCLI.printMessage("Export complete"); -+ } -+} -diff --git a/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12ImportCLI.java b/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12ImportCLI.java -new file mode 100644 -index 0000000000000000000000000000000000000000..ae574d3870a610cdf009b852732644675424a700 ---- /dev/null -+++ b/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12ImportCLI.java -@@ -0,0 +1,153 @@ -+// --- BEGIN COPYRIGHT BLOCK --- -+// 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. -+// -+// (C) 2016 Red Hat, Inc. -+// All rights reserved. -+// --- END COPYRIGHT BLOCK --- -+package com.netscape.cmstools.pkcs12; -+ -+import java.io.BufferedReader; -+import java.io.FileReader; -+import java.util.logging.Level; -+import java.util.logging.Logger; -+ -+import org.apache.commons.cli.CommandLine; -+import org.apache.commons.cli.Option; -+import org.mozilla.jss.util.Password; -+ -+import com.netscape.cmstools.cli.CLI; -+import com.netscape.cmstools.cli.MainCLI; -+ -+import netscape.security.pkcs.PKCS12; -+import netscape.security.pkcs.PKCS12Util; -+ -+/** -+ * Tool for importing NSS database from PKCS #12 file -+ */ -+public class PKCS12ImportCLI extends CLI { -+ -+ public PKCS12ImportCLI(PKCS12CLI certCLI) { -+ super("import", "Import PKCS #12 file into NSS database", certCLI); -+ -+ createOptions(); -+ } -+ -+ public void printHelp() { -+ formatter.printHelp(getFullName() + " [OPTIONS...] [nicknames...]", options); -+ } -+ -+ public void createOptions() { -+ Option option = new Option(null, "pkcs12-file", true, "PKCS #12 file"); -+ option.setArgName("path"); -+ options.addOption(option); -+ -+ option = new Option(null, "pkcs12-password", true, "PKCS #12 password"); -+ option.setArgName("password"); -+ options.addOption(option); -+ -+ option = new Option(null, "pkcs12-password-file", true, "PKCS #12 password file"); -+ option.setArgName("path"); -+ options.addOption(option); -+ -+ options.addOption(null, "no-trust-flags", false, "Do not include trust flags"); -+ -+ options.addOption("v", "verbose", false, "Run in verbose mode."); -+ options.addOption(null, "debug", false, "Run in debug mode."); -+ options.addOption(null, "help", false, "Show help message."); -+ } -+ -+ public void execute(String[] args) throws Exception { -+ -+ CommandLine cmd = null; -+ -+ try { -+ cmd = parser.parse(options, args, true); -+ } catch (Exception e) { -+ System.err.println("Error: " + e.getMessage()); -+ printHelp(); -+ System.exit(-1); -+ } -+ -+ if (cmd.hasOption("help")) { -+ printHelp(); -+ System.exit(0); -+ } -+ -+ if (cmd.hasOption("verbose")) { -+ Logger.getLogger("org.dogtagpki").setLevel(Level.INFO); -+ Logger.getLogger("com.netscape").setLevel(Level.INFO); -+ Logger.getLogger("netscape").setLevel(Level.INFO); -+ -+ } else if (cmd.hasOption("debug")) { -+ Logger.getLogger("org.dogtagpki").setLevel(Level.FINE); -+ Logger.getLogger("com.netscape").setLevel(Level.FINE); -+ Logger.getLogger("netscape").setLevel(Level.FINE); -+ } -+ -+ String[] nicknames = cmd.getArgs(); -+ String filename = cmd.getOptionValue("pkcs12-file"); -+ -+ if (filename == null) { -+ System.err.println("Error: Missing PKCS #12 file."); -+ printHelp(); -+ System.exit(-1); -+ } -+ -+ String passwordString = cmd.getOptionValue("pkcs12-password"); -+ -+ if (passwordString == null) { -+ -+ String passwordFile = cmd.getOptionValue("pkcs12-password-file"); -+ if (passwordFile != null) { -+ try (BufferedReader in = new BufferedReader(new FileReader(passwordFile))) { -+ passwordString = in.readLine(); -+ } -+ } -+ } -+ -+ if (passwordString == null) { -+ System.err.println("Error: Missing PKCS #12 password."); -+ printHelp(); -+ System.exit(-1); -+ } -+ -+ Password password = new Password(passwordString.toCharArray()); -+ -+ boolean trustFlagsEnabled = !cmd.hasOption("no-trust-flags"); -+ -+ try { -+ PKCS12Util util = new PKCS12Util(); -+ util.setTrustFlagsEnabled(trustFlagsEnabled); -+ -+ PKCS12 pkcs12 = util.loadFromFile(filename, password); -+ -+ if (nicknames.length == 0) { -+ // store all certificates -+ util.storeIntoNSS(pkcs12); -+ -+ } else { -+ // load specified certificates -+ for (String nickname : nicknames) { -+ util.storeCertIntoNSS(pkcs12, nickname); -+ } -+ } -+ -+ -+ } finally { -+ password.clear(); -+ } -+ -+ MainCLI.printMessage("Import complete"); -+ } -+} -diff --git a/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12KeyCLI.java b/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12KeyCLI.java -new file mode 100644 -index 0000000000000000000000000000000000000000..fbebddabb918f12c0f94943d1ecf8fe102d01121 ---- /dev/null -+++ b/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12KeyCLI.java -@@ -0,0 +1,43 @@ -+// --- BEGIN COPYRIGHT BLOCK --- -+// 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. -+// -+// (C) 2016 Red Hat, Inc. -+// All rights reserved. -+// --- END COPYRIGHT BLOCK --- -+ -+package com.netscape.cmstools.pkcs12; -+ -+import com.netscape.cmstools.cli.CLI; -+ -+import netscape.security.pkcs.PKCS12KeyInfo; -+ -+/** -+ * @author Endi S. Dewata -+ */ -+public class PKCS12KeyCLI extends CLI { -+ -+ public PKCS12KeyCLI(PKCS12CLI parent) { -+ super("key", "PKCS #12 key management commands", parent); -+ -+ addModule(new PKCS12KeyFindCLI(this)); -+ addModule(new PKCS12KeyRemoveCLI(this)); -+ } -+ -+ public static void printKeyInfo(PKCS12KeyInfo keyInfo) throws Exception { -+ -+ System.out.println(" Key ID: " + keyInfo.getID().toString(16)); -+ System.out.println(" Subject DN: " + keyInfo.getSubjectDN()); -+ System.out.println(" Algorithm: " + keyInfo.getPrivateKeyInfo().getAlgorithm()); -+ } -+} -diff --git a/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12KeyFindCLI.java b/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12KeyFindCLI.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0dc39f470279016373f0d159824d5b8ab7695c32 ---- /dev/null -+++ b/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12KeyFindCLI.java -@@ -0,0 +1,163 @@ -+// --- BEGIN COPYRIGHT BLOCK --- -+// 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. -+// -+// (C) 2016 Red Hat, Inc. -+// All rights reserved. -+// --- END COPYRIGHT BLOCK --- -+ -+package com.netscape.cmstools.pkcs12; -+ -+import java.io.BufferedReader; -+import java.io.FileReader; -+import java.util.Collection; -+import java.util.logging.Level; -+import java.util.logging.Logger; -+ -+import org.apache.commons.cli.CommandLine; -+import org.apache.commons.cli.Option; -+import org.apache.commons.cli.ParseException; -+import org.mozilla.jss.util.Password; -+ -+import com.netscape.cmstools.cli.CLI; -+import com.netscape.cmstools.cli.MainCLI; -+ -+import netscape.security.pkcs.PKCS12; -+import netscape.security.pkcs.PKCS12KeyInfo; -+import netscape.security.pkcs.PKCS12Util; -+ -+/** -+ * @author Endi S. Dewata -+ */ -+public class PKCS12KeyFindCLI extends CLI { -+ -+ public PKCS12KeyFindCLI(PKCS12KeyCLI certCLI) { -+ super("find", "Find keys in PKCS #12 file", certCLI); -+ -+ createOptions(); -+ } -+ -+ public void printHelp() { -+ formatter.printHelp(getFullName() + " [OPTIONS...]", options); -+ } -+ -+ public void createOptions() { -+ Option option = new Option(null, "pkcs12-file", true, "PKCS #12 file"); -+ option.setArgName("path"); -+ options.addOption(option); -+ -+ option = new Option(null, "pkcs12-password", true, "PKCS #12 password"); -+ option.setArgName("password"); -+ options.addOption(option); -+ -+ option = new Option(null, "pkcs12-password-file", true, "PKCS #12 password file"); -+ option.setArgName("path"); -+ options.addOption(option); -+ -+ options.addOption("v", "verbose", false, "Run in verbose mode."); -+ options.addOption(null, "debug", false, "Run in debug mode."); -+ options.addOption(null, "help", false, "Show help message."); -+ } -+ -+ public void execute(String[] args) throws Exception { -+ -+ CommandLine cmd = null; -+ -+ try { -+ cmd = parser.parse(options, args); -+ } catch (ParseException e) { -+ System.err.println("Error: " + e.getMessage()); -+ printHelp(); -+ System.exit(-1); -+ } -+ -+ if (cmd.hasOption("help")) { -+ printHelp(); -+ System.exit(0); -+ } -+ -+ if (cmd.hasOption("verbose")) { -+ Logger.getLogger("org.dogtagpki").setLevel(Level.INFO); -+ Logger.getLogger("com.netscape").setLevel(Level.INFO); -+ Logger.getLogger("netscape").setLevel(Level.INFO); -+ -+ } else if (cmd.hasOption("debug")) { -+ Logger.getLogger("org.dogtagpki").setLevel(Level.FINE); -+ Logger.getLogger("com.netscape").setLevel(Level.FINE); -+ Logger.getLogger("netscape").setLevel(Level.FINE); -+ } -+ -+ String[] cmdArgs = cmd.getArgs(); -+ -+ if (cmdArgs.length != 0) { -+ System.err.println("Error: Too many arguments specified."); -+ printHelp(); -+ System.exit(-1); -+ } -+ -+ String filename = cmd.getOptionValue("pkcs12-file"); -+ -+ if (filename == null) { -+ System.err.println("Error: Missing PKCS #12 file."); -+ printHelp(); -+ System.exit(-1); -+ } -+ -+ String passwordString = cmd.getOptionValue("pkcs12-password"); -+ -+ if (passwordString == null) { -+ -+ String passwordFile = cmd.getOptionValue("pkcs12-password-file"); -+ if (passwordFile != null) { -+ try (BufferedReader in = new BufferedReader(new FileReader(passwordFile))) { -+ passwordString = in.readLine(); -+ } -+ } -+ } -+ -+ if (passwordString == null) { -+ System.err.println("Error: Missing PKCS #12 password."); -+ printHelp(); -+ System.exit(-1); -+ } -+ -+ Password password = new Password(passwordString.toCharArray()); -+ -+ Collection keyInfos; -+ -+ try { -+ PKCS12Util util = new PKCS12Util(); -+ PKCS12 pkcs12 = util.loadFromFile(filename, password); -+ -+ keyInfos = pkcs12.getKeyInfos(); -+ -+ } finally { -+ password.clear(); -+ } -+ -+ MainCLI.printMessage(keyInfos.size() + " entries found"); -+ if (keyInfos.size() == 0) return; -+ -+ boolean first = true; -+ -+ for (PKCS12KeyInfo keyInfo : keyInfos) { -+ if (first) { -+ first = false; -+ } else { -+ System.out.println(); -+ } -+ -+ PKCS12KeyCLI.printKeyInfo(keyInfo); -+ } -+ } -+} -diff --git a/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12KeyRemoveCLI.java b/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12KeyRemoveCLI.java -new file mode 100644 -index 0000000000000000000000000000000000000000..19b368765d0ea93a15b4c2ecd037f545a75b03ea ---- /dev/null -+++ b/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12KeyRemoveCLI.java -@@ -0,0 +1,150 @@ -+// --- BEGIN COPYRIGHT BLOCK --- -+// 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. -+// -+// (C) 2016 Red Hat, Inc. -+// All rights reserved. -+// --- END COPYRIGHT BLOCK --- -+ -+package com.netscape.cmstools.pkcs12; -+ -+import java.io.BufferedReader; -+import java.io.FileReader; -+import java.math.BigInteger; -+import java.util.logging.Level; -+import java.util.logging.Logger; -+ -+import org.apache.commons.cli.CommandLine; -+import org.apache.commons.cli.Option; -+import org.apache.commons.cli.ParseException; -+import org.mozilla.jss.util.Password; -+ -+import com.netscape.cmstools.cli.CLI; -+import com.netscape.cmstools.cli.MainCLI; -+ -+import netscape.security.pkcs.PKCS12; -+import netscape.security.pkcs.PKCS12Util; -+ -+/** -+ * @author Endi S. Dewata -+ */ -+public class PKCS12KeyRemoveCLI extends CLI { -+ -+ public PKCS12KeyRemoveCLI(PKCS12KeyCLI certCLI) { -+ super("del", "Remove key from PKCS #12 file", certCLI); -+ -+ createOptions(); -+ } -+ -+ public void printHelp() { -+ formatter.printHelp(getFullName() + " [OPTIONS...]", options); -+ } -+ -+ public void createOptions() { -+ Option option = new Option(null, "pkcs12-file", true, "PKCS #12 file"); -+ option.setArgName("path"); -+ options.addOption(option); -+ -+ option = new Option(null, "pkcs12-password", true, "PKCS #12 password"); -+ option.setArgName("password"); -+ options.addOption(option); -+ -+ option = new Option(null, "pkcs12-password-file", true, "PKCS #12 password file"); -+ option.setArgName("path"); -+ options.addOption(option); -+ -+ options.addOption("v", "verbose", false, "Run in verbose mode."); -+ options.addOption(null, "debug", false, "Run in debug mode."); -+ options.addOption(null, "help", false, "Show help message."); -+ } -+ -+ public void execute(String[] args) throws Exception { -+ -+ CommandLine cmd = null; -+ -+ try { -+ cmd = parser.parse(options, args); -+ } catch (ParseException e) { -+ System.err.println("Error: " + e.getMessage()); -+ printHelp(); -+ System.exit(-1); -+ } -+ -+ if (cmd.hasOption("help")) { -+ printHelp(); -+ System.exit(0); -+ } -+ -+ if (cmd.hasOption("verbose")) { -+ Logger.getLogger("org.dogtagpki").setLevel(Level.INFO); -+ Logger.getLogger("com.netscape").setLevel(Level.INFO); -+ Logger.getLogger("netscape").setLevel(Level.INFO); -+ -+ } else if (cmd.hasOption("debug")) { -+ Logger.getLogger("org.dogtagpki").setLevel(Level.FINE); -+ Logger.getLogger("com.netscape").setLevel(Level.FINE); -+ Logger.getLogger("netscape").setLevel(Level.FINE); -+ } -+ -+ String[] cmdArgs = cmd.getArgs(); -+ -+ if (cmdArgs.length == 0) { -+ System.err.println("Error: Missing key ID."); -+ printHelp(); -+ System.exit(-1); -+ } -+ -+ BigInteger keyID = new BigInteger(cmdArgs[0], 16); -+ -+ String filename = cmd.getOptionValue("pkcs12-file"); -+ -+ if (filename == null) { -+ System.err.println("Error: Missing PKCS #12 file."); -+ printHelp(); -+ System.exit(-1); -+ } -+ -+ String passwordString = cmd.getOptionValue("pkcs12-password"); -+ -+ if (passwordString == null) { -+ -+ String passwordFile = cmd.getOptionValue("pkcs12-password-file"); -+ if (passwordFile != null) { -+ try (BufferedReader in = new BufferedReader(new FileReader(passwordFile))) { -+ passwordString = in.readLine(); -+ } -+ } -+ } -+ -+ if (passwordString == null) { -+ System.err.println("Error: Missing PKCS #12 password."); -+ printHelp(); -+ System.exit(-1); -+ } -+ -+ Password password = new Password(passwordString.toCharArray()); -+ -+ try { -+ PKCS12Util util = new PKCS12Util(); -+ -+ PKCS12 pkcs12 = util.loadFromFile(filename, password); -+ pkcs12.removeKeyInfoByID(keyID); -+ util.storeIntoFile(pkcs12, filename, password); -+ -+ } finally { -+ password.clear(); -+ } -+ -+ MainCLI.printMessage("Deleted key \"" + keyID.toString(16) + "\""); -+ } -+} -diff --git a/base/java-tools/templates/pki_java_command_wrapper.in b/base/java-tools/templates/pki_java_command_wrapper.in -index 404bcf0a12914f714b59f9e8fe286fd75a42367a..56ca9f1fcbdd95a2e5e2be11e1ff42c0d1f0b22b 100644 ---- a/base/java-tools/templates/pki_java_command_wrapper.in -+++ b/base/java-tools/templates/pki_java_command_wrapper.in -@@ -124,12 +124,17 @@ CP=/usr/share/java/${PRODUCT}/pki-cmsutil.jar:${CP} - CP=/usr/share/java/${PRODUCT}/pki-tools.jar:${CP} - export CP - -+LOGGING_CONFIG=`source /usr/share/pki/etc/pki.conf && source /etc/pki/pki.conf && echo $LOGGING_CONFIG` - - ############################################################################### - ## (6) Execute the java command specified by this java command wrapper ## - ## based upon the preset LD_LIBRARY_PATH and CP environment variables. ## - ############################################################################### - --${JAVA} ${JAVA_OPTIONS} -cp ${CP} com.netscape.cmstools.${COMMAND} "$@" -+${JAVA} ${JAVA_OPTIONS} \ -+ -cp ${CP} \ -+ -Djava.util.logging.config.file=${LOGGING_CONFIG} \ -+ com.netscape.cmstools.${COMMAND} "$@" -+ - exit $? - -diff --git a/base/server/python/pki/server/__init__.py b/base/server/python/pki/server/__init__.py -index 4493b59df00adc0dad9b6808fb10c1769634335c..22b6fcfc3b874e129c55e11d385a09ad3ce31d14 100644 ---- a/base/server/python/pki/server/__init__.py -+++ b/base/server/python/pki/server/__init__.py -@@ -20,6 +20,7 @@ - # - - from lxml import etree -+import functools - import getpass - import grp - import io -@@ -58,15 +59,15 @@ class PKIServer(object): - return instances - - -+@functools.total_ordering - class PKISubsystem(object): - - def __init__(self, instance, subsystem_name): - - self.instance = instance -- self.name = subsystem_name -- self.type = instance.type -+ self.name = subsystem_name # e.g. ca, kra - -- if self.type >= 10: -+ if instance.type >= 10: - self.base_dir = os.path.join(self.instance.base_dir, self.name) - else: - self.base_dir = instance.base_dir -@@ -81,12 +82,35 @@ class PKISubsystem(object): - instance.conf_dir, 'Catalina', 'localhost', self.name + '.xml') - - self.config = {} -- self.type = None -- self.prefix = None -+ self.type = None # e.g. CA, KRA -+ self.prefix = None # e.g. ca, kra - - # custom subsystem location - self.doc_base = os.path.join(self.base_dir, 'webapps', self.name) - -+ def __eq__(self, other): -+ if not isinstance(other, PKISubsystem): -+ return NotImplemented -+ return (self.name == other.name and -+ self.instance == other.instance and -+ self.type == other.type) -+ -+ def __ne__(self, other): -+ if not isinstance(other, PKISubsystem): -+ return NotImplemented -+ return not self.__eq__(other) -+ -+ def __lt__(self, other): -+ if not isinstance(other, PKISubsystem): -+ return NotImplemented -+ self_type = self.type if self.type is not None else '' -+ other_type = other.type if other.type is not None else '' -+ return (self.name < other.name or -+ self.instance < other.instance or -+ self_type < other_type) -+ -+ __hash__ = None -+ - def load(self): - self.config.clear() - -@@ -101,7 +125,7 @@ class PKISubsystem(object): - self.type = self.config['cs.type'] - self.prefix = self.type.lower() - -- def find_subsystem_certs(self): -+ def find_system_certs(self): - certs = [] - - cert_ids = self.config['%s.cert.list' % self.name].split(',') -@@ -130,6 +154,116 @@ class PKISubsystem(object): - self.config['%s.%s.cert' % (self.name, cert_id)] = cert.get('data', None) - self.config['%s.%s.certreq' % (self.name, cert_id)] = cert.get('request', None) - -+ def export_system_cert( -+ self, -+ cert_id, -+ pkcs12_file, -+ pkcs12_password_file, -+ new_file=False): -+ -+ 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) -+ -+ tmpdir = tempfile.mkdtemp() -+ -+ try: -+ nssdb_password_file = os.path.join(tmpdir, 'password.txt') -+ with open(nssdb_password_file, 'w') as f: -+ f.write(nssdb_password) -+ -+ # add the certificate, key, and chain -+ cmd = [ -+ 'pki', -+ '-d', self.instance.nssdb_dir, -+ '-C', nssdb_password_file -+ ] -+ -+ if token and token != 'internal': -+ cmd.extend(['--token', token]) -+ -+ cmd.extend([ -+ 'pkcs12-cert-add', -+ '--pkcs12-file', pkcs12_file, -+ '--pkcs12-password-file', pkcs12_password_file, -+ ]) -+ -+ if new_file: -+ cmd.extend(['--new-file']) -+ -+ cmd.extend([ -+ nickname -+ ]) -+ -+ subprocess.check_call(cmd) -+ -+ finally: -+ shutil.rmtree(tmpdir) -+ -+ def export_cert_chain( -+ self, -+ pkcs12_file, -+ pkcs12_password_file): -+ -+ # use subsystem certificate to get certificate chain -+ 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) -+ -+ tmpdir = tempfile.mkdtemp() -+ -+ try: -+ nssdb_password_file = os.path.join(tmpdir, 'password.txt') -+ with open(nssdb_password_file, 'w') as f: -+ f.write(nssdb_password) -+ -+ # export the certificate, key, and chain -+ cmd = [ -+ 'pki', -+ '-d', self.instance.nssdb_dir, -+ '-C', nssdb_password_file -+ ] -+ -+ if token and token != 'internal': -+ cmd.extend(['--token', token]) -+ -+ cmd.extend([ -+ 'pkcs12-export', -+ '--pkcs12-file', pkcs12_file, -+ '--pkcs12-password-file', pkcs12_password_file, -+ nickname -+ ]) -+ -+ subprocess.check_call(cmd) -+ -+ # remove the certificate and key, but keep the chain -+ cmd = [ -+ 'pki', -+ '-d', self.instance.nssdb_dir, -+ '-C', nssdb_password_file -+ ] -+ -+ if token and token != 'internal': -+ cmd.extend(['--token', token]) -+ -+ cmd.extend([ -+ 'pkcs12-cert-del', -+ '--pkcs12-file', pkcs12_file, -+ '--pkcs12-password-file', pkcs12_password_file, -+ nickname -+ ]) -+ -+ subprocess.check_call(cmd) -+ -+ finally: -+ shutil.rmtree(tmpdir) -+ - def save(self): - sorted_config = sorted(self.config.items(), key=operator.itemgetter(0)) - with io.open(self.cs_conf, 'wb') as f: -@@ -240,6 +374,25 @@ class PKIInstance(object): - - self.subsystems = [] - -+ def __eq__(self, other): -+ if not isinstance(other, PKIInstance): -+ return NotImplemented -+ return (self.name == other.name and -+ self.type == other.type) -+ -+ def __ne__(self, other): -+ if not isinstance(other, PKIInstance): -+ return NotImplemented -+ return not self.__eq__(other) -+ -+ def __lt__(self, other): -+ if not isinstance(other, PKIInstance): -+ return NotImplemented -+ return (self.name < other.name or -+ self.type < other.type) -+ -+ __hash__ = None -+ - def is_valid(self): - return os.path.exists(self.conf_dir) - -diff --git a/base/server/python/pki/server/cli/ca.py b/base/server/python/pki/server/cli/ca.py -index 2ad8652f4fddd032779941cb7e2ae4e643c25e0a..fe8ce2bc302145570fa96a5767790a6981cdd354 100644 ---- a/base/server/python/pki/server/cli/ca.py -+++ b/base/server/python/pki/server/cli/ca.py -@@ -23,10 +23,12 @@ from __future__ import absolute_import - from __future__ import print_function - import getopt - import io -+import os -+import shutil - import sys -+import tempfile - - import pki.cli --import pki.server.ca - - - class CACLI(pki.cli.CLI): -@@ -36,6 +38,7 @@ class CACLI(pki.cli.CLI): - 'ca', 'CA management commands') - - self.add_module(CACertCLI()) -+ self.add_module(CACloneCLI()) - - - class CACertCLI(pki.cli.CLI): -@@ -44,9 +47,106 @@ class CACertCLI(pki.cli.CLI): - super(CACertCLI, self).__init__( - 'cert', 'CA certificates management commands') - -+ self.add_module(CACertChainCLI()) - self.add_module(CACertRequestCLI()) - - -+class CACertChainCLI(pki.cli.CLI): -+ -+ def __init__(self): -+ super(CACertChainCLI, self).__init__( -+ 'chain', 'CA certificate chain management commands') -+ -+ self.add_module(CACertChainExportCLI()) -+ -+ -+class CACertChainExportCLI(pki.cli.CLI): -+ -+ def __init__(self): -+ super(CACertChainExportCLI, self).__init__( -+ 'export', 'Export certificate chain') -+ -+ def print_help(self): -+ print('Usage: pki-server ca-cert-chain-export [OPTIONS]') -+ print() -+ print(' -i, --instance Instance ID (default: pki-tomcat).') -+ print(' --pkcs12-file PKCS #12 file to store certificates and keys.') -+ print(' --pkcs12-password Password for the PKCS #12 file.') -+ print(' --pkcs12-password-file File containing the PKCS #12 password.') -+ print(' -v, --verbose Run in verbose mode.') -+ print(' --help Show help message.') -+ print() -+ -+ def execute(self, args): -+ -+ try: -+ opts, _ = getopt.gnu_getopt(args, 'i:v', [ -+ 'instance=', 'pkcs12-file=', 'pkcs12-password=', 'pkcs12-password-file=', -+ 'verbose', 'help']) -+ -+ except getopt.GetoptError as e: -+ print('ERROR: ' + str(e)) -+ self.print_help() -+ sys.exit(1) -+ -+ instance_name = 'pki-tomcat' -+ pkcs12_file = None -+ pkcs12_password = None -+ -+ for o, a in opts: -+ if o in ('-i', '--instance'): -+ instance_name = a -+ -+ elif o == '--pkcs12-file': -+ pkcs12_file = a -+ -+ elif o == '--pkcs12-password': -+ pkcs12_password = a -+ -+ elif o == '--pkcs12-password-file': -+ with io.open(a, 'rb') as f: -+ pkcs12_password = f.read() -+ -+ elif o in ('-v', '--verbose'): -+ self.set_verbose(True) -+ -+ elif o == '--help': -+ self.print_help() -+ sys.exit() -+ -+ else: -+ print('ERROR: unknown option ' + o) -+ self.print_help() -+ sys.exit(1) -+ -+ if not pkcs12_file: -+ print('ERROR: Missing PKCS #12 file') -+ self.print_help() -+ sys.exit(1) -+ -+ if not pkcs12_password: -+ print('ERROR: Missing PKCS #12 password') -+ self.print_help() -+ sys.exit(1) -+ -+ instance = pki.server.PKIInstance(instance_name) -+ instance.load() -+ -+ subsystem = instance.get_subsystem('ca') -+ -+ tmpdir = tempfile.mkdtemp() -+ -+ try: -+ pkcs12_password_file = os.path.join(tmpdir, 'pkcs12_password.txt') -+ with open(pkcs12_password_file, 'w') as f: -+ f.write(pkcs12_password) -+ -+ subsystem.export_cert_chain(pkcs12_file, pkcs12_password_file) -+ -+ finally: -+ shutil.rmtree(tmpdir) -+ -+ - class CACertRequestCLI(pki.cli.CLI): - - def __init__(self): -@@ -204,3 +304,106 @@ class CACertRequestShowCLI(pki.cli.CLI): - - else: - CACertRequestCLI.print_request(request, details=True) -+ -+ -+class CACloneCLI(pki.cli.CLI): -+ -+ def __init__(self): -+ super(CACloneCLI, self).__init__( -+ 'clone', 'CA clone management commands') -+ -+ self.add_module(CAClonePrepareCLI()) -+ -+ -+class CAClonePrepareCLI(pki.cli.CLI): -+ -+ def __init__(self): -+ super(CAClonePrepareCLI, self).__init__( -+ 'prepare', 'Prepare CA clone') -+ -+ def print_help(self): -+ print('Usage: pki-server ca-clone-prepare [OPTIONS]') -+ print() -+ print(' -i, --instance Instance ID (default: pki-tomcat).') -+ print(' --pkcs12-file PKCS #12 file to store certificates and keys.') -+ print(' --pkcs12-password Password for the PKCS #12 file.') -+ print(' --pkcs12-password-file File containing the PKCS #12 password.') -+ print(' -v, --verbose Run in verbose mode.') -+ print(' --help Show help message.') -+ print() -+ -+ def execute(self, args): -+ -+ try: -+ opts, _ = getopt.gnu_getopt(args, 'i:v', [ -+ 'instance=', 'pkcs12-file=', 'pkcs12-password=', 'pkcs12-password-file=', -+ 'verbose', 'help']) -+ -+ except getopt.GetoptError as e: -+ print('ERROR: ' + str(e)) -+ self.print_help() -+ sys.exit(1) -+ -+ instance_name = 'pki-tomcat' -+ pkcs12_file = None -+ pkcs12_password = None -+ -+ for o, a in opts: -+ if o in ('-i', '--instance'): -+ instance_name = a -+ -+ elif o == '--pkcs12-file': -+ pkcs12_file = a -+ -+ elif o == '--pkcs12-password': -+ pkcs12_password = a -+ -+ elif o == '--pkcs12-password-file': -+ with io.open(a, 'rb') as f: -+ pkcs12_password = f.read() -+ -+ elif o in ('-v', '--verbose'): -+ self.set_verbose(True) -+ -+ elif o == '--help': -+ self.print_help() -+ sys.exit() -+ -+ else: -+ print('ERROR: unknown option ' + o) -+ self.print_help() -+ sys.exit(1) -+ -+ if not pkcs12_file: -+ print('ERROR: Missing PKCS #12 file') -+ self.print_help() -+ sys.exit(1) -+ -+ if not pkcs12_password: -+ print('ERROR: Missing PKCS #12 password') -+ self.print_help() -+ sys.exit(1) -+ -+ instance = pki.server.PKIInstance(instance_name) -+ instance.load() -+ -+ subsystem = instance.get_subsystem('ca') -+ -+ tmpdir = tempfile.mkdtemp() -+ -+ try: -+ pkcs12_password_file = os.path.join(tmpdir, 'pkcs12_password.txt') -+ with open(pkcs12_password_file, 'w') as f: -+ f.write(pkcs12_password) -+ -+ subsystem.export_system_cert( -+ 'subsystem', pkcs12_file, pkcs12_password_file, new_file=True) -+ subsystem.export_system_cert( -+ 'signing', pkcs12_file, pkcs12_password_file) -+ subsystem.export_system_cert( -+ 'ocsp_signing', pkcs12_file, pkcs12_password_file) -+ subsystem.export_system_cert( -+ 'audit_signing', pkcs12_file, pkcs12_password_file) -+ -+ finally: -+ shutil.rmtree(tmpdir) -diff --git a/base/server/python/pki/server/cli/instance.py b/base/server/python/pki/server/cli/instance.py -index becad1447e5eebd45f09afe8ac37e495c38c6276..ebde6f19b2080dd827298d84aca9adaa263b89bd 100644 ---- a/base/server/python/pki/server/cli/instance.py -+++ b/base/server/python/pki/server/cli/instance.py -@@ -20,10 +20,12 @@ - # - - import getopt -+import getpass - import os - import sys - - import pki.cli -+import pki.nssdb - import pki.server - import pki.server.cli.nuxwdog - -@@ -34,6 +36,7 @@ class InstanceCLI(pki.cli.CLI): - super(InstanceCLI, self).__init__('instance', - 'Instance management commands') - -+ self.add_module(InstanceCertCLI()) - self.add_module(InstanceFindCLI()) - self.add_module(InstanceShowCLI()) - self.add_module(InstanceStartCLI()) -@@ -48,6 +51,101 @@ class InstanceCLI(pki.cli.CLI): - print ' Active: %s' % instance.is_active() - - -+class InstanceCertCLI(pki.cli.CLI): -+ -+ def __init__(self): -+ super(InstanceCertCLI, self).__init__( -+ 'cert', 'Instance certificate management commands') -+ -+ self.add_module(InstanceCertExportCLI()) -+ -+ -+class InstanceCertExportCLI(pki.cli.CLI): -+ -+ def __init__(self): -+ super(InstanceCertExportCLI, self).__init__( -+ 'export', 'Export system certificates') -+ -+ def print_help(self): # flake8: noqa -+ print('Usage: pki-server instance-cert-export [OPTIONS] [nicknames...]') -+ print() -+ print(' -i, --instance Instance ID (default: pki-tomcat).') -+ print(' --pkcs12-file Output file to store the exported certificate and key in PKCS #12 format.') -+ print(' --pkcs12-password Password for the PKCS #12 file.') -+ print(' --pkcs12-password-file Input file containing the password for the PKCS #12 file.') -+ print(' -v, --verbose Run in verbose mode.') -+ print(' --help Show help message.') -+ print() -+ -+ def execute(self, argv): -+ -+ try: -+ opts, args = getopt.gnu_getopt(argv, 'i:v', [ -+ 'instance=', -+ 'pkcs12-file=', 'pkcs12-password=', 'pkcs12-password-file=', -+ 'verbose', 'help']) -+ -+ except getopt.GetoptError as e: -+ print('ERROR: ' + str(e)) -+ self.print_help() -+ sys.exit(1) -+ -+ nicknames = args -+ -+ instance_name = 'pki-tomcat' -+ pkcs12_file = None -+ pkcs12_password = None -+ pkcs12_password_file = None -+ -+ for o, a in opts: -+ if o in ('-i', '--instance'): -+ instance_name = a -+ -+ elif o == '--pkcs12-file': -+ pkcs12_file = a -+ -+ elif o == '--pkcs12-password': -+ pkcs12_password = a -+ -+ elif o == '--pkcs12-password-file': -+ pkcs12_password_file = a -+ -+ elif o in ('-v', '--verbose'): -+ self.set_verbose(True) -+ -+ elif o == '--help': -+ self.print_help() -+ sys.exit() -+ -+ else: -+ print('ERROR: unknown option ' + o) -+ self.print_help() -+ sys.exit(1) -+ -+ if not pkcs12_file: -+ print('ERROR: missing output file') -+ self.print_help() -+ sys.exit(1) -+ -+ instance = pki.server.PKIInstance(instance_name) -+ instance.load() -+ -+ if not pkcs12_password and not pkcs12_password_file: -+ pkcs12_password = getpass.getpass(prompt='Enter password for PKCS #12 file: ') -+ -+ nssdb = instance.open_nssdb() -+ try: -+ nssdb.export_pkcs12( -+ pkcs12_file=pkcs12_file, -+ pkcs12_password=pkcs12_password, -+ pkcs12_password_file=pkcs12_password_file, -+ nicknames=nicknames) -+ finally: -+ nssdb.close() -+ -+ self.print_message('Exported certificates') -+ -+ - class InstanceFindCLI(pki.cli.CLI): - - def __init__(self): -diff --git a/base/server/python/pki/server/cli/kra.py b/base/server/python/pki/server/cli/kra.py -new file mode 100644 -index 0000000000000000000000000000000000000000..7dfa680cf67141b8d7dc6518f9d8a9e78a05a906 ---- /dev/null -+++ b/base/server/python/pki/server/cli/kra.py -@@ -0,0 +1,142 @@ -+# 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) 2016 Red Hat, Inc. -+# All rights reserved. -+# -+ -+from __future__ import absolute_import -+from __future__ import print_function -+import getopt -+import io -+import os -+import shutil -+import sys -+import tempfile -+ -+import pki.cli -+ -+ -+class KRACLI(pki.cli.CLI): -+ -+ def __init__(self): -+ super(KRACLI, self).__init__( -+ 'kra', 'KRA management commands') -+ -+ self.add_module(KRACloneCLI()) -+ -+ -+class KRACloneCLI(pki.cli.CLI): -+ -+ def __init__(self): -+ super(KRACloneCLI, self).__init__( -+ 'clone', 'KRA clone management commands') -+ -+ self.add_module(KRAClonePrepareCLI()) -+ -+ -+class KRAClonePrepareCLI(pki.cli.CLI): -+ -+ def __init__(self): -+ super(KRAClonePrepareCLI, self).__init__( -+ 'prepare', 'Prepare KRA clone') -+ -+ def print_help(self): -+ print('Usage: pki-server kra-clone-prepare [OPTIONS]') -+ print() -+ print(' -i, --instance Instance ID (default: pki-tomcat).') -+ print(' --pkcs12-file PKCS #12 file to store certificates and keys.') -+ print(' --pkcs12-password Password for the PKCS #12 file.') -+ print(' --pkcs12-password-file File containing the PKCS #12 password.') -+ print(' -v, --verbose Run in verbose mode.') -+ print(' --help Show help message.') -+ print() -+ -+ def execute(self, args): -+ -+ try: -+ opts, _ = getopt.gnu_getopt(args, 'i:v', [ -+ 'instance=', 'pkcs12-file=', 'pkcs12-password=', 'pkcs12-password-file=', -+ 'verbose', 'help']) -+ -+ except getopt.GetoptError as e: -+ print('ERROR: ' + str(e)) -+ self.print_help() -+ sys.exit(1) -+ -+ instance_name = 'pki-tomcat' -+ pkcs12_file = None -+ pkcs12_password = None -+ -+ for o, a in opts: -+ if o in ('-i', '--instance'): -+ instance_name = a -+ -+ elif o == '--pkcs12-file': -+ pkcs12_file = a -+ -+ elif o == '--pkcs12-password': -+ pkcs12_password = a -+ -+ elif o == '--pkcs12-password-file': -+ with io.open(a, 'rb') as f: -+ pkcs12_password = f.read() -+ -+ elif o in ('-v', '--verbose'): -+ self.set_verbose(True) -+ -+ elif o == '--help': -+ self.print_help() -+ sys.exit() -+ -+ else: -+ print('ERROR: unknown option ' + o) -+ self.print_help() -+ sys.exit(1) -+ -+ if not pkcs12_file: -+ print('ERROR: Missing PKCS #12 file') -+ self.print_help() -+ sys.exit(1) -+ -+ if not pkcs12_password: -+ print('ERROR: Missing PKCS #12 password') -+ self.print_help() -+ sys.exit(1) -+ -+ instance = pki.server.PKIInstance(instance_name) -+ instance.load() -+ -+ subsystem = instance.get_subsystem('kra') -+ -+ tmpdir = tempfile.mkdtemp() -+ -+ try: -+ pkcs12_password_file = os.path.join(tmpdir, 'pkcs12_password.txt') -+ with open(pkcs12_password_file, 'w') as f: -+ f.write(pkcs12_password) -+ -+ subsystem.export_system_cert( -+ 'subsystem', pkcs12_file, pkcs12_password_file, new_file=True) -+ subsystem.export_system_cert( -+ 'transport', pkcs12_file, pkcs12_password_file) -+ subsystem.export_system_cert( -+ 'storage', pkcs12_file, pkcs12_password_file) -+ subsystem.export_system_cert( -+ 'audit_signing', pkcs12_file, pkcs12_password_file) -+ -+ finally: -+ shutil.rmtree(tmpdir) -diff --git a/base/server/python/pki/server/cli/ocsp.py b/base/server/python/pki/server/cli/ocsp.py -new file mode 100644 -index 0000000000000000000000000000000000000000..b913a20c5fb4371f86cf677ffee2b0182a9789b8 ---- /dev/null -+++ b/base/server/python/pki/server/cli/ocsp.py -@@ -0,0 +1,140 @@ -+# 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) 2016 Red Hat, Inc. -+# All rights reserved. -+# -+ -+from __future__ import absolute_import -+from __future__ import print_function -+import getopt -+import io -+import os -+import shutil -+import sys -+import tempfile -+ -+import pki.cli -+ -+ -+class OCSPCLI(pki.cli.CLI): -+ -+ def __init__(self): -+ super(OCSPCLI, self).__init__( -+ 'ocsp', 'OCSP management commands') -+ -+ self.add_module(OCSPCloneCLI()) -+ -+ -+class OCSPCloneCLI(pki.cli.CLI): -+ -+ def __init__(self): -+ super(OCSPCloneCLI, self).__init__( -+ 'clone', 'OCSP clone management commands') -+ -+ self.add_module(OCSPClonePrepareCLI()) -+ -+ -+class OCSPClonePrepareCLI(pki.cli.CLI): -+ -+ def __init__(self): -+ super(OCSPClonePrepareCLI, self).__init__( -+ 'prepare', 'Prepare OCSP clone') -+ -+ def print_help(self): -+ print('Usage: pki-server ocsp-clone-prepare [OPTIONS]') -+ print() -+ print(' -i, --instance Instance ID (default: pki-tomcat).') -+ print(' --pkcs12-file PKCS #12 file to store certificates and keys.') -+ print(' --pkcs12-password Password for the PKCS #12 file.') -+ print(' --pkcs12-password-file File containing the PKCS #12 password.') -+ print(' -v, --verbose Run in verbose mode.') -+ print(' --help Show help message.') -+ print() -+ -+ def execute(self, args): -+ -+ try: -+ opts, _ = getopt.gnu_getopt(args, 'i:v', [ -+ 'instance=', 'pkcs12-file=', 'pkcs12-password=', 'pkcs12-password-file=', -+ 'verbose', 'help']) -+ -+ except getopt.GetoptError as e: -+ print('ERROR: ' + str(e)) -+ self.print_help() -+ sys.exit(1) -+ -+ instance_name = 'pki-tomcat' -+ pkcs12_file = None -+ pkcs12_password = None -+ -+ for o, a in opts: -+ if o in ('-i', '--instance'): -+ instance_name = a -+ -+ elif o == '--pkcs12-file': -+ pkcs12_file = a -+ -+ elif o == '--pkcs12-password': -+ pkcs12_password = a -+ -+ elif o == '--pkcs12-password-file': -+ with io.open(a, 'rb') as f: -+ pkcs12_password = f.read() -+ -+ elif o in ('-v', '--verbose'): -+ self.set_verbose(True) -+ -+ elif o == '--help': -+ self.print_help() -+ sys.exit() -+ -+ else: -+ print('ERROR: unknown option ' + o) -+ self.print_help() -+ sys.exit(1) -+ -+ if not pkcs12_file: -+ print('ERROR: Missing PKCS #12 file') -+ self.print_help() -+ sys.exit(1) -+ -+ if not pkcs12_password: -+ print('ERROR: Missing PKCS #12 password') -+ self.print_help() -+ sys.exit(1) -+ -+ instance = pki.server.PKIInstance(instance_name) -+ instance.load() -+ -+ subsystem = instance.get_subsystem('ocsp') -+ -+ tmpdir = tempfile.mkdtemp() -+ -+ try: -+ pkcs12_password_file = os.path.join(tmpdir, 'pkcs12_password.txt') -+ with open(pkcs12_password_file, 'w') as f: -+ f.write(pkcs12_password) -+ -+ subsystem.export_system_cert( -+ 'subsystem', pkcs12_file, pkcs12_password_file, new_file=True) -+ subsystem.export_system_cert( -+ 'signing', pkcs12_file, pkcs12_password_file) -+ subsystem.export_system_cert( -+ 'audit_signing', pkcs12_file, pkcs12_password_file) -+ -+ finally: -+ shutil.rmtree(tmpdir) -diff --git a/base/server/python/pki/server/cli/subsystem.py b/base/server/python/pki/server/cli/subsystem.py -index 9f82dff756bf98b0a14783fdd48c25d9d406f50b..09ece80a72213764f0f69ffad894f15eef3474f5 100644 ---- a/base/server/python/pki/server/cli/subsystem.py -+++ b/base/server/python/pki/server/cli/subsystem.py -@@ -300,12 +300,14 @@ class SubsystemCertCLI(pki.cli.CLI): - self.add_module(SubsystemCertUpdateCLI()) - - @staticmethod -- def print_subsystem_cert(cert): -+ def print_subsystem_cert(cert, show_all=False): - print(' Cert ID: %s' % cert['id']) - print(' Nickname: %s' % cert['nickname']) - print(' Token: %s' % cert['token']) -- print(' Certificate: %s' % cert['data']) -- print(' Request: %s' % cert['request']) -+ -+ if show_all: -+ print(' Certificate: %s' % cert['data']) -+ print(' Request: %s' % cert['request']) - - - class SubsystemCertFindCLI(pki.cli.CLI): -@@ -314,10 +316,11 @@ class SubsystemCertFindCLI(pki.cli.CLI): - super(SubsystemCertFindCLI, self).__init__( - 'find', 'Find subsystem certificates') - -- def usage(self): -+ def print_help(self): - print('Usage: pki-server subsystem-cert-find [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() -@@ -325,27 +328,31 @@ class SubsystemCertFindCLI(pki.cli.CLI): - def execute(self, argv): - - try: -- opts, args = getopt.getopt(argv, 'i:v', [ -- 'instance=', -+ opts, args = getopt.gnu_getopt(argv, 'i:v', [ -+ 'instance=', 'show-all', - 'verbose', 'help']) - - except getopt.GetoptError as e: - print('ERROR: ' + str(e)) -- self.usage() -+ self.print_help() - sys.exit(1) - - if len(args) != 1: - print('ERROR: missing subsystem ID') -- self.usage() -+ self.print_help() - sys.exit(1) - - subsystem_name = args[0] - 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) - -@@ -355,14 +362,14 @@ class SubsystemCertFindCLI(pki.cli.CLI): - - else: - print('ERROR: unknown option ' + o) -- self.usage() -+ self.print_help() - sys.exit(1) - - instance = pki.server.PKIInstance(instance_name) - instance.load() - - subsystem = instance.get_subsystem(subsystem_name) -- results = subsystem.find_subsystem_certs() -+ results = subsystem.find_system_certs() - - self.print_message('%s entries matched' % len(results)) - -@@ -373,7 +380,7 @@ class SubsystemCertFindCLI(pki.cli.CLI): - else: - print() - -- SubsystemCertCLI.print_subsystem_cert(cert) -+ SubsystemCertCLI.print_subsystem_cert(cert, show_all) - - - class SubsystemCertShowCLI(pki.cli.CLI): -@@ -447,8 +454,8 @@ class SubsystemCertExportCLI(pki.cli.CLI): - super(SubsystemCertExportCLI, self).__init__( - 'export', 'Export subsystem certificate') - -- def usage(self): -- print('Usage: pki-server subsystem-cert-export [OPTIONS] ') -+ def print_help(self): # flake8: noqa -+ print('Usage: pki-server subsystem-cert-export [OPTIONS] [cert ID]') - print() - print(' -i, --instance Instance ID (default: pki-tomcat).') - print(' --cert-file Output file to store the exported certificate in PEM format.') -@@ -470,21 +477,16 @@ class SubsystemCertExportCLI(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 subsystem ID') -- self.usage() -- sys.exit(1) -- -- if len(args) < 2: -- print('ERROR: missing cert ID') -- self.usage() -+ self.print_help() - sys.exit(1) - - subsystem_name = args[0] -- cert_id = args[1] -+ - instance_name = 'pki-tomcat' - cert_file = None - csr_file = None -@@ -520,19 +522,28 @@ class SubsystemCertExportCLI(pki.cli.CLI): - - else: - print('ERROR: unknown option ' + o) -- self.usage() -+ self.print_help() - sys.exit(1) - -- if not cert_file and not csr_file and not pkcs12_file: -+ if not pkcs12_file: - print('ERROR: missing output file') -- self.usage() -+ self.print_help() - sys.exit(1) - - instance = pki.server.PKIInstance(instance_name) - instance.load() - - subsystem = instance.get_subsystem(subsystem_name) -- subsystem_cert = subsystem.get_subsystem_cert(cert_id) -+ subsystem_cert = None -+ -+ if len(args) >= 2: -+ cert_id = args[1] -+ subsystem_cert = subsystem.get_subsystem_cert(cert_id) -+ -+ if (cert_file or csr_file) and not subsystem_cert: -+ print('ERROR: missing cert ID') -+ self.print_help() -+ sys.exit(1) - - if cert_file: - -@@ -551,17 +562,28 @@ class SubsystemCertExportCLI(pki.cli.CLI): - if not pkcs12_password and not pkcs12_password_file: - pkcs12_password = getpass.getpass(prompt='Enter password for PKCS #12 file: ') - -+ nicknames = [] -+ -+ if subsystem_cert: -+ nicknames.append(subsystem_cert['nickname']) -+ -+ else: -+ subsystem_certs = subsystem.find_system_certs() -+ for subsystem_cert in subsystem_certs: -+ nicknames.append(subsystem_cert['nickname']) -+ - nssdb = instance.open_nssdb() - try: - nssdb.export_pkcs12( - pkcs12_file=pkcs12_file, -- nickname=subsystem_cert['nickname'], - pkcs12_password=pkcs12_password, -- pkcs12_password_file=pkcs12_password_file) -+ pkcs12_password_file=pkcs12_password_file, -+ nicknames=nicknames) -+ - finally: - nssdb.close() - -- self.print_message('Exported %s certificate' % cert_id) -+ self.print_message('Export complete') - - - class SubsystemCertUpdateCLI(pki.cli.CLI): -diff --git a/base/server/python/pki/server/cli/tks.py b/base/server/python/pki/server/cli/tks.py -new file mode 100644 -index 0000000000000000000000000000000000000000..bf96d96103470c59edd3828cfe33a2770fed33bc ---- /dev/null -+++ b/base/server/python/pki/server/cli/tks.py -@@ -0,0 +1,140 @@ -+# 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) 2016 Red Hat, Inc. -+# All rights reserved. -+# -+ -+from __future__ import absolute_import -+from __future__ import print_function -+import getopt -+import io -+import os -+import shutil -+import sys -+import tempfile -+ -+import pki.cli -+ -+ -+class TKSCLI(pki.cli.CLI): -+ -+ def __init__(self): -+ super(TKSCLI, self).__init__( -+ 'tks', 'TKS management commands') -+ -+ self.add_module(TKSCloneCLI()) -+ -+ -+class TKSCloneCLI(pki.cli.CLI): -+ -+ def __init__(self): -+ super(TKSCloneCLI, self).__init__( -+ 'clone', 'TKS clone management commands') -+ -+ self.add_module(TKSClonePrepareCLI()) -+ -+ -+class TKSClonePrepareCLI(pki.cli.CLI): -+ -+ def __init__(self): -+ super(TKSClonePrepareCLI, self).__init__( -+ 'prepare', 'Prepare TKS clone') -+ -+ def print_help(self): -+ print('Usage: pki-server tks-clone-prepare [OPTIONS]') -+ print() -+ print(' -i, --instance Instance ID (default: pki-tomcat).') -+ print(' --pkcs12-file PKCS #12 file to store certificates and keys.') -+ print(' --pkcs12-password Password for the PKCS #12 file.') -+ print(' --pkcs12-password-file File containing the PKCS #12 password.') -+ print(' -v, --verbose Run in verbose mode.') -+ print(' --help Show help message.') -+ print() -+ -+ def execute(self, args): -+ -+ try: -+ opts, _ = getopt.gnu_getopt(args, 'i:v', [ -+ 'instance=', 'pkcs12-file=', 'pkcs12-password=', 'pkcs12-password-file=', -+ 'verbose', 'help']) -+ -+ except getopt.GetoptError as e: -+ print('ERROR: ' + str(e)) -+ self.print_help() -+ sys.exit(1) -+ -+ instance_name = 'pki-tomcat' -+ pkcs12_file = None -+ pkcs12_password = None -+ -+ for o, a in opts: -+ if o in ('-i', '--instance'): -+ instance_name = a -+ -+ elif o == '--pkcs12-file': -+ pkcs12_file = a -+ -+ elif o == '--pkcs12-password': -+ pkcs12_password = a -+ -+ elif o == '--pkcs12-password-file': -+ with io.open(a, 'rb') as f: -+ pkcs12_password = f.read() -+ -+ elif o in ('-v', '--verbose'): -+ self.set_verbose(True) -+ -+ elif o == '--help': -+ self.print_help() -+ sys.exit() -+ -+ else: -+ print('ERROR: unknown option ' + o) -+ self.print_help() -+ sys.exit(1) -+ -+ if not pkcs12_file: -+ print('ERROR: Missing PKCS #12 file') -+ self.print_help() -+ sys.exit(1) -+ -+ if not pkcs12_password: -+ print('ERROR: Missing PKCS #12 password') -+ self.print_help() -+ sys.exit(1) -+ -+ instance = pki.server.PKIInstance(instance_name) -+ instance.load() -+ -+ subsystem = instance.get_subsystem('tks') -+ -+ tmpdir = tempfile.mkdtemp() -+ -+ try: -+ pkcs12_password_file = os.path.join(tmpdir, 'pkcs12_password.txt') -+ with open(pkcs12_password_file, 'w') as f: -+ f.write(pkcs12_password) -+ -+ subsystem.export_system_cert( -+ 'subsystem', pkcs12_file, pkcs12_password_file, new_file=True) -+ subsystem.export_system_cert( -+ 'signing', pkcs12_file, pkcs12_password_file) -+ subsystem.export_system_cert( -+ 'audit_signing', pkcs12_file, pkcs12_password_file) -+ -+ finally: -+ shutil.rmtree(tmpdir) -diff --git a/base/server/python/pki/server/cli/tps.py b/base/server/python/pki/server/cli/tps.py -new file mode 100644 -index 0000000000000000000000000000000000000000..7284eaa842d27b4f795a3e46466343f0915fff92 ---- /dev/null -+++ b/base/server/python/pki/server/cli/tps.py -@@ -0,0 +1,140 @@ -+# 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) 2016 Red Hat, Inc. -+# All rights reserved. -+# -+ -+from __future__ import absolute_import -+from __future__ import print_function -+import getopt -+import io -+import os -+import shutil -+import sys -+import tempfile -+ -+import pki.cli -+ -+ -+class TPSCLI(pki.cli.CLI): -+ -+ def __init__(self): -+ super(TPSCLI, self).__init__( -+ 'tps', 'TPS management commands') -+ -+ self.add_module(TPSCloneCLI()) -+ -+ -+class TPSCloneCLI(pki.cli.CLI): -+ -+ def __init__(self): -+ super(TPSCloneCLI, self).__init__( -+ 'clone', 'TPS clone management commands') -+ -+ self.add_module(TPSClonePrepareCLI()) -+ -+ -+class TPSClonePrepareCLI(pki.cli.CLI): -+ -+ def __init__(self): -+ super(TPSClonePrepareCLI, self).__init__( -+ 'prepare', 'Prepare TPS clone') -+ -+ def print_help(self): -+ print('Usage: pki-server tps-clone-prepare [OPTIONS]') -+ print() -+ print(' -i, --instance Instance ID (default: pki-tomcat).') -+ print(' --pkcs12-file PKCS #12 file to store certificates and keys.') -+ print(' --pkcs12-password Password for the PKCS #12 file.') -+ print(' --pkcs12-password-file File containing the PKCS #12 password.') -+ print(' -v, --verbose Run in verbose mode.') -+ print(' --help Show help message.') -+ print() -+ -+ def execute(self, args): -+ -+ try: -+ opts, _ = getopt.gnu_getopt(args, 'i:v', [ -+ 'instance=', 'pkcs12-file=', 'pkcs12-password=', 'pkcs12-password-file=', -+ 'verbose', 'help']) -+ -+ except getopt.GetoptError as e: -+ print('ERROR: ' + str(e)) -+ self.print_help() -+ sys.exit(1) -+ -+ instance_name = 'pki-tomcat' -+ pkcs12_file = None -+ pkcs12_password = None -+ -+ for o, a in opts: -+ if o in ('-i', '--instance'): -+ instance_name = a -+ -+ elif o == '--pkcs12-file': -+ pkcs12_file = a -+ -+ elif o == '--pkcs12-password': -+ pkcs12_password = a -+ -+ elif o == '--pkcs12-password-file': -+ with io.open(a, 'rb') as f: -+ pkcs12_password = f.read() -+ -+ elif o in ('-v', '--verbose'): -+ self.set_verbose(True) -+ -+ elif o == '--help': -+ self.print_help() -+ sys.exit() -+ -+ else: -+ print('ERROR: unknown option ' + o) -+ self.print_help() -+ sys.exit(1) -+ -+ if not pkcs12_file: -+ print('ERROR: Missing PKCS #12 file') -+ self.print_help() -+ sys.exit(1) -+ -+ if not pkcs12_password: -+ print('ERROR: Missing PKCS #12 password') -+ self.print_help() -+ sys.exit(1) -+ -+ instance = pki.server.PKIInstance(instance_name) -+ instance.load() -+ -+ subsystem = instance.get_subsystem('tps') -+ -+ tmpdir = tempfile.mkdtemp() -+ -+ try: -+ pkcs12_password_file = os.path.join(tmpdir, 'pkcs12_password.txt') -+ with open(pkcs12_password_file, 'w') as f: -+ f.write(pkcs12_password) -+ -+ subsystem.export_system_cert( -+ 'subsystem', pkcs12_file, pkcs12_password_file, new_file=True) -+ subsystem.export_system_cert( -+ 'signing', pkcs12_file, pkcs12_password_file) -+ subsystem.export_system_cert( -+ 'audit_signing', pkcs12_file, pkcs12_password_file) -+ -+ finally: -+ shutil.rmtree(tmpdir) -diff --git a/base/server/python/pki/server/deployment/scriptlets/configuration.py b/base/server/python/pki/server/deployment/scriptlets/configuration.py -index e7b257f7d3eb1178827ed2ef1e211e4a21455d1b..54f065f094c811cdbf944a0ac14e019d0d4d6145 100644 ---- a/base/server/python/pki/server/deployment/scriptlets/configuration.py -+++ b/base/server/python/pki/server/deployment/scriptlets/configuration.py -@@ -161,7 +161,7 @@ class PkiScriptlet(pkiscriptlet.AbstractBasePkiScriptlet): - external_ca_cert_chain_nickname = deployer.mdict['pki_external_ca_cert_chain_nickname'] - external_ca_cert_chain_file = deployer.mdict['pki_external_ca_cert_chain_path'] - if external_ca_cert_chain_file: -- cert_chain = nssdb.import_cert_chain( -+ cert_chain, _nicks = nssdb.import_cert_chain( - nickname=external_ca_cert_chain_nickname, - cert_chain_file=external_ca_cert_chain_file, - trust_attributes='CT,C,C') -diff --git a/base/server/python/pki/server/deployment/scriptlets/security_databases.py b/base/server/python/pki/server/deployment/scriptlets/security_databases.py -index 3f8623af159d4e52195dae010625c8e5cfbaefc8..5c28580ce861743d797f3026b8689f2e4c131fdb 100644 ---- a/base/server/python/pki/server/deployment/scriptlets/security_databases.py -+++ b/base/server/python/pki/server/deployment/scriptlets/security_databases.py -@@ -19,6 +19,10 @@ - # All rights reserved. - # - -+from __future__ import absolute_import -+ -+import pki.nssdb -+ - # PKI Deployment Imports - from .. import pkiconfig as config - from .. import pkimessages as log -@@ -35,8 +39,10 @@ class PkiScriptlet(pkiscriptlet.AbstractBasePkiScriptlet): - config.pki_log.info(log.SKIP_SECURITY_DATABASES_SPAWN_1, __name__, - extra=config.PKI_INDENTATION_LEVEL_1) - return self.rv -+ - config.pki_log.info(log.SECURITY_DATABASES_SPAWN_1, __name__, - extra=config.PKI_INDENTATION_LEVEL_1) -+ - if config.str2bool(deployer.mdict['pki_hsm_enable']): - deployer.password.create_hsm_password_conf( - deployer.mdict['pki_shared_password_conf'], -@@ -46,6 +52,7 @@ class PkiScriptlet(pkiscriptlet.AbstractBasePkiScriptlet): - deployer.password.create_password_conf( - deployer.mdict['pki_shared_password_conf'], - deployer.mdict['pki_pin']) -+ - # Since 'certutil' does NOT strip the 'token=' portion of - # the 'token=password' entries, create a temporary server 'pfile' - # which ONLY contains the 'password' for the purposes of -@@ -54,12 +61,14 @@ class PkiScriptlet(pkiscriptlet.AbstractBasePkiScriptlet): - deployer.mdict['pki_shared_pfile'], - deployer.mdict['pki_pin'], pin_sans_token=True) - deployer.file.modify(deployer.mdict['pki_shared_password_conf']) -+ - deployer.certutil.create_security_databases( - deployer.mdict['pki_database_path'], - deployer.mdict['pki_cert_database'], - deployer.mdict['pki_key_database'], - deployer.mdict['pki_secmod_database'], - password_file=deployer.mdict['pki_shared_pfile']) -+ - if config.str2bool(deployer.mdict['pki_hsm_enable']): - deployer.modutil.register_security_module( - deployer.mdict['pki_database_path'], -@@ -75,6 +84,25 @@ class PkiScriptlet(pkiscriptlet.AbstractBasePkiScriptlet): - deployer.mdict['pki_secmod_database'], - perms=config.PKI_DEPLOYMENT_DEFAULT_SECURITY_DATABASE_PERMISSIONS) - -+ # import CA certificates from PKCS #12 file for cloning -+ pki_clone_pkcs12_path = deployer.mdict['pki_clone_pkcs12_path'] -+ -+ if pki_clone_pkcs12_path: -+ -+ pki_clone_pkcs12_password = deployer.mdict[ -+ 'pki_clone_pkcs12_password'] -+ if not pki_clone_pkcs12_password: -+ raise Exception('Missing pki_clone_pkcs12_password property.') -+ -+ nssdb = pki.nssdb.NSSDatabase( -+ directory=deployer.mdict['pki_database_path'], -+ password_file=deployer.mdict['pki_shared_pfile']) -+ -+ nssdb.import_pkcs12( -+ pkcs12_file=pki_clone_pkcs12_path, -+ pkcs12_password=pki_clone_pkcs12_password, -+ no_user_certs=True) -+ - if len(deployer.instance.tomcat_instance_subsystems()) < 2: - # only create a self signed cert for a new instance - # -diff --git a/base/server/sbin/pki-server b/base/server/sbin/pki-server -index cdfd98ee16346dbbd12adb20da934d32cdc14226..cf56d1bc4320bfe6e88f6436023d50e0c7ebba24 100644 ---- a/base/server/sbin/pki-server -+++ b/base/server/sbin/pki-server -@@ -24,6 +24,10 @@ import sys - - import pki.cli - import pki.server.cli.ca -+import pki.server.cli.kra -+import pki.server.cli.ocsp -+import pki.server.cli.tks -+import pki.server.cli.tps - import pki.server.cli.instance - import pki.server.cli.subsystem - import pki.server.cli.migrate -@@ -37,6 +41,11 @@ class PKIServerCLI(pki.cli.CLI): - super(PKIServerCLI, self).__init__('pki-server', 'PKI server command-line interface') - - self.add_module(pki.server.cli.ca.CACLI()) -+ self.add_module(pki.server.cli.kra.KRACLI()) -+ self.add_module(pki.server.cli.ocsp.OCSPCLI()) -+ self.add_module(pki.server.cli.tks.TKSCLI()) -+ self.add_module(pki.server.cli.tps.TPSCLI()) -+ - self.add_module(pki.server.cli.instance.InstanceCLI()) - self.add_module(pki.server.cli.subsystem.SubsystemCLI()) - self.add_module(pki.server.cli.migrate.MigrateCLI()) -diff --git a/base/util/src/netscape/security/pkcs/PKCS12.java b/base/util/src/netscape/security/pkcs/PKCS12.java -new file mode 100644 -index 0000000000000000000000000000000000000000..6c7880aa8039e3f568285fe55adc0adb15ebeb22 ---- /dev/null -+++ b/base/util/src/netscape/security/pkcs/PKCS12.java -@@ -0,0 +1,205 @@ -+// --- BEGIN COPYRIGHT BLOCK --- -+// 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. -+// -+// (C) 2016 Red Hat, Inc. -+// All rights reserved. -+// --- END COPYRIGHT BLOCK --- -+package netscape.security.pkcs; -+ -+import java.math.BigInteger; -+import java.util.ArrayList; -+import java.util.Collection; -+import java.util.LinkedHashMap; -+import java.util.Map; -+ -+import org.mozilla.jss.asn1.OBJECT_IDENTIFIER; -+ -+public class PKCS12 { -+ -+ // PKI OID: 2.16.840.1.113730.5 -+ public final static OBJECT_IDENTIFIER PKI_OID = new OBJECT_IDENTIFIER("2.16.840.1.113730.5"); -+ -+ // PKCS #12 OID: 2.16.840.1.113730.5.1 -+ public final static OBJECT_IDENTIFIER PKCS12_OID = PKI_OID.subBranch(1); -+ -+ // PKCS #12 attributes OID: 2.16.840.1.113730.5.1.1 -+ public final static OBJECT_IDENTIFIER PKCS12_ATTRIBUTES_OID = PKCS12_OID.subBranch(1); -+ -+ // Certificate trust flags OID: 2.16.840.1.113730.5.1.1.1 -+ public final static OBJECT_IDENTIFIER CERT_TRUST_FLAGS_OID = PKCS12_ATTRIBUTES_OID.subBranch(1); -+ -+ // based on certdb.h in NSS -+ public final static int TERMINAL_RECORD = 1 << 0; -+ public final static int TRUSTED = 1 << 1; -+ public final static int SEND_WARN = 1 << 2; -+ public final static int VALID_CA = 1 << 3; -+ public final static int TRUSTED_CA = 1 << 4; -+ public final static int NS_TRUSTED_CA = 1 << 5; -+ public final static int USER = 1 << 6; -+ public final static int TRUSTED_CLIENT_CA = 1 << 7; -+ public final static int INVISIBLE_CA = 1 << 8; -+ public final static int GOVT_APPROVED_CA = 1 << 9; -+ -+ public static boolean isFlagEnabled(int flag, int flags) { -+ return (flag & flags) > 0; -+ } -+ -+ // based on printflags() in secutil.c in NSS -+ public static String encodeFlags(int flags) { -+ -+ StringBuffer sb = new StringBuffer(); -+ -+ if (isFlagEnabled(VALID_CA, flags) && !isFlagEnabled(TRUSTED_CA, flags) && !isFlagEnabled(TRUSTED_CLIENT_CA, flags)) -+ sb.append("c"); -+ -+ if (isFlagEnabled(TERMINAL_RECORD, flags) && !isFlagEnabled(TRUSTED, flags)) -+ sb.append("p"); -+ -+ if (isFlagEnabled(TRUSTED_CA, flags)) -+ sb.append("C"); -+ -+ if (isFlagEnabled(TRUSTED_CLIENT_CA, flags)) -+ sb.append("T"); -+ -+ if (isFlagEnabled(TRUSTED, flags)) -+ sb.append("P"); -+ -+ if (isFlagEnabled(USER, flags)) -+ sb.append("u"); -+ -+ if (isFlagEnabled(SEND_WARN, flags)) -+ sb.append("w"); -+ -+ if (isFlagEnabled(INVISIBLE_CA, flags)) -+ sb.append("I"); -+ -+ if (isFlagEnabled(GOVT_APPROVED_CA, flags)) -+ sb.append("G"); -+ -+ return sb.toString(); -+ } -+ -+ // based on CERT_DecodeTrustString() in certdb.c in NSS -+ public static int decodeFlags(String flags) throws Exception { -+ -+ int value = 0; -+ -+ for (char c : flags.toCharArray()) { -+ switch (c) { -+ case 'p': -+ value = value | TERMINAL_RECORD; -+ break; -+ -+ case 'P': -+ value = value | TRUSTED | TERMINAL_RECORD; -+ break; -+ -+ case 'w': -+ value = value | SEND_WARN; -+ break; -+ -+ case 'c': -+ value = value | VALID_CA; -+ break; -+ -+ case 'T': -+ value = value | TRUSTED_CLIENT_CA | VALID_CA; -+ break; -+ -+ case 'C' : -+ value = value | TRUSTED_CA | VALID_CA; -+ break; -+ -+ case 'u': -+ value = value | USER; -+ break; -+ -+ case 'i': -+ value = value | INVISIBLE_CA; -+ break; -+ case 'g': -+ value = value | GOVT_APPROVED_CA; -+ break; -+ -+ default: -+ throw new Exception("Invalid trust flag: " + c); -+ } -+ } -+ -+ return value; -+ } -+ -+ Map keyInfosByID = new LinkedHashMap(); -+ -+ Map certInfosByID = new LinkedHashMap(); -+ -+ public PKCS12() { -+ } -+ -+ public Collection getKeyInfos() { -+ return keyInfosByID.values(); -+ } -+ -+ public void addKeyInfo(PKCS12KeyInfo keyInfo) { -+ keyInfosByID.put(keyInfo.id, keyInfo); -+ } -+ -+ public PKCS12KeyInfo getKeyInfoByID(BigInteger id) { -+ return keyInfosByID.get(id); -+ } -+ -+ public PKCS12KeyInfo removeKeyInfoByID(BigInteger id) { -+ return keyInfosByID.remove(id); -+ } -+ -+ public Collection getCertInfos() { -+ return certInfosByID.values(); -+ } -+ -+ public void addCertInfo(PKCS12CertInfo certInfo, boolean replace) { -+ BigInteger id = certInfo.getID(); -+ -+ if (!replace && certInfosByID.containsKey(id)) -+ return; -+ -+ certInfosByID.put(id, certInfo); -+ } -+ -+ public PKCS12CertInfo getCertInfoByID(BigInteger id) { -+ return certInfosByID.get(id); -+ } -+ -+ public Collection getCertInfosByNickname(String nickname) { -+ -+ Collection result = new ArrayList(); -+ -+ for (PKCS12CertInfo certInfo : certInfosByID.values()) { -+ if (!nickname.equals(certInfo.getNickname())) continue; -+ result.add(certInfo); -+ } -+ -+ return result; -+ } -+ -+ public void removeCertInfoByNickname(String nickname) { -+ -+ Collection result = getCertInfosByNickname(nickname); -+ -+ for (PKCS12CertInfo certInfo : result) { -+ // remove cert and key -+ certInfosByID.remove(certInfo.getID()); -+ keyInfosByID.remove(certInfo.getID()); -+ } -+ } -+} -diff --git a/base/util/src/netscape/security/pkcs/PKCS12CertInfo.java b/base/util/src/netscape/security/pkcs/PKCS12CertInfo.java -new file mode 100644 -index 0000000000000000000000000000000000000000..ec7b0e332f8909c4a7aefae8ed58c9117e485a89 ---- /dev/null -+++ b/base/util/src/netscape/security/pkcs/PKCS12CertInfo.java -@@ -0,0 +1,65 @@ -+// --- BEGIN COPYRIGHT BLOCK --- -+// 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. -+// -+// (C) 2016 Red Hat, Inc. -+// All rights reserved. -+// --- END COPYRIGHT BLOCK --- -+package netscape.security.pkcs; -+ -+import java.math.BigInteger; -+ -+import netscape.security.x509.X509CertImpl; -+ -+public class PKCS12CertInfo { -+ -+ BigInteger id; -+ X509CertImpl cert; -+ String nickname; -+ String trustFlags; -+ -+ public PKCS12CertInfo() { -+ } -+ -+ public BigInteger getID() { -+ return id; -+ } -+ -+ public void setID(BigInteger id) { -+ this.id = id; -+ } -+ -+ public X509CertImpl getCert() { -+ return cert; -+ } -+ -+ public void setCert(X509CertImpl cert) { -+ this.cert = cert; -+ } -+ -+ public String getNickname() { -+ return nickname; -+ } -+ -+ public void setNickname(String nickname) { -+ this.nickname = nickname; -+ } -+ -+ public String getTrustFlags() { -+ return trustFlags; -+ } -+ -+ public void setTrustFlags(String trustFlags) { -+ this.trustFlags = trustFlags; -+ } -+} -diff --git a/base/util/src/netscape/security/pkcs/PKCS12KeyInfo.java b/base/util/src/netscape/security/pkcs/PKCS12KeyInfo.java -new file mode 100644 -index 0000000000000000000000000000000000000000..c7e84f01ffa19a0fc116f1f3fddf2bf3dfe9de9e ---- /dev/null -+++ b/base/util/src/netscape/security/pkcs/PKCS12KeyInfo.java -@@ -0,0 +1,56 @@ -+// --- BEGIN COPYRIGHT BLOCK --- -+// 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. -+// -+// (C) 2016 Red Hat, Inc. -+// All rights reserved. -+// --- END COPYRIGHT BLOCK --- -+package netscape.security.pkcs; -+ -+import java.math.BigInteger; -+ -+import org.mozilla.jss.pkix.primitive.PrivateKeyInfo; -+ -+public class PKCS12KeyInfo { -+ -+ BigInteger id; -+ PrivateKeyInfo privateKeyInfo; -+ String subjectDN; -+ -+ public PKCS12KeyInfo() { -+ } -+ -+ public BigInteger getID() { -+ return id; -+ } -+ -+ public void setID(BigInteger id) { -+ this.id = id; -+ } -+ -+ public PrivateKeyInfo getPrivateKeyInfo() { -+ return privateKeyInfo; -+ } -+ -+ public void setPrivateKeyInfo(PrivateKeyInfo privateKeyInfo) { -+ this.privateKeyInfo = privateKeyInfo; -+ } -+ -+ public String getSubjectDN() { -+ return subjectDN; -+ } -+ -+ public void setSubjectDN(String subjectDN) { -+ this.subjectDN = subjectDN; -+ } -+} -diff --git a/base/util/src/netscape/security/pkcs/PKCS12Util.java b/base/util/src/netscape/security/pkcs/PKCS12Util.java -new file mode 100644 -index 0000000000000000000000000000000000000000..7c9ab2fb4e9554b18c3bf09c9e7c90f8349918fd ---- /dev/null -+++ b/base/util/src/netscape/security/pkcs/PKCS12Util.java -@@ -0,0 +1,642 @@ -+// --- BEGIN COPYRIGHT BLOCK --- -+// 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. -+// -+// (C) 2016 Red Hat, Inc. -+// All rights reserved. -+// --- END COPYRIGHT BLOCK --- -+package netscape.security.pkcs; -+ -+import java.io.ByteArrayInputStream; -+import java.io.ByteArrayOutputStream; -+import java.io.FileOutputStream; -+import java.math.BigInteger; -+import java.nio.file.Files; -+import java.nio.file.Path; -+import java.nio.file.Paths; -+import java.security.MessageDigest; -+import java.security.Principal; -+import java.security.PublicKey; -+import java.security.cert.CertificateException; -+import java.util.Collection; -+import java.util.logging.Logger; -+ -+import org.mozilla.jss.CryptoManager; -+import org.mozilla.jss.asn1.ANY; -+import org.mozilla.jss.asn1.ASN1Util; -+import org.mozilla.jss.asn1.ASN1Value; -+import org.mozilla.jss.asn1.BMPString; -+import org.mozilla.jss.asn1.OBJECT_IDENTIFIER; -+import org.mozilla.jss.asn1.OCTET_STRING; -+import org.mozilla.jss.asn1.SEQUENCE; -+import org.mozilla.jss.asn1.SET; -+import org.mozilla.jss.crypto.Cipher; -+import org.mozilla.jss.crypto.CryptoStore; -+import org.mozilla.jss.crypto.CryptoToken; -+import org.mozilla.jss.crypto.EncryptionAlgorithm; -+import org.mozilla.jss.crypto.IVParameterSpec; -+import org.mozilla.jss.crypto.InternalCertificate; -+import org.mozilla.jss.crypto.KeyGenAlgorithm; -+import org.mozilla.jss.crypto.KeyGenerator; -+import org.mozilla.jss.crypto.KeyWrapAlgorithm; -+import org.mozilla.jss.crypto.KeyWrapper; -+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.SymmetricKey; -+import org.mozilla.jss.crypto.X509Certificate; -+import org.mozilla.jss.pkcs12.AuthenticatedSafes; -+import org.mozilla.jss.pkcs12.CertBag; -+import org.mozilla.jss.pkcs12.PFX; -+import org.mozilla.jss.pkcs12.PasswordConverter; -+import org.mozilla.jss.pkcs12.SafeBag; -+import org.mozilla.jss.pkix.primitive.Attribute; -+import org.mozilla.jss.pkix.primitive.EncryptedPrivateKeyInfo; -+import org.mozilla.jss.pkix.primitive.PrivateKeyInfo; -+import org.mozilla.jss.util.Password; -+ -+import netscape.ldap.LDAPDN; -+import netscape.security.x509.X509CertImpl; -+ -+public class PKCS12Util { -+ -+ private static Logger logger = Logger.getLogger(PKCS12Util.class.getName()); -+ -+ boolean trustFlagsEnabled = true; -+ -+ public boolean isTrustFlagsEnabled() { -+ return trustFlagsEnabled; -+ } -+ -+ public void setTrustFlagsEnabled(boolean trustFlagsEnabled) { -+ this.trustFlagsEnabled = trustFlagsEnabled; -+ } -+ -+ public String getTrustFlags(X509Certificate cert) { -+ -+ InternalCertificate icert = (InternalCertificate) cert; -+ -+ StringBuilder sb = new StringBuilder(); -+ -+ sb.append(PKCS12.encodeFlags(icert.getSSLTrust())); -+ sb.append(","); -+ sb.append(PKCS12.encodeFlags(icert.getEmailTrust())); -+ sb.append(","); -+ sb.append(PKCS12.encodeFlags(icert.getObjectSigningTrust())); -+ -+ return sb.toString(); -+ } -+ -+ public void setTrustFlags(X509Certificate cert, String trustFlags) throws Exception { -+ -+ InternalCertificate icert = (InternalCertificate) cert; -+ -+ String[] flags = trustFlags.split(","); -+ if (flags.length < 3) throw new Exception("Invalid trust flags: " + trustFlags); -+ -+ icert.setSSLTrust(PKCS12.decodeFlags(flags[0])); -+ icert.setEmailTrust(PKCS12.decodeFlags(flags[1])); -+ icert.setObjectSigningTrust(PKCS12.decodeFlags(flags[2])); -+ } -+ -+ byte[] getEncodedKey(PrivateKey privateKey) throws Exception { -+ -+ CryptoManager cm = CryptoManager.getInstance(); -+ CryptoToken token = cm.getInternalKeyStorageToken(); -+ -+ KeyGenerator kg = token.getKeyGenerator(KeyGenAlgorithm.DES3); -+ SymmetricKey sk = kg.generate(); -+ -+ KeyWrapper wrapper = token.getKeyWrapper(KeyWrapAlgorithm.DES3_CBC_PAD); -+ byte[] iv = { 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 }; -+ IVParameterSpec param = new IVParameterSpec(iv); -+ wrapper.initWrap(sk, param); -+ byte[] enckey = wrapper.wrap(privateKey); -+ -+ Cipher c = token.getCipherContext(EncryptionAlgorithm.DES3_CBC_PAD); -+ c.initDecrypt(sk, param); -+ return c.doFinal(enckey); -+ } -+ -+ public void addKeyBag(PKCS12KeyInfo keyInfo, Password password, -+ SEQUENCE encSafeContents) throws Exception { -+ -+ logger.fine("Creating key bag for " + keyInfo.subjectDN); -+ -+ PasswordConverter passConverter = new PasswordConverter(); -+ byte salt[] = { 0x01, 0x01, 0x01, 0x01 }; -+ -+ EncryptedPrivateKeyInfo encPrivateKeyInfo = EncryptedPrivateKeyInfo.createPBE( -+ PBEAlgorithm.PBE_SHA1_DES3_CBC, -+ password, salt, 1, passConverter, keyInfo.privateKeyInfo); -+ -+ SET keyAttrs = createKeyBagAttrs(keyInfo); -+ -+ SafeBag safeBag = new SafeBag(SafeBag.PKCS8_SHROUDED_KEY_BAG, encPrivateKeyInfo, keyAttrs); -+ encSafeContents.addElement(safeBag); -+ } -+ -+ public void addCertBag(PKCS12CertInfo certInfo, -+ SEQUENCE safeContents) throws Exception { -+ -+ logger.fine("Creating cert bag for " + certInfo.nickname); -+ -+ ASN1Value cert = new OCTET_STRING(certInfo.cert.getEncoded()); -+ CertBag certBag = new CertBag(CertBag.X509_CERT_TYPE, cert); -+ -+ SET certAttrs = createCertBagAttrs(certInfo); -+ -+ SafeBag safeBag = new SafeBag(SafeBag.CERT_BAG, certBag, certAttrs); -+ safeContents.addElement(safeBag); -+ } -+ -+ BigInteger createLocalID(X509Certificate cert) throws Exception { -+ -+ // SHA1 hash of the X509Cert DER encoding -+ byte[] certDer = cert.getEncoded(); -+ -+ MessageDigest md = MessageDigest.getInstance("SHA"); -+ -+ md.update(certDer); -+ return new BigInteger(1, md.digest()); -+ } -+ -+ SET createKeyBagAttrs(PKCS12KeyInfo keyInfo) throws Exception { -+ -+ SET attrs = new SET(); -+ -+ SEQUENCE subjectAttr = new SEQUENCE(); -+ subjectAttr.addElement(SafeBag.FRIENDLY_NAME); -+ -+ SET subjectSet = new SET(); -+ subjectSet.addElement(new BMPString(keyInfo.subjectDN)); -+ subjectAttr.addElement(subjectSet); -+ -+ attrs.addElement(subjectAttr); -+ -+ SEQUENCE localKeyAttr = new SEQUENCE(); -+ localKeyAttr.addElement(SafeBag.LOCAL_KEY_ID); -+ -+ SET localKeySet = new SET(); -+ localKeySet.addElement(new OCTET_STRING(keyInfo.id.toByteArray())); -+ localKeyAttr.addElement(localKeySet); -+ -+ attrs.addElement(localKeyAttr); -+ -+ return attrs; -+ } -+ -+ SET createCertBagAttrs(PKCS12CertInfo certInfo) throws Exception { -+ -+ SET attrs = new SET(); -+ -+ SEQUENCE nicknameAttr = new SEQUENCE(); -+ nicknameAttr.addElement(SafeBag.FRIENDLY_NAME); -+ -+ SET nicknameSet = new SET(); -+ nicknameSet.addElement(new BMPString(certInfo.nickname)); -+ nicknameAttr.addElement(nicknameSet); -+ -+ attrs.addElement(nicknameAttr); -+ -+ if (certInfo.getID() != null) { -+ SEQUENCE localKeyAttr = new SEQUENCE(); -+ localKeyAttr.addElement(SafeBag.LOCAL_KEY_ID); -+ -+ SET localKeySet = new SET(); -+ localKeySet.addElement(new OCTET_STRING(certInfo.id.toByteArray())); -+ localKeyAttr.addElement(localKeySet); -+ -+ attrs.addElement(localKeyAttr); -+ } -+ -+ if (certInfo.trustFlags != null && trustFlagsEnabled) { -+ SEQUENCE trustFlagsAttr = new SEQUENCE(); -+ trustFlagsAttr.addElement(PKCS12.CERT_TRUST_FLAGS_OID); -+ -+ SET trustFlagsSet = new SET(); -+ trustFlagsSet.addElement(new BMPString(certInfo.trustFlags)); -+ trustFlagsAttr.addElement(trustFlagsSet); -+ -+ attrs.addElement(trustFlagsAttr); -+ } -+ -+ return attrs; -+ } -+ -+ public void loadFromNSS(PKCS12 pkcs12) throws Exception { -+ -+ logger.info("Loading all certificate and keys from NSS database"); -+ -+ CryptoManager cm = CryptoManager.getInstance(); -+ CryptoToken token = cm.getInternalKeyStorageToken(); -+ CryptoStore store = token.getCryptoStore(); -+ -+ for (X509Certificate cert : store.getCertificates()) { -+ loadCertChainFromNSS(pkcs12, cert); -+ } -+ } -+ -+ public void loadCertFromNSS(PKCS12 pkcs12, String nickname) throws Exception { -+ -+ CryptoManager cm = CryptoManager.getInstance(); -+ -+ X509Certificate[] certs = cm.findCertsByNickname(nickname); -+ for (X509Certificate cert : certs) { -+ loadCertChainFromNSS(pkcs12, cert); -+ } -+ } -+ -+ public void loadCertFromNSS(PKCS12 pkcs12, X509Certificate cert, BigInteger id, boolean replace) throws Exception { -+ -+ String nickname = cert.getNickname(); -+ logger.info("Loading certificate \"" + nickname + "\" from NSS database"); -+ -+ PKCS12CertInfo certInfo = new PKCS12CertInfo(); -+ certInfo.id = id; -+ certInfo.nickname = nickname; -+ certInfo.cert = new X509CertImpl(cert.getEncoded()); -+ certInfo.trustFlags = getTrustFlags(cert); -+ -+ pkcs12.addCertInfo(certInfo, replace); -+ } -+ -+ public void loadCertKeyFromNSS(PKCS12 pkcs12, X509Certificate cert, BigInteger id) throws Exception { -+ -+ String nickname = cert.getNickname(); -+ logger.info("Loading private key for certificate \"" + nickname + "\" from NSS database"); -+ -+ CryptoManager cm = CryptoManager.getInstance(); -+ -+ try { -+ PrivateKey privateKey = cm.findPrivKeyByCert(cert); -+ logger.fine("Certificate \"" + nickname + "\" has private key"); -+ -+ PKCS12KeyInfo keyInfo = new PKCS12KeyInfo(); -+ keyInfo.id = id; -+ keyInfo.subjectDN = cert.getSubjectDN().toString(); -+ -+ byte[] privateData = getEncodedKey(privateKey); -+ keyInfo.privateKeyInfo = (PrivateKeyInfo) -+ ASN1Util.decode(PrivateKeyInfo.getTemplate(), privateData); -+ -+ pkcs12.addKeyInfo(keyInfo); -+ -+ } catch (ObjectNotFoundException e) { -+ logger.fine("Certificate \"" + nickname + "\" has no private key"); -+ } -+ } -+ -+ public void loadCertChainFromNSS(PKCS12 pkcs12, X509Certificate cert) throws Exception { -+ -+ CryptoManager cm = CryptoManager.getInstance(); -+ -+ BigInteger id = createLocalID(cert); -+ -+ // load cert key if exists -+ loadCertKeyFromNSS(pkcs12, cert, id); -+ -+ // load cert -+ loadCertFromNSS(pkcs12, cert, id, true); -+ -+ // load parent certs without key -+ X509Certificate[] certChain = cm.buildCertificateChain(cert); -+ for (int i = 1; i < certChain.length; i++) { -+ X509Certificate c = certChain[i]; -+ BigInteger cid = createLocalID(c); -+ loadCertFromNSS(pkcs12, c, cid, false); -+ } -+ } -+ -+ public void storeIntoFile(PKCS12 pkcs12, String filename, Password password) throws Exception { -+ -+ logger.info("Storing data into PKCS #12 file"); -+ -+ SEQUENCE safeContents = new SEQUENCE(); -+ -+ for (PKCS12CertInfo certInfo : pkcs12.getCertInfos()) { -+ addCertBag(certInfo, safeContents); -+ } -+ -+ SEQUENCE encSafeContents = new SEQUENCE(); -+ -+ for (PKCS12KeyInfo keyInfo : pkcs12.getKeyInfos()) { -+ addKeyBag(keyInfo, password, encSafeContents); -+ } -+ -+ AuthenticatedSafes authSafes = new AuthenticatedSafes(); -+ authSafes.addSafeContents(safeContents); -+ authSafes.addSafeContents(encSafeContents); -+ -+ PFX pfx = new PFX(authSafes); -+ pfx.computeMacData(password, null, 5); -+ -+ ByteArrayOutputStream bos = new ByteArrayOutputStream(); -+ pfx.encode(bos); -+ byte[] data = bos.toByteArray(); -+ -+ try (FileOutputStream fos = new FileOutputStream(filename)) { -+ fos.write(data); -+ } -+ } -+ -+ public PKCS12KeyInfo getKeyInfo(SafeBag bag, Password password) throws Exception { -+ -+ PKCS12KeyInfo keyInfo = new PKCS12KeyInfo(); -+ -+ // get private key info -+ EncryptedPrivateKeyInfo encPrivateKeyInfo = (EncryptedPrivateKeyInfo) bag.getInterpretedBagContent(); -+ keyInfo.privateKeyInfo = encPrivateKeyInfo.decrypt(password, new PasswordConverter()); -+ -+ // get key attributes -+ SET bagAttrs = bag.getBagAttributes(); -+ -+ for (int i = 0; i < bagAttrs.size(); i++) { -+ -+ Attribute attr = (Attribute) bagAttrs.elementAt(i); -+ OBJECT_IDENTIFIER oid = attr.getType(); -+ -+ if (oid.equals(SafeBag.FRIENDLY_NAME)) { -+ -+ SET values = attr.getValues(); -+ ANY value = (ANY) values.elementAt(0); -+ -+ ByteArrayInputStream bis = new ByteArrayInputStream(value.getEncoded()); -+ BMPString subjectDN = (BMPString) new BMPString.Template().decode(bis); -+ -+ keyInfo.subjectDN = subjectDN.toString(); -+ logger.fine("Subject DN: " + keyInfo.subjectDN); -+ -+ } else if (oid.equals(SafeBag.LOCAL_KEY_ID)) { -+ -+ SET values = attr.getValues(); -+ ANY value = (ANY) values.elementAt(0); -+ -+ ByteArrayInputStream bis = new ByteArrayInputStream(value.getEncoded()); -+ OCTET_STRING keyID = (OCTET_STRING) new OCTET_STRING.Template().decode(bis); -+ -+ keyInfo.id = new BigInteger(1, keyID.toByteArray()); -+ logger.fine("ID: " + keyInfo.id.toString(16)); -+ } -+ } -+ -+ logger.fine("Found private key " + keyInfo.subjectDN); -+ -+ return keyInfo; -+ } -+ -+ public PKCS12CertInfo getCertInfo(SafeBag bag) throws Exception { -+ -+ PKCS12CertInfo certInfo = new PKCS12CertInfo(); -+ -+ CertBag certBag = (CertBag) bag.getInterpretedBagContent(); -+ -+ OCTET_STRING certStr = (OCTET_STRING) certBag.getInterpretedCert(); -+ byte[] x509cert = certStr.toByteArray(); -+ -+ certInfo.cert = new X509CertImpl(x509cert); -+ logger.fine("Found certificate " + certInfo.cert.getSubjectDN()); -+ -+ SET bagAttrs = bag.getBagAttributes(); -+ if (bagAttrs == null) return certInfo; -+ -+ for (int i = 0; i < bagAttrs.size(); i++) { -+ -+ Attribute attr = (Attribute) bagAttrs.elementAt(i); -+ OBJECT_IDENTIFIER oid = attr.getType(); -+ -+ if (oid.equals(SafeBag.FRIENDLY_NAME)) { -+ -+ SET values = attr.getValues(); -+ ANY value = (ANY) values.elementAt(0); -+ -+ ByteArrayInputStream bis = new ByteArrayInputStream(value.getEncoded()); -+ BMPString nickname = (BMPString) (new BMPString.Template()).decode(bis); -+ -+ certInfo.nickname = nickname.toString(); -+ logger.fine("Nickname: " + certInfo.nickname); -+ -+ -+ } else if (oid.equals(SafeBag.LOCAL_KEY_ID)) { -+ -+ SET values = attr.getValues(); -+ ANY value = (ANY) values.elementAt(0); -+ -+ ByteArrayInputStream bis = new ByteArrayInputStream(value.getEncoded()); -+ OCTET_STRING keyID = (OCTET_STRING) new OCTET_STRING.Template().decode(bis); -+ -+ certInfo.id = new BigInteger(1, keyID.toByteArray()); -+ logger.fine("ID: " + certInfo.id.toString(16)); -+ -+ } else if (oid.equals(PKCS12.CERT_TRUST_FLAGS_OID) && trustFlagsEnabled) { -+ -+ SET values = attr.getValues(); -+ ANY value = (ANY) values.elementAt(0); -+ -+ ByteArrayInputStream is = new ByteArrayInputStream(value.getEncoded()); -+ BMPString trustFlags = (BMPString) (new BMPString.Template()).decode(is); -+ -+ certInfo.trustFlags = trustFlags.toString(); -+ logger.fine("Trust flags: " + certInfo.trustFlags); -+ } -+ } -+ -+ return certInfo; -+ } -+ -+ public void getKeyInfos(PKCS12 pkcs12, PFX pfx, Password password) throws Exception { -+ -+ logger.fine("Getting private keys"); -+ -+ AuthenticatedSafes safes = pfx.getAuthSafes(); -+ -+ for (int i = 0; i < safes.getSize(); i++) { -+ -+ SEQUENCE contents = safes.getSafeContentsAt(password, i); -+ -+ for (int j = 0; j < contents.size(); j++) { -+ -+ SafeBag bag = (SafeBag) contents.elementAt(j); -+ OBJECT_IDENTIFIER oid = bag.getBagType(); -+ -+ if (!oid.equals(SafeBag.PKCS8_SHROUDED_KEY_BAG)) continue; -+ -+ PKCS12KeyInfo keyInfo = getKeyInfo(bag, password); -+ pkcs12.addKeyInfo(keyInfo); -+ } -+ } -+ } -+ -+ public void getCertInfos(PKCS12 pkcs12, PFX pfx, Password password) throws Exception { -+ -+ logger.fine("Getting certificates"); -+ -+ AuthenticatedSafes safes = pfx.getAuthSafes(); -+ -+ for (int i = 0; i < safes.getSize(); i++) { -+ -+ SEQUENCE contents = safes.getSafeContentsAt(password, i); -+ -+ for (int j = 0; j < contents.size(); j++) { -+ -+ SafeBag bag = (SafeBag) contents.elementAt(j); -+ OBJECT_IDENTIFIER oid = bag.getBagType(); -+ -+ if (!oid.equals(SafeBag.CERT_BAG)) continue; -+ -+ PKCS12CertInfo certInfo = getCertInfo(bag); -+ pkcs12.addCertInfo(certInfo, true); -+ } -+ } -+ } -+ -+ public PKCS12 loadFromFile(String filename, Password password) throws Exception { -+ -+ logger.info("Loading PKCS #12 file"); -+ -+ Path path = Paths.get(filename); -+ byte[] b = Files.readAllBytes(path); -+ -+ ByteArrayInputStream bis = new ByteArrayInputStream(b); -+ -+ PFX pfx = (PFX) (new PFX.Template()).decode(bis); -+ -+ PKCS12 pkcs12 = new PKCS12(); -+ -+ StringBuffer reason = new StringBuffer(); -+ boolean valid = pfx.verifyAuthSafes(password, reason); -+ -+ if (!valid) { -+ throw new Exception("Invalid PKCS #12 password: " + reason); -+ } -+ -+ getKeyInfos(pkcs12, pfx, password); -+ getCertInfos(pkcs12, pfx, password); -+ -+ return pkcs12; -+ } -+ -+ public PKCS12 loadFromFile(String filename) throws Exception { -+ return loadFromFile(filename, null); -+ } -+ -+ public PrivateKey.Type getPrivateKeyType(PublicKey publicKey) { -+ if (publicKey.getAlgorithm().equals("EC")) { -+ return PrivateKey.Type.EC; -+ } -+ return PrivateKey.Type.RSA; -+ } -+ -+ public PKCS12CertInfo getCertBySubjectDN(PKCS12 pkcs12, String subjectDN) -+ throws CertificateException { -+ -+ for (PKCS12CertInfo certInfo : pkcs12.getCertInfos()) { -+ Principal certSubjectDN = certInfo.cert.getSubjectDN(); -+ if (LDAPDN.equals(certSubjectDN.toString(), subjectDN)) return certInfo; -+ } -+ -+ return null; -+ } -+ -+ public void importKey( -+ PKCS12 pkcs12, -+ PKCS12KeyInfo keyInfo) throws Exception { -+ -+ logger.fine("Importing private key " + keyInfo.subjectDN); -+ -+ PrivateKeyInfo privateKeyInfo = keyInfo.privateKeyInfo; -+ -+ // encode private key -+ ByteArrayOutputStream bos = new ByteArrayOutputStream(); -+ privateKeyInfo.encode(bos); -+ byte[] privateKey = bos.toByteArray(); -+ -+ PKCS12CertInfo certInfo = getCertBySubjectDN(pkcs12, keyInfo.subjectDN); -+ if (certInfo == null) { -+ logger.fine("Private key nas no certificate, ignore"); -+ return; -+ } -+ -+ CryptoManager cm = CryptoManager.getInstance(); -+ CryptoToken token = cm.getInternalKeyStorageToken(); -+ CryptoStore store = token.getCryptoStore(); -+ -+ X509Certificate cert = cm.importCACertPackage(certInfo.cert.getEncoded()); -+ -+ // get public key -+ PublicKey publicKey = cert.getPublicKey(); -+ -+ // delete the cert again -+ try { -+ store.deleteCert(cert); -+ } catch (NoSuchItemOnTokenException e) { -+ // this is OK -+ } -+ -+ // encrypt private key -+ KeyGenerator kg = token.getKeyGenerator(KeyGenAlgorithm.DES3); -+ SymmetricKey sk = kg.generate(); -+ byte iv[] = { 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 }; -+ IVParameterSpec param = new IVParameterSpec(iv); -+ Cipher c = token.getCipherContext(EncryptionAlgorithm.DES3_CBC_PAD); -+ c.initEncrypt(sk, param); -+ byte[] encpkey = c.doFinal(privateKey); -+ -+ // unwrap private key to load into database -+ KeyWrapper wrapper = token.getKeyWrapper(KeyWrapAlgorithm.DES3_CBC_PAD); -+ wrapper.initUnwrap(sk, param); -+ wrapper.unwrapPrivate(encpkey, getPrivateKeyType(publicKey), publicKey); -+ } -+ -+ public void storeCertIntoNSS(PKCS12 pkcs12, PKCS12CertInfo certInfo) throws Exception { -+ -+ CryptoManager cm = CryptoManager.getInstance(); -+ -+ X509Certificate cert; -+ BigInteger id = certInfo.getID(); -+ PKCS12KeyInfo keyInfo = pkcs12.getKeyInfoByID(id); -+ -+ if (keyInfo != null) { // cert has key -+ logger.fine("Importing user key for " + certInfo.nickname); -+ importKey(pkcs12, keyInfo); -+ -+ logger.fine("Importing user certificate " + certInfo.nickname); -+ cert = cm.importUserCACertPackage(certInfo.cert.getEncoded(), certInfo.nickname); -+ -+ } else { // cert has no key -+ logger.fine("Importing CA certificate " + certInfo.nickname); -+ // Note: JSS does not preserve CA certificate nickname -+ cert = cm.importCACertPackage(certInfo.cert.getEncoded()); -+ } -+ -+ if (certInfo.trustFlags != null && trustFlagsEnabled) -+ setTrustFlags(cert, certInfo.trustFlags); -+ } -+ -+ public void storeCertIntoNSS(PKCS12 pkcs12, String nickname) throws Exception { -+ Collection certInfos = pkcs12.getCertInfosByNickname(nickname); -+ for (PKCS12CertInfo certInfo : certInfos) { -+ storeCertIntoNSS(pkcs12, certInfo); -+ } -+ } -+ -+ public void storeIntoNSS(PKCS12 pkcs12) throws Exception { -+ -+ logger.info("Storing data into NSS database"); -+ -+ for (PKCS12CertInfo certInfo : pkcs12.getCertInfos()) { -+ storeCertIntoNSS(pkcs12, certInfo); -+ } -+ } -+} --- -2.4.3 - diff --git a/SOURCES/pki-core-Added-support-for-existing-CA-case.patch b/SOURCES/pki-core-Added-support-for-existing-CA-case.patch deleted file mode 100644 index bc1da13..0000000 --- a/SOURCES/pki-core-Added-support-for-existing-CA-case.patch +++ /dev/null @@ -1,1698 +0,0 @@ -From 0a7411f3bf1e65d2e0897c2504f376d8cf0c59af Mon Sep 17 00:00:00 2001 -From: "Endi S. Dewata" -Date: Thu, 12 Nov 2015 00:23:26 +0100 -Subject: [PATCH] Added support for existing CA case. - -The deployment procedure for external CA has been modified -such that it generates the CA CSR before starting the server. -This allows the same procedure to be used to import CA -certificate from an existing server. It also removes the -requirement to keep the server running while waiting to get -the CSR signed by an external CA. - -The pki ca-cert-request-submit command has been modified to -provide options to specify the profile name and the CSR which -will be used to create and populate the request object. This -way it's no longer necessary to download the request template -and insert the CSR manually. - -A new pki-server subsystem-cert-export command has been added -to export a system certificate, the CSR, and the key. This -command can be used to migrate a system certificate into another -instance. - -The man page have been updated to reflect these changes. - -The installation code for external CA case has been fixed such -that IPA can detect step 1 completion properly. - -The code that handles certificate data conversion has been fixed -to reformat base-64 data for PEM output properly. - -The installation summary for step 1 has been updated to provide -more accurate information. - -https://fedorahosted.org/pki/ticket/456 ---- - base/common/python/pki/nssdb.py | 532 +++++++++++++++++++++ - .../certsrv/system/ConfigurationRequest.java | 12 + - base/java-tools/man/man1/pki-cert.1 | 23 +- - .../cmstools/cert/CertRequestSubmitCLI.java | 170 ++++++- - .../cms/servlet/csadmin/ConfigurationUtils.java | 101 ++++ - .../dogtagpki/server/rest/SystemConfigService.java | 38 +- - base/server/etc/default.cfg | 10 +- - base/server/python/pki/server/__init__.py | 7 + - base/server/python/pki/server/cli/subsystem.py | 126 +++++ - .../python/pki/server/deployment/pkihelper.py | 77 +-- - .../server/deployment/scriptlets/configuration.py | 132 ++++- - .../server/deployment/scriptlets/finalization.py | 12 +- - base/server/sbin/pkispawn | 39 +- - 13 files changed, 1211 insertions(+), 68 deletions(-) - create mode 100644 base/common/python/pki/nssdb.py - -diff --git a/base/common/python/pki/nssdb.py b/base/common/python/pki/nssdb.py -new file mode 100644 -index 0000000000000000000000000000000000000000..44e286853c252675bff9e25c32377aaa86f8cf18 ---- /dev/null -+++ b/base/common/python/pki/nssdb.py -@@ -0,0 +1,532 @@ -+# 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. -+# -+ -+import base64 -+import os -+import shutil -+import subprocess -+import tempfile -+ -+ -+CSR_HEADER = '-----BEGIN NEW CERTIFICATE REQUEST-----' -+CSR_FOOTER = '-----END NEW CERTIFICATE REQUEST-----' -+ -+CERT_HEADER = '-----BEGIN CERTIFICATE-----' -+CERT_FOOTER = '-----END CERTIFICATE-----' -+ -+PKCS7_HEADER = '-----BEGIN PKCS7-----' -+PKCS7_FOOTER = '-----END PKCS7-----' -+ -+ -+def convert_data(data, input_format, output_format, header=None, footer=None): -+ -+ if input_format == output_format: -+ return data -+ -+ if input_format == 'base64' and output_format == 'pem': -+ -+ # join base-64 data into a single line -+ data = data.replace('\r', '').replace('\n', '') -+ -+ # re-split the line into fixed-length lines -+ lines = [data[i:i+64] for i in range(0, len(data), 64)] -+ -+ # add header and footer -+ return '%s\n%s\n%s\n' % (header, '\n'.join(lines), footer) -+ -+ if input_format == 'pem' and output_format == 'base64': -+ -+ # join multiple lines into a single line -+ lines = [] -+ for line in data.splitlines(): -+ line = line.rstrip('\r\n') -+ if line == header: -+ continue -+ if line == footer: -+ continue -+ lines.append(line) -+ -+ return ''.join(lines) -+ -+ raise Exception('Unable to convert data from %s to %s' % (input_format, output_format)) -+ -+def convert_csr(csr_data, input_format, output_format): -+ -+ return convert_data(csr_data, input_format, output_format, CSR_HEADER, CSR_FOOTER) -+ -+def convert_cert(cert_data, input_format, output_format): -+ -+ return convert_data(cert_data, input_format, output_format, CERT_HEADER, CERT_FOOTER) -+ -+def convert_pkcs7(pkcs7_data, input_format, output_format): -+ -+ return convert_data(pkcs7_data, input_format, output_format, PKCS7_HEADER, PKCS7_FOOTER) -+ -+def get_file_type(filename): -+ -+ with open(filename, 'r') as f: -+ data = f.read() -+ -+ if data.startswith(CSR_HEADER): -+ return 'csr' -+ -+ if data.startswith(CERT_HEADER): -+ return 'cert' -+ -+ if data.startswith(PKCS7_HEADER): -+ return 'pkcs7' -+ -+ return None -+ -+ -+class NSSDatabase(object): -+ -+ def __init__(self, directory, token='internal', password=None, password_file=None): -+ self.directory = directory -+ self.token = token -+ -+ self.tmpdir = tempfile.mkdtemp() -+ -+ if password: -+ self.password_file = os.path.join(self.tmpdir, 'password.txt') -+ with open(self.password_file, 'w') as f: -+ f.write(password) -+ -+ elif password_file: -+ self.password_file = password_file -+ -+ else: -+ raise Exception('Missing NSS database password') -+ -+ def close(self): -+ shutil.rmtree(self.tmpdir) -+ -+ def add_cert(self, -+ nickname, -+ cert_file, -+ trust_attributes=',,'): -+ -+ cmd = [ -+ 'certutil', -+ '-A', -+ '-d', self.directory, -+ '-h', self.token, -+ '-f', self.password_file, -+ '-n', nickname, -+ '-i', cert_file, -+ '-t', trust_attributes -+ ] -+ -+ subprocess.check_call(cmd) -+ -+ def modify_cert(self, -+ nickname, -+ trust_attributes): -+ -+ cmd = [ -+ 'certutil', -+ '-M', -+ '-d', self.directory, -+ '-h', self.token, -+ '-f', self.password_file, -+ '-n', nickname, -+ '-t', trust_attributes -+ ] -+ -+ subprocess.check_call(cmd) -+ -+ def create_noise(self, noise_file, size=2048): -+ -+ subprocess.check_call([ -+ 'openssl', -+ 'rand', -+ '-out', noise_file, -+ str(size) -+ ]) -+ -+ def create_request(self, -+ subject_dn, -+ request_file, -+ noise_file=None, -+ key_type=None, -+ key_size=None, -+ curve=None, -+ hash_alg=None): -+ -+ tmpdir = tempfile.mkdtemp() -+ -+ try: -+ if not noise_file: -+ noise_file = os.path.join(tmpdir, 'noise.bin') -+ if key_size: -+ size = key_size -+ else: -+ size = 2048 -+ self.create_noise( -+ noise_file=noise_file, -+ size=size) -+ -+ binary_request_file = os.path.join(tmpdir, 'request.bin') -+ -+ cmd = [ -+ 'certutil', -+ '-R', -+ '-d', self.directory, -+ '-h', self.token, -+ '-f', self.password_file, -+ '-s', subject_dn, -+ '-o', binary_request_file, -+ '-z', noise_file -+ ] -+ -+ if key_type: -+ cmd.extend(['-k', key_type]) -+ -+ if key_size: -+ cmd.extend(['-g', str(key_size)]) -+ -+ if curve: -+ cmd.extend(['-q', curve]) -+ -+ if hash_alg: -+ cmd.extend(['-Z', hash_alg]) -+ -+ # generate binary request -+ subprocess.check_call(cmd) -+ -+ # encode binary request in base-64 -+ b64_request_file = os.path.join(tmpdir, 'request.b64') -+ subprocess.check_call([ -+ 'BtoA', binary_request_file, b64_request_file]) -+ -+ # read base-64 request -+ with open(b64_request_file, 'r') as f: -+ b64_request = f.read() -+ -+ # add header and footer -+ with open(request_file, 'w') as f: -+ f.write('-----BEGIN NEW CERTIFICATE REQUEST-----\n') -+ f.write(b64_request) -+ f.write('-----END NEW CERTIFICATE REQUEST-----\n') -+ -+ finally: -+ shutil.rmtree(tmpdir) -+ -+ def create_self_signed_ca_cert(self, -+ subject_dn, -+ request_file, -+ cert_file, -+ serial='1', -+ validity=240): -+ -+ cmd = [ -+ 'certutil', -+ '-C', -+ '-x', -+ '-d', self.directory, -+ '-h', self.token, -+ '-f', self.password_file, -+ '-c', subject_dn, -+ '-a', -+ '-i', request_file, -+ '-o', cert_file, -+ '-m', serial, -+ '-v', str(validity), -+ '--keyUsage', 'digitalSignature,nonRepudiation,certSigning,crlSigning,critical', -+ '-2', -+ '-3', -+ '--extSKID', -+ '--extAIA' -+ ] -+ -+ p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) -+ -+ keystroke = '' -+ -+ # Is this a CA certificate [y/N]? -+ keystroke += 'y\n' -+ -+ # Enter the path length constraint, enter to skip [<0 for unlimited path]: -+ keystroke += '\n' -+ -+ # Is this a critical extension [y/N]? -+ keystroke += 'y\n' -+ -+ # Enter value for the authKeyID extension [y/N]? -+ keystroke += 'y\n' -+ -+ # TODO: generate SHA1 ID (see APolicyRule.formSHA1KeyId()) -+ # Enter value for the key identifier fields,enter to omit: -+ keystroke += '2d:7e:83:37:75:5a:fd:0e:8d:52:a3:70:16:93:36:b8:4a:d6:84:9f\n' -+ -+ # Select one of the following general name type: -+ keystroke += '0\n' -+ -+ # Enter value for the authCertSerial field, enter to omit: -+ keystroke += '\n' -+ -+ # Is this a critical extension [y/N]? -+ keystroke += '\n' -+ -+ # TODO: generate SHA1 ID (see APolicyRule.formSHA1KeyId()) -+ # Adding Subject Key ID extension. -+ # Enter value for the key identifier fields,enter to omit: -+ keystroke += '2d:7e:83:37:75:5a:fd:0e:8d:52:a3:70:16:93:36:b8:4a:d6:84:9f\n' -+ -+ # Is this a critical extension [y/N]? -+ keystroke += '\n' -+ -+ # Enter access method type for Authority Information Access extension: -+ keystroke += '2\n' -+ -+ # Select one of the following general name type: -+ keystroke += '7\n' -+ -+ # TODO: replace with actual hostname name and port number -+ # Enter data: -+ keystroke += 'http://server.example.com:8080/ca/ocsp\n' -+ -+ # Select one of the following general name type: -+ keystroke += '0\n' -+ -+ # Add another location to the Authority Information Access extension [y/N] -+ keystroke += '\n' -+ -+ # Is this a critical extension [y/N]? -+ keystroke += '\n' -+ -+ p.communicate(keystroke) -+ -+ rc = p.wait() -+ -+ if rc: -+ raise Exception('Failed to generate self-signed CA certificate. RC: %d' % rc) -+ -+ def get_cert(self, nickname, output_format='pem'): -+ -+ if output_format == 'pem': -+ output_format_option = '-a' -+ -+ elif output_format == 'base64': -+ output_format_option = '-r' -+ -+ else: -+ raise Exception('Unsupported output format: %s' % output_format) -+ -+ cmd = [ -+ 'certutil', -+ '-L', -+ '-d', self.directory, -+ '-h', self.token, -+ '-f', self.password_file, -+ '-n', nickname, -+ output_format_option -+ ] -+ -+ cert_data = subprocess.check_output(cmd) -+ -+ if output_format == 'base64': -+ cert_data = base64.b64encode(cert_data) -+ -+ return cert_data -+ -+ def remove_cert(self, nickname): -+ -+ cmd = [ -+ 'certutil', -+ '-D', -+ '-d', self.directory, -+ '-h', self.token, -+ '-f', self.password_file, -+ '-n', nickname -+ ] -+ -+ subprocess.check_call(cmd) -+ -+ def import_cert_chain(self, nickname, cert_chain_file, trust_attributes=None): -+ -+ tmpdir = tempfile.mkdtemp() -+ -+ try: -+ file_type = get_file_type(cert_chain_file) -+ -+ if file_type == 'cert': # import single PEM cert -+ self.add_cert( -+ nickname=nickname, -+ cert_file=cert_chain_file, -+ trust_attributes=trust_attributes) -+ return self.get_cert( -+ nickname=nickname, -+ output_format='base64') -+ -+ elif file_type == 'pkcs7': # import PKCS #7 cert chain -+ return self.import_pkcs7( -+ pkcs7_file=cert_chain_file, -+ nickname=nickname, -+ trust_attributes=trust_attributes, -+ output_format='base64') -+ -+ else: # import PKCS #7 data without header/footer -+ with open(cert_chain_file, 'r') as f: -+ base64_data = f.read() -+ pkcs7_data = convert_pkcs7(base64_data, 'base64', 'pem') -+ -+ tmp_cert_chain_file = os.path.join(tmpdir, 'cert_chain.p7b') -+ with open(tmp_cert_chain_file, 'w') as f: -+ f.write(pkcs7_data) -+ -+ self.import_pkcs7( -+ pkcs7_file=tmp_cert_chain_file, -+ nickname=nickname, -+ trust_attributes=trust_attributes) -+ -+ return base64_data -+ -+ finally: -+ shutil.rmtree(tmpdir) -+ -+ def import_pkcs7(self, pkcs7_file, nickname, trust_attributes=None, output_format='pem'): -+ -+ tmpdir = tempfile.mkdtemp() -+ -+ try: -+ # export certs from PKCS #7 into PEM output -+ output = subprocess.check_output([ -+ 'openssl', -+ 'pkcs7', -+ '-print_certs', -+ '-in', pkcs7_file -+ ]) -+ -+ # parse PEM output into separate PEM certificates -+ certs = [] -+ lines = [] -+ state = 'header' -+ -+ for line in output.splitlines(): -+ -+ if state == 'header': -+ if line != CERT_HEADER: -+ # ignore header lines -+ pass -+ else: -+ # save cert header -+ lines.append(line) -+ state = 'body' -+ -+ elif state == 'body': -+ if line != CERT_FOOTER: -+ # save cert body -+ lines.append(line) -+ else: -+ # save cert footer -+ lines.append(line) -+ -+ # construct PEM cert -+ cert = '\n'.join(lines) -+ certs.append(cert) -+ lines = [] -+ state = 'header' -+ -+ # import PEM certs into NSS database -+ counter = 1 -+ for cert in certs: -+ -+ cert_file = os.path.join(tmpdir, 'cert%d.pem' % counter) -+ with open(cert_file, 'w') as f: -+ f.write(cert) -+ -+ if counter == 1: -+ n = nickname -+ else: -+ n = '%s #%d' % (nickname, counter) -+ -+ self.add_cert(n, cert_file, trust_attributes) -+ -+ counter += 1 -+ -+ # convert PKCS #7 data to the requested format -+ with open(pkcs7_file, 'r') as f: -+ data = f.read() -+ -+ return convert_pkcs7(data, 'pem', output_format) -+ -+ finally: -+ shutil.rmtree(tmpdir) -+ -+ def import_pkcs12(self, pkcs12_file, pkcs12_password=None, pkcs12_password_file=None): -+ -+ tmpdir = tempfile.mkdtemp() -+ -+ try: -+ if pkcs12_password: -+ password_file = os.path.join(tmpdir, 'password.txt') -+ with open(password_file, 'w') as f: -+ f.write(pkcs12_password) -+ -+ elif pkcs12_password_file: -+ password_file = pkcs12_password_file -+ -+ else: -+ raise Exception('Missing PKCS #12 password') -+ -+ cmd = [ -+ 'pk12util', -+ '-d', self.directory, -+ '-h', self.token, -+ '-k', self.password_file, -+ '-i', pkcs12_file, -+ '-w', password_file -+ ] -+ -+ subprocess.check_call(cmd) -+ -+ finally: -+ shutil.rmtree(tmpdir) -+ -+ def export_pkcs12(self, pkcs12_file, nickname, pkcs12_password=None, pkcs12_password_file=None): -+ -+ tmpdir = tempfile.mkdtemp() -+ -+ try: -+ if pkcs12_password: -+ password_file = os.path.join(tmpdir, 'password.txt') -+ with open(password_file, 'w') as f: -+ f.write(pkcs12_password) -+ -+ elif pkcs12_password_file: -+ password_file = pkcs12_password_file -+ -+ else: -+ raise Exception('Missing PKCS #12 password') -+ -+ cmd = [ -+ 'pk12util', -+ '-d', self.directory, -+ '-k', self.password_file, -+ '-o', pkcs12_file, -+ '-w', password_file, -+ '-n', nickname -+ ] -+ -+ subprocess.check_call(cmd) -+ -+ finally: -+ shutil.rmtree(tmpdir) -diff --git a/base/common/src/com/netscape/certsrv/system/ConfigurationRequest.java b/base/common/src/com/netscape/certsrv/system/ConfigurationRequest.java -index 0682ac98f151f5405764636e77971974a91eed8c..f3f0f5072208ffd5dd5983b4b122c3e909c48db3 100644 ---- a/base/common/src/com/netscape/certsrv/system/ConfigurationRequest.java -+++ b/base/common/src/com/netscape/certsrv/system/ConfigurationRequest.java -@@ -175,6 +175,9 @@ public class ConfigurationRequest { - protected String adminCert; - - @XmlElement -+ protected Boolean external; -+ -+ @XmlElement - protected String standAlone; - - @XmlElement -@@ -739,6 +742,14 @@ public class ConfigurationRequest { - this.adminCert = adminCert; - } - -+ public Boolean isExternal() { -+ return external; -+ } -+ -+ public void setExternal(Boolean external) { -+ this.external = external; -+ } -+ - public boolean getStandAlone() { - return (standAlone != null && standAlone.equalsIgnoreCase("true")); - } -@@ -930,6 +941,7 @@ public class ConfigurationRequest { - ", adminCert=" + adminCert + - ", importAdminCert=" + importAdminCert + - ", generateServerCert=" + generateServerCert + -+ ", external=" + external + - ", standAlone=" + standAlone + - ", stepTwo=" + stepTwo + - ", authdbBaseDN=" + authdbBaseDN + -diff --git a/base/java-tools/man/man1/pki-cert.1 b/base/java-tools/man/man1/pki-cert.1 -index ffa1fea5d0a29a5b425b1fcaa497e8b831251f7f..7ece1ad7bfc277a4093acdee9592d8671b00b6bd 100644 ---- a/base/java-tools/man/man1/pki-cert.1 -+++ b/base/java-tools/man/man1/pki-cert.1 -@@ -191,23 +191,32 @@ To release a certificate that has been placed on hold: - .B pki ca-cert-release-hold - - .SS Certificate Requests --To request a certificate, first generate a certificate request in PKCS #10 or CRMF, and store this request in the XML template file, of the profile type the request relates to. - --The list of profiles can be viewed using the CLI command: -+To request a certificate, first generate a certificate signing request (CSR), -+then submit it with a certificate profile. The list of available profiles can -+be viewed using the following command: - - .B pki ca-cert-request-profile-find - --The XML template file for a profile type can be created by calling the ca-cert-request-profile-show CLI command. For example: -+To generate a CSR, use the certutil, PKCS10Client, or -+CRMFPopClient, and store it into a file. - --\fBpki ca-cert-request-profile-show \-\-output \fP -+Basic requests can be submitted using the following command: - --will store the XML template of the request in the specified output file. -+.B pki ca-cert-request-submit --profile --request-type --csr-file --subject - --Then, fill in the values in the XML file and submit the request for review. This can be done without authentication. -+To submit more advanced requests, download a template of the request file for -+a particular profile using the following command: -+ -+.B pki ca-cert-request-profile-show \-\-output -+ -+Then, edit the request file, fill in the input attributes required by the -+profile, and submit the request using the following command: - - .B pki ca-cert-request-submit - --Then, an agent needs to review the request by running the following command: -+Depending on the profile, an agent may need to review the request by running -+the following command: - - .B pki ca-cert-request-review --file - -diff --git a/base/java-tools/src/com/netscape/cmstools/cert/CertRequestSubmitCLI.java b/base/java-tools/src/com/netscape/cmstools/cert/CertRequestSubmitCLI.java -index 608490bb73d7df482d87e67e9c15322ddc2e5f5a..7a1f08ff3d51e785bef8b625c17082ed81efbdfd 100644 ---- a/base/java-tools/src/com/netscape/cmstools/cert/CertRequestSubmitCLI.java -+++ b/base/java-tools/src/com/netscape/cmstools/cert/CertRequestSubmitCLI.java -@@ -3,17 +3,22 @@ package com.netscape.cmstools.cert; - import java.io.File; - import java.io.FileNotFoundException; - import java.util.Arrays; -+import java.util.HashMap; -+import java.util.Map; - import java.util.Scanner; -- --import javax.xml.bind.JAXBException; -+import java.util.Vector; - - import org.apache.commons.cli.CommandLine; -+import org.apache.commons.cli.Option; - import org.apache.commons.cli.ParseException; - - import com.netscape.certsrv.cert.CertEnrollmentRequest; --import com.netscape.certsrv.cert.CertRequestInfos; -+import com.netscape.certsrv.profile.ProfileAttribute; -+import com.netscape.certsrv.profile.ProfileInput; - import com.netscape.cmstools.cli.CLI; --import com.netscape.cmstools.cli.MainCLI; -+ -+import netscape.ldap.util.DN; -+import netscape.ldap.util.RDN; - - public class CertRequestSubmitCLI extends CLI { - -@@ -22,6 +27,37 @@ public class CertRequestSubmitCLI extends CLI { - public CertRequestSubmitCLI(CertCLI certCLI) { - super("request-submit", "Submit certificate request", certCLI); - this.certCLI = certCLI; -+ -+ Option option = new Option(null, "issuer-id", true, "Authority ID (host authority if omitted)"); -+ option.setArgName("ID"); -+ options.addOption(option); -+ -+ option = new Option(null, "issuer-dn", true, "Authority DN (host authority if omitted)"); -+ option.setArgName("DN"); -+ options.addOption(option); -+ -+ option = new Option(null, "username", true, "Username for request authentication"); -+ option.setArgName("username"); -+ options.addOption(option); -+ -+ option = new Option(null, "password", false, "Prompt password for request authentication"); -+ options.addOption(option); -+ -+ option = new Option(null, "profile", true, "Certificate profile"); -+ option.setArgName("profile"); -+ options.addOption(option); -+ -+ option = new Option(null, "request-type", true, "Request type (default: pkcs10)"); -+ option.setArgName("type"); -+ options.addOption(option); -+ -+ option = new Option(null, "csr-file", true, "File containing the CSR"); -+ option.setArgName("path"); -+ options.addOption(option); -+ -+ option = new Option(null, "subject", true, "Subject DN"); -+ option.setArgName("DN"); -+ options.addOption(option); - } - - public void printHelp() { -@@ -29,7 +65,7 @@ public class CertRequestSubmitCLI extends CLI { - } - - @Override -- public void execute(String[] args) { -+ public void execute(String[] args) throws Exception { - // Always check for "--help" prior to parsing - if (Arrays.asList(args).contains("--help")) { - // Display usage -@@ -49,32 +85,124 @@ public class CertRequestSubmitCLI extends CLI { - - String[] cmdArgs = cmd.getArgs(); - -- if (cmdArgs.length < 1) { -- System.err.println("Error: No filename specified."); -+ String requestFilename = cmdArgs.length > 0 ? cmdArgs[0] : null; -+ String profileID = cmd.getOptionValue("profile"); -+ -+ if (requestFilename == null && profileID == null) { -+ System.err.println("Error: Missing request file or profile ID."); - printHelp(); - System.exit(-1); - } - -- try { -- CertEnrollmentRequest erd = getEnrollmentRequest(cmdArgs[0]); -- CertRequestInfos cri = certCLI.certClient.enrollRequest(erd); -- MainCLI.printMessage("Submitted certificate request"); -- CertCLI.printCertRequestInfos(cri); -- -- } catch (FileNotFoundException e) { -- System.err.println("Error: " + e.getMessage()); -+ if (requestFilename != null && profileID != null) { -+ System.err.println("Error: Request file and profile ID are mutually exclusive."); -+ printHelp(); - System.exit(-1); -+ } - -- } catch (JAXBException e) { -- System.err.println("Error: " + e.getMessage()); -- System.exit(-1); -+ String requestType = cmd.getOptionValue("request-type"); -+ -+ CertEnrollmentRequest request; -+ if (requestFilename == null) { // if no request file specified, generate new request from profile -+ -+ if (verbose) { -+ System.out.println("Retrieving " + profileID + " profile."); -+ } -+ -+ request = certCLI.certClient.getEnrollmentTemplate(profileID); -+ -+ // set default request type for new request -+ if (requestType == null) requestType = "pkcs10"; -+ -+ } else { // otherwise, load request from file -+ -+ if (verbose) { -+ System.out.println("Loading request from " + requestFilename + "."); -+ } -+ -+ String xml = loadFile(requestFilename); -+ request = CertEnrollmentRequest.fromXML(xml); -+ } -+ -+ if (requestType != null) { -+ -+ if (verbose) { -+ System.out.println("Request type: " + requestType); -+ } -+ -+ for (ProfileInput input : request.getInputs()) { -+ ProfileAttribute typeAttr = input.getAttribute("cert_request_type"); -+ if (typeAttr != null) { -+ typeAttr.setValue(requestType); -+ } -+ } -+ } -+ -+ String csrFilename = cmd.getOptionValue("csr-file"); -+ if (csrFilename != null) { -+ -+ String csr = loadFile(csrFilename); -+ -+ if (verbose) { -+ System.out.println("CSR:"); -+ System.out.println(csr); -+ } -+ -+ for (ProfileInput input : request.getInputs()) { -+ ProfileAttribute csrAttr = input.getAttribute("cert_request"); -+ if (csrAttr != null) { -+ csrAttr.setValue(csr); -+ } -+ } -+ } -+ -+ String subjectDN = cmd.getOptionValue("subject"); -+ if (subjectDN != null) { -+ DN dn = new DN(subjectDN); -+ Vector rdns = dn.getRDNs(); -+ -+ Map subjectAttributes = new HashMap(); -+ for (int i=0; i< rdns.size(); i++) { -+ RDN rdn = (RDN)rdns.elementAt(i); -+ String type = rdn.getTypes()[0].toLowerCase(); -+ String value = rdn.getValues()[0]; -+ subjectAttributes.put(type, value); -+ } -+ -+ ProfileInput sn = request.getInput("Subject Name"); -+ if (sn != null) { -+ if (verbose) System.out.println("Subject Name:"); -+ -+ for (ProfileAttribute attribute : sn.getAttributes()) { -+ String name = attribute.getName(); -+ String value = null; -+ -+ if (name.equals("subject")) { -+ // get the whole subject DN -+ value = subjectDN; -+ -+ } else if (name.startsWith("sn_")) { -+ // get value from subject DN -+ value = subjectAttributes.get(name.substring(3)); -+ -+ } else { -+ // unknown attribute, ignore -+ if (verbose) System.out.println(" - " + name); -+ continue; -+ } -+ -+ if (value == null) continue; -+ -+ if (verbose) System.out.println(" - " + name + ": " + value); -+ attribute.setValue(value); -+ } -+ } - } - } - -- private CertEnrollmentRequest getEnrollmentRequest(String fileName) throws JAXBException, FileNotFoundException { -+ private String loadFile(String fileName) throws FileNotFoundException { - try (Scanner scanner = new Scanner(new File(fileName))) { -- String xml = scanner.useDelimiter("\\A").next(); -- return CertEnrollmentRequest.fromXML(xml); -+ return scanner.useDelimiter("\\A").next(); - } - } - } -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 d99929f20996f1aa7ddbf21d29dfe7b54905354d..f092eacb1b5d0b340dcac06b20793334bf9baa70 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 -@@ -127,6 +127,7 @@ import com.netscape.certsrv.base.EBaseException; - import com.netscape.certsrv.base.EPropertyNotFound; - import com.netscape.certsrv.base.IConfigStore; - import com.netscape.certsrv.base.ISubsystem; -+import com.netscape.certsrv.base.MetaInfo; - import com.netscape.certsrv.base.PKIException; - import com.netscape.certsrv.base.ResourceNotFoundException; - import com.netscape.certsrv.ca.ICertificateAuthority; -@@ -134,6 +135,8 @@ import com.netscape.certsrv.client.ClientConfig; - import com.netscape.certsrv.client.PKIClient; - import com.netscape.certsrv.client.PKIConnection; - import com.netscape.certsrv.dbs.IDBSubsystem; -+import com.netscape.certsrv.dbs.certdb.ICertRecord; -+import com.netscape.certsrv.dbs.certdb.ICertificateRepository; - import com.netscape.certsrv.dbs.crldb.ICRLIssuingPointRecord; - import com.netscape.certsrv.key.KeyData; - import com.netscape.certsrv.ldap.ILdapConnFactory; -@@ -2270,6 +2273,54 @@ public class ConfigurationUtils { - certObj.setCertChain(certChainStr); - } - -+ public static KeyPair loadKeyPair(String nickname) throws Exception { -+ -+ CMS.debug("ConfigurationUtils: loadKeyPair(" + nickname + ")"); -+ -+ CryptoManager cm = CryptoManager.getInstance(); -+ -+ X509Certificate cert = cm.findCertByNickname(nickname); -+ PublicKey publicKey = cert.getPublicKey(); -+ PrivateKey privateKey = cm.findPrivKeyByCert(cert); -+ -+ return new KeyPair(publicKey, privateKey); -+ } -+ -+ public static void storeKeyPair(IConfigStore config, String tag, KeyPair pair) -+ throws TokenException, EBaseException { -+ -+ CMS.debug("ConfigurationUtils: storeKeyPair(" + tag + ")"); -+ -+ PublicKey publicKey = pair.getPublic(); -+ -+ if (publicKey instanceof RSAPublicKey) { -+ -+ RSAPublicKey rsaPublicKey = (RSAPublicKey) publicKey; -+ -+ byte modulus[] = rsaPublicKey.getModulus().toByteArray(); -+ config.putString(PCERT_PREFIX + tag + ".pubkey.modulus", -+ CryptoUtil.byte2string(modulus)); -+ -+ byte exponent[] = rsaPublicKey.getPublicExponent().toByteArray(); -+ config.putString(PCERT_PREFIX + tag + ".pubkey.exponent", -+ CryptoUtil.byte2string(exponent)); -+ -+ } else { // ECC -+ -+ CMS.debug("ConfigurationUtils: Public key class: " + publicKey.getClass().getName()); -+ byte encoded[] = publicKey.getEncoded(); -+ config.putString(PCERT_PREFIX + tag + ".pubkey.encoded", CryptoUtil.byte2string(encoded)); -+ } -+ -+ PrivateKey privateKey = (PrivateKey) pair.getPrivate(); -+ byte id[] = privateKey.getUniqueID(); -+ String kid = CryptoUtil.byte2string(id); -+ config.putString(PCERT_PREFIX + tag + ".privkey.id", kid); -+ -+ String keyAlgo = config.getString(PCERT_PREFIX + tag + ".signingalgorithm"); -+ setSigningAlgorithm(tag, keyAlgo, config); -+ } -+ - public static void createECCKeyPair(String token, String curveName, IConfigStore config, String ct) - throws NoSuchAlgorithmException, NoSuchTokenException, TokenException, - CryptoManager.NotInitializedException, EPropertyNotFound, EBaseException { -@@ -2832,6 +2883,20 @@ public class ConfigurationUtils { - } - } - -+ public static void loadCertRequest(IConfigStore config, String tag, Cert cert) throws Exception { -+ -+ CMS.debug("ConfigurationUtils.loadCertRequest(" + tag + ")"); -+ -+ String subjectDN = config.getString(PCERT_PREFIX + tag + ".dn"); -+ cert.setDN(subjectDN); -+ -+ String subsystem = config.getString(PCERT_PREFIX + tag + ".subsystem"); -+ String certreq = config.getString(subsystem + "." + tag + ".certreq"); -+ String formattedCertreq = CryptoUtil.reqFormat(certreq); -+ -+ cert.setRequest(formattedCertreq); -+ } -+ - public static void handleCertRequest(IConfigStore config, String certTag, Cert cert) throws EPropertyNotFound, - EBaseException, InvalidKeyException, NotInitializedException, TokenException, NoSuchAlgorithmException, - NoSuchProviderException, CertificateException, SignatureException, IOException { -@@ -2973,6 +3038,42 @@ public class ConfigurationUtils { - return pubk; - } - -+ public static void loadCert(IConfigStore config, Cert cert) throws Exception { -+ -+ String tag = cert.getCertTag(); -+ CMS.debug("ConfigurationUtils: loadCert(" + tag + ")"); -+ -+ CryptoManager cm = CryptoManager.getInstance(); -+ X509Certificate x509Cert = cm.findCertByNickname(cert.getNickname()); -+ -+ if (!x509Cert.getSubjectDN().equals(x509Cert.getIssuerDN())) { -+ CMS.debug("ConfigurationUtils: " + tag + " cert is not self-signed"); -+ -+ String subsystem = config.getString(PCERT_PREFIX + tag + ".subsystem"); -+ String certChain = config.getString(subsystem + ".external_ca_chain.cert"); -+ cert.setCertChain(certChain); -+ -+ return; -+ } -+ -+ CMS.debug("ConfigurationUtils: " + tag + " cert is self-signed"); -+ -+ // When importing existing self-signed CA certificate, create a -+ // certificate record to reserve the serial number. Otherwise it -+ // might conflict with system certificates to be created later. -+ -+ X509CertImpl x509CertImpl = new X509CertImpl(x509Cert.getEncoded()); -+ -+ ICertificateAuthority ca = (ICertificateAuthority) CMS.getSubsystem(ICertificateAuthority.ID); -+ ICertificateRepository cr = ca.getCertificateRepository(); -+ -+ BigInteger serialNo = x509Cert.getSerialNumber(); -+ MetaInfo meta = new MetaInfo(); -+ -+ ICertRecord record = cr.createCertRecord(serialNo, x509CertImpl, meta); -+ cr.addCertificateRecord(record); -+ } -+ - public static int handleCerts(Cert cert) throws IOException, EBaseException, CertificateException, - NotInitializedException, TokenException, InvalidKeyException { - String certTag = cert.getCertTag(); -diff --git a/base/server/cms/src/org/dogtagpki/server/rest/SystemConfigService.java b/base/server/cms/src/org/dogtagpki/server/rest/SystemConfigService.java -index e7a99601b473aca6a466873d4a776044d5e16e22..45ab5feaeb00c727157b3ac69a93059eee50c83b 100644 ---- a/base/server/cms/src/org/dogtagpki/server/rest/SystemConfigService.java -+++ b/base/server/cms/src/org/dogtagpki/server/rest/SystemConfigService.java -@@ -20,6 +20,7 @@ package org.dogtagpki.server.rest; - import java.math.BigInteger; - import java.net.MalformedURLException; - import java.net.URL; -+import java.security.KeyPair; - import java.security.NoSuchAlgorithmException; - import java.security.PublicKey; - import java.util.ArrayList; -@@ -421,7 +422,13 @@ public class SystemConfigService extends PKIService implements SystemConfigResou - } - cs.commit(false); - -- if (!request.getStepTwo()) { -+ if (request.isExternal() && tag.equals("signing")) { // external/existing CA -+ // load key pair for existing and externally-signed signing cert -+ CMS.debug("SystemConfigService: loading signing cert key pair"); -+ KeyPair pair = ConfigurationUtils.loadKeyPair(certData.getNickname()); -+ ConfigurationUtils.storeKeyPair(cs, tag, pair); -+ -+ } else if (!request.getStepTwo()) { - if (keytype.equals("ecc")) { - String curvename = certData.getKeyCurveName() != null ? - certData.getKeyCurveName() : cs.getString("keys.ecc.curve.default"); -@@ -444,7 +451,15 @@ public class SystemConfigService extends PKIService implements SystemConfigResou - cert.setSubsystem(cs.getString("preop.cert." + tag + ".subsystem")); - cert.setType(cs.getString("preop.cert." + tag + ".type")); - -- if (!request.getStepTwo()) { -+ if (request.isExternal() && tag.equals("signing")) { // external/existing CA -+ -+ // update configuration for existing or externally-signed signing certificate -+ String certStr = cs.getString("ca." + tag + ".cert" ); -+ cert.setCert(certStr); -+ CMS.debug("SystemConfigService: certificate " + tag + ": " + certStr); -+ ConfigurationUtils.updateConfig(cs, tag); -+ -+ } else if (!request.getStepTwo()) { - ConfigurationUtils.configCert(null, null, null, cert, null); - - } else { -@@ -466,8 +481,16 @@ public class SystemConfigService extends PKIService implements SystemConfigResou - CMS.debug("Step 2: certStr for '" + tag + "' is " + certStr); - } - -- // Handle Cert Requests for everything EXCEPT Stand-alone PKI (Step 2) -- if (request.getStandAlone()) { -+ if (request.isExternal() && tag.equals("signing")) { // external/existing CA -+ -+ CMS.debug("SystemConfigService: Loading cert request for " + tag + " cert"); -+ ConfigurationUtils.loadCertRequest(cs, tag, cert); -+ -+ CMS.debug("SystemConfigService: Loading cert " + tag); -+ ConfigurationUtils.loadCert(cs, cert); -+ -+ } else if (request.getStandAlone()) { -+ // Handle Cert Requests for everything EXCEPT Stand-alone PKI (Step 2) - if (!request.getStepTwo()) { - // Stand-alone PKI (Step 1) - ConfigurationUtils.handleCertRequest(cs, tag, cert); -@@ -490,6 +513,13 @@ public class SystemConfigService extends PKIService implements SystemConfigResou - ConfigurationUtils.updateCloneConfig(); - } - -+ if (request.isExternal() && tag.equals("signing")) { // external/existing CA -+ CMS.debug("SystemConfigService: External CA has signing cert"); -+ hasSigningCert.setValue(true); -+ certs.add(cert); -+ continue; -+ } -+ - // to determine if we have the signing cert when using an external ca - // this will only execute on a ca or stand-alone pki - String b64 = certData.getCert(); -diff --git a/base/server/etc/default.cfg b/base/server/etc/default.cfg -index 58f338692ac4f1c2637b575e27db2bec6254905b..c6b9686db9b2e0245f99db36c34188716e827d83 100644 ---- a/base/server/etc/default.cfg -+++ b/base/server/etc/default.cfg -@@ -22,6 +22,7 @@ sensitive_parameters= - pki_client_pkcs12_password - pki_clone_pkcs12_password - pki_ds_password -+ pki_external_pkcs12_password - pki_one_time_pin - pki_pin - pki_replication_password -@@ -363,10 +364,13 @@ pki_req_ext_add=False - pki_req_ext_oid=1.3.6.1.4.1.311.20.2 - pki_req_ext_critical=False - pki_req_ext_data=1E0A00530075006200430041 --pki_external_csr_path=%(pki_instance_configuration_path)s/ca_signing.csr -+pki_external_csr_path= - pki_external_step_two=False --pki_external_ca_cert_chain_path=%(pki_instance_configuration_path)s/external_ca_chain.cert --pki_external_ca_cert_path=%(pki_instance_configuration_path)s/external_ca.cert -+pki_external_ca_cert_chain_path= -+pki_external_ca_cert_chain_nickname=caSigningCert External CA -+pki_external_ca_cert_path= -+pki_external_pkcs12_path= -+pki_external_pkcs12_password= - pki_import_admin_cert=False - pki_ocsp_signing_key_algorithm=SHA256withRSA - pki_ocsp_signing_key_size=2048 -diff --git a/base/server/python/pki/server/__init__.py b/base/server/python/pki/server/__init__.py -index 89d4acfd5a36d5e58b6e1bbacb4d267d6f1e20c8..4493b59df00adc0dad9b6808fb10c1769634335c 100644 ---- a/base/server/python/pki/server/__init__.py -+++ b/base/server/python/pki/server/__init__.py -@@ -33,6 +33,7 @@ import subprocess - import tempfile - - import pki -+import pki.nssdb - - INSTANCE_BASE_DIR = '/var/lib/pki' - REGISTRY_DIR = '/etc/sysconfig/pki' -@@ -303,6 +304,12 @@ class PKIInstance(object): - - return password - -+ def open_nssdb(self, token='internal'): -+ return pki.nssdb.NSSDatabase( -+ directory=self.nssdb_dir, -+ token=token, -+ password=self.get_password(token)) -+ - def get_subsystem(self, name): - for subsystem in self.subsystems: - if name == subsystem.name: -diff --git a/base/server/python/pki/server/cli/subsystem.py b/base/server/python/pki/server/cli/subsystem.py -index 19db203c0d8a09817131abaabd4e3ac26e288e95..9f82dff756bf98b0a14783fdd48c25d9d406f50b 100644 ---- a/base/server/python/pki/server/cli/subsystem.py -+++ b/base/server/python/pki/server/cli/subsystem.py -@@ -23,11 +23,13 @@ from __future__ import absolute_import - from __future__ import print_function - import base64 - import getopt -+import getpass - import nss.nss as nss - import string - import sys - - import pki.cli -+import pki.nssdb - import pki.server - - -@@ -294,6 +296,7 @@ class SubsystemCertCLI(pki.cli.CLI): - - self.add_module(SubsystemCertFindCLI()) - self.add_module(SubsystemCertShowCLI()) -+ self.add_module(SubsystemCertExportCLI()) - self.add_module(SubsystemCertUpdateCLI()) - - @staticmethod -@@ -438,6 +441,129 @@ class SubsystemCertShowCLI(pki.cli.CLI): - SubsystemCertCLI.print_subsystem_cert(subsystem_cert) - - -+class SubsystemCertExportCLI(pki.cli.CLI): -+ -+ def __init__(self): -+ super(SubsystemCertExportCLI, self).__init__( -+ 'export', 'Export subsystem certificate') -+ -+ def usage(self): -+ print('Usage: pki-server subsystem-cert-export [OPTIONS] ') -+ print() -+ print(' -i, --instance Instance ID (default: pki-tomcat).') -+ print(' --cert-file Output file to store the exported certificate in PEM format.') -+ print(' --csr-file Output file to store the exported CSR in PEM format.') -+ print(' --pkcs12-file Output file to store the exported certificate and key in PKCS #12 format.') -+ print(' --pkcs12-password Password for the PKCS #12 file.') -+ print(' --pkcs12-password-file Input file containing the password for the PKCS #12 file.') -+ print(' -v, --verbose Run in verbose mode.') -+ print(' --help Show help message.') -+ print() -+ -+ def execute(self, argv): -+ -+ try: -+ opts, args = getopt.gnu_getopt(argv, 'i:v', [ -+ 'instance=', 'cert-file=', 'csr-file=', -+ 'pkcs12-file=', 'pkcs12-password=', 'pkcs12-password-file=', -+ 'verbose', 'help']) -+ -+ except getopt.GetoptError as e: -+ print('ERROR: ' + str(e)) -+ 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' -+ cert_file = None -+ csr_file = None -+ pkcs12_file = None -+ pkcs12_password = None -+ pkcs12_password_file = None -+ -+ for o, a in opts: -+ if o in ('-i', '--instance'): -+ instance_name = a -+ -+ elif o == '--cert-file': -+ cert_file = a -+ -+ elif o == '--csr-file': -+ csr_file = a -+ -+ elif o == '--pkcs12-file': -+ pkcs12_file = a -+ -+ elif o == '--pkcs12-password': -+ pkcs12_password = a -+ -+ elif o == '--pkcs12-password-file': -+ pkcs12_password_file = a -+ -+ elif o in ('-v', '--verbose'): -+ self.set_verbose(True) -+ -+ elif o == '--help': -+ self.print_help() -+ sys.exit() -+ -+ else: -+ print('ERROR: unknown option ' + o) -+ self.usage() -+ sys.exit(1) -+ -+ if not cert_file and not csr_file and not pkcs12_file: -+ print('ERROR: missing output file') -+ self.usage() -+ sys.exit(1) -+ -+ instance = pki.server.PKIInstance(instance_name) -+ instance.load() -+ -+ subsystem = instance.get_subsystem(subsystem_name) -+ subsystem_cert = subsystem.get_subsystem_cert(cert_id) -+ -+ if cert_file: -+ -+ cert_data = pki.nssdb.convert_cert(subsystem_cert['data'], 'base64', 'pem') -+ with open(cert_file, 'w') as f: -+ f.write(cert_data) -+ -+ if csr_file: -+ -+ csr_data = pki.nssdb.convert_csr(subsystem_cert['request'], 'base64', 'pem') -+ with open(csr_file, 'w') as f: -+ f.write(csr_data) -+ -+ if pkcs12_file: -+ -+ if not pkcs12_password and not pkcs12_password_file: -+ pkcs12_password = getpass.getpass(prompt='Enter password for PKCS #12 file: ') -+ -+ nssdb = instance.open_nssdb() -+ try: -+ nssdb.export_pkcs12( -+ pkcs12_file=pkcs12_file, -+ nickname=subsystem_cert['nickname'], -+ pkcs12_password=pkcs12_password, -+ pkcs12_password_file=pkcs12_password_file) -+ finally: -+ nssdb.close() -+ -+ self.print_message('Exported %s certificate' % cert_id) -+ -+ - class SubsystemCertUpdateCLI(pki.cli.CLI): - - def __init__(self): -diff --git a/base/server/python/pki/server/deployment/pkihelper.py b/base/server/python/pki/server/deployment/pkihelper.py -index 5bc4ffab814891aadf0508d0ae20bb8cc315bc90..fcef5a48bbd72eecf5e04975fc7c2401ab41b22c 100644 ---- a/base/server/python/pki/server/deployment/pkihelper.py -+++ b/base/server/python/pki/server/deployment/pkihelper.py -@@ -490,15 +490,18 @@ class ConfigurationFile: - # generic extension support in CSR - for external CA - self.add_req_ext = config.str2bool( - self.mdict['pki_req_ext_add']) -+ - self.external = config.str2bool(self.mdict['pki_external']) -+ self.external_step_one = not config.str2bool(self.mdict['pki_external_step_two']) -+ self.external_step_two = not self.external_step_one -+ - if self.external: - # generic extension support in CSR - for external CA - if self.add_req_ext: - self.req_ext_oid = self.mdict['pki_req_ext_oid'] - self.req_ext_critical = self.mdict['pki_req_ext_critical'] - self.req_ext_data = self.mdict['pki_req_ext_data'] -- self.external_step_two = config.str2bool( -- self.mdict['pki_external_step_two']) -+ - self.skip_configuration = config.str2bool( - self.mdict['pki_skip_configuration']) - self.standalone = config.str2bool(self.mdict['pki_standalone']) -@@ -744,8 +747,7 @@ class ConfigurationFile: - # External CA - if not self.external_step_two: - # External CA (Step 1) -- self.confirm_data_exists("pki_external_csr_path") -- self.confirm_missing_file("pki_external_csr_path") -+ # The pki_external_csr_path is optional. - # generic extension support in CSR - for external CA - if self.add_req_ext: - self.confirm_data_exists("pki_req_ext_oid") -@@ -753,10 +755,9 @@ class ConfigurationFile: - self.confirm_data_exists("pki_req_ext_data") - else: - # External CA (Step 2) -- self.confirm_data_exists("pki_external_ca_cert_chain_path") -- self.confirm_file_exists("pki_external_ca_cert_chain_path") -- self.confirm_data_exists("pki_external_ca_cert_path") -- self.confirm_file_exists("pki_external_ca_cert_path") -+ # The pki_external_ca_cert_chain_path and -+ # pki_external_ca_cert_path are optional. -+ pass - elif not self.skip_configuration and self.standalone: - if not self.external_step_two: - # Stand-alone PKI Admin CSR (Step 1) -@@ -3813,17 +3814,7 @@ class ConfigClient: - if not isinstance(certs, types.ListType): - certs = [certs] - for cdata in certs: -- if (self.subsystem == "CA" and self.external and -- not self.external_step_two): -- # External CA (Step 1) -- if cdata['tag'].lower() == "signing": -- # Save 'External CA Signing Certificate' CSR (Step 1) -- self.save_system_csr( -- cdata['request'], -- log.PKI_CONFIG_EXTERNAL_CSR_SAVE, -- self.mdict['pki_external_csr_path']) -- return -- elif self.standalone and not self.external_step_two: -+ if self.standalone and not self.external_step_two: - # Stand-alone PKI (Step 1) - if cdata['tag'].lower() == "audit_signing": - # Save Stand-alone PKI 'Audit Signing Certificate' CSR -@@ -3990,8 +3981,17 @@ class ConfigClient: - data.token = self.mdict['pki_token_name'] - data.tokenPassword = self.mdict['pki_token_password'] - data.subsystemName = self.mdict['pki_subsystem_name'] -+ -+ data.external = self.external - data.standAlone = self.standalone -- data.stepTwo = self.external_step_two -+ -+ if self.standalone: -+ # standalone installation uses two-step process (ticket #1698) -+ data.stepTwo = self.external_step_two -+ -+ else: -+ # other installations use only one step in the configuration servlet -+ data.stepTwo = False - - # Cloning parameters - if self.mdict['pki_instance_type'] == "Tomcat": -@@ -4119,25 +4119,46 @@ class ConfigClient: - self.mdict['pki_req_ext_critical'] - cert1.req_ext_data = \ - self.mdict['pki_req_ext_data'] -- if self.external_step_two: -- # External CA (Step 2) or Stand-alone PKI (Step 2) -- if not self.subsystem == "CA": -- # Stand-alone PKI (Step 2) -- cert1 = pki.system.SystemCertData() -- cert1.tag = self.mdict['pki_ca_signing_tag'] -- # Load the External CA or Stand-alone PKI -+ -+ if self.external and self.external_step_two: # external/existing CA step 2 -+ -+ # If specified, load the externally-signed CA cert -+ if self.mdict['pki_external_ca_cert_path']: -+ self.load_system_cert( -+ cert1, -+ log.PKI_CONFIG_EXTERNAL_CA_LOAD, -+ self.mdict['pki_external_ca_cert_path']) -+ -+ # If specified, load the external CA cert chain -+ if self.mdict['pki_external_ca_cert_chain_path']: -+ self.load_system_cert_chain( -+ cert1, -+ log.PKI_CONFIG_EXTERNAL_CA_CHAIN_LOAD, -+ self.mdict['pki_external_ca_cert_chain_path']) -+ -+ systemCerts.append(cert1) -+ -+ elif self.standalone and self.external_step_two: # standalone KRA/OCSP step 2 -+ -+ cert1 = pki.system.SystemCertData() -+ cert1.tag = self.mdict['pki_ca_signing_tag'] -+ -+ # Load the stand-alone PKI - # 'External CA Signing Certificate' (Step 2) - self.load_system_cert( - cert1, - log.PKI_CONFIG_EXTERNAL_CA_LOAD, - self.mdict['pki_external_ca_cert_path']) -- # Load the External CA or Stand-alone PKI -+ -+ # Load the stand-alone PKI - # 'External CA Signing Certificate Chain' (Step 2) - self.load_system_cert_chain( - cert1, - log.PKI_CONFIG_EXTERNAL_CA_CHAIN_LOAD, - self.mdict['pki_external_ca_cert_chain_path']) -+ - systemCerts.append(cert1) -+ - elif self.subsystem == "CA": - # PKI CA or Subordinate CA - systemCerts.append(cert1) -diff --git a/base/server/python/pki/server/deployment/scriptlets/configuration.py b/base/server/python/pki/server/deployment/scriptlets/configuration.py -index fbcb1ccaa21001ec57f0fd9e7ffb00e062349ecc..e7b257f7d3eb1178827ed2ef1e211e4a21455d1b 100644 ---- a/base/server/python/pki/server/deployment/scriptlets/configuration.py -+++ b/base/server/python/pki/server/deployment/scriptlets/configuration.py -@@ -20,13 +20,18 @@ - # - - import json -+import re - - # PKI Deployment Imports - from .. import pkiconfig as config - from .. import pkimessages as log - from .. import pkiscriptlet --import pki.system -+ - import pki.encoder -+import pki.nssdb -+import pki.server -+import pki.system -+import pki.util - - - # PKI Deployment Configuration Scriptlet -@@ -80,6 +85,131 @@ class PkiScriptlet(pkiscriptlet.AbstractBasePkiScriptlet): - deployer.mdict['pki_client_secmod_database'], - password_file=deployer.mdict['pki_client_password_conf']) - -+ instance = pki.server.PKIInstance(deployer.mdict['pki_instance_name']) -+ instance.load() -+ -+ subsystem = instance.get_subsystem(deployer.mdict['pki_subsystem'].lower()) -+ -+ token = deployer.mdict['pki_token_name'] -+ nssdb = instance.open_nssdb(token) -+ -+ external = deployer.configuration_file.external -+ step_one = deployer.configuration_file.external_step_one -+ step_two = deployer.configuration_file.external_step_two -+ -+ try: -+ if external and step_one: # external/existing CA step 1 -+ -+ key_type = deployer.mdict['pki_ca_signing_key_type'] -+ key_alg = deployer.mdict['pki_ca_signing_key_algorithm'] -+ -+ if key_type == 'rsa': -+ key_size = int(deployer.mdict['pki_ca_signing_key_size']) -+ curve = None -+ -+ m = re.match(r'(.*)withRSA', key_alg) -+ if not m: -+ raise Exception('Invalid key algorithm: %s' % key_alg) -+ hash_alg = m.group(1) -+ -+ elif key_type == 'ec' or key_type == 'ecc': -+ key_type = 'ec' -+ key_size = None -+ curve = deployer.mdict['pki_ca_signing_key_size'] -+ -+ m = re.match(r'(.*)withEC', key_alg) -+ if not m: -+ raise Exception('Invalid key algorithm: %s' % key_alg) -+ hash_alg = m.group(1) -+ -+ else: -+ raise Exception('Invalid key type: %s' % key_type) -+ -+ # If filename specified, generate CA cert request and -+ # import it into CS.cfg. -+ external_csr_path = deployer.mdict['pki_external_csr_path'] -+ if external_csr_path: -+ nssdb.create_request( -+ subject_dn=deployer.mdict['pki_ca_signing_subject_dn'], -+ request_file=external_csr_path, -+ key_type=key_type, -+ key_size=key_size, -+ curve=curve, -+ hash_alg=hash_alg) -+ with open(external_csr_path) as f: -+ signing_csr = f.read() -+ signing_csr = pki.nssdb.convert_csr(signing_csr, 'pem', 'base64') -+ subsystem.config['ca.signing.certreq'] = signing_csr -+ -+ # This is needed by IPA to detect step 1 completion. -+ # See is_step_one_done() in ipaserver/install/cainstance.py. -+ subsystem.config['preop.ca.type'] = 'otherca' -+ -+ subsystem.save() -+ -+ elif external and step_two: # external/existing CA step 2 -+ -+ # If specified, import existing CA cert request into CS.cfg. -+ external_csr_path = deployer.mdict['pki_external_csr_path'] -+ if external_csr_path: -+ with open(external_csr_path) as f: -+ signing_csr = f.read() -+ signing_csr = pki.nssdb.convert_csr(signing_csr, 'pem', 'base64') -+ subsystem.config['ca.signing.certreq'] = signing_csr -+ -+ # If specified, import external CA cert into NSS database. -+ external_ca_cert_chain_nickname = deployer.mdict['pki_external_ca_cert_chain_nickname'] -+ external_ca_cert_chain_file = deployer.mdict['pki_external_ca_cert_chain_path'] -+ if external_ca_cert_chain_file: -+ cert_chain = nssdb.import_cert_chain( -+ nickname=external_ca_cert_chain_nickname, -+ cert_chain_file=external_ca_cert_chain_file, -+ trust_attributes='CT,C,C') -+ subsystem.config['ca.external_ca_chain.cert'] = cert_chain -+ -+ # If specified, import externally-signed CA cert into NSS database. -+ signing_nickname = deployer.mdict['pki_ca_signing_nickname'] -+ signing_cert_file = deployer.mdict['pki_external_ca_cert_path'] -+ if signing_cert_file: -+ nssdb.add_cert( -+ nickname=signing_nickname, -+ cert_file=signing_cert_file, -+ trust_attributes='CT,C,C') -+ -+ # If specified, import CA cert and key from PKCS #12 file into NSS database. -+ pkcs12_file = deployer.mdict['pki_external_pkcs12_path'] -+ if pkcs12_file: -+ pkcs12_password = deployer.mdict['pki_external_pkcs12_password'] -+ nssdb.import_pkcs12(pkcs12_file, pkcs12_password) -+ -+ # Export CA cert from NSS database and import it into CS.cfg. -+ signing_cert_data = nssdb.get_cert( -+ nickname=signing_nickname, -+ output_format='base64') -+ subsystem.config['ca.signing.nickname'] = signing_nickname -+ subsystem.config['ca.signing.tokenname'] = deployer.mdict['pki_ca_signing_token'] -+ subsystem.config['ca.signing.cert'] = signing_cert_data -+ subsystem.config['ca.signing.cacertnickname'] = signing_nickname -+ subsystem.config['ca.signing.defaultSigningAlgorithm'] = deployer.mdict['pki_ca_signing_signing_algorithm'] -+ -+ subsystem.save() -+ -+ else: # self-signed CA -+ -+ # To be implemented in ticket #1692. -+ -+ # Generate CA cert request. -+ # Self sign CA cert. -+ # Import self-signed CA cert into NSS database. -+ -+ pass -+ -+ finally: -+ nssdb.close() -+ -+ if external and step_one: -+ return self.rv -+ - # Start/Restart this Tomcat PKI Process - # Optionally prepare to enable a java debugger - # (e. g. - 'eclipse'): -diff --git a/base/server/python/pki/server/deployment/scriptlets/finalization.py b/base/server/python/pki/server/deployment/scriptlets/finalization.py -index b92965929ffa845ce10a667ff412e4dbcaf2393c..4c98cc4996e74083d1d240913dbaea7951cc593f 100644 ---- a/base/server/python/pki/server/deployment/scriptlets/finalization.py -+++ b/base/server/python/pki/server/deployment/scriptlets/finalization.py -@@ -65,9 +65,15 @@ class PkiScriptlet(pkiscriptlet.AbstractBasePkiScriptlet): - if len(deployer.instance.tomcat_instance_subsystems()) == 1: - # Modify contents of 'serverCertNick.conf' (if necessary) - deployer.servercertnick_conf.modify() -- # Optionally, programmatically 'restart' the configured PKI instance -- if config.str2bool(deployer.mdict['pki_restart_configured_instance']): -- deployer.systemd.restart() -+ -+ external = config.str2bool(deployer.mdict['pki_external']) -+ step_one = not config.str2bool(deployer.mdict['pki_external_step_two']) -+ -+ if not (external and step_one): -+ # Optionally, programmatically 'restart' the configured PKI instance -+ if config.str2bool(deployer.mdict['pki_restart_configured_instance']): -+ deployer.systemd.restart() -+ - # Optionally, 'purge' the entire temporary client infrastructure - # including the client NSS security databases and password files - # -diff --git a/base/server/sbin/pkispawn b/base/server/sbin/pkispawn -index bebbf0b771a8a5b24347ffe5f97e0ce713a53e98..6b51acf920ec93c49c69dad8cc34e26ed352fb70 100755 ---- a/base/server/sbin/pkispawn -+++ b/base/server/sbin/pkispawn -@@ -611,7 +611,17 @@ def main(argv): - config.pki_log.debug(pkilogging.log_format(parser.mdict), - extra=config.PKI_INDENTATION_LEVEL_0) - -- print_install_information(parser.mdict) -+ external = deployer.configuration_file.external -+ step_one = deployer.configuration_file.external_step_one -+ -+ if external and step_one: -+ external_csr_path = deployer.mdict['pki_external_csr_path'] -+ if external_csr_path: -+ print_external_ca_step_one_information(parser.mdict) -+ else: -+ print_existing_ca_step_one_information(parser.mdict) -+ else: -+ print_install_information(parser.mdict) - - - def set_port(parser, tag, prompt, existing_data): -@@ -621,6 +631,33 @@ def set_port(parser, tag, prompt, existing_data): - parser.read_text(prompt, config.pki_subsystem, tag) - - -+def print_external_ca_step_one_information(mdict): -+ -+ print(log.PKI_SPAWN_INFORMATION_HEADER) -+ print(" The %s subsystem of the '%s' instance is still incomplete." % -+ (config.pki_subsystem, mdict['pki_instance_name'])) -+ print() -+ print(" A CSR for the CA certificate has been generated at:\n" -+ " %s" -+ % mdict['pki_external_csr_path']) -+ print() -+ print(" Submit the CSR to an external CA to generate a CA certificate\n" -+ " for this subsystem. Import the CA certificate and the certificate\n" -+ " chain, then continue the installation.") -+ print(log.PKI_SPAWN_INFORMATION_FOOTER) -+ -+ -+def print_existing_ca_step_one_information(mdict): -+ -+ print(log.PKI_SPAWN_INFORMATION_HEADER) -+ print(" The %s subsystem of the '%s' instance is still incomplete." % -+ (config.pki_subsystem, mdict['pki_instance_name'])) -+ print() -+ print(" Import an existing CA certificate with the key and the CSR, and\n" -+ " the certificate chain if available, then continue the installation.") -+ print(log.PKI_SPAWN_INFORMATION_FOOTER) -+ -+ - def print_install_information(mdict): - - skip_configuration = config.str2bool(mdict['pki_skip_configuration']) --- -2.4.3 - diff --git a/SOURCES/pki-core-Fix-build-on-Fedora-25.patch b/SOURCES/pki-core-Fix-build-on-Fedora-25.patch new file mode 100644 index 0000000..558f016 --- /dev/null +++ b/SOURCES/pki-core-Fix-build-on-Fedora-25.patch @@ -0,0 +1,280 @@ +From 3fdc686c9a4bab492d50cef707beef1f5f043153 Mon Sep 17 00:00:00 2001 +From: Fraser Tweedale +Date: Tue, 28 Jun 2016 15:50:36 +1000 +Subject: [PATCH] Fix build on Fedora 25 + +Look for the right JAX-RS API JAR (it has moved in Fedora 25). + +Also remove a lot of redundant 'find_file' operations for this JAR. + +Fixes: https://fedorahosted.org/pki/ticket/2373 +--- + base/CMakeLists.txt | 10 ++++++++++ + base/ca/src/CMakeLists.txt | 7 ------- + base/common/src/CMakeLists.txt | 7 ------- + base/java-tools/src/CMakeLists.txt | 7 ------- + base/kra/src/CMakeLists.txt | 7 ------- + base/ocsp/src/CMakeLists.txt | 7 ------- + base/server/cms/src/CMakeLists.txt | 7 ------- + base/server/cmscore/src/CMakeLists.txt | 7 ------- + base/server/tomcat/src/CMakeLists.txt | 7 ------- + base/server/tomcat7/src/CMakeLists.txt | 7 ------- + base/server/tomcat8/src/CMakeLists.txt | 7 ------- + base/tks/src/CMakeLists.txt | 7 ------- + base/tps/src/CMakeLists.txt | 14 -------------- + 13 files changed, 10 insertions(+), 91 deletions(-) + +diff --git a/base/CMakeLists.txt b/base/CMakeLists.txt +index b9d5c7b..bb156ba 100644 +--- a/base/CMakeLists.txt ++++ b/base/CMakeLists.txt +@@ -2,6 +2,16 @@ project(base) + + # The order is important! + if (APPLICATION_FLAVOR_PKI_CORE) ++ ++ find_file(JAXRS_API_JAR ++ NAMES ++ jaxrs-api.jar ++ jboss-jaxrs-2.0-api.jar ++ PATHS ++ ${RESTEASY_LIB} ++ /usr/share/java ++ ) ++ + add_subdirectory(test) + add_subdirectory(symkey) + add_subdirectory(util) +diff --git a/base/ca/src/CMakeLists.txt b/base/ca/src/CMakeLists.txt +index 2a43c8d..854ce28 100644 +--- a/base/ca/src/CMakeLists.txt ++++ b/base/ca/src/CMakeLists.txt +@@ -52,13 +52,6 @@ find_file(JACKSON_MAPPER_JAR + /usr/share/java/jackson + ) + +-find_file(JAXRS_API_JAR +- NAMES +- jaxrs-api.jar +- PATHS +- ${RESTEASY_LIB} +-) +- + find_file(RESTEASY_JAXRS_JAR + NAMES + resteasy-jaxrs.jar +diff --git a/base/common/src/CMakeLists.txt b/base/common/src/CMakeLists.txt +index 072bd00..ee41b2f 100644 +--- a/base/common/src/CMakeLists.txt ++++ b/base/common/src/CMakeLists.txt +@@ -83,13 +83,6 @@ find_file(XERCES_JAR + /usr/share/java + ) + +-find_file(JAXRS_API_JAR +- NAMES +- jaxrs-api.jar +- PATHS +- ${RESTEASY_LIB} +-) +- + find_file(RESTEASY_JAXRS_JAR + NAMES + resteasy-jaxrs.jar +diff --git a/base/java-tools/src/CMakeLists.txt b/base/java-tools/src/CMakeLists.txt +index 9a3c72f..e7ca5db 100644 +--- a/base/java-tools/src/CMakeLists.txt ++++ b/base/java-tools/src/CMakeLists.txt +@@ -60,13 +60,6 @@ find_file(XERCES_JAR + /usr/share/java + ) + +-find_file(JAXRS_API_JAR +- NAMES +- jaxrs-api.jar +- PATHS +- ${RESTEASY_LIB} +-) +- + find_file(RESTEASY_JAXRS_JAR + NAMES + resteasy-jaxrs.jar +diff --git a/base/kra/src/CMakeLists.txt b/base/kra/src/CMakeLists.txt +index bfc8cdd..400ec01 100644 +--- a/base/kra/src/CMakeLists.txt ++++ b/base/kra/src/CMakeLists.txt +@@ -61,13 +61,6 @@ find_file(COMMONS_CODEC_JAR + /usr/share/java + ) + +-find_file(JAXRS_API_JAR +- NAMES +- jaxrs-api.jar +- PATHS +- ${RESTEASY_LIB} +-) +- + find_file(RESTEASY_JAXRS_JAR + NAMES + resteasy-jaxrs.jar +diff --git a/base/ocsp/src/CMakeLists.txt b/base/ocsp/src/CMakeLists.txt +index d4a2009..32fcc92 100644 +--- a/base/ocsp/src/CMakeLists.txt ++++ b/base/ocsp/src/CMakeLists.txt +@@ -46,13 +46,6 @@ find_file(LDAPJDK_JAR + /usr/share/java + ) + +-find_file(JAXRS_API_JAR +- NAMES +- jaxrs-api.jar +- PATHS +- ${RESTEASY_LIB} +-) +- + # '${JAVA_LIB_INSTALL_DIR}' jars + find_file(JSS_JAR + NAMES +diff --git a/base/server/cms/src/CMakeLists.txt b/base/server/cms/src/CMakeLists.txt +index 33b1cd3..93f4a8a 100644 +--- a/base/server/cms/src/CMakeLists.txt ++++ b/base/server/cms/src/CMakeLists.txt +@@ -90,13 +90,6 @@ find_file(XERCES_JAR + /usr/share/java + ) + +-find_file(JAXRS_API_JAR +- NAMES +- jaxrs-api.jar +- PATHS +- ${RESTEASY_LIB} +-) +- + find_file(RESTEASY_JAXRS_JAR + NAMES + resteasy-jaxrs.jar +diff --git a/base/server/cmscore/src/CMakeLists.txt b/base/server/cmscore/src/CMakeLists.txt +index ef12938..32e4351 100644 +--- a/base/server/cmscore/src/CMakeLists.txt ++++ b/base/server/cmscore/src/CMakeLists.txt +@@ -83,13 +83,6 @@ find_file(XERCES_JAR + /usr/share/java + ) + +-find_file(JAXRS_API_JAR +- NAMES +- jaxrs-api.jar +- PATHS +- ${RESTEASY_LIB} +-) +- + find_file(RESTEASY_JAXRS_JAR + NAMES + resteasy-jaxrs.jar +diff --git a/base/server/tomcat/src/CMakeLists.txt b/base/server/tomcat/src/CMakeLists.txt +index 669cc88..4cb40ad 100644 +--- a/base/server/tomcat/src/CMakeLists.txt ++++ b/base/server/tomcat/src/CMakeLists.txt +@@ -83,13 +83,6 @@ find_file(XERCES_JAR + /usr/share/java + ) + +-find_file(JAXRS_API_JAR +- NAMES +- jaxrs-api.jar +- PATHS +- ${RESTEASY_LIB} +-) +- + find_file(RESTEASY_JAXRS_JAR + NAMES + resteasy-jaxrs.jar +diff --git a/base/server/tomcat7/src/CMakeLists.txt b/base/server/tomcat7/src/CMakeLists.txt +index f84369c..18f0b91 100644 +--- a/base/server/tomcat7/src/CMakeLists.txt ++++ b/base/server/tomcat7/src/CMakeLists.txt +@@ -83,13 +83,6 @@ find_file(XERCES_JAR + /usr/share/java + ) + +-find_file(JAXRS_API_JAR +- NAMES +- jaxrs-api.jar +- PATHS +- ${RESTEASY_LIB} +-) +- + find_file(RESTEASY_JAXRS_JAR + NAMES + resteasy-jaxrs.jar +diff --git a/base/server/tomcat8/src/CMakeLists.txt b/base/server/tomcat8/src/CMakeLists.txt +index 0f49ff9..db1b9dc 100644 +--- a/base/server/tomcat8/src/CMakeLists.txt ++++ b/base/server/tomcat8/src/CMakeLists.txt +@@ -90,13 +90,6 @@ find_file(XERCES_JAR + /usr/share/java + ) + +-find_file(JAXRS_API_JAR +- NAMES +- jaxrs-api.jar +- PATHS +- ${RESTEASY_LIB} +-) +- + find_file(RESTEASY_JAXRS_JAR + NAMES + resteasy-jaxrs.jar +diff --git a/base/tks/src/CMakeLists.txt b/base/tks/src/CMakeLists.txt +index d1ebbb1..51f98c9 100644 +--- a/base/tks/src/CMakeLists.txt ++++ b/base/tks/src/CMakeLists.txt +@@ -68,13 +68,6 @@ find_file(COMMONS_LANG_JAR + /usr/share/java + ) + +-find_file(JAXRS_API_JAR +- NAMES +- jaxrs-api.jar +- PATHS +- ${RESTEASY_LIB} +-) +- + find_file(RESTEASY_JAXRS_JAR + NAMES + resteasy-jaxrs.jar +diff --git a/base/tps/src/CMakeLists.txt b/base/tps/src/CMakeLists.txt +index b8b13a9..5e51f60 100644 +--- a/base/tps/src/CMakeLists.txt ++++ b/base/tps/src/CMakeLists.txt +@@ -28,13 +28,6 @@ find_file(COMMONS_LANG_JAR + /usr/share/java + ) + +-find_file(JAXRS_API_JAR +- NAMES +- jaxrs-api.jar +- PATHS +- ${RESTEASY_LIB} +-) +- + find_file(TOMCAT_CATALINA_JAR + NAMES + catalina.jar +@@ -77,13 +70,6 @@ find_file(PKI_NSUTIL_JAR + /usr/share/java/pki + ) + +-find_file(JAXRS_API_JAR +- NAMES +- jaxrs-api.jar +- PATHS +- ${RESTEASY_LIB} +-) +- + find_file(RESTEASY_JAXRS_JAR + NAMES + resteasy-jaxrs.jar +-- +2.5.5 + diff --git a/SOURCES/pki-core-Fix-escaping-of-password-fields-to-prevent-interpolation.patch b/SOURCES/pki-core-Fix-escaping-of-password-fields-to-prevent-interpolation.patch deleted file mode 100644 index c8aa30d..0000000 --- a/SOURCES/pki-core-Fix-escaping-of-password-fields-to-prevent-interpolation.patch +++ /dev/null @@ -1,43 +0,0 @@ -From f20517215d336e778c34dd96afae01fe34fc2f88 Mon Sep 17 00:00:00 2001 -From: Matthew Harmsen -Date: Tue, 29 Mar 2016 12:29:18 -0600 -Subject: [PATCH] Fix escaping of password fields to prevent interpolation - -Some password and pin fields are missing from the no_interpolation list. -One entry is misspelled. A '%' in password field such as -pki_clone_pkcs12_password causes an installation error. - -https://fedorahosted.org/pki/ticket/1703 - -Signed-off-by: Christian Heimes - -Based off of 'master' check-in: 2fe50f3098aba9d604a812604cecb75279f445bf ---- - base/server/python/pki/server/deployment/pkiparser.py | 8 ++++++-- - 1 file changed, 6 insertions(+), 2 deletions(-) - -diff --git a/base/server/python/pki/server/deployment/pkiparser.py b/base/server/python/pki/server/deployment/pkiparser.py -index 4b3dabb..6b4420b 100644 ---- a/base/server/python/pki/server/deployment/pkiparser.py -+++ b/base/server/python/pki/server/deployment/pkiparser.py -@@ -330,11 +330,15 @@ class PKIConfigParser: - 'pki_admin_password', - 'pki_backup_password', - 'pki_client_database_password', -+ 'pki_client_pin', - 'pki_client_pkcs12_password', -+ 'pki_clone_pkcs12_password', - 'pki_ds_password', -+ 'pki_one_time_pin', - 'pki_pin', -- 'pki_replicationdb_password', -- 'pki_security_domain_password') -+ 'pki_replication_password', -+ 'pki_security_domain_password', -+ 'pki_token_password') - - print 'Loading deployment configuration from ' + \ - config.user_deployment_cfg + '.' --- -1.8.3.1 - diff --git a/SOURCES/pki-core-Fix-to-determine-supported-javadoc-options.patch b/SOURCES/pki-core-Fix-to-determine-supported-javadoc-options.patch deleted file mode 100644 index c943807..0000000 --- a/SOURCES/pki-core-Fix-to-determine-supported-javadoc-options.patch +++ /dev/null @@ -1,86 +0,0 @@ -From db7055457d421b796c1af6f0549a746a65939a05 Mon Sep 17 00:00:00 2001 -From: Matthew Harmsen -Date: Thu, 18 Feb 2016 17:53:26 -0700 -Subject: [PATCH] Fix to determine supported javadoc options - -- PKI TRAC Ticket #2040 - Determine supported javadoc options ---- - base/javadoc/CMakeLists.txt | 61 +++++++++++++++++++++++++++++++++++++++++++-- - 1 file changed, 59 insertions(+), 2 deletions(-) - -diff --git a/base/javadoc/CMakeLists.txt b/base/javadoc/CMakeLists.txt -index fa524be..09aa410 100644 ---- a/base/javadoc/CMakeLists.txt -+++ b/base/javadoc/CMakeLists.txt -@@ -1,9 +1,66 @@ - project(pki-javadoc) - -+# It is important to identify the version of 'javadoc' being utilized since -+# different versions support different options. -+# -+# While 'cmake' contains numerous built-in references to the 'java' version, -+# it contains no built-in references to either the 'javac' or 'javadoc' -+# versions, and unfortunately, the specified version of 'java' may be -+# different from the specified versions of 'javac' and 'javadoc'. -+# -+# Additionally, although 'javadoc' contains no command-line option to identify -+# its version, it is important to note that 'javadoc' is supplied by the same -+# package that supplies 'javac', and although multiple versions of these -+# executables could co-exist on the same system, it is relatively safe to -+# assert that the currently specified 'javac' and 'javadoc' will be the same -+# version. -+# -+# As an example in support of this assertion, on systems which utilize -+# '/usr/sbin/alternatives', setting the 'javac' version will also -+# automatically set the 'javadoc' version to match the 'javac' version, and -+# 'usr/sbin/alternatives' cannot be used to set a specific 'javadoc' version. -+# -+# Therefore, regardless of the 'java' version, this 'CMakeLists.txt' file will -+# programmatically utilize the invoked 'javac' version information (output is -+# to stderr) in order to correctly identify the supported 'javadoc' options: -+# -+# # javac -version 2>&1 | awk -F \. '{printf $2}' -+# -+# NOTE: Used 'cut' instead of 'awk' due to 'cmake' parsing limitations: -+# -+# # javac -version 2>&1 | cut -f2 -d. -+# -+message( STATUS "Java_VERSION_STRING = '${Java_VERSION_STRING}'" ) -+execute_process( -+ COMMAND -+ javac -version -+ ERROR_VARIABLE -+ Javac_VERSION_OUTPUT -+ OUTPUT_VARIABLE -+ Javac_VERSION_OUTPUT -+ ERROR_STRIP_TRAILING_WHITESPACE -+ OUTPUT_STRIP_TRAILING_WHITESPACE -+) -+message( STATUS "Javac_VERSION_OUTPUT = '${Javac_VERSION_OUTPUT}'" ) -+execute_process( -+ COMMAND -+ echo ${Javac_VERSION_OUTPUT} -+ COMMAND -+ cut -f2 -d. -+ OUTPUT_VARIABLE -+ Javadoc_VERSION_MINOR -+ OUTPUT_STRIP_TRAILING_WHITESPACE -+) -+message( STATUS "Javadoc_VERSION_MINOR = '${Javadoc_VERSION_MINOR}'" ) -+ -+# REMINDER: Eventually, it would almost certainly be safer to obtain the -+# 'Javadoc_VERSION_MAJOR' number as well and perform the check -+# on "'Javadoc_VERSION_MAJOR'.'Javadoc_VERSION_MINOR'". -+# - set(doclintstr "") --if(${Java_VERSION_MINOR} VERSION_EQUAL 8 OR ${Java_VERSION_MINOR} VERSION_GREATER 8) -+if(NOT (${Javadoc_VERSION_MINOR} LESS 8)) - set(doclintstr "-Xdoclint:none") --endif(${Java_VERSION_MINOR} VERSION_EQUAL 8 OR ${Java_VERSION_MINOR} VERSION_GREATER 8) -+endif(NOT (${Javadoc_VERSION_MINOR} LESS 8)) - - javadoc(pki-javadoc - SOURCEPATH --- -1.8.3.1 - diff --git a/SOURCES/pki-core-Fixed-KRA-install-problem.patch b/SOURCES/pki-core-Fixed-KRA-install-problem.patch deleted file mode 100644 index 229ce67..0000000 --- a/SOURCES/pki-core-Fixed-KRA-install-problem.patch +++ /dev/null @@ -1,129 +0,0 @@ -From 78d42fcb8def1c21dc9a82251b760ab1b7a23f88 Mon Sep 17 00:00:00 2001 -From: Matthew Harmsen -Date: Wed, 30 Mar 2016 15:16:06 -0600 -Subject: [PATCH] Fixed KRA install problem. - -Currently when installing an additional subsystem to an existing -instance the install tool always generates a new random password in -the pki_pin property which would not work with the existing NSS -database. The code has been modified to load the existing NSS -database password from the instance if the instance already exists. - -The PKIInstance class has been modified to allow loading partially -created instance to help the installation. - -https://fedorahosted.org/pki/ticket/2247 - -Altered from 'master' (10.3.0) so that it could be applied -to 'DOGTAG_10_2_5_RHEL_BRANCH' (10.2.5). ---- - base/server/python/pki/server/__init__.py | 54 ++++++++++++---------- - .../python/pki/server/deployment/pkiparser.py | 18 ++++++-- - 2 files changed, 44 insertions(+), 28 deletions(-) - -diff --git a/base/server/python/pki/server/__init__.py b/base/server/python/pki/server/__init__.py -index 22b6fcf..971a3f6 100644 ---- a/base/server/python/pki/server/__init__.py -+++ b/base/server/python/pki/server/__init__.py -@@ -413,40 +413,44 @@ class PKIInstance(object): - - def load(self): - # load UID and GID -- with open(self.registry_file, 'r') as registry: -- lines = registry.readlines() -+ if os.path.exists(self.registry_file): - -- for line in lines: -+ with open(self.registry_file, 'r') as registry: -+ lines = registry.readlines() - -- m = re.search('^PKI_USER=(.*)$', line) -- if m: -- self.user = m.group(1) -- self.uid = pwd.getpwnam(self.user).pw_uid -+ for line in lines: -+ m = re.search('^PKI_USER=(.*)$', line) -+ if m: -+ self.user = m.group(1) -+ self.uid = pwd.getpwnam(self.user).pw_uid - -- m = re.search('^PKI_GROUP=(.*)$', line) -- if m: -- self.group = m.group(1) -- self.gid = grp.getgrnam(self.group).gr_gid -+ m = re.search('^PKI_GROUP=(.*)$', line) -+ if m: -+ self.group = m.group(1) -+ self.gid = grp.getgrnam(self.group).gr_gid - - # load passwords - self.passwords.clear() -- lines = open(self.password_conf).read().splitlines() -+ if os.path.exists(self.password_conf): - -- for line in lines: -- parts = line.split('=', 1) -- name = parts[0] -- value = parts[1] -- self.passwords[name] = value -+ lines = open(self.password_conf).read().splitlines() -+ -+ for line in lines: -+ parts = line.split('=', 1) -+ name = parts[0] -+ value = parts[1] -+ self.passwords[name] = value - - # load subsystems -- for subsystem_name in os.listdir(self.registry_dir): -- if subsystem_name in SUBSYSTEM_TYPES: -- if subsystem_name in SUBSYSTEM_CLASSES: -- subsystem = SUBSYSTEM_CLASSES[subsystem_name](self) -- else: -- subsystem = PKISubsystem(self, subsystem_name) -- subsystem.load() -- self.subsystems.append(subsystem) -+ if os.path.exists(self.registry_dir): -+ for subsystem_name in os.listdir(self.registry_dir): -+ if subsystem_name in SUBSYSTEM_TYPES: -+ if subsystem_name in SUBSYSTEM_CLASSES: -+ subsystem = SUBSYSTEM_CLASSES[subsystem_name](self) -+ else: -+ subsystem = PKISubsystem(self, subsystem_name) -+ subsystem.load() -+ self.subsystems.append(subsystem) - - def get_password(self, name): - if name in self.passwords: -diff --git a/base/server/python/pki/server/deployment/pkiparser.py b/base/server/python/pki/server/deployment/pkiparser.py -index 14fe519..a5aaa97 100644 ---- a/base/server/python/pki/server/deployment/pkiparser.py -+++ b/base/server/python/pki/server/deployment/pkiparser.py -@@ -569,9 +569,21 @@ class PKIConfigParser: - pin_low = 100000000000 - pin_high = 999999999999 - -- # use user-provided PIN if specified -- if 'pki_pin' not in self.mdict: -- # otherwise generate a random password -+ instance = pki.server.PKIInstance(self.mdict['pki_instance_name']) -+ instance.load() -+ -+ internal_password = self.mdict['pki_self_signed_token'] -+ -+ # if instance already exists and has password, reuse the password -+ if internal_password in instance.passwords: -+ self.mdict['pki_pin'] = instance.passwords.get(internal_password) -+ -+ # otherwise, use user-provided password if specified -+ elif 'pki_pin' in self.mdict: -+ pass -+ -+ # otherwise, generate a random password -+ else: - self.mdict['pki_pin'] = \ - random.randint(pin_low, pin_high) - --- -1.8.3.1 - diff --git a/SOURCES/pki-core-Fixed-certificate-chain-import-problem.patch b/SOURCES/pki-core-Fixed-certificate-chain-import-problem.patch deleted file mode 100644 index 874bdff..0000000 --- a/SOURCES/pki-core-Fixed-certificate-chain-import-problem.patch +++ /dev/null @@ -1,62 +0,0 @@ -From c2d66070b05c0230d7d508458223337a0d2571c4 Mon Sep 17 00:00:00 2001 -From: "Endi S. Dewata" -Date: Fri, 25 Mar 2016 03:33:05 +0100 -Subject: [PATCH] Fixed certificate chain import problem. - -In the external CA case if the externally-signed CA certificate -is included in the certificate chain the CA certificate may get -imported with an incorrect nickname. - -The code has been modified such that the certificate chain is -imported after the CA certificate is imported with the proper -nickname. - -https://fedorahosted.org/pki/ticket/2022 ---- - .../server/deployment/scriptlets/configuration.py | 22 ++++++++++++---------- - 1 file changed, 12 insertions(+), 10 deletions(-) - -diff --git a/base/server/python/pki/server/deployment/scriptlets/configuration.py b/base/server/python/pki/server/deployment/scriptlets/configuration.py -index 54f065f094c811cdbf944a0ac14e019d0d4d6145..e344e9652fdefc97300cb78ee6f269cfd89b805e 100644 ---- a/base/server/python/pki/server/deployment/scriptlets/configuration.py -+++ b/base/server/python/pki/server/deployment/scriptlets/configuration.py -@@ -157,17 +157,9 @@ class PkiScriptlet(pkiscriptlet.AbstractBasePkiScriptlet): - signing_csr = pki.nssdb.convert_csr(signing_csr, 'pem', 'base64') - subsystem.config['ca.signing.certreq'] = signing_csr - -- # If specified, import external CA cert into NSS database. -- external_ca_cert_chain_nickname = deployer.mdict['pki_external_ca_cert_chain_nickname'] -- external_ca_cert_chain_file = deployer.mdict['pki_external_ca_cert_chain_path'] -- if external_ca_cert_chain_file: -- cert_chain, _nicks = nssdb.import_cert_chain( -- nickname=external_ca_cert_chain_nickname, -- cert_chain_file=external_ca_cert_chain_file, -- trust_attributes='CT,C,C') -- subsystem.config['ca.external_ca_chain.cert'] = cert_chain -- - # If specified, import externally-signed CA cert into NSS database. -+ # Note: CA cert must be imported before the cert chain to ensure that -+ # the CA cert is imported with the correct nickname. - signing_nickname = deployer.mdict['pki_ca_signing_nickname'] - signing_cert_file = deployer.mdict['pki_external_ca_cert_path'] - if signing_cert_file: -@@ -182,6 +174,16 @@ class PkiScriptlet(pkiscriptlet.AbstractBasePkiScriptlet): - pkcs12_password = deployer.mdict['pki_external_pkcs12_password'] - nssdb.import_pkcs12(pkcs12_file, pkcs12_password) - -+ # If specified, import cert chain into NSS database. -+ external_ca_cert_chain_nickname = deployer.mdict['pki_external_ca_cert_chain_nickname'] -+ external_ca_cert_chain_file = deployer.mdict['pki_external_ca_cert_chain_path'] -+ if external_ca_cert_chain_file: -+ cert_chain, _nicks = nssdb.import_cert_chain( -+ nickname=external_ca_cert_chain_nickname, -+ cert_chain_file=external_ca_cert_chain_file, -+ trust_attributes='CT,C,C') -+ subsystem.config['ca.external_ca_chain.cert'] = cert_chain -+ - # Export CA cert from NSS database and import it into CS.cfg. - signing_cert_data = nssdb.get_cert( - nickname=signing_nickname, --- -2.4.3 - diff --git a/SOURCES/pki-core-Fixed-mismatching-certificate-validity-calculation.patch b/SOURCES/pki-core-Fixed-mismatching-certificate-validity-calculation.patch deleted file mode 100644 index 9a85df9..0000000 --- a/SOURCES/pki-core-Fixed-mismatching-certificate-validity-calculation.patch +++ /dev/null @@ -1,180 +0,0 @@ -From 8ef4f6fc86753cafef9256e8102926d6effbbb0b Mon Sep 17 00:00:00 2001 -From: "Endi S. Dewata" -Date: Sun, 20 Dec 2015 21:46:56 +0100 -Subject: [PATCH] Fixed mismatching certificate validity calculation. - -The CAValidityDefault has been modified to use Calendar API to -calculate the certificate validity range to be consistent with -the ValidityConstraint and ValidityDefault. - -https://fedorahosted.org/pki/ticket/1682 ---- - .../cms/profile/def/CAValidityDefault.java | 79 ++++++++++++++++++---- - base/server/cmsbundle/src/UserMessages.properties | 2 +- - 2 files changed, 67 insertions(+), 14 deletions(-) - -diff --git a/base/server/cms/src/com/netscape/cms/profile/def/CAValidityDefault.java b/base/server/cms/src/com/netscape/cms/profile/def/CAValidityDefault.java -index 44ffd474f8aa23abff922f6fc37e92cd12536dec..a98b2c28c12c78ac6ffa420c880ba0c317f5f94b 100644 ---- a/base/server/cms/src/com/netscape/cms/profile/def/CAValidityDefault.java -+++ b/base/server/cms/src/com/netscape/cms/profile/def/CAValidityDefault.java -@@ -20,14 +20,10 @@ package com.netscape.cms.profile.def; - import java.io.IOException; - import java.text.ParsePosition; - import java.text.SimpleDateFormat; -+import java.util.Calendar; - import java.util.Date; - import java.util.Locale; - --import netscape.security.x509.BasicConstraintsExtension; --import netscape.security.x509.CertificateValidity; --import netscape.security.x509.PKIXExtensions; --import netscape.security.x509.X509CertInfo; -- - import com.netscape.certsrv.apps.CMS; - import com.netscape.certsrv.base.IConfigStore; - import com.netscape.certsrv.ca.ICertificateAuthority; -@@ -38,6 +34,11 @@ import com.netscape.certsrv.property.EPropertyException; - import com.netscape.certsrv.property.IDescriptor; - import com.netscape.certsrv.request.IRequest; - -+import netscape.security.x509.BasicConstraintsExtension; -+import netscape.security.x509.CertificateValidity; -+import netscape.security.x509.PKIXExtensions; -+import netscape.security.x509.X509CertInfo; -+ - /** - * This class implements a CA signing cert enrollment default policy - * that populates a server-side configurable validity -@@ -46,6 +47,7 @@ import com.netscape.certsrv.request.IRequest; - */ - public class CAValidityDefault extends EnrollDefault { - public static final String CONFIG_RANGE = "range"; -+ public static final String CONFIG_RANGE_UNIT = "rangeUnit"; - public static final String CONFIG_START_TIME = "startTime"; - public static final String CONFIG_BYPASS_CA_NOTAFTER = "bypassCAnotafter"; - -@@ -61,6 +63,7 @@ public class CAValidityDefault extends EnrollDefault { - public CAValidityDefault() { - super(); - addConfigName(CONFIG_RANGE); -+ addConfigName(CONFIG_RANGE_UNIT); - addConfigName(CONFIG_START_TIME); - addConfigName(CONFIG_BYPASS_CA_NOTAFTER); - -@@ -103,6 +106,12 @@ public class CAValidityDefault extends EnrollDefault { - "7305", /* 20 years */ - CMS.getUserMessage(locale, - "CMS_PROFILE_VALIDITY_RANGE")); -+ } else if (name.equals(CONFIG_RANGE_UNIT)) { -+ return new Descriptor(IDescriptor.STRING, -+ null, -+ "day", -+ CMS.getUserMessage(locale, -+ "CMS_PROFILE_VALIDITY_RANGE_UNIT")); - } else if (name.equals(CONFIG_START_TIME)) { - return new Descriptor(IDescriptor.STRING, - null, -@@ -299,6 +308,28 @@ public class CAValidityDefault extends EnrollDefault { - return CMS.getUserMessage(locale, "CMS_PROFILE_DEF_VALIDITY", params); - } - -+ public int convertRangeUnit(String unit) throws Exception { -+ -+ if (unit.equals("year")) { -+ return Calendar.YEAR; -+ -+ } else if (unit.equals("month")) { -+ return Calendar.MONTH; -+ -+ } else if (unit.equals("day")) { -+ return Calendar.DAY_OF_YEAR; -+ -+ } else if (unit.equals("hour")) { -+ return Calendar.HOUR_OF_DAY; -+ -+ } else if (unit.equals("minute")) { -+ return Calendar.MINUTE; -+ -+ } else { -+ throw new Exception("Invalid range unit: " + unit); -+ } -+ } -+ - /** - * Populates the request with this policy default. - */ -@@ -307,6 +338,7 @@ public class CAValidityDefault extends EnrollDefault { - - // always + 60 seconds - String startTimeStr = getConfig(CONFIG_START_TIME); -+ CMS.debug("CAValidityDefault: start time: " + startTimeStr); - try { - startTimeStr = mapPattern(request, startTimeStr); - } catch (IOException e) { -@@ -317,21 +349,42 @@ public class CAValidityDefault extends EnrollDefault { - startTimeStr = "60"; - } - int startTime = Integer.parseInt(startTimeStr); -+ - Date notBefore = new Date(CMS.getCurrentDate().getTime() + (1000 * startTime)); -- long notAfterVal = 0; -+ CMS.debug("CAValidityDefault: not before: " + notBefore); - -+ String rangeStr = getConfig(CONFIG_RANGE, "7305"); -+ CMS.debug("CAValidityDefault: range: " + rangeStr); -+ -+ int range; - try { -- String rangeStr = getConfig(CONFIG_RANGE); - rangeStr = mapPattern(request, rangeStr); -- notAfterVal = notBefore.getTime() + -- (mDefault * Integer.parseInt(rangeStr)); -- } catch (Exception e) { -- // configured value is not correct -- CMS.debug("CAValidityDefault: populate " + e.toString()); -+ range = Integer.parseInt(rangeStr); -+ } catch (IOException e) { -+ CMS.debug(e); - throw new EProfileException(CMS.getUserMessage( - getLocale(request), "CMS_INVALID_PROPERTY", CONFIG_RANGE)); - } -- Date notAfter = new Date(notAfterVal); -+ -+ String rangeUnitStr = getConfig(CONFIG_RANGE_UNIT, "day"); -+ CMS.debug("CAValidityDefault: range unit: " + rangeUnitStr); -+ -+ int rangeUnit; -+ try { -+ rangeUnit = convertRangeUnit(rangeUnitStr); -+ } catch (Exception e) { -+ CMS.debug(e); -+ throw new EProfileException(CMS.getUserMessage( -+ getLocale(request), "CMS_INVALID_PROPERTY", CONFIG_RANGE_UNIT)); -+ } -+ -+ // calculate the end of validity range -+ Calendar date = Calendar.getInstance(); -+ date.setTime(notBefore); -+ date.add(rangeUnit, range); -+ -+ Date notAfter = date.getTime(); -+ CMS.debug("CAValidityDefault: not after: " + notAfter); - - CertificateValidity validity = - new CertificateValidity(notBefore, notAfter); -diff --git a/base/server/cmsbundle/src/UserMessages.properties b/base/server/cmsbundle/src/UserMessages.properties -index 6b4dc69b5a6787309f02b0e5e79d93b1f2918f88..7c5c77d5b589886d0a8c6323436a1fdcdd4ce8f9 100644 ---- a/base/server/cmsbundle/src/UserMessages.properties -+++ b/base/server/cmsbundle/src/UserMessages.properties -@@ -835,7 +835,7 @@ CMS_PROFILE_VALIDITY_CHECK_NOT_BEFORE=Check Not Before against current time - CMS_PROFILE_VALIDITY_CHECK_NOT_AFTER=Check Not After against Not Before - CMS_PROFILE_VALIDITY_NOT_BEFORE_GRACE_PERIOD=Grace period for Not Before being set in the future (in seconds). - CMS_PROFILE_VALIDITY_RANGE=Validity Range --CMS_PROFILE_VALIDITY_RANGE_UNIT=Validity Range Unit (default: day) -+CMS_PROFILE_VALIDITY_RANGE_UNIT=Validity Range Unit: year, month, day (default), hour, minute - CMS_PROFILE_VALIDITY_START_TIME=Relative Start Time (in seconds) - CMS_PROFILE_NOT_BEFORE_RANDOM_BITS=Not Before Random Bits - CMS_PROFILE_NOT_AFTER_RANDOM_BITS=Not After Random Bits --- -2.4.3 - diff --git a/SOURCES/pki-core-Fixed-missing-trust-flags-in-certificate-backup.patch b/SOURCES/pki-core-Fixed-missing-trust-flags-in-certificate-backup.patch deleted file mode 100644 index 42f6aaa..0000000 --- a/SOURCES/pki-core-Fixed-missing-trust-flags-in-certificate-backup.patch +++ /dev/null @@ -1,452 +0,0 @@ -From b216472ddd80f64b136b3ac367d3415b526c97d4 Mon Sep 17 00:00:00 2001 -From: Matthew Harmsen -Date: Fri, 1 Apr 2016 14:57:07 -0600 -Subject: [PATCH] Fixed missing trust flags in certificate backup. - -The ConfigurationUtils.backupKeys() has been modified to use -PKCS12Util to export the certificates and their trust flags into -a PKCS #12 file such that the file can be used for cloning. - -The code to generate PFX object has been refactored from the -PKCS12Util.storeIntoFile() into a separate generatePFX() method. - -The PKCS12Util.loadCertFromNSS() has been modified to provide -options to load a certificate from NSS database without the key -or the certificate chain. The CLIs have been modified to provide -the same options. - -The PKCS12Util.getCertInfo() has modified to ignore missing -certificate attributes in the PKCS #12 file and generate a new -local ID. - -https://fedorahosted.org/pki/ticket/2257 ---- - base/java-tools/bin/pki | 3 + - .../netscape/cmstools/pkcs12/PKCS12CertAddCLI.java | 7 +- - .../netscape/cmstools/pkcs12/PKCS12ExportCLI.java | 12 ++- - .../cms/servlet/csadmin/ConfigurationUtils.java | 39 ++++---- - .../src/netscape/security/pkcs/PKCS12Util.java | 108 ++++++++++++--------- - 5 files changed, 97 insertions(+), 72 deletions(-) - -diff --git a/base/java-tools/bin/pki b/base/java-tools/bin/pki -index e476cfc..88490f7 100644 ---- a/base/java-tools/bin/pki -+++ b/base/java-tools/bin/pki -@@ -138,6 +138,9 @@ class PKICLI(pki.cli.CLI): - if self.token and self.token != 'internal': - cmd.extend(['--token', self.token]) - -+ if self.verbose: -+ cmd.extend(['--verbose']) -+ - cmd.extend(args) - - if self.verbose: -diff --git a/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12CertAddCLI.java b/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12CertAddCLI.java -index 48e4907..a422b20 100644 ---- a/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12CertAddCLI.java -+++ b/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12CertAddCLI.java -@@ -65,6 +65,8 @@ public class PKCS12CertAddCLI extends CLI { - - options.addOption(null, "new-file", false, "Create a new PKCS #12 file"); - options.addOption(null, "no-trust-flags", false, "Do not include trust flags"); -+ options.addOption(null, "no-key", false, "Do not include private key"); -+ options.addOption(null, "no-chain", false, "Do not include certificate chain"); - - options.addOption("v", "verbose", false, "Run in verbose mode."); - options.addOption(null, "debug", false, "Run in debug mode."); -@@ -139,6 +141,8 @@ public class PKCS12CertAddCLI extends CLI { - - boolean newFile = cmd.hasOption("new-file"); - boolean includeTrustFlags = !cmd.hasOption("no-trust-flags"); -+ boolean includeKey = !cmd.hasOption("no-key"); -+ boolean includeChain = !cmd.hasOption("no-chain"); - - try { - PKCS12Util util = new PKCS12Util(); -@@ -155,7 +159,8 @@ public class PKCS12CertAddCLI extends CLI { - pkcs12 = util.loadFromFile(filename, password); - } - -- util.loadCertFromNSS(pkcs12, nickname); -+ // load the specified certificate -+ util.loadCertFromNSS(pkcs12, nickname, includeKey, includeChain); - util.storeIntoFile(pkcs12, filename, password); - - } finally { -diff --git a/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12ExportCLI.java b/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12ExportCLI.java -index d42c449..fab5ecd 100644 ---- a/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12ExportCLI.java -+++ b/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12ExportCLI.java -@@ -63,6 +63,8 @@ public class PKCS12ExportCLI extends CLI { - - options.addOption(null, "new-file", false, "Create a new PKCS #12 file"); - options.addOption(null, "no-trust-flags", false, "Do not include trust flags"); -+ options.addOption(null, "no-key", false, "Do not include private key"); -+ options.addOption(null, "no-chain", false, "Do not include certificate chain"); - - options.addOption("v", "verbose", false, "Run in verbose mode."); - options.addOption(null, "debug", false, "Run in debug mode."); -@@ -127,11 +129,13 @@ public class PKCS12ExportCLI extends CLI { - Password password = new Password(passwordString.toCharArray()); - - boolean newFile = cmd.hasOption("new-file"); -- boolean trustFlagsEnabled = !cmd.hasOption("no-trust-flags"); -+ boolean includeTrustFlags = !cmd.hasOption("no-trust-flags"); -+ boolean includeKey = !cmd.hasOption("no-key"); -+ boolean includeChain = !cmd.hasOption("no-chain"); - - try { - PKCS12Util util = new PKCS12Util(); -- util.setTrustFlagsEnabled(trustFlagsEnabled); -+ util.setTrustFlagsEnabled(includeTrustFlags); - - PKCS12 pkcs12; - -@@ -149,9 +153,9 @@ public class PKCS12ExportCLI extends CLI { - util.loadFromNSS(pkcs12); - - } else { -- // load specified certificates -+ // load the specified certificates - for (String nickname : nicknames) { -- util.loadCertFromNSS(pkcs12, nickname); -+ util.loadCertFromNSS(pkcs12, nickname, includeKey, includeChain); - } - } - -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 f092eac..713e1b0 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 -@@ -32,7 +32,6 @@ import java.net.ConnectException; - import java.net.URI; - import java.net.URISyntaxException; - import java.net.URLEncoder; --import java.security.DigestException; - import java.security.InvalidAlgorithmParameterException; - import java.security.InvalidKeyException; - import java.security.KeyPair; -@@ -171,6 +170,8 @@ 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; -@@ -3352,11 +3353,8 @@ public class ConfigurationUtils { - } - } - -- public static void backupKeys(String pwd, String fname) throws EPropertyNotFound, EBaseException, -- NotInitializedException, ObjectNotFoundException, TokenException, DigestException, -- InvalidKeyException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidBERException, -- CertificateEncodingException, IllegalStateException, IllegalBlockSizeException, BadPaddingException, -- IOException { -+ public static void backupKeys(String pwd, String fname) throws Exception { -+ - CMS.debug("backupKeys(): start"); - IConfigStore cs = CMS.getConfigStore(); - String certlist = cs.getString("preop.cert.list"); -@@ -3365,9 +3363,13 @@ public class ConfigurationUtils { - CryptoManager cm = CryptoManager.getInstance(); - - Password pass = new org.mozilla.jss.util.Password(pwd.toCharArray()); -- SEQUENCE encSafeContents = new SEQUENCE(); -- SEQUENCE safeContents = new SEQUENCE(); -+ -+ PKCS12Util util = new PKCS12Util(); -+ PKCS12 pkcs12 = new PKCS12(); -+ -+ // load system certificate (with key but without chain) - while (st.hasMoreTokens()) { -+ - String t = st.nextToken(); - if (t.equals("sslserver")) - continue; -@@ -3377,27 +3379,20 @@ public class ConfigurationUtils { - if (!modname.equals("Internal Key Storage Token")) - nickname = modname + ":" + nickname; - -- X509Certificate x509cert = cm.findCertByNickname(nickname); -- byte localKeyId[] = addCertBag(x509cert, nickname, safeContents); -- PrivateKey pkey = cm.findPrivKeyByCert(x509cert); -- addKeyBag(pkey, x509cert, pass, localKeyId, encSafeContents); -+ util.loadCertFromNSS(pkcs12, nickname, true, false); - } - -- X509Certificate[] cacerts = cm.getCACerts(); -- -- for (int i = 0; i < cacerts.length; i++) { -- String nickname = null; -- addCertBag(cacerts[i], nickname, safeContents); -+ // load CA certificates (without keys or chains) -+ for (X509Certificate caCert : cm.getCACerts()) { -+ util.loadCertFromNSS(pkcs12, caCert, false, false); - } - -- AuthenticatedSafes authSafes = new AuthenticatedSafes(); -- authSafes.addSafeContents(safeContents); -- authSafes.addSafeContents(encSafeContents); -- PFX pfx = new PFX(authSafes); -- pfx.computeMacData(pass, null, 5); -+ PFX pfx = util.generatePFX(pkcs12, pass); -+ - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - pfx.encode(bos); - byte[] output = bos.toByteArray(); -+ - cs.putString("preop.pkcs12", CryptoUtil.byte2string(output)); - pass.clear(); - cs.commit(false); -diff --git a/base/util/src/netscape/security/pkcs/PKCS12Util.java b/base/util/src/netscape/security/pkcs/PKCS12Util.java -index 7c9ab2f..967479b 100644 ---- a/base/util/src/netscape/security/pkcs/PKCS12Util.java -+++ b/base/util/src/netscape/security/pkcs/PKCS12Util.java -@@ -162,13 +162,14 @@ public class PKCS12Util { - } - - BigInteger createLocalID(X509Certificate cert) throws Exception { -- - // SHA1 hash of the X509Cert DER encoding -- byte[] certDer = cert.getEncoded(); -+ return createLocalID(cert.getEncoded()); -+ } - -- MessageDigest md = MessageDigest.getInstance("SHA"); -+ BigInteger createLocalID(byte[] bytes) throws Exception { - -- md.update(certDer); -+ MessageDigest md = MessageDigest.getInstance("SHA"); -+ md.update(bytes); - return new BigInteger(1, md.digest()); - } - -@@ -244,21 +245,46 @@ public class PKCS12Util { - CryptoStore store = token.getCryptoStore(); - - for (X509Certificate cert : store.getCertificates()) { -- loadCertChainFromNSS(pkcs12, cert); -+ loadCertFromNSS(pkcs12, cert, true, true); - } - } - -- public void loadCertFromNSS(PKCS12 pkcs12, String nickname) throws Exception { -+ public void loadCertFromNSS(PKCS12 pkcs12, String nickname, boolean includeKey, boolean includeChain) throws Exception { - - CryptoManager cm = CryptoManager.getInstance(); - - X509Certificate[] certs = cm.findCertsByNickname(nickname); - for (X509Certificate cert : certs) { -- loadCertChainFromNSS(pkcs12, cert); -+ loadCertFromNSS(pkcs12, cert, includeKey, includeChain); - } - } - -- public void loadCertFromNSS(PKCS12 pkcs12, X509Certificate cert, BigInteger id, boolean replace) throws Exception { -+ public void loadCertFromNSS(PKCS12 pkcs12, X509Certificate cert, boolean includeKey, boolean includeChain) throws Exception { -+ -+ CryptoManager cm = CryptoManager.getInstance(); -+ -+ BigInteger id = createLocalID(cert); -+ -+ // load cert info -+ loadCertInfoFromNSS(pkcs12, cert, id, true); -+ -+ if (includeKey) { -+ // load key info if exists -+ loadKeyInfoFromNSS(pkcs12, cert, id); -+ } -+ -+ if (includeChain) { -+ // load cert chain -+ X509Certificate[] certChain = cm.buildCertificateChain(cert); -+ for (int i = 1; i < certChain.length; i++) { -+ X509Certificate c = certChain[i]; -+ BigInteger cid = createLocalID(c); -+ loadCertInfoFromNSS(pkcs12, c, cid, false); -+ } -+ } -+ } -+ -+ public void loadCertInfoFromNSS(PKCS12 pkcs12, X509Certificate cert, BigInteger id, boolean replace) throws Exception { - - String nickname = cert.getNickname(); - logger.info("Loading certificate \"" + nickname + "\" from NSS database"); -@@ -272,7 +298,7 @@ public class PKCS12Util { - pkcs12.addCertInfo(certInfo, replace); - } - -- public void loadCertKeyFromNSS(PKCS12 pkcs12, X509Certificate cert, BigInteger id) throws Exception { -+ public void loadKeyInfoFromNSS(PKCS12 pkcs12, X509Certificate cert, BigInteger id) throws Exception { - - String nickname = cert.getNickname(); - logger.info("Loading private key for certificate \"" + nickname + "\" from NSS database"); -@@ -298,30 +324,9 @@ public class PKCS12Util { - } - } - -- public void loadCertChainFromNSS(PKCS12 pkcs12, X509Certificate cert) throws Exception { -- -- CryptoManager cm = CryptoManager.getInstance(); -+ public PFX generatePFX(PKCS12 pkcs12, Password password) throws Exception { - -- BigInteger id = createLocalID(cert); -- -- // load cert key if exists -- loadCertKeyFromNSS(pkcs12, cert, id); -- -- // load cert -- loadCertFromNSS(pkcs12, cert, id, true); -- -- // load parent certs without key -- X509Certificate[] certChain = cm.buildCertificateChain(cert); -- for (int i = 1; i < certChain.length; i++) { -- X509Certificate c = certChain[i]; -- BigInteger cid = createLocalID(c); -- loadCertFromNSS(pkcs12, c, cid, false); -- } -- } -- -- public void storeIntoFile(PKCS12 pkcs12, String filename, Password password) throws Exception { -- -- logger.info("Storing data into PKCS #12 file"); -+ logger.info("Generating PKCS #12 data"); - - SEQUENCE safeContents = new SEQUENCE(); - -@@ -342,6 +347,14 @@ public class PKCS12Util { - PFX pfx = new PFX(authSafes); - pfx.computeMacData(password, null, 5); - -+ return pfx; -+ } -+ -+ public void storeIntoFile(PKCS12 pkcs12, String filename, Password password) throws Exception { -+ -+ PFX pfx = generatePFX(pkcs12, password); -+ -+ logger.info("Storing data into PKCS #12 file"); - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - pfx.encode(bos); - byte[] data = bos.toByteArray(); -@@ -362,7 +375,7 @@ public class PKCS12Util { - // get key attributes - SET bagAttrs = bag.getBagAttributes(); - -- for (int i = 0; i < bagAttrs.size(); i++) { -+ for (int i = 0; bagAttrs != null && i < bagAttrs.size(); i++) { - - Attribute attr = (Attribute) bagAttrs.elementAt(i); - OBJECT_IDENTIFIER oid = attr.getType(); -@@ -376,7 +389,7 @@ public class PKCS12Util { - BMPString subjectDN = (BMPString) new BMPString.Template().decode(bis); - - keyInfo.subjectDN = subjectDN.toString(); -- logger.fine("Subject DN: " + keyInfo.subjectDN); -+ logger.fine(" Subject DN: " + keyInfo.subjectDN); - - } else if (oid.equals(SafeBag.LOCAL_KEY_ID)) { - -@@ -387,12 +400,10 @@ public class PKCS12Util { - OCTET_STRING keyID = (OCTET_STRING) new OCTET_STRING.Template().decode(bis); - - keyInfo.id = new BigInteger(1, keyID.toByteArray()); -- logger.fine("ID: " + keyInfo.id.toString(16)); -+ logger.fine(" ID: " + keyInfo.id.toString(16)); - } - } - -- logger.fine("Found private key " + keyInfo.subjectDN); -- - return keyInfo; - } - -@@ -406,12 +417,11 @@ public class PKCS12Util { - byte[] x509cert = certStr.toByteArray(); - - certInfo.cert = new X509CertImpl(x509cert); -- logger.fine("Found certificate " + certInfo.cert.getSubjectDN()); -+ logger.fine(" Subject DN: " + certInfo.cert.getSubjectDN()); - - SET bagAttrs = bag.getBagAttributes(); -- if (bagAttrs == null) return certInfo; - -- for (int i = 0; i < bagAttrs.size(); i++) { -+ for (int i = 0; bagAttrs != null && i < bagAttrs.size(); i++) { - - Attribute attr = (Attribute) bagAttrs.elementAt(i); - OBJECT_IDENTIFIER oid = attr.getType(); -@@ -425,7 +435,7 @@ public class PKCS12Util { - BMPString nickname = (BMPString) (new BMPString.Template()).decode(bis); - - certInfo.nickname = nickname.toString(); -- logger.fine("Nickname: " + certInfo.nickname); -+ logger.fine(" Nickname: " + certInfo.nickname); - - - } else if (oid.equals(SafeBag.LOCAL_KEY_ID)) { -@@ -437,7 +447,7 @@ public class PKCS12Util { - OCTET_STRING keyID = (OCTET_STRING) new OCTET_STRING.Template().decode(bis); - - certInfo.id = new BigInteger(1, keyID.toByteArray()); -- logger.fine("ID: " + certInfo.id.toString(16)); -+ logger.fine(" ID: " + certInfo.id.toString(16)); - - } else if (oid.equals(PKCS12.CERT_TRUST_FLAGS_OID) && trustFlagsEnabled) { - -@@ -448,16 +458,22 @@ public class PKCS12Util { - BMPString trustFlags = (BMPString) (new BMPString.Template()).decode(is); - - certInfo.trustFlags = trustFlags.toString(); -- logger.fine("Trust flags: " + certInfo.trustFlags); -+ logger.fine(" Trust flags: " + certInfo.trustFlags); - } - } - -+ if (certInfo.id == null) { -+ logger.fine(" ID not specified, generating new ID"); -+ certInfo.id = createLocalID(x509cert); -+ logger.fine(" ID: " + certInfo.id.toString(16)); -+ } -+ - return certInfo; - } - - public void getKeyInfos(PKCS12 pkcs12, PFX pfx, Password password) throws Exception { - -- logger.fine("Getting private keys"); -+ logger.fine("Load private keys:"); - - AuthenticatedSafes safes = pfx.getAuthSafes(); - -@@ -472,6 +488,7 @@ public class PKCS12Util { - - if (!oid.equals(SafeBag.PKCS8_SHROUDED_KEY_BAG)) continue; - -+ logger.fine(" - Private key:"); - PKCS12KeyInfo keyInfo = getKeyInfo(bag, password); - pkcs12.addKeyInfo(keyInfo); - } -@@ -480,7 +497,7 @@ public class PKCS12Util { - - public void getCertInfos(PKCS12 pkcs12, PFX pfx, Password password) throws Exception { - -- logger.fine("Getting certificates"); -+ logger.fine("Loading certificates:"); - - AuthenticatedSafes safes = pfx.getAuthSafes(); - -@@ -495,6 +512,7 @@ public class PKCS12Util { - - if (!oid.equals(SafeBag.CERT_BAG)) continue; - -+ logger.fine(" - Certificate:"); - PKCS12CertInfo certInfo = getCertInfo(bag); - pkcs12.addCertInfo(certInfo, true); - } --- -1.8.3.1 - diff --git a/SOURCES/pki-core-Install-tools-clean-up.patch b/SOURCES/pki-core-Install-tools-clean-up.patch deleted file mode 100644 index 3b055eb..0000000 --- a/SOURCES/pki-core-Install-tools-clean-up.patch +++ /dev/null @@ -1,117 +0,0 @@ -From 0762566785b11c7a9879809ae82b8925fb829c57 Mon Sep 17 00:00:00 2001 -From: "Endi S. Dewata" -Date: Wed, 30 Mar 2016 04:29:11 +0200 -Subject: [PATCH] Install tools clean-up. - -Some variables in pkispawn and pkidestroy have been renamed for -clarity. - -The unused PKI_CERT_DB_PASSWORD_SLOT variable has been removed. - -The constant pki_self_signed_token property has been moved into -default.cfg. - -https://fedorahosted.org/pki/ticket/2247 ---- - base/server/config/pkislots.cfg | 1 - - base/server/etc/default.cfg | 1 + - base/server/python/pki/server/deployment/pkiparser.py | 3 --- - base/server/sbin/pkidestroy | 12 ++++++------ - base/server/sbin/pkispawn | 12 ++++++------ - 5 files changed, 13 insertions(+), 16 deletions(-) - -diff --git a/base/server/config/pkislots.cfg b/base/server/config/pkislots.cfg -index 23c1f824a4ec27d50161549c21a55d36d662fec7..926527599cee5f0de80746bb56e075e0a3e90def 100644 ---- a/base/server/config/pkislots.cfg -+++ b/base/server/config/pkislots.cfg -@@ -11,7 +11,6 @@ PKI_AJP_PORT_SLOT=[PKI_AJP_PORT] - PKI_AJP_REDIRECT_PORT_SLOT=[PKI_AJP_REDIRECT_PORT] - PKI_CA_HOSTNAME_SLOT=[PKI_CA_HOSTNAME] - PKI_CA_PORT_SLOT=[PKI_CA_PORT] --PKI_CERT_DB_PASSWORD_SLOT=[PKI_CERT_DB_PASSWORD] - PKI_CFG_PATH_NAME_SLOT=[PKI_CFG_PATH_NAME] - PKI_CLOSE_AJP_PORT_COMMENT_SLOT=[PKI_CLOSE_AJP_PORT_COMMENT] - PKI_CLOSE_ENABLE_PROXY_COMMENT_SLOT=[PKI_CLOSE_ENABLE_PROXY_COMMENT] -diff --git a/base/server/etc/default.cfg b/base/server/etc/default.cfg -index ae0021bb19c9aeda03a7eb5a42490d4919315a82..21c792472c7757ce5eda5e96ccfbd0552cec8b98 100644 ---- a/base/server/etc/default.cfg -+++ b/base/server/etc/default.cfg -@@ -109,6 +109,7 @@ pki_security_domain_https_port=8443 - pki_security_domain_name=%(pki_dns_domainname)s Security Domain - pki_security_domain_password= - pki_security_domain_user=caadmin -+pki_self_signed_token=internal - #for supporting server cert SAN injection - pki_san_inject=False - pki_san_for_server_cert= -diff --git a/base/server/python/pki/server/deployment/pkiparser.py b/base/server/python/pki/server/deployment/pkiparser.py -index ca9ef998f69952dc1495c9b17dd1cf45d71f16f4..273b5ac3071640dd836adf1b541cc56b494a24c6 100644 ---- a/base/server/python/pki/server/deployment/pkiparser.py -+++ b/base/server/python/pki/server/deployment/pkiparser.py -@@ -794,8 +794,6 @@ class PKIConfigParser: - self.mdict['pki_ca_hostname'] - self.mdict['PKI_CA_PORT_SLOT'] = \ - self.mdict['pki_ca_port'] -- self.mdict['PKI_CERT_DB_PASSWORD_SLOT'] = \ -- self.mdict['pki_pin'] - self.mdict['PKI_CFG_PATH_NAME_SLOT'] = \ - self.mdict['pki_target_cs_cfg'] - self.mdict['PKI_CLOSE_SEPARATE_PORTS_SERVER_COMMENT_SLOT'] = \ -@@ -1106,7 +1104,6 @@ class PKIConfigParser: - self.mdict['pki_secmod_database'] = \ - os.path.join(self.mdict['pki_database_path'], - "secmod.db") -- self.mdict['pki_self_signed_token'] = "internal" - self.mdict['pki_self_signed_nickname'] = \ - self.mdict['pki_ssl_server_nickname'] - self.mdict['pki_self_signed_subject'] = \ -diff --git a/base/server/sbin/pkidestroy b/base/server/sbin/pkidestroy -index 12d37f2f39b56958e95eea98d92128d8f206301c..d7285c7e50e1f3f4e50fd30077eb385fd831f415 100755 ---- a/base/server/sbin/pkidestroy -+++ b/base/server/sbin/pkidestroy -@@ -257,12 +257,12 @@ def main(argv): - pki_subsystem_scriptlets = parser.mdict['destroy_scriplets'].split() - deployer = util.PKIDeployer(parser.mdict) - rv = 0 -- for pki_scriptlet in pki_subsystem_scriptlets: -- scriptlet = __import__("pki.server.deployment.scriptlets." + -- pki_scriptlet, -- fromlist=[pki_scriptlet]) -- instance = scriptlet.PkiScriptlet() -- rv = instance.destroy(deployer) -+ for scriptlet_name in pki_subsystem_scriptlets: -+ scriptlet_module = __import__( -+ "pki.server.deployment.scriptlets." + scriptlet_name, -+ fromlist=[scriptlet_name]) -+ scriptlet = scriptlet_module.PkiScriptlet() -+ rv = scriptlet.destroy(deployer) - if rv != 0: - sys.exit(1) - config.pki_log.debug(log.PKI_DICTIONARY_MASTER, -diff --git a/base/server/sbin/pkispawn b/base/server/sbin/pkispawn -index e7b22ef1e66598c2a1a64b544ffdc171b88bbd4a..caa5e9bee474cbb8aa76701f83cc53dab308fc44 100755 ---- a/base/server/sbin/pkispawn -+++ b/base/server/sbin/pkispawn -@@ -515,13 +515,13 @@ def main(argv): - pki_subsystem_scriptlets = parser.mdict['spawn_scriplets'].split() - deployer = util.PKIDeployer(parser.mdict, parser.slots_dict) - rv = 0 -- for pki_scriptlet in pki_subsystem_scriptlets: -- scriptlet = __import__("pki.server.deployment.scriptlets." + -- pki_scriptlet, -- fromlist=[pki_scriptlet]) -- instance = scriptlet.PkiScriptlet() -+ for scriptlet_name in pki_subsystem_scriptlets: -+ scriptlet_module = __import__( -+ "pki.server.deployment.scriptlets." + scriptlet_name, -+ fromlist=[scriptlet_name]) -+ scriptlet = scriptlet_module.PkiScriptlet() - try: -- rv = instance.spawn(deployer) -+ rv = scriptlet.spawn(deployer) - # pylint: disable=W0703 - except Exception: - log_error_details() --- -2.7.3 - diff --git a/SOURCES/pki-core-Make-PKIInstance-and-PKISubsystem-hashable.patch b/SOURCES/pki-core-Make-PKIInstance-and-PKISubsystem-hashable.patch deleted file mode 100644 index 682a6ee..0000000 --- a/SOURCES/pki-core-Make-PKIInstance-and-PKISubsystem-hashable.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 361c708d5854786d8c80dd9864818137d733661c Mon Sep 17 00:00:00 2001 -From: Christian Heimes -Date: Fri, 4 Mar 2016 23:54:04 +0100 -Subject: [PATCH] Make PKIInstance and PKISubsystem hashable - -The upgrade uses instance and subsystem as keys for dicts. - -(cherry picked from commit 9e78f981e923c879033c26eebad0cb803d66b8d9) - -Conflicts: - tests/python/server/test_server.py ---- - base/server/python/pki/server/__init__.py | 6 ++++-- - 1 file changed, 4 insertions(+), 2 deletions(-) - -diff --git a/base/server/python/pki/server/__init__.py b/base/server/python/pki/server/__init__.py -index 971a3f6..0f61f2a 100644 ---- a/base/server/python/pki/server/__init__.py -+++ b/base/server/python/pki/server/__init__.py -@@ -109,7 +109,8 @@ class PKISubsystem(object): - self.instance < other.instance or - self_type < other_type) - -- __hash__ = None -+ def __hash__(self): -+ return hash((self.name, self.instance, self.type)) - - def load(self): - self.config.clear() -@@ -391,7 +392,8 @@ class PKIInstance(object): - return (self.name < other.name or - self.type < other.type) - -- __hash__ = None -+ def __hash__(self): -+ return hash((self.name, self.type)) - - def is_valid(self): - return os.path.exists(self.conf_dir) --- -1.8.3.1 - diff --git a/SOURCES/pki-core-Use-correct-textual-encoding-for-PKCS-7-objects.patch b/SOURCES/pki-core-Use-correct-textual-encoding-for-PKCS-7-objects.patch deleted file mode 100644 index c6d7255..0000000 --- a/SOURCES/pki-core-Use-correct-textual-encoding-for-PKCS-7-objects.patch +++ /dev/null @@ -1,165 +0,0 @@ -From 670244adbca3ca5aa5e199b720061b9110c28abf Mon Sep 17 00:00:00 2001 -From: Fraser Tweedale -Date: Wed, 13 Jan 2016 17:41:05 +1100 -Subject: [PATCH] Use correct textual encoding for PKCS #7 objects - -PKCS #7 objects are being output with the "CERTIFICATE CHAIN" label -which is invalid (RFC 7468) and unrecognised by many programs -(including OpenSSL). Use the correct "PKCS7" label instead. - -Also do a drive-by refactor of the normalizeCertAndReq to remove -some redundant code. - -Fixes: https://fedorahosted.org/pki/ticket/1699 ---- - .../webapps/ca/agent/ca/displayBySerial.template | 4 +-- - .../webapps/ca/agent/ca/displayBySerial2.template | 4 +-- - .../ca/agent/ca/displayCertFromRequest.template | 4 +-- - .../webapps/ca/ee/ca/displayBySerial.template | 4 +-- - .../shared/webapps/ca/ee/ca/displayCaCert.template | 6 ++-- - .../com/netscape/cmsutil/crypto/CryptoUtil.java | 35 ++-------------------- - 6 files changed, 13 insertions(+), 44 deletions(-) - -diff --git a/base/ca/shared/webapps/ca/agent/ca/displayBySerial.template b/base/ca/shared/webapps/ca/agent/ca/displayBySerial.template -index 2bb2bfab7c2e208555b69188f6f33dd536732e3f..f95434a1b61fcc2eba00537ef050d849160e65aa 100644 ---- a/base/ca/shared/webapps/ca/agent/ca/displayBySerial.template -+++ b/base/ca/shared/webapps/ca/agent/ca/displayBySerial.template -@@ -191,11 +191,11 @@ document.write(result.header.certChainBase64); - Base 64 encoded certificate with CA certificate chain in pkcs7 format - -

-------BEGIN CERTIFICATE CHAIN-----
- 
-------END CERTIFICATE CHAIN-----
- 
- -

-diff --git a/base/ca/shared/webapps/ca/agent/ca/displayBySerial2.template b/base/ca/shared/webapps/ca/agent/ca/displayBySerial2.template -index 4a193e3243e79074feabd21e0094f4b5cea635b9..f0604ef7fc3a7a9ec4c1dd016f0652c507e204dd 100644 ---- a/base/ca/shared/webapps/ca/agent/ca/displayBySerial2.template -+++ b/base/ca/shared/webapps/ca/agent/ca/displayBySerial2.template -@@ -97,11 +97,11 @@ The following format can be used to install this certificate into a server. - Base 64 encoded certificate - -

-------BEGIN CERTIFICATE CHAIN-----
- 
-------END CERTIFICATE CHAIN-----
- 
- -

-diff --git a/base/ca/shared/webapps/ca/agent/ca/displayCertFromRequest.template b/base/ca/shared/webapps/ca/agent/ca/displayCertFromRequest.template -index f1148570c5e1cd3c251ee64008228da2e710b421..402154037790343061dc4a711de0d0fba738dbf2 100644 ---- a/base/ca/shared/webapps/ca/agent/ca/displayCertFromRequest.template -+++ b/base/ca/shared/webapps/ca/agent/ca/displayCertFromRequest.template -@@ -102,9 +102,9 @@ function displayCert(cert) - 'Base 64 encoded certificate with CA certificate chain in pkcs7 format'+ - ''+ - '

'+
--		'-----BEGIN CERTIFICATE CHAIN-----');
-+		'-----BEGIN PKCS7-----');
- 		document.writeln(cert.pkcs7ChainBase64);
--		document.writeln('-----END CERTIFICATE CHAIN-----'+
-+		document.writeln('-----END PKCS7-----'+
- 		'
'); - - } -diff --git a/base/ca/shared/webapps/ca/ee/ca/displayBySerial.template b/base/ca/shared/webapps/ca/ee/ca/displayBySerial.template -index e9b4d72bfb2b23a67c15282ae521b513d7a5dbfd..d482644b768750b704461785fe39eb744db7cbe9 100644 ---- a/base/ca/shared/webapps/ca/ee/ca/displayBySerial.template -+++ b/base/ca/shared/webapps/ca/ee/ca/displayBySerial.template -@@ -116,11 +116,11 @@ document.write(result.header.certChainBase64); - Base 64 encoded certificate with CA certificate chain in pkcs7 format - -

-------BEGIN CERTIFICATE-----
- 
-------END CERTIFICATE-----
- 
- -

-diff --git a/base/ca/shared/webapps/ca/ee/ca/displayCaCert.template b/base/ca/shared/webapps/ca/ee/ca/displayCaCert.template -index 4e93919f53d553872ff9ee98356d81edda9a7640..4da0d74c8302329addf1ec1dd042f7ffe7ea18ae 100644 ---- a/base/ca/shared/webapps/ca/ee/ca/displayCaCert.template -+++ b/base/ca/shared/webapps/ca/ee/ca/displayCaCert.template -@@ -43,9 +43,9 @@ if (result.header.displayFormat == "chain") { - document.writeln('

' + result.header.subjectdn); - document.writeln('


'); - document.writeln('

');
--    document.writeln('-----BEGIN CERTIFICATE-----');
--    document.writeln(result.header.chainBase64);
--    document.writeln('-----END CERTIFICATE-----');
-+    document.writeln('-----BEGIN PKCS7-----');
-+    document.write(result.header.chainBase64);
-+    document.writeln('-----END PKCS7-----');
-     document.writeln('
'); - } else if (result.header.displayFormat == "individual") { - if (result.recordSet.length == 0) { -diff --git a/base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java b/base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java -index 3b1041a74bb4b663dd9c5f4c9fa983da133f04a3..59883831afa5c9016594c54bbb25bf5f503f00b7 100644 ---- a/base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java -+++ b/base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java -@@ -822,46 +822,15 @@ public class CryptoUtil { - if (s == null) { - return s; - } -- s = s.replaceAll("-----BEGIN CERTIFICATE REQUEST-----", ""); -- s = s.replaceAll("-----BEGIN NEW CERTIFICATE REQUEST-----", ""); -- s = s.replaceAll("-----END CERTIFICATE REQUEST-----", ""); -- s = s.replaceAll("-----END NEW CERTIFICATE REQUEST-----", ""); -- s = s.replaceAll("-----BEGIN CERTIFICATE-----", ""); -- s = s.replaceAll("-----END CERTIFICATE-----", ""); -- s = s.replaceAll("-----BEGIN CERTIFICATE CHAIN-----", ""); -- s = s.replaceAll("-----END CERTIFICATE CHAIN-----", ""); -+ // grammar defined at https://tools.ietf.org/html/rfc7468#section-3 -+ s = s.replaceAll("-----(BEGIN|END) [\\p{Print}&&[^- ]]([- ]?[\\p{Print}&&[^- ]])*-----", ""); - - StringBuffer sb = new StringBuffer(); - StringTokenizer st = new StringTokenizer(s, "\r\n "); - - while (st.hasMoreTokens()) { - String nextLine = st.nextToken(); -- - nextLine = nextLine.trim(); -- if (nextLine.equals("-----BEGIN CERTIFICATE REQUEST-----")) { -- continue; -- } -- if (nextLine.equals("-----BEGIN NEW CERTIFICATE REQUEST-----")) { -- continue; -- } -- if (nextLine.equals("-----END CERTIFICATE REQUEST-----")) { -- continue; -- } -- if (nextLine.equals("-----END NEW CERTIFICATE REQUEST-----")) { -- continue; -- } -- if (nextLine.equals("-----BEGIN CERTIFICATE-----")) { -- continue; -- } -- if (nextLine.equals("-----END CERTIFICATE-----")) { -- continue; -- } -- if (nextLine.equals("-----BEGIN CERTIFICATE CHAIN-----")) { -- continue; -- } -- if (nextLine.equals("-----END CERTIFICATE CHAIN-----")) { -- continue; -- } - sb.append(nextLine); - } - return sb.toString(); --- -2.4.3 - diff --git a/SOURCES/pki-core-added-CLI-to-update-cert-data-and-request-in-CS-cfg.patch b/SOURCES/pki-core-added-CLI-to-update-cert-data-and-request-in-CS-cfg.patch deleted file mode 100644 index b3e919e..0000000 --- a/SOURCES/pki-core-added-CLI-to-update-cert-data-and-request-in-CS-cfg.patch +++ /dev/null @@ -1,1103 +0,0 @@ -commit 7ed1e32c574a2ee93a62297d16e07a7071e696d7 -Author: Endi S. Dewata -Date: Wed Sep 2 04:50:24 2015 +0200 - - Added CLI to update cert data and request in CS.cfg. - - A set of new pki-server commands have been added to simplify - updating the cert data and cert request stored in the CS.cfg with - the cert data and cert request stored in the NSS and LDAP database, - respectively. - - https://fedorahosted.org/pki/ticket/1551 - -diff --git a/base/server/python/pki/server/__init__.py b/base/server/python/pki/server/__init__.py -index 9777d22..d004465 100644 ---- a/base/server/python/pki/server/__init__.py -+++ b/base/server/python/pki/server/__init__.py -@@ -20,7 +20,11 @@ - # - - from lxml import etree -+import getpass - import grp -+import io -+import ldap -+import operator - import os - import pwd - import re -@@ -31,7 +35,7 @@ import pki - INSTANCE_BASE_DIR = '/var/lib/pki' - REGISTRY_DIR = '/etc/sysconfig/pki' - SUBSYSTEM_TYPES = ['ca', 'kra', 'ocsp', 'tks', 'tps'] -- -+SUBSYSTEM_CLASSES = {} - - class PKIServer(object): - -@@ -65,6 +69,7 @@ class PKISubsystem(object): - self.base_dir = instance.base_dir - - self.conf_dir = os.path.join(self.base_dir, 'conf') -+ self.cs_conf = os.path.join(self.conf_dir, 'CS.cfg') - - self.context_xml_template = os.path.join( - pki.SHARE_DIR, self.name, 'conf', 'Catalina', 'localhost', self.name + '.xml') -@@ -72,9 +77,62 @@ class PKISubsystem(object): - self.context_xml = os.path.join( - instance.conf_dir, 'Catalina', 'localhost', self.name + '.xml') - -+ self.config = {} -+ self.type = None -+ self.prefix = None -+ - # custom subsystem location - self.doc_base = os.path.join(self.base_dir, 'webapps', self.name) - -+ def load(self): -+ self.config.clear() -+ -+ lines = open(self.cs_conf).read().splitlines() -+ -+ for line in lines: -+ parts = line.split('=', 1) -+ name = parts[0] -+ value = parts[1] -+ self.config[name] = value -+ -+ self.type = self.config['cs.type'] -+ self.prefix = self.type.lower() -+ -+ def find_subsystem_certs(self): -+ certs = [] -+ -+ cert_ids = self.config['%s.cert.list' % self.name].split(',') -+ for cert_id in cert_ids: -+ cert = self.create_subsystem_cert_object(cert_id) -+ certs.append(cert) -+ -+ return certs -+ -+ def get_subsystem_cert(self, cert_id): -+ return self.create_subsystem_cert_object(cert_id) -+ -+ def create_subsystem_cert_object(self, cert_id): -+ cert = {} -+ cert['id'] = cert_id -+ cert['nickname'] = self.config.get('%s.%s.nickname' % (self.name, cert_id), None) -+ cert['token'] = self.config.get('%s.%s.tokenname' % (self.name, cert_id), None) -+ cert['data'] = self.config.get('%s.%s.cert' % (self.name, cert_id), None) -+ cert['request'] = self.config.get('%s.%s.certreq' % (self.name, cert_id), None) -+ return cert -+ -+ def update_subsystem_cert(self, cert): -+ cert_id = cert['id'] -+ self.config['%s.%s.nickname' % (self.name, cert_id)] = cert.get('nickname', None) -+ self.config['%s.%s.tokenname' % (self.name, cert_id)] = cert.get('token', None) -+ self.config['%s.%s.cert' % (self.name, cert_id)] = cert.get('data', None) -+ self.config['%s.%s.certreq' % (self.name, cert_id)] = cert.get('request', None) -+ -+ def save(self): -+ sorted_config = sorted(self.config.items(), key=operator.itemgetter(0)) -+ with io.open(self.cs_conf, 'wb') as f: -+ for (key, value) in sorted_config: -+ f.write('%s=%s\n' % (key, value)) -+ - def is_valid(self): - return os.path.exists(self.conf_dir) - -@@ -102,6 +160,21 @@ class PKISubsystem(object): - def disable(self): - self.instance.undeploy(self.name) - -+ def open_database(self, name='internaldb'): -+ -+ hostname = self.config['%s.ldapconn.host' % name] -+ port = self.config['%s.ldapconn.port' % name] -+ bind_dn = self.config['%s.ldapauth.bindDN' % name] -+ -+ # TODO: add support for other authentication -+ # mechanisms (e.g. client cert authentication, LDAPI) -+ bind_password = self.instance.get_password(name) -+ -+ con = ldap.initialize('ldap://%s:%s' % (hostname, port)) -+ con.simple_bind_s(bind_dn, bind_password) -+ -+ return con -+ - def __repr__(self): - return str(self.instance) + '/' + self.name - -@@ -119,6 +192,9 @@ class PKIInstance(object): - self.base_dir = os.path.join(pki.BASE_DIR, name) - - self.conf_dir = os.path.join(self.base_dir, 'conf') -+ self.password_conf = os.path.join(self.conf_dir, 'password.conf') -+ -+ self.nssdb_dir = os.path.join(self.base_dir, 'alias') - self.lib_dir = os.path.join(self.base_dir, 'lib') - - self.registry_dir = os.path.join(pki.server.REGISTRY_DIR, 'tomcat', self.name) -@@ -132,6 +208,8 @@ class PKIInstance(object): - self.uid = None - self.gid = None - -+ self.passwords = {} -+ - self.subsystems = [] - - def is_valid(self): -@@ -153,6 +231,7 @@ class PKIInstance(object): - return rc == 0 - - def load(self): -+ # load UID and GID - with open(self.registry_file, 'r') as registry: - lines = registry.readlines() - -@@ -168,11 +247,41 @@ class PKIInstance(object): - self.group = m.group(1) - self.gid = grp.getgrnam(self.group).gr_gid - -+ # load passwords -+ self.passwords.clear() -+ lines = open(self.password_conf).read().splitlines() -+ -+ for line in lines: -+ parts = line.split('=', 1) -+ name = parts[0] -+ value = parts[1] -+ self.passwords[name] = value -+ -+ # load subsystems - for subsystem_name in os.listdir(self.registry_dir): -- if subsystem_name in pki.server.SUBSYSTEM_TYPES: -- subsystem = PKISubsystem(self, subsystem_name) -+ if subsystem_name in SUBSYSTEM_TYPES: -+ if subsystem_name in SUBSYSTEM_CLASSES: -+ subsystem = SUBSYSTEM_CLASSES[subsystem_name](self) -+ else: -+ subsystem = PKISubsystem(self, subsystem_name) -+ subsystem.load() - self.subsystems.append(subsystem) - -+ def get_password(self, name): -+ if name in self.passwords: -+ return self.passwords[name] -+ -+ password = getpass.getpass(prompt='Enter password for %s: ' % name) -+ self.passwords[name] = password -+ -+ return password -+ -+ def get_subsystem(self, name): -+ for subsystem in self.subsystems: -+ if name == subsystem.name: -+ return subsystem -+ return None -+ - def is_deployed(self, webapp_name): - context_xml = os.path.join( - self.conf_dir, 'Catalina', 'localhost', webapp_name + '.xml') -diff --git a/base/server/python/pki/server/ca.py b/base/server/python/pki/server/ca.py -new file mode 100644 -index 0000000..70ebf4d ---- /dev/null -+++ b/base/server/python/pki/server/ca.py -@@ -0,0 +1,92 @@ -+#!/usr/bin/python -+# 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.search_s( -+ 'ou=ca,ou=requests,%s' % base_dn, -+ ldap.SCOPE_ONELEVEL, -+ search_filter, -+ None) -+ -+ con.unbind_s() -+ -+ 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.search_s( -+ 'cn=%s,ou=ca,ou=requests,%s' % (request_id, base_dn), -+ ldap.SCOPE_BASE, -+ '(objectClass=*)', -+ None) -+ -+ con.unbind_s() -+ -+ 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/ca.py b/base/server/python/pki/server/cli/ca.py -new file mode 100644 -index 0000000..2ad8652 ---- /dev/null -+++ b/base/server/python/pki/server/cli/ca.py -@@ -0,0 +1,206 @@ -+#!/usr/bin/python -+# 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 -+from __future__ import print_function -+import getopt -+import io -+import sys -+ -+import pki.cli -+import pki.server.ca -+ -+ -+class CACLI(pki.cli.CLI): -+ -+ def __init__(self): -+ super(CACLI, self).__init__( -+ 'ca', 'CA management commands') -+ -+ self.add_module(CACertCLI()) -+ -+ -+class CACertCLI(pki.cli.CLI): -+ -+ def __init__(self): -+ super(CACertCLI, self).__init__( -+ 'cert', 'CA certificates management commands') -+ -+ self.add_module(CACertRequestCLI()) -+ -+ -+class CACertRequestCLI(pki.cli.CLI): -+ -+ def __init__(self): -+ super(CACertRequestCLI, self).__init__( -+ 'request', 'CA certificate requests management commands') -+ -+ self.add_module(CACertRequestFindCLI()) -+ self.add_module(CACertRequestShowCLI()) -+ -+ @staticmethod -+ def print_request(request, details=False): -+ print(' Request ID: %s' % request['id']) -+ print(' Type: %s' % request['type']) -+ print(' Status: %s' % request['status']) -+ -+ if details: -+ print(' Request: %s' % request['request']) -+ -+ -+class CACertRequestFindCLI(pki.cli.CLI): -+ -+ def __init__(self): -+ super(CACertRequestFindCLI, self).__init__( -+ 'find', 'Find CA certificate requests') -+ -+ def usage(self): -+ print('Usage: pki-server ca-cert-request-find [OPTIONS]') -+ print() -+ print(' -i, --instance Instance ID (default: pki-tomcat).') -+ print(' --cert Issued certificate.') -+ print(' --cert-file File containing issued certificate.') -+ print(' -v, --verbose Run in verbose mode.') -+ print(' --help Show help message.') -+ print() -+ -+ def execute(self, args): -+ -+ try: -+ opts, _ = getopt.gnu_getopt(args, 'i:v', [ -+ 'instance=', 'cert=', 'cert-file=', -+ 'verbose', 'help']) -+ -+ except getopt.GetoptError as e: -+ print('ERROR: ' + str(e)) -+ self.usage() -+ sys.exit(1) -+ -+ instance_name = 'pki-tomcat' -+ cert = None -+ -+ for o, a in opts: -+ if o in ('-i', '--instance'): -+ instance_name = a -+ -+ elif o == '--cert': -+ cert = a -+ -+ elif o == '--cert-file': -+ with io.open(a, 'rb') as f: -+ cert = f.read() -+ -+ elif o in ('-v', '--verbose'): -+ self.set_verbose(True) -+ -+ elif o == '--help': -+ self.print_help() -+ sys.exit() -+ -+ else: -+ print('ERROR: unknown option ' + o) -+ self.usage() -+ sys.exit(1) -+ -+ instance = pki.server.PKIInstance(instance_name) -+ instance.load() -+ -+ subsystem = instance.get_subsystem('ca') -+ results = subsystem.find_cert_requests(cert=cert) -+ -+ self.print_message('%s entries matched' % len(results)) -+ -+ first = True -+ for request in results: -+ if first: -+ first = False -+ else: -+ print() -+ -+ CACertRequestCLI.print_request(request) -+ -+ -+class CACertRequestShowCLI(pki.cli.CLI): -+ -+ def __init__(self): -+ super(CACertRequestShowCLI, self).__init__( -+ 'show', 'Show CA certificate request') -+ -+ def usage(self): -+ print('Usage: pki-server ca-cert-request-show [OPTIONS]') -+ print() -+ print(' -i, --instance Instance ID (default: pki-tomcat).') -+ print(' -v, --verbose Run in verbose mode.') -+ print(' --help Show help message.') -+ print() -+ -+ def execute(self, args): -+ -+ try: -+ opts, args = getopt.gnu_getopt(args, 'i:v', [ -+ 'instance=', 'output-file=', -+ 'verbose', 'help']) -+ -+ except getopt.GetoptError as e: -+ print('ERROR: ' + str(e)) -+ self.usage() -+ sys.exit(1) -+ -+ if len(args) != 1: -+ print('ERROR: missing request ID') -+ self.usage() -+ sys.exit(1) -+ -+ request_id = args[0] -+ instance_name = 'pki-tomcat' -+ output_file = None -+ -+ for o, a in opts: -+ if o in ('-i', '--instance'): -+ instance_name = a -+ -+ elif o == '--output-file': -+ output_file = a -+ -+ elif o in ('-v', '--verbose'): -+ self.set_verbose(True) -+ -+ elif o == '--help': -+ self.print_help() -+ sys.exit() -+ -+ else: -+ print('ERROR: unknown option ' + o) -+ self.usage() -+ sys.exit(1) -+ -+ instance = pki.server.PKIInstance(instance_name) -+ instance.load() -+ -+ subsystem = instance.get_subsystem('ca') -+ request = subsystem.get_cert_requests(request_id) -+ -+ if output_file: -+ with io.open(output_file, 'wb') as f: -+ f.write(request['request']) -+ -+ else: -+ CACertRequestCLI.print_request(request, details=True) -diff --git a/base/server/python/pki/server/cli/subsystem.py b/base/server/python/pki/server/cli/subsystem.py -index 43eb564..fc89c27 100644 ---- a/base/server/python/pki/server/cli/subsystem.py -+++ b/base/server/python/pki/server/cli/subsystem.py -@@ -19,8 +19,12 @@ - # All rights reserved. - # - -+from __future__ import absolute_import -+from __future__ import print_function -+import base64 - import getopt --import os -+import nss.nss as nss -+import string - import sys - - import pki.cli -@@ -38,11 +42,13 @@ class SubsystemCLI(pki.cli.CLI): - self.add_module(SubsystemFindCLI()) - self.add_module(SubsystemShowCLI()) - -+ self.add_module(SubsystemCertCLI()) -+ - @staticmethod - def print_subsystem(subsystem): -- print ' Subsystem ID: %s' % subsystem.name -- print ' Instance ID: %s' % subsystem.instance.name -- print ' Enabled: %s' % subsystem.is_enabled() -+ print(' Subsystem ID: %s' % subsystem.name) -+ print(' Instance ID: %s' % subsystem.instance.name) -+ print(' Enabled: %s' % subsystem.is_enabled()) - - - class SubsystemFindCLI(pki.cli.CLI): -@@ -51,12 +57,12 @@ class SubsystemFindCLI(pki.cli.CLI): - super(SubsystemFindCLI, self).__init__('find', 'Find subsystems') - - def usage(self): -- print 'Usage: pki-server subsystem-find [OPTIONS]' -- print -- print ' -i, --instance Instance ID.' -- print ' -v, --verbose Run in verbose mode.' -- print ' --help Show help message.' -- print -+ print('Usage: pki-server subsystem-find [OPTIONS]') -+ print() -+ print(' -i, --instance Instance ID (default: pki-tomcat).') -+ print(' -v, --verbose Run in verbose mode.') -+ print(' --help Show help message.') -+ print() - - def execute(self, args): - -@@ -66,11 +72,11 @@ class SubsystemFindCLI(pki.cli.CLI): - 'verbose', 'help']) - - except getopt.GetoptError as e: -- print 'ERROR: ' + str(e) -+ print('ERROR: ' + str(e)) - self.usage() - sys.exit(1) - -- instance_name = None -+ instance_name = 'pki-tomcat' - - for o, a in opts: - if o in ('-i', '--instance'): -@@ -84,32 +90,17 @@ class SubsystemFindCLI(pki.cli.CLI): - sys.exit() - - else: -- print 'ERROR: unknown option ' + o -+ print('ERROR: unknown option ' + o) - self.usage() - sys.exit(1) - -- if not instance_name: -- print 'ERROR: missing instance ID' -- self.usage() -- sys.exit(1) -- - instance = pki.server.PKIInstance(instance_name) - instance.load() - -- results = [] -- -- for name in os.listdir(instance.base_dir): -- -- subsystem = pki.server.PKISubsystem(instance, name) -- if not subsystem.is_valid(): -- continue -- -- results.append(subsystem) -- -- self.print_message('%s entries matched' % len(results)) -+ self.print_message('%s entries matched' % len(instance.subsystems)) - - first = True -- for subsystem in results: -+ for subsystem in instance.subsystems: - if first: - first = False - else: -@@ -124,12 +115,12 @@ class SubsystemShowCLI(pki.cli.CLI): - super(SubsystemShowCLI, self).__init__('show', 'Show subsystem') - - def usage(self): -- print 'Usage: pki-server subsystem-show [OPTIONS] ' -- print -- print ' -i, --instance Instance ID.' -- print ' -v, --verbose Run in verbose mode.' -- print ' --help Show help message.' -- print -+ print('Usage: pki-server subsystem-show [OPTIONS] ') -+ print() -+ print(' -i, --instance Instance ID (default: pki-tomcat).') -+ print(' -v, --verbose Run in verbose mode.') -+ print(' --help Show help message.') -+ print() - - def execute(self, argv): - -@@ -139,17 +130,17 @@ class SubsystemShowCLI(pki.cli.CLI): - 'verbose', 'help']) - - except getopt.GetoptError as e: -- print 'ERROR: ' + str(e) -+ print('ERROR: ' + str(e)) - self.usage() - sys.exit(1) - - if len(args) != 1: -- print 'ERROR: missing subsystem ID' -+ print('ERROR: missing subsystem ID') - self.usage() - sys.exit(1) - - subsystem_name = args[0] -- instance_name = None -+ instance_name = 'pki-tomcat' - - for o, a in opts: - if o in ('-i', '--instance'): -@@ -163,19 +154,14 @@ class SubsystemShowCLI(pki.cli.CLI): - sys.exit() - - else: -- print 'ERROR: unknown option ' + o -+ print('ERROR: unknown option ' + o) - self.usage() - sys.exit(1) - -- if not instance_name: -- print 'ERROR: missing instance ID' -- self.usage() -- sys.exit(1) -- - instance = pki.server.PKIInstance(instance_name) - instance.load() - -- subsystem = pki.server.PKISubsystem(instance, subsystem_name) -+ subsystem = instance.get_subsystem(subsystem_name) - - SubsystemCLI.print_subsystem(subsystem) - -@@ -186,12 +172,12 @@ class SubsystemEnableCLI(pki.cli.CLI): - super(SubsystemEnableCLI, self).__init__('enable', 'Enable subsystem') - - def usage(self): -- print 'Usage: pki-server subsystem-enable [OPTIONS] ' -- print -- print ' -i, --instance Instance ID.' -- print ' -v, --verbose Run in verbose mode.' -- print ' --help Show help message.' -- print -+ print('Usage: pki-server subsystem-enable [OPTIONS] ') -+ print() -+ print(' -i, --instance Instance ID (default: pki-tomcat).') -+ print(' -v, --verbose Run in verbose mode.') -+ print(' --help Show help message.') -+ print() - - def execute(self, argv): - -@@ -201,17 +187,17 @@ class SubsystemEnableCLI(pki.cli.CLI): - 'verbose', 'help']) - - except getopt.GetoptError as e: -- print 'ERROR: ' + str(e) -+ print('ERROR: ' + str(e)) - self.usage() - sys.exit(1) - - if len(args) != 1: -- print 'ERROR: missing subsystem ID' -+ print('ERROR: missing subsystem ID') - self.usage() - sys.exit(1) - - subsystem_name = args[0] -- instance_name = None -+ instance_name = 'pki-tomcat' - - for o, a in opts: - if o in ('-i', '--instance'): -@@ -225,19 +211,14 @@ class SubsystemEnableCLI(pki.cli.CLI): - sys.exit() - - else: -- print 'ERROR: unknown option ' + o -+ print('ERROR: unknown option ' + o) - self.usage() - sys.exit(1) - -- if not instance_name: -- print 'ERROR: missing instance ID' -- self.usage() -- sys.exit(1) -- - instance = pki.server.PKIInstance(instance_name) - instance.load() - -- subsystem = pki.server.PKISubsystem(instance, subsystem_name) -+ subsystem = instance.get_subsystem(subsystem_name) - subsystem.enable() - - self.print_message('Enabled "%s" subsystem' % subsystem_name) -@@ -251,12 +232,12 @@ class SubsystemDisableCLI(pki.cli.CLI): - super(SubsystemDisableCLI, self).__init__('disable', 'Disable subsystem') - - def usage(self): -- print 'Usage: pki-server subsystem-disable [OPTIONS] ' -- print -- print ' -i, --instance Instance ID.' -- print ' -v, --verbose Run in verbose mode.' -- print ' --help Show help message.' -- print -+ print('Usage: pki-server subsystem-disable [OPTIONS] ') -+ print() -+ print(' -i, --instance Instance ID (default: pki-tomcat).') -+ print(' -v, --verbose Run in verbose mode.') -+ print(' --help Show help message.') -+ print() - - def execute(self, argv): - -@@ -266,17 +247,17 @@ class SubsystemDisableCLI(pki.cli.CLI): - 'verbose', 'help']) - - except getopt.GetoptError as e: -- print 'ERROR: ' + str(e) -+ print('ERROR: ' + str(e)) - self.usage() - sys.exit(1) - - if len(args) != 1: -- print 'ERROR: missing subsystem ID' -+ print('ERROR: missing subsystem ID') - self.usage() - sys.exit(1) - - subsystem_name = args[0] -- instance_name = None -+ instance_name = 'pki-tomcat' - - for o, a in opts: - if o in ('-i', '--instance'): -@@ -290,21 +271,267 @@ class SubsystemDisableCLI(pki.cli.CLI): - sys.exit() - - else: -- print 'ERROR: unknown option ' + o -+ print('ERROR: unknown option ' + o) - self.usage() - sys.exit(1) - -- if not instance_name: -- print 'ERROR: missing instance ID' -- self.usage() -- sys.exit(1) -- - instance = pki.server.PKIInstance(instance_name) - instance.load() - -- subsystem = pki.server.PKISubsystem(instance, subsystem_name) -+ subsystem = instance.get_subsystem(subsystem_name) - subsystem.disable() - - self.print_message('Disabled "%s" subsystem' % subsystem_name) - - SubsystemCLI.print_subsystem(subsystem) -+ -+ -+class SubsystemCertCLI(pki.cli.CLI): -+ -+ def __init__(self): -+ super(SubsystemCertCLI, self).__init__( -+ 'cert', 'Subsystem certificate management commands') -+ -+ self.add_module(SubsystemCertFindCLI()) -+ self.add_module(SubsystemCertShowCLI()) -+ self.add_module(SubsystemCertUpdateCLI()) -+ -+ @staticmethod -+ def print_subsystem_cert(cert): -+ print(' Cert ID: %s' % cert['id']) -+ print(' Nickname: %s' % cert['nickname']) -+ print(' Token: %s' % cert['token']) -+ print(' Certificate: %s' % cert['data']) -+ print(' Request: %s' % cert['request']) -+ -+ -+class SubsystemCertFindCLI(pki.cli.CLI): -+ -+ def __init__(self): -+ super(SubsystemCertFindCLI, self).__init__( -+ 'find', 'Find subsystem certificates') -+ -+ def usage(self): -+ print('Usage: pki-server subsystem-cert-find [OPTIONS] ') -+ print() -+ print(' -i, --instance Instance ID (default: pki-tomcat).') -+ print(' -v, --verbose Run in verbose mode.') -+ print(' --help Show help message.') -+ print() -+ -+ def execute(self, argv): -+ -+ try: -+ opts, args = getopt.getopt(argv, 'i:v', [ -+ 'instance=', -+ 'verbose', 'help']) -+ -+ except getopt.GetoptError as e: -+ print('ERROR: ' + str(e)) -+ 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: -+ if o in ('-i', '--instance'): -+ instance_name = a -+ -+ elif o in ('-v', '--verbose'): -+ self.set_verbose(True) -+ -+ elif o == '--help': -+ self.print_help() -+ sys.exit() -+ -+ else: -+ print('ERROR: unknown option ' + o) -+ self.usage() -+ sys.exit(1) -+ -+ instance = pki.server.PKIInstance(instance_name) -+ instance.load() -+ -+ subsystem = instance.get_subsystem(subsystem_name) -+ results = subsystem.find_subsystem_certs() -+ -+ self.print_message('%s entries matched' % len(results)) -+ -+ first = True -+ for cert in results: -+ if first: -+ first = False -+ else: -+ print() -+ -+ SubsystemCertCLI.print_subsystem_cert(cert) -+ -+ -+class SubsystemCertShowCLI(pki.cli.CLI): -+ -+ def __init__(self): -+ super(SubsystemCertShowCLI, self).__init__( -+ 'show', 'Show subsystem certificate') -+ -+ def usage(self): -+ print('Usage: pki-server subsystem-cert-show [OPTIONS] ') -+ print() -+ print(' -i, --instance Instance ID (default: pki-tomcat).') -+ print(' -v, --verbose Run in verbose mode.') -+ print(' --help Show help message.') -+ print() -+ -+ def execute(self, argv): -+ -+ try: -+ opts, args = getopt.getopt(argv, 'i:v', [ -+ 'instance=', -+ 'verbose', 'help']) -+ -+ except getopt.GetoptError as e: -+ print('ERROR: ' + str(e)) -+ 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: -+ if o in ('-i', '--instance'): -+ instance_name = a -+ -+ elif o in ('-v', '--verbose'): -+ self.set_verbose(True) -+ -+ elif o == '--help': -+ self.print_help() -+ sys.exit() -+ -+ else: -+ print('ERROR: unknown option ' + o) -+ self.usage() -+ sys.exit(1) -+ -+ instance = pki.server.PKIInstance(instance_name) -+ instance.load() -+ -+ subsystem = instance.get_subsystem(subsystem_name) -+ subsystem_cert = subsystem.get_subsystem_cert(cert_id) -+ -+ SubsystemCertCLI.print_subsystem_cert(subsystem_cert) -+ -+ -+class SubsystemCertUpdateCLI(pki.cli.CLI): -+ -+ def __init__(self): -+ super(SubsystemCertUpdateCLI, self).__init__( -+ 'update', 'Update subsystem certificate') -+ -+ def usage(self): -+ print('Usage: pki-server subsystem-cert-update [OPTIONS] ') -+ print() -+ print(' -i, --instance Instance ID (default: pki-tomcat).') -+ print(' -v, --verbose Run in verbose mode.') -+ print(' --help Show help message.') -+ print() -+ -+ def execute(self, argv): -+ -+ try: -+ opts, args = getopt.getopt(argv, 'i:v', [ -+ 'instance=', -+ 'verbose', 'help']) -+ -+ except getopt.GetoptError as e: -+ print('ERROR: ' + str(e)) -+ 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: -+ if o in ('-i', '--instance'): -+ instance_name = a -+ -+ elif o in ('-v', '--verbose'): -+ self.set_verbose(True) -+ -+ elif o == '--help': -+ self.print_help() -+ sys.exit() -+ -+ else: -+ print('ERROR: unknown option ' + o) -+ self.usage() -+ sys.exit(1) -+ -+ instance = pki.server.PKIInstance(instance_name) -+ instance.load() -+ -+ subsystem = instance.get_subsystem(subsystem_name) -+ subsystem_cert = subsystem.get_subsystem_cert(cert_id) -+ -+ # get cert data from NSS database -+ nss.nss_init(instance.nssdb_dir) -+ nss_cert = nss.find_cert_from_nickname(subsystem_cert['nickname']) -+ data = base64.b64encode(nss_cert.der_data) -+ del nss_cert -+ nss.nss_shutdown() -+ subsystem_cert['data'] = data -+ -+ # format cert data for LDAP database -+ lines = [data[i:i+64] for i in range(0, len(data), 64)] -+ data = string.join(lines, '\r\n') + '\r\n' -+ -+ # get cert request from local CA -+ # TODO: add support for remote CA -+ ca = instance.get_subsystem('ca') -+ results = ca.find_cert_requests(cert=data) -+ cert_request = results[-1] -+ request = cert_request['request'] -+ -+ # format cert request for CS.cfg -+ lines = request.splitlines() -+ if lines[0] == '-----BEGIN CERTIFICATE REQUEST-----': -+ lines = lines[1:] -+ if lines[-1] == '-----END CERTIFICATE REQUEST-----': -+ lines = lines[:-1] -+ request = string.join(lines, '') -+ subsystem_cert['request'] = request -+ -+ # store cert data and request in CS.cfg -+ subsystem.update_subsystem_cert(subsystem_cert) -+ subsystem.save() -+ -+ self.print_message('Updated "%s" subsystem certificate' % cert_id) -+ -+ SubsystemCertCLI.print_subsystem_cert(subsystem_cert) -diff --git a/base/server/python/pki/server/upgrade.py b/base/server/python/pki/server/upgrade.py -index c9426a0..f82ffe6 100644 ---- a/base/server/python/pki/server/upgrade.py -+++ b/base/server/python/pki/server/upgrade.py -@@ -220,6 +220,7 @@ class PKIServerUpgrader(pki.upgrade.PKIUpgrader): - if self.subsystemName: - subsystem = pki.server.PKISubsystem(instance, self.subsystemName) - subsystem.validate() -+ subsystem.load() - return [subsystem] - - subsystem_list = [] -@@ -232,6 +233,7 @@ class PKIServerUpgrader(pki.upgrade.PKIUpgrader): - if subsystemName in pki.server.SUBSYSTEM_TYPES: - subsystem = pki.server.PKISubsystem(instance, subsystemName) - subsystem.validate() -+ subsystem.load() - subsystem_list.append(subsystem) - else: - for subsystemName in pki.server.SUBSYSTEM_TYPES: -@@ -242,6 +244,7 @@ class PKIServerUpgrader(pki.upgrade.PKIUpgrader): - if os.path.exists(registry_dir): - subsystem = pki.server.PKISubsystem(instance, subsystemName) - subsystem.validate() -+ subsystem.load() - subsystem_list.append(subsystem) - - subsystem_list.sort() -diff --git a/base/server/sbin/pki-server b/base/server/sbin/pki-server -index 627a476..cdfd98e 100644 ---- a/base/server/sbin/pki-server -+++ b/base/server/sbin/pki-server -@@ -23,6 +23,7 @@ import getopt - import sys - - import pki.cli -+import pki.server.cli.ca - import pki.server.cli.instance - import pki.server.cli.subsystem - import pki.server.cli.migrate -@@ -35,6 +36,7 @@ class PKIServerCLI(pki.cli.CLI): - - super(PKIServerCLI, self).__init__('pki-server', 'PKI server command-line interface') - -+ self.add_module(pki.server.cli.ca.CACLI()) - self.add_module(pki.server.cli.instance.InstanceCLI()) - self.add_module(pki.server.cli.subsystem.SubsystemCLI()) - self.add_module(pki.server.cli.migrate.MigrateCLI()) diff --git a/SOURCES/pki-core-added-support-for-secure-database-connection-in-CLI.patch b/SOURCES/pki-core-added-support-for-secure-database-connection-in-CLI.patch deleted file mode 100644 index 21bb837..0000000 --- a/SOURCES/pki-core-added-support-for-secure-database-connection-in-CLI.patch +++ /dev/null @@ -1,449 +0,0 @@ -commit f153bd8a455953698e8af5085cd3cd7b368b1247 -Author: Endi S. Dewata -Date: Fri Sep 4 06:30:27 2015 +0200 - - Added support for secure database connection in CLI. - - The pki-server subsystem-cert-update has been modified to support - secure database connection with client certificate authentication. - The certificate and the private key will be exported temporarily - into PEM files so python-ldap can use them. - - The pki client-cert-show has been modified to provide an option - to export client certificate's private key. - - https://fedorahosted.org/pki/ticket/1551 - -diff --git a/base/java-tools/src/com/netscape/cmstools/client/ClientCertShowCLI.java b/base/java-tools/src/com/netscape/cmstools/client/ClientCertShowCLI.java -index f79501c..e44fae7 100644 ---- a/base/java-tools/src/com/netscape/cmstools/client/ClientCertShowCLI.java -+++ b/base/java-tools/src/com/netscape/cmstools/client/ClientCertShowCLI.java -@@ -29,10 +29,8 @@ import org.apache.commons.lang.RandomStringUtils; - import org.apache.commons.lang.StringUtils; - import org.mozilla.jss.crypto.X509Certificate; - --import com.netscape.certsrv.cert.CertData; - import com.netscape.cmstools.cli.CLI; - import com.netscape.cmstools.cli.MainCLI; --import com.netscape.cmsutil.util.Utils; - - /** - * @author Endi S. Dewata -@@ -57,6 +55,10 @@ public class ClientCertShowCLI extends CLI { - option.setArgName("path"); - options.addOption(option); - -+ option = new Option(null, "private-key", true, "PEM file to store the private key."); -+ option.setArgName("path"); -+ options.addOption(option); -+ - option = new Option(null, "client-cert", true, "PEM file to store the certificate and the private key."); - option.setArgName("path"); - options.addOption(option); -@@ -107,90 +109,82 @@ public class ClientCertShowCLI extends CLI { - - String nickname = cmdArgs[0]; - String certPath = cmd.getOptionValue("cert"); -+ String privateKeyPath = cmd.getOptionValue("private-key"); -+ String clientCertPath = cmd.getOptionValue("client-cert"); - String pkcs12Path = cmd.getOptionValue("pkcs12"); - String pkcs12Password = cmd.getOptionValue("pkcs12-password"); -- String clientCertPath = cmd.getOptionValue("client-cert"); -- -- if (certPath != null) { -- -- if (verbose) System.out.println("Exporting certificate to " + clientCertPath + "."); -- -- // late initialization -- mainCLI.init(); - -- client = mainCLI.getClient(); -- X509Certificate cert = client.getCert(nickname); -+ File pkcs12File; - -- try (PrintWriter out = new PrintWriter(new FileWriter(certPath))) { -- out.println(CertData.HEADER); -- out.println(Utils.base64encode(cert.getEncoded())); -- out.println(CertData.FOOTER); -- } -+ if (pkcs12Path != null) { -+ // exporting certificate to PKCS #12 file - -- } else if (pkcs12Path != null) { -- -- if (verbose) System.out.println("Exporting certificate chain and private key to " + pkcs12Path + "."); -+ pkcs12File = new File(pkcs12Path); - - if (pkcs12Password == null) { - throw new Exception("Missing PKCS #12 password"); - } - -- // store password into a temporary file -- File pkcs12PasswordFile = File.createTempFile("pki-client-cert-show-", ".pwd"); -- pkcs12PasswordFile.deleteOnExit(); -+ } else if (certPath != null || clientCertPath != null || privateKeyPath != null) { -+ // exporting certificate and/or private key to PEM files using temporary PKCS #12 file - -- try (PrintWriter out = new PrintWriter(new FileWriter(pkcs12PasswordFile))) { -- out.print(pkcs12Password); -- } -+ // prepare temporary PKCS #12 file -+ pkcs12File = File.createTempFile("pki-client-cert-show-", ".p12"); -+ pkcs12File.deleteOnExit(); - -- // export certificate chain and private key into PKCS #12 file -- exportPKCS12( -- mainCLI.certDatabase.getAbsolutePath(), -- mainCLI.config.getCertPassword(), -- pkcs12Path, -- pkcs12PasswordFile.getAbsolutePath(), -- nickname); -+ // generate random password -+ pkcs12Password = RandomStringUtils.randomAlphanumeric(16); - -- } else if (clientCertPath != null) { -+ } else { -+ // displaying certificate info - -- if (verbose) System.out.println("Exporting client certificate and private key to " + clientCertPath + "."); -+ mainCLI.init(); - -- // generate random PKCS #12 password -- pkcs12Password = RandomStringUtils.randomAlphanumeric(16); -+ client = mainCLI.getClient(); -+ X509Certificate cert = client.getCert(nickname); -+ -+ ClientCLI.printCertInfo(cert); -+ return; -+ } - -- // store password into a temporary file -- File pkcs12PasswordFile = File.createTempFile("pki-client-cert-show-", ".pwd"); -- pkcs12PasswordFile.deleteOnExit(); -+ // store password into a temporary file -+ File pkcs12PasswordFile = File.createTempFile("pki-client-cert-show-", ".pwd"); -+ pkcs12PasswordFile.deleteOnExit(); - -- try (PrintWriter out = new PrintWriter(new FileWriter(pkcs12PasswordFile))) { -- out.print(pkcs12Password); -- } -+ try (PrintWriter out = new PrintWriter(new FileWriter(pkcs12PasswordFile))) { -+ out.print(pkcs12Password); -+ } - -- // export certificate chain and private key into a temporary PKCS #12 file -- File pkcs12File = File.createTempFile("pki-client-cert-show-", ".p12"); -- pkcs12File.deleteOnExit(); -+ if (verbose) System.out.println("Exporting certificate chain and private key to " + pkcs12File + "."); -+ exportPKCS12( -+ mainCLI.certDatabase.getAbsolutePath(), -+ mainCLI.config.getCertPassword(), -+ pkcs12File.getAbsolutePath(), -+ pkcs12PasswordFile.getAbsolutePath(), -+ nickname); - -- exportPKCS12( -- mainCLI.certDatabase.getAbsolutePath(), -- mainCLI.config.getCertPassword(), -+ if (certPath != null) { -+ if (verbose) System.out.println("Exporting certificate to " + certPath + "."); -+ exportCertificate( - pkcs12File.getAbsolutePath(), - pkcs12PasswordFile.getAbsolutePath(), -- nickname); -+ certPath); -+ } - -- // export client certificate and private key into a PEM file -- exportClientCertificate( -+ if (privateKeyPath != null) { -+ if (verbose) System.out.println("Exporting private key to " + privateKeyPath + "."); -+ exportPrivateKey( - pkcs12File.getAbsolutePath(), - pkcs12PasswordFile.getAbsolutePath(), -- clientCertPath); -- -- } else { -- // late initialization -- mainCLI.init(); -- -- client = mainCLI.getClient(); -- X509Certificate cert = client.getCert(nickname); -+ privateKeyPath); -+ } - -- ClientCLI.printCertInfo(cert); -+ if (clientCertPath != null) { -+ if (verbose) System.out.println("Exporting client certificate and private key to " + clientCertPath + "."); -+ exportClientCertificateAndPrivateKey( -+ pkcs12File.getAbsolutePath(), -+ pkcs12PasswordFile.getAbsolutePath(), -+ clientCertPath); - } - } - -@@ -218,7 +212,53 @@ public class ClientCertShowCLI extends CLI { - } - } - -- public void exportClientCertificate( -+ public void exportCertificate( -+ String pkcs12Path, -+ String pkcs12PasswordPath, -+ String certPath) throws Exception { -+ -+ String[] command = { -+ "/bin/openssl", -+ "pkcs12", -+ "-clcerts", // certificate only -+ "-nokeys", -+ "-in", pkcs12Path, -+ "-passin", "file:" + pkcs12PasswordPath, -+ "-out", certPath -+ }; -+ -+ try { -+ run(command); -+ -+ } catch (Exception e) { -+ throw new Exception("Unable to export certificate", e); -+ } -+ } -+ -+ public void exportPrivateKey( -+ String pkcs12Path, -+ String pkcs12PasswordPath, -+ String privateKeyPath) throws Exception { -+ -+ String[] command = { -+ "/bin/openssl", -+ "pkcs12", -+ "-nocerts", // private key only -+ "-nodes", // no encryption -+ "-in", pkcs12Path, -+ "-passin", "file:" + pkcs12PasswordPath, -+ "-out", privateKeyPath -+ }; -+ -+ try { -+ run(command); -+ -+ } catch (Exception e) { -+ throw new Exception("Unable to export private key", e); -+ } -+ } -+ -+ public void exportClientCertificateAndPrivateKey( - String pkcs12Path, - String pkcs12PasswordPath, - String clientCertPath) throws Exception { -@@ -226,7 +266,7 @@ public class ClientCertShowCLI extends CLI { - String[] command = { - "/bin/openssl", - "pkcs12", -- "-clcerts", // client certificate only -+ "-clcerts", // client certificate and private key - "-nodes", // no encryption - "-in", pkcs12Path, - "-passin", "file:" + pkcs12PasswordPath, -@@ -237,7 +277,7 @@ public class ClientCertShowCLI extends CLI { - run(command); - - } catch (Exception e) { -- throw new Exception("Unable to export client certificate", e); -+ throw new Exception("Unable to export client certificate and private key", e); - } - } - -diff --git a/base/server/python/pki/server/__init__.py b/base/server/python/pki/server/__init__.py -index d004465..89d4acf 100644 ---- a/base/server/python/pki/server/__init__.py -+++ b/base/server/python/pki/server/__init__.py -@@ -28,7 +28,9 @@ import operator - import os - import pwd - import re -+import shutil - import subprocess -+import tempfile - - import pki - -@@ -162,18 +164,43 @@ class PKISubsystem(object): - - def open_database(self, name='internaldb'): - -+ # TODO: add LDAPI support - hostname = self.config['%s.ldapconn.host' % name] - port = self.config['%s.ldapconn.port' % name] -- bind_dn = self.config['%s.ldapauth.bindDN' % name] -+ secure = self.config['%s.ldapconn.secureConn' % name] - -- # TODO: add support for other authentication -- # mechanisms (e.g. client cert authentication, LDAPI) -- bind_password = self.instance.get_password(name) -+ if secure == 'true': -+ url = 'ldaps://%s:%s' % (hostname, port) - -- con = ldap.initialize('ldap://%s:%s' % (hostname, port)) -- con.simple_bind_s(bind_dn, bind_password) -+ elif secure == 'false': -+ url = 'ldap://%s:%s' % (hostname, port) - -- return con -+ else: -+ raise Exception('Invalid parameter value in %s.ldapconn.secureConn: %s' % (name, secure)) -+ -+ connection = PKIDatabaseConnection(url) -+ -+ connection.set_security_database(self.instance.nssdb_dir) -+ -+ auth_type = self.config['%s.ldapauth.authtype' % name] -+ if auth_type == 'BasicAuth': -+ connection.set_credentials( -+ bind_dn=self.config['%s.ldapauth.bindDN' % name], -+ bind_password=self.instance.get_password(name) -+ ) -+ -+ elif auth_type == 'SslClientAuth': -+ connection.set_credentials( -+ client_cert_nickname=self.config['%s.ldapauth.clientCertNickname' % name], -+ nssdb_password=self.instance.get_password('internal') -+ ) -+ -+ else: -+ raise Exception('Invalid parameter value in %s.ldapauth.authtype: %s' % (name, auth_type)) -+ -+ connection.open() -+ -+ return connection - - def __repr__(self): - return str(self.instance) + '/' + self.name -@@ -337,6 +364,64 @@ class PKIInstance(object): - return self.name - - -+class PKIDatabaseConnection(object): -+ -+ def __init__(self, url='ldap://localhost:389'): -+ -+ self.url = url -+ -+ self.nssdb_dir = None -+ -+ self.bind_dn = None -+ self.bind_password = None -+ -+ self.client_cert_nickname = None -+ self.nssdb_password = None -+ -+ self.temp_dir = None -+ self.ldap = None -+ -+ def set_security_database(self, nssdb_dir=None): -+ self.nssdb_dir = nssdb_dir -+ -+ def set_credentials(self, bind_dn=None, bind_password=None, -+ client_cert_nickname=None, nssdb_password=None): -+ self.bind_dn = bind_dn -+ self.bind_password = bind_password -+ self.client_cert_nickname = client_cert_nickname -+ self.nssdb_password = nssdb_password -+ -+ def open(self): -+ -+ self.temp_dir = tempfile.mkdtemp() -+ -+ if self.nssdb_dir: -+ -+ ldap.set_option(ldap.OPT_X_TLS_CACERTDIR, self.nssdb_dir) -+ -+ if self.client_cert_nickname: -+ -+ password_file = os.path.join(self.temp_dir, 'password.txt') -+ with open(password_file, 'w') as f: -+ f.write(self.nssdb_password) -+ -+ ldap.set_option(ldap.OPT_X_TLS_CERTFILE, self.client_cert_nickname) -+ ldap.set_option(ldap.OPT_X_TLS_KEYFILE, password_file) -+ -+ self.ldap = ldap.initialize(self.url) -+ -+ if self.bind_dn and self.bind_password: -+ self.ldap.simple_bind_s(self.bind_dn, self.bind_password) -+ -+ def close(self): -+ -+ if self.ldap: -+ self.ldap.unbind_s() -+ -+ if self.temp_dir: -+ shutil.rmtree(self.temp_dir) -+ -+ - class PKIServerException(pki.PKIException): - - def __init__(self, message, exception=None, -diff --git a/base/server/python/pki/server/ca.py b/base/server/python/pki/server/ca.py -index 70ebf4d..31e373a 100644 ---- a/base/server/python/pki/server/ca.py -+++ b/base/server/python/pki/server/ca.py -@@ -45,13 +45,13 @@ class CASubsystem(pki.server.PKISubsystem): - - con = self.open_database() - -- entries = con.search_s( -+ entries = con.ldap.search_s( - 'ou=ca,ou=requests,%s' % base_dn, - ldap.SCOPE_ONELEVEL, - search_filter, - None) - -- con.unbind_s() -+ con.close() - - requests = [] - for entry in entries: -@@ -65,13 +65,13 @@ class CASubsystem(pki.server.PKISubsystem): - - con = self.open_database() - -- entries = con.search_s( -+ entries = con.ldap.search_s( - 'cn=%s,ou=ca,ou=requests,%s' % (request_id, base_dn), - ldap.SCOPE_BASE, - '(objectClass=*)', - None) - -- con.unbind_s() -+ con.close() - - entry = entries[0] - return self.create_request_object(entry) -diff --git a/base/server/python/pki/server/cli/subsystem.py b/base/server/python/pki/server/cli/subsystem.py -index fc89c27..19db203 100644 ---- a/base/server/python/pki/server/cli/subsystem.py -+++ b/base/server/python/pki/server/cli/subsystem.py -@@ -104,7 +104,7 @@ class SubsystemFindCLI(pki.cli.CLI): - if first: - first = False - else: -- print -+ print() - - SubsystemCLI.print_subsystem(subsystem) - -diff --git a/base/server/upgrade/10.2.0/01-AddTLSRangeSupport b/base/server/upgrade/10.2.0/01-AddTLSRangeSupport -index b5b83f4..e225924 100755 ---- a/base/server/upgrade/10.2.0/01-AddTLSRangeSupport -+++ b/base/server/upgrade/10.2.0/01-AddTLSRangeSupport -@@ -29,7 +29,7 @@ import pki.server.upgrade - class AddTLSRangeSupport(pki.server.upgrade.PKIServerUpgradeScriptlet): - - def __init__(self): -- -+ super(AddTLSRangeSupport, self).__init__() - self.message = 'Add TLS Range Support' - - self.parser = etree.XMLParser(remove_blank_text=True) diff --git a/SOURCES/pki-core-beta.patch b/SOURCES/pki-core-beta.patch new file mode 100644 index 0000000..a32d10e --- /dev/null +++ b/SOURCES/pki-core-beta.patch @@ -0,0 +1,6301 @@ +From ca25d3856c37febe4aa89d19ba143bd1e021f0d1 Mon Sep 17 00:00:00 2001 +From: Abhijeet Kasurde +Date: Sat, 2 Jul 2016 11:03:53 +0530 +Subject: [PATCH 36/96] Added instance and subsystem validation for pki-server + subsystem-* commands. + +The pki-server subsystem-* commands have been updated to validate +the instance and subsystem before proceeding with the operation. + +https://fedorahosted.org/pki/ticket/2399 +--- + base/server/python/pki/server/cli/subsystem.py | 66 +++++++++++++++++++++----- + 1 file changed, 53 insertions(+), 13 deletions(-) + +diff --git a/base/server/python/pki/server/cli/subsystem.py b/base/server/python/pki/server/cli/subsystem.py +index 49215cf..a44243a 100644 +--- a/base/server/python/pki/server/cli/subsystem.py ++++ b/base/server/python/pki/server/cli/subsystem.py +@@ -177,6 +177,10 @@ class SubsystemShowCLI(pki.cli.CLI): + instance.load() + + subsystem = instance.get_subsystem(subsystem_name) ++ if not subsystem: ++ print('ERROR: No %s subsystem in instance ' ++ '%s.' % (subsystem_name, instance_name)) ++ sys.exit(1) + + SubsystemCLI.print_subsystem(subsystem) + +@@ -240,9 +244,17 @@ class SubsystemEnableCLI(pki.cli.CLI): + instance.load() + + subsystem = instance.get_subsystem(subsystem_name) +- subsystem.enable() ++ if not subsystem: ++ print('ERROR: No %s subsystem in instance ' ++ '%s.' % (subsystem_name, instance_name)) ++ sys.exit(1) + +- self.print_message('Enabled "%s" subsystem' % subsystem_name) ++ if subsystem.is_enabled(): ++ self.print_message('Subsystem "%s" is already ' ++ 'enabled' % subsystem_name) ++ else: ++ subsystem.enable() ++ self.print_message('Enabled "%s" subsystem' % subsystem_name) + + SubsystemCLI.print_subsystem(subsystem) + +@@ -308,9 +320,17 @@ class SubsystemDisableCLI(pki.cli.CLI): + instance.load() + + subsystem = instance.get_subsystem(subsystem_name) +- subsystem.disable() ++ if not subsystem: ++ print('ERROR: No %s subsystem in instance ' ++ '%s.' % (subsystem_name, instance_name)) ++ sys.exit(1) + +- self.print_message('Disabled "%s" subsystem' % subsystem_name) ++ if not subsystem.is_enabled(): ++ self.print_message('Subsystem "%s" is already ' ++ 'disabled' % subsystem_name) ++ else: ++ subsystem.disable() ++ self.print_message('Disabled "%s" subsystem' % subsystem_name) + + SubsystemCLI.print_subsystem(subsystem) + +@@ -403,6 +423,10 @@ class SubsystemCertFindCLI(pki.cli.CLI): + instance.load() + + subsystem = instance.get_subsystem(subsystem_name) ++ if not subsystem: ++ print('ERROR: No %s subsystem in instance ' ++ '%s.' % (subsystem_name, instance_name)) ++ sys.exit(1) + results = subsystem.find_system_certs() + + self.print_message('%s entries matched' % len(results)) +@@ -436,7 +460,7 @@ class SubsystemCertShowCLI(pki.cli.CLI): + + try: + opts, args = getopt.gnu_getopt(argv, 'i:v', [ +- 'instance=', 'show-all', ++ 'instance=', 'show-all', + 'verbose', 'help']) + + except getopt.GetoptError as e: +@@ -471,7 +495,6 @@ class SubsystemCertShowCLI(pki.cli.CLI): + self.usage() + sys.exit(1) + +- + if len(args) < 2: + print('ERROR: missing cert ID') + self.usage() +@@ -489,6 +512,10 @@ class SubsystemCertShowCLI(pki.cli.CLI): + instance.load() + + subsystem = instance.get_subsystem(subsystem_name) ++ if not subsystem: ++ print('ERROR: No %s subsystem in instance ' ++ '%s.' % (subsystem_name, instance_name)) ++ sys.exit(1) + cert = subsystem.get_subsystem_cert(cert_id) + + SubsystemCertCLI.print_subsystem_cert(cert, show_all) +@@ -611,6 +638,10 @@ class SubsystemCertExportCLI(pki.cli.CLI): + instance.load() + + subsystem = instance.get_subsystem(subsystem_name) ++ if not subsystem: ++ print('ERROR: No %s subsystem in instance ' ++ '%s.' % (subsystem_name, instance_name)) ++ sys.exit(1) + subsystem_cert = None + + if len(args) >= 2: +@@ -732,6 +763,10 @@ class SubsystemCertUpdateCLI(pki.cli.CLI): + instance.load() + + subsystem = instance.get_subsystem(subsystem_name) ++ if not subsystem: ++ print('ERROR: No %s subsystem in instance ' ++ '%s.' % (subsystem_name, instance_name)) ++ sys.exit(1) + subsystem_cert = subsystem.get_subsystem_cert(cert_id) + + # get cert data from NSS database +@@ -749,6 +784,9 @@ class SubsystemCertUpdateCLI(pki.cli.CLI): + # get cert request from local CA + # TODO: add support for remote CA + ca = instance.get_subsystem('ca') ++ if not ca: ++ print('ERROR: No CA subsystem in instance %s.' % instance_name) ++ sys.exit(1) + results = ca.find_cert_requests(cert=data) + cert_request = results[-1] + request = cert_request['request'] +@@ -820,7 +858,7 @@ class SubsystemCertValidateCLI(pki.cli.CLI): + + subsystem_name = args[0] + +- if len(args) >=2: ++ if len(args) >= 2: + cert_id = args[1] + else: + cert_id = None +@@ -835,7 +873,8 @@ class SubsystemCertValidateCLI(pki.cli.CLI): + + subsystem = instance.get_subsystem(subsystem_name) + if not subsystem: +- self.print_message('ERROR: missing subsystem ' + subsystem_name) ++ print('ERROR: No %s subsystem in instance ' ++ '%s.' % (subsystem_name, instance_name)) + sys.exit(1) + + if cert_id is not None: +@@ -909,16 +948,17 @@ class SubsystemCertValidateCLI(pki.cli.CLI): + os.close(pwfile_handle) + + try: +- cmd = ['pki', '-d', instance.nssdb_dir, +- '-C', pwfile_path ] ++ cmd = ['pki', ++ '-d', instance.nssdb_dir, ++ '-C', pwfile_path] + + if token: + cmd.extend(['--token', token]) + + cmd.extend(['client-cert-validate', +- nickname, +- '--certusage', usage] +- ) ++ nickname, ++ '--certusage', usage ++ ]) + + subprocess.check_output(cmd, stderr=subprocess.STDOUT) + print(' Status: VALID') +-- +1.8.3.1 + + +From 03926918b688d6634a46e322565bd1ab8ccdd811 Mon Sep 17 00:00:00 2001 +From: "Endi S. Dewata" +Date: Wed, 6 Jul 2016 17:40:13 +0200 +Subject: [PATCH 37/96] Fixed exception chain in SigningUnit.init(). + +The SigningUnit.init() has been modified to chain the exceptions +to help troubleshooting. + +https://fedorahosted.org/pki/ticket/2399 +--- + base/ca/src/com/netscape/ca/SigningUnit.java | 45 +++++++++++++--------- + .../certsrv/ca/CAMissingCertException.java | 3 ++ + .../netscape/certsrv/ca/CAMissingKeyException.java | 3 ++ + 3 files changed, 32 insertions(+), 19 deletions(-) + +diff --git a/base/ca/src/com/netscape/ca/SigningUnit.java b/base/ca/src/com/netscape/ca/SigningUnit.java +index 60bd84e..f708e55 100644 +--- a/base/ca/src/com/netscape/ca/SigningUnit.java ++++ b/base/ca/src/com/netscape/ca/SigningUnit.java +@@ -22,10 +22,6 @@ import java.security.NoSuchAlgorithmException; + import java.security.PublicKey; + import java.security.SignatureException; + +-import netscape.security.x509.AlgorithmId; +-import netscape.security.x509.X509CertImpl; +-import netscape.security.x509.X509Key; +- + import org.mozilla.jss.CryptoManager; + import org.mozilla.jss.NoSuchTokenException; + import org.mozilla.jss.crypto.CryptoToken; +@@ -42,15 +38,19 @@ import com.netscape.certsrv.apps.CMS; + import com.netscape.certsrv.base.EBaseException; + import com.netscape.certsrv.base.IConfigStore; + import com.netscape.certsrv.base.ISubsystem; +-import com.netscape.certsrv.ca.ECAException; + import com.netscape.certsrv.ca.CAMissingCertException; + import com.netscape.certsrv.ca.CAMissingKeyException; ++import com.netscape.certsrv.ca.ECAException; + import com.netscape.certsrv.common.Constants; + import com.netscape.certsrv.logging.ILogger; + import com.netscape.certsrv.security.ISigningUnit; + import com.netscape.cmscore.security.JssSubsystem; + import com.netscape.cmsutil.util.Cert; + ++import netscape.security.x509.AlgorithmId; ++import netscape.security.x509.X509CertImpl; ++import netscape.security.x509.X509Key; ++ + /** + * CA signing unit based on JSS. + * +@@ -171,7 +171,7 @@ public final class SigningUnit implements ISigningUnit { + mCert = mManager.findCertByNickname(mNickname); + CMS.debug("Found cert by nickname: '" + mNickname + "' with serial number: " + mCert.getSerialNumber()); + } catch (ObjectNotFoundException e) { +- throw new CAMissingCertException(CMS.getUserMessage("CMS_CA_CERT_OBJECT_NOT_FOUND")); ++ throw new CAMissingCertException(CMS.getUserMessage("CMS_CA_CERT_OBJECT_NOT_FOUND"), e); + } + + mCertImpl = new X509CertImpl(mCert.getEncoded()); +@@ -181,7 +181,7 @@ public final class SigningUnit implements ISigningUnit { + mPrivk = mManager.findPrivKeyByCert(mCert); + CMS.debug("Got private key from cert"); + } catch (ObjectNotFoundException e) { +- throw new CAMissingKeyException(CMS.getUserMessage("CMS_CA_CERT_OBJECT_NOT_FOUND")); ++ throw new CAMissingKeyException(CMS.getUserMessage("CMS_CA_CERT_OBJECT_NOT_FOUND"), e); + } + + mPubk = mCert.getPublicKey(); +@@ -194,32 +194,39 @@ public final class SigningUnit implements ISigningUnit { + CMS.debug( + "got signing algorithm " + mDefSigningAlgorithm); + mInited = true; ++ + } catch (java.security.cert.CertificateException e) { +- CMS.debug("SigningUnit init: debug " + e.toString()); ++ CMS.debug("SigningUnit: " + e); + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_SIGNING_CA_CERT", e.getMessage())); +- throw new ECAException(CMS.getUserMessage("CMS_BASE_INTERNAL_ERROR", e.toString())); ++ throw new ECAException(CMS.getUserMessage("CMS_BASE_INTERNAL_ERROR", e.toString()), e); ++ + } catch (CryptoManager.NotInitializedException e) { +- CMS.debug("SigningUnit init: debug " + e.toString()); ++ CMS.debug("SigningUnit: " + e); + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_SIGNING_TOKEN_INIT", e.toString())); +- throw new ECAException(CMS.getUserMessage("CMS_CA_CRYPTO_NOT_INITIALIZED")); ++ throw new ECAException(CMS.getUserMessage("CMS_CA_CRYPTO_NOT_INITIALIZED"), e); ++ + } catch (IncorrectPasswordException e) { +- CMS.debug("SigningUnit init: debug " + e.toString()); ++ CMS.debug("SigningUnit: " + e); + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_SIGNING_WRONG_PWD", e.toString())); +- throw new ECAException(CMS.getUserMessage("CMS_CA_INVALID_PASSWORD")); ++ throw new ECAException(CMS.getUserMessage("CMS_CA_INVALID_PASSWORD"), e); ++ + } catch (NoSuchTokenException e) { +- CMS.debug("SigningUnit init: debug " + e.toString()); ++ CMS.debug("SigningUnit: " + e); + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_SIGNING_TOKEN_NOT_FOUND", tokenname, e.toString())); +- throw new ECAException(CMS.getUserMessage("CMS_CA_TOKEN_NOT_FOUND", tokenname)); ++ throw new ECAException(CMS.getUserMessage("CMS_CA_TOKEN_NOT_FOUND", tokenname), e); ++ + } catch (CAMissingCertException | CAMissingKeyException e) { +- CMS.debug("SigningUnit init: debug " + e.toString()); ++ CMS.debug("SigningUnit: " + e); + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_SIGNING_CERT_NOT_FOUND", e.toString())); + throw e; // re-throw ++ + } catch (TokenException e) { +- CMS.debug("SigningUnit init: debug " + e.toString()); ++ CMS.debug("SigningUnit: " + e); + log(ILogger.LL_FAILURE, CMS.getLogMessage("OPERATION_ERROR", e.toString())); +- throw new ECAException(CMS.getUserMessage("CMS_CA_TOKEN_ERROR")); ++ throw new ECAException(CMS.getUserMessage("CMS_CA_TOKEN_ERROR"), e); ++ + } catch (Exception e) { +- CMS.debug("SigningUnit init: debug " + e.toString()); ++ CMS.debug(e); + } + } + +diff --git a/base/common/src/com/netscape/certsrv/ca/CAMissingCertException.java b/base/common/src/com/netscape/certsrv/ca/CAMissingCertException.java +index 49c5063..e363647 100644 +--- a/base/common/src/com/netscape/certsrv/ca/CAMissingCertException.java ++++ b/base/common/src/com/netscape/certsrv/ca/CAMissingCertException.java +@@ -12,4 +12,7 @@ public class CAMissingCertException extends ECAException { + super(msgFormat); + } + ++ public CAMissingCertException(String msgFormat, Exception cause) { ++ super(msgFormat, cause); ++ } + } +diff --git a/base/common/src/com/netscape/certsrv/ca/CAMissingKeyException.java b/base/common/src/com/netscape/certsrv/ca/CAMissingKeyException.java +index 8f5e1e7..178857f 100644 +--- a/base/common/src/com/netscape/certsrv/ca/CAMissingKeyException.java ++++ b/base/common/src/com/netscape/certsrv/ca/CAMissingKeyException.java +@@ -12,4 +12,7 @@ public class CAMissingKeyException extends ECAException { + super(msgFormat); + } + ++ public CAMissingKeyException(String msgFormat, Exception cause) { ++ super(msgFormat, cause); ++ } + } +-- +1.8.3.1 + + +From 4bdb8793eddd8d6c26a08c8f871249aa9a5bde7a Mon Sep 17 00:00:00 2001 +From: "Endi S. Dewata" +Date: Wed, 6 Jul 2016 21:12:35 +0200 +Subject: [PATCH 38/96] Fixed CLI error message on connection problems + +The CLI has been modified to display the actual error message +instead of generic ProcessingException. + +https://fedorahosted.org/pki/ticket/2377 +--- + base/java-tools/src/com/netscape/cmstools/cli/MainCLI.java | 13 ++++++++++++- + 1 file changed, 12 insertions(+), 1 deletion(-) + +diff --git a/base/java-tools/src/com/netscape/cmstools/cli/MainCLI.java b/base/java-tools/src/com/netscape/cmstools/cli/MainCLI.java +index 797f3cb..8f3293d 100644 +--- a/base/java-tools/src/com/netscape/cmstools/cli/MainCLI.java ++++ b/base/java-tools/src/com/netscape/cmstools/cli/MainCLI.java +@@ -31,6 +31,8 @@ import java.net.UnknownHostException; + import java.util.Collection; + import java.util.HashSet; + ++import javax.ws.rs.ProcessingException; ++ + import org.apache.commons.cli.CommandLine; + import org.apache.commons.cli.Option; + import org.apache.commons.lang.StringUtils; +@@ -571,11 +573,20 @@ public class MainCLI extends CLI { + MainCLI cli = new MainCLI(); + cli.execute(args); + ++ } catch (ProcessingException e) { ++ Throwable t = e.getCause(); ++ if (verbose) { ++ t.printStackTrace(System.err); ++ } else { ++ System.err.println(t.getClass().getSimpleName() + ": " + t.getMessage()); ++ } ++ System.exit(-1); ++ + } catch (Throwable t) { + if (verbose) { + t.printStackTrace(System.err); + } else { +- System.err.println(t.getClass().getSimpleName()+": "+t.getMessage()); ++ System.err.println(t.getClass().getSimpleName() + ": " + t.getMessage()); + } + System.exit(-1); + } +-- +1.8.3.1 + + +From c595208f58a2c072f9a7a243434411f66f556242 Mon Sep 17 00:00:00 2001 +From: "Endi S. Dewata" +Date: Wed, 6 Jul 2016 22:05:09 +0200 +Subject: [PATCH 39/96] Added validation for pki client-cert-request + extractable parameter. + +The pki client-cert-request CLI has been modified to validate the +boolean extractable parameter. + +https://fedorahosted.org/pki/ticket/2383 +--- + .../src/com/netscape/cmstools/client/ClientCertRequestCLI.java | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/base/java-tools/src/com/netscape/cmstools/client/ClientCertRequestCLI.java b/base/java-tools/src/com/netscape/cmstools/client/ClientCertRequestCLI.java +index 3ec4745..0277774 100644 +--- a/base/java-tools/src/com/netscape/cmstools/client/ClientCertRequestCLI.java ++++ b/base/java-tools/src/com/netscape/cmstools/client/ClientCertRequestCLI.java +@@ -194,6 +194,9 @@ public class ClientCertRequestCLI extends CLI { + if (s == null) { + extractable = -1; + } else { ++ if (!s.equalsIgnoreCase("true") && !s.equalsIgnoreCase("false")) { ++ throw new IllegalArgumentException("Invalid extractable parameter: " + s); ++ } + extractable = Boolean.parseBoolean(s) ? 1 : 0; + } + +-- +1.8.3.1 + + +From db75d23cbb90b834b2b515ce6344346522067b7b Mon Sep 17 00:00:00 2001 +From: "Endi S. Dewata" +Date: Wed, 6 Jul 2016 22:30:52 +0200 +Subject: [PATCH 40/96] Added validation for pki client-cert-request sensitive + parameter. + +The pki client-cert-request CLI has been modified to validate the +boolean sensitive parameter. + +https://fedorahosted.org/pki/ticket/2383 +--- + .../src/com/netscape/cmstools/client/ClientCertRequestCLI.java | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/base/java-tools/src/com/netscape/cmstools/client/ClientCertRequestCLI.java b/base/java-tools/src/com/netscape/cmstools/client/ClientCertRequestCLI.java +index 0277774..aff3220 100644 +--- a/base/java-tools/src/com/netscape/cmstools/client/ClientCertRequestCLI.java ++++ b/base/java-tools/src/com/netscape/cmstools/client/ClientCertRequestCLI.java +@@ -186,6 +186,9 @@ public class ClientCertRequestCLI extends CLI { + if (s == null) { + sensitive = -1; + } else { ++ if (!s.equalsIgnoreCase("true") && !s.equalsIgnoreCase("false")) { ++ throw new IllegalArgumentException("Invalid sensitive parameter: " + s); ++ } + sensitive = Boolean.parseBoolean(s) ? 1 : 0; + } + +-- +1.8.3.1 + + +From 9bf9f9628420d133010ff994cdac0f01b764b603 Mon Sep 17 00:00:00 2001 +From: "Endi S. Dewata" +Date: Wed, 6 Jul 2016 23:02:18 +0200 +Subject: [PATCH 41/96] Added general exception handling for pki-server CLI. + +The pki-server CLI has been modified to catch all exceptions and +display a simple exception message. In verbose mode it will +display the stack trace. + +https://fedorahosted.org/pki/ticket/2381 +--- + base/server/sbin/pki-server | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/base/server/sbin/pki-server b/base/server/sbin/pki-server +index cea62b7..6df70dc 100644 +--- a/base/server/sbin/pki-server ++++ b/base/server/sbin/pki-server +@@ -116,3 +116,9 @@ if __name__ == '__main__': + traceback.print_exc() + print('ERROR: %s' % e) + sys.exit(e.returncode) ++ ++ except Exception as e: # pylint: disable=broad-except ++ if cli.verbose: ++ traceback.print_exc() ++ print('ERROR: %s' % e) ++ sys.exit(1) +-- +1.8.3.1 + + +From 59ba26cf9292a578d34d98344e4b1f4d20339508 Mon Sep 17 00:00:00 2001 +From: "Endi S. Dewata" +Date: Thu, 7 Jul 2016 02:42:14 +0200 +Subject: [PATCH 42/96] Fixed problem with pki pkcs12-import --no-trust-flags. + +The pki pkcs12-import CLI has been fixed such that when it calls +pki pkcs12-cert-find internally it does not add --no-trust-flags +option. + +https://fedorahosted.org/pki/ticket/2399 +--- + base/common/python/pki/cli/pkcs12.py | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/base/common/python/pki/cli/pkcs12.py b/base/common/python/pki/cli/pkcs12.py +index 3fcea35..145f125 100644 +--- a/base/common/python/pki/cli/pkcs12.py ++++ b/base/common/python/pki/cli/pkcs12.py +@@ -159,9 +159,6 @@ class PKCS12ImportCLI(pki.cli.CLI): + if password_file: + cmd.extend(['--pkcs12-password-file', password_file]) + +- if no_trust_flags: +- cmd.extend(['--no-trust-flags']) +- + if self.verbose: + cmd.extend(['--verbose']) + +-- +1.8.3.1 + + +From 12e24ae0eb3f6fb7e0f71b95e3911f45594c5965 Mon Sep 17 00:00:00 2001 +From: "Endi S. Dewata" +Date: Thu, 7 Jul 2016 03:52:09 +0200 +Subject: [PATCH 43/96] Fixed pki pkcs12-import output. + +The pki pkcs12-import has been modified to suppress the output of +external command execution and display a completion message more +consistently. + +https://fedorahosted.org/pki/ticket/2399 +--- + base/common/python/pki/cli/pkcs12.py | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/base/common/python/pki/cli/pkcs12.py b/base/common/python/pki/cli/pkcs12.py +index 145f125..ded79c7 100644 +--- a/base/common/python/pki/cli/pkcs12.py ++++ b/base/common/python/pki/cli/pkcs12.py +@@ -314,4 +314,7 @@ class PKCS12ImportCLI(pki.cli.CLI): + + cmd.extend(nicknames) + +- main_cli.execute_java(cmd) ++ with open(os.devnull, 'w') as f: ++ main_cli.execute_java(cmd, stdout=f) ++ ++ self.print_message('Import complete') +-- +1.8.3.1 + + +From 7164c2064a7f069f0943f64167eaab982068593d Mon Sep 17 00:00:00 2001 +From: Christina Fu +Date: Thu, 7 Jul 2016 14:02:18 -0700 +Subject: [PATCH 44/96] Ticket #978 PPS connector man page: add revocation + routing info + +--- + base/tps/man/man5/pki-tps-connector.5 | 23 ++++++++++++++++++++++- + 1 file changed, 22 insertions(+), 1 deletion(-) + +diff --git a/base/tps/man/man5/pki-tps-connector.5 b/base/tps/man/man5/pki-tps-connector.5 +index 6ee009a..b3e405e 100644 +--- a/base/tps/man/man5/pki-tps-connector.5 ++++ b/base/tps/man/man5/pki-tps-connector.5 +@@ -62,12 +62,26 @@ This property contains the maximum number of HTTP connections. + .SS tps.connector.ca.uri. + + This property contains the URI to contact CA for the operation . +-Example ops: enrollment, renewal, revoke, unrevoke. ++Example ops: enrollment, renewal, revoke, unrevoke, getcert. + + .SS tps.connector.ca.timeout + + This property contains the connection timeout. + ++.SS tps.connector.connCAList ++ ++This property is used for \fIRevocation Routing\fP. It contains a list of ordered ca id's separated by ',' that the revocation attempt should be made to. ++Example: ++tps.connCAList=ca1,ca2 ++ ++.SS tps.connector.ca.caNickname ++ ++This property is used for \fIRevocation Routing\fP. It contains the nickname of the CA signing certificate that represents this ca. ++ ++.SS tps.connector.ca.caSKI ++ ++This property is used for \fIRevocation Routing\fP . It contains the Subject Key Identifier of the CA signing certificate of this ca. This value is automatically calculated by TPS once and should not need handling by the administrator. ++ + .SH KRA CONNECTOR + + A KRA connector is defined using properties that begin with tps.connector.kra where +@@ -182,6 +196,13 @@ tps.connector.ca1.uri.enrollment=/ca/ee/ca/profileSubmitSSLClient + tps.connector.ca1.uri.renewal=/ca/ee/ca/profileSubmitSSLClient + tps.connector.ca1.uri.revoke=/ca/ee/subsystem/ca/doRevoke + tps.connector.ca1.uri.unrevoke=/ca/ee/subsystem/ca/doUnrevoke ++# in case of Revocation Routing ++# note that caSKI is automatically calculated by TPS ++tps.connCAList=ca1,ca2 ++tps.connector.ca1.caNickname=caSigningCert cert-pki-tomcat CA ++tps.connector.ca1.caSKI=hAzNarQMlzit4BymAlbduZMwVCc ++# ca2 connector in case of Revocation Routing ++tps.connector.ca2. + + tps.connector.kra1.enable=true + tps.connector.kra1.host=server.example.com +-- +1.8.3.1 + + +From ee68baccc5510184ff67b903288410d3ccc6a831 Mon Sep 17 00:00:00 2001 +From: Christina Fu +Date: Mon, 11 Jul 2016 17:51:57 -0700 +Subject: [PATCH 46/96] Ticket #2389 fix for regular CA installation This patch + addresses the issue that with the previous patch, the regular (non-external + and non-existing) CA installation fails. + +--- + .../src/com/netscape/cms/servlet/csadmin/CertUtil.java | 17 +++++++++++------ + 1 file changed, 11 insertions(+), 6 deletions(-) + +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 495e4c0..ed762de 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,9 +535,14 @@ 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"); ++ if (!certTag.equals("signing")) { ++ /* ++ * (applies to non-CA-signing cert only) ++ * 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; +@@ -554,11 +559,11 @@ public class CertUtil { + } + + if (caPrik == null) { +- CMS.debug("CertUtil::createSelfSignedCert() - " ++ CMS.debug("CertUtil::createLocalCert() - " + + "CA private key is null!"); + throw new IOException("CA private key is null"); + } else { +- CMS.debug("CertUtil createSelfSignedCert: got CA private key"); ++ CMS.debug("CertUtil createLocalCert: got CA private key"); + } + + String keyAlgo = x509key.getAlgorithm(); +@@ -586,7 +591,7 @@ public class CertUtil { + } + + if (cert != null) { +- CMS.debug("CertUtil createSelfSignedCert: got cert signed"); ++ CMS.debug("CertUtil createLocalCert: got cert signed"); + } + + } catch (IOException e) { +-- +1.8.3.1 + + +From c3ff087bd07cde4cd272defad499fd4d8367e5c1 Mon Sep 17 00:00:00 2001 +From: Geetika Kapoor +Date: Wed, 13 Jul 2016 06:57:08 -0400 +Subject: [PATCH 47/96] Added fix for pki-server for db-update + +fixes: https://fedorahosted.org/pki/ticket/1667 + +Signed-off-by: Geetika Kapoor +Reviewed-by: Fraser Tweedale +--- + base/server/python/pki/server/cli/db.py | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/base/server/python/pki/server/cli/db.py b/base/server/python/pki/server/cli/db.py +index cc768da..17b1a2f 100644 +--- a/base/server/python/pki/server/cli/db.py ++++ b/base/server/python/pki/server/cli/db.py +@@ -202,7 +202,7 @@ class DBUpgrade(pki.cli.CLI): + entries = conn.ldap.search_s( + repo_dn, + ldap.SCOPE_ONELEVEL, +- '(&(objectclass=certificateRecord)(!(issuerName=*)))', ++ '(&(objectclass=certificaterecord)(|(!(issuername=*))(issuername=)))', + None) + + for entry in entries: +@@ -227,7 +227,7 @@ class DBUpgrade(pki.cli.CLI): + issuer_name = str(cert.issuer) + + try: +- conn.ldap.modify_s(dn, [(ldap.MOD_ADD, 'issuerName', issuer_name)]) ++ conn.ldap.modify_s(dn, [(ldap.MOD_REPLACE, 'issuerName', issuer_name)]) + except ldap.LDAPError as e: + print( + 'Failed to add issuerName to certificate {}: {}' +-- +1.8.3.1 + + +From 8c36ab242c99187a0356b85467e43f5b024718a2 Mon Sep 17 00:00:00 2001 +From: "Endi S. Dewata" +Date: Wed, 13 Jul 2016 04:11:56 +0200 +Subject: [PATCH 48/96] Fixed certificate validation error message. + +The pkihelper.py has been modified to display the correct external +command name on system certificate validation error. + +https://fedorahosted.org/pki/ticket/2399 +--- + base/server/python/pki/server/deployment/pkihelper.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/base/server/python/pki/server/deployment/pkihelper.py b/base/server/python/pki/server/deployment/pkihelper.py +index 0145b49..54ffe27 100644 +--- a/base/server/python/pki/server/deployment/pkihelper.py ++++ b/base/server/python/pki/server/deployment/pkihelper.py +@@ -4663,7 +4663,7 @@ class SystemCertificateVerifier: + stderr=subprocess.STDOUT) + except subprocess.CalledProcessError as e: + config.pki_log.error( +- "pki subsystem-cert-validate return code: " + str(e.returncode), ++ "pki-server subsystem-cert-validate return code: " + str(e.returncode), + extra=config.PKI_INDENTATION_LEVEL_2 + ) + config.pki_log.error( +-- +1.8.3.1 + + +From 96ebbeadc61e5a4c9df5d5adbd062a58ac3dee3c Mon Sep 17 00:00:00 2001 +From: Jack Magne +Date: Wed, 13 Jul 2016 17:15:14 -0700 +Subject: [PATCH 50/96] [MAN] Apply 'generateCRMFRequest() removed from + Firefox' workarounds to appropriate 'pki' man page + +This fix will involve the following changes to the source tree. + +1. Fixes to the CS.cfg to add two new cert profiles. +2. Make the caDualCert.cfg profile invisible since it has little chance of +working any more in Firefox. +3. Create caSigningUserCert.cfg and caSigningECUserCert.cfg to allow the CLI +to have convenient profiles from which to enroll signing ONLY certificates. +--- + base/ca/shared/conf/CS.cfg | 6 +- + base/ca/shared/profiles/ca/caDualCert.cfg | 2 +- + base/ca/shared/profiles/ca/caSigningECUserCert.cfg | 86 ++++++++++++++++++++++ + base/ca/shared/profiles/ca/caSigningUserCert.cfg | 86 ++++++++++++++++++++++ + 4 files changed, 178 insertions(+), 2 deletions(-) + create mode 100644 base/ca/shared/profiles/ca/caSigningECUserCert.cfg + create mode 100644 base/ca/shared/profiles/ca/caSigningUserCert.cfg + +diff --git a/base/ca/shared/conf/CS.cfg b/base/ca/shared/conf/CS.cfg +index 288f0d5..68e79a4 100644 +--- a/base/ca/shared/conf/CS.cfg ++++ b/base/ca/shared/conf/CS.cfg +@@ -966,7 +966,7 @@ oidmap.pse.oid=2.16.840.1.113730.1.18 + oidmap.subject_info_access.class=netscape.security.extensions.SubjectInfoAccessExtension + oidmap.subject_info_access.oid=1.3.6.1.5.5.7.1.11 + os.userid=nobody +-profile.list=caUserCert,caECUserCert,caUserSMIMEcapCert,caDualCert,caDirBasedDualCert,caECDualCert,AdminCert,caSignedLogCert,caTPSCert,caRARouterCert,caRouterCert,caServerCert,caSubsystemCert,caOtherCert,caCACert,caCrossSignedCACert,caInstallCACert,caRACert,caOCSPCert,caStorageCert,caTransportCert,caDirPinUserCert,caDirUserCert,caECDirUserCert,caAgentServerCert,caAgentFileSigning,caCMCUserCert,caFullCMCUserCert,caSimpleCMCUserCert,caTokenDeviceKeyEnrollment,caTokenUserEncryptionKeyEnrollment,caTokenUserSigningKeyEnrollment,caTempTokenDeviceKeyEnrollment,caTempTokenUserEncryptionKeyEnrollment,caTempTokenUserSigningKeyEnrollment,caAdminCert,caInternalAuthServerCert,caInternalAuthTransportCert,caInternalAuthDRMstorageCert,caInternalAuthSubsystemCert,caInternalAuthOCSPCert,caInternalAuthAuditSigningCert,DomainController,caDualRAuserCert,caRAagentCert,caRAserverCert,caUUIDdeviceCert,caSSLClientSelfRenewal,caDirUserRenewal,caManualRenewal,caTokenMSLoginEnrollment,caTokenUserSigningKeyRenewal,caTokenUserEncryptionKeyRenewal,caTokenUserAuthKeyRenewal,caJarSigningCert,caIPAserviceCert,caEncUserCert,caEncECUserCert,caTokenUserDelegateAuthKeyEnrollment,caTokenUserDelegateSigningKeyEnrollment ++profile.list=caUserCert,caECUserCert,caUserSMIMEcapCert,caDualCert,caDirBasedDualCert,caECDualCert,AdminCert,caSignedLogCert,caTPSCert,caRARouterCert,caRouterCert,caServerCert,caSubsystemCert,caOtherCert,caCACert,caCrossSignedCACert,caInstallCACert,caRACert,caOCSPCert,caStorageCert,caTransportCert,caDirPinUserCert,caDirUserCert,caECDirUserCert,caAgentServerCert,caAgentFileSigning,caCMCUserCert,caFullCMCUserCert,caSimpleCMCUserCert,caTokenDeviceKeyEnrollment,caTokenUserEncryptionKeyEnrollment,caTokenUserSigningKeyEnrollment,caTempTokenDeviceKeyEnrollment,caTempTokenUserEncryptionKeyEnrollment,caTempTokenUserSigningKeyEnrollment,caAdminCert,caInternalAuthServerCert,caInternalAuthTransportCert,caInternalAuthDRMstorageCert,caInternalAuthSubsystemCert,caInternalAuthOCSPCert,caInternalAuthAuditSigningCert,DomainController,caDualRAuserCert,caRAagentCert,caRAserverCert,caUUIDdeviceCert,caSSLClientSelfRenewal,caDirUserRenewal,caManualRenewal,caTokenMSLoginEnrollment,caTokenUserSigningKeyRenewal,caTokenUserEncryptionKeyRenewal,caTokenUserAuthKeyRenewal,caJarSigningCert,caIPAserviceCert,caEncUserCert,caSigningUserCert,caSigningECUserCert,caEncECUserCert,caTokenUserDelegateAuthKeyEnrollment,caTokenUserDelegateSigningKeyEnrollment + profile.caUUIDdeviceCert.class_id=caEnrollImpl + profile.caUUIDdeviceCert.config=[PKI_INSTANCE_PATH]/[PKI_SUBSYSTEM_TYPE]/profiles/ca/caUUIDdeviceCert.cfg + profile.caManualRenewal.class_id=caEnrollImpl +@@ -1037,6 +1037,10 @@ profile.caServerCert.class_id=caEnrollImpl + profile.caServerCert.config=[PKI_INSTANCE_PATH]/[PKI_SUBSYSTEM_TYPE]/profiles/ca/caServerCert.cfg + profile.caSignedLogCert.class_id=caEnrollImpl + profile.caSignedLogCert.config=[PKI_INSTANCE_PATH]/[PKI_SUBSYSTEM_TYPE]/profiles/ca/caSignedLogCert.cfg ++profile.caSigningECUserCert.class_id=caEnrollImpl ++profile.caSigningECUserCert.config=[PKI_INSTANCE_PATH]/[PKI_SUBSYSTEM_TYPE]/profiles/ca/caSigningECUserCert.cfg ++profile.caSigningUserCert.class_id=caEnrollImpl ++profile.caSigningUserCert.config=[PKI_INSTANCE_PATH]/[PKI_SUBSYSTEM_TYPE]/profiles/ca/caSigningUserCert.cfg + profile.caSimpleCMCUserCert.class_id=caEnrollImpl + profile.caSimpleCMCUserCert.config=[PKI_INSTANCE_PATH]/[PKI_SUBSYSTEM_TYPE]/profiles/ca/caSimpleCMCUserCert.cfg + profile.caSubsystemCert.class_id=caEnrollImpl +diff --git a/base/ca/shared/profiles/ca/caDualCert.cfg b/base/ca/shared/profiles/ca/caDualCert.cfg +index f90f78f..87036d1 100644 +--- a/base/ca/shared/profiles/ca/caDualCert.cfg ++++ b/base/ca/shared/profiles/ca/caDualCert.cfg +@@ -1,5 +1,5 @@ + desc=This certificate profile is for enrolling dual user certificates. It works only with Netscape 7.0 or later. +-visible=true ++visible=false + enable=true + enableBy=admin + name=Manual User Signing & Encryption Certificates Enrollment +diff --git a/base/ca/shared/profiles/ca/caSigningECUserCert.cfg b/base/ca/shared/profiles/ca/caSigningECUserCert.cfg +new file mode 100644 +index 0000000..b410504 +--- /dev/null ++++ b/base/ca/shared/profiles/ca/caSigningECUserCert.cfg +@@ -0,0 +1,86 @@ ++desc=This certificate profile is for enrolling user ECC signing certificates. It works only with the latest Firefox. ++visible=false ++enable=true ++enableBy=admin ++name=Manual User Signing ECC Certificate Enrollment ++auth.class_id= ++input.list=i1,i2,i3 ++input.i1.class_id=certReqInputImpl ++input.i2.class_id=subjectNameInputImpl ++input.i3.class_id=submitterInfoInputImpl ++output.list=o1 ++output.o1.class_id=certOutputImpl ++policyset.list=signingCertSet ++policyset.signingCertSet.list=1,2,3,4,5,6,7,8,9 ++policyset.signingCertSet.1.constraint.class_id=subjectNameConstraintImpl ++policyset.signingCertSet.1.constraint.name=Subject Name Constraint ++policyset.signingCertSet.1.constraint.params.pattern=CN=.* ++policyset.signingCertSet.1.constraint.params.accept=true ++policyset.signingCertSet.1.default.class_id=userSubjectNameDefaultImpl ++policyset.signingCertSet.1.default.name=Subject Name Default ++policyset.signingCertSet.1.default.params.name= ++policyset.signingCertSet.2.constraint.class_id=validityConstraintImpl ++policyset.signingCertSet.2.constraint.name=Validity Constraint ++policyset.signingCertSet.2.constraint.params.range=365 ++policyset.signingCertSet.2.constraint.params.notBeforeCheck=false ++policyset.signingCertSet.2.constraint.params.notAfterCheck=false ++policyset.signingCertSet.2.default.class_id=validityDefaultImpl ++policyset.signingCertSet.2.default.name=Validity Default ++policyset.signingCertSet.2.default.params.range=180 ++policyset.signingCertSet.2.default.params.startTime=0 ++policyset.signingCertSet.3.constraint.class_id=keyConstraintImpl ++policyset.signingCertSet.3.constraint.name=Key Constraint ++policyset.signingCertSet.3.constraint.params.keyType=EC ++policyset.signingCertSet.3.constraint.params.keyParameters=nistp256,nistp521 ++policyset.signingCertSet.3.default.class_id=userKeyDefaultImpl ++policyset.signingCertSet.3.default.name=Key Default ++policyset.signingCertSet.4.constraint.class_id=noConstraintImpl ++policyset.signingCertSet.4.constraint.name=No Constraint ++policyset.signingCertSet.4.default.class_id=authorityKeyIdentifierExtDefaultImpl ++policyset.signingCertSet.4.default.name=Authority Key Identifier Default ++policyset.signingCertSet.5.constraint.class_id=noConstraintImpl ++policyset.signingCertSet.5.constraint.name=No Constraint ++policyset.signingCertSet.5.default.class_id=authInfoAccessExtDefaultImpl ++policyset.signingCertSet.5.default.name=AIA Extension Default ++policyset.signingCertSet.5.default.params.authInfoAccessADEnable_0=true ++policyset.signingCertSet.5.default.params.authInfoAccessADLocationType_0=URIName ++policyset.signingCertSet.5.default.params.authInfoAccessADLocation_0= ++policyset.signingCertSet.5.default.params.authInfoAccessADMethod_0=1.3.6.1.5.5.7.48.1 ++policyset.signingCertSet.5.default.params.authInfoAccessCritical=false ++policyset.signingCertSet.5.default.params.authInfoAccessNumADs=1 ++policyset.signingCertSet.6.constraint.class_id=noConstraintImpl ++policyset.signingCertSet.6.constraint.name=No Constraint ++policyset.signingCertSet.6.default.class_id=keyUsageExtDefaultImpl ++policyset.signingCertSet.6.default.name=Key Usage Default ++policyset.signingCertSet.6.default.params.keyUsageCritical=true ++policyset.signingCertSet.6.default.params.keyUsageDigitalSignature=true ++policyset.signingCertSet.6.default.params.keyUsageNonRepudiation=true ++policyset.signingCertSet.6.default.params.keyUsageDataEncipherment=false ++policyset.signingCertSet.6.default.params.keyUsageKeyEncipherment=false ++policyset.signingCertSet.6.default.params.keyUsageKeyAgreement=false ++policyset.signingCertSet.6.default.params.keyUsageKeyCertSign=false ++policyset.signingCertSet.6.default.params.keyUsageCrlSign=false ++policyset.signingCertSet.6.default.params.keyUsageEncipherOnly=false ++policyset.signingCertSet.6.default.params.keyUsageDecipherOnly=false ++policyset.signingCertSet.7.constraint.class_id=noConstraintImpl ++policyset.signingCertSet.7.constraint.name=No Constraint ++policyset.signingCertSet.7.default.class_id=extendedKeyUsageExtDefaultImpl ++policyset.signingCertSet.7.default.name=Extended Key Usage Extension Default ++policyset.signingCertSet.7.default.params.exKeyUsageCritical=false ++policyset.signingCertSet.7.default.params.exKeyUsageOIDs=1.3.6.1.5.5.7.3.2,1.3.6.1.5.5.7.3.4 ++policyset.signingCertSet.8.constraint.class_id=noConstraintImpl ++policyset.signingCertSet.8.constraint.name=No Constraint ++policyset.signingCertSet.8.default.class_id=subjectAltNameExtDefaultImpl ++policyset.signingCertSet.8.default.name=Subject Alt Name Constraint ++policyset.signingCertSet.8.default.params.subjAltNameExtCritical=false ++policyset.signingCertSet.8.default.params.subjAltExtType_0=RFC822Name ++policyset.signingCertSet.8.default.params.subjAltExtPattern_0=$request.requestor_email$ ++policyset.signingCertSet.8.default.params.subjAltExtGNEnable_0=true ++policyset.signingCertSet.8.default.params.subjAltNameNumGNs=1 ++policyset.signingCertSet.9.constraint.class_id=signingAlgConstraintImpl ++policyset.signingCertSet.9.constraint.name=No Constraint ++policyset.signingCertSet.9.constraint.params.signingAlgsAllowed=SHA1withRSA,SHA256withRSA,SHA512withRSA,MD5withRSA,MD2withRSA,SHA1withDSA,SHA1withEC,SHA256withEC,SHA384withRSA,SHA384withEC,SHA512withEC ++policyset.signingCertSet.9.default.class_id=signingAlgDefaultImpl ++policyset.signingCertSet.9.default.name=Signing Alg ++policyset.signingCertSet.9.default.params.signingAlg=- ++ +diff --git a/base/ca/shared/profiles/ca/caSigningUserCert.cfg b/base/ca/shared/profiles/ca/caSigningUserCert.cfg +new file mode 100644 +index 0000000..f197ffa +--- /dev/null ++++ b/base/ca/shared/profiles/ca/caSigningUserCert.cfg +@@ -0,0 +1,86 @@ ++desc=This certificate profile is for enrolling user signing certificates. ++visible=false ++enable=true ++enableBy=admin ++name=Manual User Signing Certificate Enrollment ++auth.class_id= ++input.list=i1,i2,i3 ++input.i1.class_id=certReqInputImpl ++input.i2.class_id=subjectNameInputImpl ++input.i3.class_id=submitterInfoInputImpl ++output.list=o1 ++output.o1.class_id=certOutputImpl ++policyset.list=signingCertSet ++policyset.signingCertSet.list=1,2,3,4,5,6,7,8,9 ++policyset.signingCertSet.1.constraint.class_id=subjectNameConstraintImpl ++policyset.signingCertSet.1.constraint.name=Subject Name Constraint ++policyset.signingCertSet.1.constraint.params.pattern=CN=.* ++policyset.signingCertSet.1.constraint.params.accept=true ++policyset.signingCertSet.1.default.class_id=userSubjectNameDefaultImpl ++policyset.signingCertSet.1.default.name=Subject Name Default ++policyset.signingCertSet.1.default.params.name= ++policyset.signingCertSet.2.constraint.class_id=validityConstraintImpl ++policyset.signingCertSet.2.constraint.name=Validity Constraint ++policyset.signingCertSet.2.constraint.params.range=365 ++policyset.signingCertSet.2.constraint.params.notBeforeCheck=false ++policyset.signingCertSet.2.constraint.params.notAfterCheck=false ++policyset.signingCertSet.2.default.class_id=validityDefaultImpl ++policyset.signingCertSet.2.default.name=Validity Default ++policyset.signingCertSet.2.default.params.range=180 ++policyset.signingCertSet.2.default.params.startTime=0 ++policyset.signingCertSet.3.constraint.class_id=keyConstraintImpl ++policyset.signingCertSet.3.constraint.name=Key Constraint ++policyset.signingCertSet.3.constraint.params.keyType=RSA ++policyset.signingCertSet.3.constraint.params.keyParameters=1024,2048,3072,4096 ++policyset.signingCertSet.3.default.class_id=userKeyDefaultImpl ++policyset.signingCertSet.3.default.name=Key Default ++policyset.signingCertSet.4.constraint.class_id=noConstraintImpl ++policyset.signingCertSet.4.constraint.name=No Constraint ++policyset.signingCertSet.4.default.class_id=authorityKeyIdentifierExtDefaultImpl ++policyset.signingCertSet.4.default.name=Authority Key Identifier Default ++policyset.signingCertSet.5.constraint.class_id=noConstraintImpl ++policyset.signingCertSet.5.constraint.name=No Constraint ++policyset.signingCertSet.5.default.class_id=authInfoAccessExtDefaultImpl ++policyset.signingCertSet.5.default.name=AIA Extension Default ++policyset.signingCertSet.5.default.params.authInfoAccessADEnable_0=true ++policyset.signingCertSet.5.default.params.authInfoAccessADLocationType_0=URIName ++policyset.signingCertSet.5.default.params.authInfoAccessADLocation_0= ++policyset.signingCertSet.5.default.params.authInfoAccessADMethod_0=1.3.6.1.5.5.7.48.1 ++policyset.signingCertSet.5.default.params.authInfoAccessCritical=false ++policyset.signingCertSet.5.default.params.authInfoAccessNumADs=1 ++policyset.signingCertSet.6.constraint.class_id=noConstraintImpl ++policyset.signingCertSet.6.constraint.name=No Constraint ++policyset.signingCertSet.6.default.class_id=keyUsageExtDefaultImpl ++policyset.signingCertSet.6.default.name=Key Usage Default ++policyset.signingCertSet.6.default.params.keyUsageCritical=true ++policyset.signingCertSet.6.default.params.keyUsageDigitalSignature=true ++policyset.signingCertSet.6.default.params.keyUsageNonRepudiation=true ++policyset.signingCertSet.6.default.params.keyUsageDataEncipherment=false ++policyset.signingCertSet.6.default.params.keyUsageKeyEncipherment=false ++policyset.signingCertSet.6.default.params.keyUsageKeyAgreement=false ++policyset.signingCertSet.6.default.params.keyUsageKeyCertSign=false ++policyset.signingCertSet.6.default.params.keyUsageCrlSign=false ++policyset.signingCertSet.6.default.params.keyUsageEncipherOnly=false ++policyset.signingCertSet.6.default.params.keyUsageDecipherOnly=false ++policyset.signingCertSet.7.constraint.class_id=noConstraintImpl ++policyset.signingCertSet.7.constraint.name=No Constraint ++policyset.signingCertSet.7.default.class_id=extendedKeyUsageExtDefaultImpl ++policyset.signingCertSet.7.default.name=Extended Key Usage Extension Default ++policyset.signingCertSet.7.default.params.exKeyUsageCritical=false ++policyset.signingCertSet.7.default.params.exKeyUsageOIDs=1.3.6.1.5.5.7.3.2,1.3.6.1.5.5.7.3.4 ++policyset.signingCertSet.8.constraint.class_id=noConstraintImpl ++policyset.signingCertSet.8.constraint.name=No Constraint ++policyset.signingCertSet.8.default.class_id=subjectAltNameExtDefaultImpl ++policyset.signingCertSet.8.default.name=Subject Alt Name Constraint ++policyset.signingCertSet.8.default.params.subjAltNameExtCritical=false ++policyset.signingCertSet.8.default.params.subjAltExtType_0=RFC822Name ++policyset.signingCertSet.8.default.params.subjAltExtPattern_0=$request.requestor_email$ ++policyset.signingCertSet.8.default.params.subjAltExtGNEnable_0=true ++policyset.signingCertSet.8.default.params.subjAltNameNumGNs=1 ++policyset.signingCertSet.9.constraint.class_id=signingAlgConstraintImpl ++policyset.signingCertSet.9.constraint.name=No Constraint ++policyset.signingCertSet.9.constraint.params.signingAlgsAllowed=SHA1withRSA,SHA256withRSA,SHA512withRSA,MD5withRSA,MD2withRSA,SHA1withDSA,SHA1withEC,SHA256withEC,SHA384withRSA,SHA384withEC,SHA512withEC ++policyset.signingCertSet.9.default.class_id=signingAlgDefaultImpl ++policyset.signingCertSet.9.default.name=Signing Alg ++policyset.signingCertSet.9.default.params.signingAlg=- ++ +-- +1.8.3.1 + + +From 6bda601d3b4dea93e1a218662ae0814e3a2708a7 Mon Sep 17 00:00:00 2001 +From: "Endi S. Dewata" +Date: Thu, 14 Jul 2016 23:11:46 +0200 +Subject: [PATCH 51/96] Fixed cert usage list in pki client-cert-validate. + +The pki client-cert-validate has been modified to add the missing +EmailRecipient and to list the supported cert usages. + +https://fedorahosted.org/pki/ticket/2376 +https://fedorahosted.org/pki/ticket/2399 +--- + .../src/com/netscape/cmstools/client/ClientCertValidateCLI.java | 7 ++++++- + base/server/cmscore/src/com/netscape/cmscore/cert/CertUtils.java | 2 ++ + 2 files changed, 8 insertions(+), 1 deletion(-) + +diff --git a/base/java-tools/src/com/netscape/cmstools/client/ClientCertValidateCLI.java b/base/java-tools/src/com/netscape/cmstools/client/ClientCertValidateCLI.java +index 3988c71..50cd96f 100644 +--- a/base/java-tools/src/com/netscape/cmstools/client/ClientCertValidateCLI.java ++++ b/base/java-tools/src/com/netscape/cmstools/client/ClientCertValidateCLI.java +@@ -45,7 +45,10 @@ public class ClientCertValidateCLI extends CLI { + } + + public void createOptions() { +- Option option = new Option(null, "certusage", true, "Certificate usage."); ++ Option option = new Option(null, "certusage", true, "Certificate usage: " + ++ "CheckAllUsages, SSLServer, SSLServerWithStepUp, SSLClient, SSLCA, AnyCA, " + ++ "StatusResponder, ObjectSigner, UserCertImport, ProtectedObjectSigner, " + ++ "VerifyCA, EmailSigner, EmailRecipient."); + option.setArgName("certusage"); + options.addOption(option); + } +@@ -188,6 +191,8 @@ public class ClientCertValidateCLI extends CLI { + cu = CryptoManager.CertificateUsage.VerifyCA; + else if (certusage.equalsIgnoreCase("EmailSigner")) + cu = CryptoManager.CertificateUsage.EmailSigner; ++ else if (certusage.equalsIgnoreCase("EmailRecipient")) ++ cu = CryptoManager.CertificateUsage.EmailRecipient; + + return cu; + } +diff --git a/base/server/cmscore/src/com/netscape/cmscore/cert/CertUtils.java b/base/server/cmscore/src/com/netscape/cmscore/cert/CertUtils.java +index 5b6382e..400ad0c 100644 +--- a/base/server/cmscore/src/com/netscape/cmscore/cert/CertUtils.java ++++ b/base/server/cmscore/src/com/netscape/cmscore/cert/CertUtils.java +@@ -988,6 +988,8 @@ public class CertUtils { + cu = CryptoManager.CertificateUsage.VerifyCA; + else if (certusage.equalsIgnoreCase("EmailSigner")) + cu = CryptoManager.CertificateUsage.EmailSigner; ++ else if (certusage.equalsIgnoreCase("EmailRecipient")) ++ cu = CryptoManager.CertificateUsage.EmailRecipient; + + return cu; + } +-- +1.8.3.1 + + +From 078dfc1f01dea30800f19eed6df4ed547edffee3 Mon Sep 17 00:00:00 2001 +From: Christina Fu +Date: Tue, 12 Jul 2016 18:18:39 -0700 +Subject: [PATCH 52/96] Ticket #2246 [MAN] Man Page: AuditVerify This patch + contains the man page for AuditVerify. + +--- + base/java-tools/man/man1/AuditVerify.1 | 110 +++++++++++++++++++++++++++++++++ + 1 file changed, 110 insertions(+) + create mode 100644 base/java-tools/man/man1/AuditVerify.1 + +diff --git a/base/java-tools/man/man1/AuditVerify.1 b/base/java-tools/man/man1/AuditVerify.1 +new file mode 100644 +index 0000000..c0bd5ba +--- /dev/null ++++ b/base/java-tools/man/man1/AuditVerify.1 +@@ -0,0 +1,110 @@ ++.\" First parameter, NAME, should be all caps ++.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection ++.\" other parameters are allowed: see man(7), man(1) ++.TH AuditVerify 1 "July 7, 2016" "version 10.3" "PKI Signed Audit Log Verification Command" Dogtag Team ++.\" Please adjust this date whenever revising the man page. ++.\" ++.\" Some roff macros, for reference: ++.\" .nh disable hyphenation ++.\" .hy enable hyphenation ++.\" .ad l left justify ++.\" .ad b justify to both left and right margins ++.\" .nf disable filling ++.\" .fi enable filling ++.\" .br insert line break ++.\" .sp insert n+1 empty lines ++.\" for man page specific macros, see man(7) ++.SH NAME ++AuditVerify \- Command-Line utility for verifying Certificate System signed audit logs. ++ ++.SH SYNOPSIS ++.nf ++\fBAuditVerify\fR -d -n -a [-P cert/key_db_prefix] [-v] ++.fi ++ ++.SH DESCRIPTION ++.PP ++The \fBAuditVerify\fR command provides command-line utility to verify that signed audit logs were signed with the appropriate CS audit private signing key and that the audit logs have not been compromised. Auditors can verify the authenticity and integrity of signed audit logs using the \fBAuditVerify\fR tool. This tool uses the public key of the signed audit log signing certificate to verify the digital signatures embedded in a signed audit log file. The tool result indicates either that the signed audit log was successfully verified or that the signed audit log was not successfully verified. An unsuccessful verification warns the auditor that the signature failed to verify, indicating the log file may have been tampered with (compromised). ++.PP ++.B Note: An auditor can be any user that has the privilege to peruse the pki audit logs. ++ ++.SH OPTIONS ++.TP ++.B -d ++Specifies the directory containing the security databases with the imported audit log signing certificate. This directory is almost always the auditor's own personal certificate databases in a personal directory, such as ~jsmith/auditVerifyDir/. ++ ++.TP ++.B -n ++Gives the nickname of the certificate used to sign the log files. The nickname is whatever was used when the log signing certificate was imported into that database. ++ ++.TP ++.B [-P cert/key_db_prefix] ++Optional. The prefix to prepend to the certificate and key database filenames. If used, a value of empty quotation marks (“”) should be specified for this argument, since the auditor is using separate certificate and key databases from the Certificate System instance and it is unlikely that the prefix should be prepended to the new audit security database files. ++ ++.TP ++.B -a ++Specifies the file which contains the comma-separate list of file paths (in chronological order) of the signed audit logs to be verified. ++This file should be created in a directory which is writeable by the auditor, such as a special auditing directory like ~jsmith/auditDir. ++The contents of the logListFile are the full paths to the audit logs. For example: ++.PP ++.nf ++ /var/log/pki/pki-ca/ca/signedAudit/ca_audit,/var/log/pki/pki-ca/ca/signedAudit/ca_audit.20030227102711,/var/log/pki/pki-ca/ca/signedAudit/ca_audit.20030226094015 ++.fi ++ ++.TP ++.B [-v] ++Optional. Specifies verbose output. ++ ++.SH Setting up the Auditor's Database ++ ++\fBAuditVerify\fP needs access to a set of security databases (usually the auditor's personal security databases) containing the signed audit log signing certificate and its chain of issuing certificates. One of the CA certificates in the issuance chain must be marked as trusted in the database. ++.PP ++Auditors should import the audit signing certificate into their personal certificate database before running \fBAuditVerify\fP. The auditor should not use the security databases of the Certificate System instance that generated the signed audit log files. If there are no readily accessible certificate and key database, the auditor must create a set of certificate and key databases and import the signed audit log signing certificate chain. ++.PP ++To create the security databases and import the certificate chain: ++ ++.SS Create a special directory in the auditor's home directory to use to perform the verification. For example: ++ ++mkdir ~jsmith/auditVerifyDir ++ ++.SS Use the certutil tool to create an empty set of certificate databases in the auditor's home directory. ++ ++certutil -d ~jsmith/auditVerifyDir -N ++ ++.SS Download the CA certificate from the CA's Retrieval page. The certificates can be obtained from the CA in ASCII format. ++ ++https://server.example.com:ca_https_port/ca/ee/ca/ ++ ++.SS Import the CA certificate and log signing certificate into the databases and set trust of the certificates ++ ++If the CA certificate is in a file called cacert.txt and the log signing certificate is in a file called logsigncert.txt, then the certutil can be used to set the trust for the new audit security database directory pointing to those files, as follows: ++ ++certutil -d ~jsmith/auditVerifyDir/ -A -n "CA Certificate" -t "CT,CT,CT" -a -i cacert.txt ++ ++certutil -d ~jsmith/auditVerifyDir -A -n "Log Signing Certificate" -t ",,P" -a -i logsigncert.txt ++ ++.B Note: The signedAudit directory kept by the subsystem is not writeable by any user, including auditors. ++ ++.SH Operation ++After a separate audit database directory has been configured, do the following: ++.SS Create a text file containing a comma-separated list of the log files to be verified. The name of this file is referenced in the AuditVerify command. ++ ++For example, this file could be logListFile in the ~jsmith/auditVerifyDir/ directory. The contents are the comma-separated list of audit logs to be verified, such as "auditlog.1213, auditlog.1214, auditlog.1215." ++ ++.SS If the audit databases do not contain prefixes and are located in the user home directory, such as ~jsmith/.mozilla, and the signing certificate nickname is "Log Signing Certificate", the AuditVerify command is run as follows: ++ ++AuditVerify -d ~jsmith/auditVerifyDir -n Log Signing Certificate -a ~jsmith/auditVerifyDir/logListFile -P "" -v ++ ++.I Note: It has been observed that if audit signing is enabled after system is first started, the first audit signature would not be verified. What happens is that the signature starts calculating from it's in-memory audit log message when it signs, and since log signing is turned on mid-way (not from a fresh new log file), the previous content were not signed along for calculating the first signature (and rightfully so). When AuditVerify is run, it does not know where the log signing begins, so it assumes it starts from the beginning of the file till the first signature. This is why the first signature (if signing is turned on mid-way) will always appear to be incorrect. ++ ++ ++.SH AUTHORS ++Christina Fu . ++ ++.SH COPYRIGHT ++Copyright (c) 2016 Red Hat, Inc. This is licensed under the GNU General Public ++License, version 2 (GPLv2). A copy of this license is available at ++http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. ++ ++.SH SEE ALSO ++.BR pki(1) +-- +1.8.3.1 + + +From d20638e2916fb99da5cf09d869a1fbc89cd6f17b Mon Sep 17 00:00:00 2001 +From: "Endi S. Dewata" +Date: Sat, 16 Jul 2016 07:01:23 +0200 +Subject: [PATCH 53/96] Removed redundant question in interactive pkispawn. + +The pkispawn has been modified such that if the admin selects to +import the admin certificate the admin will not be asked where to +export the certificate. + +https://fedorahosted.org/pki/ticket/2399 +--- + base/server/sbin/pkispawn | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/base/server/sbin/pkispawn b/base/server/sbin/pkispawn +index d3a111f..11745b4 100755 +--- a/base/server/sbin/pkispawn ++++ b/base/server/sbin/pkispawn +@@ -226,9 +226,9 @@ def main(argv): + 'pki_import_admin_cert', + 'False') + +- parser.read_text('Export certificate to', +- config.pki_subsystem, +- 'pki_client_admin_cert') ++ parser.read_text('Export certificate to', ++ config.pki_subsystem, ++ 'pki_client_admin_cert') + + # if parser.mdict['pki_hsm_enable'] == 'True': + # use_hsm = 'Y' +@@ -261,7 +261,7 @@ def main(argv): + # parser.set_property(config.pki_subsystem, + # 'pki_hsm_libfile', + # libfile) +- # print ++ print() + + print("Directory Server:") + while True: +-- +1.8.3.1 + + +From 28176087a94f74b451c2dbf3c59b4d13a20014c6 Mon Sep 17 00:00:00 2001 +From: "Endi S. Dewata" +Date: Sat, 16 Jul 2016 09:22:27 +0200 +Subject: [PATCH 54/96] Fixed pkispawn installation summary. + +The pkispawn installation summary has been modified not to +show the admin certificate nickname and NSS database if +pki_client_database_purge or pki_clone is set to true since +the NSS database will not be created in those cases. + +https://fedorahosted.org/pki/ticket/2399 +--- + base/server/sbin/pkispawn | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +diff --git a/base/server/sbin/pkispawn b/base/server/sbin/pkispawn +index 11745b4..13139fa 100755 +--- a/base/server/sbin/pkispawn ++++ b/base/server/sbin/pkispawn +@@ -754,16 +754,15 @@ def print_final_install_information(mdict): + print(" Administrator's PKCS #12 file:\n %s" % + mdict['pki_client_admin_cert_p12']) + +- if not config.str2bool(mdict['pki_client_database_purge']): ++ if not config.str2bool(mdict['pki_client_database_purge']) and \ ++ not config.str2bool(mdict['pki_clone']): + print() + print(" Administrator's certificate nickname:\n %s" + % mdict['pki_admin_nickname']) +- +- if not config.str2bool(mdict['pki_clone']): + print(" Administrator's certificate database:\n %s" + % mdict['pki_client_database_dir']) + +- else: ++ if config.str2bool(mdict['pki_clone']): + print() + print(" This %s subsystem of the '%s' instance\n" + " is a clone." % +-- +1.8.3.1 + + +From eddbcedba312258cd4105f0353313c1423084593 Mon Sep 17 00:00:00 2001 +From: "Endi S. Dewata" +Date: Wed, 20 Jul 2016 00:38:41 +0200 +Subject: [PATCH 55/96] Fixed error handling in SystemConfigService. + +To help troubleshooting the SystemConfigService has been modified +to chain the original exception and to log stack trace into the +debug log. + +https://fedorahosted.org/pki/ticket/2399 +--- + .../src/org/dogtagpki/server/rest/SystemConfigService.java | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/base/server/cms/src/org/dogtagpki/server/rest/SystemConfigService.java b/base/server/cms/src/org/dogtagpki/server/rest/SystemConfigService.java +index 6fc37b5..95afa4c 100644 +--- a/base/server/cms/src/org/dogtagpki/server/rest/SystemConfigService.java ++++ b/base/server/cms/src/org/dogtagpki/server/rest/SystemConfigService.java +@@ -782,7 +782,7 @@ public class SystemConfigService extends PKIService implements SystemConfigResou + ConfigurationUtils.populateVLVIndexes(); + } + } catch (Exception e) { +- e.printStackTrace(); ++ CMS.debug(e); + throw new PKIException("Error in populating database: " + e, e); + } + } +@@ -1029,14 +1029,14 @@ public class SystemConfigService extends PKIService implements SystemConfigResou + String tokenpwd = data.getTokenPassword(); + ConfigurationUtils.loginToken(ctoken, tokenpwd); + } catch (NotInitializedException e) { +- throw new PKIException("Token is not initialized"); ++ throw new PKIException("Token is not initialized", e); + } catch (NoSuchTokenException e) { +- throw new BadRequestException("Invalid Token provided. No such token."); ++ throw new BadRequestException("Invalid Token provided. No such token.", e); + } catch (TokenException e) { +- e.printStackTrace(); +- throw new PKIException("Token Exception" + e); ++ CMS.debug(e); ++ throw new PKIException("Token Exception: " + e, e); + } catch (IncorrectPasswordException e) { +- throw new BadRequestException("Incorrect Password provided for token."); ++ throw new BadRequestException("Incorrect Password provided for token.", e); + } + } + } +-- +1.8.3.1 + + +From 3998429da6e4a96b1ec667436f1da6b96d0ca33c Mon Sep 17 00:00:00 2001 +From: "Endi S. Dewata" +Date: Fri, 22 Jul 2016 13:35:54 +0200 +Subject: [PATCH 56/96] Fixed param substitution problem. + +The string splice operation in substitute_deployment_params() has +been fixed to include the rest of the string. + +https://fedorahosted.org/pki/ticket/2399 +--- + base/server/python/pki/server/deployment/pkihelper.py | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/base/server/python/pki/server/deployment/pkihelper.py b/base/server/python/pki/server/deployment/pkihelper.py +index 54ffe27..6ac68b1 100644 +--- a/base/server/python/pki/server/deployment/pkihelper.py ++++ b/base/server/python/pki/server/deployment/pkihelper.py +@@ -1810,8 +1810,8 @@ class File: + line[begin:end + 1], value, + extra=config.PKI_INDENTATION_LEVEL_3) + +- # replace parameter with value +- line = line[0:begin] + value + line[end + 1] ++ # replace parameter with value, keep the rest of the line ++ line = line[0:begin] + value + line[end + 1:] + + # calculate the new end position + end = begin + len(value) + 1 +-- +1.8.3.1 + + +From 215d07d0754a5397e5008e98fe42626e8de9e399 Mon Sep 17 00:00:00 2001 +From: Jack Magne +Date: Fri, 22 Jul 2016 14:43:21 -0700 +Subject: [PATCH 57/96] Stop using a java8 only constant. Will allow + compilation with java7. Trivial fix. + +--- + .../cms/src/com/netscape/cms/servlet/tks/SecureChannelProtocol.java | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +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 9593816..db42cab 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 +@@ -56,6 +56,8 @@ public class SecureChannelProtocol { + static final int PROTOCOL_THREE = 3; + static final int HOST_CRYPTOGRAM = 0; + static final int CARD_CRYPTOGRAM = 1; ++ //Size of long type in bytes, since java7 has no define for this ++ static final int LONG_SIZE = 8; + + private SymmetricKey transportKey = null; + CryptoManager cryptoManager = null; +@@ -762,7 +764,7 @@ public class SecureChannelProtocol { + } + + public static byte[] longToBytes(long x) { +- ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES); ++ ByteBuffer buffer = ByteBuffer.allocate(LONG_SIZE); + buffer.putLong(x); + return buffer.array(); + } +-- +1.8.3.1 + + +From a307cf68e91327ddbef4b9d7e2bbd3991354831f Mon Sep 17 00:00:00 2001 +From: Matthew Harmsen +Date: Fri, 22 Jul 2016 18:38:19 -0600 +Subject: [PATCH 58/96] Allow PrettyPrintCert to process HEADERs and TRAILERs. + +* PKI TRAC Ticket #2399 - Dogtag 10.3.5: Miscellaneous Enhancements + Checked-in under one-liner/trivial rule. +--- + base/java-tools/templates/pretty_print_cert_command_wrapper.in | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/base/java-tools/templates/pretty_print_cert_command_wrapper.in b/base/java-tools/templates/pretty_print_cert_command_wrapper.in +index 63451d0..882e7a1 100644 +--- a/base/java-tools/templates/pretty_print_cert_command_wrapper.in ++++ b/base/java-tools/templates/pretty_print_cert_command_wrapper.in +@@ -137,7 +137,7 @@ if [ $# -eq 1 ] || + then + if [ "$1" = "-simpleinfo" ] + then +- file $2 | grep 'ASCII text' > /dev/null ++ file $2 | grep -E 'ASCII text|PEM certificate' > /dev/null + if [ $? -ne 0 ] ; then + ${JAVA} ${JAVA_OPTIONS} -cp ${CP} com.netscape.cmstools.${COMMAND} + printf "\n" +@@ -147,7 +147,7 @@ then + exit 255 + fi + else +- file $1 | grep 'ASCII text' > /dev/null ++ file $1 | grep -E 'ASCII text|PEM certificate' > /dev/null + if [ $? -ne 0 ] ; then + ${JAVA} ${JAVA_OPTIONS} -cp ${CP} com.netscape.cmstools.${COMMAND} + printf "\n" +-- +1.8.3.1 + + +From 3f4c9e4e7946f3f330b71cfe36a00ae933de2575 Mon Sep 17 00:00:00 2001 +From: "Endi S. Dewata" +Date: Thu, 21 Jul 2016 02:26:24 +0200 +Subject: [PATCH 59/96] Added CMake target dependencies. + +To help troubleshooting build issues, some CMake dependencies have +been added to some targets even though the actual codes do not +require those dependencies. This will ensure the targets are built +sequentially so build failures can be found more easily at the end +of the build log. + +https://fedorahosted.org/pki/ticket/2403 +--- + base/native-tools/src/tkstool/CMakeLists.txt | 2 +- + base/server/tomcat/src/CMakeLists.txt | 2 ++ + base/tps-client/src/CMakeLists.txt | 1 + + base/tps-client/src/authentication/CMakeLists.txt | 1 + + base/tps-client/src/modules/tokendb/CMakeLists.txt | 1 + + base/tps-client/src/modules/tps/CMakeLists.txt | 1 + + base/tps-client/src/tus/CMakeLists.txt | 1 + + 7 files changed, 8 insertions(+), 1 deletion(-) + +diff --git a/base/native-tools/src/tkstool/CMakeLists.txt b/base/native-tools/src/tkstool/CMakeLists.txt +index 8b07950..8c65717 100644 +--- a/base/native-tools/src/tkstool/CMakeLists.txt ++++ b/base/native-tools/src/tkstool/CMakeLists.txt +@@ -34,7 +34,7 @@ set(tkstool_SRCS + include_directories(${TKSTOOL_PRIVATE_INCLUDE_DIRS}) + + add_executable(tkstool ${tkstool_SRCS}) +- ++add_dependencies(tkstool pki-certsrv-jar) + target_link_libraries(tkstool ${TKSTOOL_LINK_LIBRARIES}) + + install( +diff --git a/base/server/tomcat/src/CMakeLists.txt b/base/server/tomcat/src/CMakeLists.txt +index 4cb40ad..c589758 100644 +--- a/base/server/tomcat/src/CMakeLists.txt ++++ b/base/server/tomcat/src/CMakeLists.txt +@@ -135,4 +135,6 @@ javac(pki-tomcat-classes + ${NUXWDOG_JAR} ${APACHE_COMMONS_LANG_JAR} ${TOMCATJSS_JAR} + OUTPUT_DIR + ${CMAKE_BINARY_DIR}/../../tomcat ++ DEPENDS ++ pki-certsrv-jar + ) +diff --git a/base/tps-client/src/CMakeLists.txt b/base/tps-client/src/CMakeLists.txt +index b0276f8..28ca2e4 100644 +--- a/base/tps-client/src/CMakeLists.txt ++++ b/base/tps-client/src/CMakeLists.txt +@@ -129,6 +129,7 @@ set(tps_library_SRCS + include_directories(${TPS_PRIVATE_INCLUDE_DIRS}) + + add_library(${TPS_SHARED_LIBRARY} SHARED ${tps_library_SRCS}) ++add_dependencies(${TPS_SHARED_LIBRARY} pki-tps-jar) + target_link_libraries(${TPS_SHARED_LIBRARY} ${TPS_LINK_LIBRARIES}) + + set_target_properties( +diff --git a/base/tps-client/src/authentication/CMakeLists.txt b/base/tps-client/src/authentication/CMakeLists.txt +index ba8ca07..b0ca83a 100644 +--- a/base/tps-client/src/authentication/CMakeLists.txt ++++ b/base/tps-client/src/authentication/CMakeLists.txt +@@ -37,6 +37,7 @@ set(ldapauth_library_SRCS + include_directories(${LDAPAUTH_PRIVATE_INCLUDE_DIRS}) + + add_library(${LDAPAUTH_SHARED_LIBRARY} SHARED ${ldapauth_library_SRCS}) ++add_dependencies(${LDAPAUTH_SHARED_LIBRARY} pki-tps-jar) + target_link_libraries(${LDAPAUTH_SHARED_LIBRARY} ${LDAPAUTH_LINK_LIBRARIES}) + + set_target_properties(${LDAPAUTH_SHARED_LIBRARY} +diff --git a/base/tps-client/src/modules/tokendb/CMakeLists.txt b/base/tps-client/src/modules/tokendb/CMakeLists.txt +index 7b6edae..94db88e 100644 +--- a/base/tps-client/src/modules/tokendb/CMakeLists.txt ++++ b/base/tps-client/src/modules/tokendb/CMakeLists.txt +@@ -31,6 +31,7 @@ set(tokendb_module_SRCS + include_directories(${TOKENDB_PRIVATE_INCLUDE_DIRS}) + + add_library(${TOKENDB_MODULE} MODULE ${tokendb_module_SRCS}) ++add_dependencies(${TOKENDB_MODULE} pki-tps-jar) + target_link_libraries(${TOKENDB_MODULE} ${TOKENDB_LINK_LIBRARIES}) + + set_target_properties(${TOKENDB_MODULE} +diff --git a/base/tps-client/src/modules/tps/CMakeLists.txt b/base/tps-client/src/modules/tps/CMakeLists.txt +index 275d8b3..ac990e5 100644 +--- a/base/tps-client/src/modules/tps/CMakeLists.txt ++++ b/base/tps-client/src/modules/tps/CMakeLists.txt +@@ -35,6 +35,7 @@ set(tps_module_SRCS + include_directories(${TPS_PRIVATE_INCLUDE_DIRS}) + + add_library(${TPS_MODULE} MODULE ${tps_module_SRCS}) ++add_dependencies(${TPS_MODULE} pki-tps-jar) + target_link_libraries(${TPS_MODULE} ${TPS_LINK_LIBRARIES}) + + set_target_properties(${TPS_MODULE} +diff --git a/base/tps-client/src/tus/CMakeLists.txt b/base/tps-client/src/tus/CMakeLists.txt +index 3148d9e..912075f 100644 +--- a/base/tps-client/src/tus/CMakeLists.txt ++++ b/base/tps-client/src/tus/CMakeLists.txt +@@ -35,6 +35,7 @@ set(tokendb_library_SRCS + include_directories(${TOKENDB_PRIVATE_INCLUDE_DIRS}) + + add_library(${TOKENDB_SHARED_LIBRARY} SHARED ${tokendb_library_SRCS}) ++add_dependencies(${TOKENDB_SHARED_LIBRARY} pki-tps-jar) + target_link_libraries(${TOKENDB_SHARED_LIBRARY} ${TOKENDB_LINK_LIBRARIES}) + + set_target_properties(${TOKENDB_SHARED_LIBRARY} +-- +1.8.3.1 + + +From 9e77b42d88da07e91a42966bc2d1ea9237e62f47 Mon Sep 17 00:00:00 2001 +From: "Endi S. Dewata" +Date: Fri, 22 Jul 2016 17:31:20 +0200 +Subject: [PATCH 60/96] Removed hard-coded paths in pki.policy. + +The operations script has been modified to generate pki.policy +dynamically from links in the /common/lib directory. +This allows the pki.policy to match the actual paths in different +platforms. + +https://fedorahosted.org/pki/ticket/2403 +--- + base/server/scripts/operations | 16 ++++- + base/server/share/conf/pki.policy | 132 +------------------------------------- + 2 files changed, 17 insertions(+), 131 deletions(-) + +diff --git a/base/server/scripts/operations b/base/server/scripts/operations +index 14443c4..5991670 100644 +--- a/base/server/scripts/operations ++++ b/base/server/scripts/operations +@@ -1352,10 +1352,24 @@ start_instance() + return $rv + fi + ++ # Copy pki.policy template ++ /bin/cp /usr/share/pki/server/conf/pki.policy /var/lib/pki/$PKI_INSTANCE_NAME/conf ++ ++ # Add permissions for all JAR files in /var/lib/pki/$PKI_INSTANCE_NAME/common/lib ++ for path in /var/lib/pki/$PKI_INSTANCE_NAME/common/lib/*; do ++ ++ cat >> /var/lib/pki/$PKI_INSTANCE_NAME/conf/pki.policy << EOF ++ ++grant codeBase "file:$(realpath $path)" { ++ permission java.security.AllPermission; ++}; ++EOF ++ done ++ + # Generate catalina.policy dynamically. + cat /usr/share/pki/server/conf/catalina.policy \ + /usr/share/tomcat/conf/catalina.policy \ +- /usr/share/pki/server/conf/pki.policy \ ++ /var/lib/pki/$PKI_INSTANCE_NAME/conf/pki.policy \ + /var/lib/pki/$PKI_INSTANCE_NAME/conf/custom.policy > \ + /var/lib/pki/$PKI_INSTANCE_NAME/conf/catalina.policy + +diff --git a/base/server/share/conf/pki.policy b/base/server/share/conf/pki.policy +index e281e01..7d8cfec 100644 +--- a/base/server/share/conf/pki.policy ++++ b/base/server/share/conf/pki.policy +@@ -4,10 +4,10 @@ + // --- END COPYRIGHT BLOCK --- + + // ============================================================================ +-// pki.policy - Default Security Policy Permissions for PKI on Tomcat 7 ++// pki.policy - Default Security Policy Permissions for PKI on Tomcat + // + // This file contains a default set of security policies for PKI running inside +-// Tomcat 7. ++// Tomcat. + // ============================================================================ + + grant codeBase "file:${catalina.home}/bin/tomcat-juli.jar" { +@@ -22,42 +22,6 @@ grant codeBase "file:${catalina.base}/lib/-" { + permission java.security.AllPermission; + }; + +-grant codeBase "file:/usr/lib/java/jss4.jar" { +- permission java.security.AllPermission; +-}; +- +-grant codeBase "file:/usr/lib/java/symkey.jar" { +- permission java.security.AllPermission; +-}; +- +-grant codeBase "file:/usr/lib64/java/jss4.jar" { +- permission java.security.AllPermission; +-}; +- +-grant codeBase "file:/usr/lib64/java/symkey.jar" { +- permission java.security.AllPermission; +-}; +- +-grant codeBase "file:/usr/share/java/commons-codec.jar" { +- permission java.security.AllPermission; +-}; +- +-grant codeBase "file:/usr/share/java/apache-commons-collections.jar" { +- permission java.security.AllPermission; +-}; +- +-grant codeBase "file:/usr/share/java/apache-commons-io.jar" { +- permission java.security.AllPermission; +-}; +- +-grant codeBase "file:/usr/share/java/apache-commons-lang.jar" { +- permission java.security.AllPermission; +-}; +- +-grant codeBase "file:/usr/share/java/apache-commons-logging.jar" { +- permission java.security.AllPermission; +-}; +- + grant codeBase "file:/usr/share/java/ecj.jar" { + permission java.security.AllPermission; + }; +@@ -70,18 +34,6 @@ grant codeBase "file:/usr/share/java/glassfish-jsp.jar" { + permission java.security.AllPermission; + }; + +-grant codeBase "file:/usr/share/java/httpcomponents/httpclient.jar" { +- permission java.security.AllPermission; +-}; +- +-grant codeBase "file:/usr/share/java/httpcomponents/httpcore.jar" { +- permission java.security.AllPermission; +-}; +- +-grant codeBase "file:/usr/share/java/javassist.jar" { +- permission java.security.AllPermission; +-}; +- + grant codeBase "file:/usr/share/java/jaxb-api.jar" { + permission java.security.AllPermission; + }; +@@ -98,66 +50,10 @@ grant codeBase "file:/usr/share/java/jboss-web.jar" { + permission java.security.AllPermission; + }; + +-grant codeBase "file:/usr/share/java/jackson/jackson-core-asl.jar" { +- permission java.security.AllPermission; +-}; +- +-grant codeBase "file:/usr/share/java/jackson/jackson-jaxrs.jar" { +- permission java.security.AllPermission; +-}; +- +-grant codeBase "file:/usr/share/java/jackson/jackson-mapper-asl.jar" { +- permission java.security.AllPermission; +-}; +- +-grant codeBase "file:/usr/share/java/jackson/jackson-mrbean.jar" { +- permission java.security.AllPermission; +-}; +- +-grant codeBase "file:/usr/share/java/jackson/jackson-smile.jar" { +- permission java.security.AllPermission; +-}; +- +-grant codeBase "file:/usr/share/java/jackson/jackson-xc.jar" { +- permission java.security.AllPermission; +-}; +- +-grant codeBase "file:/usr/share/java/ldapjdk.jar" { +- permission java.security.AllPermission; +-}; +- + grant codeBase "file:/usr/share/java/log4j.jar" { + permission java.security.AllPermission; + }; + +-grant codeBase "file:${RESTEASY_LIB}/jaxrs-api.jar" { +- permission java.security.AllPermission; +-}; +- +-grant codeBase "file:${RESTEASY_LIB}/resteasy-atom-provider.jar" { +- permission java.security.AllPermission; +-}; +- +-grant codeBase "file:${RESTEASY_LIB}/resteasy-client.jar" { +- permission java.security.AllPermission; +-}; +- +-grant codeBase "file:${RESTEASY_LIB}/resteasy-jaxb-provider.jar" { +- permission java.security.AllPermission; +-}; +- +-grant codeBase "file:${RESTEASY_LIB}/resteasy-jaxrs.jar" { +- permission java.security.AllPermission; +-}; +- +-grant codeBase "file:${RESTEASY_LIB}/resteasy-jackson-provider.jar" { +- permission java.security.AllPermission; +-}; +- +-grant codeBase "file:/usr/share/java/scannotation.jar" { +- permission java.security.AllPermission; +-}; +- + grant codeBase "file:/usr/share/java/servlet.jar" { + permission java.security.AllPermission; + }; +@@ -166,10 +62,6 @@ grant codeBase "file:/usr/share/java/tomcat/-" { + permission java.security.AllPermission; + }; + +-grant codeBase "file:/usr/share/java/tomcatjss.jar" { +- permission java.security.AllPermission; +-}; +- + grant codeBase "file:/usr/share/java/tomcat-el-api.jar" { + permission java.security.AllPermission; + }; +@@ -178,22 +70,6 @@ grant codeBase "file:/usr/share/java/tomcat-servlet-api.jar" { + permission java.security.AllPermission; + }; + +-grant codeBase "file:/usr/share/java/velocity.jar" { +- permission java.security.AllPermission; +-}; +- +-grant codeBase "file:/usr/share/java/xerces-j2.jar" { +- permission java.security.AllPermission; +-}; +- +-grant codeBase "file:/usr/share/java/xml-commons-apis.jar" { +- permission java.security.AllPermission; +-}; +- +-grant codeBase "file:/usr/share/java/xml-commons-resolver.jar" { +- permission java.security.AllPermission; +-}; +- + grant codeBase "file:/usr/share/java/pki/-" { + permission java.security.AllPermission; + }; +@@ -221,7 +97,3 @@ grant codeBase "file:${catalina.base}/webapps/tks/-" { + grant codeBase "file:${catalina.base}/webapps/ROOT/-" { + permission java.security.AllPermission; + }; +- +-grant codeBase "file:/usr/lib/java/nuxwdog.jar" { +- permission java.security.AllPermission; +-}; +-- +1.8.3.1 + + +From ecbf1cded60cec973316584baf272ae4c7bae1dd Mon Sep 17 00:00:00 2001 +From: "Endi S. Dewata" +Date: Thu, 21 Jul 2016 05:08:25 +0200 +Subject: [PATCH 61/96] Removed hard-coded paths in pki CLI. + +The pki CLI has been modified to use java.ext.dirs property to +load the dependencies instead of listing them individually. The +dependencies are stored as links in /usr/share/pki/lib folder. +This allows the RPM spec to customize the links for different +platforms. + +https://fedorahosted.org/pki/ticket/2403 +--- + base/common/CMakeLists.txt | 45 ++++++++++++++++++++++++++++++++++++++++++ + base/common/share/etc/pki.conf | 3 +++ + base/java-tools/bin/pki | 43 ++++------------------------------------ + 3 files changed, 52 insertions(+), 39 deletions(-) + +diff --git a/base/common/CMakeLists.txt b/base/common/CMakeLists.txt +index 1213925..dc5cecf 100644 +--- a/base/common/CMakeLists.txt ++++ b/base/common/CMakeLists.txt +@@ -11,6 +11,51 @@ configure_file( + ${CMAKE_CURRENT_BINARY_DIR}/etc/pki.conf + ) + ++# Create /usr/share/pki/lib. This can be customized for different platforms in RPM spec. ++ ++add_custom_target(pki-lib ALL) ++ ++add_custom_command( ++ TARGET pki-lib ++ COMMAND ${CMAKE_COMMAND} -E make_directory lib ++ COMMAND ${CMAKE_COMMAND} -E create_symlink /usr/share/java/commons-cli.jar lib/commons-cli.jar ++ COMMAND ${CMAKE_COMMAND} -E create_symlink /usr/share/java/commons-codec.jar lib/commons-codec.jar ++ COMMAND ${CMAKE_COMMAND} -E create_symlink /usr/share/java/commons-httpclient.jar lib/commons-httpclient.jar ++ COMMAND ${CMAKE_COMMAND} -E create_symlink /usr/share/java/commons-io.jar lib/commons-io.jar ++ COMMAND ${CMAKE_COMMAND} -E create_symlink /usr/share/java/commons-lang.jar lib/commons-lang.jar ++ COMMAND ${CMAKE_COMMAND} -E create_symlink /usr/share/java/commons-logging.jar lib/commons-logging.jar ++ COMMAND ${CMAKE_COMMAND} -E create_symlink /usr/share/java/httpcomponents/httpclient.jar lib/httpclient.jar ++ COMMAND ${CMAKE_COMMAND} -E create_symlink /usr/share/java/httpcomponents/httpcore.jar lib/httpcore.jar ++ COMMAND ${CMAKE_COMMAND} -E create_symlink /usr/share/java/jackson/jackson-core-asl.jar lib/jackson-core-asl.jar ++ COMMAND ${CMAKE_COMMAND} -E create_symlink /usr/share/java/jackson/jackson-jaxrs.jar lib/jackson-jaxrs.jar ++ COMMAND ${CMAKE_COMMAND} -E create_symlink /usr/share/java/jackson/jackson-mapper-asl.jar lib/jackson-mapper-asl.jar ++ COMMAND ${CMAKE_COMMAND} -E create_symlink /usr/share/java/jackson/jackson-mrbean.jar lib/jackson-mrbean.jar ++ COMMAND ${CMAKE_COMMAND} -E create_symlink /usr/share/java/jackson/jackson-smile.jar lib/jackson-smile.jar ++ COMMAND ${CMAKE_COMMAND} -E create_symlink /usr/share/java/jackson/jackson-xc.jar lib/jackson-xc.jar ++ COMMAND ${CMAKE_COMMAND} -E create_symlink /usr/share/java/jaxb-api.jar lib/jaxb-api.jar ++ COMMAND ${CMAKE_COMMAND} -E create_symlink /usr/lib/java/jss4.jar lib/jss4.jar ++ COMMAND ${CMAKE_COMMAND} -E create_symlink /usr/share/java/ldapjdk.jar lib/ldapjdk.jar ++ COMMAND ${CMAKE_COMMAND} -E create_symlink /usr/share/java/pki/pki-certsrv.jar lib/pki-certsrv.jar ++ COMMAND ${CMAKE_COMMAND} -E create_symlink /usr/share/java/pki/pki-cmsutil.jar lib/pki-cmsutil.jar ++ COMMAND ${CMAKE_COMMAND} -E create_symlink /usr/share/java/pki/pki-nsutil.jar lib/pki-nsutil.jar ++ COMMAND ${CMAKE_COMMAND} -E create_symlink /usr/share/java/pki/pki-tools.jar lib/pki-tools.jar ++ COMMAND ${CMAKE_COMMAND} -E create_symlink ${RESTEASY_LIB}/resteasy-atom-provider.jar lib/resteasy-atom-provider.jar ++ COMMAND ${CMAKE_COMMAND} -E create_symlink ${RESTEASY_LIB}/resteasy-client.jar lib/resteasy-client.jar ++ COMMAND ${CMAKE_COMMAND} -E create_symlink ${RESTEASY_LIB}/resteasy-jackson-provider.jar lib/resteasy-jackson-provider.jar ++ COMMAND ${CMAKE_COMMAND} -E create_symlink ${RESTEASY_LIB}/resteasy-jaxb-provider.jar lib/resteasy-jaxb-provider.jar ++ COMMAND ${CMAKE_COMMAND} -E create_symlink ${RESTEASY_LIB}/jaxrs-api.jar lib/resteasy-jaxrs-api.jar ++ COMMAND ${CMAKE_COMMAND} -E create_symlink ${RESTEASY_LIB}/resteasy-jaxrs-jandex.jar lib/resteasy-jaxrs-jandex.jar ++ COMMAND ${CMAKE_COMMAND} -E create_symlink ${RESTEASY_LIB}/resteasy-jaxrs.jar lib/resteasy-jaxrs.jar ++ COMMAND ${CMAKE_COMMAND} -E create_symlink /usr/share/java/servlet.jar lib/servlet.jar ++) ++ ++install( ++ DIRECTORY ++ ${CMAKE_CURRENT_BINARY_DIR}/lib/ ++ DESTINATION ++ ${DATA_INSTALL_DIR}/lib ++) ++ + install( + FILES + ${CMAKE_CURRENT_SOURCE_DIR}/share/etc/logging.properties +diff --git a/base/common/share/etc/pki.conf b/base/common/share/etc/pki.conf +index f43d914..97f3777 100644 +--- a/base/common/share/etc/pki.conf ++++ b/base/common/share/etc/pki.conf +@@ -4,5 +4,8 @@ JAVA_HOME=${JAVA_HOME} + # JNI jar file location + JNI_JAR_DIR=/usr/lib/java + ++# PKI library ++PKI_LIB=/usr/share/pki/lib ++ + # logging configuration location + LOGGING_CONFIG=/usr/share/pki/etc/logging.properties +diff --git a/base/java-tools/bin/pki b/base/java-tools/bin/pki +index c1ba34e..ba321be 100644 +--- a/base/java-tools/bin/pki ++++ b/base/java-tools/bin/pki +@@ -76,11 +76,11 @@ class PKICLI(pki.cli.CLI): + shell=True) + java_home = value.decode(sys.getfilesystemencoding()).strip() + +- # read RESTEasy library path ++ # read PKI library + value = subprocess.check_output( +- '. /usr/share/pki/etc/pki.conf && . /etc/pki/pki.conf && echo $RESTEASY_LIB', ++ '. /usr/share/pki/etc/pki.conf && . /etc/pki/pki.conf && echo $PKI_LIB', + shell=True) +- resteasy_lib = value.decode(sys.getfilesystemencoding()).strip() ++ pki_lib = value.decode(sys.getfilesystemencoding()).strip() + + # read logging configuration path + value = subprocess.check_output( +@@ -88,44 +88,9 @@ class PKICLI(pki.cli.CLI): + shell=True) + logging_config = value.decode(sys.getfilesystemencoding()).strip() + +- # construct classpath +- classpath = [ +- '/usr/share/java/commons-cli.jar', +- '/usr/share/java/commons-codec.jar', +- '/usr/share/java/commons-httpclient.jar', +- '/usr/share/java/commons-io.jar', +- '/usr/share/java/commons-lang.jar', +- '/usr/share/java/commons-logging.jar', +- '/usr/share/java/httpcomponents/httpclient.jar', +- '/usr/share/java/httpcomponents/httpcore.jar', +- '/usr/share/java/jackson/jackson-core-asl.jar', +- '/usr/share/java/jackson/jackson-jaxrs.jar', +- '/usr/share/java/jackson/jackson-mapper-asl.jar', +- '/usr/share/java/jackson/jackson-mrbean.jar', +- '/usr/share/java/jackson/jackson-smile.jar', +- '/usr/share/java/jackson/jackson-xc.jar', +- '/usr/share/java/jaxb-api.jar', +- '/usr/share/java/ldapjdk.jar', +- '/usr/share/java/servlet.jar', +- resteasy_lib + '/jaxrs-api.jar', +- resteasy_lib + '/resteasy-atom-provider.jar', +- resteasy_lib + '/resteasy-client.jar', +- resteasy_lib + '/resteasy-jaxb-provider.jar', +- resteasy_lib + '/resteasy-jaxrs.jar', +- resteasy_lib + '/resteasy-jaxrs-jandex.jar', +- resteasy_lib + '/resteasy-jackson-provider.jar', +- '/usr/share/java/pki/pki-nsutil.jar', +- '/usr/share/java/pki/pki-cmsutil.jar', +- '/usr/share/java/pki/pki-certsrv.jar', +- '/usr/share/java/pki/pki-tools.jar', +- '/usr/lib64/java/jss4.jar', +- '/usr/lib/java/jss4.jar' +- ] +- + cmd = [ + java_home + '/bin/java', +- '-cp', +- ':'.join(classpath), ++ '-Djava.ext.dirs=' + pki_lib, + '-Djava.util.logging.config.file=' + logging_config, + 'com.netscape.cmstools.cli.MainCLI' + ] +-- +1.8.3.1 + + +From 4926aace5cf0be65ddddf51c031e6cac6646a1dd Mon Sep 17 00:00:00 2001 +From: "Endi S. Dewata" +Date: Thu, 21 Jul 2016 05:08:25 +0200 +Subject: [PATCH 63/96] Removed hard-coded paths in deployment tool. + +The deployment tool has been modified to link /common +to /usr/share/pki/server/common instead of creating separate links +for each dependency. This allows the RPM spec to customize the +links for different platforms. + +https://fedorahosted.org/pki/ticket/2403 +--- + base/server/CMakeLists.txt | 47 +++++++ + base/server/etc/default.cfg | 82 ------------ + .../deployment/scriptlets/instance_layout.py | 143 +-------------------- + base/server/scripts/operations | 79 ------------ + 4 files changed, 54 insertions(+), 297 deletions(-) + +diff --git a/base/server/CMakeLists.txt b/base/server/CMakeLists.txt +index 5a6aea9..27470f3 100644 +--- a/base/server/CMakeLists.txt ++++ b/base/server/CMakeLists.txt +@@ -21,6 +21,53 @@ set(APACHE_SUBSYSTEMS + tps + ) + ++# Create /usr/share/pki/server/common/lib. This can be customized for different platforms in RPM spec. ++ ++add_custom_target(pki-server-common-lib ALL) ++ ++add_custom_command( ++ TARGET pki-server-common-lib ++ COMMAND ${CMAKE_COMMAND} -E make_directory common/lib ++ COMMAND ${CMAKE_COMMAND} -E create_symlink /usr/share/java/commons-codec.jar common/lib/commons-codec.jar ++ COMMAND ${CMAKE_COMMAND} -E create_symlink /usr/share/java/commons-collections.jar common/lib/commons-collections.jar ++ COMMAND ${CMAKE_COMMAND} -E create_symlink /usr/share/java/commons-io.jar common/lib/commons-io.jar ++ COMMAND ${CMAKE_COMMAND} -E create_symlink /usr/share/java/commons-lang.jar common/lib/commons-lang.jar ++ COMMAND ${CMAKE_COMMAND} -E create_symlink /usr/share/java/commons-logging.jar common/lib/commons-logging.jar ++ COMMAND ${CMAKE_COMMAND} -E create_symlink /usr/share/java/httpcomponents/httpclient.jar common/lib/httpclient.jar ++ COMMAND ${CMAKE_COMMAND} -E create_symlink /usr/share/java/httpcomponents/httpcore.jar common/lib/httpcore.jar ++ COMMAND ${CMAKE_COMMAND} -E create_symlink /usr/share/java/jackson/jackson-core-asl.jar common/lib/jackson-core-asl.jar ++ COMMAND ${CMAKE_COMMAND} -E create_symlink /usr/share/java/jackson/jackson-jaxrs.jar common/lib/jackson-jaxrs.jar ++ COMMAND ${CMAKE_COMMAND} -E create_symlink /usr/share/java/jackson/jackson-mapper-asl.jar common/lib/jackson-mapper-asl.jar ++ COMMAND ${CMAKE_COMMAND} -E create_symlink /usr/share/java/jackson/jackson-mrbean.jar common/lib/jackson-mrbean.jar ++ COMMAND ${CMAKE_COMMAND} -E create_symlink /usr/share/java/jackson/jackson-smile.jar common/lib/jackson-smile.jar ++ COMMAND ${CMAKE_COMMAND} -E create_symlink /usr/share/java/jackson/jackson-xc.jar common/lib/jackson-xc.jar ++ COMMAND ${CMAKE_COMMAND} -E create_symlink /usr/share/java/javassist.jar common/lib/javassist.jar ++ COMMAND ${CMAKE_COMMAND} -E create_symlink /usr/lib/java/jss4.jar common/lib/jss4.jar ++ COMMAND ${CMAKE_COMMAND} -E create_symlink /usr/share/java/ldapjdk.jar common/lib/ldapjdk.jar ++ COMMAND ${CMAKE_COMMAND} -E create_symlink /usr/lib/java/nuxwdog.jar common/lib/nuxwdog.jar ++ COMMAND ${CMAKE_COMMAND} -E create_symlink /usr/share/java/pki/pki-tomcat.jar common/lib/pki-tomcat.jar ++ COMMAND ${CMAKE_COMMAND} -E create_symlink ${RESTEASY_LIB}/resteasy-atom-provider.jar common/lib/resteasy-atom-provider.jar ++ COMMAND ${CMAKE_COMMAND} -E create_symlink ${RESTEASY_LIB}/resteasy-client.jar common/lib/resteasy-client.jar ++ COMMAND ${CMAKE_COMMAND} -E create_symlink ${RESTEASY_LIB}/resteasy-jackson-provider.jar common/lib/resteasy-jackson-provider.jar ++ COMMAND ${CMAKE_COMMAND} -E create_symlink ${RESTEASY_LIB}/resteasy-jaxb-provider.jar common/lib/resteasy-jaxb-provider.jar ++ COMMAND ${CMAKE_COMMAND} -E create_symlink ${RESTEASY_LIB}/jaxrs-api.jar common/lib/resteasy-jaxrs-api.jar ++ COMMAND ${CMAKE_COMMAND} -E create_symlink ${RESTEASY_LIB}/resteasy-jaxrs.jar common/lib/resteasy-jaxrs.jar ++ COMMAND ${CMAKE_COMMAND} -E create_symlink /usr/share/java/scannotation.jar common/lib/scannotation.jar ++ COMMAND ${CMAKE_COMMAND} -E create_symlink /usr/lib/java/symkey.jar common/lib/symkey.jar ++ COMMAND ${CMAKE_COMMAND} -E create_symlink /usr/share/java/tomcatjss.jar common/lib/tomcatjss.jar ++ COMMAND ${CMAKE_COMMAND} -E create_symlink /usr/share/java/velocity.jar common/lib/velocity.jar ++ COMMAND ${CMAKE_COMMAND} -E create_symlink /usr/share/java/xerces-j2.jar common/lib/xerces-j2.jar ++ COMMAND ${CMAKE_COMMAND} -E create_symlink /usr/share/java/xml-commons-apis.jar common/lib/xml-commons-apis.jar ++ COMMAND ${CMAKE_COMMAND} -E create_symlink /usr/share/java/xml-commons-resolver.jar common/lib/xml-commons-resolver.jar ++) ++ ++install( ++ DIRECTORY ++ ${CMAKE_CURRENT_BINARY_DIR}/common/lib/ ++ DESTINATION ++ ${DATA_INSTALL_DIR}/server/common/lib ++) ++ + install( + DIRECTORY + man/ +diff --git a/base/server/etc/default.cfg b/base/server/etc/default.cfg +index edd2632..4919cb4 100644 +--- a/base/server/etc/default.cfg ++++ b/base/server/etc/default.cfg +@@ -268,88 +268,6 @@ pki_tomcat_subsystem_webapps_path=%(pki_subsystem_path)s/webapps + pki_tomcat_webapps_subsystem_path=%(pki_tomcat_subsystem_webapps_path)s/%(pki_subsystem_type)s + pki_tomcat_webapps_subsystem_webinf_classes_path=%(pki_tomcat_webapps_subsystem_path)s/WEB-INF/classes + pki_tomcat_webapps_subsystem_webinf_lib_path=%(pki_tomcat_webapps_subsystem_path)s/WEB-INF/lib +-pki_certsrv_jar_link=%(pki_tomcat_webapps_subsystem_webinf_lib_path)s/pki-certsrv.jar +-pki_cmsbundle_jar_link=%(pki_tomcat_webapps_subsystem_webinf_lib_path)s/pki-cmsbundle.jar +-pki_cmscore_jar_link=%(pki_tomcat_webapps_subsystem_webinf_lib_path)s/pki-cmscore.jar +-pki_cms_jar_link=%(pki_tomcat_webapps_subsystem_webinf_lib_path)s/pki-cms.jar +-pki_cmsutil_jar_link=%(pki_tomcat_webapps_subsystem_webinf_lib_path)s/pki-cmsutil.jar +-pki_nsutil_jar_link=%(pki_tomcat_webapps_subsystem_webinf_lib_path)s/pki-nsutil.jar +- +- +-# JAR paths +-# These are used in the processing of pkispawn and are not supposed +-# to be overwritten by user configuration files +-pki_jss_jar=%(jni_jar_dir)s/jss4.jar +-pki_symkey_jar=%(jni_jar_dir)s/symkey.jar +-pki_apache_commons_collections_jar=/usr/share/java/apache-commons-collections.jar +-pki_apache_commons_io_jar=/usr/share/java/apache-commons-io.jar +-pki_apache_commons_lang_jar=/usr/share/java/apache-commons-lang.jar +-pki_apache_commons_logging_jar=/usr/share/java/apache-commons-logging.jar +-pki_commons_codec_jar=/usr/share/java/commons-codec.jar +-pki_httpclient_jar=/usr/share/java/httpcomponents/httpclient.jar +-pki_httpcore_jar=/usr/share/java/httpcomponents/httpcore.jar +-pki_javassist_jar=/usr/share/java/javassist.jar +-pki_ldapjdk_jar=/usr/share/java/ldapjdk.jar +-pki_certsrv_jar=/usr/share/java/pki/pki-certsrv.jar +-pki_cmsbundle=/usr/share/java/pki/pki-cmsbundle.jar +-pki_cmscore=/usr/share/java/pki/pki-cmscore.jar +-pki_cms=/usr/share/java/pki/pki-cms.jar +-pki_cmsutil=/usr/share/java/pki/pki-cmsutil.jar +-pki_nsutil=/usr/share/java/pki/pki-nsutil.jar +-pki_tomcat_jar=/usr/share/java/pki/pki-tomcat.jar +-pki_scannotation_jar=/usr/share/java/scannotation.jar +-pki_tomcatjss_jar=/usr/share/java/tomcatjss.jar +-pki_velocity_jar=/usr/share/java/velocity.jar +-pki_xerces_j2_jar=/usr/share/java/xerces-j2.jar +-pki_xml_commons_apis_jar=/usr/share/java/xml-commons-apis.jar +-pki_xml_commons_resolver_jar=/usr/share/java/xml-commons-resolver.jar +-pki_jss_jar_link=%(pki_tomcat_common_lib_path)s/jss4.jar +-pki_symkey_jar_link=%(pki_tomcat_common_lib_path)s/symkey.jar +-pki_apache_commons_collections_jar_link=%(pki_tomcat_common_lib_path)s/apache-commons-collections.jar +-pki_apache_commons_io_jar_link=%(pki_tomcat_common_lib_path)s/apache-commons-io.jar +-pki_apache_commons_lang_jar_link=%(pki_tomcat_common_lib_path)s/apache-commons-lang.jar +-pki_apache_commons_logging_jar_link=%(pki_tomcat_common_lib_path)s/apache-commons-logging.jar +-pki_commons_codec_jar_link=%(pki_tomcat_common_lib_path)s/apache-commons-codec.jar +-pki_httpclient_jar_link=%(pki_tomcat_common_lib_path)s/httpclient.jar +-pki_httpcore_jar_link=%(pki_tomcat_common_lib_path)s/httpcore.jar +-pki_javassist_jar_link=%(pki_tomcat_common_lib_path)s/javassist.jar +-pki_ldapjdk_jar_link=%(pki_tomcat_common_lib_path)s/ldapjdk.jar +-pki_tomcat_jar_link=%(pki_tomcat_common_lib_path)s/pki-tomcat.jar +-pki_scannotation_jar_link=%(pki_tomcat_common_lib_path)s/scannotation.jar +-pki_tomcatjss_jar_link=%(pki_tomcat_common_lib_path)s/tomcatjss.jar +-pki_velocity_jar_link=%(pki_tomcat_common_lib_path)s/velocity.jar +-pki_xerces_j2_jar_link=%(pki_tomcat_common_lib_path)s/xerces-j2.jar +-pki_xml_commons_apis_jar_link=%(pki_tomcat_common_lib_path)s/xml-commons-apis.jar +-pki_xml_commons_resolver_jar_link=%(pki_tomcat_common_lib_path)s/xml-commons-resolver.jar +-pki_ca_jar=/usr/share/java/pki/pki-ca.jar +-pki_ca_jar_link=%(pki_tomcat_webapps_subsystem_webinf_lib_path)s/pki-ca.jar +-pki_kra_jar=/usr/share/java/pki/pki-kra.jar +-pki_kra_jar_link=%(pki_tomcat_webapps_subsystem_webinf_lib_path)s/pki-kra.jar +-pki_ocsp_jar=/usr/share/java/pki/pki-ocsp.jar +-pki_ocsp_jar_link=%(pki_tomcat_webapps_subsystem_webinf_lib_path)s/pki-ocsp.jar +-pki_tks_jar=/usr/share/java/pki/pki-tks.jar +-pki_tks_jar_link=%(pki_tomcat_webapps_subsystem_webinf_lib_path)s/pki-tks.jar +-pki_tps_jar=/usr/share/java/pki/pki-tps.jar +-pki_tps_jar_link=%(pki_tomcat_webapps_subsystem_webinf_lib_path)s/pki-tps.jar +- +-# Jackson +-pki_jackson_core_asl_jar=/usr/share/java/jackson/jackson-core-asl.jar +-pki_jackson_jaxrs_jar=/usr/share/java/jackson/jackson-jaxrs.jar +-pki_jackson_mapper_asl_jar=/usr/share/java/jackson/jackson-mapper-asl.jar +-pki_jackson_mrbean_jar=/usr/share/java/jackson/jackson-mrbean.jar +-pki_jackson_smile_jar=/usr/share/java/jackson/jackson-smile.jar +-pki_jackson_xc_jar=/usr/share/java/jackson/jackson-xc.jar +- +-# RESTEasy +-pki_resteasy_atom_provider_jar=%(resteasy_lib)s/resteasy-atom-provider.jar +-pki_resteasy_client_jar=%(resteasy_lib)s/resteasy-client.jar +-pki_resteasy_jaxb_provider_jar=%(resteasy_lib)s/resteasy-jaxb-provider.jar +-pki_resteasy_jaxrs_api_jar=%(resteasy_lib)s/jaxrs-api.jar +-pki_resteasy_jaxrs_jar=%(resteasy_lib)s/resteasy-jaxrs.jar +-pki_resteasy_jackson_provider_jar=%(resteasy_lib)s/resteasy-jackson-provider.jar +- +-# nuxwdog +-pki_nuxwdog_client_jar=/usr/lib/java/nuxwdog.jar + + + ############################################################################### +diff --git a/base/server/python/pki/server/deployment/scriptlets/instance_layout.py b/base/server/python/pki/server/deployment/scriptlets/instance_layout.py +index 57f8537..c470c7f 100644 +--- a/base/server/python/pki/server/deployment/scriptlets/instance_layout.py ++++ b/base/server/python/pki/server/deployment/scriptlets/instance_layout.py +@@ -122,11 +122,7 @@ class PkiScriptlet(pkiscriptlet.AbstractBasePkiScriptlet): + "localhost", + "pki#js.xml")) + +- # establish Tomcat instance base +- deployer.directory.create(deployer.mdict['pki_tomcat_common_path']) +- deployer.directory.create( +- deployer.mdict['pki_tomcat_common_lib_path']) +- # establish Tomcat instance library ++ # Create Tomcat instance library + deployer.directory.create(deployer.mdict['pki_instance_lib']) + for name in os.listdir(deployer.mdict['pki_tomcat_lib_path']): + deployer.symlink.create( +@@ -139,6 +135,12 @@ class PkiScriptlet(pkiscriptlet.AbstractBasePkiScriptlet): + deployer.symlink.create( + deployer.mdict['pki_instance_conf_log4j_properties'], + deployer.mdict['pki_instance_lib_log4j_properties']) ++ ++ # Link /var/lib/pki//common to /usr/share/pki/server/common ++ deployer.symlink.create( ++ '/usr/share/pki/server/common', ++ deployer.mdict['pki_tomcat_common_path']) ++ + deployer.directory.create(deployer.mdict['pki_tomcat_tmpdir_path']) + + deployer.directory.create(deployer.mdict['pki_tomcat_work_path']) +@@ -160,129 +162,6 @@ class PkiScriptlet(pkiscriptlet.AbstractBasePkiScriptlet): + deployer.mdict['pki_tomcat_systemd'], + deployer.mdict['pki_instance_systemd_link'], + uid=0, gid=0) +- # establish Tomcat instance common lib jar symbolic links +- deployer.symlink.create( +- deployer.mdict['pki_apache_commons_collections_jar'], +- deployer.mdict['pki_apache_commons_collections_jar_link']) +- deployer.symlink.create( +- deployer.mdict['pki_apache_commons_io_jar'], +- deployer.mdict['pki_apache_commons_io_jar_link']) +- deployer.symlink.create( +- deployer.mdict['pki_apache_commons_lang_jar'], +- deployer.mdict['pki_apache_commons_lang_jar_link']) +- deployer.symlink.create( +- deployer.mdict['pki_apache_commons_logging_jar'], +- deployer.mdict['pki_apache_commons_logging_jar_link']) +- deployer.symlink.create( +- deployer.mdict['pki_commons_codec_jar'], +- deployer.mdict['pki_commons_codec_jar_link']) +- deployer.symlink.create( +- deployer.mdict['pki_httpclient_jar'], +- deployer.mdict['pki_httpclient_jar_link']) +- deployer.symlink.create( +- deployer.mdict['pki_httpcore_jar'], +- deployer.mdict['pki_httpcore_jar_link']) +- deployer.symlink.create( +- deployer.mdict['pki_javassist_jar'], +- deployer.mdict['pki_javassist_jar_link']) +- deployer.symlink.create( +- deployer.mdict['pki_jss_jar'], +- deployer.mdict['pki_jss_jar_link']) +- deployer.symlink.create( +- deployer.mdict['pki_ldapjdk_jar'], +- deployer.mdict['pki_ldapjdk_jar_link']) +- deployer.symlink.create( +- deployer.mdict['pki_tomcat_jar'], +- deployer.mdict['pki_tomcat_jar_link']) +- deployer.symlink.create( +- deployer.mdict['pki_scannotation_jar'], +- deployer.mdict['pki_scannotation_jar_link']) +- deployer.symlink.create( +- deployer.mdict['pki_tomcatjss_jar'], +- deployer.mdict['pki_tomcatjss_jar_link']) +- deployer.symlink.create( +- deployer.mdict['pki_velocity_jar'], +- deployer.mdict['pki_velocity_jar_link']) +- deployer.symlink.create( +- deployer.mdict['pki_xerces_j2_jar'], +- deployer.mdict['pki_xerces_j2_jar_link']) +- deployer.symlink.create( +- deployer.mdict['pki_xml_commons_apis_jar'], +- deployer.mdict['pki_xml_commons_apis_jar_link']) +- deployer.symlink.create( +- deployer.mdict['pki_xml_commons_resolver_jar'], +- deployer.mdict['pki_xml_commons_resolver_jar_link']) +- +- # Jackson +- deployer.symlink.create( +- deployer.mdict['pki_jackson_core_asl_jar'], +- os.path.join( +- deployer.mdict['pki_tomcat_common_lib_path'], +- 'jackson-core-asl.jar')) +- deployer.symlink.create( +- deployer.mdict['pki_jackson_jaxrs_jar'], +- os.path.join( +- deployer.mdict['pki_tomcat_common_lib_path'], +- 'jackson-jaxrs.jar')) +- deployer.symlink.create( +- deployer.mdict['pki_jackson_mapper_asl_jar'], +- os.path.join( +- deployer.mdict['pki_tomcat_common_lib_path'], +- 'jackson-mapper-asl.jar')) +- deployer.symlink.create( +- deployer.mdict['pki_jackson_mrbean_jar'], +- os.path.join( +- deployer.mdict['pki_tomcat_common_lib_path'], +- 'jackson-mrbean.jar')) +- deployer.symlink.create( +- deployer.mdict['pki_jackson_smile_jar'], +- os.path.join( +- deployer.mdict['pki_tomcat_common_lib_path'], +- 'jackson-smile.jar')) +- deployer.symlink.create( +- deployer.mdict['pki_jackson_xc_jar'], +- os.path.join( +- deployer.mdict['pki_tomcat_common_lib_path'], +- 'jackson-xc.jar')) +- +- # RESTEasy +- deployer.symlink.create( +- deployer.mdict['pki_resteasy_atom_provider_jar'], +- os.path.join( +- deployer.mdict['pki_tomcat_common_lib_path'], +- 'resteasy-atom-provider.jar')) +- deployer.symlink.create( +- deployer.mdict['pki_resteasy_client_jar'], +- os.path.join( +- deployer.mdict['pki_tomcat_common_lib_path'], +- 'resteasy-client.jar')) +- deployer.symlink.create( +- deployer.mdict['pki_resteasy_jaxb_provider_jar'], +- os.path.join( +- deployer.mdict['pki_tomcat_common_lib_path'], +- 'resteasy-jaxb-provider.jar')) +- deployer.symlink.create( +- deployer.mdict['pki_resteasy_jaxrs_api_jar'], +- os.path.join( +- deployer.mdict['pki_tomcat_common_lib_path'], +- 'jaxrs-api.jar')) +- deployer.symlink.create( +- deployer.mdict['pki_resteasy_jaxrs_jar'], +- os.path.join( +- deployer.mdict['pki_tomcat_common_lib_path'], +- 'resteasy-jaxrs.jar')) +- deployer.symlink.create( +- deployer.mdict['pki_resteasy_jackson_provider_jar'], +- os.path.join( +- deployer.mdict['pki_tomcat_common_lib_path'], +- 'resteasy-jackson-provider.jar')) +- +- # nuxwdog +- deployer.symlink.create( +- deployer.mdict['pki_nuxwdog_client_jar'], +- os.path.join( +- deployer.mdict['pki_tomcat_common_lib_path'], +- 'nuxwdog.jar')) + + # establish shared NSS security databases for this instance + deployer.directory.create(deployer.mdict['pki_database_path']) +@@ -297,14 +176,6 @@ class PkiScriptlet(pkiscriptlet.AbstractBasePkiScriptlet): + deployer.mdict['pki_instance_log_path'], + deployer.mdict['pki_instance_logs_link']) + +- # create the sym link to symkey regardless of subsystem +- # as long as pki-symkey is installed on the system +- if os.path.exists(deployer.mdict['pki_symkey_jar']): +- if not os.path.exists(deployer.mdict['pki_symkey_jar_link']): +- deployer.symlink.create( +- deployer.mdict['pki_symkey_jar'], +- deployer.mdict['pki_symkey_jar_link']) +- + # create Tomcat instance systemd service link + deployer.symlink.create(deployer.mdict['pki_systemd_service'], + deployer.mdict['pki_systemd_service_link']) +diff --git a/base/server/scripts/operations b/base/server/scripts/operations +index 5991670..5b50178 100644 +--- a/base/server/scripts/operations ++++ b/base/server/scripts/operations +@@ -909,7 +909,6 @@ verify_symlinks() + declare -A ocsp_symlinks + declare -A tks_symlinks + declare -A tps_symlinks +- declare -A common_jar_symlinks + declare -A ca_jar_symlinks + declare -A kra_jar_symlinks + declare -A ocsp_jar_symlinks +@@ -985,75 +984,6 @@ verify_symlinks() + [logs]=/var/log/pki/${PKI_INSTANCE_NAME}/tps + [registry]=${pki_registry_dir}) + +- # '${pki_common_jar_dir}' symlinks +- if ! $debian; then +- common_jar_symlinks=( +- [apache-commons-codec.jar]=${java_dir}/commons-codec.jar +- [apache-commons-collections.jar]=${java_dir}/apache-commons-collections.jar +- [apache-commons-io.jar]=${java_dir}/apache-commons-io.jar +- [apache-commons-lang.jar]=${java_dir}/apache-commons-lang.jar +- [apache-commons-logging.jar]=${java_dir}/apache-commons-logging.jar +- [httpclient.jar]=${java_dir}/httpcomponents/httpclient.jar +- [httpcore.jar]=${java_dir}/httpcomponents/httpcore.jar +- [javassist.jar]=${java_dir}/javassist.jar +- [jaxrs-api.jar]=${RESTEASY_LIB}/jaxrs-api.jar +- [jackson-core-asl.jar]=${java_dir}/jackson/jackson-core-asl.jar +- [jackson-jaxrs.jar]=${java_dir}/jackson/jackson-jaxrs.jar +- [jackson-mapper-asl.jar]=${java_dir}/jackson/jackson-mapper-asl.jar +- [jackson-mrbean.jar]=${java_dir}/jackson/jackson-mrbean.jar +- [jackson-smile.jar]=${java_dir}/jackson/jackson-smile.jar +- [jackson-xc.jar]=${java_dir}/jackson/jackson-xc.jar +- [jss4.jar]=${jni_jar_dir}/jss4.jar +- [ldapjdk.jar]=${java_dir}/ldapjdk.jar +- [pki-tomcat.jar]=${java_dir}/pki/pki-tomcat.jar +- [resteasy-atom-provider.jar]=${RESTEASY_LIB}/resteasy-atom-provider.jar +- [resteasy-client.jar]=${RESTEASY_LIB}/resteasy-client.jar +- [resteasy-jaxb-provider.jar]=${RESTEASY_LIB}/resteasy-jaxb-provider.jar +- [resteasy-jaxrs.jar]=${RESTEASY_LIB}/resteasy-jaxrs.jar +- [resteasy-jackson-provider.jar]=${RESTEASY_LIB}/resteasy-jackson-provider.jar +- [scannotation.jar]=${java_dir}/scannotation.jar +- [tomcatjss.jar]=${java_dir}/tomcatjss.jar +- [velocity.jar]=${java_dir}/velocity.jar +- [xerces-j2.jar]=${java_dir}/xerces-j2.jar +- [xml-commons-apis.jar]=${java_dir}/xml-commons-apis.jar +- [xml-commons-resolver.jar]=${java_dir}/xml-commons-resolver.jar) +- else +- common_jar_symlinks=( +- [apache-commons-codec.jar]=${java_dir}/commons-codec.jar +- [apache-commons-collections.jar]=${java_dir}/commons-collections3.jar +- [apache-commons-io.jar]=${java_dir}/commons-io.jar +- [apache-commons-lang.jar]=${java_dir}/commons-lang.jar +- [apache-commons-logging.jar]=${java_dir}/commons-logging.jar +- [httpclient.jar]=${java_dir}/httpclient.jar +- [httpcore.jar]=${java_dir}/httpcore.jar +- [javassist.jar]=${java_dir}/javassist.jar +- [jaxrs-api.jar]=${RESTEASY_LIB}/jaxrs-api.jar +- [jackson-core-asl.jar]=${java_dir}/jackson-core-asl.jar +- [jackson-jaxrs.jar]=${java_dir}/jackson-jaxrs.jar +- [jackson-mapper-asl.jar]=${java_dir}/jackson-mapper-asl.jar +- [jackson-mrbean.jar]=${java_dir}/jackson-mrbean.jar +- [jackson-smile.jar]=${java_dir}/jackson-smile.jar +- [jackson-xc.jar]=${java_dir}/jackson-xc.jar +- [jss4.jar]=${jni_jar_dir}/jss4.jar +- [ldapjdk.jar]=${java_dir}/ldapjdk.jar +- [pki-tomcat.jar]=${java_dir}/pki/pki-tomcat.jar +- [resteasy-atom-provider.jar]=${RESTEASY_LIB}/resteasy-atom-provider.jar +- [resteasy-client.jar]=${RESTEASY_LIB}/resteasy-client.jar +- [resteasy-jaxb-provider.jar]=${RESTEASY_LIB}/resteasy-jaxb-provider.jar +- [resteasy-jaxrs.jar]=${RESTEASY_LIB}/resteasy-jaxrs.jar +- [resteasy-jackson-provider.jar]=${RESTEASY_LIB}/resteasy-jackson-provider.jar +- [scannotation.jar]=${java_dir}/scannotation.jar +- [tomcatjss.jar]=${java_dir}/tomcatjss.jar +- [velocity.jar]=${java_dir}/velocity.jar +- [xerces-j2.jar]=${java_dir}/xercesImpl.jar +- [xml-commons-apis.jar]=${java_dir}/xml-apis.jar +- [xml-commons-resolver.jar]=${java_dir}/xml-resolver.jar) +- fi +- +- if [ -e ${PKI_INSTANCE_PATH}/tks ]; then +- common_jar_symlinks[symkey.jar]=${jni_jar_dir}/symkey.jar +- fi +- + # '${pki_systemd_dir}' symlinks + systemd_symlinks[${pki_systemd_link}]=${systemd_dir}/${pki_systemd_service} + +@@ -1132,15 +1062,6 @@ verify_symlinks() + fi + fi + +- # Detect and correct 'common_jar_symlinks' +- common_jar_symlinks_string=$(declare -p common_jar_symlinks) +- eval "declare -A symlinks=${common_jar_symlinks_string#*=}" +- check_symlinks ${pki_common_jar_dir} ${PKI_USER} ${PKI_GROUP} +- rv=$? +- if [ $rv -ne 0 ]; then +- return $rv +- fi +- + # Detect and correct 'systemd_symlinks' + systemd_symlinks_string=$(declare -p systemd_symlinks) + eval "declare -A symlinks=${systemd_symlinks_string#*=}" +-- +1.8.3.1 + + +From 0c502a387c90d2e2d8ebe9e3edf3dfeaf1d6eba4 Mon Sep 17 00:00:00 2001 +From: Jack Magne +Date: Wed, 27 Jul 2016 11:43:33 -0700 +Subject: [PATCH 66/96] Make starting CRL Number configurable. + +Ticket #2406 Make starting CRL Number configurable + +This simple patch provides a pkispawn config param that passes +some starting crl number value to the config process. + +Here is a sample: + +[CA] +pki_ca_starting_crl_number=4000 + +After the CA comes up the value of "crlNumber" in the db will +reflect that value of 4000. + +Currently no other values are changed. We can talk about if we +need more values reset in the given case. + +Also, this creates a setting in the CS.cfg + +ca.crl.MasterCrl.startingCrlNumber=4000 + +This setting is only consulted when the crl Issuing Point record is created +for the first time. +--- + base/ca/src/com/netscape/ca/CRLIssuingPoint.java | 65 +++++++++++++++------- + .../server/ca/rest/CAInstallerService.java | 7 +++ + .../certsrv/system/ConfigurationRequest.java | 12 ++++ + base/server/etc/default.cfg | 1 + + .../python/pki/server/deployment/pkihelper.py | 4 ++ + 5 files changed, 69 insertions(+), 20 deletions(-) + +diff --git a/base/ca/src/com/netscape/ca/CRLIssuingPoint.java b/base/ca/src/com/netscape/ca/CRLIssuingPoint.java +index fc9e6a3..a593eb8 100644 +--- a/base/ca/src/com/netscape/ca/CRLIssuingPoint.java ++++ b/base/ca/src/com/netscape/ca/CRLIssuingPoint.java +@@ -31,6 +31,23 @@ import java.util.StringTokenizer; + import java.util.TimeZone; + import java.util.Vector; + ++import netscape.security.util.BitArray; ++import netscape.security.x509.AlgorithmId; ++import netscape.security.x509.CRLExtensions; ++import netscape.security.x509.CRLNumberExtension; ++import netscape.security.x509.CRLReasonExtension; ++import netscape.security.x509.DeltaCRLIndicatorExtension; ++import netscape.security.x509.Extension; ++import netscape.security.x509.FreshestCRLExtension; ++import netscape.security.x509.IssuingDistributionPoint; ++import netscape.security.x509.IssuingDistributionPointExtension; ++import netscape.security.x509.RevocationReason; ++import netscape.security.x509.RevokedCertImpl; ++import netscape.security.x509.RevokedCertificate; ++import netscape.security.x509.X509CRLImpl; ++import netscape.security.x509.X509CertImpl; ++import netscape.security.x509.X509ExtensionException; ++ + import com.netscape.certsrv.apps.CMS; + import com.netscape.certsrv.base.EBaseException; + import com.netscape.certsrv.base.IConfigStore; +@@ -66,23 +83,6 @@ import com.netscape.cmscore.dbs.CertRecord; + import com.netscape.cmscore.dbs.CertificateRepository; + import com.netscape.cmscore.util.Debug; + +-import netscape.security.util.BitArray; +-import netscape.security.x509.AlgorithmId; +-import netscape.security.x509.CRLExtensions; +-import netscape.security.x509.CRLNumberExtension; +-import netscape.security.x509.CRLReasonExtension; +-import netscape.security.x509.DeltaCRLIndicatorExtension; +-import netscape.security.x509.Extension; +-import netscape.security.x509.FreshestCRLExtension; +-import netscape.security.x509.IssuingDistributionPoint; +-import netscape.security.x509.IssuingDistributionPointExtension; +-import netscape.security.x509.RevocationReason; +-import netscape.security.x509.RevokedCertImpl; +-import netscape.security.x509.RevokedCertificate; +-import netscape.security.x509.X509CRLImpl; +-import netscape.security.x509.X509CertImpl; +-import netscape.security.x509.X509ExtensionException; +- + /** + * This class encapsulates CRL issuing mechanism. CertificateAuthority + * contains a map of CRLIssuingPoint indexed by string ids. Each issuing +@@ -112,6 +112,8 @@ public class CRLIssuingPoint implements ICRLIssuingPoint, Runnable { + + private static final int CRL_PAGE_SIZE = 10000; + ++ private static final String PROP_CRL_STARTING_NUMBER = "startingCrlNumber"; ++ + /* configuration file property names */ + + public IPublisherProcessor mPublisherProcessor = null; +@@ -923,13 +925,36 @@ public class CRLIssuingPoint implements ICRLIssuingPoint, Runnable { + if (crlRecord == null) { + // no crl was ever created, or crl in db is corrupted. + // create new one. ++ ++ IConfigStore ipStore = mCA.getConfigStore().getSubStore(ICertificateAuthority.PROP_CRL_SUBSTORE).getSubStore(mId); + try { +- crlRecord = new CRLIssuingPointRecord(mId, BigInteger.ZERO, Long.valueOf(-1), ++ ++ BigInteger startingCrlNumberBig = ipStore.getBigInteger(PROP_CRL_STARTING_NUMBER, BigInteger.ZERO); ++ CMS.debug("startingCrlNumber: " + startingCrlNumberBig); ++ ++ // Check for bogus negative value ++ ++ if(startingCrlNumberBig.compareTo(BigInteger.ZERO) < 0) { ++ //Make it the default of ZERO ++ startingCrlNumberBig = BigInteger.ZERO; ++ } ++ ++ crlRecord = new CRLIssuingPointRecord(mId, startingCrlNumberBig, Long.valueOf(-1), + null, null, BigInteger.ZERO, Long.valueOf(-1), + mRevokedCerts, mUnrevokedCerts, mExpiredCerts); + mCRLRepository.addCRLIssuingPointRecord(crlRecord); +- mCRLNumber = BigInteger.ZERO; //BIG_ZERO; +- mNextCRLNumber = BigInteger.ONE; //BIG_ONE; ++ mCRLNumber = startingCrlNumberBig; ++ ++ // The default case calls for ZERO being the starting point where ++ // it is then incremented by one to ONE ++ // If we specificy an explicit starting point, ++ // We want that exact number to be the next CRL Number. ++ if(mCRLNumber.compareTo(BigInteger.ZERO) == 0) { ++ mNextCRLNumber = BigInteger.ONE; ++ } else { ++ mNextCRLNumber = mCRLNumber; ++ } ++ + mLastCRLNumber = mCRLNumber; + mDeltaCRLNumber = mCRLNumber; + mNextDeltaCRLNumber = mNextCRLNumber; +diff --git a/base/ca/src/org/dogtagpki/server/ca/rest/CAInstallerService.java b/base/ca/src/org/dogtagpki/server/ca/rest/CAInstallerService.java +index e1b7160..3c7e483 100644 +--- a/base/ca/src/org/dogtagpki/server/ca/rest/CAInstallerService.java ++++ b/base/ca/src/org/dogtagpki/server/ca/rest/CAInstallerService.java +@@ -80,6 +80,8 @@ public class CAInstallerService extends SystemConfigService { + disableCRLCachingAndGenerationForClone(request); + } + ++ configureStartingCRLNumber(request); ++ + } catch (Exception e) { + CMS.debug(e); + throw new PKIException("Errors in determining if security domain host is a master CA"); +@@ -187,6 +189,11 @@ public class CAInstallerService extends SystemConfigService { + configStore.commit(false /* no backup */); + } + ++ private void configureStartingCRLNumber(ConfigurationRequest data) { ++ CMS.debug("CAInstallerService:configureStartingCRLNumber entering."); ++ cs.putString("ca.crl.MasterCRL.startingCrlNumber",data.getStartingCRLNumber() ); ++ ++ } + private void disableCRLCachingAndGenerationForClone(ConfigurationRequest data) throws MalformedURLException { + + CMS.debug("CAInstallerService:disableCRLCachingAndGenerationForClone entering."); +diff --git a/base/common/src/com/netscape/certsrv/system/ConfigurationRequest.java b/base/common/src/com/netscape/certsrv/system/ConfigurationRequest.java +index 890f7d0..cd9d3c8 100644 +--- a/base/common/src/com/netscape/certsrv/system/ConfigurationRequest.java ++++ b/base/common/src/com/netscape/certsrv/system/ConfigurationRequest.java +@@ -234,6 +234,9 @@ public class ConfigurationRequest { + @XmlElement + protected String sharedDBUserDN; + ++ @XmlElement ++ protected String startingCRLNumber; ++ + public ConfigurationRequest() { + // required for JAXB + } +@@ -932,6 +935,14 @@ public class ConfigurationRequest { + this.subordinateSecurityDomainName = subordinateSecurityDomainName; + } + ++ public String getStartingCRLNumber() { ++ return startingCRLNumber; ++ } ++ ++ public void setStartingCRLNumber(String startingCRLNumber) { ++ this.startingCRLNumber = startingCRLNumber; ++ } ++ + @Override + public String toString() { + return "ConfigurationRequest [pin=XXXX" + +@@ -995,6 +1006,7 @@ public class ConfigurationRequest { + ", setupReplication=" + setupReplication + + ", subordinateSecurityDomainName=" + subordinateSecurityDomainName + + ", reindexData=" + reindexData + ++ ", startingCrlNumber=" + startingCRLNumber + + "]"; + } + +diff --git a/base/server/etc/default.cfg b/base/server/etc/default.cfg +index 4919cb4..3a7e005 100644 +--- a/base/server/etc/default.cfg ++++ b/base/server/etc/default.cfg +@@ -296,6 +296,7 @@ pki_ca_signing_subject_dn=cn=CA Signing Certificate,o=%(pki_security_domain_name + pki_ca_signing_token=Internal Key Storage Token + pki_ca_signing_csr_path= + pki_ca_signing_cert_path= ++pki_ca_starting_crl_number=0 + pki_external=False + pki_req_ext_add=False + # MS subca request ext data +diff --git a/base/server/python/pki/server/deployment/pkihelper.py b/base/server/python/pki/server/deployment/pkihelper.py +index 6ac68b1..8a1dbdd 100644 +--- a/base/server/python/pki/server/deployment/pkihelper.py ++++ b/base/server/python/pki/server/deployment/pkihelper.py +@@ -4113,6 +4113,10 @@ class ConfigClient: + if self.subsystem == "TPS": + self.set_tps_parameters(data) + ++ # Misc CA parameters ++ if self.subsystem == "CA": ++ data.startingCRLNumber = self.mdict['pki_ca_starting_crl_number'] ++ + return data + + def save_admin_csr(self): +-- +1.8.3.1 + + +From f990cb0dee46df211c2c7212ca0165465b5f3531 Mon Sep 17 00:00:00 2001 +From: "Endi S. Dewata" +Date: Sun, 24 Jul 2016 07:36:36 +0200 +Subject: [PATCH 67/96] Added upgrade scripts to fix server library. + +An upgrade script has been added to replace the /common +in existing instances with a link to /usr/share/pki/server/common +which contains links to server dependencies. + +https://fedorahosted.org/pki/ticket/2403 +--- + base/common/upgrade/10.3.4/.gitignore | 4 +++ + base/common/upgrade/10.3.5/.gitignore | 4 +++ + base/server/upgrade/10.3.4/.gitignore | 4 +++ + base/server/upgrade/10.3.5/01-FixServerLibrary | 46 ++++++++++++++++++++++++++ + 4 files changed, 58 insertions(+) + create mode 100644 base/common/upgrade/10.3.4/.gitignore + create mode 100644 base/common/upgrade/10.3.5/.gitignore + create mode 100644 base/server/upgrade/10.3.4/.gitignore + create mode 100644 base/server/upgrade/10.3.5/01-FixServerLibrary + +diff --git a/base/common/upgrade/10.3.4/.gitignore b/base/common/upgrade/10.3.4/.gitignore +new file mode 100644 +index 0000000..5e7d273 +--- /dev/null ++++ b/base/common/upgrade/10.3.4/.gitignore +@@ -0,0 +1,4 @@ ++# Ignore everything in this directory ++* ++# Except this file ++!.gitignore +diff --git a/base/common/upgrade/10.3.5/.gitignore b/base/common/upgrade/10.3.5/.gitignore +new file mode 100644 +index 0000000..5e7d273 +--- /dev/null ++++ b/base/common/upgrade/10.3.5/.gitignore +@@ -0,0 +1,4 @@ ++# Ignore everything in this directory ++* ++# Except this file ++!.gitignore +diff --git a/base/server/upgrade/10.3.4/.gitignore b/base/server/upgrade/10.3.4/.gitignore +new file mode 100644 +index 0000000..5e7d273 +--- /dev/null ++++ b/base/server/upgrade/10.3.4/.gitignore +@@ -0,0 +1,4 @@ ++# Ignore everything in this directory ++* ++# Except this file ++!.gitignore +diff --git a/base/server/upgrade/10.3.5/01-FixServerLibrary b/base/server/upgrade/10.3.5/01-FixServerLibrary +new file mode 100644 +index 0000000..79d4965 +--- /dev/null ++++ b/base/server/upgrade/10.3.5/01-FixServerLibrary +@@ -0,0 +1,46 @@ ++#!/usr/bin/python ++# 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) 2016 Red Hat, Inc. ++# All rights reserved. ++ ++from __future__ import absolute_import ++import os.path ++import shutil ++import pki.server.upgrade ++ ++ ++class FixServerLibrary(pki.server.upgrade.PKIServerUpgradeScriptlet): ++ ++ def __init__(self): ++ super(FixServerLibrary, self).__init__() ++ self.message = 'Fix server library' ++ ++ def upgrade_instance(self, instance): ++ ++ common_dir = os.path.join(instance.base_dir, 'common') ++ ++ # if /common is already a link, skip ++ if os.path.islink(common_dir): ++ return ++ ++ # remove old /common ++ shutil.rmtree(common_dir) ++ ++ # link /common to /usr/share/pki/server/common ++ os.symlink('/usr/share/pki/server/common', common_dir) ++ os.lchown(common_dir, instance.uid, instance.gid) +-- +1.8.3.1 + + +From ba1e18ba4c9c47930efa0cdfc46fe326f71d3cd4 Mon Sep 17 00:00:00 2001 +From: "Endi S. Dewata" +Date: Wed, 27 Jul 2016 19:51:37 +0200 +Subject: [PATCH 68/96] Fixed SELinux contexts. + +The deployment tool has been modified to set up SELinux contexts +after all instance files have been created to ensure they have the +correct contexts. + +An upgrade script has been added to fix existing instances. + +https://fedorahosted.org/pki/ticket/2421 +--- + base/server/etc/default.cfg | 2 +- + base/server/python/pki/server/__init__.py | 7 ++++- + base/server/upgrade/10.3.5/02-FixSELinuxContexts | 36 ++++++++++++++++++++++++ + 3 files changed, 43 insertions(+), 2 deletions(-) + create mode 100644 base/server/upgrade/10.3.5/02-FixSELinuxContexts + +diff --git a/base/server/etc/default.cfg b/base/server/etc/default.cfg +index 3a7e005..24e4a43 100644 +--- a/base/server/etc/default.cfg ++++ b/base/server/etc/default.cfg +@@ -39,10 +39,10 @@ spawn_scriplets= + infrastructure_layout + instance_layout + subsystem_layout +- selinux_setup + webapp_deployment + slot_substitution + security_databases ++ selinux_setup + configuration + finalization + +diff --git a/base/server/python/pki/server/__init__.py b/base/server/python/pki/server/__init__.py +index 03bb225..13b3258 100644 +--- a/base/server/python/pki/server/__init__.py ++++ b/base/server/python/pki/server/__init__.py +@@ -39,7 +39,10 @@ import pki.nssdb + import pki.util + + INSTANCE_BASE_DIR = '/var/lib/pki' ++CONFIG_BASE_DIR = '/etc/pki' ++LOG_BASE_DIR = '/var/log/pki' + REGISTRY_DIR = '/etc/sysconfig/pki' ++ + SUBSYSTEM_TYPES = ['ca', 'kra', 'ocsp', 'tks', 'tps'] + SUBSYSTEM_CLASSES = {} + +@@ -476,7 +479,9 @@ class PKIInstance(object): + else: + self.base_dir = os.path.join(pki.BASE_DIR, name) + +- self.conf_dir = os.path.join(self.base_dir, 'conf') ++ self.conf_dir = os.path.join(CONFIG_BASE_DIR, name) ++ self.log_dir = os.path.join(LOG_BASE_DIR, name) ++ + self.password_conf = os.path.join(self.conf_dir, 'password.conf') + self.external_certs_conf = os.path.join( + self.conf_dir, 'external_certs.conf') +diff --git a/base/server/upgrade/10.3.5/02-FixSELinuxContexts b/base/server/upgrade/10.3.5/02-FixSELinuxContexts +new file mode 100644 +index 0000000..f3d981e +--- /dev/null ++++ b/base/server/upgrade/10.3.5/02-FixSELinuxContexts +@@ -0,0 +1,36 @@ ++#!/usr/bin/python ++# 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) 2016 Red Hat, Inc. ++# All rights reserved. ++ ++from __future__ import absolute_import ++import selinux ++import pki.server.upgrade ++ ++ ++class FixSELinuxContexts(pki.server.upgrade.PKIServerUpgradeScriptlet): ++ ++ def __init__(self): ++ super(FixSELinuxContexts, self).__init__() ++ self.message = 'Fix SELinux contexts' ++ ++ def upgrade_instance(self, instance): ++ ++ selinux.restorecon(instance.base_dir, True) ++ selinux.restorecon(instance.conf_dir, True) ++ selinux.restorecon(instance.log_dir, True) +-- +1.8.3.1 + + +From 0f6ddc442d2ac2c166126295dbce32f0c682e0fe Mon Sep 17 00:00:00 2001 +From: Ade Lee +Date: Thu, 28 Jul 2016 10:36:50 +0100 +Subject: [PATCH 70/96] Re-license the python client files to LGPLv3 + +--- + base/common/LICENSE.LESSER | 170 +++++++++++++++++++++++++++++++++ + base/common/python/pki/__init__.py | 13 +-- + base/common/python/pki/account.py | 13 +-- + base/common/python/pki/authority.py | 13 +-- + base/common/python/pki/cert.py | 13 +-- + base/common/python/pki/cli/__init__.py | 13 +-- + base/common/python/pki/cli/pkcs12.py | 13 +-- + base/common/python/pki/client.py | 13 +-- + base/common/python/pki/crypto.py | 13 +-- + base/common/python/pki/encoder.py | 17 ++++ + base/common/python/pki/feature.py | 13 +-- + base/common/python/pki/key.py | 13 +-- + base/common/python/pki/kra.py | 13 +-- + base/common/python/pki/nssdb.py | 13 +-- + base/common/python/pki/profile.py | 13 +-- + base/common/python/pki/system.py | 13 +-- + base/common/python/pki/systemcert.py | 13 +-- + base/common/python/pki/upgrade.py | 13 +-- + base/common/python/pki/util.py | 13 +-- + base/common/python/setup.py | 16 ++-- + 20 files changed, 314 insertions(+), 110 deletions(-) + create mode 100644 base/common/LICENSE.LESSER + +diff --git a/base/common/LICENSE.LESSER b/base/common/LICENSE.LESSER +new file mode 100644 +index 0000000..ca70b83 +--- /dev/null ++++ b/base/common/LICENSE.LESSER +@@ -0,0 +1,170 @@ ++The Python client code is released under LGPLv3+. ++This license is provided below: ++****************************************************************************** ++ ++ GNU LESSER GENERAL PUBLIC LICENSE ++ Version 3, 29 June 2007 ++ ++ Copyright (C) 2007 Free Software Foundation, Inc. ++ Everyone is permitted to copy and distribute verbatim copies ++ of this license document, but changing it is not allowed. ++ ++ ++ This version of the GNU Lesser General Public License incorporates ++the terms and conditions of version 3 of the GNU General Public ++License, supplemented by the additional permissions listed below. ++ ++ 0. Additional Definitions. ++ ++ As used herein, "this License" refers to version 3 of the GNU Lesser ++General Public License, and the "GNU GPL" refers to version 3 of the GNU ++General Public License. ++ ++ "The Library" refers to a covered work governed by this License, ++other than an Application or a Combined Work as defined below. ++ ++ An "Application" is any work that makes use of an interface provided ++by the Library, but which is not otherwise based on the Library. ++Defining a subclass of a class defined by the Library is deemed a mode ++of using an interface provided by the Library. ++ ++ A "Combined Work" is a work produced by combining or linking an ++Application with the Library. The particular version of the Library ++with which the Combined Work was made is also called the "Linked ++Version". ++ ++ The "Minimal Corresponding Source" for a Combined Work means the ++Corresponding Source for the Combined Work, excluding any source code ++for portions of the Combined Work that, considered in isolation, are ++based on the Application, and not on the Linked Version. ++ ++ The "Corresponding Application Code" for a Combined Work means the ++object code and/or source code for the Application, including any data ++and utility programs needed for reproducing the Combined Work from the ++Application, but excluding the System Libraries of the Combined Work. ++ ++ 1. Exception to Section 3 of the GNU GPL. ++ ++ You may convey a covered work under sections 3 and 4 of this License ++without being bound by section 3 of the GNU GPL. ++ ++ 2. Conveying Modified Versions. ++ ++ If you modify a copy of the Library, and, in your modifications, a ++facility refers to a function or data to be supplied by an Application ++that uses the facility (other than as an argument passed when the ++facility is invoked), then you may convey a copy of the modified ++version: ++ ++ a) under this License, provided that you make a good faith effort to ++ ensure that, in the event an Application does not supply the ++ function or data, the facility still operates, and performs ++ whatever part of its purpose remains meaningful, or ++ ++ b) under the GNU GPL, with none of the additional permissions of ++ this License applicable to that copy. ++ ++ 3. Object Code Incorporating Material from Library Header Files. ++ ++ The object code form of an Application may incorporate material from ++a header file that is part of the Library. You may convey such object ++code under terms of your choice, provided that, if the incorporated ++material is not limited to numerical parameters, data structure ++layouts and accessors, or small macros, inline functions and templates ++(ten or fewer lines in length), you do both of the following: ++ ++ a) Give prominent notice with each copy of the object code that the ++ Library is used in it and that the Library and its use are ++ covered by this License. ++ ++ b) Accompany the object code with a copy of the GNU GPL and this license ++ document. ++ ++ 4. Combined Works. ++ ++ You may convey a Combined Work under terms of your choice that, ++taken together, effectively do not restrict modification of the ++portions of the Library contained in the Combined Work and reverse ++engineering for debugging such modifications, if you also do each of ++the following: ++ ++ a) Give prominent notice with each copy of the Combined Work that ++ the Library is used in it and that the Library and its use are ++ covered by this License. ++ ++ b) Accompany the Combined Work with a copy of the GNU GPL and this license ++ document. ++ ++ c) For a Combined Work that displays copyright notices during ++ execution, include the copyright notice for the Library among ++ these notices, as well as a reference directing the user to the ++ copies of the GNU GPL and this license document. ++ ++ d) Do one of the following: ++ ++ 0) Convey the Minimal Corresponding Source under the terms of this ++ License, and the Corresponding Application Code in a form ++ suitable for, and under terms that permit, the user to ++ recombine or relink the Application with a modified version of ++ the Linked Version to produce a modified Combined Work, in the ++ manner specified by section 6 of the GNU GPL for conveying ++ Corresponding Source. ++ ++ 1) Use a suitable shared library mechanism for linking with the ++ Library. A suitable mechanism is one that (a) uses at run time ++ a copy of the Library already present on the user's computer ++ system, and (b) will operate properly with a modified version ++ of the Library that is interface-compatible with the Linked ++ Version. ++ ++ e) Provide Installation Information, but only if you would otherwise ++ be required to provide such information under section 6 of the ++ GNU GPL, and only to the extent that such information is ++ necessary to install and execute a modified version of the ++ Combined Work produced by recombining or relinking the ++ Application with a modified version of the Linked Version. (If ++ you use option 4d0, the Installation Information must accompany ++ the Minimal Corresponding Source and Corresponding Application ++ Code. If you use option 4d1, you must provide the Installation ++ Information in the manner specified by section 6 of the GNU GPL ++ for conveying Corresponding Source.) ++ ++ 5. Combined Libraries. ++ ++ You may place library facilities that are a work based on the ++Library side by side in a single library together with other library ++facilities that are not Applications and are not covered by this ++License, and convey such a combined library under terms of your ++choice, if you do both of the following: ++ ++ a) Accompany the combined library with a copy of the same work based ++ on the Library, uncombined with any other library facilities, ++ conveyed under the terms of this License. ++ ++ b) Give prominent notice with the combined library that part of it ++ is a work based on the Library, and explaining where to find the ++ accompanying uncombined form of the same work. ++ ++ 6. Revised Versions of the GNU Lesser General Public License. ++ ++ The Free Software Foundation may publish revised and/or new versions ++of the GNU Lesser General Public License from time to time. Such new ++versions will be similar in spirit to the present version, but may ++differ in detail to address new problems or concerns. ++ ++ Each version is given a distinguishing version number. If the ++Library as you received it specifies that a certain numbered version ++of the GNU Lesser General Public License "or any later version" ++applies to it, you have the option of following the terms and ++conditions either of that published version or of any later version ++published by the Free Software Foundation. If the Library as you ++received it does not specify a version number of the GNU Lesser ++General Public License, you may choose any version of the GNU Lesser ++General Public License ever published by the Free Software Foundation. ++ ++ If the Library as you received it specifies that a proxy can decide ++whether future versions of the GNU Lesser General Public License shall ++apply, that proxy's public statement of acceptance of any version is ++permanent authorization for you to choose that version for the ++Library. ++ +diff --git a/base/common/python/pki/__init__.py b/base/common/python/pki/__init__.py +index 4c4b88a..5d2a143 100644 +--- a/base/common/python/pki/__init__.py ++++ b/base/common/python/pki/__init__.py +@@ -2,17 +2,18 @@ + # 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. ++# it under the terms of the Lesser GNU General Public License as published by ++# the Free Software Foundation; either version 3 of the License or ++# (at your option) any later version. + # + # 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. ++# GNU Lesser 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. ++# You should have received a copy of the GNU Lesser 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) 2013 Red Hat, Inc. + # All rights reserved. +diff --git a/base/common/python/pki/account.py b/base/common/python/pki/account.py +index ee7507b..62d22fc 100644 +--- a/base/common/python/pki/account.py ++++ b/base/common/python/pki/account.py +@@ -2,17 +2,18 @@ + # 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. ++# it under the terms of the Lesser GNU General Public License as published by ++# the Free Software Foundation; either version 3 of the License or ++# (at your option) any later version. + # + # 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. ++# GNU Lesser 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. ++# You should have received a copy of the GNU Lesser 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) 2013 Red Hat, Inc. + # All rights reserved. +diff --git a/base/common/python/pki/authority.py b/base/common/python/pki/authority.py +index 8827db8..00c6fd9 100644 +--- a/base/common/python/pki/authority.py ++++ b/base/common/python/pki/authority.py +@@ -1,15 +1,16 @@ + # 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. ++# it under the terms of the Lesser GNU General Public License as published by ++# the Free Software Foundation; either version 3 of the License or ++# (at your option) any later version. + # + # 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. ++# GNU Lesser 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. ++# You should have received a copy of the GNU Lesser 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) 2014 Red Hat, Inc. + # All rights reserved. +diff --git a/base/common/python/pki/cert.py b/base/common/python/pki/cert.py +index 05db87c..c53d757 100644 +--- a/base/common/python/pki/cert.py ++++ b/base/common/python/pki/cert.py +@@ -1,15 +1,16 @@ + # 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. ++# it under the terms of the Lesser GNU General Public License as published by ++# the Free Software Foundation; either version 3 of the License or ++# (at your option) any later version. + # + # 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. ++# GNU Lesser 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. ++# You should have received a copy of the GNU Lesser 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) 2014 Red Hat, Inc. + # All rights reserved. +diff --git a/base/common/python/pki/cli/__init__.py b/base/common/python/pki/cli/__init__.py +index 3be9cce..2bed317 100644 +--- a/base/common/python/pki/cli/__init__.py ++++ b/base/common/python/pki/cli/__init__.py +@@ -2,17 +2,18 @@ + # 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. ++# it under the terms of the Lesser GNU General Public License as published by ++# the Free Software Foundation; either version 3 of the License or ++# (at your option) any later version. + # + # 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. ++# GNU Lesser 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. ++# You should have received a copy of the GNU Lesser 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. +diff --git a/base/common/python/pki/cli/pkcs12.py b/base/common/python/pki/cli/pkcs12.py +index ded79c7..8934d33 100644 +--- a/base/common/python/pki/cli/pkcs12.py ++++ b/base/common/python/pki/cli/pkcs12.py +@@ -2,17 +2,18 @@ + # 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. ++# it under the terms of the Lesser GNU General Public License as published by ++# the Free Software Foundation; either version 3 of the License or ++# (at your option) any later version. + # + # 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. ++# GNU Lesser 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. ++# You should have received a copy of the GNU Lesser 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) 2016 Red Hat, Inc. + # All rights reserved. +diff --git a/base/common/python/pki/client.py b/base/common/python/pki/client.py +index 230c236..7e91046 100644 +--- a/base/common/python/pki/client.py ++++ b/base/common/python/pki/client.py +@@ -2,17 +2,18 @@ + # 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. ++# it under the terms of the Lesser GNU General Public License as published by ++# the Free Software Foundation; either version 3 of the License or ++# (at your option) any later version. + # + # 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. ++# GNU Lesser 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. ++# You should have received a copy of the GNU Lesser 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) 2013 Red Hat, Inc. + # All rights reserved. +diff --git a/base/common/python/pki/crypto.py b/base/common/python/pki/crypto.py +index 60e83c9..86fa16e 100644 +--- a/base/common/python/pki/crypto.py ++++ b/base/common/python/pki/crypto.py +@@ -2,17 +2,18 @@ + # Ade Lee + # + # 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. ++# it under the terms of the Lesser GNU General Public License as published by ++# the Free Software Foundation; either version 3 of the License or ++# (at your option) any later version. + # + # 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. ++# GNU Lesser 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. ++# You should have received a copy of the GNU Lesser 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) 2013 Red Hat, Inc. + # All rights reserved. +diff --git a/base/common/python/pki/encoder.py b/base/common/python/pki/encoder.py +index f830601..8485ab8 100644 +--- a/base/common/python/pki/encoder.py ++++ b/base/common/python/pki/encoder.py +@@ -1,3 +1,20 @@ ++# This program is free software; you can redistribute it and/or modify ++# it under the terms of the Lesser GNU General Public License as published by ++# the Free Software Foundation; either version 3 of the License or ++# (at your option) any later version. ++# ++# 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 Lesser General Public License for more details. ++# ++# You should have received a copy of the GNU Lesser 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) 2016 Red Hat, Inc. ++# All rights reserved. ++# + from __future__ import absolute_import + + import base64 +diff --git a/base/common/python/pki/feature.py b/base/common/python/pki/feature.py +index 45af63c..0e5171d 100644 +--- a/base/common/python/pki/feature.py ++++ b/base/common/python/pki/feature.py +@@ -1,15 +1,16 @@ + # 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. ++# it under the terms of the Lesser GNU General Public License as published by ++# the Free Software Foundation; either version 3 of the License or ++# (at your option) any later version. + # + # 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. ++# GNU Lesser 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. ++# You should have received a copy of the GNU Lesser 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) 2014 Red Hat, Inc. + # All rights reserved. +diff --git a/base/common/python/pki/key.py b/base/common/python/pki/key.py +index 28c0e96..14e0b14 100644 +--- a/base/common/python/pki/key.py ++++ b/base/common/python/pki/key.py +@@ -1,15 +1,16 @@ + # 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. ++# it under the terms of the Lesser GNU General Public License as published by ++# the Free Software Foundation; either version 3 of the License or ++# (at your option) any later version. + # + # 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. ++# GNU Lesser 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. ++# You should have received a copy of the GNU Lesser 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) 2013 Red Hat, Inc. + # All rights reserved. +diff --git a/base/common/python/pki/kra.py b/base/common/python/pki/kra.py +index 522773b..b98f856 100644 +--- a/base/common/python/pki/kra.py ++++ b/base/common/python/pki/kra.py +@@ -3,17 +3,18 @@ + # Ade Lee + # + # 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. ++# it under the terms of the Lesser GNU General Public License as published by ++# the Free Software Foundation; either version 3 of the License or ++# (at your option) any later version. + # + # 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. ++# GNU Lesser 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. ++# You should have received a copy of the GNU Lesser 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) 2013 Red Hat, Inc. + # All rights reserved. +diff --git a/base/common/python/pki/nssdb.py b/base/common/python/pki/nssdb.py +index f563fd8..a0b0302 100644 +--- a/base/common/python/pki/nssdb.py ++++ b/base/common/python/pki/nssdb.py +@@ -2,17 +2,18 @@ + # 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. ++# it under the terms of the Lesser GNU General Public License as published by ++# the Free Software Foundation; either version 3 of the License or ++# (at your option) any later version. + # + # 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. ++# GNU Lesser 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. ++# You should have received a copy of the GNU Lesser 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. +diff --git a/base/common/python/pki/profile.py b/base/common/python/pki/profile.py +index c463a6b..a2e7621 100644 +--- a/base/common/python/pki/profile.py ++++ b/base/common/python/pki/profile.py +@@ -1,15 +1,16 @@ + # 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. ++# it under the terms of the Lesser GNU General Public License as published by ++# the Free Software Foundation; either version 3 of the License or ++# (at your option) any later version. + # + # 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. ++# GNU Lesser 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. ++# You should have received a copy of the GNU Lesser 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) 2014 Red Hat, Inc. + # All rights reserved. +diff --git a/base/common/python/pki/system.py b/base/common/python/pki/system.py +index 45aa0d6..cbb908f 100644 +--- a/base/common/python/pki/system.py ++++ b/base/common/python/pki/system.py +@@ -2,17 +2,18 @@ + # 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. ++# it under the terms of the Lesser GNU General Public License as published by ++# the Free Software Foundation; either version 3 of the License or ++# (at your option) any later version. + # + # 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. ++# GNU Lesser 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. ++# You should have received a copy of the GNU Lesser 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) 2013 Red Hat, Inc. + # All rights reserved. +diff --git a/base/common/python/pki/systemcert.py b/base/common/python/pki/systemcert.py +index ed41be9..9bf4678 100644 +--- a/base/common/python/pki/systemcert.py ++++ b/base/common/python/pki/systemcert.py +@@ -2,17 +2,18 @@ + # Ade Lee + # + # 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. ++# it under the terms of the Lesser GNU General Public License as published by ++# the Free Software Foundation; either version 3 of the License or ++# (at your option) any later version. + # + # 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. ++# GNU Lesser 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. ++# You should have received a copy of the GNU Lesser 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) 2013 Red Hat, Inc. + # All rights reserved. +diff --git a/base/common/python/pki/upgrade.py b/base/common/python/pki/upgrade.py +index 2261ba8..3106c70 100644 +--- a/base/common/python/pki/upgrade.py ++++ b/base/common/python/pki/upgrade.py +@@ -2,17 +2,18 @@ + # 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. ++# it under the terms of the Lesser GNU General Public License as published by ++# the Free Software Foundation; either version 3 of the License or ++# (at your option) any later version. + # + # 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. ++# GNU Lesser 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. ++# You should have received a copy of the GNU Lesser 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) 2013 Red Hat, Inc. + # All rights reserved. +diff --git a/base/common/python/pki/util.py b/base/common/python/pki/util.py +index 2cac1d8..95a3670 100644 +--- a/base/common/python/pki/util.py ++++ b/base/common/python/pki/util.py +@@ -2,17 +2,18 @@ + # 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. ++# it under the terms of the Lesser GNU General Public License as published by ++# the Free Software Foundation; either version 3 of the License or ++# (at your option) any later version. + # + # 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. ++# GNU Lesser 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. ++# You should have received a copy of the GNU Lesser 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) 2013 Red Hat, Inc. + # All rights reserved. +diff --git a/base/common/python/setup.py b/base/common/python/setup.py +index 2ab0337..86e0704 100644 +--- a/base/common/python/setup.py ++++ b/base/common/python/setup.py +@@ -2,17 +2,17 @@ + # Christian Heimes + # + # 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. ++# it under the terms of the Lesser GNU General Public License as published by ++# the Free Software Foundation; version 3 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. ++# GNU Lesser 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. ++# You should have received a copy of the GNU Lesser 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. +@@ -81,7 +81,7 @@ hardened by real-world deployments. It supports all aspects of certificate + lifecycle management, including key archival, OCSP and smartcard management, + and much more. The Dogtag Certificate System can be downloaded for free + and set up in less than an hour.""", +- license='GPL', ++ license='LGPLv3+', + keywords='pki x509 cert certificate', + url='http://pki.fedoraproject.org/', + packages=['pki', 'pki.cli'], +@@ -93,7 +93,7 @@ and set up in less than an hour.""", + 'Operating System :: OS Independent', + 'Programming Language :: Python :: 2.7', + 'Programming Language :: Python :: 3.4', +- 'License :: OSI Approved :: GNU General Public License v2 (GPLv2)', ++ 'License :: OSI Approved :: GNU Lesser General Public License v3+ (LGPLv3+)', + 'Topic :: Security :: Cryptography', + ], + ) +-- +1.8.3.1 + + +From d85080be85eb54756d9db69302a6117cef063017 Mon Sep 17 00:00:00 2001 +From: Ade Lee +Date: Fri, 29 Jul 2016 12:23:39 +0100 +Subject: [PATCH 71/96] Do slot substitution for SERVER_KEYGEN + +Ticket 2418 +--- + base/server/config/pkislots.cfg | 1 + + base/server/python/pki/server/deployment/pkiparser.py | 2 ++ + 2 files changed, 3 insertions(+) + +diff --git a/base/server/config/pkislots.cfg b/base/server/config/pkislots.cfg +index 473b0da..3873b83 100644 +--- a/base/server/config/pkislots.cfg ++++ b/base/server/config/pkislots.cfg +@@ -64,6 +64,7 @@ PKI_UNSECURE_PORT_SERVER_COMMENT_SLOT=[PKI_UNSECURE_PORT_SERVER_COMMENT] + PKI_USER_SLOT=[PKI_USER] + PKI_WEB_SERVER_TYPE_SLOT=[PKI_WEB_SERVER_TYPE] + PKI_WEBAPPS_NAME_SLOT=[PKI_WEBAPPS_NAME] ++SERVER_KEYGEN_SLOT=[SERVER_KEYGEN] + TOKENDB_HOST_SLOT=[TOKENDB_HOST] + TOKENDB_PORT_SLOT={TOKENDB_PORT] + TOKENDB_ROOT_SLOT=[TOKENDB_ROOT] +diff --git a/base/server/python/pki/server/deployment/pkiparser.py b/base/server/python/pki/server/deployment/pkiparser.py +index d940e2c..622f87e 100644 +--- a/base/server/python/pki/server/deployment/pkiparser.py ++++ b/base/server/python/pki/server/deployment/pkiparser.py +@@ -941,6 +941,8 @@ class PKIConfigParser: + "tomcat" + self.mdict['PKI_WEBAPPS_NAME_SLOT'] = \ + "webapps" ++ self.mdict['SERVER_KEYGEN_SLOT'] = \ ++ self.mdict['pki_enable_server_side_keygen'] + self.mdict['TOMCAT_CFG_SLOT'] = \ + self.mdict['pki_target_tomcat_conf'] + self.mdict['TOMCAT_INSTANCE_COMMON_LIB_SLOT'] = \ +-- +1.8.3.1 + + +From 7cfff9fb0c08d08f57d6229cb8a67d7c94f785aa Mon Sep 17 00:00:00 2001 +From: Ade Lee +Date: Fri, 29 Jul 2016 14:42:35 +0100 +Subject: [PATCH 72/96] Fix client-cert-import to set provided trust bits + +Ticket 2412 +--- + .../netscape/cmstools/client/ClientCertImportCLI.java | 16 ++++++++++++---- + 1 file changed, 12 insertions(+), 4 deletions(-) + +diff --git a/base/java-tools/src/com/netscape/cmstools/client/ClientCertImportCLI.java b/base/java-tools/src/com/netscape/cmstools/client/ClientCertImportCLI.java +index 9625440..a920079 100644 +--- a/base/java-tools/src/com/netscape/cmstools/client/ClientCertImportCLI.java ++++ b/base/java-tools/src/com/netscape/cmstools/client/ClientCertImportCLI.java +@@ -83,7 +83,7 @@ public class ClientCertImportCLI extends CLI { + option.setArgName("serial number"); + options.addOption(option); + +- option = new Option(null, "trust", true, "Trust attributes. Default: u,u,u."); ++ option = new Option(null, "trust", true, "Trust attributes."); + option.setArgName("trust attributes"); + options.addOption(option); + } +@@ -140,13 +140,16 @@ public class ClientCertImportCLI extends CLI { + String pkcs12PasswordPath = cmd.getOptionValue("pkcs12-password-file"); + boolean importFromCAServer = cmd.hasOption("ca-server"); + String serialNumber = cmd.getOptionValue("serial"); +- String trustAttributes = cmd.getOptionValue("trust", "u,u,u"); ++ String trustAttributes = cmd.getOptionValue("trust"); + + // load the certificate + if (certPath != null) { + + if (verbose) System.out.println("Importing certificate from " + certPath + "."); + ++ if (trustAttributes == null) ++ trustAttributes = "u,u,u"; ++ + importCert( + mainCLI.certDatabase.getAbsolutePath(), + certPath, +@@ -157,7 +160,8 @@ public class ClientCertImportCLI extends CLI { + + if (verbose) System.out.println("Importing CA certificate from " + caCertPath + "."); + +- trustAttributes = "CT,c,"; ++ if (trustAttributes == null) ++ trustAttributes = "CT,c,"; + + importCert( + mainCLI.certDatabase.getAbsolutePath(), +@@ -218,7 +222,8 @@ public class ClientCertImportCLI extends CLI { + out.write(bytes); + } + +- trustAttributes = "CT,c,"; ++ if (trustAttributes == null) ++ trustAttributes = "CT,c,"; + + importCert( + mainCLI.certDatabase.getAbsolutePath(), +@@ -250,6 +255,9 @@ public class ClientCertImportCLI extends CLI { + out.write(encoded); + } + ++ if (trustAttributes == null) ++ trustAttributes = "u,u,u"; ++ + importCert( + mainCLI.certDatabase.getAbsolutePath(), + certFile.getAbsolutePath(), +-- +1.8.3.1 + + +From e46fdb07d014368bb506b02d4ca9fafda672800a Mon Sep 17 00:00:00 2001 +From: "Endi S. Dewata" +Date: Sat, 30 Jul 2016 00:23:48 +0200 +Subject: [PATCH 73/96] Added log message in PKIClient. + +To help troubleshooting the PKIClient class has been modified to +log the certificate chain retrieved from the CA. + +https://fedorahosted.org/pki/ticket/2399 +--- + base/common/src/com/netscape/certsrv/client/PKIClient.java | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +diff --git a/base/common/src/com/netscape/certsrv/client/PKIClient.java b/base/common/src/com/netscape/certsrv/client/PKIClient.java +index 5c13554..8cad382 100644 +--- a/base/common/src/com/netscape/certsrv/client/PKIClient.java ++++ b/base/common/src/com/netscape/certsrv/client/PKIClient.java +@@ -32,6 +32,7 @@ import javax.xml.parsers.DocumentBuilder; + import javax.xml.parsers.DocumentBuilderFactory; + import javax.xml.parsers.ParserConfigurationException; + ++import org.apache.commons.codec.binary.Base64; + import org.mozilla.jss.CryptoManager; + import org.mozilla.jss.CryptoManager.NicknameConflictException; + import org.mozilla.jss.CryptoManager.NotInitializedException; +@@ -177,7 +178,15 @@ public class PKIClient { + Element element = (Element)list.item(0); + + String encodedChain = element.getTextContent(); +- return Utils.base64decode(encodedChain); ++ byte[] bytes = Utils.base64decode(encodedChain); ++ ++ if (verbose) { ++ System.out.println("-----BEGIN PKCS7-----"); ++ System.out.print(new Base64(64).encodeToString(bytes)); ++ System.out.println("-----END PKCS7-----"); ++ } ++ ++ return bytes; + } + + public X509Certificate importCertPackage(byte[] bytes, String nickname) +-- +1.8.3.1 + + +From 1b246d46671472d0b395957d3e550e54c3068758 Mon Sep 17 00:00:00 2001 +From: Matthew Harmsen +Date: Mon, 1 Aug 2016 16:36:00 -0600 +Subject: [PATCH 74/96] pki-tools man pages + +* PKI TRAC Ticket #690 - [MAN] pki-tools man pages + - AtoB, + - BtoA, + - KRATool, + - PrettyPrintCert, and + - PrettyPrintCrl +--- + base/java-tools/man/man1/AtoB.1 | 56 ++++ + base/java-tools/man/man1/BtoA.1 | 56 ++++ + base/java-tools/man/man1/KRATool.1 | 459 +++++++++++++++++++++++++++++ + base/java-tools/man/man1/PrettyPrintCert.1 | 204 +++++++++++++ + base/java-tools/man/man1/PrettyPrintCrl.1 | 141 +++++++++ + 5 files changed, 916 insertions(+) + create mode 100644 base/java-tools/man/man1/AtoB.1 + create mode 100644 base/java-tools/man/man1/BtoA.1 + create mode 100644 base/java-tools/man/man1/KRATool.1 + create mode 100644 base/java-tools/man/man1/PrettyPrintCert.1 + create mode 100644 base/java-tools/man/man1/PrettyPrintCrl.1 + +diff --git a/base/java-tools/man/man1/AtoB.1 b/base/java-tools/man/man1/AtoB.1 +new file mode 100644 +index 0000000..228e3e0 +--- /dev/null ++++ b/base/java-tools/man/man1/AtoB.1 +@@ -0,0 +1,56 @@ ++.\" First parameter, NAME, should be all caps ++.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection ++.\" other parameters are allowed: see man(7), man(1) ++.TH AtoB 1 "July 20, 2016" "version 10.3" "PKI ASCII to Binary Conversion Tool" Dogtag Team ++.\" Please adjust this date whenever revising the man page. ++.\" ++.\" Some roff macros, for reference: ++.\" .nh disable hyphenation ++.\" .hy enable hyphenation ++.\" .ad l left justify ++.\" .ad b justify to both left and right margins ++.\" .nf disable filling ++.\" .fi enable filling ++.\" .br insert line break ++.\" .sp insert n+1 empty lines ++.\" for man page specific macros, see man(7) ++.SH NAME ++AtoB \- Convert ASCII base-64 encoded data to binary base-64 encoded data. ++ ++.SH SYNOPSIS ++.PP ++\fBAtoB \fP ++ ++.SH DESCRIPTION ++.PP ++The \fBAtoB\fP command provides a command-line utility used to convert ASCII base-64 encoded data to binary base-64 encoded data. ++ ++.SH OPTIONS ++.PP ++The following parameters are mandatory: ++.TP ++.B ++Specifies the path to the file containing the base-64 encoded ASCII data. ++ ++.TP ++.B ++Specifies the path to the file where the utility should write the binary output. ++ ++.SH EXAMPLES ++.PP ++This example command takes the base-64 ASCII data in the \fBascii_data.pem\fP file and writes the binary equivalent of the data to the \fBbinary_data.der\fP file: ++.IP ++.nf ++AtoB ascii_data.pem binary_data.der ++.if ++ ++.SH AUTHORS ++Matthew Harmsen . ++ ++.SH COPYRIGHT ++Copyright (c) 2016 Red Hat, Inc. This is licensed under the GNU General Public ++License, version 2 (GPLv2). A copy of this license is available at ++http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. ++ ++.SH SEE ALSO ++.BR BtoA(1), pki(1) +diff --git a/base/java-tools/man/man1/BtoA.1 b/base/java-tools/man/man1/BtoA.1 +new file mode 100644 +index 0000000..95c742d +--- /dev/null ++++ b/base/java-tools/man/man1/BtoA.1 +@@ -0,0 +1,56 @@ ++.\" First parameter, NAME, should be all caps ++.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection ++.\" other parameters are allowed: see man(7), man(1) ++.TH BtoA 1 "July 20, 2016" "version 10.3" "PKI Binary to ASCII Conversion Tool" Dogtag Team ++.\" Please adjust this date whenever revising the man page. ++.\" ++.\" Some roff macros, for reference: ++.\" .nh disable hyphenation ++.\" .hy enable hyphenation ++.\" .ad l left justify ++.\" .ad b justify to both left and right margins ++.\" .nf disable filling ++.\" .fi enable filling ++.\" .br insert line break ++.\" .sp insert n+1 empty lines ++.\" for man page specific macros, see man(7) ++.SH NAME ++BtoA \- Convert binary base-64 encoded data to ASCII base-64 encoded data. ++ ++.SH SYNOPSIS ++.PP ++\fBBtoA \fP ++ ++.SH DESCRIPTION ++.PP ++The \fBBtoA\fP command provides a command-line utility used to convert binary base-64 encoded data to ASCII base-64 encoded data. ++ ++.SH OPTIONS ++.PP ++The following parameters are mandatory: ++.TP ++.B ++Specifies the path to the file which contains the base-64 encoded binary data. ++ ++.TP ++.B ++Specifies the path to the file where the utility should write the ASCII output. ++ ++.SH EXAMPLES ++.PP ++This example command takes the base-64 binary data in the \fBbinary_data.der\fP file and writes the ASCII equivalent of the data to the \fBascii_data.pem\fP file: ++.IP ++.nf ++BtoA binary_data.der ascii_data.pem ++.if ++ ++.SH AUTHORS ++Matthew Harmsen . ++ ++.SH COPYRIGHT ++Copyright (c) 2016 Red Hat, Inc. This is licensed under the GNU General Public ++License, version 2 (GPLv2). A copy of this license is available at ++http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. ++ ++.SH SEE ALSO ++.BR AtoB(1), pki(1) +diff --git a/base/java-tools/man/man1/KRATool.1 b/base/java-tools/man/man1/KRATool.1 +new file mode 100644 +index 0000000..b04cd2b +--- /dev/null ++++ b/base/java-tools/man/man1/KRATool.1 +@@ -0,0 +1,459 @@ ++.\" First parameter, NAME, should be all caps ++.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection ++.\" other parameters are allowed: see man(7), man(1) ++.TH KRATool 1 "July 18, 2016" "version 10.3" "PKI Key Recovery Authority (KRA) Tool" Dogtag Team ++.\" Please adjust this date whenever revising the man page. ++.\" ++.\" Some roff macros, for reference: ++.\" .nh disable hyphenation ++.\" .hy enable hyphenation ++.\" .ad l left justify ++.\" .ad b justify to both left and right margins ++.\" .nf disable filling ++.\" .fi enable filling ++.\" .br insert line break ++.\" .sp insert n+1 empty lines ++.\" for man page specific macros, see man(7) ++.SH NAME ++KRATool \- Command-Line utility used to export private keys from one or more KRA instances (generally legacy) into a KRA instance (generally modern); during the process of moving the keys, the KRATool can rewrap keys, renumber keys, or both. ++ ++.SH SYNOPSIS ++.PP ++The syntax for rewrapping keys: ++.IP ++.nf ++\fBKRATool\fR -kratool_config_file
++ -source_ldif_file
++ -target_ldif_file
++ -log_file
++ [-source_pki_security_database_path
++ -source_storage_token_name
++ -source_storage_certificate_nickname ++ -target_storage_certificate_file
++ [-source_pki_security_database_pwdfile
]] ++ [-source_kra_naming_context -target_kra_naming_context ] ++ [-process_requests_and_key_records_only] ++.fi ++.PP ++The syntax for renumbering keys: ++.IP ++.nf ++\fBKRATool\fR -kratool_config_file
++ -source_ldif_file
++ -target_ldif_file
++ -log_file
++ [-append_id_offset | -remove_id_offset ] ++ [-source_kra_naming_context -target_kra_naming_context ] ++ [-process_requests_and_key_records_only] ++.fi ++ ++.SH DESCRIPTION ++.PP ++The \fBKRATool\fR command provides a command-line utility used to rewrap keys, renumber keys, or both. For example, some private keys (mainly in older deployments) were wrapped in SHA-1, 1024-bit storage keys when they were archived in the Key Recovery Authority (KRA). These algorithms have become less secure as processor speeds improve and algorithms have been broken. As a security measure, it is possible to rewrap the private keys in a new, stronger storage key (SHA-256, 2048-bit keys). ++.TP ++\fBNote:\fP ++Because the KRATool utility can export private keys from one KRA, rewrap them with a new storage key, and then import them into a new KRA, this tool can be used as part of a process of combining multiple KRA instances into a single KRA. ++ ++.SH OPTIONS ++.PP ++The following parameters are mandatory for both rewrapping and renumbering keys: ++.TP ++.B -kratool_config_file
++Gives the complete path and filename of the configuration file used by the tool. This configuration process tells the tool how to process certain parameters in the existing key records, whether to apply any formatting changes (like changing the naming context or adding an offset) or even whether to update the modify date. The configuration file is required and a default file is included with the tool. The file format is described in the section entitled ++.B Configuration File (.cfg). ++ ++.TP ++.B -source_ldif_file
++Gives the complete path and filename of the Lightweight Directory Access Protocol (LDAP) Data Interchange Format (LDIF) file which contains all of the key data from the old KRA. ++ ++.TP ++.B -target_ldif_file
++Gives the complete path and filename of the LDIF file to which the tool will write all of the key data from the new KRA. This file is created by the tool as it runs. ++ ++.TP ++.B -log_file
++Gives the path and filename of the log file to use to log the tool progress and messages. This file is created by the tool as it runs. ++ ++.PP ++The following parameters are optional for both rewrapping and renumbering keys: ++ ++.TP ++.B -source_kra_naming_context ++Gives the naming context of the original KRA instance, the Distinguished Name (DN) element that refers to the original KRA. Key-related LDIF entries have a DN with the KRA instance name in it, such as \fIcn=1,ou=kra,ou=requests,dc=alpha.example.com-pki-kra\fP. The naming context for that entry is the DN value, \fIalpha.example.com-pki-kra\fP. These entries can be renamed, automatically, from the old KRA instance naming context to the new KRA instance naming context. ++ ++While this argument is optional, it is recommended because it means that the LDIF file does not have to be edited before it is imported into the target KRA. ++If this argument is used, then the \fB-target_kra_naming_context\fP argument must also be used. ++ ++.TP ++.B -target_kra_naming_context ++Gives the naming context of the new KRA instance, the name that the original key entries should be changed too. Key-related LDIF entries have a DN with the KRA instance name in it, such as \fIcn=1,ou=kra,ou=requests,dc=omega.example.com-pki-kra\fP. The naming context for that entry is the DN value, \fIomega.example.com-pki-kra\fP.These entries can be renamed, automatically, from the old KRA instance to the new KRA instance naming context. ++ ++While this argument is optional, it is recommended because it means that the LDIF file does not have to be edited before it is imported into the target KRA. ++If this argument is used, then the \fB-source_kra_naming_context\fP argument must also be used. ++ ++.TP ++.B -process_requests_and_key_records_only ++Removes configuration entries from the source LDIF file, leaving only the key and request entries. ++ ++While this argument is optional, it is recommended because it means that the LDIF file does not have to be edited before it is imported into the target KRA. ++ ++.PP ++The following parameters are optional for rewrapping keys: ++ ++.TP ++.B -source_pki_security_database_path
++Gives the full path to the directory which contains the Network Security Services (NSS) security databases used by the old KRA instance. ++ ++This option is required if any other rewrap parameters are used. ++ ++.TP ++.B -source_storage_token_name
++Gives the name of the token which stores the KRA data, like \fIInternal Key Storage Token\fP for internal tokens or a name like \fINHSM6000-OCS\fP for the hardware token name. ++ ++This option is required if any other rewrap parameters are used. ++ ++.TP ++.B -source_storage_certificate_nickname ++Gives the nickname of the KRA storage certificate for the old KRA instance. Either this certificate will be located in the security database for the old KRA instance or the security database will contain a pointer to the certificate in the hardware token. ++ ++This option is required if any other rewrap parameters are used. ++ ++.TP ++.B -target_storage_certificate_file
++Gives the path and filename of an ASCII-formatted file of the storage certificate for the new KRA instance. The storage certificate should be exported from the new KRA's databases and stored in an accessible location before running KRATool. ++ ++This option is required if any other rewrap parameters are used. ++ ++.TP ++.B -source_pki_security_database_pwdfile
++Gives the path and filename to a password file that contains only the password for the storage token given in the \fB-source_storage_token_name\fP option. ++ ++This argument is optional when other rewrap parameters are used. If this argument is not used, then the script prompts for the password. ++ ++.PP ++The following parameters are optional for renumbering keys: ++ ++.TP ++.B -append_id_offset ++Gives an ID number which will be preprended to every imported key, to prevent possible collisions. A unique ID offset should be used for every KRA instance which has keys exported using KRATool. ++ ++If \fB-append_id_offset\fP is used, then do not use the \fB-remove_id_offset\fP option. ++ ++.TP ++.B -remove_id_offset ++Gives an ID number to remove from the beginning of every imported key. ++ ++If \fB-remove_id_offset\fP is used, then do not use the \fB-append_id_offset\fP option. ++ ++.SH Configuration File (.cfg) ++.PP ++The required configuration file instructs the KRATool how to process attributes in the key archival and key request entries in the LDIF file. There are six types of entries: ++.IP ++* CA enrollment requests ++* TPS enrollment requests ++* CA key records ++* TPS key records ++* CA and TPS recovery requests (which are treated the same in the KRA) ++.PP ++Each key and key request has an LDAP entry with attributes that are specific to that kind of record. For example, for a recovery request: ++.IP ++.nf ++dn: cn=1,ou=kra,ou=requests,dc=alpha.example.com-pki-kra ++objectClass: top ++objectClass: request ++objectClass: extensibleObject ++requestId: 011 ++requestState: complete ++dateOfCreate: 20110121181006Z ++dateOfModify: 20110524094652Z ++extdata-kra--005ftrans--005fdeskey: 3#C7#82#0F#5D#97GqY#0Aib#966#E5B#F56#F24n# ++ F#9E#98#B3 ++extdata-public--005fkey: MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDu6E3uG+Ep27bF1 ++ yTWvwIDAQAB ++extdata-archive: true ++extdata-requesttype: netkeyKeygen ++extdata-iv--005fs: %F2%67%45%96%41%D7%FF%10 ++extdata-requestversion: 8.1.0 ++extdata-requestortype: NETKEY_RA ++extdata-keyrecord: 1 ++extdata-wrappeduserprivate: %94%C1%36%D3%EA%4E%36%B5%42%91%AB%47%34%C0%35%A3%6 ++ F%E8%10%A9%B1%25%F4%BE%9C%11%D1%B3%3D%90%AB%79 ++extdata-userid: jmagne ++extdata-keysize: 1024 ++extdata-updatedby: TPS-alpha.example.com-7889 ++extdata-dbstatus: UPDATED ++extdata-cuid: 40906145C76224192D2B ++extdata-requeststatus: complete ++extdata-requestid: 1 ++extdata-result: 1 ++requestType: netkeyKeygen ++cn: 1 ++creatorsName: cn=directory manager ++modifiersName: cn=directory manager ++createTimestamp: 20110122021010Z ++modifyTimestamp: 20110122021010Z ++nsUniqueId: b2891805-1dd111b2-a6d7e85f-2c2f0000 ++.if ++ ++.PP ++Much of that information passes through the script processing unchanged, so it is entered into the new, target KRA just the same. However, some of those attributes can and should be edited, like the Common Name (CN) and DN being changed to match the new KRA instance. The fields which can safely be changed are listed in the configuration file for each type of key entry. (Any attribute not listed is not touched by the tool under any circumstances.) ++.PP ++If a field /fIshould/fP be edited — meaning, the tool can update the record ID number or rename the entry — then the value is set to true in the configuration file. For example, this configuration updates the CN, DN, ID number, last modified date, and associated entry notes for all CA enrollment requests: ++.IP ++.nf ++kratool.ldif.caEnrollmentRequest.cn=true ++kratool.ldif.caEnrollmentRequest.dateOfModify=true ++kratool.ldif.caEnrollmentRequest.dn=true ++kratool.ldif.caEnrollmentRequest.extdata.keyRecord=true ++kratool.ldif.caEnrollmentRequest.extdata.requestNotes=true ++kratool.ldif.caEnrollmentRequest.requestId=true ++.if ++ ++.PP ++If a line is set to true, then the attribute is processed in the LDIF file. By default, all possible attributes are processed. Setting a line to false means that the KRATool skips that attribute and passes the value unchanged. For example, this leaves the last modified time unchanged so that it doesn't update for when the KRATool runs: ++.IP ++.nf ++kratool.ldif.caEnrollmentRequest.dateOfModify=false ++.if ++ ++.TP ++\fBNOTE:\fP ++Key enrollments, records, and requests all have an optional notes attribute where administrators can enter notes about the process. When the KRATool runs, it appends a note to that attribute or adds the attribute with information about the tool running, what operations were performed, and a timestamp: ++.IP ++.nf ++extdata-requestnotes: [20110701150056Z]: REWRAPPED the 'existing DES3 symmetric session key' with the '2048-bit RSA public key' obtained from the target storage certificate + APPENDED ID offset '100000000000' + RENAMED source KRA naming context 'alpha.example.com-pki-kra' to target KRA naming context 'omega.example.com-pki-kra' + PROCESSED requests and key records ONLY! ++.if ++ ++.TP ++\fB\fP ++This information is very useful for both audit and maintenance of the KRA, so it is beneficial to keep the extdata.requestNotes parameter for all of the key record types set to true. ++ ++.TP ++\fBIMPORTANT:\fP ++Every parameter line in the default \fBkratool.cfg\fP must be present in the \fI.cfg\fP file used when the tool is invoked. No line can be omitted and every line must have a valid value (true or false). If the file is not properly formatted, the KRATool will fail. ++ ++.PP ++The formatting of the \fI.cfg\fP file is the same as the formatting used in the instance \fBCS.cfg\fP files. ++ ++.PP ++A default \fI.cfg\fP file is included with the KRATool script. This file (shown in the example entitled \fBDefault kratool.cfg File\fP) can be copied and edited into a custom file or edited directly and used with the tool. ++ ++.SS Default kratool.cfg File ++.BR ++.IP ++.nf ++kratool.ldif.caEnrollmentRequest._000=######################################## ++kratool.ldif.caEnrollmentRequest._001=## KRA CA Enrollment Request ## ++kratool.ldif.caEnrollmentRequest._002=######################################## ++kratool.ldif.caEnrollmentRequest._003=## ## ++kratool.ldif.caEnrollmentRequest._004=## NEVER allow 'KRATOOL' the ability ## ++kratool.ldif.caEnrollmentRequest._005=## to change the CA 'naming context' ## ++kratool.ldif.caEnrollmentRequest._006=## data in the following fields: ## ++kratool.ldif.caEnrollmentRequest._007=## ## ++kratool.ldif.caEnrollmentRequest._008=## extdata-auth--005ftoken;uid ## ++kratool.ldif.caEnrollmentRequest._009=## extdata-auth--005ftoken;userid ## ++kratool.ldif.caEnrollmentRequest._010=## extdata-updatedby ## ++kratool.ldif.caEnrollmentRequest._011=## ## ++kratool.ldif.caEnrollmentRequest._012=## NEVER allow 'KRATOOL' the ability ## ++kratool.ldif.caEnrollmentRequest._013=## to change CA 'numeric' data in ## ++kratool.ldif.caEnrollmentRequest._014=## the following fields: ## ++kratool.ldif.caEnrollmentRequest._015=## ## ++kratool.ldif.caEnrollmentRequest._016=## extdata-requestId ## ++kratool.ldif.caEnrollmentRequest._017=## ## ++kratool.ldif.caEnrollmentRequest._018=######################################## ++kratool.ldif.caEnrollmentRequest.cn=true ++kratool.ldif.caEnrollmentRequest.dateOfModify=true ++kratool.ldif.caEnrollmentRequest.dn=true ++kratool.ldif.caEnrollmentRequest.extdata.keyRecord=true ++kratool.ldif.caEnrollmentRequest.extdata.requestNotes=true ++kratool.ldif.caEnrollmentRequest.requestId=true ++kratool.ldif.caKeyRecord._000=######################################### ++kratool.ldif.caKeyRecord._001=## KRA CA Key Record ## ++kratool.ldif.caKeyRecord._002=######################################### ++kratool.ldif.caKeyRecord._003=## ## ++kratool.ldif.caKeyRecord._004=## NEVER allow 'KRATOOL' the ability ## ++kratool.ldif.caKeyRecord._005=## to change the CA 'naming context' ## ++kratool.ldif.caKeyRecord._006=## data in the following fields: ## ++kratool.ldif.caKeyRecord._007=## ## ++kratool.ldif.caKeyRecord._008=## archivedBy ## ++kratool.ldif.caKeyRecord._009=## ## ++kratool.ldif.caKeyRecord._010=######################################### ++kratool.ldif.caKeyRecord.cn=true ++kratool.ldif.caKeyRecord.dateOfModify=true ++kratool.ldif.caKeyRecord.dn=true ++kratool.ldif.caKeyRecord.privateKeyData=true ++kratool.ldif.caKeyRecord.serialno=true ++kratool.ldif.namingContext._000=############################################ ++kratool.ldif.namingContext._001=## KRA Naming Context Fields ## ++kratool.ldif.namingContext._002=############################################ ++kratool.ldif.namingContext._003=## ## ++kratool.ldif.namingContext._004=## NEVER allow 'KRATOOL' the ability to ## ++kratool.ldif.namingContext._005=## change the CA 'naming context' data ## ++kratool.ldif.namingContext._006=## in the following 'non-KeyRecord / ## ++kratool.ldif.namingContext._007=## non-Request' fields (as these records ## ++kratool.ldif.namingContext._008=## should be removed via the option to ## ++kratool.ldif.namingContext._009=## process requests and key records only ## ++kratool.ldif.namingContext._010=## if this is a KRA migration): ## ++kratool.ldif.namingContext._011=## ## ++kratool.ldif.namingContext._012=## cn ## ++kratool.ldif.namingContext._013=## sn ## ++kratool.ldif.namingContext._014=## uid ## ++kratool.ldif.namingContext._015=## uniqueMember ## ++kratool.ldif.namingContext._016=## ## ++kratool.ldif.namingContext._017=## NEVER allow 'KRATOOL' the ability to ## ++kratool.ldif.namingContext._018=## change the KRA 'naming context' data ## ++kratool.ldif.namingContext._019=## in the following 'non-KeyRecord / ## ++kratool.ldif.namingContext._020=## non-Request' fields (as these records ## ++kratool.ldif.namingContext._021=## should be removed via the option to ## ++kratool.ldif.namingContext._022=## process requests and key records only ## ++kratool.ldif.namingContext._023=## if this is a KRA migration): ## ++kratool.ldif.namingContext._024=## ## ++kratool.ldif.namingContext._025=## dc ## ++kratool.ldif.namingContext._026=## dn ## ++kratool.ldif.namingContext._027=## uniqueMember ## ++kratool.ldif.namingContext._028=## ## ++kratool.ldif.namingContext._029=## NEVER allow 'KRATOOL' the ability to ## ++kratool.ldif.namingContext._030=## change the TPS 'naming context' data ## ++kratool.ldif.namingContext._031=## in the following 'non-KeyRecord / ## ++kratool.ldif.namingContext._032=## non-Request' fields (as these records ## ++kratool.ldif.namingContext._033=## should be removed via the option to ## ++kratool.ldif.namingContext._034=## process requests and key records only ## ++kratool.ldif.namingContext._035=## if this is a KRA migration): ## ++kratool.ldif.namingContext._036=## ## ++kratool.ldif.namingContext._037=## uid ## ++kratool.ldif.namingContext._038=## uniqueMember ## ++kratool.ldif.namingContext._039=## ## ++kratool.ldif.namingContext._040=## If '-source_naming_context ## ++kratool.ldif.namingContext._041=## original source KRA naming context' ## ++kratool.ldif.namingContext._042=## and '-target_naming_context ## ++kratool.ldif.namingContext._043=## renamed target KRA naming context' ## ++kratool.ldif.namingContext._044=## options are specified, ALWAYS ## ++kratool.ldif.namingContext._045=## require 'KRATOOL' to change the ## ++kratool.ldif.namingContext._046=## KRA 'naming context' data in ALL of ## ++kratool.ldif.namingContext._047=## the following fields in EACH of the ## ++kratool.ldif.namingContext._048=## following types of records: ## ++kratool.ldif.namingContext._049=## ## ++kratool.ldif.namingContext._050=## caEnrollmentRequest: ## ++kratool.ldif.namingContext._051=## ## ++kratool.ldif.namingContext._052=## dn ## ++kratool.ldif.namingContext._053=## extdata-auth--005ftoken;user ## ++kratool.ldif.namingContext._054=## extdata-auth--005ftoken;userdn ## ++kratool.ldif.namingContext._055=## ## ++kratool.ldif.namingContext._056=## caKeyRecord: ## ++kratool.ldif.namingContext._057=## ## ++kratool.ldif.namingContext._058=## dn ## ++kratool.ldif.namingContext._059=## ## ++kratool.ldif.namingContext._060=## recoveryRequest: ## ++kratool.ldif.namingContext._061=## ## ++kratool.ldif.namingContext._062=## dn ## ++kratool.ldif.namingContext._063=## ## ++kratool.ldif.namingContext._064=## tpsKeyRecord: ## ++kratool.ldif.namingContext._065=## ## ++kratool.ldif.namingContext._066=## dn ## ++kratool.ldif.namingContext._067=## ## ++kratool.ldif.namingContext._068=## tpsNetkeyKeygenRequest: ## ++kratool.ldif.namingContext._069=## ## ++kratool.ldif.namingContext._070=## dn ## ++kratool.ldif.namingContext._071=## ## ++kratool.ldif.namingContext._072=############################################ ++kratool.ldif.recoveryRequest._000=##################################### ++kratool.ldif.recoveryRequest._001=## KRA CA / TPS Recovery Request ## ++kratool.ldif.recoveryRequest._002=##################################### ++kratool.ldif.recoveryRequest.cn=true ++kratool.ldif.recoveryRequest.dateOfModify=true ++kratool.ldif.recoveryRequest.dn=true ++kratool.ldif.recoveryRequest.extdata.requestId=true ++kratool.ldif.recoveryRequest.extdata.requestNotes=true ++kratool.ldif.recoveryRequest.extdata.serialnumber=true ++kratool.ldif.recoveryRequest.requestId=true ++kratool.ldif.tpsKeyRecord._000=######################################### ++kratool.ldif.tpsKeyRecord._001=## KRA TPS Key Record ## ++kratool.ldif.tpsKeyRecord._002=######################################### ++kratool.ldif.tpsKeyRecord._003=## ## ++kratool.ldif.tpsKeyRecord._004=## NEVER allow 'KRATOOL' the ability ## ++kratool.ldif.tpsKeyRecord._005=## to change the TPS 'naming context' ## ++kratool.ldif.tpsKeyRecord._006=## data in the following fields: ## ++kratool.ldif.tpsKeyRecord._007=## ## ++kratool.ldif.tpsKeyRecord._008=## archivedBy ## ++kratool.ldif.tpsKeyRecord._009=## ## ++kratool.ldif.tpsKeyRecord._010=######################################### ++kratool.ldif.tpsKeyRecord.cn=true ++kratool.ldif.tpsKeyRecord.dateOfModify=true ++kratool.ldif.tpsKeyRecord.dn=true ++kratool.ldif.tpsKeyRecord.privateKeyData=true ++kratool.ldif.tpsKeyRecord.serialno=true ++kratool.ldif.tpsNetkeyKeygenRequest._000=##################################### ++kratool.ldif.tpsNetkeyKeygenRequest._001=## KRA TPS Netkey Keygen Request ## ++kratool.ldif.tpsNetkeyKeygenRequest._002=##################################### ++kratool.ldif.tpsNetkeyKeygenRequest._003=## ## ++kratool.ldif.tpsNetkeyKeygenRequest._004=## NEVER allow 'KRATOOL' the ## ++kratool.ldif.tpsNetkeyKeygenRequest._005=## ability to change the ## ++kratool.ldif.tpsNetkeyKeygenRequest._006=## TPS 'naming context' data in ## ++kratool.ldif.tpsNetkeyKeygenRequest._007=## the following fields: ## ++kratool.ldif.tpsNetkeyKeygenRequest._008=## ## ++kratool.ldif.tpsNetkeyKeygenRequest._009=## extdata-updatedby ## ++kratool.ldif.tpsNetkeyKeygenRequest._010=## ## ++kratool.ldif.tpsNetkeyKeygenRequest._011=##################################### ++kratool.ldif.tpsNetkeyKeygenRequest.cn=true ++kratool.ldif.tpsNetkeyKeygenRequest.dateOfModify=true ++kratool.ldif.tpsNetkeyKeygenRequest.dn=true ++kratool.ldif.tpsNetkeyKeygenRequest.extdata.keyRecord=true ++kratool.ldif.tpsNetkeyKeygenRequest.extdata.requestId=true ++kratool.ldif.tpsNetkeyKeygenRequest.extdata.requestNotes=true ++kratool.ldif.tpsNetkeyKeygenRequest.requestId=true ++.if ++ ++.SH EXAMPLES ++.PP ++The KRATool performs two operations: it can rewrap keys with a new private key, and it can renumber attributes in the LDIF file entries for key records, including enrollments and recovery requests. At least one operation (rewrap or renumber) must be performed and both can be performed in a single invocation. ++ ++.SS Rewrapping Keys ++.BR ++.PP ++When rewrapping keys, the tool needs to be able to access the original NSS databases for the source KRA and its storage certificate to unwrap the keys, as well as the storage certificate for the new KRA, which is used to rewrap the keys. ++.IP ++.nf ++KRATool -kratool_config_file "/usr/share/pki/java-tools/KRATool.cfg" -source_ldif_file "/tmp/files/originalKRA.ldif" -target_ldif_file "/tmp/files/newKRA.ldif" -log_file "/tmp/kratool.log" -source_pki_security_database_path "/tmp/files/" -source_storage_token_name "Internal Key Storage Token" -source_storage_certificate_nickname "storageCert cert-pki-kra" -target_storage_certificate_file "/tmp/files/omega.cert" ++.if ++ ++.SS Renumbering Keys ++.BR ++.PP ++When multiple KRA instances are being merged into a single instance, it is important to make sure that no key or request records have conflicting CNs, DNs, serial numbers, or request ID numbers. These values can be processed to append a new, larger number to the existing values. ++.PP ++For the CN, the new number is the addition of the original CN plus the appended number. For example, if the CN is 4 and the append number is 1000000, the new CN is 1000004. ++.PP ++For serial numbers and request IDs, the value is always a digit count plus the value. So a CN of 4 has a serial number of 014, or one digit and the CN value. If the append number is 1000000, the new serial number is 071000004, for seven digits and then the sum of the append number (1000000) and the original value (4). ++.IP ++.nf ++KRATool -kratool_config_file "/usr/share/pki/java-tools/KRATool.cfg" -source_ldif_file "/tmp/files/originalKRA.ldif" -target_ldif_file "/tmp/files/newKRA.ldif" -log_file "/tmp/kratool.log" -append_id_offset 100000000000 ++.if ++ ++.SS Restoring the Original Numbering ++.BR ++.PP ++If a number has been appended to key entries, as in the example entitled \fBRenumbering Keys\fP, that number can also be removed. Along with updating the CN, it also reconstructs any associated numbers, like serial numbers and request ID numbers. Undoing a renumbering action may be necessary if the original number wasn't large enough to prevent conflicts or as part of testing a migration or KRA consolidation process. ++.IP ++.nf ++KRATool -kratool_config_file "/usr/share/pki/java-tools/KRATool.cfg" -source_ldif_file "/tmp/files/originalKRA.ldif" -target_ldif_file "/tmp/files/newKRA.ldif" -log_file "/tmp/kratool.log" -remove_id_offset 100000000000 ++.if ++ ++.SS Renumbering and Rewrapping in a Single Command ++.BR ++.PP ++Rewrapping and renumbering operations can be performed in the same invocation. ++.IP ++.nf ++KRATool -kratool_config_file "/usr/share/pki/java-tools/KRATool.cfg" -source_ldif_file "/tmp/files/originalKRA.ldif" -target_ldif_file "/tmp/files/newKRA.ldif" -log_file "/tmp/kratool.log" -source_pki_security_database_path "/tmp/files/" -source_storage_token_name "Internal Key Storage Token" -source_storage_certificate_nickname "storageCert cert-pki-kra" -target_storage_certificate_file "/tmp/files/omega.cert" -append_id_offset 100000000000 ++.if ++ ++.SH AUTHORS ++Matthew Harmsen . ++ ++.SH COPYRIGHT ++Copyright (c) 2016 Red Hat, Inc. This is licensed under the GNU General Public ++License, version 2 (GPLv2). A copy of this license is available at ++http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. ++ ++.SH SEE ALSO ++.BR pki(1) +diff --git a/base/java-tools/man/man1/PrettyPrintCert.1 b/base/java-tools/man/man1/PrettyPrintCert.1 +new file mode 100644 +index 0000000..3cfb2f9 +--- /dev/null ++++ b/base/java-tools/man/man1/PrettyPrintCert.1 +@@ -0,0 +1,204 @@ ++.\" First parameter, NAME, should be all caps ++.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection ++.\" other parameters are allowed: see man(7), man(1) ++.TH PrettyPrintCert 1 "July 20, 2016" "version 10.3" "PKI Certificate Print Tool" Dogtag Team ++.\" Please adjust this date whenever revising the man page. ++.\" ++.\" Some roff macros, for reference: ++.\" .nh disable hyphenation ++.\" .hy enable hyphenation ++.\" .ad l left justify ++.\" .ad b justify to both left and right margins ++.\" .nf disable filling ++.\" .fi enable filling ++.\" .br insert line break ++.\" .sp insert n+1 empty lines ++.\" for man page specific macros, see man(7) ++.SH NAME ++PrettyPrintCert \- print the contents of a certificate stored as ASCII base-64 encoded data to a readable format. ++ ++.SH SYNOPSIS ++.PP ++\fBPrettyPrintCert [-simpleinfo] [output_file]\fP ++ ++.SH DESCRIPTION ++.PP ++The \fBPrettyPrintCert\fP command provides a command-line utility used to print the contents of a certificate stored as ASCII base-64 encoded data to a readable format. The output of this command is displayed to standard output, but can be optionally saved into a specified file. An additional non-mandatory option is available which limits the certificate information output of this command for easier parsing. ++ ++.SH OPTIONS ++.TP ++.B [-simpleinfo] ++\fBOptional\fP. Prints limited certificate information in an easy to parse format; if this option is not specified, the entire contents of the certificate will be printed. ++ ++.TP ++.B ++\fBMandatory\fP. Specifies the path to the file containing the ASCII base-64 encoded certificate. ++ ++.TP ++.B [output_file] ++\fBOptional\fP. Specifies the path to the file in which the tool should write the certificate. If this option is not specified, the certificate information is written to the standard output. ++ ++.SH EXAMPLES ++.PP ++The following example converts the ASCII base-64 encoded certificate in the \fBascii_data.cert\fP file and writes the certificate in the pretty-print form to the output file \fBcert.out\fP: ++.IP ++.nf ++PrettyPrintCert ascii_data.cert cert.out ++.if ++ ++.PP ++For this example, the base-64 encoded certificate data in the \fBascii_data.cert\fP looks like the following: ++.IP ++.nf ++-----BEGIN CERTIFICATE----- ++MIIECjCCAvKgAwIBAgIBCTANBgkqhkiG9w0BAQsFADBOMSswKQYDVQQKDCJ1c2Vy ++c3lzLnJlZGhhdC5jb20gU2VjdXJpdHkgRG9tYWluMR8wHQYDVQQDDBZDQSBTaWdu ++aW5nIENlcnRpZmljYXRlMB4XDTE2MDcyMjIwMzEzOFoXDTE3MDExODIxMzEzOFow ++gZwxCzAJBgNVBAYTAlVTMRwwGgYDVQQKDBNFeGFtcGxlIENvcnBvcmF0aW9uMQsw ++CQYDVQQLDAJJUzEpMCcGA1UEAwwgUHJldHR5UHJpbnRDZXJ0IFRlc3QgQ2VydGlm ++aWNhdGUxIDAeBgkqhkiG9w0BCQEWEWFkbWluQGV4YW1wbGUuY29tMRUwEwYKCZIm ++iZPyLGQBAQwFYWRtaW4wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDn ++Jv8ADWpC7C3Bzb13n9zQwaDW8YfyshZd7lXI0cghJOSfRLT6C10LOi1yhI+7W3NN ++MgYeLDCiRmKfHnqq6lpPg9aZmrxBwrn+30OdP+m1K6Crf6X9wqAWSR/r2hG4NuYi ++ovcJg7ani5h4BL+V0hbUvfEs4o7QfOWjQZcoo2KbOKmRrodAA21XVjWGB1ELQLNN ++hGwmZ6l1rtnN04Ruoclu8LaKMAAzFSH8cHEBtdCgxeDNy+bNnXbjO1wdruFNrars ++W6wdc230AvHRcEUWEvQVq86vHfS4UZ5q0N1ychibrHZXB0/+TUtyKDQGx0K7ELSB ++xgwt9QxEjKlXHiStcGupAgMBAAGjgaMwgaAwHwYDVR0jBBgwFoAUuzaYXWXLiOCH ++IzdvW/evi4rrurUwTgYIKwYBBQUHAQEEQjBAMD4GCCsGAQUFBzABhjJodHRwOi8v ++cGtpLWRlc2t0b3AudXNlcnN5cy5yZWRoYXQuY29tOjgwODAvY2Evb2NzcDAOBgNV ++HQ8BAf8EBAMCBeAwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMEMA0GCSqG ++SIb3DQEBCwUAA4IBAQCgQ/vTCyQ+lHKNDNCtvbul2l6V3Sjzvj0il9t4HtorxoBF ++3FIE6VNpUYFq0AkNS/LjV7ek7LRl8kuuiKaNpqF6RvAIPrABPDh7hE1Gi3Vm+Xw/ ++ndodT1AVII3x6xUbRsHu2iUVdZM5xO9ZFwA18nJUznL9q8lEGjj8vVCyFZuplUL+ ++pdKqL3SgBNUdyfiV6vywevI9jFoZBlsQbn4EjBs2nNeaFSZhZ1NG6tktSt85fJ51 ++IAiZv9Ipq0deHxFgpEywPq9lSrMZnm178PFlzRQUySHSm1pA+ngTydUKqZqAU0vr ++XIDTmj4lE93VPZspnPS94p/0OT4Pe3NKAe+IbIv/ ++-----END CERTIFICATE----- ++.if ++ ++.PP ++The certificate in pretty-print format in the \fBcert.out\fP file looks like the following: ++.IP ++.nf ++ Certificate: ++ Data: ++ Version: v3 ++ Serial Number: 0x9 ++ Signature Algorithm: SHA256withRSA - 1.2.840.113549.1.1.11 ++ Issuer: CN=CA Signing Certificate,O=example.com Security Domain ++ Validity: ++ Not Before: Friday, July 22, 2016 2:31:38 PM MDT America/Denver ++ Not After: Wednesday, January 18, 2017 2:31:38 PM MST America/Denver ++ Subject: UID=admin,E=admin@example.com,CN=PrettyPrintCert Test Certificate,OU=IS,O=Example Corporation,C=US ++ Subject Public Key Info: ++ Algorithm: RSA - 1.2.840.113549.1.1.1 ++ Public Key: ++ Exponent: 65537 ++ Public Key Modulus: (2048 bits) : ++ E7:26:FF:00:0D:6A:42:EC:2D:C1:CD:BD:77:9F:DC:D0: ++ C1:A0:D6:F1:87:F2:B2:16:5D:EE:55:C8:D1:C8:21:24: ++ E4:9F:44:B4:FA:0B:5D:0B:3A:2D:72:84:8F:BB:5B:73: ++ 4D:32:06:1E:2C:30:A2:46:62:9F:1E:7A:AA:EA:5A:4F: ++ 83:D6:99:9A:BC:41:C2:B9:FE:DF:43:9D:3F:E9:B5:2B: ++ A0:AB:7F:A5:FD:C2:A0:16:49:1F:EB:DA:11:B8:36:E6: ++ 22:A2:F7:09:83:B6:A7:8B:98:78:04:BF:95:D2:16:D4: ++ BD:F1:2C:E2:8E:D0:7C:E5:A3:41:97:28:A3:62:9B:38: ++ A9:91:AE:87:40:03:6D:57:56:35:86:07:51:0B:40:B3: ++ 4D:84:6C:26:67:A9:75:AE:D9:CD:D3:84:6E:A1:C9:6E: ++ F0:B6:8A:30:00:33:15:21:FC:70:71:01:B5:D0:A0:C5: ++ E0:CD:CB:E6:CD:9D:76:E3:3B:5C:1D:AE:E1:4D:AD:AA: ++ EC:5B:AC:1D:73:6D:F4:02:F1:D1:70:45:16:12:F4:15: ++ AB:CE:AF:1D:F4:B8:51:9E:6A:D0:DD:72:72:18:9B:AC: ++ 76:57:07:4F:FE:4D:4B:72:28:34:06:C7:42:BB:10:B4: ++ 81:C6:0C:2D:F5:0C:44:8C:A9:57:1E:24:AD:70:6B:A9 ++ Extensions: ++ Identifier: Authority Key Identifier - 2.5.29.35 ++ Critical: no ++ Key Identifier: ++ BB:36:98:5D:65:CB:88:E0:87:23:37:6F:5B:F7:AF:8B: ++ 8A:EB:BA:B5 ++ Identifier: 1.3.6.1.5.5.7.1.1 ++ Critical: no ++ Value: ++ 30:40:30:3E:06:08:2B:06:01:05:05:07:30:01:86:32: ++ 68:74:74:70:3A:2F:2F:70:6B:69:2D:64:65:73:6B:74: ++ 6F:70:2E:75:73:65:72:73:79:73:2E:72:65:64:68:61: ++ 74:2E:63:6F:6D:3A:38:30:38:30:2F:63:61:2F:6F:63: ++ 73:70 ++ Identifier: Key Usage: - 2.5.29.15 ++ Critical: yes ++ Key Usage: ++ Digital Signature ++ Non Repudiation ++ Key Encipherment ++ Identifier: Extended Key Usage: - 2.5.29.37 ++ Critical: no ++ Extended Key Usage: ++ 1.3.6.1.5.5.7.3.2 ++ 1.3.6.1.5.5.7.3.4 ++ Signature: ++ Algorithm: SHA256withRSA - 1.2.840.113549.1.1.11 ++ Signature: ++ A0:43:FB:D3:0B:24:3E:94:72:8D:0C:D0:AD:BD:BB:A5: ++ DA:5E:95:DD:28:F3:BE:3D:22:97:DB:78:1E:DA:2B:C6: ++ 80:45:DC:52:04:E9:53:69:51:81:6A:D0:09:0D:4B:F2: ++ E3:57:B7:A4:EC:B4:65:F2:4B:AE:88:A6:8D:A6:A1:7A: ++ 46:F0:08:3E:B0:01:3C:38:7B:84:4D:46:8B:75:66:F9: ++ 7C:3F:9D:DA:1D:4F:50:15:20:8D:F1:EB:15:1B:46:C1: ++ EE:DA:25:15:75:93:39:C4:EF:59:17:00:35:F2:72:54: ++ CE:72:FD:AB:C9:44:1A:38:FC:BD:50:B2:15:9B:A9:95: ++ 42:FE:A5:D2:AA:2F:74:A0:04:D5:1D:C9:F8:95:EA:FC: ++ B0:7A:F2:3D:8C:5A:19:06:5B:10:6E:7E:04:8C:1B:36: ++ 9C:D7:9A:15:26:61:67:53:46:EA:D9:2D:4A:DF:39:7C: ++ 9E:75:20:08:99:BF:D2:29:AB:47:5E:1F:11:60:A4:4C: ++ B0:3E:AF:65:4A:B3:19:9E:6D:7B:F0:F1:65:CD:14:14: ++ C9:21:D2:9B:5A:40:FA:78:13:C9:D5:0A:A9:9A:80:53: ++ 4B:EB:5C:80:D3:9A:3E:25:13:DD:D5:3D:9B:29:9C:F4: ++ BD:E2:9F:F4:39:3E:0F:7B:73:4A:01:EF:88:6C:8B:FF ++ FingerPrint ++ MD2: ++ EC:AE:A5:A3:E5:FA:30:3B:34:0E:FD:9D:ED:46:56:03 ++ MD5: ++ CB:E1:80:0C:B3:66:DF:CF:3A:2B:A9:C1:F4:88:88:23 ++ SHA-1: ++ B6:BA:84:0D:AE:4E:B0:CD:84:71:D8:A4:61:60:A7:2D: ++ 3A:7C:55:46 ++ SHA-256: ++ B2:95:9C:8C:B9:3C:7B:9F:FF:8E:BD:92:90:BC:75:F5: ++ BB:0D:96:2C:93:05:20:1B:4C:9D:B9:59:6F:54:25:5B ++ SHA-512: ++ B9:7A:1E:2E:59:8C:6F:76:F5:52:36:AD:A6:62:E9:DD: ++ 00:6E:82:7A:BA:38:1E:29:FC:F8:80:F1:DD:7C:81:92: ++ F1:C2:E3:34:27:1A:7A:EB:95:36:DB:65:41:A2:46:19: ++ FB:14:89:00:B5:8B:DB:AA:33:41:8C:6C:C4:75:CF:17 ++.if ++ ++.PP ++The following example command takes the same ASCII base-64 encoded certificate in the \fBascii_data.cert\fP file and writes the information contained within the certificate to the simple format output file \fBcert.simple\fP: ++.IP ++.nf ++PrettyPrintCert -simpleinfo ascii_data.cert cert.simple ++.if ++ ++.PP ++The simple certificate information in the \fBcert.simple\fP output file looks like the following: ++.IP ++.nf ++UID=admin ++E=admin@example.com ++CN=PrettyPrintCert Test Certificate ++OU=IS ++O=Example Corporation ++C=US ++.if ++ ++.SH AUTHORS ++Matthew Harmsen . ++ ++.SH COPYRIGHT ++Copyright (c) 2016 Red Hat, Inc. This is licensed under the GNU General Public ++License, version 2 (GPLv2). A copy of this license is available at ++http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. ++ ++.SH SEE ALSO ++.BR PrettyPrintCrl(1), pki(1) +diff --git a/base/java-tools/man/man1/PrettyPrintCrl.1 b/base/java-tools/man/man1/PrettyPrintCrl.1 +new file mode 100644 +index 0000000..31a73a0 +--- /dev/null ++++ b/base/java-tools/man/man1/PrettyPrintCrl.1 +@@ -0,0 +1,141 @@ ++.\" First parameter, NAME, should be all caps ++.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection ++.\" other parameters are allowed: see man(7), man(1) ++.TH PrettyPrintCrl 1 "July 20, 2016" "version 10.3" "PKI CRL Print Tool" Dogtag Team ++.\" Please adjust this date whenever revising the man page. ++.\" ++.\" Some roff macros, for reference: ++.\" .nh disable hyphenation ++.\" .hy enable hyphenation ++.\" .ad l left justify ++.\" .ad b justify to both left and right margins ++.\" .nf disable filling ++.\" .fi enable filling ++.\" .br insert line break ++.\" .sp insert n+1 empty lines ++.\" for man page specific macros, see man(7) ++.SH NAME ++PrettyPrintCrl \- reads a certificate revocation list (CRL) stored in an ASCII base-64 encoded file and outputs it in a readable format. ++ ++.SH SYNOPSIS ++.PP ++\fBPrettyPrintCrl [output_file]\fP ++ ++.SH DESCRIPTION ++.PP ++The \fBPrettyPrintCrl\fP command provides a command-line utility used to print the contents of a CRL stored as ASCII base-64 encoded data in a file to a readable format. The output of this command is displayed to standard output, but can be optionally saved into a specified file. ++ ++.SH OPTIONS ++.TP ++.B ++\fBMandatory\fP. Specifies the path to the file that contains the ASCII base-64 encoded CRL. ++ ++.TP ++.B [output_file] ++\fBOptional\fP. Specifies the path to the file to write the CRL. If the output file is not specified, the CRL information is written to the standard output. ++ ++.SH EXAMPLES ++.PP ++The following example \fBPrettyPrintCrl\fP command takes the ASCII base-64 encoded CRL in the \fBascii_data.crl\fP file and writes the CRL in the pretty-print format to the output file \fBcrl.out\fP: ++.IP ++.nf ++PrettyPrintCrl ascii_data.crl crl.out ++.if ++ ++.PP ++For this example, the base-64 encoded CRL data in the \fBascii_data.crl\fP looks like the following: ++.IP ++.nf ++-----BEGIN X509 CRL----- ++MIICVDCCATwCAQEwDQYJKoZIhvcNAQELBQAwTjErMCkGA1UECgwidXNlcnN5cy5y ++ZWRoYXQuY29tIFNlY3VyaXR5IERvbWFpbjEfMB0GA1UEAwwWQ0EgU2lnbmluZyBD ++ZXJ0aWZpY2F0ZRcNMTYwNzIyMjExMjUwWhcNMTYwNzIyMjMwMDAwWjCBiDAgAgEK ++Fw0xNjA3MjIyMDU1MTZaMAwwCgYDVR0VBAMKAQYwIAIBCRcNMTYwNzIyMjEwMTU2 ++WjAMMAoGA1UdFQQDCgEGMCACAQgXDTE2MDcyMjIxMTIyNVowDDAKBgNVHRUEAwoB ++ATAgAgEHFw0xNjA3MjIyMTAxNTZaMAwwCgYDVR0VBAMKAQagLzAtMB8GA1UdIwQY ++MBaAFLs2mF1ly4jghyM3b1v3r4uK67q1MAoGA1UdFAQDAgEKMA0GCSqGSIb3DQEB ++CwUAA4IBAQCjnwpdLVU4sg3GnOFQiHpBuWspevzj0poHQs9b4Uv17o0MC4irftkR ++zRBVgwLvdSd5WFEUSbhWVjhS4o4w84BXdmti/+UBS+mOVNxiKqs3Z7Fxcg+mCsiH ++SDWT3iiqZVqlPMOKDzIQGj4XeArSBK13qjNdwKzVJZlXYfwzdDtyVKBJcoETXGZ3 ++irU8RTXo7OhO6xKDAaHjzVVynjfGdIDaavl1fjwXFufwZBeiXm1zyyFSvDUdny4G ++29NTmM2945jCESeR7DV2q1LHG/v2rzCOKTWdPdXTPCics05KzUA4S6X+mp051wkh ++yJM2LYpV6lKV6JiczHLrgf5QcqfwSkTX ++-----END X509 CRL----- ++.if ++ ++.PP ++The CRL in pretty-print format in the \fBcrl.out\fP file looks like the following: ++.IP ++.nf ++ Certificate Revocation List: ++ Data: ++ Version: v2 ++ Signature Algorithm: SHA256withRSA - 1.2.840.113549.1.1.11 ++ Issuer: CN=CA Signing Certificate,O=example.com Security Domain ++ This Update: Friday, July 22, 2016 3:12:50 PM MDT America/Denver ++ Next Update: Friday, July 22, 2016 5:00:00 PM MDT America/Denver ++ Revoked Certificates: ++ Serial Number: 0xA ++ Revocation Date: Friday, July 22, 2016 2:55:16 PM MDT America/Denver ++ Extensions: ++ Identifier: Revocation Reason - 2.5.29.21 ++ Critical: no ++ Reason: CA_Compromise ++ Serial Number: 0x9 ++ Revocation Date: Friday, July 22, 2016 3:01:56 PM MDT America/Denver ++ Extensions: ++ Identifier: Revocation Reason - 2.5.29.21 ++ Critical: no ++ Reason: Affiliation_Changed ++ Serial Number: 0x8 ++ Revocation Date: Friday, July 22, 2016 3:12:25 PM MDT America/Denver ++ Extensions: ++ Identifier: Revocation Reason - 2.5.29.21 ++ Critical: no ++ Reason: Key_Compromise ++ Serial Number: 0x7 ++ Revocation Date: Friday, July 22, 2016 3:01:56 PM MDT America/Denver ++ Extensions: ++ Identifier: Revocation Reason - 2.5.29.21 ++ Critical: no ++ Reason: Certificate_Hold ++ Extensions: ++ Identifier: Authority Key Identifier - 2.5.29.35 ++ Critical: no ++ Key Identifier: ++ BB:36:98:5D:65:CB:88:E0:87:23:37:6F:5B:F7:AF:8B: ++ 8A:EB:BA:B5 ++ Identifier: CRL Number - 2.5.29.20 ++ Critical: no ++ Number: 10 ++ Signature: ++ Algorithm: SHA256withRSA - 1.2.840.113549.1.1.11 ++ Signature: ++ A3:9F:0A:5D:2D:55:38:B2:0D:C6:9C:E1:50:88:7A:41: ++ B9:6B:29:7A:FC:E3:D2:9A:07:42:CF:5B:E1:4B:F5:EE: ++ 8D:0C:0B:88:AB:7E:D9:11:CD:10:55:83:02:EF:75:27: ++ 79:58:51:14:49:B8:56:56:38:52:E2:8E:30:F3:80:57: ++ 76:6B:62:FF:E5:01:4B:E9:8E:54:DC:62:2A:AB:37:67: ++ B1:71:72:0F:A6:0A:C8:87:48:35:93:DE:28:AA:65:5A: ++ A5:3C:C3:8A:0F:32:10:1A:3E:17:78:0A:D2:04:AD:77: ++ AA:33:5D:C0:AC:D5:25:99:57:61:FC:33:74:3B:72:54: ++ A0:49:72:81:13:5C:66:77:8A:B5:3C:45:35:E8:EC:E8: ++ 4E:EB:12:83:01:A1:E3:CD:55:72:9E:37:C6:74:80:DA: ++ 6A:F9:75:7E:3C:17:16:E7:F0:64:17:A2:5E:6D:73:CB: ++ 21:52:BC:35:1D:9F:2E:06:DB:D3:53:98:CD:BD:E3:98: ++ C2:11:27:91:EC:35:76:AB:52:C7:1B:FB:F6:AF:30:8E: ++ 29:35:9D:3D:D5:D3:3C:28:9C:B3:4E:4A:CD:40:38:4B: ++ A5:FE:9A:9D:39:D7:09:21:C8:93:36:2D:8A:55:EA:52: ++ 95:E8:98:9C:CC:72:EB:81:FE:50:72:A7:F0:4A:44:D7 ++.if ++ ++.SH AUTHORS ++Matthew Harmsen . ++ ++.SH COPYRIGHT ++Copyright (c) 2016 Red Hat, Inc. This is licensed under the GNU General Public ++License, version 2 (GPLv2). A copy of this license is available at ++http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. ++ ++.SH SEE ALSO ++.BR PrettyPrintCert(1), pki(1) +-- +1.8.3.1 + + +From ad454dedb6ba7b5161f962fe65f78fb236c1a7fe Mon Sep 17 00:00:00 2001 +From: Ade Lee +Date: Tue, 2 Aug 2016 11:18:31 -0400 +Subject: [PATCH 76/96] Fix deployment issue + +Need to put pki_server_side_keygen in a conditional to avoid +breaking other subsystem deployments. + +Ticket 2418 +--- + base/server/python/pki/server/deployment/pkiparser.py | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/base/server/python/pki/server/deployment/pkiparser.py b/base/server/python/pki/server/deployment/pkiparser.py +index 622f87e..3e5d355 100644 +--- a/base/server/python/pki/server/deployment/pkiparser.py ++++ b/base/server/python/pki/server/deployment/pkiparser.py +@@ -941,8 +941,11 @@ class PKIConfigParser: + "tomcat" + self.mdict['PKI_WEBAPPS_NAME_SLOT'] = \ + "webapps" +- self.mdict['SERVER_KEYGEN_SLOT'] = \ +- self.mdict['pki_enable_server_side_keygen'] ++ ++ if self.mdict['pki_subsystem'] == "TPS": ++ self.mdict['SERVER_KEYGEN_SLOT'] = \ ++ self.mdict['pki_enable_server_side_keygen'] ++ + self.mdict['TOMCAT_CFG_SLOT'] = \ + self.mdict['pki_target_tomcat_conf'] + self.mdict['TOMCAT_INSTANCE_COMMON_LIB_SLOT'] = \ +-- +1.8.3.1 + + +From e6c426eb69e294207a657897fdce0a7b07e4c41d Mon Sep 17 00:00:00 2001 +From: "Endi S. Dewata" +Date: Tue, 2 Aug 2016 05:15:17 +0200 +Subject: [PATCH 77/96] Fixed problem creating links to PKI JAR files. + +The CMake create_symlink command fails if the link target does not +exist already. Since PKI JAR files may not exist at build time, the +commands to create the links to those files have been replaced with +the ln -sf command which will create the links regardless of the +targets' existence. + +https://fedorahosted.org/pki/ticket/2403 +--- + base/common/CMakeLists.txt | 8 ++++---- + base/server/CMakeLists.txt | 4 ++-- + 2 files changed, 6 insertions(+), 6 deletions(-) + +diff --git a/base/common/CMakeLists.txt b/base/common/CMakeLists.txt +index dc5cecf..d4b0d7f 100644 +--- a/base/common/CMakeLists.txt ++++ b/base/common/CMakeLists.txt +@@ -35,10 +35,10 @@ add_custom_command( + COMMAND ${CMAKE_COMMAND} -E create_symlink /usr/share/java/jaxb-api.jar lib/jaxb-api.jar + COMMAND ${CMAKE_COMMAND} -E create_symlink /usr/lib/java/jss4.jar lib/jss4.jar + COMMAND ${CMAKE_COMMAND} -E create_symlink /usr/share/java/ldapjdk.jar lib/ldapjdk.jar +- COMMAND ${CMAKE_COMMAND} -E create_symlink /usr/share/java/pki/pki-certsrv.jar lib/pki-certsrv.jar +- COMMAND ${CMAKE_COMMAND} -E create_symlink /usr/share/java/pki/pki-cmsutil.jar lib/pki-cmsutil.jar +- COMMAND ${CMAKE_COMMAND} -E create_symlink /usr/share/java/pki/pki-nsutil.jar lib/pki-nsutil.jar +- COMMAND ${CMAKE_COMMAND} -E create_symlink /usr/share/java/pki/pki-tools.jar lib/pki-tools.jar ++ COMMAND /usr/bin/ln -sf /usr/share/java/pki/pki-certsrv.jar ${CMAKE_CURRENT_BINARY_DIR}/lib/pki-certsrv.jar ++ COMMAND /usr/bin/ln -sf /usr/share/java/pki/pki-cmsutil.jar ${CMAKE_CURRENT_BINARY_DIR}/lib/pki-cmsutil.jar ++ COMMAND /usr/bin/ln -sf /usr/share/java/pki/pki-nsutil.jar ${CMAKE_CURRENT_BINARY_DIR}/lib/pki-nsutil.jar ++ COMMAND /usr/bin/ln -sf /usr/share/java/pki/pki-tools.jar ${CMAKE_CURRENT_BINARY_DIR}/lib/pki-tools.jar + COMMAND ${CMAKE_COMMAND} -E create_symlink ${RESTEASY_LIB}/resteasy-atom-provider.jar lib/resteasy-atom-provider.jar + COMMAND ${CMAKE_COMMAND} -E create_symlink ${RESTEASY_LIB}/resteasy-client.jar lib/resteasy-client.jar + COMMAND ${CMAKE_COMMAND} -E create_symlink ${RESTEASY_LIB}/resteasy-jackson-provider.jar lib/resteasy-jackson-provider.jar +diff --git a/base/server/CMakeLists.txt b/base/server/CMakeLists.txt +index 27470f3..be58c05 100644 +--- a/base/server/CMakeLists.txt ++++ b/base/server/CMakeLists.txt +@@ -45,7 +45,7 @@ add_custom_command( + COMMAND ${CMAKE_COMMAND} -E create_symlink /usr/lib/java/jss4.jar common/lib/jss4.jar + COMMAND ${CMAKE_COMMAND} -E create_symlink /usr/share/java/ldapjdk.jar common/lib/ldapjdk.jar + COMMAND ${CMAKE_COMMAND} -E create_symlink /usr/lib/java/nuxwdog.jar common/lib/nuxwdog.jar +- COMMAND ${CMAKE_COMMAND} -E create_symlink /usr/share/java/pki/pki-tomcat.jar common/lib/pki-tomcat.jar ++ COMMAND /usr/bin/ln -sf /usr/share/java/pki/pki-tomcat.jar ${CMAKE_CURRENT_BINARY_DIR}/common/lib/pki-tomcat.jar + COMMAND ${CMAKE_COMMAND} -E create_symlink ${RESTEASY_LIB}/resteasy-atom-provider.jar common/lib/resteasy-atom-provider.jar + COMMAND ${CMAKE_COMMAND} -E create_symlink ${RESTEASY_LIB}/resteasy-client.jar common/lib/resteasy-client.jar + COMMAND ${CMAKE_COMMAND} -E create_symlink ${RESTEASY_LIB}/resteasy-jackson-provider.jar common/lib/resteasy-jackson-provider.jar +@@ -53,7 +53,7 @@ add_custom_command( + COMMAND ${CMAKE_COMMAND} -E create_symlink ${RESTEASY_LIB}/jaxrs-api.jar common/lib/resteasy-jaxrs-api.jar + COMMAND ${CMAKE_COMMAND} -E create_symlink ${RESTEASY_LIB}/resteasy-jaxrs.jar common/lib/resteasy-jaxrs.jar + COMMAND ${CMAKE_COMMAND} -E create_symlink /usr/share/java/scannotation.jar common/lib/scannotation.jar +- COMMAND ${CMAKE_COMMAND} -E create_symlink /usr/lib/java/symkey.jar common/lib/symkey.jar ++ COMMAND /usr/bin/ln -sf /usr/lib/java/symkey.jar ${CMAKE_CURRENT_BINARY_DIR}/common/lib/symkey.jar + COMMAND ${CMAKE_COMMAND} -E create_symlink /usr/share/java/tomcatjss.jar common/lib/tomcatjss.jar + COMMAND ${CMAKE_COMMAND} -E create_symlink /usr/share/java/velocity.jar common/lib/velocity.jar + COMMAND ${CMAKE_COMMAND} -E create_symlink /usr/share/java/xerces-j2.jar common/lib/xerces-j2.jar +-- +1.8.3.1 + + +From c73f98926d6c3b5bd1fe5e6d7d1f48d5f4e77220 Mon Sep 17 00:00:00 2001 +From: Ade Lee +Date: Wed, 3 Aug 2016 23:55:53 -0400 +Subject: [PATCH 78/96] Add pkispawn option to disable Master CRL + +--- + base/ca/shared/conf/CS.cfg | 2 +- + base/server/config/pkislots.cfg | 1 + + base/server/etc/default.cfg | 1 + + base/server/python/pki/server/deployment/pkiparser.py | 4 ++++ + 4 files changed, 7 insertions(+), 1 deletion(-) + +diff --git a/base/ca/shared/conf/CS.cfg b/base/ca/shared/conf/CS.cfg +index 68e79a4..3beb45c 100644 +--- a/base/ca/shared/conf/CS.cfg ++++ b/base/ca/shared/conf/CS.cfg +@@ -578,7 +578,7 @@ ca.crl.MasterCRL.unexpectedExceptionLoopMax=10 + ca.crl.MasterCRL.class=com.netscape.ca.CRLIssuingPoint + ca.crl.MasterCRL.dailyUpdates=1:00 + ca.crl.MasterCRL.description=CA's complete Certificate Revocation List +-ca.crl.MasterCRL.enable=true ++ca.crl.MasterCRL.enable=[MASTER_CRL_ENABLE] + ca.crl.MasterCRL.enableCRLCache=true + ca.crl.MasterCRL.enableCRLUpdates=true + ca.crl.MasterCRL.enableCacheTesting=false +diff --git a/base/server/config/pkislots.cfg b/base/server/config/pkislots.cfg +index 3873b83..d806c1f 100644 +--- a/base/server/config/pkislots.cfg ++++ b/base/server/config/pkislots.cfg +@@ -1,6 +1,7 @@ + [Tomcat] + application_version=[APPLICATION_VERSION] + INSTALL_TIME_SLOT=[INSTALL_TIME] ++MASTER_CRL_ENABLE_SLOT=[MASTER_CRL_ENABLE] + NUXWDOG_JNI_PATH_SLOT=[NUXWDOG_JNI_PATH] + PKI_ADMIN_SECURE_PORT_SLOT=[PKI_ADMIN_SECURE_PORT] + PKI_ADMIN_SECURE_PORT_CONNECTOR_NAME_SLOT=[PKI_ADMIN_SECURE_PORT_CONNECTOR_NAME] +diff --git a/base/server/etc/default.cfg b/base/server/etc/default.cfg +index 24e4a43..cfbd289 100644 +--- a/base/server/etc/default.cfg ++++ b/base/server/etc/default.cfg +@@ -335,6 +335,7 @@ pki_ds_database=%(pki_instance_name)s-CA + pki_ds_hostname=%(pki_hostname)s + pki_subsystem_name=CA %(pki_hostname)s %(pki_https_port)s + pki_share_db=False ++pki_master_crl_enable=True + + # Default OCSP URI added by AuthInfoAccessExtDefault if the profile + # config is blank. If both are blank, the value is constructed +diff --git a/base/server/python/pki/server/deployment/pkiparser.py b/base/server/python/pki/server/deployment/pkiparser.py +index 3e5d355..115f3ca 100644 +--- a/base/server/python/pki/server/deployment/pkiparser.py ++++ b/base/server/python/pki/server/deployment/pkiparser.py +@@ -946,6 +946,10 @@ class PKIConfigParser: + self.mdict['SERVER_KEYGEN_SLOT'] = \ + self.mdict['pki_enable_server_side_keygen'] + ++ if self.mdict['pki_subsystem'] == "CA": ++ self.mdict['MASTER_CRL_ENABLE_SLOT'] = \ ++ self.mdict['pki_master_crl_enable'] ++ + self.mdict['TOMCAT_CFG_SLOT'] = \ + self.mdict['pki_target_tomcat_conf'] + self.mdict['TOMCAT_INSTANCE_COMMON_LIB_SLOT'] = \ +-- +1.8.3.1 + + +From d2e8c9c5fb54e39884ecf304a234f8cb52c5a40e Mon Sep 17 00:00:00 2001 +From: Christina Fu +Date: Thu, 4 Aug 2016 16:40:06 -0700 +Subject: [PATCH 79/96] Ticket#2428 broken request links for CA's system certs + in agent request viewing This patch fixes the issue that when an agent visit + one of the CA's system cert request records, exception is thrown. + +--- + .../cms/src/com/netscape/cms/servlet/profile/ProfileReviewServlet.java | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileReviewServlet.java b/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileReviewServlet.java +index 3cbf0f9..caf2cf1 100644 +--- a/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileReviewServlet.java ++++ b/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileReviewServlet.java +@@ -431,7 +431,7 @@ public class ProfileReviewServlet extends ProfileServlet { + defset.set(ARG_DEF_SYNTAX, defSyntax); + defset.set(ARG_DEF_CONSTRAINT, defConstraint); + defset.set(ARG_DEF_NAME, defValueName); +- defset.set(ARG_DEF_VAL, defValue); ++ defset.set(ARG_DEF_VAL, (defValue!=null)? defValue:""); + deflist.add(defset); + } + } +-- +1.8.3.1 + + +From 7702dae72b59a39b31b52640a9d1a4b5b6ca62ca Mon Sep 17 00:00:00 2001 +From: Geetika Kapoor +Date: Thu, 28 Jul 2016 02:59:40 -0400 +Subject: [PATCH 80/96] Fixed NumberFormatException in tps-cert-find + +Signed-off-by: Geetika Kapoor +--- + .../netscape/cmstools/tps/cert/TPSCertFindCLI.java | 20 ++++++++++++++++---- + 1 file changed, 16 insertions(+), 4 deletions(-) + +diff --git a/base/java-tools/src/com/netscape/cmstools/tps/cert/TPSCertFindCLI.java b/base/java-tools/src/com/netscape/cmstools/tps/cert/TPSCertFindCLI.java +index 9cbdad6..83c977b 100644 +--- a/base/java-tools/src/com/netscape/cmstools/tps/cert/TPSCertFindCLI.java ++++ b/base/java-tools/src/com/netscape/cmstools/tps/cert/TPSCertFindCLI.java +@@ -84,12 +84,24 @@ public class TPSCertFindCLI extends CLI { + String filter = cmdArgs.length > 0 ? cmdArgs[0] : null; + + String tokenID = cmd.getOptionValue("token"); ++ String string3 = cmd.getOptionValue("start"); ++ String string4 = cmd.getOptionValue("size"); ++ Integer start = null; ++ Integer size = null; + +- String s = cmd.getOptionValue("start"); +- Integer start = s == null ? null : Integer.valueOf(s); ++ try { ++ start = string3 == null ? null : Integer.valueOf(string3); ++ } catch (NumberFormatException e) { ++ System.err.println("Error: Invalid value for --start parameter: " + string3); ++ System.exit(-1); ++ } + +- s = cmd.getOptionValue("size"); +- Integer size = s == null ? null : Integer.valueOf(s); ++ try { ++ size = string4 == null ? null : Integer.valueOf(string4); ++ } catch (NumberFormatException e) { ++ System.err.println("Error: Invalid value for --size parameter: " + string4); ++ System.exit(-1); ++ } + + TPSCertCollection result = certCLI.certClient.findCerts(filter, tokenID, start, size); + +-- +1.8.3.1 + + +From 5178567bf5c65d23d3903b0956a47813bdc1fe23 Mon Sep 17 00:00:00 2001 +From: Abhijeet Kasurde +Date: Tue, 2 Aug 2016 16:46:29 +0530 +Subject: [PATCH 81/96] Added check for Subsystem data and request in + 'pki-server subsystem-cert-export' + +Partially fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1353245 + +Signed-off-by: Abhijeet Kasurde +--- + base/server/python/pki/server/cli/subsystem.py | 15 ++++++++++++--- + 1 file changed, 12 insertions(+), 3 deletions(-) + +diff --git a/base/server/python/pki/server/cli/subsystem.py b/base/server/python/pki/server/cli/subsystem.py +index a44243a..4651d74 100644 +--- a/base/server/python/pki/server/cli/subsystem.py ++++ b/base/server/python/pki/server/cli/subsystem.py +@@ -1,5 +1,6 @@ + # Authors: + # Endi S. Dewata ++# Abhijeet Kasurde + # + # 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 +@@ -14,7 +15,7 @@ + # 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. ++# Copyright (C) 2015-2016 Red Hat, Inc. + # All rights reserved. + # + +@@ -654,14 +655,22 @@ class SubsystemCertExportCLI(pki.cli.CLI): + sys.exit(1) + + if cert_file: ++ cert_data = subsystem_cert.get('data', None) ++ if cert_data is None: ++ print("ERROR: Unable to find certificate data for %s" % cert_id) ++ sys.exit(1) + +- cert_data = pki.nssdb.convert_cert(subsystem_cert['data'], 'base64', 'pem') ++ cert_data = pki.nssdb.convert_cert(cert_data, 'base64', 'pem') + with open(cert_file, 'w') as f: + f.write(cert_data) + + if csr_file: ++ cert_request = subsystem_cert.get('request', None) ++ if cert_request is None: ++ print("ERROR: Unable to find certificate request for %s" % cert_id) ++ sys.exit(1) + +- csr_data = pki.nssdb.convert_csr(subsystem_cert['request'], 'base64', 'pem') ++ csr_data = pki.nssdb.convert_csr(cert_request, 'base64', 'pem') + with open(csr_file, 'w') as f: + f.write(csr_data) + +-- +1.8.3.1 + + +From f0b1854a8f5cfe97d2d267ea16e4556d94666bb6 Mon Sep 17 00:00:00 2001 +From: Jack Magne +Date: Wed, 3 Aug 2016 18:01:23 -0700 +Subject: [PATCH 82/96] Fix to sort the output of a cert search by serialno. + +--- + .../src/com/netscape/certsrv/dbs/IDBSSession.java | 35 +++++++- + .../certsrv/dbs/certdb/ICertificateRepository.java | 27 ++++++ + .../com/netscape/cms/servlet/cert/SrchCerts.java | 4 +- + .../cmscore/dbs/CertificateRepository.java | 37 ++++++++- + .../src/com/netscape/cmscore/dbs/DBSSession.java | 97 +++++++++++++++++++--- + .../cmscore/dbs/DBSSessionDefaultStub.java | 15 +++- + 6 files changed, 197 insertions(+), 18 deletions(-) + +diff --git a/base/common/src/com/netscape/certsrv/dbs/IDBSSession.java b/base/common/src/com/netscape/certsrv/dbs/IDBSSession.java +index 6569505..9ab2fde 100644 +--- a/base/common/src/com/netscape/certsrv/dbs/IDBSSession.java ++++ b/base/common/src/com/netscape/certsrv/dbs/IDBSSession.java +@@ -17,11 +17,11 @@ + // --- END COPYRIGHT BLOCK --- + package com.netscape.certsrv.dbs; + ++import netscape.ldap.LDAPSearchResults; ++ + import com.netscape.certsrv.base.EBaseException; + import com.netscape.certsrv.base.ISubsystem; + +-import netscape.ldap.LDAPSearchResults; +- + /** + * An interface represents the database session. Operations + * can be performed with a session. +@@ -132,6 +132,21 @@ public interface IDBSSession extends AutoCloseable { + * @param base starting point of the search + * @param filter search filter + * @param maxSize max number of entries ++ * @param sortAttribute Field to sort the records on ++ * @return search results ++ * @exception EBaseException failed to search ++ */ ++ public IDBSearchResults search(String base, String filter, int maxSize,String sortAttribute) ++ throws EBaseException; ++ ++ ++ /** ++ * Searchs for a list of objects that match the ++ * filter. ++ * ++ * @param base starting point of the search ++ * @param filter search filter ++ * @param maxSize max number of entries + * @param timeLimit timeout limit + * @return search results + * @exception EBaseException failed to search +@@ -140,6 +155,22 @@ public interface IDBSSession extends AutoCloseable { + int timeLimit) throws EBaseException; + + /** ++ * Searchs for a list of objects that match the ++ * filter. ++ * ++ * @param base starting point of the search ++ * @param filter search filter ++ * @param maxSize max number of entries ++ * @param timeLimit timeout limit ++ * @param sortAttribute Field to sort the records on ++ * @return search results ++ * @exception EBaseException failed to search ++ */ ++ public IDBSearchResults search(String base, String filter, int maxSize, ++ int timeLimit, String sortAttribute) throws EBaseException; ++ ++ ++ /** + * Retrieves a list of object that satifies the given + * filter. + * +diff --git a/base/common/src/com/netscape/certsrv/dbs/certdb/ICertificateRepository.java b/base/common/src/com/netscape/certsrv/dbs/certdb/ICertificateRepository.java +index f113ea0..2efb023 100644 +--- a/base/common/src/com/netscape/certsrv/dbs/certdb/ICertificateRepository.java ++++ b/base/common/src/com/netscape/certsrv/dbs/certdb/ICertificateRepository.java +@@ -239,6 +239,33 @@ public interface ICertificateRepository extends IRepository { + * the filter. + * + * @param filter search filter ++ * @param maxSize max size to return ++ * @param timeLimit timeout value ++ * @param sortAttribute Attribute of ICertRecord to sort the results ++ * @return a list of certificates ++ * @exception EBaseException failed to search ++ */ ++ public Enumeration searchCertificates(String filter, int maxSize, ++ int timeLimit,String sortAttribute) throws EBaseException; ++ ++ /** ++ * Finds a list of certificate records that satisifies ++ * the filter. ++ * ++ * @param filter search filter ++ * @param maxSize max size to return ++ * @param sortAttribute Attribute of ICertRecord to sort the results ++ * @return a list of certificates ++ * @exception EBaseException failed to search ++ */ ++ public Enumeration searchCertificates(String filter, int maxSize, ++ String sortAttribute) throws EBaseException; ++ ++ /** ++ * Finds a list of certificate records that satisifies ++ * the filter. ++ * ++ * @param filter search filter + * @param attrs selected attribute + * @param pageSize page size + * @return a list of certificates +diff --git a/base/server/cms/src/com/netscape/cms/servlet/cert/SrchCerts.java b/base/server/cms/src/com/netscape/cms/servlet/cert/SrchCerts.java +index 508a8df..c55dfea 100644 +--- a/base/server/cms/src/com/netscape/cms/servlet/cert/SrchCerts.java ++++ b/base/server/cms/src/com/netscape/cms/servlet/cert/SrchCerts.java +@@ -608,7 +608,9 @@ public class SrchCerts extends CMSServlet { + } + CMS.debug("Start searching ... " + + "filter=" + filter + " maxreturns=" + maxResults + " timelimit=" + timeLimit); +- Enumeration e = mCertDB.searchCertificates(filter, maxResults, timeLimit); ++ ++ // Do the search with the optional sortAtribute field, giving an assured list of certs sorted by serialno ++ Enumeration e = mCertDB.searchCertificates(filter, maxResults, timeLimit, "serialno"); + + int count = 0; + +diff --git a/base/server/cmscore/src/com/netscape/cmscore/dbs/CertificateRepository.java b/base/server/cmscore/src/com/netscape/cmscore/dbs/CertificateRepository.java +index d0a604e..8406f36 100644 +--- a/base/server/cmscore/src/com/netscape/cmscore/dbs/CertificateRepository.java ++++ b/base/server/cmscore/src/com/netscape/cmscore/dbs/CertificateRepository.java +@@ -1124,7 +1124,7 @@ public class CertificateRepository extends Repository + ModificationSet mods = new ModificationSet(); + if (isAlreadyOnHold) { + mods.add(CertRecord.ATTR_REVO_INFO, Modification.MOD_REPLACE, info); +- } else { ++ } else { + mods.add(CertRecord.ATTR_REVO_INFO, Modification.MOD_ADD, info); + } + SessionContext ctx = SessionContext.getContext(); +@@ -1190,6 +1190,21 @@ public class CertificateRepository extends Repository + modifyCertificateRecord(id, mods); + } + ++ public Enumeration searchCertificates(String filter, int maxSize,String sortAttribute) ++ throws EBaseException { ++ IDBSSession s = mDBService.createSession(); ++ Enumeration e = null; ++ ++ CMS.debug("searchCertificates filter " + filter + " maxSize " + maxSize); ++ try { ++ e = s.search(getDN(), filter, maxSize,sortAttribute); ++ } finally { ++ if (s != null) ++ s.close(); ++ } ++ return e; ++ } ++ + public Enumeration searchCertificates(String filter, int maxSize) + throws EBaseException { + IDBSSession s = mDBService.createSession(); +@@ -1223,6 +1238,26 @@ public class CertificateRepository extends Repository + return v.elements(); + } + ++ public Enumeration searchCertificates(String filter, int maxSize, ++ int timeLimit,String sortAttribute) throws EBaseException { ++ IDBSSession s = mDBService.createSession(); ++ Vector v = new Vector(); ++ ++ CMS.debug("searchCertificateswith time limit filter " + filter); ++ try { ++ IDBSearchResults sr = s.search(getDN(), filter, maxSize, timeLimit,sortAttribute); ++ while (sr.hasMoreElements()) { ++ v.add((ICertRecord) sr.nextElement()); ++ } ++ } finally { ++ if (s != null) ++ s.close(); ++ } ++ return v.elements(); ++ ++ } ++ ++ + /** + * Returns a list of X509CertImp that satisfies the filter. + * +diff --git a/base/server/cmscore/src/com/netscape/cmscore/dbs/DBSSession.java b/base/server/cmscore/src/com/netscape/cmscore/dbs/DBSSession.java +index 2bfd5f2..853dfe4 100644 +--- a/base/server/cmscore/src/com/netscape/cmscore/dbs/DBSSession.java ++++ b/base/server/cmscore/src/com/netscape/cmscore/dbs/DBSSession.java +@@ -19,6 +19,20 @@ package com.netscape.cmscore.dbs; + + import java.util.Enumeration; + ++import netscape.ldap.LDAPAttribute; ++import netscape.ldap.LDAPAttributeSet; ++import netscape.ldap.LDAPConnection; ++import netscape.ldap.LDAPEntry; ++import netscape.ldap.LDAPException; ++import netscape.ldap.LDAPModification; ++import netscape.ldap.LDAPModificationSet; ++import netscape.ldap.LDAPSearchConstraints; ++import netscape.ldap.LDAPSearchResults; ++import netscape.ldap.LDAPSortKey; ++import netscape.ldap.LDAPv2; ++import netscape.ldap.controls.LDAPPersistSearchControl; ++import netscape.ldap.controls.LDAPSortControl; ++ + import com.netscape.certsrv.apps.CMS; + import com.netscape.certsrv.base.EBaseException; + import com.netscape.certsrv.base.ISubsystem; +@@ -34,18 +48,6 @@ import com.netscape.certsrv.dbs.Modification; + import com.netscape.certsrv.dbs.ModificationSet; + import com.netscape.certsrv.logging.ILogger; + +-import netscape.ldap.LDAPAttribute; +-import netscape.ldap.LDAPAttributeSet; +-import netscape.ldap.LDAPConnection; +-import netscape.ldap.LDAPEntry; +-import netscape.ldap.LDAPException; +-import netscape.ldap.LDAPModification; +-import netscape.ldap.LDAPModificationSet; +-import netscape.ldap.LDAPSearchConstraints; +-import netscape.ldap.LDAPSearchResults; +-import netscape.ldap.LDAPv2; +-import netscape.ldap.controls.LDAPPersistSearchControl; +- + /** + * A class represents the database session. Operations + * can be performed with a session. +@@ -295,6 +297,40 @@ public class DBSSession implements IDBSSession { + } + + @SuppressWarnings("unchecked") ++ public IDBSearchResults search(String base, String filter, int maxSize,String sortAttribute) ++ throws EBaseException { ++ try { ++ String ldapattrs[] = null; ++ String ldapfilter = ++ mDBSystem.getRegistry().getFilter(filter); ++ ++ LDAPSearchConstraints cons = new LDAPSearchConstraints(); ++ ++ cons.setMaxResults(maxSize); ++ ++ if(sortAttribute != null) { ++ LDAPSortKey sortOrder = new LDAPSortKey( sortAttribute ); ++ LDAPSortControl sortCtrl = new LDAPSortControl(sortOrder,true); ++ cons.setServerControls( sortCtrl ); ++ } ++ ++ LDAPSearchResults res = mConn.search(base, ++ LDAPv2.SCOPE_ONE, ldapfilter, ldapattrs, false, cons); ++ ++ return new DBSearchResults(mDBSystem.getRegistry(), ++ res); ++ } catch (LDAPException e) { ++ if (e.getLDAPResultCode() == LDAPException.UNAVAILABLE) ++ throw new EDBNotAvailException( ++ CMS.getUserMessage("CMS_DBS_INTERNAL_DIR_UNAVAILABLE")); ++ // XXX error handling, should not raise exception if ++ // entry not found ++ throw new EDBException(CMS.getUserMessage("CMS_DBS_LDAP_OP_FAILURE", ++ e.toString())); ++ } ++ } ++ ++ @SuppressWarnings("unchecked") + public IDBSearchResults search(String base, String filter, int maxSize, int timeLimit) + throws EBaseException { + try { +@@ -323,6 +359,43 @@ public class DBSSession implements IDBSSession { + } + } + ++ @SuppressWarnings("unchecked") ++ public IDBSearchResults search(String base, String filter, int maxSize, ++ int timeLimit, String sortAttribute) throws EBaseException { ++ ++ try { ++ String ldapattrs[] = null; ++ String ldapfilter = ++ mDBSystem.getRegistry().getFilter(filter); ++ ++ LDAPSearchConstraints cons = new LDAPSearchConstraints(); ++ ++ cons.setMaxResults(maxSize); ++ cons.setServerTimeLimit(timeLimit); ++ ++ if(sortAttribute != null) { ++ LDAPSortKey sortOrder = new LDAPSortKey( sortAttribute ); ++ LDAPSortControl sortCtrl = new LDAPSortControl(sortOrder,true); ++ cons.setServerControls( sortCtrl ); ++ } ++ ++ LDAPSearchResults res = mConn.search(base, ++ LDAPv2.SCOPE_ONE, ldapfilter, ldapattrs, false, cons); ++ ++ return new DBSearchResults(mDBSystem.getRegistry(), ++ res); ++ } catch (LDAPException e) { ++ if (e.getLDAPResultCode() == LDAPException.UNAVAILABLE) ++ throw new EDBNotAvailException( ++ CMS.getUserMessage("CMS_DBS_INTERNAL_DIR_UNAVAILABLE")); ++ // XXX error handling, should not raise exception if ++ // entry not found ++ throw new EDBException(CMS.getUserMessage("CMS_DBS_LDAP_OP_FAILURE", ++ e.toString())); ++ } ++ ++ } ++ + /** + * Retrieves a list of object that satifies the given + * filter. +diff --git a/base/server/test/com/netscape/cmscore/dbs/DBSSessionDefaultStub.java b/base/server/test/com/netscape/cmscore/dbs/DBSSessionDefaultStub.java +index e4e7157..8d7bbc0 100644 +--- a/base/server/test/com/netscape/cmscore/dbs/DBSSessionDefaultStub.java ++++ b/base/server/test/com/netscape/cmscore/dbs/DBSSessionDefaultStub.java +@@ -1,5 +1,7 @@ + package com.netscape.cmscore.dbs; + ++import netscape.ldap.LDAPSearchResults; ++ + import com.netscape.certsrv.base.EBaseException; + import com.netscape.certsrv.base.ISubsystem; + import com.netscape.certsrv.dbs.EDBException; +@@ -9,8 +11,6 @@ import com.netscape.certsrv.dbs.IDBSearchResults; + import com.netscape.certsrv.dbs.IDBVirtualList; + import com.netscape.certsrv.dbs.ModificationSet; + +-import netscape.ldap.LDAPSearchResults; +- + /** + * A default stub ojbect for tests to extend. + */ +@@ -81,4 +81,15 @@ public class DBSSessionDefaultStub implements IDBSSession { + String sortKey, int pageSize) throws EBaseException { + return null; + } ++ ++ @Override ++ public IDBSearchResults search(String base, String filter, int maxSize, int timeLimit, String sortAttribute) ++ throws EBaseException { ++ return null; ++ } ++ ++ @Override ++ public IDBSearchResults search(String base, String filter, int maxSize, String sortAttribute) throws EBaseException { ++ return null; ++ } + } +-- +1.8.3.1 + + +From f726f9a668b523c4e5a9438d8ea301f4b556efd4 Mon Sep 17 00:00:00 2001 +From: "Endi S. Dewata" +Date: Mon, 1 Aug 2016 22:35:32 +0200 +Subject: [PATCH 83/96] Added log messages for certificate validation. + +The ConfigCertApprovalCallback has been modified such that it +logs the server certificate being validated and can be configured +to ignore certain validation errors. + +The ConfigurationUtils has been modified to use the +ConfigCertApprovalCallback to show and validate the server +certificate in all GET and POST operations except for the +importCertChain() in which the code needs to ignore untrusted +issuer in order to get the certificate chain via SSL. + +https://fedorahosted.org/pki/ticket/2424 +--- + .../csadmin/ConfigCertApprovalCallback.java | 63 +++++++++++++++++++++- + .../cms/servlet/csadmin/ConfigurationUtils.java | 63 ++++++++++++---------- + 2 files changed, 97 insertions(+), 29 deletions(-) + +diff --git a/base/server/cms/src/com/netscape/cms/servlet/csadmin/ConfigCertApprovalCallback.java b/base/server/cms/src/com/netscape/cms/servlet/csadmin/ConfigCertApprovalCallback.java +index 956c285..9b741af 100644 +--- a/base/server/cms/src/com/netscape/cms/servlet/csadmin/ConfigCertApprovalCallback.java ++++ b/base/server/cms/src/com/netscape/cms/servlet/csadmin/ConfigCertApprovalCallback.java +@@ -17,17 +17,78 @@ + // --- END COPYRIGHT BLOCK --- + package com.netscape.cms.servlet.csadmin; + ++import java.lang.reflect.Field; ++import java.lang.reflect.Modifier; ++import java.util.Enumeration; ++import java.util.HashSet; ++import java.util.Set; ++ + import org.mozilla.jss.crypto.X509Certificate; + import org.mozilla.jss.ssl.SSLCertificateApprovalCallback; + ++import com.netscape.certsrv.apps.CMS; ++ + public class ConfigCertApprovalCallback + implements SSLCertificateApprovalCallback { + ++ public Set ignoredErrors = new HashSet(); ++ + public ConfigCertApprovalCallback() { + } + ++ public void ignoreError(int error) { ++ ignoredErrors.add(error); ++ } ++ ++ public String getErrorDescription(int reason) { ++ ++ // iterate through all constants in ValidityStatus ++ for (Field f : ValidityStatus.class.getDeclaredFields()) { ++ int mod = f.getModifiers(); ++ if (Modifier.isPublic(mod) && ++ Modifier.isFinal(mod) && ++ Modifier.isStatic(mod)) { ++ ++ try { ++ int value = f.getInt(null); ++ ++ // if value matches the reason, return the name ++ if (value == reason) { ++ return f.getName(); ++ } ++ ++ } catch (IllegalAccessException e) { ++ return "ERROR #" + reason; ++ } ++ } ++ } ++ ++ return "UNKNOWN_ERROR"; ++ } ++ + public boolean approve(X509Certificate cert, + SSLCertificateApprovalCallback.ValidityStatus status) { +- return true; ++ ++ CMS.debug("Server certificate:"); ++ CMS.debug(" - subject: " + cert.getSubjectDN()); ++ CMS.debug(" - issuer: " + cert.getIssuerDN()); ++ ++ Enumeration errors = status.getReasons(); ++ boolean result = true; ++ ++ while (errors.hasMoreElements()) { ++ SSLCertificateApprovalCallback.ValidityItem item = (SSLCertificateApprovalCallback.ValidityItem) errors.nextElement(); ++ int reason = item.getReason(); ++ String description = getErrorDescription(reason); ++ ++ if (ignoredErrors.contains(reason)) { ++ CMS.debug("WARNING: " + description); ++ } else { ++ CMS.debug("ERROR: " + description); ++ result = false; ++ } ++ } ++ ++ return result; + } + } +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 ab5e4d6..fe65bb8 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 +@@ -58,34 +58,6 @@ 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; +@@ -131,6 +103,7 @@ import org.mozilla.jss.pkix.primitive.Attribute; + import org.mozilla.jss.pkix.primitive.EncryptedPrivateKeyInfo; + import org.mozilla.jss.pkix.primitive.PrivateKeyInfo; + import org.mozilla.jss.ssl.SSLCertificateApprovalCallback; ++import org.mozilla.jss.ssl.SSLCertificateApprovalCallback.ValidityStatus; + import org.mozilla.jss.util.IncorrectPasswordException; + import org.mozilla.jss.util.Password; + import org.w3c.dom.Document; +@@ -180,6 +153,34 @@ 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. + * +@@ -196,6 +197,8 @@ public class ConfigurationUtils { + public static final Long MINUS_ONE = Long.valueOf(-1); + public static final String DBUSER = "pkidbuser"; + ++ public static ConfigCertApprovalCallback certApprovalCallback = new ConfigCertApprovalCallback(); ++ + public static boolean loginToken(CryptoToken token, String tokPwd) throws TokenException, + IncorrectPasswordException { + boolean rv = true; +@@ -229,6 +232,7 @@ public class ConfigurationUtils { + + CMS.debug("ConfigurationUtils: GET " + config.getServerURI() + path); + PKIConnection connection = new PKIConnection(config); ++ if (certApprovalCallback == null) certApprovalCallback = ConfigurationUtils.certApprovalCallback; + connection.setCallback(certApprovalCallback); + return connection.get(path); + } +@@ -245,6 +249,7 @@ public class ConfigurationUtils { + + CMS.debug("ConfigurationUtils: POST " + config.getServerURI() + path); + PKIConnection connection = new PKIConnection(config); ++ if (certApprovalCallback == null) certApprovalCallback = ConfigurationUtils.certApprovalCallback; + connection.setCallback(certApprovalCallback); + return connection.post(path, content); + } +@@ -256,6 +261,8 @@ public class ConfigurationUtils { + + IConfigStore cs = CMS.getConfigStore(); + ConfigCertApprovalCallback certApprovalCallback = new ConfigCertApprovalCallback(); ++ // Ignore untrusted issuer to get cert chain. ++ certApprovalCallback.ignoreError(ValidityStatus.UNTRUSTED_ISSUER); + String c = get(host, port, true, serverPath, null, certApprovalCallback); + + if (c != null) { +-- +1.8.3.1 + + +From da66600e8ae07fa4169d24909c7d04ed69d2906c Mon Sep 17 00:00:00 2001 +From: "Endi S. Dewata" +Date: Mon, 1 Aug 2016 22:35:32 +0200 +Subject: [PATCH 84/96] Added log messages for certificate import during + cloning. + +To help troubleshooting cloning issues the security_databases.py +has been modified to log the content of the PKCS #12 file before +import and the NSS database after import. + +https://fedorahosted.org/pki/ticket/2424 +--- + base/common/python/pki/nssdb.py | 10 +++ + base/common/python/pki/pkcs12.py | 73 ++++++++++++++++++++++ + .../deployment/scriptlets/security_databases.py | 42 ++++++++++--- + 3 files changed, 118 insertions(+), 7 deletions(-) + create mode 100644 base/common/python/pki/pkcs12.py + +diff --git a/base/common/python/pki/nssdb.py b/base/common/python/pki/nssdb.py +index a0b0302..ed45654 100644 +--- a/base/common/python/pki/nssdb.py ++++ b/base/common/python/pki/nssdb.py +@@ -398,6 +398,16 @@ class NSSDatabase(object): + if rc: + raise Exception('Failed to generate self-signed CA certificate. RC: %d' % rc) + ++ def show_certs(self): ++ ++ cmd = [ ++ 'certutil', ++ '-L', ++ '-d', self.directory ++ ] ++ ++ subprocess.check_call(cmd) ++ + def get_cert(self, nickname, output_format='pem'): + + if output_format == 'pem': +diff --git a/base/common/python/pki/pkcs12.py b/base/common/python/pki/pkcs12.py +new file mode 100644 +index 0000000..a62ca09 +--- /dev/null ++++ b/base/common/python/pki/pkcs12.py +@@ -0,0 +1,73 @@ ++# Authors: ++# Endi S. Dewata ++# ++# This program is free software; you can redistribute it and/or modify ++# it under the terms of the Lesser GNU General Public License as published by ++# the Free Software Foundation; either version 3 of the License or ++# (at your option) any later version. ++# ++# 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 Lesser General Public License for more details. ++# ++# You should have received a copy of the GNU Lesser 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) 2016 Red Hat, Inc. ++# All rights reserved. ++# ++ ++from __future__ import absolute_import ++import os ++import shutil ++import subprocess ++import tempfile ++ ++ ++class PKCS12(object): ++ ++ def __init__(self, path, password=None, password_file=None, nssdb=None): ++ ++ # The pki CLI needs an NSS database to run PKCS #12 operations ++ # as required by JSS. If the nssdb parameter is provided, the CLI ++ # will use the specified NSS database object. Otherwise, it will use ++ # the default NSS database in ~/.dogtag/nssdb. ++ ++ self.path = path ++ self.nssdb = nssdb ++ ++ self.tmpdir = tempfile.mkdtemp() ++ ++ if password: ++ self.password_file = os.path.join(self.tmpdir, 'password.txt') ++ with open(self.password_file, 'w') as f: ++ f.write(password) ++ ++ elif password_file: ++ self.password_file = password_file ++ ++ else: ++ raise Exception('Missing PKCS #12 password') ++ ++ def close(self): ++ shutil.rmtree(self.tmpdir) ++ ++ def show_certs(self): ++ ++ cmd = ['pki'] ++ ++ if self.nssdb: ++ cmd.extend([ ++ '-d', self.nssdb.directory, ++ '-C', self.nssdb.password_file ++ ]) ++ ++ cmd.extend([ ++ 'pkcs12-cert-find', ++ '--pkcs12-file', self.path, ++ '--pkcs12-password-file', self.password_file ++ ]) ++ ++ subprocess.check_call(cmd) +diff --git a/base/server/python/pki/server/deployment/scriptlets/security_databases.py b/base/server/python/pki/server/deployment/scriptlets/security_databases.py +index 18fc3e1..99daf15 100644 +--- a/base/server/python/pki/server/deployment/scriptlets/security_databases.py ++++ b/base/server/python/pki/server/deployment/scriptlets/security_databases.py +@@ -19,9 +19,11 @@ + # + + from __future__ import absolute_import ++from __future__ import print_function + + import os + import pki.nssdb ++import pki.pkcs12 + import pki.server + + # PKI Deployment Imports +@@ -104,9 +106,12 @@ class PkiScriptlet(pkiscriptlet.AbstractBasePkiScriptlet): + directory=deployer.mdict['pki_database_path'], + password_file=deployer.mdict['pki_shared_pfile']) + +- nssdb.import_pkcs12( +- pkcs12_file=pki_server_pkcs12_path, +- pkcs12_password=pki_server_pkcs12_password) ++ try: ++ nssdb.import_pkcs12( ++ pkcs12_file=pki_server_pkcs12_path, ++ pkcs12_password=pki_server_pkcs12_password) ++ finally: ++ nssdb.close() + + # update external CA file (if needed) + external_certs_path = deployer.mdict['pki_server_external_certs_path'] +@@ -127,10 +132,33 @@ class PkiScriptlet(pkiscriptlet.AbstractBasePkiScriptlet): + directory=deployer.mdict['pki_database_path'], + password_file=deployer.mdict['pki_shared_pfile']) + +- nssdb.import_pkcs12( +- pkcs12_file=pki_clone_pkcs12_path, +- pkcs12_password=pki_clone_pkcs12_password, +- no_user_certs=True) ++ try: ++ print('Importing certificates from %s:' % pki_clone_pkcs12_path) ++ ++ # The PKCS12 class requires an NSS database to run. For simplicity ++ # it uses the NSS database that has just been created. ++ pkcs12 = pki.pkcs12.PKCS12( ++ path=pki_clone_pkcs12_path, ++ password=pki_clone_pkcs12_password, ++ nssdb=nssdb) ++ ++ try: ++ pkcs12.show_certs() ++ finally: ++ pkcs12.close() ++ ++ # Import certificates ++ nssdb.import_pkcs12( ++ pkcs12_file=pki_clone_pkcs12_path, ++ pkcs12_password=pki_clone_pkcs12_password, ++ no_user_certs=True) ++ ++ print('Imported certificates in %s:' % deployer.mdict['pki_database_path']) ++ ++ nssdb.show_certs() ++ ++ finally: ++ nssdb.close() + + if len(deployer.instance.tomcat_instance_subsystems()) < 2: + +-- +1.8.3.1 + + +From b7d4f6e9efd8b2e7d26a001f6c18a10b82df6b56 Mon Sep 17 00:00:00 2001 +From: "Endi S. Dewata" +Date: Mon, 1 Aug 2016 22:35:32 +0200 +Subject: [PATCH 85/96] Fixed PKCS #12 import for cloning. + +To fix cloning issue in IPA the security_database.py has been +modified to import all certificates and keys in the PKCS #12 file +before the PKI server is started. Since the PKCS #12 generated by +IPA may not contain the certificate trust flags, the script will +also reset the trust flags on the imported certificates (i.e. +CT,C,C for CA certificate and u,u,Pu for audit certificate). + +The ConfigurationUtils.restoreCertsFromP12() is now redundant and +it should be removed in the future, but for now it has been +modified to set the same trust flags on imported certificates. + +The CryptoUtil.importCertificateChain() has also been modified to +set the same trust flags on imported certificates. + +https://fedorahosted.org/pki/ticket/2424 +--- + .../cms/servlet/csadmin/ConfigurationUtils.java | 9 +++- + .../deployment/scriptlets/security_databases.py | 13 ++++- + .../com/netscape/cmsutil/crypto/CryptoUtil.java | 60 ++++++++++++---------- + 3 files changed, 51 insertions(+), 31 deletions(-) + +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 fe65bb8..3494882 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 +@@ -834,7 +834,8 @@ public class ConfigurationUtils { + BadPaddingException, NotInitializedException, NicknameConflictException, UserCertConflictException, + NoSuchItemOnTokenException, InvalidBERException, IOException { + +- // TODO: refactor into a PKCS #12 utility class ++ // TODO: The PKCS #12 file is already imported in security_database.py. ++ // This method should be removed. + + byte b[] = new byte[1000000]; + FileInputStream fis = new FileInputStream(p12File); +@@ -1109,10 +1110,14 @@ public class ConfigurationUtils { + InternalCertificate icert = (InternalCertificate) xcert; + + if (isCASigningCert) { +- // we need to change the trust attribute to CT ++ // set trust flags to CT,C,C + icert.setSSLTrust(InternalCertificate.TRUSTED_CA + | InternalCertificate.TRUSTED_CLIENT_CA + | InternalCertificate.VALID_CA); ++ icert.setEmailTrust(InternalCertificate.TRUSTED_CA ++ | InternalCertificate.VALID_CA); ++ icert.setObjectSigningTrust(InternalCertificate.TRUSTED_CA ++ | InternalCertificate.VALID_CA); + + } else if (isAuditSigningCert(name)) { + icert.setObjectSigningTrust(InternalCertificate.USER +diff --git a/base/server/python/pki/server/deployment/scriptlets/security_databases.py b/base/server/python/pki/server/deployment/scriptlets/security_databases.py +index 99daf15..e80a1d0 100644 +--- a/base/server/python/pki/server/deployment/scriptlets/security_databases.py ++++ b/base/server/python/pki/server/deployment/scriptlets/security_databases.py +@@ -150,8 +150,17 @@ class PkiScriptlet(pkiscriptlet.AbstractBasePkiScriptlet): + # Import certificates + nssdb.import_pkcs12( + pkcs12_file=pki_clone_pkcs12_path, +- pkcs12_password=pki_clone_pkcs12_password, +- no_user_certs=True) ++ pkcs12_password=pki_clone_pkcs12_password) ++ ++ # Set certificate trust flags ++ if subsystem.type == 'CA': ++ nssdb.modify_cert( ++ nickname=deployer.mdict['pki_ca_signing_nickname'], ++ trust_attributes='CTu,Cu,Cu') ++ ++ nssdb.modify_cert( ++ nickname=deployer.mdict['pki_audit_signing_nickname'], ++ trust_attributes='u,u,Pu') + + print('Imported certificates in %s:' % deployer.mdict['pki_database_path']) + +diff --git a/base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java b/base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java +index 9cabdc5..b02c363 100644 +--- a/base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java ++++ b/base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java +@@ -47,33 +47,6 @@ import java.util.Random; + import java.util.StringTokenizer; + import java.util.Vector; + +-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; + import org.mozilla.jss.NoSuchTokenException; +@@ -132,6 +105,33 @@ 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 { + +@@ -1164,10 +1164,16 @@ public class CryptoUtil { + if (certchains != null) { + cert = certchains[certchains.length - 1]; + } ++ ++ // set trust flags to CT,C,C + InternalCertificate icert = (InternalCertificate) cert; + icert.setSSLTrust(InternalCertificate.TRUSTED_CA + | InternalCertificate.TRUSTED_CLIENT_CA + | InternalCertificate.VALID_CA); ++ icert.setEmailTrust(InternalCertificate.TRUSTED_CA ++ | InternalCertificate.VALID_CA); ++ icert.setObjectSigningTrust(InternalCertificate.TRUSTED_CA ++ | InternalCertificate.VALID_CA); + } + + public static SEQUENCE parseCRMFMsgs(byte cert_request[]) +-- +1.8.3.1 + + +From 018b5c1f3295fadd263d256d00866dd7b9d31163 Mon Sep 17 00:00:00 2001 +From: Fraser Tweedale +Date: Tue, 26 Jul 2016 14:07:10 +1000 +Subject: [PATCH 90/96] Fix CA OCSP responder when LWCAs are not in use + +The CA subsystem OCSP responder was updated to handle dispatching +OCSP requests to the relevant CertificateAuthority instance, +according to the issuer of the certificates identified in the +request. Unfortunately, the updated routine assumes that the +database updates that enable lightweight CAs have occurred. If they +have not, the OCSP responder always fails. + +Fix the issue by inferring that if 'caMap' is empty, lightweight CAs +are not in use, the current instance is the one and only CA, and +proceed straight to validation. + +Fixes: https://fedorahosted.org/pki/ticket/2420 +--- + base/ca/src/com/netscape/ca/CertificateAuthority.java | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/base/ca/src/com/netscape/ca/CertificateAuthority.java b/base/ca/src/com/netscape/ca/CertificateAuthority.java +index 502ab18..a5397da 100644 +--- a/base/ca/src/com/netscape/ca/CertificateAuthority.java ++++ b/base/ca/src/com/netscape/ca/CertificateAuthority.java +@@ -2240,6 +2240,10 @@ public class CertificateAuthority + * employ some heuristic to deal with this case. Our + * heuristic is: + * ++ * 0. If caMap contains no CAs, then lightweight CAs are not ++ * enabled. There is only one CA, and 'this' is it. Go ++ * straight to validation. ++ * + * 1. Find the issuer of the cert identified by the first + * CertID in the request. + * +@@ -2254,7 +2258,7 @@ public class CertificateAuthority + * aggregate OCSP response. + */ + ICertificateAuthority ocspCA = this; +- if (tbsReq.getRequestCount() > 0) { ++ if (caMap.size() > 0 && tbsReq.getRequestCount() > 0) { + com.netscape.cmsutil.ocsp.Request req = tbsReq.getRequestAt(0); + BigInteger serialNo = req.getCertID().getSerialNumber(); + X509CertImpl cert = mCertRepot.getX509Certificate(serialNo); +-- +1.8.3.1 + + +From 7bed80ef6b1529f948da260a6b43f2052c6ffb21 Mon Sep 17 00:00:00 2001 +From: Fraser Tweedale +Date: Mon, 8 Aug 2016 14:39:01 +1000 +Subject: [PATCH 91/96] Fix lightweight CA PEM-encoded PKCS #7 cert chain + retrieval + +The method to retrieve a lightweight CA's PEM-encoded PKCS #7 cert +chain incorrectly returns X.509 data wrapped in PKCS7 PEM header. +Return proper PKCS #7 data. + +Fixes: https://fedorahosted.org/pki/ticket/2433 +--- + base/ca/src/org/dogtagpki/server/ca/rest/AuthorityService.java | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +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 7bca10f..246a3f0 100644 +--- a/base/ca/src/org/dogtagpki/server/ca/rest/AuthorityService.java ++++ b/base/ca/src/org/dogtagpki/server/ca/rest/AuthorityService.java +@@ -173,7 +173,7 @@ public class AuthorityService extends PKIService implements AuthorityResource { + + @Override + public Response getChainPEM(String aidString) { +- byte[] der = (byte[]) getCert(aidString).getEntity(); ++ byte[] der = (byte[]) getChain(aidString).getEntity(); + return Response.ok(toPem("PKCS7", der)).build(); + } + +-- +1.8.3.1 + + +From e948a42f8bf7823b18ad4551a8fe8a5db991e966 Mon Sep 17 00:00:00 2001 +From: Christian Heimes +Date: Mon, 8 Aug 2016 13:08:17 +0200 +Subject: [PATCH 92/96] Improve setup.py for standalone Dogtag client releases + +PyPI requires a different spelling of LGPLv3+ classifier. + +The correct name for installation requirements is 'install_requires', +not 'requirements'. + +Add a new version_info command that rewrites setup.py in place to +include the current version. This fixes a problem with source +distributions of the client package. +--- + base/common/python/setup.cfg | 2 +- + base/common/python/setup.py | 83 +++++++++++++++++++++++++++++++++----------- + 2 files changed, 63 insertions(+), 22 deletions(-) + +diff --git a/base/common/python/setup.cfg b/base/common/python/setup.cfg +index ad43486..32f2126 100644 +--- a/base/common/python/setup.cfg ++++ b/base/common/python/setup.cfg +@@ -2,5 +2,5 @@ + universal = 1 + + [aliases] +-packages = clean --all egg_info bdist_wheel sdist --format=zip ++packages = clean --all version_info egg_info bdist_wheel sdist --format=zip + release = packages register upload +diff --git a/base/common/python/setup.py b/base/common/python/setup.py +index 86e0704..e0920c1 100644 +--- a/base/common/python/setup.py ++++ b/base/common/python/setup.py +@@ -43,28 +43,67 @@ try: + except ImportError: + from distutils.core import setup + ++from distutils.cmd import Command ++ ++ ++class VersionInfo(Command): ++ user_options = [] + +-def get_version(specfile='../../../specs/pki-core.spec'): + version_re = re.compile('^Version:\s*(\d+\.\d+\.\d+)') + release_re = re.compile('^Release:.*?([\d\.]+)') +- version = release = None +- with open(specfile) as f: +- for line in f: +- if version is None: +- match = version_re.match(line) +- if match is not None: +- version = match.group(1) +- if release is None: +- match = release_re.match(line) +- if match is not None: +- release = match.group(1) +- if version is not None and release is not None: +- break +- if version is None or release is None: +- raise ValueError(version, release) +- return "%s.%s" % (version, release) +- +-VERSION = get_version() ++ specfile = '../../../specs/pki-core.spec' ++ ++ def initialize_options(self): ++ self.rpm_version = None ++ ++ def finalize_options(self): ++ try: ++ version, release = self.get_version() ++ except IOError: ++ pass ++ else: ++ self.rpm_version = "%s.%s" % (version, release) ++ ++ def run(self): ++ if self.rpm_version is not None: ++ self.distribution.metadata.version = self.rpm_version ++ self.rewrite_setup_py() ++ else: ++ raise ValueError( ++ 'Cannot load version from {}'.format(self.specfile) ++ ) ++ ++ def get_version(self): ++ version = release = None ++ with open(self.specfile) as f: ++ for line in f: ++ if version is None: ++ match = self.version_re.match(line) ++ if match is not None: ++ version = match.group(1) ++ if release is None: ++ match = self.release_re.match(line) ++ if match is not None: ++ release = match.group(1) ++ if version is not None and release is not None: ++ break ++ if version is None or release is None: ++ raise ValueError(version, release) ++ return version, release ++ ++ def rewrite_setup_py(self): ++ with open(__file__) as f: ++ lines = list(f) ++ for i, line in enumerate(lines): ++ if line.startswith('VERSION ='): ++ lines[i] = "VERSION = '{}'\n".format(self.rpm_version) ++ with open(__file__, 'w') as f: ++ f.write(''.join(lines)) ++ ++ ++# auto-generated by version_info ++VERSION = None ++ + + setup( + author='Dogtag Certificate System Team', +@@ -85,7 +124,8 @@ and set up in less than an hour.""", + keywords='pki x509 cert certificate', + url='http://pki.fedoraproject.org/', + packages=['pki', 'pki.cli'], +- requirements=['python-nss', 'requests', 'six'], ++ install_requires=['python-nss', 'requests', 'six'], ++ cmdclass={'version_info': VersionInfo}, + classifiers=[ + 'Development Status :: 5 - Production/Stable', + 'Environment :: Web Environment', +@@ -93,7 +133,8 @@ and set up in less than an hour.""", + 'Operating System :: OS Independent', + 'Programming Language :: Python :: 2.7', + 'Programming Language :: Python :: 3.4', +- 'License :: OSI Approved :: GNU Lesser General Public License v3+ (LGPLv3+)', ++ 'License :: OSI Approved :: GNU Lesser General Public License ' + ++ 'v3 or later (LGPLv3+)', + 'Topic :: Security :: Cryptography', + ], + ) +-- +1.8.3.1 + + +From a38b8b875e40d0d8551752af7aa2567d2891384a Mon Sep 17 00:00:00 2001 +From: Christina Fu +Date: Mon, 8 Aug 2016 11:34:52 -0700 +Subject: [PATCH 93/96] Ticket #2428 - part2 handle NullPointerException + +--- + .../src/com/netscape/cms/servlet/profile/ProfileReviewServlet.java | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileReviewServlet.java b/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileReviewServlet.java +index caf2cf1..0073bd2 100644 +--- a/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileReviewServlet.java ++++ b/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileReviewServlet.java +@@ -423,8 +423,8 @@ public class ProfileReviewServlet extends ProfileServlet { + + try { + defValue = def.getValue(defName, locale, req); +- } catch (EPropertyException ee) { +- CMS.debug("ProfileReviewServlet: " + ee.toString()); ++ } catch (Exception exp) { ++ CMS.debug("ProfileReviewServlet: " + exp.toString()); + } + + defset.set(ARG_DEF_ID, defName); +-- +1.8.3.1 + + +From a808013629d4b4de886ec1563daebf6ea5138f0c Mon Sep 17 00:00:00 2001 +From: "Endi S. Dewata" +Date: Mon, 8 Aug 2016 19:19:16 +0200 +Subject: [PATCH 94/96] Improved SystemConfigService.configure() error message. + +The pkispawn has been modified to improve the way it displays the +error message returned by SystemConfigService.configure(). If the +method throws a PKIException, the response is returned as a JSON +message, so pkispawn will parse it and display the actual error +message. For other exceptions pkispawn will display the entire +HTML message returned by Tomcat. + +https://fedorahosted.org/pki/ticket/2399 +--- + .../python/pki/server/deployment/pkihelper.py | 23 +--------------------- + base/server/sbin/pkispawn | 20 +++++++++++++++++-- + 2 files changed, 19 insertions(+), 24 deletions(-) + +diff --git a/base/server/python/pki/server/deployment/pkihelper.py b/base/server/python/pki/server/deployment/pkihelper.py +index 8a1dbdd..b6eacf1 100644 +--- a/base/server/python/pki/server/deployment/pkihelper.py ++++ b/base/server/python/pki/server/deployment/pkihelper.py +@@ -3959,28 +3959,7 @@ class ConfigClient: + admin_cert = response['adminCert']['cert'] + self.process_admin_cert(admin_cert) + +- except Exception as e: +- config.pki_log.error( +- log.PKI_CONFIG_JAVA_CONFIGURATION_EXCEPTION + " " + str(e), +- extra=config.PKI_INDENTATION_LEVEL_2) +- +- if hasattr(e, 'response'): +- text = e.response.text # pylint: disable=E1101 +- try: +- root = ET.fromstring(text) +- except ET.ParseError as pe: +- config.pki_log.error( +- "ParseError: %s: %s " % (pe, text), +- extra=config.PKI_INDENTATION_LEVEL_2) +- raise +- +- if root.tag == 'PKIException': +- message = root.findall('.//Message')[0].text +- if message is not None: +- config.pki_log.error( +- log.PKI_CONFIG_JAVA_CONFIGURATION_EXCEPTION + " " + +- message, +- extra=config.PKI_INDENTATION_LEVEL_2) ++ except: + + raise + +diff --git a/base/server/sbin/pkispawn b/base/server/sbin/pkispawn +index 13139fa..c87c49a 100755 +--- a/base/server/sbin/pkispawn ++++ b/base/server/sbin/pkispawn +@@ -527,8 +527,24 @@ def main(argv): + + scriptlet.spawn(deployer) + +- # pylint: disable=W0703 +- except Exception as e: ++ except requests.HTTPError as e: ++ r = e.response ++ print() ++ ++ print('Installation failed:') ++ if r.headers['content-type'] == 'application/json': ++ data = r.json() ++ print('%s: %s' % (data['ClassName'], data['Message'])) ++ else: ++ print(r.text) ++ ++ print() ++ print('Please check the %s logs in %s.' % ++ (config.pki_subsystem, deployer.mdict['pki_subsystem_log_path'])) ++ ++ sys.exit(1) ++ ++ except Exception as e: # pylint: disable=broad-except + log_error_details() + print() + print("Installation failed: %s" % e) +-- +1.8.3.1 + diff --git a/SOURCES/pki-core-fix-exception-when-talking-to-Dogtag-9-systems.patch b/SOURCES/pki-core-fix-exception-when-talking-to-Dogtag-9-systems.patch deleted file mode 100644 index dc885ab..0000000 --- a/SOURCES/pki-core-fix-exception-when-talking-to-Dogtag-9-systems.patch +++ /dev/null @@ -1,57 +0,0 @@ -commit b65d6a8095b864c912e2e0884e9b50f58353805b -Author: Ade Lee -Date: Thu Jul 16 16:48:51 2015 -0400 - - Fix exception when talking to dogtag 9 systems - - When getting a token from the security domain for a Dogtag 9 - system, we first attempt to reach the REST interfaces. When this - fails (with 404 exception), we catch the exception and try the - old interfaces. - - The exception being thrown has been changed from the deprecated - ClientResponseFailure to being wrapped in a PKIException, so the - code catching the exception needs to be modified accordingly. - - Ticket 1495 - -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 5566e91..c8ab38c 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 -@@ -89,7 +89,6 @@ import netscape.security.x509.X509CertImpl; - import netscape.security.x509.X509Key; - - import org.apache.velocity.context.Context; --import org.jboss.resteasy.client.ClientResponseFailure; - import org.mozilla.jss.CryptoManager; - import org.mozilla.jss.CryptoManager.NicknameConflictException; - import org.mozilla.jss.CryptoManager.NotInitializedException; -@@ -152,6 +151,7 @@ import com.netscape.certsrv.base.EBaseException; - import com.netscape.certsrv.base.EPropertyNotFound; - import com.netscape.certsrv.base.IConfigStore; - import com.netscape.certsrv.base.ISubsystem; -+import com.netscape.certsrv.base.PKIException; - import com.netscape.certsrv.base.ResourceNotFoundException; - import com.netscape.certsrv.ca.ICertificateAuthority; - import com.netscape.certsrv.client.ClientConfig; -@@ -372,17 +372,14 @@ public class ConfigurationUtils { - InstallToken token = sdClient.getInstallToken(sdhost, csType); - accountClient.logout(); - return token.getToken(); -- -- } catch (ClientResponseFailure e) { -- -- if (e.getResponse().getResponseStatus() == Response.Status.NOT_FOUND) { -+ } catch (PKIException e) { -+ if (e.getCode() == Response.Status.NOT_FOUND.getStatusCode()) { - // try the old servlet - CMS.debug("Getting old cookie"); - String tokenString = getOldCookie(sdhost, sdport, user, passwd); - CMS.debug("Token: " + tokenString); - return tokenString; - } -- - throw e; - } - } diff --git a/SOURCES/pki-core-fixed-pkidbuser-group-memberships.patch b/SOURCES/pki-core-fixed-pkidbuser-group-memberships.patch deleted file mode 100644 index 6cd84bf..0000000 --- a/SOURCES/pki-core-fixed-pkidbuser-group-memberships.patch +++ /dev/null @@ -1,152 +0,0 @@ -commit e6f8b52e97926e7b6c30a6ce958a7e590c2e6b76 -Author: Matthew Harmsen -Date: Tue Sep 15 12:29:08 2015 -0600 - - Fixed pkidbuser group memberships. - - Due to a certificate mapping issue the subsystem certificate can - be mapped into either the subsystem user or pkidbuser, which may - cause problems since the users don't belong to the same groups. - As a temporary solution the pkidbuser is now added into the same - groups. This way the client subsystem can always access the - services regardless of which user the certificate is actually - mapped to. - - Bugzilla Bug #1258634 - CA fails to authenticate to KRA for archival - - https://fedorahosted.org/pki/ticket/1595 - -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 708240b..d99929f 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 -@@ -50,6 +50,7 @@ import java.security.cert.CertificateNotYetValidException; - import java.security.interfaces.RSAPublicKey; - import java.util.ArrayList; - import java.util.Arrays; -+import java.util.Collection; - import java.util.Enumeration; - import java.util.List; - import java.util.StringTokenizer; -@@ -62,32 +63,7 @@ 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.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; - import org.mozilla.jss.CryptoManager.NicknameConflictException; -@@ -180,6 +156,32 @@ import com.netscape.cmsutil.http.JssSSLSocketFactory; - import com.netscape.cmsutil.ldap.LDAPUtil; - 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.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 both by the RESTful installer - * and the UI Panels. -@@ -3892,7 +3894,7 @@ public class ConfigurationUtils { - String groupName = "Trusted Managers"; - IGroup group = system.getGroupFromName(groupName); - if (!group.isMember(id)) { -- CMS.debug("setupClientAuthUser: adding user to the trusted managers group."); -+ CMS.debug("setupClientAuthUser: adding user to the " + groupName + " group."); - group.addMemberName(id); - system.modifyGroup(group); - } -@@ -4119,7 +4121,7 @@ public class ConfigurationUtils { - user.setX509Certificates(certs); - - system.addUser(user); -- CMS.debug("setupDBUser(): successfully added the user"); -+ CMS.debug("setupDBUser(): successfully added " + DBUSER); - - system.addUserCert(user); - CMS.debug("setupDBUser(): successfully add the user certificate"); -@@ -4130,6 +4132,36 @@ public class ConfigurationUtils { - // remove old db users - CMS.debug("setupDBUser(): removing seeAlso from old dbusers"); - removeOldDBUsers(certs[0].getSubjectDN().toString()); -+ -+ // workaround for ticket #1595 -+ IConfigStore cs = CMS.getConfigStore(); -+ String csType = cs.getString("cs.type").toUpperCase(); -+ -+ Collection groupNames = new ArrayList(); -+ -+ if ("CA".equals(csType)) { -+ groupNames.add("Subsystem Group"); -+ groupNames.add("Certificate Manager Agents"); -+ -+ } else if ("KRA".equals(csType)) { -+ groupNames.add("Data Recovery Manager Agents"); -+ groupNames.add("Trusted Managers"); -+ -+ } else if ("OCSP".equals(csType)) { -+ groupNames.add("Trusted Managers"); -+ -+ } else if ("TKS".equals(csType)) { -+ groupNames.add("Token Key Service Manager Agents"); -+ } -+ -+ for (String groupName : groupNames) { -+ IGroup group = system.getGroupFromName(groupName); -+ if (!group.isMember(DBUSER)) { -+ CMS.debug("setupDBUser(): adding " + DBUSER + " to the " + groupName + " group."); -+ group.addMemberName(DBUSER); -+ system.modifyGroup(group); -+ } -+ } - } - - public static void addProfilesToTPSUser(String adminID) throws EUsrGrpException, LDAPException { diff --git a/SOURCES/pki-core-handle-JSON-decode-error.patch b/SOURCES/pki-core-handle-JSON-decode-error.patch deleted file mode 100644 index 8d5d9c0..0000000 --- a/SOURCES/pki-core-handle-JSON-decode-error.patch +++ /dev/null @@ -1,78 +0,0 @@ -commit 9fa1d0c968977ef23e26556b0a8e8e76b32c7288 -Author: Christian Heimes -Date: Wed Jul 15 17:55:05 2015 +0200 - - Handle JSON decode error in handle_exceptions() - - pki.handle_exceptions() raises a JSON decode exception when the body of - the HTTPException is not a valid JSON string. The JSON exception hides - the true error message. - - The patch also fixes a bug in PKIException.from_json(). The code and - ClassName attribute are now correctly set. Finally we have our first - unit test. - - https://fedorahosted.org/pki/ticket/1488 - https://fedorahosted.org/freeipa/ticket/5129 - -diff --git a/base/common/python/pki/__init__.py b/base/common/python/pki/__init__.py -index c383cdb..39a0db7 100644 ---- a/base/common/python/pki/__init__.py -+++ b/base/common/python/pki/__init__.py -@@ -24,6 +24,7 @@ This module contains top-level classes and functions used by the Dogtag project. - from functools import wraps - import os - import re -+import sys - import requests - - -@@ -205,10 +206,12 @@ class PKIException(Exception, ResourceMessage): - :type json_value: str - :return: pki.PKIException - """ -- ret = cls(json_value['Message'], json_value['Code'], -- json_value['ClassName']) -+ ret = cls( -+ message=json_value['Message'], -+ code=json_value['Code'], -+ class_name=json_value['ClassName'] -+ ) - for attr in json_value['Attributes']['Attribute']: -- print str(attr) - ret.add_attribute(attr["name"], attr["value"]) - return ret - -@@ -293,15 +296,25 @@ def handle_exceptions(): - """ Decorator to catch and re-throw PKIExceptions.""" - try: - return fn_call(inst, *args, **kwargs) -- except requests.exceptions.HTTPError as exc: -- clazz = exc.response.json()['ClassName'] -- if clazz in EXCEPTION_MAPPINGS: -- exception_class = EXCEPTION_MAPPINGS[clazz] -- pki_exception = exception_class.from_json( -- exc.response.json()) -- raise pki_exception -+ except requests.exceptions.HTTPError: -+ # store exception information. json may raise another -+ # exception. We want to re-raise the HTTPError. -+ exc_type, exc_val, exc_tb = sys.exc_info() -+ try: -+ json = exc_val.response.json() -+ except ValueError: -+ # json raises ValueError. simplejson raises -+ # JSONDecodeError, which is a subclass of ValueError. -+ # re-raise original exception -+ raise exc_type, exc_val, exc_tb - else: -- raise exc -+ # clear reference cycle -+ exc_type = exc_val = exc_tb = None -+ clazz = json.get('ClassName') -+ if clazz and clazz in EXCEPTION_MAPPINGS: -+ exception_class = EXCEPTION_MAPPINGS[clazz] -+ pki_exception = exception_class.from_json(json) -+ raise pki_exception - - return handler diff --git a/SOURCES/pki-core-post-re-base.patch b/SOURCES/pki-core-post-re-base.patch new file mode 100644 index 0000000..b2cded9 --- /dev/null +++ b/SOURCES/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/SOURCES/pki-core-rhel-7-2.patch b/SOURCES/pki-core-rhel-7-2.patch deleted file mode 100644 index 8bfeccd..0000000 --- a/SOURCES/pki-core-rhel-7-2.patch +++ /dev/null @@ -1,4468 +0,0 @@ -From cc97f8628b23f8ea75308bb97a31307cb4f162b9 Mon Sep 17 00:00:00 2001 -From: "Endi S. Dewata" -Date: Tue, 23 Jun 2015 12:23:15 -0400 -Subject: [PATCH 01/21] Fixed selftests log message. - -The SelfTestSubsystem has been modified to display a 'successful' -message only if all tests have passed. If a test fails, it will -log a failure, subsequent tests will not be executed, and the -subsystem will shutdown immediately. - -The runSelfTest() in various tests have been cleaned up to throw -the original exception to help troubleshooting. The unused -RAPresence test has been removed. - -https://fedorahosted.org/pki/ticket/1249 ---- - .../com/netscape/certsrv/selftests/ISelfTest.java | 5 +- - .../certsrv/selftests/ISelfTestSubsystem.java | 5 +- - .../src/com/netscape/cms/selftests/ASelfTest.java | 5 +- - .../com/netscape/cms/selftests/ca/CAPresence.java | 97 +++----- - .../com/netscape/cms/selftests/ca/CAValidity.java | 102 ++++---- - .../selftests/common/SystemCertsVerification.java | 35 ++- - .../netscape/cms/selftests/kra/KRAPresence.java | 84 +++---- - .../netscape/cms/selftests/ocsp/OCSPPresence.java | 123 ++++------ - .../netscape/cms/selftests/ocsp/OCSPValidity.java | 127 ++++------ - .../com/netscape/cms/selftests/ra/RAPresence.java | 261 -------------------- - .../cms/selftests/tks/TKSKnownSessionKey.java | 56 +++-- - .../cms/servlet/admin/CMSAdminServlet.java | 6 +- - .../cmscore/selftests/SelfTestSubsystem.java | 271 ++++++++++----------- - .../server/tps/selftests/TPSPresence.java | 38 ++- - .../server/tps/selftests/TPSValidity.java | 43 ++-- - 15 files changed, 449 insertions(+), 809 deletions(-) - delete mode 100644 base/server/cms/src/com/netscape/cms/selftests/ra/RAPresence.java - -diff --git a/base/common/src/com/netscape/certsrv/selftests/ISelfTest.java b/base/common/src/com/netscape/certsrv/selftests/ISelfTest.java -index 24ad623..0ffc74b 100644 ---- a/base/common/src/com/netscape/certsrv/selftests/ISelfTest.java -+++ b/base/common/src/com/netscape/certsrv/selftests/ISelfTest.java -@@ -126,8 +126,7 @@ public interface ISelfTest { - *

- * - * @param logger specifies logging subsystem -- * @exception ESelfTestException self test exception -+ * @exception Exception self test exception - */ -- public void runSelfTest(ILogEventListener logger) -- throws ESelfTestException; -+ public void runSelfTest(ILogEventListener logger) throws Exception; - } -diff --git a/base/common/src/com/netscape/certsrv/selftests/ISelfTestSubsystem.java b/base/common/src/com/netscape/certsrv/selftests/ISelfTestSubsystem.java -index 214ee17..29adde0 100644 ---- a/base/common/src/com/netscape/certsrv/selftests/ISelfTestSubsystem.java -+++ b/base/common/src/com/netscape/certsrv/selftests/ISelfTestSubsystem.java -@@ -206,10 +206,9 @@ public interface ISelfTestSubsystem - *

- * - * @exception EMissingSelfTestException subsystem has missing name -- * @exception ESelfTestException self test exception -+ * @exception Exception self test exception - */ -- public void runSelfTestsAtStartup() -- throws EMissingSelfTestException, ESelfTestException; -+ public void runSelfTestsAtStartup() throws Exception; - - // - // methods associated with the list of self test instances -diff --git a/base/server/cms/src/com/netscape/cms/selftests/ASelfTest.java b/base/server/cms/src/com/netscape/cms/selftests/ASelfTest.java -index e77ece5..c77514f 100644 ---- a/base/server/cms/src/com/netscape/cms/selftests/ASelfTest.java -+++ b/base/server/cms/src/com/netscape/cms/selftests/ASelfTest.java -@@ -186,8 +186,7 @@ public abstract class ASelfTest - *

- * - * @param logger specifies logging subsystem -- * @exception ESelfTestException self test exception -+ * @exception Exception self test exception - */ -- public abstract void runSelfTest(ILogEventListener logger) -- throws ESelfTestException; -+ public abstract void runSelfTest(ILogEventListener logger) throws Exception; - } -diff --git a/base/server/cms/src/com/netscape/cms/selftests/ca/CAPresence.java b/base/server/cms/src/com/netscape/cms/selftests/ca/CAPresence.java -index 83caa00..ab491c7 100644 ---- a/base/server/cms/src/com/netscape/cms/selftests/ca/CAPresence.java -+++ b/base/server/cms/src/com/netscape/cms/selftests/ca/CAPresence.java -@@ -191,72 +191,55 @@ public class CAPresence - *

- * - * @param logger specifies logging subsystem -- * @exception ESelfTestException self test exception -+ * @exception Exception self test exception - */ -- public void runSelfTest(ILogEventListener logger) -- throws ESelfTestException { -- String logMessage = null; -- ICertificateAuthority ca = null; -- X509CertImpl caCert = null; -- X509Key caPubKey = null; -- -- ca = (ICertificateAuthority) CMS.getSubsystem(mCaSubId); -+ public void runSelfTest(ILogEventListener logger) throws Exception { - -+ ICertificateAuthority ca = (ICertificateAuthority) CMS.getSubsystem(mCaSubId); - if (ca == null) { - // log that the CA is not installed -- logMessage = CMS.getLogMessage("SELFTESTS_CA_IS_NOT_PRESENT", -- getSelfTestName()); -- -- mSelfTestSubsystem.log(logger, -- logMessage); -- -- throw new ESelfTestException(logMessage); -- } else { -- // Retrieve the CA certificate -- caCert = ca.getCACert(); -- -- if (caCert == null) { -- // log that the CA is not yet initialized -- logMessage = CMS.getLogMessage( -- "SELFTESTS_CA_IS_NOT_INITIALIZED", -- getSelfTestName()); -- -- mSelfTestSubsystem.log(logger, -- logMessage); -- -- throw new ESelfTestException(logMessage); -- } -- -- // Retrieve the CA certificate public key -- try { -- caPubKey = (X509Key) caCert.get(X509CertImpl.PUBLIC_KEY); -- -- if (caPubKey == null) { -- // log that something is seriously wrong with the CA -- logMessage = CMS.getLogMessage("SELFTESTS_CA_IS_CORRUPT", -- getSelfTestName()); -- -- mSelfTestSubsystem.log(logger, -- logMessage); -+ String logMessage = CMS.getLogMessage( -+ "SELFTESTS_CA_IS_NOT_PRESENT", -+ getSelfTestName()); -+ mSelfTestSubsystem.log(logger, logMessage); -+ throw new Exception(logMessage); -+ } - -- throw new ESelfTestException(logMessage); -- } -- } catch (CertificateParsingException e) { -- // log that something is seriously wrong with the CA -- mSelfTestSubsystem.log(logger, -- e.toString()); -+ // Retrieve the CA certificate -+ X509CertImpl caCert = ca.getCACert(); -+ if (caCert == null) { -+ // log that the CA is not yet initialized -+ String logMessage = CMS.getLogMessage( -+ "SELFTESTS_CA_IS_NOT_INITIALIZED", -+ getSelfTestName()); -+ mSelfTestSubsystem.log(logger, logMessage); -+ throw new Exception(logMessage); -+ } - -- throw new ESelfTestException(e.toString()); -- } -+ // Retrieve the CA certificate public key -+ X509Key caPubKey; -+ try { -+ caPubKey = (X509Key) caCert.get(X509CertImpl.PUBLIC_KEY); - -- // log that the CA is present -- logMessage = CMS.getLogMessage("SELFTESTS_CA_IS_PRESENT", -- getSelfTestName()); -+ } catch (CertificateParsingException e) { -+ // log that something is seriously wrong with the CA -+ mSelfTestSubsystem.log(logger, e.toString()); -+ throw e; -+ } - -- mSelfTestSubsystem.log(logger, -- logMessage); -+ if (caPubKey == null) { -+ // log that something is seriously wrong with the CA -+ String logMessage = CMS.getLogMessage( -+ "SELFTESTS_CA_IS_CORRUPT", -+ getSelfTestName()); -+ mSelfTestSubsystem.log(logger, logMessage); -+ throw new Exception(logMessage); - } - -- return; -+ // log that the CA is present -+ String logMessage = CMS.getLogMessage( -+ "SELFTESTS_CA_IS_PRESENT", -+ getSelfTestName()); -+ mSelfTestSubsystem.log(logger, logMessage); - } - } -diff --git a/base/server/cms/src/com/netscape/cms/selftests/ca/CAValidity.java b/base/server/cms/src/com/netscape/cms/selftests/ca/CAValidity.java -index b1751ec..4d90be1 100644 ---- a/base/server/cms/src/com/netscape/cms/selftests/ca/CAValidity.java -+++ b/base/server/cms/src/com/netscape/cms/selftests/ca/CAValidity.java -@@ -191,72 +191,56 @@ public class CAValidity - *

- * - * @param logger specifies logging subsystem -- * @exception ESelfTestException self test exception -+ * @exception Exception self test exception - */ -- public void runSelfTest(ILogEventListener logger) -- throws ESelfTestException { -- String logMessage = null; -- ICertificateAuthority ca = null; -- X509CertImpl caCert = null; -- -- ca = (ICertificateAuthority) CMS.getSubsystem(mCaSubId); -+ public void runSelfTest(ILogEventListener logger) throws Exception { - -+ ICertificateAuthority ca = (ICertificateAuthority) CMS.getSubsystem(mCaSubId); - if (ca == null) { - // log that the CA is not installed -- logMessage = CMS.getLogMessage("SELFTESTS_CA_IS_NOT_PRESENT", -- getSelfTestName()); -- -- mSelfTestSubsystem.log(logger, -- logMessage); -- -- throw new ESelfTestException(logMessage); -- } else { -- // Retrieve the CA certificate -- caCert = ca.getCACert(); -- -- if (caCert == null) { -- // log that the CA is not yet initialized -- logMessage = CMS.getLogMessage( -- "SELFTESTS_CA_IS_NOT_INITIALIZED", -- getSelfTestName()); -- -- mSelfTestSubsystem.log(logger, -- logMessage); -- -- throw new ESelfTestException(logMessage); -- } -- -- // Retrieve the CA validity period -- try { -- caCert.checkValidity(); -- } catch (CertificateNotYetValidException e) { -- // log that the CA is not yet valid -- logMessage = CMS.getLogMessage("SELFTESTS_CA_IS_NOT_YET_VALID", -- getSelfTestName()); -- -- mSelfTestSubsystem.log(logger, -- logMessage); -- -- throw new ESelfTestException(logMessage); -- } catch (CertificateExpiredException e) { -- // log that the CA is expired -- logMessage = CMS.getLogMessage("SELFTESTS_CA_IS_EXPIRED", -- getSelfTestName()); -- -- mSelfTestSubsystem.log(logger, -- logMessage); -- -- throw new ESelfTestException(logMessage); -- } -+ String logMessage = CMS.getLogMessage( -+ "SELFTESTS_CA_IS_NOT_PRESENT", -+ getSelfTestName()); -+ mSelfTestSubsystem.log(logger, logMessage); -+ throw new Exception(logMessage); -+ } - -- // log that the CA is valid -- logMessage = CMS.getLogMessage("SELFTESTS_CA_IS_VALID", -- getSelfTestName()); -+ // Retrieve the CA certificate -+ X509CertImpl caCert = ca.getCACert(); -+ if (caCert == null) { -+ // log that the CA is not yet initialized -+ String logMessage = CMS.getLogMessage( -+ "SELFTESTS_CA_IS_NOT_INITIALIZED", -+ getSelfTestName()); -+ mSelfTestSubsystem.log(logger, logMessage); -+ throw new Exception(logMessage); -+ } - -- mSelfTestSubsystem.log(logger, -- logMessage); -+ // Retrieve the CA validity period -+ try { -+ caCert.checkValidity(); -+ -+ } catch (CertificateNotYetValidException e) { -+ // log that the CA is not yet valid -+ String logMessage = CMS.getLogMessage( -+ "SELFTESTS_CA_IS_NOT_YET_VALID", -+ getSelfTestName()); -+ mSelfTestSubsystem.log(logger, logMessage); -+ throw e; -+ -+ } catch (CertificateExpiredException e) { -+ // log that the CA is expired -+ String logMessage = CMS.getLogMessage( -+ "SELFTESTS_CA_IS_EXPIRED", -+ getSelfTestName()); -+ mSelfTestSubsystem.log(logger, logMessage); -+ throw e; - } - -- return; -+ // log that the CA is valid -+ String logMessage = CMS.getLogMessage( -+ "SELFTESTS_CA_IS_VALID", -+ getSelfTestName()); -+ mSelfTestSubsystem.log(logger, logMessage); - } - } -diff --git a/base/server/cms/src/com/netscape/cms/selftests/common/SystemCertsVerification.java b/base/server/cms/src/com/netscape/cms/selftests/common/SystemCertsVerification.java -index f5b0939..5c1e97b 100644 ---- a/base/server/cms/src/com/netscape/cms/selftests/common/SystemCertsVerification.java -+++ b/base/server/cms/src/com/netscape/cms/selftests/common/SystemCertsVerification.java -@@ -185,29 +185,22 @@ public class SystemCertsVerification - *

- * - * @param logger specifies logging subsystem -- * @exception ESelfTestException self test exception -+ * @exception Exception self test exception - */ -- public void runSelfTest(ILogEventListener logger) -- throws ESelfTestException { -- String logMessage = null; -- boolean rc = false; -- -- rc = CMS.verifySystemCerts(); -- if (rc == true) { -- logMessage = CMS.getLogMessage("SELFTESTS_COMMON_SYSTEM_CERTS_VERIFICATION_SUCCESS", -- getSelfTestName()); -- -- mSelfTestSubsystem.log(logger, -- logMessage); -- } else { -- logMessage = CMS.getLogMessage("SELFTESTS_COMMON_SYSTEM_CERTS_VERIFICATION_FAILURE", -- getSelfTestName()); -- -- mSelfTestSubsystem.log(logger, -- logMessage); -- throw new ESelfTestException(logMessage); -+ public void runSelfTest(ILogEventListener logger) throws Exception { -+ -+ boolean status = CMS.verifySystemCerts(); -+ if (!status) { -+ String logMessage = CMS.getLogMessage( -+ "SELFTESTS_COMMON_SYSTEM_CERTS_VERIFICATION_FAILURE", -+ getSelfTestName()); -+ mSelfTestSubsystem.log(logger, logMessage); -+ throw new Exception(logMessage); - } - -- return; -+ String logMessage = CMS.getLogMessage( -+ "SELFTESTS_COMMON_SYSTEM_CERTS_VERIFICATION_SUCCESS", -+ getSelfTestName()); -+ mSelfTestSubsystem.log(logger, logMessage); - } - } -diff --git a/base/server/cms/src/com/netscape/cms/selftests/kra/KRAPresence.java b/base/server/cms/src/com/netscape/cms/selftests/kra/KRAPresence.java -index 832d2b7..ff0c3fb 100644 ---- a/base/server/cms/src/com/netscape/cms/selftests/kra/KRAPresence.java -+++ b/base/server/cms/src/com/netscape/cms/selftests/kra/KRAPresence.java -@@ -188,64 +188,46 @@ public class KRAPresence - *

- * - * @param logger specifies logging subsystem -- * @exception ESelfTestException self test exception -+ * @exception Exception self test exception - */ -- public void runSelfTest(ILogEventListener logger) -- throws ESelfTestException { -- String logMessage = null; -- IKeyRecoveryAuthority kra = null; -- org.mozilla.jss.crypto.X509Certificate kraCert = null; -- PublicKey kraPubKey = null; -- -- kra = (IKeyRecoveryAuthority) CMS.getSubsystem(mSubId); -+ public void runSelfTest(ILogEventListener logger) throws Exception { - -+ IKeyRecoveryAuthority kra = (IKeyRecoveryAuthority) CMS.getSubsystem(mSubId); - if (kra == null) { - // log that the KRA is not installed -- logMessage = CMS.getLogMessage("SELFTESTS_KRA_IS_NOT_PRESENT", -- getSelfTestName()); -- -- mSelfTestSubsystem.log(logger, -- logMessage); -- -- throw new ESelfTestException(logMessage); -- } else { -- // Retrieve the KRA certificate -- kraCert = kra.getTransportCert(); -- -- if (kraCert == null) { -- // log that the RA is not yet initialized -- logMessage = CMS.getLogMessage( -- "SELFTESTS_KRA_IS_NOT_INITIALIZED", -- getSelfTestName()); -- -- mSelfTestSubsystem.log(logger, -- logMessage); -- -- throw new ESelfTestException(logMessage); -- } -- -- // Retrieve the KRA certificate public key -- kraPubKey = kraCert.getPublicKey(); -- -- if (kraPubKey == null) { -- // log that something is seriously wrong with the KRA -- logMessage = CMS.getLogMessage("SELFTESTS_KRA_IS_CORRUPT", -- getSelfTestName()); -- -- mSelfTestSubsystem.log(logger, -- logMessage); -- -- throw new ESelfTestException(logMessage); -- } -+ String logMessage = CMS.getLogMessage( -+ "SELFTESTS_KRA_IS_NOT_PRESENT", -+ getSelfTestName()); -+ mSelfTestSubsystem.log(logger, logMessage); -+ throw new Exception(logMessage); -+ } - -- // log that the KRA is present -- logMessage = CMS.getLogMessage("SELFTESTS_KRA_IS_PRESENT", -- getSelfTestName()); -+ // Retrieve the KRA certificate -+ org.mozilla.jss.crypto.X509Certificate kraCert = kra.getTransportCert(); -+ if (kraCert == null) { -+ // log that the RA is not yet initialized -+ String logMessage = CMS.getLogMessage( -+ "SELFTESTS_KRA_IS_NOT_INITIALIZED", -+ getSelfTestName()); -+ mSelfTestSubsystem.log(logger, logMessage); -+ throw new Exception(logMessage); -+ } - -- mSelfTestSubsystem.log(logger, -- logMessage); -+ // Retrieve the KRA certificate public key -+ PublicKey kraPubKey = kraCert.getPublicKey(); -+ if (kraPubKey == null) { -+ // log that something is seriously wrong with the KRA -+ String logMessage = CMS.getLogMessage( -+ "SELFTESTS_KRA_IS_CORRUPT", -+ getSelfTestName()); -+ mSelfTestSubsystem.log(logger, logMessage); -+ throw new Exception(logMessage); - } - -- return; -+ // log that the KRA is present -+ String logMessage = CMS.getLogMessage( -+ "SELFTESTS_KRA_IS_PRESENT", -+ getSelfTestName()); -+ mSelfTestSubsystem.log(logger, logMessage); - } - } -diff --git a/base/server/cms/src/com/netscape/cms/selftests/ocsp/OCSPPresence.java b/base/server/cms/src/com/netscape/cms/selftests/ocsp/OCSPPresence.java -index a3d9e3a..db9d237 100644 ---- a/base/server/cms/src/com/netscape/cms/selftests/ocsp/OCSPPresence.java -+++ b/base/server/cms/src/com/netscape/cms/selftests/ocsp/OCSPPresence.java -@@ -192,89 +192,66 @@ public class OCSPPresence - *

- * - * @param logger specifies logging subsystem -- * @exception ESelfTestException self test exception -+ * @exception Exception self test exception - */ -- public void runSelfTest(ILogEventListener logger) -- throws ESelfTestException { -- String logMessage = null; -- IOCSPAuthority ocsp = null; -- ISigningUnit ocspSigningUnit = null; -- X509CertImpl ocspCert = null; -- X509Key ocspPubKey = null; -- -- ocsp = (IOCSPAuthority) CMS.getSubsystem(mOcspSubId); -+ public void runSelfTest(ILogEventListener logger) throws Exception { - -+ IOCSPAuthority ocsp = (IOCSPAuthority) CMS.getSubsystem(mOcspSubId); - if (ocsp == null) { - // log that the OCSP is not installed -- logMessage = CMS.getLogMessage("SELFTESTS_OCSP_IS_NOT_PRESENT", -- getSelfTestName()); -- -- mSelfTestSubsystem.log(logger, -- logMessage); -- -- throw new ESelfTestException(logMessage); -- } else { -- // Retrieve the OCSP signing unit -- ocspSigningUnit = ocsp.getSigningUnit(); -- -- if (ocspSigningUnit == null) { -- // log that the OCSP is not yet initialized -- logMessage = CMS.getLogMessage( -- "SELFTESTS_OCSP_IS_NOT_INITIALIZED", -- getSelfTestName()); -- -- mSelfTestSubsystem.log(logger, -- logMessage); -- -- throw new ESelfTestException(logMessage); -- } -- -- // Retrieve the OCSP certificate -- ocspCert = ocspSigningUnit.getCertImpl(); -- -- if (ocspCert == null) { -- // log that the OCSP is not yet initialized -- logMessage = CMS.getLogMessage( -- "SELFTESTS_OCSP_IS_NOT_INITIALIZED", -- getSelfTestName()); -- -- mSelfTestSubsystem.log(logger, -- logMessage); -- -- throw new ESelfTestException(logMessage); -- } -- -- // Retrieve the OCSP certificate public key -- try { -- ocspPubKey = (X509Key) -- ocspCert.get(X509CertImpl.PUBLIC_KEY); -- -- if (ocspPubKey == null) { -- // log that something is seriously wrong with the OCSP -- logMessage = CMS.getLogMessage("SELFTESTS_OCSP_IS_CORRUPT", -- getSelfTestName()); -+ String logMessage = CMS.getLogMessage( -+ "SELFTESTS_OCSP_IS_NOT_PRESENT", -+ getSelfTestName()); -+ mSelfTestSubsystem.log(logger, logMessage); -+ throw new Exception(logMessage); -+ } - -- mSelfTestSubsystem.log(logger, -- logMessage); -+ // Retrieve the OCSP signing unit -+ ISigningUnit ocspSigningUnit = ocsp.getSigningUnit(); -+ if (ocspSigningUnit == null) { -+ // log that the OCSP is not yet initialized -+ String logMessage = CMS.getLogMessage( -+ "SELFTESTS_OCSP_IS_NOT_INITIALIZED", -+ getSelfTestName()); -+ mSelfTestSubsystem.log(logger, logMessage); -+ throw new Exception(logMessage); -+ } - -- throw new ESelfTestException(logMessage); -- } -- } catch (CertificateParsingException e) { -- // log that something is seriously wrong with the OCSP -- mSelfTestSubsystem.log(logger, -- e.toString()); -+ // Retrieve the OCSP certificate -+ X509CertImpl ocspCert = ocspSigningUnit.getCertImpl(); -+ if (ocspCert == null) { -+ // log that the OCSP is not yet initialized -+ String logMessage = CMS.getLogMessage( -+ "SELFTESTS_OCSP_IS_NOT_INITIALIZED", -+ getSelfTestName()); -+ mSelfTestSubsystem.log(logger, logMessage); -+ throw new Exception(logMessage); -+ } - -- throw new ESelfTestException(e.toString()); -- } -+ // Retrieve the OCSP certificate public key -+ X509Key ocspPubKey; -+ try { -+ ocspPubKey = (X509Key)ocspCert.get(X509CertImpl.PUBLIC_KEY); - -- // log that the OCSP is present -- logMessage = CMS.getLogMessage("SELFTESTS_OCSP_IS_PRESENT", -- getSelfTestName()); -+ } catch (CertificateParsingException e) { -+ // log that something is seriously wrong with the OCSP -+ mSelfTestSubsystem.log(logger, e.toString()); -+ throw e; -+ } - -- mSelfTestSubsystem.log(logger, -- logMessage); -+ if (ocspPubKey == null) { -+ // log that something is seriously wrong with the OCSP -+ String logMessage = CMS.getLogMessage( -+ "SELFTESTS_OCSP_IS_CORRUPT", -+ getSelfTestName()); -+ mSelfTestSubsystem.log(logger, logMessage); -+ throw new Exception(logMessage); - } - -- return; -+ // log that the OCSP is present -+ String logMessage = CMS.getLogMessage( -+ "SELFTESTS_OCSP_IS_PRESENT", -+ getSelfTestName()); -+ mSelfTestSubsystem.log(logger, logMessage); - } - } -diff --git a/base/server/cms/src/com/netscape/cms/selftests/ocsp/OCSPValidity.java b/base/server/cms/src/com/netscape/cms/selftests/ocsp/OCSPValidity.java -index 383779d..6aadf84 100644 ---- a/base/server/cms/src/com/netscape/cms/selftests/ocsp/OCSPValidity.java -+++ b/base/server/cms/src/com/netscape/cms/selftests/ocsp/OCSPValidity.java -@@ -192,89 +192,68 @@ public class OCSPValidity - *

- * - * @param logger specifies logging subsystem -- * @exception ESelfTestException self test exception -+ * @exception Exception self test exception - */ -- public void runSelfTest(ILogEventListener logger) -- throws ESelfTestException { -+ public void runSelfTest(ILogEventListener logger) throws Exception { - String logMessage = null; -- IOCSPAuthority ocsp = null; -- ISigningUnit ocspSigningUnit = null; -- X509CertImpl ocspCert = null; -- -- ocsp = (IOCSPAuthority) CMS.getSubsystem(mOcspSubId); - -+ IOCSPAuthority ocsp = (IOCSPAuthority) CMS.getSubsystem(mOcspSubId); - if (ocsp == null) { - // log that the OCSP is not installed -- logMessage = CMS.getLogMessage("SELFTESTS_OCSP_IS_NOT_PRESENT", -- getSelfTestName()); -- -- mSelfTestSubsystem.log(logger, -- logMessage); -- -- throw new ESelfTestException(logMessage); -- } else { -- // Retrieve the OCSP signing unit -- ocspSigningUnit = ocsp.getSigningUnit(); -- -- if (ocspSigningUnit == null) { -- // log that the OCSP is not yet initialized -- logMessage = CMS.getLogMessage( -- "SELFTESTS_OCSP_IS_NOT_INITIALIZED", -- getSelfTestName()); -- -- mSelfTestSubsystem.log(logger, -- logMessage); -- -- throw new ESelfTestException(logMessage); -- } -- -- // Retrieve the OCSP certificate -- ocspCert = ocspSigningUnit.getCertImpl(); -- -- if (ocspCert == null) { -- // log that the OCSP is not yet initialized -- logMessage = CMS.getLogMessage( -- "SELFTESTS_OCSP_IS_NOT_INITIALIZED", -- getSelfTestName()); -- -- mSelfTestSubsystem.log(logger, -- logMessage); -- -- throw new ESelfTestException(logMessage); -- } -- -- // Retrieve the OCSP validity period -- try { -- ocspCert.checkValidity(); -- } catch (CertificateNotYetValidException e) { -- // log that the OCSP is not yet valid -- logMessage = CMS.getLogMessage( -- "SELFTESTS_OCSP_IS_NOT_YET_VALID", -- getSelfTestName()); -- -- mSelfTestSubsystem.log(logger, -- logMessage); -- -- throw new ESelfTestException(logMessage); -- } catch (CertificateExpiredException e) { -- // log that the OCSP is expired -- logMessage = CMS.getLogMessage("SELFTESTS_OCSP_IS_EXPIRED", -- getSelfTestName()); -- -- mSelfTestSubsystem.log(logger, -- logMessage); -+ logMessage = CMS.getLogMessage( -+ "SELFTESTS_OCSP_IS_NOT_PRESENT", -+ getSelfTestName()); -+ mSelfTestSubsystem.log(logger, logMessage); -+ throw new Exception(logMessage); -+ } - -- throw new ESelfTestException(logMessage); -- } -+ // Retrieve the OCSP signing unit -+ ISigningUnit ocspSigningUnit = ocsp.getSigningUnit(); -+ if (ocspSigningUnit == null) { -+ // log that the OCSP is not yet initialized -+ logMessage = CMS.getLogMessage( -+ "SELFTESTS_OCSP_IS_NOT_INITIALIZED", -+ getSelfTestName()); -+ mSelfTestSubsystem.log(logger, logMessage); -+ throw new Exception(logMessage); -+ } - -- // log that the OCSP is valid -- logMessage = CMS.getLogMessage("SELFTESTS_OCSP_IS_VALID", -- getSelfTestName()); -+ // Retrieve the OCSP certificate -+ X509CertImpl ocspCert = ocspSigningUnit.getCertImpl(); -+ if (ocspCert == null) { -+ // log that the OCSP is not yet initialized -+ logMessage = CMS.getLogMessage( -+ "SELFTESTS_OCSP_IS_NOT_INITIALIZED", -+ getSelfTestName()); -+ mSelfTestSubsystem.log(logger, logMessage); -+ throw new Exception(logMessage); -+ } - -- mSelfTestSubsystem.log(logger, -- logMessage); -+ // Retrieve the OCSP validity period -+ try { -+ ocspCert.checkValidity(); -+ -+ } catch (CertificateNotYetValidException e) { -+ // log that the OCSP is not yet valid -+ logMessage = CMS.getLogMessage( -+ "SELFTESTS_OCSP_IS_NOT_YET_VALID", -+ getSelfTestName()); -+ mSelfTestSubsystem.log(logger, logMessage); -+ throw e; -+ -+ } catch (CertificateExpiredException e) { -+ // log that the OCSP is expired -+ logMessage = CMS.getLogMessage( -+ "SELFTESTS_OCSP_IS_EXPIRED", -+ getSelfTestName()); -+ mSelfTestSubsystem.log(logger, logMessage); -+ throw e; - } - -- return; -+ // log that the OCSP is valid -+ logMessage = CMS.getLogMessage( -+ "SELFTESTS_OCSP_IS_VALID", -+ getSelfTestName()); -+ mSelfTestSubsystem.log(logger, logMessage); - } - } -diff --git a/base/server/cms/src/com/netscape/cms/selftests/ra/RAPresence.java b/base/server/cms/src/com/netscape/cms/selftests/ra/RAPresence.java -deleted file mode 100644 -index 6facd80..0000000 ---- a/base/server/cms/src/com/netscape/cms/selftests/ra/RAPresence.java -+++ /dev/null -@@ -1,261 +0,0 @@ --// --- BEGIN COPYRIGHT BLOCK --- --// 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. --// --// (C) 2007 Red Hat, Inc. --// All rights reserved. --// --- END COPYRIGHT BLOCK --- --// package statement // --/////////////////////// -- --package com.netscape.cms.selftests.ra; -- --/////////////////////// --// import statements // --/////////////////////// -- --import java.security.PublicKey; --import java.util.Locale; -- --import com.netscape.certsrv.apps.CMS; --import com.netscape.certsrv.base.EBaseException; --import com.netscape.certsrv.base.IConfigStore; --import com.netscape.certsrv.logging.ILogEventListener; --import com.netscape.certsrv.ra.IRegistrationAuthority; --import com.netscape.certsrv.selftests.EDuplicateSelfTestException; --import com.netscape.certsrv.selftests.EInvalidSelfTestException; --import com.netscape.certsrv.selftests.EMissingSelfTestException; --import com.netscape.certsrv.selftests.ESelfTestException; --import com.netscape.certsrv.selftests.ISelfTestSubsystem; --import com.netscape.cms.selftests.ASelfTest; -- --////////////////////// --// class definition // --////////////////////// -- --/** -- * This class implements a self test to check for RA presence. -- *

-- * -- *

-- * NOTE:  This self-test is for Registration Authorities prior to
-- *        Netscape Certificate Management System 7.0.  It does NOT
-- *        apply to the Registration Authority found in
-- *        Red Hat Certificate System 7.3 or later (including
-- *        ALL versions of Dogtag Certificate System).
-- * 
-- *

-- * -- * @deprecated -- * @author mharmsen -- * @author thomask -- * @version $Revision$, $Date$ -- */ --public class RAPresence -- extends ASelfTest { -- //////////////////////// -- // default parameters // -- //////////////////////// -- -- /////////////////////////// -- // RAPresence parameters // -- /////////////////////////// -- -- // parameter information -- public static final String PROP_RA_SUB_ID = "RaSubId"; -- private String mRaSubId = null; -- -- ///////////////////// -- // default methods // -- ///////////////////// -- -- //////////////////////// -- // RAPresence methods // -- //////////////////////// -- -- /** -- * Initializes this subsystem with the configuration store -- * associated with this instance name. -- *

-- * -- * @param subsystem the associated subsystem -- * @param instanceName the name of this self test instance -- * @param parameters configuration store (self test parameters) -- * @exception EDuplicateSelfTestException subsystem has duplicate name/value -- * @exception EInvalidSelfTestException subsystem has invalid name/value -- * @exception EMissingSelfTestException subsystem has missing name/value -- */ -- public void initSelfTest(ISelfTestSubsystem subsystem, -- String instanceName, -- IConfigStore parameters) -- throws EDuplicateSelfTestException, -- EInvalidSelfTestException, -- EMissingSelfTestException { -- super.initSelfTest(subsystem, instanceName, parameters); -- -- // retrieve mandatory parameter(s) -- try { -- mRaSubId = mConfig.getString(PROP_RA_SUB_ID); -- if (mRaSubId != null) { -- mRaSubId = mRaSubId.trim(); -- } else { -- mSelfTestSubsystem.log(mSelfTestSubsystem.getSelfTestLogger(), -- CMS.getLogMessage( -- "SELFTESTS_MISSING_VALUES", -- getSelfTestName(), -- mPrefix -- + "." -- + PROP_RA_SUB_ID)); -- -- throw new EMissingSelfTestException(PROP_RA_SUB_ID); -- } -- } catch (EBaseException e) { -- mSelfTestSubsystem.log(mSelfTestSubsystem.getSelfTestLogger(), -- CMS.getLogMessage( -- "SELFTESTS_MISSING_NAME", -- getSelfTestName(), -- mPrefix -- + "." -- + PROP_RA_SUB_ID)); -- -- throw new EMissingSelfTestException(mPrefix, -- PROP_RA_SUB_ID, -- null); -- } -- -- // retrieve optional parameter(s) -- -- return; -- } -- -- /** -- * Notifies this subsystem if it is in execution mode. -- *

-- * -- * @exception ESelfTestException failed to start -- */ -- public void startupSelfTest() -- throws ESelfTestException { -- return; -- } -- -- /** -- * Stops this subsystem. The subsystem may call shutdownSelfTest -- * anytime after initialization. -- *

-- */ -- public void shutdownSelfTest() { -- return; -- } -- -- /** -- * Returns the name associated with this self test. This method may -- * return null if the self test has not been intialized. -- *

-- * -- * @return instanceName of this self test -- */ -- public String getSelfTestName() { -- return super.getSelfTestName(); -- } -- -- /** -- * Returns the root configuration storage (self test parameters) -- * associated with this subsystem. -- *

-- * -- * @return configuration store (self test parameters) of this subsystem -- */ -- public IConfigStore getSelfTestConfigStore() { -- return super.getSelfTestConfigStore(); -- } -- -- /** -- * Retrieves description associated with an individual self test. -- * This method may return null. -- *

-- * -- * @param locale locale of the client that requests the description -- * @return description of self test -- */ -- public String getSelfTestDescription(Locale locale) { -- return CMS.getUserMessage(locale, -- "CMS_SELFTESTS_RA_PRESENCE_DESCRIPTION"); -- } -- -- /** -- * Execute an individual self test. -- *

-- * -- * @param logger specifies logging subsystem -- * @exception ESelfTestException self test exception -- */ -- public void runSelfTest(ILogEventListener logger) -- throws ESelfTestException { -- String logMessage = null; -- IRegistrationAuthority ra = null; -- org.mozilla.jss.crypto.X509Certificate raCert = null; -- PublicKey raPubKey = null; -- -- ra = (IRegistrationAuthority) CMS.getSubsystem(mRaSubId); -- -- if (ra == null) { -- // log that the RA is not installed -- logMessage = CMS.getLogMessage("SELFTESTS_RA_IS_NOT_PRESENT", -- getSelfTestName()); -- -- mSelfTestSubsystem.log(logger, -- logMessage); -- -- throw new ESelfTestException(logMessage); -- } else { -- // Retrieve the RA certificate -- raCert = ra.getRACert(); -- -- if (raCert == null) { -- // log that the RA is not yet initialized -- logMessage = CMS.getLogMessage( -- "SELFTESTS_RA_IS_NOT_INITIALIZED", -- getSelfTestName()); -- -- mSelfTestSubsystem.log(logger, -- logMessage); -- -- throw new ESelfTestException(logMessage); -- } -- -- // Retrieve the RA certificate public key -- raPubKey = raCert.getPublicKey(); -- -- if (raPubKey == null) { -- // log that something is seriously wrong with the RA -- logMessage = CMS.getLogMessage("SELFTESTS_RA_IS_CORRUPT", -- getSelfTestName()); -- -- mSelfTestSubsystem.log(logger, -- logMessage); -- -- throw new ESelfTestException(logMessage); -- } -- -- // log that the RA is present -- logMessage = CMS.getLogMessage("SELFTESTS_RA_IS_PRESENT", -- getSelfTestName()); -- -- mSelfTestSubsystem.log(logger, -- logMessage); -- } -- -- return; -- } --} -diff --git a/base/server/cms/src/com/netscape/cms/selftests/tks/TKSKnownSessionKey.java b/base/server/cms/src/com/netscape/cms/selftests/tks/TKSKnownSessionKey.java -index d5e7c11..1686ba5 100644 ---- a/base/server/cms/src/com/netscape/cms/selftests/tks/TKSKnownSessionKey.java -+++ b/base/server/cms/src/com/netscape/cms/selftests/tks/TKSKnownSessionKey.java -@@ -104,7 +104,7 @@ public class TKSKnownSessionKey - mMacKey = getConfigByteArray("macKey", 16); - mUseSoftToken = getConfigString("useSoftToken"); - -- // AC: KDF SPEC CHANGE -+ // AC: KDF SPEC CHANGE - // read CUID for the KDD field - mKDD = getConfigByteArray("CUID", 10); - // -@@ -143,7 +143,7 @@ public class TKSKnownSessionKey - getSelfTestName(), mPrefix + ".nistSP800-108KdfUseCuidAsKdd")); - throw new EMissingSelfTestException("nistSP800-108KdfUseCuidAsKdd"); - } -- -+ - String defKeySetMacKey = null; - tks = CMS.getSubsystem(mTksSubId); - if (tks != null) { -@@ -175,7 +175,7 @@ public class TKSKnownSessionKey - if (mSessionKey == null) { - mSessionKey = SessionKey.ComputeSessionKey(mToken, mKeyName, - mCardChallenge, mHostChallenge, -- mKeyInfo, -+ mKeyInfo, - mNistSP800_108KdfOnKeyVersion, // AC: KDF SPEC CHANGE - pass in configuration self-test value - mNistSP800_108KdfUseCuidAsKdd, // AC: KDF SPEC CHANGE - pass in configuration self-test value - mCUID, -@@ -320,13 +320,12 @@ public class TKSKnownSessionKey - *

- * - * @param logger specifies logging subsystem -- * @exception ESelfTestException self test exception -+ * @exception Exception self test exception - */ -- public void runSelfTest(ILogEventListener logger) -- throws ESelfTestException { -- IConfigStore cs = CMS.getConfigStore(); -- String sharedSecretName; -+ public void runSelfTest(ILogEventListener logger) throws Exception { -+ - try { -+ IConfigStore cs = CMS.getConfigStore(); - boolean useNewNames = cs.getBoolean("tks.useNewSharedSecretNames", false); - if (useNewNames) { - String tpsList = cs.getString("tps.list", ""); -@@ -336,29 +335,39 @@ public class TKSKnownSessionKey - } - - for (String tpsID : tpsList.split(",")) { -- sharedSecretName = cs.getString("tps." + tpsID + ".nickname", ""); -+ String sharedSecretName = cs.getString("tps." + tpsID + ".nickname", ""); - if (!sharedSecretName.isEmpty()) { - CMS.debug("TKSKnownSessionKey: testing with key " + sharedSecretName); -- generateSessionKey(logger, sharedSecretName); -+ generateSessionKey(sharedSecretName); - } - } -+ - } else { - // legacy systems -- sharedSecretName = cs.getString("tks.tksSharedSymKeyName", "sharedSecret"); -- generateSessionKey(logger, sharedSecretName); -+ String sharedSecretName = cs.getString("tks.tksSharedSymKeyName", "sharedSecret"); -+ generateSessionKey(sharedSecretName); - } -- } catch (EBaseException e) { -- e.printStackTrace(); -- CMS.debug("TKSKnownSessionKey: failed to read config file to set up test"); -- String logMessage = CMS.getLogMessage("SELFTESTS_TKS_FAILED", getSelfTestName(), getSelfTestName()); -+ -+ String logMessage = CMS.getLogMessage( -+ "SELFTESTS_TKS_SUCCEEDED", -+ getSelfTestName(), -+ getSelfTestName()); -+ mSelfTestSubsystem.log(logger, logMessage); -+ CMS.debug("TKSKnownSessionKey self test SUCCEEDED"); -+ -+ } catch (Exception e) { -+ String logMessage = CMS.getLogMessage( -+ "SELFTESTS_TKS_FAILED", -+ getSelfTestName(), -+ getSelfTestName()); - mSelfTestSubsystem.log(logger, logMessage); -- throw new ESelfTestException(logMessage); -+ throw e; - } -+ - return; - } - -- private void generateSessionKey(ILogEventListener logger, String sharedSecretName) throws ESelfTestException { -- String logMessage; -+ private void generateSessionKey(String sharedSecretName) throws Exception { - String keySet = "defKeySet"; - - byte[] sessionKey = SessionKey.ComputeSessionKey( -@@ -374,14 +383,7 @@ public class TKSKnownSessionKey - // For FIPS compliance, the routine now returns a wrapped key, which can't be extracted and compared. - if (sessionKey == null) { - CMS.debug("TKSKnownSessionKey: generated no session key"); -- CMS.debug("TKSKnownSessionKey self test FAILED"); -- logMessage = CMS.getLogMessage("SELFTESTS_TKS_FAILED", getSelfTestName(), getSelfTestName()); -- mSelfTestSubsystem.log(logger, logMessage); -- throw new ESelfTestException(logMessage); -- } else { -- logMessage = CMS.getLogMessage("SELFTESTS_TKS_SUCCEEDED", getSelfTestName(), getSelfTestName()); -- mSelfTestSubsystem.log(logger, logMessage); -- CMS.debug("TKSKnownSessionKey self test SUCCEEDED"); -+ throw new Exception("No session key generated"); - } - } - } -diff --git a/base/server/cms/src/com/netscape/cms/servlet/admin/CMSAdminServlet.java b/base/server/cms/src/com/netscape/cms/servlet/admin/CMSAdminServlet.java -index b8cf27c..b6325b7 100644 ---- a/base/server/cms/src/com/netscape/cms/servlet/admin/CMSAdminServlet.java -+++ b/base/server/cms/src/com/netscape/cms/servlet/admin/CMSAdminServlet.java -@@ -3248,7 +3248,11 @@ public final class CMSAdminServlet extends AdminServlet { - - // store this information for console notification - content += "COMPLETED SUCCESSFULLY\n"; -- } catch (ESelfTestException e) { -+ -+ } catch (Exception e) { -+ -+ CMS.debug(e); -+ - // Check to see if the self test was critical: - if (mSelfTestSubsystem.isSelfTestCriticalOnDemand( - instanceName)) { -diff --git a/base/server/cmscore/src/com/netscape/cmscore/selftests/SelfTestSubsystem.java b/base/server/cmscore/src/com/netscape/cmscore/selftests/SelfTestSubsystem.java -index ad1a1b0..d060f81 100644 ---- a/base/server/cmscore/src/com/netscape/cmscore/selftests/SelfTestSubsystem.java -+++ b/base/server/cmscore/src/com/netscape/cmscore/selftests/SelfTestSubsystem.java -@@ -530,7 +530,11 @@ public class SelfTestSubsystem - } - - test.runSelfTest(mLogger); -- } catch (ESelfTestException e) { -+ -+ } catch (Exception e) { -+ -+ CMS.debug(e); -+ - // Check to see if the self test was critical: - if (isSelfTestCriticalOnDemand(instanceName)) { - log(mLogger, -@@ -810,146 +814,76 @@ public class SelfTestSubsystem - * - * - * @exception EMissingSelfTestException subsystem has missing name -- * @exception ESelfTestException self test exception -+ * @exception Exception self test exception - */ -- public void runSelfTestsAtStartup() -- throws EMissingSelfTestException, ESelfTestException { -- String auditMessage = null; -+ public void runSelfTestsAtStartup() throws Exception { - -- // ensure that any low-level exceptions are reported -- // to the signed audit log and stored as failures -- try { -- if (CMS.debugOn()) { -- CMS.debug("SelfTestSubsystem::runSelfTestsAtStartup():" -- + " ENTERING . . ."); -- } -+ // log that execution of startup self tests has begun -+ log(mLogger, -+ CMS.getLogMessage( -+ "CMSCORE_SELFTESTS_RUN_AT_STARTUP")); - -- // loop through all self test plugin instances -- // specified to be executed at server startup -- Enumeration instances = mStartupOrder.elements(); -+ // loop through all self test plugin instances -+ // specified to be executed at server startup -+ Enumeration instances = mStartupOrder.elements(); - -- while (instances.hasMoreElements()) { -- SelfTestOrderedInstance instance = instances.nextElement(); -+ while (instances.hasMoreElements()) { -+ SelfTestOrderedInstance instance = instances.nextElement(); - -- String instanceFullName = null; -- String instanceName = instance.getSelfTestName(); -+ String instanceFullName = null; -+ String instanceName = instance.getSelfTestName(); - -- if (instanceName != null) { -- instanceName = instanceName.trim(); -- instanceFullName = getFullName(mPrefix, -- instanceName); -- } else { -- log(mLogger, -- CMS.getLogMessage( -- "CMSCORE_SELFTESTS_PROPERTY_NAME_IS_NULL")); -+ if (instanceName == null) { -+ log(mLogger, -+ CMS.getLogMessage( -+ "CMSCORE_SELFTESTS_PROPERTY_NAME_IS_NULL")); - -- // store a message in the signed audit log file -- auditMessage = CMS.getLogMessage( -- LOGGING_SIGNED_AUDIT_SELFTESTS_EXECUTION, -- ILogger.SYSTEM_UID, -- ILogger.FAILURE); -+ throw new EMissingSelfTestException(); -+ } - -- audit(auditMessage); -+ instanceName = instanceName.trim(); -+ instanceFullName = getFullName(mPrefix, instanceName); - -- throw new EMissingSelfTestException(); -- } -+ if (!mSelfTestInstances.containsKey(instanceName)) { -+ // self test plugin instance property name is not present -+ log(mLogger, -+ CMS.getLogMessage( -+ "CMSCORE_SELFTESTS_PROPERTY_MISSING_NAME", -+ instanceFullName)); - -- if (mSelfTestInstances.containsKey(instanceName)) { -- ISelfTest test = mSelfTestInstances.get(instanceName); -- -- try { -- if (CMS.debugOn()) { -- CMS.debug("SelfTestSubsystem::runSelfTestsAtStartup():" -- + " running \"" -- + test.getSelfTestName() -- + "\""); -- } -- -- test.runSelfTest(mLogger); -- } catch (ESelfTestException e) { -- // Check to see if the self test was critical: -- if (isSelfTestCriticalAtStartup(instanceName)) { -- log(mLogger, -- CMS.getLogMessage( -- "CMSCORE_SELFTESTS_RUN_AT_STARTUP_FAILED", -- instanceFullName)); -- -- // store a message in the signed audit log file -- auditMessage = CMS.getLogMessage( -- LOGGING_SIGNED_AUDIT_SELFTESTS_EXECUTION, -- ILogger.SYSTEM_UID, -- ILogger.FAILURE); -- -- audit(auditMessage); -- -- // shutdown the system gracefully -- CMS.shutdown(); -- -- IConfigStore cs = CMS.getConfigStore(); -- String instanceID = cs.get("instanceId"); -- String subsystemID = cs.get("cs.type").toLowerCase(); -- -- System.out.println("SelfTestSubsystem: Disabling \"" + subsystemID + "\" subsystem due to selftest failure."); -- -- try { -- ProcessBuilder pb = new ProcessBuilder("pki-server", "subsystem-disable", "-i", instanceID, subsystemID); -- Process process = pb.inheritIO().start(); -- int rc = process.waitFor(); -- -- if (rc != 0) { -- System.out.println("SelfTestSubsystem: Unable to disable \"" + subsystemID + "\". RC: " + rc); -- } -- -- } catch (Exception e2) { -- e.printStackTrace(); -- } -- -- return; -- } -- } -- } else { -- // self test plugin instance property name is not present -- log(mLogger, -- CMS.getLogMessage( -- "CMSCORE_SELFTESTS_PROPERTY_MISSING_NAME", -- instanceFullName)); -+ throw new EMissingSelfTestException(instanceFullName); -+ } - -- // store a message in the signed audit log file -- auditMessage = CMS.getLogMessage( -- LOGGING_SIGNED_AUDIT_SELFTESTS_EXECUTION, -- ILogger.SYSTEM_UID, -- ILogger.FAILURE); -+ ISelfTest test = mSelfTestInstances.get(instanceName); - -- audit(auditMessage); -+ try { -+ CMS.debug("SelfTestSubsystem: running " + test.getSelfTestName()); -+ test.runSelfTest(mLogger); - -- throw new EMissingSelfTestException(instanceFullName); -- } -- } -+ } catch (Exception e) { - -- // store a message in the signed audit log file -- auditMessage = CMS.getLogMessage( -- LOGGING_SIGNED_AUDIT_SELFTESTS_EXECUTION, -- ILogger.SYSTEM_UID, -- ILogger.SUCCESS); -+ CMS.debug(e); - -- audit(auditMessage); -+ // Check to see if the self test was critical: -+ if (!isSelfTestCriticalAtStartup(instanceName)) { -+ continue; -+ } -+ -+ log(mLogger, -+ CMS.getLogMessage( -+ "CMSCORE_SELFTESTS_RUN_AT_STARTUP_FAILED", -+ instanceFullName)); - -- if (CMS.debugOn()) { -- CMS.debug("SelfTestSubsystem::runSelfTestsAtStartup():" -- + " EXITING."); -+ throw e; - } -- } catch (EMissingSelfTestException eAudit1) { -- // store a message in the signed audit log file -- auditMessage = CMS.getLogMessage( -- LOGGING_SIGNED_AUDIT_SELFTESTS_EXECUTION, -- ILogger.SYSTEM_UID, -- ILogger.FAILURE); -+ } - -- audit(auditMessage); -+ // log that execution of all "critical" startup self tests -+ // has completed "successfully" -+ log(mLogger, -+ CMS.getLogMessage( -+ "CMSCORE_SELFTESTS_RUN_AT_STARTUP_SUCCEEDED")); - -- // rethrow the specific exception to be handled later -- throw eAudit1; -- } - } - - public void log(int level, String msg) { -@@ -1831,39 +1765,88 @@ public class SelfTestSubsystem - * - * @exception EBaseException base CMS exception - */ -- public void startup() -- throws EBaseException { -+ public void startup() throws EBaseException { -+ - // loop through all self test plugin instances - Enumeration instances = mSelfTestInstances.elements(); - - while (instances.hasMoreElements()) { - ISelfTest instance = instances.nextElement(); -- - instance.startupSelfTest(); - } - -- if (!CMS.isPreOpMode()) { -- // run all self test plugin instances (designated at startup) -- Enumeration selftests = mStartupOrder.elements(); -+ if (CMS.isPreOpMode()) { -+ // do not run selftests in pre-op mode -+ return; -+ } - -- if (selftests.hasMoreElements()) { -- // log that execution of startup self tests has begun -- log(mLogger, -- CMS.getLogMessage( -- "CMSCORE_SELFTESTS_RUN_AT_STARTUP")); -+ // run all self test plugin instances (designated at startup) -+ Enumeration selftests = mStartupOrder.elements(); - -- // execute all startup self tests -- runSelfTestsAtStartup(); -+ if (!selftests.hasMoreElements()) { -+ log(mLogger, -+ CMS.getLogMessage( -+ "CMSCORE_SELFTESTS_NOT_RUN_AT_STARTUP")); -+ return; -+ } - -- // log that execution of all "critical" startup self tests -- // has completed "successfully" -- log(mLogger, -- CMS.getLogMessage( -- "CMSCORE_SELFTESTS_RUN_AT_STARTUP_SUCCEEDED")); -- } else { -- log(mLogger, -- CMS.getLogMessage( -- "CMSCORE_SELFTESTS_NOT_RUN_AT_STARTUP")); -+ // ensure that any low-level exceptions are reported -+ // to the signed audit log and stored as failures -+ try { -+ // execute all startup self tests -+ runSelfTestsAtStartup(); -+ -+ // store a message in the signed audit log file -+ String auditMessage = CMS.getLogMessage( -+ LOGGING_SIGNED_AUDIT_SELFTESTS_EXECUTION, -+ ILogger.SYSTEM_UID, -+ ILogger.SUCCESS); -+ -+ audit(auditMessage); -+ -+ } catch (EMissingSelfTestException e) { -+ -+ // store a message in the signed audit log file -+ String auditMessage = CMS.getLogMessage( -+ LOGGING_SIGNED_AUDIT_SELFTESTS_EXECUTION, -+ ILogger.SYSTEM_UID, -+ ILogger.FAILURE); -+ -+ audit(auditMessage); -+ -+ // rethrow the specific exception to be handled later -+ throw e; -+ -+ } catch (Exception e) { -+ -+ // store a message in the signed audit log file -+ String auditMessage = CMS.getLogMessage( -+ LOGGING_SIGNED_AUDIT_SELFTESTS_EXECUTION, -+ ILogger.SYSTEM_UID, -+ ILogger.FAILURE); -+ -+ audit(auditMessage); -+ -+ // shutdown the system gracefully -+ CMS.shutdown(); -+ -+ IConfigStore cs = CMS.getConfigStore(); -+ String instanceID = cs.get("instanceId"); -+ String subsystemID = cs.get("cs.type").toLowerCase(); -+ -+ System.out.println("SelfTestSubsystem: Disabling \"" + subsystemID + "\" subsystem due to selftest failure."); -+ -+ try { -+ ProcessBuilder pb = new ProcessBuilder("pki-server", "subsystem-disable", "-i", instanceID, subsystemID); -+ Process process = pb.inheritIO().start(); -+ int rc = process.waitFor(); -+ -+ if (rc != 0) { -+ System.out.println("SelfTestSubsystem: Unable to disable \"" + subsystemID + "\". RC: " + rc); -+ } -+ -+ } catch (Exception e2) { -+ e.printStackTrace(); - } - } - } -diff --git a/base/tps/src/org/dogtagpki/server/tps/selftests/TPSPresence.java b/base/tps/src/org/dogtagpki/server/tps/selftests/TPSPresence.java -index 65ac197..665f068 100644 ---- a/base/tps/src/org/dogtagpki/server/tps/selftests/TPSPresence.java -+++ b/base/tps/src/org/dogtagpki/server/tps/selftests/TPSPresence.java -@@ -140,48 +140,60 @@ public class TPSPresence extends ASelfTest { - *

- * - * @param logger specifies logging subsystem -- * @exception ESelfTestException self test exception -+ * @exception Exception self test exception - */ -- public void runSelfTest(ILogEventListener logger) -- throws ESelfTestException { -- String logMessage = null; -+ public void runSelfTest(ILogEventListener logger) throws Exception { -+ - TPSSubsystem tps = (TPSSubsystem) CMS.getSubsystem(tpsSubId); - if (tps == null) { - // log that the TPS is not installed -- logMessage = CMS.getLogMessage("SELFTESTS_TPS_IS_NOT_PRESENT", getSelfTestName()); -+ String logMessage = CMS.getLogMessage( -+ "SELFTESTS_TPS_IS_NOT_PRESENT", -+ getSelfTestName()); - mSelfTestSubsystem.log(logger, logMessage); -- throw new ESelfTestException(logMessage); -+ throw new Exception(logMessage); - } - - // Retrieve the TPS certificate -- org.mozilla.jss.crypto.X509Certificate tpsCert = null; -+ org.mozilla.jss.crypto.X509Certificate tpsCert; - try { - tpsCert = tps.getSubsystemCert(); -+ - } catch (Exception e) { -- e.printStackTrace(); - // cert does not exist or is not yet configured - // tpsCert will remain null -+ // log that the TPS is not yet initialized -+ String logMessage = CMS.getLogMessage( -+ "SELFTESTS_TPS_IS_NOT_INITIALIZED", -+ getSelfTestName()); -+ mSelfTestSubsystem.log(logger, logMessage); -+ throw e; - } - - if (tpsCert == null) { - // log that the TPS is not yet initialized -- logMessage = CMS.getLogMessage("SELFTESTS_TPS_IS_NOT_INITIALIZED", -+ String logMessage = CMS.getLogMessage( -+ "SELFTESTS_TPS_IS_NOT_INITIALIZED", - getSelfTestName()); - mSelfTestSubsystem.log(logger, logMessage); -- throw new ESelfTestException(logMessage); -+ throw new Exception(logMessage); - } - - // Retrieve the TPS certificate public key - PublicKey tpsPubKey = tpsCert.getPublicKey(); - if (tpsPubKey == null) { - // log that something is seriously wrong with the TPS -- logMessage = CMS.getLogMessage("SELFTESTS_TPS_IS_CORRUPT", getSelfTestName()); -+ String logMessage = CMS.getLogMessage( -+ "SELFTESTS_TPS_IS_CORRUPT", -+ getSelfTestName()); - mSelfTestSubsystem.log(logger, logMessage); -- throw new ESelfTestException(logMessage); -+ throw new Exception(logMessage); - } - - // log that the TPS is present -- logMessage = CMS.getLogMessage("SELFTESTS_TPS_IS_PRESENT", getSelfTestName()); -+ String logMessage = CMS.getLogMessage( -+ "SELFTESTS_TPS_IS_PRESENT", -+ getSelfTestName()); - mSelfTestSubsystem.log(logger, logMessage); - } - } -diff --git a/base/tps/src/org/dogtagpki/server/tps/selftests/TPSValidity.java b/base/tps/src/org/dogtagpki/server/tps/selftests/TPSValidity.java -index f140d6e..28ac38d 100644 ---- a/base/tps/src/org/dogtagpki/server/tps/selftests/TPSValidity.java -+++ b/base/tps/src/org/dogtagpki/server/tps/selftests/TPSValidity.java -@@ -144,54 +144,59 @@ public class TPSValidity extends ASelfTest { - *

- * - * @param logger specifies logging subsystem -- * @exception ESelfTestException self test exception -+ * @exception Exception self test exception - */ -- public void runSelfTest(ILogEventListener logger) -- throws ESelfTestException { -- String logMessage = null; -- TPSSubsystem tps = (TPSSubsystem) CMS.getSubsystem(tpsSubId); -+ public void runSelfTest(ILogEventListener logger) throws Exception { - -+ TPSSubsystem tps = (TPSSubsystem) CMS.getSubsystem(tpsSubId); - if (tps == null) { - // log that the TPS is not installed -- logMessage = CMS.getLogMessage("SELFTESTS_TPS_IS_NOT_PRESENT", getSelfTestName()); -+ String logMessage = CMS.getLogMessage( -+ "SELFTESTS_TPS_IS_NOT_PRESENT", -+ getSelfTestName()); - mSelfTestSubsystem.log(logger, logMessage); -- throw new ESelfTestException(logMessage); -+ throw new Exception(logMessage); - } - - // Retrieve the TPS subsystem certificate -- X509CertImpl tpsCert = null; -+ X509CertImpl tpsCert; - try { - tpsCert = new X509CertImpl(tps.getSubsystemCert().getEncoded()); - } catch (Exception e) { - // certificate is not present or has not been configured -- // tpsCert will remain null -- } -- -- if (tpsCert == null) { - // log that the TPS is not yet initialized -- logMessage = CMS.getLogMessage("SELFTESTS_TPS_IS_NOT_INITIALIZED", -+ String logMessage = CMS.getLogMessage( -+ "SELFTESTS_TPS_IS_NOT_INITIALIZED", - getSelfTestName()); - mSelfTestSubsystem.log(logger, logMessage); -- throw new ESelfTestException(logMessage); -+ throw e; - } - - // Check the TPS validity period - try { - tpsCert.checkValidity(); -+ - } catch (CertificateNotYetValidException e) { - // log that the TPS is not yet valid -- logMessage = CMS.getLogMessage("SELFTESTS_TPS_IS_NOT_YET_VALID", getSelfTestName()); -+ String logMessage = CMS.getLogMessage( -+ "SELFTESTS_TPS_IS_NOT_YET_VALID", -+ getSelfTestName()); - mSelfTestSubsystem.log(logger, logMessage); -- throw new ESelfTestException(logMessage); -+ throw e; -+ - } catch (CertificateExpiredException e) { - // log that the TPS is expired -- logMessage = CMS.getLogMessage("SELFTESTS_TPS_IS_EXPIRED", getSelfTestName()); -+ String logMessage = CMS.getLogMessage( -+ "SELFTESTS_TPS_IS_EXPIRED", -+ getSelfTestName()); - mSelfTestSubsystem.log(logger, logMessage); -- throw new ESelfTestException(logMessage); -+ throw e; - } - - // log that the TPS is valid -- logMessage = CMS.getLogMessage("SELFTESTS_TPS_IS_VALID", getSelfTestName()); -+ String logMessage = CMS.getLogMessage( -+ "SELFTESTS_TPS_IS_VALID", -+ getSelfTestName()); - mSelfTestSubsystem.log(logger, logMessage); - } - } --- -1.8.3.1 - - -From 9b62371172bbf0868e84e7f1d8d9ab48e5a0afff Mon Sep 17 00:00:00 2001 -From: "Endi S. Dewata" -Date: Wed, 24 Jun 2015 16:19:55 -0400 -Subject: [PATCH 03/21] Fixed Modutil.is_security_module_registered(). - -Due to issues with HSM the Modutil.is_security_module_registered() -has been modified to the get the list of all registered modules -and then use it to check if a module is registered. - -https://fedorahosted.org/pki/ticket/1444 ---- - .../python/pki/server/deployment/pkihelper.py | 90 +++++++++++----------- - 1 file changed, 45 insertions(+), 45 deletions(-) - -diff --git a/base/server/python/pki/server/deployment/pkihelper.py b/base/server/python/pki/server/deployment/pkihelper.py -index 42ca0d9..5bc4ffa 100644 ---- a/base/server/python/pki/server/deployment/pkihelper.py -+++ b/base/server/python/pki/server/deployment/pkihelper.py -@@ -2688,56 +2688,56 @@ class Modutil: - def __init__(self, deployer): - self.mdict = deployer.mdict - -- def is_security_module_registered(self, path, modulename, -- prefix=None, critical_failure=True): -- status = False -- try: -- # Compose this "modutil" command -- command = ["modutil"] -- # Provide a path to the NSS security databases -- if path: -- command.extend(["-dbdir", path]) -- else: -- config.pki_log.error( -- log.PKIHELPER_MODUTIL_MISSING_PATH, -- extra=config.PKI_INDENTATION_LEVEL_2) -- raise Exception(log.PKIHELPER_MODUTIL_MISSING_PATH) -- # Add optional security database prefix -- if prefix is not None: -- command.extend(["--dbprefix", prefix]) -- # Append '-nocertdb' switch -- command.extend(["-nocertdb"]) -- # Specify a 'modulename' -- if modulename: -- command.extend(["-list", modulename]) -- else: -- config.pki_log.error( -- log.PKIHELPER_MODUTIL_MISSING_MODULENAME, -- extra=config.PKI_INDENTATION_LEVEL_2) -- raise Exception(log.PKIHELPER_MODUTIL_MISSING_MODULENAME) -- # Display this "modutil" command -- config.pki_log.info( -- log.PKIHELPER_REGISTERED_SECURITY_MODULE_CHECK_1, -- ' '.join(command), -+ def is_security_module_registered(self, path, modulename, prefix=None): -+ -+ if not path: -+ config.pki_log.error( -+ log.PKIHELPER_MODUTIL_MISSING_PATH, - extra=config.PKI_INDENTATION_LEVEL_2) -- # Execute this "modutil" command -- subprocess.check_call(command) -- # 'modulename' is already registered -- status = True -- config.pki_log.info( -- log.PKIHELPER_REGISTERED_SECURITY_MODULE_1, modulename, -+ raise Exception(log.PKIHELPER_MODUTIL_MISSING_PATH) -+ -+ if not modulename: -+ config.pki_log.error( -+ log.PKIHELPER_MODUTIL_MISSING_MODULENAME, - extra=config.PKI_INDENTATION_LEVEL_2) -- except subprocess.CalledProcessError as exc: -- # 'modulename' is not registered -+ raise Exception(log.PKIHELPER_MODUTIL_MISSING_MODULENAME) -+ -+ command = [ -+ 'modutil', -+ '-list', -+ '-dbdir', path, -+ '-nocertdb'] -+ -+ if prefix: -+ command.extend(['--dbprefix', prefix]) -+ -+ config.pki_log.info( -+ log.PKIHELPER_REGISTERED_SECURITY_MODULE_CHECK_1, -+ ' '.join(command), -+ extra=config.PKI_INDENTATION_LEVEL_2) -+ -+ # execute command -+ p = subprocess.Popen(command, stdout=subprocess.PIPE) -+ output = p.communicate()[0] -+ -+ p.wait() -+ # ignore return code due to issues with HSM -+ # https://fedorahosted.org/pki/ticket/1444 -+ -+ # find modules from lines such as '1. NSS Internal PKCS #11 Module' -+ modules = re.findall(r'^ +\d+\. +(.*)$', output, re.MULTILINE) -+ -+ if modulename not in modules: - config.pki_log.info( - log.PKIHELPER_UNREGISTERED_SECURITY_MODULE_1, modulename, - extra=config.PKI_INDENTATION_LEVEL_2) -- except OSError as exc: -- config.pki_log.error(log.PKI_OSERROR_1, exc, -- extra=config.PKI_INDENTATION_LEVEL_2) -- if critical_failure: -- raise -- return status -+ return False -+ -+ config.pki_log.info( -+ log.PKIHELPER_REGISTERED_SECURITY_MODULE_1, modulename, -+ extra=config.PKI_INDENTATION_LEVEL_2) -+ return True -+ - - def register_security_module(self, path, modulename, libfile, - prefix=None, critical_failure=True): --- -1.8.3.1 - - -From c9180f086971dcf6f183ed5f627510f2183cc61e Mon Sep 17 00:00:00 2001 -From: "Endi S. Dewata" -Date: Mon, 29 Jun 2015 15:09:07 -0400 -Subject: [PATCH 04/21] Updated pki-cert man page. - -The man page for pki-cert has been modified to describe the file -format used to specify the search constraints. - -https://fedorahosted.org/pki/ticket/995 ---- - base/java-tools/man/man1/pki-cert.1 | 67 +++++++++++++++++++++++++++++++++++++ - 1 file changed, 67 insertions(+) - -diff --git a/base/java-tools/man/man1/pki-cert.1 b/base/java-tools/man/man1/pki-cert.1 -index ad2f566..ffa1fea 100644 ---- a/base/java-tools/man/man1/pki-cert.1 -+++ b/base/java-tools/man/man1/pki-cert.1 -@@ -105,6 +105,73 @@ It is also possible to search for and list specific certificates by adding a sea - - .B pki ca-cert-find --issuedOnFrom 2012-06-15 - -+To list certificates with search constraints defined in a file: -+ -+.B pki ca-cert-find --input -+ -+where the file is in the following format: -+ -+.IP -+.nf -+ -+ -+ -+ true -+ -+ -+ -+ false -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ false -+ -+ -+ -+ false -+ -+ -+ false -+ -+ -+ false -+ -+ -+ false -+ -+ -+ false -+ -+ -+ -+ false -+ -+ -+ -+ false -+ -+ -+ -+ false -+ -+ -+ -+ -+ false -+ -+ -+ -+ -+ -+.fi -+ -+.PP - To view a particular certificate: - - .B pki ca-cert-show --- -1.8.3.1 - - -From b9e461ca8a099b4535aa916886697c6eff01e431 Mon Sep 17 00:00:00 2001 -From: "Endi S. Dewata" -Date: Mon, 29 Jun 2015 16:04:16 -0400 -Subject: [PATCH 05/21] Updated pki man page. - -The pki man page has been updated to describe results paging -parameters. - -https://fedorahosted.org/pki/ticket/1122 ---- - base/java-tools/man/man1/pki.1 | 25 +++++++++++++++++++++++++ - 1 file changed, 25 insertions(+) - -diff --git a/base/java-tools/man/man1/pki.1 b/base/java-tools/man/man1/pki.1 -index 9e174e1..41ee3d3 100644 ---- a/base/java-tools/man/man1/pki.1 -+++ b/base/java-tools/man/man1/pki.1 -@@ -220,6 +220,31 @@ Client-side password files generally store a password in an equals-sign-delimite - .B foobar - where: token="internal" (default), password="foobar" - -+.SS Results Paging -+ -+Some commands (e.g. cert-find) may return multiple results. Since the number -+of results may be large, the results are split into multiple pages. By default -+the command will return only the first page (e.g. the first 20 results). To -+retrieve results from another page, additional paging parameters can be -+specified: -+ -+.nf -+* start: index of the first result to return (default: 0) -+* size: number of results to return (default: 20) -+.fi -+ -+For example, to retrieve the first page (index #0-#19): -+ -+.B pki cert-find --start 0 --size 20 -+ -+To retrieve the second page (index #20-#39): -+ -+.B pki cert-find --start 20 --size 20 -+ -+To retrieve the third page (index #40-#59): -+ -+.B pki cert-find --start 40 --size 20 -+ - .SH FILES - .I /usr/bin/pki - --- -1.8.3.1 - - -From f0637352f12faed2727ee6dcd4661835bf9e2c40 Mon Sep 17 00:00:00 2001 -From: "Endi S. Dewata" -Date: Mon, 29 Jun 2015 10:00:08 -0400 -Subject: [PATCH 06/21] Cleaned up SystemConfigService.validateRequest(). - -The configure() in SystemConfigService method has been modified to -log only the error message in normal responses but log the full -stack trace when unexpected issues occur. - -The validateData() in SystemConfigService has been renamed to -validateRequest() for clarity. The log messages have been modified -to include the invalid values entered in the request. ---- - .../cms/servlet/test/ConfigurationTest.java | 2 +- - .../certsrv/system/SystemConfigClient.java | 2 +- - .../certsrv/system/SystemConfigResource.java | 2 +- - .../dogtagpki/server/rest/SystemConfigService.java | 69 ++++++++++++---------- - 4 files changed, 41 insertions(+), 34 deletions(-) - -diff --git a/base/common/functional/src/com/netscape/cms/servlet/test/ConfigurationTest.java b/base/common/functional/src/com/netscape/cms/servlet/test/ConfigurationTest.java -index bf4dc89..69994fa 100644 ---- a/base/common/functional/src/com/netscape/cms/servlet/test/ConfigurationTest.java -+++ b/base/common/functional/src/com/netscape/cms/servlet/test/ConfigurationTest.java -@@ -76,7 +76,7 @@ public class ConfigurationTest { - System.exit(1); - } - -- public static void main(String args[]) throws NoSuchAlgorithmException, TokenException, IOException, InvalidBERException { -+ public static void main(String args[]) throws Exception { - String host = null; - String port = null; - String cstype = null; -diff --git a/base/common/src/com/netscape/certsrv/system/SystemConfigClient.java b/base/common/src/com/netscape/certsrv/system/SystemConfigClient.java -index 242f005..8208915 100644 ---- a/base/common/src/com/netscape/certsrv/system/SystemConfigClient.java -+++ b/base/common/src/com/netscape/certsrv/system/SystemConfigClient.java -@@ -40,7 +40,7 @@ public class SystemConfigClient extends Client { - configClient = createProxy(SystemConfigResource.class); - } - -- public ConfigurationResponse configure(ConfigurationRequest data) { -+ public ConfigurationResponse configure(ConfigurationRequest data) throws Exception { - return configClient.configure(data); - } - } -diff --git a/base/common/src/com/netscape/certsrv/system/SystemConfigResource.java b/base/common/src/com/netscape/certsrv/system/SystemConfigResource.java -index 0cebb60..9c570eb 100644 ---- a/base/common/src/com/netscape/certsrv/system/SystemConfigResource.java -+++ b/base/common/src/com/netscape/certsrv/system/SystemConfigResource.java -@@ -29,5 +29,5 @@ public interface SystemConfigResource { - - @POST - @Path("configure") -- public ConfigurationResponse configure(ConfigurationRequest data); -+ public ConfigurationResponse configure(ConfigurationRequest data) throws Exception; - } -diff --git a/base/server/cms/src/org/dogtagpki/server/rest/SystemConfigService.java b/base/server/cms/src/org/dogtagpki/server/rest/SystemConfigService.java -index 2de087b..75e3065 100644 ---- a/base/server/cms/src/org/dogtagpki/server/rest/SystemConfigService.java -+++ b/base/server/cms/src/org/dogtagpki/server/rest/SystemConfigService.java -@@ -111,28 +111,38 @@ public class SystemConfigService extends PKIService implements SystemConfigResou - * @see com.netscape.cms.servlet.csadmin.SystemConfigurationResource#configure(com.netscape.cms.servlet.csadmin.data.ConfigurationData) - */ - @Override -- public ConfigurationResponse configure(ConfigurationRequest request) { -+ public ConfigurationResponse configure(ConfigurationRequest request) throws Exception { -+ -+ CMS.debug("SystemConfigService: configure()"); -+ - try { - ConfigurationResponse response = new ConfigurationResponse(); - configure(request, response); - return response; - -- } catch (Throwable t) { -- CMS.debug(t); -- throw t; -+ } catch (PKIException e) { // normal responses -+ CMS.debug(e.getMessage()); // log the response -+ throw e; -+ -+ } catch (Exception e) { // unexpected exceptions -+ CMS.debug(e); // show stack trace for troubleshooting -+ throw e; -+ -+ } catch (Error e) { // system errors -+ CMS.debug(e); // show stack trace for troubleshooting -+ throw e; - } - } - -- public void configure(ConfigurationRequest data, ConfigurationResponse response) { -+ public void configure(ConfigurationRequest data, ConfigurationResponse response) throws Exception { -+ - - if (csState.equals("1")) { - throw new BadRequestException("System is already configured"); - } - -- CMS.debug("SystemConfigService(): configure() called"); -- CMS.debug(data.toString()); -- -- validateData(data); -+ CMS.debug("SystemConfigService: request: " + data); -+ validateRequest(data); - - Collection certList = getCertList(data); - -@@ -1020,22 +1030,15 @@ public class SystemConfigService extends PKIService implements SystemConfigResou - } - } - -- private void validateData(ConfigurationRequest data) { -- // get required info from CS.cfg -- String preopPin; -- try { -- preopPin = cs.getString("preop.pin"); -- } catch (Exception e) { -- CMS.debug("validateData: Failed to get required config form CS.cfg"); -- e.printStackTrace(); -- throw new PKIException("Unable to retrieve required configuration from configuration files"); -- } -+ private void validateRequest(ConfigurationRequest data) throws Exception { - -- // get the preop pin and validate it -+ // validate installation pin - String pin = data.getPin(); - if (pin == null) { - throw new BadRequestException("No preop pin provided"); - } -+ -+ String preopPin = cs.getString("preop.pin"); - if (!preopPin.equals(pin)) { - throw new BadRequestException("Incorrect pin provided"); - } -@@ -1067,6 +1070,7 @@ public class SystemConfigService extends PKIService implements SystemConfigResou - if (data.getSecurityDomainName() == null) { - throw new BadRequestException("Security Domain Name is not provided"); - } -+ - } else if (domainType.equals(ConfigurationRequest.EXISTING_DOMAIN) || - domainType.equals(ConfigurationRequest.NEW_SUBDOMAIN)) { - if (data.getStandAlone()) { -@@ -1079,11 +1083,11 @@ public class SystemConfigService extends PKIService implements SystemConfigResou - } - - try { -- @SuppressWarnings("unused") -- URL admin_u = new URL(domainURI); // check for invalid URL -+ new URL(domainURI); - } catch (MalformedURLException e) { -- throw new BadRequestException("Invalid security domain URI"); -+ throw new BadRequestException("Invalid security domain URI: " + domainURI, e); - } -+ - if ((data.getSecurityDomainUser() == null) || (data.getSecurityDomainPassword() == null)) { - throw new BadRequestException("Security domain user or password not provided"); - } -@@ -1109,11 +1113,13 @@ public class SystemConfigService extends PKIService implements SystemConfigResou - throw new BadRequestException("Clone selected, but no clone URI provided"); - } - try { -- @SuppressWarnings("unused") -- URL url = new URL(cloneUri); // check for invalid URL -+ URL url = new URL(cloneUri); - // confirm protocol is https -+ if (!"https".equals(url.getProtocol())) { -+ throw new BadRequestException("Clone URI must use HTTPS protocol: " + cloneUri); -+ } - } catch (MalformedURLException e) { -- throw new BadRequestException("Invalid clone URI"); -+ throw new BadRequestException("Invalid clone URI: " + cloneUri, e); - } - - if (data.getToken().equals(ConfigurationRequest.TOKEN_DEFAULT)) { -@@ -1133,6 +1139,7 @@ public class SystemConfigService extends PKIService implements SystemConfigResou - throw new BadRequestException("P12 password should not be provided since HSM clones must share their HSM master's private keys"); - } - } -+ - } else { - data.setClone("false"); - } -@@ -1145,7 +1152,7 @@ public class SystemConfigService extends PKIService implements SystemConfigResou - try { - Integer.parseInt(data.getDsPort()); // check for errors - } catch (NumberFormatException e) { -- throw new BadRequestException("Internal database port is invalid"); -+ throw new BadRequestException("Internal database port is invalid: " + data.getDsPort(), e); - } - - String basedn = data.getBaseDN(); -@@ -1173,7 +1180,7 @@ public class SystemConfigService extends PKIService implements SystemConfigResou - try { - Integer.parseInt(masterReplicationPort); // check for errors - } catch (NumberFormatException e) { -- throw new BadRequestException("Master replication port is invalid"); -+ throw new BadRequestException("Master replication port is invalid: " + masterReplicationPort, e); - } - } - -@@ -1181,8 +1188,8 @@ public class SystemConfigService extends PKIService implements SystemConfigResou - if (cloneReplicationPort != null && cloneReplicationPort.length() > 0) { - try { - Integer.parseInt(cloneReplicationPort); // check for errors -- } catch (Exception e) { -- throw new BadRequestException("Clone replication port is invalid"); -+ } catch (NumberFormatException e) { -+ throw new BadRequestException("Clone replication port is invalid: " + cloneReplicationPort, e); - } - } - -@@ -1293,7 +1300,7 @@ public class SystemConfigService extends PKIService implements SystemConfigResou - try { - Integer.parseInt(data.getAuthdbPort()); // check for errors - } catch (NumberFormatException e) { -- throw new BadRequestException("Authdb port is invalid"); -+ throw new BadRequestException("Authentication Database port is invalid: " + data.getAuthdbPort(), e); - } - - // TODO check connection with authdb --- -1.8.3.1 - - -From 3937d69c1dd5f9ecd7940809b474097d63cb97b3 Mon Sep 17 00:00:00 2001 -From: "Endi S. Dewata" -Date: Mon, 29 Jun 2015 13:29:41 -0400 -Subject: [PATCH 07/21] Cleaned up SystemConfigService.configureClone(). - -The getCloningData() in SystemConfigService has been renamed to -configureClone(). Redundant try-catch blocks have been removed. -Some exception messages have been modified to include more info. ---- - .../dogtagpki/server/rest/SystemConfigService.java | 72 +++++++--------------- - .../server/tps/rest/TPSInstallerService.java | 2 +- - 2 files changed, 23 insertions(+), 51 deletions(-) - -diff --git a/base/server/cms/src/org/dogtagpki/server/rest/SystemConfigService.java b/base/server/cms/src/org/dogtagpki/server/rest/SystemConfigService.java -index 75e3065..73d24a7 100644 ---- a/base/server/cms/src/org/dogtagpki/server/rest/SystemConfigService.java -+++ b/base/server/cms/src/org/dogtagpki/server/rest/SystemConfigService.java -@@ -799,7 +799,7 @@ public class SystemConfigService extends PKIService implements SystemConfigResou - } - } - -- private void getCloningData(ConfigurationRequest data, Collection certList, String token, String domainXML) { -+ private void configureClone(ConfigurationRequest data, Collection certList, String token, String domainXML) throws Exception { - for (String tag : certList) { - if (tag.equals("sslserver")) { - cs.putBoolean("preop.cert." + tag + ".enable", true); -@@ -809,73 +809,45 @@ public class SystemConfigService extends PKIService implements SystemConfigResou - } - - String cloneUri = data.getCloneUri(); -- URL url = null; -- try { -- url = new URL(cloneUri); -- } catch (MalformedURLException e) { -- // should not reach here as this check is done in validate() -- } -+ URL url = new URL(cloneUri); - String masterHost = url.getHost(); - int masterPort = url.getPort(); - -- // check and store cloneURI information -- boolean validCloneUri; -- try { -- validCloneUri = ConfigurationUtils.isValidCloneURI(domainXML, masterHost, masterPort); -- } catch (Exception e) { -- CMS.debug(e); -- throw new PKIException("Error in determining whether clone URI is valid"); -- } -+ CMS.debug("SystemConfigService: validate clone URI: " + url); -+ boolean validCloneUri = ConfigurationUtils.isValidCloneURI(domainXML, masterHost, masterPort); - - if (!validCloneUri) { - throw new BadRequestException( -- "Invalid clone URI provided. Does not match the available subsystems in the security domain"); -+ "Clone URI does not match available subsystems: " + url); - } - - if (csType.equals("CA")) { -- try { -- int masterAdminPort = ConfigurationUtils.getPortFromSecurityDomain(domainXML, -- masterHost, masterPort, "CA", "SecurePort", "SecureAdminPort"); -- ConfigurationUtils.importCertChain(masterHost, masterAdminPort, "/ca/admin/ca/getCertChain", -- "clone"); -- } catch (Exception e) { -- CMS.debug(e); -- throw new PKIException("Failed to import certificate chain from master" + e); -- } -+ CMS.debug("SystemConfigService: import certificate chain from master"); -+ int masterAdminPort = ConfigurationUtils.getPortFromSecurityDomain(domainXML, -+ masterHost, masterPort, "CA", "SecurePort", "SecureAdminPort"); -+ ConfigurationUtils.importCertChain(masterHost, masterAdminPort, -+ "/ca/admin/ca/getCertChain", "clone"); - } - -- try { -- CMS.debug("SystemConfigService.getCloningData(): get config entries"); -- ConfigurationUtils.getConfigEntriesFromMaster(); -- } catch (Exception e) { -- CMS.debug(e); -- throw new PKIException("Failed to obtain configuration entries from the master for cloning " + e); -- } -+ CMS.debug("SystemConfigService: get configuration entries from master"); -+ ConfigurationUtils.getConfigEntriesFromMaster(); - - if (token.equals(ConfigurationRequest.TOKEN_DEFAULT)) { -- CMS.debug("SystemConfigService.getCloningData(): restore certs from P12 file"); -+ CMS.debug("SystemConfigService: restore certificates from P12 file"); - String p12File = data.getP12File(); - String p12Pass = data.getP12Password(); -- try { -- ConfigurationUtils.restoreCertsFromP12(p12File, p12Pass); -- } catch (Exception e) { -- CMS.debug(e); -- throw new PKIException("Failed to restore certificates from p12 file" + e); -- } -+ ConfigurationUtils.restoreCertsFromP12(p12File, p12Pass); -+ - } else { -- CMS.debug("SystemConfigService.getCloningData(): set permissions for certs stored in hardware"); -- try { -- ConfigurationUtils.importAndSetCertPermissionsFromHSM(); -- } catch (Exception e) { -- CMS.debug(e); -- throw new PKIException("Failed to import certs from HSM and set permissions:" + e); -- } -+ CMS.debug("SystemConfigService: import certificates from HSM and set permission"); -+ ConfigurationUtils.importAndSetCertPermissionsFromHSM(); - } - -- CMS.debug("SystemConfigService.getCloningData(): verify certs"); -+ CMS.debug("SystemConfigService: verify certificates"); - boolean cloneReady = ConfigurationUtils.isCertdbCloned(); -+ - if (!cloneReady) { -- CMS.debug("clone does not have all the certificates."); -+ CMS.debug("SystemConfigService: clone does not have all the certificates."); - throw new PKIException("Clone does not have all the required certificates"); - } - } -@@ -992,7 +964,7 @@ public class SystemConfigService extends PKIService implements SystemConfigResou - } - - public void configureSubsystem(ConfigurationRequest request, -- Collection certList, String token, String domainXML) { -+ Collection certList, String token, String domainXML) throws Exception { - - cs.putString("preop.subsystem.name", request.getSubsystemName()); - -@@ -1004,7 +976,7 @@ public class SystemConfigService extends PKIService implements SystemConfigResou - } else { - cs.putString("preop.subsystem.select", "clone"); - cs.putString("subsystem.select", "Clone"); -- getCloningData(request, certList, token, domainXML); -+ configureClone(request, certList, token, domainXML); - } - } - -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 9c4943b..fe4e124 100644 ---- a/base/tps/src/org/dogtagpki/server/tps/rest/TPSInstallerService.java -+++ b/base/tps/src/org/dogtagpki/server/tps/rest/TPSInstallerService.java -@@ -44,7 +44,7 @@ public class TPSInstallerService extends SystemConfigService { - - @Override - public void configureSubsystem(ConfigurationRequest request, -- Collection certList, String token, String domainXML) { -+ Collection certList, String token, String domainXML) throws Exception { - - super.configureSubsystem(request, certList, token, domainXML); - --- -1.8.3.1 - - -From 7c1af7f7dac89363c7923802ec759ccb84813bfb Mon Sep 17 00:00:00 2001 -From: Christina Fu -Date: Mon, 29 Jun 2015 15:34:01 -0700 -Subject: [PATCH 08/21] Ticket 1438 pkispawn: SSL_ForceHandshake issue for - non-CA on HSM on both shared and nonshared tomcat instances - ---- - .../python/pki/server/deployment/pkiparser.py | 107 ++++++++++++++------- - 1 file changed, 72 insertions(+), 35 deletions(-) - -diff --git a/base/server/python/pki/server/deployment/pkiparser.py b/base/server/python/pki/server/deployment/pkiparser.py -index 7e1813c..4b3dabb 100644 ---- a/base/server/python/pki/server/deployment/pkiparser.py -+++ b/base/server/python/pki/server/deployment/pkiparser.py -@@ -921,41 +921,78 @@ class PKIConfigParser: - "tls1_0:tls1_2" - self.mdict['TOMCAT_SSL_VERSION_RANGE_DATAGRAM_SLOT'] = \ - "tls1_1:tls1_2" -- self.mdict['TOMCAT_SSL_RANGE_CIPHERS_SLOT'] = \ -- "-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_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_RSA_WITH_AES_128_CBC_SHA256," + \ -- "+TLS_RSA_WITH_AES_256_CBC_SHA256," + \ -- "+TLS_RSA_WITH_AES_128_GCM_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_ECDH_ECDSA_WITH_AES_128_GCM_SHA256," + \ -- "+TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256," + \ -- "+TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256" -+ if self.mdict['pki_ssl_server_key_type'] == "ecc": -+ self.mdict['TOMCAT_SSL_RANGE_CIPHERS_SLOT'] = \ -+ "+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_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_RSA_WITH_AES_128_CBC_SHA256," + \ -+ "-TLS_RSA_WITH_AES_256_CBC_SHA256," + \ -+ "-TLS_RSA_WITH_AES_128_GCM_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_ECDH_ECDSA_WITH_AES_128_GCM_SHA256," + \ -+ "+TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256," + \ -+ "+TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256" -+ else: -+ self.mdict['TOMCAT_SSL_RANGE_CIPHERS_SLOT'] = \ -+ "-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_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_RSA_WITH_AES_128_CBC_SHA256," + \ -+ "+TLS_RSA_WITH_AES_256_CBC_SHA256," + \ -+ "+TLS_RSA_WITH_AES_128_GCM_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_ECDH_ECDSA_WITH_AES_128_GCM_SHA256," + \ -+ "-TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256," + \ -+ "-TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256" - self.mdict['TOMCAT_SSL2_CIPHERS_SLOT'] = \ - "-SSL2_RC4_128_WITH_MD5," + \ - "-SSL2_RC4_128_EXPORT40_WITH_MD5," + \ --- -1.8.3.1 - - -From b253cad196f57e79a5aede53aceffede1c9edfbe Mon Sep 17 00:00:00 2001 -From: Jack Magne -Date: Wed, 1 Jul 2015 15:01:45 -0700 -Subject: [PATCH 09/21] Ability to toggle profile usablity in Web vs CLI tools. - -Ticket #1442. - -This fix gives the command line enrollment commands the ability to enroll a cert against a profile -that has been marked as not visible but "enabled". - -With the simple fix the following scenarios tested to work: - -The "caUserCert" Profile was marked as not visible, but enabled. - -1. pki -c Secret123 client-cert-request --profile caUserCert uid=jmagne - This is the simplest form of user cert enrollment. - -2. pki ca-cert-request-profile-show caUserCert --output testuser.xml - pki ca-cert-request-submit testuser.xml - - The first command gives us the profile's xml file, which after modification is used to enroll. - -3. pki -d ~/.dogtag/pki -c "" -n "PKI Administrator for localdomain" ca-profile-show caUserCert - - This one shows that we can view the contents of a non visible profile. Listing is not allowed. - We felt this appropiate to allow a command line user to get the details of a non visible profile that - they know aobut and want to use. ---- - base/ca/src/org/dogtagpki/server/ca/rest/CertRequestService.java | 5 ++--- - 1 file changed, 2 insertions(+), 3 deletions(-) - -diff --git a/base/ca/src/org/dogtagpki/server/ca/rest/CertRequestService.java b/base/ca/src/org/dogtagpki/server/ca/rest/CertRequestService.java -index 969cfd1..a11cb47 100644 ---- a/base/ca/src/org/dogtagpki/server/ca/rest/CertRequestService.java -+++ b/base/ca/src/org/dogtagpki/server/ca/rest/CertRequestService.java -@@ -336,9 +336,8 @@ public class CertRequestService extends PKIService implements CertRequestResourc - } - - if (! profile.isVisible()) { -- CMS.debug("getEnrollmentTemplate(): attempt to get enrollment template for non-visible profile"); -- throw new BadRequestException("Cannot provide enrollment template for profile `" + profileId + -- "`. Profile not marked as visible"); -+ CMS.debug("getEnrollmentTemplate(): attempt to get enrollment template for non-visible profile. This is ok since command line enrollments should be able to use enabled but non visible profiles."); -+ - } - - CertEnrollmentRequest request = new CertEnrollmentRequest(); --- -1.8.3.1 - - -From 4af223feb262a707b65d4860f6e8552873306209 Mon Sep 17 00:00:00 2001 -From: Matthew Harmsen -Date: Thu, 2 Jul 2015 11:09:14 -0600 -Subject: [PATCH 12/21] Limited Interactive Installation Support - -- PKI TRAC Ticket #1441 - Lack of Interactive Installation Support - (Cloning, Subordinates, Externals, HSMs, ECC) ---- - .../python/pki/server/deployment/pkimessages.py | 19 ++++++ - base/server/sbin/pkispawn | 70 ++++++++++++---------- - 2 files changed, 56 insertions(+), 33 deletions(-) - -diff --git a/base/server/python/pki/server/deployment/pkimessages.py b/base/server/python/pki/server/deployment/pkimessages.py -index 6528407..ff3d370 100644 ---- a/base/server/python/pki/server/deployment/pkimessages.py -+++ b/base/server/python/pki/server/deployment/pkimessages.py -@@ -146,6 +146,25 @@ REMINDER: - Finally, if an optional '-p ' is defined, this value WILL NOT - be prepended in front of the mandatory '-f '. - """ + PKI_VERBOSITY -+PKISPAWN_INTERACTIVE_INSTALLATION=''' -+IMPORTANT: -+ -+ Interactive installation currently only exists for very basic deployments! -+ -+ For example, deployments intent upon using advanced features such as: -+ -+ * Cloning, -+ * Elliptic Curve Cryptography (ECC), -+ * External CA, -+ * Hardware Security Module (HSM), -+ * Subordinate CA, -+ * etc., -+ -+ must provide the necessary override parameters in a separate -+ configuration file. -+ -+ Run 'man pkispawn' for details. -+''' - - - # PKI Deployment "Helper" Messages -diff --git a/base/server/sbin/pkispawn b/base/server/sbin/pkispawn -index 893a22a..bebbf0b 100755 ---- a/base/server/sbin/pkispawn -+++ b/base/server/sbin/pkispawn -@@ -125,8 +125,12 @@ def main(argv): - parser.validate() - interactive = False - -- while True: -+ if config.user_deployment_cfg is None: -+ interactive = True -+ parser.indent = 0 -+ print log.PKISPAWN_INTERACTIVE_INSTALLATION - -+ while True: - # -s - if args.pki_subsystem is None: - interactive = True -@@ -215,38 +219,38 @@ def main(argv): - config.pki_subsystem, - 'pki_client_admin_cert') - -- if parser.mdict['pki_hsm_enable'] == 'True': -- use_hsm = 'Y' -- else: -- use_hsm = 'N' -- -- use_hsm = parser.read_text( -- 'Using hardware security module (HSM) (Yes/No)', -- default=use_hsm, options=['Yes', 'Y', 'No', 'N'], -- sign='?', case_sensitive=False).lower() -- -- if use_hsm == 'y' or use_hsm == 'yes': -- # XXX: Suppress interactive HSM installation -- print "Interactive HSM installation is currently unsupported." -- sys.exit(0) -- -- # TBD: Interactive HSM installation -- # parser.set_property(config.pki_subsystem, -- # 'pki_hsm_enable', -- # 'True') -- # modulename = parser.read_text( -- # 'HSM Module Name (e. g. - nethsm)', allow_empty=False) -- # parser.set_property(config.pki_subsystem, -- # 'pki_hsm_modulename', -- # modulename) -- # libfile = parser.read_text( -- # 'HSM Lib File ' + -- # '(e. g. - /opt/nfast/toolkits/pkcs11/libcknfast.so)', -- # allow_empty=False) -- # parser.set_property(config.pki_subsystem, -- # 'pki_hsm_libfile', -- # libfile) -- print -+ # if parser.mdict['pki_hsm_enable'] == 'True': -+ # use_hsm = 'Y' -+ # else: -+ # use_hsm = 'N' -+ -+ # use_hsm = parser.read_text( -+ # 'Using hardware security module (HSM) (Yes/No)', -+ # default=use_hsm, options=['Yes', 'Y', 'No', 'N'], -+ # sign='?', case_sensitive=False).lower() -+ -+ # if use_hsm == 'y' or use_hsm == 'yes': -+ # # XXX: Suppress interactive HSM installation -+ # print "Interactive HSM installation is currently unsupported." -+ # sys.exit(0) -+ -+ # TBD: Interactive HSM installation -+ # parser.set_property(config.pki_subsystem, -+ # 'pki_hsm_enable', -+ # 'True') -+ # modulename = parser.read_text( -+ # 'HSM Module Name (e. g. - nethsm)', allow_empty=False) -+ # parser.set_property(config.pki_subsystem, -+ # 'pki_hsm_modulename', -+ # modulename) -+ # libfile = parser.read_text( -+ # 'HSM Lib File ' + -+ # '(e. g. - /opt/nfast/toolkits/pkcs11/libcknfast.so)', -+ # allow_empty=False) -+ # parser.set_property(config.pki_subsystem, -+ # 'pki_hsm_libfile', -+ # libfile) -+ # print - - print "Directory Server:" - while True: --- -1.8.3.1 - - -From bbd2feaa1f0ca4c338ca490f191184f2bd5c1a41 Mon Sep 17 00:00:00 2001 -From: Jack Magne -Date: Tue, 30 Jun 2015 17:22:23 -0700 -Subject: [PATCH 13/21] Unable to select ECC Curves from EE fix. - -Ticket #1446: - -Without the crypto object, the user is now presented with a very bared bones -keygen tag powered UI. ONe can only select a key strength and only use RSA. - -This fix adds simple UI to make better use of the keygen tag: - -1. Allows the use of ECC. -2. Gives simple info on how the key strengths map to RSA key size and -ECC curves. - -When the user selects High, they get RSA 2043, and ECC nistp384. -When the user selects Medium, they get RSA 1024, and ECC nistp256. ---- - .../shared/webapps/ca/ee/ca/ProfileSelect.template | 81 +++++++++++++++++++++- - 1 file changed, 80 insertions(+), 1 deletion(-) - -diff --git a/base/ca/shared/webapps/ca/ee/ca/ProfileSelect.template b/base/ca/shared/webapps/ca/ee/ca/ProfileSelect.template -index 0e68e36..5075962 100644 ---- a/base/ca/shared/webapps/ca/ee/ca/ProfileSelect.template -+++ b/base/ca/shared/webapps/ca/ee/ca/ProfileSelect.template -@@ -47,6 +47,71 @@ var key = new Object(); - key.type = "EC"; - keyList[1] = key; - -+function getKeyStrengthTableForKeyGen() { -+ -+ document.writeln(""); -+ document.writeln(""); -+ document.writeln(""); -+ document.writeln("
KeyGen Key Strength Info
Key Type High Grade Medium Grade
RSA 2048 1024
ECC nistp384 nistp256
"); -+ -+} -+ -+function getKeyTypesOptionsForKeyGen() { -+ var keyTypesDef = "RSA"; -+ var keyTypes = null; -+ for (var i = 0; i < policySetListSet.length; i++) { -+ for (var j = 0; j < policySetListSet[i].policySet.length; j++) { -+ if (typeof(policySetListSet[i].policySet[j].constraintSet) != "undefined") { -+ for (var k = 0; k < policySetListSet[i].policySet[j].constraintSet.length; k++) { -+ if (policySetListSet[i].policySet[j].constraintSet[k].name == "keyType") { -+ if (policySetListSet[i].policySet[j].constraintSet[k].value == "-") { -+ keyTypes = "RSA,EC"; -+ } else { -+ keyTypes = policySetListSet[i].policySet[j].constraintSet[k].value; -+ } -+ } -+ } -+ } -+ } -+ } -+ -+ if(keyTypes == null) { -+ keyTypes = keyTypesDef; -+ } -+ -+ var keyTypesRet = keyTypes.split(","); -+ var options = ""; -+ var optionLabel = ""; -+ var selected = ""; -+ for(types= 0 ; types < keyTypesRet.length ; types ++) { -+ if(keyTypesRet[types] == "EC") { -+ optionLabel = "ECC"; -+ } else { -+ optionLabel = keyTypesRet[types]; -+ } -+ -+ if( types == 0 ) { -+ selected = "SELECTED"; -+ } else { -+ selected = ""; -+ } -+ -+ options += ' '; -+ } -+ -+ return options; -+} -+ -+function keyGenKeyTypeSelected(keygenObj,keyTypeSelectObj) { -+ -+ if(keygenObj == null || keyTypeSelectObj == null) -+ return; -+ -+ var selectedValue = keyTypeSelectObj.options[keyTypeSelectObj.selectedIndex].value; -+ -+ keygenObj.setAttribute("keytype", selectedValue); -+} -+ - function keyTypeOptions (keyPurpose) - { - var keyType = "RSA"; -@@ -682,7 +747,21 @@ for (var m = 0; m < inputPluginListSet.length; m++) { - } - document.writeln(''); - } else { -- document.writeln(''); -+ -+ getKeyStrengthTableForKeyGen(); -+ -+ var keyTypesOptions = getKeyTypesOptionsForKeyGen(); -+ -+ var keygendata = ' ' ; -+ document.writeln(keygendata); -+ -+ var keygenObj = document.getElementById("keygentag"); -+ var selectKeyTypeData = ' ' ; -+ -+ document.writeln(selectKeyTypeData); -+ -+ var selectKeyTypeObject = document.getElementById("keyTypeSelectedId"); -+ keyGenKeyTypeSelected(keygenObj,selectKeyTypeObject); - } - } else if (inputListSet[n].inputSyntax == 'dual_keygen_request_type') { - keygen_request = 'true'; --- -1.8.3.1 - - -From 067cbce6c015a50f4a1747f8894b13c9052c2ed9 Mon Sep 17 00:00:00 2001 -From: "Endi S. Dewata" -Date: Tue, 30 Jun 2015 22:49:11 -0400 -Subject: [PATCH 14/21] Fixed pki help CLI. - -A new findModules() method has been added to the CLI class to find -the list of modules handling a command. The list will be used by the -pki help CLI to find the proper man page for the specified command. ---- - .../src/com/netscape/cmstools/cert/CertCLI.java | 5 ++ - .../src/com/netscape/cmstools/cli/CLI.java | 72 ++++++++++++++++++++++ - .../src/com/netscape/cmstools/cli/HelpCLI.java | 27 ++++++-- - .../src/com/netscape/cmstools/cli/MainCLI.java | 5 ++ - .../com/netscape/cmstools/client/ClientCLI.java | 5 ++ - .../src/com/netscape/cmstools/group/GroupCLI.java | 5 ++ - .../netscape/cmstools/group/GroupMemberCLI.java | 5 ++ - .../src/com/netscape/cmstools/key/KeyCLI.java | 5 ++ - .../com/netscape/cmstools/logging/AuditCLI.java | 5 ++ - .../com/netscape/cmstools/profile/ProfileCLI.java | 5 ++ - .../cmstools/system/SecurityDomainCLI.java | 5 ++ - .../src/com/netscape/cmstools/user/UserCLI.java | 5 ++ - .../com/netscape/cmstools/user/UserCertCLI.java | 5 ++ - 13 files changed, 148 insertions(+), 6 deletions(-) - -diff --git a/base/java-tools/src/com/netscape/cmstools/cert/CertCLI.java b/base/java-tools/src/com/netscape/cmstools/cert/CertCLI.java -index 9ffa3ad..e0924d3 100644 ---- a/base/java-tools/src/com/netscape/cmstools/cert/CertCLI.java -+++ b/base/java-tools/src/com/netscape/cmstools/cert/CertCLI.java -@@ -67,6 +67,11 @@ public class CertCLI extends CLI { - } - } - -+ @Override -+ public String getManPage() { -+ return "pki-cert"; -+ } -+ - public void execute(String[] args) throws Exception { - - client = parent.getClient(); -diff --git a/base/java-tools/src/com/netscape/cmstools/cli/CLI.java b/base/java-tools/src/com/netscape/cmstools/cli/CLI.java -index ed01edc..1338749 100644 ---- a/base/java-tools/src/com/netscape/cmstools/cli/CLI.java -+++ b/base/java-tools/src/com/netscape/cmstools/cli/CLI.java -@@ -21,6 +21,7 @@ package com.netscape.cmstools.cli; - import java.util.ArrayList; - import java.util.Collection; - import java.util.LinkedHashMap; -+import java.util.List; - import java.util.Map; - - import org.apache.commons.cli.CommandLineParser; -@@ -113,6 +114,75 @@ public class CLI { - return modules.remove(name); - } - -+ /** -+ * Find the list of modules that handle the specified command. -+ */ -+ public List findModules(String command) throws Exception { -+ -+ List results = new ArrayList(); -+ -+ // split command into list of names: -+ // ---...- -+ String[] names = command.split("-"); -+ -+ CLI current = this; -+ int i = 0; -+ -+ // translate all names into modules starting from the beginning -+ while (i < names.length) { -+ -+ String moduleName = null; -+ CLI module = null; -+ int j = i; -+ -+ // find module that matches the shortest sequence of names -+ while (j < names.length) { -+ -+ // construct module name -+ if (moduleName == null) { -+ moduleName = names[j]; -+ } else { -+ moduleName = moduleName + "-" + names[j]; -+ } -+ -+ // find module with name -...- -+ module = current.getModule(moduleName); -+ -+ if (module != null) { -+ // module found, stop -+ break; -+ } -+ -+ // try again with longer sequence -+ j++; -+ } -+ -+ if (module == null) -+ throw new Error("Invalid module \"" + moduleName + "\"."); -+ -+ // module found -+ results.add(module); -+ -+ // repeat for the remaining parts -+ current = module; -+ i = j + 1; -+ } -+ -+ return results; -+ } -+ -+ /** -+ * Find the last module that handles the specified command. -+ */ -+ public CLI findModule(String command) throws Exception { -+ List modules = findModules(command); -+ return modules.get(modules.size() - 1); -+ } -+ -+ public String getManPage() { -+ return null; -+ } -+ - public PKIClient getClient() { - return client; - } -@@ -182,6 +252,8 @@ public class CLI { - System.exit(0); - } - -+ // TODO: Rewrite using findModules(). -+ - // A command consists of parts joined by dashes: --...-. - // For example: cert-request-find - String command = args[0]; -diff --git a/base/java-tools/src/com/netscape/cmstools/cli/HelpCLI.java b/base/java-tools/src/com/netscape/cmstools/cli/HelpCLI.java -index 6b2a123..b348ffc 100644 ---- a/base/java-tools/src/com/netscape/cmstools/cli/HelpCLI.java -+++ b/base/java-tools/src/com/netscape/cmstools/cli/HelpCLI.java -@@ -18,6 +18,8 @@ - - package com.netscape.cmstools.cli; - -+import java.util.List; -+ - import org.apache.commons.cli.CommandLine; - - /** -@@ -51,19 +53,32 @@ public class HelpCLI extends CLI { - - String[] cmdArgs = cmd.getArgs(); - -- String command; -+ String manPage = null; - if (cmdArgs.length == 0) { -- command = "pki"; -+ // no command specified, show the pki man page -+ manPage = parent.getManPage(); - - } else { -- command = "pki-" + cmdArgs[0]; -+ // find all modules handling the specified command -+ List modules = parent.findModules(cmdArgs[0]); -+ -+ // find the module that has a man page starting from the last one -+ for (int i = modules.size() - 1; i >= 0; i--) { -+ CLI module = modules.get(i); -+ manPage = module.getManPage(); -+ if (manPage != null) break; -+ } -+ -+ // if no module has a man page, show the pki man page -+ if (manPage == null) -+ manPage = parent.getManPage(); - } - - while (true) { - // display man page for the command - ProcessBuilder pb = new ProcessBuilder( - "/bin/man", -- command); -+ manPage); - - pb.inheritIO(); - Process p = pb.start(); -@@ -71,10 +86,10 @@ public class HelpCLI extends CLI { - - if (rc == 16) { - // man page not found, find the parent command -- int i = command.lastIndexOf('-'); -+ int i = manPage.lastIndexOf('-'); - if (i >= 0) { - // parent command exists, try again -- command = command.substring(0, i); -+ manPage = manPage.substring(0, i); - continue; - - } else { -diff --git a/base/java-tools/src/com/netscape/cmstools/cli/MainCLI.java b/base/java-tools/src/com/netscape/cmstools/cli/MainCLI.java -index 1792922..77245ec 100644 ---- a/base/java-tools/src/com/netscape/cmstools/cli/MainCLI.java -+++ b/base/java-tools/src/com/netscape/cmstools/cli/MainCLI.java -@@ -89,6 +89,11 @@ public class MainCLI extends CLI { - return moduleName; - } - -+ @Override -+ public String getManPage() { -+ return "pki"; -+ } -+ - public void printVersion() { - Package pkg = MainCLI.class.getPackage(); - System.out.println("PKI Command-Line Interface "+pkg.getImplementationVersion()); -diff --git a/base/java-tools/src/com/netscape/cmstools/client/ClientCLI.java b/base/java-tools/src/com/netscape/cmstools/client/ClientCLI.java -index c9c7152..f09ea74 100644 ---- a/base/java-tools/src/com/netscape/cmstools/client/ClientCLI.java -+++ b/base/java-tools/src/com/netscape/cmstools/client/ClientCLI.java -@@ -50,6 +50,11 @@ public class ClientCLI extends CLI { - } - } - -+ @Override -+ public String getManPage() { -+ return "pki-client"; -+ } -+ - public void execute(String[] args) throws Exception { - - client = parent.getClient(); -diff --git a/base/java-tools/src/com/netscape/cmstools/group/GroupCLI.java b/base/java-tools/src/com/netscape/cmstools/group/GroupCLI.java -index 973e0ba..ca15130 100644 ---- a/base/java-tools/src/com/netscape/cmstools/group/GroupCLI.java -+++ b/base/java-tools/src/com/netscape/cmstools/group/GroupCLI.java -@@ -54,6 +54,11 @@ public class GroupCLI extends CLI { - } - } - -+ @Override -+ public String getManPage() { -+ return "pki-group"; -+ } -+ - public void execute(String[] args) throws Exception { - - client = parent.getClient(); -diff --git a/base/java-tools/src/com/netscape/cmstools/group/GroupMemberCLI.java b/base/java-tools/src/com/netscape/cmstools/group/GroupMemberCLI.java -index e21d817..1df404b 100644 ---- a/base/java-tools/src/com/netscape/cmstools/group/GroupMemberCLI.java -+++ b/base/java-tools/src/com/netscape/cmstools/group/GroupMemberCLI.java -@@ -40,6 +40,11 @@ public class GroupMemberCLI extends CLI { - addModule(new GroupMemberRemoveCLI(this)); - } - -+ @Override -+ public String getManPage() { -+ return "pki-group-member"; -+ } -+ - public void execute(String[] args) throws Exception { - - client = parent.getClient(); -diff --git a/base/java-tools/src/com/netscape/cmstools/key/KeyCLI.java b/base/java-tools/src/com/netscape/cmstools/key/KeyCLI.java -index fb324be..d83bcf2 100644 ---- a/base/java-tools/src/com/netscape/cmstools/key/KeyCLI.java -+++ b/base/java-tools/src/com/netscape/cmstools/key/KeyCLI.java -@@ -65,6 +65,11 @@ public class KeyCLI extends CLI { - } - } - -+ @Override -+ public String getManPage() { -+ return "pki-key"; -+ } -+ - public void execute(String[] args) throws Exception { - - client = parent.getClient(); -diff --git a/base/java-tools/src/com/netscape/cmstools/logging/AuditCLI.java b/base/java-tools/src/com/netscape/cmstools/logging/AuditCLI.java -index 11e5300..531d920 100644 ---- a/base/java-tools/src/com/netscape/cmstools/logging/AuditCLI.java -+++ b/base/java-tools/src/com/netscape/cmstools/logging/AuditCLI.java -@@ -41,6 +41,11 @@ public class AuditCLI extends CLI { - addModule(new AuditShowCLI(this)); - } - -+ @Override -+ public String getManPage() { -+ return "pki-audit"; -+ } -+ - public void execute(String[] args) throws Exception { - - client = parent.getClient(); -diff --git a/base/java-tools/src/com/netscape/cmstools/profile/ProfileCLI.java b/base/java-tools/src/com/netscape/cmstools/profile/ProfileCLI.java -index e9e2159..ecfa753 100644 ---- a/base/java-tools/src/com/netscape/cmstools/profile/ProfileCLI.java -+++ b/base/java-tools/src/com/netscape/cmstools/profile/ProfileCLI.java -@@ -51,6 +51,11 @@ public class ProfileCLI extends CLI { - } - } - -+ @Override -+ public String getManPage() { -+ return "pki-ca-profile"; -+ } -+ - public void execute(String[] args) throws Exception { - - client = parent.getClient(); -diff --git a/base/java-tools/src/com/netscape/cmstools/system/SecurityDomainCLI.java b/base/java-tools/src/com/netscape/cmstools/system/SecurityDomainCLI.java -index b1a3597..0c2ed37 100644 ---- a/base/java-tools/src/com/netscape/cmstools/system/SecurityDomainCLI.java -+++ b/base/java-tools/src/com/netscape/cmstools/system/SecurityDomainCLI.java -@@ -47,6 +47,11 @@ public class SecurityDomainCLI extends CLI { - } - } - -+ @Override -+ public String getManPage() { -+ return "pki-securitydomain"; -+ } -+ - public void execute(String[] args) throws Exception { - - client = parent.getClient(); -diff --git a/base/java-tools/src/com/netscape/cmstools/user/UserCLI.java b/base/java-tools/src/com/netscape/cmstools/user/UserCLI.java -index 7a03d33..5382c47 100644 ---- a/base/java-tools/src/com/netscape/cmstools/user/UserCLI.java -+++ b/base/java-tools/src/com/netscape/cmstools/user/UserCLI.java -@@ -57,6 +57,11 @@ public class UserCLI extends CLI { - } - } - -+ @Override -+ public String getManPage() { -+ return "pki-user"; -+ } -+ - public void execute(String[] args) throws Exception { - - client = parent.getClient(); -diff --git a/base/java-tools/src/com/netscape/cmstools/user/UserCertCLI.java b/base/java-tools/src/com/netscape/cmstools/user/UserCertCLI.java -index ead915a..d8ea917 100644 ---- a/base/java-tools/src/com/netscape/cmstools/user/UserCertCLI.java -+++ b/base/java-tools/src/com/netscape/cmstools/user/UserCertCLI.java -@@ -40,6 +40,11 @@ public class UserCertCLI extends CLI { - addModule(new UserCertRemoveCLI(this)); - } - -+ @Override -+ public String getManPage() { -+ return "pki-user-cert"; -+ } -+ - public void execute(String[] args) throws Exception { - - client = parent.getClient(); --- -1.8.3.1 - - -From 433e1dba905f9d45f9eefcbf39e5b11ddfbfbc94 Mon Sep 17 00:00:00 2001 -From: "Endi S. Dewata" -Date: Thu, 2 Jul 2015 18:33:48 -0400 -Subject: [PATCH 15/21] Fixed NPE in key-archive CLI. - -The pki CLI has been modified such that if the security database -location (-d) is not specified, the config.certDatabase will be -initialized with the default value (i.e. ~/.dogtag/nssdb). The -config.certDatabase is needed by the CLI to prepare the client -library for key archival operations. ---- - .../src/com/netscape/cmstools/cli/MainCLI.java | 21 ++++++++------------- - .../src/com/netscape/cmstools/key/KeyCLI.java | 10 ++++++++-- - 2 files changed, 16 insertions(+), 15 deletions(-) - -diff --git a/base/java-tools/src/com/netscape/cmstools/cli/MainCLI.java b/base/java-tools/src/com/netscape/cmstools/cli/MainCLI.java -index 77245ec..4d63d9b 100644 ---- a/base/java-tools/src/com/netscape/cmstools/cli/MainCLI.java -+++ b/base/java-tools/src/com/netscape/cmstools/cli/MainCLI.java -@@ -330,9 +330,14 @@ public class MainCLI extends CLI { - } - } - -- // store security database path -- if (certDatabase != null) -+ if (certDatabase != null) { -+ // store user-provided security database location - config.setCertDatabase(new File(certDatabase).getAbsolutePath()); -+ } else { -+ // store default security database location -+ config.setCertDatabase(System.getProperty("user.home") + -+ File.separator + ".dogtag" + File.separator + "nssdb"); -+ } - - // store token name - config.setTokenName(tokenName); -@@ -395,17 +400,7 @@ public class MainCLI extends CLI { - list = cmd.getOptionValue("ignore-cert-status"); - convertCertStatusList(list, ignoredCertStatuses); - -- if (config.getCertDatabase() == null) { -- // Use default client security database -- this.certDatabase = new File( -- System.getProperty("user.home") + File.separator + -- ".dogtag" + File.separator + "nssdb"); -- -- } else { -- // Use existing client security database -- this.certDatabase = new File(config.getCertDatabase()); -- } -- -+ this.certDatabase = new File(config.getCertDatabase()); - if (verbose) System.out.println("Client security database: "+this.certDatabase.getAbsolutePath()); - - String messageFormat = cmd.getOptionValue("message-format"); -diff --git a/base/java-tools/src/com/netscape/cmstools/key/KeyCLI.java b/base/java-tools/src/com/netscape/cmstools/key/KeyCLI.java -index d83bcf2..f242ece 100644 ---- a/base/java-tools/src/com/netscape/cmstools/key/KeyCLI.java -+++ b/base/java-tools/src/com/netscape/cmstools/key/KeyCLI.java -@@ -81,14 +81,20 @@ public class KeyCLI extends CLI { - - // create new key client - keyClient = new KeyClient(client, subsystem); -- if (client.getConfig().getCertDatabase() != null && client.getConfig().getCertPassword() != null) { -+ -+ // if security database password is specified, -+ // prepare key client for archival/retrieval -+ if (client.getConfig().getCertPassword() != null) { -+ // create crypto provider for key client - keyClient.setCrypto(new NSSCryptoProvider(client.getConfig())); - -- // Set the transport cert for crypto operations -+ // download transport cert - systemCertClient = new SystemCertClient(client, subsystem); - String transportCert = systemCertClient.getTransportCert().getEncoded(); - transportCert = transportCert.substring(CertData.HEADER.length(), - transportCert.indexOf(CertData.FOOTER)); -+ -+ // set transport cert for key client - keyClient.setTransportCert(transportCert); - } - --- -1.8.3.1 - - -From cc8f6468bb9f509d16ed526e42d546aaa2ae9ed3 Mon Sep 17 00:00:00 2001 -From: "Endi S. Dewata" -Date: Wed, 1 Jul 2015 14:41:51 -0400 -Subject: [PATCH 16/21] Fixed fail-over in HttpConnection. - -The HttpConnection class has been modified to support fail-over -and timeout more consistently. The targets are parsed into a list -during initialization. All direct calls to HttpClient.connect() -are replaced with a method that will connect to the first available -target. All connections are now created with a timeout (which by -default is 0). - -https://fedorahosted.org/pki/ticket/891 ---- - base/ca/src/com/netscape/ca/CAService.java | 5 +- - .../netscape/cmscore/connector/HttpConnection.java | 214 +++++++++++---------- - .../src/com/netscape/cmsutil/http/HttpClient.java | 40 ++-- - .../netscape/cmsutil/http/JssSSLSocketFactory.java | 27 ++- - .../com/netscape/cmsutil/net/ISocketFactory.java | 10 +- - 5 files changed, 154 insertions(+), 142 deletions(-) - -diff --git a/base/ca/src/com/netscape/ca/CAService.java b/base/ca/src/com/netscape/ca/CAService.java -index 6edaf2a..36f0bd5 100644 ---- a/base/ca/src/com/netscape/ca/CAService.java -+++ b/base/ca/src/com/netscape/ca/CAService.java -@@ -435,9 +435,8 @@ public class CAService implements ICAService, IService { - // send request to KRA first - if (type.equals(IRequest.ENROLLMENT_REQUEST) && - isPKIArchiveOptionPresent(request) && mKRAConnector != null) { -- if (Debug.ON) { -- Debug.trace("*** Sending enrollment request to KRA"); -- } -+ -+ CMS.debug("CAService: Sending enrollment request to KRA"); - boolean sendStatus = mKRAConnector.send(request); - - if (mArchivalRequired == true) { -diff --git a/base/server/cmscore/src/com/netscape/cmscore/connector/HttpConnection.java b/base/server/cmscore/src/com/netscape/cmscore/connector/HttpConnection.java -index c179f4b..c480478 100644 ---- a/base/server/cmscore/src/com/netscape/cmscore/connector/HttpConnection.java -+++ b/base/server/cmscore/src/com/netscape/cmscore/connector/HttpConnection.java -@@ -18,7 +18,9 @@ - package com.netscape.cmscore.connector; - - import java.io.IOException; --import java.util.StringTokenizer; -+import java.net.InetSocketAddress; -+import java.util.ArrayList; -+import java.util.List; - - import com.netscape.certsrv.apps.CMS; - import com.netscape.certsrv.base.EBaseException; -@@ -33,50 +35,32 @@ import com.netscape.cmsutil.http.HttpResponse; - import com.netscape.cmsutil.net.ISocketFactory; - - public class HttpConnection implements IHttpConnection { -+ - protected IRemoteAuthority mDest = null; - protected HttpRequest mHttpreq = new HttpRequest(); - protected IRequestEncoder mReqEncoder = null; - protected HttpClient mHttpClient = null; - -- protected boolean Connect(String host, HttpClient client) { -- StringTokenizer st = new StringTokenizer(host, " "); -- while (st.hasMoreTokens()) { -- String hp = st.nextToken(); // host:port -- StringTokenizer st1 = new StringTokenizer(hp, ":"); -- try { -- String h = st1.nextToken(); -- int p = Integer.parseInt(st1.nextToken()); -- client.connect(h, p); -- return true; -- } catch (Exception e) { -- // may want to log the failure -- } -- try { -- Thread.sleep(5000); // 5 seconds -- } catch (Exception e) { -- } -+ int timeout = 0; -+ List targets; - -- } -- return false; -- } -+ public HttpConnection(IRemoteAuthority dest, ISocketFactory factory, -+ int timeout // seconds -+ ) { - -- public void setRequestURI(String uri) -- throws EBaseException { -- mHttpreq.setURI(uri); -- } -+ CMS.debug("HttpConnection: Creating HttpConnection with timeout=" + timeout); - -- public String getRequestURI() { -- return mHttpreq.getURI(); -- } -- -- public HttpConnection(IRemoteAuthority dest, ISocketFactory factory) { - mDest = dest; - mReqEncoder = new HttpRequestEncoder(); - mHttpClient = new HttpClient(factory); -- if (Debug.ON) -- Debug.trace("Created HttpClient"); -+ -+ this.timeout = timeout; -+ -+ targets = parseTarget(dest.getHost(), dest.getPort()); -+ - try { - mHttpreq.setMethod("POST"); -+ - // in case of multi-uri, uri will be set right before send - // by calling setRequestURI(uri) - if (mDest.getURI() != null) -@@ -89,62 +73,85 @@ public class HttpConnection implements IHttpConnection { - } - - mHttpreq.setHeader("Connection", "Keep-Alive"); -- CMS.debug("HttpConnection: connecting to " + dest.getHost() + ":" + dest.getPort()); -- String host = dest.getHost(); -- // we could have a list of host names in the host parameters -- // the format is, for example, -- // "directory.knowledge.com:1050 people.catalog.com 199.254.1.2" -- if (host != null && host.indexOf(' ') != -1) { -- // try to do client-side failover -- boolean connected = false; -- do { -- connected = Connect(host, mHttpClient); -- } while (!connected); -- } else { -- mHttpClient.connect(host, dest.getPort()); -- } -- CMS.debug("HttpConnection: connected to " + dest.getHost() + ":" + dest.getPort()); -+ -+ connect(); -+ - } catch (IOException e) { - // server's probably down. that's fine. try later. -- //System.out.println( -- //"Can't connect to server in connection creation"); -+ CMS.debug("HttpConnection: Unable to create connection: " + e); - } - } - -- /* -- * @param op operation to determine the receiving servlet (multi-uri support) -- */ -- public HttpConnection(IRemoteAuthority dest, ISocketFactory factory, int timeout) { -- mDest = dest; -- mReqEncoder = new HttpRequestEncoder(); -- mHttpClient = new HttpClient(factory); -- CMS.debug("HttpConn:Created HttpConnection: factory " + factory + "client " + mHttpClient); -- try { -- mHttpreq.setMethod("POST"); -- // in case of multi-uri, uri will be set right before send -- // by calling setRequestURI(op) -- if (mDest.getURI() != null) -- mHttpreq.setURI(mDest.getURI()); -+ public HttpConnection(IRemoteAuthority dest, ISocketFactory factory) { -+ this(dest, factory, 0); -+ } - -- String contentType = dest.getContentType(); -- if (contentType != null) { -- CMS.debug("HttpConnection: setting Content-Type"); -- mHttpreq.setHeader("Content-Type", contentType ); -- } -+ List parseTarget(String target, int port) { - -- mHttpreq.setHeader("Connection", "Keep-Alive"); -- CMS.debug("HttpConnection: connecting to " + dest.getHost() + ":" + dest.getPort() + " timeout:" + timeout); -- mHttpClient.connect(dest.getHost(), dest.getPort(), timeout); -- CMS.debug("HttpConnection: connected to " + dest.getHost() + ":" + dest.getPort() + " timeout:" + timeout); -- } catch (IOException e) { -- // server's probably down. that's fine. try later. -- //System.out.println( -- //"Can't connect to server in connection creation"); -- CMS.debug("CMSConn:IOException in creating HttpConnection " + e.toString()); -+ List results = new ArrayList(); -+ -+ if (target == null || target.indexOf(' ') < 0) { -+ // target is a single hostname -+ -+ // add hostname and the global port to the results -+ results.add(new InetSocketAddress(target, port)); -+ return results; -+ } -+ -+ // target is a list of hostname:port, for example: -+ // "server1.example.com:8443 server2.example.com:8443" -+ -+ for (String hostnamePort : target.split(" ")) { -+ -+ // parse hostname and port, and ignore the global port -+ String[] parts = hostnamePort.split(":"); -+ String hostname = parts[0]; -+ port = Integer.parseInt(parts[1]); -+ -+ // add hostname and port to the results -+ results.add(new InetSocketAddress(hostname, port)); - } -+ -+ return results; - } - -- // Insert end -+ void connect() throws IOException { -+ -+ IOException exception = null; -+ -+ // try all targets -+ for (InetSocketAddress target : targets) { -+ -+ String hostname = target.getHostString(); -+ int port = target.getPort(); -+ -+ try { -+ CMS.debug("HttpConnection: Connecting to " + hostname + ":" + port + " with timeout " + timeout + "s"); -+ -+ mHttpClient.connect(hostname, port, timeout * 1000); -+ -+ CMS.debug("HttpConnection: Connected to " + hostname + ":" + port); -+ return; -+ -+ } catch (IOException e) { -+ exception = e; -+ CMS.debug("HttpConnection: Unable to connect to " + hostname + ":" + port + ": " + e); -+ // try the next target immediately -+ } -+ } -+ -+ // throw the last exception -+ throw exception; -+ } -+ -+ public void setRequestURI(String uri) -+ throws EBaseException { -+ mHttpreq.setURI(uri); -+ } -+ -+ public String getRequestURI() { -+ return mHttpreq.getURI(); -+ } - /** - * sends a request to remote RA/CA, returning the result. - * -@@ -207,16 +214,17 @@ public class HttpConnection implements IHttpConnection { - CMS.debug("HttpConnection.send: with String content: null or empty"); - throw new EBaseException("HttpConnection.send: with String content: null or empty"); - } -- // CMS.debug("HttpConnection.send: with String content: " + content); -+ -+ CMS.debug("HttpConnection.send: with String content: " + content); - - resp = doSend(content); - return resp; - } - -- private HttpResponse doSend(String content) -- throws EBaseException { -+ private HttpResponse doSend(String content) throws EBaseException { -+ - HttpResponse resp = null; -- boolean reconnect = false; -+ boolean reconnected = false; - - if (getRequestURI() == null) { - throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_ATTRIBUTE", "URI not set in HttpRequest")); -@@ -229,18 +237,21 @@ public class HttpConnection implements IHttpConnection { - - try { - if (!mHttpClient.connected()) { -- mHttpClient.connect(mDest.getHost(), mDest.getPort()); -- CMS.debug("HttpConnection.doSend: reconnected to " + mDest.getHost() + ":" + mDest.getPort()); -- reconnect = true; -+ connect(); -+ reconnected = true; - } -+ - } catch (IOException e) { -+ -+ CMS.debug(e); -+ - if (e.getMessage().indexOf("Peer's certificate issuer has been marked as not trusted") != -1) { - throw new EBaseException( - CMS.getUserMessage( - "CMS_BASE_CONN_FAILED", - "(This local authority cannot connect to the remote authority. The local authority's signing certificate must chain to a CA certificate trusted for client authentication in the certificate database. Use the certificate manager, or command line tool such as certutil to verify that the trust permissions of the local authority's issuer cert have 'CT' setting in the SSL client auth field.)")); - } -- CMS.debug("HttpConn:Couldn't reconnect " + e); -+ - throw new EBaseException(CMS.getUserMessage("CMS_BASE_CONN_FAILED", "Couldn't reconnect " + e)); - } - -@@ -249,28 +260,35 @@ public class HttpConnection implements IHttpConnection { - try { - CMS.debug("HttpConnection.doSend: sending request"); - resp = mHttpClient.send(mHttpreq); -+ - } catch (IOException e) { -- CMS.debug("HttpConn: mHttpClient.send failed " + e.toString()); -- if (reconnect) { -- CMS.debug("HttpConnection.doSend:resend failed again. " + e); -- throw new EBaseException(CMS.getUserMessage("CMS_BASE_CONN_FAILED", "resend failed again. " + e)); -+ -+ CMS.debug(e); -+ -+ if (reconnected) { -+ CMS.debug("HttpConnection.doSend: resend failed again."); -+ throw new EBaseException( -+ CMS.getUserMessage("CMS_BASE_CONN_FAILED", "resend failed again: " + e), e); - } -+ - try { - CMS.debug("HttpConnection.doSend: trying a reconnect "); -- mHttpClient.connect(mDest.getHost(), mDest.getPort()); -+ connect(); -+ - } catch (IOException ex) { - CMS.debug("HttpConnection.doSend: reconnect for resend failed. " + ex); -- throw new EBaseException(CMS.getUserMessage("CMS_BASE_CONN_FAILED", "reconnect for resend failed." -- + ex)); -+ throw new EBaseException( -+ CMS.getUserMessage("CMS_BASE_CONN_FAILED", "reconnect for resend failed: " + ex), e); - } -- reconnect = true; -+ -+ reconnected = true; - } - } //while - - // got reply; check status - String statusStr = resp.getStatusCode(); - -- CMS.debug("HttpConnection.doSend:server returned status " + statusStr); -+ CMS.debug("HttpConnection.doSend: server returned status " + statusStr); - int statuscode = -1; - - try { -@@ -287,16 +305,18 @@ public class HttpConnection implements IHttpConnection { - // XXX what to do here. - String msg = "request no good " + statuscode + " " + resp.getReasonPhrase(); - -- CMS.debug(msg); -+ CMS.debug("HttpConnection: " + msg); - throw new EBaseException(CMS.getUserMessage("CMS_BASE_AUTHENTICATE_FAILED", msg)); -+ - } else { - // XXX what to do here. -- String msg = "HttpConn:request no good " + statuscode + " " + resp.getReasonPhrase(); -+ String msg = "HttpConnection: request no good " + statuscode + " " + resp.getReasonPhrase(); - - CMS.debug(msg); - throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_ATTRIBUTE", msg)); - } - } -+ - return resp; - } - } -diff --git a/base/util/src/com/netscape/cmsutil/http/HttpClient.java b/base/util/src/com/netscape/cmsutil/http/HttpClient.java -index 438c70c..db042a7 100644 ---- a/base/util/src/com/netscape/cmsutil/http/HttpClient.java -+++ b/base/util/src/com/netscape/cmsutil/http/HttpClient.java -@@ -59,22 +59,24 @@ public class HttpClient { - mCertApprovalCallback = certApprovalCallback; - } - -- public void connect(String host, int port) -- throws IOException { -+ public void connect(String host, int port, -+ int timeout // milliseconds -+ ) throws IOException { -+ - if (mFactory != null) { - if (mCertApprovalCallback == null) { -- mSocket = mFactory.makeSocket(host, port); -+ mSocket = mFactory.makeSocket(host, port, timeout); - } else { -- mSocket = mFactory.makeSocket(host, port, mCertApprovalCallback, null); -+ mSocket = mFactory.makeSocket(host, port, mCertApprovalCallback, null, timeout); - } -+ - } else { - mSocket = new Socket(host, port); -+ mSocket.setSoTimeout(timeout); - } - - if (mSocket == null) { -- IOException e = new IOException("Couldn't make connection"); -- -- throw e; -+ throw new IOException("Couldn't make connection"); - } - - mInputStream = mSocket.getInputStream(); -@@ -85,30 +87,10 @@ public class HttpClient { - mConnected = true; - } - -- // Inserted by beomsuk -- public void connect(String host, int port, int timeout) -- throws IOException { -- if (mFactory != null) { -- mSocket = mFactory.makeSocket(host, port, timeout); -- } else { -- mSocket = new Socket(host, port); -- } -- -- if (mSocket == null) { -- IOException e = new IOException("Couldn't make connection"); -- -- throw e; -- } -- -- mInputStream = mSocket.getInputStream(); -- mOutputStream = mSocket.getOutputStream(); -- mInputStreamReader = new InputStreamReader(mInputStream, "UTF8"); -- mBufferedReader = new BufferedReader(mInputStreamReader); -- mOutputStreamWriter = new OutputStreamWriter(mOutputStream, "UTF8"); -- mConnected = true; -+ public void connect(String host, int port) throws IOException { -+ connect(host, port, 0); - } - -- // Insert end - public boolean connected() { - return mConnected; - } -diff --git a/base/util/src/com/netscape/cmsutil/http/JssSSLSocketFactory.java b/base/util/src/com/netscape/cmsutil/http/JssSSLSocketFactory.java -index 166479d..8c70480 100644 ---- a/base/util/src/com/netscape/cmsutil/http/JssSSLSocketFactory.java -+++ b/base/util/src/com/netscape/cmsutil/http/JssSSLSocketFactory.java -@@ -48,13 +48,14 @@ public class JssSSLSocketFactory implements ISocketFactory { - - public Socket makeSocket(String host, int port) - throws IOException, UnknownHostException { -- return makeSocket(host, port, null, null); -+ return makeSocket(host, port, null, null, 0); - } - - public Socket makeSocket(String host, int port, - SSLCertificateApprovalCallback certApprovalCallback, -- SSLClientCertificateSelectionCallback clientCertCallback) -- throws IOException, UnknownHostException { -+ SSLClientCertificateSelectionCallback clientCertCallback, -+ int timeout // milliseconds -+ ) throws IOException, UnknownHostException { - - try { - /* -@@ -63,6 +64,7 @@ public class JssSSLSocketFactory implements ISocketFactory { - s = new SSLSocket(host, port, null, 0, certApprovalCallback, - clientCertCallback); - s.setUseClientMode(true); -+ s.setSoTimeout(timeout); - - SSLHandshakeCompletedListener listener = null; - -@@ -79,27 +81,34 @@ public class JssSSLSocketFactory implements ISocketFactory { - s.setClientCertNickname(mClientAuthCertNickname); - } - s.forceHandshake(); -+ - } catch (org.mozilla.jss.crypto.ObjectNotFoundException e) { -- throw new IOException(e.toString()); -+ throw new IOException(e.toString(), e); -+ - } catch (org.mozilla.jss.crypto.TokenException e) { -- throw new IOException(e.toString()); -+ throw new IOException(e.toString(), e); -+ - } catch (UnknownHostException e) { - throw e; -+ - } catch (IOException e) { - throw e; -+ - } catch (Exception e) { -- throw new IOException(e.toString()); -+ throw new IOException(e.toString(), e); - } -+ - return s; - } - -- public Socket makeSocket(String host, int port, int timeout) -- throws IOException, UnknownHostException { -+ public Socket makeSocket(String host, int port, -+ int timeout // milliseconds -+ ) throws IOException, UnknownHostException { - Thread t = new ConnectAsync(this, host, port); - - t.start(); - try { -- t.join(1000 * timeout); -+ t.join(timeout); - } catch (InterruptedException e) { - } - -diff --git a/base/util/src/com/netscape/cmsutil/net/ISocketFactory.java b/base/util/src/com/netscape/cmsutil/net/ISocketFactory.java -index 18f6cac..0dd6963 100644 ---- a/base/util/src/com/netscape/cmsutil/net/ISocketFactory.java -+++ b/base/util/src/com/netscape/cmsutil/net/ISocketFactory.java -@@ -28,11 +28,13 @@ public interface ISocketFactory { - Socket makeSocket(String host, int port) - throws IOException, UnknownHostException; - -- Socket makeSocket(String host, int port, int timeout) -- throws IOException, UnknownHostException; -+ Socket makeSocket(String host, int port, -+ int timeout // milliseconds -+ ) throws IOException, UnknownHostException; - - Socket makeSocket(String host, int port, - SSLCertificateApprovalCallback certApprovalCallback, -- SSLClientCertificateSelectionCallback clientCertCallback) -- throws IOException, UnknownHostException; -+ SSLClientCertificateSelectionCallback clientCertCallback, -+ int timeout // milliseconds -+ ) throws IOException, UnknownHostException; - } --- -1.8.3.1 - - -From 6db01bd091ce991322b004cdd74bf7c15c57fe8c Mon Sep 17 00:00:00 2001 -From: Christina Fu -Date: Tue, 30 Jun 2015 18:46:33 -0700 -Subject: [PATCH 17/21] Ticket 1447 pkispawn: findCertByNickname fails to find - cert in creating shared tomcat subsystems on HSM - ---- - .../src/org/dogtagpki/server/rest/SystemConfigService.java | 14 +++++++++----- - 1 file changed, 9 insertions(+), 5 deletions(-) - -diff --git a/base/server/cms/src/org/dogtagpki/server/rest/SystemConfigService.java b/base/server/cms/src/org/dogtagpki/server/rest/SystemConfigService.java -index 73d24a7..e7a9960 100644 ---- a/base/server/cms/src/org/dogtagpki/server/rest/SystemConfigService.java -+++ b/base/server/cms/src/org/dogtagpki/server/rest/SystemConfigService.java -@@ -345,6 +345,7 @@ public class SystemConfigService extends PKIService implements SystemConfigResou - throw new BadRequestException("No data for '" + tag + "' was found!"); - } - -+ String tokenName = certData.getToken() != null ? certData.getToken() : token; - if (request.getStandAlone() && request.getStepTwo()) { - // Stand-alone PKI (Step 2) - if (tag.equals("external_signing")) { -@@ -355,7 +356,6 @@ public class SystemConfigService extends PKIService implements SystemConfigResou - - if (request.getIssuingCA().equals("External CA")) { - String nickname = certData.getNickname() != null ? certData.getNickname() : "caSigningCert External CA"; -- String tokenName = certData.getToken() != null ? certData.getToken() : token; - Cert cert = new Cert(tokenName, nickname, tag); - ConfigurationUtils.setExternalCACert(b64, csSubsystem, cs, cert); - -@@ -387,7 +387,7 @@ public class SystemConfigService extends PKIService implements SystemConfigResou - updateConfiguration(request, certData, "subsystem"); - - // get parameters needed for cloning -- updateCloneConfiguration(certData, "subsystem"); -+ updateCloneConfiguration(certData, "subsystem", tokenName); - continue; - } - -@@ -439,7 +439,6 @@ public class SystemConfigService extends PKIService implements SystemConfigResou - CMS.debug("configure(): step two selected. keys will not be generated for '" + tag + "'"); - } - -- String tokenName = certData.getToken() != null ? certData.getToken() : token; - Cert cert = new Cert(tokenName, nickname, tag); - cert.setDN(dn); - cert.setSubsystem(cs.getString("preop.cert." + tag + ".subsystem")); -@@ -529,11 +528,16 @@ public class SystemConfigService extends PKIService implements SystemConfigResou - } - } - -- private void updateCloneConfiguration(SystemCertData cdata, String tag) throws NotInitializedException, -+ private void updateCloneConfiguration(SystemCertData cdata, String tag, String tokenName) throws NotInitializedException, - ObjectNotFoundException, TokenException { - // TODO - some of these parameters may only be valid for RSA - CryptoManager cryptoManager = CryptoManager.getInstance(); -- X509Certificate cert = cryptoManager.findCertByNickname(cdata.getNickname()); -+ if (!tokenName.isEmpty()) -+ CMS.debug("SystemConfigService:updateCloneConfiguration: tokenName=" + tokenName); -+ else -+ CMS.debug("SystemConfigService:updateCloneConfiguration: tokenName empty; using internal"); -+ -+ X509Certificate cert = cryptoManager.findCertByNickname(!tokenName.isEmpty()? tokenName + ":" + cdata.getNickname() : cdata.getNickname()); - PublicKey pubk = cert.getPublicKey(); - byte[] exponent = CryptoUtil.getPublicExponent(pubk); - byte[] modulus = CryptoUtil.getModulus(pubk); --- -1.8.3.1 - - -From a3773d042de25120803154c96763de55bc0bd7c4 Mon Sep 17 00:00:00 2001 -From: Matthew Harmsen -Date: Mon, 6 Jul 2015 15:09:54 -0600 -Subject: [PATCH 18/21] Note on overriding pki_client_dir when using an HSM - -- PKI TRAC Ticket #1425 - pkispawn CA with HSM - if the config file has - pki_client related params the dir is not created and the admin cert p12 file - is stored nowhere ---- - base/server/man/man5/pki_default.cfg.5 | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/base/server/man/man5/pki_default.cfg.5 b/base/server/man/man5/pki_default.cfg.5 -index f3db6a8..2c8dbbd 100644 ---- a/base/server/man/man5/pki_default.cfg.5 -+++ b/base/server/man/man5/pki_default.cfg.5 -@@ -152,6 +152,9 @@ Set to True to back up the subsystem certificates and keys to a PKCS #12 file. - .B pki_client_dir - .IP - This is the location where all client data used during the installation is stored. At the end of the invocation of \fBpkispawn\fP, the administrative user's certificate and keys are stored in a PKCS #12 file in this location. -+.IP -+\fBNote:\fP -+When using an HSM, it is currently recommended to NOT specify a value for \fBpki_client_dir\fP that is different from the default value. - .TP - .B pki_client_database_dir, pki_client_database_password - .IP --- -1.8.3.1 - - -From 02c50813a2f5054ad1b6b0a42e919e3ae1472fe0 Mon Sep 17 00:00:00 2001 -From: Jack Magne -Date: Mon, 6 Jul 2015 14:05:57 -0700 -Subject: [PATCH 19/21] Omit OCSP from clone description. - -Ticket #1358. -Also note that OCSP cloning is unsupported as of now. ---- - base/server/man/man8/pkispawn.8 | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) - -diff --git a/base/server/man/man8/pkispawn.8 b/base/server/man/man8/pkispawn.8 -index 33c36e3..ef1857d 100644 ---- a/base/server/man/man8/pkispawn.8 -+++ b/base/server/man/man8/pkispawn.8 -@@ -277,10 +277,10 @@ A cloned CA is a CA which uses the same signing, OCSP signing, and audit signing - .PP - Before the clone can be generated, the Directory Server must be created that is separate from the master CA's Directory Server. The example assumes that the master CA and cloned CA are on different machines, and that their Directory Servers are on port 389. In addition, the master's system certs and keys have been stored in a PKCS #12 file that is copied over to the clone subsystem in the location specified in . This file is created when the master CA is installed; it can also be generated using \fBPKCS12Export\fP. The file needs to be readable by the user the Certificate Server runs as (by default, pkiuser) and be given the SELinux context pki_tomcat_cert_t. - .PP --.SS Installing a KRA, OCSP, or TKS clone -+.SS Installing a KRA or TKS clone (OCSP unsupported as of now) - \x'-1'\fBpkispawn \-s \-f myconfig.txt\fR - .PP --where subsystem is KRA, OCSP, or TKS, and \fImyconfig.txt\fP contains the following text: -+where subsystem is KRA or TKS and \fImyconfig.txt\fP contains the following text: - .IP - .nf - [DEFAULT] -@@ -302,9 +302,9 @@ pki_clone_uri=https://: - pki_issuing_ca=https://: - .fi - .PP --As with a CA clone, a KRA, OCSP, or TKS clone uses the same certificates and basic configuration as the original subsystem. The configuration points to the original subsystem to copy its configuration. This example also assumes that the CA is on a remote machine and specifies the CA and security domain information. -+As with a CA clone, a KRA or TKS clone uses the same certificates and basic configuration as the original subsystem. The configuration points to the original subsystem to copy its configuration. This example also assumes that the CA is on a remote machine and specifies the CA and security domain information. - .PP --The subsystem section is [KRA], [OCSP], or [TKS]. -+The subsystem section is [KRA] or [TKS]. - .SS Installing a subordinate CA - \x'-1'\fBpkispawn \-s CA \-f myconfig.txt\fR - .PP --- -1.8.3.1 - - -From c48c52703c374c8e7e65c11fdeee9eeda464290f Mon Sep 17 00:00:00 2001 -From: Fraser Tweedale -Date: Sat, 4 Jul 2015 11:00:29 -0400 -Subject: [PATCH 20/21] Verify raw profile config before accepting it - -Creating or modifying a profile with bad profile data in the "raw" -format succeeds and saves the bad data. After restart, the profile -cannot be loaded and attempting to use, modify or delete or recreate -the profile will fail. - -Verify raw profile data by instantiating a temporary profile and -attempting to initialise it with the received configuration. - -Fixes: https://fedorahosted.org/pki/ticket/1462 ---- - .../dogtagpki/server/ca/rest/ProfileService.java | 43 +++++++++++++++++++++- - 1 file changed, 42 insertions(+), 1 deletion(-) - -diff --git a/base/ca/src/org/dogtagpki/server/ca/rest/ProfileService.java b/base/ca/src/org/dogtagpki/server/ca/rest/ProfileService.java -index f7d82b0..a1dba80 100644 ---- a/base/ca/src/org/dogtagpki/server/ca/rest/ProfileService.java -+++ b/base/ca/src/org/dogtagpki/server/ca/rest/ProfileService.java -@@ -81,6 +81,7 @@ import com.netscape.cms.servlet.base.PKIService; - import com.netscape.cms.servlet.profile.PolicyConstraintFactory; - import com.netscape.cms.servlet.profile.PolicyDefaultFactory; - import com.netscape.cmscore.base.SimpleProperties; -+import com.netscape.cmscore.base.PropConfigStore; - - /** - * @author alee -@@ -583,8 +584,27 @@ public class ProfileService extends PKIService implements ProfileResource { - auditParams.put("class_id", classId); - - IPluginInfo info = registry.getPluginInfo("profile", classId); -+ String className = info.getClassName(); - -- profile = ps.createProfile(profileId, classId, info.getClassName()); -+ // create temporary profile to verify profile configuration -+ IProfile tempProfile; -+ try { -+ tempProfile = (IProfile) Class.forName(className).newInstance(); -+ } catch (Exception e) { -+ throw new PKIException( -+ "Error instantiating profile class: " + className); -+ } -+ tempProfile.setId(profileId); -+ try { -+ PropConfigStore tempConfig = new PropConfigStore(null); -+ tempConfig.load(new ByteArrayInputStream(data)); -+ tempProfile.init(ps, tempConfig); -+ } catch (Exception e) { -+ throw new BadRequestException("Invalid profile data", e); -+ } -+ -+ // no error thrown, proceed with profile creation -+ profile = ps.createProfile(profileId, classId, className); - profile.getConfigStore().commit(false); - profile.getConfigStore().load(new ByteArrayInputStream(data)); - ps.disableProfile(profileId); -@@ -698,6 +718,27 @@ public class ProfileService extends PKIService implements ProfileResource { - simpleProperties.store(out, null); - data = out.toByteArray(); // original data sans profileId, classId - -+ // create temporary profile to verify profile configuration -+ String classId = ps.getProfileClassId(profileId); -+ String className = -+ registry.getPluginInfo("profile", classId).getClassName(); -+ IProfile tempProfile; -+ try { -+ tempProfile = (IProfile) Class.forName(className).newInstance(); -+ } catch (Exception e) { -+ throw new PKIException( -+ "Error instantiating profile class: " + className); -+ } -+ tempProfile.setId(profileId); -+ try { -+ PropConfigStore tempConfig = new PropConfigStore(null); -+ tempConfig.load(new ByteArrayInputStream(data)); -+ tempProfile.init(ps, tempConfig); -+ } catch (Exception e) { -+ throw new BadRequestException("Invalid profile data", e); -+ } -+ -+ // no error thrown, so commit updated profile config - profile.getConfigStore().load(new ByteArrayInputStream(data)); - ps.disableProfile(profileId); - profile.getConfigStore().commit(false); --- -1.8.3.1 - - -From ac5447a8e0bac5112882be700a17a9274e322adc Mon Sep 17 00:00:00 2001 -From: "Endi S. Dewata" -Date: Mon, 6 Jul 2015 13:31:22 -0400 -Subject: [PATCH 21/21] Fixed default cert-find filter. - -To improve the performance the default LDAP filter generated by -cert-find has been changed to (certStatus=*) to match an existing -VLV index. - -https://fedorahosted.org/pki/ticket/1449 ---- - .../org/dogtagpki/server/ca/rest/CertService.java | 16 +- - .../com/netscape/cmstools/cert/CertFindCLI.java | 1 - - .../netscape/cms/servlet/cert/FilterBuilder.java | 248 +++++++++++---------- - 3 files changed, 136 insertions(+), 129 deletions(-) - -diff --git a/base/ca/src/org/dogtagpki/server/ca/rest/CertService.java b/base/ca/src/org/dogtagpki/server/ca/rest/CertService.java -index ee974d4..e43909b 100644 ---- a/base/ca/src/org/dogtagpki/server/ca/rest/CertService.java -+++ b/base/ca/src/org/dogtagpki/server/ca/rest/CertService.java -@@ -367,15 +367,13 @@ public class CertService extends PKIService implements CertResource { - } - - private String createSearchFilter(String status) { -- String filter = ""; -+ String filter; - -- if ((status == null)) { -- filter = "(serialno=*)"; -- return filter; -- } -+ if (status == null) { -+ filter = "(certstatus=*)"; // allCerts VLV - -- if (status != null) { -- filter += "(certStatus=" + LDAPUtil.escapeFilter(status) + ")"; -+ } else { -+ filter = "(certStatus=" + LDAPUtil.escapeFilter(status) + ")"; - } - - return filter; -@@ -398,7 +396,7 @@ public class CertService extends PKIService implements CertResource { - size = size == null ? DEFAULT_SIZE : size; - - String filter = createSearchFilter(status); -- CMS.debug("listCerts: filter is " + filter); -+ CMS.debug("CertService.listCerts: filter: " + filter); - - CertDataInfos infos = new CertDataInfos(); - try { -@@ -450,7 +448,9 @@ public class CertService extends PKIService implements CertResource { - - start = start == null ? 0 : start; - size = size == null ? DEFAULT_SIZE : size; -+ - String filter = createSearchFilter(data); -+ CMS.debug("CertService.searchCerts: filter: " + filter); - - CertDataInfos infos = new CertDataInfos(); - try { -diff --git a/base/java-tools/src/com/netscape/cmstools/cert/CertFindCLI.java b/base/java-tools/src/com/netscape/cmstools/cert/CertFindCLI.java -index 8c7a4df..cb2d80e 100644 ---- a/base/java-tools/src/com/netscape/cmstools/cert/CertFindCLI.java -+++ b/base/java-tools/src/com/netscape/cmstools/cert/CertFindCLI.java -@@ -254,7 +254,6 @@ public class CertFindCLI extends CLI { - - } else { - searchData = new CertSearchRequest(); -- searchData.setSerialNumberRangeInUse(true); - } - - String s = cmd.getOptionValue("start"); -diff --git a/base/server/cms/src/com/netscape/cms/servlet/cert/FilterBuilder.java b/base/server/cms/src/com/netscape/cms/servlet/cert/FilterBuilder.java -index 5c337af..be44c47 100644 ---- a/base/server/cms/src/com/netscape/cms/servlet/cert/FilterBuilder.java -+++ b/base/server/cms/src/com/netscape/cms/servlet/cert/FilterBuilder.java -@@ -18,7 +18,9 @@ - - package com.netscape.cms.servlet.cert; - -+import java.util.ArrayList; - import java.util.Calendar; -+import java.util.List; - import java.util.StringTokenizer; - - import com.netscape.certsrv.cert.CertSearchRequest; -@@ -30,210 +32,214 @@ import com.netscape.cmsutil.ldap.LDAPUtil; - * - */ - public class FilterBuilder { -- private final static String MATCH_EXACTLY = "exact"; -- private String searchFilter = null; -- private CertSearchRequest request = null; -+ -+ private List filters = new ArrayList(); -+ private CertSearchRequest request; - - public FilterBuilder(CertSearchRequest request) { - this.request = request; - } - - public String buildFilter() { -- StringBuffer filter = new StringBuffer(); -- buildSerialNumberRangeFilter(filter); -- buildSubjectFilter(filter); -- buildStatusFilter(filter); -- buildRevokedByFilter(filter); -- buildRevokedOnFilter(filter); -- buildRevocationReasonFilter(filter); -- buildIssuedByFilter(filter); -- buildIssuedOnFilter(filter); -- buildValidNotBeforeFilter(filter); -- buildValidNotAfterFilter(filter); -- buildValidityLengthFilter(filter); -- buildCertTypeFilter(filter); -- -- searchFilter = filter.toString(); -- -- if (searchFilter != null && !searchFilter.equals("")) { -- searchFilter = "(&" + searchFilter + ")"; -- } - -- return searchFilter; -+ buildSerialNumberRangeFilter(); -+ buildSubjectFilter(); -+ buildStatusFilter(); -+ buildRevokedByFilter(); -+ buildRevokedOnFilter(); -+ buildRevocationReasonFilter(); -+ buildIssuedByFilter(); -+ buildIssuedOnFilter(); -+ buildValidNotBeforeFilter(); -+ buildValidNotAfterFilter(); -+ buildValidityLengthFilter(); -+ buildCertTypeFilter(); -+ -+ if (filters.size() == 0) { -+ return "(certstatus=*)"; // allCerts VLV -+ -+ } else if (filters.size() == 1) { -+ return filters.get(0); -+ -+ } else { -+ StringBuilder sb = new StringBuilder(); -+ for (String filter : filters) { -+ sb.append(filter); -+ } -+ return "(&" + sb + ")"; -+ } - } - -- private void buildSerialNumberRangeFilter(StringBuffer filter) { -+ private void buildSerialNumberRangeFilter() { - -- if (!request.getSerialNumberRangeInUse()) { -- return; -- } -- boolean changed = false; - String serialFrom = request.getSerialFrom(); - if (serialFrom != null && !serialFrom.equals("")) { -- filter.append("(certRecordId>=" + LDAPUtil.escapeFilter(serialFrom) + ")"); -- changed = true; -+ filters.add("(certRecordId>=" + LDAPUtil.escapeFilter(serialFrom) + ")"); - } -+ - String serialTo = request.getSerialTo(); - if (serialTo != null && !serialTo.equals("")) { -- filter.append("(certRecordId<=" + LDAPUtil.escapeFilter(serialTo) + ")"); -- changed = true; -+ filters.add("(certRecordId<=" + LDAPUtil.escapeFilter(serialTo) + ")"); - } -- if (!changed) { -- filter.append("(certRecordId=*)"); -- } -- - } - -- private void buildSubjectFilter(StringBuffer filter) { -+ private void buildSubjectFilter() { -+ - if (!request.getSubjectInUse()) { - return; - } -- StringBuffer lf = new StringBuffer(); - -- String matchStr = null; -+ StringBuffer lf = new StringBuffer(); - boolean match = request.getMatchExactly(); - -- if (match == true) { -- matchStr = MATCH_EXACTLY; -- } -- -- buildAVAFilter(request.getEmail(), "E", lf, matchStr); -- buildAVAFilter(request.getCommonName(), "CN", lf, matchStr); -- buildAVAFilter(request.getUserID(), "UID", lf, matchStr); -- buildAVAFilter(request.getOrgUnit(), "OU", lf, matchStr); -- buildAVAFilter(request.getOrg(), "O", lf, matchStr); -- buildAVAFilter(request.getLocality(), "L", lf, matchStr); -- buildAVAFilter(request.getState(), "ST", lf, matchStr); -- buildAVAFilter(request.getCountry(), "C", lf, matchStr); -+ buildAVAFilter(request.getEmail(), "E", lf, match); -+ buildAVAFilter(request.getCommonName(), "CN", lf, match); -+ buildAVAFilter(request.getUserID(), "UID", lf, match); -+ buildAVAFilter(request.getOrgUnit(), "OU", lf, match); -+ buildAVAFilter(request.getOrg(), "O", lf, match); -+ buildAVAFilter(request.getLocality(), "L", lf, match); -+ buildAVAFilter(request.getState(), "ST", lf, match); -+ buildAVAFilter(request.getCountry(), "C", lf, match); - - if (lf.length() == 0) { -- filter.append("("+ICertRecord.ATTR_X509CERT_SUBJECT+"=*)"); -- return; -- } -- if (matchStr != null && matchStr.equals(MATCH_EXACTLY)) { -- filter.append("(&"); -- filter.append(lf); -- filter.append(")"); -+ filters.add("(" + ICertRecord.ATTR_X509CERT_SUBJECT + "=*)"); -+ -+ } else if (match) { -+ filters.add("(&" + lf + ")"); -+ - } else { -- filter.append("(|"); -- filter.append(lf); -- filter.append(")"); -+ filters.add("(|" + lf + ")"); - } - } - -- private void buildStatusFilter(StringBuffer filter) { -+ private void buildStatusFilter() { -+ - String status = request.getStatus(); - if (status == null || status.equals("")) { - return; - } -- filter.append("(certStatus="); -- filter.append(LDAPUtil.escapeFilter(status)); -- filter.append(")"); -+ -+ filters.add("(certStatus=" + LDAPUtil.escapeFilter(status) + ")"); - } - -- private void buildRevokedByFilter(StringBuffer filter) { -+ private void buildRevokedByFilter() { -+ - if (!request.getRevokedByInUse()) { - return; - } - - String revokedBy = request.getRevokedBy(); - if (revokedBy == null || revokedBy.equals("")) { -- filter.append("(certRevokedBy=*)"); -+ filters.add("(certRevokedBy=*)"); -+ - } else { -- filter.append("(certRevokedBy="); -- filter.append(LDAPUtil.escapeFilter(revokedBy)); -- filter.append(")"); -+ filters.add("(certRevokedBy=" + LDAPUtil.escapeFilter(revokedBy) + ")"); - } - } - - private void buildDateFilter(String prefix, -- String outStr, long adjustment, -- StringBuffer filter) { -+ String outStr, long adjustment) { -+ - if (prefix == null || prefix.length() == 0) return; -+ - long epoch = Long.parseLong(prefix); - Calendar from = Calendar.getInstance(); - from.setTimeInMillis(epoch); -+ -+ StringBuilder filter = new StringBuilder(); - filter.append("("); - filter.append(LDAPUtil.escapeFilter(outStr)); - filter.append(Long.toString(from.getTimeInMillis() + adjustment)); - filter.append(")"); -+ -+ filters.add(filter.toString()); - } - -- private void buildRevokedOnFilter(StringBuffer filter) { -+ private void buildRevokedOnFilter() { -+ - if (!request.getRevokedOnInUse()) { - return; - } -- buildDateFilter(request.getRevokedOnFrom(), "certRevokedOn>=", 0, filter); -- buildDateFilter(request.getRevokedOnTo(), "certRevokedOn<=", 86399999, filter); -+ -+ buildDateFilter(request.getRevokedOnFrom(), "certRevokedOn>=", 0); -+ buildDateFilter(request.getRevokedOnTo(), "certRevokedOn<=", 86399999); - } - -- private void buildRevocationReasonFilter(StringBuffer filter) { -+ private void buildRevocationReasonFilter() { -+ - if (!request.getRevocationReasonInUse()) { - return; - } -+ - String reasons = request.getRevocationReason(); - if (reasons == null) { - return; - } -- String queryCertFilter = null; -+ -+ StringBuilder filter = new StringBuilder(); - StringTokenizer st = new StringTokenizer(reasons, ","); - int count = st.countTokens(); - if (st.hasMoreTokens()) { -- if (count >=2) filter.append("(|"); -+ if (count >= 2) filter.append("(|"); - while (st.hasMoreTokens()) { - String token = st.nextToken(); -- if (queryCertFilter == null) { -- queryCertFilter = ""; -- } - filter.append("(x509cert.certRevoInfo="); - filter.append(LDAPUtil.escapeFilter(token)); - filter.append(")"); - } - if (count >= 2) filter.append(")"); - } -+ -+ filters.add(filter.toString()); - } - -- private void buildIssuedByFilter(StringBuffer filter) { -+ private void buildIssuedByFilter() { -+ - if (!request.getIssuedByInUse()) { - return; - } -+ - String issuedBy = request.getIssuedBy(); - if (issuedBy == null || issuedBy.equals("")) { -- filter.append("(certIssuedBy=*)"); -+ filters.add("(certIssuedBy=*)"); - } else { -- filter.append("(certIssuedBy="); -- filter.append(LDAPUtil.escapeFilter(issuedBy)); -- filter.append(")"); -+ filters.add("(certIssuedBy=" + LDAPUtil.escapeFilter(issuedBy) + ")"); - } - } - -- private void buildIssuedOnFilter(StringBuffer filter) { -+ private void buildIssuedOnFilter() { -+ - if (!request.getIssuedOnInUse()) { - return; - } -- buildDateFilter(request.getIssuedOnFrom(), "certCreateTime>=", 0, filter); -- buildDateFilter(request.getIssuedOnTo(), "certCreateTime<=", 86399999, filter); -+ -+ buildDateFilter(request.getIssuedOnFrom(), "certCreateTime>=", 0); -+ buildDateFilter(request.getIssuedOnTo(), "certCreateTime<=", 86399999); - } - -- private void buildValidNotBeforeFilter(StringBuffer filter) { -+ private void buildValidNotBeforeFilter() { -+ - if (!request.getValidNotBeforeInUse()) { - return; - } -- buildDateFilter(request.getValidNotBeforeFrom(), ICertRecord.ATTR_X509CERT_NOT_BEFORE+">=", 0, filter); -- buildDateFilter(request.getValidNotBeforeTo(), ICertRecord.ATTR_X509CERT_NOT_BEFORE+"<=", 86399999, filter); -+ -+ buildDateFilter(request.getValidNotBeforeFrom(), ICertRecord.ATTR_X509CERT_NOT_BEFORE+">=", 0); -+ buildDateFilter(request.getValidNotBeforeTo(), ICertRecord.ATTR_X509CERT_NOT_BEFORE+"<=", 86399999); - - } - -- private void buildValidNotAfterFilter(StringBuffer filter) { -+ private void buildValidNotAfterFilter() { -+ - if (!request.getValidNotAfterInUse()) { - return; - } -- buildDateFilter(request.getValidNotAfterFrom(), ICertRecord.ATTR_X509CERT_NOT_AFTER+">=", 0, filter); -- buildDateFilter(request.getValidNotAfterTo(), ICertRecord.ATTR_X509CERT_NOT_AFTER+"<=", 86399999, filter); -+ -+ buildDateFilter(request.getValidNotAfterFrom(), ICertRecord.ATTR_X509CERT_NOT_AFTER+">=", 0); -+ buildDateFilter(request.getValidNotAfterTo(), ICertRecord.ATTR_X509CERT_NOT_AFTER+"<=", 86399999); - - } - -- private void buildValidityLengthFilter(StringBuffer filter) { -+ private void buildValidityLengthFilter() { - if (!request.getValidityLengthInUse()) { - return; - } -@@ -242,70 +248,72 @@ public class FilterBuilder { - Integer count = request.getValidityCount(); - Long unit = request.getValidityUnit(); - -+ StringBuilder filter = new StringBuilder(); - filter.append("("); - filter.append(ICertRecord.ATTR_X509CERT_DURATION); - filter.append(LDAPUtil.escapeFilter(op)); - filter.append(count * unit); - filter.append(")"); -+ -+ filters.add(filter.toString()); - } - -- private void buildCertTypeFilter(StringBuffer filter) { -+ private void buildCertTypeFilter() { -+ - if (!request.getCertTypeInUse()) { - return; - } -+ - if (isOn(request.getCertTypeSSLClient())) { -- filter.append("(x509cert.nsExtension.SSLClient=on)"); -+ filters.add("(x509cert.nsExtension.SSLClient=on)"); - } else if (isOff(request.getCertTypeSSLClient())) { -- filter.append("(x509cert.nsExtension.SSLClient=off)"); -+ filters.add("(x509cert.nsExtension.SSLClient=off)"); - } -+ - if (isOn(request.getCertTypeSSLServer())) { -- filter.append("(x509cert.nsExtension.SSLServer=on)"); -+ filters.add("(x509cert.nsExtension.SSLServer=on)"); - } else if (isOff(request.getCertTypeSSLServer())) { -- filter.append("(x509cert.nsExtension.SSLServer=off)"); -+ filters.add("(x509cert.nsExtension.SSLServer=off)"); - } -+ - if (isOn(request.getCertTypeSecureEmail())) { -- filter.append("(x509cert.nsExtension.SecureEmail=on)"); -+ filters.add("(x509cert.nsExtension.SecureEmail=on)"); - } else if (isOff(request.getCertTypeSecureEmail())) { -- filter.append("(x509cert.nsExtension.SecureEmail=off)"); -+ filters.add("(x509cert.nsExtension.SecureEmail=off)"); - } -+ - if (isOn(request.getCertTypeSubSSLCA())) { -- filter.append("(x509cert.nsExtension.SubordinateSSLCA=on)"); -+ filters.add("(x509cert.nsExtension.SubordinateSSLCA=on)"); - } else if (isOff(request.getCertTypeSubSSLCA())) { -- filter.append("(x509cert.nsExtension.SubordinateSSLCA=off)"); -+ filters.add("(x509cert.nsExtension.SubordinateSSLCA=off)"); - } -+ - if (isOn(request.getCertTypeSubEmailCA())) { -- filter.append("(x509cert.nsExtension.SubordinateEmailCA=on)"); -+ filters.add("(x509cert.nsExtension.SubordinateEmailCA=on)"); - } else if (isOff(request.getCertTypeSubEmailCA())) { -- filter.append("(x509cert.nsExtension.SubordinateEmailCA=off)"); -+ filters.add("(x509cert.nsExtension.SubordinateEmailCA=off)"); - } - } - - private boolean isOn(String value) { -- String inUse = value; -- if (inUse == null) { -- return false; -- } -- if (inUse.equals("on")) { -+ if (value != null && value.equals("on")) { - return true; - } - return false; - } - - private boolean isOff(String value) { -- String inUse = value; -- if (inUse == null) { -- return false; -- } -- if (inUse.equals("off")) { -+ if (value != null && value.equals("off")) { - return true; - } - return false; - } - - private void buildAVAFilter(String param, -- String avaName, StringBuffer lf, String match) { -+ String avaName, StringBuffer lf, boolean match) { -+ - if (param != null && !param.equals("")) { -- if (match != null && match.equals(MATCH_EXACTLY)) { -+ if (match) { - lf.append("(|"); - lf.append("("+ICertRecord.ATTR_X509CERT_SUBJECT+"=*"); - lf.append(avaName); -@@ -318,6 +326,7 @@ public class FilterBuilder { - lf.append(LDAPUtil.escapeFilter(LDAPUtil.escapeRDNValue(param))); - lf.append(")"); - lf.append(")"); -+ - } else { - lf.append("("+ICertRecord.ATTR_X509CERT_SUBJECT+"=*"); - lf.append(avaName); -@@ -327,6 +336,5 @@ public class FilterBuilder { - lf.append("*)"); - } - } -- - } - } --- -1.8.3.1 - diff --git a/SOURCES/pki-core-snapshot-1.patch b/SOURCES/pki-core-snapshot-1.patch new file mode 100644 index 0000000..f23cbcd --- /dev/null +++ b/SOURCES/pki-core-snapshot-1.patch @@ -0,0 +1,1332 @@ +From 53eec401f222178ff2ac34fd6223b121f485969d Mon Sep 17 00:00:00 2001 +From: "Endi S. Dewata" +Date: Fri, 12 Aug 2016 02:23:18 +0200 +Subject: [PATCH 01/10] Removed PKCS #7 from add user cert dialog in TPS UI. + +The dialog box for adding user certificate in TPS UI has been +modified to no longer mention PKCS #7. The REST service itself +still accepts PKCS #7, but it should be cleaned up in the future. + +https://fedorahosted.org/pki/ticket/2437 +(cherry picked from commit d27d4600784acb49c42764d02835dedf3ee87227) +(cherry picked from commit 2dae5f18fa5c68f7923b6b6691395790fb14791f) +--- + base/server/cms/src/org/dogtagpki/server/rest/UserService.java | 2 ++ + base/tps/shared/webapps/tps/ui/user-certs.html | 2 +- + 2 files changed, 3 insertions(+), 1 deletion(-) + +diff --git a/base/server/cms/src/org/dogtagpki/server/rest/UserService.java b/base/server/cms/src/org/dogtagpki/server/rest/UserService.java +index 0893c4b..1f8e9fa 100644 +--- a/base/server/cms/src/org/dogtagpki/server/rest/UserService.java ++++ b/base/server/cms/src/org/dogtagpki/server/rest/UserService.java +@@ -863,6 +863,8 @@ public class UserService extends PKIService implements UserResource { + } + + if (cert == null) { ++ // TODO: Remove this code. Importing PKCS #7 is not supported. ++ + // cert chain direction + boolean assending = true; + +diff --git a/base/tps/shared/webapps/tps/ui/user-certs.html b/base/tps/shared/webapps/tps/ui/user-certs.html +index 049583e..04593f3 100644 +--- a/base/tps/shared/webapps/tps/ui/user-certs.html ++++ b/base/tps/shared/webapps/tps/ui/user-certs.html +@@ -93,7 +93,7 @@ +
+ +
+- Enter a PEM certificate or PKCS #7 data. ++ Enter a PEM certificate. + + +