Blob Blame History Raw
From 14e44691ef0b61220d390afb745496b7d62945ee Mon Sep 17 00:00:00 2001
From: "Endi S. Dewata" <edewata@redhat.com>
Date: Tue, 30 May 2017 21:15:44 +0200
Subject: [PATCH 04/27] Added pkispawn options for two-step installation.

New --skip-configuration and --skip-installation options have
been added to pkispawn to provide a mechanism to set the
pki_skip_configuration and pki_skip_installation parameters
without changing the deployment configuration file.

https://pagure.io/dogtagpki/issue/2707

Change-Id: I069b51b5be65dee2fe0f4ca75e3693bcd21007de
---
 base/server/sbin/pkispawn | 40 ++++++++++++++++++++++++++++++++++------
 1 file changed, 34 insertions(+), 6 deletions(-)

diff --git a/base/server/sbin/pkispawn b/base/server/sbin/pkispawn
index 9e2ebc8..742f579 100755
--- a/base/server/sbin/pkispawn
+++ b/base/server/sbin/pkispawn
@@ -91,6 +91,18 @@ def main(argv):
         dest='precheck', action='store_true',
         help='Execute pre-checks and exit')
 
+    parser.optional.add_argument(
+        '--skip-configuration',
+        dest='skip_configuration',
+        action='store_true',
+        help='skip configuration step')
+
+    parser.optional.add_argument(
+        '--skip-installation',
+        dest='skip_installation',
+        action='store_true',
+        help='skip installation step')
+
     args = parser.process_command_line_arguments()
 
     config.default_deployment_cfg = \
@@ -475,6 +487,24 @@ def main(argv):
         sys.exit(1)
 
     start_logging()
+
+    # Read the specified PKI configuration file.
+    rv = parser.read_pki_configuration_file()
+    if rv != 0:
+        config.pki_log.error(log.PKI_UNABLE_TO_PARSE_1, rv,
+                             extra=config.PKI_INDENTATION_LEVEL_0)
+        sys.exit(1)
+
+    # --skip-configuration
+    if args.skip_configuration:
+        parser.set_property(deployer.subsystem_name,
+                            'pki_skip_configuration', 'True')
+
+    # --skip-installation
+    if args.skip_installation:
+        parser.set_property(deployer.subsystem_name,
+                            'pki_skip_installation', 'True')
+
     create_master_dictionary(parser)
 
     if not interactive and \
@@ -635,23 +665,21 @@ def start_logging():
 
 
 def create_master_dictionary(parser):
-    # Read the specified PKI configuration file.
-    rv = parser.read_pki_configuration_file()
-    if rv != 0:
-        config.pki_log.error(log.PKI_UNABLE_TO_PARSE_1, rv,
-                             extra=config.PKI_INDENTATION_LEVEL_0)
-        sys.exit(1)
 
     # Read in the PKI slots configuration file.
     parser.compose_pki_slots_dictionary()
+
     config.pki_log.debug(log.PKI_DICTIONARY_SLOTS,
                          extra=config.PKI_INDENTATION_LEVEL_0)
     config.pki_log.debug(pkilogging.log_format(parser.slots_dict),
                          extra=config.PKI_INDENTATION_LEVEL_0)
+
     # Combine the various sectional dictionaries into a PKI master dictionary
     parser.compose_pki_master_dictionary()
+
     parser.mdict['pki_spawn_log'] = \
         config.pki_log_dir + "/" + config.pki_log_name
+
     config.pki_log.debug(log.PKI_DICTIONARY_MASTER,
                          extra=config.PKI_INDENTATION_LEVEL_0)
     config.pki_log.debug(pkilogging.log_format(parser.mdict),
-- 
1.8.3.1


From 9af1746463bec2e62c990279d857635f693cfac7 Mon Sep 17 00:00:00 2001
From: "Endi S. Dewata" <edewata@redhat.com>
Date: Tue, 30 May 2017 21:07:59 +0200
Subject: [PATCH 05/27] Fixed two-step subordinate CA installation.

The initialization scriptlet has been fixed to verify the subsystem
existence properly when running the second step of the two-step
subordinate CA installation.

https://pagure.io/dogtagpki/issue/2707

Change-Id: I0cc8ca21fda8637b4b34f4c5a1c108d213f638f8
---
 .../pki/server/deployment/scriptlets/initialization.py       | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/base/server/python/pki/server/deployment/scriptlets/initialization.py b/base/server/python/pki/server/deployment/scriptlets/initialization.py
index 4dc4e9a..1ae77e4 100644
--- a/base/server/python/pki/server/deployment/scriptlets/initialization.py
+++ b/base/server/python/pki/server/deployment/scriptlets/initialization.py
@@ -54,13 +54,19 @@ class PkiScriptlet(pkiscriptlet.AbstractBasePkiScriptlet):
         else:
             config.pki_log.info(log.INITIALIZATION_SPAWN_1, __name__,
                                 extra=config.PKI_INDENTATION_LEVEL_1)
+
+            # Verify that the subsystem already exists for the following cases:
+            # - External CA (Step 2)
+            # - Stand-alone PKI (Step 2)
+            # - Two-step installation (Step 2)
+
             if (deployer.mdict['pki_subsystem'] == "CA" or
                 config.str2bool(deployer.mdict['pki_standalone'])) and \
-                    config.str2bool(deployer.mdict['pki_external_step_two']):
-                # verify that this External CA (Step 2), or Stand-alone PKI
-                # (Step 2) currently EXISTS for this "instance"
+                    config.str2bool(deployer.mdict['pki_external_step_two']) or \
+               config.str2bool(deployer.mdict['pki_skip_installation']):
                 deployer.instance.verify_subsystem_exists()
                 deployer.mdict['pki_skip_installation'] = "True"
+
             else:
                 # verify that this type of "subsystem" does NOT yet
                 # exist for this "instance"
-- 
1.8.3.1


From 0984d8a114b326a75b2c32cd9da2b7dee23920bb Mon Sep 17 00:00:00 2001
From: Ade Lee <alee@redhat.com>
Date: Fri, 26 May 2017 22:57:07 -0400
Subject: [PATCH 07/27] Convert CMC code to use AES

* Switched out CrytoUtil calls that use DES and replaced them
  with AES equivalents.  Removed these now unneeded methods.
* Added 16 byte constant IV for AES operations.  This must be
  replaced by a randomly generated IV.  Added TODOs where IVs
  should be replaced.
* Corrected misspellings of "enreypted" in both request fields
  and variable names
* Removed some code from null checks where the result could
  never be null.  These cases were flagged in eclipse as dead
  code.

Change-Id: Iec0c0e86fd772af8b3c9588f11a0ea1e517776fb
---
 .../src/com/netscape/cmstools/CMCRequest.java      |  18 +++-
 .../netscape/cms/profile/common/EnrollProfile.java | 111 ++++++++++++++-------
 .../cms/servlet/common/CMCOutputTemplate.java      |  40 ++++----
 .../com/netscape/cmsutil/crypto/CryptoUtil.java    |  84 ++--------------
 4 files changed, 113 insertions(+), 140 deletions(-)

diff --git a/base/java-tools/src/com/netscape/cmstools/CMCRequest.java b/base/java-tools/src/com/netscape/cmstools/CMCRequest.java
index 9c41403..8d49b20 100644
--- a/base/java-tools/src/com/netscape/cmstools/CMCRequest.java
+++ b/base/java-tools/src/com/netscape/cmstools/CMCRequest.java
@@ -52,6 +52,9 @@ import org.mozilla.jss.asn1.SET;
 import org.mozilla.jss.asn1.UTF8String;
 import org.mozilla.jss.crypto.CryptoToken;
 import org.mozilla.jss.crypto.DigestAlgorithm;
+import org.mozilla.jss.crypto.EncryptionAlgorithm;
+import org.mozilla.jss.crypto.IVParameterSpec;
+import org.mozilla.jss.crypto.KeyWrapAlgorithm;
 import org.mozilla.jss.crypto.ObjectNotFoundException;
 import org.mozilla.jss.crypto.PrivateKey;
 import org.mozilla.jss.crypto.Signature;
@@ -1718,19 +1721,30 @@ public class CMCRequest {
             CryptoToken token = CryptoUtil.getKeyStorageToken(tokenName);
             SymmetricKey symKey = CryptoUtil.unwrap(
                     token,
+                    SymmetricKey.AES,
+                    128,
                     SymmetricKey.Usage.DECRYPT,
                     privKey,
-                    recipient.getEncryptedKey().toByteArray());
+                    recipient.getEncryptedKey().toByteArray(),
+                    KeyWrapAlgorithm.RSA);
+
             if (symKey == null) {
                 System.out.println(method + "symKey returned null from CryptoUtil.unwrap(). Abort!");
                 System.exit(1);
             }
             System.out.println(method + "symKey unwrapped.");
 
+            // TODO(alee) The code below should be replaced by code that generates a random IV
+            byte[] iv = { 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 };
+            IVParameterSpec default_iv = new IVParameterSpec(iv);
+
             byte challenge[] = CryptoUtil.decryptUsingSymmetricKey(
                     token,
+                    default_iv,
                     encCI.getEncryptedContent().toByteArray(),
-                    symKey);
+                    symKey,
+                    EncryptionAlgorithm.AES_128_CBC);
+
             if (challenge == null) {
                 System.out
                         .println(method + "challenge returned null from CryptoUtil.decryptUsingSymmetricKey(). Abort!");
diff --git a/base/server/cms/src/com/netscape/cms/profile/common/EnrollProfile.java b/base/server/cms/src/com/netscape/cms/profile/common/EnrollProfile.java
index 1443a0a..12fb736 100644
--- a/base/server/cms/src/com/netscape/cms/profile/common/EnrollProfile.java
+++ b/base/server/cms/src/com/netscape/cms/profile/common/EnrollProfile.java
@@ -45,7 +45,11 @@ import org.mozilla.jss.asn1.SET;
 import org.mozilla.jss.asn1.UTF8String;
 import org.mozilla.jss.crypto.CryptoToken;
 import org.mozilla.jss.crypto.DigestAlgorithm;
+import org.mozilla.jss.crypto.EncryptionAlgorithm;
 import org.mozilla.jss.crypto.HMACAlgorithm;
+import org.mozilla.jss.crypto.IVParameterSpec;
+import org.mozilla.jss.crypto.KeyGenAlgorithm;
+import org.mozilla.jss.crypto.KeyWrapAlgorithm;
 import org.mozilla.jss.crypto.PrivateKey;
 import org.mozilla.jss.crypto.SymmetricKey;
 import org.mozilla.jss.pkcs10.CertificationRequest;
@@ -399,6 +403,10 @@ public abstract class EnrollProfile extends BasicProfile
                 String tokenName = CMS.getConfigStore().getString("cmc.token", CryptoUtil.INTERNAL_TOKEN_NAME);
                 token = CryptoUtil.getCryptoToken(tokenName);
 
+                // TODO(alee) Replace the IV definition with a call that generates a random IV of  the correct length
+                byte[] iv = { 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 };
+                IVParameterSpec ivps = new IVParameterSpec(iv);
+
                 PublicKey userPubKey = X509Key.parsePublicKey(new DerValue(req_key_data));
                 if (userPubKey == null) {
                     msg = method + "userPubKey null after X509Key.parsePublicKey";
@@ -406,37 +414,57 @@ public abstract class EnrollProfile extends BasicProfile
                     throw new EBaseException(msg);
                 }
 
-                SymmetricKey symKey = CryptoUtil.generateKey(token);
-                byte[] pop_encreyptedData = CryptoUtil.encryptUsingSymmetricKey(
-                        token, symKey, challenge);
-                if (pop_encreyptedData == null) {
-                    msg = method + "pop_encreyptedData null";
+                SymmetricKey symKey = CryptoUtil.generateKey(
+                        token,
+                        KeyGenAlgorithm.AES,
+                        128,
+                        null,
+                        true);
+
+                byte[] pop_encryptedData = CryptoUtil.encryptUsingSymmetricKey(
+                        token,
+                        symKey,
+                        challenge,
+                        EncryptionAlgorithm.AES_128_CBC,
+                        ivps);
+
+                if (pop_encryptedData == null) {
+                    msg = method + "pop_encryptedData null";
                     CMS.debug(msg);
                     throw new EBaseException(msg);
                 }
 
-                byte[] pop_sysPubEncreyptedSession = CryptoUtil.wrapUsingPublicKey(
-                        token, issuanceProtPubKey, symKey);
-                if (pop_sysPubEncreyptedSession == null) {
-                    msg = method + "pop_sysPubEncreyptedSession null";
+                byte[] pop_sysPubEncryptedSession =  CryptoUtil.wrapUsingPublicKey(
+                        token,
+                        issuanceProtPubKey,
+                        symKey,
+                        KeyWrapAlgorithm.RSA);
+
+                if (pop_sysPubEncryptedSession == null) {
+                    msg = method + "pop_sysPubEncryptedSession null";
                     CMS.debug(msg);
                     throw new EBaseException(msg);
                 }
 
-                byte[] pop_userPubEncreyptedSession = CryptoUtil.wrapUsingPublicKey(
-                        token, userPubKey, symKey);
-                if (pop_userPubEncreyptedSession == null) {
-                    msg = method + "pop_userPubEncreyptedSession null";
+
+                byte[] pop_userPubEncryptedSession = CryptoUtil.wrapUsingPublicKey(
+                        token,
+                        userPubKey,
+                        symKey,
+                        KeyWrapAlgorithm.RSA);
+
+                if (pop_userPubEncryptedSession == null) {
+                    msg = method + "pop_userPubEncryptedSession null";
                     CMS.debug(msg);
                     throw new EBaseException(msg);
                 }
                 CMS.debug(method + "POP challenge fields generated successfully...setting request extData");
 
-                req.setExtData("pop_encreyptedData", pop_encreyptedData);
+                req.setExtData("pop_encryptedData", pop_encryptedData);
 
-                req.setExtData("pop_sysPubEncreyptedSession", pop_sysPubEncreyptedSession);
+                req.setExtData("pop_sysPubEncryptedSession", pop_sysPubEncryptedSession);
 
-                req.setExtData("pop_userPubEncreyptedSession", pop_userPubEncreyptedSession);
+                req.setExtData("pop_userPubEncryptedSession", pop_userPubEncryptedSession);
 
                 // now compute and set witness
                 CMS.debug(method + "now compute and set witness");
@@ -1038,19 +1066,19 @@ public abstract class EnrollProfile extends BasicProfile
         }
 
         // now verify the POP witness
-        byte[] pop_encreyptedData = req.getExtDataInByteArray("pop_encreyptedData");
-        if (pop_encreyptedData == null) {
+        byte[] pop_encryptedData = req.getExtDataInByteArray("pop_encryptedData");
+        if (pop_encryptedData == null) {
             msg = method +
-                    "pop_encreyptedData not found in request:" +
+                    "pop_encryptedData not found in request:" +
                     reqId.toString();
             CMS.debug(msg);
             return null;
         }
 
-        byte[] pop_sysPubEncreyptedSession = req.getExtDataInByteArray("pop_sysPubEncreyptedSession");
-        if (pop_sysPubEncreyptedSession == null) {
+        byte[] pop_sysPubEncryptedSession = req.getExtDataInByteArray("pop_sysPubEncryptedSession");
+        if (pop_sysPubEncryptedSession == null) {
             msg = method +
-                    "pop_sysPubEncreyptedSession not found in request:" +
+                    "pop_sysPubEncryptedSession not found in request:" +
                     reqId.toString();
             CMS.debug(msg);
             return null;
@@ -1082,17 +1110,31 @@ public abstract class EnrollProfile extends BasicProfile
 
             SymmetricKey symKey = CryptoUtil.unwrap(
                     token,
+                    SymmetricKey.AES,
+                    128,
                     SymmetricKey.Usage.DECRYPT,
                     issuanceProtPrivKey,
-                    pop_sysPubEncreyptedSession);
+                    pop_sysPubEncryptedSession,
+                    KeyWrapAlgorithm.RSA);
+
             if (symKey == null) {
                 msg = "symKey null after CryptoUtil.unwrap returned";
                 CMS.debug(msg);
                 return null;
             }
 
+            // TODO(alee) The code below should be replaced by code that gets the IV from the Pop request
+            // This IV is supposed to be random
+            byte[] iv = { 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 };
+            IVParameterSpec default_iv = new IVParameterSpec(iv);
+
             byte[] challenge_b = CryptoUtil.decryptUsingSymmetricKey(
-                    token, pop_encreyptedData, symKey);
+                    token,
+                    default_iv,
+                    pop_encryptedData,
+                    symKey,
+                    EncryptionAlgorithm.AES_128_CBC);
+
             if (challenge_b == null) {
                 msg = method + "challenge_b null after decryptUsingSymmetricKey returned";
                 CMS.debug(msg);
@@ -1596,23 +1638,16 @@ public abstract class EnrollProfile extends BasicProfile
                     witness_bytes,
                     hashAlg, macAlg);
 
-            String authMgrID =
-                    (String) sessionContext.get(SessionContext.AUTH_MANAGER_ID);
             String auditSubjectID = null;
 
             if (verified) {
-                // update auditSubjectID
-                if (sessionContext != null) {
-                    auditSubjectID = (String)
-                            sessionContext.get(SessionContext.USER_ID);
-                    CMS.debug(method + "current auditSubjectID was:"+ auditSubjectID);
-                    CMS.debug(method + "identity verified. Updating auditSubjectID");
-                    CMS.debug(method + "updated auditSubjectID is:"+ ident_string);
-                    auditSubjectID = ident_string;
-                    sessionContext.put(SessionContext.USER_ID, auditSubjectID);
-                } else { //very unlikely
-                    CMS.debug(method + "sessionContext null; cannot update auditSubjectID");
-                }
+                auditSubjectID = (String)
+                        sessionContext.get(SessionContext.USER_ID);
+                CMS.debug(method + "current auditSubjectID was:"+ auditSubjectID);
+                CMS.debug(method + "identity verified. Updating auditSubjectID");
+                CMS.debug(method + "updated auditSubjectID is:"+ ident_string);
+                auditSubjectID = ident_string;
+                sessionContext.put(SessionContext.USER_ID, auditSubjectID);
 
                 auditMessage = CMS.getLogMessage(
                         AuditEvent.CMC_PROOF_OF_IDENTIFICATION,
diff --git a/base/server/cms/src/com/netscape/cms/servlet/common/CMCOutputTemplate.java b/base/server/cms/src/com/netscape/cms/servlet/common/CMCOutputTemplate.java
index c130a1e..8e47298 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/common/CMCOutputTemplate.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/common/CMCOutputTemplate.java
@@ -43,6 +43,7 @@ import org.mozilla.jss.asn1.SEQUENCE;
 import org.mozilla.jss.asn1.SET;
 import org.mozilla.jss.asn1.UTF8String;
 import org.mozilla.jss.crypto.DigestAlgorithm;
+import org.mozilla.jss.crypto.EncryptionAlgorithm;
 import org.mozilla.jss.crypto.SignatureAlgorithm;
 import org.mozilla.jss.pkcs11.PK11PubKey;
 import org.mozilla.jss.pkix.cert.Certificate;
@@ -433,10 +434,7 @@ public class CMCOutputTemplate {
 
             ResponseBody respBody = new ResponseBody(controlSeq,
                     cmsSeq, otherMsgSeq);
-            if (respBody != null)
-                CMS.debug(method + " after new ResponseBody, respBody not null");
-            else
-                CMS.debug(method + " after new ResponseBody, respBody null");
+            CMS.debug(method + " after new ResponseBody, respBody not null");
 
             ContentInfo contentInfo = getContentInfo(respBody, certs);
             ByteArrayOutputStream fos = new ByteArrayOutputStream();
@@ -489,30 +487,25 @@ public class CMCOutputTemplate {
         CMS.debug(method + "popChallengeRequired true");
 
         byte[] cmc_msg = req.getExtDataInByteArray(IEnrollProfile.CTX_CERT_REQUEST);
-        byte[] pop_encreyptedData = req.getExtDataInByteArray("pop_encreyptedData");
+        byte[] pop_encryptedData = req.getExtDataInByteArray("pop_encryptedData");
         //don't need this for encryptedPOP, but need to check for existence anyway
-        byte[] pop_sysPubEncreyptedSession = req.getExtDataInByteArray("pop_sysPubEncreyptedSession");
-        byte[] pop_userPubEncreyptedSession = req.getExtDataInByteArray("pop_userPubEncreyptedSession");
-        if ((pop_encreyptedData != null) &&
-                (pop_sysPubEncreyptedSession != null) &&
-                (pop_userPubEncreyptedSession != null)) {
+        byte[] pop_sysPubEncryptedSession = req.getExtDataInByteArray("pop_sysPubEncryptedSession");
+        byte[] pop_userPubEncryptedSession = req.getExtDataInByteArray("pop_userPubEncryptedSession");
+        if ((pop_encryptedData != null) &&
+                (pop_sysPubEncryptedSession != null) &&
+                (pop_userPubEncryptedSession != null)) {
             // generate encryptedPOP here
             // algs are hard-coded for now
 
             try {
                 EnvelopedData envData = CryptoUtil.createEnvelopedData(
-                        pop_encreyptedData,
-                        pop_userPubEncreyptedSession);
+                        pop_encryptedData,
+                        pop_userPubEncryptedSession);
                 if (envData == null) {
                     msg = "envData null returned by createEnvelopedData";
                     throw new EBaseException(method + msg);
                 }
                 ContentInfo ci = new ContentInfo(envData);
-                if (ci == null) {
-                    msg = "ci null from new ContentInfo";
-                    CMS.debug(msg);
-                    throw new EBaseException(method + msg);
-                }
                 CMS.debug(method + "now we can compose encryptedPOP");
 
                 TaggedRequest.Template tReqTemplate = new TaggedRequest.Template();
@@ -524,17 +517,18 @@ public class CMCOutputTemplate {
                     throw new EBaseException(method + msg);
                 }
 
+                // TODO(alee) The code below should be replaced by code that generates a random IV
+                byte[] default_iv = { 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 };
+
+                OBJECT_IDENTIFIER oid = EncryptionAlgorithm.AES_128_CBC.toOID();
+                AlgorithmIdentifier aid = new AlgorithmIdentifier(oid, new OCTET_STRING(default_iv));
+
                 encPop = new EncryptedPOP(
                         tReq,
                         ci,
-                        CryptoUtil.getDefaultEncAlg(),
+                        aid,
                         CryptoUtil.getDefaultHashAlg(),
                         new OCTET_STRING(req.getExtDataInByteArray("pop_witness")));
-                if (encPop == null) {
-                    msg = "encPop null returned by new EncryptedPOP";
-                    CMS.debug(msg);
-                    throw new EBaseException(method + msg);
-                }
 
             } catch (Exception e) {
                 CMS.debug(method + " excepton:" + e);
diff --git a/base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java b/base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java
index 8b8c443..95b8f81 100644
--- a/base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java
+++ b/base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java
@@ -2572,15 +2572,15 @@ public class CryptoUtil {
             throw new Exception(method + msg);
         }
 
+        // TODO(alee) Replace the below with a random IV that is likely passed in
+        byte[] default_iv = { 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 };
+        OBJECT_IDENTIFIER oid = EncryptionAlgorithm.AES_128_CBC.toOID();
+        AlgorithmIdentifier aid = new AlgorithmIdentifier(oid, new OCTET_STRING(default_iv));
+
         EncryptedContentInfo encCInfo = new EncryptedContentInfo(
                 ContentInfo.DATA,
-                getDefaultEncAlg(),
+                aid,
                 new OCTET_STRING(encContent));
-        if (encCInfo == null) {
-            msg = method + "encCInfo null from new EncryptedContentInfo";
-            System.out.println(msg);
-            throw new Exception(method + msg);
-        }
 
         Name name = new Name();
         name.addCommonName("unUsedIssuerName"); //unused; okay for cmc EncryptedPOP
@@ -2589,11 +2589,6 @@ public class CryptoUtil {
                 new IssuerAndSerialNumber(name, new INTEGER(0)), //unUsed
                 new AlgorithmIdentifier(RSA_ENCRYPTION, new NULL()),
                 new OCTET_STRING(encSymKey));
-        if (recipient == null) {
-            msg = method + "recipient null from new RecipientInfo";
-            System.out.println(msg);
-            throw new Exception(method + msg);
-        }
 
         SET recipients = new SET();
         recipients.addElement(recipient);
@@ -2615,77 +2610,14 @@ public class CryptoUtil {
      * the defaults
      */
 
-    private static byte default_iv[] = { 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 };
-    private static IVParameterSpec default_IV = new IVParameterSpec(default_iv);
-
-    // this generates a temporary 128 bit AES symkey with defaults
-    public static SymmetricKey generateKey(CryptoToken token) throws Exception {
-        return generateKey(token,
-//TODO:                KeyGenAlgorithm.AES, 128,
-                KeyGenAlgorithm.DES3, 128 /*unused*/,
-                null, true);
-    }
-
-    // decryptUsingSymmetricKey with default algorithms
-    public static byte[] decryptUsingSymmetricKey(CryptoToken token, byte[] encryptedData, SymmetricKey wrappingKey) throws Exception {
-        return decryptUsingSymmetricKey(token, default_IV, encryptedData,
-                wrappingKey,
-                EncryptionAlgorithm.DES3_CBC_PAD);
-//TODO:                EncryptionAlgorithm.AES_128_CBC);
-    }
-
-    // encryptUsingSymmetricKey with default algorithms
-    public static byte[] encryptUsingSymmetricKey(CryptoToken token, SymmetricKey wrappingKey, byte[] data) throws Exception {
-        return encryptUsingSymmetricKey(
-                token,
-                wrappingKey,
-                data,
-                EncryptionAlgorithm.DES3_CBC_PAD,
-//TODO:                EncryptionAlgorithm.AES_128_CBC,
-                default_IV);
-    }
-
-    // wrapUsingPublicKey using default algorithm
-    public static byte[] wrapUsingPublicKey(CryptoToken token, PublicKey wrappingKey, SymmetricKey data) throws Exception {
-        return wrapUsingPublicKey(token, wrappingKey, data, KeyWrapAlgorithm.RSA);
-    }
-
-    // unwrap sym key using default algorithms
-    public static SymmetricKey unwrap(CryptoToken token, SymmetricKey.Usage usage, PrivateKey wrappingKey, byte[] wrappedSymKey) throws Exception {
-        return unwrap(
-               token,
-//TODO:               SymmetricKey.AES,
-               SymmetricKey.DES3,
-               0,
-               usage,
-               wrappingKey,
-               wrappedSymKey,
-               getDefaultKeyWrapAlg());
-    }
-
-    public static AlgorithmIdentifier getDefaultEncAlg()
-           throws Exception {
-        OBJECT_IDENTIFIER oid =
-                EncryptionAlgorithm.DES3_CBC.toOID();
-//TODO:                EncryptionAlgorithm.AES_128_CBC.toOID();
-
-        AlgorithmIdentifier aid =
-                new AlgorithmIdentifier(oid, new OCTET_STRING(default_iv));
-        return aid;
-    }
-
     public static String getDefaultHashAlgName() {
         return ("SHA-256");
     }
 
-    public static KeyWrapAlgorithm getDefaultKeyWrapAlg() {
-        return KeyWrapAlgorithm.RSA;
-    }
-
     public static AlgorithmIdentifier getDefaultHashAlg()
            throws Exception {
         AlgorithmIdentifier hashAlg;
-            hashAlg = new AlgorithmIdentifier(CryptoUtil.getHashAlgorithmOID("SHA-256"));
+            hashAlg = new AlgorithmIdentifier(CryptoUtil.getHashAlgorithmOID(getDefaultHashAlgName()));
         return hashAlg;
     }
 
@@ -2768,8 +2700,6 @@ public class CryptoUtil {
      */
     public static String getNameFromHashAlgorithm(AlgorithmIdentifier ai)
            throws NoSuchAlgorithmException {
-        OBJECT_IDENTIFIER oid = null;
-
         System.out.println("CryptoUtil: getNameFromHashAlgorithm: " + ai.getOID().toString());
         if (ai != null) {
             if (ai.getOID().equals((DigestAlgorithm.SHA256).toOID())) {
-- 
1.8.3.1


From 772e05e746570c13afeb60516c07a3fb95ca3e78 Mon Sep 17 00:00:00 2001
From: "Endi S. Dewata" <edewata@redhat.com>
Date: Thu, 1 Jun 2017 23:38:04 +0200
Subject: [PATCH 10/27] Removed superfluous deployment configuration backup.

The pkispawn has been modified to generate a temporary backup
file (instead of permanent and timestamped backup files) of the
deployment configuration file before normalizing its content.
The temporary backup will be removed automatically when the
normalization is complete.

https://pagure.io/dogtagpki/issue/2674

Change-Id: Ia541e23314acc120954fa574d1f6f885961c8047
---
 base/server/sbin/pkispawn | 7 +------
 1 file changed, 1 insertion(+), 6 deletions(-)

diff --git a/base/server/sbin/pkispawn b/base/server/sbin/pkispawn
index 742f579..1aa7079 100755
--- a/base/server/sbin/pkispawn
+++ b/base/server/sbin/pkispawn
@@ -34,8 +34,6 @@ try:
     import ldap
     import os
     import requests
-    import time
-    from time import strftime as date
     import traceback
     import pki
     from pki.server.deployment import pkiconfig as config
@@ -610,12 +608,9 @@ def main(argv):
 
 
 def sanitize_user_deployment_cfg(cfg):
-    # Generate a timestamp
-    ticks = time.time()
-    timestamp = date('%Y%m%d%H%M%S', time.localtime(ticks))
 
     # Correct any section headings in the user's configuration file
-    for line in fileinput.FileInput(cfg, inplace=1, backup='.' + timestamp):
+    for line in fileinput.FileInput(cfg, inplace=1):
         # Remove extraneous leading and trailing whitespace from all lines
         line = line.strip()
         # Normalize section headings to match '/etc/pki/default.cfg'
-- 
1.8.3.1


From f7b6305396581f5916498cc4ea8247596bf39aaf Mon Sep 17 00:00:00 2001
From: Matthew Harmsen <mharmsen@redhat.com>
Date: Fri, 2 Jun 2017 02:10:02 +0200
Subject: [PATCH 11/27] Fixed pylint issues

- https://pagure.io/dogtagpki/issue/2713 - Build failure due to Pylint issues
---
 base/common/python/pki/cli/pkcs12.py           |  4 ++--
 base/common/python/pki/encoder.py              | 12 ++++++------
 base/server/python/pki/server/cli/audit.py     |  8 ++++----
 base/server/python/pki/server/cli/ca.py        | 16 ++++++++--------
 base/server/python/pki/server/cli/db.py        |  8 ++++----
 base/server/python/pki/server/cli/kra.py       | 20 ++++++++++----------
 base/server/python/pki/server/cli/ocsp.py      |  4 ++--
 base/server/python/pki/server/cli/subsystem.py |  4 ++--
 base/server/python/pki/server/cli/tks.py       |  4 ++--
 base/server/python/pki/server/cli/tps.py       | 20 ++++++++++----------
 base/server/python/pki/server/upgrade.py       |  3 ---
 11 files changed, 50 insertions(+), 53 deletions(-)

diff --git a/base/common/python/pki/cli/pkcs12.py b/base/common/python/pki/cli/pkcs12.py
index 8934d33..6b99fcf 100644
--- a/base/common/python/pki/cli/pkcs12.py
+++ b/base/common/python/pki/cli/pkcs12.py
@@ -62,10 +62,10 @@ class PKCS12ImportCLI(pki.cli.CLI):
         print('      --help                         Show help message.')
         print()
 
-    def execute(self, args):
+    def execute(self, argv):
 
         try:
-            opts, _ = getopt.gnu_getopt(args, 'v', [
+            opts, _ = getopt.gnu_getopt(argv, 'v', [
                 'pkcs12-file=', 'pkcs12-password=', 'pkcs12-password-file=',
                 'no-trust-flags', 'no-user-certs', 'no-ca-certs', 'overwrite',
                 'verbose', 'debug', 'help'])
diff --git a/base/common/python/pki/encoder.py b/base/common/python/pki/encoder.py
index 8485ab8..d3298bc 100644
--- a/base/common/python/pki/encoder.py
+++ b/base/common/python/pki/encoder.py
@@ -82,14 +82,14 @@ class CustomTypeEncoder(json.JSONEncoder):
     """
     # pylint: disable=E0202
 
-    def default(self, obj):
+    def default(self, o):
         for k, v in iteritems(TYPES):
-            if isinstance(obj, v):
-                return {k: obj.__dict__}
+            if isinstance(o, v):
+                return {k: o.__dict__}
         for t in itervalues(NOTYPES):
-            if isinstance(obj, t):
-                return self.attr_name_conversion(obj.__dict__, type(obj))
-        return json.JSONEncoder.default(self, obj)
+            if isinstance(o, t):
+                return self.attr_name_conversion(o.__dict__, type(o))
+        return json.JSONEncoder.default(self, o)
 
     @staticmethod
     def attr_name_conversion(attr_dict, object_class):
diff --git a/base/server/python/pki/server/cli/audit.py b/base/server/python/pki/server/cli/audit.py
index 0833ca8..a19ca8c 100644
--- a/base/server/python/pki/server/cli/audit.py
+++ b/base/server/python/pki/server/cli/audit.py
@@ -56,10 +56,10 @@ class AuditFileFindCLI(pki.cli.CLI):
         print('      --help                         Show help message.')
         print()
 
-    def execute(self, args):
+    def execute(self, argv):
 
         try:
-            opts, _ = getopt.gnu_getopt(args, 'i:v', [
+            opts, _ = getopt.gnu_getopt(argv, 'i:v', [
                 'instance=',
                 'verbose', 'help'])
 
@@ -129,10 +129,10 @@ class AuditFileVerifyCLI(pki.cli.CLI):
         print('      --help                         Show help message.')
         print()
 
-    def execute(self, args):
+    def execute(self, argv):
 
         try:
-            opts, _ = getopt.gnu_getopt(args, 'i:v', [
+            opts, _ = getopt.gnu_getopt(argv, 'i:v', [
                 'instance=',
                 'verbose', 'help'])
 
diff --git a/base/server/python/pki/server/cli/ca.py b/base/server/python/pki/server/cli/ca.py
index 550e511..48c7dba 100644
--- a/base/server/python/pki/server/cli/ca.py
+++ b/base/server/python/pki/server/cli/ca.py
@@ -78,10 +78,10 @@ class CACertChainExportCLI(pki.cli.CLI):
         print('      --help                         Show help message.')
         print()
 
-    def execute(self, args):
+    def execute(self, argv):
 
         try:
-            opts, _ = getopt.gnu_getopt(args, 'i:v', [
+            opts, _ = getopt.gnu_getopt(argv, 'i:v', [
                 'instance=', 'pkcs12-file=', 'pkcs12-password=', 'pkcs12-password-file=',
                 'verbose', 'help'])
 
@@ -190,10 +190,10 @@ class CACertRequestFindCLI(pki.cli.CLI):
         print('      --help                      Show help message.')
         print()
 
-    def execute(self, args):
+    def execute(self, argv):
 
         try:
-            opts, _ = getopt.gnu_getopt(args, 'i:v', [
+            opts, _ = getopt.gnu_getopt(argv, 'i:v', [
                 'instance=', 'cert=', 'cert-file=',
                 'verbose', 'help'])
 
@@ -268,10 +268,10 @@ class CACertRequestShowCLI(pki.cli.CLI):
         print('      --help                      Show help message.')
         print()
 
-    def execute(self, args):
+    def execute(self, argv):
 
         try:
-            opts, args = getopt.gnu_getopt(args, 'i:v', [
+            opts, args = getopt.gnu_getopt(argv, 'i:v', [
                 'instance=', 'output-file=',
                 'verbose', 'help'])
 
@@ -356,10 +356,10 @@ class CAClonePrepareCLI(pki.cli.CLI):
         print('      --help                         Show help message.')
         print()
 
-    def execute(self, args):
+    def execute(self, argv):
 
         try:
-            opts, _ = getopt.gnu_getopt(args, 'i:v', [
+            opts, _ = getopt.gnu_getopt(argv, 'i:v', [
                 'instance=', 'pkcs12-file=', 'pkcs12-password=', 'pkcs12-password-file=',
                 'verbose', 'help'])
 
diff --git a/base/server/python/pki/server/cli/db.py b/base/server/python/pki/server/cli/db.py
index 17b1a2f..3df911c 100644
--- a/base/server/python/pki/server/cli/db.py
+++ b/base/server/python/pki/server/cli/db.py
@@ -58,10 +58,10 @@ class DBSchemaUpgrade(pki.cli.CLI):
         print('      --help                         Show help message.')
         print()
 
-    def execute(self, args):
+    def execute(self, argv):
         try:
             opts, _ = getopt.gnu_getopt(
-                args, 'i:D:w:v', ['instance=', 'bind-dn=', 'bind-password=',
+                argv, 'i:D:w:v', ['instance=', 'bind-dn=', 'bind-password=',
                                   'verbose', 'help'])
 
         except getopt.GetoptError as e:
@@ -150,10 +150,10 @@ class DBUpgrade(pki.cli.CLI):
         print('      --help                         Show help message.')
         print()
 
-    def execute(self, args):
+    def execute(self, argv):
         try:
             opts, _ = getopt.gnu_getopt(
-                args, 'i:v', ['instance=', 'verbose', 'help'])
+                argv, 'i:v', ['instance=', 'verbose', 'help'])
 
         except getopt.GetoptError as e:
             print('ERROR: ' + str(e))
diff --git a/base/server/python/pki/server/cli/kra.py b/base/server/python/pki/server/cli/kra.py
index 3724014..6c1ade9 100644
--- a/base/server/python/pki/server/cli/kra.py
+++ b/base/server/python/pki/server/cli/kra.py
@@ -81,10 +81,10 @@ class KRAClonePrepareCLI(pki.cli.CLI):
         print('      --help                         Show help message.')
         print()
 
-    def execute(self, args):
+    def execute(self, argv):
 
         try:
-            opts, _ = getopt.gnu_getopt(args, 'i:v', [
+            opts, _ = getopt.gnu_getopt(argv, 'i:v', [
                 'instance=', 'pkcs12-file=', 'pkcs12-password=', 'pkcs12-password-file=',
                 'verbose', 'help'])
 
@@ -203,10 +203,10 @@ class KRADBVLVFindCLI(pki.cli.CLI):
         print('      --help                         Show help message.')
         print()
 
-    def execute(self, args):
+    def execute(self, argv):
         try:
             opts, _ = getopt.gnu_getopt(
-                args,
+                argv,
                 'i:D:w:x:g:v',
                 ['instance=', 'bind-dn=', 'bind-password=', 'generate-ldif=',
                  'verbose', 'help']
@@ -315,10 +315,10 @@ class KRADBVLVAddCLI(pki.cli.CLI):
         print('      --help                         Show help message.')
         print()
 
-    def execute(self, args):
+    def execute(self, argv):
         try:
             opts, _ = getopt.gnu_getopt(
-                args,
+                argv,
                 'i:D:w:x:g:v',
                 ['instance=', 'bind-dn=', 'bind-password=', 'generate-ldif=',
                  'verbose', 'help']
@@ -421,10 +421,10 @@ class KRADBVLVDeleteCLI(pki.cli.CLI):
         print('      --help                         Show help message.')
         print()
 
-    def execute(self, args):
+    def execute(self, argv):
         try:
             opts, _ = getopt.gnu_getopt(
-                args,
+                argv,
                 'i:D:w:x:g:v',
                 ['instance=', 'bind-dn=', 'bind-password=', 'generate-ldif=',
                  'verbose', 'help']
@@ -543,10 +543,10 @@ class KRADBVLVReindexCLI(pki.cli.CLI):
         print('      --help                         Show help message.')
         print()
 
-    def execute(self, args):
+    def execute(self, argv):
         try:
             opts, _ = getopt.gnu_getopt(
-                args,
+                argv,
                 'i:D:w:x:g:v',
                 ['instance=', 'bind-dn=', 'bind-password=', 'generate-ldif=',
                  'verbose', 'help']
diff --git a/base/server/python/pki/server/cli/ocsp.py b/base/server/python/pki/server/cli/ocsp.py
index 3e9b6aa..b3e4e45 100644
--- a/base/server/python/pki/server/cli/ocsp.py
+++ b/base/server/python/pki/server/cli/ocsp.py
@@ -67,10 +67,10 @@ class OCSPClonePrepareCLI(pki.cli.CLI):
         print('      --help                         Show help message.')
         print()
 
-    def execute(self, args):
+    def execute(self, argv):
 
         try:
-            opts, _ = getopt.gnu_getopt(args, 'i:v', [
+            opts, _ = getopt.gnu_getopt(argv, 'i:v', [
                 'instance=', 'pkcs12-file=', 'pkcs12-password=', 'pkcs12-password-file=',
                 'verbose', 'help'])
 
diff --git a/base/server/python/pki/server/cli/subsystem.py b/base/server/python/pki/server/cli/subsystem.py
index 8395bd2..10af8ca 100644
--- a/base/server/python/pki/server/cli/subsystem.py
+++ b/base/server/python/pki/server/cli/subsystem.py
@@ -66,10 +66,10 @@ class SubsystemFindCLI(pki.cli.CLI):
         print('      --help                      Show help message.')
         print()
 
-    def execute(self, args):
+    def execute(self, argv):
 
         try:
-            opts, _ = getopt.gnu_getopt(args, 'i:v', [
+            opts, _ = getopt.gnu_getopt(argv, 'i:v', [
                 'instance=',
                 'verbose', 'help'])
 
diff --git a/base/server/python/pki/server/cli/tks.py b/base/server/python/pki/server/cli/tks.py
index 0e6a998..0bfaca1 100644
--- a/base/server/python/pki/server/cli/tks.py
+++ b/base/server/python/pki/server/cli/tks.py
@@ -67,10 +67,10 @@ class TKSClonePrepareCLI(pki.cli.CLI):
         print('      --help                         Show help message.')
         print()
 
-    def execute(self, args):
+    def execute(self, argv):
 
         try:
-            opts, _ = getopt.gnu_getopt(args, 'i:v', [
+            opts, _ = getopt.gnu_getopt(argv, 'i:v', [
                 'instance=', 'pkcs12-file=', 'pkcs12-password=', 'pkcs12-password-file=',
                 'verbose', 'help'])
 
diff --git a/base/server/python/pki/server/cli/tps.py b/base/server/python/pki/server/cli/tps.py
index 03df8de..a34bbd9 100644
--- a/base/server/python/pki/server/cli/tps.py
+++ b/base/server/python/pki/server/cli/tps.py
@@ -76,10 +76,10 @@ class TPSClonePrepareCLI(pki.cli.CLI):
         print('      --help                         Show help message.')
         print()
 
-    def execute(self, args):
+    def execute(self, argv):
 
         try:
-            opts, _ = getopt.gnu_getopt(args, 'i:v', [
+            opts, _ = getopt.gnu_getopt(argv, 'i:v', [
                 'instance=', 'pkcs12-file=', 'pkcs12-password=', 'pkcs12-password-file=',
                 'verbose', 'help'])
 
@@ -195,10 +195,10 @@ class TPSDBVLVFindCLI(pki.cli.CLI):
         print('      --help                         Show help message.')
         print()
 
-    def execute(self, args):
+    def execute(self, argv):
         try:
             opts, _ = getopt.gnu_getopt(
-                args,
+                argv,
                 'i:D:w:x:g:v',
                 ['instance=', 'bind-dn=', 'bind-password=', 'generate-ldif=',
                  'verbose', 'help']
@@ -306,10 +306,10 @@ class TPSDBVLVAddCLI(pki.cli.CLI):
         print('      --help                         Show help message.')
         print()
 
-    def execute(self, args):
+    def execute(self, argv):
         try:
             opts, _ = getopt.gnu_getopt(
-                args,
+                argv,
                 'i:D:w:x:g:v',
                 ['instance=', 'bind-dn=', 'bind-password=', 'generate-ldif=',
                  'verbose', 'help']
@@ -419,10 +419,10 @@ class TPSDBVLVDeleteCLI(pki.cli.CLI):
         print('      --help                         Show help message.')
         print()
 
-    def execute(self, args):
+    def execute(self, argv):
         try:
             opts, _ = getopt.gnu_getopt(
-                args,
+                argv,
                 'i:D:w:x:g:v',
                 ['instance=', 'bind-dn=', 'bind-password=', 'generate-ldif=',
                  'verbose', 'help']
@@ -554,10 +554,10 @@ class TPSDBVLVReindexCLI(pki.cli.CLI):
         print('      --help                         Show help message.')
         print()
 
-    def execute(self, args):
+    def execute(self, argv):
         try:
             opts, _ = getopt.gnu_getopt(
-                args,
+                argv,
                 'i:D:w:x:g:v',
                 ['instance=', 'bind-dn=', 'bind-password=', 'generate-ldif=',
                  'verbose', 'help']
diff --git a/base/server/python/pki/server/upgrade.py b/base/server/python/pki/server/upgrade.py
index 2c72e48..926c683 100644
--- a/base/server/python/pki/server/upgrade.py
+++ b/base/server/python/pki/server/upgrade.py
@@ -38,9 +38,6 @@ SUBSYSTEM_TRACKER = '%s/CS.cfg'
 
 class PKIServerUpgradeScriptlet(pki.upgrade.PKIUpgradeScriptlet):
 
-    def __init__(self):
-        super(PKIServerUpgradeScriptlet, self).__init__()
-
     def get_backup_dir(self):
         return BACKUP_DIR + '/' + str(self.version) + '/' + str(self.index)
 
-- 
1.8.3.1


From b3d851b864dc986a9af8ffcb1962f8e7b4de3114 Mon Sep 17 00:00:00 2001
From: "Endi S. Dewata" <edewata@redhat.com>
Date: Thu, 1 Jun 2017 04:54:05 +0200
Subject: [PATCH 12/27] Added upgrade script for keepAliveTimeout.

An upgrade script has been added to set the keepAliveTimeout
attribute for the Secure connector in the server.xml.

https://pagure.io/dogtagpki/issue/2687

Change-Id: Ia61ed49d0ffc26d4bb44738c71fc663bde37fb1d
---
 base/common/upgrade/10.4.1/.gitignore              |  4 ++
 base/common/upgrade/10.4.2/.gitignore              |  4 ++
 base/common/upgrade/10.4.3/.gitignore              |  4 ++
 base/common/upgrade/10.4.4/.gitignore              |  4 ++
 base/common/upgrade/10.4.5/.gitignore              |  4 ++
 base/common/upgrade/10.4.6/.gitignore              |  4 ++
 base/server/upgrade/10.4.3/.gitignore              |  4 ++
 base/server/upgrade/10.4.4/.gitignore              |  4 ++
 base/server/upgrade/10.4.5/.gitignore              |  4 ++
 .../upgrade/10.4.6/01-UpdateKeepAliveTimeout       | 59 ++++++++++++++++++++++
 10 files changed, 95 insertions(+)
 create mode 100644 base/common/upgrade/10.4.1/.gitignore
 create mode 100644 base/common/upgrade/10.4.2/.gitignore
 create mode 100644 base/common/upgrade/10.4.3/.gitignore
 create mode 100644 base/common/upgrade/10.4.4/.gitignore
 create mode 100644 base/common/upgrade/10.4.5/.gitignore
 create mode 100644 base/common/upgrade/10.4.6/.gitignore
 create mode 100644 base/server/upgrade/10.4.3/.gitignore
 create mode 100644 base/server/upgrade/10.4.4/.gitignore
 create mode 100644 base/server/upgrade/10.4.5/.gitignore
 create mode 100755 base/server/upgrade/10.4.6/01-UpdateKeepAliveTimeout

diff --git a/base/common/upgrade/10.4.1/.gitignore b/base/common/upgrade/10.4.1/.gitignore
new file mode 100644
index 0000000..5e7d273
--- /dev/null
+++ b/base/common/upgrade/10.4.1/.gitignore
@@ -0,0 +1,4 @@
+# Ignore everything in this directory
+*
+# Except this file
+!.gitignore
diff --git a/base/common/upgrade/10.4.2/.gitignore b/base/common/upgrade/10.4.2/.gitignore
new file mode 100644
index 0000000..5e7d273
--- /dev/null
+++ b/base/common/upgrade/10.4.2/.gitignore
@@ -0,0 +1,4 @@
+# Ignore everything in this directory
+*
+# Except this file
+!.gitignore
diff --git a/base/common/upgrade/10.4.3/.gitignore b/base/common/upgrade/10.4.3/.gitignore
new file mode 100644
index 0000000..5e7d273
--- /dev/null
+++ b/base/common/upgrade/10.4.3/.gitignore
@@ -0,0 +1,4 @@
+# Ignore everything in this directory
+*
+# Except this file
+!.gitignore
diff --git a/base/common/upgrade/10.4.4/.gitignore b/base/common/upgrade/10.4.4/.gitignore
new file mode 100644
index 0000000..5e7d273
--- /dev/null
+++ b/base/common/upgrade/10.4.4/.gitignore
@@ -0,0 +1,4 @@
+# Ignore everything in this directory
+*
+# Except this file
+!.gitignore
diff --git a/base/common/upgrade/10.4.5/.gitignore b/base/common/upgrade/10.4.5/.gitignore
new file mode 100644
index 0000000..5e7d273
--- /dev/null
+++ b/base/common/upgrade/10.4.5/.gitignore
@@ -0,0 +1,4 @@
+# Ignore everything in this directory
+*
+# Except this file
+!.gitignore
diff --git a/base/common/upgrade/10.4.6/.gitignore b/base/common/upgrade/10.4.6/.gitignore
new file mode 100644
index 0000000..5e7d273
--- /dev/null
+++ b/base/common/upgrade/10.4.6/.gitignore
@@ -0,0 +1,4 @@
+# Ignore everything in this directory
+*
+# Except this file
+!.gitignore
diff --git a/base/server/upgrade/10.4.3/.gitignore b/base/server/upgrade/10.4.3/.gitignore
new file mode 100644
index 0000000..5e7d273
--- /dev/null
+++ b/base/server/upgrade/10.4.3/.gitignore
@@ -0,0 +1,4 @@
+# Ignore everything in this directory
+*
+# Except this file
+!.gitignore
diff --git a/base/server/upgrade/10.4.4/.gitignore b/base/server/upgrade/10.4.4/.gitignore
new file mode 100644
index 0000000..5e7d273
--- /dev/null
+++ b/base/server/upgrade/10.4.4/.gitignore
@@ -0,0 +1,4 @@
+# Ignore everything in this directory
+*
+# Except this file
+!.gitignore
diff --git a/base/server/upgrade/10.4.5/.gitignore b/base/server/upgrade/10.4.5/.gitignore
new file mode 100644
index 0000000..5e7d273
--- /dev/null
+++ b/base/server/upgrade/10.4.5/.gitignore
@@ -0,0 +1,4 @@
+# Ignore everything in this directory
+*
+# Except this file
+!.gitignore
diff --git a/base/server/upgrade/10.4.6/01-UpdateKeepAliveTimeout b/base/server/upgrade/10.4.6/01-UpdateKeepAliveTimeout
new file mode 100755
index 0000000..31c4d1b
--- /dev/null
+++ b/base/server/upgrade/10.4.6/01-UpdateKeepAliveTimeout
@@ -0,0 +1,59 @@
+#!/usr/bin/python
+# Authors:
+#     Endi S. Dewata <edewata@redhat.com>
+#
+# 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) 2017 Red Hat, Inc.
+# All rights reserved.
+#
+
+from __future__ import absolute_import
+import os
+from lxml import etree
+
+import pki
+
+
+class UpdateKeepAliveTimeout(
+        pki.server.upgrade.PKIServerUpgradeScriptlet):
+
+    def __init__(self):
+        super(UpdateKeepAliveTimeout, self).__init__()
+        self.message = 'Update keepAliveTimeout parameter'
+
+        self.parser = etree.XMLParser(remove_blank_text=True)
+
+    def upgrade_instance(self, instance):
+
+        server_xml = os.path.join(instance.conf_dir, 'server.xml')
+        self.backup(server_xml)
+
+        document = etree.parse(server_xml, self.parser)
+
+        server = document.getroot()
+        connectors = server.findall('.//Connector')
+
+        for connector in connectors:
+
+            # find the Secure connector
+            name = connector.get('name')
+            if name != 'Secure':
+                continue
+
+            # set the keepAliveTimeout parameter to 5 minutes
+            connector.set('keepAliveTimeout', '300000')
+
+        with open(server_xml, 'wb') as f:
+            document.write(f, pretty_print=True, encoding='utf-8')
-- 
1.8.3.1


From 03235ab51d102ba722e71adf00d2f721c77cd222 Mon Sep 17 00:00:00 2001
From: "Endi S. Dewata" <edewata@redhat.com>
Date: Thu, 1 Jun 2017 21:02:41 +0200
Subject: [PATCH 15/27] Fixed random password generator.

The equal sign is no longer used to generate random password
since it's already used as token name and password delimiter in
password.conf.

https://pagure.io/dogtagpki/issue/2556

Change-Id: Id59f9aae4d01958f69c305e7d5cda44ce5c81c84
---
 base/common/python/pki/__init__.py | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/base/common/python/pki/__init__.py b/base/common/python/pki/__init__.py
index 1fc5385..0478b32 100644
--- a/base/common/python/pki/__init__.py
+++ b/base/common/python/pki/__init__.py
@@ -45,6 +45,11 @@ PACKAGE_VERSION = SHARE_DIR + '/VERSION'
 CERT_HEADER = "-----BEGIN CERTIFICATE-----"
 CERT_FOOTER = "-----END CERTIFICATE-----"
 
+# Valid punctuation characters for random password.
+# This is identical to string.punctuation minus the equal
+# sign since it's used as delimiter in password.conf.
+PUNCTUATIONS = '!"#$%&\'()*+,-./:;<>?@[\\]^_`{|}~'
+
 
 def read_text(message,
               options=None, default=None, delimiter=':',
@@ -139,7 +144,7 @@ def generate_password():
      * digits (string.digits)
      * ASCII lowercase letters (string.ascii_lowercase)
      * ASCII uppercase letters (string.ascii_uppercase)
-     * ASCII non-alphanumeric characters (string.punctuation)
+     * ASCII non-alphanumeric characters (PUNCTUATIONS)
      * non-ASCII characters
 
     If an ASCII uppercase letter is the first character of the password,
@@ -159,7 +164,7 @@ def generate_password():
     valid_chars = string.digits +\
         string.ascii_lowercase +\
         string.ascii_uppercase +\
-        string.punctuation
+        PUNCTUATIONS
 
     chars = []
 
@@ -168,7 +173,7 @@ def generate_password():
     chars.append(rnd.choice(string.digits))
     chars.append(rnd.choice(string.ascii_lowercase))
     chars.append(rnd.choice(string.ascii_uppercase))
-    chars.append(rnd.choice(string.punctuation))
+    chars.append(rnd.choice(PUNCTUATIONS))
 
     # add 6 additional random chars
     chars.extend(rnd.choice(valid_chars) for i in range(6))
-- 
1.8.3.1


From 08bf26f786b8d233382c6fedfad5d33d8c11d78f Mon Sep 17 00:00:00 2001
From: Ade Lee <alee@redhat.com>
Date: Thu, 1 Jun 2017 17:46:27 -0400
Subject: [PATCH 16/27] Fix NPE in audit log invocation

Some audit log objects take a RequestId or KeyId, on which we call
toString().  In some cases, we were creating a KeyId or RequestId
with null values, resulting in an NPE.  We fix these in this patch.

Bugzilla BZ# 1458043

Change-Id: I38d5a20e9920966c8414d56afd7690dc3c11a1db
---
 base/kra/src/com/netscape/kra/KeyRecoveryAuthority.java        | 3 ++-
 base/kra/src/com/netscape/kra/TokenKeyRecoveryService.java     | 4 ++--
 3 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/base/kra/src/com/netscape/kra/KeyRecoveryAuthority.java b/base/kra/src/com/netscape/kra/KeyRecoveryAuthority.java
index ed20394..5e3b8a9 100644
--- a/base/kra/src/com/netscape/kra/KeyRecoveryAuthority.java
+++ b/base/kra/src/com/netscape/kra/KeyRecoveryAuthority.java
@@ -1128,7 +1128,8 @@ public class KeyRecoveryAuthority implements IAuthority, IKeyService, IKeyRecove
         r = queue.findRequest(new RequestId(reqID));
 
         auditAgents = r.getExtDataInString(IRequest.ATTR_APPROVE_AGENTS);
-        keyID = new KeyId(r.getExtDataInBigInteger("serialNumber"));
+        BigInteger serialNumber = r.getExtDataInBigInteger("serialNumber");
+        keyID = serialNumber != null? new KeyId(serialNumber) : null;
 
         // set transient parameters
         params = createVolatileRequest(r.getRequestId());
diff --git a/base/kra/src/com/netscape/kra/TokenKeyRecoveryService.java b/base/kra/src/com/netscape/kra/TokenKeyRecoveryService.java
index c0b5cdd..891b083 100644
--- a/base/kra/src/com/netscape/kra/TokenKeyRecoveryService.java
+++ b/base/kra/src/com/netscape/kra/TokenKeyRecoveryService.java
@@ -283,7 +283,7 @@ public class TokenKeyRecoveryService implements IService {
         // retrieve based on Certificate
         String cert_s = request.getExtDataInString(ATTR_USER_CERT);
         String keyid_s = request.getExtDataInString(IRequest.NETKEY_ATTR_KEYID);
-        KeyId keyId = new KeyId(request.getExtDataInString(IRequest.NETKEY_ATTR_KEYID));
+        KeyId keyId = keyid_s != null ? new KeyId(keyid_s): null;
         /* have to have at least one */
         if ((cert_s == null) && (keyid_s == null)) {
             CMS.debug("TokenKeyRecoveryService: not receive cert or keyid");
@@ -593,7 +593,7 @@ public class TokenKeyRecoveryService implements IService {
             return true;
 
         } catch (Exception e) {
-            CMS.debug("TokenKeyRecoveryService: " + e.toString());
+            CMS.debug(e);
             request.setExtData(IRequest.RESULT, Integer.valueOf(4));
         }
 
-- 
1.8.3.1


From 29dbed75f1c214a065cd3bcc438d0584fd980d4f Mon Sep 17 00:00:00 2001
From: "Endi S. Dewata" <edewata@redhat.com>
Date: Fri, 2 Jun 2017 18:46:01 +0200
Subject: [PATCH 17/27] Excluded backslash from random password.

The backslash is no longer used for generating random password
since it's causing SSL hanshake failure.

https://pagure.io/dogtagpki/issue/2676

Change-Id: I2e63769b16fc3fa617b27dccb7b85f139714a411
---
 base/common/python/pki/__init__.py | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/base/common/python/pki/__init__.py b/base/common/python/pki/__init__.py
index 0478b32..1a6f5c2 100644
--- a/base/common/python/pki/__init__.py
+++ b/base/common/python/pki/__init__.py
@@ -46,9 +46,10 @@ CERT_HEADER = "-----BEGIN CERTIFICATE-----"
 CERT_FOOTER = "-----END CERTIFICATE-----"
 
 # Valid punctuation characters for random password.
-# This is identical to string.punctuation minus the equal
-# sign since it's used as delimiter in password.conf.
-PUNCTUATIONS = '!"#$%&\'()*+,-./:;<>?@[\\]^_`{|}~'
+# This is based on string.punctuation except:
+#  - equal sign since it's used as delimiter in password.conf
+#  - backslash since it's causing SSL handshake failure
+PUNCTUATIONS = '!"#$%&\'()*+,-./:;<>?@[]^_`{|}~'
 
 
 def read_text(message,
-- 
1.8.3.1


From a614eb15476adb00df571d3ea05fdd8ea282141d Mon Sep 17 00:00:00 2001
From: Jack Magne <jmagne@dhcp-16-206.sjc.redhat.com>
Date: Fri, 2 Jun 2017 15:40:52 -0700
Subject: [PATCH 18/27] Resolve  #1663 Add SCP03 support .

This particular fix resolves a simple issue when formatting a token in FIPS mode for SCP03.
---
 base/tps/src/org/dogtagpki/server/tps/channel/SecureChannel.java  | 7 ++++---
 base/tps/src/org/dogtagpki/server/tps/processor/TPSProcessor.java | 4 ++++
 2 files changed, 8 insertions(+), 3 deletions(-)

diff --git a/base/tps/src/org/dogtagpki/server/tps/channel/SecureChannel.java b/base/tps/src/org/dogtagpki/server/tps/channel/SecureChannel.java
index 5e5646b..3b80f27 100644
--- a/base/tps/src/org/dogtagpki/server/tps/channel/SecureChannel.java
+++ b/base/tps/src/org/dogtagpki/server/tps/channel/SecureChannel.java
@@ -421,10 +421,11 @@ public class SecureChannel {
                 throw new TPSException(method + "Failed to calculate card cryptogram!", TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
             }
 
-            CMS.debug(method + " dumped macSessionKey: " + new TPSBuffer(macSessionKey.getEncoded()).toHexString() );
+            if(cardCryptogram != null)
+                CMS.debug(method + " actual card cryptogram " + cardCryptogram.toHexString());
 
-            CMS.debug(method + " actual card cryptogram " + cardCryptogram.toHexString());
-            CMS.debug(method + " calculated card cryptogram " + calculatedCardCryptogram.toHexString());
+            if(calculatedCardCryptogram != null)
+                CMS.debug(method + " calculated card cryptogram " + calculatedCardCryptogram.toHexString());
 
             ExternalAuthenticateAPDUGP211 externalAuth = new ExternalAuthenticateAPDUGP211(hostCryptogram,
                     /* secLevel */secLevelGP211);
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 0f96915..e1a5748 100644
--- a/base/tps/src/org/dogtagpki/server/tps/processor/TPSProcessor.java
+++ b/base/tps/src/org/dogtagpki/server/tps/processor/TPSProcessor.java
@@ -957,6 +957,10 @@ public class TPSProcessor {
                 kekSessionKeySCP03 = (PK11SymKey) protocol.unwrapWrappedSymKeyOnToken(token, sharedSecret,
                         kekSessionKeyBuff.toBytesArray(), false, SymmetricKey.AES);
 
+            CMS.debug(" encSessionKeySCP03 " + encSessionKeySCP03);
+            CMS.debug(" macSessionKeySCP03 " + macSessionKeySCP03);
+            CMS.debug(" kekSessionKeySCP03 " + kekSessionKeySCP03);
+
             channel = new SecureChannel(this, encSessionKeySCP03, macSessionKeySCP03, kekSessionKeySCP03,
                     drmDesKeyBuff, kekDesKeyBuff,
                     keyCheckBuff, keyDiversificationData, cardChallenge,
-- 
1.8.3.1


From af41896f083e1101b1ba62f6cc8c9be6064c6786 Mon Sep 17 00:00:00 2001
From: "Endi S. Dewata" <edewata@redhat.com>
Date: Sat, 3 Jun 2017 02:07:04 +0200
Subject: [PATCH 19/27] Refactored MainCLI.loadPassword() (part 1).

The method that loads password from a file in MainCLI has been
renamed into loadPassword() and modified to return early for
clarity.

https://pagure.io/dogtagpki/issue/2717

Change-Id: I9b031c31040c2d00f04d9997abcdae38163bf6d5
---
 .../src/com/netscape/cmstools/cli/MainCLI.java     | 24 ++++++++++++----------
 1 file changed, 13 insertions(+), 11 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 1b9c569..2402196 100644
--- a/base/java-tools/src/com/netscape/cmstools/cli/MainCLI.java
+++ b/base/java-tools/src/com/netscape/cmstools/cli/MainCLI.java
@@ -229,7 +229,7 @@ public class MainCLI extends CLI {
         options.addOption(null, "version", false, "Show version number.");
     }
 
-    public String[] readPlaintextPasswordFromFile(String pwfile) throws Exception {
+    public String[] loadPassword(String pwfile) throws Exception {
         String[] tokenPassword = { null, null };
         BufferedReader br = null;
         String delimiter = "=";
@@ -238,11 +238,16 @@ public class MainCLI extends CLI {
             br = new BufferedReader(new FileReader(pwfile));
 
             String line = br.readLine();
-            if (line != null) {
-                if (line.isEmpty()) {
-                    throw new Exception("File '" + pwfile + "' does not define a token or a password!");
 
-                } else if (line.contains(delimiter)) {
+            if (line == null) {
+                throw new Exception("File '" + pwfile + "' is empty!");
+            }
+
+            if (line.isEmpty()) {
+                throw new Exception("File '" + pwfile + "' does not define a token or a password!");
+            }
+
+                if (line.contains(delimiter)) {
                     // Process 'token=password' format:
                     //
                     //     Token:     tokenPassword[0]
@@ -270,10 +275,7 @@ public class MainCLI extends CLI {
                     // Set simple 'password' (do not trim leading/trailing whitespace)
                     tokenPassword[1] = line;
                 }
-            } else {
-                // Case of an empty password file
-                throw new Exception("File '" + pwfile + "' is empty!");
-            }
+
         } finally {
             if (br != null) {
                 br.close();
@@ -397,7 +399,7 @@ public class MainCLI extends CLI {
 
         if (certPasswordFile != null) {
             // read client security database password from specified file
-            tokenPasswordPair = readPlaintextPasswordFromFile(certPasswordFile);
+            tokenPasswordPair = loadPassword(certPasswordFile);
             // XXX TBD set client security database token
 
             certPassword = tokenPasswordPair[1];
@@ -411,7 +413,7 @@ public class MainCLI extends CLI {
 
         if (passwordFile != null) {
             // read user password from specified file
-            tokenPasswordPair = readPlaintextPasswordFromFile(passwordFile);
+            tokenPasswordPair = loadPassword(passwordFile);
             // XXX TBD set user token
 
             password = tokenPasswordPair[1];
-- 
1.8.3.1


From 9741b7873005419b922ba79c61ef98ae17cb58be Mon Sep 17 00:00:00 2001
From: "Endi S. Dewata" <edewata@redhat.com>
Date: Sat, 3 Jun 2017 02:03:32 +0200
Subject: [PATCH 20/27] Refactored MainCLI.loadPassword() (part 2).

The MainCLI.loadPassword() has been modified to fix the code
indentation.

https://pagure.io/dogtagpki/issue/2717

Change-Id: I7d208f1f4568f2fb1323ab206f45af5c0338b53f
---
 .../src/com/netscape/cmstools/cli/MainCLI.java     | 49 +++++++++++-----------
 1 file changed, 25 insertions(+), 24 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 2402196..2b6b173 100644
--- a/base/java-tools/src/com/netscape/cmstools/cli/MainCLI.java
+++ b/base/java-tools/src/com/netscape/cmstools/cli/MainCLI.java
@@ -247,35 +247,36 @@ public class MainCLI extends CLI {
                 throw new Exception("File '" + pwfile + "' does not define a token or a password!");
             }
 
-                if (line.contains(delimiter)) {
-                    // Process 'token=password' format:
-                    //
-                    //     Token:     tokenPassword[0]
-                    //     Password:  tokenPassword[1]
-                    //
-                    tokenPassword = line.split(delimiter, 2);
-
-                    // Always trim leading/trailing whitespace from 'token'
-                    tokenPassword[0] = tokenPassword[0].trim();
-
-                    // Check for undefined 'token'
-                    if (tokenPassword[0].isEmpty()) {
-                        // Set default 'token'
-                        tokenPassword[0] = CryptoUtil.INTERNAL_TOKEN_NAME;
-                    }
-
-                    // Check for undefined 'password'
-                    if (tokenPassword[1].isEmpty()) {
-                        throw new Exception("File '" + pwfile + "' does not define a password!");
-                    }
-                } else {
+            if (line.contains(delimiter)) {
+                // Process 'token=password' format:
+                //
+                //     Token:     tokenPassword[0]
+                //     Password:  tokenPassword[1]
+                //
+                tokenPassword = line.split(delimiter, 2);
+
+                // Always trim leading/trailing whitespace from 'token'
+                tokenPassword[0] = tokenPassword[0].trim();
+
+                // Check for undefined 'token'
+                if (tokenPassword[0].isEmpty()) {
                     // Set default 'token'
                     tokenPassword[0] = CryptoUtil.INTERNAL_TOKEN_NAME;
+                }
 
-                    // Set simple 'password' (do not trim leading/trailing whitespace)
-                    tokenPassword[1] = line;
+                // Check for undefined 'password'
+                if (tokenPassword[1].isEmpty()) {
+                    throw new Exception("File '" + pwfile + "' does not define a password!");
                 }
 
+            } else {
+                // Set default 'token'
+                tokenPassword[0] = CryptoUtil.INTERNAL_TOKEN_NAME;
+
+                // Set simple 'password' (do not trim leading/trailing whitespace)
+                tokenPassword[1] = line;
+            }
+
         } finally {
             if (br != null) {
                 br.close();
-- 
1.8.3.1


From 729468e46612569da4c93b15bc0d674099003aba Mon Sep 17 00:00:00 2001
From: "Endi S. Dewata" <edewata@redhat.com>
Date: Sat, 3 Jun 2017 02:28:00 +0200
Subject: [PATCH 21/27] Refactored MainCLI.loadPassword() (part 3).

The MainCLI.loadPassword() has been modified to use try-with-
resources. Some log messages have been added for clarity.

https://pagure.io/dogtagpki/issue/2717

Change-Id: Ic4950ba677613565f548b51d1f985177c6726510
---
 .../src/com/netscape/cmstools/cli/MainCLI.java      | 21 +++++++++------------
 1 file changed, 9 insertions(+), 12 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 2b6b173..dcc60e2 100644
--- a/base/java-tools/src/com/netscape/cmstools/cli/MainCLI.java
+++ b/base/java-tools/src/com/netscape/cmstools/cli/MainCLI.java
@@ -230,12 +230,11 @@ public class MainCLI extends CLI {
     }
 
     public String[] loadPassword(String pwfile) throws Exception {
+
         String[] tokenPassword = { null, null };
-        BufferedReader br = null;
         String delimiter = "=";
 
-        try {
-            br = new BufferedReader(new FileReader(pwfile));
+        try (BufferedReader br = new BufferedReader(new FileReader(pwfile))) {
 
             String line = br.readLine();
 
@@ -276,11 +275,6 @@ public class MainCLI extends CLI {
                 // Set simple 'password' (do not trim leading/trailing whitespace)
                 tokenPassword[1] = line;
             }
-
-        } finally {
-            if (br != null) {
-                br.close();
-            }
         }
 
         return tokenPassword;
@@ -399,7 +393,7 @@ public class MainCLI extends CLI {
         config.setCertNickname(certNickname);
 
         if (certPasswordFile != null) {
-            // read client security database password from specified file
+            if (verbose) System.out.println("Loading NSS password from " + certPasswordFile);
             tokenPasswordPair = loadPassword(certPasswordFile);
             // XXX TBD set client security database token
 
@@ -413,7 +407,7 @@ public class MainCLI extends CLI {
         config.setUsername(username);
 
         if (passwordFile != null) {
-            // read user password from specified file
+            if (verbose) System.out.println("Loading user password from " + passwordFile);
             tokenPasswordPair = loadPassword(passwordFile);
             // XXX TBD set user token
 
@@ -494,15 +488,18 @@ public class MainCLI extends CLI {
 
         // If password is specified, use password to access security token
         if (config.getCertPassword() != null) {
-            if (verbose) System.out.println("Logging into security token");
+
             try {
                 CryptoManager manager = CryptoManager.getInstance();
 
                 String tokenName = config.getTokenName();
-                CryptoToken token = CryptoUtil.getKeyStorageToken(tokenName);
+                if (verbose) System.out.println("Getting " + (tokenName == null ? "internal" : tokenName) + " token");
 
+                CryptoToken token = CryptoUtil.getKeyStorageToken(tokenName);
                 manager.setThreadToken(token);
 
+                if (verbose) System.out.println("Logging into " + token.getName());
+
                 Password password = new Password(config.getCertPassword().toCharArray());
                 token.login(password);
 
-- 
1.8.3.1


From d4e5176702b3a08a67233e069ac211e95e01b228 Mon Sep 17 00:00:00 2001
From: "Endi S. Dewata" <edewata@redhat.com>
Date: Sat, 3 Jun 2017 01:32:37 +0200
Subject: [PATCH 22/27] Refactored CLI.runExternal().

The methods for running external commands in various CLI classes
have been merged into CLI.runExternal().

https://pagure.io/dogtagpki/issue/2717

Change-Id: I5b6d136db699d3bb48e4f36f7f187d0240bbbf62
---
 .../src/com/netscape/cmstools/cli/CLI.java         | 35 ++++++++++++++++++++++
 .../src/com/netscape/cmstools/cli/MainCLI.java     | 10 +++----
 .../cmstools/client/ClientCertImportCLI.java       | 23 ++------------
 .../cmstools/client/ClientCertModifyCLI.java       | 35 +++++-----------------
 .../cmstools/client/ClientCertRequestCLI.java      | 10 +++----
 .../cmstools/client/ClientCertShowCLI.java         | 27 +++--------------
 .../netscape/cmstools/client/ClientInitCLI.java    | 25 ++++++----------
 7 files changed, 65 insertions(+), 100 deletions(-)

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 4911b8a..60db7a1 100644
--- a/base/java-tools/src/com/netscape/cmstools/cli/CLI.java
+++ b/base/java-tools/src/com/netscape/cmstools/cli/CLI.java
@@ -18,6 +18,7 @@
 
 package com.netscape.cmstools.cli;
 
+import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.LinkedHashMap;
@@ -351,4 +352,38 @@ public class CLI {
     public static void setVerbose(boolean verbose) {
         CLI.verbose = verbose;
     }
+
+    public void runExternal(List<String> command) throws CLIException, IOException, InterruptedException {
+        String[] array = command.toArray(new String[command.size()]);
+        runExternal(array);
+    }
+
+    public void runExternal(String[] command) throws CLIException, IOException, InterruptedException {
+
+        if (verbose) {
+
+            System.out.print("External command:");
+
+           for (String c : command) {
+
+               boolean quote = c.contains(" ");
+
+               System.out.print(" ");
+
+               if (quote) System.out.print("\"");
+               System.out.print(c);
+               if (quote) System.out.print("\"");
+           }
+
+           System.out.println();
+        }
+
+        Runtime rt = Runtime.getRuntime();
+        Process p = rt.exec(command);
+        int rc = p.waitFor();
+
+        if (rc != 0) {
+            throw new CLIException("External command failed. RC: " + rc, rc);
+        }
+    }
 }
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 dcc60e2..51861b5 100644
--- a/base/java-tools/src/com/netscape/cmstools/cli/MainCLI.java
+++ b/base/java-tools/src/com/netscape/cmstools/cli/MainCLI.java
@@ -473,12 +473,10 @@ public class MainCLI extends CLI {
                     "--empty-password"
             };
 
-            Runtime rt = Runtime.getRuntime();
-            Process p = rt.exec(commands);
-
-            int rc = p.waitFor();
-            if (rc != 0) {
-                throw new Exception("Unable to create security database: " + certDatabase.getAbsolutePath() + " (rc: " + rc + ")");
+            try {
+                runExternal(commands);
+            } catch (Exception e) {
+                throw new Exception("Unable to create security database", e);
             }
         }
 
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 9cb3e67..687dfc4 100644
--- a/base/java-tools/src/com/netscape/cmstools/client/ClientCertImportCLI.java
+++ b/base/java-tools/src/com/netscape/cmstools/client/ClientCertImportCLI.java
@@ -21,14 +21,12 @@ package com.netscape.cmstools.client;
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.FileWriter;
-import java.io.IOException;
 import java.io.PrintWriter;
 import java.net.URI;
 import java.util.Arrays;
 
 import org.apache.commons.cli.CommandLine;
 import org.apache.commons.cli.Option;
-import org.apache.commons.lang.StringUtils;
 
 import com.netscape.certsrv.cert.CertClient;
 import com.netscape.certsrv.cert.CertData;
@@ -283,8 +281,7 @@ public class ClientCertImportCLI extends CLI {
         };
 
         try {
-            run(command);
-
+            runExternal(command);
         } catch (Exception e) {
             throw new Exception("Unable to import certificate file", e);
         }
@@ -305,25 +302,9 @@ public class ClientCertImportCLI extends CLI {
         };
 
         try {
-            run(command);
-
+            runExternal(command);
         } catch (Exception e) {
             throw new Exception("Unable to import PKCS #12 file", e);
         }
     }
-
-    public void run(String[] command) throws IOException, InterruptedException {
-
-        if (verbose) {
-           System.out.println("Command: " + StringUtils.join(command, " "));
-        }
-
-        Runtime rt = Runtime.getRuntime();
-        Process p = rt.exec(command);
-        int rc = p.waitFor();
-
-        if (rc != 0) {
-            throw new IOException("Command failed. RC: " + rc);
-        }
-    }
 }
diff --git a/base/java-tools/src/com/netscape/cmstools/client/ClientCertModifyCLI.java b/base/java-tools/src/com/netscape/cmstools/client/ClientCertModifyCLI.java
index f229e67..8ae7c6d 100644
--- a/base/java-tools/src/com/netscape/cmstools/client/ClientCertModifyCLI.java
+++ b/base/java-tools/src/com/netscape/cmstools/client/ClientCertModifyCLI.java
@@ -18,8 +18,6 @@
 
 package com.netscape.cmstools.client;
 
-import java.io.IOException;
-
 import org.apache.commons.cli.CommandLine;
 import org.apache.commons.cli.Option;
 
@@ -75,38 +73,19 @@ public class ClientCertModifyCLI extends CLI {
 
         String trustAttributes = cmd.getOptionValue("trust", "u,u,u");
 
-        int rc = modifyCert(
-                mainCLI.certDatabase.getAbsolutePath(),
-                nickname,
-                trustAttributes);
-
-        if (rc != 0) {
-            MainCLI.printMessage("Modified failed");
-            return;
-        }
-
-        MainCLI.printMessage("Modified certificate \"" + nickname + "\"");
-    }
-
-    public int modifyCert(
-            String dbPath,
-            String nickname,
-            String trustAttributes) throws IOException, InterruptedException {
-
         String[] command = {
                 "/usr/bin/certutil", "-M",
-                "-d", dbPath,
+                "-d", mainCLI.certDatabase.getAbsolutePath(),
                 "-n", nickname,
                 "-t", trustAttributes
         };
 
-        return run(command);
-    }
-
-    public int run(String[] command) throws IOException, InterruptedException {
+        try {
+            runExternal(command);
+        } catch (Exception e) {
+            throw new Exception("Unable to modify certificate", e);
+        }
 
-        Runtime rt = Runtime.getRuntime();
-        Process p = rt.exec(command);
-        return p.waitFor();
+        MainCLI.printMessage("Modified certificate \"" + nickname + "\"");
     }
 }
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 696ab8b..a14bb24 100644
--- a/base/java-tools/src/com/netscape/cmstools/client/ClientCertRequestCLI.java
+++ b/base/java-tools/src/com/netscape/cmstools/client/ClientCertRequestCLI.java
@@ -386,12 +386,10 @@ public class ClientCertRequestCLI extends CLI {
                 "-n", subjectDN
         };
 
-        Runtime rt = Runtime.getRuntime();
-        Process p = rt.exec(commands);
-
-        int rc = p.waitFor();
-        if (rc != 0) {
-            throw new Exception("CSR generation failed");
+        try {
+            runExternal(commands);
+        } catch (Exception e) {
+            throw new Exception("CSR generation failed", e);
         }
 
         if (verbose) {
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 2242b37..bb60fbf 100644
--- a/base/java-tools/src/com/netscape/cmstools/client/ClientCertShowCLI.java
+++ b/base/java-tools/src/com/netscape/cmstools/client/ClientCertShowCLI.java
@@ -20,13 +20,11 @@ package com.netscape.cmstools.client;
 
 import java.io.File;
 import java.io.FileWriter;
-import java.io.IOException;
 import java.io.PrintWriter;
 
 import org.apache.commons.cli.CommandLine;
 import org.apache.commons.cli.Option;
 import org.apache.commons.lang.RandomStringUtils;
-import org.apache.commons.lang.StringUtils;
 import org.mozilla.jss.crypto.X509Certificate;
 
 import com.netscape.certsrv.client.PKIClient;
@@ -192,8 +190,7 @@ public class ClientCertShowCLI extends CLI {
         };
 
         try {
-            run(command);
-
+            runExternal(command);
         } catch (Exception e) {
             throw new Exception("Unable to export PKCS #12 file", e);
         }
@@ -215,8 +212,7 @@ public class ClientCertShowCLI extends CLI {
         };
 
         try {
-            run(command);
-
+            runExternal(command);
         } catch (Exception e) {
             throw new Exception("Unable to export certificate", e);
         }
@@ -238,8 +234,7 @@ public class ClientCertShowCLI extends CLI {
         };
 
         try {
-            run(command);
-
+            runExternal(command);
         } catch (Exception e) {
             throw new Exception("Unable to export private key", e);
         }
@@ -261,23 +256,9 @@ public class ClientCertShowCLI extends CLI {
         };
 
         try {
-            run(command);
-
+            runExternal(command);
         } catch (Exception e) {
             throw new Exception("Unable to export client certificate and private key", e);
         }
     }
-
-    public void run(String[] command) throws IOException, InterruptedException {
-
-        if (verbose) System.out.println("Command: " + StringUtils.join(command, " "));
-
-        Runtime rt = Runtime.getRuntime();
-        Process p = rt.exec(command);
-        int rc = p.waitFor();
-
-        if (rc != 0) {
-            throw new IOException("Command failed. RC: " + rc);
-        }
-    }
 }
diff --git a/base/java-tools/src/com/netscape/cmstools/client/ClientInitCLI.java b/base/java-tools/src/com/netscape/cmstools/client/ClientInitCLI.java
index 893b40b..7e018de 100644
--- a/base/java-tools/src/com/netscape/cmstools/client/ClientInitCLI.java
+++ b/base/java-tools/src/com/netscape/cmstools/client/ClientInitCLI.java
@@ -95,12 +95,11 @@ public class ClientInitCLI extends CLI {
         File passwordFile = new File(certDatabase, "password.txt");
 
         try {
-            String[] commands = {
-                    "/usr/bin/certutil", "-N",
-                    "-d", certDatabase.getAbsolutePath(),
-            };
-
-            List<String> list = new ArrayList<>(Arrays.asList(commands));
+            List<String> list = new ArrayList<>();
+            list.add("/usr/bin/certutil");
+            list.add("-N");
+            list.add("-d");
+            list.add(certDatabase.getAbsolutePath());
 
             if (mainCLI.config.getCertPassword() == null) {
                 list.add("--empty-password");
@@ -114,16 +113,10 @@ public class ClientInitCLI extends CLI {
                 list.add(passwordFile.getAbsolutePath());
             }
 
-            commands = new String[list.size()];
-            list.toArray(commands);
-
-            Runtime rt = Runtime.getRuntime();
-            Process p = rt.exec(commands);
-
-            int rc = p.waitFor();
-            if (rc != 0) {
-                MainCLI.printMessage("Client initialization failed");
-                return;
+            try {
+                runExternal(list);
+            } catch (Exception e) {
+                throw new Exception("Client initialization failed", e);
             }
 
             MainCLI.printMessage("Client initialized");
-- 
1.8.3.1


From 3ef47867df74eb9dce408b88756ccce7d7438da5 Mon Sep 17 00:00:00 2001
From: "Endi S. Dewata" <edewata@redhat.com>
Date: Sat, 3 Jun 2017 00:29:29 +0200
Subject: [PATCH 23/27] Fixed pki client-cert-import CLI.

The pki client-cert-import CLI has been modified to provide a
password file when invoking the certutil -A command.

https://pagure.io/dogtagpki/issue/2717

Change-Id: If32f9eeb39d140aaef38c9bc1933f3ae0f57a5a2
---
 .../cmstools/client/ClientCertImportCLI.java       | 94 +++++++++++++++-------
 1 file changed, 66 insertions(+), 28 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 687dfc4..1c67f99 100644
--- a/base/java-tools/src/com/netscape/cmstools/client/ClientCertImportCLI.java
+++ b/base/java-tools/src/com/netscape/cmstools/client/ClientCertImportCLI.java
@@ -23,7 +23,9 @@ import java.io.FileOutputStream;
 import java.io.FileWriter;
 import java.io.PrintWriter;
 import java.net.URI;
+import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.List;
 
 import org.apache.commons.cli.CommandLine;
 import org.apache.commons.cli.Option;
@@ -128,6 +130,20 @@ public class ClientCertImportCLI extends CLI {
         String serialNumber = cmd.getOptionValue("serial");
         String trustAttributes = cmd.getOptionValue("trust");
 
+        File nssdbPasswordFile = null;
+
+        if (mainCLI.config.getCertPassword() != null) {
+
+            // store NSS database password in a temporary file
+
+            nssdbPasswordFile = File.createTempFile("pki-client-cert-import-", ".nssdb-pwd");
+            nssdbPasswordFile.deleteOnExit();
+
+            try (PrintWriter out = new PrintWriter(new FileWriter(nssdbPasswordFile))) {
+                out.print(mainCLI.config.getCertPassword());
+            }
+        }
+
         // load the certificate
         if (certPath != null) {
 
@@ -137,7 +153,8 @@ public class ClientCertImportCLI extends CLI {
                 trustAttributes = "u,u,u";
 
             importCert(
-                    mainCLI.certDatabase.getAbsolutePath(),
+                    mainCLI.certDatabase,
+                    nssdbPasswordFile,
                     certPath,
                     nickname,
                     trustAttributes);
@@ -150,7 +167,8 @@ public class ClientCertImportCLI extends CLI {
                 trustAttributes = "CT,c,";
 
             importCert(
-                    mainCLI.certDatabase.getAbsolutePath(),
+                    mainCLI.certDatabase,
+                    nssdbPasswordFile,
                     caCertPath,
                     nickname,
                     trustAttributes);
@@ -164,7 +182,7 @@ public class ClientCertImportCLI extends CLI {
 
             } else if (pkcs12Password != null) {
                 // store password into a temporary file
-                File pkcs12PasswordFile = File.createTempFile("pki-client-cert-import-", ".pwd");
+                File pkcs12PasswordFile = File.createTempFile("pki-client-cert-import-", ".pkcs12-pwd");
                 pkcs12PasswordFile.deleteOnExit();
 
                 try (PrintWriter out = new PrintWriter(new FileWriter(pkcs12PasswordFile))) {
@@ -182,8 +200,8 @@ public class ClientCertImportCLI extends CLI {
 
             // import certificates and private key into PKCS #12 file
             importPKCS12(
-                    mainCLI.certDatabase.getAbsolutePath(),
-                    mainCLI.config.getCertPassword(),
+                    mainCLI.certDatabase,
+                    nssdbPasswordFile,
                     pkcs12Path,
                     pkcs12PasswordPath);
 
@@ -212,7 +230,8 @@ public class ClientCertImportCLI extends CLI {
                 trustAttributes = "CT,c,";
 
             importCert(
-                    mainCLI.certDatabase.getAbsolutePath(),
+                    mainCLI.certDatabase,
+                    nssdbPasswordFile,
                     certFile.getAbsolutePath(),
                     nickname,
                     trustAttributes);
@@ -245,7 +264,8 @@ public class ClientCertImportCLI extends CLI {
                 trustAttributes = "u,u,u";
 
             importCert(
-                    mainCLI.certDatabase.getAbsolutePath(),
+                    mainCLI.certDatabase,
+                    nssdbPasswordFile,
                     certFile.getAbsolutePath(),
                     nickname,
                     trustAttributes);
@@ -263,8 +283,9 @@ public class ClientCertImportCLI extends CLI {
     }
 
     public void importCert(
-            String dbPath,
-            String certPath,
+            File dbPath,
+            File dbPasswordFile,
+            String certFile,
             String nickname,
             String trustAttributes) throws Exception {
 
@@ -272,13 +293,23 @@ public class ClientCertImportCLI extends CLI {
             throw new Exception("Missing certificate nickname.");
         }
 
-        String[] command = {
-                "/bin/certutil", "-A",
-                "-d", dbPath,
-                "-i", certPath,
-                "-n", nickname,
-                "-t", trustAttributes
-        };
+        List<String> command = new ArrayList<>();
+        command.add("/bin/certutil");
+        command.add("-A");
+        command.add("-d");
+        command.add(dbPath.getAbsolutePath());
+
+        if (dbPasswordFile != null) {
+            command.add("-f");
+            command.add(dbPasswordFile.getAbsolutePath());
+        }
+
+        command.add("-i");
+        command.add(certFile);
+        command.add("-n");
+        command.add(nickname);
+        command.add("-t");
+        command.add(trustAttributes);
 
         try {
             runExternal(command);
@@ -288,18 +319,25 @@ public class ClientCertImportCLI extends CLI {
     }
 
     public void importPKCS12(
-            String dbPath,
-            String dbPassword,
-            String pkcs12Path,
-            String pkcs12PasswordPath) throws Exception {
-
-        String[] command = {
-                "/bin/pk12util",
-                "-d", dbPath,
-                "-K", dbPassword,
-                "-i", pkcs12Path,
-                "-w", pkcs12PasswordPath
-        };
+            File dbPath,
+            File dbPasswordFile,
+            String pkcs12File,
+            String pkcs12PasswordFile) throws Exception {
+
+        List<String> command = new ArrayList<>();
+        command.add("/bin/pk12util");
+        command.add("-d");
+        command.add(dbPath.getAbsolutePath());
+
+        if (dbPasswordFile != null) {
+            command.add("-k");
+            command.add(dbPasswordFile.getAbsolutePath());
+        }
+
+        command.add("-i");
+        command.add(pkcs12File);
+        command.add("-w");
+        command.add(pkcs12PasswordFile);
 
         try {
             runExternal(command);
-- 
1.8.3.1


From 64b7b7abfed29b6a520be66414139364d713461e Mon Sep 17 00:00:00 2001
From: "Endi S. Dewata" <edewata@redhat.com>
Date: Sat, 3 Jun 2017 03:52:09 +0200
Subject: [PATCH 24/27] Fixed default CA cert trust flags in pki CLI.

The pki CLI has been modified to use CT,C,C as the default trust
flags for CA certificate import operations.

https://pagure.io/dogtagpki/issue/2726

Change-Id: I68c5a0303459319cc746a77703d0a420f4f68377
---
 base/common/python/pki/cli/pkcs12.py                                  | 2 +-
 .../src/com/netscape/cmstools/client/ClientCertImportCLI.java         | 4 ++--
 .../cms/src/com/netscape/cms/servlet/csadmin/ConfigurationUtils.java  | 1 +
 3 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/base/common/python/pki/cli/pkcs12.py b/base/common/python/pki/cli/pkcs12.py
index 6b99fcf..2f8aabf 100644
--- a/base/common/python/pki/cli/pkcs12.py
+++ b/base/common/python/pki/cli/pkcs12.py
@@ -237,7 +237,7 @@ class PKCS12ImportCLI(pki.cli.CLI):
                         trust_flags = cert_info['trust_flags']
                     else:
                         # default trust flags for CA certificates
-                        trust_flags = 'CT,c,c'
+                        trust_flags = 'CT,C,C'
 
                     if main_cli.verbose:
                         print('Exporting %s (%s) from PKCS #12 file' % (nickname, cert_id))
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 1c67f99..844453e 100644
--- a/base/java-tools/src/com/netscape/cmstools/client/ClientCertImportCLI.java
+++ b/base/java-tools/src/com/netscape/cmstools/client/ClientCertImportCLI.java
@@ -164,7 +164,7 @@ public class ClientCertImportCLI extends CLI {
             if (verbose) System.out.println("Importing CA certificate from " + caCertPath + ".");
 
             if (trustAttributes == null)
-                trustAttributes = "CT,c,";
+                trustAttributes = "CT,C,C";
 
             importCert(
                     mainCLI.certDatabase,
@@ -227,7 +227,7 @@ public class ClientCertImportCLI extends CLI {
             }
 
             if (trustAttributes == null)
-                trustAttributes = "CT,c,";
+                trustAttributes = "CT,C,C";
 
             importCert(
                     mainCLI.certDatabase,
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 c9a375f..ebade36 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
@@ -1113,6 +1113,7 @@ public class ConfigurationUtils {
                             | InternalCertificate.VALID_CA);
 
                 } else if (isAuditSigningCert(name)) {
+                    // set trust flags to u,u,Pu
                     icert.setObjectSigningTrust(InternalCertificate.USER
                             | InternalCertificate.VALID_PEER
                             | InternalCertificate.TRUSTED_PEER);
-- 
1.8.3.1


From c0b2daef934a8f5ac1c61d673865348aa2a0f702 Mon Sep 17 00:00:00 2001
From: Fraser Tweedale <ftweedal@redhat.com>
Date: Thu, 25 May 2017 15:32:14 +1000
Subject: [PATCH 25/27] Improve exception message for null
 AuthorityKeyIdentifier

When the Authority Key Identifier extension cannot be instantiated,
we currently fail with a generic "extension not found" error
message.  Throw a better exception for this case in particular, and
improve the exception message for the general case of attempting to
add a null exception.

Fixes: https://pagure.io/dogtagpki/issue/2705
Change-Id: Ic79742d8a228391275ffe5bfeef0a324f6b431bd
---
 .../netscape/cms/profile/def/AuthorityKeyIdentifierExtDefault.java    | 4 ++++
 base/server/cms/src/com/netscape/cms/profile/def/EnrollDefault.java   | 2 +-
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/base/server/cms/src/com/netscape/cms/profile/def/AuthorityKeyIdentifierExtDefault.java b/base/server/cms/src/com/netscape/cms/profile/def/AuthorityKeyIdentifierExtDefault.java
index 42931de..f8d8b44 100644
--- a/base/server/cms/src/com/netscape/cms/profile/def/AuthorityKeyIdentifierExtDefault.java
+++ b/base/server/cms/src/com/netscape/cms/profile/def/AuthorityKeyIdentifierExtDefault.java
@@ -183,6 +183,10 @@ public class AuthorityKeyIdentifierExtDefault extends CAEnrollDefault {
         } catch (EBaseException e) {
             throw new EProfileException(e);
         }
+        if (ext == null) {
+            throw new EProfileException(
+                "Could not instantiate AuthorityKeyIdentifier extension.");
+        }
         addExtension(PKIXExtensions.AuthorityKey_Id.toString(), ext, info);
     }
 
diff --git a/base/server/cms/src/com/netscape/cms/profile/def/EnrollDefault.java b/base/server/cms/src/com/netscape/cms/profile/def/EnrollDefault.java
index 1d5bfc4..6192888 100644
--- a/base/server/cms/src/com/netscape/cms/profile/def/EnrollDefault.java
+++ b/base/server/cms/src/com/netscape/cms/profile/def/EnrollDefault.java
@@ -367,7 +367,7 @@ public abstract class EnrollDefault implements IPolicyDefault, ICertInfoPolicyDe
     protected void addExtension(String name, Extension ext, X509CertInfo info)
             throws EProfileException {
         if (ext == null) {
-            throw new EProfileException("extension not found");
+            throw new EProfileException("addExtension: extension '" + name + "' is null");
         }
         CertificateExtensions exts = null;
 
-- 
1.8.3.1