1   /*
2    * Copyright 2005-2010 the original author or authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.springframework.ws.soap.security.xwss;
18  
19  import javax.security.auth.callback.Callback;
20  import javax.security.auth.callback.CallbackHandler;
21  import javax.xml.soap.SOAPMessage;
22  
23  import org.springframework.core.io.ClassPathResource;
24  import org.springframework.ws.soap.saaj.SaajSoapMessage;
25  import org.springframework.ws.soap.security.callback.AbstractCallbackHandler;
26  
27  import com.sun.xml.wss.impl.callback.PasswordCallback;
28  import com.sun.xml.wss.impl.callback.PasswordValidationCallback;
29  import com.sun.xml.wss.impl.callback.TimestampValidationCallback;
30  import com.sun.xml.wss.impl.callback.UsernameCallback;
31  import org.junit.Test;
32  
33  import static org.junit.Assert.*;
34  
35  public class XwssMessageInterceptorUsernameTokenTest extends AbstractXwssMessageInterceptorTestCase {
36  
37  
38      @Test
39     public void testAddUsernameTokenDigest() throws Exception {
40          interceptor.setPolicyConfiguration(new ClassPathResource("usernameToken-digest-config.xml", getClass()));
41          CallbackHandler handler = new AbstractCallbackHandler() {
42  
43              @Override
44              protected void handleInternal(Callback callback) {
45                  if (callback instanceof UsernameCallback) {
46                      ((UsernameCallback) callback).setUsername("Bert");
47                  }
48                  else if (callback instanceof PasswordCallback) {
49                      PasswordCallback passwordCallback = (PasswordCallback) callback;
50                      passwordCallback.setPassword("Ernie");
51                  }
52                  else {
53                      fail("Unexpected callback");
54                  }
55              }
56          };
57          interceptor.setCallbackHandler(handler);
58          interceptor.afterPropertiesSet();
59          SaajSoapMessage message = loadSaajMessage("empty-soap.xml");
60          interceptor.secureMessage(message, null);
61          SOAPMessage result = message.getSaajMessage();
62          assertNotNull("No result returned", result);
63          assertXpathEvaluatesTo("Invalid Username", "Bert",
64  		        "/SOAP-ENV:Envelope/SOAP-ENV:Header/wsse:Security/wsse:UsernameToken/wsse:Username/text()",
65  		        result);
66          assertXpathExists("Password does not exist",
67  		        "/SOAP-ENV:Envelope/SOAP-ENV:Header/wsse:Security/wsse:UsernameToken/wsse:Password[@Type='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest']",
68  		        result);
69          assertXpathExists("Nonce does not exist",
70  		        "/SOAP-ENV:Envelope/SOAP-ENV:Header/wsse:Security/wsse:UsernameToken/wsse:Nonce",
71  		        result);
72          assertXpathExists("Created does not exist",
73                  "/SOAP-ENV:Envelope/SOAP-ENV:Header/wsse:Security/wsse:UsernameToken/wsu:Created",
74                  result);
75      }
76  
77      @Test
78      public void testAddUsernameTokenPlainText() throws Exception {
79          interceptor.setPolicyConfiguration(new ClassPathResource("usernameToken-plainText-config.xml", getClass()));
80          CallbackHandler handler = new AbstractCallbackHandler() {
81  
82              @Override
83              protected void handleInternal(Callback callback) {
84                  if (callback instanceof UsernameCallback) {
85                      ((UsernameCallback) callback).setUsername("Bert");
86                  }
87                  else if (callback instanceof PasswordCallback) {
88                      PasswordCallback passwordCallback = (PasswordCallback) callback;
89                      passwordCallback.setPassword("Ernie");
90                  }
91                  else {
92                      fail("Unexpected callback");
93                  }
94              }
95          };
96          interceptor.setCallbackHandler(handler);
97          interceptor.afterPropertiesSet();
98          SaajSoapMessage message = loadSaajMessage("empty-soap.xml");
99          interceptor.secureMessage(message, null);
100         SOAPMessage result = message.getSaajMessage();
101         assertNotNull("No result returned", result);
102         assertXpathEvaluatesTo("Invalid Username", "Bert",
103                 "/SOAP-ENV:Envelope/SOAP-ENV:Header/wsse:Security/wsse:UsernameToken/wsse:Username/text()", result);
104         assertXpathEvaluatesTo("Invalid Password", "Ernie",
105                 "/SOAP-ENV:Envelope/SOAP-ENV:Header/wsse:Security/wsse:UsernameToken/wsse:Password[@Type='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText']/text()",
106                 result);
107     }
108 
109     @Test
110     public void testAddUsernameTokenPlainTextNonce() throws Exception {
111 	    interceptor.setPolicyConfiguration(
112 			    new ClassPathResource("usernameToken-plainText-nonce-config.xml",
113 					    getClass()));
114 	    CallbackHandler handler = new AbstractCallbackHandler() {
115 
116 		    @Override
117 		    protected void handleInternal(Callback callback) {
118 			    if (callback instanceof UsernameCallback) {
119 				    ((UsernameCallback) callback).setUsername("Bert");
120 			    }
121 			    else if (callback instanceof PasswordCallback) {
122 				    PasswordCallback passwordCallback = (PasswordCallback) callback;
123 				    passwordCallback.setPassword("Ernie");
124 			    }
125 			    else {
126 				    fail("Unexpected callback");
127 			    }
128 		    }
129 	    };
130 	    interceptor.setCallbackHandler(handler);
131 	    interceptor.afterPropertiesSet();
132 	    SaajSoapMessage message = loadSaajMessage("empty-soap.xml");
133 	    interceptor.secureMessage(message, null);
134 	    SOAPMessage result = message.getSaajMessage();
135 	    assertNotNull("No result returned", result);
136 	    assertXpathEvaluatesTo("Invalid Username", "Bert",
137 			    "/SOAP-ENV:Envelope/SOAP-ENV:Header/wsse:Security/wsse:UsernameToken/wsse:Username/text()",
138 			    result);
139 	    assertXpathEvaluatesTo("Invalid Password", "Ernie",
140 			    "/SOAP-ENV:Envelope/SOAP-ENV:Header/wsse:Security/wsse:UsernameToken/wsse:Password[@Type='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText']/text()",
141 			    result);
142 	    assertXpathExists("Nonce does not exist",
143 			    "/SOAP-ENV:Envelope/SOAP-ENV:Header/wsse:Security/wsse:UsernameToken/wsse:Nonce",
144 			    result);
145 	    assertXpathExists("Created does not exist",
146 			    "/SOAP-ENV:Envelope/SOAP-ENV:Header/wsse:Security/wsse:UsernameToken/wsu:Created",
147 			    result);
148     }
149 
150 	@Test
151     public void testValidateUsernameTokenPlainText() throws Exception {
152         interceptor
153                 .setPolicyConfiguration(new ClassPathResource("requireUsernameToken-plainText-config.xml", getClass()));
154         CallbackHandler handler = new AbstractCallbackHandler() {
155 
156             @Override
157             protected void handleInternal(Callback callback) {
158                 if (callback instanceof PasswordValidationCallback) {
159                     PasswordValidationCallback validationCallback = (PasswordValidationCallback) callback;
160                     validationCallback.setValidator(new PasswordValidationCallback.PasswordValidator() {
161                         public boolean validate(PasswordValidationCallback.Request request) {
162                             if (request instanceof PasswordValidationCallback.PlainTextPasswordRequest) {
163                                 PasswordValidationCallback.PlainTextPasswordRequest passwordRequest =
164                                         (PasswordValidationCallback.PlainTextPasswordRequest) request;
165                                 assertEquals("Invalid username", "Bert", passwordRequest.getUsername());
166                                 assertEquals("Invalid password", "Ernie", passwordRequest.getPassword());
167                                 return true;
168                             }
169                             else {
170                                 fail("Unexpected request");
171                                 return false;
172                             }
173                         }
174                     });
175                 }
176                 else {
177                     fail("Unexpected callback");
178                 }
179             }
180         };
181         interceptor.setCallbackHandler(handler);
182         interceptor.afterPropertiesSet();
183         SaajSoapMessage message = loadSaajMessage("usernameTokenPlainText-soap.xml");
184         interceptor.validateMessage(message, null);
185         SOAPMessage result = message.getSaajMessage();
186         assertNotNull("No result returned", result);
187         assertXpathNotExists("Security Header not removed", "/SOAP-ENV:Envelope/SOAP-ENV:Header/wsse:Security", result);
188     }
189 
190     @Test
191     public void testValidateUsernameTokenPlainTextNonce() throws Exception {
192         interceptor
193                 .setPolicyConfiguration(new ClassPathResource("requireUsernameToken-plainText-nonce-config.xml", getClass()));
194         CallbackHandler handler = new AbstractCallbackHandler() {
195 
196             @Override
197             protected void handleInternal(Callback callback) {
198                 if (callback instanceof PasswordValidationCallback) {
199                     PasswordValidationCallback validationCallback = (PasswordValidationCallback) callback;
200                     validationCallback.setValidator(new PasswordValidationCallback.PasswordValidator() {
201                         public boolean validate(PasswordValidationCallback.Request request) {
202                             if (request instanceof PasswordValidationCallback.PlainTextPasswordRequest) {
203                                 PasswordValidationCallback.PlainTextPasswordRequest passwordRequest =
204                                         (PasswordValidationCallback.PlainTextPasswordRequest) request;
205                                 assertEquals("Invalid username", "Bert", passwordRequest.getUsername());
206                                 assertEquals("Invalid password", "Ernie", passwordRequest.getPassword());
207                                 return true;
208                             }
209                             else {
210                                 fail("Unexpected request");
211                                 return false;
212                             }
213                         }
214                     });
215                 }
216                 else if (callback instanceof TimestampValidationCallback) {
217                     TimestampValidationCallback validationCallback = (TimestampValidationCallback) callback;
218                     validationCallback.setValidator(new TimestampValidationCallback.TimestampValidator() {
219                         public void validate(TimestampValidationCallback.Request request) {
220                         }
221                     });
222                 }
223                 else {
224                     fail("Unexpected callback");
225                 }
226             }
227         };
228         interceptor.setCallbackHandler(handler);
229         interceptor.afterPropertiesSet();
230         SaajSoapMessage message = loadSaajMessage("usernameTokenPlainText-nonce-soap.xml");
231         interceptor.validateMessage(message, null);
232         SOAPMessage result = message.getSaajMessage();
233         assertNotNull("No result returned", result);
234         assertXpathNotExists("Security Header not removed", "/SOAP-ENV:Envelope/SOAP-ENV:Header/wsse:Security", result);
235     }
236 
237     @Test
238     public void testValidateUsernameTokenDigest() throws Exception {
239         interceptor.setPolicyConfiguration(new ClassPathResource("requireUsernameToken-digest-config.xml", getClass()));
240         CallbackHandler handler = new AbstractCallbackHandler() {
241 
242             @Override
243             protected void handleInternal(Callback callback) {
244                 if (callback instanceof PasswordValidationCallback) {
245                     PasswordValidationCallback validationCallback = (PasswordValidationCallback) callback;
246                     if (validationCallback.getRequest() instanceof PasswordValidationCallback.DigestPasswordRequest) {
247                         PasswordValidationCallback.DigestPasswordRequest passwordRequest =
248                                 (PasswordValidationCallback.DigestPasswordRequest) validationCallback.getRequest();
249                         assertEquals("Invalid username", "Bert", passwordRequest.getUsername());
250                         passwordRequest.setPassword("Ernie");
251                         validationCallback.setValidator(new PasswordValidationCallback.DigestPasswordValidator());
252                     }
253                     else {
254                         fail("Unexpected request");
255                     }
256                 }
257                 else if (callback instanceof TimestampValidationCallback) {
258                     TimestampValidationCallback validationCallback = (TimestampValidationCallback) callback;
259                     validationCallback.setValidator(new TimestampValidationCallback.TimestampValidator() {
260                         public void validate(TimestampValidationCallback.Request request) {
261                         }
262                     });
263                 }
264                 else {
265                     fail("Unexpected callback");
266                 }
267             }
268         };
269         interceptor.setCallbackHandler(handler);
270         interceptor.afterPropertiesSet();
271         SaajSoapMessage message = loadSaajMessage("usernameTokenDigest-soap.xml");
272         interceptor.validateMessage(message, null);
273         SOAPMessage result = message.getSaajMessage();
274         assertNotNull("No result returned", result);
275         assertXpathNotExists("Security Header not removed", "/SOAP-ENV:Envelope/SOAP-ENV:Header/wsse:Security", result);
276     }
277 
278 }