• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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      */
setDefaultHostnameVerifier(HostnameVerifier v)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      */
getDefaultHostnameVerifier()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      */
setDefaultSSLSocketFactory(SSLSocketFactory sf)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      */
getDefaultSSLSocketFactory()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      */
HttpsURLConnection(URL url)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      */
getCipherSuite()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      */
getLocalCertificates()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      */
getServerCertificates()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      */
getPeerPrincipal()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      */
getLocalPrincipal()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      */
setHostnameVerifier(HostnameVerifier v)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      */
getHostnameVerifier()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      */
setSSLSocketFactory(SSLSocketFactory sf)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      */
getSSLSocketFactory()299     public SSLSocketFactory getSSLSocketFactory() {
300         return sslSocketFactory;
301     }
302 
303 }
304