From 9cb68043945f53246928443cea723b58ee2b1c24 Mon Sep 17 00:00:00 2001 From: Florian Reimair Date: Tue, 21 Jan 2014 14:38:35 +0100 Subject: updated samlengine --- .../eu/stork/peps/auth/engine/STORKSAMLEngine.java | 900 +++++++++++++++++++-- 1 file changed, 811 insertions(+), 89 deletions(-) (limited to 'id/server/stork2-saml-engine/src/main/java/eu/stork/peps/auth/engine/STORKSAMLEngine.java') diff --git a/id/server/stork2-saml-engine/src/main/java/eu/stork/peps/auth/engine/STORKSAMLEngine.java b/id/server/stork2-saml-engine/src/main/java/eu/stork/peps/auth/engine/STORKSAMLEngine.java index 3cac2f637..20ebb709d 100644 --- a/id/server/stork2-saml-engine/src/main/java/eu/stork/peps/auth/engine/STORKSAMLEngine.java +++ b/id/server/stork2-saml-engine/src/main/java/eu/stork/peps/auth/engine/STORKSAMLEngine.java @@ -64,6 +64,8 @@ import org.opensaml.saml2.core.AuthnRequest; import org.opensaml.saml2.core.AuthnStatement; import org.opensaml.saml2.core.Conditions; import org.opensaml.saml2.core.Issuer; +import org.opensaml.saml2.core.LogoutRequest; +import org.opensaml.saml2.core.LogoutResponse; import org.opensaml.saml2.core.NameID; import org.opensaml.saml2.core.OneTimeUse; import org.opensaml.saml2.core.Response; @@ -82,6 +84,7 @@ import org.opensaml.xml.schema.impl.XSAnyBuilder; import org.opensaml.xml.schema.impl.XSAnyImpl; import org.opensaml.xml.schema.impl.XSAnyMarshaller; import org.opensaml.xml.schema.impl.XSAnyUnmarshaller; +import org.opensaml.xml.schema.impl.XSDateTimeImpl; import org.opensaml.xml.schema.impl.XSStringImpl; import org.opensaml.xml.signature.KeyInfo; import org.opensaml.xml.util.Base64; @@ -100,8 +103,12 @@ import eu.stork.peps.auth.commons.STORKAttrQueryRequest; import eu.stork.peps.auth.commons.STORKAttrQueryResponse; import eu.stork.peps.auth.commons.STORKAuthnRequest; import eu.stork.peps.auth.commons.STORKAuthnResponse; +import eu.stork.peps.auth.commons.STORKLogoutRequest; +import eu.stork.peps.auth.commons.STORKLogoutResponse; import eu.stork.peps.auth.engine.core.AuthenticationAttributes; import eu.stork.peps.auth.engine.core.CitizenCountryCode; +import eu.stork.peps.auth.engine.core.CustomAttributeQuery; +import eu.stork.peps.auth.engine.core.CustomRequestAbstractType; import eu.stork.peps.auth.engine.core.EIDCrossBorderShare; import eu.stork.peps.auth.engine.core.EIDCrossSectorShare; import eu.stork.peps.auth.engine.core.EIDSectorShare; @@ -122,6 +129,7 @@ import eu.stork.peps.auth.engine.core.impl.AuthenticationAttributesUnmarshaller; import eu.stork.peps.auth.engine.core.impl.CitizenCountryCodeBuilder; import eu.stork.peps.auth.engine.core.impl.CitizenCountryCodeMarshaller; import eu.stork.peps.auth.engine.core.impl.CitizenCountryCodeUnmarshaller; +import eu.stork.peps.auth.engine.core.impl.CustomAttributeQueryUnmarshaller; import eu.stork.peps.auth.engine.core.impl.EIDCrossBorderShareBuilder; import eu.stork.peps.auth.engine.core.impl.EIDCrossBorderShareMarshaller; import eu.stork.peps.auth.engine.core.impl.EIDCrossBorderShareUnmarshaller; @@ -161,6 +169,7 @@ import eu.stork.peps.auth.engine.core.impl.SPSectorUnmarshaller; import eu.stork.peps.auth.engine.core.impl.VIDPAuthenticationAttributesBuilder; import eu.stork.peps.auth.engine.core.impl.VIDPAuthenticationAttributesMarshaller; import eu.stork.peps.auth.engine.core.impl.VIDPAuthenticationAttributesUnmarshaller; +import eu.stork.peps.auth.engine.core.validator.CustomAttributeQueryValidator; import eu.stork.peps.auth.engine.core.validator.ExtensionsSchemaValidator; import eu.stork.peps.auth.engine.core.validator.QAAAttributeSchemaValidator; import eu.stork.peps.exceptions.SAMLEngineException; @@ -806,8 +815,7 @@ public final class STORKSAMLEngine extends SAMLEngine { final XMLObject xmlObject = values.get(nextValue); if (xmlObject instanceof XSStringImpl) { - - // Process simple value. + simpleValues.add(((XSStringImpl) xmlObject).getValue()); } else if (xmlObject instanceof XSAnyImpl) { @@ -841,10 +849,9 @@ public final class STORKSAMLEngine extends SAMLEngine { simpleValues.add(str); - } else if (attributeName - .equals("http://www.stork.gov.eu/1.0/canonicalResidenceAddress")) + } else if (isComplex(xmlObject)) { - LOG.info("canonicalResidenceAddress found"); + LOG.info(attributeName + " found"); // Process complex value. final XSAnyImpl complexValue = (XSAnyImpl) xmlObject; @@ -859,61 +866,7 @@ public final class STORKSAMLEngine extends SAMLEngine { .getLocalPart(), simple.getTextContent()); } - } - else if (attributeName - .equals("http://www.stork.gov.eu/1.0/newAttribute2")) - { - LOG.info("newAttribute2 found"); - // Process complex value. - final XSAnyImpl complexValue = (XSAnyImpl) xmlObject; - - for (int nextComplexValue = 0; nextComplexValue < complexValue - .getUnknownXMLObjects().size(); nextComplexValue++) { - - final XSAnyImpl simple = (XSAnyImpl) complexValue - .getUnknownXMLObjects().get( - nextComplexValue); - - multiValues.put(simple.getElementQName() - .getLocalPart(), simple.getTextContent()); - } - } - else if (attributeName - .equals("http://www.stork.gov.eu/1.0/hasDegree")) - { - LOG.info("hasDegree found"); - // Process complex value. - final XSAnyImpl complexValue = (XSAnyImpl) xmlObject; - - for (int nextComplexValue = 0; nextComplexValue < complexValue - .getUnknownXMLObjects().size(); nextComplexValue++) { - - final XSAnyImpl simple = (XSAnyImpl) complexValue - .getUnknownXMLObjects().get( - nextComplexValue); - - multiValues.put(simple.getElementQName() - .getLocalPart(), simple.getTextContent()); - } - } - else if(attributeName - .equals("http://www.stork.gov.eu/1.0/mandateContent")) - { - LOG.info("mandateContent found"); - // Process complex value. - final XSAnyImpl complexValue = (XSAnyImpl) xmlObject; - - for (int nextComplexValue = 0; nextComplexValue < complexValue - .getUnknownXMLObjects().size(); nextComplexValue++) { - - final XSAnyImpl simple = (XSAnyImpl) complexValue - .getUnknownXMLObjects().get( - nextComplexValue); - - multiValues.put(simple.getElementQName() - .getLocalPart(), simple.getTextContent()); - } - } + } else { // Process simple value. simpleValues.add(((XSAnyImpl) xmlObject) @@ -1102,6 +1055,99 @@ public final class STORKSAMLEngine extends SAMLEngine { } return authresponse; } + + /** + * Generate stork authentication response. + * + * @param request the request + * @param responseAuthReq the response authentication request + * @param ipAddress the IP address + * @param isHashing the is hashing + * + * @return the sTORK authentication response + * + * @throws STORKSAMLEngineException the STORKSAML engine exception + */ + public STORKAuthnResponse generateSTORKAuthnResponseAfterQuery( + final STORKAuthnRequest request, + final STORKAuthnResponse responseAuthReq, final String ipAddress, + final boolean isHashing, List res) throws STORKSAMLEngineException { + LOG.info("generateSTORKAuthnResponse"); + + // Validate parameters + validateParamResponse(request, responseAuthReq); + + // Mandatory SAML + LOG.debug("Generate StatusCode"); + final StatusCode statusCode = SAMLEngineUtils + .generateStatusCode(StatusCode.SUCCESS_URI); + + LOG.debug("Generate Status"); + final Status status = SAMLEngineUtils.generateStatus(statusCode); + + LOG.debug("Generate StatusMessage"); + final StatusMessage statusMessage = (StatusMessage) SAMLEngineUtils + .generateStatusMessage(StatusCode.SUCCESS_URI); + + status.setStatusMessage(statusMessage); + + LOG.debug("Generate Response"); + + // RESPONSE + final Response response = genAuthnRespBase(status, request + .getAssertionConsumerServiceURL(), request.getSamlId()); + + DateTime notOnOrAfter = new DateTime(); + + notOnOrAfter = notOnOrAfter.plusSeconds(super.getSamlCoreProperties() + .getTimeNotOnOrAfter()); + + final Assertion assertion = this.generateAssertion(ipAddress, request + .getAssertionConsumerServiceURL(), request.getSamlId(), request + .getIssuer(), notOnOrAfter); + + final AttributeStatement attrStatement = this + .generateAttributeStatement(responseAuthReq + .getPersonalAttributeList(), isHashing); + + assertion.getAttributeStatements().add(attrStatement); + + // Add assertions + response.getAssertions().add(assertion); + // Check for response queries + if (res != null && res.size() > 0) + { + //Iterate through them + for (int i = 0; i < res.size(); i++) + { + //If response contains multiple assertions iterate through them as well + if (res.get(i).getAssertions().size() > 1) + { + for (int j = 0; j < res.get(i).getAssertions().size(); j++) + { + Assertion tempAssertion = res.get(i).getAssertions().get(j); + tempAssertion.setParent(response); + response.getAssertions().add(tempAssertion); + } + } else { + Assertion tempAssertion = res.get(i).getAssertion(); + tempAssertion.setParent(response); + response.getAssertions().add(tempAssertion); + } + } + } + + final STORKAuthnResponse authresponse = new STORKAuthnResponse(); + + try { + authresponse.setTokenSaml(super.signAndMarshall(response)); + authresponse.setSamlId(response.getID()); + } catch (SAMLEngineException e) { + LOG.error("Sign and Marshall.", e); + throw new STORKSAMLEngineException(e); + } + return authresponse; + } /** * Generate stork authentication response fail. @@ -1199,7 +1245,8 @@ public final class STORKSAMLEngine extends SAMLEngine { // Validate Parameters mandatories validateParamAttrQueryReq(request); - final AttributeQuery attrQueryRequestAux = SAMLEngineUtils + //final AttributeQuery attrQueryRequestAux = SAMLEngineUtils + final CustomAttributeQuery attrQueryRequestAux = SAMLEngineUtils .generateSAMLAttrQueryRequest(SAMLEngineUtils.generateNCName(), SAMLVersion.VERSION_20, SAMLEngineUtils .getCurrentTime()); @@ -1214,6 +1261,12 @@ public final class STORKSAMLEngine extends SAMLEngine { if (StringUtils.isNotBlank(request.getDestination())) { attrQueryRequestAux.setDestination(request.getDestination()); } + + // Add parameter optional STORK + // Consumer URL is needed if using HTTP-Post + if (StringUtils.isNotBlank(request.getAssertionConsumerServiceURL())) { + attrQueryRequestAux.setAssertionConsumerServiceURL(request.getAssertionConsumerServiceURL()); + } // Consent is optional. Set from SAMLEngine.xml - consent. attrQueryRequestAux.setConsent(super.getSamlCoreProperties() @@ -1264,7 +1317,7 @@ public final class STORKSAMLEngine extends SAMLEngine { attrQueryRequest.setSamlId(attrQueryRequestAux.getID()); attrQueryRequest.setDestination(attrQueryRequestAux.getDestination()); - + attrQueryRequest.setAssertionConsumerServiceURL(attrQueryRequestAux.getAssertionConsumerServiceURL()); attrQueryRequest.setIssuer(attrQueryRequestAux.getIssuer().getValue()); return attrQueryRequest; @@ -1274,9 +1327,9 @@ public final class STORKSAMLEngine extends SAMLEngine { * Generate stork attribute query response. * * @param request the request - * @param responseAttrQueryReq the response authentication request + * @param responseAttrQueryRes the response authentication request * @param ipAddress the IP address - * @param isHashing the is hashing + * @param isHashing the hashing of values * * @return the sTORK authentication response * @@ -1284,12 +1337,12 @@ public final class STORKSAMLEngine extends SAMLEngine { */ public STORKAttrQueryResponse generateSTORKAttrQueryResponse( final STORKAttrQueryRequest request, - final STORKAttrQueryResponse responseAttrQueryReq, final String ipAddress, + final STORKAttrQueryResponse responseAttrQueryRes, final String ipAddress, final String destinationUrl, final boolean isHashing) throws STORKSAMLEngineException { LOG.info("generateSTORKAttrQueryResponse"); // Validate parameters - validateParamAttrQueryResponse(request, responseAttrQueryReq); + validateParamAttrQueryResponse(request, responseAttrQueryRes); // Mandatory SAML LOG.debug("Generate StatusCode"); @@ -1320,7 +1373,7 @@ public final class STORKSAMLEngine extends SAMLEngine { ,request.getSamlId(), request.getIssuer(), notOnOrAfter); final AttributeStatement attrStatement = this - .generateAttributeStatement(responseAttrQueryReq + .generateAttributeStatement(responseAttrQueryRes .getPersonalAttributeList(), isHashing); assertion.getAttributeStatements().add(attrStatement); @@ -1340,6 +1393,86 @@ public final class STORKSAMLEngine extends SAMLEngine { return attrQueryResponse; } + /** + * Generate stork attribute query response from multiple assertions + * + * @param request the request + * @param responseAttrQueryRes the response to the query request + * @param responses the responses to include in the response (aggregation) + * @param ipAddress the IP address + * @param isHashing the hashing of values + * + * @return the sTORK attribute query response + * + * @throws STORKSAMLEngineException the STORKSAML engine exception + */ + public STORKAttrQueryResponse generateSTORKAttrQueryResponseWithAssertions( + final STORKAttrQueryRequest request, final STORKAttrQueryResponse responseAttrQueryRes, + final List responses, final String ipAddress, + final String destinationUrl, final boolean isHashing) throws STORKSAMLEngineException { + LOG.info("generateSTORKAttrQueryResponse"); + + // Validate parameters + validateParamAttrQueryResponse(request, responseAttrQueryRes); + + // Mandatory SAML + LOG.debug("Generate StatusCode"); + final StatusCode statusCode = SAMLEngineUtils + .generateStatusCode(StatusCode.SUCCESS_URI); + + LOG.debug("Generate Status"); + final Status status = SAMLEngineUtils.generateStatus(statusCode); + + LOG.debug("Generate StatusMessage"); + final StatusMessage statusMessage = (StatusMessage) SAMLEngineUtils + .generateStatusMessage(StatusCode.SUCCESS_URI); + + status.setStatusMessage(statusMessage); + + LOG.debug("Generate Response"); + + // RESPONSE + final Response response = genAuthnRespBase(status, destinationUrl, + request.getSamlId()); + + DateTime notOnOrAfter = new DateTime(); + + notOnOrAfter = notOnOrAfter.plusSeconds(super.getSamlCoreProperties() + .getTimeNotOnOrAfter()); + + final Assertion assertion = this.generateAssertion(ipAddress, "" + ,request.getSamlId(), request.getIssuer(), notOnOrAfter); + + final AttributeStatement attrStatement = this + .generateAttributeStatement(responseAttrQueryRes + .getPersonalAttributeList(), isHashing); + + assertion.getAttributeStatements().add(attrStatement); + + // Add the assertions from the former Query responses + response.getAssertions().add(assertion); + if (responses != null && responses.size() > 0) + { + for (int i = 0; i < responses.size(); i++) + { + Assertion tempAssertion = responses.get(i).getAssertion(); + tempAssertion.setParent(response); + response.getAssertions().add(tempAssertion); + } + } + + final STORKAttrQueryResponse attrQueryResponse = new STORKAttrQueryResponse(); + + try { + attrQueryResponse.setTokenSaml(super.signAndMarshall(response)); + attrQueryResponse.setSamlId(response.getID()); + } catch (SAMLEngineException e) { + LOG.error("Sign and Marshall.", e); + throw new STORKSAMLEngineException(e); + } + return attrQueryResponse; + } + /** * Generate stork attribute query response fail. * @@ -1403,20 +1536,298 @@ public final class STORKSAMLEngine extends SAMLEngine { request.getSamlId(), request .getIssuer(), notOnOrAfter); - responseFail.getAssertions().add(assertion); + responseFail.getAssertions().add(assertion); + + LOG.debug("Sign and Marshall ResponseFail."); + + final STORKAttrQueryResponse storkResponse = new STORKAttrQueryResponse(); + + try { + storkResponse.setTokenSaml(super.signAndMarshall(responseFail)); + storkResponse.setSamlId(responseFail.getID()); + } catch (SAMLEngineException e) { + LOG.error("SAMLEngineException.", e); + throw new STORKSAMLEngineException(e); + } + return storkResponse; + } + + /** + * Generate stork logout request. + * + * @param request the request that contain all parameters for generate an + * logout request. + * + * @return the STORK logout request that has been processed. + * + * @throws STORKSAMLEngineException the STORKSAML engine exception + */ + public STORKLogoutRequest generateSTORKLogoutRequest( + final STORKLogoutRequest request) throws STORKSAMLEngineException { + LOG.info("Generate STORKLogoutRequest."); + + // Validate Parameters mandatories + validateParamLogoutReq(request); + + final LogoutRequest logoutRequestAux = SAMLEngineUtils + .generateSAMLLogoutRequest(SAMLEngineUtils.generateNCName(), + SAMLVersion.VERSION_20, SAMLEngineUtils + .getCurrentTime()); + + // Set name spaces. + setNameSpaces(logoutRequestAux); + + + // Add parameter optional STORK + // Destination is mandatory if the destination is a C-PEPS + // The application must to know if the destination is a C-PEPS. + if (StringUtils.isNotBlank(request.getDestination())) { + logoutRequestAux.setDestination(request.getDestination()); + } + + // Consent is optional. Set from SAMLEngine.xml - consent. + logoutRequestAux.setConsent(super.getSamlCoreProperties() + .getConsentAuthnRequest()); + + final Issuer issuer = SAMLEngineUtils.generateIssuer(); + + + if(request.getIssuer()!=null){ + issuer.setValue(request.getIssuer()); + } else { + issuer.setValue(super.getSamlCoreProperties().getRequester()); + } + + // Optional STORK + final String formatEntity = super.getSamlCoreProperties() + .getFormatEntity(); + if (StringUtils.isNotBlank(formatEntity)) { + issuer.setFormat(formatEntity); + } + + logoutRequestAux.setIssuer(issuer); + + // Set the name ID + final NameID newNameID = SAMLEngineUtils.generateNameID(); + newNameID.setValue(request.getSpProvidedId()); + logoutRequestAux.setNameID(newNameID); + + + // the result contains an authentication request token (byte[]), + // identifier of the token, and all parameters from the request. + final STORKLogoutRequest logoutRequest = new STORKLogoutRequest(); + + try { + logoutRequest.setTokenSaml(super.signAndMarshall(logoutRequestAux)); + } catch (SAMLEngineException e) { + LOG.error("Sign and Marshall.", e); + throw new STORKSAMLEngineException(e); + } + + logoutRequest.setSamlId(logoutRequestAux.getID()); + logoutRequest.setDestination(logoutRequestAux.getDestination()); + logoutRequest.setIssuer(logoutRequestAux.getIssuer().getValue()); + logoutRequest.setSpProvidedId(logoutRequestAux.getNameID().getValue()); + + return logoutRequest; + } + + + /** + * Generate stork logout response. + * @param request the request thats being responded to + * @param response the tesponse that contain all parameters for generate an + * logout request. + * + * @return the STORK logout response that has been processed. + * + * @throws STORKSAMLEngineException the STORKSAML engine exception + */ + public STORKLogoutResponse generateSTORKLogoutResponse( + final STORKLogoutRequest request, + final STORKLogoutResponse response) throws STORKSAMLEngineException { + LOG.info("Generate STORKLogoutResponse."); + + // Validate Parameters mandatories + validateParamLogoutRes(request, response); + + // Mandatory SAML + LOG.debug("Generate StatusCode"); + final StatusCode statusCode = SAMLEngineUtils + .generateStatusCode(StatusCode.SUCCESS_URI); + + LOG.debug("Generate Status"); + final Status status = SAMLEngineUtils.generateStatus(statusCode); + + LOG.debug("Generate StatusMessage"); + final StatusMessage statusMessage = (StatusMessage) SAMLEngineUtils + .generateStatusMessage(StatusCode.SUCCESS_URI); + + status.setStatusMessage(statusMessage); + + final LogoutResponse logoutResponseAux= SAMLEngineUtils + .generateSAMLLogoutResponse(SAMLEngineUtils.generateNCName(), + SAMLVersion.VERSION_20, SAMLEngineUtils + .getCurrentTime(), status, request.getSamlId()); + + // Set name spaces. + setNameSpaces(logoutResponseAux); + + + // Add parameter optional STORK + // Destination is mandatory if the destination is a C-PEPS + // The application must to know if the destination is a C-PEPS. + if (StringUtils.isNotBlank(response.getDestination())) { + logoutResponseAux.setDestination(response.getDestination()); + } + + // Consent is optional. Set from SAMLEngine.xml - consent. + logoutResponseAux.setConsent(super.getSamlCoreProperties() + .getConsentAuthnRequest()); + + final Issuer issuer = SAMLEngineUtils.generateIssuer(); + + + if(response.getIssuer()!=null){ + issuer.setValue(response.getIssuer()); + } else { + issuer.setValue(super.getSamlCoreProperties().getRequester()); + } + + // Optional STORK + final String formatEntity = super.getSamlCoreProperties() + .getFormatEntity(); + if (StringUtils.isNotBlank(formatEntity)) { + issuer.setFormat(formatEntity); + } + + logoutResponseAux.setIssuer(issuer); + + + // the result contains an authentication request token (byte[]), + // identifier of the token, and all parameters from the request. + final STORKLogoutResponse logoutResponse = new STORKLogoutResponse(); + + try { + logoutResponse.setTokenSaml(super.signAndMarshall(logoutResponseAux)); + } catch (SAMLEngineException e) { + LOG.error("Sign and Marshall.", e); + throw new STORKSAMLEngineException(e); + } + + logoutResponse.setSamlId(logoutResponseAux.getID()); + logoutResponse.setDestination(logoutResponseAux.getDestination()); + logoutResponse.setIssuer(logoutResponseAux.getIssuer().getValue()); + logoutResponse.setStatusCode(logoutResponseAux.getStatus().getStatusCode().toString()); + logoutResponse.setStatusMessage(logoutResponseAux.getStatus().getStatusMessage().toString()); + + return logoutResponse; + } + + /** + * Generate failed stork logout response. + * + * @param response the response that contain all parameters for generate an + * logout request. + * + * @return the STORK logout response that has been processed. + * + * @throws STORKSAMLEngineException the STORKSAML engine exception + */ + public STORKLogoutResponse generateSTORKLogoutResponseFail( + final STORKLogoutRequest request, + final STORKLogoutResponse response ) throws STORKSAMLEngineException { + LOG.info("Generate STORKLogoutResponse."); + + // Validate Parameters mandatories + validateParamLogoutResFail(request, response); + + // Mandatory + final StatusCode statusCode = SAMLEngineUtils + .generateStatusCode(response.getStatusCode()); + + // Mandatory SAML + LOG.debug("Generate StatusCode."); + // Subordinate code it's optional in case not covered into next codes: + // - urn:oasis:names:tc:SAML:2.0:status:AuthnFailed + // - urn:oasis:names:tc:SAML:2.0:status:InvalidAttrNameOrValue + // - urn:oasis:names:tc:SAML:2.0:status:InvalidNameIDPolicy + // - urn:oasis:names:tc:SAML:2.0:status:RequestDenied + // - http://www.stork.gov.eu/saml20/statusCodes/QAANotSupported + + if (StringUtils.isNotBlank(response.getSubStatusCode())) { + final StatusCode newStatusCode = SAMLEngineUtils + .generateStatusCode(response.getSubStatusCode()); + statusCode.setStatusCode(newStatusCode); + } + + LOG.debug("Generate Status."); + final Status status = SAMLEngineUtils.generateStatus(statusCode); + + if (StringUtils.isNotBlank(response.getStatusMessage())) { + final StatusMessage statusMessage = (StatusMessage) SAMLEngineUtils + .generateStatusMessage(response.getStatusMessage()); + + status.setStatusMessage(statusMessage); + } + + final LogoutResponse logoutResponseAux= SAMLEngineUtils + .generateSAMLLogoutResponse(SAMLEngineUtils.generateNCName(), + SAMLVersion.VERSION_20, SAMLEngineUtils + .getCurrentTime(), status, request.getSamlId()); + + // Set name spaces. + setNameSpaces(logoutResponseAux); + + + // Add parameter optional STORK + // Destination is mandatory if the destination is a C-PEPS + // The application must to know if the destination is a C-PEPS. + if (StringUtils.isNotBlank(response.getDestination())) { + logoutResponseAux.setDestination(response.getDestination()); + } + + // Consent is optional. Set from SAMLEngine.xml - consent. + logoutResponseAux.setConsent(super.getSamlCoreProperties() + .getConsentAuthnRequest()); - LOG.debug("Sign and Marshall ResponseFail."); + final Issuer issuer = SAMLEngineUtils.generateIssuer(); + + + if(response.getIssuer()!=null){ + issuer.setValue(response.getIssuer()); + } else { + issuer.setValue(super.getSamlCoreProperties().getRequester()); + } - final STORKAttrQueryResponse storkResponse = new STORKAttrQueryResponse(); + // Optional STORK + final String formatEntity = super.getSamlCoreProperties() + .getFormatEntity(); + if (StringUtils.isNotBlank(formatEntity)) { + issuer.setFormat(formatEntity); + } + + logoutResponseAux.setIssuer(issuer); + + + // the result contains an authentication request token (byte[]), + // identifier of the token, and all parameters from the request. + final STORKLogoutResponse logoutResponse = new STORKLogoutResponse(); try { - storkResponse.setTokenSaml(super.signAndMarshall(responseFail)); - storkResponse.setSamlId(responseFail.getID()); + logoutResponse.setTokenSaml(super.signAndMarshall(logoutResponseAux)); } catch (SAMLEngineException e) { - LOG.error("SAMLEngineException.", e); + LOG.error("Sign and Marshall.", e); throw new STORKSAMLEngineException(e); } - return storkResponse; + + logoutResponse.setSamlId(logoutResponseAux.getID()); + logoutResponse.setDestination(logoutResponseAux.getDestination()); + logoutResponse.setIssuer(logoutResponseAux.getIssuer().getValue()); + logoutResponse.setStatusCode(logoutResponseAux.getStatus().getStatusCode().toString()); + logoutResponse.setStatusMessage(logoutResponseAux.getStatus().getStatusMessage().toString()); + + return logoutResponse; } /** @@ -2392,7 +2803,7 @@ public final class STORKSAMLEngine extends SAMLEngine { } /** - * Validate parameters from authentication request. + * Validate parameters from attribute query request. * * @param request the request. * @@ -2402,18 +2813,23 @@ public final class STORKSAMLEngine extends SAMLEngine { throws STORKSAMLEngineException { LOG.info("Validate parameters from attribute query request."); - // URL to which Authentication Response must be sent. - /*if (StringUtils.isBlank(request.getAssertionConsumerServiceURL())) { + // URL to which AP Response must be sent. + if (StringUtils.isBlank(request.getAssertionConsumerServiceURL())) { throw new STORKSAMLEngineException( "StorkSamlEngine: Assertion Consumer Service URL it's mandatory."); - }*/ + } - // the name of the original service provider requesting the - // authentication. - /*if (StringUtils.isBlank(request.getProviderName())) { + // Destination of the request - not mandatory + /*if (StringUtils.isBlank(request.getDestination())) { throw new STORKSAMLEngineException( - "StorkSamlEngine: Service Provider it's mandatory."); + "StorkSamlEngine: Destination is mandatory."); }*/ + + // SP country is empty + if (StringUtils.isBlank(request.getSpCountry())) { + throw new STORKSAMLEngineException( + "StorkSamlEngine: SP country is mandatory."); + } // object that contain all attributes requesting. if (request.getPersonalAttributeList() == null @@ -2428,7 +2844,70 @@ public final class STORKSAMLEngine extends SAMLEngine { throw new STORKSAMLEngineException("Qaal: " + request.getQaa() + ", is invalid."); } + } + + /** + * Validate parameters from logout request. + * + * @param request the request. + * + * @throws STORKSAMLEngineException the STORKSAML engine exception + */ + private void validateParamLogoutReq(final STORKLogoutRequest request) + throws STORKSAMLEngineException { + LOG.info("Validate parameters from logout request."); + + // URL to which AP Response must be sent. + /*if (StringUtils.isBlank(request.get())) { + throw new STORKSAMLEngineException( + "StorkSamlEngine: Assertion Consumer Service URL it's mandatory."); + }*/ + + // Destination of the request + if (StringUtils.isBlank(request.getDestination())) { + throw new STORKSAMLEngineException( + "StorkSamlEngine: Destination is mandatory."); + } + + // SP Provided Id + if (StringUtils.isBlank(request.getSpProvidedId())) { + throw new STORKSAMLEngineException( + "StorkSamlEngine: SP provided Id is mandatory."); + } + } + + /** + * Validate parameters from logout response. + * + * @param response the response. + * + * @throws STORKSAMLEngineException the STORKSAML engine exception + */ + private void validateParamLogoutRes(final STORKLogoutRequest request, + final STORKLogoutResponse response) throws STORKSAMLEngineException { + LOG.info("Validate parameters from logout request."); + + // Issuer is mandatory + if (StringUtils.isBlank(request.getIssuer())) { + throw new STORKSAMLEngineException( + "Issuer must be not empty or null."); + } + // Destination of the request + if (StringUtils.isBlank(response.getDestination())) { + throw new STORKSAMLEngineException( + "StorkSamlEngine: Destination is mandatory."); + } + + // SP Provided Id + if (StringUtils.isBlank(request.getSpProvidedId())) { + throw new STORKSAMLEngineException( + "StorkSamlEngine: SP provided Id is mandatory."); + } + + if (StringUtils.isBlank(request.getSamlId())) { + throw new STORKSAMLEngineException("request ID is null or empty."); + } } @@ -2544,6 +3023,32 @@ public final class STORKSAMLEngine extends SAMLEngine { throw new STORKSAMLEngineException("request ID is null or empty."); } } + + /** + * Validate parameter from response fail. + * + * @param request the request + * @param response the response + * + * @throws STORKSAMLEngineException the STORKSAML engine exception + */ + private void validateParamLogoutResFail(final STORKLogoutRequest request, + final STORKLogoutResponse response) throws STORKSAMLEngineException { + LOG.info("Validate parameters response fail."); + + if (StringUtils.isBlank(request.getIssuer())) { + throw new STORKSAMLEngineException( + "Issuer must be not empty or null."); + } + + if (StringUtils.isBlank(response.getStatusCode())) { + throw new STORKSAMLEngineException("Code error it's null or empty."); + } + + if (StringUtils.isBlank(request.getSamlId())) { + throw new STORKSAMLEngineException("request ID is null or empty."); + } + } /** * Validate stork authentication request. @@ -2611,11 +3116,11 @@ public final class STORKSAMLEngine extends SAMLEngine { } /** - * Validate stork authentication request. + * Validate stork attribute query request. * * @param tokenSaml the token SAML * - * @return the sTORK authentication request + * @return the STORK attribute query request * * @throws STORKSAMLEngineException the STORKSAML engine exception */ @@ -2623,7 +3128,8 @@ public final class STORKSAMLEngine extends SAMLEngine { throws STORKSAMLEngineException { LOG.info("validateSTORKAttrQueryRequest"); - final AttributeQuery samlRequest = (AttributeQuery) validateStorkSaml(tokenSaml); + //final AttributeQuery samlRequest = (AttributeQuery) validateStorkSaml(tokenSaml); + final CustomRequestAbstractType samlRequest = (CustomRequestAbstractType) validateStorkSaml(tokenSaml); LOG.debug("Validate Extensions."); final Validator validatorExt = new ExtensionsSchemaValidator(); @@ -2646,10 +3152,10 @@ public final class STORKSAMLEngine extends SAMLEngine { attrRequest.setSamlId(samlRequest.getID()); attrRequest.setDestination(samlRequest.getDestination()); - /*attrRequest.setAssertionConsumerServiceURL(samlRequest + attrRequest.setAssertionConsumerServiceURL(samlRequest .getAssertionConsumerServiceURL()); - authnRequest.setProviderName(samlRequest.getProviderName());*/ + /*authnRequest.setProviderName(samlRequest.getProviderName());*/ attrRequest.setIssuer(samlRequest.getIssuer().getValue()); //Delete unknown elements from requested ones @@ -2674,6 +3180,50 @@ public final class STORKSAMLEngine extends SAMLEngine { return attrRequest; } + + /** + * Validate stork logout request. + * + * @param tokenSaml the token SAML + * + * @return the STORK logout request + * + * @throws STORKSAMLEngineException the STORKSAML engine exception + */ + public STORKLogoutRequest validateSTORKLogoutRequest(final byte[] tokenSaml) + throws STORKSAMLEngineException { + LOG.info("validateSTORKLogoutRequest"); + + final LogoutRequest samlRequest = (LogoutRequest)validateStorkSaml(tokenSaml); + + LOG.debug("Validate Extensions."); + final Validator validatorExt = new ExtensionsSchemaValidator(); + try { + validatorExt.validate(samlRequest.getExtensions()); + } catch (ValidationException e) { + LOG.error("ValidationException: validate Extensions.", e); + throw new STORKSAMLEngineException(e); + } + + LOG.debug("Generate STORKLogoutRequest."); + final STORKLogoutRequest logoutRequest = new STORKLogoutRequest(); + + logoutRequest.setCountry(this.getCountry(samlRequest.getSignature() + .getKeyInfo())); + + logoutRequest.setAlias(this.getAlias(samlRequest.getSignature() + .getKeyInfo(), super.getSigner().getTrustStore())); + + logoutRequest.setSamlId(samlRequest.getID()); + logoutRequest.setDestination(samlRequest.getDestination()); + + logoutRequest.setIssuer(samlRequest.getIssuer().getValue()); + + logoutRequest.setSpProvidedId(samlRequest.getNameID().getValue()); + + return logoutRequest; + + } /** * Validate stork authentication response. @@ -2718,6 +3268,97 @@ public final class STORKSAMLEngine extends SAMLEngine { .getStatusMessage().getMessage()); } + LOG.debug("validateStorkResponse"); + final Assertion assertion = (Assertion) validateStorkResponse( + samlResponse, userIP); + + if(assertion!=null){ + final DateTime serverDate = new DateTime(); + + if (assertion.getConditions().getNotOnOrAfter().isBefore(serverDate)) { + LOG.error("Token date expired (getNotOnOrAfter = " + + assertion.getConditions().getNotOnOrAfter() + + ", server_date: " + serverDate + ")"); + throw new STORKSAMLEngineException( + "Token date expired (getNotOnOrAfter = " + + assertion.getConditions().getNotOnOrAfter() + + " ), server_date: " + serverDate); + } + + LOG.debug("Set notOnOrAfter."); + authnResponse.setNotOnOrAfter(assertion.getConditions() + .getNotOnOrAfter()); + + LOG.debug("Set notBefore."); + authnResponse.setNotBefore(assertion.getConditions().getNotBefore()); + + authnResponse.setNotBefore(assertion.getConditions().getNotBefore()); + + authnResponse.setAudienceRestriction(((AudienceRestriction) assertion + .getConditions().getAudienceRestrictions().get(0)) + .getAudiences().get(0).getAudienceURI()); + authnResponse.setAssertions(samlResponse.getAssertions()); + } + + // Case no error. + if (assertion!=null && StatusCode.SUCCESS_URI.equalsIgnoreCase(authnResponse + .getStatusCode())) { + LOG.debug("Status Success. Set PersonalAttributeList."); + authnResponse + .setPersonalAttributeList(generatePersonalAttributeList(assertion)); + authnResponse.setFail(false); + } else { + LOG.debug("Status Fail."); + authnResponse.setFail(true); + } + LOG.debug("Return result."); + return authnResponse; + + } + + /** + * Validate stork authentication response. + * + * @param tokenSaml the token SAML + * @param userIP the user IP + * + * @return the Stork authentication response + * + * @throws STORKSAMLEngineException the STORKSAML engine exception + */ + public STORKAuthnResponse validateSTORKAuthnResponseWithQuery( + final byte[] tokenSaml, final String userIP) + throws STORKSAMLEngineException { + + LOG.info("validateSTORKAuthnResponse"); + final Response samlResponse = (Response) validateStorkSaml(tokenSaml); + + LOG.debug("Create StorkAuthResponse."); + final STORKAuthnResponse authnResponse = new STORKAuthnResponse(); + + authnResponse.setCountry(this.getCountry(samlResponse.getSignature() + .getKeyInfo())); + + LOG.debug("Set ID."); + authnResponse.setSamlId(samlResponse.getID()); + LOG.debug("Set InResponseTo."); + authnResponse.setInResponseTo(samlResponse.getInResponseTo()); + LOG.debug("Set statusCode."); + authnResponse.setStatusCode(samlResponse.getStatus().getStatusCode() + .getValue()); + + // Subordinate code. + if (samlResponse.getStatus().getStatusCode().getStatusCode() != null) { + authnResponse.setSubStatusCode(samlResponse.getStatus() + .getStatusCode().getStatusCode().getValue()); + } + + if (samlResponse.getStatus().getStatusMessage() != null) { + LOG.debug("Set statusMessage."); + authnResponse.setMessage(samlResponse.getStatus() + .getStatusMessage().getMessage()); + } + LOG.debug("validateStorkResponse"); final Assertion assertion = (Assertion) validateStorkResponse( samlResponse, userIP); @@ -2760,6 +3401,30 @@ public final class STORKSAMLEngine extends SAMLEngine { LOG.debug("Status Fail."); authnResponse.setFail(true); } + + authnResponse.setAssertions(samlResponse.getAssertions()); + if (samlResponse.getAssertions().size() > 1) + { + PersonalAttributeList total = new PersonalAttributeList(); + List attrList = new ArrayList(); + for (int i = 0; i < samlResponse.getAssertions().size(); i++) + { + Assertion tempAssertion = (Assertion)samlResponse.getAssertions().get(i); + IPersonalAttributeList temp = generatePersonalAttributeList(tempAssertion); + if (temp != null) + { + attrList.add(temp); + for (PersonalAttribute attribute : temp) { + PersonalAttribute attr = (PersonalAttribute)attribute.clone(); + attr.setName(attr.getName()+tempAssertion.getID()); + total.add(attr); + } + } + } + authnResponse.setPersonalAttributeLists(attrList); + authnResponse.setTotalPersonalAttributeList(total); + } + LOG.debug("Return result."); return authnResponse; @@ -2795,6 +3460,7 @@ public final class STORKSAMLEngine extends SAMLEngine { LOG.debug("Set statusCode."); attrQueryResponse.setStatusCode(samlResponse.getStatus().getStatusCode() .getValue()); + // Subordinate code. if (samlResponse.getStatus().getStatusCode().getStatusCode() != null) { @@ -2815,6 +3481,8 @@ public final class STORKSAMLEngine extends SAMLEngine { if(assertion!=null){ final DateTime serverDate = new DateTime(); + attrQueryResponse.setAssertion(assertion); + if (assertion.getConditions().getNotOnOrAfter().isBefore(serverDate)) { LOG.error("Token date expired (getNotOnOrAfter = " + assertion.getConditions().getNotOnOrAfter() @@ -2850,6 +3518,30 @@ public final class STORKSAMLEngine extends SAMLEngine { LOG.debug("Status Fail."); attrQueryResponse.setFail(true); } + + attrQueryResponse.setAssertions(samlResponse.getAssertions()); + if (samlResponse.getAssertions().size() > 1) + { + PersonalAttributeList total = new PersonalAttributeList(); + List attrList = new ArrayList(); + for (int i = 0; i < samlResponse.getAssertions().size(); i++) + { + Assertion tempAssertion = (Assertion)samlResponse.getAssertions().get(i); + IPersonalAttributeList temp = generatePersonalAttributeList(tempAssertion); + if (temp != null) + { + attrList.add(temp); + for (PersonalAttribute attribute : temp) { + PersonalAttribute attr = (PersonalAttribute)attribute.clone(); + attr.setName(attr.getName()+tempAssertion.getID()); + total.add(attr); + } + } + } + attrQueryResponse.setPersonalAttributeLists(attrList); + attrQueryResponse.setTotalPersonalAttributeList(total); + } + LOG.debug("Return result."); return attrQueryResponse; @@ -2943,7 +3635,7 @@ public final class STORKSAMLEngine extends SAMLEngine { LOG.debug("Generate AuthnRequest from request."); SignableSAMLObject samlObject; - try { + try { samlObject = (SignableSAMLObject) super.unmarshall(tokenSaml); } catch (SAMLEngineException e) { LOG.error("SAMLEngineException unmarshall.", e); @@ -2972,7 +3664,14 @@ public final class STORKSAMLEngine extends SAMLEngine { final ValidatorSuite validatorSuite = Configuration .getValidatorSuite("saml2-core-schema-validator"); try { - validatorSuite.validate(samlObject); + if (samlObject.getElementQName().toString().endsWith(CustomAttributeQuery.DEFAULT_ELEMENT_LOCAL_NAME)) + { + CustomAttributeQueryValidator val = + new CustomAttributeQueryValidator(); + val.validate((CustomAttributeQuery)samlObject); + } + else + validatorSuite.validate(samlObject); } catch (ValidationException e) { LOG.error("ValidationException.", e); throw new STORKSAMLEngineException(e); @@ -2980,4 +3679,27 @@ public final class STORKSAMLEngine extends SAMLEngine { return samlObject; } + + private boolean isComplex(XMLObject xmlObject) + { + boolean isComplex = false; + + final XSAnyImpl complexValue = (XSAnyImpl) xmlObject; + + for (int nextComplexValue = 0; nextComplexValue < complexValue + .getUnknownXMLObjects().size(); nextComplexValue++) { + + final XSAnyImpl simple = (XSAnyImpl) complexValue + .getUnknownXMLObjects().get( + nextComplexValue); + + if (simple.getElementQName().getLocalPart() != null) + { + isComplex = true; + break; + } + } + + return isComplex; + } } -- cgit v1.2.3