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.ssl; 27 28 import java.lang.ref.WeakReference; 29 import java.io.*; 30 import java.util.*; 31 32 import java.security.*; 33 import java.security.cert.*; 34 import java.security.cert.Certificate; 35 36 import sun.security.action.*; 37 import sun.security.validator.TrustStoreUtil; 38 39 /** 40 * Collection of static utility methods to manage the default trusted KeyStores 41 * effectively. 42 */ 43 final class TrustStoreManager { 44 private static final Debug debug = Debug.getInstance("ssl"); 45 46 // A singleton service to manage the default trusted KeyStores effectively. 47 private static final TrustAnchorManager tam = new TrustAnchorManager(); 48 49 // Restrict instantiation of this class. 50 private TrustStoreManager() { 51 // empty 52 } 53 54 /** 55 * Return an unmodifiable set of all trusted X509Certificates contained 56 * in the default trusted KeyStore. 57 */ 58 public static Set<X509Certificate> getTrustedCerts() throws Exception { 59 return tam.getTrustedCerts(TrustStoreDescriptor.createInstance()); 60 } 61 62 /** 63 * Return an instance of the default trusted KeyStore. 64 */ 95 96 // the password used for the trust store 97 private final String storePassword; 98 99 // the File object of the trust store 100 private final File storeFile; 101 102 // the last modified time of the store 103 private final long lastModified; 104 105 private TrustStoreDescriptor(String storeName, String storeType, 106 String storeProvider, String storePassword, 107 File storeFile, long lastModified) { 108 this.storeName = storeName; 109 this.storeType = storeType; 110 this.storeProvider = storeProvider; 111 this.storePassword = storePassword; 112 this.storeFile = storeFile; 113 this.lastModified = lastModified; 114 115 if (debug != null && Debug.isOn("trustmanager")) { 116 System.out.println( 117 "trustStore is: " + storeName + "\n" + 118 "trustStore type is: " + storeType + "\n" + 119 "trustStore provider is: " + storeProvider + "\n" + 120 "the last modified time is: " + (new Date(lastModified))); 121 } 122 } 123 124 /** 125 * Create an instance of TrustStoreDescriptor for the default 126 * trusted KeyStore. 127 */ 128 static TrustStoreDescriptor createInstance() { 129 return AccessController.doPrivileged(new PrivilegedAction<>() { 130 131 @Override 132 public TrustStoreDescriptor run() { 133 // Get the system properties for trust store. 134 String storePropName = System.getProperty( 135 "javax.net.ssl.trustStore", jsseDefaultStore); 136 String storePropType = System.getProperty( 137 "javax.net.ssl.trustStoreType", 138 KeyStore.getDefaultType()); 139 String storePropProvider = System.getProperty( 140 "javax.net.ssl.trustStoreProvider", ""); 141 String storePropPassword = System.getProperty( 142 "javax.net.ssl.trustStorePassword", ""); 143 144 String temporaryName = ""; 145 File temporaryFile = null; 146 long temporaryTime = 0L; 147 if (!"NONE".equals(storePropName)) { 148 String[] fileNames = 149 new String[] {storePropName, defaultStore}; 150 for (String fileName : fileNames) { 151 File f = new File(fileName); 152 if (f.isFile() && f.canRead()) { 153 temporaryName = fileName;; 154 temporaryFile = f; 155 temporaryTime = f.lastModified(); 156 157 break; 158 } 159 160 // Not break, the file is inaccessible. 161 if (debug != null && 162 Debug.isOn("trustmanager")) { 163 System.out.println( 164 "Inaccessible trust store: " + 165 storePropName); 166 } 167 } 168 } else { 169 temporaryName = storePropName; 170 } 171 172 return new TrustStoreDescriptor( 173 temporaryName, storePropType, storePropProvider, 174 storePropPassword, temporaryFile, temporaryTime); 175 } 176 }); 177 } 178 179 @Override 180 public boolean equals(Object obj) { 181 if (obj == this) { 182 return true; 183 } 250 this.descriptor = null; 251 this.ksRef = new WeakReference<>(null); 252 this.csRef = new WeakReference<>(null); 253 } 254 255 /** 256 * Get the default trusted KeyStore with the specified descriptor. 257 * 258 * @return null if the underlying KeyStore is not available. 259 */ 260 synchronized KeyStore getKeyStore( 261 TrustStoreDescriptor descriptor) throws Exception { 262 263 TrustStoreDescriptor temporaryDesc = this.descriptor; 264 KeyStore ks = ksRef.get(); 265 if ((ks != null) && descriptor.equals(temporaryDesc)) { 266 return ks; 267 } 268 269 // Reload a new key store. 270 if ((debug != null) && Debug.isOn("trustmanager")) { 271 System.out.println("Reload the trust store"); 272 } 273 274 ks = loadKeyStore(descriptor); 275 this.descriptor = descriptor; 276 this.ksRef = new WeakReference<>(ks); 277 278 return ks; 279 } 280 281 /** 282 * Get trusted certificates in the default trusted KeyStore with 283 * the specified descriptor. 284 * 285 * @return empty collection if the underlying KeyStore is not available. 286 */ 287 synchronized Set<X509Certificate> getTrustedCerts( 288 TrustStoreDescriptor descriptor) throws Exception { 289 290 KeyStore ks = null; 291 TrustStoreDescriptor temporaryDesc = this.descriptor; 292 Set<X509Certificate> certs = csRef.get(); 293 if (certs != null) { 294 if (descriptor.equals(temporaryDesc)) { 295 return certs; 296 } else { 297 // Use the new descriptor. 298 this.descriptor = descriptor; 299 } 300 } else { 301 // Try to use the cached store at first. 302 if (descriptor.equals(temporaryDesc)) { 303 ks = ksRef.get(); 304 } else { 305 // Use the new descriptor. 306 this.descriptor = descriptor; 307 } 308 } 309 310 // Reload the trust store if needed. 311 if (ks == null) { 312 if ((debug != null) && Debug.isOn("trustmanager")) { 313 System.out.println("Reload the trust store"); 314 } 315 ks = loadKeyStore(descriptor); 316 } 317 318 // Reload trust certs from the key store. 319 if ((debug != null) && Debug.isOn("trustmanager")) { 320 System.out.println("Reload trust certs"); 321 } 322 323 certs = loadTrustedCerts(ks); 324 if ((debug != null) && Debug.isOn("trustmanager")) { 325 System.out.println("Reloaded " + certs.size() + " trust certs"); 326 } 327 328 // Note that as ks is a local variable, it is not 329 // necessary to add it to the ksRef weak reference. 330 this.csRef = new WeakReference<>(certs); 331 332 return certs; 333 } 334 335 /** 336 * Load the KeyStore as described in the specified descriptor. 337 */ 338 private static KeyStore loadKeyStore( 339 TrustStoreDescriptor descriptor) throws Exception { 340 if (!"NONE".equals(descriptor.storeName) && 341 descriptor.storeFile == null) { 342 343 // No file available, no KeyStore available. 344 if (debug != null && Debug.isOn("trustmanager")) { 345 System.out.println("No available key store"); 346 } 347 348 return null; 349 } 350 351 KeyStore ks; 352 if (descriptor.storeProvider.isEmpty()) { 353 ks = KeyStore.getInstance(descriptor.storeType); 354 } else { 355 ks = KeyStore.getInstance( 356 descriptor.storeType, descriptor.storeProvider); 357 } 358 359 char[] password = null; 360 if (!descriptor.storePassword.isEmpty()) { 361 password = descriptor.storePassword.toCharArray(); 362 } 363 364 if (!"NONE".equals(descriptor.storeName)) { 365 try (FileInputStream fis = AccessController.doPrivileged( 366 new OpenFileInputStreamAction(descriptor.storeFile))) { 367 ks.load(fis, password); 368 } catch (FileNotFoundException fnfe) { 369 // No file available, no KeyStore available. 370 if (debug != null && Debug.isOn("trustmanager")) { 371 System.out.println( 372 "Not available key store: " + descriptor.storeName); 373 } 374 375 return null; 376 } 377 } else { 378 ks.load(null, password); 379 } 380 381 return ks; 382 } 383 384 /** 385 * Load trusted certificates from the specified KeyStore. 386 */ 387 private static Set<X509Certificate> loadTrustedCerts(KeyStore ks) { 388 if (ks == null) { 389 return Collections.<X509Certificate>emptySet(); 390 } 391 | 1 /* 2 * Copyright (c) 2018, 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.ssl; 27 28 import java.io.*; 29 import java.lang.ref.WeakReference; 30 import java.security.*; 31 import java.security.cert.*; 32 import java.util.*; 33 import sun.security.action.*; 34 import sun.security.validator.TrustStoreUtil; 35 36 /** 37 * Collection of static utility methods to manage the default trusted KeyStores 38 * effectively. 39 */ 40 final class TrustStoreManager { 41 42 // A singleton service to manage the default trusted KeyStores effectively. 43 private static final TrustAnchorManager tam = new TrustAnchorManager(); 44 45 // Restrict instantiation of this class. 46 private TrustStoreManager() { 47 // empty 48 } 49 50 /** 51 * Return an unmodifiable set of all trusted X509Certificates contained 52 * in the default trusted KeyStore. 53 */ 54 public static Set<X509Certificate> getTrustedCerts() throws Exception { 55 return tam.getTrustedCerts(TrustStoreDescriptor.createInstance()); 56 } 57 58 /** 59 * Return an instance of the default trusted KeyStore. 60 */ 91 92 // the password used for the trust store 93 private final String storePassword; 94 95 // the File object of the trust store 96 private final File storeFile; 97 98 // the last modified time of the store 99 private final long lastModified; 100 101 private TrustStoreDescriptor(String storeName, String storeType, 102 String storeProvider, String storePassword, 103 File storeFile, long lastModified) { 104 this.storeName = storeName; 105 this.storeType = storeType; 106 this.storeProvider = storeProvider; 107 this.storePassword = storePassword; 108 this.storeFile = storeFile; 109 this.lastModified = lastModified; 110 111 if (SSLLogger.isOn && SSLLogger.isOn("trustmanager")) { 112 SSLLogger.fine( 113 "trustStore is: " + storeName + "\n" + 114 "trustStore type is: " + storeType + "\n" + 115 "trustStore provider is: " + storeProvider + "\n" + 116 "the last modified time is: " + (new Date(lastModified))); 117 } 118 } 119 120 /** 121 * Create an instance of TrustStoreDescriptor for the default 122 * trusted KeyStore. 123 */ 124 @SuppressWarnings("Convert2Lambda") 125 static TrustStoreDescriptor createInstance() { 126 return AccessController.doPrivileged( 127 new PrivilegedAction<TrustStoreDescriptor>() { 128 129 @Override 130 public TrustStoreDescriptor run() { 131 // Get the system properties for trust store. 132 String storePropName = System.getProperty( 133 "javax.net.ssl.trustStore", jsseDefaultStore); 134 String storePropType = System.getProperty( 135 "javax.net.ssl.trustStoreType", 136 KeyStore.getDefaultType()); 137 String storePropProvider = System.getProperty( 138 "javax.net.ssl.trustStoreProvider", ""); 139 String storePropPassword = System.getProperty( 140 "javax.net.ssl.trustStorePassword", ""); 141 142 String temporaryName = ""; 143 File temporaryFile = null; 144 long temporaryTime = 0L; 145 if (!"NONE".equals(storePropName)) { 146 String[] fileNames = 147 new String[] {storePropName, defaultStore}; 148 for (String fileName : fileNames) { 149 File f = new File(fileName); 150 if (f.isFile() && f.canRead()) { 151 temporaryName = fileName;; 152 temporaryFile = f; 153 temporaryTime = f.lastModified(); 154 155 break; 156 } 157 158 // Not break, the file is inaccessible. 159 if (SSLLogger.isOn && 160 SSLLogger.isOn("trustmanager")) { 161 SSLLogger.fine( 162 "Inaccessible trust store: " + 163 storePropName); 164 } 165 } 166 } else { 167 temporaryName = storePropName; 168 } 169 170 return new TrustStoreDescriptor( 171 temporaryName, storePropType, storePropProvider, 172 storePropPassword, temporaryFile, temporaryTime); 173 } 174 }); 175 } 176 177 @Override 178 public boolean equals(Object obj) { 179 if (obj == this) { 180 return true; 181 } 248 this.descriptor = null; 249 this.ksRef = new WeakReference<>(null); 250 this.csRef = new WeakReference<>(null); 251 } 252 253 /** 254 * Get the default trusted KeyStore with the specified descriptor. 255 * 256 * @return null if the underlying KeyStore is not available. 257 */ 258 synchronized KeyStore getKeyStore( 259 TrustStoreDescriptor descriptor) throws Exception { 260 261 TrustStoreDescriptor temporaryDesc = this.descriptor; 262 KeyStore ks = ksRef.get(); 263 if ((ks != null) && descriptor.equals(temporaryDesc)) { 264 return ks; 265 } 266 267 // Reload a new key store. 268 if (SSLLogger.isOn && SSLLogger.isOn("trustmanager")) { 269 SSLLogger.fine("Reload the trust store"); 270 } 271 272 ks = loadKeyStore(descriptor); 273 this.descriptor = descriptor; 274 this.ksRef = new WeakReference<>(ks); 275 276 return ks; 277 } 278 279 /** 280 * Get trusted certificates in the default trusted KeyStore with 281 * the specified descriptor. 282 * 283 * @return empty collection if the underlying KeyStore is not available. 284 */ 285 synchronized Set<X509Certificate> getTrustedCerts( 286 TrustStoreDescriptor descriptor) throws Exception { 287 288 KeyStore ks = null; 289 TrustStoreDescriptor temporaryDesc = this.descriptor; 290 Set<X509Certificate> certs = csRef.get(); 291 if (certs != null) { 292 if (descriptor.equals(temporaryDesc)) { 293 return certs; 294 } else { 295 // Use the new descriptor. 296 this.descriptor = descriptor; 297 } 298 } else { 299 // Try to use the cached store at first. 300 if (descriptor.equals(temporaryDesc)) { 301 ks = ksRef.get(); 302 } else { 303 // Use the new descriptor. 304 this.descriptor = descriptor; 305 } 306 } 307 308 // Reload the trust store if needed. 309 if (ks == null) { 310 if (SSLLogger.isOn && SSLLogger.isOn("trustmanager")) { 311 SSLLogger.fine("Reload the trust store"); 312 } 313 ks = loadKeyStore(descriptor); 314 } 315 316 // Reload trust certs from the key store. 317 if (SSLLogger.isOn && SSLLogger.isOn("trustmanager")) { 318 SSLLogger.fine("Reload trust certs"); 319 } 320 321 certs = loadTrustedCerts(ks); 322 if (SSLLogger.isOn && SSLLogger.isOn("trustmanager")) { 323 SSLLogger.fine("Reloaded " + certs.size() + " trust certs"); 324 } 325 326 // Note that as ks is a local variable, it is not 327 // necessary to add it to the ksRef weak reference. 328 this.csRef = new WeakReference<>(certs); 329 330 return certs; 331 } 332 333 /** 334 * Load the the KeyStore as described in the specified descriptor. 335 */ 336 private static KeyStore loadKeyStore( 337 TrustStoreDescriptor descriptor) throws Exception { 338 if (!"NONE".equals(descriptor.storeName) && 339 descriptor.storeFile == null) { 340 341 // No file available, no KeyStore available. 342 if (SSLLogger.isOn && SSLLogger.isOn("trustmanager")) { 343 SSLLogger.fine("No available key store"); 344 } 345 346 return null; 347 } 348 349 KeyStore ks; 350 if (descriptor.storeProvider.isEmpty()) { 351 ks = KeyStore.getInstance(descriptor.storeType); 352 } else { 353 ks = KeyStore.getInstance( 354 descriptor.storeType, descriptor.storeProvider); 355 } 356 357 char[] password = null; 358 if (!descriptor.storePassword.isEmpty()) { 359 password = descriptor.storePassword.toCharArray(); 360 } 361 362 if (!"NONE".equals(descriptor.storeName)) { 363 try (FileInputStream fis = AccessController.doPrivileged( 364 new OpenFileInputStreamAction(descriptor.storeFile))) { 365 ks.load(fis, password); 366 } catch (FileNotFoundException fnfe) { 367 // No file available, no KeyStore available. 368 if (SSLLogger.isOn && SSLLogger.isOn("trustmanager")) { 369 SSLLogger.fine( 370 "Not available key store: " + descriptor.storeName); 371 } 372 373 return null; 374 } 375 } else { 376 ks.load(null, password); 377 } 378 379 return ks; 380 } 381 382 /** 383 * Load trusted certificates from the specified KeyStore. 384 */ 385 private static Set<X509Certificate> loadTrustedCerts(KeyStore ks) { 386 if (ks == null) { 387 return Collections.<X509Certificate>emptySet(); 388 } 389 |