8297301: Cleanup unused methods in JavaUtilJarAccess

Reviewed-by: weijun
This commit is contained in:
pandaapo 2022-11-22 03:22:05 +00:00 committed by Weijun Wang
parent 392ac7055d
commit f0e99c6346
4 changed files with 16 additions and 649 deletions

View File

@ -37,15 +37,10 @@ import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.SoftReference;
import java.net.URL;
import java.security.CodeSigner;
import java.security.CodeSource;
import java.security.cert.Certificate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.stream.Stream;
import java.util.zip.ZipEntry;
@ -658,7 +653,7 @@ public class JarFile extends ZipFile {
throw new RuntimeException(e);
}
if (certs == null && jv != null) {
certs = jv.getCerts(JarFile.this, realEntry());
certs = jv.getCerts(realEntry());
}
return certs == null ? null : certs.clone();
}
@ -671,7 +666,7 @@ public class JarFile extends ZipFile {
throw new RuntimeException(e);
}
if (signers == null && jv != null) {
signers = jv.getCodeSigners(JarFile.this, realEntry());
signers = jv.getCodeSigners(realEntry());
}
return signers == null ? null : signers.clone();
}
@ -1073,195 +1068,4 @@ public class JarFile extends ZipFile {
static boolean isInitializing() {
return ThreadTrackHolder.TRACKER.contains(Thread.currentThread());
}
/*
* Returns a versioned {@code JarFileEntry} for the given entry,
* if there is one. Otherwise returns the original entry. This
* is invoked by the {@code entries2} for verifier.
*/
JarEntry newEntry(JarEntry je) {
if (isMultiRelease()) {
return getVersionedEntry(je.getName(), je);
}
return je;
}
/*
* Returns a versioned {@code JarFileEntry} for the given entry
* name, if there is one. Otherwise returns a {@code JarFileEntry}
* with the given name. It is invoked from JarVerifier's entries2
* for {@code singers}.
*/
JarEntry newEntry(String name) {
if (isMultiRelease()) {
JarEntry vje = getVersionedEntry(name, null);
if (vje != null) {
return vje;
}
}
return new JarFileEntry(name);
}
Enumeration<String> entryNames(CodeSource[] cs) {
ensureInitialization();
if (jv != null) {
return jv.entryNames(this, cs);
}
/*
* JAR file has no signed content. Is there a non-signing
* code source?
*/
boolean includeUnsigned = false;
for (CodeSource c : cs) {
if (c.getCodeSigners() == null) {
includeUnsigned = true;
break;
}
}
if (includeUnsigned) {
return unsignedEntryNames();
} else {
return Collections.emptyEnumeration();
}
}
/**
* Returns an enumeration of the zip file entries
* excluding internal JAR mechanism entries and including
* signed entries missing from the ZIP directory.
*/
Enumeration<JarEntry> entries2() {
ensureInitialization();
if (jv != null) {
return jv.entries2(this, JUZFA.entries(JarFile.this));
}
// screen out entries which are never signed
final var unfilteredEntries = JUZFA.entries(JarFile.this);
return new Enumeration<>() {
JarEntry entry;
public boolean hasMoreElements() {
if (entry != null) {
return true;
}
while (unfilteredEntries.hasMoreElements()) {
JarEntry je = unfilteredEntries.nextElement();
if (JarVerifier.isSigningRelated(je.getName())) {
continue;
}
entry = je;
return true;
}
return false;
}
public JarEntry nextElement() {
if (hasMoreElements()) {
JarEntry je = entry;
entry = null;
return newEntry(je);
}
throw new NoSuchElementException();
}
};
}
CodeSource[] getCodeSources(URL url) {
ensureInitialization();
if (jv != null) {
return jv.getCodeSources(this, url);
}
/*
* JAR file has no signed content. Is there a non-signing
* code source?
*/
Enumeration<String> unsigned = unsignedEntryNames();
if (unsigned.hasMoreElements()) {
return new CodeSource[]{JarVerifier.getUnsignedCS(url)};
} else {
return null;
}
}
private Enumeration<String> unsignedEntryNames() {
final Enumeration<JarEntry> entries = entries();
return new Enumeration<>() {
String name;
/*
* Grab entries from ZIP directory but screen out
* metadata.
*/
public boolean hasMoreElements() {
if (name != null) {
return true;
}
while (entries.hasMoreElements()) {
String value;
ZipEntry e = entries.nextElement();
value = e.getName();
if (e.isDirectory() || JarVerifier.isSigningRelated(value)) {
continue;
}
name = value;
return true;
}
return false;
}
public String nextElement() {
if (hasMoreElements()) {
String value = name;
name = null;
return value;
}
throw new NoSuchElementException();
}
};
}
CodeSource getCodeSource(URL url, String name) {
ensureInitialization();
if (jv != null) {
if (jv.eagerValidation) {
CodeSource cs;
JarEntry je = getJarEntry(name);
if (je != null) {
cs = jv.getCodeSource(url, this, je);
} else {
cs = jv.getCodeSource(url, name);
}
return cs;
} else {
return jv.getCodeSource(url, name);
}
}
return JarVerifier.getUnsignedCS(url);
}
void setEagerValidation(boolean eager) {
try {
maybeInstantiateVerifier();
} catch (IOException e) {
throw new RuntimeException(e);
}
if (jv != null) {
jv.setEagerValidation(eager);
}
}
List<Object> getManifestDigests() {
ensureInitialization();
if (jv != null) {
return jv.getManifestDigests();
}
return new ArrayList<>();
}
}

