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.token;
21  
22  import java.util.ArrayList;
23  import java.util.Collections;
24  import java.util.List;
25  
26  import javax.security.auth.callback.CallbackHandler;
27  
28  import org.apache.wss4j.common.bsp.BSPRule;
29  import org.apache.wss4j.common.ext.WSSecurityException;
30  import org.apache.wss4j.common.util.SOAPUtil;
31  import org.apache.wss4j.common.util.XMLUtils;
32  
33  import org.apache.wss4j.dom.common.UsernamePasswordCallbackHandler;
34  import org.apache.wss4j.dom.engine.WSSConfig;
35  import org.apache.wss4j.dom.engine.WSSecurityEngine;
36  import org.apache.wss4j.dom.handler.RequestData;
37  import org.apache.wss4j.dom.handler.WSHandlerResult;
38  
39  import org.junit.jupiter.api.Test;
40  import org.w3c.dom.Document;
41  
42  import static org.junit.jupiter.api.Assertions.assertTrue;
43  import static org.junit.jupiter.api.Assertions.fail;
44  
45  
46  /**
47   * A test-case for WSS-199 - "Add support for WCF non-standard Username Tokens"
48   * (see also WSS-148 - "WCF interop issue: Namespace not honored incase of attributes.").
49   * The issue is that WCF generated Username Tokens where the password type is namespace
50   * qualified (incorrectly). WSS-199 added the ability to process these Username Tokens.
51   */
52  public class WCFUsernameTokenTest {
53      private static final org.slf4j.Logger LOG =
54          org.slf4j.LoggerFactory.getLogger(WCFUsernameTokenTest.class);
55      private static final String SOAPUTMSG =
56          "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
57          + "<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" "
58          + "xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" "
59          + "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">"
60          + "<SOAP-ENV:Header>"
61          + "<wsse:Security SOAP-ENV:mustUnderstand=\"1\" "
62          + "xmlns:wsse=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd\">"
63          + "<wsse:UsernameToken wsu:Id=\"UsernameToken-29477163\" xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\">"
64          + "<wsse:Username>wernerd</wsse:Username>"
65          + "<wsse:Password "
66          + "wsse:Type=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText\">verySecret</wsse:Password>"
67          + "</wsse:UsernameToken></wsse:Security></SOAP-ENV:Header>"
68          + "<SOAP-ENV:Body>"
69          + "<add xmlns=\"http://ws.apache.org/counter/counter_port_type\">"
70          + "<value xmlns=\"\">15</value>" + "</add>"
71          + "</SOAP-ENV:Body>\r\n       \r\n" + "</SOAP-ENV:Envelope>";
72  
73      private CallbackHandler callbackHandler = new UsernamePasswordCallbackHandler();
74  
75      /**
76       * Test that adds a UserNameToken with a namespace qualified type. This should fail
77       * as WSS4J rejects these tokens by default.
78       */
79      @Test
80      public void testNamespaceQualifiedTypeRejected() throws Exception {
81          Document doc = SOAPUtil.toSOAPPart(SOAPUTMSG);
82  
83          if (LOG.isDebugEnabled()) {
84              LOG.debug("Message with UserNameToken PW Digest:");
85              String outputString =
86                  XMLUtils.prettyDocumentToString(doc);
87              LOG.debug(outputString);
88          }
89          try {
90              verify(doc);
91              fail("Failure expected on a bad password type");
92          } catch (WSSecurityException ex) {
93              assertTrue(ex.getErrorCode() == WSSecurityException.ErrorCode.INVALID_SECURITY);
94          }
95      }
96  
97  
98      /**
99       * Test that adds a UserNameToken with a namespace qualified type. This should pass
100      * as WSS4J has been configured to accept these tokens.
101      */
102     @Test
103     public void testNamespaceQualifiedTypeAccepted() throws Exception {
104         Document doc = SOAPUtil.toSOAPPart(SOAPUTMSG);
105 
106         if (LOG.isDebugEnabled()) {
107             LOG.debug("Message with UserNameToken PW Digest:");
108             String outputString =
109                 XMLUtils.prettyDocumentToString(doc);
110             LOG.debug(outputString);
111         }
112 
113         RequestData requestData = new RequestData();
114         requestData.setAllowNamespaceQualifiedPasswordTypes(true);
115         requestData.setWssConfig(WSSConfig.getNewInstance());
116         requestData.setIgnoredBSPRules(Collections.singletonList(BSPRule.R4201));
117         verify(doc, requestData);
118     }
119 
120 
121     /**
122      * Verifies the soap envelope
123      */
124     private WSHandlerResult verify(Document doc) throws Exception {
125         return verify(doc, new ArrayList<>(0));
126     }
127 
128     /**
129      * Verifies the soap envelope
130      */
131     private WSHandlerResult verify(
132         Document doc, List<BSPRule> ignoredRules
133     ) throws Exception {
134         WSSecurityEngine secEngine = new WSSecurityEngine();
135         RequestData requestData = new RequestData();
136         requestData.setIgnoredBSPRules(ignoredRules);
137         requestData.setCallbackHandler(callbackHandler);
138         return secEngine.processSecurityHeader(doc, requestData);
139     }
140 
141     /**
142      * Verifies the soap envelope
143      */
144     private WSHandlerResult verify(
145         Document doc, RequestData requestData
146     ) throws Exception {
147         WSSecurityEngine secEngine = new WSSecurityEngine();
148         requestData.setCallbackHandler(callbackHandler);
149         return secEngine.processSecurityHeader(doc, requestData);
150     }
151 
152 
153 }