Home | History | Annotate | Download | only in ssl
      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 
     18 package javax.net.ssl;
     19 
     20 import java.net.HttpURLConnection;
     21 import java.net.URL;
     22 import java.security.Principal;
     23 import java.security.cert.Certificate;
     24 import 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  *   TrustManagerFactory tmf = TrustManagerFactory.getInstance("X509");
     48  *   tmf.init(keyStore);
     49  *
     50  *   SSLContext context = SSLContext.getInstance("TLS");
     51  *   context.init(null, tmf.getTrustManagers(), null);
     52  *
     53  *   URL url = new URL("https://www.example.com/");
     54  *   HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection();
     55  *   urlConnection.setSSLSocketFactory(context.getSocketFactory());
     56  *   InputStream in = urlConnection.getInputStream();
     57  * }</pre>
     58  *
     59  * <p>It is possible to implement {@code X509TrustManager} directly
     60  * instead of using one created by a {@code
     61  * TrustManagerFactory}. While this is straightforward in the insecure
     62  * case of allowing all certificate chains to pass verification,
     63  * writing a proper implementation will usually want to take advantage
     64  * of {@link java.security.cert.CertPathValidator
     65  * CertPathValidator}. In general, it might be better to write a
     66  * custom {@code KeyStore} implementation to pass to the {@code
     67  * TrustManagerFactory} than to try and write a custom {@code
     68  * X509TrustManager}.
     69  *
     70  * <h3>Providing an application specific X509KeyManager</h3>
     71  *
     72  * A custom {@code X509KeyManager} can be used to supply a client
     73  * certificate and its associated private key to authenticate a
     74  * connection to the server. The {@code X509KeyManager} can be created
     75  * based on a {@code KeyStore} using a {@code KeyManagerFactory}.
     76  *
     77  * <p>For example, to supply client certificates from a {@code KeyStore}:
     78  * <pre>   {@code
     79  *   KeyStore keyStore = ...;
     80  *   KeyManagerFactory kmf = KeyManagerFactory.getInstance("X509");
     81  *   kmf.init(keyStore);
     82  *
     83  *   SSLContext context = SSLContext.getInstance("TLS");
     84  *   context.init(kmf.getKeyManagers(), null, null);
     85  *
     86  *   URL url = new URL("https://www.example.com/");
     87  *   HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection();
     88  *   urlConnection.setSSLSocketFactory(context.getSocketFactory());
     89  *   InputStream in = urlConnection.getInputStream();
     90  * }</pre>
     91  *
     92  * <p>A {@code X509KeyManager} can also be implemented directly. This
     93  * can allow an application to return a certificate and private key
     94  * from a non-{@code KeyStore} source or to specify its own logic for
     95  * selecting a specific credential to use when many may be present in
     96  * a single {@code KeyStore}.
     97  *
     98  * <h3>TLS Intolerance Support</h3>
     99  *
    100  * This class attempts to create secure connections using common TLS
    101  * extensions and SSL deflate compression. Should that fail, the
    102  * connection will be retried with SSLv3 only.
    103  */
    104 public abstract class HttpsURLConnection extends HttpURLConnection {
    105 
    106     private static HostnameVerifier defaultHostnameVerifier = new DefaultHostnameVerifier();
    107 
    108     private static SSLSocketFactory defaultSSLSocketFactory = (SSLSocketFactory) SSLSocketFactory
    109             .getDefault();
    110 
    111     /**
    112      * Sets the default hostname verifier to be used by new instances.
    113      *
    114      * @param v
    115      *            the new default hostname verifier
    116      * @throws IllegalArgumentException
    117      *             if the specified verifier is {@code null}.
    118      */
    119     public static void setDefaultHostnameVerifier(HostnameVerifier v) {
    120         if (v == null) {
    121             throw new IllegalArgumentException("HostnameVerifier is null");
    122         }
    123         defaultHostnameVerifier = v;
    124     }
    125 
    126     /**
    127      * Returns the default hostname verifier.
    128      *
    129      * @return the default hostname verifier.
    130      */
    131     public static HostnameVerifier getDefaultHostnameVerifier() {
    132         return defaultHostnameVerifier;
    133     }
    134 
    135     /**
    136      * Sets the default SSL socket factory to be used by new instances.
    137      *
    138      * @param sf
    139      *            the new default SSL socket factory.
    140      * @throws IllegalArgumentException
    141      *             if the specified socket factory is {@code null}.
    142      */
    143     public static void setDefaultSSLSocketFactory(SSLSocketFactory sf) {
    144         if (sf == null) {
    145             throw new IllegalArgumentException("SSLSocketFactory is null");
    146         }
    147         defaultSSLSocketFactory = sf;
    148     }
    149 
    150     /**
    151      * Returns the default SSL socket factory for new instances.
    152      *
    153      * @return the default SSL socket factory for new instances.
    154      */
    155     public static SSLSocketFactory getDefaultSSLSocketFactory() {
    156         return defaultSSLSocketFactory;
    157     }
    158 
    159     /**
    160      * The host name verifier used by this connection. It is initialized from
    161      * the default hostname verifier
    162      * {@link #setDefaultHostnameVerifier(HostnameVerifier)} or
    163      * {@link #getDefaultHostnameVerifier()}.
    164      */
    165     protected HostnameVerifier hostnameVerifier;
    166 
    167     private SSLSocketFactory sslSocketFactory;
    168 
    169     /**
    170      * Creates a new {@code HttpsURLConnection} with the specified {@code URL}.
    171      *
    172      * @param url
    173      *            the {@code URL} to connect to.
    174      */
    175     protected HttpsURLConnection(URL url) {
    176         super(url);
    177         hostnameVerifier = defaultHostnameVerifier;
    178         sslSocketFactory = defaultSSLSocketFactory;
    179     }
    180 
    181     /**
    182      * Returns the name of the cipher suite negotiated during the SSL handshake.
    183      *
    184      * @return the name of the cipher suite negotiated during the SSL handshake.
    185      * @throws IllegalStateException
    186      *             if no connection has been established yet.
    187      */
    188     public abstract String getCipherSuite();
    189 
    190     /**
    191      * Returns the list of local certificates used during the handshake. These
    192      * certificates were sent to the peer.
    193      *
    194      * @return Returns the list of certificates used during the handshake with
    195      *         the local identity certificate followed by CAs, or {@code null}
    196      *         if no certificates were used during the handshake.
    197      * @throws IllegalStateException
    198      *             if no connection has been established yet.
    199      */
    200     public abstract Certificate[] getLocalCertificates();
    201 
    202     /**
    203      * Return the list of certificates identifying the peer during the
    204      * handshake.
    205      *
    206      * @return the list of certificates identifying the peer with the peer's
    207      *         identity certificate followed by CAs.
    208      * @throws SSLPeerUnverifiedException
    209      *             if the identity of the peer has not been verified..
    210      * @throws IllegalStateException
    211      *             if no connection has been established yet.
    212      */
    213     public abstract Certificate[] getServerCertificates() throws SSLPeerUnverifiedException;
    214 
    215     /**
    216      * Returns the {@code Principal} identifying the peer.
    217      *
    218      * @return the {@code Principal} identifying the peer.
    219      * @throws SSLPeerUnverifiedException
    220      *             if the identity of the peer has not been verified.
    221      * @throws IllegalStateException
    222      *             if no connection has been established yet.
    223      */
    224     public Principal getPeerPrincipal() throws SSLPeerUnverifiedException {
    225         Certificate[] certs = getServerCertificates();
    226         if (certs == null || certs.length == 0 || (!(certs[0] instanceof X509Certificate))) {
    227             throw new SSLPeerUnverifiedException("No server's end-entity certificate");
    228         }
    229         return ((X509Certificate) certs[0]).getSubjectX500Principal();
    230     }
    231 
    232     /**
    233      * Returns the {@code Principal} used to identify the local host during the handshake.
    234      *
    235      * @return the {@code Principal} used to identify the local host during the handshake, or
    236      *         {@code null} if none was used.
    237      * @throws IllegalStateException
    238      *             if no connection has been established yet.
    239      */
    240     public Principal getLocalPrincipal() {
    241         Certificate[] certs = getLocalCertificates();
    242         if (certs == null || certs.length == 0 || (!(certs[0] instanceof X509Certificate))) {
    243             return null;
    244         }
    245         return ((X509Certificate) certs[0]).getSubjectX500Principal();
    246     }
    247 
    248     /**
    249      * Sets the hostname verifier for this instance.
    250      *
    251      * @param v
    252      *            the hostname verifier for this instance.
    253      * @throws IllegalArgumentException
    254      *             if the specified verifier is {@code null}.
    255      */
    256     public void setHostnameVerifier(HostnameVerifier v) {
    257         if (v == null) {
    258             throw new IllegalArgumentException("HostnameVerifier is null");
    259         }
    260         hostnameVerifier = v;
    261     }
    262 
    263     /**
    264      * Returns the hostname verifier used by this instance.
    265      *
    266      * @return the hostname verifier used by this instance.
    267      */
    268     public HostnameVerifier getHostnameVerifier() {
    269         return hostnameVerifier;
    270     }
    271 
    272     /**
    273      * Sets the SSL socket factory for this instance.
    274      *
    275      * @param sf
    276      *            the SSL socket factory to be used by this instance.
    277      * @throws IllegalArgumentException
    278      *             if the specified socket factory is {@code null}.
    279      */
    280     public void setSSLSocketFactory(SSLSocketFactory sf) {
    281         if (sf == null) {
    282             throw new IllegalArgumentException("SSLSocketFactory is null");
    283         }
    284         sslSocketFactory = sf;
    285     }
    286 
    287     /**
    288      * Returns the SSL socket factory used by this instance.
    289      *
    290      * @return the SSL socket factory used by this instance.
    291      */
    292     public SSLSocketFactory getSSLSocketFactory() {
    293         return sslSocketFactory;
    294     }
    295 
    296 }
    297