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     // BEGIN Android-changed: Use lazily-created OkHttp hostname verifier
182     // The RI default hostname verifier is a static member of the class, which means
183     // it's created when the class is initialized.  As well, its default verifier
184     // just fails all verification attempts, whereas we use OkHttp's verifier.
185     /*
186      * Holds the default instance so class preloading doesn't create an instance of
187      * it.
188      */
189     private static class NoPreloadHolder {
190         public static HostnameVerifier defaultHostnameVerifier;
191         public static final Class<? extends HostnameVerifier> originalDefaultHostnameVerifierClass;
192         static {
193             try {
194                 /**
195                   * <code>HostnameVerifier</code> provides a callback mechanism so that
196                   * implementers of this interface can supply a policy for
197                   * handling the case where the host to connect to and
198                   * the server name from the certificate mismatch.
199                   */
200                 defaultHostnameVerifier = (HostnameVerifier)
201                         Class.forName("com.android.okhttp.internal.tls.OkHostnameVerifier")
202                         .getField("INSTANCE").get(null);
203                 originalDefaultHostnameVerifierClass = defaultHostnameVerifier.getClass();
204             } catch (Exception e) {
205                 throw new AssertionError("Failed to obtain okhttp HostnameVerifier", e);
206             }
207         }
208     }
209 
210     /**
211      * The <code>hostnameVerifier</code> for this object.
212      */
213     protected HostnameVerifier hostnameVerifier;
214     // END Android-changed: Use lazily-created OkHttp hostname verifier
215 
216     /**
217      * Sets the default <code>HostnameVerifier</code> inherited by a
218      * new instance of this class.
219      * <P>
220      * If this method is not called, the default
221      * <code>HostnameVerifier</code> assumes the connection should not
222      * be permitted.
223      *
224      * @param v the default host name verifier
225      * @throws IllegalArgumentException if the <code>HostnameVerifier</code>
226      *          parameter is null.
227      * @throws SecurityException if a security manager exists and its
228      *         <code>checkPermission</code> method does not allow
229      *         <code>SSLPermission("setHostnameVerifier")</code>
230      * @see #getDefaultHostnameVerifier()
231      */
setDefaultHostnameVerifier(HostnameVerifier v)232     public static void setDefaultHostnameVerifier(HostnameVerifier v) {
233         if (v == null) {
234             throw new IllegalArgumentException(
235                 "no default HostnameVerifier specified");
236         }
237 
238         SecurityManager sm = System.getSecurityManager();
239         if (sm != null) {
240             sm.checkPermission(new SSLPermission("setHostnameVerifier"));
241         }
242         NoPreloadHolder.defaultHostnameVerifier = v;
243     }
244 
245     /**
246      * Gets the default <code>HostnameVerifier</code> that is inherited
247      * by new instances of this class.
248      *
249      * @return the default host name verifier
250      * @see #setDefaultHostnameVerifier(HostnameVerifier)
251      */
getDefaultHostnameVerifier()252     public static HostnameVerifier getDefaultHostnameVerifier() {
253         return NoPreloadHolder.defaultHostnameVerifier;
254     }
255 
256     /**
257      * Sets the <code>HostnameVerifier</code> for this instance.
258      * <P>
259      * New instances of this class inherit the default static hostname
260      * verifier set by {@link #setDefaultHostnameVerifier(HostnameVerifier)
261      * setDefaultHostnameVerifier}.  Calls to this method replace
262      * this object's <code>HostnameVerifier</code>.
263      *
264      * @param v the host name verifier
265      * @throws IllegalArgumentException if the <code>HostnameVerifier</code>
266      *  parameter is null.
267      * @see #getHostnameVerifier()
268      * @see #setDefaultHostnameVerifier(HostnameVerifier)
269      */
setHostnameVerifier(HostnameVerifier v)270     public void setHostnameVerifier(HostnameVerifier v) {
271         if (v == null) {
272             throw new IllegalArgumentException(
273                 "no HostnameVerifier specified");
274         }
275 
276         hostnameVerifier = v;
277     }
278 
279     /**
280      * Gets the <code>HostnameVerifier</code> in place on this instance.
281      *
282      * @return the host name verifier
283      * @see #setHostnameVerifier(HostnameVerifier)
284      * @see #setDefaultHostnameVerifier(HostnameVerifier)
285      */
getHostnameVerifier()286     public HostnameVerifier getHostnameVerifier() {
287         // Android-added: Use the default verifier if none is set
288         if (hostnameVerifier == null) {
289             hostnameVerifier = NoPreloadHolder.defaultHostnameVerifier;
290         }
291         return hostnameVerifier;
292     }
293 
294     private static SSLSocketFactory defaultSSLSocketFactory = null;
295 
296     /**
297      * The <code>SSLSocketFactory</code> inherited when an instance
298      * of this class is created.
299      */
300     private SSLSocketFactory sslSocketFactory = getDefaultSSLSocketFactory();
301 
302     /**
303      * Sets the default <code>SSLSocketFactory</code> inherited by new
304      * instances of this class.
305      * <P>
306      * The socket factories are used when creating sockets for secure
307      * https URL connections.
308      *
309      * @param sf the default SSL socket factory
310      * @throws IllegalArgumentException if the SSLSocketFactory
311      *          parameter is null.
312      * @throws SecurityException if a security manager exists and its
313      *         <code>checkSetFactory</code> method does not allow
314      *         a socket factory to be specified.
315      * @see #getDefaultSSLSocketFactory()
316      */
setDefaultSSLSocketFactory(SSLSocketFactory sf)317     public static void setDefaultSSLSocketFactory(SSLSocketFactory sf) {
318         if (sf == null) {
319             throw new IllegalArgumentException(
320                 "no default SSLSocketFactory specified");
321         }
322 
323         SecurityManager sm = System.getSecurityManager();
324         if (sm != null) {
325             sm.checkSetFactory();
326         }
327         defaultSSLSocketFactory = sf;
328     }
329 
330     /**
331      * Gets the default static <code>SSLSocketFactory</code> that is
332      * inherited by new instances of this class.
333      * <P>
334      * The socket factories are used when creating sockets for secure
335      * https URL connections.
336      *
337      * @return the default <code>SSLSocketFactory</code>
338      * @see #setDefaultSSLSocketFactory(SSLSocketFactory)
339      */
getDefaultSSLSocketFactory()340     public static SSLSocketFactory getDefaultSSLSocketFactory() {
341         if (defaultSSLSocketFactory == null) {
342             defaultSSLSocketFactory =
343                 (SSLSocketFactory)SSLSocketFactory.getDefault();
344         }
345         return defaultSSLSocketFactory;
346     }
347 
348     /**
349      * Sets the <code>SSLSocketFactory</code> to be used when this instance
350      * creates sockets for secure https URL connections.
351      * <P>
352      * New instances of this class inherit the default static
353      * <code>SSLSocketFactory</code> set by
354      * {@link #setDefaultSSLSocketFactory(SSLSocketFactory)
355      * setDefaultSSLSocketFactory}.  Calls to this method replace
356      * this object's <code>SSLSocketFactory</code>.
357      *
358      * @param sf the SSL socket factory
359      * @throws IllegalArgumentException if the <code>SSLSocketFactory</code>
360      *          parameter is null.
361      * @see #getSSLSocketFactory()
362      */
setSSLSocketFactory(SSLSocketFactory sf)363     public void setSSLSocketFactory(SSLSocketFactory sf) {
364         if (sf == null) {
365             throw new IllegalArgumentException(
366                 "no SSLSocketFactory specified");
367         }
368 
369         SecurityManager sm = System.getSecurityManager();
370         if (sm != null) {
371             sm.checkSetFactory();
372         }
373         sslSocketFactory = sf;
374     }
375 
376     /**
377      * Gets the SSL socket factory to be used when creating sockets
378      * for secure https URL connections.
379      *
380      * @return the <code>SSLSocketFactory</code>
381      * @see #setSSLSocketFactory(SSLSocketFactory)
382      */
getSSLSocketFactory()383     public SSLSocketFactory getSSLSocketFactory() {
384         return sslSocketFactory;
385     }
386 }
387