001    /* HttpsURLConnection.java -- an HTTPS connection.
002       Copyright (C) 2004, 2006 Free Software Foundation, Inc.
003    
004    This file is part of GNU Classpath.
005    
006    GNU Classpath is free software; you can redistribute it and/or modify
007    it under the terms of the GNU General Public License as published by
008    the Free Software Foundation; either version 2, or (at your option)
009    any later version.
010    
011    GNU Classpath is distributed in the hope that it will be useful, but
012    WITHOUT ANY WARRANTY; without even the implied warranty of
013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014    General Public License for more details.
015    
016    You should have received a copy of the GNU General Public License
017    along with GNU Classpath; see the file COPYING.  If not, write to the
018    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
019    02110-1301 USA.
020    
021    Linking this library statically or dynamically with other modules is
022    making a combined work based on this library.  Thus, the terms and
023    conditions of the GNU General Public License cover the whole
024    combination.
025    
026    As a special exception, the copyright holders of this library give you
027    permission to link this library with independent modules to produce an
028    executable, regardless of the license terms of these independent
029    modules, and to copy and distribute the resulting executable under
030    terms of your choice, provided that you also meet, for each linked
031    independent module, the terms and conditions of the license of that
032    module.  An independent module is a module which is not derived from
033    or based on this library.  If you modify this library, you may extend
034    this exception to your version of the library, but you are not
035    obligated to do so.  If you do not wish to do so, delete this
036    exception statement from your version. */
037    
038    
039    package javax.net.ssl;
040    
041    import java.net.HttpURLConnection;
042    import java.net.URL;
043    import java.security.Principal;
044    import java.security.cert.Certificate;
045    import java.security.cert.X509Certificate;
046    
047    /**
048     * A URL connection that connects via the <i>Secure Socket Layer</i>
049     * (<b>SSL</b>) for HTTPS connections.
050     *
051     * <p>This class may be used in the same way as {@link
052     * HttpURLConnection}, and it will transparently negotiate the SSL
053     * connection.
054     *
055     * @author Casey Marshall (rsdio@metastatic.org)
056     */
057    public abstract class HttpsURLConnection extends HttpURLConnection
058    {
059    
060      // Fields.
061      // ------------------------------------------------------------------
062    
063      /**
064       * The default verifier.
065       * This is lazily initialized as required.
066       * @see #getDefaultHostnameVerifier
067       */
068      private static HostnameVerifier defaultVerifier;
069    
070      /**
071       * The default factory.
072       * This is lazily initialized as required.
073       * @see #getDefaultSSLSocketFactory
074       */
075      private static SSLSocketFactory defaultFactory;
076    
077      /**
078       * The hostname verifier used for this connection.
079       */
080      protected HostnameVerifier hostnameVerifier;
081    
082      /**
083       * This connection's socket factory.
084       */
085      private SSLSocketFactory factory;
086    
087      // Constructor.
088      // ------------------------------------------------------------------
089    
090      /**
091       * Creates a new HTTPS URL connection.
092       *
093       * @param url The URL of the connection being established.
094       * @specnote This was marked as throwing IOException in 1.4,
095       * but this was removed in 1.5.
096       */
097      protected HttpsURLConnection(URL url)
098      {
099        super(url);
100      }
101    
102      // Class methods.
103      // ------------------------------------------------------------------
104    
105      /**
106       * Returns the default hostname verifier used in all new
107       * connections.
108       * If the default verifier has not been set, a new default one will be
109       * provided by this method.
110       *
111       * @return The default hostname verifier.
112       */
113      public static synchronized HostnameVerifier getDefaultHostnameVerifier()
114      {
115        if (defaultVerifier == null)
116          {
117            defaultVerifier = new TrivialHostnameVerifier();
118          }
119        return defaultVerifier;
120      }
121    
122      /**
123       * Sets the default hostname verifier to be used in all new
124       * connections.
125       *
126       * @param newDefault The new default hostname verifier.
127       * @throws IllegalArgumentException If <i>newDefault</i> is null.
128       * @throws SecurityException If there is a security manager
129       *   currently installed and the caller does not have the {@link
130       *   SSLPermission} "setHostnameVerifier".
131       */
132      public static void setDefaultHostnameVerifier(HostnameVerifier newDefault)
133      {
134        if (newDefault == null)
135          throw new IllegalArgumentException("default verifier cannot be null");
136        SecurityManager sm = System.getSecurityManager();
137        if (sm != null)
138          sm.checkPermission(new SSLPermission("setHostnameVerifier"));
139        synchronized (HttpsURLConnection.class)
140          {
141            defaultVerifier = newDefault;
142          }
143      }
144    
145      /**
146       * Returns the default SSL socket factory used in all new
147       * connections.
148       * If the default SSL socket factory has not been set, a new default one
149       * will be provided by this method.
150       *
151       * @return The default SSL socket factory.
152       */
153      public static synchronized SSLSocketFactory getDefaultSSLSocketFactory()
154      {
155        if (defaultFactory == null)
156          {
157            try
158              {
159                defaultFactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
160              }
161            catch (Throwable t)
162              {
163                t.printStackTrace();
164              }
165          }
166        return defaultFactory;
167      }
168    
169      /**
170       * Sets the default SSL socket factory to be used in all new
171       * connections.
172       *
173       * @param newDefault The new socket factory.
174       * @throws IllegalArgumentException If <i>newDefault</i> is null.
175       * @throws SecurityException If there is a security manager
176       *   installed and a call to {@link
177       *   SecurityManager#checkSetFactory()} fails.
178       */
179      public static void setDefaultSSLSocketFactory(SSLSocketFactory newDefault)
180      {
181        if (newDefault == null)
182          throw new IllegalArgumentException("default factory cannot be null");
183        SecurityManager sm = System.getSecurityManager();
184        if (sm != null)
185          sm.checkSetFactory();
186        synchronized (HttpsURLConnection.class)
187          {
188            defaultFactory = newDefault;
189          }
190      }
191    
192      // Instance methods.
193      // ------------------------------------------------------------------
194    
195      /**
196       * Returns the current hostname verifier for this instance.
197       *
198       * @return The hostname verifier.
199       */
200      public HostnameVerifier getHostnameVerifier()
201      {
202        if (hostnameVerifier == null)
203          {
204            hostnameVerifier = getDefaultHostnameVerifier();
205          }
206        return hostnameVerifier;
207      }
208    
209      /**
210       * Sets the hostname verifier for this instance.
211       *
212       * @param hostnameVerifier The new verifier.
213       * @throws IllegalArgumentException If <i>hostnameVerifier</i> is
214       *   null.
215       */
216      public void setHostnameVerifier(HostnameVerifier hostnameVerifier)
217      {
218        if (hostnameVerifier == null)
219          throw new IllegalArgumentException("verifier cannot be null");
220        this.hostnameVerifier = hostnameVerifier;
221      }
222    
223      /**
224       * Returns the current SSL socket factory for this instance.
225       *
226       * @return The current SSL socket factory.
227       */
228      public SSLSocketFactory getSSLSocketFactory()
229      {
230        if (factory == null)
231          {
232            factory = getDefaultSSLSocketFactory();
233          }
234        return factory;
235      }
236    
237      /**
238       * Sets the SSL socket factory for this instance.
239       *
240       * @param factory The new factory.
241       * @throws IllegalArgumentException If <i>factory</i> is null.
242       */
243      public void setSSLSocketFactory(SSLSocketFactory factory)
244      {
245        if (factory == null)
246          throw new IllegalArgumentException("factory cannot be null");
247        this.factory = factory;
248      }
249    
250      /**
251       * Returns the local principal for this connection.
252       *
253       * <p>The default implementation will return the {@link
254       * javax.security.x500.X500Principal} for the end entity certificate
255       * in the local certificate chain if those certificates are of type
256       * {@link java.security.cert.X509Certificate}. Otherwise, this
257       * method returns <code>null</code>.
258       *
259       * @return The local principal.
260       * @since 1.5
261       */
262      public Principal getLocalPrincipal ()
263      {
264        Certificate[] c = getLocalCertificates ();
265        if (c != null && c.length > 0 && (c[0] instanceof X509Certificate))
266          return ((X509Certificate) c[0]).getSubjectX500Principal ();
267        return null;
268      }
269    
270      /**
271       * Returns the remote peer's principal for this connection.
272       *
273       * <p>The default implementation will return the {@link
274       * javax.security.x500.X500Principal} for the end entity certificate
275       * in the remote peer's certificate chain if those certificates are
276       * of type {@link java.security.cert.X509Certificate}. Otherwise,
277       * this method returns <code>null</code>.
278       *
279       * @return The remote principal.
280       * @throws SSLPeerUnverifiedException If the remote peer has not
281       * been verified.
282       * @since 1.5
283       */
284      public Principal getPeerPrincipal () throws SSLPeerUnverifiedException
285      {
286        Certificate[] c = getServerCertificates ();
287        if (c != null && c.length > 0 && (c[0] instanceof X509Certificate))
288          return ((X509Certificate) c[0]).getSubjectX500Principal ();
289        return null;
290      }
291    
292      // Abstract methods.
293      // -------------------------------------------------------------------
294    
295      /**
296       * Returns the cipher name negotiated for this connection.
297       *
298       * @return The cipher name.
299       * @throws IllegalStateException If the connection has not yet been
300       *   established.
301       */
302      public abstract String getCipherSuite();
303    
304      /**
305       * Returns the certificates used on the local side in this
306       * connection.
307       *
308       * @return The local certificates.
309       * @throws IllegalStateException If the connection has not yet been
310       *  established.
311       */
312      public abstract Certificate[] getLocalCertificates();
313    
314      /**
315       * Returns the certificates sent by the other party.
316       *
317       * @return The peer's certificates.
318       * @throws IllegalStateException If the connection has not yet been
319       *   established.
320       * @throws SSLPeerUnverifiedException If the peer could not be
321       *   verified.
322       */
323      public abstract Certificate[] getServerCertificates() throws SSLPeerUnverifiedException;
324    }