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.message;
21
22 import org.apache.ws.security.WSConstants;
23 import org.apache.ws.security.WSSConfig;
24 import org.apache.ws.security.WSSecurityException;
25 import org.apache.ws.security.message.token.UsernameToken;
26 import org.apache.ws.security.util.Base64;
27 import org.apache.ws.security.util.WSSecurityUtil;
28 import org.w3c.dom.Document;
29 import org.w3c.dom.Element;
30
31 /**
32 * Builds a WS UsernameToken.
33 *
34 * Refer to the WS specification, UsernameToken profile
35 *
36 * @author Werner Dittmann (werner@apache.org).
37 */
38 public class WSSecUsernameToken extends WSSecBase {
39 private static org.apache.commons.logging.Log log =
40 org.apache.commons.logging.LogFactory.getLog(WSSecUsernameToken.class);
41
42 private String passwordType = WSConstants.PASSWORD_DIGEST;
43 private UsernameToken ut = null;
44 private boolean nonce = false;
45 private boolean created = false;
46 private boolean useDerivedKey = false;
47 private boolean useMac = false;
48 private byte[] saltValue;
49 private int iteration = UsernameToken.DEFAULT_ITERATION;
50 private int secretKeyLength = WSConstants.WSE_DERIVED_KEY_LEN;
51 private boolean passwordsAreEncoded = false;
52
53 public WSSecUsernameToken() {
54 super();
55 }
56 public WSSecUsernameToken(WSSConfig config) {
57 super(config);
58 }
59
60 /**
61 * Defines how to construct the password element of the
62 * <code>UsernameToken</code>.
63 *
64 * @param pwType
65 * contains the password type. Only allowed values are
66 * {@link WSConstants#PASSWORD_DIGEST} and
67 * {@link WSConstants#PASSWORD_TEXT}.
68 * or null when no password is needed.
69 */
70 public void setPasswordType(String pwType) {
71 this.passwordType = pwType;
72 }
73
74 /**
75 * Add a Nonce element to the UsernameToken.
76 */
77 public void addNonce() {
78 nonce = true;
79 }
80
81 /**
82 * Add a Created element to the UsernameToken.
83 */
84 public void addCreated() {
85 created = true;
86 }
87
88 /**
89 * Set the secret key length
90 */
91 public void setSecretKeyLength(int length) {
92 secretKeyLength = length;
93 }
94
95 /**
96 * Get the secret key length
97 */
98 public int getSecretKeyLength() {
99 return secretKeyLength;
100 }
101
102 /**
103 * Add a derived key to the UsernameToken
104 * @param useMac whether the derived key is to be used for a MAC or not
105 * @param saltValue The salt value to use
106 * @param iteration The number of iterations to use in deriving a key
107 */
108 public void addDerivedKey(boolean useMac, byte[] saltValue, int iteration) {
109 passwordType = null;
110 useDerivedKey = true;
111 this.useMac = useMac;
112 this.saltValue = saltValue;
113 if (iteration > 0) {
114 this.iteration = iteration;
115 }
116 }
117
118
119 /**
120 * Get the derived secret key.
121 *
122 * After the <code>prepare()</code> method was called use this method
123 * to compute a derived secret key. If "useDerivedKey" is set, then the returned secret
124 * key is derived as per the UsernameToken 1.1 specification. Otherwise, the generation
125 * of this secret key is according to the WS-Trust specifications.
126 *
127 * @return Return the derived secret key of this token or null if <code>prepare()</code>
128 * was not called before.
129 */
130 public byte[] getSecretKey() throws WSSecurityException {
131 if (ut == null) {
132 return null;
133 }
134 if (useDerivedKey) {
135 if (passwordsAreEncoded) {
136 return UsernameToken.generateDerivedKey(Base64.decode(password), saltValue, iteration);
137 } else {
138 return UsernameToken.generateDerivedKey(password, saltValue, iteration);
139 }
140 }
141 return ut.getSecretKey(secretKeyLength);
142 }
143
144 /**
145 * Get the derived key.
146 *
147 * After the <code>prepare()</code> method was called use this method
148 * to compute a derived key. The generation of this secret key is according
149 * to the UsernameTokenProfile 1.1 specification (section 4 - Key Derivation).
150 *
151 * @return Return the derived key of this token or null if <code>prepare()</code>
152 * was not called before.
153 */
154 public byte[] getDerivedKey() throws WSSecurityException {
155 if (ut == null || !useDerivedKey) {
156 return null;
157 }
158 if (passwordsAreEncoded) {
159 return UsernameToken.generateDerivedKey(Base64.decode(password), saltValue, iteration);
160 } else {
161 return UsernameToken.generateDerivedKey(password, saltValue, iteration);
162 }
163 }
164
165 /**
166 * @param passwordsAreEncoded
167 * whether passwords are encoded
168 */
169 public void setPasswordsAreEncoded(boolean passwordsAreEncoded) {
170 this.passwordsAreEncoded = passwordsAreEncoded;
171 }
172
173 /**
174 * @return whether passwords are encoded
175 */
176 public boolean getPasswordsAreEncoded() {
177 return passwordsAreEncoded;
178 }
179
180 /**
181 * Get the id generated during <code>prepare()</code>.
182 *
183 * Returns the the value of wsu:Id attribute of this UsernameToken.
184 *
185 * @return Return the wsu:Id of this token or null if <code>prepare()</code>
186 * was not called before.
187 */
188 public String getId() {
189 if (ut == null) {
190 return null;
191 }
192 return ut.getID();
193 }
194
195 /**
196 * Creates a Username token.
197 *
198 * The method prepares and initializes a WSSec UsernameToken structure after
199 * the relevant information was set. A Before calling
200 * <code>prepare()</code> all parameters such as user, password,
201 * passwordType etc. must be set. A complete <code>UsernameToken</code> is
202 * constructed.
203 *
204 * @param doc The SOAP envelope as W3C document
205 */
206 public void prepare(Document doc) {
207 ut = new UsernameToken(getWsConfig().isPrecisionInMilliSeconds(), doc, passwordType);
208 ut.setPasswordsAreEncoded(passwordsAreEncoded);
209 ut.setName(user);
210 if (useDerivedKey) {
211 saltValue = ut.addSalt(doc, saltValue, useMac);
212 ut.addIteration(doc, iteration);
213 } else {
214 ut.setPassword(password);
215 }
216 if (nonce) {
217 ut.addNonce(doc);
218 }
219 if (created) {
220 ut.addCreated(getWsConfig().isPrecisionInMilliSeconds(), doc);
221 }
222 ut.setID(getWsConfig().getIdAllocator().createId("UsernameToken-", ut));
223 }
224
225 /**
226 * Prepends the UsernameToken element to the elements already in the
227 * Security header.
228 *
229 * The method can be called any time after <code>prepare()</code>.
230 * This allows to insert the UsernameToken element at any position in the
231 * Security header.
232 *
233 * @param secHeader The security header that holds the Signature element.
234 */
235 public void prependToHeader(WSSecHeader secHeader) {
236 WSSecurityUtil.prependChildElement(secHeader.getSecurityHeader(), ut.getElement());
237 }
238
239 /**
240 * Appends the UsernameToken element to the elements already in the
241 * Security header.
242 *
243 * The method can be called any time after <code>prepare()</code>.
244 * This allows to insert the UsernameToken element at any position in the
245 * Security header.
246 *
247 * @param secHeader The security header that holds the Signature element.
248 */
249 public void appendToHeader(WSSecHeader secHeader) {
250 Element secHeaderElement = secHeader.getSecurityHeader();
251 secHeaderElement.appendChild(ut.getElement());
252 }
253
254 /**
255 * Adds a new <code>UsernameToken</code> to a soap envelope.
256 *
257 * Before calling <code>build()</code> all parameters such as user,
258 * password, passwordType etc. must be set. A complete
259 * <code>UsernameToken</code> is constructed and added to the
260 * <code>wsse:Security</code> header.
261 *
262 * @param doc The SOAP envelope as W3C document
263 * @param secHeader The security header inside the SOAP envelope
264 * @return Document with UsernameToken added
265 */
266 public Document build(Document doc, WSSecHeader secHeader) {
267 log.debug("Begin add username token...");
268
269 prepare(doc);
270 prependToHeader(secHeader);
271
272 return doc;
273 }
274
275 /**
276 * Returns the <code>UsernameToken</code> element.
277 *
278 * The method can be called any time after <code>prepare()</code>.
279 * This allows to insert the UsernameToken element at any position in the
280 * Security header.
281 *
282 * @return the Username Token element
283 */
284 public Element getUsernameTokenElement() {
285 return ut.getElement();
286 }
287 }