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