Skip to content

Commit 5dfc4ec

Browse files
eirbjowangweij
authored andcommitted
8300140: ZipFile.isSignatureRelated returns true for files in META-INF subdirectories
Reviewed-by: weijun
1 parent 5c59de5 commit 5dfc4ec

File tree

6 files changed

+421
-24
lines changed

6 files changed

+421
-24
lines changed

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

+6-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -39,6 +39,8 @@
3939
import sun.security.util.SignatureFileVerifier;
4040
import sun.security.util.Debug;
4141

42+
import static sun.security.util.SignatureFileVerifier.isInMetaInf;
43+
4244
/**
4345
*
4446
* @author Roland Schemers
@@ -135,15 +137,14 @@ public void beginEntry(JarEntry je, ManifestEntryVerifier mev)
135137
*/
136138

137139
if (parsingMeta) {
138-
String uname = name.toUpperCase(Locale.ENGLISH);
139-
if ((uname.startsWith("META-INF/") ||
140-
uname.startsWith("/META-INF/"))) {
140+
141+
if (isInMetaInf(name)) {
141142

142143
if (je.isDirectory()) {
143144
mev.setEntry(null, je);
144145
return;
145146
}
146-
147+
String uname = name.toUpperCase(Locale.ENGLISH);
147148
if (uname.equals(JarFile.MANIFEST_NAME) ||
148149
uname.equals(JarIndex.INDEX_NAME)) {
149150
return;

src/java.base/share/classes/java/util/zip/ZipFile.java

+20-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1995, 2022, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1995, 2023, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -1745,8 +1745,27 @@ private boolean isSignatureRelated(int off, int len) {
17451745
assert(signatureRelated == SignatureFileVerifier
17461746
.isBlockOrSF(new String(name, off, len, UTF_8.INSTANCE)
17471747
.toUpperCase(Locale.ENGLISH)));
1748+
1749+
// Signature related files must reside directly in META-INF/
1750+
if (signatureRelated && hasSlash(name, off + META_INF_LEN, off + len)) {
1751+
signatureRelated = false;
1752+
}
17481753
return signatureRelated;
17491754
}
1755+
/*
1756+
* Return true if the encoded name contains a '/' within the byte given range
1757+
* This assumes an ASCII-compatible encoding, which is ok here since
1758+
* it is already assumed in isMetaName
1759+
*/
1760+
private boolean hasSlash(byte[] name, int start, int end) {
1761+
for (int i = start; i < end; i++) {
1762+
int c = name[i];
1763+
if (c == '/') {
1764+
return true;
1765+
}
1766+
}
1767+
return false;
1768+
}
17501769

17511770
/*
17521771
* If the bytes represents a non-directory name beginning

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

+21-11
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -81,6 +81,8 @@ public class SignatureFileVerifier {
8181
/** ConstraintsParameters for checking disabled algorithms */
8282
private JarConstraintsParameters params;
8383

84+
private static final String META_INF = "META-INF/";
85+
8486
/**
8587
* Create the named SignatureFileVerifier.
8688
*
@@ -141,6 +143,18 @@ public void setSignatureFile(byte[] sfBytes)
141143
this.sfBytes = sfBytes;
142144
}
143145

146+
/**
147+
* Utility method used by JarVerifier and JarSigner
148+
* to determine if a path is located directly in the
149+
* META-INF/ directory
150+
*
151+
* @param name the path name to check
152+
* @return true if the path resides in META-INF directly, ignoring case
153+
*/
154+
public static boolean isInMetaInf(String name) {
155+
return name.regionMatches(true, 0, META_INF, 0, META_INF.length())
156+
&& name.lastIndexOf('/') < META_INF.length();
157+
}
144158
/**
145159
* Utility method used by JarVerifier and JarSigner
146160
* to determine the signature file names and PKCS7 block
@@ -153,7 +167,7 @@ public void setSignatureFile(byte[] sfBytes)
153167
*/
154168
public static boolean isBlockOrSF(String s) {
155169
// Note: keep this in sync with j.u.z.ZipFile.Source#isSignatureRelated
156-
// we currently only support DSA and RSA PKCS7 blocks
170+
// we currently only support DSA, RSA or EC PKCS7 blocks
157171
return s.endsWith(".SF")
158172
|| s.endsWith(".DSA")
159173
|| s.endsWith(".RSA")
@@ -191,19 +205,15 @@ public static String getBlockExtension(PrivateKey key) {
191205
* @return true if the input file name is signature related
192206
*/
193207
public static boolean isSigningRelated(String name) {
194-
name = name.toUpperCase(Locale.ENGLISH);
195-
if (!name.startsWith("META-INF/")) {
208+
if (!isInMetaInf(name)) {
196209
return false;
197210
}
198-
name = name.substring(9);
199-
if (name.indexOf('/') != -1) {
200-
return false;
201-
}
202-
if (isBlockOrSF(name) || name.equals("MANIFEST.MF")) {
211+
name = name.toUpperCase(Locale.ENGLISH);
212+
if (isBlockOrSF(name) || name.equals("META-INF/MANIFEST.MF")) {
203213
return true;
204-
} else if (name.startsWith("SIG-")) {
214+
} else if (name.startsWith("SIG-", META_INF.length())) {
205215
// check filename extension
206-
// see http://docs.oracle.com/javase/7/docs/technotes/guides/jar/jar.html#Digital_Signatures
216+
// see https://docs.oracle.com/en/java/javase/19/docs/specs/jar/jar.html#digital-signatures
207217
// for what filename extensions are legal
208218
int extIndex = name.lastIndexOf('.');
209219
if (extIndex != -1) {

src/jdk.jartool/share/classes/jdk/security/jarsigner/JarSigner.java

+5-4
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@
6363
import java.util.zip.ZipFile;
6464
import java.util.zip.ZipOutputStream;
6565

66+
import static sun.security.util.SignatureFileVerifier.isInMetaInf;
67+
6668
/**
6769
* An immutable utility class to sign a jar file.
6870
* <p>
@@ -475,8 +477,6 @@ public JarSigner build() {
475477
}
476478
}
477479

478-
private static final String META_INF = "META-INF/";
479-
480480
// All fields in Builder are duplicated here as final. Those not
481481
// provided but has a default value will be filled with default value.
482482

@@ -731,7 +731,7 @@ private void sign0(ZipFile zipFile, OutputStream os)
731731
enum_.hasMoreElements(); ) {
732732
ZipEntry ze = enum_.nextElement();
733733

734-
if (ze.getName().startsWith(META_INF)) {
734+
if (isInMetaInf(ze.getName())) {
735735
// Store META-INF files in vector, so they can be written
736736
// out first
737737
mfFiles.addElement(ze);
@@ -959,7 +959,7 @@ private void sign0(ZipFile zipFile, OutputStream os)
959959
enum_.hasMoreElements(); ) {
960960
ZipEntry ze = enum_.nextElement();
961961

962-
if (!ze.getName().startsWith(META_INF)) {
962+
if (!isInMetaInf(ze.getName())) {
963963
if (handler != null) {
964964
if (manifest.getAttributes(ze.getName()) != null) {
965965
handler.accept("signing", ze.getName());
@@ -974,6 +974,7 @@ private void sign0(ZipFile zipFile, OutputStream os)
974974
zos.close();
975975
}
976976

977+
977978
private void writeEntry(ZipFile zf, ZipOutputStream os, ZipEntry ze)
978979
throws IOException {
979980
ZipEntry ze2 = new ZipEntry(ze.getName());

src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Main.java

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -835,8 +835,7 @@ void verifyJar(String jarName)
835835
if (!extraAttrsDetected && JUZFA.getExtraAttributes(je) != -1) {
836836
extraAttrsDetected = true;
837837
}
838-
hasSignature = hasSignature
839-
|| SignatureFileVerifier.isBlockOrSF(name);
838+
hasSignature |= signatureRelated(name) && SignatureFileVerifier.isBlockOrSF(name);
840839

841840
CodeSigner[] signers = je.getCodeSigners();
842841
boolean isSigned = (signers != null);

0 commit comments

Comments
 (0)