//************************************************************************** // Filename : WsseHeaderToken.java, WSSE Toolkit 2005 // // Author : Denis Pilipchuk // // Purpose : Represents WSSE Security elements. They can be created either // from scratch, or from exisitng XML elements. // // Disclaimer: This software is provided "as-is" and does not imply // any warranty or responsibility. //**************************************************************************** package wsse.Toolkit.Tokens.Wss; import java.util.ArrayList; // W3C DOM includes import org.w3c.dom.Document; import org.w3c.dom.Element; import wsse.Toolkit.Processors.ITokenProcessor; import wsse.Toolkit.Processors.WsProcessorException; import wsse.Toolkit.Tokens.WsCompositeToken; import wsse.Toolkit.Tokens.WsToken; import wsse.Toolkit.Tokens.WsTokenException; import wsse.Toolkit.Tokens.WsTokenHelper; import wsse.Toolkit.Tokens.Refs.WsTokenRef; import wsse.Toolkit.Utils.Xml.XmlQName; import wsse.Toolkit.Utils.Xml.XmlConstants; import wsse.Toolkit.Utils.Xml.XmlDocException; public class WsseHeaderToken extends WsCompositeToken { public WsseHeaderToken() { } // This constructor accepts an existing header XML element. public WsseHeaderToken(Element token) throws WsTokenException { super(token); } /////////////////////////////////////////////////////////////////////// // Specific helpers public void AddSignature(WsToken[] tokens) { } public void AddSignature(WsTokenRef[] refTokens) { } public void AddEncryption(WsToken[] tokens) { } public void AddEncryption(WsTokenRef[] refTokens) { } public TsToken AddTimestamp(int duration) throws WsTokenException { TsToken ts = new TsToken(duration); // Add only if it's not inserted yet return EnsureToken(ts, false) ? ts : null; } // If it's a new header - this method creates an envelope, // otherwise - it navigates to the envelope node and returns it. public Element GetSoapEnvelope() throws WsTokenException { Element soapEnv = null, wsse = GetXml(true); assert null != wsse : "XML for WSSE Header should be generated"; Document doc = wsse.getOwnerDocument(); WsTokenHelper tokenHelper = GetTokenHelper(); assert null != tokenHelper:"Token helper should be set"; assert null != doc && tokenHelper.GetTokenDocument() == doc : "Token must have a valid document"; Element docElement = doc.getDocumentElement(); XmlQName envName = new XmlQName(XmlConstants.SOAP_ENVELOPE_ELEM_NAME, XmlConstants.SOAP_11_NAMESPACE_URI, XmlConstants.SOAP_NAMESPACE_PREFIX); XmlQName hdrName = new XmlQName(XmlConstants.SOAP_HEADER_ELEM_NAME, XmlConstants.SOAP_11_NAMESPACE_URI, XmlConstants.SOAP_NAMESPACE_PREFIX); XmlQName bodyName = new XmlQName(XmlConstants.SOAP_BODY_ELEM_NAME, XmlConstants.SOAP_11_NAMESPACE_URI, XmlConstants.SOAP_NAMESPACE_PREFIX); Element soapHdr = null, soapBody = null; if (null != docElement) { Element[] envelopes = WsTokenHelper.FindXmlElements(docElement, envName); // There should be either none, or exactly one assert null != envelopes && envelopes.length < 2; if (envelopes.length > 0) { // There's a SOAP envelope already present soapEnv = envelopes[0]; // Look for a SOAP Header node now - create it if it's not present Element[] headers = WsTokenHelper.FindXmlElements(docElement,hdrName); assert null != headers && headers.length < 2; soapHdr = headers.length > 0 ? headers[0] : null; Element[] bodies = WsTokenHelper.FindXmlElements(docElement,bodyName); assert null != bodies && bodies.length < 2; soapBody = bodies.length > 0 ? bodies[0] : null; } } // Make sure SOAP envelope is present, add it directly to the document otherwise if (null == soapEnv) { // Need to create a new SOAP envelope soapEnv = tokenHelper.CreateXmlElement(envName); // Add namespace declarations soapEnv.setAttributeNS(XmlConstants.XML_NAMESPACE_URI, XmlConstants.XML_XSD_ATTR_WITH_NS, XmlConstants.XML_XSD_NAMESPACE_URI); soapEnv.setAttributeNS(XmlConstants.XML_NAMESPACE_URI, XmlConstants.XML_XSI_ATTR_WITH_NS, XmlConstants.XML_XSI_NAMESPACE_URI); doc.appendChild(soapEnv); } assert null != soapEnv; // Make sure SOAP Header is present, add it if not if (null == soapHdr) { soapHdr = tokenHelper.CreateXmlElement(hdrName); soapEnv.appendChild(soapHdr); } // Make sure SOAP Body is present, add it if not if (null == soapBody) { soapBody = tokenHelper.CreateXmlElement(bodyName); soapEnv.appendChild(soapBody); } assert null != soapHdr; // Make sure that the SOAP header is the parent of WSSE header if (soapHdr != wsse.getParentNode()) { // The WSSE Header is not a child of the SOAP Header - move it as appropriate soapHdr.appendChild(wsse); } return soapEnv; } /////////////////////////////////////////////////////////////////////// // General helpers for extensibility public void AddProcessor(ITokenProcessor processor) { if (null == processor) { throw new NullPointerException("Null processor passed: " + this); } m_processors.add(processor); } public void ProcessHeader() throws WsTokenException { // Apply the processors int i = 0; try { for (; i < m_processors.size(); i++) { ITokenProcessor processor = (ITokenProcessor) m_processors.get(i); processor.ProcessTokens(this); } } catch (WsProcessorException ex) { throw new WsTokenException("Error applying processor number " + i, this, ex); } } /////////////////////////////////////////////////////////////////////// // Overriden methods protected Element GenerateTokenXml() throws WsTokenException { // Called to generate a WSSE header WsTokenHelper tokenHelper = GetTokenHelper(); assert null != tokenHelper:"Token helper should be set"; Element token = tokenHelper.CreateXmlElement( new XmlQName(XmlConstants.WSSE_SECURITY_ELEM_NAME, XmlConstants.WSSEC_WSSE_NAMESPACE_URI, XmlConstants.WSSEC_WSSE_NAMESPACE_PREFIX)); // Add necessary namespace declarations token.setAttributeNS(XmlConstants.XML_NAMESPACE_URI, XmlConstants.XML_WSU_ATTR_WITH_NS, XmlConstants.WSSEC_WSU_NAMESPACE_URI); token.setAttributeNS(XmlConstants.XML_NAMESPACE_URI, XmlConstants.XML_SAML_ATTR_WITH_NS, XmlConstants.SAML_10_ASSERTION_NAMESPACE_URI); return token; } protected void VerifyCompositeElement(Element token) throws WsTokenException { assert null != token:"Validated element should not be null"; // TODO: shallow verification of validity of the passed WSSE header } private ArrayList m_processors = new ArrayList(); }