1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * This code is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License version 2 only, as
8  * published by the Free Software Foundation.  Oracle designates this
9  * particular file as subject to the "Classpath" exception as provided
10  * by Oracle in the LICENSE file that accompanied this code.
11  *
12  * This code is distributed in the hope that it will be useful, but WITHOUT
13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15  * version 2 for more details (a copy is included in the LICENSE file that
16  * accompanied this code).
17  *
18  * You should have received a copy of the GNU General Public License version
19  * 2 along with this work; if not, write to the Free Software Foundation,
20  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21  *
22  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
23  * or visit www.oracle.com if you need additional information or have any
24  * questions.
25  */
26 
27 package javax.net.ssl;
28 
29 import java.net.URL;
30 import java.net.HttpURLConnection;
31 import java.security.Principal;
32 import java.security.cert.X509Certificate;
33 
34 /**
35  * <code>HttpsURLConnection</code> extends <code>HttpURLConnection</code>
36  * with support for https-specific features.
37  * <P>
38  * See <A HREF="http://www.w3.org/pub/WWW/Protocols/">
39  * http://www.w3.org/pub/WWW/Protocols/</A> and
40  * <A HREF="http://www.ietf.org/"> RFC 2818 </A>
41  * for more details on the
42  * https specification.
43  * <P>
44  * This class uses <code>HostnameVerifier</code> and
45  * <code>SSLSocketFactory</code>.
46  * There are default implementations defined for both classes.
47  * However, the implementations can be replaced on a per-class (static) or
48  * per-instance basis.  All new <code>HttpsURLConnection</code>s instances
49  * will be assigned
50  * the "default" static values at instance creation, but they can be overriden
51  * by calling the appropriate per-instance set method(s) before
52  * <code>connect</code>ing.
53  *
54  * @since 1.4
55  */
56 abstract public
57 class HttpsURLConnection extends HttpURLConnection
58 {
59     /**
60      * Creates an <code>HttpsURLConnection</code> using the
61      * URL specified.
62      *
63      * @param url the URL
64      */
HttpsURLConnection(URL url)65     protected HttpsURLConnection(URL url) {
66         super(url);
67     }
68 
69     /**
70      * Returns the cipher suite in use on this connection.
71      *
72      * @return the cipher suite
73      * @throws IllegalStateException if this method is called before
74      *          the connection has been established.
75      */
getCipherSuite()76     public abstract String getCipherSuite();
77 
78     /**
79      * Returns the certificate(s) that were sent to the server during
80      * handshaking.
81      * <P>
82      * Note: This method is useful only when using certificate-based
83      * cipher suites.
84      * <P>
85      * When multiple certificates are available for use in a
86      * handshake, the implementation chooses what it considers the
87      * "best" certificate chain available, and transmits that to
88      * the other side.  This method allows the caller to know
89      * which certificate chain was actually sent.
90      *
91      * @return an ordered array of certificates,
92      *          with the client's own certificate first followed by any
93      *          certificate authorities.  If no certificates were sent,
94      *          then null is returned.
95      * @throws IllegalStateException if this method is called before
96      *          the connection has been established.
97      * @see #getLocalPrincipal()
98      */
getLocalCertificates()99     public abstract java.security.cert.Certificate [] getLocalCertificates();
100 
101     /**
102      * Returns the server's certificate chain which was established
103      * as part of defining the session.
104      * <P>
105      * Note: This method can be used only when using certificate-based
106      * cipher suites; using it with non-certificate-based cipher suites,
107      * such as Kerberos, will throw an SSLPeerUnverifiedException.
108      *
109      * @return an ordered array of server certificates,
110      *          with the peer's own certificate first followed by
111      *          any certificate authorities.
112      * @throws SSLPeerUnverifiedException if the peer is not verified.
113      * @throws IllegalStateException if this method is called before
114      *          the connection has been established.
115      * @see #getPeerPrincipal()
116      */
getServerCertificates()117     public abstract java.security.cert.Certificate [] getServerCertificates()
118             throws SSLPeerUnverifiedException;
119 
120     /**
121      * Returns the server's principal which was established as part of
122      * defining the session.
123      * <P>
124      * Note: Subclasses should override this method. If not overridden, it
125      * will default to returning the X500Principal of the server's end-entity
126      * certificate for certificate-based ciphersuites, or throw an
127      * SSLPeerUnverifiedException for non-certificate based ciphersuites,
128      * such as Kerberos.
129      *
130      * @return the server's principal. Returns an X500Principal of the
131      * end-entity certiticate for X509-based cipher suites, and
132      * KerberosPrincipal for Kerberos cipher suites.
133      *
134      * @throws SSLPeerUnverifiedException if the peer was not verified
135      * @throws IllegalStateException if this method is called before
136      *          the connection has been established.
137      *
138      * @see #getServerCertificates()
139      * @see #getLocalPrincipal()
140      *
141      * @since 1.5
142      */
getPeerPrincipal()143     public Principal getPeerPrincipal()
144             throws SSLPeerUnverifiedException {
145 
146         java.security.cert.Certificate[] certs = getServerCertificates();
147         return ((X509Certificate)certs[0]).getSubjectX500Principal();
148     }
149 
150     /**
151      * Returns the principal that was sent to the server during handshaking.
152      * <P>
153      * Note: Subclasses should override this method. If not overridden, it
154      * will default to returning the X500Principal of the end-entity certificate
155      * that was sent to the server for certificate-based ciphersuites or,
156      * return null for non-certificate based ciphersuites, such as Kerberos.
157      *
158      * @return the principal sent to the server. Returns an X500Principal
159      * of the end-entity certificate for X509-based cipher suites, and
160      * KerberosPrincipal for Kerberos cipher suites. If no principal was
161      * sent, then null is returned.
162      *
163      * @throws IllegalStateException if this method is called before
164      *          the connection has been established.
165      *
166      * @see #getLocalCertificates()
167      * @see #getPeerPrincipal()
168      *
169      * @since 1.5
170      */
getLocalPrincipal()171     public Principal getLocalPrincipal() {
172 
173         java.security.cert.Certificate[] certs = getLocalCertificates();
174         if (certs != null) {
175             return ((X509Certificate)certs[0]).getSubjectX500Principal();
176         } else {
177             return null;
178         }
179     }
180 
181     /*
182      * Holds the default instance so class preloading doesn't create an instance of
183      * it.
184      */
185     private static class NoPreloadHolder {
186         public static HostnameVerifier defaultHostnameVerifier;
187         public static final Class<? extends HostnameVerifier> originalDefaultHostnameVerifierClass;
188         static {
189             try {
190                 /**
191                   * <code>HostnameVerifier</code> provides a callback mechanism so that
192                   * implementers of this interface can supply a policy for
193                   * handling the case where the host to connect to and
194                   * the server name from the certificate mismatch.
195                   */
196                 defaultHostnameVerifier = (HostnameVerifier)
197                         Class.forName("com.android.okhttp.internal.tls.OkHostnameVerifier")
198                         .getField("INSTANCE").get(null);
199                 originalDefaultHostnameVerifierClass = defaultHostnameVerifier.getClass();
200             } catch (Exception e) {
201                 throw new AssertionError("Failed to obtain okhttp HostnameVerifier", e);
202             }
203         }
204     }
205 
206     /**
207      * The <code>hostnameVerifier</code> for this object.
208      */
209     protected HostnameVerifier hostnameVerifier;
210 
211     /**
212      * Sets the default <code>HostnameVerifier</code> inherited by a
213      * new instance of this class.
214      * <P>
215      * If this method is not called, the default
216      * <code>HostnameVerifier</code> assumes the connection should not
217      * be permitted.
218      *
219      * @param v the default host name verifier
220      * @throws IllegalArgumentException if the <code>HostnameVerifier</code>
221      *          parameter is null.
222      * @throws SecurityException if a security manager exists and its
223      *         <code>checkPermission</code> method does not allow
224      *         <code>SSLPermission("setHostnameVerifier")</code>
225      * @see #getDefaultHostnameVerifier()
226      */
setDefaultHostnameVerifier(HostnameVerifier v)227     public static void setDefaultHostnameVerifier(HostnameVerifier v) {
228         if (v == null) {
229             throw new IllegalArgumentException(
230                 "no default HostnameVerifier specified");
231         }
232 
233         SecurityManager sm = System.getSecurityManager();
234         if (sm != null) {
235             sm.checkPermission(new SSLPermission("setHostnameVerifier"));
236         }
237         NoPreloadHolder.defaultHostnameVerifier = v;
238     }
239 
240     /**
241      * Gets the default <code>HostnameVerifier</code> that is inherited
242      * by new instances of this class.
243      *
244      * @return the default host name verifier
245      * @see #setDefaultHostnameVerifier(HostnameVerifier)
246      */
getDefaultHostnameVerifier()247     public static HostnameVerifier getDefaultHostnameVerifier() {
248         return NoPreloadHolder.defaultHostnameVerifier;
249     }
250 
251     /**
252      * Sets the <code>HostnameVerifier</code> for this instance.
253      * <P>
254      * New instances of this class inherit the default static hostname
255      * verifier set by {@link #setDefaultHostnameVerifier(HostnameVerifier)
256      * setDefaultHostnameVerifier}.  Calls to this method replace
257      * this object's <code>HostnameVerifier</code>.
258      *
259      * @param v the host name verifier
260      * @throws IllegalArgumentException if the <code>HostnameVerifier</code>
261      *  parameter is null.
262      * @see #getHostnameVerifier()
263      * @see #setDefaultHostnameVerifier(HostnameVerifier)
264      */
setHostnameVerifier(HostnameVerifier v)265     public void setHostnameVerifier(HostnameVerifier v) {
266         if (v == null) {
267             throw new IllegalArgumentException(
268                 "no HostnameVerifier specified");
269         }
270 
271         hostnameVerifier = v;
272     }
273 
274     /**
275      * Gets the <code>HostnameVerifier</code> in place on this instance.
276      *
277      * @return the host name verifier
278      * @see #setHostnameVerifier(HostnameVerifier)
279      * @see #setDefaultHostnameVerifier(HostnameVerifier)
280      */
getHostnameVerifier()281     public HostnameVerifier getHostnameVerifier() {
282         if (hostnameVerifier == null) {
283             hostnameVerifier = NoPreloadHolder.defaultHostnameVerifier;
284         }
285         return hostnameVerifier;
286     }
287 
288     private static SSLSocketFactory defaultSSLSocketFactory = null;
289 
290     /**
291      * The <code>SSLSocketFactory</code> inherited when an instance
292      * of this class is created.
293      */
294     private SSLSocketFactory sslSocketFactory = getDefaultSSLSocketFactory();
295 
296     /**
297      * Sets the default <code>SSLSocketFactory</code> inherited by new
298      * instances of this class.
299      * <P>
300      * The socket factories are used when creating sockets for secure
301      * https URL connections.
302      *
303      * @param sf the default SSL socket factory
304      * @throws IllegalArgumentException if the SSLSocketFactory
305      *          parameter is null.
306      * @throws SecurityException if a security manager exists and its
307      *         <code>checkSetFactory</code> method does not allow
308      *         a socket factory to be specified.
309      * @see #getDefaultSSLSocketFactory()
310      */
setDefaultSSLSocketFactory(SSLSocketFactory sf)311     public static void setDefaultSSLSocketFactory(SSLSocketFactory sf) {
312         if (sf == null) {
313             throw new IllegalArgumentException(
314                 "no default SSLSocketFactory specified");
315         }
316 
317         SecurityManager sm = System.getSecurityManager();
318         if (sm != null) {
319             sm.checkSetFactory();
320         }
321         defaultSSLSocketFactory = sf;
322     }
323 
324     /**
325      * Gets the default static <code>SSLSocketFactory</code> that is
326      * inherited by new instances of this class.
327      * <P>
328      * The socket factories are used when creating sockets for secure
329      * https URL connections.
330      *
331      * @return the default <code>SSLSocketFactory</code>
332      * @see #setDefaultSSLSocketFactory(SSLSocketFactory)
333      */
getDefaultSSLSocketFactory()334     public static SSLSocketFactory getDefaultSSLSocketFactory() {
335         if (defaultSSLSocketFactory == null) {
336             defaultSSLSocketFactory =
337                 (SSLSocketFactory)SSLSocketFactory.getDefault();
338         }
339         return defaultSSLSocketFactory;
340     }
341 
342     /**
343      * Sets the <code>SSLSocketFactory</code> to be used when this instance
344      * creates sockets for secure https URL connections.
345      * <P>
346      * New instances of this class inherit the default static
347      * <code>SSLSocketFactory</code> set by
348      * {@link #setDefaultSSLSocketFactory(SSLSocketFactory)
349      * setDefaultSSLSocketFactory}.  Calls to this method replace
350      * this object's <code>SSLSocketFactory</code>.
351      *
352      * @param sf the SSL socket factory
353      * @throws IllegalArgumentException if the <code>SSLSocketFactory</code>
354      *          parameter is null.
355      * @see #getSSLSocketFactory()
356      */
setSSLSocketFactory(SSLSocketFactory sf)357     public void setSSLSocketFactory(SSLSocketFactory sf) {
358         if (sf == null) {
359             throw new IllegalArgumentException(
360                 "no SSLSocketFactory specified");
361         }
362 
363         SecurityManager sm = System.getSecurityManager();
364         if (sm != null) {
365             sm.checkSetFactory();
366         }
367         sslSocketFactory = sf;
368     }
369 
370     /**
371      * Gets the SSL socket factory to be used when creating sockets
372      * for secure https URL connections.
373      *
374      * @return the <code>SSLSocketFactory</code>
375      * @see #setSSLSocketFactory(SSLSocketFactory)
376      */
getSSLSocketFactory()377     public SSLSocketFactory getSSLSocketFactory() {
378         return sslSocketFactory;
379     }
380 }
381