src/java.base/share/classes/sun/net/www/protocol/https/HttpsClient.java
author erikj
Tue, 12 Sep 2017 19:03:39 +0200
changeset 47216 71c04702a3d5
parent 42351 jdk/src/java.base/share/classes/sun/net/www/protocol/https/HttpsClient.java@85ed90be0ae1
child 50768 68fa3d4026ea
permissions -rw-r--r--
8187443: Forest Consolidation: Move files to unified layout Reviewed-by: darcy, ihse
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     1
/*
42351
85ed90be0ae1 8169495: Add a method to set an Authenticator on a HttpURLConnection.
dfuchs
parents: 37781
diff changeset
     2
 * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
90ce3da70b43 Initial load
duke
parents:
diff changeset
     4
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
90ce3da70b43 Initial load
duke
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 5162
diff changeset
     7
 * published by the Free Software Foundation.  Oracle designates this
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 5162
diff changeset
     9
 * by Oracle in the LICENSE file that accompanied this code.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    10
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
90ce3da70b43 Initial load
duke
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
90ce3da70b43 Initial load
duke
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
90ce3da70b43 Initial load
duke
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
90ce3da70b43 Initial load
duke
parents:
diff changeset
    15
 * accompanied this code).
90ce3da70b43 Initial load
duke
parents:
diff changeset
    16
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
90ce3da70b43 Initial load
duke
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    20
 *
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 5162
diff changeset
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 5162
diff changeset
    22
 * or visit www.oracle.com if you need additional information or have any
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 5162
diff changeset
    23
 * questions.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    24
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    25
90ce3da70b43 Initial load
duke
parents:
diff changeset
    26
90ce3da70b43 Initial load
duke
parents:
diff changeset
    27
package sun.net.www.protocol.https;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    28
90ce3da70b43 Initial load
duke
parents:
diff changeset
    29
import java.io.IOException;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    30
import java.io.UnsupportedEncodingException;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    31
import java.io.PrintStream;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    32
import java.io.BufferedOutputStream;
16499
88276d2da9c0 8009251: Add proxy handling and keep-alive fixes to jsse
robm
parents: 14342
diff changeset
    33
import java.net.InetAddress;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    34
import java.net.Socket;
5162
0dbedf4fdb8c 6614957: HttpsURLConnection not using the set SSLSocketFactory for creating all its Sockets
chegar
parents: 5160
diff changeset
    35
import java.net.SocketException;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    36
import java.net.URL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    37
import java.net.UnknownHostException;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    38
import java.net.InetSocketAddress;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    39
import java.net.Proxy;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    40
import java.security.Principal;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    41
import java.security.cert.*;
42351
85ed90be0ae1 8169495: Add a method to set an Authenticator on a HttpURLConnection.
dfuchs
parents: 37781
diff changeset
    42
import java.util.Objects;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    43
import java.util.StringTokenizer;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    44
import java.util.Vector;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    45
90ce3da70b43 Initial load
duke
parents:
diff changeset
    46
import javax.security.auth.x500.X500Principal;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    47
90ce3da70b43 Initial load
duke
parents:
diff changeset
    48
import javax.net.ssl.*;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    49
import sun.net.www.http.HttpClient;
42351
85ed90be0ae1 8169495: Add a method to set an Authenticator on a HttpURLConnection.
dfuchs
parents: 37781
diff changeset
    50
import sun.net.www.protocol.http.AuthenticatorKeys;
16499
88276d2da9c0 8009251: Add proxy handling and keep-alive fixes to jsse
robm
parents: 14342
diff changeset
    51
import sun.net.www.protocol.http.HttpURLConnection;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    52
import sun.security.action.*;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    53
90ce3da70b43 Initial load
duke
parents:
diff changeset
    54
import sun.security.util.HostnameChecker;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    55
import sun.security.ssl.SSLSocketImpl;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    56
16499
88276d2da9c0 8009251: Add proxy handling and keep-alive fixes to jsse
robm
parents: 14342
diff changeset
    57
import sun.util.logging.PlatformLogger;
88276d2da9c0 8009251: Add proxy handling and keep-alive fixes to jsse
robm
parents: 14342
diff changeset
    58
import static sun.net.www.protocol.http.HttpURLConnection.TunnelState.*;
88276d2da9c0 8009251: Add proxy handling and keep-alive fixes to jsse
robm
parents: 14342
diff changeset
    59
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    60
90ce3da70b43 Initial load
duke
parents:
diff changeset
    61
/**
90ce3da70b43 Initial load
duke
parents:
diff changeset
    62
 * This class provides HTTPS client URL support, building on the standard
90ce3da70b43 Initial load
duke
parents:
diff changeset
    63
 * "sun.net.www" HTTP protocol handler.  HTTPS is the same protocol as HTTP,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    64
 * but differs in the transport layer which it uses:  <UL>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    65
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    66
 *      <LI>There's a <em>Secure Sockets Layer</em> between TCP
90ce3da70b43 Initial load
duke
parents:
diff changeset
    67
 *      and the HTTP protocol code.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    68
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    69
 *      <LI>It uses a different default TCP port.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    70
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    71
 *      <LI>It doesn't use application level proxies, which can see and
90ce3da70b43 Initial load
duke
parents:
diff changeset
    72
 *      manipulate HTTP user level data, compromising privacy.  It uses
90ce3da70b43 Initial load
duke
parents:
diff changeset
    73
 *      low level tunneling instead, which hides HTTP protocol and data
90ce3da70b43 Initial load
duke
parents:
diff changeset
    74
 *      from all third parties.  (Traffic analysis is still possible).
90ce3da70b43 Initial load
duke
parents:
diff changeset
    75
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    76
 *      <LI>It does basic server authentication, to protect
90ce3da70b43 Initial load
duke
parents:
diff changeset
    77
 *      against "URL spoofing" attacks.  This involves deciding
90ce3da70b43 Initial load
duke
parents:
diff changeset
    78
 *      whether the X.509 certificate chain identifying the server
90ce3da70b43 Initial load
duke
parents:
diff changeset
    79
 *      is trusted, and verifying that the name of the server is
90ce3da70b43 Initial load
duke
parents:
diff changeset
    80
 *      found in the certificate.  (The application may enable an
90ce3da70b43 Initial load
duke
parents:
diff changeset
    81
 *      anonymous SSL cipher suite, and such checks are not done
90ce3da70b43 Initial load
duke
parents:
diff changeset
    82
 *      for anonymous ciphers.)
90ce3da70b43 Initial load
duke
parents:
diff changeset
    83
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    84
 *      <LI>It exposes key SSL session attributes, specifically the
90ce3da70b43 Initial load
duke
parents:
diff changeset
    85
 *      cipher suite in use and the server's X509 certificates, to
90ce3da70b43 Initial load
duke
parents:
diff changeset
    86
 *      application software which knows about this protocol handler.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    87
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    88
 *      </UL>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    89
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    90
 * <P> System properties used include:  <UL>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    91
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    92
 *      <LI><em>https.proxyHost</em> ... the host supporting SSL
90ce3da70b43 Initial load
duke
parents:
diff changeset
    93
 *      tunneling using the conventional CONNECT syntax
90ce3da70b43 Initial load
duke
parents:
diff changeset
    94
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    95
 *      <LI><em>https.proxyPort</em> ... port to use on proxyHost
90ce3da70b43 Initial load
duke
parents:
diff changeset
    96
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    97
 *      <LI><em>https.cipherSuites</em> ... comma separated list of
90ce3da70b43 Initial load
duke
parents:
diff changeset
    98
 *      SSL cipher suite names to enable.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    99
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   100
 *      <LI><em>http.nonProxyHosts</em> ...
90ce3da70b43 Initial load
duke
parents:
diff changeset
   101
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   102
 *      </UL>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   103
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   104
 * @author David Brownell
90ce3da70b43 Initial load
duke
parents:
diff changeset
   105
 * @author Bill Foote
90ce3da70b43 Initial load
duke
parents:
diff changeset
   106
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   107
90ce3da70b43 Initial load
duke
parents:
diff changeset
   108
// final for export control reasons (access to APIs); remove with care
90ce3da70b43 Initial load
duke
parents:
diff changeset
   109
final class HttpsClient extends HttpClient
90ce3da70b43 Initial load
duke
parents:
diff changeset
   110
    implements HandshakeCompletedListener
90ce3da70b43 Initial load
duke
parents:
diff changeset
   111
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
   112
    // STATIC STATE and ACCESSORS THERETO
90ce3da70b43 Initial load
duke
parents:
diff changeset
   113
90ce3da70b43 Initial load
duke
parents:
diff changeset
   114
    // HTTPS uses a different default port number than HTTP.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   115
    private static final int    httpsPortNumber = 443;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   116
7043
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   117
    // default HostnameVerifier class canonical name
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   118
    private static final String defaultHVCanonicalName =
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   119
            "javax.net.ssl.HttpsURLConnection.DefaultHostnameVerifier";
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   120
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   121
    /** Returns the default HTTPS port (443) */
