Path: blob/master/src/java.base/share/classes/sun/security/util/JarConstraintsParameters.java
41159 views
/*1* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.security.util;2627import java.security.CodeSigner;28import java.security.Key;29import java.security.Timestamp;30import java.security.cert.CertPath;31import java.security.cert.X509Certificate;32import java.util.Date;33import java.util.HashSet;34import java.util.List;35import java.util.Set;36import sun.security.util.AnchorCertificates;37import sun.security.util.ConstraintsParameters;38import sun.security.validator.Validator;3940/**41* This class contains parameters for checking signed JARs against42* constraints specified in the jdk.jar.disabledAlgorithms security43* property.44*/45public class JarConstraintsParameters implements ConstraintsParameters {4647// true if chain is anchored by a JDK root CA48private boolean anchorIsJdkCA;49private boolean anchorIsJdkCASet;50// The timestamp of the signed JAR file, if timestamped51private Date timestamp;52// The keys of the signers53private final Set<Key> keys;54// The certs in the signers' chains that are issued by the trust anchor55private final Set<X509Certificate> certsIssuedByAnchor;56// The extended exception message57private String message;5859/**60* Create a JarConstraintsParameters.61*62* @param signers the CodeSigners that signed the JAR63*/64public JarConstraintsParameters(CodeSigner[] signers) {65this.keys = new HashSet<>();66this.certsIssuedByAnchor = new HashSet<>();67Date latestTimestamp = null;68boolean skipTimestamp = false;6970// Iterate over the signers and extract the keys, the latest71// timestamp, and the last certificate of each chain which can be72// used for checking if the signer's certificate chains back to a73// JDK root CA74for (CodeSigner signer : signers) {75init(signer.getSignerCertPath());76Timestamp timestamp = signer.getTimestamp();77if (timestamp == null) {78// this means one of the signers doesn't have a timestamp79// and the JAR should be treated as if it isn't timestamped80latestTimestamp = null;81skipTimestamp = true;82} else {83// add the key and last cert of TSA too84init(timestamp.getSignerCertPath());85if (!skipTimestamp) {86Date timestampDate = timestamp.getTimestamp();87if (latestTimestamp == null) {88latestTimestamp = timestampDate;89} else {90if (latestTimestamp.before(timestampDate)) {91latestTimestamp = timestampDate;92}93}94}95}96}97this.timestamp = latestTimestamp;98}99100// extract last certificate and key from chain101private void init(CertPath cp) {102@SuppressWarnings("unchecked")103List<X509Certificate> chain =104(List<X509Certificate>)cp.getCertificates();105if (!chain.isEmpty()) {106this.certsIssuedByAnchor.add(chain.get(chain.size() - 1));107this.keys.add(chain.get(0).getPublicKey());108}109}110111@Override112public String getVariant() {113return Validator.VAR_GENERIC;114}115116/**117* Since loading the cacerts keystore can be an expensive operation,118* this is only performed if this method is called during a "jdkCA"119* constraints check of a disabled algorithm, and the result is cached.120*121* @return true if at least one of the certificates are issued by a122* JDK root CA123*/124@Override125public boolean anchorIsJdkCA() {126if (anchorIsJdkCASet) {127return anchorIsJdkCA;128}129for (X509Certificate cert : certsIssuedByAnchor) {130if (AnchorCertificates.issuerOf(cert)) {131anchorIsJdkCA = true;132break;133}134}135anchorIsJdkCASet = true;136return anchorIsJdkCA;137}138139@Override140public Date getDate() {141return timestamp;142}143144@Override145public Set<Key> getKeys() {146return keys;147}148149/**150* Sets the extended error message. Note: this should be used151* carefully as it is specific to the attribute/entry/file being checked.152*153* @param file the name of the signature related file being verified154* @param target the attribute containing the algorithm that is being155* checked156*/157public void setExtendedExceptionMsg(String file, String target) {158message = " used" + (target != null ? " with " + target : "") +159" in " + file + " file.";160}161162@Override163public String extendedExceptionMsg() {164return message;165}166167@Override168public String toString() {169StringBuilder sb = new StringBuilder("[\n");170sb.append("\n Variant: ").append(getVariant());171sb.append("\n Certs Issued by Anchor:");172for (X509Certificate cert : certsIssuedByAnchor) {173sb.append("\n Cert Issuer: ")174.append(cert.getIssuerX500Principal());175sb.append("\n Cert Subject: ")176.append(cert.getSubjectX500Principal());177}178for (Key key : keys) {179sb.append("\n Key: ").append(key.getAlgorithm());180}181if (timestamp != null) {182sb.append("\n Timestamp: ").append(timestamp);183}184sb.append("\n]");185return sb.toString();186}187}188189190