>From 8894d98714f0c03966d96173e20128183b082733 Mon Sep 17 00:00:00 2001
From: "Endi S. Dewata" <edewata@redhat.com>
Date: Tue, 15 Mar 2016 16:13:10 +0100
Subject: [PATCH] Fixed illegal token state transition via TEMP_LOST.

The TokenService.setTokenStatus() has been modified to restore
the temporarily lost token back into either uninitialized or
active state based on whether the token has certificates.

The TPSTokendb.tdbGetCertRecordsByCUID() has been modified to use
only tokenID attribute to search for token certificates more
accurately. It also has been simplified to return the certificate
records collection object directly.

Some constructors were added to the TPSException to allow chaining
the exception cause.

https://fedorahosted.org/pki/ticket/1808
---
 .../src/org/dogtagpki/tps/main/TPSException.java   | 23 ++++++++++++----
 .../src/org/dogtagpki/server/tps/TPSTokendb.java   | 24 ++++++----------
 .../server/tps/processor/TPSEnrollProcessor.java   |  5 ++--
 .../server/tps/processor/TPSProcessor.java         |  4 +--
 .../dogtagpki/server/tps/rest/TokenService.java    | 32 +++++++++++++++++++---
 5 files changed, 60 insertions(+), 28 deletions(-)

