001: /*
002: * XWSSClientPipe.java
003: *
004: * Created on October 26, 2006, 12:53 PM
005: *
006: * To change this template, choose Tools | Template Manager
007: * and open the template in the editor.
008: */
009:
010: package com.sun.xml.xwss;
011:
012: import com.sun.xml.ws.api.SOAPVersion;
013: import com.sun.xml.ws.api.WSBinding;
014: import com.sun.xml.ws.api.WSService;
015: import com.sun.xml.ws.api.message.Messages;
016: import com.sun.xml.ws.api.message.Packet;
017: import com.sun.xml.ws.api.model.wsdl.WSDLBoundOperation;
018: import com.sun.xml.ws.api.model.wsdl.WSDLPort;
019: import com.sun.xml.ws.api.pipe.Pipe;
020: import com.sun.xml.ws.api.pipe.PipeCloner;
021: import com.sun.xml.wss.ProcessingContext;
022: import com.sun.xml.wss.XWSSecurityException;
023: import com.sun.xml.wss.impl.MessageConstants;
024: import com.sun.xml.wss.impl.PolicyTypeUtil;
025: import com.sun.xml.wss.impl.PolicyViolationException;
026: import com.sun.xml.wss.impl.ProcessingContextImpl;
027: import com.sun.xml.wss.impl.SecurableSoapMessage;
028: import com.sun.xml.wss.impl.SecurityAnnotator;
029: import com.sun.xml.wss.impl.SecurityRecipient;
030: import com.sun.xml.wss.impl.WssSoapFaultException;
031: import com.sun.xml.wss.impl.XWSSecurityRuntimeException;
032: import com.sun.xml.wss.impl.config.ApplicationSecurityConfiguration;
033: import com.sun.xml.wss.impl.config.DeclarativeSecurityConfiguration;
034: import com.sun.xml.wss.impl.configuration.StaticApplicationContext;
035: import com.sun.xml.wss.impl.misc.SecurityUtil;
036: import com.sun.xml.wss.impl.policy.SecurityPolicy;
037: import java.net.URL;
038: import javax.xml.namespace.QName;
039: import javax.xml.soap.MessageFactory;
040: import javax.xml.soap.SOAPBody;
041: import javax.xml.soap.SOAPConstants;
042: import javax.xml.soap.SOAPException;
043: import javax.xml.soap.SOAPFactory;
044: import javax.xml.soap.SOAPFault;
045: import javax.xml.soap.SOAPMessage;
046: import javax.xml.ws.WebServiceException;
047: import javax.xml.ws.soap.SOAPFaultException;
048: import org.w3c.dom.Node;
049:
050: /**
051: * This pipe is used to handle XWSS 2.0 Style Message Security using
052: * Security Configuration files
053: * @author kumar.jayanti
054: */
055: public class XWSSClientPipe implements Pipe {
056:
057: protected Pipe nextPipe = null;
058: protected WSDLPort port = null;
059: protected WSService service = null;
060: protected WSBinding binding = null;
061:
062: protected SOAPFactory soapFactory = null;
063: protected MessageFactory messageFactory = null;
064: protected SOAPVersion soapVersion = null;
065: protected boolean isSOAP12 = false;
066:
067: private static final String MESSAGE_SECURITY_CONFIGURATION = SecurityConfiguration.MESSAGE_SECURITY_CONFIGURATION;
068:
069: private static final String CONTEXT_WSDL_OPERATION = "com.sun.xml.ws.wsdl.operation";
070:
071: /** Creates a new instance of XWSSClientPipe */
072: public XWSSClientPipe(WSDLPort prt, WSService svc, WSBinding bnd,
073: Pipe nextP) {
074:
075: nextPipe = nextP;
076: port = prt;
077: service = svc;
078: binding = bnd;
079:
080: soapVersion = bnd.getSOAPVersion();
081: isSOAP12 = (soapVersion == SOAPVersion.SOAP_12) ? true : false;
082: soapFactory = soapVersion.saajSoapFactory;
083: messageFactory = soapVersion.saajMessageFactory;
084:
085: }
086:
087: public XWSSClientPipe(XWSSClientPipe that) {
088:
089: this .nextPipe = that.nextPipe;
090: this .binding = that.binding;
091: this .port = that.port;
092: this .service = that.service;
093: this .soapFactory = that.soapFactory;
094: this .messageFactory = that.messageFactory;
095: this .soapVersion = that.soapVersion;
096: this .isSOAP12 = that.isSOAP12;
097:
098: }
099:
100: public Packet process(Packet packet) {
101: SecurityConfiguration sConfig = (SecurityConfiguration) packet.invocationProperties
102: .get(MESSAGE_SECURITY_CONFIGURATION);
103:
104: if (sConfig == null) {
105: //No Security case here...
106: //now look for "client_security_config.xml file from META-INF/ classpath"
107: String configUrl = "META-INF/client_security_config.xml";
108: URL url = SecurityUtil.loadFromClasspath(configUrl);
109: if (url != null) {
110: try {
111: sConfig = new SecurityConfiguration(url);
112: packet.invocationProperties.put(
113: MESSAGE_SECURITY_CONFIGURATION, sConfig);
114: } catch (XWSSecurityException e) {
115: throw new XWSSecurityRuntimeException(e);
116: }
117: } else {
118: return nextPipe.process(packet);
119: }
120: }
121:
122: Packet ret = secureRequest(packet);
123: ret = nextPipe.process(ret);
124: //could be one-way
125: if (ret == null || ret.getMessage() == null) {
126: return ret;
127: }
128: return validateResponse(ret);
129: }
130:
131: public void preDestroy() {
132: }
133:
134: public Pipe copy(PipeCloner pipeCloner) {
135: Pipe clonedNextPipe = null;
136: if (nextPipe != null) {
137: clonedNextPipe = pipeCloner.copy(nextPipe);
138: }
139: Pipe copied = new XWSSClientPipe(this );
140: ((XWSSClientPipe) copied).setNextPipe(clonedNextPipe);
141: pipeCloner.add(this , copied);
142: return copied;
143: }
144:
145: public void setNextPipe(Pipe pipe) {
146: nextPipe = pipe;
147: }
148:
149: // client side incoming request handling code
150: public Packet validateResponse(Packet packet) {
151: try {
152: SecurityConfiguration sConfig = (SecurityConfiguration) packet.invocationProperties
153: .get(MESSAGE_SECURITY_CONFIGURATION);
154:
155: if (sConfig == null) {
156: return packet;
157: }
158: SOAPMessage message = null;
159: try {
160: message = packet.getMessage().readAsSOAPMessage();
161: } catch (SOAPException ex) {
162: throw new WebServiceException(ex);
163: }
164:
165: String operation = (String) packet.invocationProperties
166: .get(CONTEXT_WSDL_OPERATION);
167:
168: StaticApplicationContext sContext = getPolicyContext(
169: packet, sConfig);
170: sContext.setOperationIdentifier(operation);
171:
172: ApplicationSecurityConfiguration config = sConfig
173: .getSecurityConfiguration();
174:
175: SecurityPolicy policy = config
176: .getSecurityConfiguration(sContext);
177:
178: ProcessingContext context = new ProcessingContextImpl(
179: packet.invocationProperties);
180: context.setPolicyContext(sContext);
181: context.setSOAPMessage(message);
182:
183: if (PolicyTypeUtil.declarativeSecurityConfiguration(policy)) {
184: context
185: .setSecurityPolicy(((DeclarativeSecurityConfiguration) policy)
186: .receiverSettings());
187: } else {
188: context.setSecurityPolicy(policy);
189: }
190:
191: context.setSecurityEnvironment(sConfig
192: .getSecurityEnvironment());
193: context.isInboundMessage(true);
194:
195: if (config.retainSecurityHeader()) {
196: context.retainSecurityHeader(true);
197: }
198:
199: SecurityRecipient.validateMessage(context);
200:
201: /* TODO: not sure if this is needed
202: if (messageContext.get("javax.security.auth.Subject") != null) {
203: messageContext.setScope("javax.security.auth.Subject", MessageContext.Scope.APPLICATION);
204: }*/
205: packet
206: .setMessage(Messages.create(context
207: .getSOAPMessage()));
208: return packet;
209:
210: } catch (com.sun.xml.wss.impl.WssSoapFaultException soapFaultException) {
211: throw getSOAPFaultException(soapFaultException, isSOAP12);
212: } catch (com.sun.xml.wss.XWSSecurityException xwse) {
213: QName qname = null;
214:
215: if (xwse.getCause() instanceof PolicyViolationException)
216: qname = MessageConstants.WSSE_RECEIVER_POLICY_VIOLATION;
217: else
218: qname = MessageConstants.WSSE_FAILED_AUTHENTICATION;
219:
220: com.sun.xml.wss.impl.WssSoapFaultException wsfe = SecurableSoapMessage
221: .newSOAPFaultException(qname, xwse.getMessage(),
222: xwse);
223: throw getSOAPFaultException(wsfe, isSOAP12);
224: }
225: }
226:
227: // client side request sending hook
228: public Packet secureRequest(Packet packet) {
229:
230: ProcessingContext context = null;
231: SOAPMessage message = null;
232: try {
233: message = packet.getMessage().readAsSOAPMessage();
234: } catch (SOAPException ex) {
235: throw new WebServiceException(ex);
236: }
237:
238: try {
239: //TODO: whether property on BindingProvider.RequestContext is available here
240: SecurityConfiguration sConfig = (SecurityConfiguration) packet.invocationProperties
241: .get(MESSAGE_SECURITY_CONFIGURATION);
242:
243: if (sConfig == null) {
244: return packet;
245: }
246:
247: WSDLBoundOperation op = null;
248: if (port != null) {
249: op = packet.getMessage().getOperation(port);
250: }
251:
252: QName operationQName = null;
253: if (op != null) {
254: operationQName = op.getName();
255: }
256:
257: String operation = null;
258: try {
259: if (operationQName == null) {
260: operation = getOperationName(message);
261: } else {
262: operation = operationQName.toString();
263: }
264: } catch (XWSSecurityException e) {
265: throw new WebServiceException(e);
266: }
267:
268: packet.invocationProperties.put(CONTEXT_WSDL_OPERATION,
269: operation);
270:
271: StaticApplicationContext sContext = getPolicyContext(
272: packet, sConfig);
273: sContext.setOperationIdentifier(operation);
274:
275: ApplicationSecurityConfiguration config = sConfig
276: .getSecurityConfiguration();
277:
278: SecurityPolicy policy = config
279: .getSecurityConfiguration(sContext);
280:
281: context = new ProcessingContextImpl(
282: packet.invocationProperties);
283:
284: context.setPolicyContext(sContext);
285:
286: if (PolicyTypeUtil.declarativeSecurityConfiguration(policy)) {
287: context
288: .setSecurityPolicy(((DeclarativeSecurityConfiguration) policy)
289: .senderSettings());
290: } else {
291: context.setSecurityPolicy(policy);
292: }
293:
294: context.setSecurityEnvironment(sConfig
295: .getSecurityEnvironment());
296: context.isInboundMessage(false);
297: context.setSOAPMessage(message);
298: SecurityAnnotator.secureMessage(context);
299: packet
300: .setMessage(Messages.create(context
301: .getSOAPMessage()));
302: return packet;
303:
304: } catch (com.sun.xml.wss.impl.WssSoapFaultException soapFaultException) {
305: throw new WebServiceException(soapFaultException);
306: } catch (com.sun.xml.wss.XWSSecurityException xwse) {
307: // log the exception here
308: throw new WebServiceException(xwse);
309: }
310:
311: }
312:
313: private String getOperationName(SOAPMessage message)
314: throws XWSSecurityException {
315: Node node = null;
316: String key = null;
317: SOAPBody body = null;
318:
319: if (message != null) {
320: try {
321: body = message.getSOAPBody();
322: } catch (SOAPException ex) {
323: throw new XWSSecurityException(ex);
324: }
325: } else {
326: throw new XWSSecurityException(
327: "SOAPMessage in message context is null");
328: }
329:
330: if (body != null)
331: node = body.getFirstChild();
332: else
333: throw new XWSSecurityException(
334: "No body element identifying an operation is found");
335:
336: StringBuffer tmp = new StringBuffer("");
337: String operation = "";
338:
339: for (; node != null; node = node.getNextSibling())
340: tmp.append("{" + node.getNamespaceURI() + "}"
341: + node.getLocalName() + ":");
342: operation = tmp.toString();
343: if (operation.length() > 0) {
344: return operation.substring(0, operation.length() - 1);
345: } else {
346: return operation;
347: }
348: }
349:
350: public SOAPFaultException getSOAPFaultException(
351: WssSoapFaultException sfe, boolean isSOAP12) {
352:
353: SOAPFault fault = null;
354: try {
355: if (isSOAP12) {
356: fault = soapFactory.createFault(sfe.getFaultString(),
357: SOAPConstants.SOAP_SENDER_FAULT);
358:
359: fault.appendFaultSubcode(sfe.getFaultCode());
360: } else {
361: fault = soapFactory.createFault(sfe.getFaultString(),
362: sfe.getFaultCode());
363: }
364: } catch (Exception e) {
365: throw new RuntimeException(
366: this
367: + ": Internal Error while trying to create a SOAPFault");
368: }
369: return new SOAPFaultException(fault);
370: }
371:
372: private StaticApplicationContext getPolicyContext(Packet packet,
373: SecurityConfiguration config) {
374:
375: // assumed to contain single nested container
376: ApplicationSecurityConfiguration appconfig = config
377: .getSecurityConfiguration();
378:
379: StaticApplicationContext iContext = (StaticApplicationContext) appconfig
380: .getAllContexts().next();
381: StaticApplicationContext sContext = new StaticApplicationContext(
382: iContext);
383:
384: QName portQname = null;
385: if (port != null) {
386: portQname = port.getName();
387: }
388: String prt = null;
389:
390: if (portQname == null) {
391: prt = "";
392: } else {
393: prt = portQname.toString();
394: }
395:
396: sContext.setPortIdentifier(prt);
397: return sContext;
398: }
399:
400: }
|