package at.gv.egiz.eaaf.modules.pvp2.test; import at.gv.egiz.eaaf.core.api.idp.IConfiguration; import at.gv.egiz.eaaf.core.exceptions.EaafException; import at.gv.egiz.eaaf.core.exceptions.EaafProtocolException; import at.gv.egiz.eaaf.core.exceptions.InvalidProtocolRequestException; import at.gv.egiz.eaaf.core.impl.data.Pair; import at.gv.egiz.eaaf.modules.pvp2.api.credential.EaafX509Credential; import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider; import at.gv.egiz.eaaf.modules.pvp2.exception.CredentialsNotAvailableException; import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2MetadataException; import at.gv.egiz.eaaf.modules.pvp2.exception.SamlAssertionValidationExeption; import at.gv.egiz.eaaf.modules.pvp2.exception.SamlSigningException; import at.gv.egiz.eaaf.modules.pvp2.impl.message.PvpSProfileRequest; import at.gv.egiz.eaaf.modules.pvp2.impl.validation.TrustEngineFactory; import at.gv.egiz.eaaf.modules.pvp2.impl.verification.SamlVerificationEngine; import at.gv.egiz.eaaf.modules.pvp2.test.dummy.DummyCredentialProvider; import at.gv.egiz.eaaf.modules.pvp2.test.dummy.DummyMetadataProvider; import org.joda.time.DateTime; import org.junit.Test; import org.junit.runner.RunWith; import org.opensaml.core.xml.io.UnmarshallingException; import org.opensaml.core.xml.util.XMLObjectSupport; import org.opensaml.saml.common.xml.SAMLConstants; import org.opensaml.saml.saml2.core.Assertion; import org.opensaml.saml.saml2.core.AuthnRequest; import org.opensaml.saml.saml2.core.EncryptedAssertion; import org.opensaml.saml.saml2.core.Response; import org.opensaml.saml.saml2.core.StatusCode; import org.opensaml.xmlsec.signature.support.SignatureConstants; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.util.Assert; import org.w3c.dom.Element; import net.shibboleth.utilities.java.support.xml.XMLParserException; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration({ "/spring/test_eaaf_pvp.beans.xml", "/spring/test_eaaf_core_spring_config.beans.xml", "/spring/eaaf_utils.beans.xml" }) @TestPropertySource(locations = { "/config/config_1.props" }) public class SamlVerificationEngineTest extends AbstractSamlVerificationEngine { @Autowired private SamlVerificationEngine verifyEngine; @Autowired private DummyCredentialProvider credentialProvider; @Autowired DummyMetadataProvider metadataProvider; @Autowired IConfiguration authConfig; @Override protected String getMetadataClassPathEntityPath() { return "classpath:/data/pvp_metadata_junit_keystore_classpath_entityId.xml"; } @Override protected String getMetadataJunitJKeystore() { return "classpath:/data/pvp_metadata_junit_keystore.xml"; } @Override protected String getAuthnRequestWithoutSigPath() { return "/data/AuthRequest_without_sig_1.xml"; } @Override protected String getResponseWithSigPath() { return "/data/Response_with_sig_1.xml"; } @Override protected String getResponseWithoutSigPath() { return "/data/Response_without_sig_1.xml"; } @Test public void validateSamlRequestWrongSignatureAlg() throws SecurityException, Exception { final String authnReqPath = getAuthnRequestWithoutSigPath(); final String metadataPath = getMetadataJunitJKeystore(); final String spEntityId = metadataPath; metadataProvider.runGarbageCollector(); final EaafX509Credential cred = credentialProvider.getMetaDataSigningCredential(); cred.setSignatureAlgorithmForSigning(SignatureConstants.ALGO_ID_SIGNATURE_NOT_RECOMMENDED_RSA_MD5); final Pair inputMsg = initializeAuthnRequest(spEntityId, metadataPath, authnReqPath, cred); final PvpSProfileRequest msg = new PvpSProfileRequest( inputMsg.getFirst(), SAMLConstants.SAML2_POST_BINDING_URI); msg.setEntityID(spEntityId); try { verifyEngine.verify(msg, TrustEngineFactory.getSignatureKnownKeysTrustEngine(metadataProvider)); org.junit.Assert.fail("Wrong SigAlg not detected"); } catch (final Exception e) { Assert.isInstanceOf(EaafProtocolException.class, e, "Wrong exceptionType"); org.junit.Assert.assertEquals("Wrong errorcode", "internal.pvp.99", ((EaafException) e).getErrorId()); } } @Test public void validateSamlInvalidRequest() throws SecurityException, Exception { final String authnReqPath = "/data/AuthRequest_without_sig_missing_id.xml"; final String metadataPath = getMetadataJunitJKeystore(); final String spEntityId = metadataPath; final Pair inputMsg = initializeAuthnRequest(spEntityId, metadataPath, authnReqPath, credentialProvider.getMetaDataSigningCredential()); metadataProvider.addMetadataResolverIntoChain(inputMsg.getSecond()); final PvpSProfileRequest msg = new PvpSProfileRequest( inputMsg.getFirst(), SAMLConstants.SAML2_POST_BINDING_URI); msg.setEntityID(spEntityId); try { verifyEngine.verify(msg, TrustEngineFactory.getSignatureKnownKeysTrustEngine(metadataProvider)); org.junit.Assert.fail("invalid request not detected"); } catch (final Exception e) { Assert.isInstanceOf(InvalidProtocolRequestException.class, e, "Wrong exceptionType"); org.junit.Assert.assertEquals("Wrong errorcode", "internal.pvp.03", ((EaafException) e).getErrorId()); } } @Test public void verifyAssertionSucessNotEncrypted() throws SamlSigningException, Pvp2MetadataException, CredentialsNotAvailableException, XMLParserException, UnmarshallingException, SamlAssertionValidationExeption { final String authnReqPath = "/data/Response_without_sig_classpath_entityid.xml"; final String metadataPath = getMetadataJunitJKeystore(); final String spEntityId = "https://demo.egiz.gv.at/demoportal_demologin/"; final Pair inputMsg = initializeResponse(spEntityId, metadataPath, authnReqPath, credentialProvider.getMetaDataSigningCredential()); verifyEngine.validateAssertion(inputMsg.getFirst(), credentialProvider.getMetaDataSigningCredential(), spEntityId, "jUnit Test", false); } @Test public void verifyAssertionWrongAudiency() throws SamlSigningException, Pvp2MetadataException, CredentialsNotAvailableException, XMLParserException, UnmarshallingException, SamlAssertionValidationExeption { final String authnReqPath = "/data/Response_without_sig_classpath_entityid.xml"; final String metadataPath = getMetadataJunitJKeystore(); final String spEntityId = "https://demo.egiz.gv.at/"; final Pair inputMsg = initializeResponse(spEntityId, metadataPath, authnReqPath, credentialProvider.getMetaDataSigningCredential()); try { verifyEngine.validateAssertion(inputMsg.getFirst(), credentialProvider.getMetaDataSigningCredential(), spEntityId, "jUnit Test", false); org.junit.Assert.fail("Wrong Audiency not detected"); } catch (final SamlAssertionValidationExeption e) { org.junit.Assert.assertEquals("Wrong errorcode", "internal.pvp.15", ((EaafException) e).getErrorId()); } } @Test public void verifyAssertionWrongStatusCode() throws SamlSigningException, Pvp2MetadataException, CredentialsNotAvailableException, XMLParserException, UnmarshallingException, SamlAssertionValidationExeption { final String authnReqPath = "/data/Response_without_sig_classpath_entityid.xml"; final String metadataPath = getMetadataJunitJKeystore(); final String spEntityId = "https://demo.egiz.gv.at/demoportal_demologin/"; final Pair inputMsg = initializeResponse(spEntityId, metadataPath, authnReqPath, credentialProvider.getMetaDataSigningCredential()); final Response response = inputMsg.getFirst(); response.getStatus().getStatusCode().setValue(StatusCode.RESPONDER); try { verifyEngine.validateAssertion(response, credentialProvider.getMetaDataSigningCredential(), spEntityId, "jUnit Test", false); org.junit.Assert.fail("Wrong StatusCode not detected"); } catch (final SamlAssertionValidationExeption e) { org.junit.Assert.assertEquals("Wrong errorcode", "internal.pvp.17", ((EaafException) e).getErrorId()); } } @Test public void verifyAssertionWrongIssueInstant() throws SamlSigningException, Pvp2MetadataException, CredentialsNotAvailableException, XMLParserException, UnmarshallingException, SamlAssertionValidationExeption { final String authnReqPath = "/data/Response_without_sig_classpath_entityid.xml"; final String metadataPath = getMetadataJunitJKeystore(); final String spEntityId = "https://demo.egiz.gv.at/demoportal_demologin/"; final Pair inputMsg = initializeResponse(spEntityId, metadataPath, authnReqPath, credentialProvider.getMetaDataSigningCredential()); final Response response = inputMsg.getFirst(); response.setIssueInstant(DateTime.now().plusMinutes(10)); try { verifyEngine.validateAssertion(response, credentialProvider.getMetaDataSigningCredential(), spEntityId, "jUnit Test", true); org.junit.Assert.fail("Wrong date not detected"); } catch (final SamlAssertionValidationExeption e) { org.junit.Assert.assertEquals("Wrong errorcode", "internal.pvp.14", ((EaafException) e).getErrorId()); } } @Test public void verifyAssertionNoContitions() throws SamlSigningException, Pvp2MetadataException, CredentialsNotAvailableException, XMLParserException, UnmarshallingException, SamlAssertionValidationExeption { final String authnReqPath = "/data/Response_without_sig_classpath_entityid.xml"; final String metadataPath = getMetadataJunitJKeystore(); final String spEntityId = "https://demo.egiz.gv.at/demoportal_demologin/"; final Pair inputMsg = initializeResponse(spEntityId, metadataPath, authnReqPath, credentialProvider.getMetaDataSigningCredential()); final Response response = inputMsg.getFirst(); response.getAssertions().get(0).setConditions(null); try { verifyEngine.validateAssertion(response, credentialProvider.getMetaDataSigningCredential(), spEntityId, "jUnit Test", true); org.junit.Assert.fail("Wrong date not detected"); } catch (final SamlAssertionValidationExeption e) { org.junit.Assert.assertEquals("Wrong errorcode", "internal.pvp.15", ((EaafException) e).getErrorId()); } } @Test public void verifyAssertionWrongContitions() throws SamlSigningException, Pvp2MetadataException, CredentialsNotAvailableException, XMLParserException, UnmarshallingException, SamlAssertionValidationExeption { final String authnReqPath = "/data/Response_without_sig_classpath_entityid.xml"; final String metadataPath = getMetadataJunitJKeystore(); final String spEntityId = "https://demo.egiz.gv.at/demoportal_demologin/"; final Pair inputMsg = initializeResponse(spEntityId, metadataPath, authnReqPath, credentialProvider.getMetaDataSigningCredential()); final Response response = inputMsg.getFirst(); try { verifyEngine.validateAssertion(response, credentialProvider.getMetaDataSigningCredential(), spEntityId, "jUnit Test", true); org.junit.Assert.fail("Wrong date not detected"); } catch (final SamlAssertionValidationExeption e) { org.junit.Assert.assertEquals("Wrong errorcode", "internal.pvp.15", ((EaafException) e).getErrorId()); } } @Test public void verifyAssertionWrongContitionsAudienceRestrictions() throws SamlSigningException, Pvp2MetadataException, CredentialsNotAvailableException, XMLParserException, UnmarshallingException, SamlAssertionValidationExeption { final String authnReqPath = "/data/Response_without_sig_classpath_entityid.xml"; final String metadataPath = getMetadataJunitJKeystore(); final String spEntityId = "https://demo.egiz.gv.at/demoportal_demologin/"; final Pair inputMsg = initializeResponse(spEntityId, metadataPath, authnReqPath, credentialProvider.getMetaDataSigningCredential()); final Response response = inputMsg.getFirst(); response.getAssertions().get(0).getConditions().setNotBefore(DateTime.now()); response.getAssertions().get(0).getConditions().setNotOnOrAfter(DateTime.now().plusMinutes(15)); response.getAssertions().get(0).getConditions().getAudienceRestrictions().clear(); try { verifyEngine.validateAssertion(response, credentialProvider.getMetaDataSigningCredential(), spEntityId, "jUnit Test", true); org.junit.Assert.fail("Wrong date not detected"); } catch (final SamlAssertionValidationExeption e) { org.junit.Assert.assertEquals("Wrong errorcode", "internal.pvp.15", ((EaafException) e).getErrorId()); } } @Test public void verifyAssertionWrongContitionsNotBefore() throws SamlSigningException, Pvp2MetadataException, CredentialsNotAvailableException, XMLParserException, UnmarshallingException, SamlAssertionValidationExeption { final String authnReqPath = "/data/Response_without_sig_classpath_entityid.xml"; final String metadataPath = getMetadataJunitJKeystore(); final String spEntityId = "https://demo.egiz.gv.at/demoportal_demologin/"; final Pair inputMsg = initializeResponse(spEntityId, metadataPath, authnReqPath, credentialProvider.getMetaDataSigningCredential()); final Response response = inputMsg.getFirst(); response.getAssertions().get(0).getConditions().setNotBefore(DateTime.now().plusMinutes(10)); response.getAssertions().get(0).getConditions().setNotOnOrAfter(DateTime.now().plusMinutes(15)); try { verifyEngine.validateAssertion(response, credentialProvider.getMetaDataSigningCredential(), spEntityId, "jUnit Test", true); org.junit.Assert.fail("Wrong date not detected"); } catch (final SamlAssertionValidationExeption e) { org.junit.Assert.assertEquals("Wrong errorcode", "internal.pvp.15", ((EaafException) e).getErrorId()); } } @Test public void verifyAssertionWrongContitionsNotOnOrAfter() throws SamlSigningException, Pvp2MetadataException, CredentialsNotAvailableException, XMLParserException, UnmarshallingException, SamlAssertionValidationExeption { final String authnReqPath = "/data/Response_without_sig_classpath_entityid.xml"; final String metadataPath = getMetadataJunitJKeystore(); final String spEntityId = "https://demo.egiz.gv.at/demoportal_demologin/"; final Pair inputMsg = initializeResponse(spEntityId, metadataPath, authnReqPath, credentialProvider.getMetaDataSigningCredential()); final Response response = inputMsg.getFirst(); response.getAssertions().get(0).getConditions().setNotBefore(DateTime.now()); response.getAssertions().get(0).getConditions().setNotOnOrAfter(DateTime.now().minusMinutes(5)); try { verifyEngine.validateAssertion(response, credentialProvider.getMetaDataSigningCredential(), spEntityId, "jUnit Test", true); org.junit.Assert.fail("Wrong date not detected"); } catch (final SamlAssertionValidationExeption e) { org.junit.Assert.assertEquals("Wrong errorcode", "internal.pvp.15", ((EaafException) e).getErrorId()); } } @Test public void verifyAssertionValidContitions() throws SamlSigningException, Pvp2MetadataException, CredentialsNotAvailableException, XMLParserException, UnmarshallingException, SamlAssertionValidationExeption { final String authnReqPath = "/data/Response_without_sig_classpath_entityid.xml"; final String metadataPath = getMetadataJunitJKeystore(); final String spEntityId = "https://demo.egiz.gv.at/demoportal_demologin/"; final Pair inputMsg = initializeResponse(spEntityId, metadataPath, authnReqPath, credentialProvider.getMetaDataSigningCredential()); final Response response = inputMsg.getFirst(); response.getAssertions().get(0).getConditions().setNotBefore(DateTime.now()); response.getAssertions().get(0).getConditions().setNotOnOrAfter(DateTime.now().plusMinutes(5)); verifyEngine.validateAssertion(response, credentialProvider.getMetaDataSigningCredential(), spEntityId, "jUnit Test", true); } @Test public void verifyEncAssertionWrongKey() throws SamlSigningException, Pvp2MetadataException, CredentialsNotAvailableException, XMLParserException, UnmarshallingException, SamlAssertionValidationExeption { final String authnReqPath = "/data/Asserion_enc_no_key.xml"; final String metadataPath = getMetadataJunitJKeystore(); final String spEntityId = "https://eid.a-sit.at/Shibboleth.sso/"; final Pair inputMsg = initializeResponse(spEntityId, metadataPath, authnReqPath, credentialProvider.getMetaDataSigningCredential()); try { verifyEngine.validateAssertion(inputMsg.getFirst(), credentialProvider.getMetaDataSigningCredential(), spEntityId, "jUnit Test", false); org.junit.Assert.fail("Wrong date not detected"); } catch (final SamlAssertionValidationExeption e) { org.junit.Assert.assertEquals("Wrong errorcode", "internal.pvp.16", ((EaafException) e).getErrorId()); } } @Test public void verifyEncAssertion() throws Exception { final String authnReqPath = "/data/Response_without_sig_classpath_entityid.xml"; final String metadataPath = getMetadataJunitJKeystore(); final String spEntityId = "https://demo.egiz.gv.at/demoportal_demologin/"; final Pair inputMsg = initializeResponse(spEntityId, metadataPath, authnReqPath, credentialProvider.getMetaDataSigningCredential()); final Response response = inputMsg.getFirst(); response.getAssertions().get(0).getConditions().setNotBefore(DateTime.now()); response.getAssertions().get(0).getConditions().setNotOnOrAfter(DateTime.now().plusMinutes(5)); final Element secAssertionElement = XMLObjectSupport.marshall(response.getAssertions().get(0)); secAssertionElement.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:xs", "http://www.w3.org/2001/XMLSchema"); final Assertion secAssertion = (Assertion) XMLObjectSupport.getUnmarshaller(secAssertionElement) .unmarshall(secAssertionElement); final EncryptedAssertion encAsserton = doEncryption(secAssertion, credentialProvider.getMetaDataSigningCredential(), authConfig); response.getEncryptedAssertions().add(encAsserton); verifyEngine.validateAssertion(response, credentialProvider.getMetaDataSigningCredential(), spEntityId, "jUnit Test", false); org.junit.Assert.assertEquals("Assertions not match", 2, response.getAssertions().size()); } @Test public void verifyEncAssertionWrongSchema() throws Exception { final String authnReqPath = "/data/Response_without_sig_classpath_entityid.xml"; final String metadataPath = getMetadataJunitJKeystore(); final String spEntityId = "https://demo.egiz.gv.at/demoportal_demologin/"; final Pair inputMsg = initializeResponse(spEntityId, metadataPath, authnReqPath, credentialProvider.getMetaDataSigningCredential()); final Response response = inputMsg.getFirst(); response.getAssertions().get(0).getConditions().setNotBefore(DateTime.now()); response.getAssertions().get(0).getConditions().setNotOnOrAfter(DateTime.now().plusMinutes(5)); final Element secAssertionElement = XMLObjectSupport.marshall(response.getAssertions().get(0)); final Assertion secAssertion = (Assertion) XMLObjectSupport.getUnmarshaller(secAssertionElement) .unmarshall(secAssertionElement); final EncryptedAssertion encAsserton = doEncryption(secAssertion, credentialProvider.getMetaDataSigningCredential(), authConfig); response.getEncryptedAssertions().add(encAsserton); try { verifyEngine.validateAssertion(response, credentialProvider.getMetaDataSigningCredential(), spEntityId, "jUnit Test", false); org.junit.Assert.fail("Wrong XML Schema not detected"); } catch (final SamlAssertionValidationExeption e) { org.junit.Assert.assertEquals("Wrong errorcode", "internal.pvp.15", ((EaafException) e).getErrorId()); } } }