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 holder class idiom for a 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 final String OK_HOSTNAME_VERIFIER_CLASS
190         = "com.android.okhttp.internal.tls.OkHostnameVerifier";
191     private static class NoPreloadHolder {
192         public static HostnameVerifier defaultHostnameVerifier;
193         static {
194             try {
195                 /**
196                   * <code>HostnameVerifier</code> provides a callback mechanism so that
197                   * implementers of this interface can supply a policy for
198                   * handling the case where the host to connect to and
199                   * the server name from the certificate mismatch.
200                   */
201                 defaultHostnameVerifier = (HostnameVerifier)
202                         Class.forName(OK_HOSTNAME_VERIFIER_CLASS)
203                         .getField("INSTANCE").get(null);
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 = NoPreloadHolder.defaultHostnameVerifier;
214     // END Android-changed: Use holder class idiom for a lazily-created OkHttp hostname verifier.
215 
216     // Android-changed: Modified the documentation to explain side effects / discourage method use.
217     /**
218      * Sets the default <code>HostnameVerifier</code> inherited by a
219      * new instance of this class.
220      * <p>
221      * Developers are <em>strongly</em> discouraged from changing the default
222      * {@code HostnameVerifier} as {@link #getDefaultHostnameVerifier()} is used by several
223      * classes for hostname verification on Android.
224      * <table>
225      *     <tr>
226      *         <th>User</th>
227      *         <th>Effect</th>
228      *     </tr>
229      *     <tr>
230      *         <td>Android's default {@link TrustManager}, as used with Android's default
231      *         {@link SSLContext}, {@link SSLSocketFactory} and {@link SSLSocket} implementations.
232      *         </td>
233      *         <td>The {@code HostnameVerifier} is used to verify the peer's
234      *         certificate hostname after connecting if {@code
235      *         SSLParameters.setEndpointIdentificationAlgorithm("HTTPS")} has been called.
236      *         Instances use the <em>current</em> default {@code HostnameVerifier} at verification
237      *         time.</td>
238      *     </tr>
239      *     <tr>
240      *         <td>{@link android.net.SSLCertificateSocketFactory}</td>
241      *         <td>The current default {@code HostnameVerifier} is used from various {@code
242      *         createSocket} methods. See {@link android.net.SSLCertificateSocketFactory} for
243      *         details; for example {@link
244      *         android.net.SSLCertificateSocketFactory#createSocket(String, int)}.
245      *         </td>
246      *     </tr>
247      *     <tr>
248      *         <td>Android's default {@link HttpsURLConnection} implementation.</td>
249      *         <td>The {@code HostnameVerifier} is used after a successful TLS handshake to verify
250      *         the URI host against the TLS session server. Instances use the default {@code
251      *         HostnameVerifier} set <em>when they were created</em> unless overridden with {@link
252      *         #setHostnameVerifier(HostnameVerifier)}.
253      *         Android's <code>HttpsURLConnection</code> relies on the {@code HostnameVerifier}
254      *         for the <em>entire</em> hostname verification step.</td>
255      *     </tr>
256      * </table>
257      * <p>
258      * If this method is not called, the default <code>HostnameVerifier</code> will check the
259      * hostname according to RFC 2818.
260      *
261      * @param v the default host name verifier
262      * @throws IllegalArgumentException if the <code>HostnameVerifier</code>
263      *          parameter is null.
264      * @throws SecurityException if a security manager exists and its
265      *         <code>checkPermission</code> method does not allow
266      *         <code>SSLPermission("setHostnameVerifier")</code>
267      * @see #getDefaultHostnameVerifier()
268      */
setDefaultHostnameVerifier(HostnameVerifier v)269     public static void setDefaultHostnameVerifier(HostnameVerifier v) {
270         if (v == null) {
271             throw new IllegalArgumentException(
272                 "no default HostnameVerifier specified");
273         }
274 
275         SecurityManager sm = System.getSecurityManager();
276         if (sm != null) {
277             sm.checkPermission(new SSLPermission("setHostnameVerifier"));
278         }
279         // Android-changed: Use holder class idiom for a lazily-created OkHttp hostname verifier.
280         // defaultHostnameVerifier = v;
281         NoPreloadHolder.defaultHostnameVerifier = v;
282     }
283 
284     /**
285      * Gets the default <code>HostnameVerifier</code> that is inherited
286      * by new instances of this class.
287      *
288      * @return the default host name verifier
289      * @see #setDefaultHostnameVerifier(HostnameVerifier)
290      */
getDefaultHostnameVerifier()291     public static HostnameVerifier getDefaultHostnameVerifier() {
292         // Android-changed: Use holder class idiom for a lazily-created OkHttp hostname verifier.
293         // return defaultHostnameVerifier;
294         return NoPreloadHolder.defaultHostnameVerifier;
295     }
296 
297     // Android-changed: Modified the documentation to explain Android behavior.
298     /**
299      * Sets the <code>HostnameVerifier</code> for this instance.
300      * <P>
301      * New instances of this class inherit the default static hostname
302      * verifier set by {@link #setDefaultHostnameVerifier(HostnameVerifier)
303      * setDefaultHostnameVerifier}.  Calls to this method replace
304      * this object's <code>HostnameVerifier</code>.
305      * <p>
306      * Android's <code>HttpsURLConnection</code> relies on the {@code HostnameVerifier}
307      * for the <em>entire</em> hostname verification step.
308      *
309      * @param v the host name verifier
310      * @throws IllegalArgumentException if the <code>HostnameVerifier</code>
311      *  parameter is null.
312      * @see #getHostnameVerifier()
313      * @see #setDefaultHostnameVerifier(HostnameVerifier)
314      */
setHostnameVerifier(HostnameVerifier v)315     public void setHostnameVerifier(HostnameVerifier v) {
316         if (v == null) {
317             throw new IllegalArgumentException(
318                 "no HostnameVerifier specified");
319         }
320 
321         hostnameVerifier = v;
322     }
323 
324     // BEGIN Android-added: Core platform API to obtain a strict hostname verifier
325     /**
326      * Obtains a stricter {@code HostnameVerifier}.
327      *
328      * The {@code HostnameVerifier} returned by this method will reject certificates
329      * with wildcards for top-level domains such "*.com".
330      *
331      * This is a vendor hook (called from Zygote init code) to allow stricter hostname
332      * checking on NIAP-certified devices.
333      *
334      * @see com.squareup.okhttp.internal.tls.OkHostnameVerifier
335      *
336      * @hide
337      */
getStrictHostnameVerifier()338     public static HostnameVerifier getStrictHostnameVerifier() {
339         try {
340             return (HostnameVerifier) Class
341                 .forName(OK_HOSTNAME_VERIFIER_CLASS)
342                 .getMethod("strictInstance")
343                 .invoke(null);
344         } catch (Exception e) {
345             return null;
346         }
347      }
348     // END Android-added: Core platform API to obtain a strict hostname verifier
349 
350     /**
351      * Gets the <code>HostnameVerifier</code> in place on this instance.
352      *
353      * @return the host name verifier
354      * @see #setHostnameVerifier(HostnameVerifier)
355      * @see #setDefaultHostnameVerifier(HostnameVerifier)
356      */
getHostnameVerifier()357     public HostnameVerifier getHostnameVerifier() {
358         return hostnameVerifier;
359     }
360 
361     private static SSLSocketFactory defaultSSLSocketFactory = null;
362 
363     /**
364      * The <code>SSLSocketFactory</code> inherited when an instance
365      * of this class is created.
366      */
367     private SSLSocketFactory sslSocketFactory = getDefaultSSLSocketFactory();
368 
369     /**
370      * Sets the default <code>SSLSocketFactory</code> inherited by new
371      * instances of this class.
372      * <P>
373      * The socket factories are used when creating sockets for secure
374      * https URL connections.
375      *
376      * @param sf the default SSL socket factory
377      * @throws IllegalArgumentException if the SSLSocketFactory
378      *          parameter is null.
379      * @throws SecurityException if a security manager exists and its
380      *         <code>checkSetFactory</code> method does not allow
381      *         a socket factory to be specified.
382      * @see #getDefaultSSLSocketFactory()
383      */
setDefaultSSLSocketFactory(SSLSocketFactory sf)384     public static void setDefaultSSLSocketFactory(SSLSocketFactory sf) {
385         if (sf == null) {
386             throw new IllegalArgumentException(
387                 "no default SSLSocketFactory specified");
388         }
389 
390         SecurityManager sm = System.getSecurityManager();
391         if (sm != null) {
392             sm.checkSetFactory();
393         }
394         defaultSSLSocketFactory = sf;
395     }
396 
397     /**
398      * Gets the default static <code>SSLSocketFactory</code> that is
399      * inherited by new instances of this class.
400      * <P>
401      * The socket factories are used when creating sockets for secure
402      * https URL connections.
403      *
404      * @return the default <code>SSLSocketFactory</code>
405      * @see #setDefaultSSLSocketFactory(SSLSocketFactory)
406      */
getDefaultSSLSocketFactory()407     public static SSLSocketFactory getDefaultSSLSocketFactory() {
408         if (defaultSSLSocketFactory == null) {
409             defaultSSLSocketFactory =
410                 (SSLSocketFactory)SSLSocketFactory.getDefault();
411         }
412         return defaultSSLSocketFactory;
413     }
414 
415     /**
416      * Sets the <code>SSLSocketFactory</code> to be used when this instance
417      * creates sockets for secure https URL connections.
418      * <P>
419      * New instances of this class inherit the default static
420      * <code>SSLSocketFactory</code> set by
421      * {@link #setDefaultSSLSocketFactory(SSLSocketFactory)
422      * setDefaultSSLSocketFactory}.  Calls to this method replace
423      * this object's <code>SSLSocketFactory</code>.
424      *
425      * @param sf the SSL socket factory
426      * @throws IllegalArgumentException if the <code>SSLSocketFactory</code>
427      *          parameter is null.
428      * @throws SecurityException if a security manager exists and its
429      *         <code>checkSetFactory</code> method does not allow
430      *         a socket factory to be specified.
431      * @see #getSSLSocketFactory()
432      */
setSSLSocketFactory(SSLSocketFactory sf)433     public void setSSLSocketFactory(SSLSocketFactory sf) {
434         if (sf == null) {
435             throw new IllegalArgumentException(
436                 "no SSLSocketFactory specified");
437         }
438 
439         SecurityManager sm = System.getSecurityManager();
440         if (sm != null) {
441             sm.checkSetFactory();
442         }
443         sslSocketFactory = sf;
444     }
445 
446     /**
447      * Gets the SSL socket factory to be used when creating sockets
448      * for secure https URL connections.
449      *
450      * @return the <code>SSLSocketFactory</code>
451      * @see #setSSLSocketFactory(SSLSocketFactory)
452      */
getSSLSocketFactory()453     public SSLSocketFactory getSSLSocketFactory() {
454         return sslSocketFactory;
455     }
456 }
457