Skip to content

Commit 9512c47

Browse files
committed
8273826: Correct Manifest file name and NPE checks
Reviewed-by: mdoerr Backport-of: 03a8d342b86e720d3cba08d540182b4ab161fba3
1 parent bcee700 commit 9512c47

File tree

5 files changed

+137
-11
lines changed

5 files changed

+137
-11
lines changed

src/java.base/share/classes/java/util/jar/JarFile.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -758,7 +758,7 @@ private void initializeVerifier() {
758758
}
759759
if (mev == null) {
760760
mev = new ManifestEntryVerifier
761-
(getManifestFromReference());
761+
(getManifestFromReference(), jv.manifestName);
762762
}
763763
byte[] b = getBytes(e);
764764
if (b != null && b.length > 0) {

src/java.base/share/classes/java/util/jar/JarInputStream.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ private JarEntry checkManifest(JarEntry e)
9696
closeEntry();
9797
if (doVerify) {
9898
jv = new JarVerifier(e.getName(), bytes);
99-
mev = new ManifestEntryVerifier(man);
99+
mev = new ManifestEntryVerifier(man, jv.manifestName);
100100
}
101101
return (JarEntry)super.getNextEntry();
102102
}

src/java.base/share/classes/java/util/jar/JarVerifier.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -444,7 +444,7 @@ static class VerifierStream extends java.io.InputStream {
444444
{
445445
this.is = is;
446446
this.jv = jv;
447-
this.mev = new ManifestEntryVerifier(man);
447+
this.mev = new ManifestEntryVerifier(man, jv.manifestName);
448448
this.jv.beginEntry(je, mev);
449449
this.numLeft = je.getSize();
450450
if (this.numLeft == 0)

src/java.base/share/classes/sun/security/util/ManifestEntryVerifier.java

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,9 @@ private static class SunProviderHolder {
6363
ArrayList<byte[]> manifestHashes;
6464

6565
private String name = null;
66-
private Manifest man;
66+
67+
private final String manifestFileName; // never null
68+
private final Manifest man;
6769

6870
private boolean skip = true;
6971

@@ -74,11 +76,12 @@ private static class SunProviderHolder {
7476
/**
7577
* Create a new ManifestEntryVerifier object.
7678
*/
77-
public ManifestEntryVerifier(Manifest man)
79+
public ManifestEntryVerifier(Manifest man, String manifestFileName)
7880
{
7981
createdDigests = new HashMap<>(11);
8082
digests = new ArrayList<>();
8183
manifestHashes = new ArrayList<>();
84+
this.manifestFileName = manifestFileName;
8285
this.man = man;
8386
}
8487

@@ -187,7 +190,6 @@ public JarEntry getEntry()
187190
* the first time we have verified this object, remove its
188191
* code signers from sigFileSigners and place in verifiedSigners.
189192
*
190-
*
191193
*/
192194
public CodeSigner[] verify(Hashtable<String, CodeSigner[]> verifiedSigners,
193195
Hashtable<String, CodeSigner[]> sigFileSigners)
@@ -209,7 +211,6 @@ public CodeSigner[] verify(Hashtable<String, CodeSigner[]> verifiedSigners,
209211
getParams(verifiedSigners, sigFileSigners);
210212

211213
for (int i=0; i < digests.size(); i++) {
212-
213214
MessageDigest digest = digests.get(i);
214215
if (params != null) {
215216
try {
@@ -251,7 +252,8 @@ public CodeSigner[] verify(Hashtable<String, CodeSigner[]> verifiedSigners,
251252
/**
252253
* Get constraints parameters for JAR. The constraints should be
253254
* checked against all code signers. Returns the parameters,
254-
* or null if the signers for this entry have already been checked.
255+
* or null if the signers for this entry have already been checked
256+
* or there are no signers for this entry.
255257
*/
256258
private JarConstraintsParameters getParams(
257259
Map<String, CodeSigner[]> verifiedSigners,
@@ -262,17 +264,20 @@ private JarConstraintsParameters getParams(
262264
// the signers of the JAR. But if it doesn't then we need to fallback
263265
// and check verifiedSigners to see if the signers of this entry have
264266
// been checked already.
265-
if (verifiedSigners.containsKey(JarFile.MANIFEST_NAME)) {
267+
if (verifiedSigners.containsKey(manifestFileName)) {
266268
if (verifiedSigners.size() > 1) {
267269
// this means we already checked it previously
268270
return null;
269271
} else {
270272
return new JarConstraintsParameters(
271-
verifiedSigners.get(JarFile.MANIFEST_NAME));
273+
verifiedSigners.get(manifestFileName));
272274
}
273275
} else {
276+
if (debug != null) {
277+
debug.println(manifestFileName + " not present in verifiedSigners");
278+
}
274279
CodeSigner[] signers = sigFileSigners.get(name);
275-
if (verifiedSigners.containsValue(signers)) {
280+
if (signers == null || verifiedSigners.containsValue(signers)) {
276281
return null;
277282
} else {
278283
return new JarConstraintsParameters(signers);
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
/*
2+
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
24+
import jdk.testlibrary.OutputAnalyzer;
25+
import jdk.test.lib.util.JarUtils;
26+
27+
import java.nio.file.*;
28+
import java.security.Security;
29+
import java.util.Collections;
30+
31+
32+
/**
33+
* @test
34+
* @bug 8273826
35+
* @summary Test for signed jar file with lowercase META-INF files
36+
* @library /lib/testlibrary /test/lib ../
37+
* @build jdk.test.lib.util.JarUtils
38+
* @run main LowerCaseManifest
39+
*/
40+
public class LowerCaseManifest extends Test {
41+
42+
public static void main(String[] args) throws Throwable {
43+
new LowerCaseManifest().start();
44+
}
45+
46+
private void start() throws Throwable {
47+
// create a jar file that contains one class file
48+
Utils.createFiles(FIRST_FILE);
49+
JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
50+
51+
// create key pair for jar signing
52+
createAlias(CA_KEY_ALIAS, "-ext", "bc:c");
53+
createAlias(KEY_ALIAS);
54+
55+
issueCert(KEY_ALIAS);
56+
57+
// sign jar
58+
OutputAnalyzer analyzer = jarsigner(
59+
"-keystore", KEYSTORE,
60+
"-verbose",
61+
"-storepass", PASSWORD,
62+
"-keypass", PASSWORD,
63+
"-signedjar", SIGNED_JARFILE,
64+
UNSIGNED_JARFILE,
65+
KEY_ALIAS);
66+
67+
checkSigning(analyzer);
68+
69+
// verify signed jar
70+
analyzer = jarsigner(
71+
"-verify",
72+
"-verbose",
73+
"-keystore", KEYSTORE,
74+
"-storepass", PASSWORD,
75+
"-keypass", PASSWORD,
76+
SIGNED_JARFILE,
77+
KEY_ALIAS);
78+
79+
checkVerifying(analyzer, 0, JAR_VERIFIED);
80+
81+
// verify signed jar in strict mode
82+
analyzer = jarsigner(
83+
"-verify",
84+
"-verbose",
85+
"-strict",
86+
"-keystore", KEYSTORE,
87+
"-storepass", PASSWORD,
88+
"-keypass", PASSWORD,
89+
SIGNED_JARFILE,
90+
KEY_ALIAS);
91+
92+
checkVerifying(analyzer, 0, JAR_VERIFIED);
93+
94+
// convert the META-INF/ files to lower case
95+
FileSystem fs = FileSystems.newFileSystem(Path.of(SIGNED_JARFILE), null);
96+
for (String s : new String[]{"ALIAS.SF", "ALIAS.RSA", "MANIFEST.MF"}) {
97+
Path origPath = fs.getPath("META-INF/" + s);
98+
Path lowerCase = fs.getPath("META-INF/" + s.toLowerCase());
99+
Files.write(lowerCase, Files.readAllBytes(origPath));
100+
Files.delete(origPath);
101+
}
102+
fs.close();
103+
104+
// verify signed jar in strict mode (with lower case META-INF names in place)
105+
analyzer = jarsigner(
106+
"-verify",
107+
"-verbose",
108+
"-strict",
109+
"-J-Djava.security.debug=jar",
110+
"-keystore", KEYSTORE,
111+
"-storepass", PASSWORD,
112+
"-keypass", PASSWORD,
113+
SIGNED_JARFILE,
114+
KEY_ALIAS);
115+
116+
checkVerifying(analyzer, 0,
117+
JAR_VERIFIED, "!not present in verifiedSigners");
118+
System.out.println("Test passed");
119+
}
120+
121+
}

0 commit comments

Comments
 (0)