001: /**
002: * Licensed to the Apache Software Foundation (ASF) under one
003: * or more contributor license agreements. See the NOTICE file
004: * distributed with this work for additional information
005: * regarding copyright ownership. The ASF licenses this file
006: * to you under the Apache License, Version 2.0 (the
007: * "License"); you may not use this file except in compliance
008: * with the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing,
013: * software distributed under the License is distributed on an
014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015: * KIND, either express or implied. See the License for the
016: * specific language governing permissions and limitations
017: * under the License.
018: */package org.apache.cxf.ws.security.wss4j;
019:
020: import java.util.Map;
021: import java.util.Vector;
022: import java.util.logging.Level;
023: import java.util.logging.Logger;
024:
025: import javax.xml.soap.SOAPMessage;
026:
027: import org.w3c.dom.Document;
028:
029: import org.apache.cxf.binding.soap.SoapFault;
030: import org.apache.cxf.binding.soap.SoapMessage;
031: import org.apache.cxf.binding.soap.SoapVersion;
032: import org.apache.cxf.common.i18n.Message;
033: import org.apache.cxf.interceptor.Fault;
034: import org.apache.cxf.phase.Phase;
035: import org.apache.ws.security.WSConstants;
036: import org.apache.ws.security.WSSecurityException;
037: import org.apache.ws.security.handler.RequestData;
038: import org.apache.ws.security.handler.WSHandlerConstants;
039: import org.apache.ws.security.util.WSSecurityUtil;
040:
041: public class WSS4JOutInterceptor extends AbstractWSS4JInterceptor {
042: private static final Logger LOG = Logger
043: .getLogger(WSS4JOutInterceptor.class.getName());
044:
045: private static final Logger TIME_LOG = Logger
046: .getLogger(WSS4JOutInterceptor.class.getName() + "-Time");
047:
048: public WSS4JOutInterceptor() {
049: super ();
050:
051: setPhase(Phase.POST_PROTOCOL);
052: }
053:
054: public WSS4JOutInterceptor(Map<String, Object> props) {
055: this ();
056: setProperties(props);
057: }
058:
059: public void handleMessage(SoapMessage mc) throws Fault {
060: boolean doDebug = LOG.isLoggable(Level.FINE);
061: boolean doTimeDebug = TIME_LOG.isLoggable(Level.FINE);
062: SoapVersion version = mc.getVersion();
063:
064: long t0 = 0;
065: long t1 = 0;
066: long t2 = 0;
067:
068: if (doTimeDebug) {
069: t0 = System.currentTimeMillis();
070: }
071:
072: if (doDebug) {
073: LOG.fine("WSDoAllSender: enter invoke()");
074: }
075:
076: RequestData reqData = new RequestData();
077:
078: reqData.setMsgContext(mc);
079: /*
080: * The overall try, just to have a finally at the end to perform some
081: * housekeeping.
082: */
083: try {
084: /*
085: * Get the action first.
086: */
087: Vector actions = new Vector();
088: String action = getString(WSHandlerConstants.ACTION, mc);
089: if (action == null) {
090: throw new SoapFault(new Message("NO_ACTION", LOG),
091: version.getReceiver());
092: }
093:
094: int doAction = WSSecurityUtil.decodeAction(action, actions);
095: if (doAction == WSConstants.NO_SECURITY) {
096: return;
097: }
098:
099: /*
100: * For every action we need a username, so get this now. The
101: * username defined in the deployment descriptor takes precedence.
102: */
103: reqData
104: .setUsername((String) getOption(WSHandlerConstants.USER));
105: if (reqData.getUsername() == null
106: || reqData.getUsername().equals("")) {
107: String username = (String) getProperty(reqData
108: .getMsgContext(), WSHandlerConstants.USER);
109: if (username != null) {
110: reqData.setUsername(username);
111: }
112: }
113:
114: /*
115: * Now we perform some set-up for UsernameToken and Signature
116: * functions. No need to do it for encryption only. Check if
117: * username is available and then get a passowrd.
118: */
119: if ((doAction & (WSConstants.SIGN | WSConstants.UT | WSConstants.UT_SIGN)) != 0
120: && reqData.getUsername() == null
121: || reqData.getUsername().equals("")) {
122: /*
123: * We need a username - if none throw an SoapFault. For
124: * encryption there is a specific parameter to get a username.
125: */
126: throw new SoapFault(new Message("NO_USERNAME", LOG),
127: version.getReceiver());
128: }
129: if (doDebug) {
130: LOG.fine("Action: " + doAction);
131: LOG.fine("Actor: " + reqData.getActor());
132: }
133: /*
134: * Now get the SOAP part from the request message and convert it
135: * into a Document. This forces CXF to serialize the SOAP request
136: * into FORM_STRING. This string is converted into a document.
137: * During the FORM_STRING serialization CXF performs multi-ref of
138: * complex data types (if requested), generates and inserts
139: * references for attachements and so on. The resulting Document
140: * MUST be the complete and final SOAP request as CXF would send it
141: * over the wire. Therefore this must shall be the last (or only)
142: * handler in a chain. Now we can perform our security operations on
143: * this request.
144: */
145: SOAPMessage saaj = mc.getContent(SOAPMessage.class);
146:
147: if (saaj == null) {
148: LOG
149: .warning("SAAJOutHandler must be enabled for WS-Security!");
150: throw new SoapFault(new Message("NO_SAAJ_DOC", LOG),
151: version.getReceiver());
152: }
153:
154: Document doc = saaj.getSOAPPart();
155: /**
156: * There is nothing to send...Usually happens when the provider
157: * needs to send a HTTP 202 message (with no content)
158: */
159: if (mc == null) {
160: return;
161: }
162:
163: if (doTimeDebug) {
164: t1 = System.currentTimeMillis();
165: }
166:
167: doSenderAction(
168: doAction,
169: doc,
170: reqData,
171: actions,
172: !Boolean.TRUE
173: .equals(getProperty(
174: mc,
175: org.apache.cxf.message.Message.REQUESTOR_ROLE)));
176:
177: if (doTimeDebug) {
178: t2 = System.currentTimeMillis();
179: TIME_LOG.fine("Send request: total= " + (t2 - t0)
180: + " request preparation= " + (t1 - t0)
181: + " request processing= " + (t2 - t1) + "\n");
182: }
183:
184: if (doDebug) {
185: LOG.fine("WSDoAllSender: exit invoke()");
186: }
187: } catch (WSSecurityException e) {
188: throw new SoapFault(new Message("SECURITY_FAILED", LOG), e,
189: version.getSender());
190: } finally {
191: reqData.clear();
192: reqData = null;
193: }
194: }
195: }
|