1 /* 2 * Copyright (c) 2001, 2006, Oracle and/or its affiliates. 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * 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 }