5162
0dbedf4fdb8c 6614957: HttpsURLConnection not using the set SSLSocketFactory for creating all its Sockets
chegar
parents: 5160
diff changeset
   122
    @Override
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   123
    protected int getDefaultPort() { return httpsPortNumber; }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   124
90ce3da70b43 Initial load
duke
parents:
diff changeset
   125
    private HostnameVerifier hv;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   126
    private SSLSocketFactory sslSocketFactory;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   127
90ce3da70b43 Initial load
duke
parents:
diff changeset
   128
    // HttpClient.proxyDisabled will always be false, because we don't
90ce3da70b43 Initial load
duke
parents:
diff changeset
   129
    // use an application-level HTTP proxy.  We might tunnel through
90ce3da70b43 Initial load
duke
parents:
diff changeset
   130
    // our http proxy, though.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   131
90ce3da70b43 Initial load
duke
parents:
diff changeset
   132
90ce3da70b43 Initial load
duke
parents:
diff changeset
   133
    // INSTANCE DATA
90ce3da70b43 Initial load
duke
parents:
diff changeset
   134
90ce3da70b43 Initial load
duke
parents:
diff changeset
   135
    // last negotiated SSL session
90ce3da70b43 Initial load
duke
parents:
diff changeset
   136
    private SSLSession  session;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   137
90ce3da70b43 Initial load
duke
parents:
diff changeset
   138
    private String [] getCipherSuites() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   139
        //
90ce3da70b43 Initial load
duke
parents:
diff changeset
   140
        // If ciphers are assigned, sort them into an array.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   141
        //
90ce3da70b43 Initial load
duke
parents:
diff changeset
   142
        String ciphers [];
37593
824750ada3d6 8154231: Simplify access to System properties from JDK code
redestad
parents: 29615
diff changeset
   143
        String cipherString =
