You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@santuario.apache.org by mu...@apache.org on 2007/09/07 16:40:20 UTC

svn commit: r573598 - /xml/security/branches/stax_jsr105/src/com/r_bg/stax/XMLSignatureWorker.java

Author: mullan
Date: Fri Sep  7 07:40:20 2007
New Revision: 573598

URL: http://svn.apache.org/viewvc?rev=573598&view=rev
Log:
Lots of changes ...
- added support for base URI and relative Reference URIs.
- added support for "http:" Reference URIs
- added support for "file:" Reference URIs
- removed all calls to XMLStreamReader.getElementText() since it messes up
  the ordering of the StaxWorkers; instead use XMLStreamReader.getText().


Modified:
    xml/security/branches/stax_jsr105/src/com/r_bg/stax/XMLSignatureWorker.java

Modified: xml/security/branches/stax_jsr105/src/com/r_bg/stax/XMLSignatureWorker.java
URL: http://svn.apache.org/viewvc/xml/security/branches/stax_jsr105/src/com/r_bg/stax/XMLSignatureWorker.java?rev=573598&r1=573597&r2=573598&view=diff
==============================================================================
--- xml/security/branches/stax_jsr105/src/com/r_bg/stax/XMLSignatureWorker.java (original)
+++ xml/security/branches/stax_jsr105/src/com/r_bg/stax/XMLSignatureWorker.java Fri Sep  7 07:40:20 2007
@@ -3,8 +3,14 @@
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.OutputStream;
+import java.io.File;
+import java.io.FileInputStream;
 import java.io.InputStream;
+import java.io.IOException;
 import java.math.BigInteger;
+import java.net.URI;
+import java.net.URL;
+import java.net.URLConnection;
 import java.security.KeyException;
 import java.security.KeyFactory;
 import java.security.MessageDigest;
@@ -33,6 +39,7 @@
 import javax.xml.crypto.dsig.keyinfo.RetrievalMethod;
 import javax.xml.crypto.dsig.keyinfo.X509Data;
 import javax.xml.crypto.dsig.keyinfo.X509IssuerSerial;
+import javax.xml.stream.XMLInputFactory;
 import javax.xml.stream.XMLStreamException;
 import javax.xml.stream.XMLStreamReader;
 
@@ -59,6 +66,10 @@
 	private String id;
 	private String type;
 	List<Transform> transforms = new ArrayList<Transform>();
