< prev index next >
src/java.base/share/classes/sun/security/ssl/X509KeyManagerImpl.java
Print this page
@@ -52,11 +52,11 @@
* . it is explicitly designed to accommodate KeyStores that change over
* the lifetime of the process.
* . it makes an effort to choose the key that matches best, i.e. one that
* is not expired and has the appropriate certificate extensions.
*
- * Note that this code is not explicitly performance optimzied yet.
+ * Note that this code is not explicitly performance optimized yet.
*
* @author Andreas Sterbenz
*/
final class X509KeyManagerImpl extends X509ExtendedKeyManager
implements X509KeyManager {
@@ -133,10 +133,11 @@
@Override
public String chooseServerAlias(String keyType,
Principal[] issuers, Socket socket) {
return chooseAlias(getKeyTypes(keyType), issuers, CheckType.SERVER,
getAlgorithmConstraints(socket),
+ getCertificateAuthorities(socket),
X509TrustManagerImpl.getRequestedServerNames(socket),
"HTTPS"); // The SNI HostName is a fully qualified domain name.
// The certificate selection scheme for SNI HostName
// is similar to HTTPS endpoint identification scheme
// implemented in this provider.
@@ -151,10 +152,11 @@
@Override
public String chooseEngineServerAlias(String keyType,
Principal[] issuers, SSLEngine engine) {
return chooseAlias(getKeyTypes(keyType), issuers, CheckType.SERVER,
getAlgorithmConstraints(engine),
+ getCertificateAuthorities(engine),
X509TrustManagerImpl.getRequestedServerNames(engine),
"HTTPS"); // The SNI HostName is a fully qualified domain name.
// The certificate selection scheme for SNI HostName
// is similar to HTTPS endpoint identification scheme
// implemented in this provider.
@@ -236,10 +238,44 @@
}
return new SSLAlgorithmConstraints(engine, true);
}
+ private CertificateAuthority[] getCertificateAuthorities(Socket socket) {
+ if(socket != null && socket.isConnected() && socket instanceof SSLSocket){
+ final SSLSocket sslSocket = (SSLSocket)socket;
+ final SSLParameters sslParameters = sslSocket.getSSLParameters();
+ if (sslParameters.getUseCertificateAuthorities()) {
+ return getCertificateAuthorities(sslSocket.getHandshakeSession());
+ }
+ }
+ return null;
+ }
+
+ private CertificateAuthority[] getCertificateAuthorities(SSLEngine engine) {
+ if (engine != null) {
+ final SSLParameters sslParameters = engine.getSSLParameters();
+ if (sslParameters.getUseCertificateAuthorities()) {
+ return getCertificateAuthorities(engine.getHandshakeSession());
+ }
+ }
+ return null;
+ }
+
+ private CertificateAuthority[] getCertificateAuthorities(SSLSession session) {
+ if (session != null) {
+ final ProtocolVersion protocolVersion =
+ ProtocolVersion.valueOf(session.getProtocol());
+ if (protocolVersion.useTLS12PlusSpec()) {
+ if (session instanceof ExtendedSSLSession) {
+ return ((ExtendedSSLSession)session).getCertificateAuthorities();
+ }
+ }
+ }
+ return null;
+ }
+
// we construct the alias we return to JSSE as seen in the code below
// a unique id is included to allow us to reliably cache entries
// between the calls to getCertificateChain() and getPrivateKey()
// even if tokens are inserted or removed
private String makeAlias(EntryStatus entry) {
@@ -362,15 +398,16 @@
*/
private String chooseAlias(List<KeyType> keyTypeList, Principal[] issuers,
CheckType checkType, AlgorithmConstraints constraints) {
return chooseAlias(keyTypeList, issuers,
- checkType, constraints, null, null);
+ checkType, constraints, null, null, null);
}
private String chooseAlias(List<KeyType> keyTypeList, Principal[] issuers,
CheckType checkType, AlgorithmConstraints constraints,
+ CertificateAuthority[] certificateAuthorities,
List<SNIServerName> requestedServerNames, String idAlgorithm) {
if (keyTypeList == null || keyTypeList.isEmpty()) {
return null;
}
@@ -379,11 +416,12 @@
List<EntryStatus> allResults = null;
for (int i = 0, n = builders.size(); i < n; i++) {
try {
List<EntryStatus> results = getAliases(i, keyTypeList,
issuerSet, false, checkType, constraints,
- requestedServerNames, idAlgorithm);
+ certificateAuthorities, requestedServerNames,
+ idAlgorithm);
if (results != null) {
// the results will either be a single perfect match
// or 1 or more imperfect matches
// if it's a perfect match, return immediately
EntryStatus status = results.get(0);
@@ -434,11 +472,11 @@
List<EntryStatus> allResults = null;
for (int i = 0, n = builders.size(); i < n; i++) {
try {
List<EntryStatus> results = getAliases(i, keyTypeList,
issuerSet, true, checkType, constraints,
- null, null);
+ null, null, null);
if (results != null) {
if (allResults == null) {
allResults = new ArrayList<EntryStatus>();
}
allResults.addAll(results);
@@ -711,10 +749,11 @@
*/
private List<EntryStatus> getAliases(int builderIndex,
List<KeyType> keyTypes, Set<Principal> issuerSet,
boolean findAll, CheckType checkType,
AlgorithmConstraints constraints,
+ CertificateAuthority[] certificateAuthorities,
List<SNIServerName> requestedServerNames,
String idAlgorithm) throws Exception {
Builder builder = builders.get(builderIndex);
KeyStore ks = builder.getKeyStore();
@@ -780,10 +819,37 @@
}
continue;
}
}
+ // check that certificate chain has an indicated certificate authority
+ // (if indications are available)
+ if (certificateAuthorities != null) {
+ boolean foundCertificateAuthority = false;
+ // Iterate the certificate chain starting from root certificate
+ look_for_ca:
+ for (int i = chain.length; i > 0;) {
+ i--;
+ final X509Certificate cert = (X509Certificate) chain[i];
+ // Can safely cast because of
+ // previous check for X509Certificate
+ for (CertificateAuthority certificateAuthority : certificateAuthorities) {
+ try {
+ if (certificateAuthority.implies(cert)) {
+ foundCertificateAuthority = true;
+ break look_for_ca;
+ }
+ } catch (Exception e1) {
+ // Certificate matching is a best-effort. Continue looking for matches.
+ }
+ }
+ }
+ if (foundCertificateAuthority == false) {
+ continue;
+ }
+ }
+
// check the algorithm constraints
if (constraints != null &&
!conformsToAlgorithmConstraints(constraints, chain,
checkType.getValidator())) {
< prev index next >