Consolidating Crypto/Certificate loading in the IdP
Project: http://git-wip-us.apache.org/repos/asf/cxf-fediz/repo Commit: http://git-wip-us.apache.org/repos/asf/cxf-fediz/commit/f545ba0c Tree: http://git-wip-us.apache.org/repos/asf/cxf-fediz/tree/f545ba0c Diff: http://git-wip-us.apache.org/repos/asf/cxf-fediz/diff/f545ba0c Branch: refs/heads/master Commit: f545ba0c03ca60907ca78942d31ff9afbc00d0d5 Parents: 5263f52 Author: Colm O hEigeartaigh <[email protected]> Authored: Wed Feb 24 15:17:05 2016 +0000 Committer: Colm O hEigeartaigh <[email protected]> Committed: Wed Feb 24 15:17:05 2016 +0000 ---------------------------------------------------------------------- .../cxf/fediz/core/config/FedizContext.java | 4 + .../apache/cxf/fediz/core/util/CertsUtils.java | 30 ++++- .../TrustedIdpOIDCProtocolHandler.java | 131 +++++++------------ .../TrustedIdpSAMLProtocolHandler.java | 48 +++---- .../TrustedIdpWSFedProtocolHandler.java | 23 +--- 5 files changed, 104 insertions(+), 132 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/f545ba0c/plugins/core/src/main/java/org/apache/cxf/fediz/core/config/FedizContext.java ---------------------------------------------------------------------- diff --git a/plugins/core/src/main/java/org/apache/cxf/fediz/core/config/FedizContext.java b/plugins/core/src/main/java/org/apache/cxf/fediz/core/config/FedizContext.java index f94ac4a..bb352f8 100644 --- a/plugins/core/src/main/java/org/apache/cxf/fediz/core/config/FedizContext.java +++ b/plugins/core/src/main/java/org/apache/cxf/fediz/core/config/FedizContext.java @@ -23,6 +23,7 @@ import java.io.Closeable; import java.io.File; import java.io.IOException; import java.math.BigInteger; +import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.List; @@ -120,6 +121,9 @@ public class FedizContext implements Closeable { } catch (WSSecurityException e) { LOG.error("Failed to load keystore '" + tm.getName() + "'", e); throw new IllegalConfigurationException("Failed to load keystore '" + tm.getName() + "'"); + } catch (CertificateException ex) { + LOG.error("Failed to read keystore", ex); + throw new RuntimeException("Failed to read keystore"); } } return certificateStores; http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/f545ba0c/plugins/core/src/main/java/org/apache/cxf/fediz/core/util/CertsUtils.java ---------------------------------------------------------------------- diff --git a/plugins/core/src/main/java/org/apache/cxf/fediz/core/util/CertsUtils.java b/plugins/core/src/main/java/org/apache/cxf/fediz/core/util/CertsUtils.java index 0737ea1..038de09 100644 --- a/plugins/core/src/main/java/org/apache/cxf/fediz/core/util/CertsUtils.java +++ b/plugins/core/src/main/java/org/apache/cxf/fediz/core/util/CertsUtils.java @@ -20,9 +20,11 @@ package org.apache.cxf.fediz.core.util; import java.io.BufferedInputStream; +import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.security.cert.Certificate; +import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.util.Properties; @@ -32,6 +34,8 @@ import org.apache.wss4j.common.crypto.CryptoFactory; import org.apache.wss4j.common.crypto.CryptoType; import org.apache.wss4j.common.crypto.Merlin; import org.apache.wss4j.common.ext.WSSecurityException; +import org.apache.xml.security.exceptions.Base64DecodingException; +import org.apache.xml.security.utils.Base64; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -43,12 +47,17 @@ public final class CertsUtils { super(); } - public static X509Certificate getX509Certificate(String filename) { + public static X509Certificate getX509Certificate(String filename) throws CertificateException { return getX509Certificate(filename, Thread.currentThread().getContextClassLoader()); } - public static X509Certificate getX509Certificate(String filename, ClassLoader classLoader) { + public static X509Certificate getX509Certificate(String filename, ClassLoader classLoader) + throws CertificateException { + if (filename == null) { + return null; + } + ClassLoader cl = classLoader; if (cl == null) { cl = Thread.currentThread().getContextClassLoader(); @@ -74,9 +83,12 @@ public final class CertsUtils { LOG.error("No bytes can be read in certificate file " + filename); throw new RuntimeException("No bytes can be read in certificate file " + filename); } - } catch (Exception ex) { + } catch (WSSecurityException ex) { LOG.error("Failed to read certificate file " + filename, ex); throw new RuntimeException("Failed to read certificate file " + filename, ex); + } catch (IOException ex) { + LOG.error("Failed to read keystore", ex); + throw new RuntimeException("Failed to read keystore"); } } @@ -113,4 +125,16 @@ public final class CertsUtils { } return issuerCerts[0]; } + + public static X509Certificate parseCertificate(String certificate) + throws CertificateException, Base64DecodingException, IOException { + + //before decoding we need to get rod off the prefix and suffix + byte[] decoded = Base64.decode(certificate.replaceAll("-----BEGIN CERTIFICATE-----", ""). + replaceAll("-----END CERTIFICATE-----", "")); + + try (InputStream is = new ByteArrayInputStream(decoded)) { + return (X509Certificate)CertificateFactory.getInstance("X.509").generateCertificate(is); + } + } } http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/f545ba0c/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/protocols/TrustedIdpOIDCProtocolHandler.java ---------------------------------------------------------------------- diff --git a/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/protocols/TrustedIdpOIDCProtocolHandler.java b/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/protocols/TrustedIdpOIDCProtocolHandler.java index ea90193..52e007e 100644 --- a/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/protocols/TrustedIdpOIDCProtocolHandler.java +++ b/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/protocols/TrustedIdpOIDCProtocolHandler.java @@ -19,17 +19,15 @@ package org.apache.cxf.fediz.service.idp.protocols; -import java.io.ByteArrayInputStream; import java.io.IOException; -import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.net.MalformedURLException; import java.net.URL; import java.net.URLEncoder; import java.security.cert.CertificateException; -import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.util.ArrayList; +import java.util.Collections; import java.util.Date; import java.util.List; @@ -65,7 +63,6 @@ import org.apache.cxf.rs.security.oauth2.utils.OAuthConstants; import org.apache.cxf.ws.security.tokenstore.SecurityToken; import org.apache.wss4j.common.crypto.CertificateStore; import org.apache.wss4j.common.crypto.Crypto; -import org.apache.wss4j.common.crypto.Merlin; import org.apache.wss4j.common.ext.WSSecurityException; import org.apache.wss4j.common.saml.SAMLCallback; import org.apache.wss4j.common.saml.SAMLUtil; @@ -75,7 +72,6 @@ import org.apache.wss4j.common.saml.bean.SubjectBean; import org.apache.wss4j.common.saml.bean.Version; import org.apache.wss4j.common.saml.builder.SAML2Constants; import org.apache.xml.security.exceptions.Base64DecodingException; -import org.apache.xml.security.utils.Base64; import org.joda.time.DateTime; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -179,7 +175,7 @@ public class TrustedIdpOIDCProtocolHandler implements TrustedIdpProtocolHandler } try { - X509Certificate validatingCert = getCertificate(trustedIdp); + X509Certificate validatingCert = getCertificate(trustedIdp.getCertificate()); if (validatingCert == null) { LOG.warn("No X.509 Certificate configured for signature validation"); return null; @@ -238,53 +234,61 @@ public class TrustedIdpOIDCProtocolHandler implements TrustedIdpProtocolHandler return null; } - - private X509Certificate getCertificate(TrustedIdp trustedIdp) - throws CertificateException, Base64DecodingException, IOException { - String certificate = trustedIdp.getCertificate(); - if (certificate != null) { - boolean isCertificateLocation = !certificate.startsWith("-----BEGIN CERTIFICATE"); - if (isCertificateLocation) { - InputStream is = null; - try { - is = Merlin.loadInputStream(Thread.currentThread().getContextClassLoader(), certificate); - - CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); - return (X509Certificate) certFactory.generateCertificate(is); - } catch (WSSecurityException ex) { - LOG.error("Failed to load keystore " + certificate, ex); - throw new RuntimeException("Failed to load keystore " + certificate); - } catch (IOException ex) { - LOG.error("Failed to read keystore", ex); - throw new RuntimeException("Failed to read keystore"); - } catch (CertificateException ex) { - // This is ok as it could be a WSS4J properties file - } finally { - if (is != null) { - try { - is.close(); - } catch (IOException e) { - // Do nothing - } - } + private Crypto getCrypto(String certificate) throws ProcessingException { + if (certificate == null) { + return null; + } + + boolean isCertificateLocation = !certificate.startsWith("-----BEGIN CERTIFICATE"); + if (isCertificateLocation) { + try { + X509Certificate cert = CertsUtils.getX509Certificate(certificate); + if (cert == null) { + return null; } - } else { - return parseCertificate(certificate); + return new CertificateStore(new X509Certificate[]{cert}); + } catch (CertificateException ex) { + // Maybe it's a WSS4J properties file... + return CertsUtils.createCrypto(certificate); } } - return null; + // Here the certificate is encoded in the configuration file + X509Certificate cert; + try { + cert = CertsUtils.parseCertificate(certificate); + } catch (Exception ex) { + LOG.error("Failed to parse trusted certificate", ex); + throw new ProcessingException("Failed to parse trusted certificate"); + } + return new CertificateStore(Collections.singletonList(cert).toArray(new X509Certificate[0])); } - private X509Certificate parseCertificate(String certificate) - throws CertificateException, Base64DecodingException, IOException { + private X509Certificate getCertificate(String certificate) + throws CertificateException, WSSecurityException, ProcessingException, Base64DecodingException, IOException { + if (certificate == null) { + return null; + } - //before decoding we need to get rod off the prefix and suffix - byte [] decoded = Base64.decode(certificate.replaceAll("-----BEGIN CERTIFICATE-----", ""). - replaceAll("-----END CERTIFICATE-----", "")); - - try (InputStream is = new ByteArrayInputStream(decoded)) { - return (X509Certificate)CertificateFactory.getInstance("X.509").generateCertificate(is); + boolean isCertificateLocation = !certificate.startsWith("-----BEGIN CERTIFICATE"); + if (isCertificateLocation) { + try { + return CertsUtils.getX509Certificate(certificate); + } catch (CertificateException ex) { + // Maybe it's a WSS4J properties file... + Crypto crypto = CertsUtils.createCrypto(certificate); + if (crypto != null) { + return CertsUtils.getX509Certificate(crypto, null); + } + } + } + + // Here the certificate is encoded in the configuration file + try { + return CertsUtils.parseCertificate(certificate); + } catch (Exception ex) { + LOG.error("Failed to parse trusted certificate", ex); + throw new ProcessingException("Failed to parse trusted certificate"); } } @@ -325,41 +329,6 @@ public class TrustedIdpOIDCProtocolHandler implements TrustedIdpProtocolHandler return assertion; } - private Crypto getCrypto(String certificate) throws ProcessingException { - if (certificate == null) { - return null; - } - - // First see if it's a certificate file - InputStream is = null; - try { - is = Merlin.loadInputStream(Thread.currentThread().getContextClassLoader(), certificate); - - CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); - X509Certificate cert = (X509Certificate) certFactory.generateCertificate(is); - return new CertificateStore(new X509Certificate[]{cert}); - } catch (WSSecurityException ex) { - LOG.error("Failed to load keystore " + certificate, ex); - throw new RuntimeException("Failed to load keystore " + certificate); - } catch (IOException ex) { - LOG.error("Failed to read keystore", ex); - throw new RuntimeException("Failed to read keystore"); - } catch (CertificateException ex) { - // This is ok as it could be a WSS4J properties file - } finally { - if (is != null) { - try { - is.close(); - } catch (IOException e) { - // Do nothing - } - } - } - - // Maybe it's a WSS4J properties file... - return CertsUtils.createCrypto(certificate); - } - private static class SamlCallbackHandler implements CallbackHandler { private ConditionsBean conditionsBean; private SubjectBean subjectBean; http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/f545ba0c/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/protocols/TrustedIdpSAMLProtocolHandler.java ---------------------------------------------------------------------- diff --git a/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/protocols/TrustedIdpSAMLProtocolHandler.java b/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/protocols/TrustedIdpSAMLProtocolHandler.java index adc85d1..f128467 100644 --- a/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/protocols/TrustedIdpSAMLProtocolHandler.java +++ b/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/protocols/TrustedIdpSAMLProtocolHandler.java @@ -30,8 +30,8 @@ import java.net.URLEncoder; import java.security.PrivateKey; import java.security.Signature; import java.security.cert.CertificateException; -import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; +import java.util.Collections; import java.util.Map; import java.util.zip.DataFormatException; @@ -67,7 +67,6 @@ import org.apache.cxf.staxutils.StaxUtils; import org.apache.cxf.ws.security.tokenstore.SecurityToken; import org.apache.wss4j.common.crypto.CertificateStore; import org.apache.wss4j.common.crypto.Crypto; -import org.apache.wss4j.common.crypto.Merlin; import org.apache.wss4j.common.ext.WSSecurityException; import org.apache.wss4j.common.saml.OpenSAMLUtil; import org.apache.wss4j.common.util.DOM2Writer; @@ -308,34 +307,29 @@ public class TrustedIdpSAMLProtocolHandler implements TrustedIdpProtocolHandler return null; } - // First see if it's a certificate file - InputStream is = null; - try { - is = Merlin.loadInputStream(Thread.currentThread().getContextClassLoader(), certificate); - - CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); - X509Certificate cert = (X509Certificate) certFactory.generateCertificate(is); - return new CertificateStore(new X509Certificate[]{cert}); - } catch (WSSecurityException ex) { - LOG.error("Failed to load keystore " + certificate, ex); - throw new RuntimeException("Failed to load keystore " + certificate); - } catch (IOException ex) { - LOG.error("Failed to read keystore", ex); - throw new RuntimeException("Failed to read keystore"); - } catch (CertificateException ex) { - // This is ok as it could be a WSS4J properties file - } finally { - if (is != null) { - try { - is.close(); - } catch (IOException e) { - // Do nothing + boolean isCertificateLocation = !certificate.startsWith("-----BEGIN CERTIFICATE"); + if (isCertificateLocation) { + try { + X509Certificate cert = CertsUtils.getX509Certificate(certificate); + if (cert == null) { + return null; } + return new CertificateStore(new X509Certificate[]{cert}); + } catch (CertificateException ex) { + // Maybe it's a WSS4J properties file... + return CertsUtils.createCrypto(certificate); } - } + } - // Maybe it's a WSS4J properties file... - return CertsUtils.createCrypto(certificate); + // Here the certificate is encoded in the configuration file + X509Certificate cert; + try { + cert = CertsUtils.parseCertificate(certificate); + } catch (Exception ex) { + LOG.error("Failed to parse trusted certificate", ex); + throw new ProcessingException("Failed to parse trusted certificate"); + } + return new CertificateStore(Collections.singletonList(cert).toArray(new X509Certificate[0])); } private org.opensaml.saml.saml2.core.Response readSAMLResponse(String samlResponse, TrustedIdp trustedIdp) { http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/f545ba0c/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/protocols/TrustedIdpWSFedProtocolHandler.java ---------------------------------------------------------------------- diff --git a/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/protocols/TrustedIdpWSFedProtocolHandler.java b/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/protocols/TrustedIdpWSFedProtocolHandler.java index 4ac9605..946ab61 100644 --- a/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/protocols/TrustedIdpWSFedProtocolHandler.java +++ b/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/protocols/TrustedIdpWSFedProtocolHandler.java @@ -19,15 +19,10 @@ package org.apache.cxf.fediz.service.idp.protocols; -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.net.MalformedURLException; import java.net.URL; import java.net.URLEncoder; -import java.security.cert.CertificateException; -import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.util.Collections; @@ -51,15 +46,14 @@ import org.apache.cxf.fediz.core.processor.FederationProcessorImpl; import org.apache.cxf.fediz.core.processor.FedizProcessor; import org.apache.cxf.fediz.core.processor.FedizRequest; import org.apache.cxf.fediz.core.processor.FedizResponse; +import org.apache.cxf.fediz.core.util.CertsUtils; import org.apache.cxf.fediz.service.idp.domain.Idp; import org.apache.cxf.fediz.service.idp.domain.TrustedIdp; import org.apache.cxf.fediz.service.idp.spi.TrustedIdpProtocolHandler; import org.apache.cxf.fediz.service.idp.util.WebUtils; import org.apache.cxf.ws.security.tokenstore.SecurityToken; import org.apache.wss4j.common.crypto.CertificateStore; -import org.apache.xml.security.exceptions.Base64DecodingException; import org.apache.xml.security.stax.impl.util.IDGenerator; -import org.apache.xml.security.utils.Base64; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; @@ -222,7 +216,7 @@ public class TrustedIdpWSFedProtocolHandler implements TrustedIdpProtocolHandler X509Certificate cert; try { - cert = parseCertificate(trustedIdpConfig.getCertificate()); + cert = CertsUtils.parseCertificate(trustedIdpConfig.getCertificate()); } catch (Exception ex) { LOG.error("Failed to parse trusted certificate", ex); throw new ProcessingException("Failed to parse trusted certificate"); @@ -237,17 +231,4 @@ public class TrustedIdpWSFedProtocolHandler implements TrustedIdpProtocolHandler return fedContext; } - private X509Certificate parseCertificate(String certificate) - throws CertificateException, Base64DecodingException, IOException { - - //before decoding we need to get rod off the prefix and suffix - byte [] decoded = Base64.decode(certificate.replaceAll("-----BEGIN CERTIFICATE-----", ""). - replaceAll("-----END CERTIFICATE-----", "")); - - try (InputStream is = new ByteArrayInputStream(decoded)) { - return (X509Certificate)CertificateFactory.getInstance("X.509").generateCertificate(is); - } - } - - }
