From b02d774374b614d4520b6396e56f90d0d0c84257 Mon Sep 17 00:00:00 2001 From: Steve Loughran Date: Thu, 24 Mar 2005 17:17:09 +0000 Subject: [PATCH] Well, a bit of hackery and you can verify that JAR is signed. But there is *nothing* to verify that the signature itself is trusted. Essentially "jarsigner -verify" is a worthless piece of junk from the security perspective. git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@278060 13f79535-47bb-0310-9956-ffa450edef68 --- src/etc/testcases/taskdefs/signjar.xml | 8 ++ .../ant/taskdefs/AbstractJarSignerTask.java | 23 +++-- .../apache/tools/ant/taskdefs/VerifyJar.java | 83 ++++++++++++++++++- .../tools/ant/taskdefs/SignJarTest.java | 13 ++- 4 files changed, 117 insertions(+), 10 deletions(-) diff --git a/src/etc/testcases/taskdefs/signjar.xml b/src/etc/testcases/taskdefs/signjar.xml index adfb060a6..054b2c115 100644 --- a/src/etc/testcases/taskdefs/signjar.xml +++ b/src/etc/testcases/taskdefs/signjar.xml @@ -194,10 +194,18 @@ + + + + + + + + diff --git a/src/main/org/apache/tools/ant/taskdefs/AbstractJarSignerTask.java b/src/main/org/apache/tools/ant/taskdefs/AbstractJarSignerTask.java index fde4087a0..7e7ac7cf7 100644 --- a/src/main/org/apache/tools/ant/taskdefs/AbstractJarSignerTask.java +++ b/src/main/org/apache/tools/ant/taskdefs/AbstractJarSignerTask.java @@ -203,15 +203,26 @@ public abstract class AbstractJarSignerTask extends Task { */ private RedirectorElement createRedirector() { RedirectorElement result = new RedirectorElement(); - StringBuffer input = new StringBuffer(storepass).append('\n'); - if (keypass != null) { - input.append(keypass).append('\n'); + if(storepass!=null) { + StringBuffer input = new StringBuffer(storepass).append('\n'); + if (keypass != null) { + input.append(keypass).append('\n'); + } + result.setInputString(input.toString()); + result.setLogInputString(false); } - result.setInputString(input.toString()); - result.setLogInputString(false); return result; } + /** + * get the redirector. Non-null between invocations of + * {@link #beginExecution()} and {@link #endExecution()} + * @return a redirector or null + */ + public RedirectorElement getRedirector() { + return redirector; + } + /** * these are options common to signing and verifying * @param cmd command to configure @@ -224,7 +235,7 @@ public abstract class AbstractJarSignerTask extends Task { if (verbose) { addValue(cmd,"-verbose"); } - + //now patch in all system properties Vector props=sysProperties.getVariablesVector(); Enumeration e=props.elements(); diff --git a/src/main/org/apache/tools/ant/taskdefs/VerifyJar.java b/src/main/org/apache/tools/ant/taskdefs/VerifyJar.java index 22fd2e7a5..655eeb9ac 100644 --- a/src/main/org/apache/tools/ant/taskdefs/VerifyJar.java +++ b/src/main/org/apache/tools/ant/taskdefs/VerifyJar.java @@ -19,10 +19,15 @@ package org.apache.tools.ant.taskdefs; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.DirectoryScanner; +import org.apache.tools.ant.filters.ChainableReader; import org.apache.tools.ant.types.FileSet; +import org.apache.tools.ant.types.RedirectorElement; +import org.apache.tools.ant.types.FilterChain; import java.util.Vector; import java.io.File; +import java.io.Reader; +import java.io.IOException; /** * JAR verification task. @@ -38,10 +43,17 @@ public class VerifyJar extends AbstractJarSignerTask { */ public static final String ERROR_NO_FILE = "Not found :"; + /** + * The string we look for in the text to indicate direct verification + */ + private static final String VERIFIED_TEXT = "jar verified."; + /** * certification flag */ private boolean certificates=false; + private BufferingOutputFilter outputCache = new BufferingOutputFilter(); + public static final String ERROR_NO_VERIFY = "Failed to verify "; /** * Ask for certificate information to be printed @@ -65,6 +77,13 @@ public class VerifyJar extends AbstractJarSignerTask { } beginExecution(); + + //patch the redirector to save output to a file + RedirectorElement redirector = getRedirector(); + redirector.setAlwaysLog(true); + FilterChain outputFilterChain = redirector.createOutputFilterChain(); + outputFilterChain.add(outputCache); + try { Vector sources = createUnifiedSources(); for (int i = 0; i < sources.size(); i++) { @@ -114,7 +133,69 @@ public class VerifyJar extends AbstractJarSignerTask { log("Verifying JAR: " + jar.getAbsolutePath()); - + outputCache.clear(); cmd.execute(); + String results=outputCache.toString(); + if(results.indexOf(VERIFIED_TEXT)<0) { + throw new BuildException(ERROR_NO_VERIFY+jar); + } + } + + /** + * we are not thread safe here. Do not use on multiple threads at the same time. + */ + private class BufferingOutputFilter implements ChainableReader { + + private BufferingOutputFilterReader buffer; + + public Reader chain(Reader rdr) { + buffer = new BufferingOutputFilterReader(rdr); + return buffer; + } + + public String toString() { + return buffer.toString(); + } + + public void clear() { + if(buffer!=null) { + buffer.clear(); + } + } + } + + /** + * catch the output of the buffer + */ + private class BufferingOutputFilterReader extends Reader { + + private Reader next; + + private StringBuffer buffer=new StringBuffer(); + + public BufferingOutputFilterReader(Reader next) { + this.next = next; + } + + public int read(char cbuf[], int off, int len) throws IOException { + //hand down + int result=next.read(cbuf,off,len); + //cache + buffer.append(cbuf,off,len); + //return + return result; + } + + public void close() throws IOException { + next.close(); + } + + public String toString() { + return buffer.toString(); + } + + public void clear() { + buffer=new StringBuffer(); + } } } diff --git a/src/testcases/org/apache/tools/ant/taskdefs/SignJarTest.java b/src/testcases/org/apache/tools/ant/taskdefs/SignJarTest.java index 564c9bc00..0fef96e8e 100644 --- a/src/testcases/org/apache/tools/ant/taskdefs/SignJarTest.java +++ b/src/testcases/org/apache/tools/ant/taskdefs/SignJarTest.java @@ -164,9 +164,16 @@ public class SignJarTest extends BuildFileTest { AbstractJarSignerTask.ERROR_NO_SOURCE); } - public void NotestVerifyJarUnsigned() { - expectBuildException("testVerifyJarUnsigned", - "unsigned JAR file"); + public void testVerifyJarUnsigned() { + expectBuildExceptionContaining("testVerifyJarUnsigned", + "unsigned JAR file", + VerifyJar.ERROR_NO_VERIFY); + } + + public void NotestVerifyJarNotInKeystore() { + expectBuildExceptionContaining("testVerifyJarNotInKeystore", + "signature not in keystore", + VerifyJar.ERROR_NO_VERIFY); } public void testVerifyFileset() {