1 /*
   2  * Copyright (c) 2001, 2019, 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.ProtocolException;
  31 import java.net.MalformedURLException;
  32 import java.io.*;
  33 import java.net.Authenticator;
  34 import javax.net.ssl.*;
  35 import java.security.Permission;
  36 import java.security.Principal;
  37 import java.util.Map;
  38 import java.util.List;
  39 import java.util.Optional;
  40 import sun.net.www.http.HttpClient;
  41 
  42 /**
  43  * A class to represent an HTTP connection to a remote object.
  44  *
  45  * Ideally, this class should subclass and inherit the http handler
  46  * implementation, but it can't do so because that class have the
  47  * wrong Java Type.  Thus it uses the delegate (aka, the
  48  * Adapter/Wrapper design pattern) to reuse code from the http
  49  * handler.
  50  *
  51  * Since it would use a delegate to access
  52  * sun.net.www.protocol.http.HttpURLConnection functionalities, it
  53  * needs to implement all public methods in it's super class and all
  54  * the way to Object.
  55  *
  56  */
  57 public class HttpsURLConnectionImpl
  58         extends javax.net.ssl.HttpsURLConnection {
  59 
  60     private final DelegateHttpsURLConnection delegate;
  61 
  62     HttpsURLConnectionImpl(URL u, Handler handler) throws IOException {
  63         this(u, null, handler);
  64     }
  65 
  66     static URL checkURL(URL u) throws IOException {
  67         if (u != null) {
  68             if (u.toExternalForm().indexOf('\n') > -1) {
  69                 throw new MalformedURLException("Illegal character in URL");
  70             }
  71         }
  72         return u;
  73     }
  74 
  75     HttpsURLConnectionImpl(URL u, Proxy p, Handler handler) throws IOException {
  76         super(checkURL(u));
  77         delegate = new DelegateHttpsURLConnection(url, p, handler, this);
  78     }
  79 
  80     /**
  81      * Create a new HttpClient object, bypassing the cache of
  82      * HTTP client objects/connections.
  83      *
  84      * @param url       the URL being accessed
  85      */
  86     protected void setNewClient(URL url) throws IOException {
  87         delegate.setNewClient(url, false);
  88     }
  89 
  90     /**
  91      * Obtain a HttpClient object. Use the cached copy if specified.
  92      *
  93      * @param url       the URL being accessed
  94      * @param useCache  whether the cached connection should be used
  95      *                  if present
  96      */
  97     protected void setNewClient(URL url, boolean useCache)
  98             throws IOException {
  99         delegate.setNewClient(url, useCache);
 100     }
 101 
 102     /**
 103      * Create a new HttpClient object, set up so that it uses
 104      * per-instance proxying to the given HTTP proxy.  This
 105      * bypasses the cache of HTTP client objects/connections.
 106      *
 107      * @param url       the URL being accessed
 108      * @param proxyHost the proxy host to use
 109      * @param proxyPort the proxy port to use
 110      */
 111     protected void setProxiedClient(URL url, String proxyHost, int proxyPort)
 112             throws IOException {
 113         delegate.setProxiedClient(url, proxyHost, proxyPort);
 114     }
 115 
 116     /**
 117      * Obtain a HttpClient object, set up so that it uses per-instance
 118      * proxying to the given HTTP proxy. Use the cached copy of HTTP
 119      * client objects/connections if specified.
 120      *
 121      * @param url       the URL being accessed
 122      * @param proxyHost the proxy host to use
 123      * @param proxyPort the proxy port to use
 124      * @param useCache  whether the cached connection should be used
 125      *                  if present
 126      */
 127     protected void setProxiedClient(URL url, String proxyHost, int proxyPort,
 128             boolean useCache) throws IOException {
 129         delegate.setProxiedClient(url, proxyHost, proxyPort, useCache);
 130     }
 131 
 132     /**
 133      * Implements the HTTP protocol handler's "connect" method,
 134      * establishing an SSL connection to the server as necessary.
 135      */
 136     public void connect() throws IOException {
 137         delegate.connect();
 138     }
 139 
 140     /**
 141      * Used by subclass to access "connected" variable.  Since we are
 142      * delegating the actual implementation to "delegate", we need to
 143      * delegate the access of "connected" as well.
 144      */
 145     protected boolean isConnected() {
 146         return delegate.isConnected();
 147     }
 148 
 149     /**
 150      * Used by subclass to access "connected" variable.  Since we are
 151      * delegating the actual implementation to "delegate", we need to
 152      * delegate the access of "connected" as well.
 153      */
 154     protected void setConnected(boolean conn) {
 155         delegate.setConnected(conn);
 156     }
 157 
 158     /**
 159      * Returns the cipher suite in use on this connection.
 160      */
 161     public String getCipherSuite() {
 162         return delegate.getCipherSuite();
 163     }
 164 
 165     /**
 166      * Returns the certificate chain the client sent to the
 167      * server, or null if the client did not authenticate.
 168      */
 169     public java.security.cert.Certificate []
 170         getLocalCertificates() {
 171         return delegate.getLocalCertificates();
 172     }
 173 
 174     /**
 175      * Returns the server's certificate chain, or throws
 176      * SSLPeerUnverified Exception if
 177      * the server did not authenticate.
 178      */
 179     public java.security.cert.Certificate []
 180         getServerCertificates() throws SSLPeerUnverifiedException {
 181         return delegate.getServerCertificates();
 182     }
 183 
 184     /**
 185      * Returns the principal with which the server authenticated itself,
 186      * or throw a SSLPeerUnverifiedException if the server did not authenticate.
 187      */
 188     public Principal getPeerPrincipal()
 189             throws SSLPeerUnverifiedException
 190     {
 191         return delegate.getPeerPrincipal();
 192     }
 193 
 194     /**
 195      * Returns the principal the client sent to the
 196      * server, or null if the client did not authenticate.
 197      */
 198     public Principal getLocalPrincipal()
 199     {
 200         return delegate.getLocalPrincipal();
 201     }
 202 
 203     /*
 204      * Allowable input/output sequences:
 205      * [interpreted as POST/PUT]
 206      * - get output, [write output,] get input, [read input]
 207      * - get output, [write output]
 208      * [interpreted as GET]
 209      * - get input, [read input]
 210      * Disallowed:
 211      * - get input, [read input,] get output, [write output]
 212      */
 213 
 214     public OutputStream getOutputStream() throws IOException {
 215         return delegate.getOutputStream();
 216     }
 217 
 218     public InputStream getInputStream() throws IOException {
 219         return delegate.getInputStream();
 220     }
 221 
 222     public InputStream getErrorStream() {
 223         return delegate.getErrorStream();
 224     }
 225 
 226     /**
 227      * Disconnect from the server.
 228      */
 229     public void disconnect() {
 230         delegate.disconnect();
 231     }
 232 
 233     public boolean usingProxy() {
 234         return delegate.usingProxy();
 235     }
 236 
 237     /**
 238      * Returns an unmodifiable Map of the header fields.
 239      * The Map keys are Strings that represent the
 240      * response-header field names. Each Map value is an
 241      * unmodifiable List of Strings that represents
 242      * the corresponding field values.
 243      *
 244      * @return a Map of header fields
 245      * @since 1.4
 246      */
 247     public Map<String,List<String>> getHeaderFields() {
 248         return delegate.getHeaderFields();
 249     }
 250 
 251     /**
 252      * Gets a header field by name. Returns null if not known.
 253      * @param name the name of the header field
 254      */
 255     public String getHeaderField(String name) {
 256         return delegate.getHeaderField(name);
 257     }
 258 
 259     /**
 260      * Gets a header field by index. Returns null if not known.
 261      * @param n the index of the header field
 262      */
 263     public String getHeaderField(int n) {
 264         return delegate.getHeaderField(n);
 265     }
 266 
 267     /**
 268      * Gets a header field by index. Returns null if not known.
 269      * @param n the index of the header field
 270      */
 271     public String getHeaderFieldKey(int n) {
 272         return delegate.getHeaderFieldKey(n);
 273     }
 274 
 275     /**
 276      * Sets request property. If a property with the key already
 277      * exists, overwrite its value with the new value.
 278      * @param value the value to be set
 279      */
 280     public void setRequestProperty(String key, String value) {
 281         delegate.setRequestProperty(key, value);
 282     }
 283 
 284     /**
 285      * Adds a general request property specified by a
 286      * key-value pair.  This method will not overwrite
 287      * existing values associated with the same key.
 288      *
 289      * @param   key     the keyword by which the request is known
 290      *                  (e.g., "<code>accept</code>").
 291      * @param   value  the value associated with it.
 292      * @see #getRequestProperties(java.lang.String)
 293      * @since 1.4
 294      */
 295     public void addRequestProperty(String key, String value) {
 296         delegate.addRequestProperty(key, value);
 297     }
 298 
 299     /**
 300      * Overwrite super class method
 301      */
 302     public int getResponseCode() throws IOException {
 303         return delegate.getResponseCode();
 304     }
 305 
 306     public String getRequestProperty(String key) {
 307         return delegate.getRequestProperty(key);
 308     }
 309 
 310     /**
 311      * Returns an unmodifiable Map of general request
 312      * properties for this connection. The Map keys
 313      * are Strings that represent the request-header
 314      * field names. Each Map value is a unmodifiable List
 315      * of Strings that represents the corresponding
 316      * field values.
 317      *
 318      * @return  a Map of the general request properties for this connection.
 319      * @throws IllegalStateException if already connected
 320      * @since 1.4
 321      */
 322     public Map<String,List<String>> getRequestProperties() {
 323         return delegate.getRequestProperties();
 324     }
 325 
 326     /*
 327      * We support JDK 1.2.x so we can't count on these from JDK 1.3.
 328      * We override and supply our own version.
 329      */
 330     public void setInstanceFollowRedirects(boolean shouldFollow) {
 331         delegate.setInstanceFollowRedirects(shouldFollow);
 332     }
 333 
 334     public boolean getInstanceFollowRedirects() {
 335         return delegate.getInstanceFollowRedirects();
 336     }
 337 
 338     public void setRequestMethod(String method) throws ProtocolException {
 339         delegate.setRequestMethod(method);
 340     }
 341 
 342     public String getRequestMethod() {
 343         return delegate.getRequestMethod();
 344     }
 345 
 346     public String getResponseMessage() throws IOException {
 347         return delegate.getResponseMessage();
 348     }
 349 
 350     public long getHeaderFieldDate(String name, long Default) {
 351         return delegate.getHeaderFieldDate(name, Default);
 352     }
 353 
 354     public Permission getPermission() throws IOException {
 355         return delegate.getPermission();
 356     }
 357 
 358     public URL getURL() {
 359         return delegate.getURL();
 360     }
 361 
 362     public int getContentLength() {
 363         return delegate.getContentLength();
 364     }
 365 
 366     public long getContentLengthLong() {
 367         return delegate.getContentLengthLong();
 368     }
 369 
 370     public String getContentType() {
 371         return delegate.getContentType();
 372     }
 373 
 374     public String getContentEncoding() {
 375         return delegate.getContentEncoding();
 376     }
 377 
 378     public long getExpiration() {
 379         return delegate.getExpiration();
 380     }
 381 
 382     public long getDate() {
 383         return delegate.getDate();
 384     }
 385 
 386     public long getLastModified() {
 387         return delegate.getLastModified();
 388     }
 389 
 390     public int getHeaderFieldInt(String name, int Default) {
 391         return delegate.getHeaderFieldInt(name, Default);
 392     }
 393 
 394     public long getHeaderFieldLong(String name, long Default) {
 395         return delegate.getHeaderFieldLong(name, Default);
 396     }
 397 
 398     public Object getContent() throws IOException {
 399         return delegate.getContent();
 400     }
 401 
 402     @SuppressWarnings("rawtypes")
 403     public Object getContent(Class[] classes) throws IOException {
 404         return delegate.getContent(classes);
 405     }
 406 
 407     public String toString() {
 408         return delegate.toString();
 409     }
 410 
 411     public void setDoInput(boolean doinput) {
 412         delegate.setDoInput(doinput);
 413     }
 414 
 415     public boolean getDoInput() {
 416         return delegate.getDoInput();
 417     }
 418 
 419     public void setDoOutput(boolean dooutput) {
 420         delegate.setDoOutput(dooutput);
 421     }
 422 
 423     public boolean getDoOutput() {
 424         return delegate.getDoOutput();
 425     }
 426 
 427     public void setAllowUserInteraction(boolean allowuserinteraction) {
 428         delegate.setAllowUserInteraction(allowuserinteraction);
 429     }
 430 
 431     public boolean getAllowUserInteraction() {
 432         return delegate.getAllowUserInteraction();
 433     }
 434 
 435     public void setUseCaches(boolean usecaches) {
 436         delegate.setUseCaches(usecaches);
 437     }
 438 
 439     public boolean getUseCaches() {
 440         return delegate.getUseCaches();
 441     }
 442 
 443     public void setIfModifiedSince(long ifmodifiedsince) {
 444         delegate.setIfModifiedSince(ifmodifiedsince);
 445     }
 446 
 447     public long getIfModifiedSince() {
 448         return delegate.getIfModifiedSince();
 449     }
 450 
 451     public boolean getDefaultUseCaches() {
 452         return delegate.getDefaultUseCaches();
 453     }
 454 
 455     public void setDefaultUseCaches(boolean defaultusecaches) {
 456         delegate.setDefaultUseCaches(defaultusecaches);
 457     }
 458 
 459     /*
 460      * finalize (dispose) the delegated object.  Otherwise
 461      * sun.net.www.protocol.http.HttpURLConnection's finalize()
 462      * would have to be made public.
 463      */
 464     @SuppressWarnings("deprecation")
 465     protected void finalize() throws Throwable {
 466         delegate.dispose();
 467     }
 468 
 469     public boolean equals(Object obj) {
 470         return this == obj || ((obj instanceof HttpsURLConnectionImpl) &&
 471             delegate.equals(((HttpsURLConnectionImpl)obj).delegate));
 472     }
 473 
 474     public int hashCode() {
 475         return delegate.hashCode();
 476     }
 477 
 478     public void setConnectTimeout(int timeout) {
 479         delegate.setConnectTimeout(timeout);
 480     }
 481 
 482     public int getConnectTimeout() {
 483         return delegate.getConnectTimeout();
 484     }
 485 
 486     public void setReadTimeout(int timeout) {
 487         delegate.setReadTimeout(timeout);
 488     }
 489 
 490     public int getReadTimeout() {
 491         return delegate.getReadTimeout();
 492     }
 493 
 494     public void setFixedLengthStreamingMode (int contentLength) {
 495         delegate.setFixedLengthStreamingMode(contentLength);
 496     }
 497 
 498     public void setFixedLengthStreamingMode(long contentLength) {
 499         delegate.setFixedLengthStreamingMode(contentLength);
 500     }
 501 
 502     public void setChunkedStreamingMode (int chunklen) {
 503         delegate.setChunkedStreamingMode(chunklen);
 504     }
 505 
 506     @Override
 507     public void setAuthenticator(Authenticator auth) {
 508         delegate.setAuthenticator(auth);
 509     }
 510 
 511     @Override
 512     public Optional<SSLSession> getSSLSession() {
 513         return Optional.ofNullable(delegate.getSSLSession());
 514     }
 515 }