Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

8273826: Correct Manifest file name and NPE checks #503

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/java.base/share/classes/java/util/jar/JarFile.java
Expand Up @@ -758,7 +758,7 @@ private void initializeVerifier() {
}
if (mev == null) {
mev = new ManifestEntryVerifier
(getManifestFromReference());
(getManifestFromReference(), jv.manifestName);
}
byte[] b = getBytes(e);
if (b != null && b.length > 0) {
Expand Down
Expand Up @@ -96,7 +96,7 @@ private JarEntry checkManifest(JarEntry e)
closeEntry();
if (doVerify) {
jv = new JarVerifier(e.getName(), bytes);
mev = new ManifestEntryVerifier(man);
mev = new ManifestEntryVerifier(man, jv.manifestName);
}
return (JarEntry)super.getNextEntry();
}
Expand Down
2 changes: 1 addition & 1 deletion src/java.base/share/classes/java/util/jar/JarVerifier.java
Expand Up @@ -444,7 +444,7 @@ static class VerifierStream extends java.io.InputStream {
{
this.is = is;
this.jv = jv;
this.mev = new ManifestEntryVerifier(man);
this.mev = new ManifestEntryVerifier(man, jv.manifestName);
this.jv.beginEntry(je, mev);
this.numLeft = je.getSize();
if (this.numLeft == 0)
Expand Down
Expand Up @@ -63,7 +63,9 @@ private static class SunProviderHolder {
ArrayList<byte[]> manifestHashes;

private String name = null;
private Manifest man;

private final String manifestFileName; // never null
private final Manifest man;

private boolean skip = true;

Expand All @@ -74,11 +76,12 @@ private static class SunProviderHolder {
/**
* Create a new ManifestEntryVerifier object.
*/
public ManifestEntryVerifier(Manifest man)
public ManifestEntryVerifier(Manifest man, String manifestFileName)
{
createdDigests = new HashMap<>(11);
digests = new ArrayList<>();
manifestHashes = new ArrayList<>();
this.manifestFileName = manifestFileName;
this.man = man;
}

Expand Down Expand Up @@ -187,7 +190,6 @@ public JarEntry getEntry()
* the first time we have verified this object, remove its
* code signers from sigFileSigners and place in verifiedSigners.
*
*
*/
public CodeSigner[] verify(Hashtable<String, CodeSigner[]> verifiedSigners,
Hashtable<String, CodeSigner[]> sigFileSigners)
Expand All @@ -209,7 +211,6 @@ public CodeSigner[] verify(Hashtable<String, CodeSigner[]> verifiedSigners,
getParams(verifiedSigners, sigFileSigners);

for (int i=0; i < digests.size(); i++) {

MessageDigest digest = digests.get(i);
if (params != null) {
try {
Expand Down Expand Up @@ -251,7 +252,8 @@ public CodeSigner[] verify(Hashtable<String, CodeSigner[]> verifiedSigners,
/**
* Get constraints parameters for JAR. The constraints should be
* checked against all code signers. Returns the parameters,
* or null if the signers for this entry have already been checked.
* or null if the signers for this entry have already been checked
* or there are no signers for this entry.
*/
private JarConstraintsParameters getParams(
Map<String, CodeSigner[]> verifiedSigners,
Expand All @@ -262,17 +264,20 @@ private JarConstraintsParameters getParams(
// the signers of the JAR. But if it doesn't then we need to fallback
// and check verifiedSigners to see if the signers of this entry have
// been checked already.
if (verifiedSigners.containsKey(JarFile.MANIFEST_NAME)) {
if (verifiedSigners.containsKey(manifestFileName)) {
if (verifiedSigners.size() > 1) {
// this means we already checked it previously
return null;
} else {
return new JarConstraintsParameters(
verifiedSigners.get(JarFile.MANIFEST_NAME));
verifiedSigners.get(manifestFileName));
}
} else {
if (debug != null) {
debug.println(manifestFileName + " not present in verifiedSigners");
}
CodeSigner[] signers = sigFileSigners.get(name);
if (verifiedSigners.containsValue(signers)) {
if (signers == null || verifiedSigners.containsValue(signers)) {
return null;
} else {
return new JarConstraintsParameters(signers);
Expand Down
121 changes: 121 additions & 0 deletions test/jdk/sun/security/tools/jarsigner/warnings/LowerCaseManifest.java
@@ -0,0 +1,121 @@
/*
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/

import jdk.testlibrary.OutputAnalyzer;
import jdk.test.lib.util.JarUtils;

import java.nio.file.*;
import java.security.Security;
import java.util.Collections;


/**
* @test
* @bug 8273826
* @summary Test for signed jar file with lowercase META-INF files
* @library /lib/testlibrary /test/lib ../
* @build jdk.test.lib.util.JarUtils
* @run main LowerCaseManifest
*/
public class LowerCaseManifest extends Test {

public static void main(String[] args) throws Throwable {
new LowerCaseManifest().start();
}

private void start() throws Throwable {
// create a jar file that contains one class file
Utils.createFiles(FIRST_FILE);
JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);

// create key pair for jar signing
createAlias(CA_KEY_ALIAS, "-ext", "bc:c");
createAlias(KEY_ALIAS);

issueCert(KEY_ALIAS);

// sign jar
OutputAnalyzer analyzer = jarsigner(
"-keystore", KEYSTORE,
"-verbose",
"-storepass", PASSWORD,
"-keypass", PASSWORD,
"-signedjar", SIGNED_JARFILE,
UNSIGNED_JARFILE,
KEY_ALIAS);

checkSigning(analyzer);

// verify signed jar
analyzer = jarsigner(
"-verify",
"-verbose",
"-keystore", KEYSTORE,
"-storepass", PASSWORD,
"-keypass", PASSWORD,
SIGNED_JARFILE,
KEY_ALIAS);

checkVerifying(analyzer, 0, JAR_VERIFIED);

// verify signed jar in strict mode
analyzer = jarsigner(
"-verify",
"-verbose",
"-strict",
"-keystore", KEYSTORE,
"-storepass", PASSWORD,
"-keypass", PASSWORD,
SIGNED_JARFILE,
KEY_ALIAS);

checkVerifying(analyzer, 0, JAR_VERIFIED);

// convert the META-INF/ files to lower case
FileSystem fs = FileSystems.newFileSystem(Path.of(SIGNED_JARFILE), null);
for (String s : new String[]{"ALIAS.SF", "ALIAS.RSA", "MANIFEST.MF"}) {
Path origPath = fs.getPath("META-INF/" + s);
Path lowerCase = fs.getPath("META-INF/" + s.toLowerCase());
Files.write(lowerCase, Files.readAllBytes(origPath));
Files.delete(origPath);
}
fs.close();

// verify signed jar in strict mode (with lower case META-INF names in place)
analyzer = jarsigner(
"-verify",
"-verbose",
"-strict",
"-J-Djava.security.debug=jar",
"-keystore", KEYSTORE,
"-storepass", PASSWORD,
"-keypass", PASSWORD,
SIGNED_JARFILE,
KEY_ALIAS);

checkVerifying(analyzer, 0,
JAR_VERIFIED, "!not present in verifiedSigners");
System.out.println("Test passed");
}

}