/* * Copyright 2004,2005 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.rampart; import org.apache.axiom.om.OMElement; import org.apache.axiom.soap.SOAPEnvelope; import org.apache.axiom.soap.SOAPHeaderBlock; import org.apache.axis2.AxisFault; import org.apache.axis2.context.MessageContext; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.rahas.Token; import org.apache.rahas.TokenStorage; import org.apache.rampart.policy.RampartPolicyData; import org.apache.rampart.util.Axis2Util; import org.apache.rampart.util.RampartUtil; import org.apache.ws.secpolicy.WSSPolicyException; import org.apache.ws.security.WSConstants; import org.apache.ws.security.WSSecurityEngine; import org.apache.ws.security.WSSecurityEngineResult; import org.apache.ws.security.WSSecurityException; import org.apache.ws.security.components.crypto.Crypto; import org.apache.ws.security.saml.SAMLKeyInfo; import org.apache.ws.security.saml.SAMLUtil; import org.apache.ws.security.util.WSSecurityUtil; import org.opensaml.SAMLAssertion; import javax.xml.namespace.QName; import java.util.ArrayList; import java.util.Date; import java.util.Iterator; import java.util.Vector; public class RampartEngine { private static Log log = LogFactory.getLog(RampartEngine.class); private static Log tlog = LogFactory.getLog(RampartConstants.TIME_LOG); public Vector process(MessageContext msgCtx) throws WSSPolicyException, RampartException, WSSecurityException, AxisFault { boolean doDebug = log.isDebugEnabled(); boolean dotDebug = tlog.isDebugEnabled(); if(doDebug){ log.debug("Enter process(MessageContext msgCtx)"); } RampartMessageData rmd = new RampartMessageData(msgCtx, false); //If there is no policy information or if the message is a fault RampartPolicyData rpd = rmd.getPolicyData(); if(rpd == null || WSSecurityUtil.findElement(rmd.getDocument().getDocumentElement(), "Fault", rmd.getSoapConstants().getEnvelopeURI()) != null) { SOAPEnvelope env = Axis2Util.getSOAPEnvelopeFromDOMDocument(rmd.getDocument(), true); //Convert back to llom since the inflow cannot use llom msgCtx.setEnvelope(env); Axis2Util.useDOOM(false); if(doDebug){ log.debug("Return process MessageContext msgCtx)"); } return null; } Vector results = null; WSSecurityEngine engine = new WSSecurityEngine(); ValidatorData data = new ValidatorData(rmd); ArrayList headerBlocks = rmd.getMsgContext().getEnvelope() .getHeader().getHeaderBlocksWithNSURI(WSConstants.WSSE_NS); SOAPHeaderBlock secHeader = null; //Issue is axiom - a returned collection must not be null if(headerBlocks != null) { Iterator headerBlocksIterator = headerBlocks.iterator(); while (headerBlocksIterator.hasNext()) { SOAPHeaderBlock elem = (SOAPHeaderBlock) headerBlocksIterator.next(); if(elem.getLocalName().equals(WSConstants.WSSE_LN)) { secHeader = elem; break; } } } if(secHeader == null) { throw new RampartException("missingSecurityHeader"); } long t0=0, t1=0, t2=0, t3=0; if(dotDebug){ t0 = System.currentTimeMillis(); } String actorValue = secHeader.getAttributeValue(new QName(rmd .getSoapConstants().getEnvelopeURI(), "actor")); Crypto signatureCrypto = RampartUtil.getSignatureCrypto(rpd.getRampartConfig(), msgCtx.getAxisService().getClassLoader()); TokenCallbackHandler tokenCallbackHandler = new TokenCallbackHandler(rmd.getTokenStorage(), RampartUtil.getPasswordCB(rmd)); if(rpd.isSymmetricBinding()) { //Here we have to create the CB handler to get the tokens from the //token storage if(doDebug){ log.debug("Processing security header using SymetricBinding"); } results = engine.processSecurityHeader(rmd.getDocument(), actorValue, tokenCallbackHandler, signatureCrypto); } else { if(doDebug){ log.debug("Processing security header in normal path"); } results = engine.processSecurityHeader(rmd.getDocument(), actorValue, tokenCallbackHandler, signatureCrypto, RampartUtil.getEncryptionCrypto(rpd.getRampartConfig(), msgCtx.getAxisService().getClassLoader())); } if(dotDebug){ t1 = System.currentTimeMillis(); } //Store symm tokens //Pick the first SAML token //TODO : This is a hack , MUST FIX //get the sec context id from the req msg ctx for (int j = 0; j < results.size(); j++) { WSSecurityEngineResult wser = (WSSecurityEngineResult) results.get(j); final Integer actInt = (Integer)wser.get(WSSecurityEngineResult.TAG_ACTION); if(WSConstants.ST_UNSIGNED == actInt.intValue()) { final SAMLAssertion assertion = ((SAMLAssertion) wser .get(WSSecurityEngineResult.TAG_SAML_ASSERTION)); String id = assertion.getId(); Date created = assertion.getNotBefore(); Date expires = assertion.getNotOnOrAfter(); SAMLKeyInfo samlKi = SAMLUtil.getSAMLKeyInfo(assertion, signatureCrypto, tokenCallbackHandler); try { TokenStorage store = rmd.getTokenStorage(); if(store.getToken(id) == null) { Token token = new Token(id, (OMElement)assertion.toDOM(), created, expires); token.setSecret(samlKi.getSecret()); store.add(token); } } catch (Exception e) { throw new RampartException( "errorInAddingTokenIntoStore", e); } } } SOAPEnvelope env = Axis2Util.getSOAPEnvelopeFromDOMDocument(rmd.getDocument(), true); if(dotDebug){ t2 = System.currentTimeMillis(); } //Convert back to llom since the inflow cannot use DOOM msgCtx.setEnvelope(env); Axis2Util.useDOOM(false); PolicyBasedResultsValidator validator = new PolicyBasedResultsValidator(); validator.validate(data, results); if(dotDebug){ t3 = System.currentTimeMillis(); tlog.debug("processHeader by WSSecurityEngine took : " + (t1 - t0) + ", DOOM conversion took :" + (t2 - t1) + ", PolicyBasedResultsValidattor took " + (t3 - t2)); } if(doDebug){ log.debug("Return process(MessageContext msgCtx)"); } return results; } }