# HG changeset patch # User xuelei # Date 1322476519 28800 # Node ID 6561c702c8a7d4b423c9719c1269fecd69964bcd # Parent fc8efc57da082f6cbca2f768887c29868a8d48f6 7115524: sun.security.provider.certpath.ssl.SSLServerCertStore no longer works Reviewed-by: weijun diff -r fc8efc57da08 -r 6561c702c8a7 jdk/src/share/classes/sun/security/provider/certpath/ssl/SSLServerCertStore.java --- a/jdk/src/share/classes/sun/security/provider/certpath/ssl/SSLServerCertStore.java Mon Nov 28 18:16:29 2011 +0800 +++ b/jdk/src/share/classes/sun/security/provider/certpath/ssl/SSLServerCertStore.java Mon Nov 28 02:35:19 2011 -0800 @@ -44,12 +44,16 @@ import java.security.cert.CRLSelector; import java.security.cert.X509Certificate; import java.security.cert.X509CRL; +import java.net.Socket; +import java.net.URLConnection; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSession; +import javax.net.ssl.SSLEngine; +import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManager; -import javax.net.ssl.X509TrustManager; +import javax.net.ssl.X509ExtendedTrustManager; /** * A CertStore that retrieves an SSL server's certificate chain. @@ -57,31 +61,74 @@ public final class SSLServerCertStore extends CertStoreSpi { private final URI uri; + private final static GetChainTrustManager trustManager; + private final static SSLSocketFactory socketFactory; + private final static HostnameVerifier hostnameVerifier; + + static { + trustManager = new GetChainTrustManager(); + hostnameVerifier = new HostnameVerifier() { + public boolean verify(String hostname, SSLSession session) { + return true; + } + }; + + SSLSocketFactory tempFactory; + try { + SSLContext context = SSLContext.getInstance("SSL"); + context.init(null, new TrustManager[] { trustManager }, null); + tempFactory = context.getSocketFactory(); + } catch (GeneralSecurityException gse) { + tempFactory = null; + } + + socketFactory = tempFactory; + } SSLServerCertStore(URI uri) throws InvalidAlgorithmParameterException { super(null); this.uri = uri; } - public synchronized Collection engineGetCertificates - (CertSelector selector) throws CertStoreException - { + public Collection engineGetCertificates + (CertSelector selector) throws CertStoreException { + try { - SSLContext sc = SSLContext.getInstance("SSL"); - GetChainTrustManager xtm = new GetChainTrustManager(); - sc.init(null, new TrustManager[] { xtm }, null); - HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); - HttpsURLConnection.setDefaultHostnameVerifier( - new HostnameVerifier() { - public boolean verify(String hostname, SSLSession session) { - return true; + URLConnection urlConn = uri.toURL().openConnection(); + if (urlConn instanceof HttpsURLConnection) { + if (socketFactory == null) { + throw new CertStoreException( + "No initialized SSLSocketFactory"); + } + + HttpsURLConnection https = (HttpsURLConnection)urlConn; + https.setSSLSocketFactory(socketFactory); + https.setHostnameVerifier(hostnameVerifier); + synchronized (trustManager) { + try { + https.connect(); + return getMatchingCerts( + trustManager.serverChain, selector); + } catch (IOException ioe) { + // If the server certificate has already been + // retrieved, don't mind the connection state. + if (trustManager.exchangedServerCerts) { + return getMatchingCerts( + trustManager.serverChain, selector); + } + + // otherwise, rethrow the exception + throw ioe; + } finally { + trustManager.cleanup(); } - }); - uri.toURL().openConnection().connect(); - return getMatchingCerts(xtm.serverChain, selector); - } catch (GeneralSecurityException | IOException e) { - throw new CertStoreException(e); + } + } + } catch (IOException ioe) { + throw new CertStoreException(ioe); } + + return Collections.emptySet(); } private static List getMatchingCerts @@ -106,37 +153,77 @@ throw new UnsupportedOperationException(); } - static synchronized CertStore getInstance(URI uri) + static CertStore getInstance(URI uri) throws InvalidAlgorithmParameterException { return new CS(new SSLServerCertStore(uri), null, "SSLServer", null); } /* - * An X509TrustManager that simply stores a reference to the server's - * certificate chain. + * An X509ExtendedTrustManager that ignores the server certificate + * validation. */ - private static class GetChainTrustManager implements X509TrustManager { - private List serverChain; + private static class GetChainTrustManager + extends X509ExtendedTrustManager { + + private List serverChain = + Collections.emptyList(); + private boolean exchangedServerCerts = false; + + @Override + public X509Certificate[] getAcceptedIssuers() { + return new X509Certificate[0]; + } - public X509Certificate[] getAcceptedIssuers() { + @Override + public void checkClientTrusted(X509Certificate[] chain, + String authType) throws CertificateException { + + throw new UnsupportedOperationException(); + } + + @Override + public void checkClientTrusted(X509Certificate[] chain, String authType, + Socket socket) throws CertificateException { + throw new UnsupportedOperationException(); } - public void checkClientTrusted(X509Certificate[] chain, - String authType) - throws CertificateException - { + @Override + public void checkClientTrusted(X509Certificate[] chain, String authType, + SSLEngine engine) throws CertificateException { + throw new UnsupportedOperationException(); } + @Override public void checkServerTrusted(X509Certificate[] chain, - String authType) - throws CertificateException - { + String authType) throws CertificateException { + + exchangedServerCerts = true; this.serverChain = (chain == null) - ? Collections.emptyList() - : Arrays.asList(chain); + ? Collections.emptyList() + : Arrays.asList(chain); + + } + + @Override + public void checkServerTrusted(X509Certificate[] chain, String authType, + Socket socket) throws CertificateException { + + checkServerTrusted(chain, authType); + } + + @Override + public void checkServerTrusted(X509Certificate[] chain, String authType, + SSLEngine engine) throws CertificateException { + + checkServerTrusted(chain, authType); + } + + void cleanup() { + exchangedServerCerts = false; + serverChain = Collections.emptyList(); } }