Repository: cxf-fediz Updated Branches: refs/heads/master f15c92f65 -> 7c5463176
Added some negative unit tests based around signature validation failure Project: http://git-wip-us.apache.org/repos/asf/cxf-fediz/repo Commit: http://git-wip-us.apache.org/repos/asf/cxf-fediz/commit/7c546317 Tree: http://git-wip-us.apache.org/repos/asf/cxf-fediz/tree/7c546317 Diff: http://git-wip-us.apache.org/repos/asf/cxf-fediz/diff/7c546317 Branch: refs/heads/master Commit: 7c54631762db4a48fe342dc5f56f7ec5fac7ed73 Parents: f15c92f Author: Colm O hEigeartaigh <[email protected]> Authored: Tue Jul 29 17:01:41 2014 +0100 Committer: Colm O hEigeartaigh <[email protected]> Committed: Tue Jul 29 17:01:41 2014 +0100 ---------------------------------------------------------------------- .../core/federation/FederationResponseTest.java | 92 ++++++++++++ .../fediz/core/samlsso/SAMLResponseTest.java | 148 ++++++++++++++++++- plugins/core/src/test/resources/clientonly.jks | Bin 0 -> 1280 bytes .../src/test/resources/fediz_test_config.xml | 32 ++++ .../test/resources/fediz_test_config_saml.xml | 27 ++++ 5 files changed, 296 insertions(+), 3 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/7c546317/plugins/core/src/test/java/org/apache/cxf/fediz/core/federation/FederationResponseTest.java ---------------------------------------------------------------------- diff --git a/plugins/core/src/test/java/org/apache/cxf/fediz/core/federation/FederationResponseTest.java b/plugins/core/src/test/java/org/apache/cxf/fediz/core/federation/FederationResponseTest.java index 48063ce..a9b873b 100644 --- a/plugins/core/src/test/java/org/apache/cxf/fediz/core/federation/FederationResponseTest.java +++ b/plugins/core/src/test/java/org/apache/cxf/fediz/core/federation/FederationResponseTest.java @@ -79,6 +79,7 @@ import org.apache.wss4j.common.util.DOM2Writer; import org.apache.wss4j.dom.WSConstants; import org.apache.wss4j.dom.message.WSSecEncrypt; import org.joda.time.DateTime; +import org.joda.time.DateTimeZone; import org.junit.AfterClass; import org.junit.Assert; import org.junit.BeforeClass; @@ -1203,6 +1204,97 @@ public class FederationResponseTest { } + @org.junit.Test + public void testModifiedSignature() throws Exception { + SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler(); + callbackHandler.setStatement(SAML2CallbackHandler.Statement.ATTR); + callbackHandler.setConfirmationMethod(SAML2Constants.CONF_BEARER); + callbackHandler.setIssuer(TEST_RSTR_ISSUER); + callbackHandler.setSubjectName(TEST_USER); + ConditionsBean cp = new ConditionsBean(); + AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean(); + audienceRestriction.getAudienceURIs().add(TEST_AUDIENCE); + cp.setAudienceRestrictions(Collections.singletonList(audienceRestriction)); + callbackHandler.setConditions(cp); + + SAMLCallback samlCallback = new SAMLCallback(); + SAMLUtil.doSAMLCallback(callbackHandler, samlCallback); + SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback); + + WSPasswordCallback[] cb = { + new WSPasswordCallback("mystskey", WSPasswordCallback.SIGNATURE) + }; + cbPasswordHandler.handle(cb); + String password = cb[0].getPassword(); + + assertion.signAssertion("mystskey", password, crypto, false); + Document doc = STSUtil.toSOAPPart(STSUtil.SAMPLE_RSTR_COLL_MSG); + Element token = assertion.toDOM(doc); + + // Change IssueInstant attribute + String issueInstance = token.getAttributeNS(null, "IssueInstant"); + DateTime issueDateTime = new DateTime(issueInstance, DateTimeZone.UTC); + issueDateTime = issueDateTime.plusSeconds(1); + token.setAttributeNS(null, "IssueInstant", issueDateTime.toString()); + + Element e = FederationResponseTest.findElement(doc, "RequestedSecurityToken", + FederationConstants.WS_TRUST_13_NS); + if (e == null) { + e = FederationResponseTest.findElement(doc, "RequestedSecurityToken", + FederationConstants.WS_TRUST_2005_02_NS); + } + e.appendChild(token); + String rstr = DOM2Writer.nodeToString(doc); + + FedizRequest wfReq = new FedizRequest(); + wfReq.setAction(FederationConstants.ACTION_SIGNIN); + wfReq.setResponseToken(rstr); + + configurator = null; + FedizContext config = getFederationConfigurator().getFedizContext("ROOT"); + + FedizProcessor wfProc = new FederationProcessorImpl(); + try { + wfProc.processRequest(wfReq, config); + fail("Failure expected on signature validation"); + } catch (ProcessingException ex) { + // expected + } + } + + @org.junit.Test + public void testTrustFailure() throws Exception { + SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler(); + callbackHandler.setStatement(SAML2CallbackHandler.Statement.ATTR); + callbackHandler.setConfirmationMethod(SAML2Constants.CONF_BEARER); + callbackHandler.setIssuer(TEST_RSTR_ISSUER); + callbackHandler.setSubjectName(TEST_USER); + ConditionsBean cp = new ConditionsBean(); + AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean(); + audienceRestriction.getAudienceURIs().add(TEST_AUDIENCE); + cp.setAudienceRestrictions(Collections.singletonList(audienceRestriction)); + callbackHandler.setConditions(cp); + + SAMLCallback samlCallback = new SAMLCallback(); + SAMLUtil.doSAMLCallback(callbackHandler, samlCallback); + SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback); + String rstr = createSamlToken(assertion, "mystskey", true); + + FedizRequest wfReq = new FedizRequest(); + wfReq.setAction(FederationConstants.ACTION_SIGNIN); + wfReq.setResponseToken(rstr); + + configurator = null; + FedizContext config = getFederationConfigurator().getFedizContext("CLIENT_TRUST"); + + FedizProcessor wfProc = new FederationProcessorImpl(); + try { + wfProc.processRequest(wfReq, config); + fail("Failure expected on non-trusted signing cert"); + } catch (ProcessingException ex) { + // expected + } + } private String encryptAndSignToken( SamlAssertionWrapper assertion http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/7c546317/plugins/core/src/test/java/org/apache/cxf/fediz/core/samlsso/SAMLResponseTest.java ---------------------------------------------------------------------- diff --git a/plugins/core/src/test/java/org/apache/cxf/fediz/core/samlsso/SAMLResponseTest.java b/plugins/core/src/test/java/org/apache/cxf/fediz/core/samlsso/SAMLResponseTest.java index 7a1f474..a4b2772 100644 --- a/plugins/core/src/test/java/org/apache/cxf/fediz/core/samlsso/SAMLResponseTest.java +++ b/plugins/core/src/test/java/org/apache/cxf/fediz/core/samlsso/SAMLResponseTest.java @@ -37,7 +37,7 @@ import javax.xml.parsers.DocumentBuilderFactory; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; - +import org.w3c.dom.NodeList; import org.apache.cxf.fediz.common.STSUtil; import org.apache.cxf.fediz.common.SecurityTestUtil; import org.apache.cxf.fediz.core.AbstractSAMLCallbackHandler; @@ -72,9 +72,11 @@ import org.apache.wss4j.common.saml.bean.ConditionsBean; import org.apache.wss4j.common.saml.bean.SubjectConfirmationDataBean; import org.apache.wss4j.common.saml.builder.SAML2Constants; import org.apache.wss4j.common.util.DOM2Writer; +import org.apache.wss4j.dom.WSConstants; import org.apache.xml.security.utils.Base64; import org.easymock.EasyMock; import org.joda.time.DateTime; +import org.joda.time.DateTimeZone; import org.junit.AfterClass; import org.junit.Assert; import org.junit.BeforeClass; @@ -1139,6 +1141,148 @@ public class SAMLResponseTest { Assert.assertEquals("Audience wrong", TEST_REQUEST_URL, wfRes.getAudience()); } + @org.junit.Test + public void testModifiedSignature() throws Exception { + // Mock up a Request + FedizContext config = getFederationConfigurator().getFedizContext("ROOT"); + + String requestId = URLEncoder.encode(UUID.randomUUID().toString(), "UTF-8"); + + RequestState requestState = new RequestState(TEST_REQUEST_URL, + TEST_IDP_ISSUER, + requestId, + TEST_REQUEST_URL, + (String)config.getProtocol().getIssuer(), + null, + System.currentTimeMillis()); + + String relayState = URLEncoder.encode(UUID.randomUUID().toString(), "UTF-8"); + ((SAMLProtocol)config.getProtocol()).getStateManager().setRequestState(relayState, requestState); + + // Create SAML Response + SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler(); + callbackHandler.setAlsoAddAuthnStatement(true); + callbackHandler.setStatement(SAML2CallbackHandler.Statement.ATTR); + callbackHandler.setConfirmationMethod(SAML2Constants.CONF_BEARER); + callbackHandler.setIssuer(TEST_IDP_ISSUER); + callbackHandler.setSubjectName(TEST_USER); + + ConditionsBean cp = new ConditionsBean(); + AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean(); + audienceRestriction.getAudienceURIs().add(TEST_REQUEST_URL); + cp.setAudienceRestrictions(Collections.singletonList(audienceRestriction)); + callbackHandler.setConditions(cp); + + // Subject Confirmation Data + SubjectConfirmationDataBean subjectConfirmationData = new SubjectConfirmationDataBean(); + subjectConfirmationData.setAddress(TEST_CLIENT_ADDRESS); + subjectConfirmationData.setInResponseTo(requestId); + subjectConfirmationData.setNotAfter(new DateTime().plusMinutes(5)); + subjectConfirmationData.setRecipient(TEST_REQUEST_URL); + callbackHandler.setSubjectConfirmationData(subjectConfirmationData); + + SAMLCallback samlCallback = new SAMLCallback(); + SAMLUtil.doSAMLCallback(callbackHandler, samlCallback); + SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback); + + WSPasswordCallback[] cb = { + new WSPasswordCallback("mystskey", WSPasswordCallback.SIGNATURE) + }; + cbPasswordHandler.handle(cb); + String password = cb[0].getPassword(); + + assertion.signAssertion("mystskey", password, crypto, false); + + DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder(); + Document doc = docBuilder.newDocument(); + + Status status = + SAML2PResponseComponentBuilder.createStatus( + "urn:oasis:names:tc:SAML:2.0:status:Success", null + ); + Response response = + SAML2PResponseComponentBuilder.createSAMLResponse(requestId, + assertion.getIssuerString(), + status); + + response.getAssertions().add(assertion.getSaml2()); + + Element policyElement = OpenSAMLUtil.toDom(response, doc); + doc.appendChild(policyElement); + + NodeList assertionNodes = + policyElement.getElementsByTagNameNS(WSConstants.SAML2_NS, "Assertion"); + Assert.assertTrue(assertionNodes != null && assertionNodes.getLength() == 1); + + Element assertionElement = (Element)assertionNodes.item(0); + + // Change IssueInstant attribute + String issueInstance = assertionElement.getAttributeNS(null, "IssueInstant"); + DateTime issueDateTime = new DateTime(issueInstance, DateTimeZone.UTC); + issueDateTime = issueDateTime.plusSeconds(1); + assertionElement.setAttributeNS(null, "IssueInstant", issueDateTime.toString()); + + String responseStr = encodeResponse(policyElement); + + HttpServletRequest req = EasyMock.createMock(HttpServletRequest.class); + EasyMock.expect(req.getRequestURL()).andReturn(new StringBuffer(TEST_REQUEST_URL)); + EasyMock.expect(req.getRemoteAddr()).andReturn(TEST_CLIENT_ADDRESS); + EasyMock.replay(req); + + FedizRequest wfReq = new FedizRequest(); + wfReq.setResponseToken(responseStr); + wfReq.setState(relayState); + wfReq.setRequest(req); + + FedizProcessor wfProc = new SAMLProcessorImpl(); + try { + wfProc.processRequest(wfReq, config); + fail("Failure expected on modified Signature"); + } catch (ProcessingException ex) { + // expected + } + } + + @org.junit.Test + public void testTrustFailure() throws Exception { + // Mock up a Request + FedizContext config = getFederationConfigurator().getFedizContext("CLIENT_TRUST"); + + String requestId = URLEncoder.encode(UUID.randomUUID().toString(), "UTF-8"); + + RequestState requestState = new RequestState(TEST_REQUEST_URL, + TEST_IDP_ISSUER, + requestId, + TEST_REQUEST_URL, + (String)config.getProtocol().getIssuer(), + null, + System.currentTimeMillis()); + + String relayState = URLEncoder.encode(UUID.randomUUID().toString(), "UTF-8"); + ((SAMLProtocol)config.getProtocol()).getStateManager().setRequestState(relayState, requestState); + + // Create SAML Response + String responseStr = createSamlResponseStr(requestId); + + HttpServletRequest req = EasyMock.createMock(HttpServletRequest.class); + EasyMock.expect(req.getRequestURL()).andReturn(new StringBuffer(TEST_REQUEST_URL)); + EasyMock.expect(req.getRemoteAddr()).andReturn(TEST_CLIENT_ADDRESS); + EasyMock.replay(req); + + FedizRequest wfReq = new FedizRequest(); + wfReq.setResponseToken(responseStr); + wfReq.setState(relayState); + wfReq.setRequest(req); + + FedizProcessor wfProc = new SAMLProcessorImpl(); + try { + wfProc.processRequest(wfReq, config); + fail("Failure expected on non-trusted signing cert"); + } catch (ProcessingException ex) { + // expected + } + } + private String createSamlResponseStr(String requestId) throws Exception { // Create SAML Assertion SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler(); @@ -1207,8 +1351,6 @@ public class SAMLResponseTest { return policyElement; } - - /** * Returns the first element that matches <code>name</code> and http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/7c546317/plugins/core/src/test/resources/clientonly.jks ---------------------------------------------------------------------- diff --git a/plugins/core/src/test/resources/clientonly.jks b/plugins/core/src/test/resources/clientonly.jks new file mode 100644 index 0000000..c216934 Binary files /dev/null and b/plugins/core/src/test/resources/clientonly.jks differ http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/7c546317/plugins/core/src/test/resources/fediz_test_config.xml ---------------------------------------------------------------------- diff --git a/plugins/core/src/test/resources/fediz_test_config.xml b/plugins/core/src/test/resources/fediz_test_config.xml index ab53717..920a723 100644 --- a/plugins/core/src/test/resources/fediz_test_config.xml +++ b/plugins/core/src/test/resources/fediz_test_config.xml @@ -233,4 +233,36 @@ </claimTypesRequested> </protocol> </contextConfig> + + <contextConfig name="CLIENT_TRUST"> + <audienceUris> + <audienceItem>http://host_one:port/url</audienceItem> + </audienceUris> + <certificateStores> + <trustManager> + <keyStore file="clientonly.jks" password="cspass" + type="JKS" /> + </trustManager> + </certificateStores> + <trustedIssuers> + <issuer certificateValidation="PeerTrust" /> + </trustedIssuers> + + <maximumClockSkew>1000</maximumClockSkew> + <protocol xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:type="federationProtocolType" version="1.2"> + <realm>target realm</realm> + <issuer>http://url_to_the_issuer</issuer> + <roleDelimiter>;</roleDelimiter> + <roleURI>http://schemas.xmlsoap.org/ws/2005/05/identity/claims/role</roleURI> + <authenticationType value="some auth type" type="String" /> + <freshness>10000</freshness> + <reply>reply value</reply> + <request>REQUEST</request> + <claimTypesRequested> + <claimType type="a particular claim type" optional="true" /> + </claimTypesRequested> + </protocol> + </contextConfig> + </FedizConfig> http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/7c546317/plugins/core/src/test/resources/fediz_test_config_saml.xml ---------------------------------------------------------------------- diff --git a/plugins/core/src/test/resources/fediz_test_config_saml.xml b/plugins/core/src/test/resources/fediz_test_config_saml.xml index cf6228e..125bccd 100644 --- a/plugins/core/src/test/resources/fediz_test_config_saml.xml +++ b/plugins/core/src/test/resources/fediz_test_config_saml.xml @@ -193,4 +193,31 @@ </claimTypesRequested> </protocol> </contextConfig> + + <contextConfig name="CLIENT_TRUST"> + <audienceUris> + <audienceItem>http://host_one:port/url</audienceItem> + </audienceUris> + <certificateStores> + <trustManager> + <keyStore file="clientonly.jks" password="storepass" + type="JKS" /> + </trustManager> + </certificateStores> + <trustedIssuers> + <issuer certificateValidation="PeerTrust" /> + </trustedIssuers> + + <maximumClockSkew>1000</maximumClockSkew> + <protocol xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:type="samlProtocolType" version="1.2"> + <issuer>http://url_to_the_issuer</issuer> + <roleDelimiter>;</roleDelimiter> + <roleURI>http://schemas.xmlsoap.org/ws/2005/05/identity/claims/role</roleURI> + <claimTypesRequested> + <claimType type="a particular claim type" optional="true" /> + </claimTypesRequested> + </protocol> + </contextConfig> + </FedizConfig>
