From 86bf9da77ae683036078a5c33225f4eb71f346d5 Mon Sep 17 00:00:00 2001 From: akila94 Date: Wed, 3 Jan 2024 10:20:47 +0530 Subject: [PATCH] Add expiry validation --- ...va => CertificateVerificationManager.java} | 46 ++++++++++++++----- .../http/conn/ClientSSLSetupHandler.java | 6 +-- .../http/conn/ServerSSLSetupHandler.java | 15 ++++-- .../config/ClientConnFactoryBuilder.java | 6 +-- .../config/ServerConnFactoryBuilder.java | 17 ++++--- .../core/ssl/SSLServerConnFactoryBuilder.java | 7 ++- 6 files changed, 63 insertions(+), 34 deletions(-) rename modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/certificatevalidation/{RevocationVerificationManager.java => CertificateVerificationManager.java} (86%) diff --git a/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/certificatevalidation/RevocationVerificationManager.java b/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/certificatevalidation/CertificateVerificationManager.java similarity index 86% rename from modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/certificatevalidation/RevocationVerificationManager.java rename to modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/certificatevalidation/CertificateVerificationManager.java index 683df58258..3ff125fd6d 100644 --- a/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/certificatevalidation/RevocationVerificationManager.java +++ b/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/certificatevalidation/CertificateVerificationManager.java @@ -36,6 +36,8 @@ import java.security.NoSuchProviderException; import java.security.SignatureException; import java.security.cert.CertificateException; +import java.security.cert.CertificateExpiredException; +import java.security.cert.CertificateNotYetValidException; import java.security.cert.X509Certificate; import java.util.Arrays; import java.util.Enumeration; @@ -45,14 +47,14 @@ * Manager class responsible for verifying certificates. This class will use the available verifiers according to * a predefined policy. */ -public class RevocationVerificationManager { +public class CertificateVerificationManager { private int cacheSize = Constants.CACHE_DEFAULT_ALLOCATED_SIZE; private int cacheDelayMins = Constants.CACHE_DEFAULT_DELAY_MINS; private boolean isFullCertChainValidationEnabled = false; - private static final Log log = LogFactory.getLog(RevocationVerificationManager.class); + private static final Log log = LogFactory.getLog(CertificateVerificationManager.class); - public RevocationVerificationManager(Integer cacheAllocatedSize, Integer cacheDelayMins) { + public CertificateVerificationManager(Integer cacheAllocatedSize, Integer cacheDelayMins) { if (cacheAllocatedSize != null && cacheAllocatedSize > Constants.CACHE_MIN_ALLOCATED_SIZE && cacheAllocatedSize < Constants.CACHE_MAX_ALLOCATED_SIZE) { @@ -64,8 +66,8 @@ public RevocationVerificationManager(Integer cacheAllocatedSize, Integer cacheDe } } - public RevocationVerificationManager(Integer cacheAllocatedSize, Integer cacheDelayMins, - boolean isFullCertChainValidationEnabled) { + public CertificateVerificationManager(Integer cacheAllocatedSize, Integer cacheDelayMins, + boolean isFullCertChainValidationEnabled) { if (cacheAllocatedSize != null && cacheAllocatedSize > Constants.CACHE_MIN_ALLOCATED_SIZE && cacheAllocatedSize < Constants.CACHE_MAX_ALLOCATED_SIZE) { @@ -157,11 +159,8 @@ public void verifyRevocationStatus(javax.security.cert.X509Certificate[] peerCer } break; } catch (SignatureException | CertificateException | NoSuchAlgorithmException | - InvalidKeyException | - NoSuchProviderException e) { + InvalidKeyException | NoSuchProviderException e) { // Unable to verify the signature. Check with the next certificate. - //todo: change this to a debug log after testing. - log.error("Unable to verify the signature, checking with the next certificate..."); } } } else { @@ -171,8 +170,8 @@ public void verifyRevocationStatus(javax.security.cert.X509Certificate[] peerCer } catch (SignatureException | CertificateException | NoSuchAlgorithmException | InvalidKeyException | NoSuchProviderException e) { - // Unable to verify the signature. Check with the next certificate. - log.error("Signature not matching for alias validate with next cert"); + // Unable to verify the signature. + throw new CertificateVerificationException("Unable to verify the signature of the certificate."); } } } @@ -238,4 +237,29 @@ private X509Certificate[] convert(javax.security.cert.X509Certificate[] certs) } return certChain; } + + /** + * Checks whether a provided certificate is expired or not at the time it is validated. + * + * @param certificates + * @throws CertificateNotYetValidException + * @throws CertificateExpiredException + * @throws CertificateVerificationException + */ + public void isExpired(javax.security.cert.X509Certificate[] certificates) throws CertificateVerificationException { + + X509Certificate[] convertedCertificates = convert(certificates); + + for (X509Certificate cert : convertedCertificates) { + try { + cert.checkValidity(); + } catch (CertificateExpiredException e) { + String msg = "Peer certificate is expired"; + throw new CertificateVerificationException(msg); + } catch (CertificateNotYetValidException e) { + String msg = "Peer certificate is not valid yet"; + throw new CertificateVerificationException(msg); + } + } + } } diff --git a/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/http/conn/ClientSSLSetupHandler.java b/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/http/conn/ClientSSLSetupHandler.java index 24977a7115..803be5cedd 100644 --- a/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/http/conn/ClientSSLSetupHandler.java +++ b/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/http/conn/ClientSSLSetupHandler.java @@ -33,7 +33,7 @@ import org.apache.http.nio.reactor.IOSession; import org.apache.http.nio.reactor.ssl.SSLSetupHandler; import org.apache.synapse.transport.certificatevalidation.CertificateVerificationException; -import org.apache.synapse.transport.certificatevalidation.RevocationVerificationManager; +import org.apache.synapse.transport.certificatevalidation.CertificateVerificationManager; public class ClientSSLSetupHandler implements SSLSetupHandler { @@ -139,10 +139,10 @@ public void verify( }; private final X509HostnameVerifier hostnameVerifier; - private final RevocationVerificationManager verificationManager; + private final CertificateVerificationManager verificationManager; public ClientSSLSetupHandler(final X509HostnameVerifier hostnameVerifier, - final RevocationVerificationManager verificationManager) { + final CertificateVerificationManager verificationManager) { this.hostnameVerifier = hostnameVerifier != null ? hostnameVerifier : DEFAULT; this.verificationManager = verificationManager; } diff --git a/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/http/conn/ServerSSLSetupHandler.java b/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/http/conn/ServerSSLSetupHandler.java index a4bc324ce1..3152d8f054 100644 --- a/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/http/conn/ServerSSLSetupHandler.java +++ b/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/http/conn/ServerSSLSetupHandler.java @@ -21,27 +21,32 @@ import javax.net.ssl.SSLEngine; import javax.net.ssl.SSLException; import javax.net.ssl.SSLSession; +import javax.security.cert.X509Certificate; import org.apache.http.nio.reactor.IOSession; import org.apache.http.nio.reactor.ssl.SSLSetupHandler; import org.apache.synapse.transport.certificatevalidation.CertificateVerificationException; -import org.apache.synapse.transport.certificatevalidation.RevocationVerificationManager; +import org.apache.synapse.transport.certificatevalidation.CertificateVerificationManager; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.SocketAddress; +import java.security.cert.CertificateExpiredException; +import java.security.cert.CertificateNotYetValidException; +import java.util.Arrays; +import java.util.List; public class ServerSSLSetupHandler implements SSLSetupHandler { private final SSLClientAuth clientAuth; /** Enabled SSL handshake protocols (e.g. SSLv3, TLSv1) */ private final String[] httpsProtocols; - private RevocationVerificationManager verificationManager; + private CertificateVerificationManager verificationManager; /** Ciphers enabled in axis2.xml, enabled all if null*/ private final String[] preferredCiphers; public ServerSSLSetupHandler(final SSLClientAuth clientAuth, final String[] httpsProtocols, - final RevocationVerificationManager verificationManager, final String[] preferredCiphers) { + final CertificateVerificationManager verificationManager, final String[] preferredCiphers) { this.clientAuth = clientAuth; this.httpsProtocols = httpsProtocols; this.verificationManager = verificationManager; @@ -78,7 +83,9 @@ public void verify( if (verificationManager != null) { try { - verificationManager.verifyRevocationStatus(sslsession.getPeerCertificateChain()); + X509Certificate[] peerCertChain = sslsession.getPeerCertificateChain(); + verificationManager.isExpired(peerCertChain); + verificationManager.verifyRevocationStatus(peerCertChain); } catch (CertificateVerificationException e) { SocketAddress remoteAddress = iosession.getRemoteAddress(); String address; diff --git a/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/nhttp/config/ClientConnFactoryBuilder.java b/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/nhttp/config/ClientConnFactoryBuilder.java index 44710be55a..bec88bfa25 100644 --- a/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/nhttp/config/ClientConnFactoryBuilder.java +++ b/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/nhttp/config/ClientConnFactoryBuilder.java @@ -31,7 +31,7 @@ import org.apache.commons.logging.LogFactory; import org.apache.http.conn.ssl.X509HostnameVerifier; import org.apache.http.params.HttpParams; -import org.apache.synapse.transport.certificatevalidation.RevocationVerificationManager; +import org.apache.synapse.transport.certificatevalidation.CertificateVerificationManager; import org.apache.synapse.transport.exceptions.InvalidConfigurationException; import org.apache.synapse.transport.http.conn.ClientConnFactory; import org.apache.synapse.transport.http.conn.ClientSSLSetupHandler; @@ -129,7 +129,7 @@ public ClientConnFactoryBuilder parseSSL() throws AxisFault { final Parameter cvp = transportOut.getParameter("CertificateRevocationVerifier"); final String cvEnable = cvp != null ? cvp.getParameterElement().getAttribute(new QName("enable")).getAttributeValue() : null; - RevocationVerificationManager revocationVerifier = null; + CertificateVerificationManager revocationVerifier = null; if ("true".equalsIgnoreCase(cvEnable)) { String cacheSizeString = cvp.getParameterElement().getFirstChildWithName(new QName("CacheSize")).getText(); @@ -142,7 +142,7 @@ public ClientConnFactoryBuilder parseSSL() throws AxisFault { cacheDelay = new Integer(cacheDelayString); } catch (NumberFormatException e) { } - revocationVerifier = new RevocationVerificationManager(cacheSize, cacheDelay); + revocationVerifier = new CertificateVerificationManager(cacheSize, cacheDelay); } // Process HttpProtocols diff --git a/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/nhttp/config/ServerConnFactoryBuilder.java b/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/nhttp/config/ServerConnFactoryBuilder.java index 483d5b56ee..2598138105 100644 --- a/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/nhttp/config/ServerConnFactoryBuilder.java +++ b/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/nhttp/config/ServerConnFactoryBuilder.java @@ -31,7 +31,7 @@ import org.apache.commons.logging.LogFactory; import org.apache.http.HttpHost; import org.apache.http.params.HttpParams; -import org.apache.synapse.transport.certificatevalidation.RevocationVerificationManager; +import org.apache.synapse.transport.certificatevalidation.CertificateVerificationManager; import org.apache.synapse.transport.http.conn.SSLClientAuth; import org.apache.synapse.transport.http.conn.SSLContextDetails; import org.apache.synapse.transport.http.conn.ServerConnFactory; @@ -73,6 +73,7 @@ public class ServerConnFactoryBuilder { protected SSLContextDetails ssl; private Map sslByIPMap = null; private ConfigurationContext configurationContext; + CertificateVerificationManager certificateVerifier = null; public ServerConnFactoryBuilder(final TransportInDescription transportIn, final HttpHost host, ConfigurationContext configurationContext) { @@ -94,7 +95,7 @@ protected SSLContextDetails createSSLContext( final OMElement cientAuthEl, final OMElement httpsProtocolsEl, final OMElement preferredCiphersEl, - final RevocationVerificationManager verificationManager, + final CertificateVerificationManager verificationManager, final String sslProtocol) throws AxisFault { SecretResolver secretResolver; @@ -114,7 +115,7 @@ protected SSLContextDetails createSSLContext( final OMElement cientAuthEl, final OMElement httpsProtocolsEl, final OMElement preferredCiphersEl, - final RevocationVerificationManager verificationManager, + final CertificateVerificationManager verificationManager, final String sslProtocol, final SecretResolver secretResolver) throws AxisFault { KeyManager[] keymanagers = null; @@ -307,7 +308,6 @@ public ServerConnFactoryBuilder parseSSL() throws AxisFault { final Parameter cvp = transportIn.getParameter("CertificateRevocationVerifier"); final String cvEnable = cvp != null ? cvp.getParameterElement().getAttribute(new QName("enable")).getAttributeValue() : null; - RevocationVerificationManager revocationVerifier = null; if ("true".equalsIgnoreCase(cvEnable)) { String cacheSizeString = cvp.getParameterElement().getFirstChildWithName(new QName("CacheSize")).getText(); @@ -332,12 +332,12 @@ public ServerConnFactoryBuilder parseSSL() throws AxisFault { isFullCertChainValidationEnabled = false; } - revocationVerifier = new RevocationVerificationManager(cacheSize, cacheDelay, + certificateVerifier = new CertificateVerificationManager(cacheSize, cacheDelay, isFullCertChainValidationEnabled); } ssl = createSSLContext(keyStoreEl, trustStoreEl, clientAuthEl, httpsProtocolsEl, preferredCiphersEl, - revocationVerifier, sslProtocol); + certificateVerifier, sslProtocol); return this; } @@ -351,7 +351,6 @@ public ServerConnFactoryBuilder parseMultiProfileSSL() throws AxisFault { OMElement profilesEl = profileParam.getParameterElement(); SecretResolver secretResolver = SecretResolverFactory.create(profilesEl, true); Iterator profiles = profilesEl.getChildrenWithName(new QName("profile")); - RevocationVerificationManager revocationVerifier = null; while (profiles.hasNext()) { OMElement profileEl = (OMElement) profiles.next(); @@ -406,12 +405,12 @@ public ServerConnFactoryBuilder parseMultiProfileSSL() throws AxisFault { isFullCertChainValidationEnabled = false; } - revocationVerifier = new RevocationVerificationManager(cacheSize, cacheDelay, + certificateVerifier = new CertificateVerificationManager(cacheSize, cacheDelay, isFullCertChainValidationEnabled); } SSLContextDetails ssl = createSSLContext(keyStoreEl, trustStoreEl, clientAuthEl, httpsProtocolsEl, - preferredCiphersEl, revocationVerifier, sslProtocol, secretResolver); + preferredCiphersEl, certificateVerifier, sslProtocol, secretResolver); if (sslByIPMap == null) { sslByIPMap = new HashMap(); } diff --git a/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/passthru/core/ssl/SSLServerConnFactoryBuilder.java b/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/passthru/core/ssl/SSLServerConnFactoryBuilder.java index 4b552bd799..8ea5433d4f 100644 --- a/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/passthru/core/ssl/SSLServerConnFactoryBuilder.java +++ b/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/passthru/core/ssl/SSLServerConnFactoryBuilder.java @@ -19,12 +19,11 @@ import org.apache.axiom.om.OMElement; import org.apache.axis2.AxisFault; -import org.apache.axis2.description.Parameter; import org.apache.axis2.description.TransportInDescription; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.http.HttpHost; -import org.apache.synapse.transport.certificatevalidation.RevocationVerificationManager; +import org.apache.synapse.transport.certificatevalidation.CertificateVerificationManager; import org.apache.synapse.transport.nhttp.config.ServerConnFactoryBuilder; import javax.xml.namespace.QName; @@ -46,7 +45,7 @@ public ServerConnFactoryBuilder parseSSL(OMElement keyStoreEl, OMElement trustSt AxisFault { final String cvEnable = cvp != null ? cvp.getAttribute(new QName("enable")).getAttributeValue() : null; - RevocationVerificationManager revocationVerifier = null; + CertificateVerificationManager revocationVerifier = null; if ("true".equalsIgnoreCase(cvEnable)) { Iterator iterator = cvp.getChildElements(); @@ -70,7 +69,7 @@ public ServerConnFactoryBuilder parseSSL(OMElement keyStoreEl, OMElement trustSt } catch (NumberFormatException e) { log.error("Please specify correct Integer numbers for CacheDelay and CacheSize"); } - revocationVerifier = new RevocationVerificationManager(cacheSize, cacheDelay, true); + revocationVerifier = new CertificateVerificationManager(cacheSize, cacheDelay); } ssl = createSSLContext(keyStoreEl, trustStoreEl, clientAuthEl, httpsProtocolsEl, preferredCiphers, revocationVerifier,