[RFC][icedtea-web] Use global JarCertVerifier in JNLPClassLoader

Danesh Dadachanji ddadacha at redhat.com
Thu May 17 11:13:16 PDT 2012



On 17/05/12 11:54 AM, Deepak Bhole wrote:
> * Deepak Bhole<dbhole at redhat.com>  [2012-05-17 11:38]:
>> * Danesh Dadachanji<ddadacha at redhat.com>  [2012-05-16 18:33]:
>>> Hi,
>>>
>>> The attached patches make JNLPClassLoader use a global JCV to ensure
>>> we can actually check the app is signed entirely by at least one
>>> common signer. Currently, the classloader does not maintain
>>> verification of jars loaded upon main initialization vs jars loaded
>>> at runtime. Therefore, we are not actually able to enforce an
>>> application to be signed entirely by one signer.
>>>
>>> The application may initially be signed entirely (i.e. all
>>> resources/archives specified have a common signer) but then as
>>> classes are loaded at runtime (e.g. via manifest classpath), these
>>> are not verified along with the original jars. A new JarCertVerifier
>>> is used to verify each set.
>>>
>>> I used an instance var per JNLPClassLoader to keep track of all the
>>> jars verified thus far. Each JNLPClassLoader keeps track of its own
>>> app's jars so when JNLP extensions are specified, a new
>>> JNLPClassLoader is created. This ensures there can be separate
>>> signers between different JNLPs.
>>>
>>> The current method to determine if a jar is signed completely was to
>>> check against JarCertVerifier#anyJarSigned. This method is somewhat
>>> flawed. If any single entry is signed then this method returns true.
>>> However, if one entry of a jar is signed and another unsigned, then
>>> the jar is considered unsigned, as is the app as a whole. Therefore,
>>> I have included JarCertVerifier#isFullySigned in the conditional as
>>> well to ensure the app is in fact fully signed.
>>>
>>> Another change is the removal of permission checking of nested jars.
>>> If the entry of the nested jar is signed, then we should assume that
>>> the person signing the jar trusts it to do whatever it must. The
>>> nested jar is given the same security context as its parent jar.
>>>
>>> I've extensively tested this against a combination of
>>> singed/unsigned entries in
>>> resource/archive-specified/nested/manifest-classpath/extension jars
>>> using JNLPs, the applet tag, javaws and jnlp_href, as well as many
>>> duplicate jars. I have also run through all the regression tests for
>>> HEAD, 1.2 and 1.1, everything ran fine.
>>>
>>> I propose the following patches to HEAD, 1.2 and 1.1.
>>
>> I see nothing immediately wrong. However this patch will now allow
>
> s/now/not
>

I thought so. =)

>> applets to have different signers -- I take it that is expected and that
>> this patch only removes individual verifiers and collapses them to 1 per
>> loader?

Yes, this is intentional, sorry for not mentioning it in the original email. We somewhat enforce this already. In HEAD, all jars passed 
into the HTML tag are verified for 1 signer. The only catch is when jars found on the manifest classpath are accessed at runtime, it 
verifies them with a new JCV var. I do not agree with this, if we are enforcing everything be signed by 1 signer (including applets) 
then we should be doing so. The patch takes that into account when using a global JCV.

FWIW, the reason to enforce this for applets (even though proprietary does not) is because JCV is not capable of handling multiple 
certs. There is no way of keeping track of the ones that have gone through and the ones all other jars have. The major changes I'm 
making to JCV are going to take that into account so for now, I think this is a good temporary solution.

Cheers,
Danesh

