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.ws.security.processor;
21  
22  import org.apache.ws.security.SAMLTokenPrincipal;
23  import org.apache.ws.security.WSConstants;
24  import org.apache.ws.security.WSDocInfo;
25  import org.apache.ws.security.WSSConfig;
26  import org.apache.ws.security.WSSecurityEngine;
27  import org.apache.ws.security.WSSecurityEngineResult;
28  import org.apache.ws.security.WSSecurityException;
29  import org.apache.ws.security.WSUsernameTokenPrincipal;
30  import org.apache.ws.security.cache.ReplayCache;
31  import org.apache.ws.security.handler.RequestData;
32  import org.apache.ws.security.message.token.UsernameToken;
33  import org.apache.ws.security.validate.Credential;
34  import org.apache.ws.security.validate.Validator;
35  import org.w3c.dom.Element;
36  
37  import java.util.List;
38  
39  public class UsernameTokenProcessor implements Processor {
40      private static org.apache.commons.logging.Log log = 
41          org.apache.commons.logging.LogFactory.getLog(UsernameTokenProcessor.class);
42      
43      public List<WSSecurityEngineResult> handleToken(
44          Element elem, 
45          RequestData data,
46          WSDocInfo wsDocInfo
47      ) throws WSSecurityException {
48          if (log.isDebugEnabled()) {
49              log.debug("Found UsernameToken list element");
50          }
51          // See if the token has been previously processed
52          String id = elem.getAttributeNS(WSConstants.WSU_NS, "Id");
53          if (!"".equals(id)) {
54              Element foundElement = wsDocInfo.getTokenElement(id);
55              if (elem.equals(foundElement)) {
56                  WSSecurityEngineResult result = wsDocInfo.getResult(id);
57                  return java.util.Collections.singletonList(result);
58              } else if (foundElement != null) {
59                  throw new WSSecurityException(
60                      WSSecurityException.INVALID_SECURITY_TOKEN, "duplicateError"
61                  );
62              }
63          }
64          
65          Validator validator = data.getValidator(WSSecurityEngine.USERNAME_TOKEN);
66          Credential credential = handleUsernameToken(elem, validator, data);
67          UsernameToken token = credential.getUsernametoken();
68          
69          int action = WSConstants.UT;
70          byte[] secretKey = null;
71          if (token.getPassword() == null) { 
72              action = WSConstants.UT_NOPASSWORD;
73              if (token.isDerivedKey()) {
74                  token.setRawPassword(data);
75                  secretKey = token.getDerivedKey();
76              } 
77          }
78          WSSecurityEngineResult result = new WSSecurityEngineResult(action, token);
79          result.put(WSSecurityEngineResult.TAG_ID, token.getID());
80          result.put(WSSecurityEngineResult.TAG_SECRET, secretKey);
81          
82          if (validator != null) {
83              result.put(WSSecurityEngineResult.TAG_VALIDATED_TOKEN, Boolean.TRUE);
84              if (credential.getTransformedToken() != null) {
85                  result.put(
86                      WSSecurityEngineResult.TAG_TRANSFORMED_TOKEN, credential.getTransformedToken()
87                  );
88                  SAMLTokenPrincipal samlPrincipal = 
89                      new SAMLTokenPrincipal(credential.getTransformedToken());
90                  result.put(WSSecurityEngineResult.TAG_PRINCIPAL, samlPrincipal);
91              } else {
92                  WSUsernameTokenPrincipal principal = 
93                      new WSUsernameTokenPrincipal(token.getName(), token.isHashed());
94                  principal.setNonce(token.getNonce());
95                  principal.setPassword(token.getPassword());
96                  principal.setCreatedTime(token.getCreated());
97                  principal.setPasswordType(token.getPasswordType());
98                  result.put(WSSecurityEngineResult.TAG_PRINCIPAL, principal);
99              }
100             result.put(WSSecurityEngineResult.TAG_SUBJECT, credential.getSubject());
101         }
102         
103         wsDocInfo.addTokenElement(elem);
104         wsDocInfo.addResult(result);
105         return java.util.Collections.singletonList(result);
106     }
107 
108     /**
109      * Check the UsernameToken element and validate it.
110      *
111      * @param token the DOM element that contains the UsernameToken
112      * @param data The RequestData object from which to obtain configuration
113      * @return a Credential object corresponding to the (validated) Username Token
114      * @throws WSSecurityException
115      */
116     public Credential 
117     handleUsernameToken(
118         Element token, 
119         Validator validator,
120         RequestData data
121     ) throws WSSecurityException {
122         boolean allowNamespaceQualifiedPasswordTypes = false;
123         boolean bspCompliant = true;
124         WSSConfig wssConfig = data.getWssConfig();
125         if (wssConfig != null) {
126             allowNamespaceQualifiedPasswordTypes = 
127                 wssConfig.getAllowNamespaceQualifiedPasswordTypes();
128             bspCompliant = wssConfig.isWsiBSPCompliant();
129         }
130         
131         //
132         // Parse and validate the UsernameToken element
133         //
134         UsernameToken ut = 
135             new UsernameToken(token, allowNamespaceQualifiedPasswordTypes, bspCompliant);
136         
137         // Test for replay attacks
138         ReplayCache replayCache = data.getNonceReplayCache();
139         if (replayCache != null && ut.getNonce() != null) {
140             if (replayCache.contains(ut.getNonce())) {
141                 throw new WSSecurityException(
142                     WSSecurityException.INVALID_SECURITY,
143                     "badUsernameToken",
144                     new Object[] {"A replay attack has been detected"}
145                 );
146             }
147             replayCache.add(ut.getNonce());
148         }
149         
150         Credential credential = new Credential();
151         credential.setUsernametoken(ut);
152         if (validator != null) {
153             return validator.validate(credential, data);
154         }
155         return credential;
156     }
157 
158 }