United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
Bug ID: JDK-4263225 JarInputStream doesn't work if the manifest isn't at the beginning of stream
JDK-4263225 : JarInputStream doesn't work if the manifest isn't at the beginning of stream

Details
Type:
Enhancement
Submit Date:
1999-08-17
Status:
Closed
Updated Date:
1999-09-03
Project Name:
JDK
Resolved Date:
1999-09-03
Component:
core-libs
OS:
solaris_2.6
Sub-Component:
java.util
CPU:
sparc
Priority:
P4
Resolution:
Won't Fix
Affected Versions:
1.3.0
Fixed Versions:

Related Reports

Sub Tasks

Description
The JDK jarsigner always puts the manifest at the beginning of a JAR file; but
the Netscape's signtool puts the manifest at the end of a JAR file.

The current JarInputStream implementation cannot verify a jar file signed
by Netscape' signtool since it doesn't even read the manifest in such a JAR
file.

JarFile can verify JAR files signed by Netscape's sihntool; but JarFile only
works with files, not other kind of inputstreams.

When you pass a JAR file signed by Netscape's signtool (e.g.,
/home/shliu/public_html/testJAR/getpropThawe.jar) to the
TestJarInputStream, you get exceptions; but the TestJarFile does get
the manifest from that JAR file.
 
=========================== TestJarInputStream.java ================
import java.util.jar.*;
import java.net.*;
import java.io.*;

public class TestJarInputStream {

    public static void main(String[] args) throws Exception {

        isJarSigned(new URL(args[0]));
        System.out.println("Okey:" + args[0]);
    }

    /*
     * Verify a jar file is signed by a signer with a certificate which can be 
     * traced back to a trusted CA.
     */
    private static void isJarSigned(URL jarURL)
        throws IOException
    {
        String jarURLString = jarURL.toString();

        URLConnection connection = jarURL.openConnection();
        JarInputStream jis = new JarInputStream(connection.getInputStream());

        Manifest man = jis.getManifest();
        if (man == null)
            throw new JarException(jarURL.toString() + " is not signed.");

    }    
}

============================= TestJarFile.java ===================
import java.util.jar.*;
import java.net.*;
import java.io.*;

public class TestJarFile {

    public static void main(String[] args) throws Exception {

        isJarSigned(args[0]);
        System.out.println("Okey:" + args[0]);
    }

    /*
     * Verify a jar file is signed by a signer with a certificate which can be 
     * traced back to a trusted CA.
     */
    private static void isJarSigned(String fName)
        throws IOException
    {
        JarFile jf = new JarFile(new File(fName));

        Manifest man = jf.getManifest();
        if (man == null)
            throw new JarException(fName + " is not signed.");

    }    
}




                                    

Comments
EVALUATION

JarInputStream is a sequential input stream which doesn't mean to provide
random access to the input data. Requiring it to be able to find the manifest
at the end of the stream is not reasonable.

Secondly, the manifest file should always be the first entry in a particular
jar file, in fact our jar tool enforces this restriction. Of course, we cannot
prevent other vendors from manually putting the manifest at any other place in a 
jar, which is otherwise semantically equivalent. I think if we do want to 
support this random access functionality, we should do it somewhere else, either 
in the security checking code itself, or by using the ZipFile API with support
of byte range transmission in http1.1 and adding more constructors to ZipFile
class.

###@###.### 1999-08-23

For a remote URL source, JarURLConnection.getJarFile() can be used to
get the locally cached jar file and random access is allowed. This code
can be added to the security checking procedure and the location of the
manifest will not matter any more.

###@###.### 1999-09-03
                                     
1999-09-03
SUGGESTED FIX

If the manifest isn't at the beginning of a JarInputStream, read the inputstream
twice: 1) get the manifest; 2) read each entry and verify it against the
manifest if necessary.
                                     
2004-06-11



Hardware and Software, Engineered to Work Together