use of org.bouncycastle.asn1.x509.CRLReason in project jruby-openssl by jruby.
the class X509Extension method value.
@JRubyMethod
public RubyString value(final ThreadContext context) {
if (this.value instanceof RubyString) {
// return the same as set
return (RubyString) this.value;
}
final Ruby runtime = context.runtime;
final String oid = getRealObjectID().getId();
try {
if (oid.equals("2.5.29.19")) {
// basicConstraints
ASN1Sequence seq2 = (ASN1Sequence) ASN1.readObject(getRealValueEncoded());
final ByteList val = new ByteList(32);
if (seq2.size() > 0) {
val.append(CA_);
ASN1Encodable obj0 = seq2.getObjectAt(0);
final boolean bool;
if (obj0 instanceof ASN1Boolean) {
bool = ((ASN1Boolean) obj0).isTrue();
} else {
// NOTE: keep it due BC <= 1.50
bool = ((DERBoolean) obj0).isTrue();
}
val.append(bool ? TRUE : FALSE);
}
if (seq2.size() > 1) {
val.append(", pathlen:".getBytes());
val.append(seq2.getObjectAt(1).toString().getBytes());
}
return runtime.newString(val);
}
if (oid.equals("2.5.29.15")) {
// keyUsage
final byte[] enc = getRealValueEncoded();
byte b3 = 0;
byte b2 = enc[2];
if (enc.length > 3)
b3 = enc[3];
final ByteList val = new ByteList(64);
byte[] sep = _;
if ((b2 & (byte) 128) != 0) {
val.append(sep);
val.append(Decipher_Only);
sep = SEP;
}
if ((b3 & (byte) 128) != 0) {
val.append(sep);
val.append(Digital_Signature);
sep = SEP;
}
if ((b3 & (byte) 64) != 0) {
val.append(sep);
val.append(Non_Repudiation);
sep = SEP;
}
if ((b3 & (byte) 32) != 0) {
val.append(sep);
val.append(Key_Encipherment);
sep = SEP;
}
if ((b3 & (byte) 16) != 0) {
val.append(sep);
val.append(Data_Encipherment);
sep = SEP;
}
if ((b3 & (byte) 8) != 0) {
val.append(sep);
val.append(Key_Agreement);
sep = SEP;
}
if ((b3 & (byte) 4) != 0) {
val.append(sep);
val.append(Certificate_Sign);
sep = SEP;
}
if ((b3 & (byte) 2) != 0) {
val.append(sep);
val.append(CRL_Sign);
sep = SEP;
}
if ((b3 & (byte) 1) != 0) {
// sep = SEP;
val.append(sep);
// sep = SEP;
val.append(Encipher_Only);
}
return runtime.newString(val);
}
if (oid.equals("2.16.840.1.113730.1.1")) {
// nsCertType
final byte b0 = getRealValueEncoded()[0];
final ByteList val = new ByteList(64);
byte[] sep = _;
if ((b0 & (byte) 128) != 0) {
val.append(sep);
val.append(SSL_Client);
sep = SEP;
}
if ((b0 & (byte) 64) != 0) {
val.append(sep);
val.append(SSL_Server);
sep = SEP;
}
if ((b0 & (byte) 32) != 0) {
val.append(sep);
val.append(SMIME);
sep = SEP;
}
if ((b0 & (byte) 16) != 0) {
val.append(sep);
val.append(Object_Signing);
sep = SEP;
}
if ((b0 & (byte) 8) != 0) {
val.append(sep);
val.append(Unused);
sep = SEP;
}
if ((b0 & (byte) 4) != 0) {
val.append(sep);
val.append(SSL_CA);
sep = SEP;
}
if ((b0 & (byte) 2) != 0) {
val.append(sep);
val.append(SMIME_CA);
sep = SEP;
}
if ((b0 & (byte) 1) != 0) {
val.append(sep);
val.append(Object_Signing_CA);
}
return runtime.newString(val);
}
if (oid.equals("2.5.29.14")) {
// subjectKeyIdentifier
ASN1Encodable value = getRealValue();
if (value instanceof ASN1OctetString) {
byte[] octets = ((ASN1OctetString) value).getOctets();
if (octets.length > 0 && octets[0] == BERTags.OCTET_STRING) {
// read nested octets
value = ASN1.readObject(octets);
}
}
return runtime.newString(hexBytes(keyidBytes(value.toASN1Primitive()), 0));
}
if (oid.equals("2.5.29.35")) {
// authorityKeyIdentifier
ASN1Encodable value = getRealValue();
if (value instanceof ASN1OctetString) {
value = ASN1.readObject(((ASN1OctetString) value).getOctets());
}
final ByteList val = new ByteList(72);
val.append(keyid_);
if (value instanceof ASN1Sequence) {
final ASN1Sequence seq = (ASN1Sequence) value;
final int size = seq.size();
if (size == 0)
return RubyString.newEmptyString(runtime);
ASN1Primitive keyid = seq.getObjectAt(0).toASN1Primitive();
hexBytes(keyidBytes(keyid), val).append('\n');
for (int i = 1; i < size; i++) {
final ASN1Encodable issuer = seq.getObjectAt(i);
// NOTE: blindly got OpenSSL tests passing (likely in-complete) :
if (issuer instanceof ASN1TaggedObject) {
ASN1Primitive obj = ((ASN1TaggedObject) issuer).getObject();
switch(((ASN1TaggedObject) issuer).getTagNo()) {
case 1:
if (obj instanceof ASN1TaggedObject) {
formatGeneralName(GeneralName.getInstance(obj), val, true);
}
break;
case // serial
2:
val.append(new byte[] { 's', 'e', 'r', 'i', 'a', 'l', ':' });
if (obj instanceof ASN1Integer) {
hexBytes(((ASN1Integer) obj).getValue().toByteArray(), val);
} else {
hexBytes(((ASN1OctetString) obj).getOctets(), val);
}
break;
}
}
val.append('\n');
}
return runtime.newString(val);
}
hexBytes(keyidBytes(value.toASN1Primitive()), val).append('\n');
return runtime.newString(val);
}
if (oid.equals("2.5.29.21")) {
// CRLReason
final IRubyObject value = getValue(runtime);
switch(RubyNumeric.fix2int(value)) {
case 0:
return runtime.newString(new ByteList(Unspecified));
case 1:
return RubyString.newString(runtime, "Key Compromise");
case 2:
return RubyString.newString(runtime, "CA Compromise");
case 3:
return RubyString.newString(runtime, "Affiliation Changed");
case 4:
return RubyString.newString(runtime, "Superseded");
case 5:
return RubyString.newString(runtime, "Cessation Of Operation");
case 6:
return RubyString.newString(runtime, "Certificate Hold");
case 8:
return RubyString.newString(runtime, "Remove From CRL");
case 9:
return RubyString.newString(runtime, "Privilege Withdrawn");
default:
return runtime.newString(new ByteList(Unspecified));
}
}
if (oid.equals("2.5.29.17") || oid.equals("2.5.29.18")) {
// subjectAltName || issuerAltName
try {
ASN1Encodable value = getRealValue();
final ByteList val = new ByteList(64);
if (value instanceof ASN1TaggedObject) {
formatGeneralName(GeneralName.getInstance(value), val, false);
return runtime.newString(val);
}
if (value instanceof GeneralName) {
formatGeneralName((GeneralName) value, val, false);
return runtime.newString(val);
}
if (value instanceof ASN1OctetString) {
// decoded octets will end up as an ASN1Sequence instance :
value = ASN1.readObject(((ASN1OctetString) value).getOctets());
}
if (value instanceof ASN1TaggedObject) {
// DERTaggedObject (issuerAltName wrapping)
formatGeneralName(GeneralName.getInstance(value), val, false);
return runtime.newString(val);
}
final GeneralName[] names = GeneralNames.getInstance(value).getNames();
for (int i = 0; i < names.length; i++) {
boolean other = formatGeneralName(names[i], val, false);
if (i < names.length - 1) {
if (other)
val.append(';');
else
val.append(',').append(' ');
}
}
return runtime.newString(val);
} catch (IllegalArgumentException e) {
debugStackTrace(runtime, e);
return rawValueAsString(context);
}
}
if (oid.equals("2.5.29.37")) {
// extendedKeyUsage
final ByteList val = new ByteList(64);
if (this.value instanceof ASN1Sequence) {
// opt "short" path
final ASN1Sequence seq = (ASN1Sequence) this.value;
final int size = seq.size();
for (int i = 0; i < size; i++) {
ASN1Encodable o = seq.getObjectAt(i);
String name = o.toString();
Integer nid = ASN1.oid2nid(runtime, new ASN1ObjectIdentifier(name));
if (nid != null)
name = ASN1.nid2ln(runtime, nid);
if (name == null)
name = o.toString();
val.append(ByteList.plain(name));
if (i < size - 1)
val.append(',').append(' ');
}
return runtime.newString(val);
}
final IRubyObject value = getValue(runtime);
if (value instanceof RubyArray) {
final RubyArray arr = (RubyArray) value;
final int size = arr.size();
for (int i = 0; i < size; i++) {
IRubyObject entry = arr.eltInternal(i);
if ("ObjectId".equals(entry.getMetaClass().getBaseName())) {
entry = entry.callMethod(context, "ln");
} else if (entry.respondsTo("value")) {
entry = entry.callMethod(context, "value");
}
val.append(entry.asString().getByteList());
if (i < size - 1)
val.append(',').append(' ');
}
}
return runtime.newString(val);
}
return rawValueAsString(context);
} catch (IOException e) {
debugStackTrace(runtime, e);
throw newExtensionError(runtime, e);
}
}
use of org.bouncycastle.asn1.x509.CRLReason in project xipki by xipki.
the class CertStoreQueryExecutor method revokeSuspendedCert.
// method revokeCert
X509CertWithRevocationInfo revokeSuspendedCert(NameId ca, BigInteger serialNumber, CrlReason reason, boolean publishToDeltaCrlCache, CaIdNameMap idNameMap) throws OperationException, DataAccessException {
ParamUtil.requireNonNull("ca", ca);
ParamUtil.requireNonNull("serialNumber", serialNumber);
ParamUtil.requireNonNull("reason", reason);
X509CertWithRevocationInfo certWithRevInfo = getCertWithRevocationInfo(ca, serialNumber, idNameMap);
if (certWithRevInfo == null) {
LOG.warn("certificate with CA={} and serialNumber={} does not exist", ca.getName(), LogUtil.formatCsn(serialNumber));
return null;
}
CertRevocationInfo currentRevInfo = certWithRevInfo.getRevInfo();
if (currentRevInfo == null) {
throw new OperationException(ErrorCode.CERT_UNREVOKED, "certificate is not revoked");
}
CrlReason currentReason = currentRevInfo.getReason();
if (currentReason != CrlReason.CERTIFICATE_HOLD) {
throw new OperationException(ErrorCode.CERT_REVOKED, "certificate is revoked but not with reason " + CrlReason.CERTIFICATE_HOLD.getDescription());
}
long certId = certWithRevInfo.getCert().getCertId().longValue();
PreparedStatement ps = borrowPreparedStatement(SQLs.SQL_REVOKE_SUSPENDED_CERT);
try {
int idx = 1;
ps.setLong(idx++, System.currentTimeMillis() / 1000);
ps.setInt(idx++, reason.getCode());
ps.setLong(idx++, certId);
int count = ps.executeUpdate();
if (count != 1) {
String message = (count > 1) ? count + " rows modified, but exactly one is expected" : "no row is modified, but exactly one is expected";
throw new OperationException(ErrorCode.SYSTEM_FAILURE, message);
}
} catch (SQLException ex) {
throw datasource.translate(SQLs.SQL_REVOKE_CERT, ex);
} finally {
releaseDbResources(ps, null);
}
if (publishToDeltaCrlCache) {
publishToDeltaCrlCache(ca, certWithRevInfo.getCert().getCert().getSerialNumber());
}
currentRevInfo.setReason(reason);
return certWithRevInfo;
}
use of org.bouncycastle.asn1.x509.CRLReason in project xipki by xipki.
the class CertStoreQueryExecutor method revokeCert.
// method addCrl
X509CertWithRevocationInfo revokeCert(NameId ca, BigInteger serialNumber, CertRevocationInfo revInfo, boolean force, boolean publishToDeltaCrlCache, CaIdNameMap idNameMap) throws OperationException, DataAccessException {
ParamUtil.requireNonNull("ca", ca);
ParamUtil.requireNonNull("serialNumber", serialNumber);
ParamUtil.requireNonNull("revInfo", revInfo);
X509CertWithRevocationInfo certWithRevInfo = getCertWithRevocationInfo(ca, serialNumber, idNameMap);
if (certWithRevInfo == null) {
LOG.warn("certificate with CA={} and serialNumber={} does not exist", ca.getName(), LogUtil.formatCsn(serialNumber));
return null;
}
CertRevocationInfo currentRevInfo = certWithRevInfo.getRevInfo();
if (currentRevInfo != null) {
CrlReason currentReason = currentRevInfo.getReason();
if (currentReason == CrlReason.CERTIFICATE_HOLD) {
if (revInfo.getReason() == CrlReason.CERTIFICATE_HOLD) {
throw new OperationException(ErrorCode.CERT_REVOKED, "certificate already revoked with the requested reason " + currentReason.getDescription());
} else {
revInfo.setRevocationTime(currentRevInfo.getRevocationTime());
revInfo.setInvalidityTime(currentRevInfo.getInvalidityTime());
}
} else if (!force) {
throw new OperationException(ErrorCode.CERT_REVOKED, "certificate already revoked with reason " + currentReason.getDescription());
}
}
long certId = certWithRevInfo.getCert().getCertId().longValue();
long revTimeSeconds = revInfo.getRevocationTime().getTime() / 1000;
Long invTimeSeconds = null;
if (revInfo.getInvalidityTime() != null) {
invTimeSeconds = revInfo.getInvalidityTime().getTime() / 1000;
}
PreparedStatement ps = borrowPreparedStatement(SQLs.SQL_REVOKE_CERT);
try {
int idx = 1;
ps.setLong(idx++, System.currentTimeMillis() / 1000);
setBoolean(ps, idx++, true);
ps.setLong(idx++, revTimeSeconds);
setLong(ps, idx++, invTimeSeconds);
ps.setInt(idx++, revInfo.getReason().getCode());
ps.setLong(idx++, certId);
int count = ps.executeUpdate();
if (count != 1) {
String message = (count > 1) ? count + " rows modified, but exactly one is expected" : "no row is modified, but exactly one is expected";
throw new OperationException(ErrorCode.SYSTEM_FAILURE, message);
}
} catch (SQLException ex) {
throw datasource.translate(SQLs.SQL_REVOKE_CERT, ex);
} finally {
releaseDbResources(ps, null);
}
if (publishToDeltaCrlCache) {
publishToDeltaCrlCache(ca, certWithRevInfo.getCert().getCert().getSerialNumber());
}
certWithRevInfo.setRevInfo(revInfo);
return certWithRevInfo;
}
use of org.bouncycastle.asn1.x509.CRLReason in project xipki by xipki.
the class X509CaCmpResponderImpl method unRevokeRemoveCertificates.
private PKIBody unRevokeRemoveCertificates(PKIMessage request, RevReqContent rr, int permission, CmpControl cmpControl, String msgId) {
RevDetails[] revContent = rr.toRevDetailsArray();
RevRepContentBuilder repContentBuilder = new RevRepContentBuilder();
final int n = revContent.length;
// test the request
for (int i = 0; i < n; i++) {
RevDetails revDetails = revContent[i];
CertTemplate certDetails = revDetails.getCertDetails();
X500Name issuer = certDetails.getIssuer();
ASN1Integer serialNumber = certDetails.getSerialNumber();
try {
X500Name caSubject = getCa().getCaInfo().getCert().getSubjectAsX500Name();
if (issuer == null) {
return buildErrorMsgPkiBody(PKIStatus.rejection, PKIFailureInfo.badCertTemplate, "issuer is not present");
}
if (!issuer.equals(caSubject)) {
return buildErrorMsgPkiBody(PKIStatus.rejection, PKIFailureInfo.badCertTemplate, "issuer does not target at the CA");
}
if (serialNumber == null) {
return buildErrorMsgPkiBody(PKIStatus.rejection, PKIFailureInfo.badCertTemplate, "serialNumber is not present");
}
if (certDetails.getSigningAlg() != null || certDetails.getValidity() != null || certDetails.getSubject() != null || certDetails.getPublicKey() != null || certDetails.getIssuerUID() != null || certDetails.getSubjectUID() != null) {
return buildErrorMsgPkiBody(PKIStatus.rejection, PKIFailureInfo.badCertTemplate, "only version, issuer and serialNumber in RevDetails.certDetails are " + "allowed, but more is specified");
}
if (certDetails.getExtensions() == null) {
if (cmpControl.isRrAkiRequired()) {
return buildErrorMsgPkiBody(PKIStatus.rejection, PKIFailureInfo.badCertTemplate, "issuer's AKI not present");
}
} else {
Extensions exts = certDetails.getExtensions();
ASN1ObjectIdentifier[] oids = exts.getCriticalExtensionOIDs();
if (oids != null) {
for (ASN1ObjectIdentifier oid : oids) {
if (!Extension.authorityKeyIdentifier.equals(oid)) {
return buildErrorMsgPkiBody(PKIStatus.rejection, PKIFailureInfo.badCertTemplate, "unknown critical extension " + oid.getId());
}
}
}
Extension ext = exts.getExtension(Extension.authorityKeyIdentifier);
if (ext == null) {
return buildErrorMsgPkiBody(PKIStatus.rejection, PKIFailureInfo.badCertTemplate, "issuer's AKI not present");
} else {
AuthorityKeyIdentifier aki = AuthorityKeyIdentifier.getInstance(ext.getParsedValue());
if (aki.getKeyIdentifier() == null) {
return buildErrorMsgPkiBody(PKIStatus.rejection, PKIFailureInfo.badCertTemplate, "issuer's AKI not present");
}
boolean issuerMatched = true;
byte[] caSki = getCa().getCaInfo().getCert().getSubjectKeyIdentifier();
if (!Arrays.equals(caSki, aki.getKeyIdentifier())) {
issuerMatched = false;
}
if (issuerMatched && aki.getAuthorityCertSerialNumber() != null) {
BigInteger caSerial = getCa().getCaInfo().getSerialNumber();
if (!caSerial.equals(aki.getAuthorityCertSerialNumber())) {
issuerMatched = false;
}
}
if (issuerMatched && aki.getAuthorityCertIssuer() != null) {
GeneralName[] names = aki.getAuthorityCertIssuer().getNames();
for (GeneralName name : names) {
if (name.getTagNo() != GeneralName.directoryName) {
issuerMatched = false;
break;
}
if (!caSubject.equals(name.getName())) {
issuerMatched = false;
break;
}
}
}
if (!issuerMatched) {
return buildErrorMsgPkiBody(PKIStatus.rejection, PKIFailureInfo.badCertTemplate, "issuer does not target at the CA");
}
}
}
} catch (IllegalArgumentException ex) {
return buildErrorMsgPkiBody(PKIStatus.rejection, PKIFailureInfo.badRequest, "the request is not invalid");
}
}
// end for
byte[] encodedRequest = null;
if (getCa().getCaInfo().isSaveRequest()) {
try {
encodedRequest = request.getEncoded();
} catch (IOException ex) {
LOG.warn("could not encode request");
}
}
Long reqDbId = null;
for (int i = 0; i < n; i++) {
RevDetails revDetails = revContent[i];
CertTemplate certDetails = revDetails.getCertDetails();
ASN1Integer serialNumber = certDetails.getSerialNumber();
// serialNumber is not null due to the check in the previous for-block.
X500Name caSubject = getCa().getCaInfo().getCert().getSubjectAsX500Name();
BigInteger snBigInt = serialNumber.getPositiveValue();
CertId certId = new CertId(new GeneralName(caSubject), serialNumber);
PKIStatusInfo status;
try {
Object returnedObj = null;
Long certDbId = null;
X509Ca ca = getCa();
if (PermissionConstants.UNREVOKE_CERT == permission) {
// unrevoke
returnedObj = ca.unrevokeCertificate(snBigInt, msgId);
if (returnedObj != null) {
certDbId = ((X509CertWithDbId) returnedObj).getCertId();
}
} else if (PermissionConstants.REMOVE_CERT == permission) {
// remove
returnedObj = ca.removeCertificate(snBigInt, msgId);
} else {
// revoke
Date invalidityDate = null;
CrlReason reason = null;
Extensions crlDetails = revDetails.getCrlEntryDetails();
if (crlDetails != null) {
ASN1ObjectIdentifier extId = Extension.reasonCode;
ASN1Encodable extValue = crlDetails.getExtensionParsedValue(extId);
if (extValue != null) {
int reasonCode = ASN1Enumerated.getInstance(extValue).getValue().intValue();
reason = CrlReason.forReasonCode(reasonCode);
}
extId = Extension.invalidityDate;
extValue = crlDetails.getExtensionParsedValue(extId);
if (extValue != null) {
try {
invalidityDate = ASN1GeneralizedTime.getInstance(extValue).getDate();
} catch (ParseException ex) {
throw new OperationException(ErrorCode.INVALID_EXTENSION, "invalid extension " + extId.getId());
}
}
}
if (reason == null) {
reason = CrlReason.UNSPECIFIED;
}
returnedObj = ca.revokeCertificate(snBigInt, reason, invalidityDate, msgId);
if (returnedObj != null) {
certDbId = ((X509CertWithRevocationInfo) returnedObj).getCert().getCertId();
}
}
if (returnedObj == null) {
throw new OperationException(ErrorCode.UNKNOWN_CERT, "cert not exists");
}
if (certDbId != null && ca.getCaInfo().isSaveRequest()) {
if (reqDbId == null) {
reqDbId = ca.addRequest(encodedRequest);
}
ca.addRequestCert(reqDbId, certDbId);
}
status = new PKIStatusInfo(PKIStatus.granted);
} catch (OperationException ex) {
ErrorCode code = ex.getErrorCode();
LOG.warn("{}, OperationException: code={}, message={}", PermissionConstants.getTextForCode(permission), code.name(), ex.getErrorMessage());
String errorMessage;
switch(code) {
case DATABASE_FAILURE:
case SYSTEM_FAILURE:
errorMessage = code.name();
break;
default:
errorMessage = code.name() + ": " + ex.getErrorMessage();
break;
}
// end switch code
int failureInfo = getPKiFailureInfo(ex);
status = generateRejectionStatus(failureInfo, errorMessage);
}
// end try
repContentBuilder.add(status, certId);
}
return new PKIBody(PKIBody.TYPE_REVOCATION_REP, repContentBuilder.build());
}
use of org.bouncycastle.asn1.x509.CRLReason in project xipki by xipki.
the class X509Ca method generateCrl0.
private X509CRL generateCrl0(boolean deltaCrl, Date thisUpdate, Date nextUpdate, AuditEvent event, String msgId) throws OperationException {
X509CrlSignerEntryWrapper crlSigner = getCrlSigner();
if (crlSigner == null) {
throw new OperationException(ErrorCode.NOT_PERMITTED, "CRL generation is not allowed");
}
LOG.info(" START generateCrl: ca={}, deltaCRL={}, nextUpdate={}", caIdent, deltaCrl, nextUpdate);
event.addEventData(CaAuditConstants.NAME_crlType, deltaCrl ? "DELTA_CRL" : "FULL_CRL");
if (nextUpdate == null) {
event.addEventData(CaAuditConstants.NAME_nextUpdate, "null");
} else {
event.addEventData(CaAuditConstants.NAME_nextUpdate, DateUtil.toUtcTimeyyyyMMddhhmmss(nextUpdate));
if (nextUpdate.getTime() - thisUpdate.getTime() < 10 * 60 * MS_PER_SECOND) {
// less than 10 minutes
throw new OperationException(ErrorCode.CRL_FAILURE, "nextUpdate and thisUpdate are too close");
}
}
CrlControl crlControl = crlSigner.getCrlControl();
boolean successful = false;
try {
ConcurrentContentSigner tmpCrlSigner = crlSigner.getSigner();
CrlControl control = crlSigner.getCrlControl();
boolean directCrl;
X500Name crlIssuer;
if (tmpCrlSigner == null) {
directCrl = true;
crlIssuer = caInfo.getPublicCaInfo().getX500Subject();
} else {
directCrl = false;
crlIssuer = X500Name.getInstance(tmpCrlSigner.getCertificate().getSubjectX500Principal().getEncoded());
}
X509v2CRLBuilder crlBuilder = new X509v2CRLBuilder(crlIssuer, thisUpdate);
if (nextUpdate != null) {
crlBuilder.setNextUpdate(nextUpdate);
}
final int numEntries = 100;
Date notExpireAt;
if (control.isIncludeExpiredCerts()) {
notExpireAt = new Date(0);
} else {
// 10 minutes buffer
notExpireAt = new Date(thisUpdate.getTime() - 600L * MS_PER_SECOND);
}
long startId = 1;
// we have to cache the serial entries to sort them
List<CertRevInfoWithSerial> allRevInfos = new LinkedList<>();
List<CertRevInfoWithSerial> revInfos;
do {
if (deltaCrl) {
revInfos = certstore.getCertsForDeltaCrl(caIdent, startId, numEntries, control.isOnlyContainsCaCerts(), control.isOnlyContainsUserCerts());
} else {
revInfos = certstore.getRevokedCerts(caIdent, notExpireAt, startId, numEntries, control.isOnlyContainsCaCerts(), control.isOnlyContainsUserCerts());
}
allRevInfos.addAll(revInfos);
long maxId = 1;
for (CertRevInfoWithSerial revInfo : revInfos) {
if (revInfo.getId() > maxId) {
maxId = revInfo.getId();
}
}
// end for
startId = maxId + 1;
} while (// end do
revInfos.size() >= numEntries);
if (revInfos != null) {
// free the memory
revInfos.clear();
}
// sort the list by SerialNumber ASC
Collections.sort(allRevInfos);
boolean isFirstCrlEntry = true;
for (CertRevInfoWithSerial revInfo : allRevInfos) {
CrlReason reason = revInfo.getReason();
if (crlControl.isExcludeReason() && reason != CrlReason.REMOVE_FROM_CRL) {
reason = CrlReason.UNSPECIFIED;
}
Date revocationTime = revInfo.getRevocationTime();
Date invalidityTime = revInfo.getInvalidityTime();
switch(crlControl.getInvalidityDateMode()) {
case FORBIDDEN:
invalidityTime = null;
break;
case OPTIONAL:
break;
case REQUIRED:
if (invalidityTime == null) {
invalidityTime = revocationTime;
}
break;
default:
throw new RuntimeException("unknown TripleState: " + crlControl.getInvalidityDateMode());
}
BigInteger serial = revInfo.getSerial();
LOG.debug("added cert ca={} serial={} to CRL", caIdent, serial);
if (directCrl || !isFirstCrlEntry) {
if (invalidityTime != null) {
crlBuilder.addCRLEntry(serial, revocationTime, reason.getCode(), invalidityTime);
} else {
crlBuilder.addCRLEntry(serial, revocationTime, reason.getCode());
}
continue;
}
List<Extension> extensions = new ArrayList<>(3);
if (reason != CrlReason.UNSPECIFIED) {
Extension ext = createReasonExtension(reason.getCode());
extensions.add(ext);
}
if (invalidityTime != null) {
Extension ext = createInvalidityDateExtension(invalidityTime);
extensions.add(ext);
}
Extension ext = createCertificateIssuerExtension(caInfo.getPublicCaInfo().getX500Subject());
extensions.add(ext);
crlBuilder.addCRLEntry(serial, revocationTime, new Extensions(extensions.toArray(new Extension[0])));
isFirstCrlEntry = false;
}
// free the memory
allRevInfos.clear();
BigInteger crlNumber = caInfo.nextCrlNumber();
event.addEventData(CaAuditConstants.NAME_crlNumber, crlNumber);
boolean onlyUserCerts = crlControl.isOnlyContainsUserCerts();
boolean onlyCaCerts = crlControl.isOnlyContainsCaCerts();
if (onlyUserCerts && onlyCaCerts) {
throw new RuntimeException("should not reach here, onlyUserCerts and onlyCACerts are both true");
}
try {
// AuthorityKeyIdentifier
byte[] akiValues = directCrl ? caInfo.getPublicCaInfo().getSubjectKeyIdentifer() : crlSigner.getSubjectKeyIdentifier();
AuthorityKeyIdentifier aki = new AuthorityKeyIdentifier(akiValues);
crlBuilder.addExtension(Extension.authorityKeyIdentifier, false, aki);
// add extension CRL Number
crlBuilder.addExtension(Extension.cRLNumber, false, new ASN1Integer(crlNumber));
// IssuingDistributionPoint
if (onlyUserCerts || onlyCaCerts || !directCrl) {
IssuingDistributionPoint idp = new IssuingDistributionPoint(// distributionPoint,
(DistributionPointName) null, // onlyContainsUserCerts,
onlyUserCerts, // onlyContainsCACerts,
onlyCaCerts, // onlySomeReasons,
(ReasonFlags) null, // indirectCRL,
!directCrl, // onlyContainsAttributeCerts
false);
crlBuilder.addExtension(Extension.issuingDistributionPoint, true, idp);
}
// freshestCRL
List<String> deltaCrlUris = getCaInfo().getPublicCaInfo().getDeltaCrlUris();
if (control.getDeltaCrlIntervals() > 0 && CollectionUtil.isNonEmpty(deltaCrlUris)) {
CRLDistPoint cdp = CaUtil.createCrlDistributionPoints(deltaCrlUris, caInfo.getPublicCaInfo().getX500Subject(), crlIssuer);
crlBuilder.addExtension(Extension.freshestCRL, false, cdp);
}
} catch (CertIOException ex) {
LogUtil.error(LOG, ex, "crlBuilder.addExtension");
throw new OperationException(ErrorCode.INVALID_EXTENSION, ex);
}
addXipkiCertset(crlBuilder, deltaCrl, control, notExpireAt, onlyCaCerts, onlyUserCerts);
ConcurrentContentSigner concurrentSigner = (tmpCrlSigner == null) ? caInfo.getSigner(null) : tmpCrlSigner;
ConcurrentBagEntrySigner signer0;
try {
signer0 = concurrentSigner.borrowSigner();
} catch (NoIdleSignerException ex) {
throw new OperationException(ErrorCode.SYSTEM_FAILURE, "NoIdleSignerException: " + ex.getMessage());
}
X509CRLHolder crlHolder;
try {
crlHolder = crlBuilder.build(signer0.value());
} finally {
concurrentSigner.requiteSigner(signer0);
}
try {
X509CRL crl = X509Util.toX509Crl(crlHolder.toASN1Structure());
caInfo.getCaEntry().setNextCrlNumber(crlNumber.longValue() + 1);
caManager.commitNextCrlNo(caIdent, caInfo.getCaEntry().getNextCrlNumber());
publishCrl(crl);
successful = true;
LOG.info("SUCCESSFUL generateCrl: ca={}, crlNumber={}, thisUpdate={}", caIdent, crlNumber, crl.getThisUpdate());
if (!deltaCrl) {
// clean up the CRL
cleanupCrlsWithoutException(msgId);
}
return crl;
} catch (CRLException | CertificateException ex) {
throw new OperationException(ErrorCode.CRL_FAILURE, ex);
}
} finally {
if (!successful) {
LOG.info(" FAILED generateCrl: ca={}", caIdent);
}
}
}
Aggregations