/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* This class provides HTTPS client URL support, building on the standard
* "sun.net.www" HTTP protocol handler. HTTPS is the same protocol as HTTP,
* but differs in the transport layer which it uses: <UL>
*
* <LI>There's a <em>Secure Sockets Layer</em> between TCP
* and the HTTP protocol code.
*
* <LI>It uses a different default TCP port.
*
* <LI>It doesn't use application level proxies, which can see and
* manipulate HTTP user level data, compromising privacy. It uses
* low level tunneling instead, which hides HTTP protocol and data
* from all third parties. (Traffic analysis is still possible).
*
* <LI>It does basic server authentication, to protect
* against "URL spoofing" attacks. This involves deciding
* whether the X.509 certificate chain identifying the server
* is trusted, and verifying that the name of the server is
* found in the certificate. (The application may enable an
* anonymous SSL cipher suite, and such checks are not done
* for anonymous ciphers.)
*
* <LI>It exposes key SSL session attributes, specifically the
* cipher suite in use and the server's X509 certificates, to
* application software which knows about this protocol handler.
*
* </UL>
*
* <P> System properties used include: <UL>
*
* <LI><em>https.proxyHost</em> ... the host supporting SSL
* tunneling using the conventional CONNECT syntax
*
* <LI><em>https.proxyPort</em> ... port to use on proxyHost
*
* <LI><em>https.cipherSuites</em> ... comma separated list of
* SSL cipher suite names to enable.
*
* <LI><em>http.nonProxyHosts</em> ...
*
* </UL>
*
* @author David Brownell
* @author Bill Foote
*/
// final for export control reasons (access to APIs); remove with care
implements HandshakeCompletedListener
{
// STATIC STATE and ACCESSORS THERETO
// HTTPS uses a different default port number than HTTP.
// default HostnameVerifier class canonical name
"javax.net.ssl.HttpsURLConnection.DefaultHostnameVerifier";
/** Returns the default HTTPS port (443) */
// HttpClient.proxyDisabled will always be false, because we don't
// use an application-level HTTP proxy. We might tunnel through
// our http proxy, though.
// INSTANCE DATA
// last negotiated SSL session
//
// If ciphers are assigned, sort them into an array.
//
new GetPropertyAction("https.cipherSuites"));
} else {
while (tokenizer.hasMoreTokens())
}
return ciphers;
}
//
// If protocols are assigned, sort them into an array.
//
new GetPropertyAction("https.protocols"));
} else {
while (tokenizer.hasMoreTokens())
}
}
return protocols;
}
userAgent = "JSSE";
}
return userAgent;
}
// should remove once HttpClient.newHttpProxy is putback
try {
public InetSocketAddress run() {
}});
}
}
// CONSTRUCTOR, FACTORY
/**
* Create an HTTPS client URL. Traffic will be tunneled through any
* intermediate nodes rather than proxied, so that confidentiality
* of data exchanged can be preserved. However, note that all the
* anonymous SSL flavors are subject to "person-in-the-middle"
* attacks against confidentiality. If you enable use of those
* flavors, you may be giving up the protection you get through
* SSL tunneling.
*
* Use New to get new HttpsClient. This constructor is meant to be
* used only by New method. New properly checks for URL spoofing.
*
* @param URL https URL with which a connection must be established
*/
throws IOException
{
// HttpClient-level proxying is always disabled,
// because we override doConnect to do tunneling instead.
}
/**
* Create an HTTPS client URL. Traffic will be tunneled through
* the specified proxy server.
*/
throws IOException {
}
/**
* Create an HTTPS client URL. Traffic will be tunneled through
* the specified proxy server, with a connect timeout
*/
int connectTimeout)
throws IOException {
}
/**
* Same as previous constructor except using a Proxy
*/
int connectTimeout)
throws IOException {
this.proxyDisabled = true;
if (port == -1) {
port = getDefaultPort();
}
openServer();
}
// This code largely ripped off from HttpClient.New, and
// it uses the same keepalive cache.
throws IOException {
}
/** See HttpClient for the model for this method. */
}
/**
* Get a HTTPS client to the URL. Traffic will be tunneled through
* the specified proxy server.
*/
}
throws IOException {
httpuc);
}
throws IOException {
}
throws IOException
{
if (p == null) {
}
if (useCache) {
/* see if one's already around */
}
synchronized (ret) {
ret.cachedHttpClient = true;
}
}
} else {
// We cannot return this connection to the cache as it's
// KeepAliveTimeout will get reset. We simply close the connection.
// This should be fine as it is very rare that a connection
// to the same host will not use the same proxy.
synchronized(ret) {
ret.closeServer();
}
}
}
}
} else {
} else {
}
}
}
return ret;
}
// METHODS
}
}
return sslSocketFactory;
}
/**
* The following method, createSocket, is defined in NetworkClient
* and overridden here so that the socket facroty is used to create
* new sockets.
*/
try {
return sslSocketFactory.createSocket();
} catch (SocketException se) {
//
// bug 6771432
// javax.net.SocketFactory throws a SocketException with an
// UnsupportedOperationException as its cause to indicate that
// unconnected sockets have not been implemented.
//
if (t != null && t instanceof UnsupportedOperationException) {
return super.createSocket();
} else {
throw se;
}
}
}
public boolean needsTunneling() {
}
if (!isCachedConnection()) {
try {
if (!(serverSocket instanceof SSLSocket)) {
} else {
s = (SSLSocket)serverSocket;
if (s instanceof SSLSocketImpl) {
}
}
} catch (IOException ex) {
// If we fail to connect through the tunnel, try it
// locally, as a last resort. If this doesn't work,
// throw the original exception.
try {
} catch (IOException ignored) {
throw ex;
}
}
//
// Force handshaking, so that we get any authentication.
// Register a handshake callback so our session state tracks any
// later session renegotiations.
//
}
}
s.addHandshakeCompletedListener(this);
// We have two hostname verification approaches. One is in
// SSLParameters.setEndpointIdentificationAlgorithm(), and the
// hostname verification is done by X509ExtendedTrustManager when
// the algorithm is "HTTPS". The other one is in HTTPS layer,
// where the algorithm is customized by
// HttpsURLConnection.setHostnameVerifier(), and the hostname
// verification is done by HostnameVerifier when the default
// rules for hostname verification fail.
//
// The relationship between two hostname verification approaches
// likes the following:
//
// | EIA algorithm
// +----------------------------------------------
// -------------------------------------------------------------
// | |1 |2 |3 |
// HNV | default | Set HTTPS EIA | use EIA | HTTPS |
// |--------------------------------------------------------
// | non - |4 |5 |6 |
// -------------------------------------------------------------
//
// Abbreviation:
// socket layer
// HNV: the hostname verification object in HTTPS layer
// Notes:
// case 1. default HNV and EIA is null
// layer.
// case 2. default HNV and EIA is HTTPS
// layer.
// case 3. default HNV and EIA is other than HTTPS
// layer, then do HTTPS check in HTTPS layer.
// case 4. non-default HNV and EIA is null
// HTTPS check in HTTPS layer using HNV as override.
// case 5. non-default HNV and EIA is HTTPS
// layer. No HNV override possible. We will review this
// decision and may update the architecture for JDK 7.
// case 6. non-default HNV and EIA is other than HTTPS
// then do HTTPS check in HTTPS layer as override.
boolean needToCheckSpoofing = true;
// Do not check server identity again out of SSLSocket,
// the endpoint will be identified during TLS handshaking
// in SSLSocket.
needToCheckSpoofing = false;
} // else, we don't understand the identification algorithm,
// need to check URL spoofing here.
} else {
boolean isDefaultHostnameVerifier = false;
// We prefer to let the SSLSocket do the spoof checks, but if
// the application has specified a HostnameVerifier (HNV),
// we will always use that.
if (canonicalName != null &&
isDefaultHostnameVerifier = true;
}
} else {
// Unlikely to happen! As the behavior is the same as the
// default hostname verifier, so we prefer to let the
// SSLSocket do the spoof checks.
isDefaultHostnameVerifier = true;
}
if (isDefaultHostnameVerifier) {
// If the HNV is the default from HttpsURLConnection, we
// will do the spoof checks in SSLSocket.
needToCheckSpoofing = false;
}
}
s.startHandshake();
session = s.getSession();
// change the serverSocket and serverOutput
serverSocket = s;
try {
serverOutput = new PrintStream(
false, encoding);
} catch (UnsupportedEncodingException e) {
}
// check URL spoofing if it has not been checked under handshaking
if (needToCheckSpoofing) {
}
} else {
// if we are reusing a cached https session,
// we don't need to do handshaking etc. But we do need to
// set the ssl session
}
}
// Server identity checking is done according to RFC 2818: HTTP over TLS
// Section 3.1 Server Identity
throws IOException {
//
// Get authenticated server name, if any
//
// if IPv6 strip off the "[]"
}
try {
// Use ciphersuite to determine whether Kerberos is present.
throw new SSLPeerUnverifiedException("Hostname checker" +
" failed for Kerberos");
}
} else { // X.509
// get the subject's certificate
if (peerCerts[0] instanceof
} else {
throw new SSLPeerUnverifiedException("");
}
}
// if it doesn't throw an exception, we passed. Return.
return;
} catch (SSLPeerUnverifiedException e) {
//
// client explicitly changed default policy and enabled
// anonymous ciphers; we can't check the standard policy
//
// ignore
// ignore
}
return;
} else if ((hostnameVerifier != null) &&
return;
}
throw new IOException("HTTPS hostname wrong: should be <"
}
protected void putInKeepAliveCache() {
if (inCache) {
assert false : "Duplicate put to keep alive cache";
return;
}
inCache = true;
}
/*
* Close an idle connection to this URL (if it exists in the cache).
*/
public void closeIdleConnection() {
http.closeServer();
}
}
/**
* Returns the cipher suite in use on this connection.
*/
return session.getCipherSuite();
}
/**
* Returns the certificate chain the client sent to the
* server, or null if the client did not authenticate.
*/
return session.getLocalCertificates();
}
/**
* Returns the certificate chain with which the server
* authenticated itself, or throw a SSLPeerUnverifiedException
* if the server did not authenticate.
*/
throws SSLPeerUnverifiedException
{
return session.getPeerCertificates();
}
/**
* Returns the X.509 certificate chain with which the server
* authenticated itself, or null if the server did not authenticate.
*/
throws SSLPeerUnverifiedException
{
return session.getPeerCertificateChain();
}
/**
* Returns the principal with which the server authenticated
* itself, or throw a SSLPeerUnverifiedException if the
* server did not authenticate.
*/
throws SSLPeerUnverifiedException
{
try {
} catch (AbstractMethodError e) {
// if the provider does not support it, fallback to peer certs.
// return the X500Principal of the end-entity cert.
}
return principal;
}
/**
* Returns the principal the client sent to the
* server, or null if the client did not authenticate.
*/
{
try {
} catch (AbstractMethodError e) {
// if the provider does not support it, fallback to local certs.
// return the X500Principal of the end-entity cert.
}
}
return principal;
}
/**
* This method implements the SSL HandshakeCompleted callback,
* remembering the resulting session so that it may be queried
* for the current cipher suite and peer certificates. Servers
* sometimes re-initiate handshaking, so the session in use on
* a given connection may change. When sessions change, so may
* peer identities and cipher suites.
*/
{
}
/**
* @return the proxy host being used for this client, or null
* if we're not going through a proxy
*/
if (!needsTunneling()) {
return null;
} else {
return super.getProxyHostUsed();
}
}
/**
* @return the proxy port being used for this client. Meaningless
* if getProxyHostUsed() gives null.
*/
public int getProxyPortUsed() {
}
}