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