From 6c7a6f8e222e4fb39a11c220b63e785f2037d428 Mon Sep 17 00:00:00 2001 From: Florian Reimair Date: Thu, 16 Jan 2014 08:55:06 +0100 Subject: fix added real source of stork modules --- .../engine/.svn/text-base/SAMLEngine.java.svn-base | 409 +++ .../.svn/text-base/SAMLEngineUtils.java.svn-base | 833 ++++++ .../.svn/text-base/STORKSAMLEngine.java.svn-base | 2983 ++++++++++++++++++++ .../.svn/text-base/X509PrincipalUtil.java.svn-base | 69 + .../.svn/text-base/package-info.java.svn-base | 19 + 5 files changed, 4313 insertions(+) create mode 100644 id/server/stork2-saml-engine/src/main/java/eu/stork/peps/auth/engine/.svn/text-base/SAMLEngine.java.svn-base create mode 100644 id/server/stork2-saml-engine/src/main/java/eu/stork/peps/auth/engine/.svn/text-base/SAMLEngineUtils.java.svn-base create mode 100644 id/server/stork2-saml-engine/src/main/java/eu/stork/peps/auth/engine/.svn/text-base/STORKSAMLEngine.java.svn-base create mode 100644 id/server/stork2-saml-engine/src/main/java/eu/stork/peps/auth/engine/.svn/text-base/X509PrincipalUtil.java.svn-base create mode 100644 id/server/stork2-saml-engine/src/main/java/eu/stork/peps/auth/engine/.svn/text-base/package-info.java.svn-base (limited to 'id/server/stork2-saml-engine/src/main/java/eu/stork/peps/auth/engine/.svn/text-base') diff --git a/id/server/stork2-saml-engine/src/main/java/eu/stork/peps/auth/engine/.svn/text-base/SAMLEngine.java.svn-base b/id/server/stork2-saml-engine/src/main/java/eu/stork/peps/auth/engine/.svn/text-base/SAMLEngine.java.svn-base new file mode 100644 index 000000000..f8f50fc74 --- /dev/null +++ b/id/server/stork2-saml-engine/src/main/java/eu/stork/peps/auth/engine/.svn/text-base/SAMLEngine.java.svn-base @@ -0,0 +1,409 @@ +/* + * 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/european-union-public-licence-eupl-v.1.1 + * + * 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. + */ + +package eu.stork.peps.auth.engine; + +import java.io.ByteArrayInputStream; +import java.io.StringWriter; +import java.io.UnsupportedEncodingException; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; + +import javax.xml.XMLConstants; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerConfigurationException; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + +import org.opensaml.Configuration; +import org.opensaml.DefaultBootstrap; +import org.opensaml.common.SAMLObject; +import org.opensaml.common.SignableSAMLObject; +import org.opensaml.xml.ConfigurationException; +import org.opensaml.xml.XMLObject; +import org.opensaml.xml.io.Marshaller; +import org.opensaml.xml.io.MarshallerFactory; +import org.opensaml.xml.io.MarshallingException; +import org.opensaml.xml.io.Unmarshaller; +import org.opensaml.xml.io.UnmarshallerFactory; +import org.opensaml.xml.io.UnmarshallingException; +import org.opensaml.xml.parse.BasicParserPool; +import org.opensaml.xml.parse.XMLParserException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import eu.stork.peps.auth.engine.core.SAMLEngineSignI; +import eu.stork.peps.auth.engine.core.STORKSAMLCore; +import eu.stork.peps.auth.engine.core.impl.SignModuleFactory; +import eu.stork.peps.configuration.ConfigurationCreator; +import eu.stork.peps.configuration.ConfigurationReader; +import eu.stork.peps.configuration.InstanceEngine; +import eu.stork.peps.exceptions.SAMLEngineException; +import eu.stork.peps.exceptions.STORKSAMLEngineException; +import eu.stork.peps.exceptions.STORKSAMLEngineRuntimeException; + +/** + * Class that wraps the operations over SAML tokens, both generation and + * validation of SAML requests and SAML responses. Compliant with "OASIS Secure + * Assertion Markup Language (SAML) 2.0, May 2005", but taking into account + * STORK specific requirements. + * + * @author fjquevedo + * @author iinigo + */ + +public class SAMLEngine { + + /** The Document Builder Factory. */ + private static javax.xml.parsers.DocumentBuilderFactory dbf = null; + + /** The instance of every engine SAML. */ + private static Map instanceConfigs; + + /** The instances of SAML engine. */ + private static Map> instances; + + /** The logger. */ + private static final Logger LOG = LoggerFactory.getLogger(SAMLEngine.class + .getName()); + + /** The Constant MODULE_SIGN_CONF. */ + private static final String MODULE_SIGN_CONF = "SignatureConf"; + + /** The Constant SAML_ENGINE_SIGN_CLASS. */ + private static final String SAML_ENGINE_SIGN_CLASS = "class"; + + /** The Constant SAML_ENGINE_CONF. */ + private static final String SAML_ENGINE_CONF = "SamlEngineConf"; + + /** The Constant SAML_ENGINE_FILE_CONF. */ + private static final String SAML_ENGINE_FILE_CONF = "fileConfiguration"; + + /** The codification of characters. */ + private static final String CHARACTER_ENCODING = "UTF-8"; + + /** The SAML core. */ + private STORKSAMLCore samlCore; + + /** The Module of Signature. */ + private SAMLEngineSignI signer; + + + /** Initializes the SAML engine. */ + /** Configure Document Builder Factory. */ + + static { + startUp(); + loadDocumentFactory(); + } + + /** + * Load document factory. + */ + private static void loadDocumentFactory() { + + try { + dbf = javax.xml.parsers.DocumentBuilderFactory.newInstance(); + dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); + dbf.setNamespaceAware(true); + dbf.setIgnoringComments(true); + } catch (ParserConfigurationException e) { + LOG.error("Error parser configuration."); + throw new STORKSAMLEngineRuntimeException(e); + } + + } + + /** + * Method that initializes the basic services for the SAML Engine, like the + * OpenSAML library and the BouncyCastle provider. + */ + private static void startUp() { + + LOG.info("SAMLEngine: Initialize OpenSAML"); + + try { + DefaultBootstrap.bootstrap(); + } catch (ConfigurationException e) { + LOG.error("Problem initializing the OpenSAML library."); + throw new STORKSAMLEngineRuntimeException(e); + } + + LOG.debug("Read all file configurations. (instances of SAMLEngine)"); + try { + instanceConfigs = ConfigurationReader.readConfiguration(); + } catch (SAMLEngineException e) { + LOG.error("Error read configuration file."); + throw new STORKSAMLEngineRuntimeException(e); + } + + LOG.debug("Create all instaces of saml engine. (instances of SAMLEngine)"); + try { + instances = ConfigurationCreator + .createConfiguration(instanceConfigs); + } catch (STORKSAMLEngineException e) { + LOG.error("Error initializing instances from Stork SAML engine."); + throw new STORKSAMLEngineRuntimeException(e); + } + } + + /** + * Instantiates a new SAML engine. + */ + private SAMLEngine() { + + } + + /** + * Instantiates a new SAML engine. + * + * @param nameInstance the name instance + * + * @throws STORKSAMLEngineException the STORKSAML engine exception + */ + protected SAMLEngine(final String nameInstance) + throws STORKSAMLEngineException { + LOG.info("Loading Specific Configuration."); + + LOG.debug("Create intance of saml messages."); + + Map instance = instances.get(nameInstance); + + if (instance == null || instance.isEmpty()) { + LOG.error("Instance: " + nameInstance + " not exist."); + throw new STORKSAMLEngineException("Instance: " + nameInstance + + " not exist."); + } + + Properties properties = (Properties) instance.get(SAML_ENGINE_CONF); + + if (properties == null) { + LOG.error("SamlEngine.xml: not exist."); + throw new STORKSAMLEngineException("SamlEngine.xml: not exist."); + } + + samlCore = new STORKSAMLCore(properties); + + final HashMap propertiesSign = (HashMap) instance + .get(MODULE_SIGN_CONF); + + LOG.debug("Loading Module of sign."); + signer = SignModuleFactory.getInstance(propertiesSign + .get(SAML_ENGINE_SIGN_CLASS)); + + try { + LOG.info("Initialize module of sign."); + signer.init(propertiesSign.get(SAML_ENGINE_FILE_CONF)); + LOG.info("Load cryptographic service provider of module of sign."); + signer.loadCryptServiceProvider(); + } catch (SAMLEngineException e) { + LOG.error("Error create signature module: " + + propertiesSign.get(SAML_ENGINE_FILE_CONF)); + LOG.info("Exception" + e); + throw new STORKSAMLEngineException(e); + } + } + + /** + * Gets the Signer properties. + * + * @return the SAML Sign properties + */ + protected SAMLEngineSignI getSigner() { + return signer; + } + + /** + * Gets the SAML core properties. + * + * @return the SAML core properties + */ + protected final STORKSAMLCore getSamlCoreProperties() { + return samlCore; + } + + /** + * Method that transform the received SAML object into a byte array + * representation. + * + * @param samlToken the SAML token. + * + * @return the byte[] of the SAML token. + * + * @throws SAMLEngineException the SAML engine exception + */ + private byte[] marshall(final XMLObject samlToken) + throws SAMLEngineException { + + try { + javax.xml.parsers.DocumentBuilder docBuilder = null; + + final MarshallerFactory marshallerFactory = Configuration + .getMarshallerFactory(); + + final Marshaller marshaller = marshallerFactory + .getMarshaller(samlToken); + + docBuilder = dbf.newDocumentBuilder(); + + final Document doc = docBuilder.newDocument(); + + marshaller.marshall(samlToken, doc); + + // Obtain a byte array representation of the marshalled SAML object + final DOMSource domSource = new DOMSource(doc); + final StringWriter writer = new StringWriter(); + final StreamResult result = new StreamResult(writer); + final TransformerFactory transFactory = TransformerFactory + .newInstance(); + Transformer transformer; + + transformer = transFactory.newTransformer(); + transformer.transform(domSource, result); + LOG.debug("SAML request \n"+ writer.toString()); + return writer.toString().getBytes(CHARACTER_ENCODING); + + } catch (ParserConfigurationException e) { + LOG.error("ParserConfigurationException."); + throw new SAMLEngineException(e); + } catch (MarshallingException e) { + LOG.error("MarshallingException."); + throw new SAMLEngineException(e); + } catch (TransformerConfigurationException e) { + LOG.error("TransformerConfigurationException."); + throw new SAMLEngineException(e); + } catch (TransformerException e) { + LOG.error("TransformerException."); + throw new SAMLEngineException(e); + } catch (UnsupportedEncodingException e) { + LOG.error("UnsupportedEncodingException: " + CHARACTER_ENCODING); + throw new SAMLEngineException(e); + } + } + + /** + * Method that signs a SAML Token. + * + * @param tokenSaml the token SAML + * + * @return the SAML object sign + * + * @throws SAMLEngineException the SAML engine exception + */ + private SignableSAMLObject sign(final SignableSAMLObject tokenSaml) + throws SAMLEngineException { + LOG.debug("Sign SamlToken."); + signer.sign(tokenSaml); + return tokenSaml; + } + + /** + * Sign and transform to byte array. + * + * @param samlToken the SAML token + * + * @return the byte[] of the SAML token + * + * @throws SAMLEngineException the SAML engine exception + */ + protected final byte[] signAndMarshall(final SignableSAMLObject samlToken) + throws SAMLEngineException { + LOG.debug("Marshall Saml Token."); + SignableSAMLObject signElement = sign(samlToken); + return marshall(signElement); + } + + /** + * Method that unmarshalls a SAML Object from a byte array representation to + * an XML Object. + * + * @param samlToken Byte array representation of a SAML Object + * + * @return XML Object (superclass of SAMLObject) + * + * @throws SAMLEngineException the SAML engine exception + */ + protected final XMLObject unmarshall(final byte[] samlToken) + throws SAMLEngineException { + try { + // Get parser pool manager + final BasicParserPool ppMgr = new BasicParserPool(); + // Note: this is necessary due to an unresolved Xerces deferred DOM + // issue/bug + final HashMap features = new HashMap(); + features.put(XMLConstants.FEATURE_SECURE_PROCESSING, Boolean.TRUE); + ppMgr.setBuilderFeatures(features); + + ppMgr.setNamespaceAware(true); + + // Parse SAMLToken + Document document = ppMgr.parse(new ByteArrayInputStream(samlToken)); + if (document != null){ + final Element root = document.getDocumentElement(); + // Get appropriate unmarshaller + final UnmarshallerFactory unmarshallerFact = Configuration.getUnmarshallerFactory(); + // Unmarshall using the SAML Token root element + if (unmarshallerFact != null && root != null){ + final Unmarshaller unmarshaller = unmarshallerFact.getUnmarshaller(root); + try { + return unmarshaller.unmarshall(root); + } catch (NullPointerException e){ + LOG.error("Error element tag incomplet or null."); + throw new SAMLEngineException("NullPointerException", e); + } + } else { + LOG.error("Error element tag incomplet or null."); + throw new SAMLEngineException("NullPointerException : unmarshallerFact or root is null"); + } + } else { + LOG.error("Error element tag incomplet or null."); + throw new SAMLEngineException("NullPointerException : document is null"); + } + } catch (XMLParserException e) { + LOG.error("XML Parsing Error.", e); + throw new SAMLEngineException(e); + } catch (UnmarshallingException e) { + LOG.error("TransformerException.", e); + throw new SAMLEngineException(e); + } catch (NullPointerException e) { + LOG.error("Error element tag incomplet or null.", e); + throw new SAMLEngineException(e); + } + } + + /** + * Method that validates an XML Signature contained in a SAML Token. + * + * @param samlToken the SAML token + * + * @return the SAML object + * + * @throws SAMLEngineException the SAML engine exception + */ + protected final SAMLObject validateSignature( + final SignableSAMLObject samlToken) throws SAMLEngineException { + + LOG.info("Validate Signature"); + signer.validateSignature(samlToken); + + return samlToken; + } +} diff --git a/id/server/stork2-saml-engine/src/main/java/eu/stork/peps/auth/engine/.svn/text-base/SAMLEngineUtils.java.svn-base b/id/server/stork2-saml-engine/src/main/java/eu/stork/peps/auth/engine/.svn/text-base/SAMLEngineUtils.java.svn-base new file mode 100644 index 000000000..60f7c3091 --- /dev/null +++ b/id/server/stork2-saml-engine/src/main/java/eu/stork/peps/auth/engine/.svn/text-base/SAMLEngineUtils.java.svn-base @@ -0,0 +1,833 @@ +/* + * 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/european-union-public-licence-eupl-v.1.1 + * + * 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. + */ + +package eu.stork.peps.auth.engine; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import javax.xml.namespace.QName; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +import org.apache.commons.lang.StringUtils; +import org.joda.time.DateTime; +import org.opensaml.Configuration; +import org.opensaml.common.SAMLVersion; +import org.opensaml.common.impl.SecureRandomIdentifierGenerator; +import org.opensaml.saml2.common.Extensions; +import org.opensaml.saml2.common.impl.ExtensionsBuilder; +import org.opensaml.saml2.core.Assertion; +import org.opensaml.saml2.core.Attribute; +import org.opensaml.saml2.core.AttributeQuery; +import org.opensaml.saml2.core.AttributeValue; +import org.opensaml.saml2.core.AuthnContext; +import org.opensaml.saml2.core.AuthnRequest; +import org.opensaml.saml2.core.AuthnStatement; +import org.opensaml.saml2.core.Issuer; +import org.opensaml.saml2.core.NameID; +import org.opensaml.saml2.core.Response; +import org.opensaml.saml2.core.Status; +import org.opensaml.saml2.core.StatusCode; +import org.opensaml.saml2.core.StatusMessage; +import org.opensaml.saml2.core.Subject; +import org.opensaml.saml2.core.SubjectConfirmation; +import org.opensaml.saml2.core.SubjectConfirmationData; +import org.opensaml.saml2.core.SubjectLocality; +import org.opensaml.saml2.core.impl.AssertionBuilder; +import org.opensaml.xml.XMLObject; +import org.opensaml.xml.schema.XSAny; +import org.opensaml.xml.schema.XSString; +import org.opensaml.xml.signature.KeyInfo; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.xml.sax.SAXException; + +import eu.stork.peps.auth.engine.core.QAAAttribute; +import eu.stork.peps.auth.engine.core.RequestedAttribute; +import eu.stork.peps.auth.engine.core.SAMLCore; +import eu.stork.peps.auth.engine.core.SPApplication; +import eu.stork.peps.auth.engine.core.SPCountry; +import eu.stork.peps.auth.engine.core.SPInstitution; +import eu.stork.peps.auth.engine.core.SPSector; +import eu.stork.peps.exceptions.STORKSAMLEngineException; +import eu.stork.peps.exceptions.STORKSAMLEngineRuntimeException; + +/** + * The Class SAMLEngineUtils. + * + * @author fjquevedo + * @author iinigo + */ +public final class SAMLEngineUtils { + + /** The Constant UTF_8. */ + public static final String UTF_8 = "UTF-8"; + + /** The Constant SHA_512. */ + public static final String SHA_512 = "SHA-512"; + + + /** The generator. */ + private static SecureRandomIdentifierGenerator generator; + + /** The Constant LOG. */ + private static final Logger LOG = LoggerFactory + .getLogger(SAMLEngineUtils.class.getName()); + + /** + * Method that generates a random value according to NCName grammar. + * + * NCName ::= NCNameStartChar NCNameChar* NCNameChar ::= NameChar - ':' + * NCNameStartChar ::= Letter | '_' NameStartChar ::= ":" | [A-Z] | "_" | + * [a-z] | [#xC0-#xD6] | [#xD8-#xF6] | [#xF8-#x2FF] | [#x370-#x37D] | + * [#x37F-#x1FFF] | [#x200C-#x200D] | [#x2070-#x218F] | [#x2C00-#x2FEF] | + * [#x3001-#xD7FF] | [#xF900-#xFDCF] | [#xFDF0-#xFFFD] | [#x10000-#xEFFFF] + * NameChar ::= NameStartChar | "-" | "." | [0-9] | #xB7 | [#x0300-#x036F] | + * [#x203F-#x2040] Name ::= NameStartChar (NameChar)* Letter ::= BaseChar | + * Ideographic BaseChar ::= [#x0041-#x005A] | [#x0061-#x007A] | + * [#x00C0-#x00D6] | [#x00D8-#x00F6] | [#x00F8-#x00FF] | [#x0100-#x0131] | + * [#x0134-#x013E] | [#x0141-#x0148] | [#x014A-#x017E] | [#x0180-#x01C3] | + * [#x01CD-#x01F0] | [#x01F4-#x01F5] | [#x01FA-#x0217] | [#x0250-#x02A8] | + * [#x02BB-#x02C1] | #x0386 | [#x0388-#x038A] | #x038C | [#x038E-#x03A1] | + * [#x03A3-#x03CE] | [#x03D0-#x03D6] | #x03DA | #x03DC | #x03DE | #x03E0 | + * [#x03E2-#x03F3] | [#x0401-#x040C] | [#x040E-#x044F] | [#x0451-#x045C] | + * [#x045E-#x0481] | [#x0490-#x04C4] | [#x04C7-#x04C8] | [#x04CB-#x04CC] | + * [#x04D0-#x04EB] | [#x04EE-#x04F5] | [#x04F8-#x04F9] | [#x0531-#x0556] | + * #x0559 | [#x0561-#x0586] | [#x05D0-#x05EA] | [#x05F0-#x05F2] | + * [#x0621-#x063A] | [#x0641-#x064A] | [#x0671-#x06B7] | [#x06BA-#x06BE] | + * [#x06C0-#x06CE] | [#x06D0-#x06D3] | #x06D5 | [#x06E5-#x06E6] | + * [#x0905-#x0939] | #x093D | [#x0958-#x0961] | [#x0985-#x098C] | + * [#x098F-#x0990] | [#x0993-#x09A8] | [#x09AA-#x09B0] | #x09B2 | + * [#x09B6-#x09B9] | [#x09DC-#x09DD] | [#x09DF-#x09E1] | [#x09F0-#x09F1] | + * [#x0A05-#x0A0A] | [#x0A0F-#x0A10] | [#x0A13-#x0A28] | [#x0A2A-#x0A30] | + * [#x0A32-#x0A33] | [#x0A35-#x0A36] | [#x0A38-#x0A39] | [#x0A59-#x0A5C] | + * #x0A5E | [#x0A72-#x0A74] | [#x0A85-#x0A8B] | #x0A8D | [#x0A8F-#x0A91] | + * [#x0A93-#x0AA8] | [#x0AAA-#x0AB0] | [#x0AB2-#x0AB3] | [#x0AB5-#x0AB9] | + * #x0ABD | #x0AE0 | [#x0B05-#x0B0C] | [#x0B0F-#x0B10] | [#x0B13-#x0B28] | + * [#x0B2A-#x0B30] | [#x0B32-#x0B33] | [#x0B36-#x0B39] | #x0B3D | + * [#x0B5C-#x0B5D] | [#x0B5F-#x0B61] | [#x0B85-#x0B8A] | [#x0B8E-#x0B90] | + * [#x0B92-#x0B95] | [#x0B99-#x0B9A] | #x0B9C | [#x0B9E-#x0B9F] | + * [#x0BA3-#x0BA4] | [#x0BA8-#x0BAA] | [#x0BAE-#x0BB5] | [#x0BB7-#x0BB9] | + * [#x0C05-#x0C0C] | [#x0C0E-#x0C10] | [#x0C12-#x0C28] | [#x0C2A-#x0C33] | + * [#x0C35-#x0C39] | [#x0C60-#x0C61] | [#x0C85-#x0C8C] | [#x0C8E-#x0C90] | + * [#x0C92-#x0CA8] | [#x0CAA-#x0CB3] | [#x0CB5-#x0CB9] | #x0CDE | + * [#x0CE0-#x0CE1] | [#x0D05-#x0D0C] | [#x0D0E-#x0D10] | [#x0D12-#x0D28] | + * [#x0D2A-#x0D39] | [#x0D60-#x0D61] | [#x0E01-#x0E2E] | #x0E30 | + * [#x0E32-#x0E33] | [#x0E40-#x0E45] | [#x0E81-#x0E82] | #x0E84 | + * [#x0E87-#x0E88] | #x0E8A | #x0E8D | [#x0E94-#x0E97] | [#x0E99-#x0E9F] | + * [#x0EA1-#x0EA3] | #x0EA5 | #x0EA7 | [#x0EAA-#x0EAB] | [#x0EAD-#x0EAE] | + * #x0EB0 | [#x0EB2-#x0EB3] | #x0EBD | [#x0EC0-#x0EC4] | [#x0F40-#x0F47] | + * [#x0F49-#x0F69] | [#x10A0-#x10C5] | [#x10D0-#x10F6] | #x1100 | + * [#x1102-#x1103] | [#x1105-#x1107] | #x1109 | [#x110B-#x110C] | + * [#x110E-#x1112] | #x113C | #x113E | #x1140 | #x114C | #x114E | #x1150 | + * [#x1154-#x1155] | #x1159 | [#x115F-#x1161] | #x1163 | #x1165 | #x1167 | + * #x1169 | [#x116D-#x116E] | [#x1172-#x1173] | #x1175 | #x119E | #x11A8 | + * #x11AB | [#x11AE-#x11AF] | [#x11B7-#x11B8] | #x11BA | [#x11BC-#x11C2] | + * #x11EB | #x11F0 | #x11F9 | [#x1E00-#x1E9B] | [#x1EA0-#x1EF9] | + * [#x1F00-#x1F15] | [#x1F18-#x1F1D] | [#x1F20-#x1F45] | [#x1F48-#x1F4D] | + * [#x1F50-#x1F57] | #x1F59 | #x1F5B | #x1F5D | [#x1F5F-#x1F7D] | + * [#x1F80-#x1FB4] | [#x1FB6-#x1FBC] | #x1FBE | [#x1FC2-#x1FC4] | + * [#x1FC6-#x1FCC] | [#x1FD0-#x1FD3] | [#x1FD6-#x1FDB] | [#x1FE0-#x1FEC] | + * [#x1FF2-#x1FF4] | [#x1FF6-#x1FFC] | #x2126 | [#x212A-#x212B] | #x212E | + * [#x2180-#x2182] | [#x3041-#x3094] | [#x30A1-#x30FA] | [#x3105-#x312C] | + * [#xAC00-#xD7A3] Ideographic ::= [#x4E00-#x9FA5] | #x3007 | + * [#x3021-#x3029] + * + * @return Random ID value + */ + + //Initialization of a generator of identifiers for all token SAML. + + static { + loadRandomIdentifierGenerator(); + } + + + /** + * Load random identifier generator. + * + *@throws STORKSAMLEngineRuntimeException the STORKSAML engine runtime exception + */ + private static void loadRandomIdentifierGenerator() { + + try { + generator = new SecureRandomIdentifierGenerator(); + } catch (NoSuchAlgorithmException ex) { + LOG.error("Error init SecureRandomIdentifierGenerator", ex); + throw new STORKSAMLEngineRuntimeException(ex); + } + + } + + /** + * Creates the SAML object. + * + * @param qname the QName + * + * @return the XML object + */ + public static XMLObject createSamlObject(final QName qname) { + return Configuration.getBuilderFactory().getBuilder(qname).buildObject( + qname); + } + + /** + * Creates the SAML object. + * + * @param qname the quality name + * @param qname1 the qname1 + * + * @return the xML object + */ + public static XMLObject createSamlObject(final QName qname, + final QName qname1) { + return Configuration.getBuilderFactory().getBuilder(qname1) + .buildObject(qname, qname1); + } + + /** + * Encode value with an specific algorithm. + * + * @param value the value + * @param alg the algorithm + * + * @return the string + * + * @throws STORKSAMLEngineException the STORKSAML engine exception + */ + public static String encode(final String value, final String alg) + throws STORKSAMLEngineException { + LOG.debug("Encode value with " + alg + " algorithm."); + byte[] buffer; + + final StringBuffer hash = new StringBuffer(""); + try { + buffer = value.getBytes(UTF_8); + MessageDigest msgDig; + msgDig = MessageDigest.getInstance(alg); + + + msgDig.update(buffer); + final byte[] digest = msgDig.digest(); + + final int signedByte = 0xff; + for (byte aux : digest) { + final int byt = aux & signedByte; + if (Integer.toHexString(byt).length() == 1) { + hash.append('0'); + } + hash.append(Integer.toHexString(byt)); + } + + } catch (UnsupportedEncodingException e1) { + LOG.error("UnsupportedEncodingException: " + UTF_8); + throw new STORKSAMLEngineException(e1); + } catch (NoSuchAlgorithmException e) { + LOG.error("NoSuchAlgorithmException: " + alg); + throw new STORKSAMLEngineException(e); + } + + return hash.toString(); + } + + /** + * Generate assertion. + * + * @param version the version + * @param identifier the identifier + * @param issueInstant the issue instant + * @param issuer the issuer + * + * @return the assertion + */ + public static Assertion generateAssertion(final SAMLVersion version, + final String identifier, final DateTime issueInstant, + final Issuer issuer) { + final AssertionBuilder assertionBuilder = new AssertionBuilder(); + final Assertion assertion = assertionBuilder.buildObject(); + assertion.setVersion(version); + assertion.setID(identifier); + assertion.setIssueInstant(issueInstant); + + // + assertion.setIssuer(issuer); + return assertion; + } + + /** + * Generate authentication statement. + * + * @param authnInstant the authentication instant + * @param authnContext the authentication context + * + * @return the authentication statement + */ + public static AuthnStatement generateAthnStatement(final DateTime authnInstant, + final AuthnContext authnContext) { + // + final AuthnStatement authnStatement = (AuthnStatement) SAMLEngineUtils + .createSamlObject(AuthnStatement.DEFAULT_ELEMENT_NAME); + + authnStatement.setAuthnInstant(authnInstant); + authnStatement.setAuthnContext(authnContext); + + return authnStatement; + } + + + + + + /** + * Generate attribute from a list of values. + * + * @param name the name of the attribute. + * @param status the status of the parameter: "Available", "NotAvailable" or + * "Withheld". + * @param values the value of the attribute. + * @param isHashing the is hashing with "SHA-512" algorithm. + * @return the attribute + * @throws STORKSAMLEngineException the STORKSAML engine exception + */ + public static Attribute generateAttrComplex(final String name, + final String status, final Map values, + final boolean isHashing) throws STORKSAMLEngineException { + LOG.debug("Generate attribute complex: " + name); + final Attribute attribute = (Attribute) SAMLEngineUtils + .createSamlObject(Attribute.DEFAULT_ELEMENT_NAME); + + attribute.setName(name); + attribute.setNameFormat(Attribute.URI_REFERENCE); + + attribute.getUnknownAttributes().put( + new QName(SAMLCore.STORK10_NS.getValue(), "AttributeStatus", + SAMLCore.STORK10_PREFIX.getValue()), status); + + if (!values.isEmpty()) { + LOG.debug("Add attribute values."); + + // Create an attribute that contains all XSAny elements. + final XSAny attrValue = (XSAny) SAMLEngineUtils.createSamlObject( + AttributeValue.DEFAULT_ELEMENT_NAME, XSAny.TYPE_NAME); + + final Iterator> iterator = values.entrySet() + .iterator(); + while (iterator.hasNext()) { + final Map.Entry pairs = iterator.next(); + + final String value = pairs.getValue(); + + if (StringUtils.isNotBlank(value)) { + // Create the attribute statement + final XSAny attrValueSimple = (XSAny) SAMLEngineUtils + .createSamlObject(new QName(SAMLCore.STORK10_NS.getValue(), + pairs.getKey().toString(), + SAMLCore.STORK10_PREFIX.getValue()), XSAny.TYPE_NAME); + + // if it's necessary encode the information. + if (isHashing) { + attrValueSimple + .setTextContent(encode(value, SHA_512)); + } else { + attrValueSimple.setTextContent(value); + } + + attrValue.getUnknownXMLObjects().add(attrValueSimple); + attribute.getAttributeValues().add(attrValue); + } + } + + } + return attribute; + } + + /** + * Generate extension. + * + * @return the extensions + */ + public static Extensions generateExtension() { + final ExtensionsBuilder extensionsBuilder = new ExtensionsBuilder(); + return extensionsBuilder.buildObject( + "urn:oasis:names:tc:SAML:2.0:protocol", "Extensions", "saml2p"); + } + + + + + /** + * Generate issuer. + * + * @return the issuer + */ + public static Issuer generateIssuer() { + return (Issuer) SAMLEngineUtils + .createSamlObject(Issuer.DEFAULT_ELEMENT_NAME); + } + + /** + * Generate key info. + * + * @return the key info + */ + public static KeyInfo generateKeyInfo() { + return (KeyInfo) SAMLEngineUtils + .createSamlObject(KeyInfo.DEFAULT_ELEMENT_NAME); + } + + /** + * Generate name id. + * + * @return the name id + */ + public static NameID generateNameID() { + return (NameID) SAMLEngineUtils + .createSamlObject(NameID.DEFAULT_ELEMENT_NAME); + } + + /** + * Generate name id. + * + * @param nameQualifier the name qualifier + * @param format the format + * @param spNameQualifier the sP name qualifier + * + * @return the name id + */ + public static NameID generateNameID(final String nameQualifier, + final String format, final String spNameQualifier) { + // + final NameID nameId = (NameID) Configuration.getBuilderFactory() + .getBuilder(NameID.DEFAULT_ELEMENT_NAME).buildObject( + NameID.DEFAULT_ELEMENT_NAME); + + // optional + nameId.setNameQualifier(nameQualifier); + + // optional + nameId.setFormat(format); + + // optional + nameId.setSPNameQualifier(spNameQualifier); + + return nameId; + } + + /** + * Generate NCName. + * + * @return the string + */ + public static String generateNCName() { + return generator.generateIdentifier(); + } + + + /** + * Generate the quality authentication assurance level. + * + * @param qaal the level of quality authentication assurance. + * + * @return the quality authentication assurance attribute + * + * @throws STORKSAMLEngineException the STORKSAML engine exception + */ + public static QAAAttribute generateQAAAttribute(final int qaal) + throws STORKSAMLEngineException { + LOG.debug("Generate QAAAttribute."); + + final QAAAttribute qaaAttribute = (QAAAttribute) SAMLEngineUtils + .createSamlObject(QAAAttribute.DEF_ELEMENT_NAME); + qaaAttribute.setQaaLevel(String.valueOf(qaal)); + return qaaAttribute; + } + + /** + * Generate requested attribute. + * + * @param name the name + * @param friendlyName the friendly name + * @param isRequired the is required + * @param value the value + * + * @return the requested attribute + */ + public static RequestedAttribute generateReqAuthnAttributeSimple( + final String name, final String friendlyName, + final String isRequired, final List value) { + LOG.debug("Generate the requested attribute."); + + final RequestedAttribute requested = (RequestedAttribute) SAMLEngineUtils + .createSamlObject(RequestedAttribute.DEF_ELEMENT_NAME); + requested.setName(name); + requested.setNameFormat(RequestedAttribute.URI_REFERENCE); + + requested.setFriendlyName(friendlyName); + + requested.setIsRequired(isRequired); + + // The value is optional in an authentication request. + if (!value.isEmpty()) { + for (int nextValue = 0; nextValue < value.size(); nextValue++) { + final String valor = value.get(nextValue); + if (StringUtils.isNotBlank(valor)) { + + if(!name.equals("http://www.stork.gov.eu/1.0/signedDoc")){ + + // Create the attribute statement + final XSAny attrValue = (XSAny) SAMLEngineUtils + .createSamlObject( + new QName(SAMLCore.STORK10_NS.getValue(), + "AttributeValue", + SAMLCore.STORK10_PREFIX.getValue()), + XSAny.TYPE_NAME); + + attrValue.setTextContent(valor.trim()); + requested.getAttributeValues().add(attrValue); + + }else{ + + DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance(); + domFactory.setNamespaceAware(true); + Document document = null; + DocumentBuilder builder; + + // Parse the signedDoc value into an XML DOM Document + try { + builder = domFactory.newDocumentBuilder(); + InputStream is; + is = new ByteArrayInputStream(valor.trim().getBytes("UTF-8")); + document = builder.parse(is); + is.close(); + } catch (SAXException e1) { + LOG.error("SAX Error while parsing signModule attribute", e1); + throw new STORKSAMLEngineRuntimeException(e1); + } catch (ParserConfigurationException e2) { + LOG.error("Parser Configuration Error while parsing signModule attribute", e2); + throw new STORKSAMLEngineRuntimeException(e2); + } catch (UnsupportedEncodingException e3) { + LOG.error("Unsupported encoding Error while parsing signModule attribute", e3); + throw new STORKSAMLEngineRuntimeException(e3); + } catch (IOException e4) { + LOG.error("IO Error while parsing signModule attribute", e4); + throw new STORKSAMLEngineRuntimeException(e4); + } + + // Create the XML statement(this will be overwritten with the previous DOM structure) + final XSAny xmlValue = (XSAny) SAMLEngineUtils + .createSamlObject( + new QName(SAMLCore.STORK10_NS.getValue(), + "XMLValue", + SAMLCore.STORK10_PREFIX.getValue()), + XSAny.TYPE_NAME); + + //Set the signedDoc XML content to this element + xmlValue.setDOM(document.getDocumentElement()); + + // Create the attribute statement + final XSAny attrValue = (XSAny) SAMLEngineUtils + .createSamlObject( + new QName(SAMLCore.STORK10_NS.getValue(), + "AttributeValue", + SAMLCore.STORK10_PREFIX.getValue()), + XSAny.TYPE_NAME); + + //Add previous signedDocXML to the AttributeValue Element + attrValue.getUnknownXMLObjects().add(xmlValue); + + requested.getAttributeValues().add(attrValue); + } + + + } + } + } + + return requested; + } + + /** + * Generate response. + * + * @param version the version + * @param identifier the identifier + * @param issueInstant the issue instant + * @param status the status + * + * @return the response + */ + public static Response generateResponse(final SAMLVersion version, + final String identifier, final DateTime issueInstant, + final Status status) { + final Response response = (Response) SAMLEngineUtils + .createSamlObject(Response.DEFAULT_ELEMENT_NAME); + response.setID(identifier); + response.setIssueInstant(issueInstant); + response.setStatus(status); + return response; + } + + /** + * Method that generates a SAML Authentication Request basing on the + * provided information. + * + * @param identifier the identifier + * @param version the version + * @param issueInstant the issue instant + * + * @return the authentication request + */ + public static AuthnRequest generateSAMLAuthnRequest(final String identifier, + final SAMLVersion version, final DateTime issueInstant) { + LOG.debug("Generate basic authentication request."); + final AuthnRequest authnRequest = (AuthnRequest) SAMLEngineUtils + .createSamlObject(AuthnRequest.DEFAULT_ELEMENT_NAME); + + authnRequest.setID(identifier); + authnRequest.setVersion(version); + authnRequest.setIssueInstant(issueInstant); + return authnRequest; + } + + public static AttributeQuery generateSAMLAttrQueryRequest(final String identifier, + final SAMLVersion version, final DateTime issueInstant) { + LOG.debug("Generate attribute query request."); + final AttributeQuery attrQueryRequest = (AttributeQuery) SAMLEngineUtils + .createSamlObject(AttributeQuery.DEFAULT_ELEMENT_NAME); + + attrQueryRequest.setID(identifier); + attrQueryRequest.setVersion(version); + attrQueryRequest.setIssueInstant(issueInstant); + return attrQueryRequest; + } + + /** + * Generate service provider application. + * + * @param spApplication the service provider application + * + * @return the sP application + * + * @throws STORKSAMLEngineException the STORKSAML engine exception + */ + public static SPApplication generateSPApplication(final String spApplication) + throws STORKSAMLEngineException { + LOG.debug("Generate SPApplication."); + + final SPApplication applicationAttr = (SPApplication) SAMLEngineUtils + .createSamlObject(SPApplication.DEF_ELEMENT_NAME); + applicationAttr.setSPApplication(spApplication); + return applicationAttr; + } + + /** + * Generate service provider country. + * + * @param spCountry the service provider country + * + * @return the service provider country + * + * @throws STORKSAMLEngineException the STORKSAML engine exception + */ + public static SPCountry generateSPCountry(final String spCountry) + throws STORKSAMLEngineException { + LOG.debug("Generate SPApplication."); + + final SPCountry countryAttribute = (SPCountry) SAMLEngineUtils + .createSamlObject(SPCountry.DEF_ELEMENT_NAME); + countryAttribute.setSPCountry(spCountry); + return countryAttribute; + } + + /** + * Generate service provider institution. + * + * @param spInstitution the service provider institution + * + * @return the service provider institution + * + * @throws STORKSAMLEngineException the STORKSAML engine exception + */ + public static SPInstitution generateSPInstitution(final String spInstitution) + throws STORKSAMLEngineException { + LOG.debug("Generate SPInstitution."); + + final SPInstitution institutionAttr = (SPInstitution) SAMLEngineUtils + .createSamlObject(SPInstitution.DEF_ELEMENT_NAME); + institutionAttr.setSPInstitution(spInstitution); + return institutionAttr; + } + + /** + * Generate service provider sector. + * + * @param spSector the service provider sector + * + * @return the service provider sector + * + * @throws STORKSAMLEngineException the STORKSAML engine exception + */ + public static SPSector generateSPSector(final String spSector) + throws STORKSAMLEngineException { + LOG.debug("Generate SPSector."); + + final SPSector sectorAttribute = (SPSector) SAMLEngineUtils + .createSamlObject(SPSector.DEF_ELEMENT_NAME); + sectorAttribute.setSPSector(spSector); + return sectorAttribute; + } + + /** + * Generate status. + * + * @param statusCode the status code + * + * @return the status + */ + public static Status generateStatus(final StatusCode statusCode) { + final Status status = (Status) SAMLEngineUtils + .createSamlObject(Status.DEFAULT_ELEMENT_NAME); + status.setStatusCode(statusCode); + return status; + } + + /** + * Generate status code. + * + * @param value the value + * + * @return the status code + */ + public static StatusCode generateStatusCode(final String value) { + final StatusCode statusCode = (StatusCode) SAMLEngineUtils + .createSamlObject(StatusCode.DEFAULT_ELEMENT_NAME); + statusCode.setValue(value); + return statusCode; + } + + + /** + * Generate status message. + * + * @param message the message + * + * @return the status message + */ + public static StatusMessage generateStatusMessage(final String message) { + final StatusMessage statusMessage = (StatusMessage) SAMLEngineUtils + .createSamlObject(StatusMessage.DEFAULT_ELEMENT_NAME); + statusMessage.setMessage(message); + return statusMessage; + } + + /** + * Generate subject. + * + * @return the subject + */ + public static Subject generateSubject() { + return (Subject) SAMLEngineUtils + .createSamlObject(Subject.DEFAULT_ELEMENT_NAME); + } + + /** + * Generate subject confirmation. + * + * @param method the method + * @param data the data + * + * @return the subject confirmation + */ + public static SubjectConfirmation generateSubjectConfirmation( + final String method, final SubjectConfirmationData data) { + final SubjectConfirmation subjectConf = (SubjectConfirmation) Configuration + .getBuilderFactory().getBuilder( + SubjectConfirmation.DEFAULT_ELEMENT_NAME).buildObject( + SubjectConfirmation.DEFAULT_ELEMENT_NAME); + + subjectConf.setMethod(method); + + subjectConf.setSubjectConfirmationData(data); + + return subjectConf; + } + + + /** + * Generate subject confirmation data. + * + * @param notOnOrAfter the not on or after + * @param recipient the recipient + * @param inResponseTo the in response to + * + * @return the subject confirmation data + */ + public static SubjectConfirmationData generateSubjectConfirmationData( + final DateTime notOnOrAfter, final String recipient, + final String inResponseTo) { + final SubjectConfirmationData subjectConfData = (SubjectConfirmationData) SAMLEngineUtils + .createSamlObject(SubjectConfirmationData.DEFAULT_ELEMENT_NAME); + subjectConfData.setNotOnOrAfter(notOnOrAfter); + subjectConfData.setRecipient(recipient); + subjectConfData.setInResponseTo(inResponseTo); + return subjectConfData; + } + + + /** + * Generate subject locality. + * + * @param address the address + * + * @return the subject locality + */ + public static SubjectLocality generateSubjectLocality(final String address) { + final SubjectLocality subjectLocality = (SubjectLocality) SAMLEngineUtils + .createSamlObject(SubjectLocality.DEFAULT_ELEMENT_NAME); + subjectLocality.setAddress(address); + return subjectLocality; + } + + + + + /** + * Method that returns the current time. + * + * @return the current time + */ + public static DateTime getCurrentTime() { + return new DateTime(); + } + + + /** + * Instantiates a new SAML engine utilities. + */ + private SAMLEngineUtils() { + } + +} diff --git a/id/server/stork2-saml-engine/src/main/java/eu/stork/peps/auth/engine/.svn/text-base/STORKSAMLEngine.java.svn-base b/id/server/stork2-saml-engine/src/main/java/eu/stork/peps/auth/engine/.svn/text-base/STORKSAMLEngine.java.svn-base new file mode 100644 index 000000000..3cac2f637 --- /dev/null +++ b/id/server/stork2-saml-engine/src/main/java/eu/stork/peps/auth/engine/.svn/text-base/STORKSAMLEngine.java.svn-base @@ -0,0 +1,2983 @@ +/* + * 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/european-union-public-licence-eupl-v.1.1 + * + * 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. + */ + +package eu.stork.peps.auth.engine; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.StringWriter; +import java.io.UnsupportedEncodingException; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; + +import javax.xml.namespace.QName; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.OutputKeys; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerConfigurationException; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + +import org.apache.commons.lang.StringUtils; +import org.bouncycastle.jce.X509Principal; +import org.joda.time.DateTime; +import org.opensaml.Configuration; +import org.opensaml.common.SAMLVersion; +import org.opensaml.common.SignableSAMLObject; +import org.opensaml.common.xml.SAMLConstants; +import org.opensaml.saml2.common.Extensions; +import org.opensaml.saml2.core.Assertion; +import org.opensaml.saml2.core.Attribute; +import org.opensaml.saml2.core.AttributeQuery; +import org.opensaml.saml2.core.AttributeStatement; +import org.opensaml.saml2.core.AttributeValue; +import org.opensaml.saml2.core.Audience; +import org.opensaml.saml2.core.AudienceRestriction; +import org.opensaml.saml2.core.AuthnContext; +import org.opensaml.saml2.core.AuthnContextDecl; +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.NameID; +import org.opensaml.saml2.core.OneTimeUse; +import org.opensaml.saml2.core.Response; +import org.opensaml.saml2.core.Status; +import org.opensaml.saml2.core.StatusCode; +import org.opensaml.saml2.core.StatusMessage; +import org.opensaml.saml2.core.Subject; +import org.opensaml.saml2.core.SubjectConfirmation; +import org.opensaml.saml2.core.SubjectConfirmationData; +import org.opensaml.saml2.core.SubjectLocality; +import org.opensaml.saml2.core.impl.SubjectConfirmationBuilder; +import org.opensaml.xml.Namespace; +import org.opensaml.xml.XMLObject; +import org.opensaml.xml.schema.XSAny; +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.XSStringImpl; +import org.opensaml.xml.signature.KeyInfo; +import org.opensaml.xml.util.Base64; +import org.opensaml.xml.validation.ValidationException; +import org.opensaml.xml.validation.Validator; +import org.opensaml.xml.validation.ValidatorSuite; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.xml.sax.SAXException; + +import eu.stork.peps.auth.commons.IPersonalAttributeList; +import eu.stork.peps.auth.commons.PersonalAttribute; +import eu.stork.peps.auth.commons.PersonalAttributeList; +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.engine.core.AuthenticationAttributes; +import eu.stork.peps.auth.engine.core.CitizenCountryCode; +import eu.stork.peps.auth.engine.core.EIDCrossBorderShare; +import eu.stork.peps.auth.engine.core.EIDCrossSectorShare; +import eu.stork.peps.auth.engine.core.EIDSectorShare; +import eu.stork.peps.auth.engine.core.QAAAttribute; +import eu.stork.peps.auth.engine.core.RequestedAttribute; +import eu.stork.peps.auth.engine.core.RequestedAttributes; +import eu.stork.peps.auth.engine.core.SAMLCore; +import eu.stork.peps.auth.engine.core.SPApplication; +import eu.stork.peps.auth.engine.core.SPCountry; +import eu.stork.peps.auth.engine.core.SPID; +import eu.stork.peps.auth.engine.core.SPInformation; +import eu.stork.peps.auth.engine.core.SPInstitution; +import eu.stork.peps.auth.engine.core.SPSector; +import eu.stork.peps.auth.engine.core.VIDPAuthenticationAttributes; +import eu.stork.peps.auth.engine.core.impl.AuthenticationAttributesBuilder; +import eu.stork.peps.auth.engine.core.impl.AuthenticationAttributesMarshaller; +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.EIDCrossBorderShareBuilder; +import eu.stork.peps.auth.engine.core.impl.EIDCrossBorderShareMarshaller; +import eu.stork.peps.auth.engine.core.impl.EIDCrossBorderShareUnmarshaller; +import eu.stork.peps.auth.engine.core.impl.EIDCrossSectorShareBuilder; +import eu.stork.peps.auth.engine.core.impl.EIDCrossSectorShareMarshaller; +import eu.stork.peps.auth.engine.core.impl.EIDCrossSectorShareUnmarshaller; +import eu.stork.peps.auth.engine.core.impl.EIDSectorShareBuilder; +import eu.stork.peps.auth.engine.core.impl.EIDSectorShareMarshaller; +import eu.stork.peps.auth.engine.core.impl.EIDSectorShareUnmarshaller; +import eu.stork.peps.auth.engine.core.impl.QAAAttributeBuilder; +import eu.stork.peps.auth.engine.core.impl.QAAAttributeMarshaller; +import eu.stork.peps.auth.engine.core.impl.QAAAttributeUnmarshaller; +import eu.stork.peps.auth.engine.core.impl.RequestedAttributeBuilder; +import eu.stork.peps.auth.engine.core.impl.RequestedAttributeMarshaller; +import eu.stork.peps.auth.engine.core.impl.RequestedAttributeUnmarshaller; +import eu.stork.peps.auth.engine.core.impl.RequestedAttributesBuilder; +import eu.stork.peps.auth.engine.core.impl.RequestedAttributesMarshaller; +import eu.stork.peps.auth.engine.core.impl.RequestedAttributesUnmarshaller; +import eu.stork.peps.auth.engine.core.impl.SPApplicationBuilder; +import eu.stork.peps.auth.engine.core.impl.SPApplicationMarshaller; +import eu.stork.peps.auth.engine.core.impl.SPApplicationUnmarshaller; +import eu.stork.peps.auth.engine.core.impl.SPCountryBuilder; +import eu.stork.peps.auth.engine.core.impl.SPCountryMarshaller; +import eu.stork.peps.auth.engine.core.impl.SPCountryUnmarshaller; +import eu.stork.peps.auth.engine.core.impl.SPIDBuilder; +import eu.stork.peps.auth.engine.core.impl.SPIDMarshaller; +import eu.stork.peps.auth.engine.core.impl.SPIDUnmarshaller; +import eu.stork.peps.auth.engine.core.impl.SPInformationBuilder; +import eu.stork.peps.auth.engine.core.impl.SPInformationMarshaller; +import eu.stork.peps.auth.engine.core.impl.SPInformationUnmarshaller; +import eu.stork.peps.auth.engine.core.impl.SPInstitutionBuilder; +import eu.stork.peps.auth.engine.core.impl.SPInstitutionMarshaller; +import eu.stork.peps.auth.engine.core.impl.SPInstitutionUnmarshaller; +import eu.stork.peps.auth.engine.core.impl.SPSectorBuilder; +import eu.stork.peps.auth.engine.core.impl.SPSectorMarshaller; +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.ExtensionsSchemaValidator; +import eu.stork.peps.auth.engine.core.validator.QAAAttributeSchemaValidator; +import eu.stork.peps.exceptions.SAMLEngineException; +import eu.stork.peps.exceptions.STORKSAMLEngineException; +import eu.stork.peps.exceptions.STORKSAMLEngineRuntimeException; + +/** + * Class that wraps the operations over SAML tokens, both generation and + * validation of SAML STORK requests and SAML STORK responses. Complaint with + * "OASIS Secure Assertion Markup Language (SAML) 2.0, May 2005", but taking + * into account STORK specific requirements. + * + * @author fjquevedo + * @author iinigo + */ +public final class STORKSAMLEngine extends SAMLEngine { + + /** The Constant LOG. */ + private static final Logger LOG = LoggerFactory + .getLogger(STORKSAMLEngine.class.getName()); + + private static final String ATTRIBUTE_EMPTY_LITERAL = "Attribute name is null or empty."; + /** + * Gets the single instance of STORKSAMLEngine. + * + * @param nameInstance the name instance + * + * @return single instance of STORKSAMLEngine + */ + public static synchronized STORKSAMLEngine getInstance( + final String nameInstance) { + STORKSAMLEngine engine = null; + LOG.info("Get instance: " + nameInstance); + try { + engine = new STORKSAMLEngine(nameInstance.trim()); + } catch (Exception e) { + LOG.error("Error get instance: " + nameInstance); + } + return engine; + } + + /** + * Instantiate a new STORKSAML engine. + * + * @param nameInstance the name instance + * + * @throws STORKSAMLEngineException the STORKSAML engine exception + */ + private STORKSAMLEngine(final String nameInstance) + throws STORKSAMLEngineException { + // Initialization OpenSAML. + super(nameInstance); + LOG.info("Register STORK objects provider."); + Configuration.registerObjectProvider(QAAAttribute.DEF_ELEMENT_NAME, + new QAAAttributeBuilder(), new QAAAttributeMarshaller(), + new QAAAttributeUnmarshaller()); + + Configuration.registerObjectProvider(EIDSectorShare.DEF_ELEMENT_NAME, + new EIDSectorShareBuilder(), new EIDSectorShareMarshaller(), + new EIDSectorShareUnmarshaller()); + + Configuration.registerObjectProvider( + EIDCrossSectorShare.DEF_ELEMENT_NAME, + new EIDCrossSectorShareBuilder(), + new EIDCrossSectorShareMarshaller(), + new EIDCrossSectorShareUnmarshaller()); + + Configuration.registerObjectProvider( + EIDCrossBorderShare.DEF_ELEMENT_NAME, + new EIDCrossBorderShareBuilder(), + new EIDCrossBorderShareMarshaller(), + new EIDCrossBorderShareUnmarshaller()); + + Configuration.registerObjectProvider(SPSector.DEF_ELEMENT_NAME, + new SPSectorBuilder(), new SPSectorMarshaller(), + new SPSectorUnmarshaller()); + + Configuration.registerObjectProvider(SPInstitution.DEF_ELEMENT_NAME, + new SPInstitutionBuilder(), new SPInstitutionMarshaller(), + new SPInstitutionUnmarshaller()); + + Configuration.registerObjectProvider(SPApplication.DEF_ELEMENT_NAME, + new SPApplicationBuilder(), new SPApplicationMarshaller(), + new SPApplicationUnmarshaller()); + + Configuration.registerObjectProvider(SPCountry.DEF_ELEMENT_NAME, + new SPCountryBuilder(), new SPCountryMarshaller(), + new SPCountryUnmarshaller()); + + Configuration.registerObjectProvider(XSAny.TYPE_NAME, + new XSAnyBuilder(), new XSAnyMarshaller(), + new XSAnyUnmarshaller()); + + Configuration.registerObjectProvider( + RequestedAttribute.DEF_ELEMENT_NAME, + new RequestedAttributeBuilder(), + new RequestedAttributeMarshaller(), + new RequestedAttributeUnmarshaller()); + + Configuration.registerObjectProvider( + RequestedAttributes.DEF_ELEMENT_NAME, + new RequestedAttributesBuilder(), + new RequestedAttributesMarshaller(), + new RequestedAttributesUnmarshaller()); + + Configuration.registerObjectProvider( + AuthenticationAttributes.DEF_ELEMENT_NAME, + new AuthenticationAttributesBuilder(), + new AuthenticationAttributesMarshaller(), + new AuthenticationAttributesUnmarshaller()); + + Configuration.registerObjectProvider( + VIDPAuthenticationAttributes.DEF_ELEMENT_NAME, + new VIDPAuthenticationAttributesBuilder(), + new VIDPAuthenticationAttributesMarshaller(), + new VIDPAuthenticationAttributesUnmarshaller()); + + Configuration.registerObjectProvider( + CitizenCountryCode.DEF_ELEMENT_NAME, + new CitizenCountryCodeBuilder(), + new CitizenCountryCodeMarshaller(), + new CitizenCountryCodeUnmarshaller()); + + Configuration.registerObjectProvider( + SPID.DEF_ELEMENT_NAME, + new SPIDBuilder(), + new SPIDMarshaller(), + new SPIDUnmarshaller()); + + Configuration.registerObjectProvider( + SPInformation.DEF_ELEMENT_NAME, + new SPInformationBuilder(), + new SPInformationMarshaller(), + new SPInformationUnmarshaller()); + + LOG.info("Register STORK object validators."); + final ValidatorSuite validatorSuite = new ValidatorSuite( + QAAAttribute.DEF_LOCAL_NAME); + + validatorSuite.registerValidator(QAAAttribute.DEF_ELEMENT_NAME, + new QAAAttributeSchemaValidator()); + final Extensions extensions = SAMLEngineUtils.generateExtension(); + validatorSuite.registerValidator(extensions.getElementQName(), + new ExtensionsSchemaValidator()); + + Configuration.registerValidatorSuite( + "stork:QualityAuthenticationAssuranceLevel", validatorSuite); + + } + + /** + * Generate authentication response base. + * + * @param status the status + * @param assertConsumerURL the assert consumer URL. + * @param inResponseTo the in response to + * + * @return the response + * + * @throws STORKSAMLEngineException the STORKSAML engine exception + */ + private Response genAuthnRespBase(final Status status, + final String assertConsumerURL, final String inResponseTo) + throws STORKSAMLEngineException { + LOG.debug("Generate Authentication Response base."); + final Response response = SAMLEngineUtils.generateResponse( + SAMLVersion.VERSION_20, SAMLEngineUtils.generateNCName(), + SAMLEngineUtils.getCurrentTime(), status); + + // Set name Spaces + this.setNameSpaces(response); + + // Mandatory STORK + LOG.debug("Generate Issuer"); + final Issuer issuer = SAMLEngineUtils.generateIssuer(); + issuer.setValue(super.getSamlCoreProperties().getResponder()); + + // Format Entity Optional STORK + issuer.setFormat(super.getSamlCoreProperties().getFormatEntity()); + + response.setIssuer(issuer); + + // destination Mandatory Stork + response.setDestination(assertConsumerURL.trim()); + + // inResponseTo Mandatory Stork + response.setInResponseTo(inResponseTo.trim()); + + // Optional STORK + response.setConsent(super.getSamlCoreProperties() + .getConsentAuthnResponse()); + + return response; + } + + /** + * Generate attribute query response base. + * + * @param status the status + * @param destinationURL the assert consumer URL. + * @param inResponseTo the in response to + * + * @return the response + * + * @throws STORKSAMLEngineException the STORKSAML engine exception + */ + private Response genAttrQueryRespBase(final Status status, + final String destinationURL, final String inResponseTo) + throws STORKSAMLEngineException { + LOG.debug("Generate Attribute query Response base."); + final Response response = SAMLEngineUtils.generateResponse( + SAMLVersion.VERSION_20, SAMLEngineUtils.generateNCName(), + SAMLEngineUtils.getCurrentTime(), status); + + // Set name Spaces + this.setNameSpaces(response); + + // Mandatory STORK + LOG.debug("Generate Issuer"); + final Issuer issuer = SAMLEngineUtils.generateIssuer(); + issuer.setValue(super.getSamlCoreProperties().getResponder()); + + // Format Entity Optional STORK + issuer.setFormat(super.getSamlCoreProperties().getFormatEntity()); + + response.setIssuer(issuer); + + // destination Mandatory Stork + response.setDestination(destinationURL.trim()); + + // inResponseTo Mandatory Stork + response.setInResponseTo(inResponseTo.trim()); + + // Optional STORK + response.setConsent(super.getSamlCoreProperties() + .getConsentAuthnResponse()); + + return response; + } + + /** + * Generate assertion. + * + * @param ipAddress the IP address. + * @param assertConsumerURL the assert consumer URL. + * @param inResponseTo the in response to + * @param issuer the issuer + * @param notOnOrAfter the not on or after + * + * @return the assertion + * + * @throws STORKSAMLEngineException the STORKSAML engine exception + */ + private Assertion generateAssertion(final String ipAddress, + final String assertConsumerURL, final String inResponseTo, + final String issuer, final DateTime notOnOrAfter) + throws STORKSAMLEngineException { + LOG.info("Generate Assertion."); + + // Mandatory STORK + LOG.debug("Generate Issuer to Assertion"); + final Issuer issuerAssertion = SAMLEngineUtils.generateIssuer(); + issuerAssertion.setValue(super.getSamlCoreProperties().getResponder()); + + // Format Entity Optional STORK + issuerAssertion.setFormat(super.getSamlCoreProperties() + .getFormatEntity()); + + final Assertion assertion = SAMLEngineUtils.generateAssertion( + SAMLVersion.VERSION_20, SAMLEngineUtils.generateNCName(), + SAMLEngineUtils.getCurrentTime(), issuerAssertion); + + final Subject subject = SAMLEngineUtils.generateSubject(); + + // Mandatory STORK verified + // String format = NameID.UNSPECIFIED + // specification: 'SAML:2.0' exist + // opensaml: "urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified" + // opensaml "urn:oasis:names:tc:SAML:2.0:nameid-format:unspecified" + final String format = "urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"; + + final String nameQualifier = ""; + + LOG.debug("Generate NameID"); + final NameID nameId = SAMLEngineUtils.generateNameID(super + .getSamlCoreProperties().getResponder(), format, nameQualifier); + nameId.setValue(format); + subject.setNameID(nameId); + + // Mandatory if urn:oasis:names:tc:SAML:2.0:cm:bearer. + // Optional in other case. + LOG.debug("Generate SubjectConfirmationData."); + final SubjectConfirmationData dataBearer = SAMLEngineUtils + .generateSubjectConfirmationData(SAMLEngineUtils + .getCurrentTime(), assertConsumerURL, inResponseTo); + + // Mandatory if urn:oasis:names:tc:SAML:2.0:cm:bearer. + // Optional in other case. + LOG.debug("Generate SubjectConfirmation"); + final SubjectConfirmation subjectConf = SAMLEngineUtils + .generateSubjectConfirmation(SubjectConfirmation.METHOD_BEARER, + dataBearer); + + final ArrayList listSubjectConf = new ArrayList(); + listSubjectConf.add(subjectConf); + + for (final Iterator iter = listSubjectConf + .iterator(); iter.hasNext();) { + final SubjectConfirmation element = iter.next(); + + if (SubjectConfirmation.METHOD_BEARER.equals(element.getMethod())) { + // ipAddress Mandatory if method is Bearer. + + if (StringUtils.isBlank(ipAddress)) { + throw new STORKSAMLEngineException( + "ipAddress is null or empty"); + } + element.getSubjectConfirmationData().setAddress( + ipAddress.trim()); + } + + element.getSubjectConfirmationData() + .setRecipient(assertConsumerURL); + element.getSubjectConfirmationData().setNotOnOrAfter(notOnOrAfter); + } + + // The SAML 2.0 specification allows multiple SubjectConfirmations + subject.getSubjectConfirmations().addAll(listSubjectConf); + + // Mandatory Stork + assertion.setSubject(subject); + + // Conditions that MUST be evaluated when assessing the validity of + // and/or when using the assertion. + final Conditions conditions = this.generateConditions(SAMLEngineUtils + .getCurrentTime(), notOnOrAfter, issuer); + + assertion.setConditions(conditions); + + LOG.debug("Generate stork Authentication Statement."); + final AuthnStatement storkAuthnStat = this + .generateStorkAuthStatement(ipAddress); + assertion.getAuthnStatements().add(storkAuthnStat); + + return assertion; + } + + private String getAttributeName(final PersonalAttribute attribute) throws STORKSAMLEngineException { + if (StringUtils.isBlank(attribute.getName())) { + LOG.error(ATTRIBUTE_EMPTY_LITERAL); + throw new STORKSAMLEngineException(ATTRIBUTE_EMPTY_LITERAL); + } + + final String attributeName = super.getSamlCoreProperties() + .getProperty(attribute.getName()); + + if (StringUtils.isBlank(attributeName)) { + LOG.error("Attribute name: {} it is not known.", attribute + .getName()); + throw new STORKSAMLEngineException("Attribute name: " + + attribute.getName() + " it is not known."); + } + return attributeName; + } + /** + * Generate attribute statement. + * + * @param personalAttrList the personal attribute list + * @param isHashing the is hashing + * + * @return the attribute statement + * + * @throws STORKSAMLEngineException the STORKSAML engine exception + * @throws IOException + */ + private AttributeStatement generateAttributeStatement( + final IPersonalAttributeList personalAttrList, + final boolean isHashing) throws STORKSAMLEngineException { + LOG.debug("Generate attribute statement"); + + final AttributeStatement attrStatement = (AttributeStatement) SAMLEngineUtils + .createSamlObject(AttributeStatement.DEFAULT_ELEMENT_NAME); + + for (PersonalAttribute attribute : personalAttrList) { + + String attributeName = getAttributeName(attribute); + + // Verification that only one value it's permitted, simple or + // complex, not both. + + final boolean simpleNull = (attribute.getValue() == null); + final boolean simpleEmpty = (simpleNull || (!simpleNull && attribute + .getValue().isEmpty())); + + final boolean complexNull = (attribute.getComplexValue() == null); + final boolean complexEmpty = (complexNull || (!complexNull && attribute + .getComplexValue().isEmpty())); + + if ((!simpleEmpty && !complexEmpty)) { + throw new STORKSAMLEngineException( + "Attribute name: " + + attribute.getName() + + " must be contain one value, simple or complex value."); + } else { + + if (!simpleEmpty) { + attrStatement.getAttributes().add( + this.generateAttrSimple(attributeName, attribute + .getStatus(), attribute.getValue(), + isHashing)); + } else if (!complexEmpty) { + attrStatement.getAttributes().add( + SAMLEngineUtils.generateAttrComplex(attributeName, + attribute.getStatus(), attribute + .getComplexValue(), isHashing)); + } else if (!simpleNull) { + attrStatement.getAttributes().add( + this.generateAttrSimple(attributeName, attribute + .getStatus(), new ArrayList(), + isHashing)); + } else { + // Add attribute complex. + attrStatement.getAttributes().add( + SAMLEngineUtils.generateAttrComplex(attributeName, + attribute.getStatus(), + new HashMap(), isHashing)); + } + } + } + return attrStatement; + } + private XSAny createAttributeValueForSignedDoc(final String value, final boolean isHashing) throws STORKSAMLEngineException { + DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance(); + domFactory.setNamespaceAware(true); + Document document = null; + DocumentBuilder builder; + + // Parse the signedDoc value into an XML DOM Document + try { + builder = domFactory.newDocumentBuilder(); + InputStream is; + is = new ByteArrayInputStream(value.trim().getBytes("UTF-8")); + document = builder.parse(is); + is.close(); + } catch (SAXException e1) { + LOG.error("SAX Error while parsing signModule attribute", e1); + throw new STORKSAMLEngineRuntimeException(e1); + } catch (ParserConfigurationException e2) { + LOG.error("Parser Configuration Error while parsing signModule attribute", e2); + throw new STORKSAMLEngineRuntimeException(e2); + } catch (UnsupportedEncodingException e3) { + LOG.error("Unsupported encoding Error while parsing signModule attribute", e3); + throw new STORKSAMLEngineRuntimeException(e3); + } catch (IOException e4) { + LOG.error("IO Error while parsing signModule attribute", e4); + throw new STORKSAMLEngineRuntimeException(e4); + } + + // Create the attribute statement + final XSAny xmlValue = (XSAny) SAMLEngineUtils + .createSamlObject( + AttributeValue.DEFAULT_ELEMENT_NAME, + XSAny.TYPE_NAME); + + //Set the signedDoc XML content to this element + xmlValue.setDOM(document.getDocumentElement()); + + // Create the attribute statement + final XSAny attrValue = (XSAny) SAMLEngineUtils + .createSamlObject( + AttributeValue.DEFAULT_ELEMENT_NAME, + XSAny.TYPE_NAME); + + //Add previous signedDocXML to the AttributeValue Element + + // if it's necessary encode the information. + if (!isHashing) { + attrValue.getUnknownXMLObjects().add(xmlValue); + } + return attrValue; + } + + private XSAny createAttributeValueForNonSignedDoc(final String value, final boolean isHashing) throws STORKSAMLEngineException { + // Create the attribute statement + final XSAny attrValue = (XSAny) SAMLEngineUtils + .createSamlObject( + AttributeValue.DEFAULT_ELEMENT_NAME, + XSAny.TYPE_NAME); + // if it's necessary encode the information. + if (isHashing) { + attrValue.setTextContent(SAMLEngineUtils.encode(value, SAMLEngineUtils.SHA_512)); + } else { + attrValue.setTextContent(value); + } + return attrValue; + } + + /** + * Generate attribute from a list of values. + * + * @param name the name of the attribute. + * @param values the value of the attribute. + * @param isHashing the is hashing with "SHA-512" algorithm. + * @param status the status of the parameter: "Available", "NotAvailable" or + * "Withheld". + * + * @return the attribute + * + * @throws STORKSAMLEngineException the STORKSAML engine exception + */ + private Attribute generateAttrSimple(final String name, + final String status, final List values, + final boolean isHashing) throws STORKSAMLEngineException { + LOG.debug("Generate attribute simple: " + name); + final Attribute attribute = (Attribute) SAMLEngineUtils + .createSamlObject(Attribute.DEFAULT_ELEMENT_NAME); + + attribute.setName(name); + attribute.setNameFormat(Attribute.URI_REFERENCE); + + attribute.getUnknownAttributes().put( + new QName(SAMLCore.STORK10_NS.getValue(), "AttributeStatus", + SAMLCore.STORK10_PREFIX.getValue()), status); + + if (values != null) { + LOG.debug("Add attribute values."); + for (int i = 0; i < values.size(); i++) { + final String value = values.get(i); + if (StringUtils.isNotBlank(value)) { + XSAny attrValue = null; + if (!name.equals("http://www.stork.gov.eu/1.0/signedDoc")) { + // Create the attribute statement + attrValue = createAttributeValueForNonSignedDoc(value, isHashing); + + } else { + attrValue = createAttributeValueForSignedDoc(value, isHashing); + attribute.getAttributeValues().add(attrValue); + } + attribute.getAttributeValues().add(attrValue); + } + } + } + return attribute; + } + + /** + * Generate conditions that MUST be evaluated when assessing the validity of + * and/or when using the assertion. + * + * @param notBefore the not before + * @param notOnOrAfter the not on or after + * @param audienceURI the audience URI. + * + * @return the conditions + */ + private Conditions generateConditions(final DateTime notBefore, + final DateTime notOnOrAfter, final String audienceURI) { + LOG.debug("Generate conditions."); + final Conditions conditions = (Conditions) SAMLEngineUtils + .createSamlObject(Conditions.DEFAULT_ELEMENT_NAME); + conditions.setNotBefore(notBefore); + conditions.setNotOnOrAfter(notOnOrAfter); + + final AudienceRestriction restrictions = (AudienceRestriction) SAMLEngineUtils + .createSamlObject(AudienceRestriction.DEFAULT_ELEMENT_NAME); + + final Audience audience = (Audience) SAMLEngineUtils + .createSamlObject(Audience.DEFAULT_ELEMENT_NAME); + audience.setAudienceURI(audienceURI); + + restrictions.getAudiences().add(audience); + conditions.getAudienceRestrictions().add(restrictions); + + if (super.getSamlCoreProperties().isOneTimeUse()) { + final OneTimeUse oneTimeUse = (OneTimeUse) SAMLEngineUtils + .createSamlObject(OneTimeUse.DEFAULT_ELEMENT_NAME); + conditions.getConditions().add(oneTimeUse); + } + return conditions; + } + + /** + * Generate personal attribute list. + * + * @param assertion the assertion + * + * @return the personal attribute list + * + * @throws STORKSAMLEngineException the STORKSAML engine exception + */ + private IPersonalAttributeList generatePersonalAttributeList( + final Assertion assertion) throws STORKSAMLEngineException { + LOG.debug("Generate personal attribute list from XMLObject."); + final List listExtensions = assertion.getOrderedChildren(); + + boolean find = false; + AttributeStatement requestedAttr = null; + + // Search the attribute statement. + for (int i = 0; i < listExtensions.size() && !find; i++) { + final XMLObject xml = listExtensions.get(i); + if (xml instanceof AttributeStatement) { + requestedAttr = (AttributeStatement) xml; + find = true; + } + } + + if (!find) { + LOG.error("Error: AttributeStatement it's not present."); + throw new STORKSAMLEngineException( + "AttributeStatement it's not present."); + } + + final List reqAttrs = requestedAttr.getAttributes(); + + final IPersonalAttributeList personalAttrList = new PersonalAttributeList(); + String attributeName; + + // Process the attributes. + for (int nextAttribute = 0; nextAttribute < reqAttrs.size(); nextAttribute++) { + final Attribute attribute = reqAttrs.get(nextAttribute); + + final PersonalAttribute personalAttribute = new PersonalAttribute(); + + attributeName = attribute.getName(); + personalAttribute.setName(attributeName.substring(attributeName + .lastIndexOf('/') + 1)); + + personalAttribute.setStatus(attribute.getUnknownAttributes().get( + new QName(SAMLCore.STORK10_NS.getValue(), + "AttributeStatus", SAMLCore.STORK10_PREFIX + .getValue()))); + + final ArrayList simpleValues = new ArrayList(); + final HashMap multiValues = new HashMap(); + + final List values = attribute.getOrderedChildren(); + + + // Process the values. + for (int nextValue = 0; nextValue < values.size(); nextValue++) { + + final XMLObject xmlObject = values.get(nextValue); + + if (xmlObject instanceof XSStringImpl) { + + // Process simple value. + simpleValues.add(((XSStringImpl) xmlObject).getValue()); + + } else if (xmlObject instanceof XSAnyImpl) { + + if (attributeName.equals("http://www.stork.gov.eu/1.0/signedDoc")) { + + final XSAnyImpl xmlString = (XSAnyImpl) values + .get(nextValue); + + TransformerFactory transFactory = TransformerFactory + .newInstance(); + Transformer transformer = null; + try { + transformer = transFactory.newTransformer(); + transformer.setOutputProperty( + OutputKeys.OMIT_XML_DECLARATION, "yes"); + } catch (TransformerConfigurationException e) { + LOG.error("Error transformer configuration exception", e); + } + StringWriter buffer = new StringWriter(); + try { + if (xmlString != null && xmlString.getUnknownXMLObjects() != null && xmlString.getUnknownXMLObjects().size() > 0 ){ + transformer.transform(new DOMSource(xmlString + .getUnknownXMLObjects().get(0).getDOM()), + new StreamResult(buffer)); + } + } catch (TransformerException e) { + LOG.error("Error transformer exception", e); + } + String str = buffer.toString(); + + simpleValues.add(str); + + } else if (attributeName + .equals("http://www.stork.gov.eu/1.0/canonicalResidenceAddress")) + { + LOG.info("canonicalResidenceAddress 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/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) + .getTextContent()); + } + + } else { + LOG.error("Error: attribute value it's unknown."); + throw new STORKSAMLEngineException( + "Attribute value it's unknown."); + } + } + + personalAttribute.setValue(simpleValues); + personalAttribute.setComplexValue(multiValues); + personalAttrList.add(personalAttribute); + } + + return personalAttrList; + } + + /** + * Generate stork authentication request. + * + * @param request the request that contain all parameters for generate an + * authentication request. + * + * @return the STORK authentication request that has been processed. + * + * @throws STORKSAMLEngineException the STORKSAML engine exception + */ + public STORKAuthnRequest generateSTORKAuthnRequest( + final STORKAuthnRequest request) throws STORKSAMLEngineException { + LOG.info("Generate SAMLAuthnRequest."); + + // Validate Parameters mandatories + validateParamAuthnReq(request); + + final AuthnRequest authnRequestAux = SAMLEngineUtils + .generateSAMLAuthnRequest(SAMLEngineUtils.generateNCName(), + SAMLVersion.VERSION_20, SAMLEngineUtils + .getCurrentTime()); + + // Set name spaces. + setNameSpaces(authnRequestAux); + + // Add parameter Mandatory STORK + authnRequestAux.setForceAuthn(Boolean.TRUE); + + // Add parameter Mandatory STORK + authnRequestAux.setIsPassive(Boolean.FALSE); + + authnRequestAux.setAssertionConsumerServiceURL(request + .getAssertionConsumerServiceURL()); + + authnRequestAux.setProviderName(request.getProviderName()); + + // Add protocol binding + authnRequestAux.setProtocolBinding(super.getSamlCoreProperties() + .getProtocolBinding()); + + // 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())) { + authnRequestAux.setDestination(request.getDestination()); + } + + // Consent is optional. Set from SAMLEngine.xml - consent. + authnRequestAux.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); + } + + authnRequestAux.setIssuer(issuer); + + // Generate stork extensions. + final Extensions storkExtensions = this + .generateSTORKExtensions(request); + // add the extensions to the SAMLAuthnRequest + authnRequestAux.setExtensions(storkExtensions); + + // the result contains an authentication request token (byte[]), + // identifier of the token, and all parameters from the request. + final STORKAuthnRequest authRequest = processExtensions(authnRequestAux + .getExtensions()); + + try { + authRequest.setTokenSaml(super.signAndMarshall(authnRequestAux)); + } catch (SAMLEngineException e) { + LOG.error("Sign and Marshall.", e); + throw new STORKSAMLEngineException(e); + } + + authRequest.setSamlId(authnRequestAux.getID()); + authRequest.setDestination(authnRequestAux.getDestination()); + authRequest.setAssertionConsumerServiceURL(authnRequestAux + .getAssertionConsumerServiceURL()); + + authRequest.setProviderName(authnRequestAux.getProviderName()); + authRequest.setIssuer(authnRequestAux.getIssuer().getValue()); + + return authRequest; + } + + /** + * 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 generateSTORKAuthnResponse( + final STORKAuthnRequest request, + final STORKAuthnResponse responseAuthReq, final String ipAddress, + final boolean isHashing) 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); + + 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. + * + * @param request the request + * @param response the response + * @param ipAddress the IP address + * @param isHashing the is hashing + * + * @return the sTORK authentication response + * + * @throws STORKSAMLEngineException the STORKSAML engine exception + */ + public STORKAuthnResponse generateSTORKAuthnResponseFail( + final STORKAuthnRequest request, final STORKAuthnResponse response, + final String ipAddress, final boolean isHashing) + throws STORKSAMLEngineException { + LOG.info("generateSTORKAuthnResponseFail"); + + validateParamResponseFail(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.getMessage())) { + final StatusMessage statusMessage = (StatusMessage) SAMLEngineUtils + .generateStatusMessage(response.getMessage()); + + status.setStatusMessage(statusMessage); + } + + LOG.debug("Generate Response."); + // RESPONSE + final Response responseFail = 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); + + responseFail.getAssertions().add(assertion); + + LOG.debug("Sign and Marshall ResponseFail."); + + final STORKAuthnResponse storkResponse = new STORKAuthnResponse(); + + 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 attribute query request. + * + * @param request the request that contain all parameters for generate an + * attribute query request. + * + * @return the STORK attribute query request that has been processed. + * + * @throws STORKSAMLEngineException the STORKSAML engine exception + */ + public STORKAttrQueryRequest generateSTORKAttrQueryRequest( + final STORKAttrQueryRequest request) throws STORKSAMLEngineException { + LOG.info("Generate STORKAttrQueryRequest."); + + // Validate Parameters mandatories + validateParamAttrQueryReq(request); + + final AttributeQuery attrQueryRequestAux = SAMLEngineUtils + .generateSAMLAttrQueryRequest(SAMLEngineUtils.generateNCName(), + SAMLVersion.VERSION_20, SAMLEngineUtils + .getCurrentTime()); + + // Set name spaces. + setNameSpaces(attrQueryRequestAux); + + + // 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())) { + attrQueryRequestAux.setDestination(request.getDestination()); + } + + // Consent is optional. Set from SAMLEngine.xml - consent. + attrQueryRequestAux.setConsent(super.getSamlCoreProperties() + .getConsentAuthnRequest()); + + final Issuer issuer = SAMLEngineUtils.generateIssuer(); + + //Set the subject - needed for attribute query validation + Subject subject = SAMLEngineUtils.generateSubject(); + SubjectConfirmationBuilder builder = new SubjectConfirmationBuilder(); + SubjectConfirmation subjectConfirmation = builder.buildObject(); + subjectConfirmation.setMethod("urn:oasis:names:tc:SAML:2.0:cm:bearer"); + subject.getSubjectConfirmations().add(subjectConfirmation); + attrQueryRequestAux.setSubject(subject); + + 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); + } + + attrQueryRequestAux.setIssuer(issuer); + + // Generate stork extensions. + final Extensions storkExtensions = this + .generateSTORKAttrExtensions(request); + // add the extensions to the SAMLAuthnRequest + attrQueryRequestAux.setExtensions(storkExtensions); + + // the result contains an authentication request token (byte[]), + // identifier of the token, and all parameters from the request. + final STORKAttrQueryRequest attrQueryRequest = processAttrExtensions(attrQueryRequestAux + .getExtensions()); + + try { + attrQueryRequest.setTokenSaml(super.signAndMarshall(attrQueryRequestAux)); + } catch (SAMLEngineException e) { + LOG.error("Sign and Marshall.", e); + throw new STORKSAMLEngineException(e); + } + + attrQueryRequest.setSamlId(attrQueryRequestAux.getID()); + attrQueryRequest.setDestination(attrQueryRequestAux.getDestination()); + + attrQueryRequest.setIssuer(attrQueryRequestAux.getIssuer().getValue()); + + return attrQueryRequest; + } + + /** + * Generate stork attribute query response. + * + * @param request the request + * @param responseAttrQueryReq 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 STORKAttrQueryResponse generateSTORKAttrQueryResponse( + final STORKAttrQueryRequest request, + final STORKAttrQueryResponse responseAttrQueryReq, final String ipAddress, + final String destinationUrl, final boolean isHashing) throws STORKSAMLEngineException { + LOG.info("generateSTORKAttrQueryResponse"); + + // Validate parameters + validateParamAttrQueryResponse(request, responseAttrQueryReq); + + // 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(responseAttrQueryReq + .getPersonalAttributeList(), isHashing); + + assertion.getAttributeStatements().add(attrStatement); + + // Add assertions + response.getAssertions().add(assertion); + + 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. + * + * @param request the request + * @param response the response + * @param ipAddress the IP address + * @param isHashing the is hashing + * + * @return the STORK attribute query response + * + * @throws STORKSAMLEngineException the STORKSAML engine exception + */ + public STORKAttrQueryResponse generateSTORKAttrQueryResponseFail( + final STORKAttrQueryRequest request, final STORKAttrQueryResponse response, + final String ipAddress, final String destinationUrl, final boolean isHashing) + throws STORKSAMLEngineException { + LOG.info("generateSTORKAttrQueryResponseFail"); + + validateParamAttrQueryResponseFail(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.getMessage())) { + final StatusMessage statusMessage = (StatusMessage) SAMLEngineUtils + .generateStatusMessage(response.getMessage()); + + status.setStatusMessage(statusMessage); + } + + LOG.debug("Generate Response."); + // RESPONSE + final Response responseFail = 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); + + 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 authentication statement for the authentication statement. + * + * @param ipAddress the IP address + * + * @return the authentication statement + */ + private AuthnStatement generateStorkAuthStatement(final String ipAddress) { + LOG.debug("Generate stork authenticate statement."); + final SubjectLocality subjectLocality = SAMLEngineUtils + .generateSubjectLocality(ipAddress); + + final AuthnContext authnContext = (AuthnContext) SAMLEngineUtils + .createSamlObject(AuthnContext.DEFAULT_ELEMENT_NAME); + + final AuthnContextDecl authnContextDecl = (AuthnContextDecl) SAMLEngineUtils + .createSamlObject(AuthnContextDecl.DEFAULT_ELEMENT_NAME); + + authnContext.setAuthnContextDecl(authnContextDecl); + + final AuthnStatement authnStatement = SAMLEngineUtils + .generateAthnStatement(new DateTime(), authnContext); + + // Optional STORK + authnStatement.setSessionIndex(null); + authnStatement.setSubjectLocality(subjectLocality); + + return authnStatement; + } + + /** + * Generate stork extensions. + * + * @param request the request + * + * @return the extensions + * + * @throws STORKSAMLEngineException the STORKSAML engine exception + */ + private Extensions generateSTORKExtensions(final STORKAuthnRequest request) + throws STORKSAMLEngineException { + LOG.debug("Generate STORKExtensions"); + + final Extensions extensions = SAMLEngineUtils.generateExtension(); + + LOG.debug("Generate QAAAttribute"); + final QAAAttribute qaaAttribute = SAMLEngineUtils + .generateQAAAttribute(request.getQaa()); + extensions.getUnknownXMLObjects().add(qaaAttribute); + + + if (StringUtils.isNotEmpty(request + .getSpSector())) { + // Add information about service provider. + LOG.debug("Generate SPSector"); + final SPSector sector = SAMLEngineUtils.generateSPSector(request + .getSpSector()); + extensions.getUnknownXMLObjects().add(sector); + } + + //Delete from specification. Kept for compatibility with Provider Name value + LOG.debug("Generate SPInstitution"); + final SPInstitution institution = SAMLEngineUtils + .generateSPInstitution(request.getProviderName()); + extensions.getUnknownXMLObjects().add(institution); + + + if (StringUtils.isNotEmpty(request.getSpApplication())) { + LOG.debug("Generate SPApplication"); + final SPApplication application = SAMLEngineUtils + .generateSPApplication(request.getSpApplication()); + extensions.getUnknownXMLObjects().add(application); + } + + if (StringUtils.isNotEmpty(request.getSpCountry())) { + LOG.debug("Generate SPCountry"); + final SPCountry country = SAMLEngineUtils.generateSPCountry(request + .getSpCountry()); + extensions.getUnknownXMLObjects().add(country); + } + + //eIDSectorShare: optional; default value: false. + String valueSectorShare = super.getSamlCoreProperties() + .iseIDSectorShare(); + + if (StringUtils.isNotEmpty(valueSectorShare)) { + // Add information about the use of the SAML message. + LOG.debug("Generate EIDSectorShare"); + final EIDSectorShare eIdSectorShare = (EIDSectorShare) SAMLEngineUtils + .createSamlObject(EIDSectorShare.DEF_ELEMENT_NAME); + + eIdSectorShare.setEIDSectorShare(String.valueOf(Boolean.valueOf(valueSectorShare))); + + extensions.getUnknownXMLObjects().add(eIdSectorShare); + } + + String valueCrossSectorShare = super.getSamlCoreProperties() + .iseIDCrossSectorShare(); + + if (StringUtils.isNotEmpty(valueCrossSectorShare)) { + LOG.debug("Generate EIDCrossSectorShare"); + final EIDCrossSectorShare eIdCrossSecShare = (EIDCrossSectorShare) SAMLEngineUtils + .createSamlObject(EIDCrossSectorShare.DEF_ELEMENT_NAME); + eIdCrossSecShare.setEIDCrossSectorShare(String.valueOf(Boolean.valueOf(valueCrossSectorShare))); + extensions.getUnknownXMLObjects().add(eIdCrossSecShare); + } + + + String valueCrossBorderShare = super.getSamlCoreProperties() + .iseIDCrossBorderShare(); + + if (StringUtils.isNotEmpty(valueCrossBorderShare)) { + LOG.debug("Generate EIDCrossBorderShare"); + final EIDCrossBorderShare eIdCrossBordShare = (EIDCrossBorderShare) SAMLEngineUtils + .createSamlObject(EIDCrossBorderShare.DEF_ELEMENT_NAME); + eIdCrossBordShare.setEIDCrossBorderShare(String.valueOf(Boolean.valueOf(valueCrossBorderShare))); + extensions.getUnknownXMLObjects().add(eIdCrossBordShare); + } + + + // Add information about requested attributes. + LOG.debug("Generate RequestedAttributes."); + final RequestedAttributes reqAttributes = (RequestedAttributes) SAMLEngineUtils + .createSamlObject(RequestedAttributes.DEF_ELEMENT_NAME); + + LOG.debug("SAML Engine configuration properties load."); + final Iterator iterator = request + .getPersonalAttributeList().iterator(); + + while (iterator.hasNext()) { + + final PersonalAttribute attribute = iterator.next(); + + if (attribute == null || StringUtils.isBlank(attribute.getName())) { + LOG.error(ATTRIBUTE_EMPTY_LITERAL); + throw new STORKSAMLEngineException(ATTRIBUTE_EMPTY_LITERAL); + } + + // Verified if exits the attribute name. + final String attributeName = super.getSamlCoreProperties() + .getProperty(attribute.getName()); + + if (StringUtils.isBlank(attributeName)) { + LOG.debug("Attribute name: {} was not found.", attribute + .getName()); + throw new STORKSAMLEngineException("Attribute name: " + + attribute.getName() + " was not found."); + } + + // Friendly name it's an optional attribute. + String friendlyName = null; + + if (super.getSamlCoreProperties().isFriendlyName()) { + friendlyName = attribute.getName(); + } + + + String isRequired = null; + if (super.getSamlCoreProperties().isRequired()) { + isRequired = String.valueOf(attribute.isRequired()); + } + + + LOG.debug("Generate requested attribute: " + attributeName); + final RequestedAttribute requestedAttr = SAMLEngineUtils + .generateReqAuthnAttributeSimple(attributeName, + friendlyName, isRequired, attribute + .getValue()); + + // Add requested attribute. + reqAttributes.getAttributes().add(requestedAttr); + } + + // Add requested attributes. + extensions.getUnknownXMLObjects().add(reqAttributes); + + CitizenCountryCode citizenCountryCode = null; + if (request.getCitizenCountryCode() != null && StringUtils.isNotBlank(request.getCitizenCountryCode())){ + LOG.debug("Generate CitizenCountryCode"); + citizenCountryCode = (CitizenCountryCode) SAMLEngineUtils + .createSamlObject(CitizenCountryCode.DEF_ELEMENT_NAME); + + citizenCountryCode.setCitizenCountryCode(request + .getCitizenCountryCode().toUpperCase()); + } + + SPID spid = null; + if(request.getSPID()!=null && StringUtils.isNotBlank(request.getSPID())) { + LOG.debug("Generate SPID"); + spid = (SPID) SAMLEngineUtils + .createSamlObject(SPID.DEF_ELEMENT_NAME); + + spid.setSPID(request.getSPID().toUpperCase()); + } + + AuthenticationAttributes authenticationAttr = (AuthenticationAttributes) SAMLEngineUtils + .createSamlObject(AuthenticationAttributes.DEF_ELEMENT_NAME); + + final VIDPAuthenticationAttributes vIDPauthenticationAttr = (VIDPAuthenticationAttributes) SAMLEngineUtils + .createSamlObject(VIDPAuthenticationAttributes.DEF_ELEMENT_NAME); + + final SPInformation spInformation = (SPInformation) SAMLEngineUtils + .createSamlObject(SPInformation.DEF_ELEMENT_NAME); + + if(citizenCountryCode!=null){ + vIDPauthenticationAttr.setCitizenCountryCode(citizenCountryCode); + } + + if(spid!=null){ + spInformation.setSPID(spid); + } + + vIDPauthenticationAttr.setSPInformation(spInformation); + + authenticationAttr + .setVIDPAuthenticationAttributes(vIDPauthenticationAttr); + extensions.getUnknownXMLObjects().add(authenticationAttr); + + + return extensions; + + } + + /** + * Generate stork extensions. + * + * @param request the attribute query request + * + * @return the extensions + * + * @throws STORKSAMLEngineException the STORKSAML engine exception + */ + private Extensions generateSTORKAttrExtensions(final STORKAttrQueryRequest request) + throws STORKSAMLEngineException { + LOG.debug("Generate STORKExtensions"); + + final Extensions extensions = SAMLEngineUtils.generateExtension(); + + LOG.debug("Generate QAAAttribute"); + final QAAAttribute qaaAttribute = SAMLEngineUtils + .generateQAAAttribute(request.getQaa()); + extensions.getUnknownXMLObjects().add(qaaAttribute); + + + if (StringUtils.isNotEmpty(request + .getSpSector())) { + // Add information about service provider. + LOG.debug("Generate SPSector"); + final SPSector sector = SAMLEngineUtils.generateSPSector(request + .getSpSector()); + extensions.getUnknownXMLObjects().add(sector); + } + + + if (StringUtils.isNotEmpty(request.getSpApplication())) { + LOG.debug("Generate SPApplication"); + final SPApplication application = SAMLEngineUtils + .generateSPApplication(request.getSpApplication()); + extensions.getUnknownXMLObjects().add(application); + } + + if (StringUtils.isNotEmpty(request.getSpCountry())) { + LOG.debug("Generate SPCountry"); + final SPCountry country = SAMLEngineUtils.generateSPCountry(request + .getSpCountry()); + extensions.getUnknownXMLObjects().add(country); + } + + final EIDSectorShare eIdSectorShare = (EIDSectorShare) SAMLEngineUtils + .createSamlObject(EIDSectorShare.DEF_ELEMENT_NAME); + + eIdSectorShare.setEIDSectorShare(String.valueOf(request.isEIDSectorShare())); + + extensions.getUnknownXMLObjects().add(eIdSectorShare); + + final EIDCrossSectorShare eIdCrossSecShare = (EIDCrossSectorShare) SAMLEngineUtils + .createSamlObject(EIDCrossSectorShare.DEF_ELEMENT_NAME); + eIdCrossSecShare.setEIDCrossSectorShare(String.valueOf(request.isEIDCrossSectorShare())); + extensions.getUnknownXMLObjects().add(eIdCrossSecShare); + + final EIDCrossBorderShare eIdCrossBordShare = (EIDCrossBorderShare) SAMLEngineUtils + .createSamlObject(EIDCrossBorderShare.DEF_ELEMENT_NAME); + eIdCrossBordShare.setEIDCrossBorderShare(String.valueOf(request.isEIDCrossBorderShare())); + extensions.getUnknownXMLObjects().add(eIdCrossBordShare); + + + // Add information about requested attributes. + LOG.debug("Generate RequestedAttributes."); + final RequestedAttributes reqAttributes = (RequestedAttributes) SAMLEngineUtils + .createSamlObject(RequestedAttributes.DEF_ELEMENT_NAME); + + LOG.debug("SAML Engine configuration properties load."); + final Iterator iterator = request + .getPersonalAttributeList().iterator(); + + while (iterator.hasNext()) { + + final PersonalAttribute attribute = iterator.next(); + + if (attribute == null || StringUtils.isBlank(attribute.getName())) { + LOG.error(ATTRIBUTE_EMPTY_LITERAL); + throw new STORKSAMLEngineException(ATTRIBUTE_EMPTY_LITERAL); + } + + // Verified if exits the attribute name. + final String attributeName = super.getSamlCoreProperties() + .getProperty(attribute.getName()); + + if (StringUtils.isBlank(attributeName)) { + LOG.debug("Attribute name: {} was not found.", attribute + .getName()); + throw new STORKSAMLEngineException("Attribute name: " + + attribute.getName() + " was not found."); + } + + // Friendly name it's an optional attribute. + String friendlyName = null; + + if (super.getSamlCoreProperties().isFriendlyName()) { + friendlyName = attribute.getName(); + } + + + String isRequired = null; + if (super.getSamlCoreProperties().isRequired()) { + isRequired = String.valueOf(attribute.isRequired()); + } + + + LOG.debug("Generate requested attribute: " + attributeName); + final RequestedAttribute requestedAttr = SAMLEngineUtils + .generateReqAuthnAttributeSimple(attributeName, + friendlyName, isRequired, attribute + .getValue()); + + // Add requested attribute. + reqAttributes.getAttributes().add(requestedAttr); + } + + // Add requested attributes. + extensions.getUnknownXMLObjects().add(reqAttributes); + + CitizenCountryCode citizenCountryCode = null; + if (request.getCitizenCountryCode() != null && StringUtils.isNotBlank(request.getCitizenCountryCode())){ + LOG.debug("Generate CitizenCountryCode"); + citizenCountryCode = (CitizenCountryCode) SAMLEngineUtils + .createSamlObject(CitizenCountryCode.DEF_ELEMENT_NAME); + + citizenCountryCode.setCitizenCountryCode(request + .getCitizenCountryCode().toUpperCase()); + } + + SPID spid = null; + if(request.getSPID()!=null && StringUtils.isNotBlank(request.getSPID())) { + LOG.debug("Generate SPID"); + spid = (SPID) SAMLEngineUtils + .createSamlObject(SPID.DEF_ELEMENT_NAME); + + spid.setSPID(request.getSPID().toUpperCase()); + } + + + return extensions; + + } + + /** + * Gets the alias from X.509 Certificate at keystore. + * + * @param keyInfo the key info + * @param storkOwnKeyStore + * @param storkOwnKeyStore + * + * @return the alias + */ + private String getAlias(final KeyInfo keyInfo, KeyStore storkOwnKeyStore) { + + LOG.debug("Recover alias information"); + + String alias = null; + try { + final org.opensaml.xml.signature.X509Certificate xmlCert = keyInfo + .getX509Datas().get(0).getX509Certificates().get(0); + + // Transform the KeyInfo to X509Certificate. + CertificateFactory certFact; + certFact = CertificateFactory.getInstance("X.509"); + + final ByteArrayInputStream bis = new ByteArrayInputStream(Base64 + .decode(xmlCert.getValue())); + + final X509Certificate cert = (X509Certificate) certFact + .generateCertificate(bis); + + final String tokenSerialNumber = cert.getSerialNumber().toString(16); + final X509Principal tokenIssuerDN = new X509Principal(cert.getIssuerDN().getName()); + + + String aliasCert; + X509Certificate certificate; + boolean find = false; + + for (final Enumeration e = storkOwnKeyStore.aliases(); e + .hasMoreElements() + && !find; ) { + aliasCert = e.nextElement(); + certificate = (X509Certificate) storkOwnKeyStore + .getCertificate(aliasCert); + + final String serialNum = certificate.getSerialNumber() + .toString(16); + + X509Principal issuerDN = new X509Principal(certificate + .getIssuerDN().getName()); + + if(serialNum.equalsIgnoreCase(tokenSerialNumber) + && X509PrincipalUtil.equals2(issuerDN, tokenIssuerDN)){ + alias = aliasCert; + find = true; + } + + } + + } catch (KeyStoreException e) { + LOG.error("Procces getAlias from certificate associated into the signing keystore..", e); + } catch (CertificateException e) { + LOG.error("Procces getAlias from certificate associated into the signing keystore..", e); + } catch (RuntimeException e) { + LOG.error("Procces getAlias from certificate associated into the signing keystore..", e); + } + return alias; + } + + /** + * Gets the country from X.509 Certificate. + * + * @param keyInfo the key info + * + * @return the country + */ + private String getCountry(final KeyInfo keyInfo) { + LOG.debug("Recover country information."); + + String result = ""; + try { + final org.opensaml.xml.signature.X509Certificate xmlCert = keyInfo + .getX509Datas().get(0).getX509Certificates().get(0); + + // Transform the KeyInfo to X509Certificate. + CertificateFactory certFact; + certFact = CertificateFactory.getInstance("X.509"); + + final ByteArrayInputStream bis = new ByteArrayInputStream(Base64 + .decode(xmlCert.getValue())); + + final X509Certificate cert = (X509Certificate) certFact + .generateCertificate(bis); + + String distName = cert.getSubjectDN().toString(); + + distName = StringUtils.deleteWhitespace(StringUtils + .upperCase(distName)); + + final String countryCode = "C="; + final int init = distName.indexOf(countryCode); + + if (init > StringUtils.INDEX_NOT_FOUND) { // Exist country code. + int end = distName.indexOf(',', init); + + if (end <= StringUtils.INDEX_NOT_FOUND) { + end = distName.length(); + } + + if (init < end && end > StringUtils.INDEX_NOT_FOUND) { + result = distName.substring(init + countryCode.length(), + end); + //It must be a two characters value + if(result.length()>2){ + result = result.substring(0, 2); + } + } + } + + } catch (CertificateException e) { + LOG.error("Procces getCountry from certificate."); + } + return result.trim(); + } + + /** + * Process all elements XMLObjects from the extensions. + * + * @param extensions the extensions from the authentication request. + * + * @return the STORK authentication request + * + * @throws STORKSAMLEngineException the STORKSAML engine exception + */ + private STORKAuthnRequest processExtensions(final Extensions extensions) + throws STORKSAMLEngineException { + LOG.debug("Procces the extensions."); + + final STORKAuthnRequest request = new STORKAuthnRequest(); + + final QAAAttribute qaa = (QAAAttribute) extensions + .getUnknownXMLObjects(QAAAttribute.DEF_ELEMENT_NAME).get(0); + request.setQaa(Integer.parseInt(qaa.getQaaLevel())); + + List optionalElements = extensions.getUnknownXMLObjects( + SPSector.DEF_ELEMENT_NAME); + + if (!optionalElements.isEmpty()) { + final SPSector sector = (SPSector) extensions.getUnknownXMLObjects( + SPSector.DEF_ELEMENT_NAME).get(0); + request.setSpSector(sector.getSPSector()); + } + + optionalElements = extensions.getUnknownXMLObjects(SPApplication.DEF_ELEMENT_NAME); + + if (!optionalElements.isEmpty()) { + final SPApplication application = (SPApplication) extensions + .getUnknownXMLObjects(SPApplication.DEF_ELEMENT_NAME).get(0); + request.setSpApplication(application.getSPApplication()); + } + + optionalElements = extensions.getUnknownXMLObjects(SPCountry.DEF_ELEMENT_NAME); + + if (!optionalElements.isEmpty()) { + final SPCountry application = (SPCountry) extensions + .getUnknownXMLObjects(SPCountry.DEF_ELEMENT_NAME).get(0); + request.setSpCountry(application.getSPCountry()); + } + + + List listCrossBorderShare = extensions + .getUnknownXMLObjects(EIDCrossBorderShare.DEF_ELEMENT_NAME); + + if (!listCrossBorderShare .isEmpty()) { + final EIDCrossBorderShare crossBorderShare = (EIDCrossBorderShare) listCrossBorderShare.get(0); + request.setEIDCrossBorderShare(Boolean.parseBoolean(crossBorderShare + .getEIDCrossBorderShare())); + } + + + List listCrosSectorShare = extensions + .getUnknownXMLObjects(EIDCrossSectorShare.DEF_ELEMENT_NAME); + + if (!listCrosSectorShare.isEmpty()) { + final EIDCrossSectorShare crossSectorShare = (EIDCrossSectorShare) listCrosSectorShare.get(0); + request.setEIDCrossSectorShare(Boolean.parseBoolean(crossSectorShare + .getEIDCrossSectorShare())); + } + + List listSectorShareExtension = extensions + .getUnknownXMLObjects(EIDSectorShare.DEF_ELEMENT_NAME); + if (!listSectorShareExtension.isEmpty()) { + final EIDSectorShare sectorShare = (EIDSectorShare) listSectorShareExtension.get(0); + request.setEIDSectorShare(Boolean.parseBoolean(sectorShare.getEIDSectorShare())); + } + + + + List authAttrs = extensions + .getUnknownXMLObjects(AuthenticationAttributes.DEF_ELEMENT_NAME); + + if (authAttrs != null && !authAttrs.isEmpty()) { + + final AuthenticationAttributes authnAttr = (AuthenticationAttributes) authAttrs + .get(0); + + VIDPAuthenticationAttributes vidpAuthnAttr = null; + if (authnAttr != null && !authAttrs.isEmpty()){ + vidpAuthnAttr = authnAttr.getVIDPAuthenticationAttributes(); + } + + CitizenCountryCode citizenCountryCodeElement = null; + SPInformation spInformation = null; + if (vidpAuthnAttr != null){ + citizenCountryCodeElement = vidpAuthnAttr.getCitizenCountryCode(); + spInformation = vidpAuthnAttr.getSPInformation(); + } + + String citizenCountryCode = null; + if(citizenCountryCodeElement!=null){ + citizenCountryCode = citizenCountryCodeElement.getCitizenCountryCode(); + } + + if(citizenCountryCode!= null && StringUtils.isNotBlank(citizenCountryCode)){ + request.setCitizenCountryCode(citizenCountryCode); + } + + SPID spidElement = null; + if (spInformation != null){ + spidElement = spInformation.getSPID(); + } + + String spid = null; + if(spidElement!=null){ + spid = spidElement.getSPID(); + } + + if (spid != null && StringUtils.isNotBlank(spid)) { + request.setSPID(spid); + } + } + + if (extensions + .getUnknownXMLObjects(RequestedAttributes.DEF_ELEMENT_NAME) == null) { + LOG.error("Extensions not contains any requested attribute."); + throw new STORKSAMLEngineException( + "Extensions not contains any requested attribute."); + } + + final RequestedAttributes requestedAttr = (RequestedAttributes) extensions + .getUnknownXMLObjects(RequestedAttributes.DEF_ELEMENT_NAME) + .get(0); + + final List reqAttrs = requestedAttr.getAttributes(); + + final IPersonalAttributeList personalAttrList = new PersonalAttributeList(); + + String attributeName; + for (int nextAttribute = 0; nextAttribute < reqAttrs.size(); nextAttribute++) { + final RequestedAttribute attribute = reqAttrs.get(nextAttribute); + final PersonalAttribute personalAttribute = new PersonalAttribute(); + personalAttribute.setIsRequired(Boolean.valueOf(attribute.isRequired())); + personalAttribute.setFriendlyName(attribute.getFriendlyName()); + attributeName = attribute.getName(); + + // recover the last name from the string. + personalAttribute.setName(attributeName.substring(attributeName + .lastIndexOf('/') + 1)); + + final ArrayList valores = new ArrayList(); + final List values = attribute.getOrderedChildren(); + + for (int nextSimpleValue = 0; nextSimpleValue < values.size(); nextSimpleValue++) { + + // Process attributes simples. An AuthenticationRequest only + // must contains simple values. + + final XMLObject xmlObject = values.get(nextSimpleValue); + + if(xmlObject instanceof XSStringImpl){ + + final XSStringImpl xmlString = (XSStringImpl) values + .get(nextSimpleValue); + valores.add(xmlString.getValue()); + + }else{ + + if (attributeName.equals("http://www.stork.gov.eu/1.0/signedDoc")) { + + final XSAnyImpl xmlString = (XSAnyImpl) values + .get(nextSimpleValue); + + TransformerFactory transFactory = TransformerFactory.newInstance(); + Transformer transformer = null; + try { + transformer = transFactory.newTransformer(); + transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); + } catch (TransformerConfigurationException e) { + LOG.error("Error transformer configuration exception", e); + } + StringWriter buffer = new StringWriter(); + try { + if (xmlString != null && xmlString.getUnknownXMLObjects() != null && xmlString.getUnknownXMLObjects().size() > 0 ){ + transformer.transform(new DOMSource(xmlString.getUnknownXMLObjects().get(0).getDOM()), + new StreamResult(buffer)); + } + } catch (TransformerException e) { + LOG.error("Error transformer exception", e); + } + String str = buffer.toString(); + + valores.add(str); + + }else{ + + final XSAnyImpl xmlString = (XSAnyImpl) values + .get(nextSimpleValue); + valores.add(xmlString.getTextContent()); + } + + + + } + } + personalAttribute.setValue(valores); + personalAttrList.add(personalAttribute); + } + + request.setPersonalAttributeList(personalAttrList); + + return request; + } + + + /** + * Process all elements XMLObjects from the extensions. + * + * @param extensions the extensions from the authentication request. + * + * @return the STORK authentication request + * + * @throws STORKSAMLEngineException the STORKSAML engine exception + */ + private STORKAttrQueryRequest processAttrExtensions(final Extensions extensions) + throws STORKSAMLEngineException { + LOG.debug("Procces the atribute query extensions."); + + final STORKAttrQueryRequest request = new STORKAttrQueryRequest(); + + final QAAAttribute qaa = (QAAAttribute) extensions + .getUnknownXMLObjects(QAAAttribute.DEF_ELEMENT_NAME).get(0); + request.setQaa(Integer.parseInt(qaa.getQaaLevel())); + + List optionalElements = extensions.getUnknownXMLObjects( + SPSector.DEF_ELEMENT_NAME); + + if (!optionalElements.isEmpty()) { + final SPSector sector = (SPSector) extensions.getUnknownXMLObjects( + SPSector.DEF_ELEMENT_NAME).get(0); + request.setSpSector(sector.getSPSector()); + } + + optionalElements = extensions.getUnknownXMLObjects(SPApplication.DEF_ELEMENT_NAME); + + if (!optionalElements.isEmpty()) { + final SPApplication application = (SPApplication) extensions + .getUnknownXMLObjects(SPApplication.DEF_ELEMENT_NAME).get(0); + request.setSpApplication(application.getSPApplication()); + } + + optionalElements = extensions.getUnknownXMLObjects(SPCountry.DEF_ELEMENT_NAME); + + if (!optionalElements.isEmpty()) { + final SPCountry application = (SPCountry) extensions + .getUnknownXMLObjects(SPCountry.DEF_ELEMENT_NAME).get(0); + request.setSpCountry(application.getSPCountry()); + } + + + List listCrossBorderShare = extensions + .getUnknownXMLObjects(EIDCrossBorderShare.DEF_ELEMENT_NAME); + + if (!listCrossBorderShare .isEmpty()) { + final EIDCrossBorderShare crossBorderShare = (EIDCrossBorderShare) listCrossBorderShare.get(0); + request.setEIDCrossBorderShare(Boolean.parseBoolean(crossBorderShare + .getEIDCrossBorderShare())); + } + + + List listCrosSectorShare = extensions + .getUnknownXMLObjects(EIDCrossSectorShare.DEF_ELEMENT_NAME); + + if (!listCrosSectorShare.isEmpty()) { + final EIDCrossSectorShare crossSectorShare = (EIDCrossSectorShare) listCrosSectorShare.get(0); + request.setEIDCrossSectorShare(Boolean.parseBoolean(crossSectorShare + .getEIDCrossSectorShare())); + } + + List listSectorShareExtension = extensions + .getUnknownXMLObjects(EIDSectorShare.DEF_ELEMENT_NAME); + if (!listSectorShareExtension.isEmpty()) { + final EIDSectorShare sectorShare = (EIDSectorShare) listSectorShareExtension.get(0); + request.setEIDSectorShare(Boolean.parseBoolean(sectorShare.getEIDSectorShare())); + } + + + + List authAttrs = extensions + .getUnknownXMLObjects(AuthenticationAttributes.DEF_ELEMENT_NAME); + + if (authAttrs != null && !authAttrs.isEmpty()) { + + final AuthenticationAttributes authnAttr = (AuthenticationAttributes) authAttrs + .get(0); + + VIDPAuthenticationAttributes vidpAuthnAttr = null; + if (authnAttr != null && !authAttrs.isEmpty()){ + vidpAuthnAttr = authnAttr.getVIDPAuthenticationAttributes(); + } + + CitizenCountryCode citizenCountryCodeElement = null; + SPInformation spInformation = null; + if (vidpAuthnAttr != null){ + citizenCountryCodeElement = vidpAuthnAttr.getCitizenCountryCode(); + spInformation = vidpAuthnAttr.getSPInformation(); + } + + String citizenCountryCode = null; + if(citizenCountryCodeElement!=null){ + citizenCountryCode = citizenCountryCodeElement.getCitizenCountryCode(); + } + + if(citizenCountryCode!= null && StringUtils.isNotBlank(citizenCountryCode)){ + request.setCitizenCountryCode(citizenCountryCode); + } + + SPID spidElement = null; + if (spInformation != null){ + spidElement = spInformation.getSPID(); + } + + String spid = null; + if(spidElement!=null){ + spid = spidElement.getSPID(); + } + + if (spid != null && StringUtils.isNotBlank(spid)) { + request.setSPID(spid); + } + } + + if (extensions + .getUnknownXMLObjects(RequestedAttributes.DEF_ELEMENT_NAME) == null) { + LOG.error("Extensions not contains any requested attribute."); + throw new STORKSAMLEngineException( + "Extensions not contains any requested attribute."); + } + + final RequestedAttributes requestedAttr = (RequestedAttributes) extensions + .getUnknownXMLObjects(RequestedAttributes.DEF_ELEMENT_NAME) + .get(0); + + final List reqAttrs = requestedAttr.getAttributes(); + + final IPersonalAttributeList personalAttrList = new PersonalAttributeList(); + + String attributeName; + for (int nextAttribute = 0; nextAttribute < reqAttrs.size(); nextAttribute++) { + final RequestedAttribute attribute = reqAttrs.get(nextAttribute); + final PersonalAttribute personalAttribute = new PersonalAttribute(); + personalAttribute.setIsRequired(Boolean.valueOf(attribute.isRequired())); + personalAttribute.setFriendlyName(attribute.getFriendlyName()); + attributeName = attribute.getName(); + + // recover the last name from the string. + personalAttribute.setName(attributeName.substring(attributeName + .lastIndexOf('/') + 1)); + + final ArrayList valores = new ArrayList(); + final List values = attribute.getOrderedChildren(); + + for (int nextSimpleValue = 0; nextSimpleValue < values.size(); nextSimpleValue++) { + + // Process attributes simples. An AuthenticationRequest only + // must contains simple values. + + final XMLObject xmlObject = values.get(nextSimpleValue); + + if(xmlObject instanceof XSStringImpl){ + + final XSStringImpl xmlString = (XSStringImpl) values + .get(nextSimpleValue); + valores.add(xmlString.getValue()); + + }else{ + + if (attributeName.equals("http://www.stork.gov.eu/1.0/signedDoc")) { + + final XSAnyImpl xmlString = (XSAnyImpl) values + .get(nextSimpleValue); + + TransformerFactory transFactory = TransformerFactory.newInstance(); + Transformer transformer = null; + try { + transformer = transFactory.newTransformer(); + transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); + } catch (TransformerConfigurationException e) { + LOG.error("Error transformer configuration exception", e); + } + StringWriter buffer = new StringWriter(); + try { + if (xmlString != null && xmlString.getUnknownXMLObjects() != null && xmlString.getUnknownXMLObjects().size() > 0 ){ + transformer.transform(new DOMSource(xmlString.getUnknownXMLObjects().get(0).getDOM()), + new StreamResult(buffer)); + } + } catch (TransformerException e) { + LOG.error("Error transformer exception", e); + } + String str = buffer.toString(); + + valores.add(str); + + }else{ + + final XSAnyImpl xmlString = (XSAnyImpl) values + .get(nextSimpleValue); + valores.add(xmlString.getTextContent()); + } + + + + } + } + personalAttribute.setValue(valores); + personalAttrList.add(personalAttribute); + } + + request.setPersonalAttributeList(personalAttrList); + + return request; + } + + /** + * Sets the name spaces. + * + * @param tokenSaml the new name spaces + */ + private void setNameSpaces(final XMLObject tokenSaml) { + LOG.debug("Set namespaces."); + + final Namespace saml2 = new Namespace(SAMLConstants.SAML20_NS, + SAMLConstants.SAML20_PREFIX); + tokenSaml.addNamespace(saml2); + + final Namespace digSig = new Namespace( + "http://www.w3.org/2000/09/xmldsig#", "ds"); + tokenSaml.addNamespace(digSig); + + final Namespace storkp = new Namespace(SAMLCore.STORK10P_NS.getValue(), + SAMLCore.STORK10P_PREFIX.getValue()); + tokenSaml.addNamespace(storkp); + + final Namespace stork = new Namespace(SAMLCore.STORK10_NS.getValue(), + SAMLCore.STORK10_PREFIX.getValue()); + + tokenSaml.addNamespace(stork); + } + + /** + * Validate parameters from authentication request. + * + * @param request the request. + * + * @throws STORKSAMLEngineException the STORKSAML engine exception + */ + private void validateParamAuthnReq(final STORKAuthnRequest request) + throws STORKSAMLEngineException { + LOG.info("Validate parameters from authentication request."); + + // URL to which Authentication 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())) { + throw new STORKSAMLEngineException( + "StorkSamlEngine: Service Provider it's mandatory."); + } + + // object that contain all attributes requesting. + if (request.getPersonalAttributeList() == null + || request.getPersonalAttributeList().isEmpty()) { + throw new STORKSAMLEngineException( + "attributeQueries is null or empty."); + } + + // Quality authentication assurance level. + if ((request.getQaa() < QAAAttribute.MIN_VALUE) + || (request.getQaa() > QAAAttribute.MAX_VALUE)) { + throw new STORKSAMLEngineException("Qaal: " + request.getQaa() + + ", is invalid."); + } + + } + + /** + * Validate parameters from authentication request. + * + * @param request the request. + * + * @throws STORKSAMLEngineException the STORKSAML engine exception + */ + private void validateParamAttrQueryReq(final STORKAttrQueryRequest request) + throws STORKSAMLEngineException { + LOG.info("Validate parameters from attribute query request."); + + // URL to which Authentication 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())) { + throw new STORKSAMLEngineException( + "StorkSamlEngine: Service Provider it's mandatory."); + }*/ + + // object that contain all attributes requesting. + if (request.getPersonalAttributeList() == null + || request.getPersonalAttributeList().isEmpty()) { + throw new STORKSAMLEngineException( + "attributeQueries is null or empty."); + } + + // Quality authentication assurance level. + if ((request.getQaa() < QAAAttribute.MIN_VALUE) + || (request.getQaa() > QAAAttribute.MAX_VALUE)) { + throw new STORKSAMLEngineException("Qaal: " + request.getQaa() + + ", is invalid."); + } + + } + + + /** + * Validate parameters from response. + * + * @param request the request + * @param responseAuthReq the response authentication request + * + * @throws STORKSAMLEngineException the STORKSAML engine exception + */ + private void validateParamResponse(final STORKAuthnRequest request, + final STORKAuthnResponse responseAuthReq) + throws STORKSAMLEngineException { + LOG.info("Validate parameters response."); + if (StringUtils.isBlank(request.getIssuer())) { + throw new STORKSAMLEngineException( + "Issuer must be not empty or null."); + } + + if (responseAuthReq.getPersonalAttributeList() == null + || responseAuthReq.getPersonalAttributeList().isEmpty()) { + LOG.error("PersonalAttributeList is null or empty."); + throw new STORKSAMLEngineException( + "PersonalAttributeList is null or empty."); + } + + if (StringUtils.isBlank(request.getAssertionConsumerServiceURL())) { + throw new STORKSAMLEngineException( + "assertionConsumerServiceURL is null or empty."); + } + + if (StringUtils.isBlank(request.getSamlId())) { + throw new STORKSAMLEngineException("request ID is null or empty."); + } + } + + /** + * Validate parameters from response. + * + * @param request the request + * @param responseAttrQueryReq the response authentication request + * + * @throws STORKSAMLEngineException the STORKSAML engine exception + */ + private void validateParamAttrQueryResponse(final STORKAttrQueryRequest request, + final STORKAttrQueryResponse responseAttrQueryReq) + throws STORKSAMLEngineException { + LOG.info("Validate attribute querey parameters response."); + if (StringUtils.isBlank(request.getIssuer())) { + throw new STORKSAMLEngineException( + "Issuer must be not empty or null."); + } + + if (responseAttrQueryReq.getPersonalAttributeList() == null + || responseAttrQueryReq.getPersonalAttributeList().isEmpty()) { + LOG.error("PersonalAttributeList is null or empty."); + throw new STORKSAMLEngineException( + "PersonalAttributeList is null or empty."); + } + + /*if (StringUtils.isBlank(request.getAssertionConsumerServiceURL())) { + throw new STORKSAMLEngineException( + "assertionConsumerServiceURL is null or empty."); + }*/ + + if (StringUtils.isBlank(request.getSamlId())) { + 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 validateParamResponseFail(final STORKAuthnRequest request, + final STORKAuthnResponse response) throws STORKSAMLEngineException { + LOG.info("Validate parameters response fail."); + if (StringUtils.isBlank(response.getStatusCode())) { + throw new STORKSAMLEngineException("Code error it's null or empty."); + } + + if (StringUtils.isBlank(request.getAssertionConsumerServiceURL())) { + throw new STORKSAMLEngineException( + "assertionConsumerServiceURL is null or empty."); + } + + if (StringUtils.isBlank(request.getSamlId())) { + 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 validateParamAttrQueryResponseFail(final STORKAttrQueryRequest request, + final STORKAttrQueryResponse response) throws STORKSAMLEngineException { + LOG.info("Validate parameters response fail."); + 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. + * + * @param tokenSaml the token SAML + * + * @return the sTORK authentication request + * + * @throws STORKSAMLEngineException the STORKSAML engine exception + */ + public STORKAuthnRequest validateSTORKAuthnRequest(final byte[] tokenSaml) + throws STORKSAMLEngineException { + LOG.info("validateSTORKAuthnRequest"); + + final AuthnRequest samlRequest = (AuthnRequest) 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 STORKAuthnRequest."); + final STORKAuthnRequest authnRequest = processExtensions(samlRequest + .getExtensions()); + + authnRequest.setCountry(this.getCountry(samlRequest.getSignature() + .getKeyInfo())); + + authnRequest.setAlias(this.getAlias(samlRequest.getSignature() + .getKeyInfo(), super.getSigner().getTrustStore())); + + authnRequest.setSamlId(samlRequest.getID()); + authnRequest.setDestination(samlRequest.getDestination()); + authnRequest.setAssertionConsumerServiceURL(samlRequest + .getAssertionConsumerServiceURL()); + + authnRequest.setProviderName(samlRequest.getProviderName()); + authnRequest.setIssuer(samlRequest.getIssuer().getValue()); + + //Delete unknown elements from requested ones + final Iterator iterator = authnRequest.getPersonalAttributeList().iterator(); + IPersonalAttributeList cleanPerAttrList = (PersonalAttributeList) authnRequest.getPersonalAttributeList(); + while (iterator.hasNext()) { + + final PersonalAttribute attribute = iterator.next(); + + // Verify if the attribute name exits. + final String attributeName = super.getSamlCoreProperties() + .getProperty(attribute.getName()); + + if (StringUtils.isBlank(attributeName)) { + LOG.info("Attribute name: {} was not found. It will be removed from the request object", attribute.getName()); + cleanPerAttrList.remove(attribute.getName()); + } + + } + authnRequest.setPersonalAttributeList(cleanPerAttrList); + + return authnRequest; + + } + + /** + * Validate stork authentication request. + * + * @param tokenSaml the token SAML + * + * @return the sTORK authentication request + * + * @throws STORKSAMLEngineException the STORKSAML engine exception + */ + public STORKAttrQueryRequest validateSTORKAttrQueryRequest(final byte[] tokenSaml) + throws STORKSAMLEngineException { + LOG.info("validateSTORKAttrQueryRequest"); + + final AttributeQuery samlRequest = (AttributeQuery) 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 STORKAttrQueryRequest."); + final STORKAttrQueryRequest attrRequest = processAttrExtensions(samlRequest + .getExtensions()); + + attrRequest.setCountry(this.getCountry(samlRequest.getSignature() + .getKeyInfo())); + + attrRequest.setAlias(this.getAlias(samlRequest.getSignature() + .getKeyInfo(), super.getSigner().getTrustStore())); + + attrRequest.setSamlId(samlRequest.getID()); + attrRequest.setDestination(samlRequest.getDestination()); + /*attrRequest.setAssertionConsumerServiceURL(samlRequest + .getAssertionConsumerServiceURL()); + + authnRequest.setProviderName(samlRequest.getProviderName());*/ + attrRequest.setIssuer(samlRequest.getIssuer().getValue()); + + //Delete unknown elements from requested ones + final Iterator iterator = attrRequest.getPersonalAttributeList().iterator(); + IPersonalAttributeList cleanPerAttrList = (PersonalAttributeList) attrRequest.getPersonalAttributeList(); + while (iterator.hasNext()) { + + final PersonalAttribute attribute = iterator.next(); + + // Verify if the attribute name exits. + final String attributeName = super.getSamlCoreProperties() + .getProperty(attribute.getName()); + + if (StringUtils.isBlank(attributeName)) { + LOG.info("Attribute name: {} was not found. It will be removed from the request object", attribute.getName()); + cleanPerAttrList.remove(attribute.getName()); + } + + } + attrRequest.setPersonalAttributeList(cleanPerAttrList); + + return attrRequest; + + } + + /** + * 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 validateSTORKAuthnResponse( + 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); + + 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()); + } + + // 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 attribute query response. + * + * @param tokenSaml the token SAML + * @param userIP the user IP + * + * @return the Stork attribute query response + * + * @throws STORKSAMLEngineException the STORKSAML engine exception + */ + public STORKAttrQueryResponse validateSTORKAttrQueryResponse( + final byte[] tokenSaml, final String userIP) + throws STORKSAMLEngineException { + + LOG.info("validateSTORKAttrQueryResponse"); + final Response samlResponse = (Response) validateStorkSaml(tokenSaml); + + LOG.debug("Create StorkAttrQueryResponse."); + final STORKAttrQueryResponse attrQueryResponse = new STORKAttrQueryResponse(); + + attrQueryResponse.setCountry(this.getCountry(samlResponse.getSignature() + .getKeyInfo())); + + LOG.debug("Set ID."); + attrQueryResponse.setSamlId(samlResponse.getID()); + LOG.debug("Set InResponseTo."); + attrQueryResponse.setInResponseTo(samlResponse.getInResponseTo()); + LOG.debug("Set statusCode."); + attrQueryResponse.setStatusCode(samlResponse.getStatus().getStatusCode() + .getValue()); + + // Subordinate code. + if (samlResponse.getStatus().getStatusCode().getStatusCode() != null) { + attrQueryResponse.setSubStatusCode(samlResponse.getStatus() + .getStatusCode().getStatusCode().getValue()); + } + + if (samlResponse.getStatus().getStatusMessage() != null) { + LOG.debug("Set statusMessage."); + attrQueryResponse.setMessage(samlResponse.getStatus() + .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."); + attrQueryResponse.setNotOnOrAfter(assertion.getConditions() + .getNotOnOrAfter()); + + LOG.debug("Set notBefore."); + attrQueryResponse.setNotBefore(assertion.getConditions().getNotBefore()); + + attrQueryResponse.setNotBefore(assertion.getConditions().getNotBefore()); + + attrQueryResponse.setAudienceRestriction(((AudienceRestriction) assertion + .getConditions().getAudienceRestrictions().get(0)) + .getAudiences().get(0).getAudienceURI()); + } + + // Case no error. + if (assertion!=null && StatusCode.SUCCESS_URI.equalsIgnoreCase(attrQueryResponse + .getStatusCode())) { + LOG.debug("Status Success. Set PersonalAttributeList."); + attrQueryResponse + .setPersonalAttributeList(generatePersonalAttributeList(assertion)); + attrQueryResponse.setFail(false); + } else { + LOG.debug("Status Fail."); + attrQueryResponse.setFail(true); + } + LOG.debug("Return result."); + return attrQueryResponse; + + } + + /** + * Validate stork response. + * + * @param samlResponse the SAML response + * @param userIP the user IP + * + * @return the assertion + * + * @throws STORKSAMLEngineException the STORKSAML engine exception + */ + private Assertion validateStorkResponse(final Response samlResponse, + final String userIP) throws STORKSAMLEngineException { + // Exist only one Assertion + + if (samlResponse.getAssertions() == null + || samlResponse.getAssertions().isEmpty()) { + LOG.info("Assertion is null or empty."); //in replace of throw new STORKSAMLEngineException("Assertion is null or empty.") + return null; + } + + final Assertion assertion = (Assertion) samlResponse.getAssertions() + .get(0); + + LOG.debug("Verified method Bearer"); + for (final Iterator iter = assertion.getSubject() + .getSubjectConfirmations().iterator(); iter.hasNext();) { + final SubjectConfirmation element = iter.next(); + final boolean isBearer = SubjectConfirmation.METHOD_BEARER + .equals(element.getMethod()); + + final boolean ipValidate = super.getSamlCoreProperties() + .isIpValidation(); + + if (ipValidate) { + if (isBearer) { + if (StringUtils.isBlank(userIP)) { + LOG.error("browser_ip is null or empty."); + throw new STORKSAMLEngineException( + "browser_ip is null or empty."); + } else if (StringUtils.isBlank(element + .getSubjectConfirmationData().getAddress())) { + LOG.error("token_ip attribute is null or empty."); + throw new STORKSAMLEngineException( + "token_ip attribute is null or empty."); + } + } + + final boolean ipEqual = element.getSubjectConfirmationData() + .getAddress().equals(userIP); + + // Validation ipUser + if (!ipEqual && ipValidate) { + LOG.error("SubjectConfirmation BEARER: "); + throw new STORKSAMLEngineException( + "IPs doesn't match : token_ip (" + + element.getSubjectConfirmationData() + .getAddress() + ") browser_ip (" + + userIP + ")"); + } + } + + } + return assertion; + } + + /** + * Validate stork SAML. + * + * @param tokenSaml the token SAML + * + * @return the signable SAML object + * + * @throws STORKSAMLEngineException the STORKSAML engine exception + */ + private SignableSAMLObject validateStorkSaml(final byte[] tokenSaml) + throws STORKSAMLEngineException { + + LOG.info("Validate StorkSaml message."); + + if (tokenSaml == null) { + LOG.error("Saml authentication request is null."); + throw new STORKSAMLEngineException( + "Saml authentication request is null."); + } + + LOG.debug("Generate AuthnRequest from request."); + SignableSAMLObject samlObject; + + try { + samlObject = (SignableSAMLObject) super.unmarshall(tokenSaml); + } catch (SAMLEngineException e) { + LOG.error("SAMLEngineException unmarshall.", e); + throw new STORKSAMLEngineException(e); + } + + boolean validateSign = true; + + if (StringUtils.isNotBlank(super.getSamlCoreProperties().getProperty( + "validateSignature"))) { + validateSign = Boolean.valueOf(super.getSamlCoreProperties() + .getProperty("validateSignature")); + } + + if (validateSign) { + LOG.debug("Validate Signature."); + try { + super.validateSignature(samlObject); + } catch (SAMLEngineException e) { + LOG.error("SAMLEngineException validateSignature.", e); + throw new STORKSAMLEngineException(e); + } + } + + LOG.debug("Validate Schema."); + final ValidatorSuite validatorSuite = Configuration + .getValidatorSuite("saml2-core-schema-validator"); + try { + validatorSuite.validate(samlObject); + } catch (ValidationException e) { + LOG.error("ValidationException.", e); + throw new STORKSAMLEngineException(e); + } + + return samlObject; + } +} diff --git a/id/server/stork2-saml-engine/src/main/java/eu/stork/peps/auth/engine/.svn/text-base/X509PrincipalUtil.java.svn-base b/id/server/stork2-saml-engine/src/main/java/eu/stork/peps/auth/engine/.svn/text-base/X509PrincipalUtil.java.svn-base new file mode 100644 index 000000000..e38cc5f0b --- /dev/null +++ b/id/server/stork2-saml-engine/src/main/java/eu/stork/peps/auth/engine/.svn/text-base/X509PrincipalUtil.java.svn-base @@ -0,0 +1,69 @@ +package eu.stork.peps.auth.engine; + +import org.bouncycastle.asn1.DERObjectIdentifier; +import org.bouncycastle.jce.X509Principal; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Utility class used to decrease complexity of comparison of 2 X509principal + * + * @author vanegdi + * @version $Revision: 1.00 $, $Date: 2013-05-24 20:53:51 $ + */ +public final class X509PrincipalUtil{ + + private static final DERObjectIdentifier[] DER_OBJECT_IDENTIFIERS_ARRAY= { + X509Principal.CN, + X509Principal.OU, + X509Principal.O, + X509Principal.L, + X509Principal.ST, + X509Principal.C, + X509Principal.E + }; + + private static final Logger LOG = LoggerFactory.getLogger(eu.stork.peps.auth.engine.X509PrincipalUtil.class); + + /** + * Compares 2 X509Principals to detect if they equals + * @param principal1 + * @param principal2 + * @return true if arguments are not null and equals + */ + public static boolean equals(X509Principal principal1, X509Principal principal2) { + boolean continueProcess = true; + if (principal1 == null || principal2 == null){ + return false; + } + + int cpt = 0; + while(continueProcess && cpt < DER_OBJECT_IDENTIFIERS_ARRAY.length){ + continueProcess = continueProcess && x509ValuesByIdentifierEquals(principal1, principal2, DER_OBJECT_IDENTIFIERS_ARRAY[cpt]); + cpt++; + } + return continueProcess; + } + + public static boolean equals2(X509Principal principal1, X509Principal principal2) { + + if (principal1 == null || principal2 == null){ + return false; + } + + if (principal1.getName().equals(principal2.getName())) + return true; + else + return false; + + } + + private static boolean x509ValuesByIdentifierEquals(X509Principal principal1, X509Principal principal2, DERObjectIdentifier identifier){ + return principal1.getValues(identifier).equals(principal2.getValues(identifier)); + } + + private X509PrincipalUtil(){ + // default contructor + LOG.error("Fake X509PrincipalUtil : never be called"); + } +} diff --git a/id/server/stork2-saml-engine/src/main/java/eu/stork/peps/auth/engine/.svn/text-base/package-info.java.svn-base b/id/server/stork2-saml-engine/src/main/java/eu/stork/peps/auth/engine/.svn/text-base/package-info.java.svn-base new file mode 100644 index 000000000..d3e353e51 --- /dev/null +++ b/id/server/stork2-saml-engine/src/main/java/eu/stork/peps/auth/engine/.svn/text-base/package-info.java.svn-base @@ -0,0 +1,19 @@ +/* + * 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/european-union-public-licence-eupl-v.1.1 + * + * 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. + */ + +/** + * Provides the classes necessary to create a SAML message. + */ +package eu.stork.peps.auth.engine; \ No newline at end of file -- cgit v1.2.3