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.message;
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.common.CustomHandler;
26  import org.apache.ws.security.common.SOAPUtil;
27  import org.apache.ws.security.common.UsernamePasswordCallbackHandler;
28  import org.apache.ws.security.handler.RequestData;
29  import org.apache.ws.security.handler.WSHandlerConstants;
30  
31  import org.w3c.dom.Document;
32  
33  import javax.security.auth.callback.CallbackHandler;
34  
35  
36  /**
37   * This a test for deriving a key from a Username Token using a non-standard (WSE) implementation.
38   * 
39   * @author Werner Dittmann (Wern.erDittmann@siemens.com)
40   */
41  public class UTWseSignatureTest extends org.junit.Assert {
42      private static final org.apache.commons.logging.Log LOG = 
43          org.apache.commons.logging.LogFactory.getLog(UTWseSignatureTest.class);
44      private WSSecurityEngine secEngine = new WSSecurityEngine();
45      private CallbackHandler callbackHandler = new UsernamePasswordCallbackHandler();
46  
47      /**
48       * Test the specific signing method that use UsernameToken values
49       * <p/>
50       * 
51       * @throws java.lang.Exception Thrown when there is any problem in signing or verification
52       */
53      @org.junit.Test
54      public void testUsernameTokenSigning() throws Exception {
55          Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
56  
57          WSSecHeader secHeader = new WSSecHeader();
58          secHeader.insertSecurityHeader(doc);
59  
60          WSSecUsernameToken builder = new WSSecUsernameToken();
61          builder.setPasswordType(WSConstants.PASSWORD_TEXT);
62          builder.setUserInfo("wernerd", "verySecret");
63          builder.addCreated();
64          builder.addNonce();
65          builder.prepare(doc);
66          
67          WSSecSignature sign = new WSSecSignature();
68          sign.setCustomTokenValueType(WSConstants.USERNAMETOKEN_NS + "#UsernameToken");
69          sign.setCustomTokenId(builder.getId());
70          sign.setSecretKey(builder.getSecretKey());
71          sign.setKeyIdentifierType(WSConstants.CUSTOM_SYMM_SIGNING);
72          sign.setSignatureAlgorithm(WSConstants.HMAC_SHA1);
73          
74          LOG.info("Before signing with UT text....");
75          sign.build(doc, null, secHeader);
76          LOG.info("Before adding UsernameToken PW Text....");
77          builder.prependToHeader(secHeader);
78          Document signedDoc = doc;
79          if (LOG.isDebugEnabled()) {
80              LOG.debug("Message with UserNameToken PW Text:");
81              String outputString = 
82                  org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(signedDoc);
83              LOG.debug(outputString);
84          }
85          LOG.info("After adding UsernameToken PW Text....");
86          verify(signedDoc);
87      }
88      
89      /**
90       * Test the specific signing method that use UsernameToken values
91       * Test that uses a 32 byte key length for the secret key, instead of the default 16 bytes.
92       */
93      @org.junit.Test
94      public void testWSS226() throws Exception {
95          Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
96  
97          WSSecHeader secHeader = new WSSecHeader();
98          secHeader.insertSecurityHeader(doc);
99  
100         WSSecUsernameToken builder = new WSSecUsernameToken();
101         builder.setPasswordType(WSConstants.PASSWORD_TEXT);
102         builder.setUserInfo("wernerd", "verySecret");
103         builder.addCreated();
104         builder.setSecretKeyLength(32);
105         builder.addNonce();
106         builder.prepare(doc);
107         
108         WSSecSignature sign = new WSSecSignature();
109         sign.setCustomTokenValueType(WSConstants.USERNAMETOKEN_NS + "#UsernameToken");
110         sign.setCustomTokenId(builder.getId());
111         sign.setSecretKey(builder.getSecretKey());
112         sign.setKeyIdentifierType(WSConstants.CUSTOM_SYMM_SIGNING);
113         sign.setSignatureAlgorithm(WSConstants.HMAC_SHA1);
114         
115         LOG.info("Before signing with UT text....");
116         sign.build(doc, null, secHeader);
117         LOG.info("Before adding UsernameToken PW Text....");
118         builder.prependToHeader(secHeader);
119         Document signedDoc = doc;
120         if (LOG.isDebugEnabled()) {
121             LOG.debug("Message using a 32 byte key length:");
122             String outputString = 
123                 org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(signedDoc);
124             LOG.debug(outputString);
125         }
126         
127         //
128         // It should fail on the default key length of 16...
129         //
130         try {
131             secEngine.processSecurityHeader(doc, null, callbackHandler, null);
132             fail("An error was expected on verifying the signature");
133         } catch (Exception ex) {
134             // expected
135         }
136         
137         WSSecurityEngine wss226SecurityEngine = new WSSecurityEngine();
138         WSSConfig wssConfig = WSSConfig.getNewInstance();
139         wssConfig.setSecretKeyLength(32);
140         wss226SecurityEngine.setWssConfig(wssConfig);
141         wss226SecurityEngine.processSecurityHeader(doc, null, callbackHandler, null);
142     }
143     
144     /**
145      * Test that uses a 32 byte key length for the secret key, instead of the default 16 bytes.
146      * This test configures the key length via WSHandler.
147      */
148     @org.junit.Test
149     public void testWSS226Handler() throws Exception {
150         CustomHandler handler = new CustomHandler();
151         Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
152         
153         RequestData reqData = new RequestData();
154         reqData.setWssConfig(WSSConfig.getNewInstance());
155         java.util.Map<String, Object> config = new java.util.TreeMap<String, Object>();
156         config.put("password", "verySecret");
157         config.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_TEXT);
158         config.put(WSHandlerConstants.WSE_SECRET_KEY_LENGTH, "32");
159         config.put(WSHandlerConstants.USE_DERIVED_KEY, "false");
160         reqData.setUsername("wernerd");
161         reqData.setMsgContext(config);
162         
163         java.util.List<Integer> actions = new java.util.ArrayList<Integer>();
164         actions.add(Integer.valueOf(WSConstants.UT_SIGN));
165         
166         handler.send(WSConstants.UT_SIGN, doc, reqData, actions, true);
167         
168         if (LOG.isDebugEnabled()) {
169             LOG.debug("Username Token Signature via WSHandler");
170             String outputString = 
171                 org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(doc);
172             LOG.debug(outputString);
173         }
174         
175         //
176         // It should fail on the default key length of 16...
177         //
178         try {
179             secEngine.processSecurityHeader(doc, null, callbackHandler, null);
180             fail("An error was expected on verifying the signature");
181         } catch (Exception ex) {
182             // expected
183         }
184         
185         handler.receive(WSConstants.UT_SIGN, reqData);
186         
187         WSSecurityEngine wss226SecurityEngine = new WSSecurityEngine();
188         wss226SecurityEngine.setWssConfig(reqData.getWssConfig());
189         wss226SecurityEngine.processSecurityHeader(doc, null, callbackHandler, null);
190     }
191     
192     /**
193      * Test the specific signing method that use UsernameToken values
194      * <p/>
195      * 
196      * @throws java.lang.Exception Thrown when there is any problem in signing or verification
197      */
198     @org.junit.Test
199     public void testUsernameTokenSigningDigest() throws Exception {
200         Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
201 
202         WSSecHeader secHeader = new WSSecHeader();
203         secHeader.insertSecurityHeader(doc);
204 
205         WSSecUsernameToken builder = new WSSecUsernameToken();
206         builder.setPasswordType(WSConstants.PASSWORD_DIGEST);
207         builder.setUserInfo("wernerd", "verySecret");
208         builder.addCreated();
209         builder.addNonce();
210         builder.prepare(doc);
211         
212         WSSecSignature sign = new WSSecSignature();
213         sign.setCustomTokenValueType(WSConstants.USERNAMETOKEN_NS + "#UsernameToken");
214         sign.setCustomTokenId(builder.getId());
215         sign.setSecretKey(builder.getSecretKey());
216         sign.setKeyIdentifierType(WSConstants.CUSTOM_SYMM_SIGNING);
217         sign.setSignatureAlgorithm(WSConstants.HMAC_SHA1);
218         
219         LOG.info("Before signing with UT digest....");
220         sign.build(doc, null, secHeader);
221         LOG.info("Before adding UsernameToken PW Digest....");
222         builder.prependToHeader(secHeader);
223         Document signedDoc = doc;
224         if (LOG.isDebugEnabled()) {
225             LOG.debug("Message with UserNameToken PW Digest:");
226             String outputString = 
227                 org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(signedDoc);
228             LOG.debug(outputString);
229         }
230         LOG.info("After adding UsernameToken PW Digest....");
231         verify(signedDoc);
232     }
233 
234     /**
235      * Verifies the soap envelope
236      * <p/>
237      * 
238      * @param env soap envelope
239      * @throws java.lang.Exception Thrown when there is a problem in verification
240      */
241     private void verify(Document doc) throws Exception {
242         LOG.info("Before verifying UsernameToken....");
243         secEngine.processSecurityHeader(doc, null, callbackHandler, null);
244         LOG.info("After verifying UsernameToken....");
245     }
246 
247 }