diff options
Diffstat (limited to 'eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml')
12 files changed, 890 insertions, 489 deletions
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/EaafHttpPostDecoder.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/EaafHttpPostDecoder.java new file mode 100644 index 00000000..fdd44b9a --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/EaafHttpPostDecoder.java @@ -0,0 +1,79 @@ +package at.gv.egiz.eaaf.modules.pvp2.impl.opensaml; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; + +import javax.servlet.http.HttpServletRequest; + +import at.gv.egiz.eaaf.modules.pvp2.impl.utils.Saml2Utils; +import at.gv.egiz.eaaf.modules.pvp2.impl.utils.SamlHttpUtils; + +import org.opensaml.core.xml.XMLObject; +import org.opensaml.messaging.decoder.MessageDecodingException; +import org.opensaml.saml.saml2.binding.decoding.impl.HTTPPostDecoder; + +import com.google.common.base.Strings; +import lombok.extern.slf4j.Slf4j; +import net.shibboleth.utilities.java.support.codec.Base64Support; + +/** + * SAML2 Post-Binding decoder with same EAAF specific hardening regarding http + * request-parameter processing. + * + * @author tlenz + * + */ +@Slf4j +public class EaafHttpPostDecoder extends HTTPPostDecoder { + + private static final String SAML_REQ_PARAM_NAME = "SAMLRequest"; + private static final String SAML_RESP_PARAM_NAME = "SAMLResponse"; + + public EaafHttpPostDecoder(HttpServletRequest req) { + setHttpServletRequest(req); + } + + @Override + protected InputStream getBase64DecodedMessage(final HttpServletRequest request) + throws MessageDecodingException { + + log.debug("Getting Base64 encoded message from request"); + String encodedMessage = SamlHttpUtils.getLastParameterFromRequest(request, SAML_REQ_PARAM_NAME); + if (Strings.isNullOrEmpty(encodedMessage)) { + encodedMessage = SamlHttpUtils.getLastParameterFromRequest(request, SAML_RESP_PARAM_NAME); + + } + + if (Strings.isNullOrEmpty(encodedMessage)) { + log.info("Request did not contain either a SAMLRequest or " + + "SAMLResponse paramter. Invalid request for SAML 2 HTTP POST binding."); + throw new MessageDecodingException("No SAML message present in request"); + } + + log.trace("Base64 decoding SAML message: {}", encodedMessage); + final byte[] decodedBytes = Base64Support.decode(encodedMessage); + + try { + log.trace("Decoded SAML message: {}", new String(decodedBytes, "UTF-8")); + + } catch (final UnsupportedEncodingException e) { + log.warn("Logging of incomming message failed", e); + + } + + return new ByteArrayInputStream(decodedBytes); + } + + /** + * EAAF specific unmarshaller perform XML schema validation before unmarshalling + * the SAML message. + * + */ + @Override + protected XMLObject unmarshallMessage(final InputStream messageStream) throws MessageDecodingException { + return Saml2Utils.unmarshallMessage(messageStream); + + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/EaafHttpRedirectDeflateDecoder.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/EaafHttpRedirectDeflateDecoder.java new file mode 100644 index 00000000..c5174f02 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/EaafHttpRedirectDeflateDecoder.java @@ -0,0 +1,97 @@ +package at.gv.egiz.eaaf.modules.pvp2.impl.opensaml; + +import java.io.InputStream; + +import javax.servlet.http.HttpServletRequest; + +import at.gv.egiz.eaaf.modules.pvp2.impl.utils.Saml2Utils; +import at.gv.egiz.eaaf.modules.pvp2.impl.utils.SamlHttpUtils; + +import org.opensaml.core.xml.XMLObject; +import org.opensaml.messaging.context.MessageContext; +import org.opensaml.messaging.decoder.MessageDecodingException; +import org.opensaml.saml.common.SAMLObject; +import org.opensaml.saml.common.binding.SAMLBindingSupport; +import org.opensaml.saml.common.xml.SAMLConstants; +import org.opensaml.saml.saml2.binding.decoding.impl.HTTPRedirectDeflateDecoder; + +import com.google.common.base.Strings; +import lombok.extern.slf4j.Slf4j; +import net.shibboleth.utilities.java.support.primitive.StringSupport; + +/** + * SAML2 Redirect-Binding deflate decoder with same EAAF specific hardening + * regarding http request-parameter processing. + * + * @author tlenz + * + */ +@Slf4j +public class EaafHttpRedirectDeflateDecoder extends HTTPRedirectDeflateDecoder { + + private static final String SAML_REQ_PARAM_NAME = "SAMLRequest"; + private static final String SAML_RESP_PARAM_NAME = "SAMLResponse"; + + public EaafHttpRedirectDeflateDecoder(HttpServletRequest req) { + setHttpServletRequest(req); + + } + + @Override + protected void doDecode() throws MessageDecodingException { + final MessageContext<SAMLObject> messageContext = new MessageContext<>(); + final HttpServletRequest request = getHttpServletRequest(); + + if (!"GET".equalsIgnoreCase(request.getMethod())) { + throw new MessageDecodingException("This message decoder only supports the HTTP GET method"); + } + + final String samlEncoding = StringSupport.trimOrNull(request.getParameter("SAMLEncoding")); + if (samlEncoding != null && !SAMLConstants.SAML2_BINDING_URL_ENCODING_DEFLATE_URI.equals(samlEncoding)) { + throw new MessageDecodingException("Request indicated an unsupported SAMLEncoding: " + samlEncoding); + + } + + final String relayState = request.getParameter("RelayState"); + log.debug("Decoded RelayState: {}", relayState); + SAMLBindingSupport.setRelayState(messageContext, relayState); + + final InputStream samlMessageIns; + + // implement parameter extraction as same as in + // SAML2HTTPRedirectDeflateSignatureSecurityHandler.java + final String samlReq = SamlHttpUtils.getLastParameterFromRequest(request, SAML_REQ_PARAM_NAME); + final String samlResp = SamlHttpUtils.getLastParameterFromRequest(request, SAML_RESP_PARAM_NAME); + if (!Strings.isNullOrEmpty(samlReq)) { + samlMessageIns = decodeMessage(samlReq); + + } else if (!Strings.isNullOrEmpty(samlResp)) { + samlMessageIns = decodeMessage(samlResp); + + } else { + throw new MessageDecodingException( + "No SAMLRequest or SAMLResponse query path parameter, invalid SAML 2 HTTP Redirect message"); + } + + final SAMLObject samlMessage = (SAMLObject) unmarshallMessage(samlMessageIns); + messageContext.setMessage(samlMessage); + log.debug("Decoded SAML message"); + + populateBindingContext(messageContext); + + setMessageContext(messageContext); + + } + + /** + * EAAF specific unmarshaller perform XML schema validation before unmarshalling + * the SAML message. + * + */ + @Override + protected XMLObject unmarshallMessage(final InputStream messageStream) throws MessageDecodingException { + return Saml2Utils.unmarshallMessage(messageStream); + + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/EaafKeyStoreX509CredentialAdapter.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/EaafKeyStoreX509CredentialAdapter.java new file mode 100644 index 00000000..1611d623 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/EaafKeyStoreX509CredentialAdapter.java @@ -0,0 +1,122 @@ +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text file for details on the + * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative + * works that you distribute must include a readable copy of the "NOTICE" text file. +*/ + +package at.gv.egiz.eaaf.modules.pvp2.impl.opensaml; + +import java.security.KeyStore; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +import at.gv.egiz.eaaf.modules.pvp2.PvpConstants; +import at.gv.egiz.eaaf.modules.pvp2.api.credential.EaafX509Credential; +import at.gv.egiz.eaaf.modules.pvp2.exception.CredentialsNotAvailableException; +import at.gv.egiz.eaaf.modules.pvp2.exception.SamlSigningException; +import at.gv.egiz.eaaf.modules.pvp2.impl.utils.Saml2Utils; + +import org.opensaml.security.x509.X509Credential; +import org.opensaml.security.x509.impl.KeyStoreX509CredentialAdapter; + +import lombok.extern.slf4j.Slf4j; + +/** + * OpenSAML2 KeyStore adapter. + * + * @author tlenz + * + */ +@Slf4j +public class EaafKeyStoreX509CredentialAdapter extends KeyStoreX509CredentialAdapter + implements EaafX509Credential { + + private String signatureAlgorithmtToUse; + private String keyEncryptionAlgorithmtToUse; + + /** + * Get an OpenSAML2 keystore. + * + * @param store Java KeyStore + * @param alias Key alias + * @param password key Password + * @param keyStoreFriendlyName Friendlyname of this keystore for logging + * purposes + * @throws CredentialsNotAvailableException In case of an initialization + * exception + */ + public EaafKeyStoreX509CredentialAdapter(@Nonnull final KeyStore store, @Nonnull final String alias, + @Nullable final char[] password, @Nonnull String keyStoreFriendlyName) + throws CredentialsNotAvailableException { + super(store, alias, password); + + if (getPrivateKey() == null && getSecretKey() == null) { + log.error("KeyStore: {} Key with alias: {} not found or contains no PrivateKey.", + keyStoreFriendlyName, alias); + throw new CredentialsNotAvailableException("internal.pvp.00", + new Object[] { keyStoreFriendlyName, alias }); + + } + + try { + setSignatureAlgorithmForSigning(Saml2Utils.getKeyOperationAlgorithmFromCredential(this, + PvpConstants.DEFAULT_SIGNING_METHODE_RSA, + PvpConstants.DEFAULT_SIGNING_METHODE_EC)); + + setKeyEncryptionAlgorithmForDataEncryption( + Saml2Utils.getKeyOperationAlgorithmFromCredential(this, + PvpConstants.DEFAULT_ASYM_ENCRYPTION_METHODE_RSA, + PvpConstants.DEFAULT_ASYM_ENCRYPTION_METHODE_EC)); + + } catch (final SamlSigningException e) { + throw new CredentialsNotAvailableException("internal.pvp.01", new Object[] { keyStoreFriendlyName, + alias }, e); + + } + + } + + @Override + public Class<? extends X509Credential> getCredentialType() { + return X509Credential.class; + } + + @Override + public String getSignatureAlgorithmForSigning() { + return this.signatureAlgorithmtToUse; + + } + + @Override + public void setSignatureAlgorithmForSigning(String sigAlg) { + this.signatureAlgorithmtToUse = sigAlg; + + } + + @Override + public String getKeyEncryptionAlgorithmForDataEncryption() { + return this.keyEncryptionAlgorithmtToUse; + + } + + @Override + public void setKeyEncryptionAlgorithmForDataEncryption(String sigAlg) { + this.keyEncryptionAlgorithmtToUse = sigAlg; + + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/HTTPPostEncoderWithOwnTemplate.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/HTTPPostEncoderWithOwnTemplate.java deleted file mode 100644 index 8af12acc..00000000 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/HTTPPostEncoderWithOwnTemplate.java +++ /dev/null @@ -1,122 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -package at.gv.egiz.eaaf.modules.pvp2.impl.opensaml; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.OutputStreamWriter; -import java.io.Writer; - -import org.apache.velocity.VelocityContext; -import org.apache.velocity.app.VelocityEngine; -import org.opensaml.common.binding.SAMLMessageContext; -import org.opensaml.saml2.binding.encoding.HTTPPostEncoder; -import org.opensaml.ws.message.encoder.MessageEncodingException; -import org.opensaml.ws.transport.http.HTTPOutTransport; -import org.opensaml.ws.transport.http.HTTPTransportUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import at.gv.egiz.eaaf.core.api.gui.IVelocityGUIBuilderConfiguration; -import at.gv.egiz.eaaf.core.api.gui.IVelocityGuiFormBuilder; - -/** - * @author tlenz - * - */ -public class HTTPPostEncoderWithOwnTemplate extends HTTPPostEncoder { - private static final Logger log = LoggerFactory.getLogger(HTTPPostEncoderWithOwnTemplate.class); - - - private final VelocityEngine velocityEngine; - private final IVelocityGUIBuilderConfiguration guiConfig; - private final IVelocityGuiFormBuilder guiBuilder; - - /** - * @param engine - * @param templateId - */ - public HTTPPostEncoderWithOwnTemplate(IVelocityGUIBuilderConfiguration guiConfig, IVelocityGuiFormBuilder guiBuilder, VelocityEngine engine) { - super(engine, null); - this.velocityEngine = engine; - this.guiConfig = guiConfig; - this.guiBuilder = guiBuilder; - - } - - /** - * Base64 and POST encodes the outbound message and writes it to the outbound transport. - * - * @param messageContext current message context - * @param endpointURL endpoint URL to which to encode message - * - * @throws MessageEncodingException thrown if there is a problem encoding the message - */ - @Override - protected void postEncode(SAMLMessageContext messageContext, String endpointURL) throws MessageEncodingException { - log.debug("Invoking Velocity template to create POST body"); - InputStream is = null; - try { - //build Velocity Context from GUI input paramters - final VelocityContext context = guiBuilder.generateVelocityContextFromConfiguration(guiConfig); - - //load template - is = guiBuilder.getTemplateInputStream(guiConfig); - - //populate velocity context with SAML2 parameters - populateVelocityContext(context, messageContext, endpointURL); - - //populate transport parameter - final HTTPOutTransport outTransport = (HTTPOutTransport) messageContext.getOutboundMessageTransport(); - HTTPTransportUtils.addNoCacheHeaders(outTransport); - HTTPTransportUtils.setUTF8Encoding(outTransport); - HTTPTransportUtils.setContentType(outTransport, "text/html"); - - //evaluate template and write content to response - final Writer out = new OutputStreamWriter(outTransport.getOutgoingStream(), "UTF-8"); - velocityEngine.evaluate(context, out, "SAML2_POST_BINDING", new BufferedReader(new InputStreamReader(is))); - out.flush(); - - } catch (final Exception e) { - log.error("Error invoking Velocity template", e); - throw new MessageEncodingException("Error creating output document", e); - - } finally { - if (is != null) { - try { - is.close(); - - } catch (final IOException e) { - log.error("Can NOT close GUI-Template InputStream.", e); - } - } - - } - } -} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/HttpPostEncoderWithOwnTemplate.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/HttpPostEncoderWithOwnTemplate.java new file mode 100644 index 00000000..fa77b73c --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/HttpPostEncoderWithOwnTemplate.java @@ -0,0 +1,125 @@ +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text file for details on the + * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative + * works that you distribute must include a readable copy of the "NOTICE" text file. +*/ + +package at.gv.egiz.eaaf.modules.pvp2.impl.opensaml; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.io.Writer; + +import javax.servlet.http.HttpServletResponse; + +import at.gv.egiz.eaaf.core.api.gui.IVelocityGuiBuilderConfiguration; +import at.gv.egiz.eaaf.core.api.gui.IVelocityGuiFormBuilder; +import at.gv.egiz.eaaf.core.impl.gui.velocity.VelocityProvider; + +import org.apache.velocity.VelocityContext; +import org.apache.velocity.app.Velocity; +import org.opensaml.messaging.context.MessageContext; +import org.opensaml.messaging.encoder.MessageEncodingException; +import org.opensaml.saml.common.SAMLObject; +import org.opensaml.saml.saml2.binding.encoding.impl.HTTPPostEncoder; + +import lombok.extern.slf4j.Slf4j; +import net.shibboleth.utilities.java.support.net.HttpServletSupport; + +/** + * OpenSAML2 Post-Binding encoder that uses dynamic loaded templates. + * + * @author tlenz + * + */ +@Slf4j +public class HttpPostEncoderWithOwnTemplate extends HTTPPostEncoder { + + private final IVelocityGuiBuilderConfiguration guiConfig; + private final IVelocityGuiFormBuilder guiBuilder; + + /** + * Own Post-Binding encoder. + * + * @param guiConfig GUI configuration + * @param guiBuilder GUI builder implementation + * @throws Exception In case of a {@link Velocity} initialization error + */ + public HttpPostEncoderWithOwnTemplate(final IVelocityGuiBuilderConfiguration guiConfig, + final IVelocityGuiFormBuilder guiBuilder) throws Exception { + this.guiConfig = guiConfig; + this.guiBuilder = guiBuilder; + + setVelocityEngine(VelocityProvider.getClassPathVelocityEngine()); + + } + + /** + * Base64 and POST encodes the out-bound message and writes it to the out-bound + * transport. + * + * @param messageContext current message context + * + * @throws MessageEncodingException thrown if there is a problem encoding the + * message + */ + @Override + protected void postEncode(final MessageContext<SAMLObject> messageContext, final String endpointUrl) + throws MessageEncodingException { + log.debug("Invoking Velocity template to create POST body"); + InputStream is = null; + try { + // build Velocity Context from GUI input paramters + final VelocityContext context = + guiBuilder.generateVelocityContextFromConfiguration(guiConfig); + + // load template + is = guiBuilder.getTemplateInputStream(guiConfig); + + populateVelocityContext(context, messageContext, endpointUrl); + + final HttpServletResponse response = getHttpServletResponse(); + + HttpServletSupport.addNoCacheHeaders(response); + HttpServletSupport.setUTF8Encoding(response); + HttpServletSupport.setContentType(response, "text/html"); + + final Writer out = new OutputStreamWriter(response.getOutputStream(), "UTF-8"); + getVelocityEngine().evaluate(context, out, "SAML2_POST_BINDING", + new BufferedReader(new InputStreamReader(is, "UTF-8"))); + out.flush(); + + } catch (final Exception e) { + log.error("Error invoking Velocity template", e); + throw new MessageEncodingException("Error creating output document", e); + + } finally { + if (is != null) { + try { + is.close(); + + } catch (final IOException e) { + log.error("Can NOT close GUI-Template InputStream.", e); + } + } + + } + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/KeyStoreX509CredentialAdapter.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/KeyStoreX509CredentialAdapter.java deleted file mode 100644 index 2f3912ca..00000000 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/KeyStoreX509CredentialAdapter.java +++ /dev/null @@ -1,56 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -package at.gv.egiz.eaaf.modules.pvp2.impl.opensaml; - -import java.security.KeyStore; - -import org.opensaml.xml.security.x509.X509Credential; - - -/** - * @author tlenz - * - */ -public class KeyStoreX509CredentialAdapter extends - org.opensaml.xml.security.x509.KeyStoreX509CredentialAdapter { - - /** - * @param store - * @param alias - * @param password - */ - public KeyStoreX509CredentialAdapter(KeyStore store, String alias, - char[] password) { - super(store, alias, password); - } - - public Class<? extends X509Credential> getCredentialType() { - return X509Credential.class; - } - - -} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/OpenSaml3ResourceAdapter.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/OpenSaml3ResourceAdapter.java new file mode 100644 index 00000000..f474267f --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/OpenSaml3ResourceAdapter.java @@ -0,0 +1,86 @@ +package at.gv.egiz.eaaf.modules.pvp2.impl.opensaml; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import java.net.URL; + +import net.shibboleth.utilities.java.support.resource.Resource; + +/** + * Adapter that connects a Spring {@link org.springframework.core.io.Resource} + * to a {@link Resource}. + * + * @author tlenz + * + */ +public class OpenSaml3ResourceAdapter implements Resource { + + private final org.springframework.core.io.Resource internalResource; + + public OpenSaml3ResourceAdapter(org.springframework.core.io.Resource resource) { + this.internalResource = resource; + } + + @Override + public boolean exists() { + return internalResource.exists(); + } + + @Override + public boolean isReadable() { + return internalResource.isReadable(); + } + + @Override + public boolean isOpen() { + return internalResource.isOpen(); + } + + @Override + public URL getURL() throws IOException { + return internalResource.getURL(); + } + + @Override + public URI getURI() throws IOException { + return internalResource.getURI(); + } + + @Override + public File getFile() throws IOException { + return internalResource.getFile(); + } + + @Override + public InputStream getInputStream() throws IOException { + return internalResource.getInputStream(); + } + + @Override + public long contentLength() throws IOException { + return internalResource.contentLength(); + } + + @Override + public long lastModified() throws IOException { + return internalResource.lastModified(); + } + + @Override + public Resource createRelativeResource(String relativePath) throws IOException { + throw new IOException("This method is not supperted by this adapter"); + } + + @Override + public String getFilename() { + return internalResource.getFilename(); + } + + @Override + public String getDescription() { + return internalResource.getDescription(); + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/StringRedirectDeflateEncoder.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/StringRedirectDeflateEncoder.java index 544dc9f5..38735fb8 100644 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/StringRedirectDeflateEncoder.java +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/StringRedirectDeflateEncoder.java @@ -1,81 +1,66 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text file for details on the + * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative + * works that you distribute must include a readable copy of the "NOTICE" text file. +*/ + package at.gv.egiz.eaaf.modules.pvp2.impl.opensaml; -import org.opensaml.common.binding.SAMLMessageContext; -import org.opensaml.saml2.binding.encoding.HTTPRedirectDeflateEncoder; -import org.opensaml.ws.message.MessageContext; -import org.opensaml.ws.message.encoder.MessageEncodingException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import org.opensaml.messaging.context.MessageContext; +import org.opensaml.messaging.encoder.MessageEncodingException; +import org.opensaml.saml.common.SAMLObject; +import org.opensaml.saml.saml2.binding.encoding.impl.HTTPRedirectDeflateEncoder; -import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize.EAAFDefaultSAML2Bootstrap; +import lombok.extern.slf4j.Slf4j; /** + * Create deflate encoded SAML2 redirect-binding informations. + * * @author tlenz * */ + +@Slf4j public class StringRedirectDeflateEncoder extends HTTPRedirectDeflateEncoder { - private static final Logger log = LoggerFactory.getLogger(StringRedirectDeflateEncoder.class); - - private String redirectURL = null; - - public void encode(MessageContext messageContext) - throws MessageEncodingException { - if (!(messageContext instanceof SAMLMessageContext)) { - log.error("Invalid message context type, this encoder only support SAMLMessageContext"); - throw new MessageEncodingException( - "Invalid message context type, this encoder only support SAMLMessageContext"); - } + private String redirectUrl = null; + + @Override + protected void doEncode() throws MessageEncodingException { + final MessageContext<SAMLObject> messageContext = getMessageContext(); + final SAMLObject outboundMessage = messageContext.getMessage(); + + final String endpointUrl = getEndpointURL(messageContext).toString(); - //load default PVP security configurations - EAAFDefaultSAML2Bootstrap.initializeDefaultPVPConfiguration(); - - SAMLMessageContext samlMsgCtx = (SAMLMessageContext) messageContext; + removeSignature(outboundMessage); - String endpointURL = getEndpointURL(samlMsgCtx).buildURL(); + final String encodedMessage = deflateAndBase64Encode(outboundMessage); - setResponseDestination(samlMsgCtx.getOutboundSAMLMessage(), endpointURL); + redirectUrl = buildRedirectURL(messageContext, endpointUrl, encodedMessage); - removeSignature(samlMsgCtx); + log.trace("SAML2 redirect-binding URL was generated as: {}", redirectUrl); - String encodedMessage = deflateAndBase64Encode(samlMsgCtx - .getOutboundSAMLMessage()); + } - redirectURL = buildRedirectURL(samlMsgCtx, endpointURL, - encodedMessage); - } + /** + * Get generated redirect URL. + * + * @return the redirectURL + */ + public String getRedirectUrl() { + return redirectUrl; + } - /** - * @return the redirectURL - */ - public String getRedirectURL() { - return redirectURL; - } - - } diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/initialize/EAAFDefaultSAML2Bootstrap.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/initialize/EAAFDefaultSAML2Bootstrap.java deleted file mode 100644 index 266b6e5f..00000000 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/initialize/EAAFDefaultSAML2Bootstrap.java +++ /dev/null @@ -1,94 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -package at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize; - -import org.opensaml.Configuration; -import org.opensaml.DefaultBootstrap; -import org.opensaml.xml.ConfigurationException; - -import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EAAFRequestedAttribute; -import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EAAFRequestedAttributes; -import at.gv.egiz.eaaf.modules.pvp2.impl.builder.reqattr.EAAFRequestedAttributeBuilder; -import at.gv.egiz.eaaf.modules.pvp2.impl.builder.reqattr.EAAFRequestedAttributeMarshaller; -import at.gv.egiz.eaaf.modules.pvp2.impl.builder.reqattr.EAAFRequestedAttributeUnmarshaller; -import at.gv.egiz.eaaf.modules.pvp2.impl.builder.reqattr.EAAFRequestedAttributesBuilder; -import at.gv.egiz.eaaf.modules.pvp2.impl.builder.reqattr.EAAFRequestedAttributesMarshaller; -import at.gv.egiz.eaaf.modules.pvp2.impl.builder.reqattr.EAAFRequestedAttributesUnmarshaller; - -/** - * @author tlenz - * - */ -public class EAAFDefaultSAML2Bootstrap extends DefaultBootstrap { - - public static synchronized void bootstrap() throws ConfigurationException { - - initializeXMLSecurity(); - - initializeXMLTooling(); - - initializeArtifactBuilderFactories(); - - initializeGlobalSecurityConfiguration(); - - initializeParserPool(); - - initializeESAPI(); - - initializeExtenstions(); - - } - - private static void initializeExtenstions() { - Configuration.registerObjectProvider( - EAAFRequestedAttribute.DEFAULT_ELEMENT_NAME, - new EAAFRequestedAttributeBuilder(), - new EAAFRequestedAttributeMarshaller(), - new EAAFRequestedAttributeUnmarshaller() - ); - - Configuration.registerObjectProvider( - EAAFRequestedAttributes.DEFAULT_ELEMENT_NAME, - new EAAFRequestedAttributesBuilder(), - new EAAFRequestedAttributesMarshaller(), - new EAAFRequestedAttributesUnmarshaller() - ); - - } - - public static void initializeDefaultPVPConfiguration() { - initializeGlobalSecurityConfiguration(); - - } - - /** - * Initializes the default global security configuration. - */ - protected static void initializeGlobalSecurityConfiguration() { - Configuration.setGlobalSecurityConfiguration(EAAFDefaultSecurityConfigurationBootstrap.buildDefaultConfig()); - } -} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/initialize/EAAFDefaultSecurityConfigurationBootstrap.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/initialize/EAAFDefaultSecurityConfigurationBootstrap.java deleted file mode 100644 index ddd5b13e..00000000 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/initialize/EAAFDefaultSecurityConfigurationBootstrap.java +++ /dev/null @@ -1,156 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -package at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize; - -import org.opensaml.xml.encryption.EncryptionConstants; -import org.opensaml.xml.security.BasicSecurityConfiguration; -import org.opensaml.xml.security.DefaultSecurityConfigurationBootstrap; -import org.opensaml.xml.security.credential.BasicKeyInfoGeneratorFactory; -import org.opensaml.xml.security.keyinfo.KeyInfoGeneratorManager; -import org.opensaml.xml.security.keyinfo.NamedKeyInfoGeneratorManager; -import org.opensaml.xml.security.x509.X509KeyInfoGeneratorFactory; -import org.opensaml.xml.signature.SignatureConstants; - -/** - * @author tlenz - * - */ -public class EAAFDefaultSecurityConfigurationBootstrap extends - DefaultSecurityConfigurationBootstrap { - - public static BasicSecurityConfiguration buildDefaultConfig() { - BasicSecurityConfiguration config = new BasicSecurityConfiguration(); - - populateSignatureParams(config); - populateEncryptionParams(config); - populateKeyInfoCredentialResolverParams(config); - populateKeyInfoGeneratorManager(config); - populateKeyParams(config); - - return config; - } - - protected static void populateKeyInfoGeneratorManager( - BasicSecurityConfiguration config) { - NamedKeyInfoGeneratorManager namedManager = new NamedKeyInfoGeneratorManager(); - config.setKeyInfoGeneratorManager(namedManager); - - namedManager.setUseDefaultManager(true); - KeyInfoGeneratorManager defaultManager = namedManager - .getDefaultManager(); - - BasicKeyInfoGeneratorFactory basicFactory = new BasicKeyInfoGeneratorFactory(); - basicFactory.setEmitPublicKeyValue(true); - - X509KeyInfoGeneratorFactory x509Factory = new X509KeyInfoGeneratorFactory(); - x509Factory.setEmitEntityCertificate(true); - - defaultManager.registerFactory(basicFactory); - defaultManager.registerFactory(x509Factory); - } - - protected static void populateSignatureParams( - BasicSecurityConfiguration config) { - - //use SHA256 instead of SHA1 - config.registerSignatureAlgorithmURI("RSA", - SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA256); - - config.registerSignatureAlgorithmURI("DSA", - "http://www.w3.org/2000/09/xmldsig#dsa-sha1"); - - //use SHA256 instead of SHA1 - config.registerSignatureAlgorithmURI("EC", - SignatureConstants.ALGO_ID_SIGNATURE_ECDSA_SHA256); - - //use SHA256 instead of SHA1 - config.registerSignatureAlgorithmURI("AES", - SignatureConstants.ALGO_ID_MAC_HMAC_SHA256); - - - config.registerSignatureAlgorithmURI("DESede", - SignatureConstants.ALGO_ID_MAC_HMAC_SHA256); - - config.setSignatureCanonicalizationAlgorithm("http://www.w3.org/2001/10/xml-exc-c14n#"); - config.setSignatureHMACOutputLength(null); - - //use SHA256 instead of SHA1 - config.setSignatureReferenceDigestMethod(SignatureConstants.ALGO_ID_DIGEST_SHA256); - } - - protected static void populateEncryptionParams( - BasicSecurityConfiguration config) { - config.registerDataEncryptionAlgorithmURI("AES", Integer.valueOf(128), - "http://www.w3.org/2001/04/xmlenc#aes128-cbc"); - config.registerDataEncryptionAlgorithmURI("AES", Integer.valueOf(192), - "http://www.w3.org/2001/04/xmlenc#aes192-cbc"); - config.registerDataEncryptionAlgorithmURI("AES", Integer.valueOf(256), - "http://www.w3.org/2001/04/xmlenc#aes256-cbc"); - - //support GCM mode - config.registerDataEncryptionAlgorithmURI("AES", Integer.valueOf(128), - EncryptionConstants.ALGO_ID_BLOCKCIPHER_AES128_GCM); - - config.registerDataEncryptionAlgorithmURI("AES", Integer.valueOf(192), - EncryptionConstants.ALGO_ID_BLOCKCIPHER_AES192_GCM); - - config.registerDataEncryptionAlgorithmURI("AES", Integer.valueOf(256), - EncryptionConstants.ALGO_ID_BLOCKCIPHER_AES256_GCM); - - - config.registerDataEncryptionAlgorithmURI("DESede", - Integer.valueOf(168), - "http://www.w3.org/2001/04/xmlenc#tripledes-cbc"); - config.registerDataEncryptionAlgorithmURI("DESede", - Integer.valueOf(192), - "http://www.w3.org/2001/04/xmlenc#tripledes-cbc"); - - config.registerKeyTransportEncryptionAlgorithmURI("RSA", null, "AES", - "http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p"); - - config.registerKeyTransportEncryptionAlgorithmURI("RSA", null, - "DESede", "http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p"); - - config.registerKeyTransportEncryptionAlgorithmURI("AES", - Integer.valueOf(128), null, - "http://www.w3.org/2001/04/xmlenc#kw-aes128"); - config.registerKeyTransportEncryptionAlgorithmURI("AES", - Integer.valueOf(192), null, - "http://www.w3.org/2001/04/xmlenc#kw-aes192"); - config.registerKeyTransportEncryptionAlgorithmURI("AES", - Integer.valueOf(256), null, - "http://www.w3.org/2001/04/xmlenc#kw-aes256"); - config.registerKeyTransportEncryptionAlgorithmURI("DESede", - Integer.valueOf(168), null, - "http://www.w3.org/2001/04/xmlenc#kw-tripledes"); - config.registerKeyTransportEncryptionAlgorithmURI("DESede", - Integer.valueOf(192), null, - "http://www.w3.org/2001/04/xmlenc#kw-tripledes"); - - config.setAutoGeneratedDataEncryptionKeyAlgorithmURI("http://www.w3.org/2001/04/xmlenc#aes128-cbc"); - } -} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/initialize/EaafDefaultSecurityConfigurationBootstrap.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/initialize/EaafDefaultSecurityConfigurationBootstrap.java new file mode 100644 index 00000000..97f0f225 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/initialize/EaafDefaultSecurityConfigurationBootstrap.java @@ -0,0 +1,177 @@ +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text file for details on the + * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative + * works that you distribute must include a readable copy of the "NOTICE" text file. +*/ + +package at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize; + +import java.util.Arrays; +import java.util.Collections; + +import org.opensaml.xmlsec.config.impl.DefaultSecurityConfigurationBootstrap; +import org.opensaml.xmlsec.encryption.support.EncryptionConstants; +import org.opensaml.xmlsec.encryption.support.RSAOAEPParameters; +import org.opensaml.xmlsec.impl.BasicDecryptionConfiguration; +import org.opensaml.xmlsec.impl.BasicEncryptionConfiguration; +import org.opensaml.xmlsec.impl.BasicSignatureSigningConfiguration; +import org.opensaml.xmlsec.impl.BasicSignatureValidationConfiguration; +import org.opensaml.xmlsec.signature.support.SignatureConstants; + +/** + * EAAF specific OpenSAML2 security configuration. + * + * @author tlenz + * + */ +public class EaafDefaultSecurityConfigurationBootstrap + extends DefaultSecurityConfigurationBootstrap { + + /** + * Set EAAF specific encryption configuration to OpenSAML 3.x. + * + * @return + */ + public static BasicEncryptionConfiguration buildEaafEncryptionConfiguration() { + final BasicEncryptionConfiguration config = new BasicEncryptionConfiguration(); + + config.setBlacklistedAlgorithms(Arrays.asList( + EncryptionConstants.ALGO_ID_KEYTRANSPORT_RSA15, + EncryptionConstants.ALGO_ID_BLOCKCIPHER_TRIPLEDES, + EncryptionConstants.ALGO_ID_KEYWRAP_TRIPLEDES)); + + config.setDataEncryptionAlgorithms(Arrays.asList( + // The order of these is significant. + EncryptionConstants.ALGO_ID_BLOCKCIPHER_AES128, + EncryptionConstants.ALGO_ID_BLOCKCIPHER_AES192, + EncryptionConstants.ALGO_ID_BLOCKCIPHER_AES256, + + // register GCM algorithms + EncryptionConstants.ALGO_ID_BLOCKCIPHER_AES128_GCM, + EncryptionConstants.ALGO_ID_BLOCKCIPHER_AES192_GCM, + EncryptionConstants.ALGO_ID_BLOCKCIPHER_AES256_GCM)); + + config.setKeyTransportEncryptionAlgorithms(Arrays.asList( + // The order of the RSA algos is significant. + EncryptionConstants.ALGO_ID_KEYTRANSPORT_RSAOAEP, + EncryptionConstants.ALGO_ID_KEYTRANSPORT_RSAOAEP11, + + // The order of these is not significant. + // These aren't really "preferences" per se. They just need to be registered + // so that they can be used if a credential with a key of that type and size is + // seen. + EncryptionConstants.ALGO_ID_KEYWRAP_AES128, + EncryptionConstants.ALGO_ID_KEYWRAP_AES192, + EncryptionConstants.ALGO_ID_KEYWRAP_AES256)); + + config.setRSAOAEPParameters(new RSAOAEPParameters( + SignatureConstants.ALGO_ID_DIGEST_SHA1, + EncryptionConstants.ALGO_ID_MGF1_SHA1, + null)); + + config.setDataKeyInfoGeneratorManager(buildDataEncryptionKeyInfoGeneratorManager()); + config.setKeyTransportKeyInfoGeneratorManager(buildKeyTransportEncryptionKeyInfoGeneratorManager()); + + return config; + } + + /** + * Set EAAF specific decryption configuration to OpenSAML 3.x. + * + * @return + */ + public static BasicDecryptionConfiguration buildEaaftDecryptionConfiguration() { + final BasicDecryptionConfiguration config = new BasicDecryptionConfiguration(); + + config.setBlacklistedAlgorithms(Collections.singletonList( + EncryptionConstants.ALGO_ID_KEYTRANSPORT_RSA15)); + + config.setEncryptedKeyResolver(buildBasicEncryptedKeyResolver()); + + return config; + } + + /** + * Set EAAF specific signature-creation configuration to OpenSAML 3.x. + * + * @return + */ + public static BasicSignatureSigningConfiguration buildEaafSignatureSigningConfiguration() { + final BasicSignatureSigningConfiguration config = new BasicSignatureSigningConfiguration(); + + config.setBlacklistedAlgorithms(Arrays.asList( + SignatureConstants.ALGO_ID_DIGEST_NOT_RECOMMENDED_MD5, + SignatureConstants.ALGO_ID_SIGNATURE_NOT_RECOMMENDED_RSA_MD5, + SignatureConstants.ALGO_ID_MAC_HMAC_NOT_RECOMMENDED_MD5, + SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA1, + SignatureConstants.ALGO_ID_SIGNATURE_ECDSA_SHA1, + SignatureConstants.ALGO_ID_SIGNATURE_DSA_SHA1, + SignatureConstants.ALGO_ID_DIGEST_SHA1)); + + config.setSignatureAlgorithms(Arrays.asList( + // The order within each key group is significant. + // The order of the key groups themselves is not significant. + + // RSA + SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA256, + SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA384, + SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA512, + + // ECDSA + SignatureConstants.ALGO_ID_SIGNATURE_ECDSA_SHA256, + SignatureConstants.ALGO_ID_SIGNATURE_ECDSA_SHA384, + SignatureConstants.ALGO_ID_SIGNATURE_ECDSA_SHA512 + + // HMAC (all symmetric keys) + // SignatureConstants.ALGO_ID_MAC_HMAC_SHA256, + // SignatureConstants.ALGO_ID_MAC_HMAC_SHA384, + // SignatureConstants.ALGO_ID_MAC_HMAC_SHA512, + // SignatureConstants.ALGO_ID_MAC_HMAC_SHA1 + )); + + config.setSignatureReferenceDigestMethods(Arrays.asList( + // The order of these is significant. + SignatureConstants.ALGO_ID_DIGEST_SHA256, + SignatureConstants.ALGO_ID_DIGEST_SHA384, + SignatureConstants.ALGO_ID_DIGEST_SHA512)); + + config.setSignatureCanonicalizationAlgorithm(SignatureConstants.ALGO_ID_C14N_EXCL_OMIT_COMMENTS); + + config.setKeyInfoGeneratorManager(buildSignatureKeyInfoGeneratorManager()); + + return config; + } + + /** + * Set EAAF specific signature-verification configuration to OpenSAML 3.x. + * + * @return + */ + public static BasicSignatureValidationConfiguration buildEaafSignatureValidationConfiguration() { + final BasicSignatureValidationConfiguration config = new BasicSignatureValidationConfiguration(); + + config.setBlacklistedAlgorithms(Arrays.asList( + SignatureConstants.ALGO_ID_DIGEST_NOT_RECOMMENDED_MD5, + SignatureConstants.ALGO_ID_SIGNATURE_NOT_RECOMMENDED_RSA_MD5, + SignatureConstants.ALGO_ID_MAC_HMAC_NOT_RECOMMENDED_MD5, + SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA1, + SignatureConstants.ALGO_ID_SIGNATURE_ECDSA_SHA1, + SignatureConstants.ALGO_ID_SIGNATURE_DSA_SHA1, + SignatureConstants.ALGO_ID_DIGEST_SHA1)); + + return config; + } +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/initialize/EaafOpenSaml3xInitializer.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/initialize/EaafOpenSaml3xInitializer.java new file mode 100644 index 00000000..5c6d861d --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/initialize/EaafOpenSaml3xInitializer.java @@ -0,0 +1,158 @@ +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text file for details on the + * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative + * works that you distribute must include a readable copy of the "NOTICE" text file. +*/ + +package at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize; + +import java.util.HashMap; +import java.util.Map; + +import javax.annotation.Nonnull; +import javax.xml.XMLConstants; + +import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EaafRequestedAttribute; +import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EaafRequestedAttributes; +import at.gv.egiz.eaaf.modules.pvp2.impl.builder.reqattr.EaafRequestedAttributeBuilder; +import at.gv.egiz.eaaf.modules.pvp2.impl.builder.reqattr.EaafRequestedAttributeMarshaller; +import at.gv.egiz.eaaf.modules.pvp2.impl.builder.reqattr.EaafRequestedAttributeUnmarshaller; +import at.gv.egiz.eaaf.modules.pvp2.impl.builder.reqattr.EaafRequestedAttributesBuilder; +import at.gv.egiz.eaaf.modules.pvp2.impl.builder.reqattr.EaafRequestedAttributesMarshaller; +import at.gv.egiz.eaaf.modules.pvp2.impl.builder.reqattr.EaafRequestedAttributesUnmarshaller; + +import org.opensaml.core.config.ConfigurationService; +import org.opensaml.core.config.InitializationException; +import org.opensaml.core.config.InitializationService; +import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport; +import org.opensaml.xmlsec.DecryptionConfiguration; +import org.opensaml.xmlsec.EncryptionConfiguration; +import org.opensaml.xmlsec.SignatureSigningConfiguration; +import org.opensaml.xmlsec.SignatureValidationConfiguration; + +import lombok.extern.slf4j.Slf4j; +import net.shibboleth.utilities.java.support.component.ComponentInitializationException; +import net.shibboleth.utilities.java.support.xml.BasicParserPool; +import net.shibboleth.utilities.java.support.xml.ParserPool; + +/** + * EAAF specific OpenSAML Initializer. + * + * @author tlenz + * + */ +@Slf4j +public class EaafOpenSaml3xInitializer extends InitializationService { + + /** + * EAAF specific OpenSAML3.x initialization. + * + * @throws InitializationException In case of an error + * @throws ComponentInitializationException In case of an OpenSAML3 + * initialization error + */ + public static synchronized void eaafInitialize() throws InitializationException, + ComponentInitializationException { + log.debug("Initializing OpenSAML 3.x ... "); + initialize(); + + log.debug("Injecting EAAF-specific configuration into OpenSAML 3.x ... "); + injectEaafSecurityProperty(); + injectEaafExtenstions(); + + XMLObjectProviderRegistrySupport.setParserPool(eaafSecuredBasicParserPool()); + + log.info("OpenSAML3.x with EAAF extensions initialized"); + + } + + private static void injectEaafSecurityProperty() { + ConfigurationService.register(EncryptionConfiguration.class, + EaafDefaultSecurityConfigurationBootstrap.buildEaafEncryptionConfiguration()); + + ConfigurationService.register(DecryptionConfiguration.class, + EaafDefaultSecurityConfigurationBootstrap.buildEaaftDecryptionConfiguration()); + + ConfigurationService.register(SignatureSigningConfiguration.class, + EaafDefaultSecurityConfigurationBootstrap.buildEaafSignatureSigningConfiguration()); + + ConfigurationService.register(SignatureValidationConfiguration.class, + EaafDefaultSecurityConfigurationBootstrap.buildEaafSignatureValidationConfiguration()); + + } + + private static void injectEaafExtenstions() { + XMLObjectProviderRegistrySupport.registerObjectProvider( + EaafRequestedAttribute.DEFAULT_ELEMENT_NAME, new EaafRequestedAttributeBuilder(), + new EaafRequestedAttributeMarshaller(), new EaafRequestedAttributeUnmarshaller()); + + XMLObjectProviderRegistrySupport.registerObjectProvider( + EaafRequestedAttributes.DEFAULT_ELEMENT_NAME, new EaafRequestedAttributesBuilder(), + new EaafRequestedAttributesMarshaller(), new EaafRequestedAttributesUnmarshaller()); + + } + + /** + * Build a secured OpenSAML 3.x XML parser-pool. + * + * @return {@link ParserPool} + * @throws ComponentInitializationException In case of an initialization error + */ + @Nonnull + private static ParserPool eaafSecuredBasicParserPool() throws ComponentInitializationException { + // Get parser pool manager + final BasicParserPool ppMgr = new BasicParserPool(); + // Note: this is necessary due to an unresolved Xerces deferred DOM issue/bug + ppMgr.setBuilderFeatures(getSecureDocumentBuilderFeatures()); + ppMgr.setNamespaceAware(true); + ppMgr.setIgnoreComments(true); + ppMgr.setExpandEntityReferences(false); + ppMgr.setXincludeAware(false); + ppMgr.initialize(); + return ppMgr; + } + + @Nonnull + private static Map<String, Boolean> getSecureDocumentBuilderFeatures() { + final Map<String, Boolean> features = new HashMap<>(); + features.put(XMLConstants.FEATURE_SECURE_PROCESSING, Boolean.TRUE); + + // Ignore the external DTD completely + // Note: this is for Xerces only: + features.put("http://apache.org/xml/features/nonvalidating/load-external-dtd", Boolean.FALSE); + // This is the PRIMARY defense. If DTDs (doctypes) are disallowed, almost all + // XML entity attacks are prevented + // Xerces 2 only - + // http://xerces.apache.org/xerces2-j/features.html#disallow-doctype-decl + features.put("http://apache.org/xml/features/disallow-doctype-decl", Boolean.TRUE); + + // If you can't completely disable DTDs, then at least do the following: + // Xerces 1 - + // http://xerces.apache.org/xerces-j/features.html#external-general-entities + // Xerces 2 - + // http://xerces.apache.org/xerces2-j/features.html#external-general-entities + features.put("http://xml.org/sax/features/external-general-entities", Boolean.FALSE); + + // Xerces 1 - + // http://xerces.apache.org/xerces-j/features.html#external-parameter-entities + // Xerces 2 - + // http://xerces.apache.org/xerces2-j/features.html#external-parameter-entities + features.put("http://xml.org/sax/features/external-parameter-entities", Boolean.FALSE); + + return features; + } + +} |