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.wss4j.dom.message;
21
22 import org.apache.wss4j.dom.WSConstants;
23
24 import org.apache.wss4j.common.ext.WSSecurityException;
25 import org.apache.wss4j.common.util.UsernameTokenUtil;
26 import org.apache.wss4j.common.util.WSCurrentTimeSource;
27 import org.apache.wss4j.common.util.WSTimeSource;
28 import org.apache.wss4j.dom.message.token.UsernameToken;
29 import org.apache.wss4j.dom.util.WSSecurityUtil;
30 import org.w3c.dom.Document;
31 import org.w3c.dom.Element;
32
33 /**
34 * Builds a WS UsernameToken.
35 *
36 * Refer to the WS specification, UsernameToken profile
37 */
38 public class WSSecUsernameToken extends WSSecBase {
39 private static final org.slf4j.Logger LOG =
40 org.slf4j.LoggerFactory.getLogger(WSSecUsernameToken.class);
41
42 private String passwordType = WSConstants.PASSWORD_DIGEST;
43 private UsernameToken ut;
44 private boolean nonce;
45 private boolean created;
46 private boolean useDerivedKey;
47 private int iteration = UsernameToken.DEFAULT_ITERATION;
48 private boolean passwordsAreEncoded;
49 private boolean precisionInMilliSeconds = true;
50 private WSTimeSource wsTimeSource = new WSCurrentTimeSource();
51
52 public WSSecUsernameToken(WSSecHeader securityHeader) {
53 super(securityHeader);
54 }
55
56 public WSSecUsernameToken(Document doc) {
57 super(doc);
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 * Add a derived key to the UsernameToken
90 * @param iteration The number of iterations to use in deriving a key
91 */
92 public void addDerivedKey(int iteration) {
93 passwordType = null;
94 useDerivedKey = true;
95 if (iteration > 0) {
96 this.iteration = iteration;
97 }
98 }
99
100 /**
101 * Get the derived key.
102 *
103 * After the <code>prepare()</code> method was called use this method
104 * to compute a derived key. The generation of this secret key is according
105 * to the UsernameTokenProfile 1.1 specification (section 4 - Key Derivation).
106 *
107 * @param saltValue The salt value to use
108 * @return Return the derived key of this token or null if <code>prepare()</code>
109 * was not called before.
110 */
111 public byte[] getDerivedKey(byte[] saltValue) throws WSSecurityException {
112 if (ut == null || !useDerivedKey) {
113 return new byte[0];
114 }
115 if (passwordsAreEncoded) {
116 return UsernameTokenUtil.generateDerivedKey(org.apache.xml.security.utils.XMLUtils.decode(password),
117 saltValue, iteration);
118 } else {
119 return UsernameTokenUtil.generateDerivedKey(password, saltValue, iteration);
120 }
121 }
122
123 /**
124 * @param passwordsAreEncoded
125 * whether passwords are encoded
126 */
127 public void setPasswordsAreEncoded(boolean passwordsAreEncoded) {
128 this.passwordsAreEncoded = passwordsAreEncoded;
129 }
130
131 /**
132 * @return whether passwords are encoded
133 */
134 public boolean getPasswordsAreEncoded() {
135 return passwordsAreEncoded;
136 }
137
138 /**
139 * Get the id generated during <code>prepare()</code>.
140 *
141 * Returns the the value of wsu:Id attribute of this UsernameToken.
142 *
143 * @return Return the wsu:Id of this token or null if <code>prepare()</code>
144 * was not called before.
145 */
146 public String getId() {
147 if (ut == null) {
148 return null;
149 }
150 return ut.getID();
151 }
152
153 /**
154 * Creates a Username token.
155 *
156 * The method prepares and initializes a WSSec UsernameToken structure after
157 * the relevant information was set. A Before calling
158 * <code>prepare()</code> all parameters such as user, password,
159 * passwordType etc. must be set. A complete <code>UsernameToken</code> is
160 * constructed.
161 */
162 public void prepare() {
163 prepare(null);
164 }
165
166 public void prepare(byte[] saltValue) {
167 ut = new UsernameToken(precisionInMilliSeconds, getDocument(), wsTimeSource, passwordType);
168 ut.setPasswordsAreEncoded(passwordsAreEncoded);
169 ut.setName(user);
170 if (useDerivedKey) {
171 ut.addSalt(getDocument(), saltValue);
172 ut.addIteration(getDocument(), iteration);
173 } else {
174 ut.setPassword(password);
175 }
176 if (nonce) {
177 ut.addNonce(getDocument());
178 }
179 if (created) {
180 ut.addCreated(precisionInMilliSeconds, wsTimeSource, getDocument());
181 }
182 ut.setID(getIdAllocator().createId("UsernameToken-", ut));
183 if (addWSUNamespace) {
184 ut.addWSUNamespace();
185 }
186 }
187
188 /**
189 * Prepends the UsernameToken element to the elements already in the
190 * Security header.
191 *
192 * The method can be called any time after <code>prepare()</code>.
193 * This allows to insert the UsernameToken element at any position in the
194 * Security header.
195 */
196 public void prependToHeader() {
197 Element securityHeaderElement = getSecurityHeader().getSecurityHeaderElement();
198 WSSecurityUtil.prependChildElement(securityHeaderElement, ut.getElement());
199 }
200
201 /**
202 * Appends the UsernameToken element to the elements already in the
203 * Security header.
204 *
205 * The method can be called any time after <code>prepare()</code>.
206 * This allows to insert the UsernameToken element at any position in the
207 * Security header.
208 */
209 public void appendToHeader() {
210 Element securityHeaderElement = getSecurityHeader().getSecurityHeaderElement();
211 securityHeaderElement.appendChild(ut.getElement());
212 }
213
214 /**
215 * Adds a new <code>UsernameToken</code> to a soap envelope.
216 *
217 * Before calling <code>build()</code> all parameters such as user,
218 * password, passwordType etc. must be set. A complete
219 * <code>UsernameToken</code> is constructed and added to the
220 * <code>wsse:Security</code> header.
221 *
222 * @param salt the salt value to add if we are using a derived key
223 * @return Document with UsernameToken added
224 */
225 public Document build(byte[] salt) {
226 LOG.debug("Begin add username token...");
227
228 prepare(salt);
229 prependToHeader();
230
231 return getDocument();
232 }
233
234 public Document build() {
235 return build(null);
236 }
237
238 /**
239 * Returns the <code>UsernameToken</code> element.
240 *
241 * The method can be called any time after <code>prepare()</code>.
242 * This allows to insert the UsernameToken element at any position in the
243 * Security header.
244 *
245 * @return the Username Token element
246 */
247 public Element getUsernameTokenElement() {
248 return ut.getElement();
249 }
250
251 public boolean isPrecisionInMilliSeconds() {
252 return precisionInMilliSeconds;
253 }
254
255 public void setPrecisionInMilliSeconds(boolean precisionInMilliSeconds) {
256 this.precisionInMilliSeconds = precisionInMilliSeconds;
257 }
258
259 public WSTimeSource getWsTimeSource() {
260 return wsTimeSource;
261 }
262
263 public void setWsTimeSource(WSTimeSource wsTimeSource) {
264 this.wsTimeSource = wsTimeSource;
265 }
266 }