/******************************************************************************* * 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.validator; import java.util.Calendar; import java.util.GregorianCalendar; import java.util.Iterator; 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.egiz.eaaf.core.api.IRequest; import at.gv.egiz.eaaf.core.api.idp.auth.data.IIdentityLink; import at.gv.egiz.eaaf.core.exceptions.EAAFBuilderException; import at.gv.egiz.eaaf.core.impl.data.Pair; import at.gv.egiz.eaaf.core.impl.idp.auth.builder.BPKBuilder; import at.gv.egiz.eaaf.core.impl.utils.XPathUtils; import at.gv.egovernment.moa.id.auth.builder.AuthenticationBlockAssertionBuilder; import at.gv.egovernment.moa.id.auth.data.CreateXMLSignatureResponse; import at.gv.egovernment.moa.id.auth.data.SAMLAttribute; import at.gv.egovernment.moa.id.auth.exception.BuildException; import at.gv.egovernment.moa.id.auth.exception.ValidateException; import at.gv.egovernment.moa.id.commons.MOAIDAuthConstants; import at.gv.egovernment.moa.id.commons.api.IOAAuthParameters; import at.gv.egovernment.moa.id.commons.api.data.ExtendedSAMLAttribute; import at.gv.egovernment.moa.id.commons.api.data.IAuthenticationSession; 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.logging.SpecificTraceLogger; import at.gv.egovernment.moa.logging.Logger; import at.gv.egovernment.moa.util.Constants; import at.gv.egovernment.moa.util.MiscUtil; import at.gv.egovernment.moa.util.StringUtils; /** * * This class is used to validate an {@link CreateXMLSignatureResponse} * returned by the security layer. * This class implements the Singleton pattern. * @author Stefan Knirsch * @version $Id$ */ public class CreateXMLSignatureResponseValidator { /** Xpath expression to the dsig:Signature element */ private static final String SIGNATURE_XPATH = Constants.DSIG_PREFIX + ":Signature"; private static final String XADES_1_1_1_SIGNINGTIME_PATH = "//" + Constants.XADES_1_1_1_NS_PREFIX + ":SigningTime"; private static final String XADES_1_3_2_SIGNINGTIME_PATH = "//" + Constants.XADES_1_3_2_NS_PREFIX + ":SigningTime"; private static final long MAX_DIFFERENCE_IN_MILLISECONDS = 600000; // 10min /** Singleton instance. null, if none has been created. */ private static CreateXMLSignatureResponseValidator instance; private static SimpleNamespaceContext NS_CONTEXT; static { NS_CONTEXT = new SimpleNamespaceContext(); NS_CONTEXT.addNamespace(Constants.XADES_1_1_1_NS_PREFIX, Constants.XADES_1_1_1_NS_URI); NS_CONTEXT.addNamespace(Constants.XADES_1_2_2_NS_PREFIX, Constants.XADES_1_2_2_NS_URI); NS_CONTEXT.addNamespace(Constants.XADES_1_3_2_NS_PREFIX, Constants.XADES_1_3_2_NS_URI); NS_CONTEXT.addNamespace(Constants.XADES_1_4_1_NS_PREFIX, Constants.XADES_1_4_1_NS_URI); } /** * Constructor for a singleton CreateXMLSignatureResponseValidator. * @return an instance of CreateXMLSignatureResponseValidator * @throws ValidateException if no instance can be created */ public static synchronized CreateXMLSignatureResponseValidator getInstance() throws ValidateException { if (instance == null) { instance = new CreateXMLSignatureResponseValidator(); } return instance; } /** * The Method validate is used for validating an explicit {@link CreateXMLSignatureResponse} * @param createXMLSignatureResponse * @param session * @param pendingReq * @param validateTargetFriendlyName * @throws ValidateException * @throws BuildException * @throws ConfigurationException */ public void validate(CreateXMLSignatureResponse createXMLSignatureResponse, IAuthenticationSession session, IRequest pendingReq, boolean validateTargetFriendlyName) throws ValidateException, BuildException, ConfigurationException, EAAFBuilderException { // A3.056: more then one /saml:Assertion/saml:AttributeStatement/saml:Subject/saml:NameIdentifier IOAAuthParameters oaParam = pendingReq.getServiceProviderConfiguration(IOAAuthParameters.class); String oaURL = oaParam.getPublicURLPrefix(); IIdentityLink identityLink = session.getIdentityLink(); @Deprecated String saml1RequestedTarget = pendingReq.getRawData( MOAIDAuthConstants.AUTHPROCESS_DATA_TARGET, String.class); @Deprecated String saml1RequestedFriendlyName = pendingReq.getRawData( MOAIDAuthConstants.AUTHPROCESS_DATA_TARGETFRIENDLYNAME, String.class); 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().replaceAll("'", "'"))) 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 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 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 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; } } /** * The Method validate is used for validating an explicit {@link CreateXMLSignatureResponse} * @param createXMLSignatureResponse * @param session * @param pendingReq * @throws ValidateException */ public void validateSSO(CreateXMLSignatureResponse createXMLSignatureResponse, IAuthenticationSession session, IRequest pendingReq) throws ValidateException { 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().replaceAll("'", "'"); 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 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 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: " + session.getAuthBlock()); SpecificTraceLogger.trace("OA config: " + pendingReq.getServiceProviderConfiguration().toString()); throw e; } } public void validateSigningDateTime( CreateXMLSignatureResponse csresp) throws ValidateException { Element dsigSignatureElement = csresp.getDsigSignature(); if (dsigSignatureElement == null) { throw new ValidateException("validator.05", new Object[] {"im AUTHBlock"}) ; } else { Element signingTimeElem = (Element) XPathUtils.selectSingleNode(dsigSignatureElement, NS_CONTEXT, XADES_1_1_1_SIGNINGTIME_PATH); if (signingTimeElem == null) { signingTimeElem = (Element) XPathUtils.selectSingleNode(dsigSignatureElement, NS_CONTEXT, XADES_1_3_2_SIGNINGTIME_PATH); if (signingTimeElem == null) throw new ValidateException("validator.68", null) ; } String signingTimeStr = signingTimeElem.getTextContent(); if (signingTimeStr == null) throw new ValidateException("validator.68", null) ; Calendar signingTimeCal = DatatypeConverter.parseDate(signingTimeStr); Calendar serverTimeCal = new GregorianCalendar(); long diff = Math.abs(signingTimeCal.getTimeInMillis() - serverTimeCal.getTimeInMillis()); if (diff > MAX_DIFFERENCE_IN_MILLISECONDS) throw new ValidateException("validator.69", new Object[] {"mehr als " + MAX_DIFFERENCE_IN_MILLISECONDS + " Millisekunden"}) ; Logger.debug("Compare \"" + signingTimeCal.getTime() + "\" (SigningTime) with \"" + serverTimeCal.getTime() + "\" (server time)"); } } }