On Friday 08 May 2009 17:33:45 Alexei Fedotov wrote:
> Hello Chris,
> It seems SignatureTest2.java keeps vanishing. Could it be that some
> paranoid anti-virus scanner removed the attachment?
Pooh, probably Scarlet's honky webmail. Blocking source files and letting
through executable jars, that's what I call smart ... this time both attached
and inline, using good ol' SMTP. Scroll down further and I will ramble on
about a possible solution.
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.util.Enumeration;
import java.util.jar.*;
class SignatureTest2 {
static public void main(String[] args) {
try {
String filename = args.length == 0 ? "SignedTestBundle_1.0.0.jar" :
args[0];
System.out.println("Opening file: " + filename);
System.out.println();
FileInputStream fis = new FileInputStream(filename);
BufferedInputStream bis = new BufferedInputStream(fis, 8192);
JarInputStream jis = new JarInputStream(bis);
Manifest m = jis.getManifest();
JarEntry je = jis.getNextJarEntry();
while (je != null) {
System.out.println("JarEntry: " + je);
if (!je.isDirectory()) {
String name = je.getName();
if (!name.startsWith("META-INF/")) {
jis.closeEntry();
java.security.cert.Certificate[] certs = je.getCertificates();
if (certs == null) {
System.out.println("No certificates");
}
else {
System.out.println("Certificates:");
for (int i = 0; i < certs.length; ++i)
System.out.println(certs[i].toString());
}
System.out.println();
}
}
je = jis.getNextJarEntry();
}
}
catch (Throwable t) {
t.printStackTrace();
}
}
}
Note that this code doesn't even call closeEntry() on the meta-files it
encounters, and yet it still works on RI 1.4/1.6. On harmony the *.DSA and
*.SF files are simply skipped, without any entries being added to the
metaEntries map. Adding an else clause in which meta-files are first
exhaustively read([BII) and then closeEntry() is called seems to help a lot.
I think the answer is to treat all meta-files the way we now treat the
manifest, i.e. provided they are presented in the "right" order we read them
all in during the JarInputFile constructor and extract whatever data will
later be needed by the JarVerifier. "Right" order means something like: meta-
files precede all non-meta files, manifest precedes all except possible the
META-INF/ directory itself. This implies that we also suck in the META-
INF/INDEX.LST file and omy[deity] the META-INF/services directory if present,
unless we can insist that these come after the signature data. Instead of
mEntry we would have a whole queue of entries buffered and waiting for
getNextEntry() to fish them out.
I'm not a fan of long-running constructors (imagine if the jar file were being
read in from a slow server over a chunked HTTP stream - been there, done
that), but in this case it's probably justified; arguably the JarInputStream
object is not fully constructed until the signatures have been processed.
What a mess. What a format. What an API.
Cheers
Chris
--
Chris Gray /k/ Embedded Java Solutions BE0809.435.306
Embedded & Mobile Java, OSGi http://www.k-embedded-java.com/
[email protected] +32 3 216 0369
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.util.Enumeration;
import java.util.jar.*;
class SignatureTest2 {
static public void main(String[] args) {
try {
String filename = args.length == 0 ? "SignedTestBundle_1.0.0.jar" : args[0];
System.out.println("Opening file: " + filename);
System.out.println();
FileInputStream fis = new FileInputStream(filename);
BufferedInputStream bis = new BufferedInputStream(fis, 8192);
JarInputStream jis = new JarInputStream(bis);
Manifest m = jis.getManifest();
JarEntry je = jis.getNextJarEntry();
while (je != null) {
System.out.println("JarEntry: " + je);
if (!je.isDirectory()) {
String name = je.getName();
if (!name.startsWith("META-INF/")) {
jis.closeEntry();
java.security.cert.Certificate[] certs = je.getCertificates();
if (certs == null) {
System.out.println("No certificates");
}
else {
System.out.println("Certificates:");
for (int i = 0; i < certs.length; ++i)
System.out.println(certs[i].toString());
}
System.out.println();
}
}
je = jis.getNextJarEntry();
}
}
catch (Throwable t) {
t.printStackTrace();
}
}
}