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
18package javax.net.ssl;
19
20import java.net.HttpURLConnection;
21import java.net.URL;
22import java.security.Principal;
23import java.security.cert.Certificate;
24import 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 */
106public 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