1 /*
2 * Copyright 2001-2006 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26 package sun.net.www.protocol.https;
27
28 import java.net.URL;
29 import java.net.Proxy;
30 import java.net.SecureCacheResponse;
31 import java.security.Principal;
32 import java.io.IOException;
33 import java.util.List;
34 import javax.net.ssl.SSLPeerUnverifiedException;
35 import sun.net.www.http;
36 import sun.net.www.protocol.http.HttpURLConnection;
37
38 /**
39 * HTTPS URL connection support.
40 * We need this delegate because HttpsURLConnection is a subclass of
41 * java.net.HttpURLConnection. We will avoid copying over the code from
42 * sun.net.www.protocol.http.HttpURLConnection by having this class
43 *
44 */
45 public abstract class AbstractDelegateHttpsURLConnection extends
46 HttpURLConnection {
47
48 protected AbstractDelegateHttpsURLConnection(URL url,
49 sun.net.www.protocol.http.Handler handler) throws IOException {
50 this(url, null, handler);
51 }
52
53 protected AbstractDelegateHttpsURLConnection(URL url, Proxy p,
54 sun.net.www.protocol.http.Handler handler) throws IOException {
55 super(url, p, handler);
56 }
57
58 protected abstract javax.net.ssl.SSLSocketFactory getSSLSocketFactory();
59
60 protected abstract javax.net.ssl.HostnameVerifier getHostnameVerifier();
61
62 /**
63 * No user application is able to call these routines, as no one
64 * should ever get access to an instance of
65 * DelegateHttpsURLConnection (sun.* or com.*)
66 */
67
68 /**
69 * Create a new HttpClient object, bypassing the cache of
70 * HTTP client objects/connections.
71 *
72 * Note: this method is changed from protected to public because
73 * the com.sun.ssl.internal.www.protocol.https handler reuses this
74 * class for its actual implemantation
75 *
76 * @param url the URL being accessed
77 */
78 public void setNewClient (URL url)
79 throws IOException {
80 setNewClient (url, false);
81 }
82
83 /**
84 * Obtain a HttpClient object. Use the cached copy if specified.
85 *
86 * Note: this method is changed from protected to public because
87 * the com.sun.ssl.internal.www.protocol.https handler reuses this
88 * class for its actual implemantation
89 *
90 * @param url the URL being accessed
91 * @param useCache whether the cached connection should be used
92 * if present
93 */
94 public void setNewClient (URL url, boolean useCache)
95 throws IOException {
96 http = HttpsClient.New (getSSLSocketFactory(),
97 url,
98 getHostnameVerifier(),
99 useCache);
100 ((HttpsClient)http).afterConnect();
101 }
102
103 /**
104 * Create a new HttpClient object, set up so that it uses
105 * per-instance proxying to the given HTTP proxy. This
106 * bypasses the cache of HTTP client objects/connections.
107 *
108 * Note: this method is changed from protected to public because
109 * the com.sun.ssl.internal.www.protocol.https handler reuses this
110 * class for its actual implemantation
111 *
112 * @param url the URL being accessed
113 * @param proxyHost the proxy host to use
114 * @param proxyPort the proxy port to use
115 */
116 public void setProxiedClient (URL url, String proxyHost, int proxyPort)
117 throws IOException {
118 setProxiedClient(url, proxyHost, proxyPort, false);
119 }
120
121 /**
122 * Obtain a HttpClient object, set up so that it uses per-instance
123 * proxying to the given HTTP proxy. Use the cached copy of HTTP
124 * client objects/connections if specified.
125 *
126 * Note: this method is changed from protected to public because
127 * the com.sun.ssl.internal.www.protocol.https handler reuses this
128 * class for its actual implemantation
129 *
130 * @param url the URL being accessed
131 * @param proxyHost the proxy host to use
132 * @param proxyPort the proxy port to use
133 * @param useCache whether the cached connection should be used
134 * if present
135 */
136 public void setProxiedClient (URL url, String proxyHost, int proxyPort,
137 boolean useCache) throws IOException {
138 proxiedConnect(url, proxyHost, proxyPort, useCache);
139 if (!http.isCachedConnection()) {
140 doTunneling();
141 }
142 ((HttpsClient)http).afterConnect();
143 }
144
145 protected void proxiedConnect(URL url, String proxyHost, int proxyPort,
146 boolean useCache) throws IOException {
147 if (connected)
148 return;
149 http = HttpsClient.New (getSSLSocketFactory(),
150 url,
151 getHostnameVerifier(),
152 proxyHost, proxyPort, useCache);
153 connected = true;
154 }
155
156 /**
157 * Used by subclass to access "connected" variable.
158 */
159 public boolean isConnected() {
160 return connected;
161 }
162
163 /**
164 * Used by subclass to access "connected" variable.
165 */
166 public void setConnected(boolean conn) {
167 connected = conn;
168 }
169
170 /**
171 * Implements the HTTP protocol handler's "connect" method,
172 * establishing an SSL connection to the server as necessary.
173 */
174 public void connect() throws IOException {
175 if (connected)
176 return;
177 plainConnect();
178 if (cachedResponse != null) {
179 // using cached response
180 return;
181 }
182 if (!http.isCachedConnection() && http.needsTunneling()) {
183 doTunneling();
184 }
185 ((HttpsClient)http).afterConnect();
186 }
187
188 // will try to use cached HttpsClient
189 protected HttpClient getNewHttpClient(URL url, Proxy p, int connectTimeout)
190 throws IOException {
191 return HttpsClient.New(getSSLSocketFactory(), url,
192 getHostnameVerifier(), p, true, connectTimeout);
193 }
194
195 // will open new connection
196 protected HttpClient getNewHttpClient(URL url, Proxy p, int connectTimeout,
197 boolean useCache)
198 throws IOException {
199 return HttpsClient.New(getSSLSocketFactory(), url,
200 getHostnameVerifier(), p,
201 useCache, connectTimeout);
202 }
203
204 /**
205 * Returns the cipher suite in use on this connection.
206 */
207 public String getCipherSuite () {
208 if (cachedResponse != null) {
209 return ((SecureCacheResponse)cachedResponse).getCipherSuite();
210 }
211 if (http == null) {
212 throw new IllegalStateException("connection not yet open");
213 } else {
214 return ((HttpsClient)http).getCipherSuite ();
215 }
216 }
217
218 /**
219 * Returns the certificate chain the client sent to the
220 * server, or null if the client did not authenticate.
221 */
222 public java.security.cert.Certificate[] getLocalCertificates() {
223 if (cachedResponse != null) {
224 List l = ((SecureCacheResponse)cachedResponse).getLocalCertificateChain();
225 if (l == null) {
226 return null;
227 } else {
228 return (java.security.cert.Certificate[])l.toArray();
229 }
230 }
231 if (http == null) {
232 throw new IllegalStateException("connection not yet open");
233 } else {
234 return (((HttpsClient)http).getLocalCertificates ());
235 }
236 }
237
238 /**
239 * Returns the server's certificate chain, or throws
240 * SSLPeerUnverified Exception if
241 * the server did not authenticate.
242 */
243 public java.security.cert.Certificate[] getServerCertificates()
244 throws SSLPeerUnverifiedException {
245 if (cachedResponse != null) {
246 List l = ((SecureCacheResponse)cachedResponse).getServerCertificateChain();
247 if (l == null) {
248 return null;
249 } else {
250 return (java.security.cert.Certificate[])l.toArray();
251 }
252 }
253
254 if (http == null) {
255 throw new IllegalStateException("connection not yet open");
256 } else {
257 return (((HttpsClient)http).getServerCertificates ());
258 }
259 }
260
261 /**
262 * Returns the server's X.509 certificate chain, or null if
263 * the server did not authenticate.
264 */
265 public javax.security.cert.X509Certificate[] getServerCertificateChain()
266 throws SSLPeerUnverifiedException {
267 if (cachedResponse != null) {
268 throw new UnsupportedOperationException("this method is not supported when using cache");
269 }
270 if (http == null) {
271 throw new IllegalStateException("connection not yet open");
272 } else {
273 return ((HttpsClient)http).getServerCertificateChain ();
274 }
275 }
276
277 /**
278 * Returns the server's principal, or throws SSLPeerUnverifiedException
279 * if the server did not authenticate.
280 */
281 Principal getPeerPrincipal()
282 throws SSLPeerUnverifiedException
283 {
284 if (cachedResponse != null) {
285 return ((SecureCacheResponse)cachedResponse).getPeerPrincipal();
286 }
287
288 if (http == null) {
289 throw new IllegalStateException("connection not yet open");
290 } else {
291 return (((HttpsClient)http).getPeerPrincipal());
292 }
293 }
294
295 /**
296 * Returns the principal the client sent to the
297 * server, or null if the client did not authenticate.
298 */
299 Principal getLocalPrincipal()
300 {
301 if (cachedResponse != null) {
302 return ((SecureCacheResponse)cachedResponse).getLocalPrincipal();
303 }
304
305 if (http == null) {
306 throw new IllegalStateException("connection not yet open");
307 } else {
308 return (((HttpsClient)http).getLocalPrincipal());
309 }
310 }
311
312 }