diff options
13 files changed, 628 insertions, 509 deletions
diff --git a/id/server/data/deploy/conf/moa-id/moa-id.properties b/id/server/data/deploy/conf/moa-id/moa-id.properties index fa6bccef0..24fe78261 100644 --- a/id/server/data/deploy/conf/moa-id/moa-id.properties +++ b/id/server/data/deploy/conf/moa-id/moa-id.properties @@ -18,6 +18,8 @@ configuration.moasession.key=SessionEncryptionKey configuration.moaconfig.key=ConfigurationEncryptionKey configuration.ssl.validation.revocation.method.order=ocsp,crl #configuration.ssl.validation.hostname=false +#configuration.validate.authblock.targetfriendlyname=true< + #MOA-ID 3.x Monitoring Servlet configuration.monitoring.active=false diff --git a/id/server/doc/handbook/config/config.html b/id/server/doc/handbook/config/config.html index 8b2f6a632..9e70c073d 100644 --- a/id/server/doc/handbook/config/config.html +++ b/id/server/doc/handbook/config/config.html @@ -423,6 +423,13 @@ UNIX: moa.id.configuration=file:C:/Programme/apache/tomcat-8.x.x/conf/moa-id/moa <p><strong>Hinweis: </strong>Workaround, da der httpClient der openSAML2 Implementierung kein SNI (Server Name Indication) unterstützt.</p></td> </tr> <tr> + <td>configuration.validate.authblock.targetfriendlyname</td> + <td>true / false</td> + <td>Hiermit kann die Überprüfung des 'TargetFriendlyName', welcher Teil des vom Benutzer signierten Authblock ist, deaktiviert werden. Eine Deaktivierung hat keinen Einfluss auf die Sicherheit des Authentifizierungsvorgangs mittels qualifizierter Signatur, jedoch kann der 'TargetFriendlyName im Authblock nicht als gesichert betrachtet werden.' Die Validierung ist deaktiviert wenn der Parameter auf <code>false</code> gesetzt wird.<br> + <strong>Hinweis:</strong> Hierbei handelt es sich um einen Workaround für Systeme auf denen die Validierung des 'TargetFriendlyName' wegen Problemen mit der Zeichencodierung fehlschlägt, die Signatur des AuthBlocks jedoch gültig ist.<br> + <strong>Defaultwert:</strong> true</td> + </tr> + <tr> <td>configuration.monitoring.active</td> <td>true / false</td> <td>Aktiviert das Modul für internes Monitoring / Testing.</td> @@ -2190,7 +2197,7 @@ Alle in diesem Abschnitt angegebenen Parameter sind Optional und werden bei Beda <p><strong>Hinweis:</strong> Bei Verwendung einer online-applikationsspezifischen Bürgerkartenauswahl stehen alle Parameter die die Bürgerkartenauswahl betreffen nicht zur Verfügung.</p> <p><strong>Hinweis:</strong> Bei Verwendung eines online-applikationsspezifischen Security-Layer-Request Templates stehen alle Parameter die das SL-Template betreffen nicht zur Verfügung.</p> <h5><a name="service_revisionslogging" id="uebersicht_zentraledatei_aktualisierung11"></a>3.2.10 Revisionslogging</h5> -<p>Ab MOA-ID 3.x steht ein erweitertes speziell für Revisionsaufgaben abgestimmtest Logging zur Verfügung. Über dieses Feld können die zu loggenden Events als CSV codierte Eventcodes konfiguriert werden. Werden keine Eventcodes konfiguriert wird eine in MOA-ID hinterlegte Defaultkonfiguration verwendet. Eine Liste aller möglichen Eventcodes finden Sie <a href="../additional/additional.html#revisionslog">hier</a>.</p> +<p>Ab MOA-ID 3.x steht ein erweitertes speziell für Revisionsaufgaben abgestimmtest Logging zur Verfügung. Über dieses Feld können die zu loggenden Events spezifisch nach Online Applikationen als CSV codierte Eventcodes konfiguriert werden. Hierfür muss die online-applikationsspezifische Konfiguration des Loggings mittels Checkbox aktiviert und zumindesdt ein Eventcode definiert werden. Werden keine Eventcodes konfiguriert oder wird das OA spezifische Verhalten nicht aktiviertwird eine in MOA-ID hinterlegte Defaultkonfiguration verwendet. Eine Liste aller möglichen Eventcodes finden Sie <a href="../additional/additional.html#revisionslog">hier</a>.</p> <h3><a name="import_export" id="uebersicht_zentraledatei_aktualisierung4"></a>3.3 Import / Export</h3> <p>Üer diese Funktionalität besteht die Möglichkeit eine bestehende MOA-ID 2.x.x Konfiguration in MOA-ID 3.x zu importieren. Zusätzlich besteht die Möglichkeit eine MOA-ID-Auth 3.0 diff --git a/id/server/idserverlib/pom.xml b/id/server/idserverlib/pom.xml index f859b6a45..ce1430aa0 100644 --- a/id/server/idserverlib/pom.xml +++ b/id/server/idserverlib/pom.xml @@ -530,6 +530,17 @@ </execution>
</executions>
</plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>3.6.1</version>
+ <configuration>
+ <source>1.7</source>
+ <target>1.7</target>
+ <encoding>UTF-8</encoding>
+ </configuration>
+ </plugin>
+
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/MOAIDAuthInitializer.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/MOAIDAuthInitializer.java index 3d45e2468..d09aac0f4 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/MOAIDAuthInitializer.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/MOAIDAuthInitializer.java @@ -35,6 +35,7 @@ import org.springframework.web.context.support.GenericWebApplicationContext; import at.gv.egovernment.moa.id.commons.api.AuthConfiguration; import at.gv.egovernment.moa.id.commons.api.exceptions.ConfigurationException; import at.gv.egovernment.moa.id.commons.utils.MOAIDMessageProvider; +import at.gv.egovernment.moa.id.config.ConfigurationProviderImpl; import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory; import at.gv.egovernment.moa.id.util.Random; import at.gv.egovernment.moa.id.util.SSLUtils; @@ -163,6 +164,10 @@ public class MOAIDAuthInitializer { fixJava8_141ProblemWithSSLAlgorithms(); + if (!authConf.getBasicMOAIDConfigurationBoolean(ConfigurationProviderImpl.VALIDATION_AUTHBLOCK_TARGETFRIENDLYNAME, true)) + Logger.info("AuthBlock 'TargetFriendlyName' validation deactivated"); + + if (Logger.isDebugEnabled()) { Logger.debug("Loaded Security Provider:"); Provider[] providerList = Security.getProviders(); diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/ConfigurationProviderImpl.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/ConfigurationProviderImpl.java index 804b98a5f..8b0134f9c 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/ConfigurationProviderImpl.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/ConfigurationProviderImpl.java @@ -103,7 +103,11 @@ public abstract class ConfigurationProviderImpl implements ConfigurationProvider public static final String TRUST_MANAGER_REVOCATION_CHECKING = "TrustManager.RevocationChecking"; - + /** + * Deactivate TargetFriendlyName validation in Authblock + */ + public static final String VALIDATION_AUTHBLOCK_TARGETFRIENDLYNAME = "configuration.validate.authblock.targetfriendlyname"; + /** * A <code>Map</code> which contains generic configuration information. Maps a * configuration name (a <code>String</code>) to a configuration value (also a diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/OAAuthParameter.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/OAAuthParameter.java index 99b4154e0..5642861c5 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/OAAuthParameter.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/OAAuthParameter.java @@ -50,11 +50,14 @@ import java.io.IOException; import java.io.Serializable; import java.security.PrivateKey; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; +import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import java.util.Set; import org.apache.commons.lang.SerializationUtils; @@ -73,7 +76,7 @@ import at.gv.egovernment.moa.id.commons.api.data.StorkAttributeProviderPlugin; import at.gv.egovernment.moa.id.commons.api.exceptions.ConfigurationException; import at.gv.egovernment.moa.id.commons.config.MOAIDConfigurationConstants; import at.gv.egovernment.moa.id.commons.utils.KeyValueUtils; -import at.gv.egovernment.moa.id.commons.validation.TargetValidator; +import at.gv.egovernment.moa.id.config.TargetToSectorNameMapper; import at.gv.egovernment.moa.id.data.EncryptedData; import at.gv.egovernment.moa.id.util.ConfigurationEncrytionUtil; import at.gv.egovernment.moa.logging.Logger; @@ -242,7 +245,7 @@ private String getTargetFriendlyName() { return oaConfiguration.get(MOAIDConfigurationConstants.SERVICE_AUTH_TARGET_PUBLIC_OWN_NAME); else - return TargetValidator.getTargetFriendlyName(oaConfiguration.get(MOAIDConfigurationConstants.SERVICE_AUTH_TARGET_PUBLIC_TARGET)); + return TargetToSectorNameMapper.getSectorNameViaTarget(oaConfiguration.get(MOAIDConfigurationConstants.SERVICE_AUTH_TARGET_PUBLIC_TARGET)); } @@ -925,4 +928,11 @@ public boolean isUseAuthBlockTestTestStore() { return false; } +public String toString() { + if (oaConfiguration != null) + return Arrays.asList(oaConfiguration).toString(); + + return "Object not initialized"; +} + } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/logging/SpecificTraceLogger.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/logging/SpecificTraceLogger.java new file mode 100644 index 000000000..c12021f2c --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/logging/SpecificTraceLogger.java @@ -0,0 +1,18 @@ +package at.gv.egovernment.moa.id.logging; + + +import at.gv.egovernment.moa.logging.Logger; + +public class SpecificTraceLogger{ + + /** + * Enables Logging on Trace level for single specific parts + * @param message + */ + public static void trace(Object message) { + if (Logger.isTraceEnabled()) { + Logger.traceWithOutEscaption(message); + + } + } +} diff --git a/id/server/idserverlib/src/main/resources/resources/properties/id_messages_de.properties b/id/server/idserverlib/src/main/resources/resources/properties/id_messages_de.properties index 05f58d5bc..4205f2175 100644 --- a/id/server/idserverlib/src/main/resources/resources/properties/id_messages_de.properties +++ b/id/server/idserverlib/src/main/resources/resources/properties/id_messages_de.properties @@ -161,7 +161,7 @@ validator.09=Die \u00F6ffentlichen Schl\u00FCssel des Identitiy Link stimmen nic validator.10=Anzahl der URLs zur Authentisierungskomponente ung\u00FCltig {0}
validator.11="Gesch\\u00E4ftsbereich" wurde nicht in den SAML-Attributen gefunden {0}
validator.12=Der Namespace des SAML-Attributs "Gesch\\u00E4ftsbereich" ist ung\u00FCltig {0}
-validator.13=Das Target des 'Gesch\u00E4ftsbereichs' ist ung\u00FCltig {0}
+validator.13=Das Target des 'Gesch\u00E4ftsbereichs' ist ung\u00FCltig. Authblock: {0} , Config: {1}
validator.14="OA" wurde nicht in den SAML-Attributen gefunden {0}
validator.15=Der Namespace des SAML-Attributs "OA" ist ung\u00FCltig {0}
validator.16=Die vorkonfigurierte URL der OnlineApplikation ist fehlerhaft {0}
@@ -179,7 +179,7 @@ validator.25=Eine formal korrekte Zertifikatskette vom Signatorzertifikat zu ein validator.26=OA Applikation ist eine Wirtschaftsapplikation, trotzdem ist ein SAML-Attribut "Gesch\u00E4ftsbereich" enthalten
validator.27=OA Applikation ist keine Wirtschaftsapplikation, trotzdem ist ein SAML-Attribut "wbPK" enthalten
-validator.28=Fehlerhafter Wert im "wbPK" SAML-Attribut {0}
+validator.28=Fehlerhafter Wert im "wbPK" SAML-Attribut. Authblock: {0} , Config: {1}
validator.29=Fehler beim Auslesen des "wbPK" SAML-Attributs {0}
validator.30=Der Namespace des SAML-Attributs "wbPK" ist ung\u00FCltig {0}
validator.31="wbPK" wurde nicht in den SAML-Attributen gefunden {0}
diff --git a/id/server/moa-id-commons/pom.xml b/id/server/moa-id-commons/pom.xml index fd8ddc7fb..31fe6af26 100644 --- a/id/server/moa-id-commons/pom.xml +++ b/id/server/moa-id-commons/pom.xml @@ -321,6 +321,7 @@ <configuration> <source>1.7</source> <target>1.7</target> + <encoding>UTF-8</encoding> </configuration> </plugin> <plugin> diff --git a/id/server/moa-id-commons/src/main/java/at/gv/egovernment/moa/logging/Logger.java b/id/server/moa-id-commons/src/main/java/at/gv/egovernment/moa/logging/Logger.java index 9152f2549..197247630 100644 --- a/id/server/moa-id-commons/src/main/java/at/gv/egovernment/moa/logging/Logger.java +++ b/id/server/moa-id-commons/src/main/java/at/gv/egovernment/moa/logging/Logger.java @@ -86,12 +86,16 @@ public class Logger { * <p>Mainly introduce because the <code>message</code> might be <code>null</code>. * * @param message the message + * @param escape if this flag is true than the message get escapted before logging * @return the string */ - private static String prepareMessage(Object message) { + private static String prepareMessage(Object message, boolean escape) { if(null == message) return "no message given"; - return StringEscapeUtils.escapeHtml4(message.toString()); + if (escape) + return StringEscapeUtils.escapeHtml4(message.toString()); + else + return message.toString(); } /** @@ -124,7 +128,17 @@ public class Logger { */ public static void trace(Object message) { org.slf4j.Logger logger = getLogger(); - logger.trace(prepareMessage(message)); + logger.trace(prepareMessage(message, true)); + } + + /** + * Trace a message. + * + * @param message The message to trace. + */ + public static void traceWithOutEscaption(Object message) { + org.slf4j.Logger logger = getLogger(); + logger.trace(prepareMessage(message, false)); } /** @@ -157,7 +171,7 @@ public class Logger { */ public static void debug(Object message) { org.slf4j.Logger logger = getLogger(); - logger.debug(prepareMessage(message)); + logger.debug(prepareMessage(message, true)); } /** @@ -167,7 +181,7 @@ public class Logger { */ public static void info(Object message) { org.slf4j.Logger logger = getLogger(); - logger.info(prepareMessage(message)); + logger.info(prepareMessage(message, true)); } /** @@ -178,7 +192,7 @@ public class Logger { */ public static void info(String message, Object[] args) { org.slf4j.Logger logger = getLogger(); - logger.info(prepareMessage(message), args); + logger.info(prepareMessage(message, true), args); } /** @@ -188,7 +202,7 @@ public class Logger { */ public static void warn(Object message) { org.slf4j.Logger logger = getLogger(); - logger.warn(prepareMessage(message)); + logger.warn(prepareMessage(message, true)); } /** @@ -199,7 +213,7 @@ public class Logger { */ public static void warn(Object message, Throwable t) { org.slf4j.Logger logger = getLogger(); - logger.warn(prepareMessage(message), t); + logger.warn(prepareMessage(message, true), t); } /** @@ -209,7 +223,7 @@ public class Logger { */ public static void error(Object message) { org.slf4j.Logger logger = getLogger(); - logger.error(prepareMessage(message)); + logger.error(prepareMessage(message, true)); } /** @@ -220,7 +234,7 @@ public class Logger { */ public static void error(Object message, Throwable t) { org.slf4j.Logger logger = getLogger(); - logger.error(prepareMessage(message), t); + logger.error(prepareMessage(message, true), t); } /** @@ -231,7 +245,7 @@ public class Logger { */ public static void error(Object message, Object[] variables) { org.slf4j.Logger logger = getLogger(); - logger.error(prepareMessage(message), variables); + logger.error(prepareMessage(message, true), variables); } /** diff --git a/id/server/modules/moa-id-modul-citizencard_authentication/src/main/java/at/gv/egovernment/moa/id/auth/AuthenticationServer.java b/id/server/modules/moa-id-modul-citizencard_authentication/src/main/java/at/gv/egovernment/moa/id/auth/AuthenticationServer.java index f7c3db8d1..3d0073276 100644 --- a/id/server/modules/moa-id-modul-citizencard_authentication/src/main/java/at/gv/egovernment/moa/id/auth/AuthenticationServer.java +++ b/id/server/modules/moa-id-modul-citizencard_authentication/src/main/java/at/gv/egovernment/moa/id/auth/AuthenticationServer.java @@ -4,6 +4,7 @@ package at.gv.egovernment.moa.id.auth; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; +import java.io.UnsupportedEncodingException; import java.security.Principal; import java.security.cert.CertificateException; import java.util.Calendar; @@ -20,6 +21,7 @@ import org.apache.xpath.XPathAPI; import org.opensaml.xml.util.Base64; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import org.springframework.util.Base64Utils; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NodeList; @@ -65,7 +67,9 @@ import at.gv.egovernment.moa.id.commons.api.data.IMISMandate; import at.gv.egovernment.moa.id.commons.api.data.IVerifiyXMLSignatureResponse; import at.gv.egovernment.moa.id.commons.api.exceptions.ConfigurationException; import at.gv.egovernment.moa.id.commons.api.exceptions.MOAIDException; +import at.gv.egovernment.moa.id.config.ConfigurationProviderImpl; import at.gv.egovernment.moa.id.data.Pair; +import at.gv.egovernment.moa.id.logging.SpecificTraceLogger; import at.gv.egovernment.moa.id.protocols.pvp2x.PVPConstants; import at.gv.egovernment.moa.logging.Logger; import at.gv.egovernment.moa.util.Constants; @@ -445,6 +449,12 @@ public class AuthenticationServer extends BaseAuthenticationServer { String createXMLSignatureRequest = new CreateXMLSignatureRequestBuilder() .build(authBlock, oaParam.getKeyBoxIdentifier(), transformsInfos); + + SpecificTraceLogger.trace("Req. Authblock: " + Base64Utils.encodeToString(createXMLSignatureRequest.getBytes())); + SpecificTraceLogger.trace("OA config: " + pendingReq.getOnlineApplicationConfiguration().toString()); + SpecificTraceLogger.trace("saml1RequestedTarget: " + pendingReq.getGenericData(MOAIDAuthConstants.AUTHPROCESS_DATA_TARGET, String.class)); + SpecificTraceLogger.trace("saml1RequestedFriendlyName: " + pendingReq.getGenericData(MOAIDAuthConstants.AUTHPROCESS_DATA_TARGETFRIENDLYNAME, String.class)); + return createXMLSignatureRequest; } @@ -949,12 +959,15 @@ public class AuthenticationServer extends BaseAuthenticationServer { throw new ParseException("parser.04", new Object[]{ REQ_VERIFY_AUTH_BLOCK, PARAM_XMLRESPONSE}, e); } + // validates <CreateXMLSignatureResponse> if (pendingReq.needSingleSignOnFunctionality()) new CreateXMLSignatureResponseValidator().validateSSO(csresp, session, pendingReq); else - new CreateXMLSignatureResponseValidator().validate(csresp, session, pendingReq); + new CreateXMLSignatureResponseValidator().validate(csresp, session, pendingReq, + authConfig.getBasicMOAIDConfigurationBoolean( + ConfigurationProviderImpl.VALIDATION_AUTHBLOCK_TARGETFRIENDLYNAME, true)); // builds a <VerifyXMLSignatureRequest> for a MOA-SPSS call List<String> vtids = authConfig.getMoaSpAuthBlockVerifyTransformsInfoIDs(); diff --git a/id/server/modules/moa-id-modul-citizencard_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/VerifyAuthenticationBlockTask.java b/id/server/modules/moa-id-modul-citizencard_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/VerifyAuthenticationBlockTask.java index ddd52c337..5730224e5 100644 --- a/id/server/modules/moa-id-modul-citizencard_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/VerifyAuthenticationBlockTask.java +++ b/id/server/modules/moa-id-modul-citizencard_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/VerifyAuthenticationBlockTask.java @@ -3,6 +3,7 @@ package at.gv.egovernment.moa.id.auth.modules.internal.tasks; import static at.gv.egovernment.moa.id.commons.MOAIDAuthConstants.PARAM_XMLRESPONSE; import java.io.IOException; +import java.io.UnsupportedEncodingException; import java.util.Map; import javax.servlet.http.HttpServletRequest; @@ -12,6 +13,7 @@ import org.apache.commons.fileupload.FileUploadException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Component; +import org.springframework.util.Base64Utils; import at.gv.egovernment.moa.id.advancedlogging.MOAIDEventConstants; import at.gv.egovernment.moa.id.auth.AuthenticationServer; @@ -19,9 +21,11 @@ import at.gv.egovernment.moa.id.auth.exception.WrongParametersException; import at.gv.egovernment.moa.id.auth.modules.AbstractAuthServletTask; import at.gv.egovernment.moa.id.auth.modules.TaskExecutionException; import at.gv.egovernment.moa.id.commons.api.exceptions.MOAIDException; +import at.gv.egovernment.moa.id.logging.SpecificTraceLogger; import at.gv.egovernment.moa.id.process.api.ExecutionContext; import at.gv.egovernment.moa.id.util.ParamValidatorUtils; import at.gv.egovernment.moa.logging.Logger; +import at.gv.egovernment.moa.util.MiscUtil; /** * Verifies the signed authentication block (provided as {@code CreateXMLSignatureResponse}).<p/> @@ -79,7 +83,9 @@ public class VerifyAuthenticationBlockTask extends AbstractAuthServletTask { } String createXMLSignatureResponse = (String)parameters.get(PARAM_XMLRESPONSE); - + if (createXMLSignatureResponse != null) + SpecificTraceLogger.trace("Raw signed AuthBlock: " + Base64Utils.encodeToString(createXMLSignatureResponse.getBytes())); + try { //check if authblock is received if (!ParamValidatorUtils.isValidXMLDocument(createXMLSignatureResponse)) diff --git a/id/server/modules/moa-id-modul-citizencard_authentication/src/main/java/at/gv/egovernment/moa/id/auth/validator/CreateXMLSignatureResponseValidator.java b/id/server/modules/moa-id-modul-citizencard_authentication/src/main/java/at/gv/egovernment/moa/id/auth/validator/CreateXMLSignatureResponseValidator.java index 827690ebd..1d2887e6a 100644 --- a/id/server/modules/moa-id-modul-citizencard_authentication/src/main/java/at/gv/egovernment/moa/id/auth/validator/CreateXMLSignatureResponseValidator.java +++ b/id/server/modules/moa-id-modul-citizencard_authentication/src/main/java/at/gv/egovernment/moa/id/auth/validator/CreateXMLSignatureResponseValidator.java @@ -54,6 +54,7 @@ import java.util.List; import javax.xml.bind.DatatypeConverter; import org.jaxen.SimpleNamespaceContext; +import org.springframework.util.Base64Utils; import org.w3c.dom.Element; import at.gv.egovernment.moa.id.auth.builder.AuthenticationBlockAssertionBuilder; @@ -72,6 +73,7 @@ import at.gv.egovernment.moa.id.commons.api.exceptions.ConfigurationException; import at.gv.egovernment.moa.id.config.TargetToSectorNameMapper; import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory; import at.gv.egovernment.moa.id.data.Pair; +import at.gv.egovernment.moa.id.logging.SpecificTraceLogger; import at.gv.egovernment.moa.logging.Logger; import at.gv.egovernment.moa.util.Constants; import at.gv.egovernment.moa.util.MiscUtil; @@ -134,9 +136,8 @@ public class CreateXMLSignatureResponseValidator { * @throws BuildException * @throws ConfigurationException */ - public void validate(CreateXMLSignatureResponse createXMLSignatureResponse, IAuthenticationSession session, IRequest pendingReq) + public void validate(CreateXMLSignatureResponse createXMLSignatureResponse, IAuthenticationSession session, IRequest pendingReq, boolean validateTargetFriendlyName) throws ValidateException, BuildException, ConfigurationException { - // A3.056: more then one /saml:Assertion/saml:AttributeStatement/saml:Subject/saml:NameIdentifier IOAAuthParameters oaParam = pendingReq.getOnlineApplicationConfiguration(); String oaURL = oaParam.getPublicURLPrefix(); @@ -148,283 +149,302 @@ public class CreateXMLSignatureResponseValidator { @Deprecated String saml1RequestedFriendlyName = pendingReq.getGenericData( MOAIDAuthConstants.AUTHPROCESS_DATA_TARGETFRIENDLYNAME, String.class); - - - Element samlAssertion = createXMLSignatureResponse.getSamlAssertion(); - - //validate issuer - String issuer = samlAssertion.getAttribute("Issuer"); - if (issuer == null) { - // should not happen, because parser would dedect this - throw new ValidateException("validator.32", null); - } - // replace ' in name with ' - issuer = issuer.replaceAll("'", "'"); - if (!issuer.equals(identityLink.getName())) - throw new ValidateException("validator.33", new Object[] {issuer, identityLink.getName()}); - - - //validate issuerInstant - String issueInstant = samlAssertion.getAttribute("IssueInstant"); - if (!issueInstant.equals(session.getIssueInstant())) - throw new ValidateException("validator.39", new Object[] {issueInstant, session.getIssueInstant()}); - - - //validate extended attributes - SAMLAttribute[] samlAttributes = createXMLSignatureResponse.getSamlAttributes(); - - boolean foundOA = false; - boolean foundGB = false; - boolean foundWBPK = false; - int offset = 0; - - // check number of SAML attributes - List<ExtendedSAMLAttribute> extendedSAMLAttributes = session.getExtendedSAMLAttributesAUTH(); - int extendedSAMLAttributesNum = 0; - if (extendedSAMLAttributes != null) { - extendedSAMLAttributesNum = extendedSAMLAttributes.size(); - } - int expectedSAMLAttributeNumber = AuthenticationBlockAssertionBuilder.NUM_OF_SAML_ATTRIBUTES + extendedSAMLAttributesNum; - - //remove one attribute from expected attributes if public SP target or wbPK is not part of AuthBlock - if (!session.getSAMLAttributeGebeORwbpk()) expectedSAMLAttributeNumber--; - - //check number of attributes in AuthBlock response against expected number of attributes - int actualSAMLAttributeNumber = samlAttributes.length; - if (actualSAMLAttributeNumber != expectedSAMLAttributeNumber) { - Logger.error("Wrong number of SAML attributes in CreateXMLSignatureResponse: expected " + - expectedSAMLAttributeNumber + ", but was " + actualSAMLAttributeNumber); - throw new ValidateException("validator.36", - new Object[] {String.valueOf(actualSAMLAttributeNumber), String.valueOf(expectedSAMLAttributeNumber)}); - - } - - //now check every single attribute - SAMLAttribute samlAttribute = null; - Pair<String, String> userSectorId = null; - if (session.getSAMLAttributeGebeORwbpk()) { - //check the first attribute ("Geschaeftsbereich" or "wbPK") - samlAttribute = samlAttributes[0]; - - //calculate bPK or wbPK as reference value for validation - if (MiscUtil.isNotEmpty(saml1RequestedTarget)) - userSectorId = new BPKBuilder().generateAreaSpecificPersonIdentifier( - identityLink.getIdentificationValue(), identityLink.getIdentificationType(), - saml1RequestedTarget); - else - userSectorId = new BPKBuilder().generateAreaSpecificPersonIdentifier( - identityLink.getIdentificationValue(), identityLink.getIdentificationType(), - oaParam.getAreaSpecificTargetIdentifier()); - - //every sector specific identifier that has not 'urn:publicid:gv.at:cdid+' as prefix - // is internally handled as an AuthBlock with wbPK - if (!userSectorId.getSecond().startsWith(MOAIDAuthConstants.PREFIX_CDID)) { - if (!samlAttribute.getName().equals("wbPK")) { - if (samlAttribute.getName().equals("Geschaeftsbereich")) { - throw new ValidateException("validator.26", null); - - } else { - throw new ValidateException("validator.37", - new Object[] {samlAttribute.getName(), "wbPK", String.valueOf(1)}); - } - } - - if (samlAttribute.getNamespace().equals("http://reference.e-government.gv.at/namespace/moa/20020822#")) { - foundWBPK = true; - try { - Element attrValue = (Element)samlAttribute.getValue(); - String value = ((Element)attrValue.getElementsByTagNameNS(Constants.PD_NS_URI, "Value").item(0)).getFirstChild().getNodeValue(); - String type = ((Element)attrValue.getElementsByTagNameNS(Constants.PD_NS_URI, "Type").item(0)).getFirstChild().getNodeValue(); - if (!value.equals(userSectorId.getFirst())) - throw new ValidateException("validator.28", null); - - if (!type.equals(userSectorId.getSecond())) - throw new ValidateException("validator.28", null); - - } catch (Exception ex) { - throw new ValidateException("validator.29", null); - } - - } else - throw new ValidateException("validator.30", null); - - } else { - if (!samlAttribute.getName().equals("Geschaeftsbereich")) { - if (samlAttribute.getName().equals("wbPK")) - throw new ValidateException("validator.26", null); - - else - throw new ValidateException("validator.37", - new Object[] {samlAttribute.getName(), "Geschaeftsbereich", String.valueOf(1)}); - } - - if (samlAttribute.getNamespace().equals("http://reference.e-government.gv.at/namespace/moa/20020822#")) { - foundGB = true; - - String sectorName = TargetToSectorNameMapper.getSectorNameViaTarget(userSectorId.getSecond()); - if (StringUtils.isEmpty(sectorName)) { - if (saml1RequestedFriendlyName != null) - sectorName = saml1RequestedFriendlyName; - else - sectorName = oaParam.getAreaSpecificTargetIdentifierFriendlyName(); - } - - String refValueSector = userSectorId.getSecond().substring(MOAIDAuthConstants.PREFIX_CDID.length()) + " (" + sectorName + ")"; - if (!refValueSector.equals((String)samlAttribute.getValue())) - throw new ValidateException("validator.13", null); - - } else - throw new ValidateException("validator.12", null); - - } - - } else - //check nothing if wbPK or public SP target is not part of AuthBlock - offset--; - - // check the second attribute (must be "OA") - samlAttribute = samlAttributes[1 + offset]; - if (!samlAttribute.getName().equals("OA")) - throw new ValidateException("validator.37", - new Object[] {samlAttribute.getName(), "OA", String.valueOf(2)}); - - if (samlAttribute.getNamespace().equals("http://reference.e-government.gv.at/namespace/moa/20020822#")) { - foundOA = true; - if (!oaURL.equals((String)samlAttribute.getValue())) - throw new ValidateException("validator.16", new Object[] {":gefunden wurde '" + oaURL + "', erwartet wurde '" + samlAttribute.getValue()}); - - } else - throw new ValidateException("validator.15", null); - - - // check the third attribute (must be "Geburtsdatum") - samlAttribute = samlAttributes[2 + offset]; - if (!samlAttribute.getName().equals("Geburtsdatum")) - throw new ValidateException("validator.37", - new Object[] {samlAttribute.getName(), "Geburtsdatum", String.valueOf(3)}); - - if (samlAttribute.getNamespace().equals("http://reference.e-government.gv.at/namespace/moa/20020822#")) { - String samlDateOfBirth = (String)samlAttribute.getValue(); - String dateOfBirth = identityLink.getDateOfBirth(); - if (!samlDateOfBirth.equals(dateOfBirth)) - throw new ValidateException("validator.34", new Object[] {samlDateOfBirth, dateOfBirth}); - - } else - throw new ValidateException("validator.35", null); - - // check four attribute could be a special text - samlAttribute = samlAttributes[3 + offset]; - if (!samlAttribute.getName().equals("SpecialText")) - throw new ValidateException("validator.37", - new Object[] {samlAttribute.getName(), "SpecialText", String.valueOf(4)}); - - if (samlAttribute.getNamespace().equals("http://reference.e-government.gv.at/namespace/moa/20020822#")) { - String samlSpecialText = (String)samlAttribute.getValue(); - samlSpecialText = samlSpecialText.replaceAll("'", "'"); - - String text = ""; - if (MiscUtil.isNotEmpty(oaParam.getAditionalAuthBlockText())) { - Logger.debug("Use addional AuthBlock Text from OA=" + oaParam.getPublicURLPrefix()); - text = oaParam.getAditionalAuthBlockText(); - - } - - String specialText = AuthenticationBlockAssertionBuilder.generateSpecialText(text, - AuthenticationBlockAssertionBuilder.generateSpezialAuthBlockPatternMap( - pendingReq, issuer, identityLink.getDateOfBirth(), issueInstant)); - if (!samlSpecialText.equals(specialText)) - throw new ValidateException("validator.67", new Object[] {samlSpecialText, specialText}); - - } else - throw new ValidateException("validator.35", null); - - - //check unique AuthBlock tokken - samlAttribute = samlAttributes[4 + offset]; - if (!samlAttribute.getName().equals("UniqueTokken")) - throw new ValidateException("validator.37", - new Object[] {samlAttribute.getName(), "UniqueTokken", String.valueOf(5)}); - - if (samlAttribute.getNamespace().equals("http://reference.e-government.gv.at/namespace/moa/20020822#")) { - String uniquetokken = (String)samlAttribute.getValue(); - - if (!uniquetokken.equals(session.getAuthBlockTokken())) - throw new ValidateException("validator.70", new Object[] {uniquetokken, session.getAuthBlockTokken()}); - } else - throw new ValidateException("validator.35", null); - - - // now check the extended SAML attributes - int i = AuthenticationBlockAssertionBuilder.NUM_OF_SAML_ATTRIBUTES + offset; - if (extendedSAMLAttributes != null) { - Iterator<ExtendedSAMLAttribute> it = extendedSAMLAttributes.iterator(); - while (it.hasNext()) { - ExtendedSAMLAttribute extendedSAMLAttribute = (ExtendedSAMLAttribute)it.next(); - samlAttribute = samlAttributes[i]; - String actualName = samlAttribute.getName(); - String expectedName = extendedSAMLAttribute.getName(); - if (!actualName.equals(expectedName)) - throw new ValidateException("validator.38", - new Object[] {"Name", String.valueOf((i+1)), actualName, actualName, expectedName }); - - String actualNamespace = samlAttribute.getNamespace(); - String expectedNamespace = extendedSAMLAttribute.getNameSpace(); - if (!actualNamespace.equals(expectedNamespace)) - throw new ValidateException("validator.38", - new Object[] {"Namespace", String.valueOf((i+1)), actualName, actualNamespace, expectedNamespace, }); - - Object expectedValue = extendedSAMLAttribute.getValue(); - Object actualValue = samlAttribute.getValue(); - try { - if (expectedValue instanceof String) { - // replace \r\n because text might be base64-encoded - String expValue = StringUtils.replaceAll((String)expectedValue,"\r",""); - expValue = StringUtils.replaceAll(expValue,"\n",""); - String actValue = StringUtils.replaceAll((String)actualValue,"\r",""); - actValue = StringUtils.replaceAll(actValue,"\n",""); - if (!expValue.equals(actValue)) - throw new ValidateException("validator.38", - new Object[] {"Wert", String.valueOf((i+1)), actualName, actualValue, expectedValue }); - - } else if (expectedValue instanceof Element) { - // only check the name of the element - String actualElementName = ((Element)actualValue).getNodeName(); - String expectedElementName = ((Element)expectedValue).getNodeName(); - if (!(expectedElementName.equals(actualElementName))) - throw new ValidateException("validator.38", - new Object[] {"Wert", String.valueOf((i+1)), actualName, actualElementName, expectedElementName}); - - } else - // should not happen - throw new ValidateException("validator.38", - new Object[] {"Typ", String.valueOf((i+1)), expectedName, "java.lang.String oder org.wrc.dom.Element", expectedValue.getClass().getName()}); - - } catch (ClassCastException e) { - throw new ValidateException("validator.38", - new Object[] {"Typ", String.valueOf((i+1)), expectedName, expectedValue.getClass().getName(), actualValue.getClass().getName()}); - } - - i++; - } - } - - if (!foundOA) - throw new ValidateException("validator.14", null); - - if (userSectorId != null && !userSectorId.getSecond().startsWith(MOAIDAuthConstants.PREFIX_CDID)) { - if (session.getSAMLAttributeGebeORwbpk() && !foundWBPK) - throw new ValidateException("validator.31", null); - - } else { - if (!foundGB && session.getSAMLAttributeGebeORwbpk()) - throw new ValidateException("validator.11", null); - } - - //Check if dsig:Signature exists - Element dsigSignature = (Element) XPathUtils.selectSingleNode(samlAssertion, SIGNATURE_XPATH); - if (dsigSignature == null) - throw new ValidateException("validator.05", new Object[] {"im AUTHBlock"}) ; - + + try { + Element samlAssertion = createXMLSignatureResponse.getSamlAssertion(); + + //validate issuer + String issuer = samlAssertion.getAttribute("Issuer"); + if (issuer == null) { + // should not happen, because parser would dedect this + throw new ValidateException("validator.32", null); + } + // replace ' in name with ' + issuer = issuer.replaceAll("'", "'"); + if (!issuer.equals(identityLink.getName())) + throw new ValidateException("validator.33", new Object[] {issuer, identityLink.getName()}); + + + //validate issuerInstant + String issueInstant = samlAssertion.getAttribute("IssueInstant"); + if (!issueInstant.equals(session.getIssueInstant())) + throw new ValidateException("validator.39", new Object[] {issueInstant, session.getIssueInstant()}); + + + //validate extended attributes + SAMLAttribute[] samlAttributes = createXMLSignatureResponse.getSamlAttributes(); + + boolean foundOA = false; + boolean foundGB = false; + boolean foundWBPK = false; + int offset = 0; + + // check number of SAML attributes + List<ExtendedSAMLAttribute> extendedSAMLAttributes = session.getExtendedSAMLAttributesAUTH(); + int extendedSAMLAttributesNum = 0; + if (extendedSAMLAttributes != null) { + extendedSAMLAttributesNum = extendedSAMLAttributes.size(); + } + int expectedSAMLAttributeNumber = AuthenticationBlockAssertionBuilder.NUM_OF_SAML_ATTRIBUTES + extendedSAMLAttributesNum; + + //remove one attribute from expected attributes if public SP target or wbPK is not part of AuthBlock + if (!session.getSAMLAttributeGebeORwbpk()) expectedSAMLAttributeNumber--; + + //check number of attributes in AuthBlock response against expected number of attributes + int actualSAMLAttributeNumber = samlAttributes.length; + if (actualSAMLAttributeNumber != expectedSAMLAttributeNumber) { + Logger.error("Wrong number of SAML attributes in CreateXMLSignatureResponse: expected " + + expectedSAMLAttributeNumber + ", but was " + actualSAMLAttributeNumber); + throw new ValidateException("validator.36", + new Object[] {String.valueOf(actualSAMLAttributeNumber), String.valueOf(expectedSAMLAttributeNumber)}); + + } + + //now check every single attribute + SAMLAttribute samlAttribute = null; + Pair<String, String> userSectorId = null; + if (session.getSAMLAttributeGebeORwbpk()) { + //check the first attribute ("Geschaeftsbereich" or "wbPK") + samlAttribute = samlAttributes[0]; + + //calculate bPK or wbPK as reference value for validation + if (MiscUtil.isNotEmpty(saml1RequestedTarget)) + userSectorId = new BPKBuilder().generateAreaSpecificPersonIdentifier( + identityLink.getIdentificationValue(), identityLink.getIdentificationType(), + saml1RequestedTarget); + else + userSectorId = new BPKBuilder().generateAreaSpecificPersonIdentifier( + identityLink.getIdentificationValue(), identityLink.getIdentificationType(), + oaParam.getAreaSpecificTargetIdentifier()); + + //every sector specific identifier that has not 'urn:publicid:gv.at:cdid+' as prefix + // is internally handled as an AuthBlock with wbPK + if (!userSectorId.getSecond().startsWith(MOAIDAuthConstants.PREFIX_CDID)) { + if (!samlAttribute.getName().equals("wbPK")) { + if (samlAttribute.getName().equals("Geschaeftsbereich")) { + throw new ValidateException("validator.26", null); + + } else { + throw new ValidateException("validator.37", + new Object[] {samlAttribute.getName(), "wbPK", String.valueOf(1)}); + } + } + + if (samlAttribute.getNamespace().equals("http://reference.e-government.gv.at/namespace/moa/20020822#")) { + foundWBPK = true; + try { + Element attrValue = (Element)samlAttribute.getValue(); + String value = ((Element)attrValue.getElementsByTagNameNS(Constants.PD_NS_URI, "Value").item(0)).getFirstChild().getNodeValue(); + String type = ((Element)attrValue.getElementsByTagNameNS(Constants.PD_NS_URI, "Type").item(0)).getFirstChild().getNodeValue(); + if (!value.equals(userSectorId.getFirst())) + throw new ValidateException("validator.28", + new Object[] {value, userSectorId.getFirst()}); + + if (!type.equals(userSectorId.getSecond())) + throw new ValidateException("validator.28", + new Object[] {type, userSectorId.getSecond()}); + + } catch (Exception ex) { + throw new ValidateException("validator.29", null); + } + + } else + throw new ValidateException("validator.30", null); + + } else { + if (!samlAttribute.getName().equals("Geschaeftsbereich")) { + if (samlAttribute.getName().equals("wbPK")) + throw new ValidateException("validator.26", null); + + else + throw new ValidateException("validator.37", + new Object[] {samlAttribute.getName(), "Geschaeftsbereich", String.valueOf(1)}); + } + + if (samlAttribute.getNamespace().equals("http://reference.e-government.gv.at/namespace/moa/20020822#")) { + foundGB = true; + + String sectorName = TargetToSectorNameMapper.getSectorNameViaTarget(userSectorId.getSecond()); + if (StringUtils.isEmpty(sectorName)) { + if (saml1RequestedFriendlyName != null) + sectorName = saml1RequestedFriendlyName; + else + sectorName = oaParam.getAreaSpecificTargetIdentifierFriendlyName(); + } + + String refValueSector = userSectorId.getSecond().substring(MOAIDAuthConstants.PREFIX_CDID.length()) + " (" + sectorName + ")"; + if (!refValueSector.equals((String)samlAttribute.getValue())) { + if (validateTargetFriendlyName) + throw new ValidateException("validator.13", new Object[] {(String)samlAttribute.getValue(), refValueSector}); + + else { + Logger.warn("AuthBlock 'TargetFriendlyName' " + samlAttribute.getValue() + " does not match to " + refValueSector); + + } + + } + + } else + throw new ValidateException("validator.12", null); + + } + + } else + //check nothing if wbPK or public SP target is not part of AuthBlock + offset--; + + // check the second attribute (must be "OA") + samlAttribute = samlAttributes[1 + offset]; + if (!samlAttribute.getName().equals("OA")) + throw new ValidateException("validator.37", + new Object[] {samlAttribute.getName(), "OA", String.valueOf(2)}); + + if (samlAttribute.getNamespace().equals("http://reference.e-government.gv.at/namespace/moa/20020822#")) { + foundOA = true; + if (!oaURL.equals((String)samlAttribute.getValue())) + throw new ValidateException("validator.16", new Object[] {":gefunden wurde '" + oaURL + "', erwartet wurde '" + samlAttribute.getValue()}); + + } else + throw new ValidateException("validator.15", null); + + + // check the third attribute (must be "Geburtsdatum") + samlAttribute = samlAttributes[2 + offset]; + if (!samlAttribute.getName().equals("Geburtsdatum")) + throw new ValidateException("validator.37", + new Object[] {samlAttribute.getName(), "Geburtsdatum", String.valueOf(3)}); + + if (samlAttribute.getNamespace().equals("http://reference.e-government.gv.at/namespace/moa/20020822#")) { + String samlDateOfBirth = (String)samlAttribute.getValue(); + String dateOfBirth = identityLink.getDateOfBirth(); + if (!samlDateOfBirth.equals(dateOfBirth)) + throw new ValidateException("validator.34", new Object[] {samlDateOfBirth, dateOfBirth}); + + } else + throw new ValidateException("validator.35", null); + + // check four attribute could be a special text + samlAttribute = samlAttributes[3 + offset]; + if (!samlAttribute.getName().equals("SpecialText")) + throw new ValidateException("validator.37", + new Object[] {samlAttribute.getName(), "SpecialText", String.valueOf(4)}); + + if (samlAttribute.getNamespace().equals("http://reference.e-government.gv.at/namespace/moa/20020822#")) { + String samlSpecialText = (String)samlAttribute.getValue(); + samlSpecialText = samlSpecialText.replaceAll("'", "'"); + + String text = ""; + if (MiscUtil.isNotEmpty(oaParam.getAditionalAuthBlockText())) { + Logger.debug("Use addional AuthBlock Text from OA=" + oaParam.getPublicURLPrefix()); + text = oaParam.getAditionalAuthBlockText(); + + } + + String specialText = AuthenticationBlockAssertionBuilder.generateSpecialText(text, + AuthenticationBlockAssertionBuilder.generateSpezialAuthBlockPatternMap( + pendingReq, issuer, identityLink.getDateOfBirth(), issueInstant)); + if (!samlSpecialText.equals(specialText)) + throw new ValidateException("validator.67", new Object[] {samlSpecialText, specialText}); + + } else + throw new ValidateException("validator.35", null); + + + //check unique AuthBlock tokken + samlAttribute = samlAttributes[4 + offset]; + if (!samlAttribute.getName().equals("UniqueTokken")) + throw new ValidateException("validator.37", + new Object[] {samlAttribute.getName(), "UniqueTokken", String.valueOf(5)}); + + if (samlAttribute.getNamespace().equals("http://reference.e-government.gv.at/namespace/moa/20020822#")) { + String uniquetokken = (String)samlAttribute.getValue(); + + if (!uniquetokken.equals(session.getAuthBlockTokken())) + throw new ValidateException("validator.70", new Object[] {uniquetokken, session.getAuthBlockTokken()}); + } else + throw new ValidateException("validator.35", null); + + + // now check the extended SAML attributes + int i = AuthenticationBlockAssertionBuilder.NUM_OF_SAML_ATTRIBUTES + offset; + if (extendedSAMLAttributes != null) { + Iterator<ExtendedSAMLAttribute> it = extendedSAMLAttributes.iterator(); + while (it.hasNext()) { + ExtendedSAMLAttribute extendedSAMLAttribute = (ExtendedSAMLAttribute)it.next(); + samlAttribute = samlAttributes[i]; + String actualName = samlAttribute.getName(); + String expectedName = extendedSAMLAttribute.getName(); + if (!actualName.equals(expectedName)) + throw new ValidateException("validator.38", + new Object[] {"Name", String.valueOf((i+1)), actualName, actualName, expectedName }); + + String actualNamespace = samlAttribute.getNamespace(); + String expectedNamespace = extendedSAMLAttribute.getNameSpace(); + if (!actualNamespace.equals(expectedNamespace)) + throw new ValidateException("validator.38", + new Object[] {"Namespace", String.valueOf((i+1)), actualName, actualNamespace, expectedNamespace, }); + + Object expectedValue = extendedSAMLAttribute.getValue(); + Object actualValue = samlAttribute.getValue(); + try { + if (expectedValue instanceof String) { + // replace \r\n because text might be base64-encoded + String expValue = StringUtils.replaceAll((String)expectedValue,"\r",""); + expValue = StringUtils.replaceAll(expValue,"\n",""); + String actValue = StringUtils.replaceAll((String)actualValue,"\r",""); + actValue = StringUtils.replaceAll(actValue,"\n",""); + if (!expValue.equals(actValue)) + throw new ValidateException("validator.38", + new Object[] {"Wert", String.valueOf((i+1)), actualName, actualValue, expectedValue }); + + } else if (expectedValue instanceof Element) { + // only check the name of the element + String actualElementName = ((Element)actualValue).getNodeName(); + String expectedElementName = ((Element)expectedValue).getNodeName(); + if (!(expectedElementName.equals(actualElementName))) + throw new ValidateException("validator.38", + new Object[] {"Wert", String.valueOf((i+1)), actualName, actualElementName, expectedElementName}); + + } else + // should not happen + throw new ValidateException("validator.38", + new Object[] {"Typ", String.valueOf((i+1)), expectedName, "java.lang.String oder org.wrc.dom.Element", expectedValue.getClass().getName()}); + + } catch (ClassCastException e) { + throw new ValidateException("validator.38", + new Object[] {"Typ", String.valueOf((i+1)), expectedName, expectedValue.getClass().getName(), actualValue.getClass().getName()}); + } + + i++; + } + } + + if (!foundOA) + throw new ValidateException("validator.14", null); + + if (userSectorId != null && !userSectorId.getSecond().startsWith(MOAIDAuthConstants.PREFIX_CDID)) { + if (session.getSAMLAttributeGebeORwbpk() && !foundWBPK) + throw new ValidateException("validator.31", null); + + } else { + if (!foundGB && session.getSAMLAttributeGebeORwbpk()) + throw new ValidateException("validator.11", null); + } + + //Check if dsig:Signature exists + Element dsigSignature = (Element) XPathUtils.selectSingleNode(samlAssertion, SIGNATURE_XPATH); + if (dsigSignature == null) + throw new ValidateException("validator.05", new Object[] {"im AUTHBlock"}) ; + + } catch (Exception e) { + SpecificTraceLogger.trace("Validate AuthBlock without SSO"); + SpecificTraceLogger.trace("Signed AuthBlock: " + Base64Utils.encodeToString(session.getAuthBlock().getBytes())); + SpecificTraceLogger.trace("OA config: " + oaParam.toString()); + SpecificTraceLogger.trace("saml1RequestedTarget: " + saml1RequestedTarget); + SpecificTraceLogger.trace("saml1RequestedFriendlyName: " + saml1RequestedFriendlyName); + throw e; + + } } /** @@ -436,219 +456,227 @@ public class CreateXMLSignatureResponseValidator { */ public void validateSSO(CreateXMLSignatureResponse createXMLSignatureResponse, IAuthenticationSession session, IRequest pendingReq) throws ValidateException { - - // A3.056: more then one /saml:Assertion/saml:AttributeStatement/saml:Subject/saml:NameIdentifier - String oaURL = pendingReq.getAuthURL(); - - IIdentityLink identityLink = session.getIdentityLink(); - - Element samlAssertion = createXMLSignatureResponse.getSamlAssertion(); - String issuer = samlAssertion.getAttribute("Issuer"); - if (issuer == null) { - // should not happen, because parser would dedect this - throw new ValidateException("validator.32", null); - } - // replace ' in name with ' - issuer = issuer.replaceAll("'", "'"); - - String issueInstant = samlAssertion.getAttribute("IssueInstant"); - if (!issueInstant.equals(session.getIssueInstant())) { - throw new ValidateException("validator.39", new Object[] {issueInstant, session.getIssueInstant()}); - } - - String name = identityLink.getName(); - - if (!issuer.equals(name)) { - throw new ValidateException("validator.33", new Object[] {issuer, name}); - } - - SAMLAttribute[] samlAttributes = createXMLSignatureResponse.getSamlAttributes(); - - boolean foundOA = false; -// boolean foundGB = false; -// boolean foundWBPK = false; - int offset = 0; - - // check number of SAML aatributes - List<ExtendedSAMLAttribute> extendedSAMLAttributes = session.getExtendedSAMLAttributesAUTH(); - int extendedSAMLAttributesNum = 0; - if (extendedSAMLAttributes != null) { - extendedSAMLAttributesNum = extendedSAMLAttributes.size(); - } - int expectedSAMLAttributeNumber = - AuthenticationBlockAssertionBuilder.NUM_OF_SAML_ATTRIBUTES_SSO + extendedSAMLAttributesNum; - if (!session.getSAMLAttributeGebeORwbpk()) expectedSAMLAttributeNumber--; - int actualSAMLAttributeNumber = samlAttributes.length; - if (actualSAMLAttributeNumber != expectedSAMLAttributeNumber) { - Logger.error("Wrong number of SAML attributes in CreateXMLSignatureResponse: expected " + - expectedSAMLAttributeNumber + ", but was " + actualSAMLAttributeNumber); - throw new ValidateException( - "validator.36", - new Object[] {String.valueOf(actualSAMLAttributeNumber), String.valueOf(expectedSAMLAttributeNumber)}); - } - - SAMLAttribute samlAttribute; - if (!session.getSAMLAttributeGebeORwbpk()) { - offset--; - } - - // check the first attribute (must be "OA") - samlAttribute = samlAttributes[0 + offset]; - if (!samlAttribute.getName().equals("OA")) { - throw new ValidateException( - "validator.37", - new Object[] {samlAttribute.getName(), "OA", String.valueOf(2)}); - } - if (samlAttribute.getNamespace().equals("http://reference.e-government.gv.at/namespace/moa/20020822#")) { - foundOA = true; - if (!oaURL.equals((String)samlAttribute.getValue())) { // CHECKS für die AttributeVALUES fehlen noch - throw new ValidateException("validator.16", new Object[] {":gefunden wurde '" + oaURL + "', erwartet wurde '" + samlAttribute.getValue()}); - } - } else { - throw new ValidateException("validator.15", null); - } - - // check the third attribute (must be "Geburtsdatum") - samlAttribute = samlAttributes[1 + offset]; - if (!samlAttribute.getName().equals("Geburtsdatum")) { - throw new ValidateException( - "validator.37", - new Object[] {samlAttribute.getName(), "Geburtsdatum", String.valueOf(3)}); - } - if (samlAttribute.getNamespace().equals("http://reference.e-government.gv.at/namespace/moa/20020822#")) { - String samlDateOfBirth = (String)samlAttribute.getValue(); - String dateOfBirth = identityLink.getDateOfBirth(); - if (!samlDateOfBirth.equals(dateOfBirth)) { - throw new ValidateException("validator.34", new Object[] {samlDateOfBirth, dateOfBirth}); - } - } else { - throw new ValidateException("validator.35", null); - } - - // check four attribute could be a special text - samlAttribute = samlAttributes[2 + offset]; - if (!samlAttribute.getName().equals("SpecialText")) { - throw new ValidateException( - "validator.37", - new Object[] {samlAttribute.getName(), "SpecialText", String.valueOf(4)}); - } - if (samlAttribute.getNamespace().equals("http://reference.e-government.gv.at/namespace/moa/20020822#")) { - String samlSpecialText = (String)samlAttribute.getValue(); - samlSpecialText = samlSpecialText.replaceAll("'", "'"); - - String text = ""; - try { - if (MiscUtil.isNotEmpty(AuthConfigurationProviderFactory.getInstance().getSSOSpecialText())) { - text = AuthConfigurationProviderFactory.getInstance().getSSOSpecialText(); - Logger.debug("Use addional AuthBlock Text from SSO=" +text); - - } - else - text = new String(); - } catch (ConfigurationException e) { - Logger.warn("Addional AuthBlock Text can not loaded from SSO!", e); - } - - - String specialText = AuthenticationBlockAssertionBuilder.generateSpecialText(text, - AuthenticationBlockAssertionBuilder.generateSpezialAuthBlockPatternMap( - pendingReq, issuer, identityLink.getDateOfBirth(), issueInstant)); - if (!samlSpecialText.equals(specialText)) { - throw new ValidateException("validator.67", new Object[] {samlSpecialText, specialText}); - } - } else { - throw new ValidateException("validator.35", null); - } - - //check unique AuthBlock tokken - samlAttribute = samlAttributes[3 + offset]; - if (!samlAttribute.getName().equals("UniqueTokken")) { - throw new ValidateException( - "validator.37", - new Object[] {samlAttribute.getName(), "UniqueTokken", String.valueOf(5)}); - } - if (samlAttribute.getNamespace().equals("http://reference.e-government.gv.at/namespace/moa/20020822#")) { - String uniquetokken = (String)samlAttribute.getValue(); - - if (!uniquetokken.equals(session.getAuthBlockTokken())) { - throw new ValidateException("validator.70", new Object[] {uniquetokken, session.getAuthBlockTokken()}); - } - } else { - throw new ValidateException("validator.35", null); - } - - - // now check the extended SAML attributes - int i = AuthenticationBlockAssertionBuilder.NUM_OF_SAML_ATTRIBUTES_SSO + offset; - if (extendedSAMLAttributes != null) { - Iterator<ExtendedSAMLAttribute> it = extendedSAMLAttributes.iterator(); - while (it.hasNext()) { - ExtendedSAMLAttribute extendedSAMLAttribute = (ExtendedSAMLAttribute)it.next(); - samlAttribute = samlAttributes[i]; - String actualName = samlAttribute.getName(); - String expectedName = extendedSAMLAttribute.getName(); - if (!actualName.equals(expectedName)) { - throw new ValidateException( - "validator.38", - new Object[] {"Name", String.valueOf((i+1)), actualName, actualName, expectedName }); - } - String actualNamespace = samlAttribute.getNamespace(); - String expectedNamespace = extendedSAMLAttribute.getNameSpace(); - if (!actualNamespace.equals(expectedNamespace)) { - throw new ValidateException( - "validator.38", - new Object[] {"Namespace", String.valueOf((i+1)), actualName, actualNamespace, expectedNamespace, }); - } - Object expectedValue = extendedSAMLAttribute.getValue(); - Object actualValue = samlAttribute.getValue(); - try { - if (expectedValue instanceof String) { - // replace \r\n because text might be base64-encoded - String expValue = StringUtils.replaceAll((String)expectedValue,"\r",""); - expValue = StringUtils.replaceAll(expValue,"\n",""); - String actValue = StringUtils.replaceAll((String)actualValue,"\r",""); - actValue = StringUtils.replaceAll(actValue,"\n",""); - if (!expValue.equals(actValue)) { - throw new ValidateException( - "validator.38", - new Object[] {"Wert", String.valueOf((i+1)), actualName, actualValue, expectedValue }); - } - } else if (expectedValue instanceof Element) { - // only check the name of the element - String actualElementName = ((Element)actualValue).getNodeName(); - String expectedElementName = ((Element)expectedValue).getNodeName(); - if (!(expectedElementName.equals(actualElementName))){ - throw new ValidateException( - "validator.38", - new Object[] {"Wert", String.valueOf((i+1)), actualName, actualElementName, expectedElementName}); - } - } else { - // should not happen - throw new ValidateException( - "validator.38", - new Object[] {"Typ", String.valueOf((i+1)), expectedName, "java.lang.String oder org.wrc.dom.Element", expectedValue.getClass().getName()}); - } - } catch (ClassCastException e) { - throw new ValidateException( - "validator.38", - new Object[] {"Typ", String.valueOf((i+1)), expectedName, expectedValue.getClass().getName(), actualValue.getClass().getName()}); - } - i++; - } - } + try { + // A3.056: more then one /saml:Assertion/saml:AttributeStatement/saml:Subject/saml:NameIdentifier + String oaURL = pendingReq.getAuthURL(); + IIdentityLink identityLink = session.getIdentityLink(); + + Element samlAssertion = createXMLSignatureResponse.getSamlAssertion(); + String issuer = samlAssertion.getAttribute("Issuer"); + if (issuer == null) { + // should not happen, because parser would dedect this + throw new ValidateException("validator.32", null); + } + // replace ' in name with ' + issuer = issuer.replaceAll("'", "'"); + + String issueInstant = samlAssertion.getAttribute("IssueInstant"); + if (!issueInstant.equals(session.getIssueInstant())) { + throw new ValidateException("validator.39", new Object[] {issueInstant, session.getIssueInstant()}); + } + + String name = identityLink.getName(); + + if (!issuer.equals(name)) { + throw new ValidateException("validator.33", new Object[] {issuer, name}); + } + + SAMLAttribute[] samlAttributes = createXMLSignatureResponse.getSamlAttributes(); + + boolean foundOA = false; + // boolean foundGB = false; + // boolean foundWBPK = false; + int offset = 0; + + // check number of SAML aatributes + List<ExtendedSAMLAttribute> extendedSAMLAttributes = session.getExtendedSAMLAttributesAUTH(); + int extendedSAMLAttributesNum = 0; + if (extendedSAMLAttributes != null) { + extendedSAMLAttributesNum = extendedSAMLAttributes.size(); + } + int expectedSAMLAttributeNumber = + AuthenticationBlockAssertionBuilder.NUM_OF_SAML_ATTRIBUTES_SSO + extendedSAMLAttributesNum; + if (!session.getSAMLAttributeGebeORwbpk()) expectedSAMLAttributeNumber--; + int actualSAMLAttributeNumber = samlAttributes.length; + if (actualSAMLAttributeNumber != expectedSAMLAttributeNumber) { + Logger.error("Wrong number of SAML attributes in CreateXMLSignatureResponse: expected " + + expectedSAMLAttributeNumber + ", but was " + actualSAMLAttributeNumber); + throw new ValidateException( + "validator.36", + new Object[] {String.valueOf(actualSAMLAttributeNumber), String.valueOf(expectedSAMLAttributeNumber)}); + } + + SAMLAttribute samlAttribute; + if (!session.getSAMLAttributeGebeORwbpk()) { + offset--; + } + + // check the first attribute (must be "OA") + samlAttribute = samlAttributes[0 + offset]; + if (!samlAttribute.getName().equals("OA")) { + throw new ValidateException( + "validator.37", + new Object[] {samlAttribute.getName(), "OA", String.valueOf(2)}); + } + if (samlAttribute.getNamespace().equals("http://reference.e-government.gv.at/namespace/moa/20020822#")) { + foundOA = true; + if (!oaURL.equals((String)samlAttribute.getValue())) { // CHECKS für die AttributeVALUES fehlen noch + throw new ValidateException("validator.16", new Object[] {":gefunden wurde '" + oaURL + "', erwartet wurde '" + samlAttribute.getValue()}); + } + } else { + throw new ValidateException("validator.15", null); + } + + // check the third attribute (must be "Geburtsdatum") + samlAttribute = samlAttributes[1 + offset]; + if (!samlAttribute.getName().equals("Geburtsdatum")) { + throw new ValidateException( + "validator.37", + new Object[] {samlAttribute.getName(), "Geburtsdatum", String.valueOf(3)}); + } + if (samlAttribute.getNamespace().equals("http://reference.e-government.gv.at/namespace/moa/20020822#")) { + String samlDateOfBirth = (String)samlAttribute.getValue(); + String dateOfBirth = identityLink.getDateOfBirth(); + if (!samlDateOfBirth.equals(dateOfBirth)) { + throw new ValidateException("validator.34", new Object[] {samlDateOfBirth, dateOfBirth}); + } + } else { + throw new ValidateException("validator.35", null); + } + + // check four attribute could be a special text + samlAttribute = samlAttributes[2 + offset]; + if (!samlAttribute.getName().equals("SpecialText")) { + throw new ValidateException( + "validator.37", + new Object[] {samlAttribute.getName(), "SpecialText", String.valueOf(4)}); + } + if (samlAttribute.getNamespace().equals("http://reference.e-government.gv.at/namespace/moa/20020822#")) { + String samlSpecialText = (String)samlAttribute.getValue(); + samlSpecialText = samlSpecialText.replaceAll("'", "'"); + + String text = ""; + try { + if (MiscUtil.isNotEmpty(AuthConfigurationProviderFactory.getInstance().getSSOSpecialText())) { + text = AuthConfigurationProviderFactory.getInstance().getSSOSpecialText(); + Logger.debug("Use addional AuthBlock Text from SSO=" +text); + + } + else + text = new String(); + } catch (ConfigurationException e) { + Logger.warn("Addional AuthBlock Text can not loaded from SSO!", e); + } + + + String specialText = AuthenticationBlockAssertionBuilder.generateSpecialText(text, + AuthenticationBlockAssertionBuilder.generateSpezialAuthBlockPatternMap( + pendingReq, issuer, identityLink.getDateOfBirth(), issueInstant)); + if (!samlSpecialText.equals(specialText)) { + throw new ValidateException("validator.67", new Object[] {samlSpecialText, specialText}); + } + } else { + throw new ValidateException("validator.35", null); + } + + //check unique AuthBlock tokken + samlAttribute = samlAttributes[3 + offset]; + if (!samlAttribute.getName().equals("UniqueTokken")) { + throw new ValidateException( + "validator.37", + new Object[] {samlAttribute.getName(), "UniqueTokken", String.valueOf(5)}); + } + if (samlAttribute.getNamespace().equals("http://reference.e-government.gv.at/namespace/moa/20020822#")) { + String uniquetokken = (String)samlAttribute.getValue(); + + if (!uniquetokken.equals(session.getAuthBlockTokken())) { + throw new ValidateException("validator.70", new Object[] {uniquetokken, session.getAuthBlockTokken()}); + } + } else { + throw new ValidateException("validator.35", null); + } + + + // now check the extended SAML attributes + int i = AuthenticationBlockAssertionBuilder.NUM_OF_SAML_ATTRIBUTES_SSO + offset; + if (extendedSAMLAttributes != null) { + Iterator<ExtendedSAMLAttribute> it = extendedSAMLAttributes.iterator(); + while (it.hasNext()) { + ExtendedSAMLAttribute extendedSAMLAttribute = (ExtendedSAMLAttribute)it.next(); + samlAttribute = samlAttributes[i]; + String actualName = samlAttribute.getName(); + String expectedName = extendedSAMLAttribute.getName(); + if (!actualName.equals(expectedName)) { + throw new ValidateException( + "validator.38", + new Object[] {"Name", String.valueOf((i+1)), actualName, actualName, expectedName }); + } + String actualNamespace = samlAttribute.getNamespace(); + String expectedNamespace = extendedSAMLAttribute.getNameSpace(); + if (!actualNamespace.equals(expectedNamespace)) { + throw new ValidateException( + "validator.38", + new Object[] {"Namespace", String.valueOf((i+1)), actualName, actualNamespace, expectedNamespace, }); + } + Object expectedValue = extendedSAMLAttribute.getValue(); + Object actualValue = samlAttribute.getValue(); + try { + if (expectedValue instanceof String) { + // replace \r\n because text might be base64-encoded + String expValue = StringUtils.replaceAll((String)expectedValue,"\r",""); + expValue = StringUtils.replaceAll(expValue,"\n",""); + String actValue = StringUtils.replaceAll((String)actualValue,"\r",""); + actValue = StringUtils.replaceAll(actValue,"\n",""); + if (!expValue.equals(actValue)) { + throw new ValidateException( + "validator.38", + new Object[] {"Wert", String.valueOf((i+1)), actualName, actualValue, expectedValue }); + } + } else if (expectedValue instanceof Element) { + // only check the name of the element + String actualElementName = ((Element)actualValue).getNodeName(); + String expectedElementName = ((Element)expectedValue).getNodeName(); + if (!(expectedElementName.equals(actualElementName))){ + throw new ValidateException( + "validator.38", + new Object[] {"Wert", String.valueOf((i+1)), actualName, actualElementName, expectedElementName}); + } + } else { + // should not happen + throw new ValidateException( + "validator.38", + new Object[] {"Typ", String.valueOf((i+1)), expectedName, "java.lang.String oder org.wrc.dom.Element", expectedValue.getClass().getName()}); + } + } catch (ClassCastException e) { + throw new ValidateException( + "validator.38", + new Object[] {"Typ", String.valueOf((i+1)), expectedName, expectedValue.getClass().getName(), actualValue.getClass().getName()}); + } + i++; + } + } + + + if (!foundOA) throw new ValidateException("validator.14", null); + + //Check if dsig:Signature exists + // NodeList nl = createXMLSignatureResponse.getSamlAssertion().getElementsByTagNameNS(Constants.DSIG_NS_URI, "Signature"); + // if (nl.getLength() != 1) { + // throw new ValidateException("validator.05", null); + // } + Element dsigSignature = (Element) XPathUtils.selectSingleNode(samlAssertion, SIGNATURE_XPATH); + if (dsigSignature == null) { + throw new ValidateException("validator.05", new Object[] {"im AUTHBlock"}) ; + } + } catch (Exception e) { + SpecificTraceLogger.trace("Validate AuthBlock with SSO"); + SpecificTraceLogger.trace("Signed AuthBlock: " + Base64Utils.encodeToString(session.getAuthBlock().getBytes())); + SpecificTraceLogger.trace("OA config: " + pendingReq.getOnlineApplicationConfiguration().toString()); + throw e; + + } - if (!foundOA) throw new ValidateException("validator.14", null); - - //Check if dsig:Signature exists -// NodeList nl = createXMLSignatureResponse.getSamlAssertion().getElementsByTagNameNS(Constants.DSIG_NS_URI, "Signature"); -// if (nl.getLength() != 1) { -// throw new ValidateException("validator.05", null); -// } - Element dsigSignature = (Element) XPathUtils.selectSingleNode(samlAssertion, SIGNATURE_XPATH); - if (dsigSignature == null) { - throw new ValidateException("validator.05", new Object[] {"im AUTHBlock"}) ; - } } public void validateSigningDateTime( CreateXMLSignatureResponse csresp) throws ValidateException { |