1 /*
   2  * Copyright (c) 2016, 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 sun.security.x509.X509CertImpl;
  40 
  41 /**
  42  * The purpose of this class is to determine the trust anchor certificates is in
  43  * the cacerts file.  This is used for PKIX CertPath checking.
  44  */
  45 public class AnchorCertificates {
  46 
  47     private static final Debug debug = Debug.getInstance("certpath");
  48     private static final String HASH = "SHA-256";
  49     private static Set<String> certs = Collections.emptySet();
  50 
  51     static  {
  52         AccessController.doPrivileged(new PrivilegedAction<Void>() {
  53             @Override
  54             public Void run() {
  55                 File f = new File(System.getProperty("java.home"),
  56                         "lib/security/cacerts");
  57                 KeyStore cacerts;
  58                 try {
  59                     cacerts = KeyStore.getInstance("JKS");
  60                     try (FileInputStream fis = new FileInputStream(f)) {
  61                         cacerts.load(fis, "changeit".toCharArray());
  62                         certs = new HashSet<>();
  63                         Enumeration<String> list = cacerts.aliases();
  64                         String alias;
  65                         while (list.hasMoreElements()) {
  66                             alias = list.nextElement();
  67                             // Check if this cert is labeled a trust anchor.
  68                             if (alias.contains(" [jdk")) {
  69                                 X509Certificate cert = (X509Certificate) cacerts
  70                                         .getCertificate(alias);
  71                                 certs.add(X509CertImpl.getFingerprint(HASH, cert));
  72                             }
  73                         }
  74                     }
  75                 } catch (Exception e) {
  76                     if (debug != null) {
  77                         debug.println("Error parsing cacerts");
  78                     }
  79                     e.printStackTrace();
  80                 }
  81                 return null;
  82             }
  83         });
  84     }
  85 
  86     /**
  87      * Checks if a certificate is a trust anchor.
  88      *
  89      * @param cert the certificate to check
  90      * @return true if the certificate is trusted.
  91      */
  92     public static boolean contains(X509Certificate cert) {
  93         String key = X509CertImpl.getFingerprint(HASH, cert);
  94         boolean result = certs.contains(key);
  95         if (result && debug != null) {
  96             debug.println("AnchorCertificate.contains: matched " +
  97                     cert.getSubjectDN());
  98         }
  99         return result;
 100     }
 101 
 102     private AnchorCertificates() {}
 103 }