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.components.crypto;
21  
22  import org.apache.ws.security.WSSConfig;
23  import org.apache.ws.security.WSSecurityEngine;
24  import org.apache.ws.security.WSConstants;
25  import org.apache.ws.security.WSSecurityEngineResult;
26  import org.apache.ws.security.WSSecurityException;
27  import org.apache.ws.security.common.KeystoreCallbackHandler;
28  import org.apache.ws.security.common.SOAPUtil;
29  import org.apache.ws.security.message.WSSecHeader;
30  import org.apache.ws.security.message.WSSecSignature;
31  import org.apache.ws.security.util.WSSecurityUtil;
32  import org.w3c.dom.Document;
33  
34  import java.security.cert.X509Certificate;
35  import java.util.List;
36  
37  import javax.security.auth.callback.CallbackHandler;
38  
39  /**
40   * This is a test for the CertificateStore Crypto instance. This class does not know anything
41   * about Java KeyStores, but just wraps a list of trusted certificates.
42   */
43  public class CertificateStoreTest extends org.junit.Assert {
44      private static final org.apache.commons.logging.Log LOG = 
45          org.apache.commons.logging.LogFactory.getLog(CertificateStoreTest.class);
46      private WSSecurityEngine secEngine = new WSSecurityEngine();
47      private Crypto senderCrypto = CryptoFactory.getInstance("wss40.properties");
48      private Crypto receiverCrypto = null;
49      private CallbackHandler keystoreCallbackHandler = new KeystoreCallbackHandler();
50      
51      public CertificateStoreTest() throws Exception {
52          CryptoType cryptoType = new CryptoType(CryptoType.TYPE.ALIAS);
53          cryptoType.setAlias("wss40");
54          X509Certificate[] certs = senderCrypto.getX509Certificates(cryptoType);
55          receiverCrypto = new CertificateStore(certs);
56          WSSConfig.init();
57      }
58  
59      /**
60       * Test signing a SOAP message using a BST.
61       */
62      @org.junit.Test
63      public void testSignatureDirectReference() throws Exception {
64          WSSecSignature sign = new WSSecSignature();
65          sign.setUserInfo("wss40", "security");
66          sign.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE);
67  
68          Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
69  
70          WSSecHeader secHeader = new WSSecHeader();
71          secHeader.insertSecurityHeader(doc);
72          Document signedDoc = sign.build(doc, senderCrypto, secHeader);
73          
74          if (LOG.isDebugEnabled()) {
75              String outputString = 
76                  org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(signedDoc);
77              LOG.debug(outputString);
78          }
79          //
80          // Verify the signature
81          //
82          List<WSSecurityEngineResult> results = verify(signedDoc, receiverCrypto);
83          WSSecurityEngineResult result = 
84              WSSecurityUtil.fetchActionResult(results, WSConstants.SIGN);
85          X509Certificate cert = 
86              (X509Certificate)result.get(WSSecurityEngineResult.TAG_X509_CERTIFICATE);
87          assertTrue (cert != null);
88      }
89      
90      /**
91       * Test signing a SOAP message using an X.509 Key Identifier.
92       */
93      @org.junit.Test
94      public void testSignatureX509() throws Exception {
95          WSSecSignature sign = new WSSecSignature();
96          sign.setUserInfo("wss40", "security");
97          sign.setKeyIdentifierType(WSConstants.X509_KEY_IDENTIFIER);
98  
99          Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
100 
101         WSSecHeader secHeader = new WSSecHeader();
102         secHeader.insertSecurityHeader(doc);
103         Document signedDoc = sign.build(doc, senderCrypto, secHeader);
104         
105         if (LOG.isDebugEnabled()) {
106             String outputString = 
107                 org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(signedDoc);
108             LOG.debug(outputString);
109         }
110         //
111         // Verify the signature
112         //
113         // Turn off BSP spec compliance
114         WSSecurityEngine newEngine = new WSSecurityEngine();
115         WSSConfig config = WSSConfig.getNewInstance();
116         config.setWsiBSPCompliant(false);
117         newEngine.setWssConfig(config);
118         List<WSSecurityEngineResult> results = 
119             newEngine.processSecurityHeader(signedDoc, null, keystoreCallbackHandler, receiverCrypto);
120         WSSecurityEngineResult result = 
121             WSSecurityUtil.fetchActionResult(results, WSConstants.SIGN);
122         X509Certificate cert = 
123             (X509Certificate)result.get(WSSecurityEngineResult.TAG_X509_CERTIFICATE);
124         assertTrue (cert != null);
125     }
126     
127     /**
128      * Test signing a SOAP message using Issuer Serial.
129      */
130     @org.junit.Test
131     public void testSignatureIssuerSerial() throws Exception {
132         WSSecSignature sign = new WSSecSignature();
133         sign.setUserInfo("wss40", "security");
134         sign.setKeyIdentifierType(WSConstants.ISSUER_SERIAL);
135 
136         Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
137 
138         WSSecHeader secHeader = new WSSecHeader();
139         secHeader.insertSecurityHeader(doc);
140         Document signedDoc = sign.build(doc, senderCrypto, secHeader);
141         
142         if (LOG.isDebugEnabled()) {
143             String outputString = 
144                 org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(signedDoc);
145             LOG.debug(outputString);
146         }
147         
148         //
149         // Verify the signature
150         //
151         List<WSSecurityEngineResult> results = verify(signedDoc, receiverCrypto);
152         WSSecurityEngineResult result = 
153             WSSecurityUtil.fetchActionResult(results, WSConstants.SIGN);
154         X509Certificate cert = 
155             (X509Certificate)result.get(WSSecurityEngineResult.TAG_X509_CERTIFICATE);
156         assertTrue (cert != null);
157     }
158     
159     /**
160      * Test signing a SOAP message using a Thumbprint
161      */
162     @org.junit.Test
163     public void testSignatureThumbprint() throws Exception {
164         WSSecSignature sign = new WSSecSignature();
165         sign.setUserInfo("wss40", "security");
166         sign.setKeyIdentifierType(WSConstants.THUMBPRINT_IDENTIFIER);
167 
168         Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
169 
170         WSSecHeader secHeader = new WSSecHeader();
171         secHeader.insertSecurityHeader(doc);
172         Document signedDoc = sign.build(doc, senderCrypto, secHeader);
173         
174         if (LOG.isDebugEnabled()) {
175             String outputString = 
176                 org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(signedDoc);
177             LOG.debug(outputString);
178         }
179         
180         //
181         // Verify the signature
182         //
183         List<WSSecurityEngineResult> results = verify(signedDoc, receiverCrypto);
184         WSSecurityEngineResult result = 
185             WSSecurityUtil.fetchActionResult(results, WSConstants.SIGN);
186         X509Certificate cert = 
187             (X509Certificate)result.get(WSSecurityEngineResult.TAG_X509_CERTIFICATE);
188         assertTrue (cert != null);
189     }
190     
191     /**
192      * Test signing a SOAP message using a SKI Key Identifier
193      */
194     @org.junit.Test
195     public void testSignatureSKI() throws Exception {
196         WSSecSignature sign = new WSSecSignature();
197         sign.setUserInfo("wss40", "security");
198         sign.setKeyIdentifierType(WSConstants.SKI_KEY_IDENTIFIER);
199 
200         Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
201 
202         WSSecHeader secHeader = new WSSecHeader();
203         secHeader.insertSecurityHeader(doc);
204         Document signedDoc = sign.build(doc, senderCrypto, secHeader);
205         
206         if (LOG.isDebugEnabled()) {
207             String outputString = 
208                 org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(signedDoc);
209             LOG.debug(outputString);
210         }
211         
212         //
213         // Verify the signature
214         //
215         List<WSSecurityEngineResult> results = verify(signedDoc, receiverCrypto);
216         WSSecurityEngineResult result = 
217             WSSecurityUtil.fetchActionResult(results, WSConstants.SIGN);
218         X509Certificate cert = 
219             (X509Certificate)result.get(WSSecurityEngineResult.TAG_X509_CERTIFICATE);
220         assertTrue (cert != null);
221     }
222     
223     /**
224      * Test signing a SOAP message using a BST. The certificate is not known to the
225      * CertificateStore and so should throw an exception.
226      */
227     @org.junit.Test
228     public void testSignatureDirectReferenceUntrusted() throws Exception {
229         WSSecSignature sign = new WSSecSignature();
230         sign.setUserInfo("16c73ab6-b892-458f-abf5-2f875f74882e", "security");
231         sign.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE);
232 
233         Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
234 
235         WSSecHeader secHeader = new WSSecHeader();
236         secHeader.insertSecurityHeader(doc);
237         Document signedDoc = sign.build(doc, CryptoFactory.getInstance(), secHeader);
238         
239         if (LOG.isDebugEnabled()) {
240             String outputString = 
241                 org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(signedDoc);
242             LOG.debug(outputString);
243         }
244         //
245         // Verify the signature
246         //
247         try {
248             verify(signedDoc, receiverCrypto);
249             fail("Failure expected on an unknown certificate");
250         } catch (WSSecurityException ex) {
251             // expected
252         }
253     }
254     
255     /**
256      * Verifies the soap envelope
257      * <p/>
258      * 
259      * @param doc 
260      * @throws Exception Thrown when there is a problem in verification
261      */
262     private List<WSSecurityEngineResult> 
263     verify(Document doc, Crypto crypto) throws WSSecurityException {
264         List<WSSecurityEngineResult> results = secEngine.processSecurityHeader(
265             doc, null, keystoreCallbackHandler, crypto
266         );
267         if (LOG.isDebugEnabled()) {
268             LOG.debug("Verfied and decrypted message:");
269             String outputString = 
270                 org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(doc);
271             LOG.debug(outputString);
272         }
273         return results;
274     }
275 
276     
277 }