+	private String baseURI;
+	ReferenceWorker(String baseURI) {
+	    this.baseURI = baseURI;
+	}
 	public StaxWorker read(XMLStreamReader reader) {
 		switch (reader.getEventType()) {
 		
@@ -111,12 +122,77 @@
 		return null;
 	}
 	public StaxWatcher remove() {		
-	    if (uri != null && uri.startsWith("#")) {
-		return new IdWatcher(uri.substring(1), this, transforms, os);
-//		return new IdWatcher(uri.substring(1),this,transforms,System.out);
-	    } else {
-		return null;
-	    }
+	    if (uri != null) {
+		if (uri.startsWith("#")) {
+		    return new IdWatcher(uri.substring(1), this, transforms, os);
+//		    return new IdWatcher(uri.substring(1),this,transforms,System.out);
+		} else if (uri.isEmpty()) {
+		    System.out.println("enveloped");
+//		    return new EnvelopedIdWatcher(transforms, os);
+		} else if (uri.startsWith("http:") ||
+		    (baseURI != null && baseURI.startsWith("http:"))) {
+		    try {
+			URLConnection uc = null;
+		        if (baseURI != null) {
+		            uc = new URL(new URL(baseURI),uri).openConnection();
+			} else {
+		            uc = new URL(uri).openConnection();
+			}
+			InputStream is = uc.getInputStream();
+                        if (!transforms.isEmpty()) {
+                            // only Base64 supported right now ...
+			    try {
+                                Base64.decode(is, os);
+			    } catch (Base64DecodingException e) {
+				e.printStackTrace();
+			    }
+			} else {
+         		    byte buf[] = new byte[4096];
+         		    int read = 0;
+         		    while ((read = is.read(buf)) >= 0) {
+            		        os.write(buf, 0, read);
+         		    }
+			}
+			setResult(null);
+
+		    } catch (IOException e) {
+			e.printStackTrace();
+		    }
+		} else if (uri.startsWith("file:") ||
+		    (baseURI != null && baseURI.startsWith("file:"))) {
+		    try {
+		        URI fileURI = null;
+		        if (baseURI != null) {
+			    fileURI = new URI(baseURI).resolve(uri);
+		        } else {
+			    fileURI = new URI(uri);
+		        }
+		        FileInputStream fs = new FileInputStream(new File(fileURI));
+			XMLInputFactory xif = XMLInputFactory.newInstance();
+			XMLStreamReader re = xif.createXMLStreamReader(fs);
+			while (re.getEventType() != XMLStreamReader.END_DOCUMENT) {
+//			    System.out.println(re.getEventType());
+/*
+                        if (transforms.isEmpty()) {
+                            return new C14nWorker(re, os, false);
+                        }
+*/
+                            for (Transform t : transforms) {
+                                // Only one Transform supported right now
+                                t.transform(new StaxData(re), null, os);
+//                                t.transform(new StaxData(re), null, System.out);
+				break;
+			    }
+			    re.next();
+                        }
+
+			setResult(null);
+		    } catch (Exception e) {
+			e.printStackTrace();
+		    }
+		}
+	    } 
+	    return null;
 	}
 	/* (non-Javadoc)
 	 * @see com.r_bg.stax.DigestResultListener#setResult(byte[])
@@ -177,19 +253,23 @@
 	ByteArrayOutputStream bos=new ByteArrayOutputStream(); 
 	byte[] canonData;
 	boolean initial=true;
-	C14nWorker c14n=new C14nWorker(this,bos);
-//	C14nWorker c14n=new C14nWorker(this,System.out);
+	C14nWorker c14n=new C14nWorker(this, bos, false);
+//	C14nWorker c14n=new C14nWorker(this, System.out, false);
 	List<ReferenceWorker> references=new ArrayList<ReferenceWorker>();
 	StaxSignatureMethod signatureMethod;
 	String c14nMethod;
 	private String id;
+	private String baseURI;
+	SignedInfoWorker(String baseURI) {
+	    this.baseURI = baseURI;
+	}
 	public StaxWorker read(XMLStreamReader reader) {
 		if (reader.getEventType()==XMLStreamReader.START_ELEMENT && Constants.DS_URI.equals(reader.getNamespaceURI())) {
 			String name=reader.getLocalName();
 			if (name.equals("SignedInfo") ) {
 				id=reader.getAttributeValue(null,"Id");
 			} else if (name.equals("Reference") ) {
-				ReferenceWorker r=new ReferenceWorker();
+				ReferenceWorker r=new ReferenceWorker(baseURI);
 				references.add(r);
 				return r;			
 			} else if (name.equals("SignatureMethod")) {
@@ -263,18 +343,21 @@
 	
 }
 class SignatureWatcher implements StaxWatcher {	
-	public StaxWorker watch(XMLStreamReader reader, StaxSignatureValidator sig) {
-		String name=reader.getLocalName();
-		String uri=reader.getNamespaceURI();
-		if (name.equals("Signature") && 
-				uri.equals(Constants.DS_URI)) {			
-			XMLSignatureWorker s=new XMLSignatureWorker();
-			sig.addSignature(s);
-			return s;
-		}
-		
-		return null;
+    private StaxValidateContext context;
+    SignatureWatcher(StaxValidateContext context) {
+	this.context = context;
+    }
+    public StaxWorker watch(XMLStreamReader reader, StaxSignatureValidator sig) {
+	String name=reader.getLocalName();
+	String uri=reader.getNamespaceURI();
+	if (name.equals("Signature") && uri.equals(XMLSignature.XMLNS)) {
+	    XMLSignatureWorker s = new XMLSignatureWorker(context.getBaseURI());
+	    sig.addSignature(s);
+	    return s;
 	}
+		
+	return null;
+    }
 }
 
 class SignatureValueWorker implements StaxWorker,XMLSignature.SignatureValue {		
@@ -424,6 +507,8 @@
 class X509DataWorker implements StaxWorker, X509Data {		
     private List content = new ArrayList();
     private CertificateFactory cf; 
+    private boolean readSN, readSki, readISName, readSerial, readCert, readCRL;
+    private String issuer;
 
     public StaxWorker read(XMLStreamReader reader) {
 	switch (reader.getEventType()) {
@@ -431,51 +516,80 @@
 		if(Constants.DS_URI.equals(reader.getNamespaceURI())) {
 		    String name = reader.getLocalName();
 		    if (name.equals("X509SubjectName")) {
-			try {
-			    content.add(reader.getElementText());
-			} catch (XMLStreamException xse) {
-			    xse.printStackTrace();
-			}
+			readSN = true;
 		    } else if (name.equals("X509SKI")) {
-			try {
-			    byte[] ski = Base64.decode(reader.getElementText());
-			    content.add(ski);
-			} catch (Exception e) {
-			    e.printStackTrace();
-			}
+			readSki = true;
+		    } else if (name.equals("X509IssuerName")) {
+			readISName = true;
 		    } else if (name.equals("X509IssuerSerial")) {
-			content.add(new X509IssuerSerial() {
-			    public String getIssuerName() {
-				return null;
-			    }
-			    public BigInteger getSerialNumber() {
-				return null;
-			    }
-			    public boolean isFeatureSupported(String feature) {
-				return false;
-			    }
-			});
+			readSerial = true;
 		    } else if (name.equals("X509Certificate")) {
-			try {
-			    byte[] cert = Base64.decode(reader.getElementText());
-			    if (cf == null) {
-    				cf = CertificateFactory.getInstance("X.509");
-			    }
-			    content.add(cf.generateCertificate(new ByteArrayInputStream(cert)));
-			} catch (Exception e) {
-			    e.printStackTrace();
-			}
+			readCert = true;
 		    } else if (name.equals("X509CRL")) {
-			try {
-			    byte[] crl = Base64.decode(reader.getElementText());
-			    if (cf == null) {
-    				cf = CertificateFactory.getInstance("X.509");
-			    }
-			    content.add(cf.generateCRL(new ByteArrayInputStream(crl)));
-			} catch (Exception e) {
-			    e.printStackTrace();
-			}
+			readCRL = true;
+		    }
+		}
+		break;
+	    case XMLStreamReader.CHARACTERS:
+		String text = reader.getText();
+		if (readSN) {
+		    content.add(text);
+		    readSN = false;
+		} else if (readISName) {
+		    issuer = text;
+		    readISName = false;
+		} else if (readSerial) {
+		    byte[] bytes = null;
+		    try {
+			bytes = Base64.decode(text);
+		    } catch (Base64DecodingException e) {
+			e.printStackTrace();
+		    }
+		    final BigInteger serial = new BigInteger(1, bytes);
+	            content.add(new X509IssuerSerial() {
+		        public String getIssuerName() {
+		            return issuer;
+		        }
+		        public BigInteger getSerialNumber() {
+		            return serial;
+		        }
+		        public boolean isFeatureSupported(String feature) {
+		            return false;
+		        }
+		    });
+		    readSerial = false;
+		} else if (readSki) {
+		    try {
+		        byte[] ski = Base64.decode(text);
+		        content.add(ski);
+		    } catch (Base64DecodingException e) {
+		        e.printStackTrace();
+		    }
+		    readSki = false;
+		} else if (readCert) {
+		    try {
+		        byte[] cert = Base64.decode(text);
+		        if (cf == null) {
+    			    cf = CertificateFactory.getInstance("X.509");
+		        }
+		        content.add(cf.generateCertificate
+			    (new ByteArrayInputStream(cert)));
+		    } catch (Exception e) {
+		        e.printStackTrace();
+		    }
+		    readCert = false;
+		} else if (readCRL) {
+		    try {
+		        byte[] crl = Base64.decode(text);
+		        if (cf == null) {
+    			    cf = CertificateFactory.getInstance("X.509");
+		        }
+		        content.add
+			    (cf.generateCRL(new ByteArrayInputStream(crl)));
+		    } catch (Exception e) {
+		        e.printStackTrace();
 		    }
+		    readCRL = false;
 		}
 		break;
 	}
@@ -491,10 +605,52 @@
 	return false;
     }
 }
+
+class RetrievalMethodWorker implements StaxWorker, RetrievalMethod {
+    private String uri, type;
+    private List<Transform> transforms = new ArrayList<Transform>();
+    public StaxWorker read(XMLStreamReader reader) {
+	switch (reader.getEventType()) {
+	    case XMLStreamReader.START_ELEMENT: 
+		if(Constants.DS_URI.equals(reader.getNamespaceURI())) {
+		    String name = reader.getLocalName();
+		    if (name.equals("RetrievalMethod") ) {
+			uri = reader.getAttributeValue(null, "URI");
+			type = reader.getAttributeValue(null, "Type");
+		    } else if (name.equals("Transform")) {
+			StaxTransform t = new StaxTransform();
+			transforms.add(t);
+			return t;
+		    }
+		}
+		break;
+	}
+        return null;
+    }
+    public StaxWatcher remove() {
+	return null;
+    }
+    public List getTransforms() {
+	return Collections.unmodifiableList(transforms);
+    }
+    public String getType() {
+	return type;
+    }
+    public String getURI() {
+	return uri;
+    }
+    public Data dereference(XMLCryptoContext context) {
+	throw new UnsupportedOperationException();
+    }
+    public boolean isFeatureSupported(String feature) {
+        return false;
+    }
+}
 			
 class KeyInfoWorker implements StaxWorker, KeyInfo {		
     private String id;
     private List content = new ArrayList();
+    private boolean readKeyName = false;
     public StaxWorker read(XMLStreamReader reader) {
 	switch (reader.getEventType()) {
 	    case XMLStreamReader.START_ELEMENT: 
@@ -503,43 +659,15 @@
 		    if (name.equals("KeyInfo") ) {
 			id = reader.getAttributeValue(null, "Id");
 		    } else if (name.equals("KeyName") ) {
-			try {
-			    final String keyName = reader.getElementText();
-			    content.add(new KeyName() {
-			        public String getName() {
-				    return keyName;
-			        }
-			        public boolean isFeatureSupported(String feature) {
-				    return false;
-			        }
-			    });
-			} catch (XMLStreamException xse) {
-			    xse.printStackTrace();
-			}
+			readKeyName = true;
 		    } else if (name.equals("KeyValue") ) {
 			KeyValueWorker kv = new KeyValueWorker();
 			content.add(kv);
 			return kv;
 		    } else if (name.equals("RetrievalMethod") ) {
-			final String uri = reader.getAttributeValue(null, "URI");
-			final String type = reader.getAttributeValue(null, "Type");
-			content.add(new RetrievalMethod() {
-			    public List getTransforms() {
-				return null;
-			    }
-			    public String getType() {
-				return type;
-			    }
-			    public String getURI() {
-				return uri;
-			    }
-			    public Data dereference(XMLCryptoContext context) {
-				throw new UnsupportedOperationException();
-			    }
-		            public boolean isFeatureSupported(String feature) {
-			        return false;
-		            }
-			});
+			RetrievalMethodWorker rm = new RetrievalMethodWorker();
+			content.add(rm);
+			return rm;
 		    } else if (name.equals("X509Data") ) {
 			X509DataWorker xd = new X509DataWorker();
 			content.add(xd);
@@ -547,6 +675,20 @@
 		    }
 		}
 		break;
+	    case XMLStreamReader.CHARACTERS:
+		if (readKeyName) {
+		    final String keyName = reader.getText();
+		    content.add(new KeyName() {
+		        public String getName() {
+			    return keyName;
+		        }
+		        public boolean isFeatureSupported(String feature) {
+			    return false;
+		        }
+		    });
+		    readKeyName = false;
+		}
+		break;
 	}
 	return null;
     }
@@ -619,7 +761,10 @@
 class ManifestWorker implements StaxWorker, Manifest {		
     private String id;
     private List<Reference> refs = new ArrayList<Reference>();
-
+    private String baseURI;
+    ManifestWorker(String baseURI) {
+	this.baseURI = baseURI;
+    }
     public StaxWorker read(XMLStreamReader reader) {
 	switch (reader.getEventType()) {
 	    case XMLStreamReader.START_ELEMENT: 
@@ -628,7 +773,7 @@
 		    if (name.equals("Manifest") ) {
 			id = reader.getAttributeValue(null, "Id");
 		    } else if (name.equals("Reference")) {
-			ReferenceWorker rw = new ReferenceWorker();
+			ReferenceWorker rw = new ReferenceWorker(baseURI);
 			refs.add(rw);
 			return rw;
 		    }
@@ -656,7 +801,10 @@
     private String mimeType;
     private String encoding;
     private List<XMLStructure> content = new ArrayList<XMLStructure>();
-
+    private String baseURI;
+    XMLObjectWorker(String baseURI) {
+	this.baseURI = baseURI;
+    }
     public StaxWorker read(XMLStreamReader reader) {
 	switch (reader.getEventType()) {
 	    case XMLStreamReader.START_ELEMENT: 
@@ -667,7 +815,7 @@
 			mimeType = reader.getAttributeValue(null, "MimeType");
 			encoding = reader.getAttributeValue(null, "Encoding");
 		    } else if (name.equals("Manifest")) {
-			ManifestWorker mw = new ManifestWorker();
+			ManifestWorker mw = new ManifestWorker(baseURI);
 			content.add(mw);
 			return mw;
 		    } else if (name.equals("SignatureProperties")) {
@@ -711,6 +859,10 @@
 	private String id;
 	private List<XMLObject> xmlObjects = new ArrayList<XMLObject>();
 	private KeySelectorResult ksr;
+	private String baseURI;
+	XMLSignatureWorker(String baseURI) {
+	    this.baseURI = baseURI;
+	}
 	public StaxWorker read(XMLStreamReader reader) {
 		switch (reader.getEventType()) {
 		  case XMLStreamReader.START_ELEMENT:
@@ -719,13 +871,13 @@
 				if (name.equals("Signature") ) {
 					id=reader.getAttributeValue(null,"Id");
 				} else if (name.equals("SignedInfo") ) {
-					si=new SignedInfoWorker();
+					si=new SignedInfoWorker(baseURI);
 					return si;			
 				} else if (name.equals("SignatureValue")) {
 					sv=new SignatureValueWorker();
 					return sv;
 				} else if (name.equals("Object")) {
-					XMLObjectWorker xo=new XMLObjectWorker();
+					XMLObjectWorker xo=new XMLObjectWorker(baseURI);
 					xmlObjects.add(xo);
 					return xo;
 				} else if (name.equals("KeyInfo")) {
@@ -745,10 +897,6 @@
 		if (validateContext == null) throw new NullPointerException();
 		StaxValidateContext ctx=(StaxValidateContext) validateContext;
 		try {
-			for (Reference ref: si.references) {
-				if (!ref.validate(ctx))
-					return false;
-			}
 			// get key from KeySelector
                         try {
                             ksr = ctx.getKeySelector().select(getKeyInfo(), 
@@ -762,7 +910,12 @@
 			    (ksr.getKey(), si.canonData, sv.signatureValue, 
 			     validateContext);
 			sv.isValid = isSignatureValid;
-			return isSignatureValid;
+			if (!isSignatureValid) return false;
+			for (Reference ref: si.references) {
+				if (!ref.validate(ctx))
+					return false;
+			}
+			return true;
 		} catch (Exception e) {
 			throw new XMLSignatureException(e);
 		}