| /* |
| * Copyright 2003-2004 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.ws.security.message; |
| |
| import org.apache.commons.logging.Log; |
| import org.apache.commons.logging.LogFactory; |
| import org.apache.ws.security.SOAPConstants; |
| import org.apache.ws.security.WSConstants; |
| import org.apache.ws.security.WSDocInfo; |
| import org.apache.ws.security.WSDocInfoStore; |
| import org.apache.ws.security.WSEncryptionPart; |
| import org.apache.ws.security.WSSecurityException; |
| import org.apache.ws.security.components.crypto.Crypto; |
| import org.apache.ws.security.message.token.BinarySecurity; |
| import org.apache.ws.security.message.token.PKIPathSecurity; |
| import org.apache.ws.security.message.token.Reference; |
| import org.apache.ws.security.message.token.SecurityTokenReference; |
| import org.apache.ws.security.message.token.X509Security; |
| import org.apache.ws.security.saml.SAMLUtil; |
| import org.apache.ws.security.transform.STRTransform; |
| import org.apache.ws.security.util.WSSecurityUtil; |
| import org.apache.xml.security.algorithms.SignatureAlgorithm; |
| import org.apache.xml.security.c14n.Canonicalizer; |
| import org.apache.xml.security.exceptions.XMLSecurityException; |
| import org.apache.xml.security.keys.KeyInfo; |
| import org.apache.xml.security.keys.content.X509Data; |
| import org.apache.xml.security.keys.content.x509.XMLX509IssuerSerial; |
| import org.apache.xml.security.signature.XMLSignature; |
| import org.apache.xml.security.signature.XMLSignatureException; |
| import org.apache.xml.security.transforms.TransformationException; |
| import org.apache.xml.security.transforms.Transforms; |
| import org.apache.xml.security.transforms.params.InclusiveNamespaces; |
| import org.apache.xml.security.utils.Constants; |
| import org.apache.xml.security.utils.XMLUtils; |
| import org.w3c.dom.Document; |
| import org.w3c.dom.Element; |
| import org.w3c.dom.NamedNodeMap; |
| import org.w3c.dom.Node; |
| |
| import java.security.cert.X509Certificate; |
| import java.util.HashSet; |
| import java.util.Set; |
| import java.util.Vector; |
| |
| /** |
| * Creates a Signature according to WS Specification, X509 profile. |
| * |
| * This class is a re-factored implementation of the previous WSS4J class |
| * <code>WSSignEnvlope</code>. This new class allows better control of |
| * the process to create a Signature and to add it to the Security header. |
| * |
| * <br/> |
| * |
| * The flexibility and fine granular control is required to implement a handler |
| * that uses WSSecurityPolicy files to control the setup of a Security header. |
| * |
| * @author Davanum Srinivas (dims@yahoo.com) |
| * @author Werner Dittmann (werner@apache.org) |
| */ |
| public class WSSecSignature extends WSSecBase { |
| |
| private static Log log = LogFactory.getLog(WSSecSignature.class.getName()); |
| |
| protected boolean useSingleCert = true; |
| |
| protected String sigAlgo = null; |
| |
| protected String canonAlgo = Canonicalizer.ALGO_ID_C14N_EXCL_OMIT_COMMENTS; |
| |
| protected WSSecUsernameToken usernameToken = null; |
| |
| protected byte[] signatureValue = null; |
| |
| /* |
| * The following private variable are setup during prepare(). |
| */ |
| protected Document document = null; |
| |
| private Crypto crypto = null; |
| |
| protected WSDocInfo wsDocInfo = null; |
| |
| protected String certUri = null; |
| |
| protected XMLSignature sig = null; |
| |
| protected KeyInfo keyInfo = null; |
| |
| protected String keyInfoUri = null; |
| |
| protected SecurityTokenReference secRef = null; |
| |
| protected String strUri = null; |
| |
| private byte[] secretKey = null; |
| |
| protected BinarySecurity bstToken = null; |
| |
| private String customTokenValueType; |
| |
| private String customTokenId; |
| |
| /** |
| * Constructor. |
| */ |
| public WSSecSignature() { |
| } |
| |
| /** |
| * set the single cert flag. |
| * |
| * @param useSingleCert |
| */ |
| public void setUseSingleCertificate(boolean useSingleCert) { |
| this.useSingleCert = useSingleCert; |
| } |
| |
| /** |
| * Get the single cert flag. |
| * |
| * @return A boolean if single certificate is set. |
| */ |
| public boolean isUseSingleCertificate() { |
| return this.useSingleCert; |
| } |
| |
| /** |
| * Set the name of the signature encryption algorithm to use. |
| * |
| * If the algorithm is not set then an automatic detection of the signature |
| * algorithm to use is performed during the <code>prepare()</code> |
| * method. Refer to WSConstants which algorithms are supported. |
| * |
| * @param algo |
| * Is the name of the signature algorithm |
| * @see WSConstants#RSA |
| * @see WSConstants#DSA |
| */ |
| public void setSignatureAlgorithm(String algo) { |
| sigAlgo = algo; |
| } |
| |
| /** |
| * Get the name of the signature algorithm that is being used. |
| * |
| * Call this method after <code>prepare</code> to get the information |
| * which signature algorithm was automatically detected if no signature |
| * algorithm was preset. |
| * |
| * @return the identifier URI of the signature algorithm |
| */ |
| public String getSignatureAlgorithm() { |
| return sigAlgo; |
| } |
| |
| /** |
| * Set the canonicalization method to use. |
| * |
| * If the canonicalization method is not set then the recommended Exclusive |
| * XML Canonicalization is used by default Refer to WSConstants which |
| * algorithms are supported. |
| * |
| * @param algo |
| * Is the name of the signature algorithm |
| * @see WSConstants#C14N_OMIT_COMMENTS |
| * @see WSConstants#C14N_WITH_COMMENTS |
| * @see WSConstants#C14N_EXCL_OMIT_COMMENTS |
| * @see WSConstants#C14N_EXCL_WITH_COMMENTS |
| */ |
| public void setSigCanonicalization(String algo) { |
| canonAlgo = algo; |
| } |
| |
| /** |
| * Get the canonicalization method. |
| * |
| * If the canonicalization method was not set then Exclusive XML |
| * Canonicalization is used by default. |
| * |
| * @return The string describing the canonicalization algorithm. |
| */ |
| public String getSigCanonicalization() { |
| return canonAlgo; |
| } |
| |
| /** |
| * @param usernameToken |
| * The usernameToken to set. |
| */ |
| public void setUsernameToken(WSSecUsernameToken usernameToken) { |
| this.usernameToken = usernameToken; |
| } |
| |
| /** |
| * Returns the computed Signature value. |
| * |
| * Call this method after <code>computeSignature()</code> or <code>build()</code> |
| * methods were called. |
| * |
| * @return Returns the signatureValue. |
| */ |
| public byte[] getSignatureValue() { |
| return signatureValue; |
| } |
| |
| /** |
| * Get the id generated during <code>prepare()</code>. |
| * |
| * Returns the the value of wsu:Id attribute of the Signature element. |
| * |
| * @return Return the wsu:Id of this token or null if <code>prepare()</code> |
| * was not called before. |
| */ |
| public String getId() { |
| if (sig == null) { |
| return null; |
| } |
| return sig.getId(); |
| } |
| |
| /** |
| * Get the id of the BSt generated during <code>prepare()</code>. |
| * |
| * @return Returns the the value of wsu:Id attribute of the |
| * BinaruSecurityToken element. |
| */ |
| public String getBSTTokenId() { |
| if(this.bstToken == null) { |
| return null; |
| } |
| |
| return this.bstToken.getID(); |
| } |
| |
| /** |
| * Initialize a WSSec Signature. |
| * |
| * The method sets up and initializes a WSSec Signature structure after the |
| * relevant information was set. After setup of the references to elements |
| * to sign may be added. After all references are added they can be signed. |
| * |
| * <p/> |
| * |
| * This method does not add the Signature element to the security header. |
| * See <code>prependSignatureElementToHeader()</code> method. |
| * |
| * @param doc |
| * The SOAP envelope as <code>Document</code> |
| * @param cr |
| * An instance of the Crypto API to handle keystore and |
| * certificates |
| * @param secHeader |
| * The security header that will hold the Signature. This is used |
| * to construct namespace prefixes for Signature. This method |
| * @throws WSSecurityException |
| */ |
| public void prepare(Document doc, Crypto cr, WSSecHeader secHeader) |
| throws WSSecurityException { |
| /* |
| * Gather some info about the document to process and store it for |
| * retrieval |
| */ |
| crypto = cr; |
| document = doc; |
| |
| wsDocInfo = new WSDocInfo(doc.hashCode()); |
| wsDocInfo.setCrypto(cr); |
| |
| /* |
| * At first get the security token (certificate) according to the |
| * parameters. |
| */ |
| X509Certificate[] certs = null; |
| if (keyIdentifierType != WSConstants.UT_SIGNING |
| && keyIdentifierType != WSConstants.CUSTOM_SYMM_SIGNING) { |
| certs = crypto.getCertificates(user); |
| if (certs == null || certs.length <= 0) { |
| throw new WSSecurityException(WSSecurityException.FAILURE, |
| "invalidX509Data", new Object[] { "for Signature" }); |
| } |
| certUri = "CertId-" + certs[0].hashCode(); |
| /* |
| * If no signature algo was set try to detect it according to the |
| * data stored in the certificate. |
| */ |
| if (sigAlgo == null) { |
| String pubKeyAlgo = certs[0].getPublicKey().getAlgorithm(); |
| log.debug("automatic sig algo detection: " + pubKeyAlgo); |
| if (pubKeyAlgo.equalsIgnoreCase("DSA")) { |
| sigAlgo = XMLSignature.ALGO_ID_SIGNATURE_DSA; |
| } else if (pubKeyAlgo.equalsIgnoreCase("RSA")) { |
| sigAlgo = XMLSignature.ALGO_ID_SIGNATURE_RSA; |
| } else { |
| throw new WSSecurityException( |
| WSSecurityException.FAILURE, |
| "invalidX509Data", |
| new Object[] { "for Signature - unknown public key Algo" }); |
| } |
| } |
| } |
| |
| /* |
| * Get an initialized XMLSignature element. |
| */ |
| if (canonAlgo.equals(WSConstants.C14N_EXCL_OMIT_COMMENTS)) { |
| Element canonElem = XMLUtils.createElementInSignatureSpace(doc, |
| Constants._TAG_CANONICALIZATIONMETHOD); |
| |
| canonElem.setAttributeNS(null, Constants._ATT_ALGORITHM, canonAlgo); |
| |
| if (wssConfig.isWsiBSPCompliant()) { |
| Set prefixes = getInclusivePrefixes(secHeader.getSecurityHeader(), false); |
| |
| InclusiveNamespaces inclusiveNamespaces = new InclusiveNamespaces( |
| doc, prefixes); |
| |
| canonElem.appendChild(inclusiveNamespaces.getElement()); |
| } |
| |
| try { |
| SignatureAlgorithm signatureAlgorithm = new SignatureAlgorithm( |
| doc, sigAlgo); |
| sig = new XMLSignature(doc, null, signatureAlgorithm |
| .getElement(), canonElem); |
| } catch (XMLSecurityException e) { |
| log.error("", e); |
| throw new WSSecurityException( |
| WSSecurityException.FAILED_SIGNATURE, "noXMLSig"); |
| } |
| } else { |
| try { |
| sig = new XMLSignature(doc, null, sigAlgo, canonAlgo); |
| } catch (XMLSecurityException e) { |
| log.error("", e); |
| throw new WSSecurityException( |
| WSSecurityException.FAILED_SIGNATURE, "noXMLSig"); |
| } |
| } |
| |
| sig.addResourceResolver(EnvelopeIdResolver.getInstance()); |
| String sigUri = "Signature-" + sig.hashCode(); |
| sig.setId(sigUri); |
| |
| keyInfo = sig.getKeyInfo(); |
| keyInfoUri = "KeyId-" + keyInfo.hashCode(); |
| keyInfo.setId(keyInfoUri); |
| |
| secRef = new SecurityTokenReference(doc); |
| strUri = "STRId-" + secRef.hashCode(); |
| secRef.setID(strUri); |
| |
| /* |
| * Prepare and setup the token references for this Signature |
| */ |
| switch (keyIdentifierType) { |
| case WSConstants.BST_DIRECT_REFERENCE: |
| Reference ref = new Reference(document); |
| ref.setURI("#" + certUri); |
| if (!useSingleCert) { |
| bstToken = new PKIPathSecurity(document); |
| ((PKIPathSecurity) bstToken).setX509Certificates(certs, false, |
| crypto); |
| } else { |
| bstToken = new X509Security(document); |
| ((X509Security) bstToken).setX509Certificate(certs[0]); |
| } |
| ref.setValueType(bstToken.getValueType()); |
| secRef.setReference(ref); |
| bstToken.setID(certUri); |
| wsDocInfo.setBst(bstToken.getElement()); |
| break; |
| |
| case WSConstants.ISSUER_SERIAL: |
| XMLX509IssuerSerial data = new XMLX509IssuerSerial(document, |
| certs[0]); |
| X509Data x509Data = new X509Data(document); |
| x509Data.add(data); |
| secRef.setX509IssuerSerial(x509Data); |
| break; |
| |
| case WSConstants.X509_KEY_IDENTIFIER: |
| secRef.setKeyIdentifier(certs[0]); |
| break; |
| |
| case WSConstants.SKI_KEY_IDENTIFIER: |
| secRef.setKeyIdentifierSKI(certs[0], crypto); |
| break; |
| |
| case WSConstants.UT_SIGNING: |
| Reference refUt = new Reference(document); |
| refUt.setValueType(WSConstants.USERNAMETOKEN_NS + "#UsernameToken"); |
| String utId = usernameToken.getId(); |
| refUt.setURI("#" + utId); |
| secRef.setReference(refUt); |
| secretKey = usernameToken.getSecretKey(); |
| break; |
| |
| case WSConstants.THUMBPRINT_IDENTIFIER: |
| secRef.setKeyIdentifierThumb(certs[0]); |
| break; |
| |
| case WSConstants.CUSTOM_SYMM_SIGNING : |
| Reference refCust = new Reference(document); |
| refCust.setValueType(this.customTokenValueType); |
| refCust.setURI("#" + this.customTokenId); |
| secRef.setReference(refCust); |
| break; |
| default: |
| throw new WSSecurityException(WSSecurityException.FAILURE, |
| "unsupportedKeyId"); |
| } |
| keyInfo.addUnknownElement(secRef.getElement()); |
| |
| } |
| |
| /** |
| * This method adds references to the Signature. |
| * |
| * The added references are signed when calling |
| * <code>computeSignature()</code>. This method can be called several |
| * times to add references as required. <code>addReferencesToSign()</code> |
| * can be called any time after <code>prepare</code>. |
| * |
| * @param references |
| * A vector containing <code>WSEncryptionPart</code> objects |
| * that define the parts to sign. |
| * @param secHeader |
| * Used to compute namespaces to be inserted by |
| * InclusiveNamespaces to be WSI compliant. |
| * @throws WSSecurityException |
| */ |
| public void addReferencesToSign(Vector references, WSSecHeader secHeader) |
| throws WSSecurityException { |
| Transforms transforms = null; |
| |
| Element envelope = document.getDocumentElement(); |
| |
| for (int part = 0; part < references.size(); part++) { |
| WSEncryptionPart encPart = (WSEncryptionPart) references.get(part); |
| |
| String idToSign = encPart.getId(); |
| |
| String elemName = encPart.getName(); |
| String nmSpace = encPart.getNamespace(); |
| |
| /* |
| * Set up the elements to sign. There are two reserved element |
| * names: "Token" and "STRTransform" "Token": Setup the Signature to |
| * either sign the information that points to the security token or |
| * the token itself. If its a direct reference sign the token, |
| * otherwise sign the KeyInfo Element. "STRTransform": Setup the |
| * ds:Reference to use STR Transform |
| * |
| */ |
| transforms = new Transforms(document); |
| try { |
| if (idToSign != null) { |
| Element toSignById = WSSecurityUtil.findElementById( |
| document.getDocumentElement(), idToSign, |
| WSConstants.WSU_NS); |
| if (toSignById == null) { |
| toSignById = WSSecurityUtil.findElementById(document |
| .getDocumentElement(), idToSign, null); |
| } |
| transforms |
| .addTransform(Transforms.TRANSFORM_C14N_EXCL_OMIT_COMMENTS); |
| if (wssConfig.isWsiBSPCompliant()) { |
| transforms.item(0).getElement().appendChild( |
| new InclusiveNamespaces(document, |
| getInclusivePrefixes(toSignById)) |
| .getElement()); |
| } |
| sig.addDocument("#" + idToSign, transforms); |
| } else if (elemName.equals("Token")) { |
| transforms |
| .addTransform(Transforms.TRANSFORM_C14N_EXCL_OMIT_COMMENTS); |
| if (keyIdentifierType == WSConstants.BST_DIRECT_REFERENCE) { |
| if (wssConfig.isWsiBSPCompliant()) { |
| transforms |
| .item(0) |
| .getElement() |
| .appendChild( |
| new InclusiveNamespaces( |
| document, |
| getInclusivePrefixes(secHeader.getSecurityHeader())) |
| .getElement()); |
| } |
| sig.addDocument("#" + certUri, transforms); |
| } else { |
| if (wssConfig.isWsiBSPCompliant()) { |
| transforms.item(0).getElement().appendChild( |
| new InclusiveNamespaces(document, |
| getInclusivePrefixes(keyInfo |
| .getElement())) |
| .getElement()); |
| } |
| sig.addDocument("#" + keyInfoUri, transforms); |
| } |
| } else if (elemName.equals("STRTransform")) { // STRTransform |
| Element ctx = createSTRParameter(document); |
| transforms.addTransform( |
| STRTransform.implementedTransformURI, ctx); |
| sig.addDocument("#" + strUri, transforms); |
| } else if (elemName.equals("Assertion")) { // Assertion |
| |
| String id = null; |
| id = SAMLUtil.getAssertionId(envelope, elemName, nmSpace); |
| |
| Element body = (Element) WSSecurityUtil.findElement( |
| envelope, elemName, nmSpace); |
| if (body == null) { |
| throw new WSSecurityException( |
| WSSecurityException.FAILURE, "noEncElement", |
| new Object[] { nmSpace + ", " + elemName }); |
| } |
| transforms |
| .addTransform(Transforms.TRANSFORM_C14N_EXCL_OMIT_COMMENTS); |
| if (wssConfig.isWsiBSPCompliant()) { |
| transforms.item(0).getElement().appendChild( |
| new InclusiveNamespaces(document, |
| getInclusivePrefixes(body)) |
| .getElement()); |
| } |
| String prefix = WSSecurityUtil.setNamespace(body, |
| WSConstants.WSU_NS, WSConstants.WSU_PREFIX); |
| body.setAttributeNS(WSConstants.WSU_NS, prefix + ":Id", id); |
| sig.addDocument("#" + id, transforms); |
| |
| } else { |
| Element body = (Element) WSSecurityUtil.findElement( |
| envelope, elemName, nmSpace); |
| if (body == null) { |
| throw new WSSecurityException( |
| WSSecurityException.FAILURE, "noEncElement", |
| new Object[] { nmSpace + ", " + elemName }); |
| } |
| transforms |
| .addTransform(Transforms.TRANSFORM_C14N_EXCL_OMIT_COMMENTS); |
| if (wssConfig.isWsiBSPCompliant()) { |
| transforms.item(0).getElement().appendChild( |
| new InclusiveNamespaces(document, |
| getInclusivePrefixes(body)) |
| .getElement()); |
| } |
| sig.addDocument("#" + setWsuId(body), transforms); |
| } |
| } catch (TransformationException e1) { |
| throw new WSSecurityException( |
| WSSecurityException.FAILED_SIGNATURE, "noXMLSig", null, |
| e1); |
| } catch (XMLSignatureException e1) { |
| throw new WSSecurityException( |
| WSSecurityException.FAILED_SIGNATURE, "noXMLSig", null, |
| e1); |
| } |
| } |
| } |
| |
| /** |
| * Prepends the Signature element to the elements already in the Security |
| * header. |
| * |
| * The method can be called any time after <code>prepare()</code>. |
| * This allows to insert the Signature element at any position in the |
| * Security header. |
| * |
| * @param securityHeader |
| * The secHeader that holds the Signature element. |
| */ |
| public void prependToHeader(WSSecHeader secHeader) { |
| WSSecurityUtil.prependChildElement(document, secHeader.getSecurityHeader(), sig |
| .getElement(), false); |
| } |
| |
| /** |
| * Appends the Signature element to the elements already in the Security |
| * header. |
| * |
| * The method can be called any time after <code>prepare()</code>. |
| * This allows to insert the Signature element at any position in the |
| * Security header. |
| * |
| * @param securityHeader |
| * The secHeader that holds the Signature element. |
| */ |
| public void appendToHeader(WSSecHeader secHeader) { |
| WSSecurityUtil.appendChildElement(document, secHeader.getSecurityHeader(), sig |
| .getElement()); |
| } |
| |
| /** |
| * Prepend the BinarySecurityToken to the elements already in the Security |
| * header. |
| * |
| * The method can be called any time after <code>prepare()</code>. |
| * This allows to insert the BST element at any position in the Security |
| * header. |
| * |
| * @param secHeader |
| * The security header that holds the BST element. |
| */ |
| public void prependBSTElementToHeader(WSSecHeader secHeader) { |
| if (bstToken != null) { |
| WSSecurityUtil.prependChildElement(document, secHeader.getSecurityHeader(), |
| bstToken.getElement(), false); |
| } |
| bstToken = null; |
| } |
| |
| /** |
| * Returns the SignatureElement. |
| * The method can be called any time after <code>prepare()</code>. |
| * @return The DOM Element of the signature. |
| */ |
| public Element getSignatureElement() { |
| return this.sig.getElement(); |
| } |
| |
| /** |
| * Returns the BST Token element. |
| * The method can be called any time after <code>prepare()</code>. |
| * @return |
| */ |
| public Element getBinarySecurityTokenElement() { |
| if(this.bstToken != null) { |
| return this.bstToken.getElement(); |
| } else { |
| return null; |
| } |
| } |
| |
| public void appendBSTElementToHeader(WSSecHeader secHeader) { |
| if (bstToken != null) { |
| WSSecurityUtil.appendChildElement(document, secHeader.getSecurityHeader(), |
| bstToken.getElement()); |
| } |
| bstToken = null; |
| } |
| |
| /** |
| * Compute the Signature over the references. |
| * |
| * After references are set this method computes the Signature for them. |
| * This method can be called any time after the references were set. See |
| * <code>addReferencesToSign()</code>. |
| * |
| * @throws WSSecurityException |
| */ |
| public void computeSignature() throws WSSecurityException { |
| WSDocInfoStore.store(wsDocInfo); |
| try { |
| if (keyIdentifierType == WSConstants.UT_SIGNING || |
| keyIdentifierType == WSConstants.CUSTOM_SYMM_SIGNING) { |
| sig.sign(sig.createSecretKey(secretKey)); |
| } else { |
| sig.sign(crypto.getPrivateKey(user, password)); |
| } |
| signatureValue = sig.getSignatureValue(); |
| } catch (XMLSignatureException e1) { |
| throw new WSSecurityException(WSSecurityException.FAILED_SIGNATURE, |
| null, null, e1); |
| } catch (Exception e1) { |
| throw new WSSecurityException(WSSecurityException.FAILED_SIGNATURE, |
| null, null, e1); |
| } finally { |
| WSDocInfoStore.delete(wsDocInfo); |
| } |
| |
| } |
| |
| /** |
| * Builds a signed soap envelope. |
| * |
| * This is a convenience method and for backward compatibility. The method |
| * creates a Signature and puts it into the Security header. It does so by |
| * calling the single functions in order to perform a <i>one shot signature</i>. |
| * This method is compatible with the build method of the previous version |
| * with the exception of the additional WSSecHeader parameter. |
| * |
| * @param doc |
| * The unsigned SOAP envelope as <code>Document</code> |
| * @param cr |
| * An instance of the Crypto API to handle keystore and |
| * certificates |
| * @param secHeader |
| * the security header element to hold the encrypted key element. |
| * @return A signed SOAP envelope as <code>Document</code> |
| * @throws WSSecurityException |
| */ |
| public Document build(Document doc, Crypto cr, WSSecHeader secHeader) |
| throws WSSecurityException { |
| doDebug = log.isDebugEnabled(); |
| |
| if (doDebug) { |
| log.debug("Beginning signing..."); |
| } |
| |
| prepare(doc, cr, secHeader); |
| |
| SOAPConstants soapConstants = WSSecurityUtil.getSOAPConstants(doc |
| .getDocumentElement()); |
| |
| if (parts == null) { |
| parts = new Vector(); |
| WSEncryptionPart encP = new WSEncryptionPart(soapConstants |
| .getBodyQName().getLocalPart(), soapConstants |
| .getEnvelopeURI(), "Content"); |
| parts.add(encP); |
| } |
| |
| addReferencesToSign(parts, secHeader); |
| |
| prependToHeader(secHeader); |
| |
| /* |
| * if we have a BST prepend it in front of the Signature according to |
| * strict layout rules. |
| */ |
| if (bstToken != null) { |
| prependBSTElementToHeader(secHeader); |
| } |
| |
| computeSignature(); |
| |
| return (doc); |
| } |
| |
| protected Element createSTRParameter(Document doc) { |
| Element transformParam = doc.createElementNS(WSConstants.WSSE_NS, |
| WSConstants.WSSE_PREFIX + ":TransformationParameters"); |
| |
| WSSecurityUtil.setNamespace(transformParam, WSConstants.WSSE_NS, |
| WSConstants.WSSE_PREFIX); |
| |
| Element canonElem = doc.createElementNS(WSConstants.SIG_NS, |
| WSConstants.SIG_PREFIX + ":CanonicalizationMethod"); |
| |
| WSSecurityUtil.setNamespace(canonElem, WSConstants.SIG_NS, |
| WSConstants.SIG_PREFIX); |
| |
| canonElem.setAttributeNS(null, "Algorithm", |
| Canonicalizer.ALGO_ID_C14N_EXCL_OMIT_COMMENTS); |
| transformParam.appendChild(canonElem); |
| return transformParam; |
| } |
| |
| protected Set getInclusivePrefixes(Element target) { |
| return getInclusivePrefixes(target, true); |
| } |
| |
| protected Set getInclusivePrefixes(Element target, boolean excludeVisible) { |
| Set result = new HashSet(); |
| Node parent = target; |
| NamedNodeMap attributes; |
| Node attribute; |
| while (!(parent.getParentNode() instanceof Document)) { |
| parent = parent.getParentNode(); |
| attributes = parent.getAttributes(); |
| for (int i = 0; i < attributes.getLength(); i++) { |
| attribute = attributes.item(i); |
| if (attribute.getNamespaceURI() != null |
| && attribute.getNamespaceURI().equals( |
| org.apache.ws.security.WSConstants.XMLNS_NS)) { |
| if (attribute.getNodeName().equals("xmlns")) { |
| result.add("#default"); |
| } else { |
| result.add(attribute.getLocalName()); |
| } |
| } |
| } |
| } |
| |
| if (excludeVisible == true) { |
| attributes = target.getAttributes(); |
| for (int i = 0; i < attributes.getLength(); i++) { |
| attribute = attributes.item(i); |
| if (attribute.getNamespaceURI() != null |
| && attribute.getNamespaceURI().equals( |
| org.apache.ws.security.WSConstants.XMLNS_NS)) { |
| if (attribute.getNodeName().equals("xmlns")) { |
| result.remove("#default"); |
| } else { |
| result.remove(attribute.getLocalName()); |
| } |
| } |
| if (attribute.getPrefix() != null) { |
| result.remove(attribute.getPrefix()); |
| } |
| } |
| |
| if (target.getPrefix() == null) { |
| result.remove("#default"); |
| } else { |
| result.remove(target.getPrefix()); |
| } |
| } |
| |
| return result; |
| } |
| |
| public void setSecretKey(byte[] secretKey) { |
| this.secretKey = secretKey; |
| } |
| |
| public void setCustomTokenValueType(String customTokenValueType) { |
| this.customTokenValueType = customTokenValueType; |
| } |
| |
| public void setCustomTokenId(String customTokenId) { |
| this.customTokenId = customTokenId; |
| } |
| |
| |
| } |