View File

@ -26,11 +26,12 @@
package java.util.jar;
import java.io.*;
import java.net.URL;
import java.util.*;
import java.security.*;
import java.security.CodeSigner;
import java.security.NoSuchAlgorithmException;
import java.security.SignatureException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.util.zip.ZipEntry;
import jdk.internal.util.jar.JarIndex;
import sun.security.util.ManifestDigester;
@ -87,12 +88,6 @@ class JarVerifier {
/** the manifest name this JarVerifier is created upon */
final String manifestName;
/** controls eager signature validation */
boolean eagerValidation;
/** makes code source singleton instances unique to us */
private Object csdomain = new Object();
/** collect -DIGEST-MANIFEST values for deny list */
private List<Object> manifestDigests;
@ -333,19 +328,12 @@ class JarVerifier {
}
/**
* Return an array of java.security.cert.Certificate objects for
* Return an array of Certificate objects for
* the given file in the jar.
* @deprecated
*/
@Deprecated
public java.security.cert.Certificate[] getCerts(String name)
public Certificate[] getCerts(JarEntry entry)
{
return mapSignersToCertArray(getCodeSigners(name));
}
public java.security.cert.Certificate[] getCerts(JarFile jar, JarEntry entry)
{
return mapSignersToCertArray(getCodeSigners(jar, entry));
return mapSignersToCertArray(getCodeSigners(entry));
}
/**
@ -353,42 +341,20 @@ class JarVerifier {
* the given file in the jar. this array is not cloned.
*
*/
public CodeSigner[] getCodeSigners(String name)
public CodeSigner[] getCodeSigners(JarEntry entry)
{
return verifiedSigners.get(name);
}
public CodeSigner[] getCodeSigners(JarFile jar, JarEntry entry)
{
String name = entry.getName();
if (eagerValidation && sigFileSigners.get(name) != null) {
/*
* Force a read of the entry data to generate the
* verification hash.
*/
try {
InputStream s = jar.getInputStream(entry);
byte[] buffer = new byte[1024];
int n = buffer.length;
while (n != -1) {
n = s.read(buffer, 0, buffer.length);
}
s.close();
} catch (IOException e) {
}
}
return getCodeSigners(name);
return verifiedSigners.get(entry.getName());
}
/*
* Convert an array of signers into an array of concatenated certificate
* arrays.
*/
private static java.security.cert.Certificate[] mapSignersToCertArray(
private static Certificate[] mapSignersToCertArray(
CodeSigner[] signers) {
if (signers != null) {
ArrayList<java.security.cert.Certificate> certChains = new ArrayList<>();
ArrayList<Certificate> certChains = new ArrayList<>();
for (CodeSigner signer : signers) {
certChains.addAll(
signer.getSignerCertPath().getCertificates());
@ -396,7 +362,7 @@ class JarVerifier {
// Convert into a Certificate[]
return certChains.toArray(
new java.security.cert.Certificate[certChains.size()]);
new Certificate[certChains.size()]);
}
return null;
}
@ -510,369 +476,6 @@ class JarVerifier {
}
}
// Extended JavaUtilJarAccess CodeSource API Support
private Map<URL, Map<CodeSigner[], CodeSource>> urlToCodeSourceMap = new HashMap<>();
private Map<CodeSigner[], CodeSource> signerToCodeSource = new HashMap<>();
private URL lastURL;
private Map<CodeSigner[], CodeSource> lastURLMap;
/*
* Create a unique mapping from codeSigner cache entries to CodeSource.
* In theory, multiple URLs origins could map to a single locally cached
* and shared JAR file although in practice there will be a single URL in use.
*/
private synchronized CodeSource mapSignersToCodeSource(URL url, CodeSigner[] signers) {
Map<CodeSigner[], CodeSource> map;
if (url == lastURL) {
map = lastURLMap;
} else {
map = urlToCodeSourceMap.get(url);
if (map == null) {
map = new HashMap<>();
urlToCodeSourceMap.put(url, map);
}
lastURLMap = map;
lastURL = url;
}
CodeSource cs = map.get(signers);
if (cs == null) {
cs = new VerifierCodeSource(csdomain, url, signers);
signerToCodeSource.put(signers, cs);
}
return cs;
}
private CodeSource[] mapSignersToCodeSources(URL url, List<CodeSigner[]> signers, boolean unsigned) {
List<CodeSource> sources = new ArrayList<>();
for (CodeSigner[] signer : signers) {
sources.add(mapSignersToCodeSource(url, signer));
}
if (unsigned) {
sources.add(mapSignersToCodeSource(url, null));
}
return sources.toArray(new CodeSource[sources.size()]);
}
private CodeSigner[] emptySigner = new CodeSigner[0];
/*
* Match CodeSource to a CodeSigner[] in the signer cache.
*/
private CodeSigner[] findMatchingSigners(CodeSource cs) {
if (cs instanceof VerifierCodeSource vcs) {
if (vcs.isSameDomain(csdomain)) {
return vcs.getPrivateSigners();
}
}
/*
* In practice signers should always be optimized above
* but this handles a CodeSource of any type, just in case.
*/
CodeSource[] sources = mapSignersToCodeSources(cs.getLocation(), getJarCodeSigners(), true);
List<CodeSource> sourceList = new ArrayList<>();
for (CodeSource source : sources) {
sourceList.add(source);
}
int j = sourceList.indexOf(cs);
if (j != -1) {
CodeSigner[] match;
match = ((VerifierCodeSource) sourceList.get(j)).getPrivateSigners();
if (match == null) {
match = emptySigner;
}
return match;
}
return null;
}
/*
* Instances of this class hold uncopied references to internal
* signing data that can be compared by object reference identity.
*/
private static class VerifierCodeSource extends CodeSource {
@java.io.Serial
private static final long serialVersionUID = -9047366145967768825L;
URL vlocation;
CodeSigner[] vsigners;
java.security.cert.Certificate[] vcerts;
@SuppressWarnings("serial") // Not statically typed as Serializable
Object csdomain;
VerifierCodeSource(Object csdomain, URL location, CodeSigner[] signers) {
super(location, signers);
this.csdomain = csdomain;
vlocation = location;
vsigners = signers; // from signerCache
}
VerifierCodeSource(Object csdomain, URL location, java.security.cert.Certificate[] certs) {
super(location, certs);
this.csdomain = csdomain;
vlocation = location;
vcerts = certs; // from signerCache
}
/*
* All VerifierCodeSource instances are constructed based on
* singleton signerCache or signerCacheCert entries for each unique signer.
* No CodeSigner<->Certificate[] conversion is required.
* We use these assumptions to optimize equality comparisons.
*/
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (obj instanceof VerifierCodeSource that) {
/*
* Only compare against other per-signer singletons constructed
* on behalf of the same JarFile instance. Otherwise, compare
* things the slower way.
*/
if (isSameDomain(that.csdomain)) {
if (that.vsigners != this.vsigners
|| that.vcerts != this.vcerts) {
return false;
}
if (that.vlocation != null) {
return that.vlocation.equals(this.vlocation);
} else if (this.vlocation != null) {
return this.vlocation.equals(that.vlocation);
} else { // both null
return true;
}
}
}
return super.equals(obj);
}
boolean isSameDomain(Object csdomain) {
return this.csdomain == csdomain;
}
private CodeSigner[] getPrivateSigners() {
return vsigners;
}
private java.security.cert.Certificate[] getPrivateCertificates() {
return vcerts;
}
}
private Map<String, CodeSigner[]> signerMap;
private synchronized Map<String, CodeSigner[]> signerMap() {
if (signerMap == null) {
/*
* Snapshot signer state so it doesn't change on us. We care
* only about the asserted signatures. Verification of
* signature validity happens via the JarEntry apis.
*/
signerMap = HashMap.newHashMap(verifiedSigners.size() + sigFileSigners.size());
signerMap.putAll(verifiedSigners);
signerMap.putAll(sigFileSigners);
}
return signerMap;
}
public synchronized Enumeration<String> entryNames(JarFile jar, final CodeSource[] cs) {
final Map<String, CodeSigner[]> map = signerMap();
final Iterator<Map.Entry<String, CodeSigner[]>> itor = map.entrySet().iterator();
boolean matchUnsigned = false;
/*
* Grab a single copy of the CodeSigner arrays. Check
* to see if we can optimize CodeSigner equality test.
*/
List<CodeSigner[]> req = new ArrayList<>(cs.length);
for (CodeSource c : cs) {
CodeSigner[] match = findMatchingSigners(c);
if (match != null) {
if (match.length > 0) {
req.add(match);
} else {
matchUnsigned = true;
}
} else {
matchUnsigned = true;
}
}
final List<CodeSigner[]> signersReq = req;
final Enumeration<String> enum2 = matchUnsigned ? unsignedEntryNames(jar) : Collections.emptyEnumeration();
return new Enumeration<>() {
String name;
public boolean hasMoreElements() {
if (name != null) {
return true;
}
while (itor.hasNext()) {
Map.Entry<String, CodeSigner[]> e = itor.next();
if (signersReq.contains(e.getValue())) {
name = e.getKey();
return true;
}
}
while (enum2.hasMoreElements()) {
name = enum2.nextElement();
return true;
}
return false;
}
public String nextElement() {
if (hasMoreElements()) {
String value = name;
name = null;
return value;
}
throw new NoSuchElementException();
}
};
}
/*
* Like entries() but screens out internal JAR mechanism entries
* and includes signed entries with no ZIP data.
*/
public Enumeration<JarEntry> entries2(final JarFile jar, Enumeration<JarEntry> e) {
final Map<String, CodeSigner[]> map = new HashMap<>();
map.putAll(signerMap());
final Enumeration<JarEntry> enum_ = e;
return new Enumeration<>() {
Enumeration<String> signers = null;
JarEntry entry;
public boolean hasMoreElements() {
if (entry != null) {
return true;
}
while (enum_.hasMoreElements()) {
JarEntry je = enum_.nextElement();
if (JarVerifier.isSigningRelated(je.getName())) {
continue;
}
entry = jar.newEntry(je);
return true;
}
if (signers == null) {
signers = Collections.enumeration(map.keySet());
}
while (signers.hasMoreElements()) {
String name = signers.nextElement();
entry = jar.newEntry(name);
return true;
}
// Any map entries left?
return false;
}
public JarEntry nextElement() {
if (hasMoreElements()) {
JarEntry je = entry;
map.remove(je.getName());
entry = null;
return je;
}
throw new NoSuchElementException();
}
};
}
// true if file is part of the signature mechanism itself
static boolean isSigningRelated(String name) {
return SignatureFileVerifier.isSigningRelated(name);
}
private Enumeration<String> unsignedEntryNames(JarFile jar) {
final Map<String, CodeSigner[]> map = signerMap();
final Enumeration<JarEntry> entries = jar.entries();
return new Enumeration<>() {
String name;
/*
* Grab entries from ZIP directory but screen out
* metadata.
*/
public boolean hasMoreElements() {
if (name != null) {
return true;
}
while (entries.hasMoreElements()) {
String value;
ZipEntry e = entries.nextElement();
value = e.getName();
if (e.isDirectory() || isSigningRelated(value)) {
continue;
}
if (map.get(value) == null) {
name = value;
return true;
}
}
return false;
}
public String nextElement() {
if (hasMoreElements()) {
String value = name;
name = null;
return value;
}
throw new NoSuchElementException();
}
};
}
private List<CodeSigner[]> jarCodeSigners;
private synchronized List<CodeSigner[]> getJarCodeSigners() {
if (jarCodeSigners == null) {
HashSet<CodeSigner[]> set = new HashSet<>();
set.addAll(signerMap().values());
jarCodeSigners = new ArrayList<>();
jarCodeSigners.addAll(set);
}
return jarCodeSigners;
}
public synchronized CodeSource[] getCodeSources(JarFile jar, URL url) {
boolean hasUnsigned = unsignedEntryNames(jar).hasMoreElements();
return mapSignersToCodeSources(url, getJarCodeSigners(), hasUnsigned);
}
public CodeSource getCodeSource(URL url, String name) {
CodeSigner[] signers;
signers = signerMap().get(name);
return mapSignersToCodeSource(url, signers);
}
public CodeSource getCodeSource(URL url, JarFile jar, JarEntry je) {
return mapSignersToCodeSource(url, getCodeSigners(jar, je));
}
public void setEagerValidation(boolean eager) {
eagerValidation = eager;
}
public synchronized List<Object> getManifestDigests() {
return Collections.unmodifiableList(manifestDigests);
}
static CodeSource getUnsignedCS(URL url) {
return new VerifierCodeSource(null, url, (java.security.cert.Certificate[]) null);
}
/**
* Returns whether the name is trusted. Used by
* {@link Manifest#getTrustedAttributes(String)}.

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2002, 2022, 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
@ -26,12 +26,6 @@
package java.util.jar;
import java.io.IOException;
import java.net.URL;
import java.security.CodeSource;
import java.util.Enumeration;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import jdk.internal.access.JavaUtilJarAccess;
@ -40,30 +34,6 @@ class JavaUtilJarAccessImpl implements JavaUtilJarAccess {
return jar.hasClassPathAttribute();
}
public CodeSource[] getCodeSources(JarFile jar, URL url) {
return jar.getCodeSources(url);
}
public CodeSource getCodeSource(JarFile jar, URL url, String name) {
return jar.getCodeSource(url, name);
}
public Enumeration<String> entryNames(JarFile jar, CodeSource[] cs) {
return jar.entryNames(cs);
}
public Enumeration<JarEntry> entries2(JarFile jar) {
return jar.entries2();
}
public void setEagerValidation(JarFile jar, boolean eager) {
jar.setEagerValidation(eager);
}
public List<Object> getManifestDigests(JarFile jar) {
return jar.getManifestDigests();
}
public Attributes getTrustedAttributes(Manifest man, String name) {
return man.getTrustedAttributes(name);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2002, 2022, 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
@ -26,10 +26,6 @@
package jdk.internal.access;
import java.io.IOException;
import java.net.URL;
import java.security.CodeSource;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.Attributes;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
@ -37,12 +33,6 @@ import java.util.jar.Manifest;
public interface JavaUtilJarAccess {
public boolean jarFileHasClassPathAttribute(JarFile jar) throws IOException;
public CodeSource[] getCodeSources(JarFile jar, URL url);
public CodeSource getCodeSource(JarFile jar, URL url, String name);
public Enumeration<String> entryNames(JarFile jar, CodeSource[] cs);
public Enumeration<JarEntry> entries2(JarFile jar);
public void setEagerValidation(JarFile jar, boolean eager);
public List<Object> getManifestDigests(JarFile jar);
public Attributes getTrustedAttributes(Manifest man, String name);
public void ensureInitialization(JarFile jar);
public boolean isInitializing();