001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common Development
008: * and Distribution License("CDDL") (collectively, the "License"). You
009: * may not use this file except in compliance with the License. You can obtain
010: * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
011: * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
012: * language governing permissions and limitations under the License.
013: *
014: * When distributing the software, include this License Header Notice in each
015: * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
016: * Sun designates this particular file as subject to the "Classpath" exception
017: * as provided by Sun in the GPL Version 2 section of the License file that
018: * accompanied this code. If applicable, add the following below the License
019: * Header, with the fields enclosed by brackets [] replaced by your own
020: * identifying information: "Portions Copyrighted [year]
021: * [name of copyright owner]"
022: *
023: * Contributor(s):
024: *
025: * If you wish your version of this file to be governed by only the CDDL or
026: * only the GPL Version 2, indicate your decision by adding "[Contributor]
027: * elects to include this software in this distribution under the [CDDL or GPL
028: * Version 2] license." If you don't indicate a single choice of license, a
029: * recipient has the option to distribute your version of this file under
030: * either the CDDL, the GPL Version 2 or to extend the choice of license to
031: * its licensees as provided above. However, if you add GPL Version 2 code
032: * and therefore, elected the GPL Version 2 license, then the option applies
033: * only if the new code is made subject to such option by the copyright
034: * holder.
035: */
036:
037: package com.sun.xml.ws.security.secconv;
038:
039: import com.sun.xml.ws.policy.impl.bindings.AppliesTo;
040: import com.sun.xml.ws.security.IssuedTokenContext;
041: import com.sun.xml.ws.security.SecurityContextToken;
042: import com.sun.xml.ws.security.trust.Configuration;
043: import com.sun.xml.ws.security.trust.WSTrustClientContract;
044: import com.sun.xml.ws.security.trust.WSTrustConstants;
045: import com.sun.xml.ws.security.trust.elements.BinarySecret;
046: import com.sun.xml.ws.security.trust.elements.Entropy;
047: import com.sun.xml.ws.security.trust.elements.Lifetime;
048: import com.sun.xml.ws.security.trust.elements.RequestSecurityToken;
049: import com.sun.xml.ws.security.trust.elements.RequestSecurityTokenResponse;
050: import com.sun.xml.ws.security.trust.elements.RequestedAttachedReference;
051: import com.sun.xml.ws.security.trust.elements.RequestedProofToken;
052: import com.sun.xml.ws.security.trust.elements.RequestedSecurityToken;
053: import com.sun.xml.ws.security.trust.elements.RequestedTokenCancelled;
054: import com.sun.xml.ws.security.trust.elements.RequestedUnattachedReference;
055: import com.sun.xml.ws.security.trust.util.WSTrustUtil;
056: import com.sun.xml.ws.security.wsu10.AttributedDateTime;
057: import com.sun.xml.wss.impl.misc.SecurityUtil;
058:
059: import java.net.URI;
060: import java.text.ParseException;
061: import java.text.SimpleDateFormat;
062: import java.util.Date;
063: import java.util.Locale;
064:
065: import java.util.logging.Level;
066: import java.util.logging.Logger;
067: import com.sun.xml.ws.security.secconv.logging.LogDomainConstants;
068: import com.sun.xml.ws.security.secconv.logging.LogStringsMessages;
069:
070: public class WSSCClientContract implements WSTrustClientContract {
071:
072: private static final Logger log = Logger.getLogger(
073: LogDomainConstants.WSSC_IMPL_DOMAIN,
074: LogDomainConstants.WSSC_IMPL_DOMAIN_BUNDLE);
075:
076: //private final Configuration config;
077: private static final SimpleDateFormat calendarFormatter = new SimpleDateFormat(
078: "yyyy-MM-dd'T'HH:mm:ss'.'sss'Z'", Locale.getDefault());
079:
080: private static final int DEFAULT_KEY_SIZE = 256;
081:
082: public WSSCClientContract(Configuration config) {
083: //this.config = config;
084: }
085:
086: /**
087: * Handle an RSTR returned by the Issuer and update Token information into the
088: * IssuedTokenContext.
089: */
090: public void handleRSTR(final RequestSecurityToken rst,
091: final RequestSecurityTokenResponse rstr,
092: final IssuedTokenContext context)
093: throws WSSecureConversationException {
094: if (rst.getRequestType().toString().equals(
095: WSTrustConstants.ISSUE_REQUEST)) {
096: // ToDo
097: //final AppliesTo requestAppliesTo = rst.getAppliesTo();
098: //final AppliesTo responseAppliesTo = rstr.getAppliesTo();
099:
100: final RequestedSecurityToken securityToken = rstr
101: .getRequestedSecurityToken();
102:
103: // Requested References
104: final RequestedAttachedReference attachedRef = rstr
105: .getRequestedAttachedReference();
106: final RequestedUnattachedReference unattachedRef = rstr
107: .getRequestedUnattachedReference();
108:
109: // RequestedProofToken
110: final RequestedProofToken proofToken = rstr
111: .getRequestedProofToken();
112:
113: // Obtain the secret key for the context
114: final byte[] key = getKey(rstr, proofToken, rst);
115:
116: if (key != null) {
117: context.setProofKey(key);
118: }
119:
120: //get the creation time and expires time and set it in the context
121: setLifetime(rstr, context);
122:
123: if (securityToken == null && proofToken == null) {
124: log.log(Level.SEVERE, LogStringsMessages
125: .WSSC_0002_NULL_TOKEN());
126: throw new WSSecureConversationException(
127: LogStringsMessages.WSSC_0002_NULL_TOKEN());
128: }
129:
130: if (securityToken != null) {
131: context.setSecurityToken(securityToken.getToken());
132: }
133:
134: if (attachedRef != null) {
135: context.setAttachedSecurityTokenReference(attachedRef
136: .getSTR());
137: }
138:
139: if (unattachedRef != null) {
140: context
141: .setUnAttachedSecurityTokenReference(unattachedRef
142: .getSTR());
143: }
144:
145: } else if (rst.getRequestType().toString().equals(
146: WSTrustConstants.CANCEL_REQUEST)) {
147:
148: // Check if the rstr contains the RequestTedTokenCancelled element
149: // if yes cleanup the IssuedTokenContext accordingly
150: final RequestedTokenCancelled cancelled = rstr
151: .getRequestedTokenCancelled();
152: if (cancelled != null) {
153: context.setSecurityToken(null);
154: context.setProofKey(null);
155: }
156: }
157:
158: }
159:
160: private byte[] getKey(final RequestSecurityTokenResponse rstr,
161: final RequestedProofToken proofToken,
162: final RequestSecurityToken rst)
163: throws UnsupportedOperationException,
164: WSSecureConversationException,
165: WSSecureConversationException,
166: UnsupportedOperationException {
167: byte[] key = null;
168: if (proofToken != null) {
169: final String proofTokenType = proofToken
170: .getProofTokenType();
171: if (RequestedProofToken.COMPUTED_KEY_TYPE
172: .equals(proofTokenType)) {
173: key = computeKey(rstr, proofToken, rst);
174: } else if (RequestedProofToken.TOKEN_REF_TYPE
175: .equals(proofTokenType)) {
176: //ToDo
177: throw new UnsupportedOperationException("To Do");
178: } else if (RequestedProofToken.ENCRYPTED_KEY_TYPE
179: .equals(proofTokenType)) {
180: //ToDo
181: throw new UnsupportedOperationException("To Do");
182: } else if (RequestedProofToken.BINARY_SECRET_TYPE
183: .equals(proofTokenType)) {
184: final BinarySecret binarySecret = proofToken
185: .getBinarySecret();
186: key = binarySecret.getRawValue();
187: } else {
188: log.log(Level.SEVERE, LogStringsMessages
189: .WSSC_0003_INVALID_PROOFTOKEN(proofTokenType));
190: throw new WSSecureConversationException(
191: LogStringsMessages
192: .WSSC_0003_INVALID_PROOFTOKEN(proofTokenType));
193: }
194: }
195: return key;
196: }
197:
198: private void setLifetime(final RequestSecurityTokenResponse rstr,
199: final IssuedTokenContext context)
200: throws WSSecureConversationException {
201:
202: // Get Created and Expires from Lifetime
203: try {
204: final Lifetime lifetime = rstr.getLifetime();
205: final AttributedDateTime created = lifetime.getCreated();
206: final AttributedDateTime expires = lifetime.getExpires();
207: synchronized (calendarFormatter) {
208: final Date dateCreated = calendarFormatter
209: .parse(created.getValue());
210: final Date dateExpires = calendarFormatter
211: .parse(expires.getValue());
212:
213: // populate the IssuedTokenContext
214: context.setCreationTime(dateCreated);
215: context.setExpirationTime(dateExpires);
216: }
217: } catch (ParseException ex) {
218: log.log(Level.SEVERE, LogStringsMessages
219: .WSSC_0004_PARSE_EXCEPTION(), ex);
220: throw new WSSecureConversationException(LogStringsMessages
221: .WSSC_0004_PARSE_EXCEPTION(), ex);
222: }
223: }
224:
225: private byte[] computeKey(final RequestSecurityTokenResponse rstr,
226: final RequestedProofToken proofToken,
227: final RequestSecurityToken rst)
228: throws WSSecureConversationException,
229: UnsupportedOperationException {
230: // get ComputeKey algorithm URI, client entropy, server entropy and compute
231: // the SecretKey
232: final URI computedKey = proofToken.getComputedKey();
233: final Entropy clientEntropy = rst.getEntropy();
234: final Entropy serverEntropy = rstr.getEntropy();
235: final BinarySecret clientBS = clientEntropy.getBinarySecret();
236: final BinarySecret serverBS = serverEntropy.getBinarySecret();
237: byte[] clientEntr = null;
238: byte[] serverEntr = null;
239: if (clientBS != null) {
240: clientEntr = clientBS.getRawValue();
241: }
242: if (serverBS != null) {
243: serverEntr = serverBS.getRawValue();
244: }
245: byte[] key = null;
246: int keySize = (int) rstr.getKeySize();
247: if (keySize == 0) {
248: keySize = (int) rst.getKeySize();//get it from the request
249: }
250: if (keySize == 0) {
251: keySize = DEFAULT_KEY_SIZE;//key size is in bits
252: }
253: if (log.isLoggable(Level.FINE)) {
254: log.log(Level.FINE, LogStringsMessages
255: .WSSC_0005_COMPUTED_KEYSIZE(keySize,
256: DEFAULT_KEY_SIZE));
257: }
258: if (computedKey.toString().equals(WSTrustConstants.CK_PSHA1)) {
259: try {
260: key = SecurityUtil.P_SHA1(clientEntr, serverEntr,
261: keySize / 8);
262: } catch (Exception ex) {
263: log.log(Level.SEVERE, LogStringsMessages
264: .WSSC_0006_UNABLETOEXTRACT_KEY(), ex);
265: throw new WSSecureConversationException(
266: LogStringsMessages
267: .WSSC_0006_UNABLETOEXTRACT_KEY(), ex);
268: }
269: } else {
270: log.log(Level.SEVERE, LogStringsMessages
271: .WSSC_0026_UNSUPPORTED_COMPUTED_KEY(computedKey));
272: throw new WSSecureConversationException(LogStringsMessages
273: .WSSC_0026_UNSUPPORTED_COMPUTED_KEY_E(computedKey));
274: }
275: return key;
276: }
277:
278: /**
279: * Handle an RSTR returned by the Issuer and Respond to the Challenge
280: *
281: */
282: public RequestSecurityTokenResponse handleRSTRForNegotiatedExchange(
283: final RequestSecurityToken rst,
284: final RequestSecurityTokenResponse rstr,
285: final IssuedTokenContext context)
286: throws WSSecureConversationException {
287: return null;
288: }
289:
290: /**
291: * Create an RSTR for a client initiated IssuedTokenContext establishment,
292: * for example a Client Initiated WS-SecureConversation context.
293: *
294: */
295: public RequestSecurityTokenResponse createRSTRForClientInitiatedIssuedTokenContext(
296: final AppliesTo scopes, final IssuedTokenContext context)
297: throws WSSecureConversationException {
298: final WSSCElementFactory eleFac = WSSCElementFactory
299: .newInstance();
300:
301: final byte[] secret = WSTrustUtil
302: .generateRandomSecret(DEFAULT_KEY_SIZE);
303: final BinarySecret binarySecret = eleFac.createBinarySecret(
304: secret, BinarySecret.SYMMETRIC_KEY_TYPE);
305:
306: final RequestedProofToken proofToken = eleFac
307: .createRequestedProofToken();
308: proofToken
309: .setProofTokenType(RequestedProofToken.BINARY_SECRET_TYPE);
310: proofToken.setBinarySecret(binarySecret);
311:
312: final SecurityContextToken token = WSTrustUtil
313: .createSecurityContextToken(eleFac);
314: final RequestedSecurityToken rst = eleFac
315: .createRequestedSecurityToken(token);
316:
317: final RequestSecurityTokenResponse rstr = eleFac.createRSTR();
318: rstr.setAppliesTo(scopes);
319: rstr.setRequestedSecurityToken(rst);
320: rstr.setRequestedProofToken(proofToken);
321:
322: context.setSecurityToken(token);
323: context.setProofKey(secret);
324: if (log.isLoggable(Level.FINE)) {
325: log.log(Level.FINE, LogStringsMessages
326: .WSSC_0007_CREATED_RSTR(rstr.toString()));
327: }
328: return rstr;
329: }
330:
331: /**
332: * Contains Challenge
333: * @return true if the RSTR contains a SignChallenge/BinaryExchange or
334: * some other custom challenge recognized by this implementation.
335: */
336: public boolean containsChallenge(
337: final RequestSecurityTokenResponse rstr) {
338: return false;
339: }
340:
341: /**
342: * Return the <wst:ComputedKey> URI if any inside the RSTR, null otherwise
343: */
344: public URI getComputedKeyAlgorithmFromProofToken(
345: final RequestSecurityTokenResponse rstr) {
346: return null;
347: }
348: }
|