[WSS4J] wss4j/src/org/apache/ws/security/transform STRTransform.java,1.2,1.3
[email protected] Tue, 10 Feb 2004 07:22:21 -0800
| Newsgroups | gmane.text.xml.wss4j |
|---|---|
| Message-ID | <[email protected]> |
Update of /cvsroot/wss4j/wss4j/src/org/apache/ws/security/transform
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv5988/src/org/apache/ws/security/transform
Modified Files:
STRTransform.java
Log Message:
First working version of STRTransform with limited functionality. Only
direct references are supported yet. But all hooks are in place,
STRTransfrom is registered, and gets called, XML setup seems to be
ok. Refer to inline documentation of STRTransform.java
Index: STRTransform.java
===================================================================
RCS file: /cvsroot/wss4j/wss4j/src/org/apache/ws/security/transform/STRTransform.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- STRTransform.java 9 Feb 2004 16:10:28 -0000 1.2
+++ STRTransform.java 10 Feb 2004 15:22:19 -0000 1.3
@@ -60,24 +60,37 @@
import org.apache.ws.security.WSDocInfo;
import org.apache.ws.security.WSDocInfoStore;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSSecurityException;
+import org.apache.ws.security.message.token.Reference;
+import org.apache.ws.security.message.token.SecurityTokenReference;
+
+import org.apache.ws.security.util.WSSecurityUtil;
+
import java.io.IOException;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
-import java.io.InputStream;
-import java.util.Set;
-import java.util.Iterator;
import org.apache.xml.security.signature.XMLSignatureInput;
import org.apache.xml.security.exceptions.XMLSecurityException;
-import org.apache.xml.security.utils.Constants;
-import org.apache.xml.security.c14n.*;
-import org.apache.xml.security.c14n.implementations.*;
-import org.apache.xml.security.transforms.*;
-import org.apache.xml.security.transforms.params.InclusiveNamespaces;
+import org.apache.xml.security.c14n.Canonicalizer;
+import org.apache.xml.security.c14n.CanonicalizationException;
+import org.apache.xml.security.c14n.InvalidCanonicalizerException;
+import org.apache.xml.security.transforms.TransformSpi;
+import org.apache.xml.security.utils.XMLUtils;
+import org.apache.xpath.XPathAPI;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.TransformerException;
+
import org.xml.sax.SAXException;
-import org.w3c.dom.*;
+import org.w3c.dom.Node;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Document;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -97,6 +110,8 @@
private static Log log = LogFactory.getLog(STRTransform.class.getName());
private static boolean doDebug = false;
+
+ private WSDocInfo wsDocInfo = null;
public boolean wantsOctetStream() {
return false;
@@ -137,121 +152,212 @@
log.debug("Beginning STRTransform..." + input.toString());
}
- try {
-
- Document doc = this._transformObject.getDocument();
- int docHash = doc.hashCode();
- if (doDebug) {
- log.debug("doc: " + doc.toString() + ", " + docHash);
- }
- WSDocInfo wsDocInfo = WSDocInfoStore.lookup(docHash);
- if (wsDocInfo == null) {
- throw (new CanonicalizationException("no WSDocInfo found"));
- }
-
- /*
- InputStream is = input.getOctetStream();
-
- byte buf[] = new byte[is.available()];
- is.read(buf, 0, buf.length);
- ByteArrayOutputStream bos = new ByteArrayOutputStream(buf.length);
- bos.write(buf, 0, buf.length);
- if (doDebug) {
- log.debug("input bos: " + bos.toString());
- }
- */
+ try {
- /*
- * According to the OASIS WS Specification
- *
- * "Web Services Security: SOAP Message Security 1.0"
- * Monday, 19 January 2004
- *
- * in chapter 8.3 the input node set
- * must handed over to the c14n that is specified in the
- * argument element of the STRTransform element.
- *
- * First step: Get the required c14n argument. After that, get the
- * c14n, feed the node set an get back the byte[]. The byte[]
- * contains the XML doc excerpt to be verified/processed.
- *
- * Second step: find the STR element inside the resulting XML doc,
- * check if STR contains some reference to an security token.
- * As per OASIS WS specification this shall be a X509SubjectKeyIdentifier
- * (SKI) that points to a security token.
- * (are other reference types also possible/allowed?)
- *
- * Third step: locate the security token referenced by the STR
- * element. Either the Token is contained in the document as a
- * BinarySecurityToken or stored in some key storage. The WSDocInfo
- * contains the implementation of the key storage to use. To locate
- * a BST inside a document check if a BST was already found and the
- * element stored in WSDocInfo.
- *
- * Forth step: after security token was located, prepare it. Either
- * copy (clone) the BinarySeciurityToken or wrap the located token
- * in a newly created BST element as specified in WS Specification.
- *
- * Fifth step: replace the STR with the above create/copied BST, feed
- * this result in the specified c14n method and return this to
- * the caller.
- *
- */
-
- /*
- * NOTE: The followig code is debug, not a real STR Transform
- */
- Set nodeSet = input.getNodeSet();
- Iterator iter = nodeSet.iterator();
-
- while (iter.hasNext()) {
- Object obj = iter.next();
+ /*
+ * Get the main document, that is the complete SOAP request document
+ */
+ Document thisDoc = this._transformObject.getDocument();
+ int docHash = thisDoc.hashCode();
+ if (doDebug) {
+ log.debug("doc: " + thisDoc.toString() + ", " + docHash);
+ }
+ /*
+ * Her we get some information about the document that is being processed,
+ * in partucular the crypto implementation, and already detected BST that
+ * may be used later during dereferencing.
+ */
+ wsDocInfo = WSDocInfoStore.lookup(docHash);
+ if (wsDocInfo == null) {
+ throw (new CanonicalizationException("no WSDocInfo found"));
+ }
+
+ /*
+ * According to the OASIS WS Specification
+ * "Web Services Security: SOAP Message Security 1.0"
+ * Monday, 19 January 2004, chapter 8.3 describes that
+ * the input node set must be processed bythe c14n that
+ * is specified in the argument element of the STRTransform
+ * element.
+ *
+ * First step: Get the required c14n argument. After that, get
+ * the c14n, feed the node set into c14n and get back the byte[].
+ * The byte[] contains the XML doc part to be
+ * signed or verified. Then reparse the byte[] to get the DOM.
+ */
+
+ String canonAlgo = null;
+ if (this
+ ._transformObject
+ .length(WSConstants.WSSE_NS, "TransformationParameters")
+ == 1) {
+ Element tmpE =
+ this._transformObject.getChildElementLocalName(
+ 0,
+ WSConstants.WSSE_NS,
+ "TransformationParameters");
+ Element canonElem =
+ (Element) WSSecurityUtil.getDirectChild(
+ tmpE,
+ "CanonicalizationMethod",
+ WSConstants.SIG_NS);
+ canonAlgo = canonElem.getAttribute("Algorithm");
+ if (doDebug) {
+ log.debug("CanonAlgo: " + canonAlgo);
+ }
+ }
+ Canonicalizer canon = Canonicalizer.getInstance(canonAlgo);
+ byte buf[] = canon.canonicalizeXPathNodeSet(input.getNodeSet());
+
+ ByteArrayOutputStream bos = new ByteArrayOutputStream(buf.length);
+ bos.write(buf, 0, buf.length);
+
if (doDebug) {
- log.debug("Node: " + obj.toString());
+ log.debug("canon bos: " + bos.toString());
}
- }
-
- InclusiveNamespaces inclusiveNamespaces = null;
- if (this._transformObject
- .length(InclusiveNamespaces
- .ExclusiveCanonicalizationNamespace, InclusiveNamespaces
- ._TAG_EC_INCLUSIVENAMESPACES) == 1) {
- Element inclusiveElement =
- this._transformObject.getChildElementLocalName(0,
- InclusiveNamespaces.ExclusiveCanonicalizationNamespace,
- InclusiveNamespaces._TAG_EC_INCLUSIVENAMESPACES);
+ DocumentBuilderFactory dfactory =
+ DocumentBuilderFactory.newInstance();
+ dfactory.setValidating(false);
+ dfactory.setNamespaceAware(true);
- inclusiveNamespaces = new InclusiveNamespaces(inclusiveElement,
- this._transformObject.getBaseURI());
- }
+ DocumentBuilder db = dfactory.newDocumentBuilder();
- Canonicalizer20010315ExclOmitComments c14n =
- new Canonicalizer20010315ExclOmitComments();
+ Document doc =
+ db.parse(new ByteArrayInputStream(bos.toByteArray()));
- if (input.isOctetStream()) {
- return new XMLSignatureInput(c14n
- .engineCanonicalize(input.getBytes()));
- } else {
- if (inclusiveNamespaces == null) {
- return new XMLSignatureInput(c14n
- .engineCanonicalizeXPathNodeSet(input.getNodeSet()));
- } else {
- return new XMLSignatureInput(c14n
- .engineCanonicalizeXPathNodeSet(input
- .getNodeSet(), inclusiveNamespaces
- .getInclusiveNamespaces()));
- }
- }
- } catch (IOException ex) {
- throw new CanonicalizationException("empty", ex);
- } catch (ParserConfigurationException ex) {
- throw new CanonicalizationException("empty", ex);
- } catch (XMLSecurityException ex) {
- throw new CanonicalizationException("empty", ex);
- } catch (SAXException ex) {
- throw new CanonicalizationException("empty", ex);
- }
- }
+ /*
+ * Second step: find the STR element inside the resulting XML doc,
+ * check if STR contains some reference to an security token.
+ */
+
+ NodeList nodeList =
+ doc.getElementsByTagNameNS(
+ WSConstants.WSSE_NS,
+ "SecurityTokenReference");
+
+ int length = nodeList.getLength();
+
+ Element str = null;
+ /*
+ * loop over all STR elements
+ */
+ for (int i = 0; i < length; i++) {
+ Element tmpEl = (Element) nodeList.item(i);
+ if (doDebug) {
+ log.debug("STR: " + tmpEl.toString());
+ }
+ /*
+ * Third and forht step are performed by derefenceSTR()
+ */
+
+ str = dereferenceSTR(thisDoc, (Element) tmpEl);
+ /*
+ * Keep in mind: the returned element belong to "thisDoc", thus
+ * import it to "doc" before replace it.
+ */
+
+ /*
+ * Fifth step: replace the STR with the above created/copied BST, feed
+ * this result in the specified c14n method and return this to
+ * the caller.
+ *
+ */
+ str = (Element) doc.importNode(str, true);
+ Node parent = tmpEl.getParentNode();
+ parent.replaceChild(str, tmpEl);
+ }
+ /*
+ * Convert resulting STR result doc into NodeList, then c14n
+ */
+ XMLUtils.circumventBug2650(doc); // This is needed
+
+ nodeList =
+ XPathAPI.selectNodeList(
+ doc.getDocumentElement(),
+ Canonicalizer.XPATH_C14N_WITH_COMMENTS_SINGLE_NODE);
+
+ buf =
+ canon.canonicalizeXPathNodeSet(
+ XMLUtils.convertNodelistToSet(nodeList));
+
+ if (doDebug) {
+ bos = new ByteArrayOutputStream(buf.length);
+ bos.write(buf, 0, buf.length);
+ log.debug("result bos: " + bos.toString());
+ }
+ return new XMLSignatureInput(buf);
+
+ } catch (IOException ex) {
+ throw new CanonicalizationException("empty", ex);
+ } catch (ParserConfigurationException ex) {
+ throw new CanonicalizationException("empty", ex);
+ } catch (XMLSecurityException ex) {
+ throw new CanonicalizationException("empty", ex);
+ } catch (SAXException ex) {
+ throw new CanonicalizationException("empty", ex);
+ } catch (TransformerException ex) {
+ throw new CanonicalizationException("empty", ex);
+ }
+ }
+
+ private Element dereferenceSTR(Document doc, Element tmpE)
+ throws WSSecurityException {
+
+ /*
+ * Third step: locate the security token referenced by the STR
+ * element. Either the Token is contained in the document as a
+ * BinarySecurityToken or stored in some key storage. The WSDocInfo
+ * contains the implementation of the key storage to use. To locate
+ * a BST inside a document check if a BST was already found and the
+ * element stored in WSDocInfo.
+ *
+ * As per OASIS WS specification this shall be a X509SubjectKeyIdentifier
+ * (SKI) that points to a security token.
+ * (are other reference types also possible/allowed?)
+ *
+ *
+ * Forth step: after security token was located, prepare it. Either
+ * return BinarySeciurityToken or wrap the located token
+ * in a newly created BST element as specified in WS Specification.
+ *
+ * Note: every element (also newly created elemets) belong to the
+ * document defined by the parameter. This is the main SOAP document
+ * and _not_ the document part that is to be signed/verified. Thus
+ * the caller must import the returned element into the document
+ * part that is signed/verified.
+ *
+ */
+ SecurityTokenReference secRef = null;
+ Element tokElement = null;
+
+ secRef = new SecurityTokenReference(tmpE);
+
+ /*
+ * First case: direct reference, according to chap 7.2 of OASIS
+ * WS specification (main document)
+ */
+ if (secRef.containsReference()) {
+ log.debug("Found str reference");
+ Reference ref = secRef.getReference();
+ String uri = ref.getURI();
+ if (doDebug) {
+ log.debug("Token reference uri: " + uri);
+ }
+ if (uri == null) {
+ throw new WSSecurityException(
+ WSSecurityException.INVALID_SECURITY,
+ "badReferenceURI");
+ }
+ tokElement = WSSecurityUtil.getElementByWsuId(doc, uri);
+ if (tokElement == null) {
+ throw new WSSecurityException(
+ WSSecurityException.SECURITY_TOKEN_UNAVAILABLE,
+ "noToken",
+ new Object[] { uri });
+ }
+ }
+ return (Element) tokElement;
+ }
}
-------------------------------------------------------
The SF.Net email is sponsored by EclipseCon 2004
Premiere Conference on Open Tools Development and Integration
See the breadth of Eclipse activity. February 3-5 in Anaheim, CA.
http://www.eclipsecon.org/osdn