37781
71ed5645f17c 8155775: Re-examine naming of privileged methods to access System properties
redestad
parents: 37593
diff changeset
   144
                GetPropertyAction.privilegedGetProperty("https.cipherSuites");
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   145
90ce3da70b43 Initial load
duke
parents:
diff changeset
   146
        if (cipherString == null || "".equals(cipherString)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   147
            ciphers = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   148
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   149
            StringTokenizer     tokenizer;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   150
            Vector<String>      v = new Vector<String>();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   151
90ce3da70b43 Initial load
duke
parents:
diff changeset
   152
            tokenizer = new StringTokenizer(cipherString, ",");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   153
            while (tokenizer.hasMoreTokens())
90ce3da70b43 Initial load
duke
parents:
diff changeset
   154
                v.addElement(tokenizer.nextToken());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   155
            ciphers = new String [v.size()];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   156
            for (int i = 0; i < ciphers.length; i++)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   157
                ciphers [i] = v.elementAt(i);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   158
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   159
        return ciphers;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   160
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   161
90ce3da70b43 Initial load
duke
parents:
diff changeset
   162
    private String [] getProtocols() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   163
        //
90ce3da70b43 Initial load
duke
parents:
diff changeset
   164
        // If protocols are assigned, sort them into an array.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   165
        //
90ce3da70b43 Initial load
duke
parents:
diff changeset
   166
        String protocols [];
37593
824750ada3d6 8154231: Simplify access to System properties from JDK code
redestad
parents: 29615
diff changeset
   167
        String protocolString =
37781
71ed5645f17c 8155775: Re-examine naming of privileged methods to access System properties
redestad
parents: 37593
diff changeset
   168
                GetPropertyAction.privilegedGetProperty("https.protocols");
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   169
90ce3da70b43 Initial load
duke
parents:
diff changeset
   170
        if (protocolString == null || "".equals(protocolString)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   171
            protocols = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   172
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   173
            StringTokenizer     tokenizer;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   174
            Vector<String>      v = new Vector<String>();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   175
90ce3da70b43 Initial load
duke
parents:
diff changeset
   176
            tokenizer = new StringTokenizer(protocolString, ",");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   177
            while (tokenizer.hasMoreTokens())
90ce3da70b43 Initial load
duke
parents:
diff changeset
   178
                v.addElement(tokenizer.nextToken());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   179
            protocols = new String [v.size()];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   180
            for (int i = 0; i < protocols.length; i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   181
                protocols [i] = v.elementAt(i);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   182
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   183
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   184
        return protocols;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   185
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   186
90ce3da70b43 Initial load
duke
parents:
diff changeset
   187
    private String getUserAgent() {
37781
71ed5645f17c 8155775: Re-examine naming of privileged methods to access System properties
redestad
parents: 37593
diff changeset
   188
        String userAgent =
71ed5645f17c 8155775: Re-examine naming of privileged methods to access System properties
redestad
parents: 37593
diff changeset
   189
                GetPropertyAction.privilegedGetProperty("https.agent");
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   190
        if (userAgent == null || userAgent.length() == 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   191
            userAgent = "JSSE";
90ce3da70b43 Initial load
duke
parents:
diff changeset
   192
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   193
        return userAgent;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   194
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   195
90ce3da70b43 Initial load
duke
parents:
diff changeset
   196
    // CONSTRUCTOR, FACTORY
90ce3da70b43 Initial load
duke
parents:
diff changeset
   197
90ce3da70b43 Initial load
duke
parents:
diff changeset
   198
90ce3da70b43 Initial load
duke
parents:
diff changeset
   199
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   200
     * Create an HTTPS client URL.  Traffic will be tunneled through any
90ce3da70b43 Initial load
duke
parents:
diff changeset
   201
     * intermediate nodes rather than proxied, so that confidentiality
90ce3da70b43 Initial load
duke
parents:
diff changeset
   202
     * of data exchanged can be preserved.  However, note that all the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   203
     * anonymous SSL flavors are subject to "person-in-the-middle"
90ce3da70b43 Initial load
duke
parents:
diff changeset
   204
     * attacks against confidentiality.  If you enable use of those
90ce3da70b43 Initial load
duke
parents:
diff changeset
   205
     * flavors, you may be giving up the protection you get through
90ce3da70b43 Initial load
duke
parents:
diff changeset
   206
     * SSL tunneling.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   207
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   208
     * Use New to get new HttpsClient. This constructor is meant to be
90ce3da70b43 Initial load
duke
parents:
diff changeset
   209
     * used only by New method. New properly checks for URL spoofing.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   210
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   211
     * @param URL https URL with which a connection must be established
90ce3da70b43 Initial load
duke
parents:
diff changeset
   212
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   213
    private HttpsClient(SSLSocketFactory sf, URL url)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   214
    throws IOException
90ce3da70b43 Initial load
duke
parents:
diff changeset
   215
    {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   216
        // HttpClient-level proxying is always disabled,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   217
        // because we override doConnect to do tunneling instead.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   218
        this(sf, url, (String)null, -1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   219
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   220
90ce3da70b43 Initial load
duke
parents:
diff changeset
   221
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   222
     *  Create an HTTPS client URL.  Traffic will be tunneled through
90ce3da70b43 Initial load
duke
parents:
diff changeset
   223
     * the specified proxy server.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   224
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   225
    HttpsClient(SSLSocketFactory sf, URL url, String proxyHost, int proxyPort)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   226
        throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   227
        this(sf, url, proxyHost, proxyPort, -1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   228
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   229
90ce3da70b43 Initial load
duke
parents:
diff changeset
   230
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   231
     *  Create an HTTPS client URL.  Traffic will be tunneled through
90ce3da70b43 Initial load
duke
parents:
diff changeset
   232
     * the specified proxy server, with a connect timeout
90ce3da70b43 Initial load
duke
parents:
diff changeset
   233
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   234
    HttpsClient(SSLSocketFactory sf, URL url, String proxyHost, int proxyPort,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   235
                int connectTimeout)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   236
        throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   237
        this(sf, url,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   238
             (proxyHost == null? null:
28568
5325bdefc06b 8065994: HTTP Tunnel connection to NTLM proxy reauthenticates instead of using keep-alive
coffeys
parents: 25859
diff changeset
   239
                HttpClient.newHttpProxy(proxyHost, proxyPort, "https")),
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   240
                connectTimeout);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   241
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   242
90ce3da70b43 Initial load
duke
parents:
diff changeset
   243
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   244
     *  Same as previous constructor except using a Proxy
90ce3da70b43 Initial load
duke
parents:
diff changeset
   245
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   246
    HttpsClient(SSLSocketFactory sf, URL url, Proxy proxy,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   247
                int connectTimeout)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   248
        throws IOException {
28568
5325bdefc06b 8065994: HTTP Tunnel connection to NTLM proxy reauthenticates instead of using keep-alive
coffeys
parents: 25859
diff changeset
   249
        PlatformLogger logger = HttpURLConnection.getHttpLogger();
5325bdefc06b 8065994: HTTP Tunnel connection to NTLM proxy reauthenticates instead of using keep-alive
coffeys
parents: 25859
diff changeset
   250
        if (logger.isLoggable(PlatformLogger.Level.FINEST)) {
5325bdefc06b 8065994: HTTP Tunnel connection to NTLM proxy reauthenticates instead of using keep-alive
coffeys
parents: 25859
diff changeset
   251
             logger.finest("Creating new HttpsClient with url:" + url + " and proxy:" + proxy +
5325bdefc06b 8065994: HTTP Tunnel connection to NTLM proxy reauthenticates instead of using keep-alive
coffeys
parents: 25859
diff changeset
   252
             " with connect timeout:" + connectTimeout);
5325bdefc06b 8065994: HTTP Tunnel connection to NTLM proxy reauthenticates instead of using keep-alive
coffeys
parents: 25859
diff changeset
   253
        }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   254
        this.proxy = proxy;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   255
        setSSLSocketFactory(sf);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   256
        this.proxyDisabled = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   257
90ce3da70b43 Initial load
duke
parents:
diff changeset
   258
        this.host = url.getHost();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   259
        this.url = url;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   260
        port = url.getPort();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   261
        if (port == -1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   262
            port = getDefaultPort();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   263
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   264
        setConnectTimeout(connectTimeout);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   265
        openServer();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   266
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   267
90ce3da70b43 Initial load
duke
parents:
diff changeset
   268
90ce3da70b43 Initial load
duke
parents:
diff changeset
   269
    // This code largely ripped off from HttpClient.New, and
90ce3da70b43 Initial load
duke
parents:
diff changeset
   270
    // it uses the same keepalive cache.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   271
16499
88276d2da9c0 8009251: Add proxy handling and keep-alive fixes to jsse
robm
parents: 14342
diff changeset
   272
    static HttpClient New(SSLSocketFactory sf, URL url, HostnameVerifier hv,
88276d2da9c0 8009251: Add proxy handling and keep-alive fixes to jsse
robm
parents: 14342
diff changeset
   273
                          HttpURLConnection httpuc)
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   274
            throws IOException {
16499
88276d2da9c0 8009251: Add proxy handling and keep-alive fixes to jsse
robm
parents: 14342
diff changeset
   275
        return HttpsClient.New(sf, url, hv, true, httpuc);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   276
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   277
90ce3da70b43 Initial load
duke
parents:
diff changeset
   278
    /** See HttpClient for the model for this method. */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   279
    static HttpClient New(SSLSocketFactory sf, URL url,
16499
88276d2da9c0 8009251: Add proxy handling and keep-alive fixes to jsse
robm
parents: 14342
diff changeset
   280
            HostnameVerifier hv, boolean useCache,
88276d2da9c0 8009251: Add proxy handling and keep-alive fixes to jsse
robm
parents: 14342
diff changeset
   281
            HttpURLConnection httpuc) throws IOException {
88276d2da9c0 8009251: Add proxy handling and keep-alive fixes to jsse
robm
parents: 14342
diff changeset
   282
        return HttpsClient.New(sf, url, hv, (String)null, -1, useCache, httpuc);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   283
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   284
90ce3da70b43 Initial load
duke
parents:
diff changeset
   285
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   286
     * Get a HTTPS client to the URL.  Traffic will be tunneled through
90ce3da70b43 Initial load
duke
parents:
diff changeset
   287
     * the specified proxy server.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   288
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   289
    static HttpClient New(SSLSocketFactory sf, URL url, HostnameVerifier hv,
16499
88276d2da9c0 8009251: Add proxy handling and keep-alive fixes to jsse
robm
parents: 14342
diff changeset
   290
                           String proxyHost, int proxyPort,
88276d2da9c0 8009251: Add proxy handling and keep-alive fixes to jsse
robm
parents: 14342
diff changeset
   291
                           HttpURLConnection httpuc) throws IOException {
88276d2da9c0 8009251: Add proxy handling and keep-alive fixes to jsse
robm
parents: 14342
diff changeset
   292
        return HttpsClient.New(sf, url, hv, proxyHost, proxyPort, true, httpuc);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   293
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   294
90ce3da70b43 Initial load
duke
parents:
diff changeset
   295
    static HttpClient New(SSLSocketFactory sf, URL url, HostnameVerifier hv,
16499
88276d2da9c0 8009251: Add proxy handling and keep-alive fixes to jsse
robm
parents: 14342
diff changeset
   296
                           String proxyHost, int proxyPort, boolean useCache,
88276d2da9c0 8009251: Add proxy handling and keep-alive fixes to jsse
robm
parents: 14342
diff changeset
   297
                           HttpURLConnection httpuc)
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   298
        throws IOException {
16499
88276d2da9c0 8009251: Add proxy handling and keep-alive fixes to jsse
robm
parents: 14342
diff changeset
   299
        return HttpsClient.New(sf, url, hv, proxyHost, proxyPort, useCache, -1,
88276d2da9c0 8009251: Add proxy handling and keep-alive fixes to jsse
robm
parents: 14342
diff changeset
   300
                               httpuc);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   301
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   302
90ce3da70b43 Initial load
duke
parents:
diff changeset
   303
    static HttpClient New(SSLSocketFactory sf, URL url, HostnameVerifier hv,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   304
                          String proxyHost, int proxyPort, boolean useCache,
16499
88276d2da9c0 8009251: Add proxy handling and keep-alive fixes to jsse
robm
parents: 14342
diff changeset
   305
                          int connectTimeout, HttpURLConnection httpuc)
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   306
        throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   307
90ce3da70b43 Initial load
duke
parents:
diff changeset
   308
        return HttpsClient.New(sf, url, hv,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   309
                               (proxyHost == null? null :
28568
5325bdefc06b 8065994: HTTP Tunnel connection to NTLM proxy reauthenticates instead of using keep-alive
coffeys
parents: 25859
diff changeset
   310
                                HttpClient.newHttpProxy(proxyHost, proxyPort, "https")),
16499
88276d2da9c0 8009251: Add proxy handling and keep-alive fixes to jsse
robm
parents: 14342
diff changeset
   311
                               useCache, connectTimeout, httpuc);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   312
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   313
90ce3da70b43 Initial load
duke
parents:
diff changeset
   314
    static HttpClient New(SSLSocketFactory sf, URL url, HostnameVerifier hv,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   315
                          Proxy p, boolean useCache,
16499
88276d2da9c0 8009251: Add proxy handling and keep-alive fixes to jsse
robm
parents: 14342
diff changeset
   316
                          int connectTimeout, HttpURLConnection httpuc)
88276d2da9c0 8009251: Add proxy handling and keep-alive fixes to jsse
robm
parents: 14342
diff changeset
   317
        throws IOException
88276d2da9c0 8009251: Add proxy handling and keep-alive fixes to jsse
robm
parents: 14342
diff changeset
   318
    {
88276d2da9c0 8009251: Add proxy handling and keep-alive fixes to jsse
robm
parents: 14342
diff changeset
   319
        if (p == null) {
88276d2da9c0 8009251: Add proxy handling and keep-alive fixes to jsse
robm
parents: 14342
diff changeset
   320
            p = Proxy.NO_PROXY;
88276d2da9c0 8009251: Add proxy handling and keep-alive fixes to jsse
robm
parents: 14342
diff changeset
   321
        }
28568
5325bdefc06b 8065994: HTTP Tunnel connection to NTLM proxy reauthenticates instead of using keep-alive
coffeys
parents: 25859
diff changeset
   322
        PlatformLogger logger = HttpURLConnection.getHttpLogger();
5325bdefc06b 8065994: HTTP Tunnel connection to NTLM proxy reauthenticates instead of using keep-alive
coffeys
parents: 25859
diff changeset
   323
        if (logger.isLoggable(PlatformLogger.Level.FINEST)) {
5325bdefc06b 8065994: HTTP Tunnel connection to NTLM proxy reauthenticates instead of using keep-alive
coffeys
parents: 25859
diff changeset
   324
            logger.finest("Looking for HttpClient for URL " + url +
5325bdefc06b 8065994: HTTP Tunnel connection to NTLM proxy reauthenticates instead of using keep-alive
coffeys
parents: 25859
diff changeset
   325
                " and proxy value of " + p);
5325bdefc06b 8065994: HTTP Tunnel connection to NTLM proxy reauthenticates instead of using keep-alive
coffeys
parents: 25859
diff changeset
   326
        }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   327
        HttpsClient ret = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   328
        if (useCache) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   329
            /* see if one's already around */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   330
            ret = (HttpsClient) kac.get(url, sf);
16499
88276d2da9c0 8009251: Add proxy handling and keep-alive fixes to jsse
robm
parents: 14342
diff changeset
   331
            if (ret != null && httpuc != null &&
88276d2da9c0 8009251: Add proxy handling and keep-alive fixes to jsse
robm
parents: 14342
diff changeset
   332
                httpuc.streaming() &&
88276d2da9c0 8009251: Add proxy handling and keep-alive fixes to jsse
robm
parents: 14342
diff changeset
   333
                httpuc.getRequestMethod() == "POST") {
88276d2da9c0 8009251: Add proxy handling and keep-alive fixes to jsse
robm
parents: 14342
diff changeset
   334
                if (!ret.available())
88276d2da9c0 8009251: Add proxy handling and keep-alive fixes to jsse
robm
parents: 14342
diff changeset
   335
                    ret = null;
88276d2da9c0 8009251: Add proxy handling and keep-alive fixes to jsse
robm
parents: 14342
diff changeset
   336
            }
88276d2da9c0 8009251: Add proxy handling and keep-alive fixes to jsse
robm
parents: 14342
diff changeset
   337
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   338
            if (ret != null) {
42351
85ed90be0ae1 8169495: Add a method to set an Authenticator on a HttpURLConnection.
dfuchs
parents: 37781
diff changeset
   339
                String ak = httpuc == null ? AuthenticatorKeys.DEFAULT
85ed90be0ae1 8169495: Add a method to set an Authenticator on a HttpURLConnection.
dfuchs
parents: 37781
diff changeset
   340
                     : httpuc.getAuthenticatorKey();
85ed90be0ae1 8169495: Add a method to set an Authenticator on a HttpURLConnection.
dfuchs
parents: 37781
diff changeset
   341
                boolean compatible = ((ret.proxy != null && ret.proxy.equals(p)) ||
85ed90be0ae1 8169495: Add a method to set an Authenticator on a HttpURLConnection.
dfuchs
parents: 37781
diff changeset
   342
                    (ret.proxy == null && p == Proxy.NO_PROXY))
85ed90be0ae1 8169495: Add a method to set an Authenticator on a HttpURLConnection.
dfuchs
parents: 37781
diff changeset
   343
                     && Objects.equals(ret.getAuthenticatorKey(), ak);
85ed90be0ae1 8169495: Add a method to set an Authenticator on a HttpURLConnection.
dfuchs
parents: 37781
diff changeset
   344
                if (compatible) {
16499
88276d2da9c0 8009251: Add proxy handling and keep-alive fixes to jsse
robm
parents: 14342
diff changeset
   345
                    synchronized (ret) {
88276d2da9c0 8009251: Add proxy handling and keep-alive fixes to jsse
robm
parents: 14342
diff changeset
   346
                        ret.cachedHttpClient = true;
88276d2da9c0 8009251: Add proxy handling and keep-alive fixes to jsse
robm
parents: 14342
diff changeset
   347
                        assert ret.inCache;
88276d2da9c0 8009251: Add proxy handling and keep-alive fixes to jsse
robm
parents: 14342
diff changeset
   348
                        ret.inCache = false;
88276d2da9c0 8009251: Add proxy handling and keep-alive fixes to jsse
robm
parents: 14342
diff changeset
   349
                        if (httpuc != null && ret.needsTunneling())
88276d2da9c0 8009251: Add proxy handling and keep-alive fixes to jsse
robm
parents: 14342
diff changeset
   350
                            httpuc.setTunnelState(TUNNELING);
18178
ee71c923891d 8016747: Replace deprecated PlatformLogger isLoggable(int) with isLoggable(Level)
chegar
parents: 16499
diff changeset
   351
                        if (logger.isLoggable(PlatformLogger.Level.FINEST)) {
16499
88276d2da9c0 8009251: Add proxy handling and keep-alive fixes to jsse
robm
parents: 14342
diff changeset
   352
                            logger.finest("KeepAlive stream retrieved from the cache, " + ret);
88276d2da9c0 8009251: Add proxy handling and keep-alive fixes to jsse
robm
parents: 14342
diff changeset
   353
                        }
88276d2da9c0 8009251: Add proxy handling and keep-alive fixes to jsse
robm
parents: 14342
diff changeset
   354
                    }
88276d2da9c0 8009251: Add proxy handling and keep-alive fixes to jsse
robm
parents: 14342
diff changeset
   355
                } else {
88276d2da9c0 8009251: Add proxy handling and keep-alive fixes to jsse
robm
parents: 14342
diff changeset
   356
                    // We cannot return this connection to the cache as it's
88276d2da9c0 8009251: Add proxy handling and keep-alive fixes to jsse
robm
parents: 14342
diff changeset
   357
                    // KeepAliveTimeout will get reset. We simply close the connection.
88276d2da9c0 8009251: Add proxy handling and keep-alive fixes to jsse
robm
parents: 14342
diff changeset
   358
                    // This should be fine as it is very rare that a connection
88276d2da9c0 8009251: Add proxy handling and keep-alive fixes to jsse
robm
parents: 14342
diff changeset
   359
                    // to the same host will not use the same proxy.
88276d2da9c0 8009251: Add proxy handling and keep-alive fixes to jsse
robm
parents: 14342
diff changeset
   360
                    synchronized(ret) {
28568
5325bdefc06b 8065994: HTTP Tunnel connection to NTLM proxy reauthenticates instead of using keep-alive
coffeys
parents: 25859
diff changeset
   361
                        if (logger.isLoggable(PlatformLogger.Level.FINEST)) {
5325bdefc06b 8065994: HTTP Tunnel connection to NTLM proxy reauthenticates instead of using keep-alive
coffeys
parents: 25859
diff changeset
   362
                            logger.finest("Not returning this connection to cache: " + ret);
5325bdefc06b 8065994: HTTP Tunnel connection to NTLM proxy reauthenticates instead of using keep-alive
coffeys
parents: 25859
diff changeset
   363
                        }
16499
88276d2da9c0 8009251: Add proxy handling and keep-alive fixes to jsse
robm
parents: 14342
diff changeset
   364
                        ret.inCache = false;
88276d2da9c0 8009251: Add proxy handling and keep-alive fixes to jsse
robm
parents: 14342
diff changeset
   365
                        ret.closeServer();
88276d2da9c0 8009251: Add proxy handling and keep-alive fixes to jsse
robm
parents: 14342
diff changeset
   366
                    }
88276d2da9c0 8009251: Add proxy handling and keep-alive fixes to jsse
robm
parents: 14342
diff changeset
   367
                    ret = null;
88276d2da9c0 8009251: Add proxy handling and keep-alive fixes to jsse
robm
parents: 14342
diff changeset
   368
                }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   369
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   370
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   371
        if (ret == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   372
            ret = new HttpsClient(sf, url, p, connectTimeout);
42351
85ed90be0ae1 8169495: Add a method to set an Authenticator on a HttpURLConnection.
dfuchs
parents: 37781
diff changeset
   373
            if (httpuc != null) {
85ed90be0ae1 8169495: Add a method to set an Authenticator on a HttpURLConnection.
dfuchs
parents: 37781
diff changeset
   374
                ret.authenticatorKey = httpuc.getAuthenticatorKey();
85ed90be0ae1 8169495: Add a method to set an Authenticator on a HttpURLConnection.
dfuchs
parents: 37781
diff changeset
   375
            }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   376
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   377
            SecurityManager security = System.getSecurityManager();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   378
            if (security != null) {
16499
88276d2da9c0 8009251: Add proxy handling and keep-alive fixes to jsse
robm
parents: 14342
diff changeset
   379
                if (ret.proxy == Proxy.NO_PROXY || ret.proxy == null) {
88276d2da9c0 8009251: Add proxy handling and keep-alive fixes to jsse
robm
parents: 14342
diff changeset
   380
                    security.checkConnect(InetAddress.getByName(url.getHost()).getHostAddress(), url.getPort());
88276d2da9c0 8009251: Add proxy handling and keep-alive fixes to jsse
robm
parents: 14342
diff changeset
   381
                } else {
88276d2da9c0 8009251: Add proxy handling and keep-alive fixes to jsse
robm
parents: 14342
diff changeset
   382
                    security.checkConnect(url.getHost(), url.getPort());
88276d2da9c0 8009251: Add proxy handling and keep-alive fixes to jsse
robm
parents: 14342
diff changeset
   383
                }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   384
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   385
            ret.url = url;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   386
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   387
        ret.setHostnameVerifier(hv);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   388
90ce3da70b43 Initial load
duke
parents:
diff changeset
   389
        return ret;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   390
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   391
90ce3da70b43 Initial load
duke
parents:
diff changeset
   392
    // METHODS
90ce3da70b43 Initial load
duke
parents:
diff changeset
   393
    void setHostnameVerifier(HostnameVerifier hv) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   394
        this.hv = hv;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   395
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   396
90ce3da70b43 Initial load
duke
parents:
diff changeset
   397
    void setSSLSocketFactory(SSLSocketFactory sf) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   398
        sslSocketFactory = sf;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   399
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   400
90ce3da70b43 Initial load
duke
parents:
diff changeset
   401
    SSLSocketFactory getSSLSocketFactory() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   402
        return sslSocketFactory;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   403
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   404
5162
0dbedf4fdb8c 6614957: HttpsURLConnection not using the set SSLSocketFactory for creating all its Sockets
chegar
parents: 5160
diff changeset
   405
    /**
0dbedf4fdb8c 6614957: HttpsURLConnection not using the set SSLSocketFactory for creating all its Sockets
chegar
parents: 5160
diff changeset
   406
     * The following method, createSocket, is defined in NetworkClient
0dbedf4fdb8c 6614957: HttpsURLConnection not using the set SSLSocketFactory for creating all its Sockets
chegar
parents: 5160
diff changeset
   407
     * and overridden here so that the socket facroty is used to create
0dbedf4fdb8c 6614957: HttpsURLConnection not using the set SSLSocketFactory for creating all its Sockets
chegar
parents: 5160
diff changeset
   408
     * new sockets.
0dbedf4fdb8c 6614957: HttpsURLConnection not using the set SSLSocketFactory for creating all its Sockets
chegar
parents: 5160
diff changeset
   409
     */
0dbedf4fdb8c 6614957: HttpsURLConnection not using the set SSLSocketFactory for creating all its Sockets
chegar
parents: 5160
diff changeset
   410
    @Override
0dbedf4fdb8c 6614957: HttpsURLConnection not using the set SSLSocketFactory for creating all its Sockets
chegar
parents: 5160
diff changeset
   411
    protected Socket createSocket() throws IOException {
0dbedf4fdb8c 6614957: HttpsURLConnection not using the set SSLSocketFactory for creating all its Sockets
chegar
parents: 5160
diff changeset
   412
        try {
0dbedf4fdb8c 6614957: HttpsURLConnection not using the set SSLSocketFactory for creating all its Sockets
chegar
parents: 5160
diff changeset
   413
            return sslSocketFactory.createSocket();
0dbedf4fdb8c 6614957: HttpsURLConnection not using the set SSLSocketFactory for creating all its Sockets
chegar
parents: 5160
diff changeset
   414
        } catch (SocketException se) {
0dbedf4fdb8c 6614957: HttpsURLConnection not using the set SSLSocketFactory for creating all its Sockets
chegar
parents: 5160
diff changeset
   415
            //
0dbedf4fdb8c 6614957: HttpsURLConnection not using the set SSLSocketFactory for creating all its Sockets
chegar
parents: 5160
diff changeset
   416
            // bug 6771432
0dbedf4fdb8c 6614957: HttpsURLConnection not using the set SSLSocketFactory for creating all its Sockets
chegar
parents: 5160
diff changeset
   417
            // javax.net.SocketFactory throws a SocketException with an
0dbedf4fdb8c 6614957: HttpsURLConnection not using the set SSLSocketFactory for creating all its Sockets
chegar
parents: 5160
diff changeset
   418
            // UnsupportedOperationException as its cause to indicate that
0dbedf4fdb8c 6614957: HttpsURLConnection not using the set SSLSocketFactory for creating all its Sockets
chegar
parents: 5160
diff changeset
   419
            // unconnected sockets have not been implemented.
0dbedf4fdb8c 6614957: HttpsURLConnection not using the set SSLSocketFactory for creating all its Sockets
chegar
parents: 5160
diff changeset
   420
            //
0dbedf4fdb8c 6614957: HttpsURLConnection not using the set SSLSocketFactory for creating all its Sockets
chegar
parents: 5160
diff changeset
   421
            Throwable t = se.getCause();
0dbedf4fdb8c 6614957: HttpsURLConnection not using the set SSLSocketFactory for creating all its Sockets
chegar
parents: 5160
diff changeset
   422
            if (t != null && t instanceof UnsupportedOperationException) {
0dbedf4fdb8c 6614957: HttpsURLConnection not using the set SSLSocketFactory for creating all its Sockets
chegar
parents: 5160
diff changeset
   423
                return super.createSocket();
0dbedf4fdb8c 6614957: HttpsURLConnection not using the set SSLSocketFactory for creating all its Sockets
chegar
parents: 5160
diff changeset
   424
            } else {
0dbedf4fdb8c 6614957: HttpsURLConnection not using the set SSLSocketFactory for creating all its Sockets
chegar
parents: 5160
diff changeset
   425
                throw se;
0dbedf4fdb8c 6614957: HttpsURLConnection not using the set SSLSocketFactory for creating all its Sockets
chegar
parents: 5160
diff changeset
   426
            }
0dbedf4fdb8c 6614957: HttpsURLConnection not using the set SSLSocketFactory for creating all its Sockets
chegar
parents: 5160
diff changeset
   427
        }
0dbedf4fdb8c 6614957: HttpsURLConnection not using the set SSLSocketFactory for creating all its Sockets
chegar
parents: 5160
diff changeset
   428
    }
0dbedf4fdb8c 6614957: HttpsURLConnection not using the set SSLSocketFactory for creating all its Sockets
chegar
parents: 5160
diff changeset
   429
0dbedf4fdb8c 6614957: HttpsURLConnection not using the set SSLSocketFactory for creating all its Sockets
chegar
parents: 5160
diff changeset
   430
0dbedf4fdb8c 6614957: HttpsURLConnection not using the set SSLSocketFactory for creating all its Sockets
chegar
parents: 5160
diff changeset
   431
    @Override
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   432
    public boolean needsTunneling() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   433
        return (proxy != null && proxy.type() != Proxy.Type.DIRECT
90ce3da70b43 Initial load
duke
parents:
diff changeset
   434
                && proxy.type() != Proxy.Type.SOCKS);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   435
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   436
5162
0dbedf4fdb8c 6614957: HttpsURLConnection not using the set SSLSocketFactory for creating all its Sockets
chegar
parents: 5160
diff changeset
   437
    @Override
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   438
    public void afterConnect() throws IOException, UnknownHostException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   439
        if (!isCachedConnection()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   440
            SSLSocket s = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   441
            SSLSocketFactory factory = sslSocketFactory;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   442
            try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   443
                if (!(serverSocket instanceof SSLSocket)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   444
                    s = (SSLSocket)factory.createSocket(serverSocket,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   445
                                                        host, port, true);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   446
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   447
                    s = (SSLSocket)serverSocket;
5162
0dbedf4fdb8c 6614957: HttpsURLConnection not using the set SSLSocketFactory for creating all its Sockets
chegar
parents: 5160
diff changeset
   448
                    if (s instanceof SSLSocketImpl) {
0dbedf4fdb8c 6614957: HttpsURLConnection not using the set SSLSocketFactory for creating all its Sockets
chegar
parents: 5160
diff changeset
   449
                        ((SSLSocketImpl)s).setHost(host);
0dbedf4fdb8c 6614957: HttpsURLConnection not using the set SSLSocketFactory for creating all its Sockets
chegar
parents: 5160
diff changeset
   450
                    }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   451
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   452
            } catch (IOException ex) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   453
                // If we fail to connect through the tunnel, try it
90ce3da70b43 Initial load
duke
parents:
diff changeset
   454
                // locally, as a last resort.  If this doesn't work,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   455
                // throw the original exception.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   456
                try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   457
                    s = (SSLSocket)factory.createSocket(host, port);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   458
                } catch (IOException ignored) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   459
                    throw ex;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   460
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   461
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   462
90ce3da70b43 Initial load
duke
parents:
diff changeset
   463
            //
90ce3da70b43 Initial load
duke
parents:
diff changeset
   464
            // Force handshaking, so that we get any authentication.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   465
            // Register a handshake callback so our session state tracks any
90ce3da70b43 Initial load
duke
parents:
diff changeset
   466
            // later session renegotiations.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   467
            //
90ce3da70b43 Initial load
duke
parents:
diff changeset
   468
            String [] protocols = getProtocols();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   469
            String [] ciphers = getCipherSuites();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   470
            if (protocols != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   471
                s.setEnabledProtocols(protocols);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   472
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   473
            if (ciphers != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   474
                s.setEnabledCipherSuites(ciphers);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   475
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   476
            s.addHandshakeCompletedListener(this);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   477
7043
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   478
            // We have two hostname verification approaches. One is in
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   479
            // SSL/TLS socket layer, where the algorithm is configured with
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   480
            // SSLParameters.setEndpointIdentificationAlgorithm(), and the
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   481
            // hostname verification is done by X509ExtendedTrustManager when
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   482
            // the algorithm is "HTTPS". The other one is in HTTPS layer,
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   483
            // where the algorithm is customized by
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   484
            // HttpsURLConnection.setHostnameVerifier(), and the hostname
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   485
            // verification is done by HostnameVerifier when the default
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   486
            // rules for hostname verification fail.
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   487
            //
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   488
            // The relationship between two hostname verification approaches
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   489
            // likes the following:
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   490
            //
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   491
            //               |             EIA algorithm
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   492
            //               +----------------------------------------------
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   493
            //               |     null      |   HTTPS    |   LDAP/other   |
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   494
            // -------------------------------------------------------------
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   495
            //     |         |1              |2           |3               |
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   496
            // HNV | default | Set HTTPS EIA | use EIA    | HTTPS          |
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   497
            //     |--------------------------------------------------------
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   498
            //     | non -   |4              |5           |6               |
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   499
            //     | default | HTTPS/HNV     | use EIA    | HTTPS/HNV      |
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   500
            // -------------------------------------------------------------
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   501
            //
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   502
            // Abbreviation:
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   503
            //     EIA: the endpoint identification algorithm in SSL/TLS
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   504
            //           socket layer
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   505
            //     HNV: the hostname verification object in HTTPS layer
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   506
            // Notes:
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   507
            //     case 1. default HNV and EIA is null
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   508
            //           Set EIA as HTTPS, hostname check done in SSL/TLS
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   509
            //           layer.
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   510
            //     case 2. default HNV and EIA is HTTPS
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   511
            //           Use existing EIA, hostname check done in SSL/TLS
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   512
            //           layer.
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   513
            //     case 3. default HNV and EIA is other than HTTPS
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   514
            //           Use existing EIA, EIA check done in SSL/TLS
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   515
            //           layer, then do HTTPS check in HTTPS layer.
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   516
            //     case 4. non-default HNV and EIA is null
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   517
            //           No EIA, no EIA check done in SSL/TLS layer, then do
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   518
            //           HTTPS check in HTTPS layer using HNV as override.
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   519
            //     case 5. non-default HNV and EIA is HTTPS
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   520
            //           Use existing EIA, hostname check done in SSL/TLS
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   521
            //           layer. No HNV override possible. We will review this
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   522
            //           decision and may update the architecture for JDK 7.
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   523
            //     case 6. non-default HNV and EIA is other than HTTPS
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   524
            //           Use existing EIA, EIA check done in SSL/TLS layer,
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   525
            //           then do HTTPS check in HTTPS layer as override.
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   526
            boolean needToCheckSpoofing = true;
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   527
            String identification =
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   528
                s.getSSLParameters().getEndpointIdentificationAlgorithm();
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   529
            if (identification != null && identification.length() != 0) {
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   530
                if (identification.equalsIgnoreCase("HTTPS")) {
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   531
                    // Do not check server identity again out of SSLSocket,
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   532
                    // the endpoint will be identified during TLS handshaking
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   533
                    // in SSLSocket.
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   534
                    needToCheckSpoofing = false;
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   535
                }   // else, we don't understand the identification algorithm,
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   536
                    // need to check URL spoofing here.
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   537
            } else {
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   538
                boolean isDefaultHostnameVerifier = false;
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   539
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   540
                // We prefer to let the SSLSocket do the spoof checks, but if
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   541
                // the application has specified a HostnameVerifier (HNV),
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   542
                // we will always use that.
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   543
                if (hv != null) {
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   544
                    String canonicalName = hv.getClass().getCanonicalName();
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   545
                    if (canonicalName != null &&
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   546
                    canonicalName.equalsIgnoreCase(defaultHVCanonicalName)) {
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   547
                        isDefaultHostnameVerifier = true;
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   548
                    }
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   549
                } else {
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   550
                    // Unlikely to happen! As the behavior is the same as the
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   551
                    // default hostname verifier, so we prefer to let the
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   552
                    // SSLSocket do the spoof checks.
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   553
                    isDefaultHostnameVerifier = true;
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   554
                }
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   555
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   556
                if (isDefaultHostnameVerifier) {
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   557
                    // If the HNV is the default from HttpsURLConnection, we
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   558
                    // will do the spoof checks in SSLSocket.
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   559
                    SSLParameters paramaters = s.getSSLParameters();
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   560
                    paramaters.setEndpointIdentificationAlgorithm("HTTPS");
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   561
                    s.setSSLParameters(paramaters);
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   562
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   563
                    needToCheckSpoofing = false;
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   564
                }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   565
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   566
90ce3da70b43 Initial load
duke
parents:
diff changeset
   567
            s.startHandshake();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   568
            session = s.getSession();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   569
            // change the serverSocket and serverOutput
90ce3da70b43 Initial load
duke
parents:
diff changeset
   570
            serverSocket = s;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   571
            try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   572
                serverOutput = new PrintStream(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   573
                    new BufferedOutputStream(serverSocket.getOutputStream()),
90ce3da70b43 Initial load
duke
parents:
diff changeset
   574
                    false, encoding);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   575
            } catch (UnsupportedEncodingException e) {
10596
39b3a979e600 7090158: Networking Libraries don't build with javac -Werror
chegar
parents: 10419
diff changeset
   576
                throw new InternalError(encoding+" encoding not found");
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   577
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   578
90ce3da70b43 Initial load
duke
parents:
diff changeset
   579
            // check URL spoofing if it has not been checked under handshaking
7043
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   580
            if (needToCheckSpoofing) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   581
                checkURLSpoofing(hv);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   582
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   583
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   584
            // if we are reusing a cached https session,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   585
            // we don't need to do handshaking etc. But we do need to
90ce3da70b43 Initial load
duke
parents:
diff changeset
   586
            // set the ssl session
90ce3da70b43 Initial load
duke
parents:
diff changeset
   587
            session = ((SSLSocket)serverSocket).getSession();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   588
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   589
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   590
90ce3da70b43 Initial load
duke
parents:
diff changeset
   591
    // Server identity checking is done according to RFC 2818: HTTP over TLS
90ce3da70b43 Initial load
duke
parents:
diff changeset
   592
    // Section 3.1 Server Identity
90ce3da70b43 Initial load
duke
parents:
diff changeset
   593
    private void checkURLSpoofing(HostnameVerifier hostnameVerifier)
7043
5e2d1edeb2c7 6916074: Add support for TLS 1.2
xuelei
parents: 5506
diff changeset
   594
            throws IOException {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   595
        //
90ce3da70b43 Initial load
duke
parents:
diff changeset
   596
        // Get authenticated server name, if any
90ce3da70b43 Initial load
duke
parents:
diff changeset
   597
        //
90ce3da70b43 Initial load
duke
parents:
diff changeset
   598
        String host = url.getHost();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   599
90ce3da70b43 Initial load
duke
parents:
diff changeset
   600
        // if IPv6 strip off the "[]"
90ce3da70b43 Initial load
duke
parents:
diff changeset
   601
        if (host != null && host.startsWith("[") && host.endsWith("]")) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   602
            host = host.substring(1, host.length()-1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   603
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   604
90ce3da70b43 Initial load
duke
parents:
diff changeset
   605
        Certificate[] peerCerts = null;
3957
c8fdb8fad795 6885204: JSSE should not require Kerberos to be present
vinnie
parents: 98
diff changeset
   606
        String cipher = session.getCipherSuite();
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   607
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   608
            HostnameChecker checker = HostnameChecker.getInstance(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   609
                                                HostnameChecker.TYPE_TLS);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   610
4236
02f52c723b79 6894643: Separate out dependency on Kerberos
vinnie
parents: 3957
diff changeset
   611
            // Use ciphersuite to determine whether Kerberos is present.
02f52c723b79 6894643: Separate out dependency on Kerberos
vinnie
parents: 3957
diff changeset
   612
            if (cipher.startsWith("TLS_KRB5")) {
5162
0dbedf4fdb8c 6614957: HttpsURLConnection not using the set SSLSocketFactory for creating all its Sockets
chegar
parents: 5160
diff changeset
   613
                if (!HostnameChecker.match(host, getPeerPrincipal())) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   614
                    throw new SSLPeerUnverifiedException("Hostname checker" +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   615
                                " failed for Kerberos");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   616
                }
4236
02f52c723b79 6894643: Separate out dependency on Kerberos
vinnie
parents: 3957
diff changeset
   617
            } else { // X.509
02f52c723b79 6894643: Separate out dependency on Kerberos
vinnie
parents: 3957
diff changeset
   618
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   619
                // get the subject's certificate
90ce3da70b43 Initial load
duke
parents:
diff changeset
   620
                peerCerts = session.getPeerCertificates();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   621
90ce3da70b43 Initial load
duke
parents:
diff changeset
   622
                X509Certificate peerCert;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   623
                if (peerCerts[0] instanceof
90ce3da70b43 Initial load
duke
parents:
diff changeset
   624
                        java.security.cert.X509Certificate) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   625
                    peerCert = (java.security.cert.X509Certificate)peerCerts[0];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   626
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   627
                    throw new SSLPeerUnverifiedException("");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   628
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   629
                checker.match(host, peerCert);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   630
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   631
90ce3da70b43 Initial load
duke
parents:
diff changeset
   632
            // if it doesn't throw an exception, we passed. Return.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   633
            return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   634
90ce3da70b43 Initial load
duke
parents:
diff changeset
   635
        } catch (SSLPeerUnverifiedException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   636
90ce3da70b43 Initial load
duke
parents:
diff changeset
   637
            //
90ce3da70b43 Initial load
duke
parents:
diff changeset
   638
            // client explicitly changed default policy and enabled
90ce3da70b43 Initial load
duke
parents:
diff changeset
   639
            // anonymous ciphers; we can't check the standard policy
90ce3da70b43 Initial load
duke
parents:
diff changeset
   640
            //
90ce3da70b43 Initial load
duke
parents:
diff changeset
   641
            // ignore
90ce3da70b43 Initial load
duke
parents:
diff changeset
   642
        } catch (java.security.cert.CertificateException cpe) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   643
            // ignore
90ce3da70b43 Initial load
duke
parents:
diff changeset
   644
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   645
90ce3da70b43 Initial load
duke
parents:
diff changeset
   646
        if ((cipher != null) && (cipher.indexOf("_anon_") != -1)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   647
            return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   648
        } else if ((hostnameVerifier != null) &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   649
                   (hostnameVerifier.verify(host, session))) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   650
            return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   651
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   652
90ce3da70b43 Initial load
duke
parents:
diff changeset
   653
        serverSocket.close();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   654
        session.invalidate();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   655
90ce3da70b43 Initial load
duke
parents:
diff changeset
   656
        throw new IOException("HTTPS hostname wrong:  should be <"
90ce3da70b43 Initial load
duke
parents:
diff changeset
   657
                              + url.getHost() + ">");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   658
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   659
5162
0dbedf4fdb8c 6614957: HttpsURLConnection not using the set SSLSocketFactory for creating all its Sockets
chegar
parents: 5160
diff changeset
   660
    @Override
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   661
    protected void putInKeepAliveCache() {
16499
88276d2da9c0 8009251: Add proxy handling and keep-alive fixes to jsse
robm
parents: 14342
diff changeset
   662
        if (inCache) {
88276d2da9c0 8009251: Add proxy handling and keep-alive fixes to jsse
robm
parents: 14342
diff changeset
   663
            assert false : "Duplicate put to keep alive cache";
88276d2da9c0 8009251: Add proxy handling and keep-alive fixes to jsse
robm
parents: 14342
diff changeset
   664
            return;
88276d2da9c0 8009251: Add proxy handling and keep-alive fixes to jsse
robm
parents: 14342
diff changeset
   665
        }
88276d2da9c0 8009251: Add proxy handling and keep-alive fixes to jsse
robm
parents: 14342
diff changeset
   666
        inCache = true;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   667
        kac.put(url, sslSocketFactory, this);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   668
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   669
98
4087c83cfab8 6618387: SSL client sessions do not close cleanly. A TCP reset occurs instead of a close_notify alert.
xuelei
parents: 2
diff changeset
   670
    /*
4087c83cfab8 6618387: SSL client sessions do not close cleanly. A TCP reset occurs instead of a close_notify alert.
xuelei
parents: 2
diff changeset
   671
     * Close an idle connection to this URL (if it exists in the cache).
4087c83cfab8 6618387: SSL client sessions do not close cleanly. A TCP reset occurs instead of a close_notify alert.
xuelei
parents: 2
diff changeset
   672
     */
5162
0dbedf4fdb8c 6614957: HttpsURLConnection not using the set SSLSocketFactory for creating all its Sockets
chegar
parents: 5160
diff changeset
   673
    @Override
98
4087c83cfab8 6618387: SSL client sessions do not close cleanly. A TCP reset occurs instead of a close_notify alert.
xuelei
parents: 2
diff changeset
   674
    public void closeIdleConnection() {
10596
39b3a979e600 7090158: Networking Libraries don't build with javac -Werror
chegar
parents: 10419
diff changeset
   675
        HttpClient http = kac.get(url, sslSocketFactory);
98
4087c83cfab8 6618387: SSL client sessions do not close cleanly. A TCP reset occurs instead of a close_notify alert.
xuelei
parents: 2
diff changeset
   676
        if (http != null) {
4087c83cfab8 6618387: SSL client sessions do not close cleanly. A TCP reset occurs instead of a close_notify alert.
xuelei
parents: 2
diff changeset
   677
            http.closeServer();
4087c83cfab8 6618387: SSL client sessions do not close cleanly. A TCP reset occurs instead of a close_notify alert.
xuelei
parents: 2
diff changeset
   678
        }
4087c83cfab8 6618387: SSL client sessions do not close cleanly. A TCP reset occurs instead of a close_notify alert.
xuelei
parents: 2
diff changeset
   679
    }
4087c83cfab8 6618387: SSL client sessions do not close cleanly. A TCP reset occurs instead of a close_notify alert.
xuelei
parents: 2
diff changeset
   680
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   681
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   682
     * Returns the cipher suite in use on this connection.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   683
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   684
    String getCipherSuite() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   685
        return session.getCipherSuite();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   686
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   687
90ce3da70b43 Initial load
duke
parents:
diff changeset
   688
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   689
     * Returns the certificate chain the client sent to the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   690
     * server, or null if the client did not authenticate.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   691
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   692
    public java.security.cert.Certificate [] getLocalCertificates() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   693
        return session.getLocalCertificates();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   694
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   695
90ce3da70b43 Initial load
duke
parents:
diff changeset
   696
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   697
     * Returns the certificate chain with which the server
90ce3da70b43 Initial load
duke
parents:
diff changeset
   698
     * authenticated itself, or throw a SSLPeerUnverifiedException
90ce3da70b43 Initial load
duke
parents:
diff changeset
   699
     * if the server did not authenticate.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   700
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   701
    java.security.cert.Certificate [] getServerCertificates()
90ce3da70b43 Initial load
duke
parents:
diff changeset
   702
            throws SSLPeerUnverifiedException
90ce3da70b43 Initial load
duke
parents:
diff changeset
   703
    {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   704
        return session.getPeerCertificates();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   705
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   706
90ce3da70b43 Initial load
duke
parents:
diff changeset
   707
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   708
     * Returns the principal with which the server authenticated
90ce3da70b43 Initial load
duke
parents:
diff changeset
   709
     * itself, or throw a SSLPeerUnverifiedException if the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   710
     * server did not authenticate.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   711
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   712
    Principal getPeerPrincipal()
90ce3da70b43 Initial load
duke
parents:
diff changeset
   713
            throws SSLPeerUnverifiedException
90ce3da70b43 Initial load
duke
parents:
diff changeset
   714
    {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   715
        Principal principal;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   716
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   717
            principal = session.getPeerPrincipal();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   718
        } catch (AbstractMethodError e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   719
            // if the provider does not support it, fallback to peer certs.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   720
            // return the X500Principal of the end-entity cert.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   721
            java.security.cert.Certificate[] certs =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   722
                        session.getPeerCertificates();
10596
39b3a979e600 7090158: Networking Libraries don't build with javac -Werror
chegar
parents: 10419
diff changeset
   723
            principal = ((X509Certificate)certs[0]).getSubjectX500Principal();
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   724
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   725
        return principal;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   726
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   727
90ce3da70b43 Initial load
duke
parents:
diff changeset
   728
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   729
     * Returns the principal the client sent to the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   730
     * server, or null if the client did not authenticate.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   731
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   732
    Principal getLocalPrincipal()
90ce3da70b43 Initial load
duke
parents:
diff changeset
   733
    {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   734
        Principal principal;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   735
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   736
            principal = session.getLocalPrincipal();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   737
        } catch (AbstractMethodError e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   738
            principal = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   739
            // if the provider does not support it, fallback to local certs.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   740
            // return the X500Principal of the end-entity cert.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   741
            java.security.cert.Certificate[] certs =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   742
                        session.getLocalCertificates();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   743
            if (certs != null) {
10596
39b3a979e600 7090158: Networking Libraries don't build with javac -Werror
chegar
parents: 10419
diff changeset
   744
                principal = ((X509Certificate)certs[0]).getSubjectX500Principal();
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   745
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   746
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   747
        return principal;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   748
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   749
90ce3da70b43 Initial load
duke
parents:
diff changeset
   750
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   751
     * This method implements the SSL HandshakeCompleted callback,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   752
     * remembering the resulting session so that it may be queried
90ce3da70b43 Initial load
duke
parents:
diff changeset
   753
     * for the current cipher suite and peer certificates.  Servers
90ce3da70b43 Initial load
duke
parents:
diff changeset
   754
     * sometimes re-initiate handshaking, so the session in use on
90ce3da70b43 Initial load
duke
parents:
diff changeset
   755
     * a given connection may change.  When sessions change, so may
90ce3da70b43 Initial load
duke
parents:
diff changeset
   756
     * peer identities and cipher suites.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   757
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   758
    public void handshakeCompleted(HandshakeCompletedEvent event)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   759
    {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   760
        session = event.getSession();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   761
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   762
90ce3da70b43 Initial load
duke
parents:
diff changeset
   763
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   764
     * @return the proxy host being used for this client, or null
90ce3da70b43 Initial load
duke
parents:
diff changeset
   765
     *          if we're not going through a proxy
90ce3da70b43 Initial load
duke
parents:
diff changeset
   766
     */
5162
0dbedf4fdb8c 6614957: HttpsURLConnection not using the set SSLSocketFactory for creating all its Sockets
chegar
parents: 5160
diff changeset
   767
    @Override
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   768
    public String getProxyHostUsed() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   769
        if (!needsTunneling()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   770
            return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   771
        } else {
5160
c0e0c9a9d338 6632169: HttpClient and HttpsClient should not try to reverse lookup IP address of a proxy server
chegar
parents: 4236
diff changeset
   772
            return super.getProxyHostUsed();
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   773
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   774
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   775
90ce3da70b43 Initial load
duke
parents:
diff changeset
   776
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   777
     * @return the proxy port being used for this client.  Meaningless
90ce3da70b43 Initial load
duke
parents:
diff changeset
   778
     *          if getProxyHostUsed() gives null.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   779
     */
5162
0dbedf4fdb8c 6614957: HttpsURLConnection not using the set SSLSocketFactory for creating all its Sockets
chegar
parents: 5160
diff changeset
   780
    @Override
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   781
    public int getProxyPortUsed() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   782
        return (proxy == null || proxy.type() == Proxy.Type.DIRECT ||
90ce3da70b43 Initial load
duke
parents:
diff changeset
   783
                proxy.type() == Proxy.Type.SOCKS)? -1:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   784
            ((InetSocketAddress)proxy.address()).getPort();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   785
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   786
}