/* * Licensed to Jasig under one or more contributor license * agreements. See the NOTICE file distributed with this work * for additional information regarding copyright ownership. * Jasig licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a * copy of the License at the following location: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.jasig.cas.adaptors.x509.authentication.handler.support; import java.math.BigInteger; import java.security.GeneralSecurityException; import java.security.cert.X509CRLEntry; import java.util.Date; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Exception that describes a revoked X.509 certificate. * * @author Marvin S. Addison * @since 3.4.6 * */ public class RevokedCertificateException extends GeneralSecurityException { private final Logger logger = LoggerFactory.getLogger(getClass()); private static final long serialVersionUID = 8827788431199129708L; /** OID for reasonCode CRL extension. */ public static final String CRL_REASON_OID = "2.5.29.21"; /** CRL revocation reason codes per RFC 3280. */ public enum Reason { Unspecified, KeyCompromise, CACompromise, AffiliationChanged, Superseded, CessationOfOperation, CertificateHold, RemoveFromCRL, PrivilegeWithdrawn, AACompromise; public static Reason fromCode(final int code) { for (int i = 0; i < Reason.values().length; i++) { if (i == code) { return Reason.values()[i]; } } throw new IllegalArgumentException("Unknown CRL reason code."); } } private final Date revocationDate; private final BigInteger serial; private Reason reason; public RevokedCertificateException(final Date revoked, final BigInteger serial) { this(revoked, serial, null); } public RevokedCertificateException(final Date revoked, final BigInteger serial, final Reason reason) { this.revocationDate = revoked; this.serial = serial; this.reason = reason; } public RevokedCertificateException(final X509CRLEntry entry) { this.revocationDate = entry.getRevocationDate(); this.serial = entry.getSerialNumber(); if (entry.hasExtensions()) { try { final int code = Integer.parseInt( new String(entry.getExtensionValue(CRL_REASON_OID), "ASCII")); if (code < Reason.values().length) { this.reason = Reason.fromCode(code); } } catch (final Exception e) { logger.trace("An exception occurred when resolving extension value: {}", e.getMessage()); } } } /** * @return Returns the revocationDate. */ public Date getRevocationDate() { return this.revocationDate; } /** * @return Returns the serial. */ public BigInteger getSerial() { return this.serial; } /** * @return Returns the reason. */ public Reason getReason() { return this.reason; } /** {@inheritDoc} */ @Override public String getMessage() { if (this.reason != null) { return String.format("Certificate %s revoked on %s for reason %s", this.serial, this.revocationDate, this.reason); } return String.format("Certificate %s revoked on %s", this.serial, this.revocationDate); } }