diff options
Diffstat (limited to 'id/server/modules/moa-id-modules-saml1')
13 files changed, 2473 insertions, 0 deletions
| diff --git a/id/server/modules/moa-id-modules-saml1/pom.xml b/id/server/modules/moa-id-modules-saml1/pom.xml new file mode 100644 index 000000000..9c43ae277 --- /dev/null +++ b/id/server/modules/moa-id-modules-saml1/pom.xml @@ -0,0 +1,44 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> +  <modelVersion>4.0.0</modelVersion> +  <parent> +    <groupId>MOA.id.server.modules</groupId> +    <artifactId>moa-id-modules</artifactId> +    <version>${moa-id-version}</version> +  </parent> +   +  <groupId>MOA.id.server.modules</groupId> +	<artifactId>moa-id-module-saml1</artifactId> +	<version>${moa-id-version}</version> +	<packaging>jar</packaging> + +	<name>MOA ID-Module SAML1</name> + +	<properties> +		<repositoryPath>${basedir}/../../../../repository</repositoryPath> +	</properties> +   +  <dependencies> +   +    <dependency> +  		<groupId>MOA.id.server</groupId> +  		<artifactId>moa-id-lib</artifactId> +  		<scope>test</scope> +  		<type>test-jar</type> +  		<version>3.0.3-Snapshot</version> +  	</dependency> +   +    <dependency> +			<groupId>MOA</groupId> +			<artifactId>moa-common</artifactId> +			<type>test-jar</type> +			<scope>test</scope> +		</dependency> +   +  	<dependency> +  		 <groupId>MOA.id.server.modules</groupId> +  		 <artifactId>moa-id-modul-citizencard_authentication</artifactId> +  	</dependency> +  </dependencies> +   +   +</project>
\ No newline at end of file diff --git a/id/server/modules/moa-id-modules-saml1/src/main/java/at/gv/egovernment/moa/id/auth/builder/AuthenticationDataAssertionBuilder.java b/id/server/modules/moa-id-modules-saml1/src/main/java/at/gv/egovernment/moa/id/auth/builder/AuthenticationDataAssertionBuilder.java new file mode 100644 index 000000000..fc04fa9a7 --- /dev/null +++ b/id/server/modules/moa-id-modules-saml1/src/main/java/at/gv/egovernment/moa/id/auth/builder/AuthenticationDataAssertionBuilder.java @@ -0,0 +1,458 @@ +/******************************************************************************* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + *  + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + *  + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + *  + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + ******************************************************************************/ + + + +package at.gv.egovernment.moa.id.auth.builder; + +import java.text.MessageFormat; +import java.util.Calendar; +import java.util.List; + +import at.gv.egovernment.moa.id.auth.data.ExtendedSAMLAttribute; +import at.gv.egovernment.moa.id.auth.exception.BuildException; +import at.gv.egovernment.moa.id.auth.exception.ParseException; +import at.gv.egovernment.moa.id.data.AuthenticationData; +import at.gv.egovernment.moa.id.protocols.saml1.SAML1AuthenticationData; +import at.gv.egovernment.moa.logging.Logger; +import at.gv.egovernment.moa.util.Constants; +import at.gv.egovernment.moa.util.DateTimeUtils; +import at.gv.egovernment.moa.util.StringUtils; + +/** + * Builder for the authentication data <code><saml:Assertion></code> + * to be provided by the MOA ID Auth component. + * + * @author Paul Ivancsics + * @version $Id$ + */ +public class AuthenticationDataAssertionBuilder extends AuthenticationAssertionBuilder implements Constants { +	 +	/** 5 minutes (=300 seconds) default length of the assertion */ +	private static int DEFAULT_CONDITIONS_LENGTH = 300; +	 +  /** private static String NL contains the NewLine representation in Java*/ +	private static final String NL = "\n"; +	/** +	 * XML template for the <code><saml:Assertion></code> to be built +	 */ +	private static final String AUTH_DATA = +		"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>" + NL + +	  "<saml:Assertion xmlns:saml=''" + SAML_NS_URI + "'' xmlns:pr=''" + PD_NS_URI + "'' xmlns:xsi=''" + XSI_NS_URI + "''" + +	  " xmlns:si=''" +  XSI_NS_URI + "''" + +    " MajorVersion=''1'' MinorVersion=''0'' AssertionID=''{0}'' Issuer=''{1}'' IssueInstant=''{2}''>" + NL + +	  "	<saml:AttributeStatement>" + NL +  +	  "		<saml:Subject>" + NL + +	  "			<saml:NameIdentifier NameQualifier=''{3}''>{4}</saml:NameIdentifier>" + NL + +	  "     <saml:SubjectConfirmation>" + NL + +	  "       <saml:ConfirmationMethod>" + MOA_NS_URI + "cm</saml:ConfirmationMethod>" + NL + +	  "       <saml:SubjectConfirmationData>{5}{6}</saml:SubjectConfirmationData>" + NL + +	  "     </saml:SubjectConfirmation>" + NL + +	  "		</saml:Subject>" + NL + +	  "		<saml:Attribute AttributeName=''PersonData'' AttributeNamespace=''" + PD_NS_URI + "''>" + NL + +	  "			<saml:AttributeValue>{7}</saml:AttributeValue>" + NL + +	  "		</saml:Attribute>" + NL + +	  "		<saml:Attribute AttributeName=''isQualifiedCertificate'' AttributeNamespace=''" + MOA_NS_URI + "''>" + NL + +	  "			<saml:AttributeValue>{8}</saml:AttributeValue>" + NL + +	  "		</saml:Attribute>" + NL + +      "   <saml:Attribute AttributeName=''bkuURL'' AttributeNamespace=''" + MOA_NS_URI + "''>" + NL + +      "     <saml:AttributeValue>{9}</saml:AttributeValue>" + NL + +      "   </saml:Attribute>" + NL + +      "{10}" +       +	  "{11}" +  +      "{12}" + +	  "	</saml:AttributeStatement>" + NL + +	  "</saml:Assertion>"; +	 +	/** +	 * XML template for the <code><saml:Assertion></code> to be built (with Conditions) +	 */ +	private static final String AUTH_DATA_WITH_CONDITIONS = +		"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>" + NL + +	  "<saml:Assertion xmlns:saml=''" + SAML_NS_URI + "'' xmlns:pr=''" + PD_NS_URI + "'' xmlns:xsi=''" + XSI_NS_URI + "''" + +	  " xmlns:si=''" +  XSI_NS_URI + "''" + +    " MajorVersion=''1'' MinorVersion=''0'' AssertionID=''{0}'' Issuer=''{1}'' IssueInstant=''{2}''>" + NL + +    "<saml:Conditions NotBefore=''{3}'' NotOnOrAfter=''{4}''/>" + NL +  +	  "	<saml:AttributeStatement>" + NL +  +	  "		<saml:Subject>" + NL + +	  "			<saml:NameIdentifier NameQualifier=''{5}''>{6}</saml:NameIdentifier>" + NL + +	  "     <saml:SubjectConfirmation>" + NL + +	  "       <saml:ConfirmationMethod>" + MOA_NS_URI + "cm</saml:ConfirmationMethod>" + NL + +	  "       <saml:SubjectConfirmationData>{7}{8}</saml:SubjectConfirmationData>" + NL + +	  "     </saml:SubjectConfirmation>" + NL + +	  "		</saml:Subject>" + NL + +	  "		<saml:Attribute AttributeName=''PersonData'' AttributeNamespace=''" + PD_NS_URI + "''>" + NL + +	  "			<saml:AttributeValue>{9}</saml:AttributeValue>" + NL + +	  "		</saml:Attribute>" + NL + +	  "		<saml:Attribute AttributeName=''isQualifiedCertificate'' AttributeNamespace=''" + MOA_NS_URI + "''>" + NL + +	  "			<saml:AttributeValue>{10}</saml:AttributeValue>" + NL + +	  "		</saml:Attribute>" + NL + +      "   <saml:Attribute AttributeName=''bkuURL'' AttributeNamespace=''" + MOA_NS_URI + "''>" + NL + +      "     <saml:AttributeValue>{11}</saml:AttributeValue>" + NL + +      "   </saml:Attribute>" + NL + +      "{12}" +       +	  "{13}" +  +      "{14}" + +	  "	</saml:AttributeStatement>" + NL + +	  "</saml:Assertion>"; +	 +	/** +	 * XML template for the <code><saml:Assertion></code> to be built +	 */ +	private static final String AUTH_DATA_MANDATE = +		"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>" + NL + +	  "<saml:Assertion xmlns:saml=''" + SAML_NS_URI + "'' xmlns:pr=''" + PD_NS_URI + "'' xmlns:xsi=''" + XSI_NS_URI + "''" + +	  " xmlns:si=''" +  XSI_NS_URI + "''" + +    " MajorVersion=''1'' MinorVersion=''0'' AssertionID=''{0}'' Issuer=''{1}'' IssueInstant=''{2}''>" + NL + +	  "	<saml:AttributeStatement>" + NL +  +	  "		<saml:Subject>" + NL + +	  "			<saml:NameIdentifier NameQualifier=''{3}''>{4}</saml:NameIdentifier>" + NL + +	  "     <saml:SubjectConfirmation>" + NL + +	  "       <saml:ConfirmationMethod>" + MOA_NS_URI + "cm</saml:ConfirmationMethod>" + NL + +	  "       <saml:SubjectConfirmationData>{5}{6}</saml:SubjectConfirmationData>" + NL + +	  "     </saml:SubjectConfirmation>" + NL + +	  "		</saml:Subject>" + NL + +	  "		<saml:Attribute AttributeName=''PersonData'' AttributeNamespace=''" + PD_NS_URI + "''>" + NL + +	  "			<saml:AttributeValue>{7}</saml:AttributeValue>" + NL + +	  "		</saml:Attribute>" + NL + +	  "		<saml:Attribute AttributeName=''MandateData'' AttributeNamespace=''" + PD_NS_URI + "''>" + NL + +	  "			<saml:AttributeValue>{8}</saml:AttributeValue>" + NL + +	  "		</saml:Attribute>" + NL + +	  "		<saml:Attribute AttributeName=''isQualifiedCertificate'' AttributeNamespace=''" + MOA_NS_URI + "''>" + NL + +	  "			<saml:AttributeValue>{9}</saml:AttributeValue>" + NL + +	  "		</saml:Attribute>" + NL + +      "   <saml:Attribute AttributeName=''bkuURL'' AttributeNamespace=''" + MOA_NS_URI + "''>" + NL + +      "     <saml:AttributeValue>{10}</saml:AttributeValue>" + NL + +      "   </saml:Attribute>" + NL + +      "{11}" + +	  "{12}" +  +      "{13}" + +	  "	</saml:AttributeStatement>" + NL + +	  "</saml:Assertion>"; +	 +	/** +	 * XML template for the <code><saml:Assertion></code> to be built +	 */ +	private static final String AUTH_DATA_MANDATE_WITH_CONDITIONS = +		"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>" + NL + +	  "<saml:Assertion xmlns:saml=''" + SAML_NS_URI + "'' xmlns:pr=''" + PD_NS_URI + "'' xmlns:xsi=''" + XSI_NS_URI + "''" + +	  " xmlns:si=''" +  XSI_NS_URI + "''" + +    " MajorVersion=''1'' MinorVersion=''0'' AssertionID=''{0}'' Issuer=''{1}'' IssueInstant=''{2}''>" + NL + +    "<saml:Conditions NotBefore=''{3}'' NotOnOrAfter=''{4}''/>" + NL + +	  "	<saml:AttributeStatement>" + NL +  +	  "		<saml:Subject>" + NL + +	  "			<saml:NameIdentifier NameQualifier=''{5}''>{6}</saml:NameIdentifier>" + NL + +	  "     <saml:SubjectConfirmation>" + NL + +	  "       <saml:ConfirmationMethod>" + MOA_NS_URI + "cm</saml:ConfirmationMethod>" + NL + +	  "       <saml:SubjectConfirmationData>{7}{8}</saml:SubjectConfirmationData>" + NL + +	  "     </saml:SubjectConfirmation>" + NL + +	  "		</saml:Subject>" + NL + +	  "		<saml:Attribute AttributeName=''PersonData'' AttributeNamespace=''" + PD_NS_URI + "''>" + NL + +	  "			<saml:AttributeValue>{9}</saml:AttributeValue>" + NL + +	  "		</saml:Attribute>" + NL + +	  "		<saml:Attribute AttributeName=''MandateData'' AttributeNamespace=''" + PD_NS_URI + "''>" + NL + +	  "			<saml:AttributeValue>{10}</saml:AttributeValue>" + NL + +	  "		</saml:Attribute>" + NL + +	  "		<saml:Attribute AttributeName=''isQualifiedCertificate'' AttributeNamespace=''" + MOA_NS_URI + "''>" + NL + +	  "			<saml:AttributeValue>{11}</saml:AttributeValue>" + NL + +	  "		</saml:Attribute>" + NL + +      "   <saml:Attribute AttributeName=''bkuURL'' AttributeNamespace=''" + MOA_NS_URI + "''>" + NL + +      "     <saml:AttributeValue>{12}</saml:AttributeValue>" + NL + +      "   </saml:Attribute>" + NL + +      "{13}" + +	  "{14}" +  +      "{15}" + +	  "	</saml:AttributeStatement>" + NL + +	  "</saml:Assertion>"; +	/** +	 * XML template for the <code><saml:Attribute></code> named <code>"isPublicAuthority"</code>, +	 * to be inserted into the <code><saml:Assertion></code> +	 */ +	private static final String PUBLIC_AUTHORITY_ATT =  +	  "		<saml:Attribute AttributeName=''isPublicAuthority'' AttributeNamespace=''urn:oid:1.2.40.0.10.1.1.1''>" + NL + +	  "			<saml:AttributeValue>{0}</saml:AttributeValue>" + NL + +	  "		</saml:Attribute>" + NL; +   +    private static final String SIGNER_CERTIFICATE_ATT =  +      "     <saml:Attribute AttributeName=''SignerCertificate'' AttributeNamespace=''" + MOA_NS_URI + "''>" + NL + +      "         <saml:AttributeValue>{0}</saml:AttributeValue>" + NL + +      "     </saml:Attribute>" + NL; +	   +  /** +   * Constructor for AuthenticationDataAssertionBuilder. +   */ +  public AuthenticationDataAssertionBuilder() { +    super(); +  } + +  /** +   * Builds the authentication data <code><saml:Assertion></code>. +   *  +   * @param authData the <code>AuthenticationData</code> to build the  +   * 				 <code><saml:Assertion></code> from +   * @param xmlPersonData <code>lt;pr:Person></code> element as a String +   * @param xmlAuthBlock authentication block to be included in a  +   * 				 <code>lt;saml:SubjectConfirmationData></code> element; may include +   * 				 the <code>"Stammzahl"</code> or not; may be empty +   * @param xmlIdentityLink the IdentityLink +   * @param signerCertificateBase64 Base64 encoded certificate of the signer. Maybe +   *         an empty string if the signer certificate should not be provided.  +   *         Will be ignored if the <code>businessService</code> parameter is +   *         set to <code>false</code>. +   * @param businessService <code>true</code> if the online application is a +   *                        business service, otherwise <code>false</code> +   * @return the <code><saml:Assertion></code> +   * @throws BuildException if an error occurs during the build process +   */ +  public String build( +  	SAML1AuthenticationData authData,  +  	String xmlPersonData,  +  	String xmlAuthBlock,  +  	String xmlIdentityLink, +    String bkuURL, +    String signerCertificateBase64, +    boolean businessService, +    List<ExtendedSAMLAttribute> extendedSAMLAttributes,  +    boolean useCondition, +    int conditionLength)  +  throws BuildException  +  { +  		 +  	String isQualifiedCertificate = authData.isQualifiedCertificate() ? "true" : "false"; +  	 +  	String publicAuthorityAttribute = ""; +  	if (authData.isPublicAuthority()) { +  		String publicAuthorityIdentification = authData.getPublicAuthorityCode(); +  		if (publicAuthorityIdentification == null) +  			publicAuthorityIdentification = "True"; +  		publicAuthorityAttribute = MessageFormat.format( +  			PUBLIC_AUTHORITY_ATT, new Object[] { publicAuthorityIdentification }); +  	} +     +     +    String signerCertificateAttribute = ""; +    if (signerCertificateBase64 != "") { +      signerCertificateAttribute = MessageFormat.format( +        SIGNER_CERTIFICATE_ATT, new Object[] { signerCertificateBase64 }); +    }  +     +    String pkType; +    String pkValue; +    if (businessService) { +      pkType = authData.getBPKType(); +      pkValue = authData.getBPK(); +            +    } else { +      // <saml:NameIdentifier NameQualifier> always has the bPK as type/value +      pkType = URN_PREFIX_BPK; +      pkValue = authData.getBPK(); +    } +     +//    System.out.println("pkType; " + pkType); +//    System.out.println("pkValue; " + pkValue); +     +  	String assertion; +    try { +    	 +    	if (!useCondition) { +    		assertion = MessageFormat.format(AUTH_DATA, new Object[] { +    		        authData.getAssertionID(),  +    		        authData.getIssuer(),  +    		        authData.getIssueInstantString(),  +    		        pkType, +    		        pkValue,  +    		        StringUtils.removeXMLDeclaration(xmlAuthBlock),  +    		        StringUtils.removeXMLDeclaration(xmlIdentityLink),  +    		        StringUtils.removeXMLDeclaration(xmlPersonData),  +    		        isQualifiedCertificate, +    		        bkuURL, +    		        publicAuthorityAttribute, +    		        signerCertificateAttribute, +    		        buildExtendedSAMLAttributes(extendedSAMLAttributes)});	 +    	} +    	else { +    		Calendar cal = Calendar.getInstance(); +    		String notBefore = DateTimeUtils.buildDateTimeUTC(cal); +    		if (conditionLength <= 0) +    			cal.add(Calendar.SECOND, DEFAULT_CONDITIONS_LENGTH); +    		else    		 +    			cal.add(Calendar.SECOND, conditionLength); +    		 +    		String notOnOrAfter = DateTimeUtils.buildDateTimeUTC(cal); +    		 +    		assertion = MessageFormat.format(AUTH_DATA_WITH_CONDITIONS, new Object[] { +    		        authData.getAssertionID(),  +    		        authData.getIssuer(),  +    		        authData.getIssueInstantString(),  +    		        notBefore, +    		        notOnOrAfter, +    		        pkType, +    		        pkValue,  +    		        StringUtils.removeXMLDeclaration(xmlAuthBlock),  +    		        StringUtils.removeXMLDeclaration(xmlIdentityLink),  +    		        StringUtils.removeXMLDeclaration(xmlPersonData),  +    		        isQualifiedCertificate, +    		        bkuURL, +    		        publicAuthorityAttribute, +    		        signerCertificateAttribute, +    		        buildExtendedSAMLAttributes(extendedSAMLAttributes)}); +    	} +   	 +       +    } catch (ParseException e) { +      Logger.error("Error on building Authentication Data Assertion: " + e.getMessage()); +      throw new BuildException("builder.00", new Object[] { "Authentication Data Assertion", e.toString()}); +    }  +    return assertion; +  } +   +  /** +   * Builds the authentication data <code><saml:Assertion></code>. +   *  +   * @param authData the <code>AuthenticationData</code> to build the  +   * 				 <code><saml:Assertion></code> from +   * @param xmlPersonData <code>lt;pr:Person></code> element as a String +   * @param xmlAuthBlock authentication block to be included in a  +   * 				 <code>lt;saml:SubjectConfirmationData></code> element; may include +   * 				 the <code>"Stammzahl"</code> or not; may be empty +   * @param xmlIdentityLink the IdentityLink +   * @param signerCertificateBase64 Base64 encoded certificate of the signer. Maybe +   *         an empty string if the signer certificate should not be provided.  +   *         Will be ignored if the <code>businessService</code> parameter is +   *         set to <code>false</code>. +   * @param businessService <code>true</code> if the online application is a +   *                        business service, otherwise <code>false</code> +   * @return the <code><saml:Assertion></code> +   * @throws BuildException if an error occurs during the build process +   */ +  public String buildMandate( +  	SAML1AuthenticationData authData,  +  	String xmlPersonData,  +  	String xmlMandateData, +  	String xmlAuthBlock,  +  	String xmlIdentityLink, +    String bkuURL, +    String signerCertificateBase64, +    boolean businessService, +    List<ExtendedSAMLAttribute> extendedSAMLAttributes, +    boolean useCondition, +    int conditionLength)  +  throws BuildException  +  { +  		 +  	String isQualifiedCertificate = authData.isQualifiedCertificate() ? "true" : "false"; +  	String publicAuthorityAttribute = ""; +  	if (authData.isPublicAuthority()) { +  		String publicAuthorityIdentification = authData.getPublicAuthorityCode(); +  		if (publicAuthorityIdentification == null) +  			publicAuthorityIdentification = "True"; +  		publicAuthorityAttribute = MessageFormat.format( +  			PUBLIC_AUTHORITY_ATT, new Object[] { publicAuthorityIdentification }); +  	} +     +     +    String signerCertificateAttribute = ""; +    if (signerCertificateBase64 != "") { +      signerCertificateAttribute = MessageFormat.format( +        SIGNER_CERTIFICATE_ATT, new Object[] { signerCertificateBase64 }); +    }  +     +    String pkType; +    String pkValue; +    if (businessService) { +      pkType = authData.getBPKType(); +      pkValue = authData.getBPK(); +            +    } else { +      // <saml:NameIdentifier NameQualifier> always has the bPK as type/value +      pkType = URN_PREFIX_BPK; +      pkValue = authData.getBPK(); +    } +     +//    System.out.println("pkType; " + pkType); +//    System.out.println("pkValue; " + pkValue); +     +  	String assertion; +    try { +    	 +    	 +    	 +    	if (!useCondition) { +    		assertion = MessageFormat.format(AUTH_DATA_MANDATE, new Object[] { +    		        authData.getAssertionID(),  +    		        authData.getIssuer(),  +    		        authData.getIssueInstantString(),  +    		        pkType, +    		        pkValue,  +    		        StringUtils.removeXMLDeclaration(xmlAuthBlock),  +    		        StringUtils.removeXMLDeclaration(xmlIdentityLink),  +    		        StringUtils.removeXMLDeclaration(xmlPersonData), +    		        StringUtils.removeXMLDeclaration(xmlMandateData), +    		        isQualifiedCertificate, +    		        bkuURL, +    		        publicAuthorityAttribute, +    		        signerCertificateAttribute, +    		        buildExtendedSAMLAttributes(extendedSAMLAttributes)});	 +    	} +    	else { +    		Calendar cal = Calendar.getInstance(); +    		String notBefore = DateTimeUtils.buildDateTimeUTC(cal); +    		if (conditionLength <= 0) +    			cal.add(Calendar.SECOND, DEFAULT_CONDITIONS_LENGTH); +    		else    		 +    			cal.add(Calendar.SECOND, conditionLength); +    		 +    		String notOnOrAfter = DateTimeUtils.buildDateTimeUTC(cal); +    		 +    		assertion = MessageFormat.format(AUTH_DATA_MANDATE_WITH_CONDITIONS, new Object[] { +    		        authData.getAssertionID(),  +    		        authData.getIssuer(),  +    		        authData.getIssueInstantString(), +    		        notBefore, +    		        notOnOrAfter, +    		        pkType, +    		        pkValue,  +    		        StringUtils.removeXMLDeclaration(xmlAuthBlock),  +    		        StringUtils.removeXMLDeclaration(xmlIdentityLink),  +    		        StringUtils.removeXMLDeclaration(xmlPersonData), +    		        StringUtils.removeXMLDeclaration(xmlMandateData), +    		        isQualifiedCertificate, +    		        bkuURL, +    		        publicAuthorityAttribute, +    		        signerCertificateAttribute, +    		        buildExtendedSAMLAttributes(extendedSAMLAttributes)}); +    	} +    	 +    	 +    	 +    	 +    	 +       +    } catch (ParseException e) { +      Logger.error("Error on building Authentication Data Assertion: " + e.getMessage()); +      throw new BuildException("builder.00", new Object[] { "Authentication Data Assertion", e.toString()}); +    }  +    return assertion; +  } + +} diff --git a/id/server/modules/moa-id-modules-saml1/src/main/java/at/gv/egovernment/moa/id/auth/builder/SAMLArtifactBuilder.java b/id/server/modules/moa-id-modules-saml1/src/main/java/at/gv/egovernment/moa/id/auth/builder/SAMLArtifactBuilder.java new file mode 100644 index 000000000..eeca78e60 --- /dev/null +++ b/id/server/modules/moa-id-modules-saml1/src/main/java/at/gv/egovernment/moa/id/auth/builder/SAMLArtifactBuilder.java @@ -0,0 +1,167 @@ +/******************************************************************************* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + *  + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + *  + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + *  + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + ******************************************************************************/ +/* + * Copyright 2003 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ + + +package at.gv.egovernment.moa.id.auth.builder; + +import java.io.ByteArrayOutputStream; +import java.security.MessageDigest; + +import at.gv.egovernment.moa.id.auth.exception.BuildException; +import at.gv.egovernment.moa.id.auth.validator.parep.ParepUtils; +import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory; +import at.gv.egovernment.moa.logging.Logger; +import at.gv.egovernment.moa.util.Base64Utils; + +/** + * Builder for the SAML artifact, as defined in the  + * Browser/Artifact profile of SAML. + *  + * @author Paul Ivancsics + * @version $Id$ + */ +public class SAMLArtifactBuilder { + +  /** +   * The generic configuration parameter for an alternative SourceID. +   */ +//  private static final String GENERIC_CONFIG_PARAM_SOURCEID = "AuthenticationServer.SourceID"; + +  /** +   * Constructor for SAMLArtifactBuilder. +   */ +  public SAMLArtifactBuilder() { +    super(); +  } +   +  /** +   * Builds the SAML artifact, encoded BASE64. +   * <ul> +   * <li><code>TypeCode</code>: <code>0x0001</code>.</li> +   * <li><code>SourceID</code>: SHA-1 hash of the authURL</li> +   * <li><code>AssertionHandle</code>: SHA-1 hash of the <code>MOASessionID</code></li> +   * </ul> +   * @param authURL URL auf the MOA-ID Auth component to be used for construction  +   *                 of <code>SourceID</code> +   * @param sessionID <code>MOASessionID</code> to be used for construction  +   *                   of <code>AssertionHandle</code> +   * @return the 42-byte SAML artifact, encoded BASE64 +   */ +  public String build(String authURL, String sessionID, String sourceIdParam) throws BuildException { +    try { +      MessageDigest md = MessageDigest.getInstance("SHA-1"); +      byte[] sourceID; +      // alternative sourceId +      String alternativeSourceID = AuthConfigurationProviderFactory.getInstance().getAlternativeSourceID(); +       +      // if sourceID is given in GET/POST param - use this as source id +      if (!ParepUtils.isEmpty(sourceIdParam)) { +          // if GET/POST parameter sourceID is set, use that sourceID instead of authURL; +          //sourceID = md.digest(sourceIdParam.getBytes()); +    	   +    	  // if sourceIdParam is too short (must have 20 characters) - add " " +    	  int length = sourceIdParam.length();  			 +  			if (length < 20) { +  				int l = 20 - length; +  				for (int i = 0; i < l; i++) { +  					sourceIdParam += " "; +  				}			 +  			} +  		 +    	  sourceID = sourceIdParam.getBytes(); +          Logger.info("Building SAMArtifact from sourceID \"" + sourceIdParam + "\" instead of authURL \"" + authURL + "\"."); +           +          byte[] assertionHandle = md.digest(sessionID.getBytes()); +          ByteArrayOutputStream out = new ByteArrayOutputStream(42); +          out.write(0); +          out.write(1); +          out.write(sourceID, 0, 20); +          out.write(assertionHandle, 0, 20); +          byte[] samlArtifact = out.toByteArray(); +          String samlArtifactBase64 = Base64Utils.encode(samlArtifact); +          return samlArtifactBase64;           +      } +       +      // if generic config parameter "AuthenticationServer.SourceID" is given, use that sourceID instead of authURL; +      if (!ParepUtils.isEmpty(alternativeSourceID)) { +          sourceID = md.digest(alternativeSourceID.getBytes());       +          Logger.info("Building SAMArtifact from sourceID \"" + alternativeSourceID + "\" instead of authURL \"" + authURL + "\"."); +           +          byte[] assertionHandle = md.digest(sessionID.getBytes()); +          ByteArrayOutputStream out = new ByteArrayOutputStream(42); +          out.write(0); +          out.write(1); +          out.write(sourceID, 0, 20); +          out.write(assertionHandle, 0, 20); +          byte[] samlArtifact = out.toByteArray(); +          String samlArtifactBase64 = Base64Utils.encode(samlArtifact); +          return samlArtifactBase64;           +      } +       +      // default: sourecID from authURL +      sourceID = md.digest(authURL.getBytes()); +      byte[] assertionHandle = md.digest(sessionID.getBytes()); +      ByteArrayOutputStream out = new ByteArrayOutputStream(42); +      out.write(0); +      out.write(1); +      out.write(sourceID, 0, 20); +      out.write(assertionHandle, 0, 20); +      byte[] samlArtifact = out.toByteArray(); +      String samlArtifactBase64 = Base64Utils.encode(samlArtifact); +      return samlArtifactBase64; +       +      //System.out.println("sourceID: " + new String(sourceID)); +       +       +    } +    catch (Throwable ex) { +      throw new BuildException( +        "builder.00",  +        new Object[] {"SAML Artifact, MOASessionID=" + sessionID, ex.toString()},  +        ex); +    } +  } + +} diff --git a/id/server/modules/moa-id-modules-saml1/src/main/java/at/gv/egovernment/moa/id/auth/parser/SAMLArtifactParser.java b/id/server/modules/moa-id-modules-saml1/src/main/java/at/gv/egovernment/moa/id/auth/parser/SAMLArtifactParser.java new file mode 100644 index 000000000..0e0b42cde --- /dev/null +++ b/id/server/modules/moa-id-modules-saml1/src/main/java/at/gv/egovernment/moa/id/auth/parser/SAMLArtifactParser.java @@ -0,0 +1,104 @@ +/******************************************************************************* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + *  + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + *  + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + *  + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + ******************************************************************************/ +/* + * Copyright 2003 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ + + +package at.gv.egovernment.moa.id.auth.parser; + +import java.io.IOException; + +import at.gv.egovernment.moa.id.auth.exception.ParseException; +import at.gv.egovernment.moa.util.Base64Utils; + +/** + * Parser for a SAML artifact. + * @author Paul Ivancsics + * @version $Id$ + */ +public class SAMLArtifactParser { +  /** byte array containing the SamlArtifact bytes */ +  private byte[] samlArtifactBytes; + +  /** +   * Constructor +   * @param samlArtifact as String +   * @throws ParseException on any parsing error +   */ +  public SAMLArtifactParser(String samlArtifact) throws ParseException { +    try { +      samlArtifactBytes = Base64Utils.decode(samlArtifact, false); +    } +    catch (IOException ex) { +      throw new ParseException("parser.02", new Object[] {ex.toString()}, ex); +    } +  } +  /** +   * Parses the type code. +   * @return type code +   * @throws ParseException when SAML artifact is invalid +   */ +  public byte[] parseTypeCode() throws ParseException { +    try { +      byte[] typeCode = new byte[] {samlArtifactBytes[0], samlArtifactBytes[1]}; +      return typeCode; +    } +    catch (Throwable ex) { +      throw new ParseException("parser.02", new Object[] {ex.toString()}, ex); +    } +  } +  /** +   * Parses the assertion handle. +   * @return assertion handle +   * @throws ParseException when SAML artifact is invalid +   */ +  public String parseAssertionHandle() throws ParseException { +    try { +      return new String(samlArtifactBytes, 22, 20); +    } +    catch (Throwable ex) { +      throw new ParseException("parser.02", new Object[] {ex.toString()}, ex); +    } +  } + +} diff --git a/id/server/modules/moa-id-modules-saml1/src/main/java/at/gv/egovernment/moa/id/protocols/saml1/GetArtifactAction.java b/id/server/modules/moa-id-modules-saml1/src/main/java/at/gv/egovernment/moa/id/protocols/saml1/GetArtifactAction.java new file mode 100644 index 000000000..d4e73690f --- /dev/null +++ b/id/server/modules/moa-id-modules-saml1/src/main/java/at/gv/egovernment/moa/id/protocols/saml1/GetArtifactAction.java @@ -0,0 +1,141 @@ +/******************************************************************************* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + *******************************************************************************/ +package at.gv.egovernment.moa.id.protocols.saml1; + +import java.util.List; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import at.gv.egovernment.moa.id.auth.MOAIDAuthConstants; +import at.gv.egovernment.moa.id.auth.data.ExtendedSAMLAttribute; +import at.gv.egovernment.moa.id.auth.exception.AuthenticationException; +import at.gv.egovernment.moa.id.auth.servlet.RedirectServlet; +import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory; +import at.gv.egovernment.moa.id.config.auth.OAAuthParameter; +import at.gv.egovernment.moa.id.data.IAuthData; +import at.gv.egovernment.moa.id.data.SLOInformationImpl; +import at.gv.egovernment.moa.id.data.SLOInformationInterface; +import at.gv.egovernment.moa.id.moduls.IAction; +import at.gv.egovernment.moa.id.moduls.IRequest; +import at.gv.egovernment.moa.logging.Logger; +import at.gv.egovernment.moa.util.URLEncoder; + +public class GetArtifactAction implements IAction { + +	public SLOInformationInterface processRequest(IRequest req, HttpServletRequest httpReq, +			HttpServletResponse httpResp, IAuthData obj) throws AuthenticationException { +			 +		String oaURL = (String) req.getOAURL(); +		 +		String sourceID = null; +		if (req instanceof SAML1RequestImpl) { +			SAML1RequestImpl saml1req = (SAML1RequestImpl) req; +			sourceID = saml1req.getSourceID(); +			 +		} +		 +		SAML1AuthenticationData authData; +		if (obj instanceof SAML1AuthenticationData) { +			authData = (SAML1AuthenticationData) obj; +			 +		} else { +			Logger.error("AuthDate is NOT of type SAML1AuthenticationData."); +			throw new AuthenticationException("AuthDate is NOT of type SAML1AuthenticationData.", new Object[]{}); +		} +					 +		try { +			OAAuthParameter oaParam = AuthConfigurationProviderFactory.getInstance() +					.getOnlineApplicationParameter(oaURL); +			 +			SAML1AuthenticationServer saml1server = SAML1AuthenticationServer.getInstace(); +						 +			// add other stork attributes to MOA assertion if available +			if(null != authData.getStorkAttributes()) { +				List<ExtendedSAMLAttribute> moaExtendedSAMLAttibutes = SAML1AuthenticationServer.addAdditionalSTORKAttributes(authData.getStorkAttributes()); +				authData.getExtendedSAMLAttributesOA().addAll(moaExtendedSAMLAttibutes); +				Logger.info("MOA assertion assembled and SAML Artifact generated."); +			} +			 +			String samlArtifactBase64 = saml1server.BuildSAMLArtifact(oaParam, authData, sourceID); +			 +			if (authData.isSsoSession()) { +				String url = req.getAuthURL() + "/RedirectServlet"; +				url = addURLParameter(url, RedirectServlet.REDIRCT_PARAM_URL, URLEncoder.encode(oaURL, "UTF-8")); +				if (!oaParam.getBusinessService()) +					url = addURLParameter(url, MOAIDAuthConstants.PARAM_TARGET, URLEncoder.encode(req.getTarget(), "UTF-8")); +				url = addURLParameter(url, MOAIDAuthConstants.PARAM_SAMLARTIFACT, URLEncoder.encode(samlArtifactBase64, "UTF-8")); +				url = httpResp.encodeRedirectURL(url); +				 +				httpResp.setContentType("text/html"); +				httpResp.setStatus(302); +				httpResp.addHeader("Location", url); +				 +			} else { +				String redirectURL = oaURL;		 +				if (!oaParam.getBusinessService()) { +					redirectURL = addURLParameter(redirectURL, MOAIDAuthConstants.PARAM_TARGET, +					URLEncoder.encode(req.getTarget(), "UTF-8")); + +				} +				 +				redirectURL = addURLParameter(redirectURL, MOAIDAuthConstants.PARAM_SAMLARTIFACT, +						URLEncoder.encode(samlArtifactBase64, "UTF-8")); +				redirectURL = httpResp.encodeRedirectURL(redirectURL); +				httpResp.setContentType("text/html"); +				httpResp.setStatus(302); +				httpResp.addHeader("Location", redirectURL); +				Logger.debug("REDIRECT TO: " + redirectURL); +			} + +			SLOInformationInterface sloInformation =  +					new SLOInformationImpl(req.getAuthURL(), authData.getAssertionID(), null, null, req.requestedModule()); +			 +			return sloInformation; +			 +		} catch (Exception ex) { +			Logger.error("SAML1 Assertion build error", ex); +			throw new AuthenticationException("SAML1 Assertion build error.", new Object[]{}, ex); +		} +		 +	} + +	protected static String addURLParameter(String url, String paramname, +			String paramvalue) { +		String param = paramname + "=" + paramvalue; +		if (url.indexOf("?") < 0) +			return url + "?" + param; +		else +			return url + "&" + param; +	} + +	public boolean needAuthentication(IRequest req, HttpServletRequest httpReq, +			HttpServletResponse httpResp) { +		return true; +	} + +	public String getDefaultActionName() { +		return SAML1Protocol.GETARTIFACT; +	} + +} diff --git a/id/server/modules/moa-id-modules-saml1/src/main/java/at/gv/egovernment/moa/id/protocols/saml1/GetAuthenticationDataService.java b/id/server/modules/moa-id-modules-saml1/src/main/java/at/gv/egovernment/moa/id/protocols/saml1/GetAuthenticationDataService.java new file mode 100644 index 000000000..2b4aaf458 --- /dev/null +++ b/id/server/modules/moa-id-modules-saml1/src/main/java/at/gv/egovernment/moa/id/protocols/saml1/GetAuthenticationDataService.java @@ -0,0 +1,213 @@ +/******************************************************************************* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + *  + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + *  + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + *  + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + ******************************************************************************/ +/* + * Copyright 2003 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ + + +package at.gv.egovernment.moa.id.protocols.saml1; + +import java.util.Calendar; + +import org.apache.axis.AxisFault; +import org.apache.commons.lang3.StringEscapeUtils; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; + +import at.gv.egovernment.moa.id.auth.builder.SAMLResponseBuilder; +import at.gv.egovernment.moa.id.auth.exception.AuthenticationException; +import at.gv.egovernment.moa.id.auth.exception.MOAIDException; +import at.gv.egovernment.moa.id.util.ErrorResponseUtils; +import at.gv.egovernment.moa.id.util.MOAIDMessageProvider; +import at.gv.egovernment.moa.id.util.Random; +import at.gv.egovernment.moa.util.Constants; +import at.gv.egovernment.moa.util.DOMUtils; +import at.gv.egovernment.moa.util.DateTimeUtils; +import at.gv.egovernment.moa.util.XPathUtils; + +/** + * Web service for picking up authentication data created in the MOA-ID Auth component. + *  + * @author Paul Ivancsics + * @version $Id: GetAuthenticationDataService.java 1233 2012-01-26 21:59:33Z kstranacher $ + * @see at.gv.egovernment.moa.id.auth.AuthenticationServer#getAuthenticationData + */ +public class GetAuthenticationDataService implements Constants { + +  /** +   * Constructor for GetAuthenticationDataService. +   */ +  public GetAuthenticationDataService() { +    super(); +  } + +	/** +	 * Takes a <code>lt;samlp:Request></code> containing a  +	 * <code>SAML artifact</code> and returns the corresponding  +	 * authentication data <code>lt;saml:Assertion></code>  +	 * (obtained from the <code>AuthenticationServer</code>), +	 * enclosed in a <code>lt;samlp:Response></code>. +	 * <br/>Bad requests are mapped into various <code>lt;samlp:StatusCode></code>s, +	 * possibly containing enclosed sub-<code>lt;samlp:StatusCode></code>s. +	 * The status codes are defined in the SAML specification. +	 *  +	 * @param requests request elements of type <code>lt;samlp:Request></code>; +	 * 				 only 1 request element is allowed +	 * @return response element of type <code>lt;samlp:Response></code>, +	 * 				  packed into an <code>Element[]</code> +	 * @throws AxisFault thrown when an error occurs in assembling the  +	 * 					<code>lt;samlp:Response></code> +	 */ +  public Element[] Request(Element[] requests)  +  	throws AxisFault { +  		 +		Element request = requests[0]; +		Element[] responses = new Element[1]; +		String requestID = ""; +		String statusCode = ""; +		String subStatusCode = null; +		String statusMessageCode = null; +		String statusMessage = null; +		String samlAssertion = ""; +		if (requests.length > 1) { +			// more than 1 request given as parameter +			statusCode = "samlp:Requester"; +			subStatusCode = "samlp:TooManyResponses"; +			statusMessageCode = "1201"; +		} +		else { +			try { +				DOMUtils.validateElement(request, ALL_SCHEMA_LOCATIONS, null); +				NodeList samlArtifactList = XPathUtils.selectNodeList(request, "samlp:AssertionArtifact"); +				if (samlArtifactList.getLength() == 0) { +					// no SAML artifact given in request +					statusCode = "samlp:Requester"; +					statusMessageCode = "1202"; +				} +				else if (samlArtifactList.getLength() > 1) { +					// too many SAML artifacts given in request +					statusCode = "samlp:Requester"; +					subStatusCode = "samlp:TooManyResponses"; +					statusMessageCode = "1203"; +				} +				 +				else { +					Element samlArtifactElem = (Element)samlArtifactList.item(0); +                    requestID = request.getAttribute("RequestID"); +					String samlArtifact = DOMUtils.getText(samlArtifactElem); +					SAML1AuthenticationServer saml1server = SAML1AuthenticationServer.getInstace(); +					 +					try { +							 +						samlAssertion = saml1server.getSaml1AuthenticationData(samlArtifact); +                         +						// success +						statusCode = "samlp:Success"; +						statusMessageCode = "1200"; +					} +					 +					catch (ClassCastException ex) { +					 +						try { +							Throwable error = saml1server.getErrorResponse(samlArtifact); +							statusCode = "samlp:Responder"; +							 +							ErrorResponseUtils errorUtils = ErrorResponseUtils.getInstance(); +							 +							if (error instanceof MOAIDException) { +								statusMessageCode = ((MOAIDException)error).getMessageId(); +								statusMessage = StringEscapeUtils.escapeXml(((MOAIDException)error).getMessage()); +								 +							} else { +								statusMessage = StringEscapeUtils.escapeXml(error.getMessage()); +							}							 +							subStatusCode = errorUtils.getResponseErrorCode(error); +																 +						} catch (Exception e) { +							//no authentication data for given SAML artifact +							statusCode = "samlp:Requester"; +							subStatusCode = "samlp:ResourceNotRecognized"; +							statusMessage = ex.toString(); +						} +						 +					} +					 +					catch (AuthenticationException ex) { +						//no authentication data for given SAML artifact +						statusCode = "samlp:Requester"; +						subStatusCode = "samlp:ResourceNotRecognized"; +						statusMessage = ex.toString(); +					} +				} +			} +	    catch (Throwable t) { +	    	// invalid request format +				statusCode = "samlp:Requester"; +				statusMessageCode = "1204"; +	    } +	} +		 +    try { +			String responseID = Random.nextRandom();			 +			String issueInstant = DateTimeUtils.buildDateTimeUTC(Calendar.getInstance()); +			 +      if (statusMessage == null) +			  statusMessage = MOAIDMessageProvider.getInstance().getMessage(statusMessageCode, null); +	    responses[0] = new SAMLResponseBuilder().build( +	    	responseID, requestID, issueInstant, statusCode, subStatusCode, statusMessage, samlAssertion); +     +  	} +    catch (MOAIDException e) { +	    AxisFault fault = AxisFault.makeFault(e); +	    fault.setFaultDetail(new Element[] { e.toErrorResponse()}); +	    throw fault; +    }  +    catch (Throwable t) { +	    MOAIDException e = new MOAIDException("1299", null, t); +	    AxisFault fault = AxisFault.makeFault(e); +	    fault.setFaultDetail(new Element[] { e.toErrorResponse()}); +	    throw fault; +    } +    return responses; +  } +  	 +} diff --git a/id/server/modules/moa-id-modules-saml1/src/main/java/at/gv/egovernment/moa/id/protocols/saml1/SAML1AuthenticationData.java b/id/server/modules/moa-id-modules-saml1/src/main/java/at/gv/egovernment/moa/id/protocols/saml1/SAML1AuthenticationData.java new file mode 100644 index 000000000..d48c0a9bb --- /dev/null +++ b/id/server/modules/moa-id-modules-saml1/src/main/java/at/gv/egovernment/moa/id/protocols/saml1/SAML1AuthenticationData.java @@ -0,0 +1,177 @@ +/******************************************************************************* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + *  + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + *  + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + *  + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + ******************************************************************************/ +/* + * Copyright 2003 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ + + +package at.gv.egovernment.moa.id.protocols.saml1; + +import java.text.ParseException; +import java.util.List; + +import at.gv.egovernment.moa.id.auth.data.ExtendedSAMLAttribute; +import at.gv.egovernment.moa.id.data.AuthenticationData; +import at.gv.egovernment.moa.id.util.Random; +import at.gv.egovernment.moa.logging.Logger; +import at.gv.egovernment.moa.util.DateTimeUtils; + +/** + * Encapsulates authentication data contained in a <code><saml:Assertion></code>. + * + * @author Paul Ivancsics + * @version $Id$ + */ + +public class SAML1AuthenticationData extends AuthenticationData { +  /** +	 *  +	 */ +	private static final long serialVersionUID = -1042697056735596866L; +/** +   * major version number of the SAML assertion +   */ +  private int majorVersion; +  /** +   * minor version number of the SAML assertion +   */ +  private int minorVersion; +  /** +   * identifier for this assertion +   */ +  private String assertionID; +/** + * @return the majorVersion + */ +   +  private String samlAssertion = null; + +  private List<ExtendedSAMLAttribute> extendedSAMLAttributesOA; +   + +  public SAML1AuthenticationData() {	  	 +		this.setMajorVersion(1); +		this.setMinorVersion(0); +		this.setAssertionID(Random.nextRandom());	   +  } +   +   +	//this method is only required for MOA-ID Proxy 2.0 Release. +	//TODO: remove it, if MOA-ID Proxy is not supported anymore. +	public String getWBPK() { +		return getBPK(); +	} +   +public int getMajorVersion() { +	return majorVersion; +} +/** + * @param majorVersion the majorVersion to set + */ +public void setMajorVersion(int majorVersion) { +	this.majorVersion = majorVersion; +} +/** + * @return the minorVersion + */ +public int getMinorVersion() { +	return minorVersion; +} +/** + * @param minorVersion the minorVersion to set + */ +public void setMinorVersion(int minorVersion) { +	this.minorVersion = minorVersion; +} +/** + * @return the assertionID + */ +public String getAssertionID() { +	return assertionID; +} +/** + * @param assertionID the assertionID to set + */ +public void setAssertionID(String assertionID) { +	this.assertionID = assertionID; +} + +public void setIssueInstant(String date) { +	try { +		setIssueInstant(DateTimeUtils.parseDateTime(date)); +		 +	} catch (ParseException e) { +		Logger.error("Parse IssueInstant element FAILED.", e); +		 +	}	 +} + +/** + * @return the samlAssertion + */ +public String getSamlAssertion() { +	return samlAssertion; +} + +/** + * @param samlAssertion the samlAssertion to set + */ +public void setSamlAssertion(String samlAssertion) { +	this.samlAssertion = samlAssertion; +} + +/** + * @return the extendedSAMLAttributesOA + */ +public List<ExtendedSAMLAttribute> getExtendedSAMLAttributesOA() { +	return extendedSAMLAttributesOA; +} + +/** + * @param extendedSAMLAttributesOA the extendedSAMLAttributesOA to set + */ +public void setExtendedSAMLAttributesOA( +		List<ExtendedSAMLAttribute> extendedSAMLAttributesOA) { +	this.extendedSAMLAttributesOA = extendedSAMLAttributesOA; +} + +} diff --git a/id/server/modules/moa-id-modules-saml1/src/main/java/at/gv/egovernment/moa/id/protocols/saml1/SAML1AuthenticationServer.java b/id/server/modules/moa-id-modules-saml1/src/main/java/at/gv/egovernment/moa/id/protocols/saml1/SAML1AuthenticationServer.java new file mode 100644 index 000000000..eb869756e --- /dev/null +++ b/id/server/modules/moa-id-modules-saml1/src/main/java/at/gv/egovernment/moa/id/protocols/saml1/SAML1AuthenticationServer.java @@ -0,0 +1,635 @@ +/******************************************************************************* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + *******************************************************************************/ +package at.gv.egovernment.moa.id.protocols.saml1; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.List; +import java.util.Vector; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBElement; +import javax.xml.bind.Marshaller; +import javax.xml.namespace.QName; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.TransformerException; + +import org.apache.commons.lang3.StringEscapeUtils; +import org.w3c.dom.Element; +import org.xml.sax.SAXException; + +import eu.stork.peps.auth.commons.IPersonalAttributeList; +import eu.stork.peps.auth.commons.PersonalAttribute; + +import at.gv.egovernment.moa.id.auth.AuthenticationServer; +import at.gv.egovernment.moa.id.auth.builder.AuthenticationDataAssertionBuilder; +import at.gv.egovernment.moa.id.auth.builder.BPKBuilder; +import at.gv.egovernment.moa.id.auth.builder.PersonDataBuilder; +import at.gv.egovernment.moa.id.auth.builder.SAMLArtifactBuilder; +import at.gv.egovernment.moa.id.auth.data.AuthenticationSession; +import at.gv.egovernment.moa.id.auth.data.ExtendedSAMLAttribute; +import at.gv.egovernment.moa.id.auth.data.ExtendedSAMLAttributeImpl; +import at.gv.egovernment.moa.id.auth.data.IdentityLink; +import at.gv.egovernment.moa.id.auth.exception.AuthenticationException; +import at.gv.egovernment.moa.id.auth.exception.BuildException; +import at.gv.egovernment.moa.id.auth.exception.ParseException; +import at.gv.egovernment.moa.id.auth.exception.ServiceException; +import at.gv.egovernment.moa.id.auth.exception.ValidateException; +import at.gv.egovernment.moa.id.auth.parser.SAMLArtifactParser; +import at.gv.egovernment.moa.id.auth.validator.parep.ParepUtils; +import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException; +import at.gv.egovernment.moa.id.config.ConfigurationException; +import at.gv.egovernment.moa.id.config.auth.OAAuthParameter; +import at.gv.egovernment.moa.id.config.auth.data.SAML1ConfigurationParameters; +import at.gv.egovernment.moa.id.data.AuthenticationData; +import at.gv.egovernment.moa.id.moduls.IRequest; +import at.gv.egovernment.moa.id.storage.AssertionStorage; +//import at.gv.egovernment.moa.id.util.IdentityLinkReSigner; +import at.gv.egovernment.moa.id.util.Random; +import at.gv.egovernment.moa.logging.Logger; +import at.gv.egovernment.moa.util.Base64Utils; +import at.gv.egovernment.moa.util.Constants; +import at.gv.egovernment.moa.util.DOMUtils; +import at.gv.egovernment.moa.util.MiscUtil; +import at.gv.egovernment.moa.util.StringUtils; +import at.gv.util.xsd.persondata.IdentificationType; +import at.gv.util.xsd.persondata.IdentificationType.Value; +import at.gv.util.xsd.persondata.PersonNameType; +import at.gv.util.xsd.persondata.PersonNameType.FamilyName; +import at.gv.util.xsd.persondata.PhysicalPersonType; + +public class SAML1AuthenticationServer extends AuthenticationServer { +	 +	private static SAML1AuthenticationServer instance; +	 +	public static SAML1AuthenticationServer getInstace() { +		if (instance == null) +			instance = new SAML1AuthenticationServer(); +		 +		return instance; +	} +	 +	private static AssertionStorage authenticationDataStore =  AssertionStorage.getInstance(); +	 +	 +	/** +	 * time out in milliseconds used by {@link cleanup} for authentication data +	 * store +	 */ +	private static final long authDataTimeOut = 2 * 60 * 1000; // default 2 minutes +		 +	 +	public Throwable getErrorResponse(String samlArtifact) throws AuthenticationException { +		try { +			new SAMLArtifactParser(samlArtifact).parseAssertionHandle(); +			 +		} catch (ParseException ex) { +			throw new AuthenticationException("1205", new Object[] { +					samlArtifact, ex.toString() }); +		} +		Throwable error = null; +		synchronized (authenticationDataStore) { +			try { +				error = authenticationDataStore +						.get(samlArtifact, Throwable.class); +			 +				authenticationDataStore.remove(samlArtifact); +				 +			} catch (MOADatabaseException e) { +				Logger.error("Assertion not found for SAML Artifact: " + samlArtifact); +				throw new AuthenticationException("1206", new Object[] { samlArtifact }); +			} +			 +		} +		 +		return error; +	} +	 +	/** +	 * Transforms additional STORK attributes to MOA Extended attributes +	 * @param iPersonalAttributeList STORK attribute list +	 * @return +	 */ +	public static List<ExtendedSAMLAttribute> addAdditionalSTORKAttributes(IPersonalAttributeList iPersonalAttributeList) { +		List<ExtendedSAMLAttribute> moaExtendedSAMLAttributeList = new Vector<ExtendedSAMLAttribute>(); +		 +		if(null == iPersonalAttributeList) +			return moaExtendedSAMLAttributeList; +		 +		Logger.trace("Adding the following attributes to MOA assertion: "); +		int count = 0; + +		for (PersonalAttribute attribute : iPersonalAttributeList) { +			Object attributeValue = attribute.getValue(); +			if (null == attributeValue) +				attributeValue = attribute.getComplexValue(); + +			// escape attributeValue +			attributeValue = StringEscapeUtils.escapeXml10(attributeValue.toString()); +			// and remove trailing and tailing brackets. Might break something but we never saw an array with more than one entry! +			attributeValue = ((String) attributeValue).substring(1, ((String) attributeValue).length() - 1); + +			ExtendedSAMLAttribute extendedSAMLAttribute =  +				new ExtendedSAMLAttributeImpl(attribute.getName(), attributeValue, Constants.STORK_NS_URI, 0); +			moaExtendedSAMLAttributeList.add(extendedSAMLAttribute); +			count++; +			Logger.trace("Additional attribute: " + attribute.getName()); +		} +		 +		Logger.debug("Added " + count + " STORK attribute(s) to the MOA assertion.");		 +		 +		return moaExtendedSAMLAttributeList; +	} +	 +	 +	/** +	 * Retrieves <code>AuthenticationData</code> indexed by the SAML artifact. +	 * The <code>AuthenticationData</code> is deleted from the store upon end of +	 * this call. +	 *  +	 * @return <code>AuthenticationData</code> +	 */ +	public String getSaml1AuthenticationData(String samlArtifact) +			throws AuthenticationException { +		try { +			new SAMLArtifactParser(samlArtifact).parseAssertionHandle(); +			 +		} catch (ParseException ex) { +			throw new AuthenticationException("1205", new Object[] { +					samlArtifact, ex.toString() }); +		} +		String authData = null; +		synchronized (authenticationDataStore) { +			// System.out.println("assertionHandle: " + assertionHandle); +						 +			try { +				authData = authenticationDataStore +						.get(samlArtifact, String.class, authDataTimeOut); +				 +			} catch (MOADatabaseException e) { +				Logger.error("Assertion not found for SAML Artifact: " + samlArtifact); +				throw new AuthenticationException("1206", new Object[] { samlArtifact }); +			}		 +		} +				 +		authenticationDataStore.remove(samlArtifact); +				 +		Logger.debug("Assertion delivered for SAML Artifact: " + samlArtifact); +		 +		return authData; +	} +	 +	public String BuildErrorAssertion(Throwable error, IRequest protocolRequest)  +			throws BuildException, MOADatabaseException { +		 +		String samlArtifact = new SAMLArtifactBuilder().build( +				protocolRequest.getOAURL(), protocolRequest.getRequestID(), +				null); +		 +		authenticationDataStore.put(samlArtifact, error); +		 +		return samlArtifact; +	} +	 +	public String BuildSAMLArtifact(OAAuthParameter oaParam,  +			SAML1AuthenticationData authData, String sourceID)  +					throws ConfigurationException, BuildException, AuthenticationException { +		 +		//Load SAML1 Parameter from OA config +		SAML1ConfigurationParameters saml1parameter = oaParam.getSAML1Parameter(); +		 +		boolean useCondition = saml1parameter.isUseCondition(); +		int conditionLength = saml1parameter.getConditionLength(); + +		try { +		 +			//set BASE64 encoded signer certificate +			String signerCertificateBase64 = ""; +			if (saml1parameter.isProvideCertificate()) { +				byte[] signerCertificate = authData.getSignerCertificate(); +				if (signerCertificate != null) { +	 +						signerCertificateBase64 = Base64Utils +								.encode(signerCertificate);				 +				} else { +					Logger.info("\"provideCertificate\" is \"true\", but no signer certificate available"); +				} +			} +			 +			//set prPersion +			boolean provideStammzahl = saml1parameter.isProvideStammzahl()  +					|| oaParam.getBusinessService(); +			 +			String prPerson = ""; +			String ilAssertion = ""; +			if (authData.getIdentityLink() != null) { +				prPerson = new PersonDataBuilder().build(authData.getIdentityLink(),			 +						provideStammzahl); + +				//set IdentityLink for assortion				 +				if (saml1parameter.isProvideIdentityLink()) {		 +					ilAssertion = authData.getIdentityLink().getSerializedSamlAssertion(); +						 +					if (!provideStammzahl) +						ilAssertion = StringUtils.replaceAll(ilAssertion, authData.getIdentityLink() +								.getIdentificationValue(), "");					 +				}			  +			} else { +				Logger.info("No IdentityLink available! Build attribute 'PersonDate' from givenname, familyname and dateofbirth. "); +				PhysicalPersonType person = new PhysicalPersonType(); +				PersonNameType name = new PersonNameType(); +				person.setName(name);				 +				FamilyName familyName = new FamilyName(); +				name.getFamilyName().add(familyName ); +				IdentificationType id = new IdentificationType(); +				person.getIdentification().add(id ); +				Value value = new Value(); +				id.setValue(value  ); +				 +				id.setType(authData.getIdentificationType()); +				//add baseID if it is requested and available +				if ( MiscUtil.isNotEmpty(authData.getIdentificationValue()) &&  +						saml1parameter.isProvideIdentityLink() ) +					value.setValue(authData.getIdentificationValue()); +				else +					value.setValue(""); +				 +				familyName.setValue(authData.getFamilyName()); +				familyName.setPrimary("undefined"); +				name.getGivenName().add(authData.getGivenName()); +				person.setDateOfBirth(authData.getFormatedDateOfBirth()); +							 +				JAXBContext jc = JAXBContext.newInstance("at.gv.util.xsd.persondata"); +				Marshaller m = jc.createMarshaller(); +				m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); +				 +//				m.setProperty("com.sun.xml.bind.namespacePrefixMapper", new NamespacePrefixMapper() { +//		            public String getPreferredPrefix(String arg0, String arg1, boolean arg2) { +//		            	if (Constants.PD_NS_URI.equals(arg0)) +//		            		return Constants.PD_PREFIX; +//		            	else +//		            		return arg1; +//		            } +//		        }); +				 +				ByteArrayOutputStream stream = new ByteArrayOutputStream(); +				m.marshal( +						new JAXBElement<PhysicalPersonType>(new QName(Constants.PD_NS_URI,"Person"), PhysicalPersonType.class, person),  +						stream);				 +				prPerson = StringUtils.removeXMLDeclaration(new String(stream.toByteArray(), "UTF-8")); +				stream.close(); +				 +				 +				 +			} +			 +			//set Authblock +			String authBlock = ""; +			if (authData.getAuthBlock() != null) { +				authBlock = saml1parameter.isProvideAUTHBlock() ? authData.getAuthBlock() : ""; +				 +			} else { +				Logger.info("\"provideAuthBlock\" is \"true\", but no authblock available"); +				 +			} +			 +			String samlAssertion;			 +			if (authData.isUseMandate()) { +				List<ExtendedSAMLAttribute> oaAttributes = authData.getExtendedSAMLAttributesOA(); +				 +				//only provide full mandate if it is included.  +				//In case of federation only a short mandate could be include  +				if (saml1parameter.isProvideFullMandatorData()  +						&& authData.getMISMandate().isFullMandateIncluded()) { +					 +					try { +															 +						ExtendedSAMLAttribute[] extendedSAMLAttributes = addExtendedSamlAttributes( +								authData.getMISMandate(), oaParam.getBusinessService(),  +								saml1parameter.isProvideStammzahl()); +						 +						if (extendedSAMLAttributes != null) { +							 +							String identifier = "MISService"; +							String friendlyName ="MISService"; +							 +							int length = extendedSAMLAttributes.length; +							for (int i = 0; i < length; i++) { +								ExtendedSAMLAttribute samlAttribute = extendedSAMLAttributes[i]; + +								Object value = verifySAMLAttribute(samlAttribute, i, identifier, +										friendlyName); + +								if ((value instanceof String) || (value instanceof Element)) { +									switch (samlAttribute.getAddToAUTHBlock()) { +									case ExtendedSAMLAttribute.ADD_TO_AUTHBLOCK: +										replaceExtendedSAMLAttribute(oaAttributes, samlAttribute); +										break; +									case ExtendedSAMLAttribute.NOT_ADD_TO_AUTHBLOCK: +										replaceExtendedSAMLAttribute(oaAttributes, samlAttribute); +										break; +									case ExtendedSAMLAttribute.ADD_TO_AUTHBLOCK_ONLY: +										break; +									default: +										Logger +												.info("Invalid return value from method \"getAddToAUTHBlock()\" (" +														+ samlAttribute.getAddToAUTHBlock() +														+ ") in SAML attribute number " +														+ (i + 1) +														+ " for infobox " + identifier); +										throw new ValidateException("validator.47", new Object[] { +												friendlyName, String.valueOf((i + 1)) }); +									} +								} else { +									Logger +											.info("The type of SAML-Attribute number " +													+ (i + 1) +													+ " returned from " +													+ identifier +													+ "-infobox validator is not valid. Must be either \"java.Lang.String\"" +													+ " or \"org.w3c.dom.Element\""); +									throw new ValidateException("validator.46", new Object[] { +											identifier, String.valueOf((i + 1)) }); +								} +							} +						}  + +					} catch (SAXException e) { +						throw new AuthenticationException("auth.16", +								new Object[] { GET_MIS_SESSIONID }, e); +					} catch (IOException e) { +						throw new AuthenticationException("auth.16", +								new Object[] { GET_MIS_SESSIONID }, e); +					} catch (ParserConfigurationException e) { +						throw new AuthenticationException("auth.16", +								new Object[] { GET_MIS_SESSIONID }, e); +					} catch (TransformerException e) { +						throw new AuthenticationException("auth.16", +								new Object[] { GET_MIS_SESSIONID }, e); +					}				 +				} +				 +				String mandateDate = generateMandateDate(oaParam, authData); +				 +				samlAssertion = new AuthenticationDataAssertionBuilder().buildMandate( +						authData,  +						prPerson,  +						mandateDate,  +						authBlock,  +						ilAssertion,  +						authData.getBkuURL(),  +						signerCertificateBase64,  +						oaParam.getBusinessService(),   +						oaAttributes,  +						useCondition,  +						conditionLength); +				 +			} else { +				samlAssertion = new AuthenticationDataAssertionBuilder().build( +					authData,  +					prPerson, +					authBlock, +					ilAssertion,  +					authData.getBkuURL(), +					signerCertificateBase64, +					oaParam.getBusinessService(), +					authData.getExtendedSAMLAttributesOA(),  +					useCondition, +					conditionLength); +			} +			 +			//authData.setSamlAssertion(samlAssertion); +				 +			String samlArtifact = new SAMLArtifactBuilder().build( +			authData.getIssuer(), Random.nextRandom(), +			sourceID); +			 +			storeAuthenticationData(samlArtifact, samlAssertion); +	 +			Logger.info("Anmeldedaten angelegt, SAML Artifakt " + samlArtifact); +			return samlArtifact; +		 +		} catch (Throwable ex) { +			throw new BuildException("builder.00", new Object[] { +					"AuthenticationData", ex.toString() }, ex); +		} + +	} + +	private String generateMandateDate(OAAuthParameter oaParam, AuthenticationData authData +			) throws AuthenticationException, BuildException, +			ParseException, ConfigurationException, ServiceException, +			ValidateException { + +		if (authData == null) +			throw new AuthenticationException("auth.10", new Object[] { +					REQ_VERIFY_AUTH_BLOCK, PARAM_SESSIONID }); +		 +		IdentityLink tempIdentityLink = null; + +		Element mandate = authData.getMandate(); +		 +		if (authData.isUseMandate()) { +			tempIdentityLink = new IdentityLink(); +			Element mandator = ParepUtils.extractMandator(mandate); +			String dateOfBirth = ""; +			Element prPerson = null; +			String familyName = ""; +			String givenName = ""; +			String identificationType = ""; +			String identificationValue = ""; +			if (mandator != null) { +				boolean physical = ParepUtils.isPhysicalPerson(mandator); +				if (physical) { +					familyName = ParepUtils.extractText(mandator, +							"descendant-or-self::pr:Name/pr:FamilyName/text()"); +					givenName = ParepUtils.extractText(mandator, +							"descendant-or-self::pr:Name/pr:GivenName/text()"); +					dateOfBirth = ParepUtils +							.extractMandatorDateOfBirth(mandator); +				} else { +					familyName = ParepUtils.extractMandatorFullName(mandator); +				} +				identificationType = ParepUtils.getIdentification(mandator, +						"Type"); +				identificationValue = ParepUtils.extractMandatorWbpk(mandator); +				 +				prPerson = ParepUtils.extractPrPersonOfMandate(mandate); +				if (physical +						&& oaParam.getBusinessService() +						&& identificationType != null +						&& Constants.URN_PREFIX_BASEID +								.equals(identificationType)) { +					// now we calculate the wbPK and do so if we got it from the +					// BKU +					 + +					//load IdentityLinkDomainType from OAParam  +					String type = oaParam.getIdentityLinkDomainIdentifier();	 +					if (type.startsWith(Constants.URN_PREFIX_WBPK + "+")) +						identificationType = type; +					else +						identificationType = Constants.URN_PREFIX_WBPK + "+" +								+ type; +					 +					 +					identificationValue = new BPKBuilder().buildWBPK( +							identificationValue, identificationType); +					ParepUtils +							.HideStammZahlen(prPerson, true, null, null, true); +				} + +				tempIdentityLink.setDateOfBirth(dateOfBirth); +				tempIdentityLink.setFamilyName(familyName); +				tempIdentityLink.setGivenName(givenName); +				tempIdentityLink.setIdentificationType(identificationType); +				tempIdentityLink.setIdentificationValue(identificationValue); +				tempIdentityLink.setPrPerson(prPerson); +				try { +					tempIdentityLink.setSamlAssertion(authData.getIdentityLink() +							.getSamlAssertion()); +				} catch (Exception e) { +					throw new ValidateException("validator.64", null); +				} + +			} + +		} + +		Element mandatePerson = tempIdentityLink.getPrPerson(); + +		String mandateData = null; +		try {			 +			 +			boolean provideStammzahl = oaParam.getSAML1Parameter().isProvideStammzahl(); + +			String oatargetType; +			 +	        if(oaParam.getBusinessService()) { +	        	if (oaParam.getIdentityLinkDomainIdentifier().startsWith(AuthenticationSession.REGISTERANDORDNR_PREFIX_)) +	        		oatargetType = oaParam.getIdentityLinkDomainIdentifier(); +	        	else +	        		oatargetType = AuthenticationSession.REGISTERANDORDNR_PREFIX_+oaParam.getIdentityLinkDomainIdentifier(); +	        	 +	        } else { +	        	oatargetType = AuthenticationSession.TARGET_PREFIX_ + oaParam.getTarget(); +	        } +			 +			Element prIdentification = (Element) mandatePerson +			.getElementsByTagNameNS(Constants.PD_NS_URI, +					"Identification").item(0); +	         +			if (!oatargetType.equals(tempIdentityLink.getIdentificationType())) { +			 +				String isPrPerson = mandatePerson.getAttribute("xsi:type"); +		 +				if (!StringUtils.isEmpty(isPrPerson)) { +					if (isPrPerson.equalsIgnoreCase("pr:PhysicalPerson")) { +						String baseid = getBaseId(mandatePerson); +						Element identificationBpK = createIdentificationBPK(mandatePerson, +						baseid, oaParam.getTarget()); +				 +						if (!provideStammzahl) { +							prIdentification.getFirstChild().setTextContent(""); +						} +		 +						mandatePerson.insertBefore(identificationBpK, +								prIdentification); +					} +				} +				 +			} else { +				 +//				Element identificationBpK = mandatePerson.getOwnerDocument() +//						.createElementNS(Constants.PD_NS_URI, "Identification"); +//				Element valueBpK = mandatePerson.getOwnerDocument().createElementNS( +//						Constants.PD_NS_URI, "Value"); +// +//				valueBpK.appendChild(mandatePerson.getOwnerDocument().createTextNode( +//						tempIdentityLink.getIdentificationValue())); +//				Element typeBpK = mandatePerson.getOwnerDocument().createElementNS( +//						Constants.PD_NS_URI, "Type"); +//				typeBpK.appendChild(mandatePerson.getOwnerDocument().createTextNode( +//						"urn:publicid:gv.at:cdid+bpk")); +//				identificationBpK.appendChild(valueBpK); +//				identificationBpK.appendChild(typeBpK); +//				 +//				mandatePerson.insertBefore(identificationBpK, prIdentification); +			} +			 + +			mandateData = DOMUtils.serializeNode(mandatePerson); + +		} catch (TransformerException e1) { +			throw new AuthenticationException("auth.16", +					new Object[] { GET_MIS_SESSIONID }); +		} catch (IOException e1) { +			throw new AuthenticationException("auth.16", +					new Object[] { GET_MIS_SESSIONID }); +		} + +		return mandateData; +	} +	 +	 +	 +	 +	/** +	 * Stores authentication data indexed by the assertion handle contained in +	 * the given saml artifact. +	 *  +	 * @param samlArtifact +	 *            SAML artifact +	 * @param authData +	 *            authentication data +	 * @throws AuthenticationException +	 *             when SAML artifact is invalid +	 */ +	private void storeAuthenticationData(String samlArtifact, +			String samlAssertion) throws AuthenticationException { + +		try { +			SAMLArtifactParser parser = new SAMLArtifactParser(samlArtifact); +			// check type code 0x0001 +			byte[] typeCode = parser.parseTypeCode(); +			if (typeCode[0] != 0 || typeCode[1] != 1) +				throw new AuthenticationException("auth.06", +						new Object[] { samlArtifact }); +			parser.parseAssertionHandle(); +			 +			synchronized (authenticationDataStore) { +				Logger.debug("Assertion stored for SAML Artifact: " +						+ samlArtifact); +				authenticationDataStore.put(samlArtifact, samlAssertion); +			} +			 +		} catch (AuthenticationException ex) { +			throw ex; +			 +		} catch (Throwable ex) { +			throw new AuthenticationException("auth.06", +					new Object[] { samlArtifact }); +		} +	} +	 +} diff --git a/id/server/modules/moa-id-modules-saml1/src/main/java/at/gv/egovernment/moa/id/protocols/saml1/SAML1Protocol.java b/id/server/modules/moa-id-modules-saml1/src/main/java/at/gv/egovernment/moa/id/protocols/saml1/SAML1Protocol.java new file mode 100644 index 000000000..ddd1f1394 --- /dev/null +++ b/id/server/modules/moa-id-modules-saml1/src/main/java/at/gv/egovernment/moa/id/protocols/saml1/SAML1Protocol.java @@ -0,0 +1,226 @@ +/******************************************************************************* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + *******************************************************************************/ +package at.gv.egovernment.moa.id.protocols.saml1; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.lang.StringEscapeUtils; + +import at.gv.egovernment.moa.id.advancedlogging.MOAIDEventConstants; +import at.gv.egovernment.moa.id.advancedlogging.MOAReversionLogger; +import at.gv.egovernment.moa.id.auth.MOAIDAuthConstants; +import at.gv.egovernment.moa.id.auth.exception.InvalidProtocolRequestException; +import at.gv.egovernment.moa.id.auth.exception.MOAIDException; +import at.gv.egovernment.moa.id.auth.exception.ProtocolNotActiveException; +import at.gv.egovernment.moa.id.auth.exception.WrongParametersException; +import at.gv.egovernment.moa.id.auth.servlet.RedirectServlet; +import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory; +import at.gv.egovernment.moa.id.config.auth.OAAuthParameter; +import at.gv.egovernment.moa.id.config.auth.data.SAML1ConfigurationParameters; +import at.gv.egovernment.moa.id.moduls.IAction; +import at.gv.egovernment.moa.id.moduls.IModulInfo; +import at.gv.egovernment.moa.id.moduls.IRequest; +import at.gv.egovernment.moa.id.protocols.pvp2x.PVPConstants; +import at.gv.egovernment.moa.id.util.ParamValidatorUtils; +import at.gv.egovernment.moa.logging.Logger; +import at.gv.egovernment.moa.util.MiscUtil; +import at.gv.egovernment.moa.util.URLEncoder; + +public class SAML1Protocol extends MOAIDAuthConstants implements IModulInfo { + +	public static final String NAME = SAML1Protocol.class.getName(); +	public static final String PATH = "id_saml1"; + +	public static final String GETARTIFACT = "GetArtifact"; + +	public static final List<String> DEFAULTREQUESTEDATTRFORINTERFEDERATION = Arrays.asList( +			new String[] { +					PVPConstants.BPK_NAME, +					PVPConstants.EID_SECTOR_FOR_IDENTIFIER_NAME, +					PVPConstants.GIVEN_NAME_NAME, +					PVPConstants.PRINCIPAL_NAME_NAME, +					PVPConstants.BIRTHDATE_NAME, +					PVPConstants.EID_CCS_URL_NAME, +					PVPConstants.EID_CITIZEN_QAA_LEVEL_NAME, +					PVPConstants.EID_IDENTITY_LINK_NAME, +					PVPConstants.EID_SOURCE_PIN_NAME, +					PVPConstants.EID_SOURCE_PIN_TYPE_NAME +			}); +	 +	private static HashMap<String, IAction> actions = new HashMap<String, IAction>(); +		 +	static { + +		actions.put(GETARTIFACT, new GetArtifactAction()); +		 +		instance = new SAML1Protocol(); +	} + +	private static SAML1Protocol instance = null; + +	public static SAML1Protocol getInstance() { +		if (instance == null) { +			instance = new SAML1Protocol(); +		} +		return instance; +	} + +	public String getName() { +		return NAME; +	} + +	public String getPath() { +		return PATH; +	} + +	public IRequest preProcess(HttpServletRequest request, +			HttpServletResponse response, String action, +			String sessionId, String transactionId) throws MOAIDException { +		SAML1RequestImpl config = new SAML1RequestImpl(request); +		 +		if (!AuthConfigurationProviderFactory.getInstance().getAllowedProtocols().isSAML1Active()) { +			Logger.info("SAML1 is deaktivated!"); +			throw new ProtocolNotActiveException("auth.22", new Object[] { "SAML 1" }); +			 +		} +			 +		String oaURL = (String) request.getParameter(PARAM_OA); +		//oaURL = StringEscapeUtils.escapeHtml(oaURL); +		 +		String target = (String) request.getParameter(PARAM_TARGET); +		target = StringEscapeUtils.escapeHtml(target); +		 +		String sourceID = request.getParameter(PARAM_SOURCEID); +		sourceID = StringEscapeUtils.escapeHtml(sourceID); +		 +		//the target parameter is used to define the OA in SAML1 standard +		if (target != null && target.startsWith("http")) { +			oaURL = target; +			target = null; +		} +		 +		if (MiscUtil.isEmpty(oaURL)) { +			Logger.info("Receive SAML1 request with no OA parameter. Authentication STOPPED!"); +			throw new WrongParametersException("StartAuthentication", PARAM_OA, +					"auth.12"); +			 +		} +		 +		if (!ParamValidatorUtils.isValidOA(oaURL)) +			throw new WrongParametersException("StartAuthentication", PARAM_OA, +					"auth.12"); +		 +		config.setOAURL(oaURL); +		 +		Logger.info("Dispatch SAML1 Request: OAURL=" + oaURL); +		 +	    if (!ParamValidatorUtils.isValidSourceID(sourceID)) +            throw new WrongParametersException("StartAuthentication", PARAM_SOURCEID, "auth.12"); +		 +		 +		//load Target only from OA config +		OAAuthParameter oaParam = AuthConfigurationProviderFactory.getInstance() +				.getOnlineApplicationParameter(oaURL); +		 +		if (oaParam == null) +			throw new InvalidProtocolRequestException("auth.00", +					new Object[] { null }); +				 +		SAML1ConfigurationParameters saml1 = oaParam.getSAML1Parameter(); +		if (saml1 == null || !(saml1.isIsActive() != null && saml1.isIsActive()) ) { +			Logger.info("Online-Application " + oaURL + " can not use SAML1 for authentication."); +			throw new InvalidProtocolRequestException("auth.00", +					new Object[] { null }); +		} +		config.setOnlineApplicationConfiguration(oaParam); +		config.setSourceID(sourceID); +		 +		MOAReversionLogger.getInstance().logEvent(sessionId, transactionId, MOAIDEventConstants.AUTHPROTOCOL_SAML1_AUTHNREQUEST); +		 +		if (MiscUtil.isNotEmpty(target)) +			config.setTarget(target); +		 +		else +			config.setTarget(oaParam.getTarget()); +			 +				 +		return config; +	} + +	public boolean generateErrorMessage(Throwable e, +			HttpServletRequest request, HttpServletResponse response, +			IRequest protocolRequest)  +					throws Throwable{ +		 +		OAAuthParameter oa = AuthConfigurationProviderFactory.getInstance().getOnlineApplicationParameter(protocolRequest.getOAURL()); +		if (!oa.getSAML1Parameter().isProvideAllErrors()) +			return false; +		 +		else { +			SAML1AuthenticationServer saml1authentication = SAML1AuthenticationServer.getInstace();			 +			String samlArtifactBase64 = saml1authentication.BuildErrorAssertion(e, protocolRequest); +		 +			String url = AuthConfigurationProviderFactory.getInstance().getPublicURLPrefix() + "/RedirectServlet"; +			url = addURLParameter(url, RedirectServlet.REDIRCT_PARAM_URL, URLEncoder.encode(protocolRequest.getOAURL(), "UTF-8")); +			url = addURLParameter(url, PARAM_SAMLARTIFACT, URLEncoder.encode(samlArtifactBase64, "UTF-8")); +			url = response.encodeRedirectURL(url); +		 +			response.setContentType("text/html"); +			response.setStatus(302); +			response.addHeader("Location", url); +			Logger.debug("REDIRECT TO: " + url); +		 +			return true; +		} +	} + +	public IAction getAction(String action) { +		return actions.get(action); +	} + +	public IAction canHandleRequest(HttpServletRequest request, +			HttpServletResponse response) { +		return null; +	} + +	public boolean validate(HttpServletRequest request, +			HttpServletResponse response, IRequest pending) { +		 +		return true; +	} +	 +	protected static String addURLParameter(String url, String paramname, +			String paramvalue) { +		String param = paramname + "=" + paramvalue; +		if (url.indexOf("?") < 0) +			return url + "?" + param; +		else +			return url + "&" + param; +	} + +} diff --git a/id/server/modules/moa-id-modules-saml1/src/main/java/at/gv/egovernment/moa/id/protocols/saml1/SAML1RequestImpl.java b/id/server/modules/moa-id-modules-saml1/src/main/java/at/gv/egovernment/moa/id/protocols/saml1/SAML1RequestImpl.java new file mode 100644 index 000000000..3da7cab80 --- /dev/null +++ b/id/server/modules/moa-id-modules-saml1/src/main/java/at/gv/egovernment/moa/id/protocols/saml1/SAML1RequestImpl.java @@ -0,0 +1,108 @@ +/* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ +package at.gv.egovernment.moa.id.protocols.saml1; + +import java.util.ArrayList; +import java.util.List; + +import javax.servlet.http.HttpServletRequest; + +import org.opensaml.saml2.core.Attribute; + +import at.gv.egovernment.moa.id.config.ConfigurationException; +import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory; +import at.gv.egovernment.moa.id.config.auth.OAAuthParameter; +import at.gv.egovernment.moa.id.config.auth.data.SAML1ConfigurationParameters; +import at.gv.egovernment.moa.id.moduls.RequestImpl; +import at.gv.egovernment.moa.id.protocols.pvp2x.PVPConstants; +import at.gv.egovernment.moa.id.protocols.pvp2x.builder.AttributQueryBuilder; +import at.gv.egovernment.moa.logging.Logger; + +/** + * @author tlenz + * + */ +public class SAML1RequestImpl extends RequestImpl { +	 +	/** +	 * @param req +	 * @throws ConfigurationException +	 */ +	public SAML1RequestImpl(HttpServletRequest req) +			throws ConfigurationException { +		super(req); +		 +	} + +	private static final long serialVersionUID = -4961979968425683115L; +	 +	private String sourceID = null; + +	/** +	 * @return the sourceID +	 */ +	public String getSourceID() { +		return sourceID; +	} + +	/** +	 * @param sourceID the sourceID to set +	 */ +	public void setSourceID(String sourceID) { +		this.sourceID = sourceID; +	} + +	/* (non-Javadoc) +	 * @see at.gv.egovernment.moa.id.moduls.RequestImpl#getRequestedAttributes() +	 */ +	@Override +	public List<Attribute> getRequestedAttributes() { +		 +		List<String> reqAttr = new ArrayList<String>(); +		reqAttr.addAll(SAML1Protocol.DEFAULTREQUESTEDATTRFORINTERFEDERATION); +		 +		try { +			OAAuthParameter oa = AuthConfigurationProviderFactory.getInstance().getOnlineApplicationParameter(getOAURL()); +			SAML1ConfigurationParameters saml1 = oa.getSAML1Parameter(); +			if (saml1 != null) { +				if (saml1.isProvideAUTHBlock()) +					reqAttr.add(PVPConstants.EID_AUTH_BLOCK_NAME); +				 +				if (saml1.isProvideCertificate()) +					reqAttr.add(PVPConstants.EID_SIGNER_CERTIFICATE_NAME); +				 +				if (saml1.isProvideFullMandatorData()) +					reqAttr.add(PVPConstants.MANDATE_FULL_MANDATE_NAME); +			} +					 +			return AttributQueryBuilder.buildSAML2AttributeList(oa, reqAttr.iterator()); +			 +		} catch (ConfigurationException e) { +			Logger.error("Load configuration for OA " + getOAURL() + " FAILED", e); +			return null; +		} +		 +		 +	} + +} diff --git a/id/server/modules/moa-id-modules-saml1/src/main/resources/META-INF/services/at.gv.egovernment.moa.id.moduls.IModulInfo b/id/server/modules/moa-id-modules-saml1/src/main/resources/META-INF/services/at.gv.egovernment.moa.id.moduls.IModulInfo new file mode 100644 index 000000000..5bff0dbc2 --- /dev/null +++ b/id/server/modules/moa-id-modules-saml1/src/main/resources/META-INF/services/at.gv.egovernment.moa.id.moduls.IModulInfo @@ -0,0 +1 @@ +at.gv.egovernment.moa.id.protocols.saml1.SAML1Protocol
\ No newline at end of file diff --git a/id/server/modules/moa-id-modules-saml1/src/test/java/test/at/gv/egovernment/moa/id/auth/builder/SAMLArtifactBuilderTest.java b/id/server/modules/moa-id-modules-saml1/src/test/java/test/at/gv/egovernment/moa/id/auth/builder/SAMLArtifactBuilderTest.java new file mode 100644 index 000000000..ebdec6d22 --- /dev/null +++ b/id/server/modules/moa-id-modules-saml1/src/test/java/test/at/gv/egovernment/moa/id/auth/builder/SAMLArtifactBuilderTest.java @@ -0,0 +1,98 @@ +/******************************************************************************* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + *  + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + *  + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + *  + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + ******************************************************************************/ +/* + * Copyright 2003 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ + + +package test.at.gv.egovernment.moa.id.auth.builder; + +import at.gv.egovernment.moa.id.auth.builder.SAMLArtifactBuilder; +import at.gv.egovernment.moa.id.auth.exception.BuildException; +import at.gv.egovernment.moa.util.Base64Utils; + +import test.at.gv.egovernment.moa.id.UnitTestCase; + +/** + * @author Paul Ivancsics + * @version $Id$ + */ +public class SAMLArtifactBuilderTest extends UnitTestCase { + +  private static final String AUTH_URL = "https://moa.gv.at/auth/"; +  private static final String SESSION_ID_1 = "123456"; +  private static final String SESSION_ID_2 = "123457"; +  private static final String SESSION_ID_3 = "1234567"; + +  private SAMLArtifactBuilder builder; +  private byte[] artifact1; +  private byte[] artifact2; +  private byte[] artifact3; + +  public SAMLArtifactBuilderTest(String name) { +    super(name); +  } +  protected void setUp() throws Exception { +  	builder = new SAMLArtifactBuilder(); +  	artifact1 = Base64Utils.decode(builder.build(AUTH_URL, SESSION_ID_1, null), false); +		artifact2 = Base64Utils.decode(builder.build(AUTH_URL, SESSION_ID_2, null), false); +		artifact3 = Base64Utils.decode(builder.build(AUTH_URL, SESSION_ID_3, null), false); +  } +     +  public void testBuildArtifactLength() throws BuildException { +		assertEquals(42, artifact1.length); +		assertEquals(42, artifact2.length); +		assertEquals(42, artifact3.length); +  } +  public void testBuildSameArtifact() throws Exception { +  	byte[] artifact1Clone = Base64Utils.decode(builder.build(AUTH_URL, SESSION_ID_1, null), false); +		assertEquals(new String(artifact1), new String(artifact1Clone)); +  } +  public void testBuildDifferentArtifacts() throws BuildException { +  	String msg = "SAML Artifacts should be different"; +		assertFalse(msg, new String(artifact1).equals(new String(artifact2))); +		assertFalse(msg, new String(artifact1).equals(new String(artifact3))); +		assertFalse(msg, new String(artifact3).equals(new String(artifact2))); +  } + + +} diff --git a/id/server/modules/moa-id-modules-saml1/src/test/java/test/at/gv/egovernment/moa/id/auth/parser/SAMLArtifactParserTest.java b/id/server/modules/moa-id-modules-saml1/src/test/java/test/at/gv/egovernment/moa/id/auth/parser/SAMLArtifactParserTest.java new file mode 100644 index 000000000..961c8d0b5 --- /dev/null +++ b/id/server/modules/moa-id-modules-saml1/src/test/java/test/at/gv/egovernment/moa/id/auth/parser/SAMLArtifactParserTest.java @@ -0,0 +1,101 @@ +/******************************************************************************* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + *  + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + *  + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + *  + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + ******************************************************************************/ +/* + * Copyright 2003 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ + + +package test.at.gv.egovernment.moa.id.auth.parser; + +import at.gv.egovernment.moa.id.auth.builder.SAMLArtifactBuilder; +import at.gv.egovernment.moa.id.auth.parser.SAMLArtifactParser; +import at.gv.egovernment.moa.id.util.Random; +import test.at.gv.egovernment.moa.id.UnitTestCase; + +/* + * @author Paul Ivancsics + * @version $Id$ + */ +public class SAMLArtifactParserTest extends UnitTestCase { +   +  private static String URL1 = "http://moa.gv.at/auth"; +  private static String URL2 = "https://moa.gv.at/auth"; +   +  public SAMLArtifactParserTest(String name) { +    super(name); +  } + +  public void testParseTypeCode() throws Exception { +    String sessionID = Random.nextRandom(); +    String samlArtifact = new SAMLArtifactBuilder().build(URL1, sessionID, null);  +    byte[] typeCode = new SAMLArtifactParser(samlArtifact).parseTypeCode(); +    assertEquals(typeCode[0], 0); +    assertEquals(typeCode[1], 1); +  } +  public void testParseAssertionHandleSameSessionID() throws Exception { +    // SAML artifacts for different authURL's but same sessionID MUST give same assertion handle +    String sessionID = Random.nextRandom(); +    String samlArtifact1 = new SAMLArtifactBuilder().build(URL1, sessionID, null); +    String samlArtifact2 = new SAMLArtifactBuilder().build(URL2, sessionID, null); +    String assertionHandle1 = new SAMLArtifactParser(samlArtifact1).parseAssertionHandle(); +    String assertionHandle2 = new SAMLArtifactParser(samlArtifact2).parseAssertionHandle(); +    assertEquals(assertionHandle1, assertionHandle2); +  } +  public void testParseAssertionHandleSameURL() throws Exception { +    // SAML artifacts for same authURL but different sessionID's MUST give different assertion handles +    String sessionID1 = Random.nextRandom(); +    String sessionID2 = Random.nextRandom(); +    String samlArtifact1 = new SAMLArtifactBuilder().build(URL1, sessionID1, null); +    String samlArtifact2 = new SAMLArtifactBuilder().build(URL1, sessionID2, null); +    String assertionHandle1 = new SAMLArtifactParser(samlArtifact1).parseAssertionHandle(); +    String assertionHandle2 = new SAMLArtifactParser(samlArtifact2).parseAssertionHandle(); +    assertFalse(assertionHandle1.equals(assertionHandle2)); +  } +  public void testParseAssertionHandleSameSAMLArtifact() throws Exception { +    // SAML artifact parsed twice MUST give same assertion handle each time +    String sessionID = Random.nextRandom(); +    String samlArtifact = new SAMLArtifactBuilder().build(URL1, sessionID, null); +    String assertionHandle1 = new SAMLArtifactParser(samlArtifact).parseAssertionHandle(); +    String assertionHandle2 = new SAMLArtifactParser(samlArtifact).parseAssertionHandle(); +    assertEquals(assertionHandle1, assertionHandle2); +  } +} | 
