1 /* 2 * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package sun.security.util; 27 28 import java.io.File; 29 import java.io.FileInputStream; 30 import java.security.AccessController; 31 import java.security.KeyStore; 32 import java.security.PrivilegedAction; 33 import java.security.cert.X509Certificate; 34 import java.util.Collections; 35 import java.util.Enumeration; 36 import java.util.HashSet; 37 import java.util.Set; 38 39 import javax.security.auth.x500.X500Principal; 40 import sun.security.x509.X509CertImpl; 41 42 /** 43 * The purpose of this class is to determine the trust anchor certificates is in 44 * the cacerts file. This is used for PKIX CertPath checking. 45 */ 46 public class AnchorCertificates { 47 48 private static final Debug debug = Debug.getInstance("certpath"); 49 private static final String HASH = "SHA-256"; 50 private static Set<String> certs = Collections.emptySet(); 51 private static Set<X500Principal> certIssuers = Collections.emptySet(); 52 53 static { 54 @SuppressWarnings("removal") 55 var dummy = AccessController.doPrivileged(new PrivilegedAction<>() { 56 @Override 57 public Void run() { 58 File f = new File(FilePaths.cacerts()); 59 try { 60 KeyStore cacerts; 61 cacerts = KeyStore.getInstance("JKS"); 62 try (FileInputStream fis = new FileInputStream(f)) { 63 cacerts.load(fis, null); 64 certs = new HashSet<>(); 65 certIssuers = new HashSet<>(); 66 Enumeration<String> list = cacerts.aliases(); 67 while (list.hasMoreElements()) { 68 String alias = list.nextElement(); 69 // Check if this cert is labeled a trust anchor. 70 if (alias.contains(" [jdk")) { 71 X509Certificate cert = (X509Certificate) cacerts 72 .getCertificate(alias); 73 String fp = 74 X509CertImpl.getFingerprint(HASH, cert, debug); 75 // only add trust anchor if fingerprint can 76 // be calculated 77 if (fp != null) { 78 certs.add(fp); 79 certIssuers.add(cert.getSubjectX500Principal()); 80 } 81 } 82 } 83 } 84 } catch (Exception e) { 85 if (debug != null) { 86 debug.println("Error parsing cacerts"); 87 e.printStackTrace(); 88 } 89 } 90 return null; 91 } 92 }); 93 } 94 95 /** 96 * Checks if a certificate is a JDK trust anchor. 97 * 98 * @param cert the certificate to check 99 * @return true if the certificate is a JDK trust anchor 100 */ contains(X509Certificate cert)101 public static boolean contains(X509Certificate cert) { 102 String key = X509CertImpl.getFingerprint(HASH, cert, debug); 103 boolean result = (key == null ? false : certs.contains(key)); 104 if (result && debug != null) { 105 debug.println("AnchorCertificate.contains: matched " + 106 cert.getSubjectX500Principal()); 107 } 108 return result; 109 } 110 111 // BEGIN Android-removed: this class was not used on Android so far 112 // and as there is no cacers file (it is a directory on Android) 113 // this method will always return false. If code you add uses this 114 // method please be mindful of that and feel free to bring it back. 115 /* 116 * Checks if a JDK trust anchor is the issuer of a certificate. 117 * 118 * @param cert the certificate to check 119 * @return true if the certificate is issued by a trust anchor 120 * 121 public static boolean issuerOf(X509Certificate cert) { 122 return certIssuers.contains(cert.getIssuerX500Principal()); 123 } 124 */ 125 // END Android-removed: this class was not used on Android so far 126 // and as there is no cacers file (it is a directory on Android) 127 // this method will always return false. If code you add uses this 128 // method please be mindful of that and feel free to bring it back. 129 AnchorCertificates()130 private AnchorCertificates() {} 131 } 132