diff options
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", |