--- a/jdk/src/share/classes/sun/security/ssl/SSLSocketImpl.java Wed Oct 17 13:22:39 2012 -0700
+++ b/jdk/src/share/classes/sun/security/ssl/SSLSocketImpl.java Thu Oct 18 01:14:00 2012 -0700
@@ -36,9 +36,9 @@
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
+import java.nio.charset.StandardCharsets;
import javax.crypto.BadPaddingException;
-
import javax.net.ssl.*;
/**
@@ -198,14 +198,6 @@
private boolean autoClose = true;
private AccessControlContext acc;
- /*
- * We cannot use the hostname resolved from name services. For
- * virtual hosting, multiple hostnames may be bound to the same IP
- * address, so the hostname resolved from name services is not
- * reliable.
- */
- private String rawHostname;
-
// The cipher suites enabled for use on this connection.
private CipherSuiteList enabledCipherSuites;
@@ -215,6 +207,12 @@
// The cryptographic algorithm constraints
private AlgorithmConstraints algorithmConstraints = null;
+ // The server name indication and matchers
+ List<SNIServerName> serverNames =
+ Collections.<SNIServerName>emptyList();
+ Collection<SNIMatcher> sniMatchers =
+ Collections.<SNIMatcher>emptyList();
+
/*
* READ ME * READ ME * READ ME * READ ME * READ ME * READ ME *
* IMPORTANT STUFF TO UNDERSTANDING THE SYNCHRONIZATION ISSUES.
@@ -397,7 +395,8 @@
throws IOException, UnknownHostException {
super();
this.host = host;
- this.rawHostname = host;
+ this.serverNames =
+ Utilities.addToSNIServerNameList(this.serverNames, this.host);
init(context, false);
SocketAddress socketAddress =
host != null ? new InetSocketAddress(host, port) :
@@ -440,7 +439,8 @@
throws IOException, UnknownHostException {
super();
this.host = host;
- this.rawHostname = host;
+ this.serverNames =
+ Utilities.addToSNIServerNameList(this.serverNames, this.host);
init(context, false);
bind(new InetSocketAddress(localAddr, localPort));
SocketAddress socketAddress =
@@ -482,13 +482,15 @@
CipherSuiteList suites, byte clientAuth,
boolean sessionCreation, ProtocolList protocols,
String identificationProtocol,
- AlgorithmConstraints algorithmConstraints) throws IOException {
+ AlgorithmConstraints algorithmConstraints,
+ Collection<SNIMatcher> sniMatchers) throws IOException {
super();
doClientAuth = clientAuth;
enableSessionCreation = sessionCreation;
this.identificationProtocol = identificationProtocol;
this.algorithmConstraints = algorithmConstraints;
+ this.sniMatchers = sniMatchers;
init(context, serverMode);
/*
@@ -535,13 +537,36 @@
throw new SocketException("Underlying socket is not connected");
}
this.host = host;
- this.rawHostname = host;
+ this.serverNames =
+ Utilities.addToSNIServerNameList(this.serverNames, this.host);
init(context, false);
this.autoClose = autoClose;
doneConnect();
}
/**
+ * Creates a server mode {@link Socket} layered over an
+ * existing connected socket, and is able to read data which has
+ * already been consumed/removed from the {@link Socket}'s
+ * underlying {@link InputStream}.
+ */
+ SSLSocketImpl(SSLContextImpl context, Socket sock,
+ InputStream consumed, boolean autoClose) throws IOException {
+ super(sock, consumed);
+ // We always layer over a connected socket
+ if (!sock.isConnected()) {
+ throw new SocketException("Underlying socket is not connected");
+ }
+
+ // In server mode, it is not necessary to set host and serverNames.
+ // Otherwise, would require a reverse DNS lookup to get the hostname.
+
+ init(context, true);
+ this.autoClose = autoClose;
+ doneConnect();
+ }
+
+ /**
* Initializes the client socket.
*/
private void init(SSLContextImpl context, boolean isServer) {
@@ -604,7 +629,7 @@
public void connect(SocketAddress endpoint, int timeout)
throws IOException {
- if (self != this) {
+ if (isLayered()) {
throw new SocketException("Already connected");
}
@@ -628,13 +653,8 @@
* java.net actually connects using the socket "self", else
* we get some pretty bizarre failure modes.
*/
- if (self == this) {
- sockInput = super.getInputStream();
- sockOutput = super.getOutputStream();
- } else {
- sockInput = self.getInputStream();
- sockOutput = self.getOutputStream();
- }
+ sockInput = super.getInputStream();
+ sockOutput = super.getOutputStream();
/*
* Move to handshaking state, with pending session initialized
@@ -761,13 +781,14 @@
// For layered, non-autoclose sockets, we are not
// able to bring them into a usable state, so we
// treat it as fatal error.
- if (self != this && !autoClose) {
+ if (isLayered() && !autoClose) {
// Note that the alert description is
// specified as -1, so no message will be send
// to peer anymore.
fatal((byte)(-1), ssle);
} else if ((debug != null) && Debug.isOn("ssl")) {
- System.out.println(threadName() +
+ System.out.println(
+ Thread.currentThread().getName() +
", received Exception: " + ssle);
}
@@ -935,7 +956,7 @@
boolean handshaking = (getConnectionState() <= cs_HANDSHAKE);
boolean rethrow = requireCloseNotify || handshaking;
if ((debug != null) && Debug.isOn("ssl")) {
- System.out.println(threadName() +
+ System.out.println(Thread.currentThread().getName() +
", received EOFException: "
+ (rethrow ? "error" : "ignored"));
}
@@ -1119,7 +1140,7 @@
// TLS requires that unrecognized records be ignored.
//
if (debug != null && Debug.isOn("ssl")) {
- System.out.println(threadName() +
+ System.out.println(Thread.currentThread().getName() +
", Received record type: "
+ r.contentType());
}
@@ -1183,7 +1204,7 @@
* for handshaking and bad_record_mac for other records.
*/
if (debug != null && Debug.isOn("ssl")) {
- System.out.println(threadName() +
+ System.out.println(Thread.currentThread().getName() +
", sequence number extremely close to overflow " +
"(2^64-1 packets). Closing connection.");
@@ -1200,7 +1221,8 @@
*/
if ((type != Record.ct_handshake) && mac.seqNumIsHuge()) {
if (debug != null && Debug.isOn("ssl")) {
- System.out.println(threadName() + ", request renegotiation " +
+ System.out.println(Thread.currentThread().getName() +
+ ", request renegotiation " +
"to avoid sequence number overflow");
}
@@ -1278,11 +1300,13 @@
enabledProtocols, doClientAuth,
protocolVersion, connectionState == cs_HANDSHAKE,
secureRenegotiation, clientVerifyData, serverVerifyData);
+ handshaker.setSNIMatchers(sniMatchers);
} else {
handshaker = new ClientHandshaker(this, sslContext,
enabledProtocols,
protocolVersion, connectionState == cs_HANDSHAKE,
secureRenegotiation, clientVerifyData, serverVerifyData);
+ handshaker.setSNIServerNames(serverNames);
}
handshaker.setEnabledCipherSuites(enabledCipherSuites);
handshaker.setEnableSessionCreation(enableSessionCreation);
@@ -1509,24 +1533,20 @@
protected void closeSocket() throws IOException {
if ((debug != null) && Debug.isOn("ssl")) {
- System.out.println(threadName() + ", called closeSocket()");
+ System.out.println(Thread.currentThread().getName() +
+ ", called closeSocket()");
}
- if (self == this) {
- super.close();
- } else {
- self.close();
- }
+
+ super.close();
}
private void closeSocket(boolean selfInitiated) throws IOException {
if ((debug != null) && Debug.isOn("ssl")) {
- System.out.println(threadName() +
+ System.out.println(Thread.currentThread().getName() +
", called closeSocket(" + selfInitiated + ")");
}
- if (self == this) {
+ if (!isLayered() || autoClose) {
super.close();
- } else if (autoClose) {
- self.close();
} else if (selfInitiated) {
// layered && non-autoclose
// read close_notify alert to clear input stream
@@ -1549,7 +1569,8 @@
*/
public void close() throws IOException {
if ((debug != null) && Debug.isOn("ssl")) {
- System.out.println(threadName() + ", called close()");
+ System.out.println(Thread.currentThread().getName() +
+ ", called close()");
}
closeInternal(true); // caller is initiating close
setConnectionState(cs_APP_CLOSED);
@@ -1567,8 +1588,8 @@
*/
private void closeInternal(boolean selfInitiated) throws IOException {
if ((debug != null) && Debug.isOn("ssl")) {
- System.out.println(threadName() + ", called closeInternal("
- + selfInitiated + ")");
+ System.out.println(Thread.currentThread().getName() +
+ ", called closeInternal(" + selfInitiated + ")");
}
int state = getConnectionState();
@@ -1630,7 +1651,7 @@
// closing since it is already in progress.
if (state == cs_SENT_CLOSE) {
if (debug != null && Debug.isOn("ssl")) {
- System.out.println(threadName() +
+ System.out.println(Thread.currentThread().getName() +
", close invoked again; state = " +
getConnectionState());
}
@@ -1653,7 +1674,7 @@
}
}
if ((debug != null) && Debug.isOn("ssl")) {
- System.out.println(threadName() +
+ System.out.println(Thread.currentThread().getName() +
", after primary close; state = " +
getConnectionState());
}
@@ -1701,7 +1722,7 @@
*/
void waitForClose(boolean rethrow) throws IOException {
if (debug != null && Debug.isOn("ssl")) {
- System.out.println(threadName() +
+ System.out.println(Thread.currentThread().getName() +
", waiting for close_notify or alert: state "
+ getConnectionState());
}
@@ -1726,7 +1747,7 @@
inrec = null;
} catch (IOException e) {
if (debug != null && Debug.isOn("ssl")) {
- System.out.println(threadName() +
+ System.out.println(Thread.currentThread().getName() +
", Exception while waiting for close " +e);
}
if (rethrow) {
@@ -1788,8 +1809,8 @@
synchronized private void handleException(Exception e, boolean resumable)
throws IOException {
if ((debug != null) && Debug.isOn("ssl")) {
- System.out.println(threadName()
- + ", handling exception: " + e.toString());
+ System.out.println(Thread.currentThread().getName() +
+ ", handling exception: " + e.toString());
}
// don't close the Socket in case of timeouts or interrupts if
@@ -1935,7 +1956,7 @@
if (debug != null && (Debug.isOn("record") ||
Debug.isOn("handshake"))) {
synchronized (System.out) {
- System.out.print(threadName());
+ System.out.print(Thread.currentThread().getName());
System.out.print(", RECV " + protocolVersion + " ALERT: ");
if (level == Alerts.alert_fatal) {
System.out.print("fatal, ");
@@ -2001,7 +2022,7 @@
boolean useDebug = debug != null && Debug.isOn("ssl");
if (useDebug) {
synchronized (System.out) {
- System.out.print(threadName());
+ System.out.print(Thread.currentThread().getName());
System.out.print(", SEND " + protocolVersion + " ALERT: ");
if (level == Alerts.alert_fatal) {
System.out.print("fatal, ");
@@ -2021,7 +2042,7 @@
writeRecord(r);
} catch (IOException e) {
if (useDebug) {
- System.out.println(threadName() +
+ System.out.println(Thread.currentThread().getName() +
", Exception sending alert: " + e);
}
}
@@ -2118,14 +2139,15 @@
return host;
}
- synchronized String getRawHostname() {
- return rawHostname;
- }
-
// ONLY used by HttpsClient to setup the URI specified hostname
+ //
+ // Please NOTE that this method MUST be called before calling to
+ // SSLSocket.setSSLParameters(). Otherwise, the {@code host} parameter
+ // may override SNIHostName in the customized server name indication.
synchronized public void setHost(String host) {
this.host = host;
- this.rawHostname = host;
+ this.serverNames =
+ Utilities.addToSNIServerNameList(this.serverNames, this.host);
}
/**
@@ -2186,7 +2208,7 @@
} catch (IOException e) {
// handshake failed. log and return a nullSession
if (debug != null && Debug.isOn("handshake")) {
- System.out.println(threadName() +
+ System.out.println(Thread.currentThread().getName() +
", IOException in getSession(): " + e);
}
}
@@ -2328,7 +2350,7 @@
default:
if (debug != null && Debug.isOn("ssl")) {
- System.out.println(threadName() +
+ System.out.println(Thread.currentThread().getName() +
", setUseClientMode() invoked in state = " +
connectionState);
}
@@ -2422,14 +2444,11 @@
*/
public void setSoTimeout(int timeout) throws SocketException {
if ((debug != null) && Debug.isOn("ssl")) {
- System.out.println(threadName() +
+ System.out.println(Thread.currentThread().getName() +
", setSoTimeout(" + timeout + ") called");
}
- if (self == this) {
- super.setSoTimeout(timeout);
- } else {
- self.setSoTimeout(timeout);
- }
+
+ super.setSoTimeout(timeout);
}
/**
@@ -2474,6 +2493,8 @@
// the super implementation does not handle the following parameters
params.setEndpointIdentificationAlgorithm(identificationProtocol);
params.setAlgorithmConstraints(algorithmConstraints);
+ params.setSNIMatchers(sniMatchers);
+ params.setServerNames(serverNames);
return params;
}
@@ -2487,9 +2508,25 @@
// the super implementation does not handle the following parameters
identificationProtocol = params.getEndpointIdentificationAlgorithm();
algorithmConstraints = params.getAlgorithmConstraints();
+
+ List<SNIServerName> sniNames = params.getServerNames();
+ if (sniNames != null) {
+ serverNames = sniNames;
+ }
+
+ Collection<SNIMatcher> matchers = params.getSNIMatchers();
+ if (matchers != null) {
+ sniMatchers = matchers;
+ }
+
if ((handshaker != null) && !handshaker.started()) {
handshaker.setIdentificationProtocol(identificationProtocol);
handshaker.setAlgorithmConstraints(algorithmConstraints);
+ if (roleIsServer) {
+ handshaker.setSNIMatchers(sniMatchers);
+ } else {
+ handshaker.setSNIServerNames(serverNames);
+ }
}
}
@@ -2531,13 +2568,6 @@
}
/**
- * Return the name of the current thread. Utility method.
- */
- private static String threadName() {
- return Thread.currentThread().getName();
- }
-
- /**
* Returns a printable representation of this end of the connection.
*/
public String toString() {
@@ -2548,11 +2578,7 @@
retval.append(sess.getCipherSuite());
retval.append(": ");
- if (self == this) {
- retval.append(super.toString());
- } else {
- retval.append(self.toString());
- }
+ retval.append(super.toString());
retval.append("]");
return retval.toString();