diff --git a/base/common/src/org/dogtagpki/tps/main/TPSException.java b/base/common/src/org/dogtagpki/tps/main/TPSException.java
index 940e89ad1172e3d25c9d858864776766d4cf2352..4ff7e4c541f0be6484ea59d3459af92b4cb2378d 100644
--- a/base/common/src/org/dogtagpki/tps/main/TPSException.java
+++ b/base/common/src/org/dogtagpki/tps/main/TPSException.java
@@ -26,16 +26,29 @@ public class TPSException extends EBaseException {
     private static final long serialVersionUID = -678878301521643436L;
     private TPSStatus status;
 
-    public TPSException(String e) {
-        super(e);
+    public TPSException(String message) {
+        super(message);
         status = TPSStatus.STATUS_ERROR_CONTACT_ADMIN;
     }
 
-    public TPSException(String msg, TPSStatus theStatus) {
+    public TPSException(String message, TPSStatus status) {
+        super(message);
+        this.status = status;
+    }
+
+    public TPSException(Throwable cause) {
+        super(cause.getMessage(), cause);
+        status = TPSStatus.STATUS_ERROR_CONTACT_ADMIN;
+    }
 
-        super(msg);
-        status = theStatus;
+    public TPSException(String message, Throwable cause) {
+        super(message, cause);
+        status = TPSStatus.STATUS_ERROR_CONTACT_ADMIN;
+    }
 
+    public TPSException(String message, TPSStatus status, Throwable cause) {
+        super(message, cause);
+        this.status = status;
     }
 
     public TPSStatus getStatus() {
diff --git a/base/tps/src/org/dogtagpki/server/tps/TPSTokendb.java b/base/tps/src/org/dogtagpki/server/tps/TPSTokendb.java
index 5a53ff7a50678f69ca0844e94ed828db839ec650..15e85fb32e0b515e7fd47f3fc6b77643c8abc181 100644
--- a/base/tps/src/org/dogtagpki/server/tps/TPSTokendb.java
+++ b/base/tps/src/org/dogtagpki/server/tps/TPSTokendb.java
@@ -299,29 +299,23 @@ public class TPSTokendb {
     /*
      * tdbGetCertificatesByCUID finds and returns certificate records belong to a token cuid
      * @param cuid the cuid of the token
-     * @return ArrayList of the cert records
+     * @return Collection of the cert records
      */
-    public ArrayList<TPSCertRecord> tdbGetCertRecordsByCUID(String cuid)
+    public Collection<TPSCertRecord> tdbGetCertRecordsByCUID(String cuid)
             throws TPSException {
+
         if (cuid == null)
             throw new TPSException("TPSTokendb.tdbGetCertificatesByCUID: cuid null");
 
-        ArrayList<TPSCertRecord> certRecords = new ArrayList<TPSCertRecord>();
-        String filter = cuid;
-        Iterator<TPSCertRecord> records;
+        Map<String, String> attributes = new HashMap<String, String>();
+        attributes.put("tokenID",  cuid);
+
         try {
-             records = tps.certDatabase.findRecords(filter).iterator();
+             return tps.certDatabase.findRecords(null, attributes);
         } catch (Exception e) {
             CMS.debug("TPSTokendb.tdbGetCertificatesByCUID:" + e);
-            throw new TPSException(e.getMessage());
+            throw new TPSException(e);
         }
-
-        while (records.hasNext()) {
-            TPSCertRecord certRecord = records.next();
-            certRecords.add(certRecord);
-        }
-
-        return certRecords;
     }
 
     public ArrayList<TPSCertRecord> tdbGetCertRecordsByCert(String serial, String issuer)
@@ -493,7 +487,7 @@ public class TPSTokendb {
             throw new TPSException(method + ": cuid null");
         String logMsg;
         IConfigStore configStore = CMS.getConfigStore();
-        ArrayList<TPSCertRecord> certRecords = tps.getTokendb().tdbGetCertRecordsByCUID(cuid);
+        Collection<TPSCertRecord> certRecords = tps.getTokendb().tdbGetCertRecordsByCUID(cuid);
         if (tokenReason != null) {
             if (!tokenReason.equalsIgnoreCase("onHold") &&
                     !tokenReason.equalsIgnoreCase("destroyed") &&
diff --git a/base/tps/src/org/dogtagpki/server/tps/processor/TPSEnrollProcessor.java b/base/tps/src/org/dogtagpki/server/tps/processor/TPSEnrollProcessor.java
index 46421068f56ea6c3b306ad4049cec6f8d8704c37..07f7fa0d02582865553ae1de591e5667dcd1bd44 100644
--- a/base/tps/src/org/dogtagpki/server/tps/processor/TPSEnrollProcessor.java
+++ b/base/tps/src/org/dogtagpki/server/tps/processor/TPSEnrollProcessor.java
@@ -6,6 +6,7 @@ import java.security.InvalidKeyException;
 import java.security.NoSuchAlgorithmException;
 import java.security.cert.CertificateException;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Date;
 import java.util.Enumeration;
 import java.util.LinkedHashMap;
@@ -1404,7 +1405,7 @@ public class TPSEnrollProcessor extends TPSProcessor {
          * Get certs from the tokendb for this token to find out about
          * renewal possibility
          */
-        ArrayList<TPSCertRecord> allCerts = tps.tdb.tdbGetCertRecordsByCUID(tokenRecord.getId());
+        Collection<TPSCertRecord> allCerts = tps.tdb.tdbGetCertRecordsByCUID(tokenRecord.getId());
 
         certsInfo.setNumCertsToEnroll(keyTypeNum);
 
@@ -1767,7 +1768,7 @@ public class TPSEnrollProcessor extends TPSProcessor {
                     actualCertIndex++;
                 }
 
-                ArrayList<TPSCertRecord> certs = tps.tdb.tdbGetCertRecordsByCUID(toBeRecovered.getId());
+                Collection<TPSCertRecord> certs = tps.tdb.tdbGetCertRecordsByCUID(toBeRecovered.getId());
 
                 String serialToRecover = null;
                 TPSCertRecord certToRecover = null;
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 05742842f0211a70aa87f78e6ee984f3e12884e0..53af08a05dad54f3c81a82d5d0bfc72add54565c 100644
--- a/base/tps/src/org/dogtagpki/server/tps/processor/TPSProcessor.java
+++ b/base/tps/src/org/dogtagpki/server/tps/processor/TPSProcessor.java
@@ -23,8 +23,8 @@ import java.math.BigInteger;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
-import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.Enumeration;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -1473,7 +1473,7 @@ public class TPSProcessor {
             throw new TPSException(logMsg, TPSStatus.STATUS_ERROR_REVOKE_CERTIFICATES_FAILED);
         }
         //find all certs belonging to the token
-        ArrayList<TPSCertRecord> certRecords = tps.tdb.tdbGetCertRecordsByCUID(cuid);
+        Collection<TPSCertRecord> certRecords = tps.tdb.tdbGetCertRecordsByCUID(cuid);
 
         CMS.debug(method + ": found " + certRecords.size() + " certs");
 
diff --git a/base/tps/src/org/dogtagpki/server/tps/rest/TokenService.java b/base/tps/src/org/dogtagpki/server/tps/rest/TokenService.java
index b3608aef2fff1d12352dc74bce6f89388dffa1ee..226f039f489e15ce7a9e1a790ce0cfe3c08f7ad1 100644
--- a/base/tps/src/org/dogtagpki/server/tps/rest/TokenService.java
+++ b/base/tps/src/org/dogtagpki/server/tps/rest/TokenService.java
@@ -39,6 +39,7 @@ import javax.ws.rs.core.UriInfo;
 import org.apache.commons.lang.StringUtils;
 import org.dogtagpki.server.tps.TPSSubsystem;
 import org.dogtagpki.server.tps.dbs.ActivityDatabase;
+import org.dogtagpki.server.tps.dbs.TPSCertRecord;
 import org.dogtagpki.server.tps.dbs.TokenDatabase;
 import org.dogtagpki.server.tps.dbs.TokenRecord;
 import org.dogtagpki.server.tps.engine.TPSEngine;
@@ -139,18 +140,37 @@ public class TokenService extends PKIService implements TokenResource {
             tokenRecord.setStatus("uninitialized");
             tokenRecord.setReason(null);
             break;
+
         case ACTIVE:
             String origStatus = tokenRecord.getStatus();
             String origReason = tokenRecord.getReason();
+
             if (origStatus.equalsIgnoreCase("lost") &&
                     origReason.equalsIgnoreCase("onHold")) {
-                //unrevoke certs
-                tps.tdb.unRevokeCertsByCUID(tokenRecord.getId(), ipAddress, remoteUser);
+
+                Collection<TPSCertRecord> certRecords = tps.tdb.tdbGetCertRecordsByCUID(tokenRecord.getId());
+                if (certRecords.isEmpty()) { // token was uninitialized
+                    // restore to uninitialized state
+                    tokenRecord.setStatus("uninitialized");
+                    tokenRecord.setReason(null);
+
+                } else { // token was active
+                    // unrevoke certs
+                    tps.tdb.unRevokeCertsByCUID(tokenRecord.getId(), ipAddress, remoteUser);
+
+                    // restore to active state
+                    tokenRecord.setStatus("active");
+                    tokenRecord.setReason(null);
+                }
+
+            } else {
+                // switch to active state
+                tokenRecord.setStatus("active");
+                tokenRecord.setReason(null);
             }
 
-            tokenRecord.setStatus("active");
-            tokenRecord.setReason(null);
             break;
+
         case PERM_LOST:
         case TEMP_LOST_PERM_LOST:
             tokenRecord.setStatus("lost");
@@ -159,6 +179,7 @@ public class TokenService extends PKIService implements TokenResource {
             //revoke certs
             tps.tdb.revokeCertsByCUID(tokenRecord.getId(), "keyCompromise", ipAddress, remoteUser);
             break;
+
         case DAMAGED:
             tokenRecord.setStatus("lost");
             tokenRecord.setReason("destroyed");
@@ -167,6 +188,7 @@ public class TokenService extends PKIService implements TokenResource {
             tps.tdb.revokeCertsByCUID(tokenRecord.getId(), "destroyed", ipAddress, remoteUser);
 
             break;
+
         case TEMP_LOST:
             tokenRecord.setStatus("lost");
             tokenRecord.setReason("onHold");
@@ -174,6 +196,7 @@ public class TokenService extends PKIService implements TokenResource {
             // put certs onHold
             tps.tdb.revokeCertsByCUID(tokenRecord.getId(), "onHold", ipAddress, remoteUser);
             break;
+
         case TERMINATED:
             String reason = "terminated";
             String origStatus2 = tokenRecord.getStatus();
@@ -189,6 +212,7 @@ public class TokenService extends PKIService implements TokenResource {
             //revoke certs
             tps.tdb.revokeCertsByCUID(tokenRecord.getId(), reason, ipAddress, remoteUser) ;
             break;
+
         default:
             throw new PKIException("Unsupported token state: " + tokenState);
         }
-- 
2.4.3

