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: * NewWSSCPlugin.java
039: *
040: * Created on November 1, 2006, 11:01 PM
041: *
042: * To change this template, choose Tools | Template Manager
043: * and open the template in the editor.
044: */
045:
046: package com.sun.xml.ws.security.secconv;
047:
048: import com.sun.xml.ws.api.message.Message;
049: import com.sun.xml.ws.api.message.Messages;
050: import com.sun.xml.ws.api.message.Packet;
051: import com.sun.xml.ws.api.message.HeaderList;
052: import com.sun.xml.ws.api.WSBinding;
053: import com.sun.xml.ws.api.model.wsdl.WSDLPort;
054: import com.sun.xml.ws.api.pipe.Pipe;
055: import com.sun.xml.ws.api.security.trust.WSTrustException;
056: import com.sun.xml.ws.policy.AssertionSet;
057: import com.sun.xml.ws.policy.NestedPolicy;
058: import com.sun.xml.ws.policy.PolicyAssertion;
059: import com.sun.xml.ws.security.IssuedTokenContext;
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.security.trust.elements.BinarySecret;
070: import com.sun.xml.ws.security.trust.elements.CancelTarget;
071: import com.sun.xml.ws.security.trust.elements.Entropy;
072: import com.sun.xml.ws.security.trust.elements.RequestSecurityToken;
073: import com.sun.xml.ws.security.trust.elements.RequestSecurityTokenResponse;
074: import com.sun.xml.ws.security.trust.elements.str.SecurityTokenReference;
075: import java.net.URI;
076: import java.security.SecureRandom;
077: import java.util.Set;
078: import javax.xml.soap.SOAPException;
079: import javax.xml.ws.soap.SOAPFaultException;
080: import javax.xml.bind.JAXBContext;
081: import javax.xml.bind.JAXBElement;
082: import javax.xml.bind.JAXBException;
083: import javax.xml.bind.Marshaller;
084: import javax.xml.bind.Unmarshaller;
085: import java.util.logging.Level;
086: import java.util.logging.Logger;
087: import com.sun.xml.ws.security.secconv.logging.LogDomainConstants;
088: import com.sun.xml.ws.security.secconv.logging.LogStringsMessages;
089: import java.io.StringWriter;
090: import javax.xml.stream.XMLOutputFactory;
091: import javax.xml.stream.XMLStreamException;
092: import javax.xml.stream.XMLStreamWriter;
093:
094: /**
095: *
096: * @author kumar jayanti
097: */
098: public class NewWSSCPlugin {
099:
100: Configuration config;
101:
102: private static final Logger log = Logger.getLogger(
103: LogDomainConstants.WSSC_IMPL_DOMAIN,
104: LogDomainConstants.WSSC_IMPL_DOMAIN_BUNDLE);
105:
106: private static WSTrustElementFactory eleFac = WSTrustElementFactory
107: .newInstance();
108:
109: private static final int DEFAULT_KEY_SIZE = 256;
110: private static final String SC_ASSERTION = "SecureConversationAssertion";
111: private static final String FOR_ISSUE = "For Issue";
112: private static final String FOR_CANCEL = "For Cancel";
113:
114: /** Creates a new instance of NewWSSCPlugin */
115: public NewWSSCPlugin(Configuration config) {
116: this .config = config;
117: }
118:
119: public RequestSecurityToken createIssueRequest(
120: final PolicyAssertion token) {
121:
122: //==============================
123: // Get Required policy assertions
124: //==============================
125: final SecureConversationToken scToken = (SecureConversationToken) token;
126: final AssertionSet assertions = getAssertions(scToken);
127: Trust10 trust10 = null;
128: SymmetricBinding symBinding = null;
129: for (PolicyAssertion policyAssertion : assertions) {
130: if (PolicyUtil.isTrust10(policyAssertion)) {
131: trust10 = (Trust10) policyAssertion;
132: } else if (PolicyUtil.isSymmetricBinding(policyAssertion)) {
133: symBinding = (SymmetricBinding) policyAssertion;
134: }
135: }
136:
137: int skl = DEFAULT_KEY_SIZE;
138: boolean reqClientEntropy = false;
139: if (symBinding != null) {
140: final AlgorithmSuite algoSuite = symBinding
141: .getAlgorithmSuite();
142: skl = algoSuite.getMinSKLAlgorithm();
143: if (skl < 1) {
144: skl = DEFAULT_KEY_SIZE;
145: }
146: if (log.isLoggable(Level.FINE)) {
147: log.log(Level.FINE, LogStringsMessages
148: .WSSC_1006_SYM_BIN_KEYSIZE(skl,
149: DEFAULT_KEY_SIZE));
150: }
151: }
152: if (trust10 != null) {
153: final Set trustReqdProps = trust10.getRequiredProperties();
154: reqClientEntropy = trustReqdProps
155: .contains(Constants.REQUIRE_CLIENT_ENTROPY);
156: }
157:
158: //==============================
159: // Create RequestSecurityToken
160: //==============================
161: RequestSecurityToken rst = null;
162: try {
163: rst = createRequestSecurityToken(reqClientEntropy, skl);
164: } catch (WSSecureConversationException ex) {
165: log.log(Level.SEVERE, LogStringsMessages
166: .WSSC_0024_ERROR_CREATING_RST(FOR_ISSUE), ex);
167: throw new RuntimeException(LogStringsMessages
168: .WSSC_0024_ERROR_CREATING_RST(FOR_ISSUE), ex);
169: } catch (WSTrustException ex) {
170: log.log(Level.SEVERE, LogStringsMessages
171: .WSSC_0021_PROBLEM_CREATING_RST_TRUST(), ex);
172: throw new RuntimeException(LogStringsMessages
173: .WSSC_0021_PROBLEM_CREATING_RST_TRUST(), ex);
174: }
175:
176: return rst;
177: }
178:
179: public Packet createIssuePacket(final PolicyAssertion token,
180: final RequestSecurityToken rst, final WSDLPort wsdlPort,
181: final WSBinding binding, final JAXBContext jbCxt,
182: final String endPointAddress, final Packet packet) {
183: final Packet ret = createSendRequestPacket(token, wsdlPort,
184: binding, jbCxt, rst,
185: WSSCConstants.REQUEST_SECURITY_CONTEXT_TOKEN_ACTION,
186: endPointAddress, packet);
187:
188: return ret;
189: }
190:
191: public RequestSecurityTokenResponse getRSTR(
192: final JAXBContext jbCxt, final Packet respPacket) {
193: Unmarshaller unmarshaller;
194:
195: try {
196: unmarshaller = jbCxt.createUnmarshaller();
197: } catch (JAXBException ex) {
198: log.log(Level.SEVERE, LogStringsMessages
199: .WSSC_0016_PROBLEM_MAR_UNMAR(), ex);
200: throw new RuntimeException(LogStringsMessages
201: .WSSC_0016_PROBLEM_MAR_UNMAR(), ex);
202: }
203:
204: // Obtain the RequestSecurtyTokenResponse
205: final Message response = respPacket.getMessage();
206: RequestSecurityTokenResponse rstr = null;
207: if (!response.isFault()) {
208: JAXBElement rstrEle = null;
209: try {
210: rstrEle = (JAXBElement) response
211: .readPayloadAsJAXB(unmarshaller);
212: } catch (JAXBException ex) {
213: log.log(Level.SEVERE, LogStringsMessages
214: .WSSC_0018_ERR_JAXB_RSTR(), ex);
215: throw new RuntimeException(LogStringsMessages
216: .WSSC_0018_ERR_JAXB_RSTR(), ex);
217: }
218: rstr = eleFac.createRSTRFrom(rstrEle);
219: } else {
220: try {
221: throw new SOAPFaultException(response
222: .readAsSOAPMessage().getSOAPBody().getFault());
223: } catch (SOAPException ex) {
224: log.log(Level.SEVERE, LogStringsMessages
225: .WSSC_0022_PROBLEM_CREATING_FAULT(), ex);
226: throw new RuntimeException(LogStringsMessages
227: .WSSC_0022_PROBLEM_CREATING_FAULT(), ex);
228: }
229: }
230:
231: return rstr;
232: }
233:
234: public IssuedTokenContext processRSTR(
235: final IssuedTokenContext context,
236: final RequestSecurityToken rst,
237: final RequestSecurityTokenResponse rstr,
238: final String endPointAddress) {
239:
240: // Handle the RequestSecurityTokenResponse
241: //IssuedTokenContext context = new IssuedTokenContextImpl();
242: try {
243: processRequestSecurityTokenResponse(rst, rstr, context);
244: } catch (WSSecureConversationException ex) {
245: log.log(Level.SEVERE, LogStringsMessages
246: .WSSC_0020_PROBLEM_CREATING_RSTR(), ex);
247: throw new RuntimeException(LogStringsMessages
248: .WSSC_0020_PROBLEM_CREATING_RSTR(), ex);
249: }
250: context.setEndpointAddress(endPointAddress);
251: return context;
252: }
253:
254: private AssertionSet getAssertions(
255: final SecureConversationToken scToken) {
256: return scToken.getBootstrapPolicy().getAssertionSet();
257: }
258:
259: public RequestSecurityToken createCancelRequest(
260: final IssuedTokenContext ctx) {
261: //==============================
262: // Create RequestSecurityToken
263: //==============================
264: RequestSecurityToken rst = null;
265: try {
266: rst = createRequestSecurityTokenForCancel(ctx);
267: } catch (WSSecureConversationException ex) {
268: log.log(Level.SEVERE, LogStringsMessages
269: .WSSC_0024_ERROR_CREATING_RST(FOR_CANCEL), ex);
270: throw new RuntimeException(LogStringsMessages
271: .WSSC_0024_ERROR_CREATING_RST(FOR_CANCEL), ex);
272: }
273: return rst;
274: }
275:
276: public Packet createCancelPacket(final RequestSecurityToken rst,
277: final WSDLPort wsdlPort, final WSBinding binding,
278: final JAXBContext jbCxt, final String endPointAddress) {
279: final Packet ret = createSendRequestPacket(null, wsdlPort,
280: binding, jbCxt, rst,
281: WSSCConstants.CANCEL_SECURITY_CONTEXT_TOKEN_ACTION,
282: endPointAddress, null);
283: return ret;
284: }
285:
286: public IssuedTokenContext processCancellation(
287: final IssuedTokenContext ctx, final WSDLPort wsdlPort,
288: final WSBinding binding, final Pipe securityPipe,
289: final JAXBContext jbCxt, final String endPointAddress) {
290:
291: //==============================
292: // Create RequestSecurityToken
293: //==============================
294: RequestSecurityToken rst = null;
295: try {
296: rst = createRequestSecurityTokenForCancel(ctx);
297: } catch (WSSecureConversationException ex) {
298: log.log(Level.SEVERE, LogStringsMessages
299: .WSSC_0024_ERROR_CREATING_RST(FOR_CANCEL), ex);
300: throw new RuntimeException(LogStringsMessages
301: .WSSC_0024_ERROR_CREATING_RST(FOR_CANCEL), ex);
302: }
303:
304: final RequestSecurityTokenResponse rstr = sendRequest(null,
305: wsdlPort, binding, securityPipe, jbCxt, rst,
306: WSSCConstants.CANCEL_SECURITY_CONTEXT_TOKEN_ACTION,
307: endPointAddress, null);
308:
309: // Handle the RequestSecurityTokenResponse
310: try {
311: processRequestSecurityTokenResponse(rst, rstr, ctx);
312: } catch (WSSecureConversationException ex) {
313: log.log(Level.SEVERE, LogStringsMessages
314: .WSSC_0020_PROBLEM_CREATING_RSTR(), ex);
315: throw new RuntimeException(LogStringsMessages
316: .WSSC_0020_PROBLEM_CREATING_RSTR(), ex);
317: }
318:
319: return ctx;
320: }
321:
322: private Packet createSendRequestPacket(
323: final PolicyAssertion issuedToken, final WSDLPort wsdlPort,
324: final WSBinding binding, final JAXBContext jbCxt,
325: final RequestSecurityToken rst, final String action,
326: final String endPointAddress, final Packet packet) {
327: Marshaller marshaller;
328:
329: try {
330: marshaller = jbCxt.createMarshaller();
331: } catch (JAXBException ex) {
332: log.log(Level.SEVERE, LogStringsMessages
333: .WSSC_0016_PROBLEM_MAR_UNMAR(), ex);
334: throw new RuntimeException(LogStringsMessages
335: .WSSC_0016_PROBLEM_MAR_UNMAR(), ex);
336: }
337:
338: final Message request = Messages.create(marshaller, eleFac
339: .toJAXBElement(rst), binding.getSOAPVersion());
340:
341: // Log Request created
342: if (log.isLoggable(Level.FINE)) {
343: log
344: .log(
345: Level.FINE,
346: LogStringsMessages
347: .WSSC_1009_SEND_REQ_MESSAGE(printMessageAsString(request)));
348: }
349: Packet reqPacket = new Packet(request);
350: if (issuedToken != null) {
351: reqPacket.invocationProperties.put(SC_ASSERTION,
352: issuedToken);
353: }
354: if (packet != null) {
355: for (WSTrustConstants.STS_PROPERTIES stsProperty : WSTrustConstants.STS_PROPERTIES
356: .values()) {
357: reqPacket.invocationProperties.put(stsProperty
358: .toString(), packet.invocationProperties
359: .get(stsProperty.toString()));
360: }
361: }
362:
363: reqPacket.setEndPointAddressString(endPointAddress);
364: if (log.isLoggable(Level.FINE)) {
365: log.log(Level.FINE, LogStringsMessages
366: .WSSC_1008_SET_EP_ADDRESS(endPointAddress));
367: }
368:
369: // Add addressing headers to the message
370: try {
371: reqPacket = addAddressingHeaders(reqPacket, wsdlPort,
372: binding, action);
373: } catch (WSSecureConversationException ex) {
374: log.log(Level.SEVERE, LogStringsMessages
375: .WSSC_0017_PROBLEM_ADD_ADDRESS_HEADERS(), ex);
376: throw new RuntimeException(LogStringsMessages
377: .WSSC_0017_PROBLEM_ADD_ADDRESS_HEADERS(), ex);
378: }
379:
380: // Ideally this property for enabling FI or not should be available to the pipeline.
381: // As a workaround for now, we
382: // copy the property for the client packet to the reqPacket mananually here.
383: if (packet != null) {
384: reqPacket.contentNegotiation = packet.contentNegotiation;
385: }
386:
387: return reqPacket;
388: }
389:
390: private RequestSecurityTokenResponse sendRequest(
391: final PolicyAssertion issuedToken, final WSDLPort wsdlPort,
392: final WSBinding binding, final Pipe securityPipe,
393: final JAXBContext jbCxt, final RequestSecurityToken rst,
394: final String action, final String endPointAddress,
395: final Packet packet) {
396: Marshaller marshaller;
397: Unmarshaller unmarshaller;
398:
399: try {
400: marshaller = jbCxt.createMarshaller();
401: unmarshaller = jbCxt.createUnmarshaller();
402: } catch (JAXBException ex) {
403: log.log(Level.SEVERE, LogStringsMessages
404: .WSSC_0016_PROBLEM_MAR_UNMAR(), ex);
405: throw new RuntimeException(LogStringsMessages
406: .WSSC_0016_PROBLEM_MAR_UNMAR(), ex);
407: }
408:
409: final Message request = Messages.create(marshaller, eleFac
410: .toJAXBElement(rst), binding.getSOAPVersion());
411:
412: // Log Request created
413: if (log.isLoggable(Level.FINE)) {
414: log
415: .log(
416: Level.FINE,
417: LogStringsMessages
418: .WSSC_1009_SEND_REQ_MESSAGE(printMessageAsString(request)));
419: }
420: Packet reqPacket = new Packet(request);
421: if (issuedToken != null) {
422: reqPacket.invocationProperties.put(SC_ASSERTION,
423: issuedToken);
424: }
425: if (packet != null) {
426: for (WSTrustConstants.STS_PROPERTIES stsProperty : WSTrustConstants.STS_PROPERTIES
427: .values()) {
428: reqPacket.invocationProperties.put(stsProperty
429: .toString(), packet.invocationProperties
430: .get(stsProperty.toString()));
431: }
432: }
433:
434: reqPacket.setEndPointAddressString(endPointAddress);
435: if (log.isLoggable(Level.FINE)) {
436: log.log(Level.FINE, LogStringsMessages
437: .WSSC_1008_SET_EP_ADDRESS(endPointAddress));
438: }
439: // Add addressing headers to the message
440: try {
441: reqPacket = addAddressingHeaders(reqPacket, wsdlPort,
442: binding, action);
443: } catch (WSSecureConversationException ex) {
444: log.log(Level.SEVERE, LogStringsMessages
445: .WSSC_0017_PROBLEM_ADD_ADDRESS_HEADERS(), ex);
446: throw new RuntimeException(LogStringsMessages
447: .WSSC_0017_PROBLEM_ADD_ADDRESS_HEADERS(), ex);
448: }
449:
450: // Ideally this property for enabling FI or not should be available to the pipeline.
451: // As a workaround for now, we
452: // copy the property for the client packet to the reqPacket mananually here.
453: if (packet != null) {
454: reqPacket.contentNegotiation = packet.contentNegotiation;
455: }
456:
457: // Send the message
458: final Packet respPacket = securityPipe.process(reqPacket);
459:
460: // Obtain the RequestSecurtyTokenResponse
461: final Message response = respPacket.getMessage();
462: RequestSecurityTokenResponse rstr = null;
463: if (!response.isFault()) {
464: JAXBElement rstrEle = null;
465: try {
466: rstrEle = (JAXBElement) response
467: .readPayloadAsJAXB(unmarshaller);
468: } catch (JAXBException ex) {
469: log.log(Level.SEVERE, LogStringsMessages
470: .WSSC_0018_ERR_JAXB_RSTR(), ex);
471: throw new RuntimeException(LogStringsMessages
472: .WSSC_0018_ERR_JAXB_RSTR(), ex);
473: }
474: rstr = eleFac.createRSTRFrom(rstrEle);
475: } else {
476: try {
477: // SOAPFaultBuilder builder = SOAPFaultBuilder.create(response);
478: //throw (SOAPFaultException)builder.createException(null, response);
479: throw new SOAPFaultException(response
480: .readAsSOAPMessage().getSOAPBody().getFault());
481: } catch (SOAPException ex) {
482: log.log(Level.SEVERE, LogStringsMessages
483: .WSSC_0022_PROBLEM_CREATING_FAULT(), ex);
484: throw new RuntimeException(LogStringsMessages
485: .WSSC_0022_PROBLEM_CREATING_FAULT(), ex);
486: }
487: }
488:
489: return rstr;
490: }
491:
492: private RequestSecurityToken createRequestSecurityToken(
493: final boolean reqClientEntropy, final int skl)
494: throws WSSecureConversationException, WSTrustException {
495:
496: final URI tokenType = URI
497: .create(WSSCConstants.SECURITY_CONTEXT_TOKEN_TYPE);
498: final URI requestType = URI
499: .create(WSTrustConstants.ISSUE_REQUEST);
500: final SecureRandom random = new SecureRandom();
501: final byte[] rawValue = new byte[skl / 8];
502: random.nextBytes(rawValue);
503: final BinarySecret secret = eleFac.createBinarySecret(rawValue,
504: BinarySecret.NONCE_KEY_TYPE);
505: final Entropy entropy = reqClientEntropy ? eleFac
506: .createEntropy(secret) : null;
507:
508: RequestSecurityToken rst = null;
509:
510: rst = eleFac.createRSTForIssue(tokenType, requestType, null,
511: null, null, entropy, null);
512:
513: rst.setKeySize(skl);
514: rst.setKeyType(URI.create(WSTrustConstants.SYMMETRIC_KEY));
515: rst.setComputedKeyAlgorithm(URI
516: .create(WSTrustConstants.CK_PSHA1));
517:
518: return rst;
519: }
520:
521: private RequestSecurityToken createRequestSecurityTokenForCancel(
522: final IssuedTokenContext ctx)
523: throws WSSecureConversationException {
524: URI requestType = null;
525: requestType = URI.create(WSTrustConstants.CANCEL_REQUEST);
526:
527: final CancelTarget target = eleFac
528: .createCancelTarget((SecurityTokenReference) ctx
529: .getUnAttachedSecurityTokenReference());
530: final RequestSecurityToken rst = eleFac.createRSTForCancel(
531: requestType, target);
532:
533: return rst;
534: }
535:
536: private void processRequestSecurityTokenResponse(
537: final RequestSecurityToken rst,
538: final RequestSecurityTokenResponse rstr,
539: final IssuedTokenContext context)
540: throws WSSecureConversationException {
541: final WSSCClientContract contract = WSSCFactory
542: .newWSSCClientContract(config);
543: contract.handleRSTR(rst, rstr, context);
544: }
545:
546: private String printMessageAsString(final Message message) {
547: final StringWriter writer = new StringWriter();
548: final XMLOutputFactory factory = XMLOutputFactory.newInstance();
549: try {
550: final XMLStreamWriter streamWriter = factory
551: .createXMLStreamWriter(writer);
552: message.writeTo(streamWriter);
553: streamWriter.flush();
554: return writer.toString();
555: } catch (XMLStreamException ex) {
556: log.log(Level.SEVERE, LogStringsMessages
557: .WSSC_0025_PROBLEM_PRINTING_MSG(), ex);
558: throw new RuntimeException(LogStringsMessages
559: .WSSC_0025_PROBLEM_PRINTING_MSG(), ex);
560: }
561: }
562:
563: private Packet addAddressingHeaders(final Packet packet,
564: final WSDLPort wsdlPort, final WSBinding binding,
565: final String action) throws WSSecureConversationException {
566: final HeaderList headers = packet.getMessage().getHeaders();
567: headers.fillRequestAddressingHeaders(packet, binding
568: .getAddressingVersion(), binding.getSOAPVersion(),
569: false, action);
570:
571: return packet;
572: }
573: }
|