From ee54508b4bc802587c59d67548b20a770110262c Mon Sep 17 00:00:00 2001 From: Thomas Lenz Date: Tue, 19 Jan 2016 16:08:12 +0100 Subject: add Single LogOut request signature validation to moa-id-configuration --- .../auth/pvp2/PVPSOAPRequestSecurityPolicy.java | 92 ++++++++++++++++++++++ .../auth/pvp2/servlets/SLOBackChannelServlet.java | 64 +++++++++------ .../auth/pvp2/servlets/SLOBasicServlet.java | 4 +- .../auth/pvp2/servlets/SLOFrontChannelServlet.java | 10 ++- .../config/ConfigurationProvider.java | 5 +- .../moa/id/configuration/utils/SAML2Utils.java | 20 +++++ .../resources/applicationResources_de.properties | 2 + .../resources/applicationResources_en.properties | 2 + 8 files changed, 167 insertions(+), 32 deletions(-) create mode 100644 id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/auth/pvp2/PVPSOAPRequestSecurityPolicy.java diff --git a/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/auth/pvp2/PVPSOAPRequestSecurityPolicy.java b/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/auth/pvp2/PVPSOAPRequestSecurityPolicy.java new file mode 100644 index 000000000..a25cc44ef --- /dev/null +++ b/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/auth/pvp2/PVPSOAPRequestSecurityPolicy.java @@ -0,0 +1,92 @@ +/* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 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: + * http://www.osor.eu/eupl/ + * + * 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.egovernment.moa.id.configuration.auth.pvp2; + +import java.util.List; + +import javax.xml.namespace.QName; + +import org.opensaml.common.SignableSAMLObject; +import org.opensaml.saml2.metadata.provider.HTTPMetadataProvider; +import org.opensaml.ws.soap.soap11.Envelope; +import org.opensaml.xml.XMLObject; +import org.opensaml.xml.signature.SignatureTrustEngine; + +import at.gv.egovernment.moa.id.configuration.config.ConfigurationProvider; +import at.gv.egovernment.moa.id.protocols.pvp2x.validation.AbstractRequestSignedSecurityPolicyRule; + +/** + * @author tlenz + * + */ +public class PVPSOAPRequestSecurityPolicy extends + AbstractRequestSignedSecurityPolicyRule { + + /** + * @param trustEngine + * @param peerEntityRole + */ + public PVPSOAPRequestSecurityPolicy(SignatureTrustEngine trustEngine, + QName peerEntityRole) { + super(trustEngine, peerEntityRole); + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.validation.AbstractRequestSignedSecurityPolicyRule#refreshMetadataProvider(java.lang.String) + */ + @Override + protected boolean refreshMetadataProvider(String entityID) { + try { + HTTPMetadataProvider metadataProvider = ConfigurationProvider.getInstance().getMetaDataProvier(); + metadataProvider.setRequireValidMetadata(true); + metadataProvider.refresh(); + + return true; + + } catch (Exception e) { + + + } + + return false; + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.validation.AbstractRequestSignedSecurityPolicyRule#getSignedSAMLObject(org.opensaml.xml.XMLObject) + */ + @Override + protected SignableSAMLObject getSignedSAMLObject(XMLObject inboundData) { + if (inboundData instanceof Envelope) { + Envelope envelope = (Envelope) inboundData; + if (envelope.getBody() != null) { + List xmlElemList = envelope.getBody().getUnknownXMLObjects(); + if (!xmlElemList.isEmpty() && xmlElemList.get(0) instanceof SignableSAMLObject) + return (SignableSAMLObject) xmlElemList.get(0); + + } + } + + return null; + } + +} diff --git a/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/auth/pvp2/servlets/SLOBackChannelServlet.java b/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/auth/pvp2/servlets/SLOBackChannelServlet.java index cff08740b..17d3d9e50 100644 --- a/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/auth/pvp2/servlets/SLOBackChannelServlet.java +++ b/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/auth/pvp2/servlets/SLOBackChannelServlet.java @@ -40,6 +40,7 @@ import org.opensaml.saml2.core.LogoutRequest; import org.opensaml.saml2.core.LogoutResponse; import org.opensaml.ws.message.decoder.MessageDecodingException; import org.opensaml.ws.message.encoder.MessageEncodingException; +import org.opensaml.ws.soap.client.BasicSOAPMessageContext; import org.opensaml.ws.soap.soap11.Envelope; import org.opensaml.ws.soap.soap11.decoder.http.HTTPSOAP11Decoder; import org.opensaml.ws.transport.http.HttpServletRequestAdapter; @@ -49,10 +50,12 @@ import org.opensaml.xml.parse.BasicParserPool; import org.opensaml.xml.security.SecurityException; import org.opensaml.xml.security.x509.KeyStoreX509CredentialAdapter; import org.opensaml.xml.security.x509.X509Credential; +import org.opensaml.xml.validation.ValidationException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import at.gv.egovernment.moa.id.config.webgui.exception.ConfigurationException; +import at.gv.egovernment.moa.id.configuration.auth.pvp2.PVP2Utils; /** * @author tlenz @@ -77,25 +80,44 @@ public class SLOBackChannelServlet extends SLOBasicServlet { try { HTTPSOAP11Decoder soapDecoder = new HTTPSOAP11Decoder(new BasicParserPool()); - BasicSAMLMessageContext messageContext = - new BasicSAMLMessageContext(); - messageContext - .setInboundMessageTransport(new HttpServletRequestAdapter( - request)); + + BasicSOAPMessageContext messageContext = new BasicSOAPMessageContext(); + +// BasicSAMLMessageContext messageContext = +// new BasicSAMLMessageContext(); + + messageContext.setInboundMessageTransport(new HttpServletRequestAdapter(request)); + + //messageContext.setMetadataProvider(getConfig().getMetaDataProvier()); + + //set trustPolicy +// BasicSecurityPolicy policy = new BasicSecurityPolicy(); +// policy.getPolicyRules().add( +// new PVPSOAPRequestSecurityPolicy( +// PVP2Utils.getTrustEngine(getConfig()), +// IDPSSODescriptor.DEFAULT_ELEMENT_NAME)); +// SecurityPolicyResolver resolver = new StaticSecurityPolicyResolver( +// policy); +// messageContext.setSecurityPolicyResolver(resolver); soapDecoder.decode(messageContext); - + Envelope inboundMessage = (Envelope) messageContext .getInboundMessage(); + LogoutResponse sloResp = null; + if (inboundMessage.getBody() != null) { List xmlElemList = inboundMessage.getBody().getUnknownXMLObjects(); - - LogoutResponse sloResp; + if (!xmlElemList.isEmpty() && xmlElemList.get(0) instanceof LogoutRequest) { LogoutRequest sloReq = (LogoutRequest) xmlElemList.get(0); - sloResp = processLogOutRequest(sloReq, request); + //validate request signature + PVP2Utils.validateSignature(sloReq, getConfig()); + + sloResp = processLogOutRequest(sloReq, request); + KeyStore keyStore = getConfig().getPVP2KeyStore(); X509Credential authcredential = new KeyStoreX509CredentialAdapter( keyStore, @@ -111,24 +133,17 @@ public class SLOBackChannelServlet extends SLOBasicServlet { context.setOutboundMessageTransport(responseAdapter); encoder.encode(context); - + } else { log.warn("Received request ist not of type LogOutRequest"); response.setStatus(HttpServletResponse.SC_BAD_REQUEST); + return; } } - } catch (MessageDecodingException e) { - log.error("SLO message processing FAILED." , e); - response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage()); - - } catch (SecurityException e) { - log.error("SLO message processing FAILED." , e); - response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage()); - - } catch (NoSuchAlgorithmException e) { - log.error("SLO message processing FAILED." , e); + } catch (MessageDecodingException | SecurityException | NoSuchAlgorithmException | ConfigurationException | ValidationException e) { + log.error("SLO message processing FAILED." , e); response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage()); } catch (CertificateException e) { @@ -139,15 +154,14 @@ public class SLOBackChannelServlet extends SLOBasicServlet { log.error("SLO message processing FAILED." , e); response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage()); - } catch (ConfigurationException e) { - log.error("SLO message processing FAILED." , e); - response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage()); - } catch (MessageEncodingException e) { log.error("SLO message processing FAILED." , e); response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage()); - } + } + + + } protected void doGet(HttpServletRequest request, diff --git a/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/auth/pvp2/servlets/SLOBasicServlet.java b/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/auth/pvp2/servlets/SLOBasicServlet.java index 2a35e50b1..c70d34d7e 100644 --- a/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/auth/pvp2/servlets/SLOBasicServlet.java +++ b/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/auth/pvp2/servlets/SLOBasicServlet.java @@ -131,13 +131,13 @@ public class SLOBasicServlet extends HttpServlet { } else { log.debug("Single LogOut not possible! User with nameID:" + sloReq.getNameID().getValue() + " is not found."); - return createSLOResponse(sloReq, StatusCode.PARTIAL_LOGOUT_URI, request); + return createSLOResponse(sloReq, StatusCode.SUCCESS_URI, request); } } - private LogoutResponse createSLOResponse(LogoutRequest sloReq, String statusCodeURI, HttpServletRequest request) throws NoSuchAlgorithmException { + protected LogoutResponse createSLOResponse(LogoutRequest sloReq, String statusCodeURI, HttpServletRequest request) throws NoSuchAlgorithmException { LogoutResponse sloResp = SAML2Utils.createSAMLObject(LogoutResponse.class); SecureRandomIdentifierGenerator gen = new SecureRandomIdentifierGenerator(); sloResp.setID(gen.generateIdentifier()); diff --git a/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/auth/pvp2/servlets/SLOFrontChannelServlet.java b/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/auth/pvp2/servlets/SLOFrontChannelServlet.java index 8df7f9d5a..274aa21bf 100644 --- a/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/auth/pvp2/servlets/SLOFrontChannelServlet.java +++ b/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/auth/pvp2/servlets/SLOFrontChannelServlet.java @@ -69,7 +69,6 @@ import at.gv.egovernment.moa.id.configuration.auth.pvp2.PVP2Utils; import at.gv.egovernment.moa.id.configuration.exception.PVP2Exception; import at.gv.egovernment.moa.id.configuration.exception.SLOException; import at.gv.egovernment.moa.id.configuration.helper.LanguageHelper; -import at.gv.egovernment.moa.id.protocols.pvp2x.verification.TrustEngineFactory; import at.gv.egovernment.moa.util.MiscUtil; /** @@ -99,8 +98,15 @@ public class SLOFrontChannelServlet extends SLOBasicServlet { if (MiscUtil.isNotEmpty(request.getParameter(Constants.REQUEST_USERSLO))) { //process user initiated single logout process Object authUserObj = request.getSession().getAttribute(Constants.SESSION_AUTH); + + if (authUserObj == null) { + log.warn("No user information found. Single Log-Out not possible"); + buildErrorMessage(request, response); + + } + AuthenticatedUser authUser = (AuthenticatedUser) authUserObj; - + String nameIDFormat = authUser.getNameIDFormat(); String nameID = authUser.getNameID(); diff --git a/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/config/ConfigurationProvider.java b/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/config/ConfigurationProvider.java index e2a55db60..ab6c22858 100644 --- a/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/config/ConfigurationProvider.java +++ b/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/config/ConfigurationProvider.java @@ -54,6 +54,7 @@ import org.springframework.beans.factory.config.AutowireCapableBeanFactory; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; +import at.gv.egovernment.moa.id.commons.db.NewConfigurationDBRead; import at.gv.egovernment.moa.id.commons.ex.MOAHttpProtocolSocketFactoryException; import at.gv.egovernment.moa.id.commons.utils.MOAHttpProtocolSocketFactory; import at.gv.egovernment.moa.id.config.webgui.MOAIDConfigurationModul; @@ -65,8 +66,6 @@ import at.gv.egovernment.moa.id.configuration.utils.UserRequestCleaner; import at.gv.egovernment.moa.util.FileUtils; import at.gv.egovernment.moa.util.MiscUtil; -import at.gv.egovernment.moa.id.commons.db.NewConfigurationDBRead; - public class ConfigurationProvider { @@ -602,7 +601,7 @@ public class ConfigurationProvider { } catch (Exception e) { log.warn("PVP2 authentification can not be initialized."); - throw new ConfigurationException("PVP2 authentification can not be initialized.", e); + throw new ConfigurationException("error.initialization.pvplogin", e); } } diff --git a/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/utils/SAML2Utils.java b/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/utils/SAML2Utils.java index fc310900e..eca4c05ef 100644 --- a/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/utils/SAML2Utils.java +++ b/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/utils/SAML2Utils.java @@ -94,6 +94,26 @@ public class SAML2Utils { return document; } +// public static SignatureTrustEngine getSignatureKnownKeysTrustEngine() throws ConfigurationException { +// MetadataCredentialResolver resolver; +// +// resolver = new MetadataCredentialResolver(ConfigurationProvider.getInstance().getMetaDataProvier()); +// +// List keyInfoProvider = new ArrayList(); +// keyInfoProvider.add(new DSAKeyValueProvider()); +// keyInfoProvider.add(new RSAKeyValueProvider()); +// keyInfoProvider.add(new InlineX509DataProvider()); +// +// KeyInfoCredentialResolver keyInfoResolver = new BasicProviderKeyInfoCredentialResolver( +// keyInfoProvider); +// +// ExplicitKeySignatureTrustEngine engine = new ExplicitKeySignatureTrustEngine( +// resolver, keyInfoResolver); +// +// return engine; +// +// } + } diff --git a/id/ConfigWebTool/src/main/resources/applicationResources_de.properties b/id/ConfigWebTool/src/main/resources/applicationResources_de.properties index 98e66c4fa..7641fbafb 100644 --- a/id/ConfigWebTool/src/main/resources/applicationResources_de.properties +++ b/id/ConfigWebTool/src/main/resources/applicationResources_de.properties @@ -7,6 +7,8 @@ config.03=Hibernate Database connector can not be initialized config.04=OpenSAML (PVP2 Login) can not be initialized config.05=Configuration file not defined +error.initialization.pvplogin=PVP2 authentication can not be initialized. + error.title=Fehler: error.login.internal=W\u00E4hrend der Verarbeitung ist ein interner Fehler aufgetreten. Bitte Versuchen Sie es nocheinmal oder kontaktieren Sie den Administrator. error.general.text=W\u00E4hrend der Verarbeitung ist ein interner Fehler aufgetreten. Bitte Versuchen Sie es nocheinmal oder kontaktieren Sie den Administrator. diff --git a/id/ConfigWebTool/src/main/resources/applicationResources_en.properties b/id/ConfigWebTool/src/main/resources/applicationResources_en.properties index 51b1d239e..2bf38f197 100644 --- a/id/ConfigWebTool/src/main/resources/applicationResources_en.properties +++ b/id/ConfigWebTool/src/main/resources/applicationResources_en.properties @@ -7,6 +7,8 @@ config.03=Hibernate Database connector can not be initialized config.04=OpenSAML (PVP2 Login) can not be initialized config.05=Configuration file is not defined +error.initialization.pvplogin=PVP2 authentication can not be initialized. + error.title=Error: error.login.internal=The error occurred during the processing. Please try again or contact Administrator. error.general.text=During the processing the error condition occured. Please try again or contact the administrator. -- cgit v1.2.3