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.impl.securityToken;
20  
21  import java.security.Key;
22  import java.security.Principal;
23  
24  import javax.crypto.spec.SecretKeySpec;
25  import javax.security.auth.Subject;
26  
27  import org.apache.wss4j.common.bsp.BSPRule;
28  import org.apache.wss4j.common.ext.WSSecurityException;
29  import org.apache.wss4j.common.principal.UsernameTokenPrincipal;
30  import org.apache.wss4j.common.util.UsernameTokenUtil;
31  import org.apache.wss4j.stax.ext.WSInboundSecurityContext;
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.xml.security.exceptions.XMLSecurityException;
36  import org.apache.xml.security.stax.config.JCEAlgorithmMapper;
37  import org.apache.xml.security.stax.ext.XMLSecurityConstants;
38  import org.apache.xml.security.stax.impl.securityToken.AbstractInboundSecurityToken;
39  
40  public class UsernameSecurityTokenImpl extends AbstractInboundSecurityToken implements UsernameSecurityToken {
41  
42      private static final long DEFAULT_ITERATION = 1000;
43  
44      private WSSConstants.UsernameTokenPasswordType usernameTokenPasswordType;
45      private String username;
46      private String password;
47      private String createdTime;
48      private byte[] nonce;
49      private byte[] salt;
50      private Long iteration;
51      private final WSInboundSecurityContext wsInboundSecurityContext;
52      private Subject subject;
53      private Principal principal;
54  
55      public UsernameSecurityTokenImpl(WSSConstants.UsernameTokenPasswordType usernameTokenPasswordType,  //NOPMD
56                                       String username, String password, String createdTime, byte[] nonce,
57                                       byte[] salt, Long iteration,
58                                       WSInboundSecurityContext wsInboundSecurityContext, String id,
59                                       WSSecurityTokenConstants.KeyIdentifier keyIdentifier) {
60          super(wsInboundSecurityContext, id, keyIdentifier, true);
61          this.usernameTokenPasswordType = usernameTokenPasswordType;
62          this.username = username;
63          this.password = password;
64          this.createdTime = createdTime;
65          this.nonce = nonce;
66          this.salt = salt;
67          this.iteration = iteration;
68          this.wsInboundSecurityContext = wsInboundSecurityContext;
69      }
70  
71      @Override
72      public boolean isAsymmetric() throws XMLSecurityException {
73          return false;
74      }
75  
76      @Override
77      protected Key getKey(String algorithmURI, XMLSecurityConstants.AlgorithmUsage algorithmUsage,
78                           String correlationID) throws XMLSecurityException {
79  
80          Key key = getSecretKey().get(algorithmURI);
81          if (key != null) {
82              return key;
83          }
84  
85          byte[] secretToken = generateDerivedKey(wsInboundSecurityContext);
86          String algoFamily = JCEAlgorithmMapper.getJCEKeyAlgorithmFromURI(algorithmURI);
87          key = new SecretKeySpec(secretToken, algoFamily);
88          setSecretKey(algorithmURI, key);
89          return key;
90      }
91  
92      @Override
93      public WSSecurityTokenConstants.TokenType getTokenType() {
94          return WSSecurityTokenConstants.USERNAME_TOKEN;
95      }
96  
97      /**
98       * This method generates a derived key as defined in WSS Username
99       * Token Profile.
100      *
101      * @return Returns the derived key a byte array
102      * @throws WSSecurityException
103      */
104     public byte[] generateDerivedKey() throws WSSecurityException {
105         return generateDerivedKey(wsInboundSecurityContext);
106     }
107 
108     /**
109      * This method generates a derived key as defined in WSS Username
110      * Token Profile.
111      *
112      * @return Returns the derived key a byte array
113      * @throws org.apache.wss4j.common.ext.WSSecurityException
114      *
115      */
116     protected byte[] generateDerivedKey(WSInboundSecurityContext wsInboundSecurityContext) throws WSSecurityException {
117 
118         if (wsInboundSecurityContext != null) {
119             if (salt == null || salt.length == 0) {
120                 wsInboundSecurityContext.handleBSPRule(BSPRule.R4217);
121             }
122             if (iteration == null || iteration < DEFAULT_ITERATION) {
123                 wsInboundSecurityContext.handleBSPRule(BSPRule.R4218);
124             }
125         }
126 
127         int iterationCount = iteration != null ? iteration.intValue() : (int)DEFAULT_ITERATION;
128         return UsernameTokenUtil.generateDerivedKey(password, salt, iterationCount);
129     }
130 
131     @Override
132     public Principal getPrincipal() throws WSSecurityException {
133         if (this.principal == null) {
134             this.principal = new UsernameTokenPrincipal() {
135                 //todo passwordType and passwordDigest return Enum-Type ?
136                 @Override
137                 public boolean isPasswordDigest() {
138                     return usernameTokenPasswordType == WSSConstants.UsernameTokenPasswordType.PASSWORD_DIGEST;
139                 }
140 
141 
142                 @Override
143                 public String getPasswordType() {
144                     return usernameTokenPasswordType.getNamespace();
145                 }
146 
147                 @Override
148                 public String getName() {
149                     return username;
150                 }
151 
152                 @Override
153                 public String getPassword() {
154                     return password;
155                 }
156 
157                 @Override
158                 public String getCreatedTime() {
159                     return createdTime;
160                 }
161 
162                 @Override
163                 public byte[] getNonce() {
164                     return nonce;
165                 }
166             };
167         }
168         return this.principal;
169     }
170 
171     public WSSConstants.UsernameTokenPasswordType getUsernameTokenPasswordType() {
172         return usernameTokenPasswordType;
173     }
174 
175     public String getCreatedTime() {
176         return createdTime;
177     }
178 
179     public String getPassword() {
180         return password;
181     }
182 
183     public String getUsername() {
184         return username;
185     }
186 
187     public byte[] getNonce() {
188         return nonce;
189     }
190 
191     public byte[] getSalt() {
192         return salt;
193     }
194 
195     public Long getIteration() {
196         return iteration;
197     }
198 
199     public void setSubject(Subject subject) {
200         this.subject = subject;
201     }
202 
203     @Override
204     public Subject getSubject() throws WSSecurityException {
205         return subject;
206     }
207 }