1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 package javax.net.ssl; 19 20 import java.net.HttpURLConnection; 21 import java.net.URL; 22 import java.security.Principal; 23 import java.security.cert.Certificate; 24 import java.security.cert.X509Certificate; 25 26 /** 27 * An {@link HttpURLConnection} for HTTPS (<a 28 * href="http://tools.ietf.org/html/rfc2818">RFC 2818</a>). A 29 * connected {@code HttpsURLConnection} allows access to the 30 * negotiated cipher suite, the server certificate chain, and the 31 * client certificate chain if any. 32 * 33 * <h3>Providing an application specific X509TrustManager</h3> 34 * 35 * If an application wants to trust Certificate Authority (CA) 36 * certificates that are not part of the system, it should specify its 37 * own {@code X509TrustManager} via a {@code SSLSocketFactory} set on 38 * the {@code HttpsURLConnection}. The {@code X509TrustManager} can be 39 * created based on a {@code KeyStore} using a {@code 40 * TrustManagerFactory} to supply trusted CA certificates. Note that 41 * self-signed certificates are effectively their own CA and can be 42 * trusted by including them in a {@code KeyStore}. 43 * 44 * <p>For example, to trust a set of certificates specified by a {@code KeyStore}: 45 * <pre> {@code 46 * KeyStore keyStore = ...; 47 * String algorithm = TrustManagerFactory.getDefaultAlgorithm(); 48 * TrustManagerFactory tmf = TrustManagerFactory.getInstance(algorithm); 49 * tmf.init(keyStore); 50 * 51 * SSLContext context = SSLContext.getInstance("TLS"); 52 * context.init(null, tmf.getTrustManagers(), null); 53 * 54 * URL url = new URL("https://www.example.com/"); 55 * HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection(); 56 * urlConnection.setSSLSocketFactory(context.getSocketFactory()); 57 * InputStream in = urlConnection.getInputStream(); 58 * }</pre> 59 * 60 * <p>It is possible to implement {@code X509TrustManager} directly 61 * instead of using one created by a {@code 62 * TrustManagerFactory}. While this is straightforward in the insecure 63 * case of allowing all certificate chains to pass verification, 64 * writing a proper implementation will usually want to take advantage 65 * of {@link java.security.cert.CertPathValidator 66 * CertPathValidator}. In general, it might be better to write a 67 * custom {@code KeyStore} implementation to pass to the {@code 68 * TrustManagerFactory} than to try and write a custom {@code 69 * X509TrustManager}. 70 * 71 * <h3>Providing an application specific X509KeyManager</h3> 72 * 73 * A custom {@code X509KeyManager} can be used to supply a client 74 * certificate and its associated private key to authenticate a 75 * connection to the server. The {@code X509KeyManager} can be created 76 * based on a {@code KeyStore} using a {@code KeyManagerFactory}. 77 * 78 * <p>For example, to supply client certificates from a {@code KeyStore}: 79 * <pre> {@code 80 * KeyStore keyStore = ...; 81 * String algorithm = KeyManagerFactory.getDefaultAlgorithm(); 82 * KeyManagerFactory kmf = KeyManagerFactory.getInstance(algorithm); 83 * kmf.init(keyStore); 84 * 85 * SSLContext context = SSLContext.getInstance("TLS"); 86 * context.init(kmf.getKeyManagers(), null, null); 87 * 88 * URL url = new URL("https://www.example.com/"); 89 * HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection(); 90 * urlConnection.setSSLSocketFactory(context.getSocketFactory()); 91 * InputStream in = urlConnection.getInputStream(); 92 * }</pre> 93 * 94 * <p>A {@code X509KeyManager} can also be implemented directly. This 95 * can allow an application to return a certificate and private key 96 * from a non-{@code KeyStore} source or to specify its own logic for 97 * selecting a specific credential to use when many may be present in 98 * a single {@code KeyStore}. 99 * 100 * <h3>TLS Intolerance Support</h3> 101 * 102 * This class attempts to create secure connections using common TLS 103 * extensions and SSL deflate compression. Should that fail, the 104 * connection will be retried with SSLv3 only. 105 */ 106 public abstract class HttpsURLConnection extends HttpURLConnection { 107 /* 108 * Holds default instances so class preloading doesn't create an instance of 109 * it. 110 */ 111 private static class NoPreloadHolder { 112 public static HostnameVerifier defaultHostnameVerifier = new DefaultHostnameVerifier(); 113 114 public static SSLSocketFactory defaultSSLSocketFactory = (SSLSocketFactory) SSLSocketFactory 115 .getDefault(); 116 } 117 118 /** 119 * Sets the default hostname verifier to be used by new instances. 120 * 121 * @param v 122 * the new default hostname verifier 123 * @throws IllegalArgumentException 124 * if the specified verifier is {@code null}. 125 */ 126 public static void setDefaultHostnameVerifier(HostnameVerifier v) { 127 if (v == null) { 128 throw new IllegalArgumentException("HostnameVerifier is null"); 129 } 130 NoPreloadHolder.defaultHostnameVerifier = v; 131 } 132 133 /** 134 * Returns the default hostname verifier. 135 * 136 * @return the default hostname verifier. 137 */ 138 public static HostnameVerifier getDefaultHostnameVerifier() { 139 return NoPreloadHolder.defaultHostnameVerifier; 140 } 141 142 /** 143 * Sets the default SSL socket factory to be used by new instances. 144 * 145 * @param sf 146 * the new default SSL socket factory. 147 * @throws IllegalArgumentException 148 * if the specified socket factory is {@code null}. 149 */ 150 public static void setDefaultSSLSocketFactory(SSLSocketFactory sf) { 151 if (sf == null) { 152 throw new IllegalArgumentException("SSLSocketFactory is null"); 153 } 154 NoPreloadHolder.defaultSSLSocketFactory = sf; 155 } 156 157 /** 158 * Returns the default SSL socket factory for new instances. 159 * 160 * @return the default SSL socket factory for new instances. 161 */ 162 public static SSLSocketFactory getDefaultSSLSocketFactory() { 163 return NoPreloadHolder.defaultSSLSocketFactory; 164 } 165 166 /** 167 * The host name verifier used by this connection. It is initialized from 168 * the default hostname verifier 169 * {@link #setDefaultHostnameVerifier(HostnameVerifier)} or 170 * {@link #getDefaultHostnameVerifier()}. 171 */ 172 protected HostnameVerifier hostnameVerifier; 173 174 private SSLSocketFactory sslSocketFactory; 175 176 /** 177 * Creates a new {@code HttpsURLConnection} with the specified {@code URL}. 178 * 179 * @param url 180 * the {@code URL} to connect to. 181 */ 182 protected HttpsURLConnection(URL url) { 183 super(url); 184 hostnameVerifier = NoPreloadHolder.defaultHostnameVerifier; 185 sslSocketFactory = NoPreloadHolder.defaultSSLSocketFactory; 186 } 187 188 /** 189 * Returns the name of the cipher suite negotiated during the SSL handshake. 190 * 191 * @return the name of the cipher suite negotiated during the SSL handshake. 192 * @throws IllegalStateException 193 * if no connection has been established yet. 194 */ 195 public abstract String getCipherSuite(); 196 197 /** 198 * Returns the list of local certificates used during the handshake. These 199 * certificates were sent to the peer. 200 * 201 * @return Returns the list of certificates used during the handshake with 202 * the local identity certificate followed by CAs, or {@code null} 203 * if no certificates were used during the handshake. 204 * @throws IllegalStateException 205 * if no connection has been established yet. 206 */ 207 public abstract Certificate[] getLocalCertificates(); 208 209 /** 210 * Return the list of certificates identifying the peer during the 211 * handshake. 212 * 213 * @return the list of certificates identifying the peer with the peer's 214 * identity certificate followed by CAs. 215 * @throws SSLPeerUnverifiedException 216 * if the identity of the peer has not been verified.. 217 * @throws IllegalStateException 218 * if no connection has been established yet. 219 */ 220 public abstract Certificate[] getServerCertificates() throws SSLPeerUnverifiedException; 221 222 /** 223 * Returns the {@code Principal} identifying the peer. 224 * 225 * @return the {@code Principal} identifying the peer. 226 * @throws SSLPeerUnverifiedException 227 * if the identity of the peer has not been verified. 228 * @throws IllegalStateException 229 * if no connection has been established yet. 230 */ 231 public Principal getPeerPrincipal() throws SSLPeerUnverifiedException { 232 Certificate[] certs = getServerCertificates(); 233 if (certs == null || certs.length == 0 || (!(certs[0] instanceof X509Certificate))) { 234 throw new SSLPeerUnverifiedException("No server's end-entity certificate"); 235 } 236 return ((X509Certificate) certs[0]).getSubjectX500Principal(); 237 } 238 239 /** 240 * Returns the {@code Principal} used to identify the local host during the handshake. 241 * 242 * @return the {@code Principal} used to identify the local host during the handshake, or 243 * {@code null} if none was used. 244 * @throws IllegalStateException 245 * if no connection has been established yet. 246 */ 247 public Principal getLocalPrincipal() { 248 Certificate[] certs = getLocalCertificates(); 249 if (certs == null || certs.length == 0 || (!(certs[0] instanceof X509Certificate))) { 250 return null; 251 } 252 return ((X509Certificate) certs[0]).getSubjectX500Principal(); 253 } 254 255 /** 256 * Sets the hostname verifier for this instance. 257 * 258 * @param v 259 * the hostname verifier for this instance. 260 * @throws IllegalArgumentException 261 * if the specified verifier is {@code null}. 262 */ 263 public void setHostnameVerifier(HostnameVerifier v) { 264 if (v == null) { 265 throw new IllegalArgumentException("HostnameVerifier is null"); 266 } 267 hostnameVerifier = v; 268 } 269 270 /** 271 * Returns the hostname verifier used by this instance. 272 * 273 * @return the hostname verifier used by this instance. 274 */ 275 public HostnameVerifier getHostnameVerifier() { 276 return hostnameVerifier; 277 } 278 279 /** 280 * Sets the SSL socket factory for this instance. 281 * 282 * @param sf 283 * the SSL socket factory to be used by this instance. 284 * @throws IllegalArgumentException 285 * if the specified socket factory is {@code null}. 286 */ 287 public void setSSLSocketFactory(SSLSocketFactory sf) { 288 if (sf == null) { 289 throw new IllegalArgumentException("SSLSocketFactory is null"); 290 } 291 sslSocketFactory = sf; 292 } 293 294 /** 295 * Returns the SSL socket factory used by this instance. 296 * 297 * @return the SSL socket factory used by this instance. 298 */ 299 public SSLSocketFactory getSSLSocketFactory() { 300 return sslSocketFactory; 301 } 302 303 } 304