mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 15:24:43 +02:00
8249906: Enhance opening JARs
Reviewed-by: weijun, rhalade, mschoene
This commit is contained in:
parent
17a741d6bc
commit
7232e3c704
24 changed files with 766 additions and 502 deletions
|
@ -0,0 +1,188 @@
|
|||
/*
|
||||
* Copyright (c) 2020, 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package sun.security.util;
|
||||
|
||||
import java.security.CodeSigner;
|
||||
import java.security.Key;
|
||||
import java.security.Timestamp;
|
||||
import java.security.cert.CertPath;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import sun.security.util.AnchorCertificates;
|
||||
import sun.security.util.ConstraintsParameters;
|
||||
import sun.security.validator.Validator;
|
||||
|
||||
/**
|
||||
* This class contains parameters for checking signed JARs against
|
||||
* constraints specified in the jdk.jar.disabledAlgorithms security
|
||||
* property.
|
||||
*/
|
||||
public class JarConstraintsParameters implements ConstraintsParameters {
|
||||
|
||||
// true if chain is anchored by a JDK root CA
|
||||
private boolean anchorIsJdkCA;
|
||||
private boolean anchorIsJdkCASet;
|
||||
// The timestamp of the signed JAR file, if timestamped
|
||||
private Date timestamp;
|
||||
// The keys of the signers
|
||||
private final Set<Key> keys;
|
||||
// The certs in the signers' chains that are issued by the trust anchor
|
||||
private final Set<X509Certificate> certsIssuedByAnchor;
|
||||
// The extended exception message
|
||||
private String message;
|
||||
|
||||
/**
|
||||
* Create a JarConstraintsParameters.
|
||||
*
|
||||
* @param signers the CodeSigners that signed the JAR
|
||||
*/
|
||||
public JarConstraintsParameters(CodeSigner[] signers) {
|
||||
this.keys = new HashSet<>();
|
||||
this.certsIssuedByAnchor = new HashSet<>();
|
||||
Date latestTimestamp = null;
|
||||
boolean skipTimestamp = false;
|
||||
|
||||
// Iterate over the signers and extract the keys, the latest
|
||||
// timestamp, and the last certificate of each chain which can be
|
||||
// used for checking if the signer's certificate chains back to a
|
||||
// JDK root CA
|
||||
for (CodeSigner signer : signers) {
|
||||
init(signer.getSignerCertPath());
|
||||
Timestamp timestamp = signer.getTimestamp();
|
||||
if (timestamp == null) {
|
||||
// this means one of the signers doesn't have a timestamp
|
||||
// and the JAR should be treated as if it isn't timestamped
|
||||
latestTimestamp = null;
|
||||
skipTimestamp = true;
|
||||
} else {
|
||||
// add the key and last cert of TSA too
|
||||
init(timestamp.getSignerCertPath());
|
||||
if (!skipTimestamp) {
|
||||
Date timestampDate = timestamp.getTimestamp();
|
||||
if (latestTimestamp == null) {
|
||||
latestTimestamp = timestampDate;
|
||||
} else {
|
||||
if (latestTimestamp.before(timestampDate)) {
|
||||
latestTimestamp = timestampDate;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
this.timestamp = latestTimestamp;
|
||||
}
|
||||
|
||||
// extract last certificate and key from chain
|
||||
private void init(CertPath cp) {
|
||||
@SuppressWarnings("unchecked")
|
||||
List<X509Certificate> chain =
|
||||
(List<X509Certificate>)cp.getCertificates();
|
||||
if (!chain.isEmpty()) {
|
||||
this.certsIssuedByAnchor.add(chain.get(chain.size() - 1));
|
||||
this.keys.add(chain.get(0).getPublicKey());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVariant() {
|
||||
return Validator.VAR_GENERIC;
|
||||
}
|
||||
|
||||
/**
|
||||
* Since loading the cacerts keystore can be an expensive operation,
|
||||
* this is only performed if this method is called during a "jdkCA"
|
||||
* constraints check of a disabled algorithm, and the result is cached.
|
||||
*
|
||||
* @return true if at least one of the certificates are issued by a
|
||||
* JDK root CA
|
||||
*/
|
||||
@Override
|
||||
public boolean anchorIsJdkCA() {
|
||||
if (anchorIsJdkCASet) {
|
||||
return anchorIsJdkCA;
|
||||
}
|
||||
for (X509Certificate cert : certsIssuedByAnchor) {
|
||||
if (AnchorCertificates.issuerOf(cert)) {
|
||||
anchorIsJdkCA = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
anchorIsJdkCASet = true;
|
||||
return anchorIsJdkCA;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Date getDate() {
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Key> getKeys() {
|
||||
return keys;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the extended error message. Note: this should be used
|
||||
* carefully as it is specific to the attribute/entry/file being checked.
|
||||
*
|
||||
* @param file the name of the signature related file being verified
|
||||
* @param target the attribute containing the algorithm that is being
|
||||
* checked
|
||||
*/
|
||||
public void setExtendedExceptionMsg(String file, String target) {
|
||||
message = " used" + (target != null ? " with " + target : "") +
|
||||
" in " + file + " file.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String extendedExceptionMsg() {
|
||||
return message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder("[\n");
|
||||
sb.append("\n Variant: ").append(getVariant());
|
||||
sb.append("\n Certs Issued by Anchor:");
|
||||
for (X509Certificate cert : certsIssuedByAnchor) {
|
||||
sb.append("\n Cert Issuer: ")
|
||||
.append(cert.getIssuerX500Principal());
|
||||
sb.append("\n Cert Subject: ")
|
||||
.append(cert.getSubjectX500Principal());
|
||||
}
|
||||
for (Key key : keys) {
|
||||
sb.append("\n Key: ").append(key.getAlgorithm());
|
||||
}
|
||||
if (timestamp != null) {
|
||||
sb.append("\n Timestamp: ").append(timestamp);
|
||||
}
|
||||
sb.append("\n]");
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue