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  package org.apache.wss4j.stax.validate;
20  
21  import javax.security.auth.Subject;
22  import javax.security.auth.callback.CallbackHandler;
23  import javax.security.auth.login.LoginContext;
24  import javax.security.auth.login.LoginException;
25  
26  import org.apache.wss4j.binding.wss10.EncodedString;
27  import org.apache.wss4j.binding.wss10.PasswordString;
28  import org.apache.wss4j.binding.wss10.UsernameTokenType;
29  import org.apache.wss4j.binding.wsu10.AttributedDateTime;
30  import org.apache.wss4j.common.NamePasswordCallbackHandler;
31  import org.apache.wss4j.common.ext.WSSecurityException;
32  import org.apache.wss4j.stax.ext.WSSConstants;
33  import org.apache.wss4j.stax.securityToken.UsernameSecurityToken;
34  import org.apache.wss4j.stax.securityToken.WSSecurityTokenConstants;
35  import org.apache.wss4j.stax.impl.securityToken.UsernameSecurityTokenImpl;
36  import org.apache.xml.security.stax.ext.XMLSecurityUtils;
37  import org.apache.xml.security.stax.securityToken.InboundSecurityToken;
38  import org.apache.xml.security.utils.XMLUtils;
39  
40  /**
41   * This class validates a processed UsernameToken, where Username/password validation is delegated
42   * to the JAAS LoginContext.
43   */
44  public class JAASUsernameTokenValidatorImpl implements UsernameTokenValidator {
45  
46      private static final transient org.slf4j.Logger LOG =
47              org.slf4j.LoggerFactory.getLogger(JAASUsernameTokenValidatorImpl.class);
48  
49      private String contextName;
50  
51      public void setContextName(String name) {
52          contextName = name;
53      }
54  
55      public String getContextName() {
56          return contextName;
57      }
58  
59      @Override
60      public <T extends UsernameSecurityToken & InboundSecurityToken> T validate(
61              UsernameTokenType usernameTokenType, TokenContext tokenContext) throws WSSecurityException {
62  
63          PasswordString passwordType = XMLSecurityUtils.getQNameType(usernameTokenType.getAny(), WSSConstants.TAG_WSSE_PASSWORD);
64          WSSConstants.UsernameTokenPasswordType usernameTokenPasswordType = WSSConstants.UsernameTokenPasswordType.PASSWORD_NONE;
65          if (passwordType != null && passwordType.getType() != null) {
66              usernameTokenPasswordType = WSSConstants.UsernameTokenPasswordType.getUsernameTokenPasswordType(passwordType.getType());
67          }
68  
69          // Digest not supported
70          if (usernameTokenPasswordType != WSSConstants.UsernameTokenPasswordType.PASSWORD_TEXT) {
71              LOG.warn("Password type is not supported");
72              throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_AUTHENTICATION);
73          }
74  
75          String username = null;
76          if (usernameTokenType.getUsername() != null) {
77              username = usernameTokenType.getUsername().getValue();
78          }
79          String password = null;
80          if (passwordType != null) {
81              password = passwordType.getValue();
82          }
83  
84          if (username == null || username.isEmpty() || password == null || password.isEmpty()) {
85              LOG.warn("User or password empty");
86              throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_AUTHENTICATION);
87          }
88  
89          Subject subject;
90          try {
91              CallbackHandler handler = getCallbackHandler(username, password);
92              LoginContext ctx = new LoginContext(getContextName(), handler);
93              ctx.login();
94              subject = ctx.getSubject();
95          } catch (LoginException ex) {
96              LOG.info("Authentication failed", ex);
97              throw new WSSecurityException(
98                  WSSecurityException.ErrorCode.FAILED_AUTHENTICATION, ex
99              );
100         }
101 
102         final EncodedString encodedNonce =
103                 XMLSecurityUtils.getQNameType(usernameTokenType.getAny(), WSSConstants.TAG_WSSE_NONCE);
104         byte[] nonceVal = null;
105         if (encodedNonce != null) {
106             if (!WSSConstants.SOAPMESSAGE_NS10_BASE64_ENCODING.equals(encodedNonce.getEncodingType())) {
107                 throw new WSSecurityException(WSSecurityException.ErrorCode.UNSUPPORTED_SECURITY_TOKEN, "badTokenType01");
108             }
109             nonceVal = XMLUtils.decode(encodedNonce.getValue());
110         }
111 
112         final AttributedDateTime attributedDateTimeCreated =
113                 XMLSecurityUtils.getQNameType(usernameTokenType.getAny(), WSSConstants.TAG_WSU_CREATED);
114 
115         UsernameSecurityTokenImpl usernameSecurityToken = new UsernameSecurityTokenImpl(
116                 usernameTokenPasswordType, username, password,
117                 attributedDateTimeCreated != null ? attributedDateTimeCreated.getValue() : null,
118                 nonceVal, null, null,
119                 tokenContext.getWsSecurityContext(), usernameTokenType.getId(),
120                 WSSecurityTokenConstants.KEYIDENTIFIER_SECURITY_TOKEN_DIRECT_REFERENCE);
121         usernameSecurityToken.setElementPath(tokenContext.getElementPath());
122         usernameSecurityToken.setXMLSecEvent(tokenContext.getFirstXMLSecEvent());
123         usernameSecurityToken.setSubject(subject);
124 
125         @SuppressWarnings("unchecked")
126         T token = (T)usernameSecurityToken;
127         return token;
128     }
129 
130     protected CallbackHandler getCallbackHandler(String name, String password) {
131         return new NamePasswordCallbackHandler(name, password);
132     }
133 }