1 /* 2 * Copyright (c) 1999, 2013, 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 javax.net.ssl.*; 29 import java.security.*; 30 import java.security.cert.*; 31 import java.security.cert.Certificate; 32 import java.util.*; 33 import java.net.Socket; 34 35 import javax.security.auth.x500.X500Principal; 36 37 38 /** 39 * An implementation of X509KeyManager backed by a KeyStore. 40 * 41 * The backing KeyStore is inspected when this object is constructed. 42 * All key entries containing a PrivateKey and a non-empty chain of 43 * X509Certificate are then copied into an internal store. This means 44 * that subsequent modifications of the KeyStore have no effect on the 45 * X509KeyManagerImpl object. 46 * 47 * Note that this class assumes that all keys are protected by the same 48 * password. 49 * 50 * The JSSE handshake code currently calls into this class via 51 * chooseClientAlias() and chooseServerAlias() to find the certificates to 52 * use. As implemented here, both always return the first alias returned by 53 * getClientAliases() and getServerAliases(). In turn, these methods are 54 * implemented by calling getAliases(), which performs the actual lookup. 55 * 56 * Note that this class currently implements no checking of the local 57 * certificates. In particular, it is *not* guaranteed that: 58 * . the certificates are within their validity period and not revoked 59 * . the signatures verify 60 * . they form a PKIX compliant chain. 61 * . the certificate extensions allow the certificate to be used for 62 * the desired purpose. 63 * 64 * Chains that fail any of these criteria will probably be rejected by 65 * the remote peer. 66 * 67 */ 68 final class SunX509KeyManagerImpl extends X509ExtendedKeyManager { 69 70 private static final Debug debug = Debug.getInstance("ssl"); 71 72 private static final String[] STRING0 = new String[0]; 73 74 /* 75 * The credentials from the KeyStore as 76 * Map: String(alias) -> X509Credentials(credentials) 77 */ 78 private Map<String,X509Credentials> credentialsMap; 79 80 /* 81 * Cached server aliases for the case issuers == null. 82 * (in the current JSSE implementation, issuers are always null for 83 * server certs). See chooseServerAlias() for details. 84 * 85 * Map: String(keyType) -> String[](alias) 86 */ 87 private final Map<String,String[]> serverAliasCache; 88 89 /* 90 * Basic container for credentials implemented as an inner class. 91 */ 131 continue; 132 } 133 Key key = ks.getKey(alias, password); 134 if (key instanceof PrivateKey == false) { 135 continue; 136 } 137 Certificate[] certs = ks.getCertificateChain(alias); 138 if ((certs == null) || (certs.length == 0) || 139 !(certs[0] instanceof X509Certificate)) { 140 continue; 141 } 142 if (!(certs instanceof X509Certificate[])) { 143 Certificate[] tmp = new X509Certificate[certs.length]; 144 System.arraycopy(certs, 0, tmp, 0, certs.length); 145 certs = tmp; 146 } 147 148 X509Credentials cred = new X509Credentials((PrivateKey)key, 149 (X509Certificate[])certs); 150 credentialsMap.put(alias, cred); 151 if (debug != null && Debug.isOn("keymanager")) { 152 System.out.println("***"); 153 System.out.println("found key for : " + alias); 154 for (int i = 0; i < certs.length; i++) { 155 System.out.println("chain [" + i + "] = " 156 + certs[i]); 157 } 158 System.out.println("***"); 159 } 160 } 161 } 162 163 /* 164 * Returns the certificate chain associated with the given alias. 165 * 166 * @return the certificate chain (ordered with the user's certificate first 167 * and the root certificate authority last) 168 */ 169 @Override 170 public X509Certificate[] getCertificateChain(String alias) { 171 if (alias == null) { 172 return null; 173 } 174 X509Credentials cred = credentialsMap.get(alias); 175 if (cred == null) { 176 return null; 177 } else { 178 return cred.certificates.clone(); 365 if (!sigType.equals( 366 certs[1].getPublicKey().getAlgorithm())) { 367 continue; 368 } 369 } else { 370 // Check the signature algorithm of the certificate itself. 371 // Look for the "withRSA" in "SHA1withRSA", etc. 372 String sigAlgName = 373 certs[0].getSigAlgName().toUpperCase(Locale.ENGLISH); 374 String pattern = "WITH" + 375 sigType.toUpperCase(Locale.ENGLISH); 376 if (sigAlgName.contains(pattern) == false) { 377 continue; 378 } 379 } 380 } 381 382 if (issuers.length == 0) { 383 // no issuer specified, match all 384 aliases.add(alias); 385 if (debug != null && Debug.isOn("keymanager")) { 386 System.out.println("matching alias: " + alias); 387 } 388 } else { 389 Set<X500Principal> certIssuers = 390 credentials.getIssuerX500Principals(); 391 for (int i = 0; i < x500Issuers.length; i++) { 392 if (certIssuers.contains(issuers[i])) { 393 aliases.add(alias); 394 if (debug != null && Debug.isOn("keymanager")) { 395 System.out.println("matching alias: " + alias); 396 } 397 break; 398 } 399 } 400 } 401 } 402 403 String[] aliasStrings = aliases.toArray(STRING0); 404 return ((aliasStrings.length == 0) ? null : aliasStrings); 405 } 406 407 /* 408 * Convert an array of Principals to an array of X500Principals, if 409 * possible. Principals that cannot be converted are ignored. 410 */ 411 private static X500Principal[] convertPrincipals(Principal[] principals) { 412 List<X500Principal> list = new ArrayList<>(principals.length); 413 for (int i = 0; i < principals.length; i++) { 414 Principal p = principals[i]; 415 if (p instanceof X500Principal) { | 1 /* 2 * Copyright (c) 1999, 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.net.Socket; 29 import java.security.Key; 30 import java.security.KeyStore; 31 import java.security.KeyStoreException; 32 import java.security.NoSuchAlgorithmException; 33 import java.security.Principal; 34 import java.security.PrivateKey; 35 import java.security.UnrecoverableKeyException; 36 import java.security.cert.Certificate; 37 import java.security.cert.X509Certificate; 38 import java.util.ArrayList; 39 import java.util.Collections; 40 import java.util.Enumeration; 41 import java.util.HashMap; 42 import java.util.HashSet; 43 import java.util.List; 44 import java.util.Locale; 45 import java.util.Map; 46 import java.util.Set; 47 import javax.net.ssl.SSLEngine; 48 import javax.net.ssl.X509ExtendedKeyManager; 49 import javax.security.auth.x500.X500Principal; 50 51 52 /** 53 * An implementation of X509KeyManager backed by a KeyStore. 54 * 55 * The backing KeyStore is inspected when this object is constructed. 56 * All key entries containing a PrivateKey and a non-empty chain of 57 * X509Certificate are then copied into an internal store. This means 58 * that subsequent modifications of the KeyStore have no effect on the 59 * X509KeyManagerImpl object. 60 * 61 * Note that this class assumes that all keys are protected by the same 62 * password. 63 * 64 * The JSSE handshake code currently calls into this class via 65 * chooseClientAlias() and chooseServerAlias() to find the certificates to 66 * use. As implemented here, both always return the first alias returned by 67 * getClientAliases() and getServerAliases(). In turn, these methods are 68 * implemented by calling getAliases(), which performs the actual lookup. 69 * 70 * Note that this class currently implements no checking of the local 71 * certificates. In particular, it is *not* guaranteed that: 72 * . the certificates are within their validity period and not revoked 73 * . the signatures verify 74 * . they form a PKIX compliant chain. 75 * . the certificate extensions allow the certificate to be used for 76 * the desired purpose. 77 * 78 * Chains that fail any of these criteria will probably be rejected by 79 * the remote peer. 80 * 81 */ 82 final class SunX509KeyManagerImpl extends X509ExtendedKeyManager { 83 84 private static final String[] STRING0 = new String[0]; 85 86 /* 87 * The credentials from the KeyStore as 88 * Map: String(alias) -> X509Credentials(credentials) 89 */ 90 private Map<String,X509Credentials> credentialsMap; 91 92 /* 93 * Cached server aliases for the case issuers == null. 94 * (in the current JSSE implementation, issuers are always null for 95 * server certs). See chooseServerAlias() for details. 96 * 97 * Map: String(keyType) -> String[](alias) 98 */ 99 private final Map<String,String[]> serverAliasCache; 100 101 /* 102 * Basic container for credentials implemented as an inner class. 103 */ 143 continue; 144 } 145 Key key = ks.getKey(alias, password); 146 if (key instanceof PrivateKey == false) { 147 continue; 148 } 149 Certificate[] certs = ks.getCertificateChain(alias); 150 if ((certs == null) || (certs.length == 0) || 151 !(certs[0] instanceof X509Certificate)) { 152 continue; 153 } 154 if (!(certs instanceof X509Certificate[])) { 155 Certificate[] tmp = new X509Certificate[certs.length]; 156 System.arraycopy(certs, 0, tmp, 0, certs.length); 157 certs = tmp; 158 } 159 160 X509Credentials cred = new X509Credentials((PrivateKey)key, 161 (X509Certificate[])certs); 162 credentialsMap.put(alias, cred); 163 if (SSLLogger.isOn && SSLLogger.isOn("keymanager")) { 164 SSLLogger.fine("found key for : " + alias, (Object[])certs); 165 } 166 } 167 } 168 169 /* 170 * Returns the certificate chain associated with the given alias. 171 * 172 * @return the certificate chain (ordered with the user's certificate first 173 * and the root certificate authority last) 174 */ 175 @Override 176 public X509Certificate[] getCertificateChain(String alias) { 177 if (alias == null) { 178 return null; 179 } 180 X509Credentials cred = credentialsMap.get(alias); 181 if (cred == null) { 182 return null; 183 } else { 184 return cred.certificates.clone(); 371 if (!sigType.equals( 372 certs[1].getPublicKey().getAlgorithm())) { 373 continue; 374 } 375 } else { 376 // Check the signature algorithm of the certificate itself. 377 // Look for the "withRSA" in "SHA1withRSA", etc. 378 String sigAlgName = 379 certs[0].getSigAlgName().toUpperCase(Locale.ENGLISH); 380 String pattern = "WITH" + 381 sigType.toUpperCase(Locale.ENGLISH); 382 if (sigAlgName.contains(pattern) == false) { 383 continue; 384 } 385 } 386 } 387 388 if (issuers.length == 0) { 389 // no issuer specified, match all 390 aliases.add(alias); 391 if (SSLLogger.isOn && SSLLogger.isOn("keymanager")) { 392 SSLLogger.fine("matching alias: " + alias); 393 } 394 } else { 395 Set<X500Principal> certIssuers = 396 credentials.getIssuerX500Principals(); 397 for (int i = 0; i < x500Issuers.length; i++) { 398 if (certIssuers.contains(issuers[i])) { 399 aliases.add(alias); 400 if (SSLLogger.isOn && SSLLogger.isOn("keymanager")) { 401 SSLLogger.fine("matching alias: " + alias); 402 } 403 break; 404 } 405 } 406 } 407 } 408 409 String[] aliasStrings = aliases.toArray(STRING0); 410 return ((aliasStrings.length == 0) ? null : aliasStrings); 411 } 412 413 /* 414 * Convert an array of Principals to an array of X500Principals, if 415 * possible. Principals that cannot be converted are ignored. 416 */ 417 private static X500Principal[] convertPrincipals(Principal[] principals) { 418 List<X500Principal> list = new ArrayList<>(principals.length); 419 for (int i = 0; i < principals.length; i++) { 420 Principal p = principals[i]; 421 if (p instanceof X500Principal) { |