Browse Source

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
master
Steve Loughran 20 years ago
parent
commit
b02d774374
4 changed files with 117 additions and 10 deletions
  1. +8
    -0
      src/etc/testcases/taskdefs/signjar.xml
  2. +17
    -6
      src/main/org/apache/tools/ant/taskdefs/AbstractJarSignerTask.java
  3. +82
    -1
      src/main/org/apache/tools/ant/taskdefs/VerifyJar.java
  4. +10
    -3
      src/testcases/org/apache/tools/ant/taskdefs/SignJarTest.java

+ 8
- 0
src/etc/testcases/taskdefs/signjar.xml View File

@@ -194,10 +194,18 @@
<verify-base jar="${test.jar}"/>
</target>

<target name="testVerifyJarCertificates" depends="basic">
<verify-base jar="${test.jar}" certificates="true" verbose="true"/>
</target>
<target name="testVerifyJarUnsigned" depends="jar">
<verify-base jar="${test.jar}"/>
</target>
<target name="testVerifyJarNotInKeystore" depends="basic">
<verifyjar jar="${test.jar}" certificates="true" verbose="true"/>
</target>
<target name="testVerifyFileset" depends="basic">
<verify-base >
<fileset file="${test.jar}" />


+ 17
- 6
src/main/org/apache/tools/ant/taskdefs/AbstractJarSignerTask.java View File

@@ -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();


+ 82
- 1
src/main/org/apache/tools/ant/taskdefs/VerifyJar.java View File

@@ -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();
}
}
}

+ 10
- 3
src/testcases/org/apache/tools/ant/taskdefs/SignJarTest.java View File

@@ -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() {


Loading…
Cancel
Save