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