package org.apereo.cas.adaptors.x509.authentication.revocation.policy; import org.apereo.cas.adaptors.x509.authentication.ExpiredCRLException; import org.apereo.cas.adaptors.x509.util.CertUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.security.cert.X509CRL; import java.time.ZoneOffset; import java.time.ZonedDateTime; /** * Implements a policy to handle expired CRL data whereby expired data is permitted * up to a threshold period of time but not afterward. * * @author Marvin S. Addison * @since 3.4.6 * */ public class ThresholdExpiredCRLRevocationPolicy implements RevocationPolicy<X509CRL> { private static final Logger LOGGER = LoggerFactory.getLogger(ThresholdExpiredCRLRevocationPolicy.class); /** Expired threshold period in seconds after which expired CRL data is rejected. */ private final int threshold; /** * Creates a new instance. * * @param threshold Number of seconds; MUST be non-negative integer. */ public ThresholdExpiredCRLRevocationPolicy(final int threshold) { this.threshold = threshold; } /** * {@inheritDoc} * The CRL next update time is compared against the current time with the threshold * applied and rejected if and only if the next update time is in the past. * * @param crl CRL instance to evaluate. * * @throws ExpiredCRLException On expired CRL data. Check the exception type for exact details * * @see RevocationPolicy#apply(java.lang.Object) */ @Override public void apply(final X509CRL crl) throws ExpiredCRLException { final ZonedDateTime cutoff = ZonedDateTime.now(ZoneOffset.UTC); if (CertUtils.isExpired(crl, cutoff)) { if (CertUtils.isExpired(crl, cutoff.minusSeconds(this.threshold))) { throw new ExpiredCRLException(crl.toString(), cutoff, this.threshold); } LOGGER.info(String.format("CRL expired on %s but is within threshold period, %s seconds.", crl.getNextUpdate(), this.threshold)); } } }