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.wss.jaxws.impl;
038:
039: import com.sun.xml.ws.api.model.wsdl.WSDLFault;
040: import com.sun.xml.ws.security.impl.policy.Constants;
041: import java.util.ArrayList;
042: import java.util.Iterator;
043: import java.util.Enumeration;
044: import java.net.URI;
045: import java.util.List;
046: import java.util.Set;
047: import javax.xml.namespace.QName;
048: import com.sun.xml.ws.api.message.Packet;
049: import com.sun.xml.ws.api.message.Message;
050: import com.sun.xml.ws.api.message.Messages;
051: import com.sun.xml.ws.api.message.HeaderList;
052: import com.sun.xml.ws.api.model.wsdl.WSDLBoundOperation;
053: import com.sun.xml.ws.api.model.wsdl.WSDLOperation;
054: import com.sun.xml.ws.api.pipe.Pipe;
055: import com.sun.xml.ws.api.pipe.PipeCloner;
056: import com.sun.xml.ws.policy.Policy;
057: import com.sun.xml.ws.policy.PolicyException;
058: import com.sun.xml.ws.assembler.ClientPipeConfiguration;
059: import com.sun.xml.ws.security.impl.policyconv.SecurityPolicyHolder;
060: import com.sun.xml.ws.security.trust.WSTrustConstants;
061: import javax.xml.soap.SOAPException;
062: import javax.xml.soap.SOAPFault;
063: import javax.xml.soap.SOAPMessage;
064: import javax.xml.ws.WebServiceException;
065: import com.sun.xml.ws.security.IssuedTokenContext;
066: import com.sun.xml.ws.security.SecurityContextToken;
067: import com.sun.xml.wss.XWSSecurityException;
068: import com.sun.xml.wss.ProcessingContext;
069: import com.sun.xml.ws.security.trust.elements.str.SecurityTokenReference;
070: import com.sun.xml.ws.security.secconv.WSSecureConversationException;
071: import com.sun.xml.ws.security.trust.WSTrustFactory;
072: import com.sun.xml.ws.security.trust.WSTrustElementFactory;
073: import com.sun.xml.ws.security.trust.TrustPlugin;
074: import com.sun.xml.ws.security.secconv.WSSCFactory;
075: import com.sun.xml.ws.security.secconv.WSSCPlugin;
076: import com.sun.xml.ws.security.policy.Token;
077: import javax.security.auth.callback.CallbackHandler;
078: import javax.xml.bind.JAXBElement;
079: import com.sun.xml.wss.impl.misc.DefaultSecurityEnvironmentImpl;
080: import com.sun.xml.ws.policy.PolicyAssertion;
081: import com.sun.xml.ws.security.secconv.SecureConversationInitiator;
082: import javax.xml.ws.soap.SOAPFaultException;
083: import com.sun.xml.wss.impl.filter.DumpFilter;
084: import com.sun.xml.wss.impl.misc.DefaultCallbackHandler;
085: import java.util.Properties;
086: import static com.sun.xml.wss.jaxws.impl.Constants.SC_ASSERTION;
087: import static com.sun.xml.wss.jaxws.impl.Constants.OPERATION_SCOPE;
088: import static com.sun.xml.wss.jaxws.impl.Constants.EMPTY_LIST;
089: import static com.sun.xml.wss.jaxws.impl.Constants.SUN_WSS_SECURITY_CLIENT_POLICY_NS;
090:
091: import java.util.logging.Level;
092: import com.sun.xml.wss.jaxws.impl.logging.LogStringsMessages;
093:
094: /**
095: *
096: * @author Vbkumar.Jayanti@Sun.COM, K.Venugopal@sun.com
097: */
098: public class SecurityClientPipe extends SecurityPipeBase implements
099: SecureConversationInitiator {
100:
101: // Plugin instances for Trust and SecureConversation invocation
102: private static TrustPlugin trustPlugin = WSTrustFactory
103: .newTrustPlugin(null);
104: private static WSSCPlugin scPlugin = WSSCFactory.newSCPlugin(null);
105: private Set trustConfig = null;
106:
107: // Creates a new instance of SecurityClientPipe
108: public SecurityClientPipe(ClientPipeConfiguration config,
109: Pipe nextPipe) {
110: super (config, nextPipe);
111:
112: CallbackHandler handler = null;
113: try {
114: Iterator it = outMessagePolicyMap.values().iterator();
115: SecurityPolicyHolder holder = (SecurityPolicyHolder) it
116: .next();
117: Set configAssertions = holder
118: .getConfigAssertions(SUN_WSS_SECURITY_CLIENT_POLICY_NS);
119: trustConfig = holder
120: .getConfigAssertions(Constants.SUN_TRUST_CLIENT_SECURITY_POLICY_NS);
121: Properties props = new Properties();
122: handler = configureClientHandler(configAssertions, props);
123: secEnv = new DefaultSecurityEnvironmentImpl(handler, props);
124: } catch (Exception e) {
125: log
126: .log(
127: Level.SEVERE,
128: LogStringsMessages
129: .WSSPIPE_0023_ERROR_CREATING_NEW_INSTANCE_SEC_CLIENT_PIPE(),
130: e);
131: throw new RuntimeException(
132: LogStringsMessages
133: .WSSPIPE_0023_ERROR_CREATING_NEW_INSTANCE_SEC_CLIENT_PIPE(),
134: e);
135: }
136:
137: }
138:
139: // copy constructor
140: protected SecurityClientPipe(SecurityClientPipe that) {
141: super (that);
142: trustConfig = that.trustConfig;
143: }
144:
145: public Packet process(Packet packet) {
146:
147: // Add Action header to trust message
148: boolean isTrustMsg = false;
149: if ("true".equals(packet.invocationProperties
150: .get(WSTrustConstants.IS_TRUST_MESSAGE))) {
151: isTrustMsg = true;
152: String action = (String) packet.invocationProperties
153: .get(WSTrustConstants.REQUEST_SECURITY_TOKEN_ISSUE_ACTION);
154: HeaderList headers = packet.getMessage().getHeaders();
155: headers.fillRequestAddressingHeaders(packet, addVer,
156: soapVersion, false, action);
157: }
158:
159: // keep the message
160: Message msg = packet.getMessage();
161:
162: boolean isSCMessage = isSCMessage(packet);
163:
164: if (!isSCMessage && !isSCCancel(packet)) {
165: // this is an application message
166: // initialize any secure-conversation sessions for this message
167: invokeSCPlugin(packet);
168: }
169:
170: // invoke the Trust Plugin if necessary
171: invokeTrustPlugin(packet, isSCMessage);
172:
173: //---------------OUTBOUND SECURITY PROCESSING----------
174: ProcessingContext ctx = initializeOutgoingProcessingContext(
175: packet, isSCMessage);
176:
177: try {
178: if (!optimized) {
179: if (!isSCMessage) {
180: cacheOperation(msg);
181: }
182: SOAPMessage soapMessage = msg.readAsSOAPMessage();
183: soapMessage = secureOutboundMessage(soapMessage, ctx);
184: msg = Messages.create(soapMessage);
185: } else {
186: msg = secureOutboundMessage(msg, ctx);
187: }
188: } catch (SOAPException se) {
189: log.log(Level.SEVERE, LogStringsMessages
190: .WSSPIPE_0024_ERROR_SECURING_OUTBOUND_MSG(), se);
191: throw new WebServiceException(LogStringsMessages
192: .WSSPIPE_0024_ERROR_SECURING_OUTBOUND_MSG(), se);
193: }
194:
195: packet.setMessage(msg);
196:
197: //--------INVOKE NEXT PIPE------------
198: Packet ret = nextPipe.process(packet);
199: // Could be OneWay
200: if (ret == null || ret.getMessage() == null) {
201: return ret;
202: }
203:
204: /* TODO:this piece of code present since payload should be read once*/
205: if (!optimized) {
206: try {
207: SOAPMessage sm = ret.getMessage().readAsSOAPMessage();
208: Message newMsg = Messages.create(sm);
209: ret.setMessage(newMsg);
210: } catch (SOAPException ex) {
211: log.log(Level.SEVERE, LogStringsMessages
212: .WSSPIPE_0005_PROBLEM_PROC_SOAP_MESSAGE(), ex);
213: throw new WebServiceException(LogStringsMessages
214: .WSSPIPE_0005_PROBLEM_PROC_SOAP_MESSAGE(), ex);
215: }
216: }
217: //---------------INBOUND SECURITY VERIFICATION----------
218:
219: ctx = initializeInboundProcessingContext(ret);
220: ctx.setExtraneousProperty(ctx.OPERATION_RESOLVER,
221: new PolicyResolverImpl(inMessagePolicyMap,
222: inProtocolPM, cachedOperation, pipeConfig,
223: addVer, true));
224:
225: try {
226: msg = ret.getMessage();
227: // Could be OneWay
228: if (msg == null) {
229: return ret;
230: }
231:
232: if (!optimized) {
233: SOAPMessage soapMessage = msg.readAsSOAPMessage();
234: soapMessage = verifyInboundMessage(soapMessage, ctx);
235: if (msg.isFault()) {
236: if (debug) {
237: DumpFilter.process(ctx);
238: }
239: SOAPFault fault = soapMessage.getSOAPBody()
240: .getFault();
241: //log.log(Level.SEVERE,
242: // LogStringsMessages.WSSPIPE_0034_FAULTY_RESPONSE_MSG(fault));
243: throw new SOAPFaultException(fault);
244: }
245: msg = Messages.create(soapMessage);
246: } else {
247: msg = verifyInboundMessage(msg, ctx);
248: }
249: } catch (XWSSecurityException xwse) {
250: log.log(Level.SEVERE, LogStringsMessages
251: .WSSPIPE_0025_ERROR_VERIFY_INBOUND_MSG(), xwse);
252: throw new WebServiceException(LogStringsMessages
253: .WSSPIPE_0025_ERROR_VERIFY_INBOUND_MSG(),
254: getSOAPFaultException(xwse));
255: } catch (SOAPException se) {
256: log.log(Level.SEVERE, LogStringsMessages
257: .WSSPIPE_0025_ERROR_VERIFY_INBOUND_MSG(), se);
258: throw new WebServiceException(LogStringsMessages
259: .WSSPIPE_0025_ERROR_VERIFY_INBOUND_MSG(), se);
260: }
261: resetCachedOperation();
262: ret.setMessage(msg);
263:
264: if (isTrustMsg) {
265: //String action = getAction(ret);
266: getAction(ret);
267: }
268:
269: return ret;
270: }
271:
272: private void invokeSCPlugin(Packet packet) {
273:
274: // get the secure conversation policies pertaining to this operation
275: List<PolicyAssertion> policies = getOutBoundSCP(packet
276: .getMessage());
277:
278: for (PolicyAssertion scAssertion : policies) {
279: Token scToken = (Token) scAssertion;
280: if (issuedTokenContextMap.get(scToken.getTokenId()) == null) {
281:
282: IssuedTokenContext ctx = scPlugin.process(scAssertion,
283: pipeConfig.getWSDLModel(), pipeConfig
284: .getBinding(), this , marshaller,
285: unmarshaller,
286: packet.endpointAddress.toString(), packet,
287: addVer);
288: issuedTokenContextMap.put(((Token) scAssertion)
289: .getTokenId(), ctx);
290: }
291: }
292: }
293:
294: // returns a list of IssuedTokenPolicy Assertions contained in the
295: // service policy
296: protected List<PolicyAssertion> getIssuedTokenPolicies(
297: Packet packet, String scope) {
298: if (outMessagePolicyMap == null) {
299: return new ArrayList<PolicyAssertion>();
300: }
301:
302: WSDLBoundOperation operation = null;
303: if (isTrustMessage(packet)) {
304: operation = getWSDLOpFromAction(packet, false);
305: } else {
306: operation = getOperation(packet.getMessage());
307: }
308:
309: SecurityPolicyHolder sph = (SecurityPolicyHolder) outMessagePolicyMap
310: .get(operation);
311: if (sph == null) {
312: return EMPTY_LIST;
313: }
314: return sph.getIssuedTokens();
315: }
316:
317: public JAXBElement startSecureConversation(Packet packet)
318: throws WSSecureConversationException {
319:
320: List toks = getOutBoundSCP(packet.getMessage());
321: if (toks.isEmpty()) {
322: if (log.isLoggable(Level.FINE)) {
323: log.log(Level.FINE, LogStringsMessages
324: .WSSPIPE_0026_NO_POLICY_FOUND_FOR_SC());
325: }
326: //throw new WSSecureConversationException(LogStringsMessages.WSSPIPE_0026_NO_POLICY_FOUND_FOR_SC());
327: return null;
328: }
329: //Note: Assuming only one SC assertion
330: Token tok = (Token) toks.get(0);
331: IssuedTokenContext ctx = (IssuedTokenContext) issuedTokenContextMap
332: .get(tok.getTokenId());
333:
334: if (ctx == null) {
335: ctx = scPlugin.process((PolicyAssertion) tok, pipeConfig
336: .getWSDLModel(), pipeConfig.getBinding(), this ,
337: marshaller, unmarshaller, packet.endpointAddress
338: .toString(), packet, addVer);
339: ctx.setEndpointAddress(packet.endpointAddress.toString());
340: issuedTokenContextMap.put(((Token) tok).getTokenId(), ctx);
341: }
342:
343: SecurityTokenReference str = (SecurityTokenReference) ctx
344: .getUnAttachedSecurityTokenReference();
345:
346: return WSTrustElementFactory.newInstance().toJAXBElement(str);
347: }
348:
349: private void cancelSecurityContextToken() {
350: Enumeration keys = issuedTokenContextMap.keys();
351: while (keys.hasMoreElements()) {
352: String id = (String) keys.nextElement();
353: IssuedTokenContext ctx = (IssuedTokenContext) issuedTokenContextMap
354: .get(id);
355:
356: if (ctx.getSecurityToken() instanceof SecurityContextToken) {
357: ctx = scPlugin.processCancellation(ctx, pipeConfig
358: .getWSDLModel(), pipeConfig.getBinding(), this ,
359: marshaller, unmarshaller, ctx
360: .getEndpointAddress(), addVer);
361: issuedTokenContextMap.remove(id);
362: }
363: }
364: }
365:
366: public void preDestroy() {
367: cancelSecurityContextToken();
368: if (nextPipe != null) {
369: nextPipe.preDestroy();
370: }
371: issuedTokenContextMap.clear();
372: }
373:
374: public Pipe copy(PipeCloner cloner) {
375: Pipe clonedNextPipe = cloner.copy(nextPipe);
376: Pipe copied = new SecurityClientPipe(this );
377: ((SecurityClientPipe) copied).setNextPipe(clonedNextPipe);
378: cloner.add(this , copied);
379: return copied;
380: }
381:
382: private void invokeTrustPlugin(Packet packet, boolean isSCMessage) {
383:
384: List<PolicyAssertion> policies = null;
385:
386: if (isSCMessage) {
387: Token scToken = (Token) packet.invocationProperties
388: .get(SC_ASSERTION);
389: policies = getIssuedTokenPoliciesFromBootstrapPolicy(scToken);
390: } else {
391: policies = getIssuedTokenPolicies(packet, OPERATION_SCOPE);
392: }
393:
394: PolicyAssertion preSetSTSAssertion = null;
395: URI stsEP = null;
396: URI wsdlLocation = null;
397: QName serviceName = null;
398: QName portName = null;
399: if (trustConfig != null) {
400: Iterator it = trustConfig.iterator();
401: while (it != null && it.hasNext()) {
402: preSetSTSAssertion = (PolicyAssertion) it.next();
403: }
404: //serviceName = (QName)packet.invocationProperties.get(WSTrustConstants.PROPERTY_SERVICE_NAME);
405: //portName = (QName)packet.invocationProperties.get(WSTrustConstants.PROPERTY_PORT_NAME);
406: }
407:
408: for (PolicyAssertion issuedTokenAssertion : policies) {
409: IssuedTokenContext ctx = trustPlugin.process(
410: issuedTokenAssertion, preSetSTSAssertion,
411: packet.endpointAddress.toString());
412: issuedTokenContextMap.put(((Token) issuedTokenAssertion)
413: .getTokenId(), ctx);
414: }
415: }
416:
417: protected SecurityPolicyHolder addOutgoingMP(
418: WSDLBoundOperation operation, Policy policy)
419: throws PolicyException {
420:
421: SecurityPolicyHolder sph = constructPolicyHolder(policy, false,
422: false);
423: outMessagePolicyMap.put(operation, sph);
424: return sph;
425: }
426:
427: protected SecurityPolicyHolder addIncomingMP(
428: WSDLBoundOperation operation, Policy policy)
429: throws PolicyException {
430:
431: SecurityPolicyHolder sph = constructPolicyHolder(policy, false,
432: true);
433: inMessagePolicyMap.put(operation, sph);
434: return sph;
435: }
436:
437: protected void addIncomingProtocolPolicy(Policy effectivePolicy,
438: String protocol) throws PolicyException {
439: inProtocolPM.put(protocol, constructPolicyHolder(
440: effectivePolicy, false, true, true));
441: }
442:
443: protected void addOutgoingProtocolPolicy(Policy effectivePolicy,
444: String protocol) throws PolicyException {
445: outProtocolPM.put(protocol, constructPolicyHolder(
446: effectivePolicy, false, false, true));
447: }
448:
449: protected void addIncomingFaultPolicy(Policy effectivePolicy,
450: SecurityPolicyHolder sph, WSDLFault fault)
451: throws PolicyException {
452: SecurityPolicyHolder faultPH = constructPolicyHolder(
453: effectivePolicy, false, true);
454: sph.addFaultPolicy(fault, faultPH);
455: }
456:
457: protected void addOutgoingFaultPolicy(Policy effectivePolicy,
458: SecurityPolicyHolder sph, WSDLFault fault)
459: throws PolicyException {
460: SecurityPolicyHolder faultPH = constructPolicyHolder(
461: effectivePolicy, false, false);
462: sph.addFaultPolicy(fault, faultPH);
463: }
464:
465: protected String getAction(WSDLOperation operation,
466: boolean inComming) {
467: if (!inComming) {
468: return operation.getInput().getAction();
469: } else {
470: return operation.getOutput().getAction();
471: }
472: }
473:
474: //TODO use constants here
475: private CallbackHandler configureClientHandler(
476: Set configAssertions, Properties props) {
477: //Properties props = new Properties();
478: String ret = populateConfigProperties(configAssertions, props);
479: try {
480: if (ret != null) {
481: Class handler = loadClass(ret);
482: Object obj = handler.newInstance();
483: if (!(obj instanceof CallbackHandler)) {
484: log
485: .log(
486: Level.SEVERE,
487: LogStringsMessages
488: .WSSPIPE_0033_INVALID_CALLBACK_HANDLER_CLASS(ret));
489: throw new RuntimeException(
490: LogStringsMessages
491: .WSSPIPE_0033_INVALID_CALLBACK_HANDLER_CLASS(ret));
492: }
493: return (CallbackHandler) obj;
494: }
495: return new DefaultCallbackHandler("client", props);
496: } catch (Exception e) {
497: log.log(Level.SEVERE, LogStringsMessages
498: .WSSPIPE_0027_ERROR_CONFIGURE_CLIENT_HANDLER(), e);
499: throw new RuntimeException(LogStringsMessages
500: .WSSPIPE_0027_ERROR_CONFIGURE_CLIENT_HANDLER(), e);
501: }
502: }
503:
504: }
|