1 /* 2 * Copyright (c) 2001, 2020, 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 int readTimeout = getReadTimeout(); 97 http = HttpsClient.New (getSSLSocketFactory(), 98 url, 99 getHostnameVerifier(), 100 null, 101 -1, 102 useCache, 103 getConnectTimeout(), 104 this); 105 http.setReadTimeout(readTimeout); 106 ((HttpsClient)http).afterConnect(); 107 } 108 109 /** 110 * Create a new HttpClient object, set up so that it uses 111 * per-instance proxying to the given HTTP proxy. This 112 * bypasses the cache of HTTP client objects/connections. 113 * 114 * Note: this method is changed from protected to public because 115 * the com.sun.ssl.internal.www.protocol.https handler reuses this 116 * class for its actual implemantation 117 * 118 * @param url the URL being accessed 119 * @param proxyHost the proxy host to use 120 * @param proxyPort the proxy port to use 121 */ 122 public void setProxiedClient (URL url, String proxyHost, int proxyPort) 123 throws IOException { 124 setProxiedClient(url, proxyHost, proxyPort, false); 125 } 126 127 /** 128 * Obtain a HttpClient object, set up so that it uses per-instance 129 * proxying to the given HTTP proxy. Use the cached copy of HTTP 130 * client objects/connections if specified. 131 * 132 * Note: this method is changed from protected to public because 133 * the com.sun.ssl.internal.www.protocol.https handler reuses this 134 * class for its actual implemantation 135 * 136 * @param url the URL being accessed 137 * @param proxyHost the proxy host to use 138 * @param proxyPort the proxy port to use 139 * @param useCache whether the cached connection should be used 140 * if present 141 */ 142 public void setProxiedClient (URL url, String proxyHost, int proxyPort, 143 boolean useCache) throws IOException { 144 proxiedConnect(url, proxyHost, proxyPort, useCache); 145 if (!http.isCachedConnection()) { 146 doTunneling(); 147 } 148 ((HttpsClient)http).afterConnect(); 149 } 150 151 protected void proxiedConnect(URL url, String proxyHost, int proxyPort, 152 boolean useCache) throws IOException { 153 if (connected) 154 return; 155 int readTimeout = getReadTimeout(); 156 http = HttpsClient.New (getSSLSocketFactory(), 157 url, 158 getHostnameVerifier(), 159 proxyHost, 160 proxyPort, 161 useCache, 162 getConnectTimeout(), 163 this); 164 http.setReadTimeout(readTimeout); 165 connected = true; 166 } 167 168 /** 169 * Used by subclass to access "connected" variable. 170 */ 171 public boolean isConnected() { 172 return connected; 173 } 174 175 /** 176 * Used by subclass to access "connected" variable. 177 */ 178 public void setConnected(boolean conn) { 179 connected = conn; 180 } 181 182 /** 183 * Implements the HTTP protocol handler's "connect" method, 184 * establishing an SSL connection to the server as necessary. 185 */ 186 public void connect() throws IOException { 187 if (connected) 188 return; 189 plainConnect(); 190 if (cachedResponse != null) { 191 // using cached response 192 return; 193 } 194 if (!http.isCachedConnection() && http.needsTunneling()) { 195 doTunneling(); 196 } 197 ((HttpsClient)http).afterConnect(); 198 } 199 200 // will try to use cached HttpsClient 201 protected HttpClient getNewHttpClient(URL url, Proxy p, int connectTimeout) 202 throws IOException { 203 return HttpsClient.New(getSSLSocketFactory(), url, 204 getHostnameVerifier(), p, true, connectTimeout, 205 this); 206 } 207 208 // will open new connection 209 protected HttpClient getNewHttpClient(URL url, Proxy p, int connectTimeout, 210 boolean useCache) 211 throws IOException { 212 return HttpsClient.New(getSSLSocketFactory(), url, 213 getHostnameVerifier(), p, 214 useCache, connectTimeout, this); 215 } 216 217 /** 218 * Returns the cipher suite in use on this connection. 219 */ 220 public String getCipherSuite () { 221 if (cachedResponse != null) { 222 return ((SecureCacheResponse)cachedResponse).getCipherSuite(); 223 } 224 if (http == null) { 225 throw new IllegalStateException("connection not yet open"); 226 } else { 227 return ((HttpsClient)http).getCipherSuite (); 228 } 229 } 230 231 /** 232 * Returns the certificate chain the client sent to the 233 * server, or null if the client did not authenticate. 234 */ 235 public java.security.cert.Certificate[] getLocalCertificates() { 236 if (cachedResponse != null) { 237 List<java.security.cert.Certificate> l = ((SecureCacheResponse)cachedResponse).getLocalCertificateChain(); 238 if (l == null) { 239 return null; 240 } else { 241 return l.toArray(new java.security.cert.Certificate[0]); 242 } 243 } 244 if (http == null) { 245 throw new IllegalStateException("connection not yet open"); 246 } else { 247 return (((HttpsClient)http).getLocalCertificates ()); 248 } 249 } 250 251 /** 252 * Returns the server's certificate chain, or throws 253 * SSLPeerUnverified Exception if 254 * the server did not authenticate. 255 */ 256 public java.security.cert.Certificate[] getServerCertificates() 257 throws SSLPeerUnverifiedException { 258 if (cachedResponse != null) { 259 List<java.security.cert.Certificate> l = ((SecureCacheResponse)cachedResponse).getServerCertificateChain(); 260 if (l == null) { 261 return null; 262 } else { 263 return l.toArray(new java.security.cert.Certificate[0]); 264 } 265 } 266 267 if (http == null) { 268 throw new IllegalStateException("connection not yet open"); 269 } else { 270 return (((HttpsClient)http).getServerCertificates ()); 271 } 272 } 273 274 /** 275 * Returns the server's X.509 certificate chain, or null if 276 * the server did not authenticate. 277 */ 278 public javax.security.cert.X509Certificate[] getServerCertificateChain() 279 throws SSLPeerUnverifiedException { 280 if (cachedResponse != null) { 281 throw new UnsupportedOperationException("this method is not supported when using cache"); 282 } 283 if (http == null) { 284 throw new IllegalStateException("connection not yet open"); 285 } else { 286 return ((HttpsClient)http).getServerCertificateChain (); 287 } 288 } 289 290 /** 291 * Returns the server's principal, or throws SSLPeerUnverifiedException 292 * if the server did not authenticate. 293 */ 294 Principal getPeerPrincipal() 295 throws SSLPeerUnverifiedException 296 { 297 if (cachedResponse != null) { 298 return ((SecureCacheResponse)cachedResponse).getPeerPrincipal(); 299 } 300 301 if (http == null) { 302 throw new IllegalStateException("connection not yet open"); 303 } else { 304 return (((HttpsClient)http).getPeerPrincipal()); 305 } 306 } 307 308 /** 309 * Returns the principal the client sent to the 310 * server, or null if the client did not authenticate. 311 */ 312 Principal getLocalPrincipal() 313 { 314 if (cachedResponse != null) { 315 return ((SecureCacheResponse)cachedResponse).getLocalPrincipal(); 316 } 317 318 if (http == null) { 319 throw new IllegalStateException("connection not yet open"); 320 } else { 321 return (((HttpsClient)http).getLocalPrincipal()); 322 } 323 } 324 325 }