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: /*
038: * WSSCPlugin.java
039: *
040: * Created on February 7, 2006, 4:09 PM
041: */
042:
043: package com.sun.xml.ws.security.secconv;
044:
045: import com.sun.xml.ws.api.addressing.AddressingVersion;
046: import com.sun.xml.ws.api.message.Message;
047: import com.sun.xml.ws.api.message.Messages;
048: import com.sun.xml.ws.api.message.Packet;
049: import com.sun.xml.ws.api.message.HeaderList;
050: import com.sun.xml.ws.api.WSBinding;
051: import com.sun.xml.ws.api.model.wsdl.WSDLPort;
052: import com.sun.xml.ws.api.pipe.Pipe;
053: import com.sun.xml.ws.api.security.trust.WSTrustException;
054: import com.sun.xml.ws.policy.AssertionSet;
055: import com.sun.xml.ws.policy.NestedPolicy; //import com.sun.xml.ws.fault.SOAPFaultBuilder;
056:
057: import com.sun.xml.ws.policy.PolicyAssertion;
058: import com.sun.xml.ws.security.IssuedTokenContext;
059: import com.sun.xml.ws.security.impl.IssuedTokenContextImpl;
060: import com.sun.xml.ws.security.impl.policy.PolicyUtil;
061: import com.sun.xml.ws.security.impl.policy.Trust10;
062: import com.sun.xml.ws.security.policy.AlgorithmSuite;
063: import com.sun.xml.ws.security.policy.Constants;
064: import com.sun.xml.ws.security.policy.SecureConversationToken;
065: import com.sun.xml.ws.security.policy.SymmetricBinding;
066: import com.sun.xml.ws.security.trust.Configuration;
067: import com.sun.xml.ws.security.trust.WSTrustConstants;
068: import com.sun.xml.ws.security.trust.WSTrustElementFactory;
069: import com.sun.xml.ws.api.security.trust.WSTrustException;
070: import com.sun.xml.ws.security.trust.elements.BinarySecret;
071: import com.sun.xml.ws.security.trust.elements.CancelTarget;
072: import com.sun.xml.ws.security.trust.elements.Entropy;
073: import com.sun.xml.ws.security.trust.elements.RequestSecurityToken;
074: import com.sun.xml.ws.security.trust.elements.RequestSecurityTokenResponse;
075: import com.sun.xml.ws.security.trust.elements.str.SecurityTokenReference;
076:
077: import java.net.URI;
078: import java.security.SecureRandom;
079: import java.util.Set;
080: import javax.xml.soap.SOAPException;
081: import javax.xml.ws.soap.SOAPFaultException;
082:
083: import javax.xml.bind.JAXBElement;
084: import javax.xml.bind.JAXBException;
085: import javax.xml.bind.Marshaller;
086: import javax.xml.bind.Unmarshaller;
087:
088: import java.util.logging.Level;
089: import java.util.logging.Logger;
090: import com.sun.xml.ws.security.secconv.logging.LogDomainConstants;
091: import com.sun.xml.ws.security.secconv.logging.LogStringsMessages;
092: import java.io.StringWriter;
093: import javax.xml.stream.XMLOutputFactory;
094: import javax.xml.stream.XMLStreamException;
095: import javax.xml.stream.XMLStreamWriter;
096:
097: /**
098: *
099: * @author ws-trust-impl-team
100: *
101: * ToDo: Handle Cancel request and response.
102: */
103: public class WSSCPlugin {
104:
105: Configuration config;
106:
107: private static final Logger log = Logger.getLogger(
108: LogDomainConstants.WSSC_IMPL_DOMAIN,
109: LogDomainConstants.WSSC_IMPL_DOMAIN_BUNDLE);
110:
111: private static WSTrustElementFactory eleFac = WSTrustElementFactory
112: .newInstance();
113:
114: private static final int DEFAULT_KEY_SIZE = 256;
115: private static final String SC_ASSERTION = "SecureConversationAssertion";
116: private static final String FOR_CANCEL = "For Cancel";
117:
118: private Packet packet = null;
119:
120: /** Creates a new instance of WSSCPlugin */
121: public WSSCPlugin(Configuration config) {
122: this .config = config;
123: }
124:
125: public IssuedTokenContext process(final PolicyAssertion token,
126: final WSDLPort wsdlPort, final WSBinding binding,
127: final Pipe securityPipe, final Marshaller marshaller,
128: final Unmarshaller unmarshaller,
129: final String endPointAddress, final Packet packet,
130: final AddressingVersion addVer) {
131:
132: this .packet = packet;
133:
134: //==============================
135: // Get Required policy assertions
136: //==============================
137: final SecureConversationToken scToken = (SecureConversationToken) token;
138: final AssertionSet assertions = getAssertions(scToken);
139: Trust10 trust10 = null;
140: SymmetricBinding symBinding = null;
141: for (PolicyAssertion policyAssertion : assertions) {
142: if (PolicyUtil.isTrust10(policyAssertion)) {
143: trust10 = (Trust10) policyAssertion;
144: } else if (PolicyUtil.isSymmetricBinding(policyAssertion)) {
145: symBinding = (SymmetricBinding) policyAssertion;
146: }
147: }
148:
149: int skl = DEFAULT_KEY_SIZE;
150: boolean reqClientEntropy = true;
151: if (symBinding != null) {
152: final AlgorithmSuite algoSuite = symBinding
153: .getAlgorithmSuite();
154: skl = algoSuite.getMinSKLAlgorithm();
155: if (skl < 1) {
156: skl = DEFAULT_KEY_SIZE;
157: }
158: if (log.isLoggable(Level.FINE)) {
159: log.log(Level.FINE, LogStringsMessages
160: .WSSC_1006_SYM_BIN_KEYSIZE(skl,
161: this .DEFAULT_KEY_SIZE));
162: }
163: }
164: if (trust10 != null) {
165: final Set trustReqdProps = trust10.getRequiredProperties();
166: reqClientEntropy = trustReqdProps
167: .contains(Constants.REQUIRE_CLIENT_ENTROPY);
168: }
169:
170: //==============================
171: // Create RequestSecurityToken
172: //==============================
173: RequestSecurityToken rst = null;
174: try {
175: rst = createRequestSecurityToken(reqClientEntropy, skl);
176: } catch (WSSecureConversationException ex) {
177: log.log(Level.SEVERE, LogStringsMessages
178: .WSSC_0024_ERROR_CREATING_RST(""), ex);
179: throw new RuntimeException(LogStringsMessages
180: .WSSC_0024_ERROR_CREATING_RST(""), ex);
181: }/* catch (WSTrustException ex){
182: log.log(Level.SEVERE,
183: LogStringsMessages.WSSC_0021_PROBLEM_CREATING_RST_TRUST(), ex);
184: throw new RuntimeException(LogStringsMessages.WSSC_0021_PROBLEM_CREATING_RST_TRUST(), ex);
185: }*/
186:
187: final RequestSecurityTokenResponse rstr = sendRequest(token,
188: wsdlPort, binding, securityPipe, marshaller,
189: unmarshaller, rst,
190: WSSCConstants.REQUEST_SECURITY_CONTEXT_TOKEN_ACTION,
191: endPointAddress, addVer);
192:
193: // Handle the RequestSecurityTokenResponse
194: final IssuedTokenContext context = new IssuedTokenContextImpl();
195: try {
196: processRequestSecurityTokenResponse(rst, rstr, context);
197: } catch (WSSecureConversationException ex) {
198: throw new RuntimeException(ex);
199: }
200: context.setEndpointAddress(endPointAddress);
201:
202: return context;
203: }
204:
205: private AssertionSet getAssertions(
206: final SecureConversationToken scToken) {
207: return scToken.getBootstrapPolicy().getAssertionSet();
208: }
209:
210: public IssuedTokenContext processCancellation(
211: final IssuedTokenContext ctx, final WSDLPort wsdlPort,
212: final WSBinding binding, final Pipe securityPipe,
213: final Marshaller marshaller,
214: final Unmarshaller unmarshaller,
215: final String endPointAddress, final AddressingVersion addVer) {
216:
217: //==============================
218: // Create RequestSecurityToken
219: //==============================
220: RequestSecurityToken rst = null;
221: try {
222: rst = createRequestSecurityTokenForCancel(ctx);
223: } catch (WSSecureConversationException ex) {
224: log.log(Level.SEVERE, LogStringsMessages
225: .WSSC_0024_ERROR_CREATING_RST(FOR_CANCEL), ex);
226: throw new RuntimeException(LogStringsMessages
227: .WSSC_0024_ERROR_CREATING_RST(FOR_CANCEL), ex);
228: }
229:
230: final RequestSecurityTokenResponse rstr = sendRequest(null,
231: wsdlPort, binding, securityPipe, marshaller,
232: unmarshaller, rst,
233: WSSCConstants.CANCEL_SECURITY_CONTEXT_TOKEN_ACTION,
234: endPointAddress, addVer);
235:
236: // Handle the RequestSecurityTokenResponse
237: try {
238: processRequestSecurityTokenResponse(rst, rstr, ctx);
239: } catch (WSSecureConversationException ex) {
240: log.log(Level.SEVERE, LogStringsMessages
241: .WSSC_0020_PROBLEM_CREATING_RSTR(), ex);
242: throw new RuntimeException(LogStringsMessages
243: .WSSC_0020_PROBLEM_CREATING_RSTR(), ex);
244: }
245:
246: return ctx;
247: }
248:
249: private RequestSecurityTokenResponse sendRequest(
250: final PolicyAssertion issuedToken, final WSDLPort wsdlPort,
251: final WSBinding binding, final Pipe securityPipe,
252: final Marshaller marshaller,
253: final Unmarshaller unmarshaller,
254: final RequestSecurityToken rst, final String action,
255: final String endPointAddress, final AddressingVersion addVer) {
256: // Marshaller marshaller;
257: //Unmarshaller unmarshaller;
258:
259: // try {
260: // marshaller = jbCxt.createMarshaller();
261: // unmarshaller = jbCxt.createUnmarshaller();
262: //} catch (JAXBException ex){
263: // log.log(Level.SEVERE,"WSSC0016.problem.mar.unmar", ex);
264: // throw new RuntimeException("Problem creating JAXB Marshaller/Unmarshaller", ex);
265: //}
266:
267: final Message request = Messages.create(marshaller, eleFac
268: .toJAXBElement(rst), binding.getSOAPVersion());
269:
270: // Log Request created
271: if (log.isLoggable(Level.FINE)) {
272: log
273: .log(
274: Level.FINE,
275: LogStringsMessages
276: .WSSC_1009_SEND_REQ_MESSAGE(printMessageAsString(request)));
277: }
278: Packet reqPacket = new Packet(request);
279: if (issuedToken != null) {
280: reqPacket.invocationProperties.put(SC_ASSERTION,
281: issuedToken);
282: }
283: if (packet != null) {
284: for (WSTrustConstants.STS_PROPERTIES stsProperty : WSTrustConstants.STS_PROPERTIES
285: .values()) {
286: reqPacket.invocationProperties.put(stsProperty
287: .toString(), packet.invocationProperties
288: .get(stsProperty.toString()));
289: }
290: }
291:
292: reqPacket.setEndPointAddressString(endPointAddress);
293: if (log.isLoggable(Level.FINE)) {
294: log.log(Level.FINE, LogStringsMessages
295: .WSSC_1008_SET_EP_ADDRESS(endPointAddress));
296: }
297:
298: // Add addressing headers to the message
299: try {
300: reqPacket = addAddressingHeaders(reqPacket, wsdlPort,
301: binding, action, addVer);
302: } catch (WSSecureConversationException ex) {
303: log.log(Level.SEVERE, LogStringsMessages
304: .WSSC_0017_PROBLEM_ADD_ADDRESS_HEADERS(), ex);
305: throw new RuntimeException(LogStringsMessages
306: .WSSC_0017_PROBLEM_ADD_ADDRESS_HEADERS(), ex);
307: }
308:
309: // Ideally this property for enabling FI or not should be available to the pipeline.
310: // As a workaround for now, we
311: // copy the property for the client packet to the reqPacket mananually here.
312: if (packet != null) {
313: reqPacket.contentNegotiation = packet.contentNegotiation;
314: }
315:
316: // Send the message
317: final Packet respPacket = securityPipe.process(reqPacket);
318:
319: // Obtain the RequestSecurtyTokenResponse
320: final Message response = respPacket.getMessage();
321: RequestSecurityTokenResponse rstr = null;
322: if (!response.isFault()) {
323: JAXBElement rstrEle = null;
324: try {
325: rstrEle = (JAXBElement) response
326: .readPayloadAsJAXB(unmarshaller);
327: } catch (JAXBException ex) {
328: log.log(Level.SEVERE, LogStringsMessages
329: .WSSC_0018_ERR_JAXB_RSTR(), ex);
330: throw new RuntimeException(LogStringsMessages
331: .WSSC_0018_ERR_JAXB_RSTR(), ex);
332: }
333: rstr = eleFac.createRSTRFrom(rstrEle);
334: } else {
335: try {
336: // SOAPFaultBuilder builder = SOAPFaultBuilder.create(response);
337: //throw (SOAPFaultException)builder.createException(null, response);
338: throw new SOAPFaultException(response
339: .readAsSOAPMessage().getSOAPBody().getFault());
340: } catch (SOAPException ex) {
341: log.log(Level.SEVERE, LogStringsMessages
342: .WSSC_0022_PROBLEM_CREATING_FAULT(), ex);
343: throw new RuntimeException(LogStringsMessages
344: .WSSC_0022_PROBLEM_CREATING_FAULT(), ex);
345: }
346: }
347:
348: return rstr;
349: }
350:
351: private RequestSecurityToken createRequestSecurityToken(
352: final boolean reqClientEntropy, final int skl)
353: throws WSSecureConversationException {
354:
355: final URI tokenType = URI
356: .create(WSSCConstants.SECURITY_CONTEXT_TOKEN_TYPE);
357: final URI requestType = URI
358: .create(WSTrustConstants.ISSUE_REQUEST);
359: final SecureRandom random = new SecureRandom();
360: final byte[] rawValue = new byte[skl / 8];
361: random.nextBytes(rawValue);
362: final BinarySecret secret = eleFac.createBinarySecret(rawValue,
363: BinarySecret.NONCE_KEY_TYPE);
364: final Entropy entropy = reqClientEntropy ? eleFac
365: .createEntropy(secret) : null;
366:
367: RequestSecurityToken rst = null;
368: try {
369: rst = eleFac.createRSTForIssue(tokenType, requestType,
370: null, null, null, entropy, null);
371: rst.setKeySize(skl);
372: rst.setKeyType(URI.create(WSTrustConstants.SYMMETRIC_KEY));
373: rst.setComputedKeyAlgorithm(URI
374: .create(WSTrustConstants.CK_PSHA1));
375: } catch (WSTrustException ex) {
376: throw new WSSecureConversationException(ex);
377: }
378:
379: return rst;
380: }
381:
382: private RequestSecurityToken createRequestSecurityTokenForCancel(
383: final IssuedTokenContext ctx)
384: throws WSSecureConversationException {
385: URI requestType = null;
386: requestType = URI.create(WSTrustConstants.CANCEL_REQUEST);
387:
388: final CancelTarget target = eleFac
389: .createCancelTarget((SecurityTokenReference) ctx
390: .getUnAttachedSecurityTokenReference());
391: final RequestSecurityToken rst = eleFac.createRSTForCancel(
392: requestType, target);
393:
394: return rst;
395: }
396:
397: private void processRequestSecurityTokenResponse(
398: final RequestSecurityToken rst,
399: final RequestSecurityTokenResponse rstr,
400: final IssuedTokenContext context)
401: throws WSSecureConversationException {
402: final WSSCClientContract contract = WSSCFactory
403: .newWSSCClientContract(config);
404: contract.handleRSTR(rst, rstr, context);
405: }
406:
407: private String printMessageAsString(final Message message) {
408: final StringWriter writer = new StringWriter();
409: final XMLOutputFactory factory = XMLOutputFactory.newInstance();
410: try {
411: final XMLStreamWriter streamWriter = factory
412: .createXMLStreamWriter(writer);
413: message.writeTo(streamWriter);
414: streamWriter.flush();
415: return writer.toString();
416: } catch (XMLStreamException ex) {
417: log.log(Level.SEVERE, LogStringsMessages
418: .WSSC_0025_PROBLEM_PRINTING_MSG(), ex);
419: throw new RuntimeException(LogStringsMessages
420: .WSSC_0025_PROBLEM_PRINTING_MSG(), ex);
421: }
422: }
423:
424: private Packet addAddressingHeaders(final Packet packet,
425: final WSDLPort wsdlPort, final WSBinding binding,
426: final String action, final AddressingVersion addVer)
427: throws WSSecureConversationException {
428: final HeaderList list = packet.getMessage().getHeaders();
429: list.fillRequestAddressingHeaders(packet, addVer, binding
430: .getSOAPVersion(), false, action);
431:
432: return packet;
433: }
434: }
|