]> source.dussan.org Git - poi.git/commitdiff
another signature ubuntu jdk6 bug fix ... and offline/online handling
authorAndreas Beeker <kiwiwings@apache.org>
Fri, 7 Nov 2014 01:16:21 +0000 (01:16 +0000)
committerAndreas Beeker <kiwiwings@apache.org>
Fri, 7 Nov 2014 01:16:21 +0000 (01:16 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1637283 13f79535-47bb-0310-9956-ffa450edef68

src/ooxml/java/org/apache/poi/poifs/crypt/dsig/SignatureInfo.java
src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/SignatureFacet.java
src/ooxml/testcases/org/apache/poi/poifs/crypt/TestSignatureInfo.java

index 59d7f44d281ea2f1c28e47607d3c055f3b288c88..bf9dae94f53c0f19f307dd168ffae1b5ab3f150b 100644 (file)
@@ -57,6 +57,7 @@ import javax.xml.crypto.dsig.XMLSignContext;
 import javax.xml.crypto.dsig.XMLSignature;\r
 import javax.xml.crypto.dsig.XMLSignatureException;\r
 import javax.xml.crypto.dsig.XMLSignatureFactory;\r
+import javax.xml.crypto.dsig.XMLValidateContext;\r
 import javax.xml.crypto.dsig.dom.DOMSignContext;\r
 import javax.xml.crypto.dsig.dom.DOMValidateContext;\r
 import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec;\r
@@ -230,9 +231,25 @@ public class SignatureInfo implements SignatureConfigurable {
                 DOMValidateContext domValidateContext = new DOMValidateContext(keySelector, doc);\r
                 domValidateContext.setProperty("org.jcp.xml.dsig.validateManifests", Boolean.TRUE);\r
                 domValidateContext.setURIDereferencer(signatureConfig.getUriDereferencer());\r
+                brokenJvmWorkaround(domValidateContext);\r
     \r
                 XMLSignatureFactory xmlSignatureFactory = signatureConfig.getSignatureFactory();\r
                 XMLSignature xmlSignature = xmlSignatureFactory.unmarshalXMLSignature(domValidateContext);\r
+                \r
+                // TODO: replace with property when xml-sec patch is applied\r
+                for (Reference ref : (List<Reference>)xmlSignature.getSignedInfo().getReferences()) {\r
+                    SignatureFacet.brokenJvmWorkaround(ref);\r
+                }\r
+                for (XMLObject xo : (List<XMLObject>)xmlSignature.getObjects()) {\r
+                    for (XMLStructure xs : (List<XMLStructure>)xo.getContent()) {\r
+                        if (xs instanceof Manifest) {\r
+                           for (Reference ref : (List<Reference>)((Manifest)xs).getReferences()) {\r
+                               SignatureFacet.brokenJvmWorkaround(ref);\r
+                           }\r
+                        }\r
+                    }\r
+                }\r
+                \r
                 boolean valid = xmlSignature.validate(domValidateContext);\r
 \r
                 if (valid) {\r
@@ -241,8 +258,6 @@ public class SignatureInfo implements SignatureConfigurable {
                 }\r
                 \r
                 return valid;\r
-            } catch (ArrayIndexOutOfBoundsException e) {\r
-                throw new JvmBrokenException(e);\r
             } catch (Exception e) {\r
                 LOG.log(POILogger.ERROR, "error in marshalling and validating the signature", e);\r
                 return false;\r
@@ -399,149 +414,141 @@ public class SignatureInfo implements SignatureConfigurable {
     @SuppressWarnings("unchecked")\r
     public DigestInfo preSign(Document document, List<DigestInfo> digestInfos)\r
     throws XMLSignatureException, MarshalException {\r
-        try {\r
-            signatureConfig.init(false);\r
-            \r
-            // it's necessary to explicitly set the mdssi namespace, but the sign() method has no\r
-            // normal way to interfere with, so we need to add the namespace under the hand ...\r
-            EventTarget target = (EventTarget)document;\r
-            EventListener creationListener = signatureConfig.getSignatureMarshalListener();\r
-            if (creationListener != null) {\r
-                if (creationListener instanceof SignatureMarshalListener) {\r
-                    ((SignatureMarshalListener)creationListener).setEventTarget(target);\r
-                }\r
-                SignatureMarshalListener.setListener(target, creationListener, true);\r
-            }\r
-            \r
-            /*\r
-             * Signature context construction.\r
-             */\r
-            XMLSignContext xmlSignContext = new DOMSignContext(signatureConfig.getKey(), document);\r
-            URIDereferencer uriDereferencer = signatureConfig.getUriDereferencer();\r
-            if (null != uriDereferencer) {\r
-                xmlSignContext.setURIDereferencer(uriDereferencer);\r
-            }\r
-    \r
-            for (Map.Entry<String,String> me : signatureConfig.getNamespacePrefixes().entrySet()) {\r
-                xmlSignContext.putNamespacePrefix(me.getKey(), me.getValue());\r
-            }\r
-            xmlSignContext.setDefaultNamespacePrefix("");\r
-            // signatureConfig.getNamespacePrefixes().get(XML_DIGSIG_NS));\r
-            \r
-            // workaround for https://bugzilla.redhat.com/show_bug.cgi?id=1155012\r
-            Provider bcProv = Security.getProvider("BC");\r
-            if (bcProv != null) {\r
-                xmlSignContext.setProperty("org.jcp.xml.dsig.internal.dom.SignatureProvider", bcProv);\r
-            }            \r
-            \r
-            XMLSignatureFactory signatureFactory = signatureConfig.getSignatureFactory();\r
-    \r
-            /*\r
-             * Add ds:References that come from signing client local files.\r
-             */\r
-            List<Reference> references = new ArrayList<Reference>();\r
-            for (DigestInfo digestInfo : safe(digestInfos)) {\r
-                byte[] documentDigestValue = digestInfo.digestValue;\r
-    \r
-                String uri = new File(digestInfo.description).getName();\r
-                Reference reference = SignatureFacet.newReference\r
-                    (uri, null, null, null, documentDigestValue, signatureConfig);\r
-                references.add(reference);\r
-            }\r
-    \r
-            /*\r
-             * Invoke the signature facets.\r
-             */\r
-            List<XMLObject> objects = new ArrayList<XMLObject>();\r
-            for (SignatureFacet signatureFacet : signatureConfig.getSignatureFacets()) {\r
-                LOG.log(POILogger.DEBUG, "invoking signature facet: " + signatureFacet.getClass().getSimpleName());\r
-                signatureFacet.preSign(document, references, objects);\r
-            }\r
-    \r
-            /*\r
-             * ds:SignedInfo\r
-             */\r
-            SignedInfo signedInfo;\r
-            try {\r
-                SignatureMethod signatureMethod = signatureFactory.newSignatureMethod\r
-                    (signatureConfig.getSignatureMethodUri(), null);\r
-                CanonicalizationMethod canonicalizationMethod = signatureFactory\r
-                    .newCanonicalizationMethod(signatureConfig.getCanonicalizationMethod(),\r
-                    (C14NMethodParameterSpec) null);\r
-                signedInfo = signatureFactory.newSignedInfo(\r
-                    canonicalizationMethod, signatureMethod, references);\r
-            } catch (GeneralSecurityException e) {\r
-                throw new XMLSignatureException(e);\r
+        signatureConfig.init(false);\r
+        \r
+        // it's necessary to explicitly set the mdssi namespace, but the sign() method has no\r
+        // normal way to interfere with, so we need to add the namespace under the hand ...\r
+        EventTarget target = (EventTarget)document;\r
+        EventListener creationListener = signatureConfig.getSignatureMarshalListener();\r
+        if (creationListener != null) {\r
+            if (creationListener instanceof SignatureMarshalListener) {\r
+                ((SignatureMarshalListener)creationListener).setEventTarget(target);\r
             }\r
-    \r
-            /*\r
-             * JSR105 ds:Signature creation\r
-             */\r
-            String signatureValueId = signatureConfig.getPackageSignatureId() + "-signature-value";\r
-            javax.xml.crypto.dsig.XMLSignature xmlSignature = signatureFactory\r
-                .newXMLSignature(signedInfo, null, objects, signatureConfig.getPackageSignatureId(),\r
-                signatureValueId);\r
-    \r
-            /*\r
-             * ds:Signature Marshalling.\r
-             */\r
-            xmlSignature.sign(xmlSignContext);\r
-    \r
-            /*\r
-             * Completion of undigested ds:References in the ds:Manifests.\r
-             */\r
-            for (XMLObject object : objects) {\r
-                LOG.log(POILogger.DEBUG, "object java type: " + object.getClass().getName());\r
-                List<XMLStructure> objectContentList = object.getContent();\r
-                for (XMLStructure objectContent : objectContentList) {\r
-                    LOG.log(POILogger.DEBUG, "object content java type: " + objectContent.getClass().getName());\r
-                    if (!(objectContent instanceof Manifest)) continue;\r
-                    Manifest manifest = (Manifest) objectContent;\r
-                    List<Reference> manifestReferences = manifest.getReferences();\r
-                    for (Reference manifestReference : manifestReferences) {\r
-                        if (manifestReference.getDigestValue() != null) continue;\r
-    \r
-                        DOMReference manifestDOMReference = (DOMReference)manifestReference;\r
-                        manifestDOMReference.digest(xmlSignContext);\r
-                    }\r
+            SignatureMarshalListener.setListener(target, creationListener, true);\r
+        }\r
+        \r
+        /*\r
+         * Signature context construction.\r
+         */\r
+        XMLSignContext xmlSignContext = new DOMSignContext(signatureConfig.getKey(), document);\r
+        URIDereferencer uriDereferencer = signatureConfig.getUriDereferencer();\r
+        if (null != uriDereferencer) {\r
+            xmlSignContext.setURIDereferencer(uriDereferencer);\r
+        }\r
+\r
+        for (Map.Entry<String,String> me : signatureConfig.getNamespacePrefixes().entrySet()) {\r
+            xmlSignContext.putNamespacePrefix(me.getKey(), me.getValue());\r
+        }\r
+        xmlSignContext.setDefaultNamespacePrefix("");\r
+        // signatureConfig.getNamespacePrefixes().get(XML_DIGSIG_NS));\r
+        \r
+        brokenJvmWorkaround(xmlSignContext);\r
+        \r
+        XMLSignatureFactory signatureFactory = signatureConfig.getSignatureFactory();\r
+\r
+        /*\r
+         * Add ds:References that come from signing client local files.\r
+         */\r
+        List<Reference> references = new ArrayList<Reference>();\r
+        for (DigestInfo digestInfo : safe(digestInfos)) {\r
+            byte[] documentDigestValue = digestInfo.digestValue;\r
+\r
+            String uri = new File(digestInfo.description).getName();\r
+            Reference reference = SignatureFacet.newReference\r
+                (uri, null, null, null, documentDigestValue, signatureConfig);\r
+            references.add(reference);\r
+        }\r
+\r
+        /*\r
+         * Invoke the signature facets.\r
+         */\r
+        List<XMLObject> objects = new ArrayList<XMLObject>();\r
+        for (SignatureFacet signatureFacet : signatureConfig.getSignatureFacets()) {\r
+            LOG.log(POILogger.DEBUG, "invoking signature facet: " + signatureFacet.getClass().getSimpleName());\r
+            signatureFacet.preSign(document, references, objects);\r
+        }\r
+\r
+        /*\r
+         * ds:SignedInfo\r
+         */\r
+        SignedInfo signedInfo;\r
+        try {\r
+            SignatureMethod signatureMethod = signatureFactory.newSignatureMethod\r
+                (signatureConfig.getSignatureMethodUri(), null);\r
+            CanonicalizationMethod canonicalizationMethod = signatureFactory\r
+                .newCanonicalizationMethod(signatureConfig.getCanonicalizationMethod(),\r
+                (C14NMethodParameterSpec) null);\r
+            signedInfo = signatureFactory.newSignedInfo(\r
+                canonicalizationMethod, signatureMethod, references);\r
+        } catch (GeneralSecurityException e) {\r
+            throw new XMLSignatureException(e);\r
+        }\r
+\r
+        /*\r
+         * JSR105 ds:Signature creation\r
+         */\r
+        String signatureValueId = signatureConfig.getPackageSignatureId() + "-signature-value";\r
+        javax.xml.crypto.dsig.XMLSignature xmlSignature = signatureFactory\r
+            .newXMLSignature(signedInfo, null, objects, signatureConfig.getPackageSignatureId(),\r
+            signatureValueId);\r
+\r
+        /*\r
+         * ds:Signature Marshalling.\r
+         */\r
+        xmlSignature.sign(xmlSignContext);\r
+\r
+        /*\r
+         * Completion of undigested ds:References in the ds:Manifests.\r
+         */\r
+        for (XMLObject object : objects) {\r
+            LOG.log(POILogger.DEBUG, "object java type: " + object.getClass().getName());\r
+            List<XMLStructure> objectContentList = object.getContent();\r
+            for (XMLStructure objectContent : objectContentList) {\r
+                LOG.log(POILogger.DEBUG, "object content java type: " + objectContent.getClass().getName());\r
+                if (!(objectContent instanceof Manifest)) continue;\r
+                Manifest manifest = (Manifest) objectContent;\r
+                List<Reference> manifestReferences = manifest.getReferences();\r
+                for (Reference manifestReference : manifestReferences) {\r
+                    if (manifestReference.getDigestValue() != null) continue;\r
+\r
+                    DOMReference manifestDOMReference = (DOMReference)manifestReference;\r
+                    manifestDOMReference.digest(xmlSignContext);\r
                 }\r
             }\r
-    \r
-            /*\r
-             * Completion of undigested ds:References.\r
-             */\r
-            List<Reference> signedInfoReferences = signedInfo.getReferences();\r
-            for (Reference signedInfoReference : signedInfoReferences) {\r
-                DOMReference domReference = (DOMReference)signedInfoReference;\r
-    \r
-                // ds:Reference with external digest value\r
-                if (domReference.getDigestValue() != null) continue;\r
-                \r
-                domReference.digest(xmlSignContext);\r
-            }\r
-    \r
-            /*\r
-             * Calculation of XML signature digest value.\r
-             */\r
-            DOMSignedInfo domSignedInfo = (DOMSignedInfo)signedInfo;\r
-            ByteArrayOutputStream dataStream = new ByteArrayOutputStream();\r
-            domSignedInfo.canonicalize(xmlSignContext, dataStream);\r
-            byte[] octets = dataStream.toByteArray();\r
-    \r
-            /*\r
-             * TODO: we could be using DigestOutputStream here to optimize memory\r
-             * usage.\r
-             */\r
-    \r
-            MessageDigest md = CryptoFunctions.getMessageDigest(signatureConfig.getDigestAlgo());\r
-            byte[] digestValue = md.digest(octets);\r
-            \r
+        }\r
+\r
+        /*\r
+         * Completion of undigested ds:References.\r
+         */\r
+        List<Reference> signedInfoReferences = signedInfo.getReferences();\r
+        for (Reference signedInfoReference : signedInfoReferences) {\r
+            DOMReference domReference = (DOMReference)signedInfoReference;\r
+\r
+            // ds:Reference with external digest value\r
+            if (domReference.getDigestValue() != null) continue;\r
             \r
-            String description = signatureConfig.getSignatureDescription();\r
-            return new DigestInfo(digestValue, signatureConfig.getDigestAlgo(), description);\r
-        } catch (ArrayIndexOutOfBoundsException e) {\r
-            throw new JvmBrokenException(e);\r
+            domReference.digest(xmlSignContext);\r
         }\r
+\r
+        /*\r
+         * Calculation of XML signature digest value.\r
+         */\r
+        DOMSignedInfo domSignedInfo = (DOMSignedInfo)signedInfo;\r
+        ByteArrayOutputStream dataStream = new ByteArrayOutputStream();\r
+        domSignedInfo.canonicalize(xmlSignContext, dataStream);\r
+        byte[] octets = dataStream.toByteArray();\r
+\r
+        /*\r
+         * TODO: we could be using DigestOutputStream here to optimize memory\r
+         * usage.\r
+         */\r
+\r
+        MessageDigest md = CryptoFunctions.getMessageDigest(signatureConfig.getDigestAlgo());\r
+        byte[] digestValue = md.digest(octets);\r
+        \r
+        \r
+        String description = signatureConfig.getSignatureDescription();\r
+        return new DigestInfo(digestValue, signatureConfig.getDigestAlgo(), description);\r
     }\r
 \r
     /**\r
@@ -651,10 +658,20 @@ public class SignatureInfo implements SignatureConfigurable {
     private static <T> List<T> safe(List<T> other) {\r
         return other == null ? Collections.EMPTY_LIST : other;\r
     }\r
-    \r
-    private static class JvmBrokenException extends EncryptedDocumentException {\r
-        public JvmBrokenException(Throwable cause) {\r
-            super("\"your JVM is just too broken\" - check https://bugzilla.redhat.com/show_bug.cgi?id=1155012 if this applies to the stacktrace ...", cause);\r
-        }\r
+\r
+    private void brokenJvmWorkaround(XMLSignContext context) {\r
+        // workaround for https://bugzilla.redhat.com/show_bug.cgi?id=1155012\r
+        Provider bcProv = Security.getProvider("BC");\r
+        if (bcProv != null) {\r
+            context.setProperty("org.jcp.xml.dsig.internal.dom.SignatureProvider", bcProv);\r
+        }        \r
+    }\r
+\r
+    private void brokenJvmWorkaround(XMLValidateContext context) {\r
+        // workaround for https://bugzilla.redhat.com/show_bug.cgi?id=1155012\r
+        Provider bcProv = Security.getProvider("BC");\r
+        if (bcProv != null) {\r
+            context.setProperty("org.jcp.xml.dsig.internal.dom.SignatureProvider", bcProv);\r
+        }        \r
     }\r
 }\r
index c21a4c8525ac4766c8ad86c10c732a86754b5ffe..21922fe1c7f4f3357bb93e4cfe5bde9a702a7426 100644 (file)
@@ -150,6 +150,16 @@ public abstract class SignatureFacet implements SignatureConfigurable {
             reference = sigFac.newReference(uri, digestMethod, transforms, type, id, digestValue);\r
         }\r
         \r
+        brokenJvmWorkaround(reference);\r
+\r
+        return reference;\r
+    }\r
+    \r
+    // helper method ... will be removed soon\r
+    public static void brokenJvmWorkaround(Reference reference) {\r
+        DigestMethod digestMethod = reference.getDigestMethod();\r
+        String digestMethodUri = digestMethod.getAlgorithm();\r
+        \r
         // workaround for https://bugzilla.redhat.com/show_bug.cgi?id=1155012\r
         // overwrite standard message digest, if a digest <> SHA1 is used\r
         Provider bcProv = Security.getProvider("BC");\r
@@ -166,7 +176,5 @@ public abstract class SignatureFacet implements SignatureConfigurable {
                 LOG.log(POILogger.WARN, "Can't overwrite message digest (workaround for https://bugzilla.redhat.com/show_bug.cgi?id=1155012)", e);\r
             }\r
         }\r
-\r
-        return reference;\r
     }\r
 }
\ No newline at end of file
index 7c185721e787458a4f7bc74ff4984cb0a01ebae9..3628ac75b455bf86378d5251794b37164d41d35c 100644 (file)
@@ -50,7 +50,6 @@ import java.util.Iterator;
 import java.util.List;\r
 import java.util.TimeZone;\r
 \r
-import org.apache.poi.EncryptedDocumentException;\r
 import org.apache.poi.POIDataSamples;\r
 import org.apache.poi.openxml4j.opc.OPCPackage;\r
 import org.apache.poi.openxml4j.opc.PackageAccess;\r
@@ -299,7 +298,9 @@ public class TestSignatureInfo {
         signatureConfig.addSignatureFacet(new XAdESSignatureFacet());\r
         signatureConfig.addSignatureFacet(new XAdESXLSignatureFacet());\r
         \r
-        boolean mockTsp = false;\r
+        // check for internet\r
+        Process p1 = Runtime.getRuntime().exec("ping www.google.com");\r
+        boolean mockTsp = (p1.waitFor() == 1);\r
         // http://timestamping.edelweb.fr/service/tsp\r
         // http://tsa.belgium.be/connect\r
         // http://timestamp.comodoca.com/authenticode\r
@@ -471,14 +472,14 @@ public class TestSignatureInfo {
                 si.confirmSignature();\r
                 boolean b = si.verifySignature();\r
                 assertTrue("Signature not correctly calculated for " + ha, b);\r
-            } catch (EncryptedDocumentException e) {\r
-                // see http://apache-poi.1045710.n5.nabble.com/org-apache-poi-poifs-crypt-TestSignatureInfo-failing-on-trunk-on-Java-6-tp5717032.html\r
-                Throwable cause = e.getCause();\r
-                if (cause instanceof ArrayIndexOutOfBoundsException) {\r
-                    LOG.log(POILogger.ERROR, "ignoring AIOOBE - hopefully a SHA2 bug ...", e);\r
-                } else {\r
-                    throw e;\r
-                }\r
+//            } catch (EncryptedDocumentException e) {\r
+//                // see http://apache-poi.1045710.n5.nabble.com/org-apache-poi-poifs-crypt-TestSignatureInfo-failing-on-trunk-on-Java-6-tp5717032.html\r
+//                Throwable cause = e.getCause();\r
+//                if (cause instanceof ArrayIndexOutOfBoundsException) {\r
+//                    LOG.log(POILogger.ERROR, "ignoring AIOOBE - hopefully a SHA2 bug ...", e);\r
+//                } else {\r
+//                    throw e;\r
+//                }\r
             } finally {\r
                 if (pkg != null) pkg.close();\r
             }\r