/* * 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.builder; import org.apache.axiom.om.OMElement; import org.apache.axiom.soap.SOAPEnvelope; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.rahas.TrustException; import org.apache.rampart.RampartConstants; import org.apache.rampart.RampartException; import org.apache.rampart.RampartMessageData; import org.apache.rampart.policy.RampartPolicyData; import org.apache.rampart.util.RampartUtil; import org.apache.ws.secpolicy.Constants; import org.apache.ws.secpolicy.model.Header; import org.apache.ws.secpolicy.model.IssuedToken; import org.apache.ws.secpolicy.model.SignedEncryptedParts; import org.apache.ws.secpolicy.model.SupportingToken; import org.apache.ws.secpolicy.model.Token; import org.apache.ws.secpolicy.model.UsernameToken; import org.apache.ws.secpolicy.model.X509Token; import org.apache.ws.security.WSConstants; import org.apache.ws.security.WSEncryptionPart; import org.apache.ws.security.WSSecurityException; import org.apache.ws.security.conversation.ConversationException; import org.apache.ws.security.handler.WSHandlerConstants; import org.apache.ws.security.message.WSSecDKSign; import org.apache.ws.security.message.WSSecEncryptedKey; import org.apache.ws.security.message.WSSecSignature; import org.apache.ws.security.message.WSSecUsernameToken; import org.w3c.dom.Document; import org.w3c.dom.Element; import java.util.ArrayList; import java.util.Iterator; import java.util.Vector; public class TransportBindingBuilder extends BindingBuilder { private static Log log = LogFactory.getLog(TransportBindingBuilder.class); private static Log tlog = LogFactory.getLog(RampartConstants.TIME_LOG); private boolean dotDebug = false; public TransportBindingBuilder(){ dotDebug = tlog.isDebugEnabled(); } public void build(RampartMessageData rmd) throws RampartException { log.debug("TransportBindingBuilder build invoked"); long t0 = 0, t1 = 0; if(dotDebug){ t1 = System.currentTimeMillis(); } RampartPolicyData rpd = rmd.getPolicyData(); if (rpd.isIncludeTimestamp()) { addTimestamp(rmd); } /* * Process Supporting tokens */ if(rmd.isInitiator()) { Vector signatureValues = new Vector(); SupportingToken sgndSuppTokens = rpd.getSignedSupportingTokens(); if(sgndSuppTokens != null && sgndSuppTokens.getTokens() != null && sgndSuppTokens.getTokens().size() > 0) { log.debug("Processing signed supporting tokens"); ArrayList tokens = sgndSuppTokens.getTokens(); for (Iterator iter = tokens.iterator(); iter.hasNext();) { Token token = (Token) iter.next(); if(token instanceof UsernameToken) { WSSecUsernameToken utBuilder = addUsernameToken(rmd); utBuilder.setPasswordType(WSConstants.PASSWORD_TEXT); utBuilder.prepare(rmd.getDocument()); //Add the UT utBuilder.appendToHeader(rmd.getSecHeader()); } else { throw new RampartException("unsupportedSignedSupportingToken", new String[]{"{" +token.getName().getNamespaceURI() + "}" + token.getName().getLocalPart()}); } } } SupportingToken sgndEndSuppTokens = rpd.getSignedEndorsingSupportingTokens(); if(sgndEndSuppTokens != null && sgndEndSuppTokens.getTokens() != null && sgndEndSuppTokens.getTokens().size() > 0) { log.debug("Processing endorsing signed supporting tokens"); ArrayList tokens = sgndEndSuppTokens.getTokens(); SignedEncryptedParts signdParts = sgndEndSuppTokens.getSignedParts(); for (Iterator iter = tokens.iterator(); iter.hasNext();) { Token token = (Token) iter.next(); if(token instanceof IssuedToken && rmd.isInitiator()) { signatureValues.add(doIssuedTokenSignature(rmd, token, signdParts)); } else if(token instanceof X509Token) { signatureValues.add(doX509TokenSignature(rmd, token, signdParts)); } } } SupportingToken endSupptokens = rpd.getEndorsingSupportingTokens(); if(endSupptokens != null && endSupptokens.getTokens() != null && endSupptokens.getTokens().size() > 0) { log.debug("Processing endorsing supporting tokens"); ArrayList tokens = endSupptokens.getTokens(); SignedEncryptedParts signdParts = endSupptokens.getSignedParts(); for (Iterator iter = tokens.iterator(); iter.hasNext();) { Token token = (Token) iter.next(); if(token instanceof IssuedToken && rmd.isInitiator()){ signatureValues.add(doIssuedTokenSignature(rmd, token, signdParts)); } else if(token instanceof X509Token) { signatureValues.add(doX509TokenSignature(rmd, token, signdParts)); } } } SupportingToken supportingToks = rpd.getSupportingTokens(); this.handleSupportingTokens(rmd, supportingToks); //Store the signature values vector rmd.getMsgContext().setProperty(WSHandlerConstants.SEND_SIGV, signatureValues); } else { addSignatureConfirmation(rmd, null); } if(dotDebug){ t1 = System.currentTimeMillis(); tlog.debug("Transport binding build took "+ (t1 - t0)); } } /** * X.509 signature * @param rmd * @param token * @param signdParts */ private byte[] doX509TokenSignature(RampartMessageData rmd, Token token, SignedEncryptedParts signdParts) throws RampartException { RampartPolicyData rpd = rmd.getPolicyData(); Document doc = rmd.getDocument(); Vector sigParts = new Vector(); if(this.timestampElement != null){ sigParts.add(new WSEncryptionPart(rmd.getTimestampId())); } if(signdParts != null) { if(signdParts.isBody()) { SOAPEnvelope env = rmd.getMsgContext().getEnvelope(); sigParts.add(new WSEncryptionPart(RampartUtil.addWsuIdToElement(env.getBody()))); } ArrayList headers = signdParts.getHeaders(); for (Iterator iterator = headers.iterator(); iterator.hasNext();) { Header header = (Header) iterator.next(); WSEncryptionPart wep = new WSEncryptionPart(header.getName(), header.getNamespace(), "Content"); sigParts.add(wep); } } if(token.isDerivedKeys()) { //In this case we will have to encrypt the ephmeral key with the //other party's key and then use it as the parent key of the // derived keys try { WSSecEncryptedKey encrKey = getEncryptedKeyBuilder(rmd, token); Element bstElem = encrKey.getBinarySecurityTokenElement(); if(bstElem != null) { RampartUtil.appendChildToSecHeader(rmd, bstElem); } encrKey.appendToHeader(rmd.getSecHeader()); WSSecDKSign dkSig = new WSSecDKSign(); dkSig.setWsConfig(rmd.getConfig()); dkSig.setSigCanonicalization(rpd.getAlgorithmSuite().getInclusiveC14n()); dkSig.setSignatureAlgorithm(rpd.getAlgorithmSuite().getSymmetricSignature()); dkSig.setDerivedKeyLength(rpd.getAlgorithmSuite().getMinimumSymmetricKeyLength()/8); dkSig.setExternalKey(encrKey.getEphemeralKey(), encrKey.getId()); dkSig.prepare(doc, rmd.getSecHeader()); if(rpd.isTokenProtection()) { sigParts.add(new WSEncryptionPart(encrKey.getBSTTokenId())); } dkSig.setParts(sigParts); dkSig.addReferencesToSign(sigParts, rmd.getSecHeader()); //Do signature dkSig.computeSignature(); dkSig.appendDKElementToHeader(rmd.getSecHeader()); dkSig.appendSigToHeader(rmd.getSecHeader()); return dkSig.getSignatureValue(); } catch (WSSecurityException e) { throw new RampartException("errorInDerivedKeyTokenSignature", e); } catch (ConversationException e) { throw new RampartException("errorInDerivedKeyTokenSignature", e); } } else { try { WSSecSignature sig = this.getSignatureBuider(rmd, token); sig.appendBSTElementToHeader(rmd.getSecHeader()); if (rpd.isTokenProtection() && !Constants.INCLUDE_NEVER .equals(token.getInclusion())) { sigParts.add(new WSEncryptionPart(sig.getBSTTokenId())); } sig.addReferencesToSign(sigParts, rmd.getSecHeader()); sig.appendToHeader(rmd.getSecHeader()); sig.computeSignature(); return sig.getSignatureValue(); } catch (WSSecurityException e) { throw new RampartException("errorInSignatureWithX509Token", e); } } } /** * IssuedToken signature * @param rmd * @param token * @param signdParts * @throws RampartException */ private byte[] doIssuedTokenSignature(RampartMessageData rmd, Token token, SignedEncryptedParts signdParts) throws RampartException { RampartPolicyData rpd = rmd.getPolicyData(); Document doc= rmd.getDocument(); //Get the issued token String id = RampartUtil.getIssuedToken(rmd, (IssuedToken)token); String inclusion = token.getInclusion(); org.apache.rahas.Token tok = null; try { tok = rmd.getTokenStorage().getToken(id); } catch (TrustException e) { throw new RampartException("errorExtractingToken", new String[]{id} ,e); } boolean tokenIncluded = false; if(inclusion.equals(Constants.INCLUDE_ALWAYS) || ((inclusion.equals(Constants.INCLUDE_ALWAYS_TO_RECIPIENT) || inclusion.equals(Constants.INCLUDE_ONCE)) && rmd.isInitiator())) { //Add the token rmd.getSecHeader().getSecurityHeader().appendChild( doc.importNode((Element) tok.getToken(), true)); tokenIncluded = true; } Vector sigParts = new Vector(); if(this.timestampElement != null){ sigParts.add(new WSEncryptionPart(rmd.getTimestampId())); } if(rpd.isTokenProtection() && tokenIncluded) { sigParts.add(new WSEncryptionPart(id)); } if(signdParts != null) { if(signdParts.isBody()) { SOAPEnvelope env = rmd.getMsgContext().getEnvelope(); sigParts.add(new WSEncryptionPart(RampartUtil.addWsuIdToElement(env.getBody()))); } ArrayList headers = signdParts.getHeaders(); for (Iterator iterator = headers.iterator(); iterator.hasNext();) { Header header = (Header) iterator.next(); WSEncryptionPart wep = new WSEncryptionPart(header.getName(), header.getNamespace(), "Content"); sigParts.add(wep); } } //check for derived keys if(token.isDerivedKeys()) { //Create a derived key and add try { //Do Signature with derived keys WSSecDKSign dkSign = new WSSecDKSign(); OMElement ref = tok.getAttachedReference(); if(ref == null) { ref = tok.getUnattachedReference(); } if(ref != null) { dkSign.setExternalKey(tok.getSecret(), (Element) doc.importNode((Element) ref, true)); } else { dkSign.setExternalKey(tok.getSecret(), tok.getId()); } //Set the algo info dkSign.setSignatureAlgorithm(rpd.getAlgorithmSuite().getSymmetricSignature()); dkSign.prepare(doc); dkSign.appendDKElementToHeader(rmd.getSecHeader()); dkSign.setParts(sigParts); dkSign.addReferencesToSign(sigParts, rmd.getSecHeader()); //Do signature dkSign.computeSignature(); dkSign.appendSigToHeader(rmd.getSecHeader()); return dkSign.getSignatureValue(); } catch (ConversationException e) { throw new RampartException( "errorInDerivedKeyTokenSignature", e); } catch (WSSecurityException e) { throw new RampartException( "errorInDerivedKeyTokenSignature", e); } } else { try { WSSecSignature sig = new WSSecSignature(); sig.setWsConfig(rmd.getConfig()); sig.setCustomTokenId(tok.getId().substring(1)); sig.setCustomTokenValueType(WSConstants.WSS_SAML_NS + WSConstants.SAML_ASSERTION_ID); sig.setSecretKey(tok.getSecret()); sig.setSignatureAlgorithm(rpd.getAlgorithmSuite().getAsymmetricSignature()); sig.setSignatureAlgorithm(rpd.getAlgorithmSuite().getSymmetricSignature()); sig.setKeyIdentifierType(WSConstants.CUSTOM_SYMM_SIGNING); sig.prepare(rmd.getDocument(), RampartUtil.getSignatureCrypto(rpd .getRampartConfig(), rmd.getCustomClassLoader()), rmd.getSecHeader()); sig.setParts(sigParts); sig.addReferencesToSign(sigParts, rmd.getSecHeader()); //Do signature sig.computeSignature(); //Add elements to header this.setInsertionLocation(RampartUtil.insertSiblingAfter( rmd, this.getInsertionLocation(), sig.getSignatureElement())); return sig.getSignatureValue(); } catch (WSSecurityException e) { throw new RampartException("errorInSignatureWithACustomToken", e); } } } }