View Javadoc
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.wss4j.dom.message;
21  
22  import java.util.Collections;
23  
24  import org.apache.wss4j.common.util.SOAPUtil;
25  import org.apache.wss4j.dom.WSConstants;
26  import org.apache.wss4j.dom.common.CustomHandler;
27  
28  import org.apache.wss4j.dom.common.UsernamePasswordCallbackHandler;
29  import org.apache.wss4j.dom.engine.WSSecurityEngine;
30  import org.apache.wss4j.common.ext.WSSecurityException;
31  import org.apache.wss4j.common.util.XMLUtils;
32  import org.apache.wss4j.dom.handler.HandlerAction;
33  import org.apache.wss4j.dom.handler.RequestData;
34  import org.apache.wss4j.dom.handler.WSHandlerConstants;
35  
36  import org.junit.jupiter.api.Test;
37  import org.w3c.dom.Document;
38  
39  import javax.security.auth.callback.CallbackHandler;
40  
41  import static org.junit.jupiter.api.Assertions.assertTrue;
42  import static org.junit.jupiter.api.Assertions.fail;
43  
44  /**
45   * This is a test for processing a Username Token to enforce either a plaintext or digest
46   * password type. See WSS-255.
47   */
48  public class PasswordTypeTest {
49      private static final org.slf4j.Logger LOG =
50          org.slf4j.LoggerFactory.getLogger(PasswordTypeTest.class);
51      private CallbackHandler callbackHandler = new UsernamePasswordCallbackHandler();
52  
53      /**
54       * Test that adds a UserNameToken with password Digest to a WS-Security envelope
55       */
56      @Test
57      public void testPasswordDigest() throws Exception {
58          Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
59          WSSecHeader secHeader = new WSSecHeader(doc);
60          secHeader.insertSecurityHeader();
61  
62          WSSecUsernameToken builder = new WSSecUsernameToken(secHeader);
63          builder.setUserInfo("wernerd", "verySecret");
64          Document signedDoc = builder.build();
65  
66          if (LOG.isDebugEnabled()) {
67              LOG.debug("Message with UserNameToken PW Digest:");
68              String outputString =
69                  XMLUtils.prettyDocumentToString(signedDoc);
70              LOG.debug(outputString);
71          }
72          WSSecurityEngine secEngine = new WSSecurityEngine();
73  
74          //
75          // It should pass with PASSWORD_DIGEST
76          //
77          RequestData requestData = new RequestData();
78          requestData.setCallbackHandler(callbackHandler);
79          requestData.setRequiredPasswordType(WSConstants.PASSWORD_DIGEST);
80          secEngine.processSecurityHeader(doc, requestData);
81  
82          //
83          // It should pass with null
84          //
85          requestData = new RequestData();
86          requestData.setCallbackHandler(callbackHandler);
87          requestData.setRequiredPasswordType(null);
88          secEngine.processSecurityHeader(doc, requestData);
89  
90          //
91          // It should fail with PASSWORD_TEXT
92          //
93          try {
94              requestData = new RequestData();
95              requestData.setCallbackHandler(callbackHandler);
96              requestData.setRequiredPasswordType(WSConstants.PASSWORD_TEXT);
97              secEngine.processSecurityHeader(doc, requestData);
98              fail("Expected failure on the wrong password type");
99          } catch (WSSecurityException ex) {
100             assertTrue(ex.getErrorCode() == WSSecurityException.ErrorCode.FAILED_AUTHENTICATION);
101             // expected
102         }
103     }
104 
105     /**
106      * Test that adds a UserNameToken with password text to a WS-Security envelope
107      */
108     @Test
109     public void testUsernameTokenText() throws Exception {
110         Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
111         WSSecHeader secHeader = new WSSecHeader(doc);
112         secHeader.insertSecurityHeader();
113 
114         WSSecUsernameToken builder = new WSSecUsernameToken(secHeader);
115         builder.setPasswordType(WSConstants.PASSWORD_TEXT);
116         builder.setUserInfo("wernerd", "verySecret");
117         Document signedDoc = builder.build();
118 
119         if (LOG.isDebugEnabled()) {
120             LOG.debug("Message with UserNameToken PW Text:");
121             String outputString =
122                 XMLUtils.prettyDocumentToString(signedDoc);
123             LOG.debug(outputString);
124         }
125         WSSecurityEngine secEngine = new WSSecurityEngine();
126 
127         //
128         // It should pass with PASSWORD_TEXT
129         //
130         RequestData requestData = new RequestData();
131         requestData.setCallbackHandler(callbackHandler);
132         requestData.setRequiredPasswordType(WSConstants.PASSWORD_TEXT);
133         secEngine.processSecurityHeader(doc, requestData);
134 
135         //
136         // It should pass with null
137         //
138         requestData = new RequestData();
139         requestData.setCallbackHandler(callbackHandler);
140         requestData.setRequiredPasswordType(null);
141         secEngine.processSecurityHeader(doc, requestData);
142 
143         //
144         // It should fail with PASSWORD_DIGEST
145         //
146         try {
147             requestData = new RequestData();
148             requestData.setCallbackHandler(callbackHandler);
149             requestData.setRequiredPasswordType(WSConstants.PASSWORD_DIGEST);
150             secEngine.processSecurityHeader(doc, requestData);
151             fail("Expected failure on the wrong password type");
152         } catch (WSSecurityException ex) {
153             assertTrue(ex.getErrorCode() == WSSecurityException.ErrorCode.FAILED_AUTHENTICATION);
154             // expected
155         }
156 
157     }
158 
159     /**
160      * Test that adds a UserNameToken via WSHandler
161      */
162     @Test
163     public void testUsernameTokenWSHandler() throws Exception {
164         CustomHandler handler = new CustomHandler();
165         Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
166 
167         RequestData reqData = new RequestData();
168         java.util.Map<String, Object> config = new java.util.TreeMap<>();
169         config.put("password", "verySecret");
170         config.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_TEXT);
171         reqData.setUsername("wernerd");
172         reqData.setMsgContext(config);
173 
174         HandlerAction action = new HandlerAction(WSConstants.UT);
175         handler.send(
176             doc,
177             reqData,
178             Collections.singletonList(action),
179             true
180         );
181 
182         if (LOG.isDebugEnabled()) {
183             LOG.debug("Username Token via WSHandler");
184             String outputString =
185                 XMLUtils.prettyDocumentToString(doc);
186             LOG.debug(outputString);
187         }
188 
189         //
190         // It should fail on a different password type
191         //
192         config.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_DIGEST);
193         reqData.setMsgContext(config);
194         handler.receive(Collections.singletonList(WSConstants.UT), reqData);
195         WSSecurityEngine secEngine = new WSSecurityEngine();
196         reqData.setCallbackHandler(callbackHandler);
197 
198         try {
199             secEngine.processSecurityHeader(doc, reqData);
200             fail("Expected failure on the wrong password type");
201         } catch (WSSecurityException ex) {
202             assertTrue(ex.getErrorCode() == WSSecurityException.ErrorCode.FAILED_AUTHENTICATION);
203         }
204     }
205 
206 }