>>
>>>
>>> ChangeLog: (s/JarCertVerifier/JarSigner/g for release branches)
>>> +2012-05-16  Danesh Dadachanji<ddadacha at redhat.com>
>>> +
>>> +	Use a global JarCertVerifier in the classloader to keep track of every
>>> +	jar that has been verified.
>>> +	* netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java
>>> +	(addNewJar), (initializeResources), (verifySignedJNLP):
>>> +	Replaced use of local JarCertVerifier variable with the instance  variable.
>>> +	Added calls to isFullySigned wherever signer verification is done.
>>> +	(activateJars): No longer verifies nested jars. These receive the same
>>> +	security permissions as their parent jar, regardless of the nested
>>> +	jar's signing.
>>> +	(verifyJars): Removed.
>>> +	* netx/net/sourceforge/jnlp/tools/JarCertVerifier.java:
>>> +	(add): New public method that resets some instance vars and
>>> +	calls verifyJars.
>>> +	(verifyJars): Modifier changed to private, above method should be used.
>>> +	(isFullySignedByASingleCert): renamed to isFullySigned.
>>> +
>>>
>>> A note for 1.1, it does not have the changeset that brought in
>>> verification of a signed JNLP as a jar entry so those 2 hunks are
>>> removed. Also, 1.1 and 1.2 are still using JarSigner instead of
>>> JarCertVerifier so I have accounted for that. Apart from these, the
>>> patches are identical in logic. All three patches attached.
>>>
>>> Any and all comments much appreciated! Please especially ask of a testcase if you have one in mind.
>>>
>>> Cheers,
>>> Danesh
>>
>>> diff --git a/netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java b/netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java
>>> --- a/netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java
>>> +++ b/netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java
>>> @@ -151,7 +151,7 @@ public class JNLPClassLoader extends URL
>>>       private ArrayList<String>  unverifiedJars = null;
>>>
>>>       /** the jar cert verifier tool to verify our jars */
>>> -    private JarCertVerifier jcv = null;
>>> +    private final JarCertVerifier jcv = new JarCertVerifier();
>>>
>>>       private boolean signing = false;
>>>
>>> @@ -469,11 +469,10 @@ public class JNLPClassLoader extends URL
>>>
>>>           if (JNLPRuntime.isVerifying()) {
>>>
>>> -            JarCertVerifier jcv;
>>>               waitForJars(initialJars); //download the jars first.
>>>
>>>               try {
>>> -                jcv = verifyJars(initialJars);
>>> +                jcv.add(initialJars, tracker);
>>>               } catch (Exception e) {
>>>                   //we caught an Exception from the JarCertVerifier class.
>>>                   //Note: one of these exceptions could be from not being able
>>> @@ -484,7 +483,7 @@ public class JNLPClassLoader extends URL
>>>               }
>>>
>>>               //Case when at least one jar has some signing
>>> -            if (jcv.anyJarsSigned()&&  jcv.isFullySignedByASingleCert()) {
>>> +            if (jcv.anyJarsSigned()&&  jcv.isFullySigned()) {
>>>                   signing = true;
>>>
>>>                   if (!jcv.allJarsSigned()&&
>>> @@ -700,7 +699,6 @@ public class JNLPClassLoader extends URL
>>>       private void verifySignedJNLP(JARDesc jarDesc, JarFile jarFile)
>>>               throws LaunchException {
>>>
>>> -        JarCertVerifier signer = new JarCertVerifier();
>>>           List<JARDesc>  desc = new ArrayList<JARDesc>();
>>>           desc.add(jarDesc);
>>>
>>> @@ -711,9 +709,7 @@ public class JNLPClassLoader extends URL
>>>           InputStreamReader jnlpReader = null;
>>>
>>>           try {
>>> -            signer.verifyJars(desc, tracker);
>>> -
>>> -            if (signer.allJarsSigned()) { // If the jar is signed
>>> +            if (jcv.isFullySigned()) { // If the jar is signed
>>>
>>>                   Enumeration<JarEntry>  entries = jarFile.entries();
>>>                   JarEntry je;
>>> @@ -1031,15 +1027,25 @@ public class JNLPClassLoader extends URL
>>>                                           continue;
>>>                                       }
>>>
>>> -                                    JarCertVerifier signer = new JarCertVerifier();
>>> -                                    List<JARDesc>  jars = new ArrayList<JARDesc>();
>>> -                                    JARDesc jarDesc = new JARDesc(new File(extractedJarLocation).toURL(), null, null, false, false, false, false);
>>> -                                    jars.add(jarDesc);
>>>                                       tracker.addResource(new File(extractedJarLocation).toURL(), null, null, null);
>>> -                                    signer.verifyJars(jars, tracker);
>>>
>>> -                                    if (signer.anyJarsSigned()&&  !signer.getAlreadyTrustPublisher()) {
>>> -                                        checkTrustWithUser(signer);
>>> +                                    URL codebase = file.getCodeBase();
>>> +                                    if (codebase == null) {
>>> +                                        //FIXME: codebase should be the codebase of the Main Jar not
>>> +                                        //the location. Although, it still works in the current state.
>>> +                                        codebase = file.getResources().getMainJAR().getLocation();
>>> +                                    }
>>> +
>>> +                                    SecurityDesc jarSecurity = null;
>>> +                                    if (jcv.isFullySigned()) {
>>> +                                        // Already trust application, nested jar should be given
>>> +                                        jarSecurity = new SecurityDesc(file,
>>> +                                                SecurityDesc.ALL_PERMISSIONS,
>>> +                                                codebase.getHost());
>>> +                                    } else {
>>> +                                        jarSecurity = new SecurityDesc(file,
>>> +                                                SecurityDesc.SANDBOX_PERMISSIONS,
>>> +                                                codebase.getHost());
>>>                                       }
>>>
>>>                                       try {
>>> @@ -1049,25 +1055,6 @@ public class JNLPClassLoader extends URL
>>>                                           CachedJarFileCallback.getInstance().addMapping(fakeRemote, fileURL);
>>>                                           addURL(fakeRemote);
>>>
>>> -                                        SecurityDesc jarSecurity = file.getSecurity();
>>> -
>>> -                                        if (file instanceof PluginBridge) {
>>> -
>>> -                                            URL codebase = null;
>>> -
>>> -                                            if (file.getCodeBase() != null) {
>>> -                                                codebase = file.getCodeBase();
>>> -                                            } else {
>>> -                                                //Fixme: codebase should be the codebase of the Main Jar not
>>> -                                                //the location. Although, it still works in the current state.
>>> -                                                codebase = file.getResources().getMainJAR().getLocation();
>>> -                                            }
>>> -
>>> -                                            jarSecurity = new SecurityDesc(file,
>>> -                                                    SecurityDesc.ALL_PERMISSIONS,
>>> -                                                    codebase.getHost());
>>> -                                        }
>>> -
>>>                                           jarLocationSecurityMap.put(fakeRemote, jarSecurity);
>>>
>>>                                       } catch (MalformedURLException mfue) {
>>> @@ -1276,18 +1263,6 @@ public class JNLPClassLoader extends URL
>>>       }
>>>
>>>       /**
>>> -         * Verifies code signing of jars to be used.
>>> -         *
>>> -         * @param jars the jars to be verified.
>>> -         */
>>> -    private JarCertVerifier verifyJars(List<JARDesc>  jars) throws Exception {
>>> -
>>> -        jcv = new JarCertVerifier();
>>> -        jcv.verifyJars(jars, tracker);
>>> -        return jcv;
>>> -    }
>>> -
>>> -    /**
>>>        * Find the loaded class in this loader or any of its extension loaders.
>>>        */
>>>       protected Class findLoadedClassAll(String name) {
>>> @@ -1442,7 +1417,6 @@ public class JNLPClassLoader extends URL
>>>
>>>               // Verify if needed
>>>
>>> -            final JarCertVerifier signer = new JarCertVerifier();
>>>               final List<JARDesc>  jars = new ArrayList<JARDesc>();
>>>               jars.add(desc);
>>>
>>> @@ -1454,14 +1428,14 @@ public class JNLPClassLoader extends URL
>>>
>>>               AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {
>>>                   public Void run() throws Exception {
>>> -                    signer.verifyJars(jars, tracker);
>>> +                    jcv.add(jars, tracker);
>>>
>>> -                    if (signer.anyJarsSigned()&&  !signer.getAlreadyTrustPublisher()) {
>>> -                        checkTrustWithUser(signer);
>>> +                    if (jcv.anyJarsSigned()&&  jcv.isFullySigned()&&  !jcv.getAlreadyTrustPublisher()) {
>>> +                        checkTrustWithUser(jcv);
>>>                       }
>>>
>>>                       final SecurityDesc security;
>>> -                    if (signer.anyJarsSigned()) {
>>> +                    if (jcv.anyJarsSigned()&&  jcv.isFullySigned()) {
>>>                           security = new SecurityDesc(file,
>>>                                   SecurityDesc.ALL_PERMISSIONS,
>>>                                   file.getCodeBase().getHost());
>>> diff --git a/netx/net/sourceforge/jnlp/tools/JarCertVerifier.java b/netx/net/sourceforge/jnlp/tools/JarCertVerifier.java
>>> --- a/netx/net/sourceforge/jnlp/tools/JarCertVerifier.java
>>> +++ b/netx/net/sourceforge/jnlp/tools/JarCertVerifier.java
>>> @@ -90,10 +90,10 @@ public class JarCertVerifier implements
>>>       private boolean anyJarsSigned = false;
>>>
>>>       /** all of the jar files that were verified */
>>> -    private ArrayList<String>  verifiedJars = null;
>>> +    private ArrayList<String>  verifiedJars = new ArrayList<String>();
>>>
>>>       /** all of the jar files that were not verified */
>>> -    private ArrayList<String>  unverifiedJars = null;
>>> +    private ArrayList<String>  unverifiedJars = new ArrayList<String>();
>>>
>>>       /** the certificates used for jar verification */
>>>       private HashMap<CertPath, Integer>  certs = new HashMap<CertPath, Integer>();
>>> @@ -165,7 +165,7 @@ public class JarCertVerifier implements
>>>        *
>>>        * @return Whether or not all entries have a common signer
>>>        */
>>> -    public boolean isFullySignedByASingleCert() {
>>> +    public boolean isFullySigned() {
>>>
>>>           for (CertPath cPath : certs.keySet()) {
>>>               // If this cert has signed everything, return true
>>> @@ -177,11 +177,27 @@ public class JarCertVerifier implements
>>>           return false;
>>>       }
>>>
>>> -    public void verifyJars(List<JARDesc>  jars, ResourceTracker tracker)
>>> +    /**
>>> +     * Update the verifier to consider new jars when verifying.
>>> +     * @param jars List of new jars to be verified.
>>> +     * @param tracker Resource tracker used to obtain the the jars from cache
>>> +     * @throws Exception Caused by issues with obtaining the jars' entries or
>>> +     *         interacting with the tracker.
>>> +     */
>>> +    public void add(List<JARDesc>  jars, ResourceTracker tracker)
>>>               throws Exception {
>>> +        // Reset the vars that need to be updated again during verification.
>>> +        certPath = null;
>>> +        alreadyTrustPublisher = false;
>>> +        rootInCacerts = false;
>>> +        details.remove(R("SUntrustedCertificate"));
>>> +        details.remove(R("STrustedCertificate"));
>>>
>>> -        verifiedJars = new ArrayList<String>();
>>> -        unverifiedJars = new ArrayList<String>();
>>> +        verifyJars(jars, tracker);
>>> +    }
>>> +
>>> +    private void verifyJars(List<JARDesc>  jars, ResourceTracker tracker)
>>> +            throws Exception {
>>>
>>>           for (int i = 0; i<  jars.size(); i++) {
>>>
>>
>>> diff --git a/netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java b/netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java
>>> --- a/netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java
>>> +++ b/netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java
>>> @@ -137,7 +137,7 @@ public class JNLPClassLoader extends URL
>>>       private ArrayList<String>  unverifiedJars = null;
>>>
>>>       /** the jarsigner tool to verify our jars */
>>> -    private JarSigner js = null;
>>> +    private final JarSigner js = new JarSigner();
>>>
>>>       private boolean signing = false;
>>>
>>> @@ -437,11 +437,10 @@ public class JNLPClassLoader extends URL
>>>
>>>           if (JNLPRuntime.isVerifying()) {
>>>
>>> -            JarSigner js;
>>>               waitForJars(initialJars); //download the jars first.
>>>
>>>               try {
>>> -                js = verifyJars(initialJars);
>>> +                js.add(initialJars, tracker);
>>>               } catch (Exception e) {
>>>                   //we caught an Exception from the JarSigner class.
>>>                   //Note: one of these exceptions could be from not being able
>>> @@ -452,7 +451,7 @@ public class JNLPClassLoader extends URL
>>>               }
>>>
>>>               //Case when at least one jar has some signing
>>> -            if (js.anyJarsSigned()&&  js.isFullySignedByASingleCert()) {
>>> +            if (js.anyJarsSigned()&&  js.isFullySigned()) {
>>>                   signing = true;
>>>
>>>                   if (!js.allJarsSigned()&&
>>> @@ -721,15 +720,25 @@ public class JNLPClassLoader extends URL
>>>                                           continue;
>>>                                       }
>>>
>>> -                                    JarSigner signer = new JarSigner();
>>> -                                    List<JARDesc>  jars = new ArrayList<JARDesc>();
>>> -                                    JARDesc jarDesc = new JARDesc(new File(extractedJarLocation).toURL(), null, null, false, false, false, false);
>>> -                                    jars.add(jarDesc);
>>>                                       tracker.addResource(new File(extractedJarLocation).toURL(), null, null, null);
>>> -                                    signer.verifyJars(jars, tracker);
>>>
>>> -                                    if (signer.anyJarsSigned()&&  !signer.getAlreadyTrustPublisher()) {
>>> -                                        checkTrustWithUser(signer);
>>> +                                    URL codebase = file.getCodeBase();
>>> +                                    if (codebase == null) {
>>> +                                        //FIXME: codebase should be the codebase of the Main Jar not
>>> +                                        //the location. Although, it still works in the current state.
>>> +                                        codebase = file.getResources().getMainJAR().getLocation();
>>> +                                    }
>>> +
>>> +                                    SecurityDesc jarSecurity = null;
>>> +                                    if (js.isFullySigned()) {
>>> +                                        // Already trust application, nested jar should be given
>>> +                                        jarSecurity = new SecurityDesc(file,
>>> +                                                SecurityDesc.ALL_PERMISSIONS,
>>> +                                                codebase.getHost());
>>> +                                    } else {
>>> +                                        jarSecurity = new SecurityDesc(file,
>>> +                                                SecurityDesc.SANDBOX_PERMISSIONS,
>>> +                                                codebase.getHost());
>>>                                       }
>>>
>>>                                       try {
>>> @@ -739,25 +748,6 @@ public class JNLPClassLoader extends URL
>>>                                           CachedJarFileCallback.getInstance().addMapping(fakeRemote, fileURL);
>>>                                           addURL(fakeRemote);
>>>
>>> -                                        SecurityDesc jarSecurity = file.getSecurity();
>>> -
>>> -                                        if (file instanceof PluginBridge) {
>>> -
>>> -                                            URL codebase = null;
>>> -
>>> -                                            if (file.getCodeBase() != null) {
>>> -                                                codebase = file.getCodeBase();
>>> -                                            } else {
>>> -                                                //Fixme: codebase should be the codebase of the Main Jar not
>>> -                                                //the location. Although, it still works in the current state.
>>> -                                                codebase = file.getResources().getMainJAR().getLocation();
>>> -                                            }
>>> -
>>> -                                            jarSecurity = new SecurityDesc(file,
>>> -                                                    SecurityDesc.ALL_PERMISSIONS,
>>> -                                                    codebase.getHost());
>>> -                                        }
>>> -
>>>                                           jarLocationSecurityMap.put(fakeRemote, jarSecurity);
>>>
>>>                                       } catch (MalformedURLException mfue) {
>>> @@ -966,18 +956,6 @@ public class JNLPClassLoader extends URL
>>>       }
>>>
>>>       /**
>>> -         * Verifies code signing of jars to be used.
>>> -         *
>>> -         * @param jars the jars to be verified.
>>> -         */
>>> -    private JarSigner verifyJars(List<JARDesc>  jars) throws Exception {
>>> -
>>> -        js = new JarSigner();
>>> -        js.verifyJars(jars, tracker);
>>> -        return js;
>>> -    }
>>> -
>>> -    /**
>>>        * Find the loaded class in this loader or any of its extension loaders.
>>>        */
>>>       protected Class findLoadedClassAll(String name) {
>>> @@ -1132,7 +1110,6 @@ public class JNLPClassLoader extends URL
>>>
>>>               // Verify if needed
>>>
>>> -            final JarSigner signer = new JarSigner();
>>>               final List<JARDesc>  jars = new ArrayList<JARDesc>();
>>>               jars.add(desc);
>>>
>>> @@ -1144,14 +1121,14 @@ public class JNLPClassLoader extends URL
>>>
>>>               AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {
>>>                   public Void run() throws Exception {
>>> -                    signer.verifyJars(jars, tracker);
>>> +                    js.add(jars, tracker);
>>>
>>> -                    if (signer.anyJarsSigned()&&  !signer.getAlreadyTrustPublisher()) {
>>> -                        checkTrustWithUser(signer);
>>> +                    if (js.anyJarsSigned()&&  js.isFullySigned()&&  !js.getAlreadyTrustPublisher()) {
>>> +                        checkTrustWithUser(js);
>>>                       }
>>>
>>>                       final SecurityDesc security;
>>> -                    if (signer.anyJarsSigned()) {
>>> +                    if (js.anyJarsSigned()&&  js.isFullySigned()) {
>>>                           security = new SecurityDesc(file,
>>>                                   SecurityDesc.ALL_PERMISSIONS,
>>>                                   file.getCodeBase().getHost());
>>> diff --git a/netx/net/sourceforge/jnlp/tools/JarSigner.java b/netx/net/sourceforge/jnlp/tools/JarSigner.java
>>> --- a/netx/net/sourceforge/jnlp/tools/JarSigner.java
>>> +++ b/netx/net/sourceforge/jnlp/tools/JarSigner.java
>>> @@ -90,10 +90,10 @@ public class JarSigner implements CertVe
>>>       private boolean anyJarsSigned = false;
>>>
>>>       /** all of the jar files that were verified */
>>> -    private ArrayList<String>  verifiedJars = null;
>>> +    private ArrayList<String>  verifiedJars = new ArrayList<String>();
>>>
>>>       /** all of the jar files that were not verified */
>>> -    private ArrayList<String>  unverifiedJars = null;
>>> +    private ArrayList<String>  unverifiedJars = new ArrayList<String>();
>>>
>>>       /** the certificates used for jar verification */
>>>       private HashMap<CertPath, Integer>  certs = new HashMap<CertPath, Integer>();
>>> @@ -165,7 +165,7 @@ public class JarSigner implements CertVe
>>>        *
>>>        * @return Whether or not all entries have a common signer
>>>        */
>>> -    public boolean isFullySignedByASingleCert() {
>>> +    public boolean isFullySigned() {
>>>
>>>           for (CertPath cPath : certs.keySet()) {
>>>               // If this cert has signed everything, return true
>>> @@ -177,11 +177,27 @@ public class JarSigner implements CertVe
>>>           return false;
>>>       }
>>>
>>> -    public void verifyJars(List<JARDesc>  jars, ResourceTracker tracker)
>>> +    /**
>>> +     * Update the verifier to consider new jars when verifying.
>>> +     * @param jars List of new jars to be verified.
>>> +     * @param tracker Resource tracker used to obtain the the jars from cache
>>> +     * @throws Exception Caused by issues with obtaining the jars' entries or
>>> +     *         interacting with the tracker.
>>> +     */
>>> +    public void add(List<JARDesc>  jars, ResourceTracker tracker)
>>>               throws Exception {
>>> +        // Reset the vars that need to be updated again during verification.
>>> +        certPath = null;
>>> +        alreadyTrustPublisher = false;
>>> +        rootInCacerts = false;
>>> +        details.remove(R("SUntrustedCertificate"));
>>> +        details.remove(R("STrustedCertificate"));
>>>
>>> -        verifiedJars = new ArrayList<String>();
>>> -        unverifiedJars = new ArrayList<String>();
>>> +        verifyJars(jars, tracker);
>>> +    }
>>> +
>>> +    private void verifyJars(List<JARDesc>  jars, ResourceTracker tracker)
>>> +            throws Exception {
>>>
>>>           for (int i = 0; i<  jars.size(); i++) {
>>>
>>
>>> diff --git a/netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java b/netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java
>>> --- a/netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java
>>> +++ b/netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java
>>> @@ -137,7 +137,7 @@ public class JNLPClassLoader extends URL
>>>       private ArrayList<String>  unverifiedJars = null;
>>>
>>>       /** the jarsigner tool to verify our jars */
>>> -    private JarSigner js = null;
>>> +    private final JarSigner js = new JarSigner();
>>>
>>>       private boolean signing = false;
>>>
>>> @@ -437,11 +437,10 @@ public class JNLPClassLoader extends URL
>>>
>>>           if (JNLPRuntime.isVerifying()) {
>>>
>>> -            JarSigner js;
>>>               waitForJars(initialJars); //download the jars first.
>>>
>>>               try {
>>> -                js = verifyJars(initialJars);
>>> +                js.add(initialJars, tracker);
>>>               } catch (Exception e) {
>>>                   //we caught an Exception from the JarSigner class.
>>>                   //Note: one of these exceptions could be from not being able
>>> @@ -452,7 +451,7 @@ public class JNLPClassLoader extends URL
>>>               }
>>>
>>>               //Case when at least one jar has some signing
>>> -            if (js.anyJarsSigned()&&  js.isFullySignedByASingleCert()) {
>>> +            if (js.anyJarsSigned()&&  js.isFullySigned()) {
>>>                   signing = true;
>>>
>>>                   if (!js.allJarsSigned()&&
>>> @@ -721,15 +720,25 @@ public class JNLPClassLoader extends URL
>>>                                           continue;
>>>                                       }
>>>
>>> -                                    JarSigner signer = new JarSigner();
>>> -                                    List<JARDesc>  jars = new ArrayList<JARDesc>();
>>> -                                    JARDesc jarDesc = new JARDesc(new File(extractedJarLocation).toURL(), null, null, false, false, false, false);
>>> -                                    jars.add(jarDesc);
>>>                                       tracker.addResource(new File(extractedJarLocation).toURL(), null, null, null);
>>> -                                    signer.verifyJars(jars, tracker);
>>>
>>> -                                    if (signer.anyJarsSigned()&&  !signer.getAlreadyTrustPublisher()) {
>>> -                                        checkTrustWithUser(signer);
>>> +                                    URL codebase = file.getCodeBase();
>>> +                                    if (codebase == null) {
>>> +                                        //FIXME: codebase should be the codebase of the Main Jar not
>>> +                                        //the location. Although, it still works in the current state.
>>> +                                        codebase = file.getResources().getMainJAR().getLocation();
>>> +                                    }
>>> +
>>> +                                    SecurityDesc jarSecurity = null;
>>> +                                    if (js.isFullySigned()) {
>>> +                                        // Already trust application, nested jar should be given
>>> +                                        jarSecurity = new SecurityDesc(file,
>>> +                                                SecurityDesc.ALL_PERMISSIONS,
>>> +                                                codebase.getHost());
>>> +                                    } else {
>>> +                                        jarSecurity = new SecurityDesc(file,
>>> +                                                SecurityDesc.SANDBOX_PERMISSIONS,
>>> +                                                codebase.getHost());
>>>                                       }
>>>
>>>                                       try {
>>> @@ -739,25 +748,6 @@ public class JNLPClassLoader extends URL
>>>                                           CachedJarFileCallback.getInstance().addMapping(fakeRemote, fileURL);
>>>                                           addURL(fakeRemote);
>>>
>>> -                                        SecurityDesc jarSecurity = file.getSecurity();
>>> -
>>> -                                        if (file instanceof PluginBridge) {
>>> -
>>> -                                            URL codebase = null;
>>> -
>>> -                                            if (file.getCodeBase() != null) {
>>> -                                                codebase = file.getCodeBase();
>>> -                                            } else {
>>> -                                                //Fixme: codebase should be the codebase of the Main Jar not
>>> -                                                //the location. Although, it still works in the current state.
>>> -                                                codebase = file.getResources().getMainJAR().getLocation();
>>> -                                            }
>>> -
>>> -                                            jarSecurity = new SecurityDesc(file,
>>> -                                                    SecurityDesc.ALL_PERMISSIONS,
>>> -                                                    codebase.getHost());
>>> -                                        }
>>> -
>>>                                           jarLocationSecurityMap.put(fakeRemote, jarSecurity);
>>>
>>>                                       } catch (MalformedURLException mfue) {
>>> @@ -966,18 +956,6 @@ public class JNLPClassLoader extends URL
>>>       }
>>>
>>>       /**
>>> -         * Verifies code signing of jars to be used.
>>> -         *
>>> -         * @param jars the jars to be verified.
>>> -         */
>>> -    private JarSigner verifyJars(List<JARDesc>  jars) throws Exception {
>>> -
>>> -        js = new JarSigner();
>>> -        js.verifyJars(jars, tracker);
>>> -        return js;
>>> -    }
>>> -
>>> -    /**
>>>        * Find the loaded class in this loader or any of its extension loaders.
>>>        */
>>>       protected Class findLoadedClassAll(String name) {
>>> @@ -1132,7 +1110,6 @@ public class JNLPClassLoader extends URL
>>>
>>>               // Verify if needed
>>>
>>> -            final JarSigner signer = new JarSigner();
>>>               final List<JARDesc>  jars = new ArrayList<JARDesc>();
>>>               jars.add(desc);
>>>
>>> @@ -1144,14 +1121,14 @@ public class JNLPClassLoader extends URL
>>>
>>>               AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {
>>>                   public Void run() throws Exception {
>>> -                    signer.verifyJars(jars, tracker);
>>> +                    js.add(jars, tracker);
>>>
>>> -                    if (signer.anyJarsSigned()&&  !signer.getAlreadyTrustPublisher()) {
>>> -                        checkTrustWithUser(signer);
>>> +                    if (js.anyJarsSigned()&&  js.isFullySigned()&&  !js.getAlreadyTrustPublisher()) {
>>> +                        checkTrustWithUser(js);
>>>                       }
>>>
>>>                       final SecurityDesc security;
>>> -                    if (signer.anyJarsSigned()) {
>>> +                    if (js.anyJarsSigned()&&  js.isFullySigned()) {
>>>                           security = new SecurityDesc(file,
>>>                                   SecurityDesc.ALL_PERMISSIONS,
>>>                                   file.getCodeBase().getHost());
>>> diff --git a/netx/net/sourceforge/jnlp/tools/JarSigner.java b/netx/net/sourceforge/jnlp/tools/JarSigner.java
>>> --- a/netx/net/sourceforge/jnlp/tools/JarSigner.java
>>> +++ b/netx/net/sourceforge/jnlp/tools/JarSigner.java
>>> @@ -90,10 +90,10 @@ public class JarSigner implements CertVe
>>>       private boolean anyJarsSigned = false;
>>>
>>>       /** all of the jar files that were verified */
>>> -    private ArrayList<String>  verifiedJars = null;
>>> +    private ArrayList<String>  verifiedJars = new ArrayList<String>();
>>>
>>>       /** all of the jar files that were not verified */
>>> -    private ArrayList<String>  unverifiedJars = null;
>>> +    private ArrayList<String>  unverifiedJars = new ArrayList<String>();
>>>
>>>       /** the certificates used for jar verification */
>>>       private HashMap<CertPath, Integer>  certs = new HashMap<CertPath, Integer>();
>>> @@ -165,7 +165,7 @@ public class JarSigner implements CertVe
>>>        *
>>>        * @return Whether or not all entries have a common signer
>>>        */
>>> -    public boolean isFullySignedByASingleCert() {
>>> +    public boolean isFullySigned() {
>>>
>>>           for (CertPath cPath : certs.keySet()) {
>>>               // If this cert has signed everything, return true
>>> @@ -177,11 +177,27 @@ public class JarSigner implements CertVe
>>>           return false;
>>>       }
>>>
>>> -    public void verifyJars(List<JARDesc>  jars, ResourceTracker tracker)
>>> +    /**
>>> +     * Update the verifier to consider new jars when verifying.
>>> +     * @param jars List of new jars to be verified.
>>> +     * @param tracker Resource tracker used to obtain the the jars from cache
>>> +     * @throws Exception Caused by issues with obtaining the jars' entries or
>>> +     *         interacting with the tracker.
>>> +     */
>>> +    public void add(List<JARDesc>  jars, ResourceTracker tracker)
>>>               throws Exception {
>>> +        // Reset the vars that need to be updated again during verification.
>>> +        certPath = null;
>>> +        alreadyTrustPublisher = false;
>>> +        rootInCacerts = false;
>>> +        details.remove(R("SUntrustedCertificate"));
>>> +        details.remove(R("STrustedCertificate"));
>>>
>>> -        verifiedJars = new ArrayList<String>();
>>> -        unverifiedJars = new ArrayList<String>();
>>> +        verifyJars(jars, tracker);
>>> +    }
>>> +
>>> +    private void verifyJars(List<JARDesc>  jars, ResourceTracker tracker)
>>> +            throws Exception {
>>>
>>>           for (int i = 0; i<  jars.size(); i++) {
>>>
>>



More information about the distro-pkg-dev mailing list