diff --git a/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/certificatevalidation/CertificateVerificationManager.java b/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/certificatevalidation/CertificateVerificationManager.java deleted file mode 100644 index 2765ac41a1..0000000000 --- a/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/certificatevalidation/CertificateVerificationManager.java +++ /dev/null @@ -1,287 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF 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 - * - * 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.apache.synapse.transport.certificatevalidation; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.synapse.transport.certificatevalidation.cache.CertCache; -import org.apache.synapse.transport.certificatevalidation.crl.CRLCache; -import org.apache.synapse.transport.certificatevalidation.crl.CRLVerifier; -import org.apache.synapse.transport.certificatevalidation.ocsp.OCSPCache; -import org.apache.synapse.transport.certificatevalidation.ocsp.OCSPVerifier; -import org.apache.synapse.transport.certificatevalidation.pathvalidation.CertificatePathValidator; -import org.apache.synapse.transport.nhttp.config.TrustStoreHolder; - -import java.io.ByteArrayInputStream; -import java.security.InvalidKeyException; -import java.security.KeyStore; -import java.security.KeyStoreException; -import java.security.NoSuchAlgorithmException; -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; -import java.util.Optional; - -/** - * Manager class responsible for verifying certificates. This class will use the available verifiers according to - * a predefined policy. - */ -public class CertificateVerificationManager { - - private int cacheSize = Constants.CACHE_DEFAULT_ALLOCATED_SIZE; - private int cacheDelayMins = Constants.CACHE_DEFAULT_DELAY_MINS; - private boolean isFullCertChainValidationEnabled = true; - private boolean isCertExpiryValidationEnabled = false; - private static final Log log = LogFactory.getLog(CertificateVerificationManager.class); - - public CertificateVerificationManager(Integer cacheAllocatedSize, Integer cacheDelayMins) { - - if (cacheAllocatedSize != null && cacheAllocatedSize > Constants.CACHE_MIN_ALLOCATED_SIZE - && cacheAllocatedSize < Constants.CACHE_MAX_ALLOCATED_SIZE) { - this.cacheSize = cacheAllocatedSize; - } else { - log.warn("The cache size is out of range. Hence, using the default cache size value of " - + Constants.CACHE_DEFAULT_ALLOCATED_SIZE + "."); - } - if (cacheDelayMins != null && cacheDelayMins > Constants.CACHE_MIN_DELAY_MINS - && cacheDelayMins < Constants.CACHE_MAX_DELAY_MINS) { - this.cacheDelayMins = cacheDelayMins; - } else { - log.warn("The cache delay is out of range. Hence, using the default cache delay value of " - + Constants.CACHE_DEFAULT_DELAY_MINS + "."); - } - } - - public CertificateVerificationManager(Integer cacheAllocatedSize, Integer cacheDelayMins, - boolean isFullCertChainValidationEnabled, - boolean isCertExpiryValidationEnabled) { - - if (cacheAllocatedSize != null && cacheAllocatedSize > Constants.CACHE_MIN_ALLOCATED_SIZE - && cacheAllocatedSize < Constants.CACHE_MAX_ALLOCATED_SIZE) { - this.cacheSize = cacheAllocatedSize; - } else { - log.warn("The cache size is out of range. Hence, using the default cache size value of " - + Constants.CACHE_DEFAULT_ALLOCATED_SIZE + "."); - } - if (cacheDelayMins != null && cacheDelayMins > Constants.CACHE_MIN_DELAY_MINS - && cacheDelayMins < Constants.CACHE_MAX_DELAY_MINS) { - this.cacheDelayMins = cacheDelayMins; - } else { - log.warn("The cache delay is out of range. Hence, using the default cache delay value of " - + Constants.CACHE_DEFAULT_DELAY_MINS + "."); - } - - this.isFullCertChainValidationEnabled = isFullCertChainValidationEnabled; - this.isCertExpiryValidationEnabled = isCertExpiryValidationEnabled; - } - - /** - * This method verifies the given certificate chain or given peer certificate for revocation based on the - * requirement of full certificate chain validation. If full chain validation is enabled (default), - * the full certificate chain will be validated before checking the chain for revocation. If full chain validation - * is disabled, this method expects a single peer certificate, and it is validated with the immediate issuer - * certificate in the truststore (The truststore must contain the immediate issuer of the peer certificate). - * In both cases, OCSP and CRL verifiers are used for revocation verification. - * It first tries to verify using OCSP since OCSP verification is faster. If that fails it tries to do the - * verification using CRL. - * - * @param peerCertificates javax.security.cert.X509Certificate[] array of peer certificate chain from peer/client. - * @throws CertificateVerificationException - */ - public void verifyCertificateValidity(javax.security.cert.X509Certificate[] peerCertificates) - throws CertificateVerificationException { - - X509Certificate[] convertedCertificates = convert(peerCertificates); - - Optional peerCertOpt; - X509Certificate peerCert = null; - X509Certificate issuerCert = null; - String alias; - - if (!isFullCertChainValidationEnabled) { - - if (log.isDebugEnabled()) { - log.debug("Retrieving the issuer certificate from client truststore since full certificate chain " + - "validation is disabled"); - } - - KeyStore trustStore = TrustStoreHolder.getInstance().getClientTrustStore(); - Enumeration aliases; - - // When full chain validation is disabled, only one cert is expected - peerCertOpt = Arrays.stream(convertedCertificates).findFirst(); - if (peerCertOpt.isPresent()) { - peerCert = peerCertOpt.get(); - } else { - throw new CertificateVerificationException("Peer certificate is not provided"); - } - - // Get cert cache and initialize it - CertCache certCache = CertCache.getCache(); - - if (certCache.getCacheValue(peerCert.getSerialNumber().toString()) == null) { - - try { - aliases = trustStore.aliases(); - } catch (KeyStoreException e) { - throw new CertificateVerificationException("Error while retrieving aliases from truststore", e); - } - - while (aliases.hasMoreElements()) { - - alias = aliases.nextElement(); - try { - issuerCert = (X509Certificate) trustStore.getCertificate(alias); - } catch (KeyStoreException e) { - throw new CertificateVerificationException("Unable to read the certificate from " + - "truststore with the alias: " + alias, e); - } - - if (issuerCert == null) { - throw new CertificateVerificationException("Issuer certificate not found in truststore"); - } - - try { - peerCert.verify(issuerCert.getPublicKey()); - - log.debug("Valid issuer certificate found in the client truststore. Caching.."); - - // Store the valid issuer cert in cache for future use - certCache.setCacheValue(peerCert.getSerialNumber().toString(), issuerCert); - if (log.isDebugEnabled()) { - log.debug("Issuer certificate with serial number: " + issuerCert.getSerialNumber() - .toString() + " has been cached against the serial number: " + peerCert - .getSerialNumber().toString() + " of the peer certificate."); - } - break; - } catch (SignatureException | CertificateException | NoSuchAlgorithmException | - InvalidKeyException | NoSuchProviderException e) { - // Unable to verify the signature. Check with the next certificate in the next loop traversal. - } - } - } else { - X509Certificate cachedIssuerCert = certCache.getCacheValue(peerCert.getSerialNumber().toString()); - try { - peerCert.verify(cachedIssuerCert.getPublicKey()); - } catch (SignatureException | CertificateException | NoSuchAlgorithmException | - InvalidKeyException | - NoSuchProviderException e) { - // Unable to verify the signature. - throw new CertificateVerificationException("Unable to verify the signature of the certificate."); - } - } - } - - OCSPCache ocspCache = OCSPCache.getCache(cacheSize, cacheDelayMins); - CRLCache crlCache = CRLCache.getCache(cacheSize, cacheDelayMins); - - RevocationVerifier[] verifiers = {new OCSPVerifier(ocspCache), new CRLVerifier(crlCache)}; - - for (RevocationVerifier verifier : verifiers) { - try { - if (isFullCertChainValidationEnabled) { - - if (isCertExpiryValidationEnabled) { - log.debug("Validating certificate chain for expiry"); - if (isExpired(convertedCertificates)) { - throw new CertificateVerificationException("One of the provided certificates are expired"); - } - } - - log.debug("Doing full certificate chain validation"); - CertificatePathValidator pathValidator = new CertificatePathValidator(convertedCertificates, - verifier); - pathValidator.validatePath(); - } else { - - if (isCertExpiryValidationEnabled) { - log.debug("Validating the client certificate for expiry"); - if (isExpired(convertedCertificates)) { - throw new CertificateVerificationException("The provided certificate is expired"); - } - } - - log.debug("Validating client certificate with the issuer certificate retrieved from" + - "the trust store"); - verifier.checkRevocationStatus(peerCert, issuerCert); - } - return; - } catch (Exception e) { - log.debug("Certificate verification with " + verifier.getClass().getSimpleName() + " failed. ", e); - } - } - throw new CertificateVerificationException("Path Verification Failed for both OCSP and CRL"); - } - - /** - * @param certs array of javax.security.cert.X509Certificate[] s. - * @return the converted array of java.security.cert.X509Certificate[] s. - * @throws CertificateVerificationException - */ - private X509Certificate[] convert(javax.security.cert.X509Certificate[] certs) - throws CertificateVerificationException { - X509Certificate[] certChain = new X509Certificate[certs.length]; - Throwable exceptionThrown; - for (int i = 0; i < certs.length; i++) { - try { - byte[] encoded = certs[i].getEncoded(); - ByteArrayInputStream bis = new ByteArrayInputStream(encoded); - java.security.cert.CertificateFactory cf - = java.security.cert.CertificateFactory.getInstance("X.509"); - certChain[i]=((X509Certificate)cf.generateCertificate(bis)); - continue; - } catch (java.security.cert.CertificateEncodingException e) { - exceptionThrown = e; - } catch (javax.security.cert.CertificateEncodingException e) { - exceptionThrown = e; - } catch (java.security.cert.CertificateException e) { - exceptionThrown = e; - } - throw new CertificateVerificationException("Cant Convert certificates from javax to java", exceptionThrown); - } - return certChain; - } - - /** - * Checks whether a provided certificate is expired or not at the time it is validated. - * - * @param certificates certificates to be validated for expiry - * @return true if one of the certs are expired, false otherwise - */ - public boolean isExpired(X509Certificate[] certificates) { - - for (X509Certificate cert : certificates) { - try { - cert.checkValidity(); - } catch (CertificateExpiredException e) { - log.error("Peer certificate is expired"); - return true; - } catch (CertificateNotYetValidException e) { - log.error("Peer certificate is not valid yet"); - return true; - } - } - return false; - } -} 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/RevocationVerificationManager.java new file mode 100644 index 0000000000..338b8a8a36 --- /dev/null +++ b/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/certificatevalidation/RevocationVerificationManager.java @@ -0,0 +1,116 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF 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 + * + * 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.apache.synapse.transport.certificatevalidation; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.synapse.transport.certificatevalidation.crl.CRLCache; +import org.apache.synapse.transport.certificatevalidation.crl.CRLVerifier; +import org.apache.synapse.transport.certificatevalidation.ocsp.OCSPCache; +import org.apache.synapse.transport.certificatevalidation.ocsp.OCSPVerifier; +import org.apache.synapse.transport.certificatevalidation.pathvalidation.CertificatePathValidator; + +import java.io.ByteArrayInputStream; +import java.security.cert.X509Certificate; + +/** + * Manager class responsible for verifying certificates. This class will use the available verifiers according to + * a predefined policy. + */ +public class RevocationVerificationManager { + + private int cacheSize = Constants.CACHE_DEFAULT_ALLOCATED_SIZE; + private int cacheDelayMins = Constants.CACHE_DEFAULT_DELAY_MINS; + private static final Log log = LogFactory.getLog(RevocationVerificationManager.class); + + public RevocationVerificationManager(Integer cacheAllocatedSize, Integer cacheDelayMins) { + + if (cacheAllocatedSize != null && cacheAllocatedSize > Constants.CACHE_MIN_ALLOCATED_SIZE + && cacheAllocatedSize < Constants.CACHE_MAX_ALLOCATED_SIZE) { + this.cacheSize = cacheAllocatedSize; + } + if (cacheDelayMins != null && cacheDelayMins > Constants.CACHE_MIN_DELAY_MINS + && cacheDelayMins < Constants.CACHE_MAX_DELAY_MINS) { + this.cacheDelayMins = cacheDelayMins; + } + } + + /** + * This method first tries to verify the given certificate chain using OCSP since OCSP verification is + * faster. If that fails it tries to do the verification using CRL. + * @param peerCertificates javax.security.cert.X509Certificate[] array of peer certificate chain from peer/client. + * @throws CertificateVerificationException + */ + public void verifyRevocationStatus(javax.security.cert.X509Certificate[] peerCertificates) + throws CertificateVerificationException { + + X509Certificate[] convertedCertificates = convert(peerCertificates); + + long start = System.currentTimeMillis(); + + OCSPCache ocspCache = OCSPCache.getCache(); + ocspCache.init(cacheSize, cacheDelayMins); + CRLCache crlCache = CRLCache.getCache(); + crlCache.init(cacheSize, cacheDelayMins); + + RevocationVerifier[] verifiers = {new OCSPVerifier(ocspCache), new CRLVerifier(crlCache)}; + + for (RevocationVerifier verifier : verifiers) { + try { + CertificatePathValidator pathValidator = new CertificatePathValidator(convertedCertificates, verifier); + pathValidator.validatePath(); + log.info("Path verification Successful. Took " + (System.currentTimeMillis() - start) + " ms."); + return; + } catch (Exception e) { + log.info(verifier.getClass().getSimpleName() + " failed."); + log.debug("Certificate verification with " + verifier.getClass().getSimpleName() + " failed. ", e); + } + } + throw new CertificateVerificationException("Path Verification Failed for both OCSP and CRL"); + } + + /** + * @param certs array of javax.security.cert.X509Certificate[] s. + * @return the converted array of java.security.cert.X509Certificate[] s. + * @throws CertificateVerificationException + */ + private X509Certificate[] convert(javax.security.cert.X509Certificate[] certs) + throws CertificateVerificationException { + X509Certificate[] certChain = new X509Certificate[certs.length]; + Throwable exceptionThrown; + for (int i = 0; i < certs.length; i++) { + try { + byte[] encoded = certs[i].getEncoded(); + ByteArrayInputStream bis = new ByteArrayInputStream(encoded); + java.security.cert.CertificateFactory cf + = java.security.cert.CertificateFactory.getInstance("X.509"); + certChain[i]=((X509Certificate)cf.generateCertificate(bis)); + continue; + } catch (java.security.cert.CertificateEncodingException e) { + exceptionThrown = e; + } catch (javax.security.cert.CertificateEncodingException e) { + exceptionThrown = e; + } catch (java.security.cert.CertificateException e) { + exceptionThrown = e; + } + throw new CertificateVerificationException("Cant Convert certificates from javax to java", exceptionThrown); + } + return certChain; + } +} diff --git a/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/certificatevalidation/cache/CertCache.java b/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/certificatevalidation/cache/CertCache.java deleted file mode 100644 index 9ada86e88d..0000000000 --- a/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/certificatevalidation/cache/CertCache.java +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF 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 - * - * 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.apache.synapse.transport.certificatevalidation.cache; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.synapse.commons.jmx.MBeanRegistrar; -import org.apache.synapse.transport.certificatevalidation.Constants; - -import java.security.cert.X509Certificate; -import java.util.Iterator; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -/** - * This is a cache to store a certificate against a unique string (can be a serial number). This is a singleton since - * more than one cache of this kind should not be allowed. This cache can be used by any place where certificate - * caching is needed. - */ -public class CertCache implements ManageableCache { - - private static volatile CertCache cache; - private static volatile Map hashMap = new ConcurrentHashMap(); - private static volatile Iterator> iterator = hashMap.entrySet().iterator(); - private static volatile CacheManager cacheManager; - private static final Log log = LogFactory.getLog(CertCache.class); - - private CertCache() { - } - - public static CertCache getCache() { - //Double-checked locking - if (cache == null) { - synchronized (CertCache.class) { - if (cache == null) { - cache = new CertCache(); - cacheManager = new CacheManager(cache, Constants.CACHE_DEFAULT_ALLOCATED_SIZE, - Constants.CACHE_DEFAULT_DELAY_MINS); - } - } - } - return cache; - } - - public synchronized X509Certificate getCacheValue(String serialNumber) { - CertCacheValue cacheValue = hashMap.get(serialNumber); - if (cacheValue != null) { - return cacheValue.getValue(); - } else - return null; - } - - @Override - public ManageableCacheValue getNextCacheValue() { - - if (iterator.hasNext()) { - return hashMap.get(iterator.next().getKey()); - } else { - resetIterator(); - return null; - } - } - - @Override - public int getCacheSize() { - - return hashMap.size(); - } - - @Override - public void resetIterator() { - - iterator = hashMap.entrySet().iterator(); - } - - public static void resetCache() { - - hashMap.clear(); - } - - public synchronized void setCacheValue(String serialNumber, X509Certificate cert) { - CertCacheValue cacheValue = new CertCacheValue(serialNumber, cert); - - if (log.isDebugEnabled()) { - log.debug("Before set - HashMap size " + hashMap.size()); - } - hashMap.put(serialNumber, cacheValue); - if (log.isDebugEnabled()) { - log.debug("After set - HashMap size " + hashMap.size()); - } - } - - public synchronized void removeCacheValue(String serialNumber) { - - if (log.isDebugEnabled()) { - log.debug("Before remove - HashMap size " + hashMap.size()); - } - hashMap.remove(serialNumber); - if (log.isDebugEnabled()) { - log.debug("After remove - HashMap size " + hashMap.size()); - } - } - - /** - * This is the wrapper class of the actual cache value. - */ - private class CertCacheValue implements ManageableCacheValue { - - private final String serialNumber; - private final X509Certificate issuerCertificate; - private final long timeStamp = System.currentTimeMillis(); - - public CertCacheValue(String serialNumber, X509Certificate issuerCertificate) { - - this.serialNumber = serialNumber; - this.issuerCertificate = issuerCertificate; - } - - public X509Certificate getValue() { - - return issuerCertificate; - } - - public String getKey() { - - return serialNumber; - } - - public boolean isValid() { - - // Will be always return true since we only set defined data. - return true; - } - - public long getTimeStamp() { - - return timeStamp; - } - - /** - * Used by cacheManager to remove invalid entries. - */ - public void removeThisCacheValue() { - - removeCacheValue(serialNumber); - } - - public void updateCacheWithNewValue() { - // No implementation needed since there are no scenarios of the cache value being invalid. - } - } -} diff --git a/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/certificatevalidation/crl/CRLCache.java b/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/certificatevalidation/crl/CRLCache.java index 2597960102..11db425524 100644 --- a/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/certificatevalidation/crl/CRLCache.java +++ b/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/certificatevalidation/crl/CRLCache.java @@ -50,13 +50,12 @@ public class CRLCache implements ManageableCache { private CRLCache() { } - public static CRLCache getCache(int cacheSize, int cacheDelayMins) { + public static CRLCache getCache() { //Double checked locking if (cache == null) { synchronized (CRLCache.class) { if (cache == null) { cache = new CRLCache(); - cacheManager = new CacheManager(cache, cacheSize, cacheDelayMins); } } } diff --git a/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/certificatevalidation/ocsp/OCSPCache.java b/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/certificatevalidation/ocsp/OCSPCache.java index cf904cd3f4..b01d509867 100644 --- a/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/certificatevalidation/ocsp/OCSPCache.java +++ b/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/certificatevalidation/ocsp/OCSPCache.java @@ -22,7 +22,6 @@ import org.apache.commons.logging.LogFactory; import org.apache.synapse.commons.jmx.MBeanRegistrar; import org.apache.synapse.transport.certificatevalidation.CertificateVerificationException; -import org.apache.synapse.transport.certificatevalidation.Constants; import org.apache.synapse.transport.certificatevalidation.cache.CacheController; import org.apache.synapse.transport.certificatevalidation.cache.CacheManager; import org.apache.synapse.transport.certificatevalidation.cache.ManageableCache; @@ -52,14 +51,12 @@ public class OCSPCache implements ManageableCache { private OCSPCache() {} - public static OCSPCache getCache(int cacheSize, int cacheDelayMins) { + public static OCSPCache getCache() { //Double checked locking if (cache == null) { synchronized (OCSPCache.class) { - if (cache == null) { + if (cache == null) cache = new OCSPCache(); - cacheManager = new CacheManager(cache, cacheSize, cacheDelayMins); - } } } return cache; @@ -119,7 +116,7 @@ private synchronized void replaceNewCacheValue(OCSPCacheValue cacheValue){ try { String serviceUrl = cacheValue.serviceUrl; OCSPReq request = cacheValue.request; - OCSPResp response= ocspVerifier.getOCSPResponse(serviceUrl, request); + OCSPResp response= ocspVerifier.getOCSPResponce(serviceUrl, request); if (OCSPResponseStatus.SUCCESSFUL != response.getStatus()) throw new CertificateVerificationException("OCSP response status not SUCCESSFUL"); diff --git a/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/certificatevalidation/ocsp/OCSPVerifier.java b/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/certificatevalidation/ocsp/OCSPVerifier.java index 5744365730..d9a3a11039 100644 --- a/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/certificatevalidation/ocsp/OCSPVerifier.java +++ b/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/certificatevalidation/ocsp/OCSPVerifier.java @@ -20,42 +20,20 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.apache.http.HttpResponse; -import org.apache.http.client.config.RequestConfig; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.entity.ByteArrayEntity; -import org.apache.http.entity.ContentType; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.HttpClientBuilder; -import org.apache.synapse.transport.certificatevalidation.CertificateVerificationException; -import org.apache.synapse.transport.certificatevalidation.Constants; -import org.apache.synapse.transport.certificatevalidation.RevocationStatus; -import org.apache.synapse.transport.certificatevalidation.RevocationVerifier; -import org.bouncycastle.asn1.ASN1InputStream; -import org.bouncycastle.asn1.DERIA5String; -import org.bouncycastle.asn1.DEROctetString; +import org.bouncycastle.asn1.*; import org.bouncycastle.asn1.ocsp.OCSPObjectIdentifiers; import org.bouncycastle.asn1.ocsp.OCSPResponseStatus; -import org.bouncycastle.asn1.x509.AccessDescription; -import org.bouncycastle.asn1.x509.AuthorityInformationAccess; -import org.bouncycastle.asn1.x509.Extension; -import org.bouncycastle.asn1.x509.Extensions; -import org.bouncycastle.asn1.x509.GeneralName; +import org.bouncycastle.asn1.x509.*; import org.bouncycastle.cert.X509CertificateHolder; -import org.bouncycastle.cert.ocsp.BasicOCSPResp; -import org.bouncycastle.cert.ocsp.CertificateID; -import org.bouncycastle.cert.ocsp.CertificateStatus; -import org.bouncycastle.cert.ocsp.OCSPReq; -import org.bouncycastle.cert.ocsp.OCSPReqBuilder; -import org.bouncycastle.cert.ocsp.OCSPResp; -import org.bouncycastle.cert.ocsp.SingleResp; +import org.bouncycastle.cert.ocsp.*; +import org.apache.synapse.transport.certificatevalidation.*; import org.bouncycastle.operator.DigestCalculatorProvider; import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder; -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStream; +import java.io.*; import java.math.BigInteger; +import java.net.HttpURLConnection; +import java.net.URL; import java.security.Provider; import java.security.Security; import java.security.cert.X509Certificate; @@ -74,12 +52,6 @@ public OCSPVerifier(OCSPCache cache) { this.cache = cache; } - public static final String CONTENT_TYPE = "Content-Type"; - public static final String JSON_TYPE ="application/json"; - public static final String ACCEPT_TYPE = "Accept"; - public static final String OCSP_REQUEST_TYPE = "application/ocsp-request"; - public static final String OCSP_RESPONSE_TYPE = "application/ocsp-response"; - /** * Gets the revocation status (Good, Revoked or Unknown) of the given peer certificate. * @@ -111,7 +83,7 @@ public RevocationStatus checkRevocationStatus(X509Certificate peerCert, X509Cert SingleResp[] responses; try { - OCSPResp ocspResponse = getOCSPResponse(serviceUrl, request); + OCSPResp ocspResponse = getOCSPResponce(serviceUrl, request); if (OCSPResponseStatus.SUCCESSFUL != ocspResponse.getStatus()) { continue; // Server didn't give the response right. } @@ -156,34 +128,37 @@ private RevocationStatus getRevocationStatus(SingleResp resp) throws Certificate * @throws CertificateVerificationException * */ - protected OCSPResp getOCSPResponse(String serviceUrl, OCSPReq request) throws CertificateVerificationException { - - if (log.isDebugEnabled()) { - log.debug("Initiating HTTP request to URL: " + serviceUrl + " to get the OCSP response"); - } - - try (CloseableHttpClient client = HttpClientBuilder.create().build()) { - HttpPost httpPost = new HttpPost(serviceUrl); + protected OCSPResp getOCSPResponce(String serviceUrl, OCSPReq request) throws CertificateVerificationException { - // adding request timeout configurations - if (httpPost.getConfig() == null) { - httpPost.setConfig(RequestConfig.custom().build()); - } + try { + //Todo: Use http client. + byte[] array = request.getEncoded(); + if (serviceUrl.startsWith("http")) { + HttpURLConnection con; + URL url = new URL(serviceUrl); + con = (HttpURLConnection) url.openConnection(); + con.setRequestProperty("Content-Type", "application/ocsp-request"); + con.setRequestProperty("Accept", "application/ocsp-response"); + con.setDoOutput(true); + OutputStream out = con.getOutputStream(); + DataOutputStream dataOut = new DataOutputStream(new BufferedOutputStream(out)); + dataOut.write(array); + + dataOut.flush(); + dataOut.close(); + + //Check errors in response: + if (con.getResponseCode() / 100 != 2) { + throw new CertificateVerificationException("Error getting ocsp response." + + "Response code is " + con.getResponseCode()); + } - httpPost.addHeader(CONTENT_TYPE, OCSP_REQUEST_TYPE); - httpPost.addHeader(ACCEPT_TYPE, OCSP_RESPONSE_TYPE); - httpPost.setEntity(new ByteArrayEntity(request.getEncoded(), ContentType.create(JSON_TYPE))); - HttpResponse httpResponse = client.execute(httpPost); - - //Check errors in response, if response status code is not 200 (success) range, throws exception - // eg: if response code is 200 (success) or 201 (accepted) return true, - // if response code is 404 (not found) or 500 throw exception - if (httpResponse.getStatusLine().getStatusCode() / 100 != 2) { - throw new CertificateVerificationException("Error getting ocsp response." + - "Response code is " + httpResponse.getStatusLine().getStatusCode()); + //Get Response + InputStream in = (InputStream) con.getContent(); + return new OCSPResp(in); + } else { + throw new CertificateVerificationException("Only http is supported for ocsp calls"); } - InputStream in = httpResponse.getEntity().getContent(); - return new OCSPResp(in); } catch (IOException e) { throw new CertificateVerificationException("Cannot get ocspResponse from url: " + serviceUrl, e); } diff --git a/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/certificatevalidation/pathvalidation/CertificatePathValidator.java b/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/certificatevalidation/pathvalidation/CertificatePathValidator.java index b6335f88a4..b041a7314d 100644 --- a/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/certificatevalidation/pathvalidation/CertificatePathValidator.java +++ b/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/certificatevalidation/pathvalidation/CertificatePathValidator.java @@ -22,7 +22,6 @@ import org.apache.commons.logging.LogFactory; import org.apache.synapse.transport.certificatevalidation.*; -import java.lang.reflect.InvocationTargetException; import java.security.*; import java.security.cert.X509Certificate; import java.util.List; 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 e5c94d91f6..24977a7115 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.CertificateVerificationManager; +import org.apache.synapse.transport.certificatevalidation.RevocationVerificationManager; public class ClientSSLSetupHandler implements SSLSetupHandler { @@ -139,10 +139,10 @@ public void verify( }; private final X509HostnameVerifier hostnameVerifier; - private final CertificateVerificationManager verificationManager; + private final RevocationVerificationManager verificationManager; public ClientSSLSetupHandler(final X509HostnameVerifier hostnameVerifier, - final CertificateVerificationManager verificationManager) { + final RevocationVerificationManager verificationManager) { this.hostnameVerifier = hostnameVerifier != null ? hostnameVerifier : DEFAULT; this.verificationManager = verificationManager; } @@ -184,7 +184,7 @@ public void verify(IOSession iosession, SSLSession sslsession) throws SSLExcepti if (verificationManager!=null) { try { - verificationManager.verifyCertificateValidity(sslsession.getPeerCertificateChain()); + verificationManager.verifyRevocationStatus(sslsession.getPeerCertificateChain()); } catch (CertificateVerificationException e) { throw new SSLException("Certificate Chain Validation failed for host : " + address, e); } 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 bb4e7c08d6..a4bc324ce1 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,12 +21,11 @@ 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.CertificateVerificationManager; +import org.apache.synapse.transport.certificatevalidation.RevocationVerificationManager; import java.net.InetAddress; import java.net.InetSocketAddress; @@ -37,12 +36,12 @@ public class ServerSSLSetupHandler implements SSLSetupHandler { private final SSLClientAuth clientAuth; /** Enabled SSL handshake protocols (e.g. SSLv3, TLSv1) */ private final String[] httpsProtocols; - private CertificateVerificationManager verificationManager; + private RevocationVerificationManager verificationManager; /** Ciphers enabled in axis2.xml, enabled all if null*/ private final String[] preferredCiphers; public ServerSSLSetupHandler(final SSLClientAuth clientAuth, final String[] httpsProtocols, - final CertificateVerificationManager verificationManager, final String[] preferredCiphers) { + final RevocationVerificationManager verificationManager, final String[] preferredCiphers) { this.clientAuth = clientAuth; this.httpsProtocols = httpsProtocols; this.verificationManager = verificationManager; @@ -79,7 +78,7 @@ public void verify( if (verificationManager != null) { try { - verificationManager.verifyCertificateValidity(sslsession.getPeerCertificateChain()); + verificationManager.verifyRevocationStatus(sslsession.getPeerCertificateChain()); } 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 5495ae9fc2..bf504b9999 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 @@ -19,6 +19,27 @@ package org.apache.synapse.transport.nhttp.config; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.security.GeneralSecurityException; +import java.security.KeyStore; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Locale; +import java.util.Map; + +import javax.net.ssl.KeyManager; +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; +import javax.net.ssl.TrustManagerFactory; +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamException; + +import org.apache.axiom.om.OMAttribute; import org.apache.axiom.om.OMElement; import org.apache.axiom.om.impl.builder.StAXOMBuilder; import org.apache.axis2.AxisFault; @@ -31,7 +52,8 @@ 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.CertificateVerificationManager; +import org.apache.synapse.commons.crypto.CryptoConstants; +import org.apache.synapse.transport.certificatevalidation.RevocationVerificationManager; import org.apache.synapse.transport.exceptions.InvalidConfigurationException; import org.apache.synapse.transport.http.conn.ClientConnFactory; import org.apache.synapse.transport.http.conn.ClientSSLSetupHandler; @@ -41,25 +63,8 @@ import org.apache.synapse.transport.nhttp.util.SecureVaultValueReader; import org.wso2.securevault.SecretResolver; import org.wso2.securevault.SecretResolverFactory; - -import javax.net.ssl.KeyManager; -import javax.net.ssl.KeyManagerFactory; -import javax.net.ssl.SSLContext; -import javax.net.ssl.TrustManager; -import javax.net.ssl.TrustManagerFactory; -import javax.xml.namespace.QName; -import javax.xml.stream.XMLStreamException; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.security.GeneralSecurityException; -import java.security.KeyStore; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Locale; -import java.util.Map; +import org.wso2.securevault.SecureVaultException; +import org.wso2.securevault.commons.MiscellaneousUtil; public class ClientConnFactoryBuilder { @@ -71,7 +76,6 @@ public class ClientConnFactoryBuilder { private SSLContextDetails ssl = null; private Map sslByHostMap = null; private ConfigurationContext configurationContext; - TrustStoreHolder trustStoreHolder = TrustStoreHolder.getInstance(); public ClientConnFactoryBuilder(final TransportOutDescription transportOut, ConfigurationContext configurationContext) { this(transportOut); @@ -83,7 +87,7 @@ public ClientConnFactoryBuilder(final TransportOutDescription transportOut) { this.transportOut = transportOut; this.name = transportOut.getName().toUpperCase(Locale.US); } - + public ClientConnFactoryBuilder parseSSL() throws AxisFault { Parameter keyParam = transportOut.getParameter("keystore"); Parameter trustParam = transportOut.getParameter("truststore"); @@ -129,7 +133,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; - CertificateVerificationManager certificateVerifier = null; + RevocationVerificationManager revocationVerifier = null; if ("true".equalsIgnoreCase(cvEnable)) { String cacheSizeString = cvp.getParameterElement().getFirstChildWithName(new QName("CacheSize")).getText(); @@ -142,7 +146,7 @@ public ClientConnFactoryBuilder parseSSL() throws AxisFault { cacheDelay = new Integer(cacheDelayString); } catch (NumberFormatException e) { } - certificateVerifier = new CertificateVerificationManager(cacheSize, cacheDelay); + revocationVerifier = new RevocationVerificationManager(cacheSize, cacheDelay); } // Process HttpProtocols @@ -163,7 +167,7 @@ public ClientConnFactoryBuilder parseSSL() throws AxisFault { } // Initiated separately to cater setting https protocols - ClientSSLSetupHandler clientSSLSetupHandler = new ClientSSLSetupHandler(hostnameVerifier, certificateVerifier); + ClientSSLSetupHandler clientSSLSetupHandler = new ClientSSLSetupHandler(hostnameVerifier, revocationVerifier); if (null != httpsProtocols) { clientSSLSetupHandler.setHttpsProtocols(httpsProtocols); @@ -349,37 +353,28 @@ private SSLContext createSSLContext(OMElement keyStoreElt, OMElement trustStoreE log.warn(name + " Ignoring novalidatecert parameter since a truststore has been specified"); } - FileInputStream fis = null; - String location = trustStoreElt.getFirstChildWithName(new QName("Location")).getText();; - KeyStore trustStore; + String location = trustStoreElt.getFirstChildWithName(new QName("Location")).getText(); + String type = trustStoreElt.getFirstChildWithName(new QName("Type")).getText(); + OMElement passwordElement = trustStoreElt.getFirstChildWithName(new QName("Password")); + if (passwordElement == null) { + throw new AxisFault("Cannot proceed because Password element is missing in TrustStore"); + } + String storePassword = SecureVaultValueReader.getSecureVaultValue(resolver, passwordElement); + FileInputStream fis = null; try { - if (trustStoreHolder.getClientTrustStore() == null) { - String type = trustStoreElt.getFirstChildWithName(new QName("Type")).getText(); - OMElement passwordElement = trustStoreElt.getFirstChildWithName(new QName("Password")); - - if (passwordElement == null) { - throw new AxisFault("Cannot proceed because Password element is missing in TrustStore"); - } - - String storePassword = SecureVaultValueReader.getSecureVaultValue(resolver, passwordElement); - trustStore = KeyStore.getInstance(type); - fis = new FileInputStream(location); - - if (log.isDebugEnabled()) { - log.debug(name + " Loading Trust Keystore from : " + location); - } - - trustStore.load(fis, storePassword.toCharArray()); - trustStoreHolder.setClientTrustStore(trustStore); - } else { - trustStore = trustStoreHolder.getClientTrustStore(); + KeyStore trustStore = KeyStore.getInstance(type); + fis = new FileInputStream(location); + if (log.isDebugEnabled()) { + log.debug(name + " Loading Trust Keystore from : " + location); } + trustStore.load(fis, storePassword.toCharArray()); TrustManagerFactory trustManagerfactory = TrustManagerFactory.getInstance( TrustManagerFactory.getDefaultAlgorithm()); trustManagerfactory.init(trustStore); trustManagers = trustManagerfactory.getTrustManagers(); + } catch (GeneralSecurityException gse) { log.error(name + " Error loading Key store : " + location, gse); throw new AxisFault("Error loading Key store : " + location, gse); @@ -429,9 +424,9 @@ private SSLContext createSSLContext(OMElement keyStoreElt, OMElement trustStoreE keyStoreElt.getFirstChildWithName(new QName("Password"))); String keyPassword = SecureVaultValueReader.getSecureVaultValue(secretResolver, keyStoreElt.getFirstChildWithName(new QName("KeyPassword"))); - - try (FileInputStream fis = new FileInputStream(location)) { - KeyStore keyStore = KeyStore.getInstance(type); + + try (FileInputStream fis = new FileInputStream(location)) { + KeyStore keyStore = KeyStore.getInstance(type); if (log.isDebugEnabled()) { log.debug(name + " Loading Identity Keystore from : " + location); } @@ -448,7 +443,7 @@ private SSLContext createSSLContext(OMElement keyStoreElt, OMElement trustStoreE } catch (IOException ioe) { log.error(name + " Error opening Keystore : " + location, ioe); throw new AxisFault("Error opening Keystore : " + location, ioe); - } + } } if (trustStoreElt != null) { @@ -456,35 +451,31 @@ private SSLContext createSSLContext(OMElement keyStoreElt, OMElement trustStoreE log.warn(name + " Ignoring novalidatecert parameter since a truststore has been specified"); } - KeyStore trustStore; String location = trustStoreElt.getFirstChildWithName(new QName("Location")).getText(); - + String type = trustStoreElt.getFirstChildWithName(new QName("Type")).getText(); + String storePassword = SecureVaultValueReader + .getSecureVaultValue(secretResolver, trustStoreElt.getFirstChildWithName(new QName("Password"))); + try (FileInputStream fis = new FileInputStream(location)) { - if (trustStoreHolder.getClientTrustStore() == null) { - String type = trustStoreElt.getFirstChildWithName(new QName("Type")).getText(); - String storePassword = SecureVaultValueReader.getSecureVaultValue(secretResolver, - trustStoreElt.getFirstChildWithName(new QName("Password"))); - trustStore = KeyStore.getInstance(type); - if (log.isDebugEnabled()) { - log.debug(name + " Loading Trust Keystore from : " + location); - } - trustStore.load(fis, storePassword.toCharArray()); - trustStoreHolder.setClientTrustStore(trustStore); - } else { - trustStore = trustStoreHolder.getClientTrustStore(); + KeyStore trustStore = KeyStore.getInstance(type); + + if (log.isDebugEnabled()) { + log.debug(name + " Loading Trust Keystore from : " + location); } + trustStore.load(fis, storePassword.toCharArray()); TrustManagerFactory trustManagerfactory = TrustManagerFactory.getInstance( TrustManagerFactory.getDefaultAlgorithm()); trustManagerfactory.init(trustStore); trustManagers = trustManagerfactory.getTrustManagers(); + } catch (GeneralSecurityException gse) { log.error(name + " Error loading Key store : " + location, gse); throw new AxisFault("Error loading Key store : " + location, gse); } catch (IOException ioe) { log.error(name + " Error opening Key store : " + location, ioe); throw new AxisFault("Error opening Key store : " + location, ioe); - } + } } else if (novalidatecert) { if (log.isWarnEnabled()) { log.warn(name + " Server certificate validation (trust) has been disabled. " + 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 b9b4b0018e..817c11e99b 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 @@ -26,12 +26,11 @@ import org.apache.axis2.description.Parameter; import org.apache.axis2.description.TransportInDescription; import org.apache.axis2.transport.base.ParamUtils; -import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.http.HttpHost; import org.apache.http.params.HttpParams; -import org.apache.synapse.transport.certificatevalidation.CertificateVerificationManager; +import org.apache.synapse.transport.certificatevalidation.RevocationVerificationManager; import org.apache.synapse.transport.http.conn.SSLClientAuth; import org.apache.synapse.transport.http.conn.SSLContextDetails; import org.apache.synapse.transport.http.conn.ServerConnFactory; @@ -41,13 +40,6 @@ import org.wso2.securevault.SecretResolver; import org.wso2.securevault.SecretResolverFactory; -import javax.net.ssl.KeyManager; -import javax.net.ssl.KeyManagerFactory; -import javax.net.ssl.SSLContext; -import javax.net.ssl.TrustManager; -import javax.net.ssl.TrustManagerFactory; -import javax.net.ssl.X509KeyManager; -import javax.xml.namespace.QName; import java.io.FileInputStream; import java.io.IOException; import java.net.InetSocketAddress; @@ -62,6 +54,14 @@ import java.util.Locale; import java.util.Map; +import javax.net.ssl.KeyManager; +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; +import javax.net.ssl.TrustManagerFactory; +import javax.net.ssl.X509KeyManager; +import javax.xml.namespace.QName; + public class ServerConnFactoryBuilder { private final Log log = LogFactory.getLog(ServerConnFactoryBuilder.class); @@ -73,7 +73,6 @@ 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) { @@ -90,13 +89,13 @@ public ServerConnFactoryBuilder(final TransportInDescription transportIn, final } protected SSLContextDetails createSSLContext( - final OMElement keyStoreEl, - final OMElement trustStoreEl, - final OMElement cientAuthEl, - final OMElement httpsProtocolsEl, - final OMElement preferredCiphersEl, - final CertificateVerificationManager verificationManager, - final String sslProtocol) throws AxisFault { + final OMElement keyStoreEl, + final OMElement trustStoreEl, + final OMElement cientAuthEl, + final OMElement httpsProtocolsEl, + final OMElement preferredCiphersEl, + final RevocationVerificationManager verificationManager, + final String sslProtocol) throws AxisFault { SecretResolver secretResolver; if (configurationContext != null && configurationContext.getAxisConfiguration() != null) { @@ -115,7 +114,7 @@ protected SSLContextDetails createSSLContext( final OMElement cientAuthEl, final OMElement httpsProtocolsEl, final OMElement preferredCiphersEl, - final CertificateVerificationManager verificationManager, + final RevocationVerificationManager verificationManager, final String sslProtocol, final SecretResolver secretResolver) throws AxisFault { KeyManager[] keymanagers = null; @@ -183,38 +182,25 @@ protected SSLContextDetails createSSLContext( } if (trustStoreEl != null) { + String location = getValueOfElementWithLocalName(trustStoreEl, "Location"); + String type = getValueOfElementWithLocalName(trustStoreEl, "Type"); + OMElement storePasswordEl = trustStoreEl.getFirstChildWithName(new QName("Password")); + if (storePasswordEl == null) { + throw new AxisFault("Cannot proceed because Password element is missing in TrustStore"); + } + String storePassword = SecureVaultValueReader.getSecureVaultValue(secretResolver, storePasswordEl); - TrustStoreHolder trustStoreHolder = TrustStoreHolder.getInstance(); FileInputStream fis = null; - String location = getValueOfElementWithLocalName(trustStoreEl, "Location"); - KeyStore trustStore; - try { - if (trustStoreHolder.getClientTrustStore() == null) { - - String type = getValueOfElementWithLocalName(trustStoreEl, "Type"); - OMElement storePasswordEl = trustStoreEl.getFirstChildWithName(new QName("Password")); - - if (storePasswordEl == null) { - throw new AxisFault("Cannot proceed because Password element is missing in TrustStore"); - } - - String storePassword = SecureVaultValueReader.getSecureVaultValue(secretResolver, storePasswordEl); - trustStore = KeyStore.getInstance(type); - fis = new FileInputStream(location); - - if (log.isDebugEnabled()) { - log.debug(name + " Loading Trust Keystore from : " + location); - } - - trustStore.load(fis, storePassword.toCharArray()); - trustStoreHolder.setClientTrustStore(trustStore); - } else { - trustStore = trustStoreHolder.getClientTrustStore(); + KeyStore trustStore = KeyStore.getInstance(type); + fis = new FileInputStream(location); + if (log.isDebugEnabled()) { + log.debug(name + " Loading Trust Keystore from : " + location); } + trustStore.load(fis, storePassword.toCharArray()); TrustManagerFactory trustManagerfactory = TrustManagerFactory.getInstance( - TrustManagerFactory.getDefaultAlgorithm()); + TrustManagerFactory.getDefaultAlgorithm()); trustManagerfactory.init(trustStore); trustManagers = trustManagerfactory.getTrustManagers(); @@ -308,6 +294,7 @@ 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(); @@ -318,33 +305,12 @@ public ServerConnFactoryBuilder parseSSL() throws AxisFault { cacheSize = new Integer(cacheSizeString); cacheDelay = new Integer(cacheDelayString); } - catch (NumberFormatException e) { - throw new AxisFault("Cache size or Cache delay values are malformed", e); - } - - // Checking whether the full certificate chain validation is enabled or not. - boolean isFullCertChainValidationEnabled = true; - boolean isCertExpiryValidationEnabled = false; - OMElement fullCertChainValidationConfig = cvp.getParameterElement() - .getFirstChildWithName(new QName("FullChainValidation")); - OMElement certExpiryValidationConfig = cvp.getParameterElement() - .getFirstChildWithName(new QName("ExpiryValidation")); - - if (fullCertChainValidationConfig != null - && StringUtils.equals("false", fullCertChainValidationConfig.getText())) { - isFullCertChainValidationEnabled = false; - } - - if (certExpiryValidationConfig != null && StringUtils.equals("true", certExpiryValidationConfig.getText())) { - isCertExpiryValidationEnabled = true; - } - - certificateVerifier = new CertificateVerificationManager(cacheSize, cacheDelay, - isFullCertChainValidationEnabled, isCertExpiryValidationEnabled); + catch (NumberFormatException e) {} + revocationVerifier = new RevocationVerificationManager(cacheSize, cacheDelay); } ssl = createSSLContext(keyStoreEl, trustStoreEl, clientAuthEl, httpsProtocolsEl, preferredCiphersEl, - certificateVerifier, sslProtocol); + revocationVerifier, sslProtocol); return this; } @@ -358,7 +324,6 @@ public ServerConnFactoryBuilder parseMultiProfileSSL() throws AxisFault { OMElement profilesEl = profileParam.getParameterElement(); SecretResolver secretResolver = SecretResolverFactory.create(profilesEl, true); Iterator profiles = profilesEl.getChildrenWithName(new QName("profile")); - while (profiles.hasNext()) { OMElement profileEl = (OMElement) profiles.next(); OMElement bindAddressEl = profileEl.getFirstChildWithName(new QName("bindAddress")); @@ -376,63 +341,8 @@ public ServerConnFactoryBuilder parseMultiProfileSSL() throws AxisFault { OMElement preferredCiphersEl = profileEl.getFirstChildWithName(new QName(NhttpConstants.PREFERRED_CIPHERS)); final Parameter sslpParameter = transportIn.getParameter("SSLProtocol"); final String sslProtocol = sslpParameter != null ? sslpParameter.getValue().toString() : "TLS"; - - /* If multi SSL profiles are configured, checking whether the certificate revocation verifier is - configured and full certificate chain validation is enabled or not. */ - if (profileEl.getFirstChildWithName(new QName("CertificateRevocationVerifier")) != null) { - - Integer cacheSize = null; - Integer cacheDelay = null; - - OMElement revocationVerifierConfig = profileEl - .getFirstChildWithName(new QName("CertificateRevocationVerifier")); - OMElement revocationEnabled = revocationVerifierConfig - .getFirstChildWithName(new QName("Enable")); - - if (revocationEnabled != null && "true".equals(revocationEnabled.getText())) { - String cacheSizeString = revocationVerifierConfig - .getFirstChildWithName(new QName("CacheSize")).getText(); - String cacheDelayString = revocationVerifierConfig - .getFirstChildWithName(new QName("CacheDelay")).getText(); - - try { - cacheSize = new Integer(cacheSizeString); - cacheDelay = new Integer(cacheDelayString); - } catch (NumberFormatException e) { - throw new AxisFault("Cache size or Cache delay values are malformed", e); - } - } - - boolean isFullCertChainValidationEnabled = true; - boolean isCertExpiryValidationEnabled = false; - - OMElement fullCertChainValidationConfig = revocationVerifierConfig - .getFirstChildWithName(new QName("FullChainValidation")); - - OMElement certExpiryValidationConfig = revocationVerifierConfig - .getFirstChildWithName(new QName("ExpiryValidation")); - - if (fullCertChainValidationConfig != null - && StringUtils.equals("false", fullCertChainValidationConfig.getText())) { - isFullCertChainValidationEnabled = false; - } - - if (certExpiryValidationConfig != null - && StringUtils.equals("true", certExpiryValidationConfig.getText())) { - isCertExpiryValidationEnabled = true; - } - - if (fullCertChainValidationConfig != null - && StringUtils.equals("false", fullCertChainValidationConfig.getText())) { - isFullCertChainValidationEnabled = false; - } - - certificateVerifier = new CertificateVerificationManager(cacheSize, cacheDelay, - isFullCertChainValidationEnabled, isCertExpiryValidationEnabled); - } - SSLContextDetails ssl = createSSLContext(keyStoreEl, trustStoreEl, clientAuthEl, httpsProtocolsEl, - preferredCiphersEl, certificateVerifier, sslProtocol, secretResolver); + preferredCiphersEl, null, sslProtocol, secretResolver); if (sslByIPMap == null) { sslByIPMap = new HashMap(); } diff --git a/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/nhttp/config/TrustStoreHolder.java b/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/nhttp/config/TrustStoreHolder.java deleted file mode 100644 index 697dd6eba6..0000000000 --- a/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/nhttp/config/TrustStoreHolder.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF 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 - * - * 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.apache.synapse.transport.nhttp.config; - -import java.security.KeyStore; - -/** - * A data holder class to store the client trust store. - */ -public class TrustStoreHolder { - - private static volatile TrustStoreHolder instance; - private KeyStore clientTrustStore; - - private TrustStoreHolder() {} - - public static TrustStoreHolder getInstance() { - - if (instance == null) { - synchronized (TrustStoreHolder.class) { - if (instance == null) { - instance = new TrustStoreHolder(); - } - } - } - return instance; - } - - public KeyStore getClientTrustStore() { - - return clientTrustStore; - } - - public void setClientTrustStore(KeyStore clientTrustStore) { - - this.clientTrustStore = clientTrustStore; - } - - /** - * Reset the instance. - */ - public static void resetInstance() { - - instance = null; - } -} diff --git a/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/passthru/PassThroughHttpListener.java b/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/passthru/PassThroughHttpListener.java index 3e7f92c6d6..1d4ddf2a6a 100644 --- a/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/passthru/PassThroughHttpListener.java +++ b/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/passthru/PassThroughHttpListener.java @@ -47,6 +47,8 @@ import org.apache.axis2.transport.TransportListener; import org.apache.axis2.transport.base.BaseConstants; import org.apache.axis2.transport.base.BaseUtils; +import org.apache.axis2.transport.base.ManagementSupport; +import org.apache.axis2.transport.base.TransportMBeanSupport; import org.apache.axis2.transport.base.threads.NativeThreadFactory; import org.apache.axis2.transport.base.threads.WorkerPool; import org.apache.axis2.transport.base.tracker.AxisServiceFilter; @@ -60,10 +62,8 @@ import org.apache.http.nio.reactor.IOReactorException; import org.apache.http.nio.reactor.IOReactorExceptionHandler; import org.apache.http.params.HttpConnectionParams; -import org.apache.synapse.transport.certificatevalidation.cache.CertCache; import org.apache.synapse.transport.http.conn.Scheme; import org.apache.synapse.transport.http.conn.ServerConnFactory; -import org.apache.synapse.transport.nhttp.config.TrustStoreHolder; import org.apache.synapse.transport.nhttp.config.ServerConnFactoryBuilder; import org.apache.synapse.transport.passthru.config.PassThroughConfiguration; import org.apache.synapse.transport.passthru.config.SourceConfiguration; @@ -683,4 +683,5 @@ public void reloadDynamicSSLConfig(TransportInDescription transportInDescription this.reloadSpecificEndPoints(transportInDescription); } } + } diff --git a/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/passthru/PassThroughHttpMultiSSLListener.java b/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/passthru/PassThroughHttpMultiSSLListener.java index 406ae5a53b..208b364178 100644 --- a/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/passthru/PassThroughHttpMultiSSLListener.java +++ b/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/passthru/PassThroughHttpMultiSSLListener.java @@ -5,12 +5,10 @@ import org.apache.axis2.description.ParameterInclude; import org.apache.axis2.description.TransportInDescription; import org.apache.http.HttpHost; -import org.apache.synapse.transport.certificatevalidation.cache.CertCache; import org.apache.synapse.transport.http.conn.Scheme; import org.apache.synapse.transport.nhttp.config.ServerConnFactoryBuilder; import org.apache.synapse.transport.dynamicconfigurations.ListenerProfileReloader; import org.apache.synapse.transport.dynamicconfigurations.SSLProfileLoader; -import org.apache.synapse.transport.nhttp.config.TrustStoreHolder; public class PassThroughHttpMultiSSLListener extends PassThroughHttpListener implements SSLProfileLoader{ @@ -41,8 +39,6 @@ protected ServerConnFactoryBuilder initConnFactoryBuilder(final TransportInDescr * @throws AxisFault */ public void reloadConfig(ParameterInclude transport) throws AxisFault { - CertCache.resetCache(); - TrustStoreHolder.resetInstance(); reloadDynamicSSLConfig((TransportInDescription) transport); } diff --git a/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/passthru/PassThroughHttpSender.java b/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/passthru/PassThroughHttpSender.java index b977eb30a7..3af961c03f 100644 --- a/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/passthru/PassThroughHttpSender.java +++ b/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/passthru/PassThroughHttpSender.java @@ -47,14 +47,12 @@ import org.apache.http.nio.reactor.IOReactorExceptionHandler; import org.apache.http.protocol.HTTP; import org.apache.synapse.commons.CorrelationConstants; -import org.apache.synapse.transport.certificatevalidation.cache.CertCache; import org.apache.synapse.transport.exceptions.InvalidConfigurationException; import org.apache.synapse.transport.http.conn.ClientConnFactory; import org.apache.synapse.transport.http.conn.ProxyConfig; import org.apache.synapse.transport.http.conn.Scheme; import org.apache.synapse.transport.nhttp.NhttpConstants; import org.apache.synapse.transport.nhttp.config.ClientConnFactoryBuilder; -import org.apache.synapse.transport.nhttp.config.TrustStoreHolder; import org.apache.synapse.transport.nhttp.config.ProxyConfigBuilder; import org.apache.synapse.transport.nhttp.util.MessageFormatterDecoratorFactory; import org.apache.synapse.transport.nhttp.util.NhttpUtil; @@ -559,7 +557,7 @@ public void submitResponse(MessageContext msgContext) ProtocolState state = SourceContext.getState(conn); if (state != null && state.compareTo(ProtocolState.REQUEST_DONE) <= 0) { // start sending the response if we - + boolean noEntityBodyResponse = false; if (noEntityBody != null && Boolean.TRUE == noEntityBody && pipe != null) { @@ -569,7 +567,7 @@ public void submitResponse(MessageContext msgContext) out.close(); noEntityBodyResponse = true; } - + if (!noEntityBodyResponse && msgContext.isPropertyTrue(PassThroughConstants.MESSAGE_BUILDER_INVOKED) && pipe != null) { OutputStream out = pipe.getOutputStream(); /*if (msgContext.isPropertyTrue(NhttpConstants.SC_ACCEPTED)) { 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 8ea5433d4f..282900b956 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,11 +19,12 @@ 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.CertificateVerificationManager; +import org.apache.synapse.transport.certificatevalidation.RevocationVerificationManager; import org.apache.synapse.transport.nhttp.config.ServerConnFactoryBuilder; import javax.xml.namespace.QName; @@ -45,7 +46,7 @@ public ServerConnFactoryBuilder parseSSL(OMElement keyStoreEl, OMElement trustSt AxisFault { final String cvEnable = cvp != null ? cvp.getAttribute(new QName("enable")).getAttributeValue() : null; - CertificateVerificationManager revocationVerifier = null; + RevocationVerificationManager revocationVerifier = null; if ("true".equalsIgnoreCase(cvEnable)) { Iterator iterator = cvp.getChildElements(); @@ -69,7 +70,7 @@ public ServerConnFactoryBuilder parseSSL(OMElement keyStoreEl, OMElement trustSt } catch (NumberFormatException e) { log.error("Please specify correct Integer numbers for CacheDelay and CacheSize"); } - revocationVerifier = new CertificateVerificationManager(cacheSize, cacheDelay); + revocationVerifier = new RevocationVerificationManager(cacheSize, cacheDelay); } ssl = createSSLContext(keyStoreEl, trustStoreEl, clientAuthEl, httpsProtocolsEl, preferredCiphers, revocationVerifier, diff --git a/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/util/ConfigurationBuilderUtil.java b/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/util/ConfigurationBuilderUtil.java index 406a7a2d30..f5a81c1572 100644 --- a/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/util/ConfigurationBuilderUtil.java +++ b/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/util/ConfigurationBuilderUtil.java @@ -170,4 +170,5 @@ public static String getStringProperty(String name, String def, Properties props return val == null ? def : val; } + } diff --git a/modules/transports/core/nhttp/src/test/java/org/apache/synapse/transport/certificatevalidation/CRLVerifierTest.java b/modules/transports/core/nhttp/src/test/java/org/apache/synapse/transport/certificatevalidation/CRLVerifierTest.java index ec582f9dd7..38d7964b8a 100644 --- a/modules/transports/core/nhttp/src/test/java/org/apache/synapse/transport/certificatevalidation/CRLVerifierTest.java +++ b/modules/transports/core/nhttp/src/test/java/org/apache/synapse/transport/certificatevalidation/CRLVerifierTest.java @@ -88,7 +88,8 @@ public void testRevokedCertificate() throws Exception { //Create a crl with fakeRevokedCertificate marked as revoked. X509CRL x509CRL = createCRL(fakeCACert, caKeyPair.getPrivate(), revokedSerialNumber); - CRLCache cache = CRLCache.getCache(5, 5); + CRLCache cache = CRLCache.getCache(); + cache.init(5, 5); cache.setCacheValue(crlDistributionPointUrl, x509CRL); CRLVerifier crlVerifier = new CRLVerifier(cache); diff --git a/modules/transports/core/nhttp/src/test/java/org/apache/synapse/transport/certificatevalidation/OCSPVerifierTest.java b/modules/transports/core/nhttp/src/test/java/org/apache/synapse/transport/certificatevalidation/OCSPVerifierTest.java index 9d4f0a01bd..9c2299bb2b 100644 --- a/modules/transports/core/nhttp/src/test/java/org/apache/synapse/transport/certificatevalidation/OCSPVerifierTest.java +++ b/modules/transports/core/nhttp/src/test/java/org/apache/synapse/transport/certificatevalidation/OCSPVerifierTest.java @@ -107,7 +107,8 @@ public void testOCSPVerifier() throws Exception{ OCSPResp response = generateOCSPResponse(request, certificateHolder, caKeyPair.getPrivate(), caKeyPair.getPublic(), revokedID); SingleResp singleResp = ((BasicOCSPResp)response.getResponseObject()).getResponses()[0]; - OCSPCache cache = OCSPCache.getCache(5, 5); + OCSPCache cache = OCSPCache.getCache(); + cache.init(5,5); cache.setCacheValue(revokedSerialNumber,singleResp, request, null); OCSPVerifier ocspVerifier= new OCSPVerifier(cache); diff --git a/modules/transports/core/nhttp/src/test/java/org/apache/synapse/transport/certificatevalidation/RevocationVerificationTest.java b/modules/transports/core/nhttp/src/test/java/org/apache/synapse/transport/certificatevalidation/RevocationVerificationTest.java index 9adc063ea0..7f282dd86c 100644 --- a/modules/transports/core/nhttp/src/test/java/org/apache/synapse/transport/certificatevalidation/RevocationVerificationTest.java +++ b/modules/transports/core/nhttp/src/test/java/org/apache/synapse/transport/certificatevalidation/RevocationVerificationTest.java @@ -116,7 +116,8 @@ public void testOCSPPathValidationWithFakeCerts() throws Exception { private void crlPathValidation(X509Certificate[] certChain) throws Exception { - CRLCache crlCache = CRLCache.getCache(5, 5); + CRLCache crlCache = CRLCache.getCache(); + crlCache.init(5, 5); RevocationVerifier verifier = new CRLVerifier(crlCache); CertificatePathValidator pathValidator = new CertificatePathValidator(certChain, verifier); pathValidator.validatePath(); @@ -124,7 +125,8 @@ private void crlPathValidation(X509Certificate[] certChain) throws Exception { private void ocspPathValidation(X509Certificate[] certChain) throws Exception { - OCSPCache ocspCache = OCSPCache.getCache(5, 5); + OCSPCache ocspCache = OCSPCache.getCache(); + ocspCache.init(5, 5); RevocationVerifier verifier = new OCSPVerifier(ocspCache); CertificatePathValidator pathValidator = new CertificatePathValidator(certChain, verifier); pathValidator.validatePath(); diff --git a/modules/transports/core/vfs/repository/conf/vfs-move-failed-records.properties b/modules/transports/core/vfs/repository/conf/vfs-move-failed-records.properties deleted file mode 100644 index 8f1ee4a76d..0000000000 --- a/modules/transports/core/vfs/repository/conf/vfs-move-failed-records.properties +++ /dev/null @@ -1 +0,0 @@ -t-0-1705986523002.txt 23/01/2024/ 10:38:43 \ No newline at end of file