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.HashMap;
23  import java.util.List;
24  import java.util.Map;
25  
26  import javax.xml.namespace.QName;
27  
28  import org.apache.ws.security.WSSecurityException;
29  import org.apache.ws.security.WSConstants;
30  import org.apache.ws.security.WSSConfig;
31  import org.apache.ws.security.WSSecurityEngine;
32  import org.apache.ws.security.WSSecurityEngineResult;
33  import org.apache.ws.security.common.SAML1CallbackHandler;
34  import org.apache.ws.security.common.SOAPUtil;
35  import org.apache.ws.security.components.crypto.AlgorithmSuite;
36  import org.apache.ws.security.components.crypto.Crypto;
37  import org.apache.ws.security.components.crypto.CryptoFactory;
38  import org.apache.ws.security.handler.RequestData;
39  import org.apache.ws.security.message.WSSecHeader;
40  import org.apache.ws.security.message.WSSecSAMLToken;
41  import org.apache.ws.security.saml.ext.AssertionWrapper;
42  import org.apache.ws.security.saml.ext.SAMLParms;
43  import org.apache.ws.security.saml.ext.builder.SAML1Constants;
44  import org.apache.ws.security.util.WSSecurityUtil;
45  import org.apache.ws.security.util.XMLUtils;
46  import org.w3c.dom.Document;
47  import org.w3c.dom.Element;
48  
49  /**
50   * A set of test-cases for signing and verifying SOAP requests containing a signed
51   * SAML (HOK) assertion when specifying an AlgorithmSuite policy.
52   */
53  public class SamlAlgorithmSuiteTest extends org.junit.Assert {
54      private static final org.apache.commons.logging.Log LOG = 
55          org.apache.commons.logging.LogFactory.getLog(SamlAlgorithmSuiteTest.class);
56      private Crypto crypto = null;
57      
58      public SamlAlgorithmSuiteTest() throws Exception {
59          WSSConfig.init();
60          crypto = CryptoFactory.getInstance("crypto.properties");
61      }
62  
63      @org.junit.Test
64      public void testSignedSAML11Assertion() throws Exception {
65          SAML1CallbackHandler callbackHandler = new SAML1CallbackHandler();
66          callbackHandler.setStatement(SAML1CallbackHandler.Statement.AUTHN);
67          callbackHandler.setConfirmationMethod(SAML1Constants.CONF_HOLDER_KEY);
68          callbackHandler.setIssuer("www.example.com");
69          
70          SAMLParms samlParms = new SAMLParms();
71          samlParms.setCallbackHandler(callbackHandler);
72          AssertionWrapper assertion = new AssertionWrapper(samlParms);
73          
74          assertion.signAssertion("16c73ab6-b892-458f-abf5-2f875f74882e", "security", crypto, false);
75  
76          WSSecSAMLToken wsSign = new WSSecSAMLToken();
77  
78          Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
79          WSSecHeader secHeader = new WSSecHeader();
80          secHeader.insertSecurityHeader(doc);
81          
82          Document signedDoc = wsSign.build(doc, assertion, secHeader);
83  
84          if (LOG.isDebugEnabled()) {
85              String outputString = 
86                  XMLUtils.PrettyDocumentToString(signedDoc);
87              LOG.debug(outputString);
88          }
89          
90          Element securityHeader = WSSecurityUtil.getSecurityHeader(signedDoc, null);
91          AlgorithmSuite algorithmSuite = createAlgorithmSuite();
92          
93          verify(securityHeader, algorithmSuite, crypto, false);
94          
95          algorithmSuite.setMinimumAsymmetricKeyLength(1024);
96          
97          try {
98              verify(securityHeader, algorithmSuite, crypto, false);
99              fail("Expected failure as 512-bit keys are not allowed");
100         } catch (WSSecurityException ex) {
101             // expected
102         }
103     }
104     
105     @org.junit.Test
106     public void testDSASignedSAML11Assertion() throws Exception {
107         Crypto dsaCrypto = CryptoFactory.getInstance("wss40.properties");
108         
109         SAML1CallbackHandler callbackHandler = new SAML1CallbackHandler();
110         callbackHandler.setStatement(SAML1CallbackHandler.Statement.AUTHN);
111         callbackHandler.setConfirmationMethod(SAML1Constants.CONF_HOLDER_KEY);
112         callbackHandler.setIssuer("www.example.com");
113         
114         SAMLParms samlParms = new SAMLParms();
115         samlParms.setCallbackHandler(callbackHandler);
116         AssertionWrapper assertion = new AssertionWrapper(samlParms);
117         
118         assertion.signAssertion("wss40DSA", "security", dsaCrypto, false);
119 
120         WSSecSAMLToken wsSign = new WSSecSAMLToken();
121 
122         Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
123         WSSecHeader secHeader = new WSSecHeader();
124         secHeader.insertSecurityHeader(doc);
125         
126         Document signedDoc = wsSign.build(doc, assertion, secHeader);
127 
128         if (LOG.isDebugEnabled()) {
129             String outputString = 
130                 XMLUtils.PrettyDocumentToString(signedDoc);
131             LOG.debug(outputString);
132         }
133         
134         Element securityHeader = WSSecurityUtil.getSecurityHeader(signedDoc, null);
135         AlgorithmSuite algorithmSuite = createAlgorithmSuite();
136         
137         try {
138             verify(securityHeader, algorithmSuite, dsaCrypto, false);
139             fail("Expected failure as DSA is not allowed");
140         } catch (WSSecurityException ex) {
141             // expected
142         }
143         
144         algorithmSuite.addSignatureMethod(WSConstants.DSA);
145         verify(securityHeader, algorithmSuite, dsaCrypto, false);
146     }
147     
148     @org.junit.Test
149     public void testC14nMethod() throws Exception {
150         SAML1CallbackHandler callbackHandler = new SAML1CallbackHandler();
151         callbackHandler.setStatement(SAML1CallbackHandler.Statement.AUTHN);
152         callbackHandler.setConfirmationMethod(SAML1Constants.CONF_HOLDER_KEY);
153         callbackHandler.setIssuer("www.example.com");
154         
155         SAMLParms samlParms = new SAMLParms();
156         samlParms.setCallbackHandler(callbackHandler);
157         AssertionWrapper assertion = new AssertionWrapper(samlParms);
158         
159         assertion.signAssertion(
160             "16c73ab6-b892-458f-abf5-2f875f74882e", "security", crypto, false,
161             WSConstants.C14N_EXCL_WITH_COMMENTS, WSConstants.RSA_SHA1);
162 
163         WSSecSAMLToken wsSign = new WSSecSAMLToken();
164 
165         Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
166         WSSecHeader secHeader = new WSSecHeader();
167         secHeader.insertSecurityHeader(doc);
168         
169         Document signedDoc = wsSign.build(doc, assertion, secHeader);
170 
171         if (LOG.isDebugEnabled()) {
172             String outputString = 
173                 XMLUtils.PrettyDocumentToString(signedDoc);
174             LOG.debug(outputString);
175         }
176         
177         Element securityHeader = WSSecurityUtil.getSecurityHeader(signedDoc, null);
178         AlgorithmSuite algorithmSuite = createAlgorithmSuite();
179         
180         try {
181             verify(securityHeader, algorithmSuite, crypto, false);
182             fail("Expected failure as C14n algorithm is not allowed");
183         } catch (WSSecurityException ex) {
184             // expected
185         }
186         
187         algorithmSuite.addC14nAlgorithm(WSConstants.C14N_EXCL_WITH_COMMENTS);
188         verify(securityHeader, algorithmSuite, crypto, false);
189     }
190 
191     private AlgorithmSuite createAlgorithmSuite() {
192         AlgorithmSuite algorithmSuite = new AlgorithmSuite();
193         algorithmSuite.addSignatureMethod(WSConstants.RSA_SHA1);
194         algorithmSuite.setMinimumAsymmetricKeyLength(512);
195         algorithmSuite.addC14nAlgorithm(WSConstants.C14N_EXCL_OMIT_COMMENTS);
196         algorithmSuite.addDigestAlgorithm(WSConstants.SHA1);
197         
198         return algorithmSuite;
199     }
200 
201     private List<WSSecurityEngineResult> verify(
202         Element securityHeader, AlgorithmSuite algorithmSuite, Crypto sigVerCrypto,
203         boolean saml2
204     ) throws Exception {
205         WSSecurityEngine secEngine = new WSSecurityEngine();
206         RequestData data = new RequestData();
207         data.setSigCrypto(sigVerCrypto);
208         data.setSamlAlgorithmSuite(algorithmSuite);
209         
210         return secEngine.processSecurityHeader(securityHeader, data);
211     }
212 
213 
214 }