use of com.github.zhenwei.core.asn1.x509.CRLReason in project xipki by xipki.
the class RestResponder method service.
public RestResponse service(String path, AuditEvent event, byte[] request, HttpRequestMetadataRetriever httpRetriever) {
event.setApplicationName(APPNAME);
event.setName(NAME_perf);
event.addEventData(NAME_req_type, RequestType.REST.name());
String msgId = RandomUtil.nextHexLong();
event.addEventData(NAME_mid, msgId);
AuditLevel auditLevel = AuditLevel.INFO;
AuditStatus auditStatus = AuditStatus.SUCCESSFUL;
String auditMessage = null;
try {
if (responderManager == null) {
String message = "responderManager in servlet not configured";
LOG.error(message);
throw new HttpRespAuditException(INTERNAL_SERVER_ERROR, message, ERROR, FAILED);
}
String caName = null;
String command = null;
X509Ca ca = null;
if (path.length() > 1) {
// the first char is always '/'
String coreUri = path;
int sepIndex = coreUri.indexOf('/', 1);
if (sepIndex == -1 || sepIndex == coreUri.length() - 1) {
String message = "invalid path " + path;
LOG.error(message);
throw new HttpRespAuditException(NOT_FOUND, message, ERROR, FAILED);
}
// skip also the first char ('/')
String caAlias = coreUri.substring(1, sepIndex).toLowerCase();
command = coreUri.substring(sepIndex + 1).toLowerCase();
caName = responderManager.getCaNameForAlias(caAlias);
if (caName == null) {
caName = caAlias;
}
CmpResponder caResponder = responderManager.getX509CaResponder(caName);
if (caResponder != null) {
ca = caResponder.getCa();
}
}
if (StringUtil.isBlank(command)) {
String message = "command is not specified";
LOG.warn(message);
throw new HttpRespAuditException(NOT_FOUND, message, INFO, FAILED);
}
if (ca == null || !ca.getCaInfo().supportsRest() || ca.getCaInfo().getStatus() != CaStatus.ACTIVE) {
String message;
if (ca == null) {
message = "unknown CA '" + caName + "'";
} else if (!ca.getCaInfo().supportsRest()) {
message = "REST is not supported by the CA '" + caName + "'";
} else {
message = "CA '" + caName + "' is out of service";
}
LOG.warn(message);
throw new HttpRespAuditException(NOT_FOUND, message, INFO, FAILED);
}
event.addEventData(NAME_ca, ca.getCaIdent().getName());
event.addEventType(command);
RequestorInfo requestor;
// Retrieve the user:password
String hdrValue = httpRetriever.getHeader("Authorization");
if (hdrValue != null && hdrValue.startsWith("Basic ")) {
String user = null;
byte[] password = null;
if (hdrValue.length() > 6) {
String b64 = hdrValue.substring(6);
byte[] userPwd = Base64.decodeFast(b64);
int idx = -1;
for (int i = 0; i < userPwd.length; i++) {
if (userPwd[i] == ':') {
idx = i;
break;
}
}
if (idx != -1 && idx < userPwd.length - 1) {
user = StringUtil.toUtf8String(Arrays.copyOfRange(userPwd, 0, idx));
password = Arrays.copyOfRange(userPwd, idx + 1, userPwd.length);
}
}
if (user == null) {
throw new HttpRespAuditException(UNAUTHORIZED, "invalid Authorization information", INFO, FAILED);
}
NameId userIdent = ca.authenticateUser(user, password);
if (userIdent == null) {
throw new HttpRespAuditException(UNAUTHORIZED, "could not authenticate user", INFO, FAILED);
}
requestor = ca.getByUserRequestor(userIdent);
} else {
X509Cert clientCert = httpRetriever.getTlsClientCert();
if (clientCert == null) {
throw new HttpRespAuditException(UNAUTHORIZED, "no client certificate", INFO, FAILED);
}
requestor = ca.getRequestor(clientCert);
}
if (requestor == null) {
throw new OperationException(NOT_PERMITTED, "no requestor specified");
}
event.addEventData(NAME_requestor, requestor.getIdent().getName());
String respCt = null;
byte[] respBytes = null;
switch(command) {
case CMD_cacert:
{
respCt = CT_pkix_cert;
respBytes = ca.getCaInfo().getCert().getEncoded();
break;
}
case CMD_pop_dh_certs:
{
PopControl control = responderManager.getX509Ca(caName).getCaInfo().getPopControl();
respBytes = new byte[0];
if (control != null) {
X509Cert[] dhCerts = control.getDhCertificates();
if (dhCerts != null) {
respCt = CT_pem_file;
respBytes = StringUtil.toUtf8Bytes(X509Util.encodeCertificates(dhCerts));
}
}
break;
}
case CMD_cacertchain:
{
respCt = CT_pem_file;
List<X509Cert> certchain = ca.getCaInfo().getCertchain();
int size = 1 + (certchain == null ? 0 : certchain.size());
X509Cert[] certchainWithCaCert = new X509Cert[size];
certchainWithCaCert[0] = ca.getCaInfo().getCert();
if (size > 1) {
for (int i = 1; i < size; i++) {
certchainWithCaCert[i] = certchain.get(i - 1);
}
}
respBytes = StringUtil.toUtf8Bytes(X509Util.encodeCertificates(certchainWithCaCert));
break;
}
case CMD_enroll_cert:
case CMD_enroll_cert_cagenkeypair:
{
String profile = httpRetriever.getParameter(PARAM_profile);
if (StringUtil.isBlank(profile)) {
throw new HttpRespAuditException(BAD_REQUEST, "required parameter " + PARAM_profile + " not specified", INFO, FAILED);
}
profile = profile.toLowerCase();
try {
requestor.assertPermitted(PermissionConstants.ENROLL_CERT);
} catch (InsufficientPermissionException ex) {
throw new OperationException(NOT_PERMITTED, ex.getMessage());
}
if (!requestor.isCertprofilePermitted(profile)) {
throw new OperationException(NOT_PERMITTED, "certprofile " + profile + " is not allowed");
}
String strNotBefore = httpRetriever.getParameter(PARAM_not_before);
Date notBefore = (strNotBefore == null) ? null : DateUtil.parseUtcTimeyyyyMMddhhmmss(strNotBefore);
String strNotAfter = httpRetriever.getParameter(PARAM_not_after);
Date notAfter = (strNotAfter == null) ? null : DateUtil.parseUtcTimeyyyyMMddhhmmss(strNotAfter);
if (CMD_enroll_cert_cagenkeypair.equals(command)) {
String ct = httpRetriever.getHeader("Content-Type");
X500Name subject;
Extensions extensions;
if (ct.startsWith("text/plain")) {
Properties props = new Properties();
props.load(new ByteArrayInputStream(request));
String strSubject = props.getProperty("subject");
if (strSubject == null) {
throw new OperationException(BAD_CERT_TEMPLATE, "subject is not specified");
}
try {
subject = new X500Name(strSubject);
} catch (Exception ex) {
throw new OperationException(BAD_CERT_TEMPLATE, "invalid subject");
}
extensions = null;
} else if (CT_pkcs10.equalsIgnoreCase(ct)) {
// some clients may send the PEM encoded CSR.
request = X509Util.toDerEncoded(request);
// The PKCS#10 will only be used for transport of subject and extensions.
// The associated key will not be used, so the verification of POP is skipped.
CertificationRequestInfo certTemp = CertificationRequest.getInstance(request).getCertificationRequestInfo();
subject = certTemp.getSubject();
extensions = CaUtil.getExtensions(certTemp);
} else {
String message = "unsupported media type " + ct;
throw new HttpRespAuditException(UNSUPPORTED_MEDIA_TYPE, message, INFO, FAILED);
}
CertTemplateData certTemplate = new CertTemplateData(subject, null, notBefore, notAfter, extensions, profile, null, true);
CertificateInfo certInfo = ca.generateCert(certTemplate, requestor, RequestType.REST, null, msgId);
if (ca.getCaInfo().isSaveRequest()) {
long dbId = ca.addRequest(request);
ca.addRequestCert(dbId, certInfo.getCert().getCertId());
}
respCt = CT_pem_file;
byte[] keyBytes = PemEncoder.encode(certInfo.getPrivateKey().getEncoded(), PemLabel.PRIVATE_KEY);
byte[] certBytes = PemEncoder.encode(certInfo.getCert().getCert().getEncoded(), PemLabel.CERTIFICATE);
respBytes = new byte[keyBytes.length + 2 + certBytes.length];
System.arraycopy(keyBytes, 0, respBytes, 0, keyBytes.length);
respBytes[keyBytes.length] = '\r';
respBytes[keyBytes.length + 1] = '\n';
System.arraycopy(certBytes, 0, respBytes, keyBytes.length + 2, certBytes.length);
} else {
String ct = httpRetriever.getHeader("Content-Type");
if (!CT_pkcs10.equalsIgnoreCase(ct)) {
String message = "unsupported media type " + ct;
throw new HttpRespAuditException(UNSUPPORTED_MEDIA_TYPE, message, INFO, FAILED);
}
CertificationRequest csr = CertificationRequest.getInstance(request);
if (!ca.verifyCsr(csr)) {
throw new OperationException(BAD_POP);
}
CertificationRequestInfo certTemp = csr.getCertificationRequestInfo();
X500Name subject = certTemp.getSubject();
SubjectPublicKeyInfo publicKeyInfo = certTemp.getSubjectPublicKeyInfo();
Extensions extensions = CaUtil.getExtensions(certTemp);
CertTemplateData certTemplate = new CertTemplateData(subject, publicKeyInfo, notBefore, notAfter, extensions, profile);
CertificateInfo certInfo = ca.generateCert(certTemplate, requestor, RequestType.REST, null, msgId);
if (ca.getCaInfo().isSaveRequest()) {
long dbId = ca.addRequest(request);
ca.addRequestCert(dbId, certInfo.getCert().getCertId());
}
CertWithDbId cert = certInfo.getCert();
if (cert == null) {
String message = "could not generate certificate";
LOG.warn(message);
throw new HttpRespAuditException(INTERNAL_SERVER_ERROR, message, INFO, FAILED);
}
respCt = CT_pkix_cert;
respBytes = cert.getCert().getEncoded();
}
break;
}
case CMD_revoke_cert:
case CMD_delete_cert:
{
int permission;
if (CMD_revoke_cert.equals(command)) {
permission = PermissionConstants.REVOKE_CERT;
} else {
permission = PermissionConstants.REMOVE_CERT;
}
try {
requestor.assertPermitted(permission);
} catch (InsufficientPermissionException ex) {
throw new OperationException(NOT_PERMITTED, ex.getMessage());
}
String strCaSha1 = httpRetriever.getParameter(PARAM_ca_sha1);
if (StringUtil.isBlank(strCaSha1)) {
throw new HttpRespAuditException(BAD_REQUEST, "required parameter " + PARAM_ca_sha1 + " not specified", INFO, FAILED);
}
String strSerialNumber = httpRetriever.getParameter(PARAM_serial_number);
if (StringUtil.isBlank(strSerialNumber)) {
throw new HttpRespAuditException(BAD_REQUEST, "required parameter " + PARAM_serial_number + " not specified", INFO, FAILED);
}
if (!strCaSha1.equalsIgnoreCase(ca.getHexSha1OfCert())) {
throw new HttpRespAuditException(BAD_REQUEST, "unknown " + PARAM_ca_sha1, INFO, FAILED);
}
BigInteger serialNumber;
try {
serialNumber = toBigInt(strSerialNumber);
} catch (NumberFormatException ex) {
throw new OperationException(ErrorCode.BAD_REQUEST, ex.getMessage());
}
if (CMD_revoke_cert.equals(command)) {
String strReason = httpRetriever.getParameter(PARAM_reason);
CrlReason reason = (strReason == null) ? CrlReason.UNSPECIFIED : CrlReason.forNameOrText(strReason);
if (reason == CrlReason.REMOVE_FROM_CRL) {
ca.unrevokeCert(serialNumber, msgId);
} else {
Date invalidityTime = null;
String strInvalidityTime = httpRetriever.getParameter(PARAM_invalidity_time);
if (StringUtil.isNotBlank(strInvalidityTime)) {
invalidityTime = DateUtil.parseUtcTimeyyyyMMddhhmmss(strInvalidityTime);
}
ca.revokeCert(serialNumber, reason, invalidityTime, msgId);
}
} else {
// if (CMD_delete_cert.equals(command)) {
ca.removeCert(serialNumber, msgId);
}
break;
}
case CMD_crl:
{
try {
requestor.assertPermitted(PermissionConstants.GET_CRL);
} catch (InsufficientPermissionException ex) {
throw new OperationException(NOT_PERMITTED, ex.getMessage());
}
String strCrlNumber = httpRetriever.getParameter(PARAM_crl_number);
BigInteger crlNumber = null;
if (StringUtil.isNotBlank(strCrlNumber)) {
try {
crlNumber = toBigInt(strCrlNumber);
} catch (NumberFormatException ex) {
String message = "invalid crlNumber '" + strCrlNumber + "'";
LOG.warn(message);
throw new HttpRespAuditException(BAD_REQUEST, message, INFO, FAILED);
}
}
X509CRLHolder crl = ca.getCrl(crlNumber, msgId);
if (crl == null) {
String message = "could not get CRL";
LOG.warn(message);
throw new HttpRespAuditException(INTERNAL_SERVER_ERROR, message, INFO, FAILED);
}
respCt = CT_pkix_crl;
respBytes = crl.getEncoded();
break;
}
case CMD_new_crl:
{
try {
requestor.assertPermitted(PermissionConstants.GEN_CRL);
} catch (InsufficientPermissionException ex) {
throw new OperationException(NOT_PERMITTED, ex.getMessage());
}
X509CRLHolder crl = ca.generateCrlOnDemand(msgId);
respCt = CT_pkix_crl;
respBytes = crl.getEncoded();
break;
}
default:
{
String message = "invalid command '" + command + "'";
LOG.error(message);
throw new HttpRespAuditException(NOT_FOUND, message, INFO, FAILED);
}
}
Map<String, String> headers = new HashMap<>();
headers.put(HEADER_PKISTATUS, PKISTATUS_accepted);
return new RestResponse(OK, respCt, headers, respBytes);
} catch (OperationException ex) {
ErrorCode code = ex.getErrorCode();
if (LOG.isWarnEnabled()) {
String msg = StringUtil.concat("generate certificate, OperationException: code=", code.name(), ", message=", ex.getErrorMessage());
LogUtil.warn(LOG, ex, msg);
}
int sc;
String failureInfo;
switch(code) {
case ALREADY_ISSUED:
sc = BAD_REQUEST;
failureInfo = FAILINFO_badRequest;
break;
case BAD_CERT_TEMPLATE:
sc = BAD_REQUEST;
failureInfo = FAILINFO_badCertTemplate;
break;
case BAD_REQUEST:
sc = BAD_REQUEST;
failureInfo = FAILINFO_badRequest;
break;
case CERT_REVOKED:
sc = CONFLICT;
failureInfo = FAILINFO_certRevoked;
break;
case CRL_FAILURE:
sc = INTERNAL_SERVER_ERROR;
failureInfo = FAILINFO_systemFailure;
break;
case DATABASE_FAILURE:
sc = INTERNAL_SERVER_ERROR;
failureInfo = FAILINFO_systemFailure;
break;
case NOT_PERMITTED:
sc = UNAUTHORIZED;
failureInfo = FAILINFO_notAuthorized;
break;
case INVALID_EXTENSION:
sc = BAD_REQUEST;
failureInfo = FAILINFO_badRequest;
break;
case SYSTEM_FAILURE:
sc = INTERNAL_SERVER_ERROR;
failureInfo = FAILINFO_systemFailure;
break;
case SYSTEM_UNAVAILABLE:
sc = SERVICE_UNAVAILABLE;
failureInfo = FAILINFO_systemUnavail;
break;
case UNKNOWN_CERT:
sc = BAD_REQUEST;
failureInfo = FAILINFO_badCertId;
break;
case UNKNOWN_CERT_PROFILE:
sc = BAD_REQUEST;
failureInfo = FAILINFO_badCertTemplate;
break;
default:
sc = INTERNAL_SERVER_ERROR;
failureInfo = FAILINFO_systemFailure;
break;
}
// end switch (code)
event.setStatus(AuditStatus.FAILED);
event.addEventData(NAME_message, code.name());
switch(code) {
case DATABASE_FAILURE:
case SYSTEM_FAILURE:
auditMessage = code.name();
break;
default:
auditMessage = code.name() + ": " + ex.getErrorMessage();
break;
}
// end switch code
Map<String, String> headers = new HashMap<>();
headers.put(HEADER_PKISTATUS, PKISTATUS_rejection);
if (StringUtil.isNotBlank(failureInfo)) {
headers.put(HEADER_failInfo, failureInfo);
}
return new RestResponse(sc, null, headers, null);
} catch (HttpRespAuditException ex) {
auditStatus = ex.getAuditStatus();
auditLevel = ex.getAuditLevel();
auditMessage = ex.getAuditMessage();
return new RestResponse(ex.getHttpStatus(), null, null, null);
} catch (Throwable th) {
if (th instanceof EOFException) {
LogUtil.warn(LOG, th, "connection reset by peer");
} else {
LOG.error("Throwable thrown, this should not happen!", th);
}
auditLevel = AuditLevel.ERROR;
auditStatus = AuditStatus.FAILED;
auditMessage = "internal error";
return new RestResponse(INTERNAL_SERVER_ERROR, null, null, null);
} finally {
event.setStatus(auditStatus);
event.setLevel(auditLevel);
if (auditMessage != null) {
event.addEventData(NAME_message, auditMessage);
}
}
}
use of com.github.zhenwei.core.asn1.x509.CRLReason in project LinLong-Java by zhenwei1108.
the class ProvOcspRevocationChecker method check.
public void check(Certificate certificate) throws CertPathValidatorException {
X509Certificate cert = (X509Certificate) certificate;
Map<X509Certificate, byte[]> ocspResponses = parent.getOcspResponses();
URI ocspUri = parent.getOcspResponder();
if (ocspUri == null) {
if (this.ocspURL != null) {
try {
ocspUri = new URI(this.ocspURL);
} catch (URISyntaxException e) {
throw new CertPathValidatorException("configuration error: " + e.getMessage(), e, parameters.getCertPath(), parameters.getIndex());
}
} else {
ocspUri = getOcspResponderURI(cert);
}
}
byte[] nonce = null;
boolean preValidated = false;
if (ocspResponses.get(cert) == null && ocspUri != null) {
// if we're here we need to make a network access, if we haven't been given a URL explicitly block it.
if (ocspURL == null && parent.getOcspResponder() == null && !isEnabledOCSP) {
throw new RecoverableCertPathValidatorException("OCSP disabled by \"ocsp.enable\" setting", null, parameters.getCertPath(), parameters.getIndex());
}
com.github.zhenwei.core.asn1.x509.Certificate issuer = extractCert();
// TODO: configure hash algorithm
CertID id = createCertID(new AlgorithmIdentifier(OIWObjectIdentifiers.idSHA1), issuer, new ASN1Integer(cert.getSerialNumber()));
OCSPResponse response = OcspCache.getOcspResponse(id, parameters, ocspUri, parent.getOcspResponderCert(), parent.getOcspExtensions(), helper);
try {
ocspResponses.put(cert, response.getEncoded());
preValidated = true;
} catch (IOException e) {
throw new CertPathValidatorException("unable to encode OCSP response", e, parameters.getCertPath(), parameters.getIndex());
}
} else {
List exts = parent.getOcspExtensions();
for (int i = 0; i != exts.size(); i++) {
Extension ext = (Extension) exts.get(i);
byte[] value = ext.getValue();
if (OCSPObjectIdentifiers.id_pkix_ocsp_nonce.getId().equals(ext.getId())) {
nonce = value;
}
}
}
if (!ocspResponses.isEmpty()) {
OCSPResponse ocspResponse = OCSPResponse.getInstance(ocspResponses.get(cert));
ASN1Integer serialNumber = new ASN1Integer(cert.getSerialNumber());
if (ocspResponse != null) {
if (OCSPResponseStatus.SUCCESSFUL == ocspResponse.getResponseStatus().getIntValue()) {
ResponseBytes respBytes = ResponseBytes.getInstance(ocspResponse.getResponseBytes());
if (respBytes.getResponseType().equals(OCSPObjectIdentifiers.id_pkix_ocsp_basic)) {
try {
BasicOCSPResponse basicResp = BasicOCSPResponse.getInstance(respBytes.getResponse().getOctets());
if (preValidated || validatedOcspResponse(basicResp, parameters, nonce, parent.getOcspResponderCert(), helper)) {
ResponseData responseData = ResponseData.getInstance(basicResp.getTbsResponseData());
ASN1Sequence s = responseData.getResponses();
CertID certID = null;
for (int i = 0; i != s.size(); i++) {
SingleResponse resp = SingleResponse.getInstance(s.getObjectAt(i));
if (serialNumber.equals(resp.getCertID().getSerialNumber())) {
ASN1GeneralizedTime nextUp = resp.getNextUpdate();
if (nextUp != null && parameters.getValidDate().after(nextUp.getDate())) {
throw new ExtCertPathValidatorException("OCSP response expired");
}
if (certID == null || !certID.getHashAlgorithm().equals(resp.getCertID().getHashAlgorithm())) {
com.github.zhenwei.core.asn1.x509.Certificate issuer = extractCert();
certID = createCertID(resp.getCertID(), issuer, serialNumber);
}
if (certID.equals(resp.getCertID())) {
if (resp.getCertStatus().getTagNo() == 0) {
// we're good!
return;
}
if (resp.getCertStatus().getTagNo() == 1) {
RevokedInfo info = RevokedInfo.getInstance(resp.getCertStatus().getStatus());
CRLReason reason = info.getRevocationReason();
throw new CertPathValidatorException("certificate revoked, reason=(" + reason + "), date=" + info.getRevocationTime().getDate(), null, parameters.getCertPath(), parameters.getIndex());
}
throw new CertPathValidatorException("certificate revoked, details unknown", null, parameters.getCertPath(), parameters.getIndex());
}
}
}
}
} catch (CertPathValidatorException e) {
throw e;
} catch (Exception e) {
throw new CertPathValidatorException("unable to process OCSP response", e, parameters.getCertPath(), parameters.getIndex());
}
}
} else {
throw new CertPathValidatorException("OCSP response failed: " + ocspResponse.getResponseStatus().getValue(), null, parameters.getCertPath(), parameters.getIndex());
}
} else {
// TODO: add checking for the OCSP extension (properly vetted)
throw new RecoverableCertPathValidatorException("no OCSP response found for certificate", null, parameters.getCertPath(), parameters.getIndex());
}
} else {
throw new RecoverableCertPathValidatorException("no OCSP response found for any certificate", null, parameters.getCertPath(), parameters.getIndex());
}
}
use of com.github.zhenwei.core.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 com.github.zhenwei.core.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);
}
}
}
use of com.github.zhenwei.core.asn1.x509.CRLReason in project xipki by xipki.
the class X509Ca method revokeSuspendedCerts0.
private int revokeSuspendedCerts0(AuditEvent event, String msgId) throws OperationException {
if (!masterMode) {
throw new OperationException(ErrorCode.NOT_PERMITTED, "CA could not remove expired certificates in slave mode");
}
final int numEntries = 100;
CertValidity val = caInfo.revokeSuspendedCertsControl().getUnchangedSince();
long ms;
switch(val.getUnit()) {
case DAY:
ms = val.getValidity() * DAY_IN_MS;
break;
case HOUR:
ms = val.getValidity() * DAY_IN_MS / 24;
break;
case YEAR:
ms = val.getValidity() * 365 * DAY_IN_MS;
break;
default:
throw new RuntimeException("should not reach here, unknown Validity Unit " + val.getUnit());
}
// seconds
final long latestLastUpdatedAt = (System.currentTimeMillis() - ms) / 1000;
final CrlReason reason = caInfo.revokeSuspendedCertsControl().getTargetReason();
int sum = 0;
while (true) {
List<BigInteger> serials = certstore.getSuspendedCertSerials(caIdent, latestLastUpdatedAt, numEntries);
if (CollectionUtil.isEmpty(serials)) {
return sum;
}
for (BigInteger serial : serials) {
boolean revoked = false;
try {
revoked = revokeSuspendedCert(serial, reason, msgId) != null;
if (revoked) {
sum++;
}
} catch (OperationException ex) {
LOG.info("revoked {} suspended certificates of CA {}", sum, caIdent);
LogUtil.error(LOG, ex, "could not revoke suspended certificate with serial" + serial);
throw ex;
}
// end try
}
// end for
}
// end while (true)
}
Aggregations