summaryrefslogtreecommitdiffstats
path: root/base/tps
diff options
context:
space:
mode:
authorAde Lee <alee@redhat.com>2015-02-11 16:28:50 -0500
committerAde Lee <alee@redhat.com>2015-02-26 23:21:46 -0500
commit705084a0021e161f1b4cea25dbaf622cfe68c47e (patch)
treebd423d083327a96423b9864e7851dffcc5b5ef99 /base/tps
parent3b6664da6c762a592573d5fa05043ecca20bf7a7 (diff)
downloadpki-705084a0021e161f1b4cea25dbaf622cfe68c47e.tar.gz
pki-705084a0021e161f1b4cea25dbaf622cfe68c47e.tar.xz
pki-705084a0021e161f1b4cea25dbaf622cfe68c47e.zip
Add granularity to token termination in TPS
BZ 1163987. Added revocation checks to optionally revoke expired certs, and handle cases where certs are shared on multiple tokens.
Diffstat (limited to 'base/tps')
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/TPSTokendb.java159
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/processor/TPSEnrollProcessor.java11
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/processor/TPSProcessor.java2
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/rest/TokenService.java23
4 files changed, 160 insertions, 35 deletions
diff --git a/base/tps/src/org/dogtagpki/server/tps/TPSTokendb.java b/base/tps/src/org/dogtagpki/server/tps/TPSTokendb.java
index bf86b19ed..c3fd70df9 100644
--- a/base/tps/src/org/dogtagpki/server/tps/TPSTokendb.java
+++ b/base/tps/src/org/dogtagpki/server/tps/TPSTokendb.java
@@ -20,6 +20,7 @@ package org.dogtagpki.server.tps;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
@@ -29,6 +30,7 @@ import netscape.security.x509.RevocationReason;
import org.dogtagpki.server.tps.cms.CARemoteRequestHandler;
import org.dogtagpki.server.tps.cms.CARevokeCertResponse;
+import org.dogtagpki.server.tps.dbs.ActivityDatabase;
import org.dogtagpki.server.tps.dbs.TPSCertRecord;
import org.dogtagpki.server.tps.dbs.TokenRecord;
import org.dogtagpki.tps.main.TPSException;
@@ -258,7 +260,7 @@ public class TPSTokendb {
* @param cuid the cuid of the token
* @return ArrayList of the cert records
*/
- public ArrayList<TPSCertRecord> tdbGetCertificatesByCUID(String cuid)
+ public ArrayList<TPSCertRecord> tdbGetCertRecordsByCUID(String cuid)
throws TPSException {
if (cuid == null)
throw new TPSException("TPSTokendb.tdbGetCertificatesByCUID: cuid null");
@@ -281,6 +283,36 @@ public class TPSTokendb {
return certRecords;
}
+ public ArrayList<TPSCertRecord> tdbGetCertRecordsByCert(String serial, String issuer)
+ throws TPSException {
+ if (serial == null)
+ throw new TPSException("TPSTokendb.tdbGetCertificatesBySerial: serial null");
+
+ if (issuer == null) {
+ throw new TPSException("TPSTokendb.tdbGetCertificatesBySerial: issuer null");
+ }
+
+ Map<String, String> attributes = new HashMap<String, String>();
+ attributes.put("serialNumber", serial);
+ attributes.put("issuedBy", issuer);
+
+ ArrayList<TPSCertRecord> certRecords = new ArrayList<TPSCertRecord>();
+ Iterator<TPSCertRecord> records;
+ try {
+ records = tps.certDatabase.findRecords(null, attributes).iterator();
+ } catch (Exception e) {
+ CMS.debug("TPSTokendb.tdbGetCertificatesByCUID:" + e);
+ throw new TPSException(e.getMessage());
+ }
+
+ while (records.hasNext()) {
+ TPSCertRecord certRecord = records.next();
+ certRecords.add(certRecord);
+ }
+
+ return certRecords;
+ }
+
public void tdbRemoveCertificatesByCUID(String cuid)
throws Exception {
String method = "TPSTokendb.tdbRemoveCertificatesByCUID";
@@ -306,20 +338,105 @@ public class TPSTokendb {
}
}
- public void revokeCertsByCUID(String cuid, String tokenReason) throws Exception {
+ public void revokeCertsByCUID(String cuid, String tokenReason, String ipAddress, String remoteUser)
+ throws Exception {
String method = "TPStokendb.revokeCertsByCUID";
CMS.debug(method + ": called");
if (cuid == null)
throw new TPSException(method + ": cuid null");
- revokeCertsByCUID(true, cuid, tokenReason);
+ revokeCertsByCUID(true, cuid, tokenReason, ipAddress, remoteUser);
}
- public void unRevokeCertsByCUID(String cuid) throws Exception {
+ public void unRevokeCertsByCUID(String cuid, String ipAddress, String remoteUser) throws Exception {
String method = "TPStokendb.unRevokeCertsByCUID";
CMS.debug(method + ": called");
if (cuid == null)
throw new TPSException(method + ": cuid null");
- revokeCertsByCUID(false, cuid, null /* null for unrevoke*/);
+ revokeCertsByCUID(false, cuid, null /* null for unrevoke*/, ipAddress, remoteUser);
+ }
+
+ private boolean isLastActiveSharedCert(String serial, String issuer, String cuid) throws TPSException {
+ ArrayList<TPSCertRecord> certRecords = tps.getTokendb().tdbGetCertRecordsByCert(serial, issuer);
+ for (TPSCertRecord cert : certRecords) {
+ // exclude current token
+ if (cert.getTokenID().equals(cuid))
+ continue;
+
+ if (cert.getStatus().equals("active"))
+ return false;
+ }
+
+ return true;
+ }
+
+ private boolean shouldRevoke(TPSCertRecord cert, String cuid, String tokenReason,
+ String ipAddress, String remoteUser) throws Exception {
+ IConfigStore configStore = CMS.getConfigStore();
+ String method = "TPStokendb.shouldRevoke";
+ String activityMsg;
+
+ if (cert == null) {
+ throw new TPSException(method + ": cert null");
+ }
+
+ String tokenType = cert.getType();
+ String keyType = cert.getKeyType();
+
+ // check if certificate revocation is enabled
+ String config = "op.enroll." + tokenType + ".keyGen." + keyType +
+ ".recovery." + tokenReason + ".revokeCert";
+ boolean revokeCerts = configStore.getBoolean(config, true);
+ if (!revokeCerts) {
+ activityMsg = "certificate revocation (serial " + cert.getSerialNumber() +
+ ") not enabled for tokenType: " + tokenType +
+ ", keyType: " + keyType +
+ ", state: " + tokenReason;
+
+ tdbActivity(ActivityDatabase.OP_DO_TOKEN, tdbGetTokenEntry(cuid),
+ ipAddress, activityMsg, "success", remoteUser);
+
+ return false;
+ }
+
+ // check if expired certificates should be revoked.
+ config = "op.enroll." + tokenType + ".keyGen." + keyType + ".recovery." +
+ tokenReason + ".revokeExpiredCerts";
+ boolean revokeExpiredCerts = configStore.getBoolean(config, true);
+ if (!revokeExpiredCerts) {
+ Date notBefore = cert.getValidNotBefore();
+ Date notAfter = cert.getValidNotAfter();
+ Date now = new Date();
+ if (now.after(notAfter)) {
+ activityMsg = "revocation not enabled for expired cert: " + cert.getSerialNumber();
+ tdbActivity(ActivityDatabase.OP_DO_TOKEN, tdbGetTokenEntry(cuid),
+ ipAddress, activityMsg, "success", remoteUser);
+ return false;
+ }
+ if (now.before(notBefore)) {
+ activityMsg = "revocation not enabled for cert that is not yet valid: " + cert.getSerialNumber();
+ tdbActivity(ActivityDatabase.OP_DO_TOKEN, tdbGetTokenEntry(cuid),
+ ipAddress, activityMsg, "success", remoteUser);
+ return false;
+ }
+ }
+
+ // check if certs on multiple tokens should be revoked
+ config = "op.enroll." + tokenType + ".keyGen." + keyType + ".recovery." +
+ tokenReason + ".holdRevocationUntilLastCredential";
+ boolean holdRevocation = configStore.getBoolean(config, false);
+ if (holdRevocation) {
+ if (!isLastActiveSharedCert(cert.getSerialNumber(), cert.getIssuedBy(), cuid)) {
+ activityMsg = "revocation not permitted as certificate " + cert.getSerialNumber() +
+ " is shared by anothr active token";
+
+ tdbActivity(ActivityDatabase.OP_DO_TOKEN, tdbGetTokenEntry(cuid),
+ ipAddress, activityMsg, "success", remoteUser);
+
+ return false;
+ }
+ }
+
+ return true;
}
/*
@@ -328,17 +445,19 @@ public class TPSTokendb {
* @param cuid cuid of token to revoke/unrevoke
* @param onHold true if revocation is to put onHold; false if to really revoke
*/
- private void revokeCertsByCUID(boolean isRevoke, String cuid, String tokenReason) throws Exception {
+ private void revokeCertsByCUID(boolean isRevoke, String cuid, String tokenReason,
+ String ipAddress, String remoteUser) throws Exception {
String method = "TPSTokendb.revokeCertsByCUID";
if (cuid == null)
throw new TPSException(method + ": cuid null");
String auditMsg;
IConfigStore configStore = CMS.getConfigStore();
- ArrayList<TPSCertRecord> certRecords = tps.getTokendb().tdbGetCertificatesByCUID(cuid);
+ ArrayList<TPSCertRecord> certRecords = tps.getTokendb().tdbGetCertRecordsByCUID(cuid);
if (tokenReason != null) {
if (!tokenReason.equalsIgnoreCase("onHold") &&
!tokenReason.equalsIgnoreCase("destroyed") &&
- !tokenReason.equalsIgnoreCase("keyCompromise")) {
+ !tokenReason.equalsIgnoreCase("keyCompromise") &&
+ !tokenReason.equalsIgnoreCase("terminated")) {
auditMsg = "unknown tokenRecord lost reason:" + tokenReason;
CMS.debug(method + ":" + auditMsg);
throw new Exception(method + ":" + auditMsg);
@@ -355,13 +474,8 @@ public class TPSTokendb {
if (isRevoke) {
auditMsg = "called to revoke";
CMS.debug(method + ":" + auditMsg);
- boolean revokeCert = false;
+ boolean revokeCert = shouldRevoke(cert, cuid, tokenReason, ipAddress, remoteUser);
- // get revoke or not
- config = "op.enroll." + cert.getType() + ".keyGen." + cert.getKeyType() +
- ".recovery." + tokenReason + ".revokeCert";
- //TODO: temporaryToken doesn't have all params; default to false if not found for now
- revokeCert = configStore.getBoolean(config, false); // default to false
if (!revokeCert) {
auditMsg = "cert not to be revoked:" + cert.getSerialNumber();
CMS.debug(method + ":" + auditMsg);
@@ -407,20 +521,29 @@ public class TPSTokendb {
// update certificate status
if (isRevoke) {
if (revokeReason == RevocationReason.CERTIFICATE_HOLD) {
- cert.setStatus("revoked_on_hold");
+ updateCertsStatus(cert.getSerialNumber(), cert.getIssuedBy(), "revoked_on_hold");
} else {
- cert.setStatus("revoked");
+ updateCertsStatus(cert.getSerialNumber(), cert.getIssuedBy(), "revoked");
}
} else {
- cert.setStatus("active");
+ updateCertsStatus(cert.getSerialNumber(), cert.getIssuedBy(), "active");
}
- tps.certDatabase.updateRecord(cert.getId(), cert);
+
auditMsg = "cert (un)revoked:" + cert.getSerialNumber();
CMS.debug(method + ":" + auditMsg);
//TODO: tdbActivity
}
}
+ public void updateCertsStatus(String serial, String issuer, String status) throws Exception {
+ ArrayList<TPSCertRecord> certRecords = tps.getTokendb().tdbGetCertRecordsByCert(serial, issuer);
+
+ for (TPSCertRecord certRecord : certRecords) {
+ certRecord.setStatus(status);
+ tps.certDatabase.updateRecord(certRecord.getId(), certRecord);
+ }
+ }
+
public void tdbAddCertEntry(TPSCertRecord certRecord, String status)
throws Exception {
certRecord.setStatus(status);
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 482236bc3..c74fe2cb6 100644
--- a/base/tps/src/org/dogtagpki/server/tps/processor/TPSEnrollProcessor.java
+++ b/base/tps/src/org/dogtagpki/server/tps/processor/TPSEnrollProcessor.java
@@ -1004,7 +1004,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.tdbGetCertificatesByCUID(tokenRecord.getId());
+ ArrayList<TPSCertRecord> allCerts = tps.tdb.tdbGetCertRecordsByCUID(tokenRecord.getId());
certsInfo.setNumCertsToEnroll(keyTypeNum);
@@ -1366,7 +1366,7 @@ public class TPSEnrollProcessor extends TPSProcessor {
actualCertIndex++;
}
- ArrayList<TPSCertRecord> certs = tps.tdb.tdbGetCertificatesByCUID(toBeRecovered.getId());
+ ArrayList<TPSCertRecord> certs = tps.tdb.tdbGetCertRecordsByCUID(toBeRecovered.getId());
String serialToRecover = null;
TPSCertRecord certToRecover = null;
@@ -1441,10 +1441,11 @@ public class TPSEnrollProcessor extends TPSProcessor {
}
}
- // set cert status to active
- certToRecover.setStatus("active");
try {
- tps.tdb.tdbUpdateCertEntry(certToRecover);
+ // set cert status to active
+ tps.tdb.updateCertsStatus(certToRecover.getSerialNumber(),
+ certToRecover.getIssuedBy(),
+ "active");
} catch (Exception e) {
auditMsg = "failed tdbUpdateCertEntry";
CMS.debug(method + ":" + auditMsg);
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 1a87f3e3c..895893924 100644
--- a/base/tps/src/org/dogtagpki/server/tps/processor/TPSProcessor.java
+++ b/base/tps/src/org/dogtagpki/server/tps/processor/TPSProcessor.java
@@ -1195,7 +1195,7 @@ public class TPSProcessor {
throw new TPSException(auditMsg, TPSStatus.STATUS_ERROR_REVOKE_CERTIFICATES_FAILED);
}
//find all certs belonging to the token
- ArrayList<TPSCertRecord> certRecords = tps.tdb.tdbGetCertificatesByCUID(cuid);
+ ArrayList<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 fc04759be..b67922e48 100644
--- a/base/tps/src/org/dogtagpki/server/tps/rest/TokenService.java
+++ b/base/tps/src/org/dogtagpki/server/tps/rest/TokenService.java
@@ -121,7 +121,8 @@ public class TokenService extends PKIService implements TokenResource {
return TokenStatus.PERM_LOST;
}
- public void setTokenStatus(TokenRecord tokenRecord, TokenStatus tokenState) throws Exception {
+ public void setTokenStatus(TokenRecord tokenRecord, TokenStatus tokenState, String ipAddress, String remoteUser)
+ throws Exception {
TPSSubsystem tps = (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
switch (tokenState) {
@@ -135,7 +136,7 @@ public class TokenService extends PKIService implements TokenResource {
if (origStatus.equalsIgnoreCase("lost") &&
origReason.equalsIgnoreCase("onHold")) {
//unrevoke certs
- tps.tdb.unRevokeCertsByCUID(tokenRecord.getId());
+ tps.tdb.unRevokeCertsByCUID(tokenRecord.getId(), ipAddress, remoteUser);
}
tokenRecord.setStatus("active");
@@ -147,14 +148,14 @@ public class TokenService extends PKIService implements TokenResource {
tokenRecord.setReason("keyCompromise");
//revoke certs
- tps.tdb.revokeCertsByCUID(tokenRecord.getId(), "keyCompromise");
+ tps.tdb.revokeCertsByCUID(tokenRecord.getId(), "keyCompromise", ipAddress, remoteUser);
break;
case DAMAGED:
tokenRecord.setStatus("lost");
tokenRecord.setReason("destroyed");
//revoke certs
- tps.tdb.revokeCertsByCUID(tokenRecord.getId(), "destroyed");
+ tps.tdb.revokeCertsByCUID(tokenRecord.getId(), "destroyed", ipAddress, remoteUser);
break;
case TEMP_LOST:
@@ -162,10 +163,10 @@ public class TokenService extends PKIService implements TokenResource {
tokenRecord.setReason("onHold");
// put certs onHold
- tps.tdb.revokeCertsByCUID(tokenRecord.getId(), "onHold");
+ tps.tdb.revokeCertsByCUID(tokenRecord.getId(), "onHold", ipAddress, remoteUser);
break;
case TERMINATED:
- String reason = "keyCompromise";
+ String reason = "terminated";
String origStatus2 = tokenRecord.getStatus();
String origReason2 = tokenRecord.getReason();
// temp token looks at "onHold"
@@ -177,7 +178,7 @@ public class TokenService extends PKIService implements TokenResource {
tokenRecord.setReason(reason);
//revoke certs
- tps.tdb.revokeCertsByCUID(tokenRecord.getId(), reason) ;
+ tps.tdb.revokeCertsByCUID(tokenRecord.getId(), reason, ipAddress, remoteUser) ;
break;
default:
throw new PKIException("Unsupported token state: " + tokenState);
@@ -213,13 +214,13 @@ public class TokenService extends PKIService implements TokenResource {
return tokenData;
}
- public TokenRecord createTokenRecord(TokenData tokenData) throws Exception {
+ public TokenRecord createTokenRecord(TokenData tokenData, String ipAddress, String remoteUser) throws Exception {
TokenRecord tokenRecord = new TokenRecord();
tokenRecord.setId(tokenData.getID());
tokenRecord.setUserID(tokenData.getUserID());
tokenRecord.setType(tokenData.getType());
- setTokenStatus(tokenRecord, tokenData.getStatus());
+ setTokenStatus(tokenRecord, tokenData.getStatus(), ipAddress, remoteUser);
tokenRecord.setAppletID(tokenData.getAppletID());
tokenRecord.setKeyInfo(tokenData.getKeyInfo());
tokenRecord.setPolicy(tokenData.getPolicy());
@@ -320,7 +321,7 @@ public class TokenService extends PKIService implements TokenResource {
// new tokens are uninitialized when created
tokenData.setStatus(TokenStatus.UNINITIALIZED);
- tokenRecord = createTokenRecord(tokenData);
+ tokenRecord = createTokenRecord(tokenData, ipAddress, remoteUser);
tokenRecord.setId(tokenID);
database.addRecord(tokenID, tokenRecord);
subsystem.tdb.tdbActivity(ActivityDatabase.OP_ADD, tokenRecord,
@@ -506,7 +507,7 @@ public class TokenService extends PKIService implements TokenResource {
}
CMS.debug("TokenService.changeTokenStatus(): next status allowed: " + tokenStatus);
- setTokenStatus(tokenRecord, tokenStatus);
+ setTokenStatus(tokenRecord, tokenStatus, ipAddress, remoteUser);
database.updateRecord(tokenID, tokenRecord);
subsystem.tdb.tdbActivity(ActivityDatabase.OP_DO_TOKEN, tokenRecord,
ipAddress, msg, "success",