1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements. See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership. The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License. You may obtain a copy of the License at
9    *
10   * http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied. See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  
20  package org.apache.ws.security.saml;
21  
22  import java.util.List;
23  
24  import org.apache.ws.security.WSConstants;
25  import org.apache.ws.security.WSSConfig;
26  import org.apache.ws.security.WSSecurityEngine;
27  import org.apache.ws.security.WSSecurityEngineResult;
28  import org.apache.ws.security.WSSecurityException;
29  import org.apache.ws.security.common.CustomSamlAssertionValidator;
30  import org.apache.ws.security.common.SAML1CallbackHandler;
31  import org.apache.ws.security.common.SAML2CallbackHandler;
32  import org.apache.ws.security.common.SOAPUtil;
33  import org.apache.ws.security.message.WSSecHeader;
34  import org.apache.ws.security.message.WSSecSAMLToken;
35  import org.apache.ws.security.saml.ext.AssertionWrapper;
36  import org.apache.ws.security.saml.ext.SAMLParms;
37  import org.apache.ws.security.saml.ext.bean.ConditionsBean;
38  import org.apache.ws.security.util.WSSecurityUtil;
39  import org.joda.time.DateTime;
40  import org.w3c.dom.Document;
41  
42  /**
43   * Test-case for sending and processing an a SAML Token with a custom Conditions element.
44   */
45  public class SamlConditionsTest extends org.junit.Assert {
46      private static final org.apache.commons.logging.Log LOG = 
47          org.apache.commons.logging.LogFactory.getLog(SamlConditionsTest.class);
48      private WSSecurityEngine secEngine = new WSSecurityEngine();
49  
50      public SamlConditionsTest() {
51          WSSConfig config = WSSConfig.getNewInstance();
52          config.setValidator(WSSecurityEngine.SAML_TOKEN, new CustomSamlAssertionValidator());
53          config.setValidator(WSSecurityEngine.SAML2_TOKEN, new CustomSamlAssertionValidator());
54          secEngine.setWssConfig(config);
55      }
56      
57      /**
58       * Test that creates, sends and processes an unsigned SAML 1.1 authentication assertion
59       * with a custom Conditions statement.
60       */
61      @org.junit.Test
62      public void testSAML1Conditions() throws Exception {
63          SAML1CallbackHandler callbackHandler = new SAML1CallbackHandler();
64          callbackHandler.setStatement(SAML1CallbackHandler.Statement.AUTHN);
65          callbackHandler.setIssuer("www.example.com");
66          
67          ConditionsBean conditions = new ConditionsBean();
68          DateTime notBefore = new DateTime();
69          conditions.setNotBefore(notBefore);
70          conditions.setNotAfter(notBefore.plusMinutes(20));
71          callbackHandler.setConditions(conditions);
72          
73          SAMLParms samlParms = new SAMLParms();
74          samlParms.setCallbackHandler(callbackHandler);
75          AssertionWrapper assertion = new AssertionWrapper(samlParms);
76  
77          WSSecSAMLToken wsSign = new WSSecSAMLToken();
78  
79          Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
80          WSSecHeader secHeader = new WSSecHeader();
81          secHeader.insertSecurityHeader(doc);
82          
83          Document unsignedDoc = wsSign.build(doc, assertion, secHeader);
84  
85          if (LOG.isDebugEnabled()) {
86              LOG.debug("SAML 1.1 Authn Assertion (sender vouches):");
87              String outputString = 
88                  org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(unsignedDoc);
89              LOG.debug(outputString);
90          }
91          
92          List<WSSecurityEngineResult> results = verify(unsignedDoc);
93          WSSecurityEngineResult actionResult =
94              WSSecurityUtil.fetchActionResult(results, WSConstants.ST_UNSIGNED);
95          AssertionWrapper receivedAssertion = 
96              (AssertionWrapper) actionResult.get(WSSecurityEngineResult.TAG_SAML_ASSERTION);
97          assertTrue(receivedAssertion != null);
98          assertTrue(!receivedAssertion.isSigned());
99          assertTrue(receivedAssertion.getSignatureValue() == null);
100     }
101     
102     /**
103      * Test that creates, sends and processes an unsigned SAML 2 authentication assertion
104      * with an (invalid) custom Conditions statement.
105      */
106     @org.junit.Test
107     public void testSAML2InvalidAfterConditions() throws Exception {
108         SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
109         callbackHandler.setStatement(SAML2CallbackHandler.Statement.AUTHN);
110         callbackHandler.setIssuer("www.example.com");
111         
112         ConditionsBean conditions = new ConditionsBean();
113         DateTime notBefore = new DateTime();
114         conditions.setNotBefore(notBefore.minusMinutes(5));
115         conditions.setNotAfter(notBefore.minusMinutes(3));
116         callbackHandler.setConditions(conditions);
117         
118         SAMLParms samlParms = new SAMLParms();
119         samlParms.setCallbackHandler(callbackHandler);
120         AssertionWrapper assertion = new AssertionWrapper(samlParms);
121 
122         WSSecSAMLToken wsSign = new WSSecSAMLToken();
123 
124         Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
125         WSSecHeader secHeader = new WSSecHeader();
126         secHeader.insertSecurityHeader(doc);
127         
128         Document unsignedDoc = wsSign.build(doc, assertion, secHeader);
129 
130         if (LOG.isDebugEnabled()) {
131             LOG.debug("SAML 2 Authn Assertion (sender vouches):");
132             String outputString = 
133                 org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(unsignedDoc);
134             LOG.debug(outputString);
135         }
136         
137         try {
138             verify(unsignedDoc);
139             fail("Failure expected in processing the SAML Conditions element");
140         } catch (WSSecurityException ex) {
141             assertTrue(ex.getMessage().contains("SAML token security failure"));
142         }
143     }
144     
145     /**
146      * Test that creates, sends and processes an unsigned SAML 2 authentication assertion
147      * with an (invalid) custom Conditions statement.
148      */
149     @org.junit.Test
150     public void testSAML2InvalidBeforeConditions() throws Exception {
151         SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
152         callbackHandler.setStatement(SAML2CallbackHandler.Statement.AUTHN);
153         callbackHandler.setIssuer("www.example.com");
154         
155         ConditionsBean conditions = new ConditionsBean();
156         DateTime notBefore = new DateTime();
157         conditions.setNotBefore(notBefore.plusMinutes(2));
158         conditions.setNotAfter(notBefore.plusMinutes(5));
159         callbackHandler.setConditions(conditions);
160         
161         SAMLParms samlParms = new SAMLParms();
162         samlParms.setCallbackHandler(callbackHandler);
163         AssertionWrapper assertion = new AssertionWrapper(samlParms);
164 
165         WSSecSAMLToken wsSign = new WSSecSAMLToken();
166 
167         Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
168         WSSecHeader secHeader = new WSSecHeader();
169         secHeader.insertSecurityHeader(doc);
170         
171         Document unsignedDoc = wsSign.build(doc, assertion, secHeader);
172 
173         if (LOG.isDebugEnabled()) {
174             LOG.debug("SAML 2 Authn Assertion (sender vouches):");
175             String outputString = 
176                 org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(unsignedDoc);
177             LOG.debug(outputString);
178         }
179         
180         try {
181             verify(unsignedDoc);
182             fail("Failure expected in processing the SAML Conditions element");
183         } catch (WSSecurityException ex) {
184             assertTrue(ex.getMessage().contains("SAML token security failure"));
185         }
186     }
187     
188     /**
189      * Test that creates, sends and processes an unsigned SAML 2 authentication assertion
190      * with a Conditions statement that has a NotBefore "in the future".
191      */
192     @org.junit.Test
193     public void testSAML2FutureTTLConditions() throws Exception {
194         SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
195         callbackHandler.setStatement(SAML2CallbackHandler.Statement.AUTHN);
196         callbackHandler.setIssuer("www.example.com");
197         
198         ConditionsBean conditions = new ConditionsBean();
199         DateTime notBefore = new DateTime();
200         conditions.setNotBefore(notBefore.plusSeconds(30));
201         conditions.setNotAfter(notBefore.plusMinutes(5));
202         callbackHandler.setConditions(conditions);
203         
204         SAMLParms samlParms = new SAMLParms();
205         samlParms.setCallbackHandler(callbackHandler);
206         AssertionWrapper assertion = new AssertionWrapper(samlParms);
207 
208         WSSecSAMLToken wsSign = new WSSecSAMLToken();
209 
210         Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
211         WSSecHeader secHeader = new WSSecHeader();
212         secHeader.insertSecurityHeader(doc);
213         
214         Document unsignedDoc = wsSign.build(doc, assertion, secHeader);
215 
216         if (LOG.isDebugEnabled()) {
217             LOG.debug("SAML 2 Authn Assertion (sender vouches):");
218             String outputString = 
219                 org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(unsignedDoc);
220             LOG.debug(outputString);
221         }
222         
223         verify(unsignedDoc);
224     }
225     
226     /**
227      * Verifies the soap envelope
228      * <p/>
229      * 
230      * @param envelope 
231      * @throws Exception Thrown when there is a problem in verification
232      */
233     private List<WSSecurityEngineResult> verify(Document doc) throws Exception {
234         List<WSSecurityEngineResult> results = 
235             secEngine.processSecurityHeader(doc, null, null, null);
236         String outputString = 
237             org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(doc);
238         assertTrue(outputString.indexOf("counter_port_type") > 0 ? true : false);
239         return results;
240     }
241     
242 }