提交 c86faaf6 编写于 作者: A aefimov

Merge

...@@ -916,3 +916,5 @@ f26f68978e0e7ed0e6e61f9d64fa2d06f1c1a24c jdk8u181-b08 ...@@ -916,3 +916,5 @@ f26f68978e0e7ed0e6e61f9d64fa2d06f1c1a24c jdk8u181-b08
0cb452d66676bc1b3824bea4a0c16ac76e58b070 jdk8u181-b13 0cb452d66676bc1b3824bea4a0c16ac76e58b070 jdk8u181-b13
b01c6e5aa43c784fc66465b56227ddd9aa29eee6 jdk8u191-b01 b01c6e5aa43c784fc66465b56227ddd9aa29eee6 jdk8u191-b01
2db6890a956723ac347b573217d91bbbedbb0528 jdk8u201-b00 2db6890a956723ac347b573217d91bbbedbb0528 jdk8u201-b00
2db6890a956723ac347b573217d91bbbedbb0528 jdk8u191-b02
89e2889d02d2f5dabdeda7f60cf80a8df3100eb4 jdk8u191-b03
...@@ -191,19 +191,24 @@ final class ClientHandshaker extends Handshaker { ...@@ -191,19 +191,24 @@ final class ClientHandshaker extends Handshaker {
*/ */
@Override @Override
void processMessage(byte type, int messageLen) throws IOException { void processMessage(byte type, int messageLen) throws IOException {
if (state >= type
&& (type != HandshakeMessage.ht_hello_request)) { // check the handshake state
throw new SSLProtocolException( List<Byte> ignoredOptStates = handshakeState.check(type);
"Handshake message sequence violation, " + type);
}
switch (type) { switch (type) {
case HandshakeMessage.ht_hello_request: case HandshakeMessage.ht_hello_request:
this.serverHelloRequest(new HelloRequest(input)); HelloRequest helloRequest = new HelloRequest(input);
handshakeState.update(helloRequest, resumingSession);
this.serverHelloRequest(helloRequest);
break; break;
case HandshakeMessage.ht_server_hello: case HandshakeMessage.ht_server_hello:
this.serverHello(new ServerHello(input, messageLen)); ServerHello serverHello = new ServerHello(input, messageLen);
this.serverHello(serverHello);
// This handshake state update needs the resumingSession value
// set by serverHello().
handshakeState.update(serverHello, resumingSession);
break; break;
case HandshakeMessage.ht_certificate: case HandshakeMessage.ht_certificate:
...@@ -213,7 +218,9 @@ final class ClientHandshaker extends Handshaker { ...@@ -213,7 +218,9 @@ final class ClientHandshaker extends Handshaker {
"unexpected server cert chain"); "unexpected server cert chain");
// NOTREACHED // NOTREACHED
} }
this.serverCertificate(new CertificateMsg(input)); CertificateMsg certificateMsg = new CertificateMsg(input);
handshakeState.update(certificateMsg, resumingSession);
this.serverCertificate(certificateMsg);
serverKey = serverKey =
session.getPeerCertificates()[0].getPublicKey(); session.getPeerCertificates()[0].getPublicKey();
break; break;
...@@ -249,15 +256,20 @@ final class ClientHandshaker extends Handshaker { ...@@ -249,15 +256,20 @@ final class ClientHandshaker extends Handshaker {
} }
try { try {
this.serverKeyExchange(new RSA_ServerKeyExchange(input)); RSA_ServerKeyExchange rsaSrvKeyExchange =
new RSA_ServerKeyExchange(input);
handshakeState.update(rsaSrvKeyExchange, resumingSession);
this.serverKeyExchange(rsaSrvKeyExchange);
} catch (GeneralSecurityException e) { } catch (GeneralSecurityException e) {
throwSSLException("Server key", e); throwSSLException("Server key", e);
} }
break; break;
case K_DH_ANON: case K_DH_ANON:
try { try {
this.serverKeyExchange(new DH_ServerKeyExchange( DH_ServerKeyExchange dhSrvKeyExchange =
input, protocolVersion)); new DH_ServerKeyExchange(input, protocolVersion);
handshakeState.update(dhSrvKeyExchange, resumingSession);
this.serverKeyExchange(dhSrvKeyExchange);
} catch (GeneralSecurityException e) { } catch (GeneralSecurityException e) {
throwSSLException("Server key", e); throwSSLException("Server key", e);
} }
...@@ -265,11 +277,14 @@ final class ClientHandshaker extends Handshaker { ...@@ -265,11 +277,14 @@ final class ClientHandshaker extends Handshaker {
case K_DHE_DSS: case K_DHE_DSS:
case K_DHE_RSA: case K_DHE_RSA:
try { try {
this.serverKeyExchange(new DH_ServerKeyExchange( DH_ServerKeyExchange dhSrvKeyExchange =
new DH_ServerKeyExchange(
input, serverKey, input, serverKey,
clnt_random.random_bytes, svr_random.random_bytes, clnt_random.random_bytes, svr_random.random_bytes,
messageLen, messageLen,
getLocalSupportedSignAlgs(), protocolVersion)); getLocalSupportedSignAlgs(), protocolVersion);
handshakeState.update(dhSrvKeyExchange, resumingSession);
this.serverKeyExchange(dhSrvKeyExchange);
} catch (GeneralSecurityException e) { } catch (GeneralSecurityException e) {
throwSSLException("Server key", e); throwSSLException("Server key", e);
} }
...@@ -278,10 +293,13 @@ final class ClientHandshaker extends Handshaker { ...@@ -278,10 +293,13 @@ final class ClientHandshaker extends Handshaker {
case K_ECDHE_RSA: case K_ECDHE_RSA:
case K_ECDH_ANON: case K_ECDH_ANON:
try { try {
this.serverKeyExchange(new ECDH_ServerKeyExchange ECDH_ServerKeyExchange ecdhSrvKeyExchange =
new ECDH_ServerKeyExchange
(input, serverKey, clnt_random.random_bytes, (input, serverKey, clnt_random.random_bytes,
svr_random.random_bytes, svr_random.random_bytes,
getLocalSupportedSignAlgs(), protocolVersion)); getLocalSupportedSignAlgs(), protocolVersion);
handshakeState.update(ecdhSrvKeyExchange, resumingSession);
this.serverKeyExchange(ecdhSrvKeyExchange);
} catch (GeneralSecurityException e) { } catch (GeneralSecurityException e) {
throwSSLException("Server key", e); throwSSLException("Server key", e);
} }
...@@ -320,6 +338,7 @@ final class ClientHandshaker extends Handshaker { ...@@ -320,6 +338,7 @@ final class ClientHandshaker extends Handshaker {
if (debug != null && Debug.isOn("handshake")) { if (debug != null && Debug.isOn("handshake")) {
certRequest.print(System.out); certRequest.print(System.out);
} }
handshakeState.update(certRequest, resumingSession);
if (protocolVersion.v >= ProtocolVersion.TLS12.v) { if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
Collection<SignatureAndHashAlgorithm> peerSignAlgs = Collection<SignatureAndHashAlgorithm> peerSignAlgs =
...@@ -345,33 +364,23 @@ final class ClientHandshaker extends Handshaker { ...@@ -345,33 +364,23 @@ final class ClientHandshaker extends Handshaker {
break; break;
case HandshakeMessage.ht_server_hello_done: case HandshakeMessage.ht_server_hello_done:
this.serverHelloDone(new ServerHelloDone(input)); ServerHelloDone serverHelloDone = new ServerHelloDone(input);
handshakeState.update(serverHelloDone, resumingSession);
this.serverHelloDone(serverHelloDone);
break; break;
case HandshakeMessage.ht_finished: case HandshakeMessage.ht_finished:
// A ChangeCipherSpec record must have been received prior to Finished serverFinished =
// reception of the Finished message (RFC 5246, 7.4.9). new Finished(protocolVersion, input, cipherSuite);
if (!receivedChangeCipherSpec()) { handshakeState.update(serverFinished, resumingSession);
fatalSE(Alerts.alert_handshake_failure, this.serverFinished(serverFinished);
"Received Finished message before ChangeCipherSpec");
}
this.serverFinished(
new Finished(protocolVersion, input, cipherSuite));
break; break;
default: default:
throw new SSLProtocolException( throw new SSLProtocolException(
"Illegal client handshake msg, " + type); "Illegal client handshake msg, " + type);
} }
//
// Move state machine forward if the message handling
// code didn't already do so
//
if (state < type) {
state = type;
}
} }
/* /*
...@@ -389,7 +398,7 @@ final class ClientHandshaker extends Handshaker { ...@@ -389,7 +398,7 @@ final class ClientHandshaker extends Handshaker {
// Could be (e.g. at connection setup) that we already // Could be (e.g. at connection setup) that we already
// sent the "client hello" but the server's not seen it. // sent the "client hello" but the server's not seen it.
// //
if (state < HandshakeMessage.ht_client_hello) { if (!clientHelloDelivered) {
if (!secureRenegotiation && !allowUnsafeRenegotiation) { if (!secureRenegotiation && !allowUnsafeRenegotiation) {
// renegotiation is not allowed. // renegotiation is not allowed.
if (activeProtocolVersion.v >= ProtocolVersion.TLS10.v) { if (activeProtocolVersion.v >= ProtocolVersion.TLS10.v) {
...@@ -613,7 +622,6 @@ final class ClientHandshaker extends Handshaker { ...@@ -613,7 +622,6 @@ final class ClientHandshaker extends Handshaker {
// looks fine; resume it, and update the state machine. // looks fine; resume it, and update the state machine.
resumingSession = true; resumingSession = true;
state = HandshakeMessage.ht_finished - 1;
calculateConnectionKeys(session.getMasterSecret()); calculateConnectionKeys(session.getMasterSecret());
if (debug != null && Debug.isOn("session")) { if (debug != null && Debug.isOn("session")) {
System.out.println("%% Server resumed " + session); System.out.println("%% Server resumed " + session);
...@@ -904,6 +912,7 @@ final class ClientHandshaker extends Handshaker { ...@@ -904,6 +912,7 @@ final class ClientHandshaker extends Handshaker {
m1.print(System.out); m1.print(System.out);
} }
m1.write(output); m1.write(output);
handshakeState.update(m1, resumingSession);
} }
} }
...@@ -1068,6 +1077,7 @@ final class ClientHandshaker extends Handshaker { ...@@ -1068,6 +1077,7 @@ final class ClientHandshaker extends Handshaker {
} }
m2.write(output); m2.write(output);
handshakeState.update(m2, resumingSession);
/* /*
* THIRD, send a "change_cipher_spec" record followed by the * THIRD, send a "change_cipher_spec" record followed by the
...@@ -1170,6 +1180,7 @@ final class ClientHandshaker extends Handshaker { ...@@ -1170,6 +1180,7 @@ final class ClientHandshaker extends Handshaker {
m3.print(System.out); m3.print(System.out);
} }
m3.write(output); m3.write(output);
handshakeState.update(m3, resumingSession);
output.doHashes(); output.doHashes();
} }
...@@ -1227,6 +1238,8 @@ final class ClientHandshaker extends Handshaker { ...@@ -1227,6 +1238,8 @@ final class ClientHandshaker extends Handshaker {
if (resumingSession) { if (resumingSession) {
input.digestNow(); input.digestNow();
sendChangeCipherAndFinish(true); sendChangeCipherAndFinish(true);
} else {
handshakeFinished = true;
} }
session.setLastAccessedTime(System.currentTimeMillis()); session.setLastAccessedTime(System.currentTimeMillis());
...@@ -1272,13 +1285,6 @@ final class ClientHandshaker extends Handshaker { ...@@ -1272,13 +1285,6 @@ final class ClientHandshaker extends Handshaker {
if (secureRenegotiation) { if (secureRenegotiation) {
clientVerifyData = mesg.getVerifyData(); clientVerifyData = mesg.getVerifyData();
} }
/*
* Update state machine so server MUST send 'finished' next.
* (In "long" handshake case; in short case, we're responding
* to its message.)
*/
state = HandshakeMessage.ht_finished - 1;
} }
......
...@@ -89,6 +89,8 @@ public abstract class HandshakeMessage { ...@@ -89,6 +89,8 @@ public abstract class HandshakeMessage {
static final byte ht_finished = 20; static final byte ht_finished = 20;
static final byte ht_not_applicable = -1; // N/A
/* Class and subclass dynamic debugging support */ /* Class and subclass dynamic debugging support */
public static final Debug debug = Debug.getInstance("ssl"); public static final Debug debug = Debug.getInstance("ssl");
......
...@@ -118,10 +118,14 @@ abstract class Handshaker { ...@@ -118,10 +118,14 @@ abstract class Handshaker {
HandshakeHash handshakeHash; HandshakeHash handshakeHash;
HandshakeInStream input; HandshakeInStream input;
HandshakeOutStream output; HandshakeOutStream output;
int state;
SSLContextImpl sslContext; SSLContextImpl sslContext;
RandomCookie clnt_random, svr_random; RandomCookie clnt_random, svr_random;
SSLSessionImpl session; SSLSessionImpl session;
HandshakeStateManager handshakeState;
boolean clientHelloDelivered;
boolean serverHelloRequested;
boolean handshakeActivated;
boolean handshakeFinished;
// current CipherSuite. Never null, initially SSL_NULL_WITH_NULL_NULL // current CipherSuite. Never null, initially SSL_NULL_WITH_NULL_NULL
CipherSuite cipherSuite; CipherSuite cipherSuite;
...@@ -135,10 +139,6 @@ abstract class Handshaker { ...@@ -135,10 +139,6 @@ abstract class Handshaker {
// True if it's OK to start a new SSL session // True if it's OK to start a new SSL session
boolean enableNewSession; boolean enableNewSession;
// True if session keys have been calculated and the caller may receive
// and process a ChangeCipherSpec message
private boolean sessKeysCalculated;
// Whether local cipher suites preference should be honored during // Whether local cipher suites preference should be honored during
// handshaking? // handshaking?
// //
...@@ -277,9 +277,13 @@ abstract class Handshaker { ...@@ -277,9 +277,13 @@ abstract class Handshaker {
this.secureRenegotiation = secureRenegotiation; this.secureRenegotiation = secureRenegotiation;
this.clientVerifyData = clientVerifyData; this.clientVerifyData = clientVerifyData;
this.serverVerifyData = serverVerifyData; this.serverVerifyData = serverVerifyData;
enableNewSession = true; this.enableNewSession = true;
invalidated = false; this.invalidated = false;
sessKeysCalculated = false; this.handshakeState = new HandshakeStateManager();
this.clientHelloDelivered = false;
this.serverHelloRequested = false;
this.handshakeActivated = false;
this.handshakeFinished = false;
setCipherSuite(CipherSuite.C_NULL); setCipherSuite(CipherSuite.C_NULL);
setEnabledProtocols(enabledProtocols); setEnabledProtocols(enabledProtocols);
...@@ -289,22 +293,6 @@ abstract class Handshaker { ...@@ -289,22 +293,6 @@ abstract class Handshaker {
} else { // engine != null } else { // engine != null
algorithmConstraints = new SSLAlgorithmConstraints(engine, true); algorithmConstraints = new SSLAlgorithmConstraints(engine, true);
} }
//
// In addition to the connection state machine, controlling
// how the connection deals with the different sorts of records
// that get sent (notably handshake transitions!), there's
// also a handshaking state machine that controls message
// sequencing.
//
// It's a convenient artifact of the protocol that this can,
// with only a couple of minor exceptions, be driven by the
// type constant for the last message seen: except for the
// client's cert verify, those constants are in a convenient
// order to drastically simplify state machine checking.
//
state = -2; // initialized but not activated
} }
/* /*
...@@ -386,14 +374,6 @@ abstract class Handshaker { ...@@ -386,14 +374,6 @@ abstract class Handshaker {
} }
} }
final boolean receivedChangeCipherSpec() {
if (conn != null) {
return conn.receivedChangeCipherSpec();
} else {
return engine.receivedChangeCipherSpec();
}
}
String getEndpointIdentificationAlgorithmSE() { String getEndpointIdentificationAlgorithmSE() {
SSLParameters paras; SSLParameters paras;
if (conn != null) { if (conn != null) {
...@@ -573,8 +553,7 @@ abstract class Handshaker { ...@@ -573,8 +553,7 @@ abstract class Handshaker {
engine.outputRecord.setHelloVersion(helloVersion); engine.outputRecord.setHelloVersion(helloVersion);
} }
// move state to activated handshakeActivated = true;
state = -1;
} }
/** /**
...@@ -919,10 +898,9 @@ abstract class Handshaker { ...@@ -919,10 +898,9 @@ abstract class Handshaker {
* this freshly created session can become the current one. * this freshly created session can become the current one.
*/ */
boolean isDone() { boolean isDone() {
return state == HandshakeMessage.ht_finished; return started() && handshakeState.isEmpty() && handshakeFinished;
} }
/* /*
* Returns the session which was created through this * Returns the session which was created through this
* handshake sequence ... should be called after isDone() * handshake sequence ... should be called after isDone()
...@@ -1028,6 +1006,13 @@ abstract class Handshaker { ...@@ -1028,6 +1006,13 @@ abstract class Handshaker {
return; return;
} }
// Set the flags in the message receiving side.
if (messageType == HandshakeMessage.ht_client_hello) {
clientHelloDelivered = true;
} else if (messageType == HandshakeMessage.ht_hello_request) {
serverHelloRequested = true;
}
/* /*
* Process the message. We require * Process the message. We require
* that processMessage() consumes the entire message. In * that processMessage() consumes the entire message. In
...@@ -1062,15 +1047,14 @@ abstract class Handshaker { ...@@ -1062,15 +1047,14 @@ abstract class Handshaker {
* In activated state, the handshaker may not send any messages out. * In activated state, the handshaker may not send any messages out.
*/ */
boolean activated() { boolean activated() {
return state >= -1; return handshakeActivated;
} }
/** /**
* Returns true iff the handshaker has sent any messages. * Returns true iff the handshaker has sent any messages.
*/ */
boolean started() { boolean started() {
return state >= 0; // 0: HandshakeMessage.ht_hello_request return (serverHelloRequested || clientHelloDelivered);
// 1: HandshakeMessage.ht_client_hello
} }
...@@ -1080,11 +1064,13 @@ abstract class Handshaker { ...@@ -1080,11 +1064,13 @@ abstract class Handshaker {
* the subclass returns. NOP if handshaking's already started. * the subclass returns. NOP if handshaking's already started.
*/ */
void kickstart() throws IOException { void kickstart() throws IOException {
if (state >= 0) { if ((isClient && clientHelloDelivered) ||
(!isClient && serverHelloRequested)) {
return; return;
} }
HandshakeMessage m = getKickstartMessage(); HandshakeMessage m = getKickstartMessage();
handshakeState.update(m, resumingSession);
if (debug != null && Debug.isOn("handshake")) { if (debug != null && Debug.isOn("handshake")) {
m.print(System.out); m.print(System.out);
...@@ -1092,7 +1078,14 @@ abstract class Handshaker { ...@@ -1092,7 +1078,14 @@ abstract class Handshaker {
m.write(output); m.write(output);
output.flush(); output.flush();
state = m.messageType(); // Set the flags in the message delivering side.
int handshakeType = m.messageType();
if (handshakeType == HandshakeMessage.ht_hello_request) {
serverHelloRequested = true;
} else { // HandshakeMessage.ht_client_hello
clientHelloDelivered = true;
}
} }
/** /**
...@@ -1124,16 +1117,6 @@ abstract class Handshaker { ...@@ -1124,16 +1117,6 @@ abstract class Handshaker {
output.flush(); // i.e. handshake data output.flush(); // i.e. handshake data
/*
* The write cipher state is protected by the connection write lock
* so we must grab it while making the change. We also
* make sure no writes occur between sending the ChangeCipherSpec
* message, installing the new cipher state, and sending the
* Finished message.
*
* We already hold SSLEngine/SSLSocket "this" by virtue
* of this being called from the readRecord code.
*/
OutputRecord r; OutputRecord r;
if (conn != null) { if (conn != null) {
r = new OutputRecord(Record.ct_change_cipher_spec); r = new OutputRecord(Record.ct_change_cipher_spec);
...@@ -1144,14 +1127,27 @@ abstract class Handshaker { ...@@ -1144,14 +1127,27 @@ abstract class Handshaker {
r.setVersion(protocolVersion); r.setVersion(protocolVersion);
r.write(1); // single byte of data r.write(1); // single byte of data
/*
* The write cipher state is protected by the connection write lock
* so we must grab it while making the change. We also
* make sure no writes occur between sending the ChangeCipherSpec
* message, installing the new cipher state, and sending the
* Finished message.
*
* We already hold SSLEngine/SSLSocket "this" by virtue
* of this being called from the readRecord code.
*/
if (conn != null) { if (conn != null) {
conn.writeLock.lock(); conn.writeLock.lock();
try { try {
handshakeState.changeCipherSpec(false, isClient);
conn.writeRecord(r); conn.writeRecord(r);
conn.changeWriteCiphers(); conn.changeWriteCiphers();
if (debug != null && Debug.isOn("handshake")) { if (debug != null && Debug.isOn("handshake")) {
mesg.print(System.out); mesg.print(System.out);
} }
handshakeState.update(mesg, resumingSession);
mesg.write(output); mesg.write(output);
output.flush(); output.flush();
} finally { } finally {
...@@ -1159,19 +1155,28 @@ abstract class Handshaker { ...@@ -1159,19 +1155,28 @@ abstract class Handshaker {
} }
} else { } else {
synchronized (engine.writeLock) { synchronized (engine.writeLock) {
handshakeState.changeCipherSpec(false, isClient);
engine.writeRecord((EngineOutputRecord)r); engine.writeRecord((EngineOutputRecord)r);
engine.changeWriteCiphers(); engine.changeWriteCiphers();
if (debug != null && Debug.isOn("handshake")) { if (debug != null && Debug.isOn("handshake")) {
mesg.print(System.out); mesg.print(System.out);
} }
mesg.write(output);
handshakeState.update(mesg, resumingSession);
mesg.write(output);
if (lastMessage) { if (lastMessage) {
output.setFinishedMsg(); output.setFinishedMsg();
} }
output.flush(); output.flush();
} }
} }
if (lastMessage) {
handshakeFinished = true;
}
}
void receiveChangeCipherSpec() throws IOException {
handshakeState.changeCipherSpec(true, isClient);
} }
/* /*
...@@ -1353,10 +1358,6 @@ abstract class Handshaker { ...@@ -1353,10 +1358,6 @@ abstract class Handshaker {
throw new ProviderException(e); throw new ProviderException(e);
} }
// Mark a flag that allows outside entities (like SSLSocket/SSLEngine)
// determine if a ChangeCipherSpec message could be processed.
sessKeysCalculated = true;
// //
// Dump the connection keys as they're generated. // Dump the connection keys as they're generated.
// //
...@@ -1411,15 +1412,6 @@ abstract class Handshaker { ...@@ -1411,15 +1412,6 @@ abstract class Handshaker {
} }
} }
/**
* Return whether or not the Handshaker has derived session keys for
* this handshake. This is used for determining readiness to process
* an incoming ChangeCipherSpec message.
*/
boolean sessionKeysCalculated() {
return sessKeysCalculated;
}
private static void printHex(HexDumpEncoder dump, byte[] bytes) { private static void printHex(HexDumpEncoder dump, byte[] bytes) {
if (bytes == null) { if (bytes == null) {
System.out.println("(key bytes not available)"); System.out.println("(key bytes not available)");
......
...@@ -211,11 +211,6 @@ final public class SSLEngineImpl extends SSLEngine { ...@@ -211,11 +211,6 @@ final public class SSLEngineImpl extends SSLEngine {
static final byte clauth_requested = 1; static final byte clauth_requested = 1;
static final byte clauth_required = 2; static final byte clauth_required = 2;
/*
* Flag indicating that the engine has received a ChangeCipherSpec message.
*/
private boolean receivedCCS;
/* /*
* Flag indicating if the next record we receive MUST be a Finished * Flag indicating if the next record we receive MUST be a Finished
* message. Temporarily set during the handshake to ensure that * message. Temporarily set during the handshake to ensure that
...@@ -377,7 +372,6 @@ final public class SSLEngineImpl extends SSLEngine { ...@@ -377,7 +372,6 @@ final public class SSLEngineImpl extends SSLEngine {
*/ */
roleIsServer = true; roleIsServer = true;
connectionState = cs_START; connectionState = cs_START;
receivedCCS = false;
// default server name indication // default server name indication
serverNames = serverNames =
...@@ -525,7 +519,6 @@ final public class SSLEngineImpl extends SSLEngine { ...@@ -525,7 +519,6 @@ final public class SSLEngineImpl extends SSLEngine {
return HandshakeStatus.NEED_UNWRAP; return HandshakeStatus.NEED_UNWRAP;
} // else not handshaking } // else not handshaking
} }
return HandshakeStatus.NOT_HANDSHAKING; return HandshakeStatus.NOT_HANDSHAKING;
} }
} }
...@@ -587,14 +580,6 @@ final public class SSLEngineImpl extends SSLEngine { ...@@ -587,14 +580,6 @@ final public class SSLEngineImpl extends SSLEngine {
* Synchronized on "this" from readRecord. * Synchronized on "this" from readRecord.
*/ */
private void changeReadCiphers() throws SSLException { private void changeReadCiphers() throws SSLException {
if (connectionState != cs_HANDSHAKE
&& connectionState != cs_RENEGOTIATE) {
throw new SSLProtocolException(
"State error, change cipher specs");
}
// ... create decompressor
CipherBox oldCipher = readCipher; CipherBox oldCipher = readCipher;
try { try {
...@@ -780,6 +765,10 @@ final public class SSLEngineImpl extends SSLEngine { ...@@ -780,6 +765,10 @@ final public class SSLEngineImpl extends SSLEngine {
synchronized (unwrapLock) { synchronized (unwrapLock) {
return readNetRecord(ea); return readNetRecord(ea);
} }
} catch (SSLProtocolException spe) {
// may be an unexpected handshake message
fatal(Alerts.alert_unexpected_message, spe.getMessage(), spe);
return null; // make compiler happy
} catch (Exception e) { } catch (Exception e) {
/* /*
* Don't reset position so it looks like we didn't * Don't reset position so it looks like we didn't
...@@ -1004,6 +993,7 @@ final public class SSLEngineImpl extends SSLEngine { ...@@ -1004,6 +993,7 @@ final public class SSLEngineImpl extends SSLEngine {
* session (new keys exchanged) with just this connection * session (new keys exchanged) with just this connection
* in it. * in it.
*/ */
initHandshaker(); initHandshaker();
if (!handshaker.activated()) { if (!handshaker.activated()) {
// prior to handshaking, activate the handshake // prior to handshaking, activate the handshake
...@@ -1027,7 +1017,6 @@ final public class SSLEngineImpl extends SSLEngine { ...@@ -1027,7 +1017,6 @@ final public class SSLEngineImpl extends SSLEngine {
if (handshaker.invalidated) { if (handshaker.invalidated) {
handshaker = null; handshaker = null;
receivedCCS = false;
// if state is cs_RENEGOTIATE, revert it to cs_DATA // if state is cs_RENEGOTIATE, revert it to cs_DATA
if (connectionState == cs_RENEGOTIATE) { if (connectionState == cs_RENEGOTIATE) {
connectionState = cs_DATA; connectionState = cs_DATA;
...@@ -1046,8 +1035,6 @@ final public class SSLEngineImpl extends SSLEngine { ...@@ -1046,8 +1035,6 @@ final public class SSLEngineImpl extends SSLEngine {
} }
handshaker = null; handshaker = null;
connectionState = cs_DATA; connectionState = cs_DATA;
receivedCCS = false;
// No handshakeListeners here. That's a // No handshakeListeners here. That's a
// SSLSocket thing. // SSLSocket thing.
} else if (handshaker.taskOutstanding()) { } else if (handshaker.taskOutstanding()) {
...@@ -1085,14 +1072,11 @@ final public class SSLEngineImpl extends SSLEngine { ...@@ -1085,14 +1072,11 @@ final public class SSLEngineImpl extends SSLEngine {
case Record.ct_change_cipher_spec: case Record.ct_change_cipher_spec:
if ((connectionState != cs_HANDSHAKE if ((connectionState != cs_HANDSHAKE
&& connectionState != cs_RENEGOTIATE) && connectionState != cs_RENEGOTIATE)) {
|| !handshaker.sessionKeysCalculated()
|| receivedCCS) {
// For the CCS message arriving in the wrong state // For the CCS message arriving in the wrong state
fatal(Alerts.alert_unexpected_message, fatal(Alerts.alert_unexpected_message,
"illegal change cipher spec msg, conn state = " "illegal change cipher spec msg, conn state = "
+ connectionState + ", handshake state = " + connectionState);
+ handshaker.state);
} else if (inputRecord.available() != 1 } else if (inputRecord.available() != 1
|| inputRecord.read() != 1) { || inputRecord.read() != 1) {
// For structural/content issues with the CCS // For structural/content issues with the CCS
...@@ -1100,11 +1084,6 @@ final public class SSLEngineImpl extends SSLEngine { ...@@ -1100,11 +1084,6 @@ final public class SSLEngineImpl extends SSLEngine {
"Malformed change cipher spec msg"); "Malformed change cipher spec msg");
} }
// Once we've received CCS, update the flag.
// If the remote endpoint sends it again in this handshake
// we won't process it.
receivedCCS = true;
// //
// The first message after a change_cipher_spec // The first message after a change_cipher_spec
// record MUST be a "Finished" handshake record, // record MUST be a "Finished" handshake record,
...@@ -1112,6 +1091,7 @@ final public class SSLEngineImpl extends SSLEngine { ...@@ -1112,6 +1091,7 @@ final public class SSLEngineImpl extends SSLEngine {
// to be checked by a minor tweak to the state // to be checked by a minor tweak to the state
// machine. // machine.
// //
handshaker.receiveChangeCipherSpec();
changeReadCiphers(); changeReadCiphers();
// next message MUST be a finished message // next message MUST be a finished message
expectingFinished = true; expectingFinished = true;
...@@ -1151,7 +1131,6 @@ final public class SSLEngineImpl extends SSLEngine { ...@@ -1151,7 +1131,6 @@ final public class SSLEngineImpl extends SSLEngine {
} }
} // synchronized (this) } // synchronized (this)
} }
return hsStatus; return hsStatus;
} }
...@@ -1185,6 +1164,10 @@ final public class SSLEngineImpl extends SSLEngine { ...@@ -1185,6 +1164,10 @@ final public class SSLEngineImpl extends SSLEngine {
synchronized (wrapLock) { synchronized (wrapLock) {
return writeAppRecord(ea); return writeAppRecord(ea);
} }
} catch (SSLProtocolException spe) {
// may be an unexpected handshake message
fatal(Alerts.alert_unexpected_message, spe.getMessage(), spe);
return null; // make compiler happy
} catch (Exception e) { } catch (Exception e) {
ea.resetPos(); ea.resetPos();
...@@ -1212,7 +1195,6 @@ final public class SSLEngineImpl extends SSLEngine { ...@@ -1212,7 +1195,6 @@ final public class SSLEngineImpl extends SSLEngine {
* See if the handshaker needs to report back some SSLException. * See if the handshaker needs to report back some SSLException.
*/ */
checkTaskThrown(); checkTaskThrown();
/* /*
* short circuit if we're closed/closing. * short circuit if we're closed/closing.
*/ */
...@@ -1234,7 +1216,6 @@ final public class SSLEngineImpl extends SSLEngine { ...@@ -1234,7 +1216,6 @@ final public class SSLEngineImpl extends SSLEngine {
* without trying to wrap anything. * without trying to wrap anything.
*/ */
hsStatus = getHSStatus(null); hsStatus = getHSStatus(null);
if (hsStatus == HandshakeStatus.NEED_UNWRAP) { if (hsStatus == HandshakeStatus.NEED_UNWRAP) {
return new SSLEngineResult(Status.OK, hsStatus, 0, 0); return new SSLEngineResult(Status.OK, hsStatus, 0, 0);
} }
...@@ -2140,14 +2121,6 @@ final public class SSLEngineImpl extends SSLEngine { ...@@ -2140,14 +2121,6 @@ final public class SSLEngineImpl extends SSLEngine {
} }
} }
/*
* Returns a boolean indicating whether the ChangeCipherSpec message
* has been received for this handshake.
*/
boolean receivedChangeCipherSpec() {
return receivedCCS;
}
/** /**
* Returns a printable representation of this end of the connection. * Returns a printable representation of this end of the connection.
*/ */
......
...@@ -174,12 +174,6 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl { ...@@ -174,12 +174,6 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
*/ */
private volatile int connectionState; private volatile int connectionState;
/*
* Flag indicating that the engine's handshaker has done the necessary
* steps so the engine may process a ChangeCipherSpec message.
*/
private boolean receivedCCS;
/* /*
* Flag indicating if the next record we receive MUST be a Finished * Flag indicating if the next record we receive MUST be a Finished
* message. Temporarily set during the handshake to ensure that * message. Temporarily set during the handshake to ensure that
...@@ -610,7 +604,6 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl { ...@@ -610,7 +604,6 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
*/ */
roleIsServer = isServer; roleIsServer = isServer;
connectionState = cs_START; connectionState = cs_START;
receivedCCS = false;
/* /*
* default read and write side cipher and MAC support * default read and write side cipher and MAC support
...@@ -940,7 +933,6 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl { ...@@ -940,7 +933,6 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
readRecord(r, true); readRecord(r, true);
} }
/* /*
* Clear the pipeline of records from the peer, optionally returning * Clear the pipeline of records from the peer, optionally returning
* application data. Caller is responsible for knowing that it's * application data. Caller is responsible for knowing that it's
...@@ -1074,7 +1066,8 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl { ...@@ -1074,7 +1066,8 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
if (handshaker.invalidated) { if (handshaker.invalidated) {
handshaker = null; handshaker = null;
receivedCCS = false; inrec.setHandshakeHash(null);
// if state is cs_RENEGOTIATE, revert it to cs_DATA // if state is cs_RENEGOTIATE, revert it to cs_DATA
if (connectionState == cs_RENEGOTIATE) { if (connectionState == cs_RENEGOTIATE) {
connectionState = cs_DATA; connectionState = cs_DATA;
...@@ -1090,7 +1083,6 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl { ...@@ -1090,7 +1083,6 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
handshakeSession = null; handshakeSession = null;
handshaker = null; handshaker = null;
connectionState = cs_DATA; connectionState = cs_DATA;
receivedCCS = false;
// //
// Tell folk about handshake completion, but do // Tell folk about handshake completion, but do
...@@ -1137,25 +1129,17 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl { ...@@ -1137,25 +1129,17 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
case Record.ct_change_cipher_spec: case Record.ct_change_cipher_spec:
if ((connectionState != cs_HANDSHAKE if ((connectionState != cs_HANDSHAKE
&& connectionState != cs_RENEGOTIATE) && connectionState != cs_RENEGOTIATE)) {
|| !handshaker.sessionKeysCalculated()
|| receivedCCS) {
// For the CCS message arriving in the wrong state // For the CCS message arriving in the wrong state
fatal(Alerts.alert_unexpected_message, fatal(Alerts.alert_unexpected_message,
"illegal change cipher spec msg, conn state = " "illegal change cipher spec msg, conn state = "
+ connectionState + ", handshake state = " + connectionState);
+ handshaker.state);
} else if (r.available() != 1 || r.read() != 1) { } else if (r.available() != 1 || r.read() != 1) {
// For structural/content issues with the CCS // For structural/content issues with the CCS
fatal(Alerts.alert_unexpected_message, fatal(Alerts.alert_unexpected_message,
"Malformed change cipher spec msg"); "Malformed change cipher spec msg");
} }
// Once we've received CCS, update the flag.
// If the remote endpoint sends it again in this handshake
// we won't process it.
receivedCCS = true;
// //
// The first message after a change_cipher_spec // The first message after a change_cipher_spec
// record MUST be a "Finished" handshake record, // record MUST be a "Finished" handshake record,
...@@ -1163,6 +1147,7 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl { ...@@ -1163,6 +1147,7 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
// to be checked by a minor tweak to the state // to be checked by a minor tweak to the state
// machine. // machine.
// //
handshaker.receiveChangeCipherSpec();
changeReadCiphers(); changeReadCiphers();
// next message MUST be a finished message // next message MUST be a finished message
expectingFinished = true; expectingFinished = true;
...@@ -1361,13 +1346,10 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl { ...@@ -1361,13 +1346,10 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
kickstartHandshake(); kickstartHandshake();
/* /*
* All initial handshaking goes through this * All initial handshaking goes through this operation
* InputRecord until we have a valid SSL connection. * until we have a valid SSL connection.
* Once initial handshaking is finished, AppInputStream's
* InputRecord can handle any future renegotiation.
* *
* Keep this local so that it goes out of scope and is * Handle handshake messages only, need no application data.
* eventually GC'd.
*/ */
if (inrec == null) { if (inrec == null) {
inrec = new InputRecord(); inrec = new InputRecord();
...@@ -2666,14 +2648,6 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl { ...@@ -2666,14 +2648,6 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
} }
} }
/*
* Returns a boolean indicating whether the ChangeCipherSpec message
* has been received for this handshake.
*/
boolean receivedChangeCipherSpec() {
return receivedCCS;
}
// //
// We allocate a separate thread to deliver handshake completion // We allocate a separate thread to deliver handshake completion
// events. This ensures that the notifications don't block the // events. This ensures that the notifications don't block the
......
...@@ -207,21 +207,14 @@ final class ServerHandshaker extends Handshaker { ...@@ -207,21 +207,14 @@ final class ServerHandshaker extends Handshaker {
@Override @Override
void processMessage(byte type, int message_len) void processMessage(byte type, int message_len)
throws IOException { throws IOException {
//
// In SSLv3 and TLS, messages follow strictly increasing // check the handshake state
// numerical order _except_ for one annoying special case. handshakeState.check(type);
//
if ((state >= type)
&& (state != HandshakeMessage.ht_client_key_exchange
&& type != HandshakeMessage.ht_certificate_verify)) {
throw new SSLProtocolException(
"Handshake message sequence violation, state = " + state
+ ", type = " + type);
}
switch (type) { switch (type) {
case HandshakeMessage.ht_client_hello: case HandshakeMessage.ht_client_hello:
ClientHello ch = new ClientHello(input, message_len); ClientHello ch = new ClientHello(input, message_len);
handshakeState.update(ch, resumingSession);
/* /*
* send it off for processing. * send it off for processing.
*/ */
...@@ -234,7 +227,9 @@ final class ServerHandshaker extends Handshaker { ...@@ -234,7 +227,9 @@ final class ServerHandshaker extends Handshaker {
"client sent unsolicited cert chain"); "client sent unsolicited cert chain");
// NOTREACHED // NOTREACHED
} }
this.clientCertificate(new CertificateMsg(input)); CertificateMsg certificateMsg = new CertificateMsg(input);
handshakeState.update(certificateMsg, resumingSession);
this.clientCertificate(certificateMsg);
break; break;
case HandshakeMessage.ht_client_key_exchange: case HandshakeMessage.ht_client_key_exchange:
...@@ -252,17 +247,20 @@ final class ServerHandshaker extends Handshaker { ...@@ -252,17 +247,20 @@ final class ServerHandshaker extends Handshaker {
protocolVersion, clientRequestedVersion, protocolVersion, clientRequestedVersion,
sslContext.getSecureRandom(), input, sslContext.getSecureRandom(), input,
message_len, privateKey); message_len, privateKey);
handshakeState.update(pms, resumingSession);
preMasterSecret = this.clientKeyExchange(pms); preMasterSecret = this.clientKeyExchange(pms);
break; break;
case K_KRB5: case K_KRB5:
case K_KRB5_EXPORT: case K_KRB5_EXPORT:
preMasterSecret = this.clientKeyExchange( KerberosClientKeyExchange kke =
new KerberosClientKeyExchange(protocolVersion, new KerberosClientKeyExchange(protocolVersion,
clientRequestedVersion, clientRequestedVersion,
sslContext.getSecureRandom(), sslContext.getSecureRandom(),
input, input,
this.getAccSE(), this.getAccSE(),
serviceCreds)); serviceCreds);
handshakeState.update(kke, resumingSession);
preMasterSecret = this.clientKeyExchange(kke);
break; break;
case K_DHE_RSA: case K_DHE_RSA:
case K_DHE_DSS: case K_DHE_DSS:
...@@ -273,16 +271,19 @@ final class ServerHandshaker extends Handshaker { ...@@ -273,16 +271,19 @@ final class ServerHandshaker extends Handshaker {
* protocol difference in these five flavors is in how * protocol difference in these five flavors is in how
* the ServerKeyExchange message was constructed! * the ServerKeyExchange message was constructed!
*/ */
preMasterSecret = this.clientKeyExchange( DHClientKeyExchange dhcke = new DHClientKeyExchange(input);
new DHClientKeyExchange(input)); handshakeState.update(dhcke, resumingSession);
preMasterSecret = this.clientKeyExchange(dhcke);
break; break;
case K_ECDH_RSA: case K_ECDH_RSA:
case K_ECDH_ECDSA: case K_ECDH_ECDSA:
case K_ECDHE_RSA: case K_ECDHE_RSA:
case K_ECDHE_ECDSA: case K_ECDHE_ECDSA:
case K_ECDH_ANON: case K_ECDH_ANON:
preMasterSecret = this.clientKeyExchange ECDHClientKeyExchange ecdhcke =
(new ECDHClientKeyExchange(input)); new ECDHClientKeyExchange(input);
handshakeState.update(ecdhcke, resumingSession);
preMasterSecret = this.clientKeyExchange(ecdhcke);
break; break;
default: default:
throw new SSLProtocolException throw new SSLProtocolException
...@@ -302,38 +303,24 @@ final class ServerHandshaker extends Handshaker { ...@@ -302,38 +303,24 @@ final class ServerHandshaker extends Handshaker {
break; break;
case HandshakeMessage.ht_certificate_verify: case HandshakeMessage.ht_certificate_verify:
this.clientCertificateVerify(new CertificateVerify(input, CertificateVerify cvm =
getLocalSupportedSignAlgs(), protocolVersion)); new CertificateVerify(input,
getLocalSupportedSignAlgs(), protocolVersion);
handshakeState.update(cvm, resumingSession);
this.clientCertificateVerify(cvm);
break; break;
case HandshakeMessage.ht_finished: case HandshakeMessage.ht_finished:
// A ChangeCipherSpec record must have been received prior to Finished cfm =
// reception of the Finished message (RFC 5246, 7.4.9). new Finished(protocolVersion, input, cipherSuite);
if (!receivedChangeCipherSpec()) { handshakeState.update(cfm, resumingSession);
fatalSE(Alerts.alert_handshake_failure, this.clientFinished(cfm);
"Received Finished message before ChangeCipherSpec");
}
this.clientFinished(
new Finished(protocolVersion, input, cipherSuite));
break; break;
default: default:
throw new SSLProtocolException( throw new SSLProtocolException(
"Illegal server handshake msg, " + type); "Illegal server handshake msg, " + type);
} }
//
// Move state machine forward if the message handling
// code didn't already do so
//
if (state < type) {
if(type == HandshakeMessage.ht_certificate_verify) {
state = type + 2; // an annoying special case
} else {
state = type;
}
}
} }
...@@ -364,7 +351,7 @@ final class ServerHandshaker extends Handshaker { ...@@ -364,7 +351,7 @@ final class ServerHandshaker extends Handshaker {
// //
// This will not have any impact on server initiated renegotiation. // This will not have any impact on server initiated renegotiation.
if (rejectClientInitiatedRenego && !isInitialHandshake && if (rejectClientInitiatedRenego && !isInitialHandshake &&
state != HandshakeMessage.ht_hello_request) { !serverHelloRequested) {
fatalSE(Alerts.alert_handshake_failure, fatalSE(Alerts.alert_handshake_failure,
"Client initiated renegotiation is not allowed"); "Client initiated renegotiation is not allowed");
} }
...@@ -876,6 +863,7 @@ final class ServerHandshaker extends Handshaker { ...@@ -876,6 +863,7 @@ final class ServerHandshaker extends Handshaker {
System.out.println("Cipher suite: " + session.getSuite()); System.out.println("Cipher suite: " + session.getSuite());
} }
m1.write(output); m1.write(output);
handshakeState.update(m1, resumingSession);
// //
// If we are resuming a session, we finish writing handshake // If we are resuming a session, we finish writing handshake
...@@ -915,6 +903,7 @@ final class ServerHandshaker extends Handshaker { ...@@ -915,6 +903,7 @@ final class ServerHandshaker extends Handshaker {
m2.print(System.out); m2.print(System.out);
} }
m2.write(output); m2.write(output);
handshakeState.update(m2, resumingSession);
// XXX has some side effects with OS TCP buffering, // XXX has some side effects with OS TCP buffering,
// leave it out for now // leave it out for now
...@@ -1010,6 +999,7 @@ final class ServerHandshaker extends Handshaker { ...@@ -1010,6 +999,7 @@ final class ServerHandshaker extends Handshaker {
m3.print(System.out); m3.print(System.out);
} }
m3.write(output); m3.write(output);
handshakeState.update(m3, resumingSession);
} }
// //
...@@ -1059,6 +1049,7 @@ final class ServerHandshaker extends Handshaker { ...@@ -1059,6 +1049,7 @@ final class ServerHandshaker extends Handshaker {
m4.print(System.out); m4.print(System.out);
} }
m4.write(output); m4.write(output);
handshakeState.update(m4, resumingSession);
} }
/* /*
...@@ -1070,6 +1061,7 @@ final class ServerHandshaker extends Handshaker { ...@@ -1070,6 +1061,7 @@ final class ServerHandshaker extends Handshaker {
m5.print(System.out); m5.print(System.out);
} }
m5.write(output); m5.write(output);
handshakeState.update(m5, resumingSession);
/* /*
* Flush any buffered messages so the client will see them. * Flush any buffered messages so the client will see them.
...@@ -1817,6 +1809,8 @@ final class ServerHandshaker extends Handshaker { ...@@ -1817,6 +1809,8 @@ final class ServerHandshaker extends Handshaker {
if (!resumingSession) { if (!resumingSession) {
input.digestNow(); input.digestNow();
sendChangeCipherAndFinish(true); sendChangeCipherAndFinish(true);
} else {
handshakeFinished = true;
} }
/* /*
...@@ -1864,16 +1858,6 @@ final class ServerHandshaker extends Handshaker { ...@@ -1864,16 +1858,6 @@ final class ServerHandshaker extends Handshaker {
if (secureRenegotiation) { if (secureRenegotiation) {
serverVerifyData = mesg.getVerifyData(); serverVerifyData = mesg.getVerifyData();
} }
/*
* Update state machine so client MUST send 'finished' next
* The update should only take place if it is not in the fast
* handshake mode since the server has to wait for a finished
* message from the client.
*/
if (finishedTag) {
state = HandshakeMessage.ht_finished;
}
} }
......
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
/* /*
* @test * @test
* @bug 8044860 * @bug 8044860 8074462
* @summary Vectors and fixed length fields should be verified * @summary Vectors and fixed length fields should be verified
* for allowed sizes. * for allowed sizes.
* @run main/othervm LengthCheckTest * @run main/othervm LengthCheckTest
...@@ -231,7 +231,7 @@ public class LengthCheckTest { ...@@ -231,7 +231,7 @@ public class LengthCheckTest {
// sent back to the server. // sent back to the server.
if (gotException == false || if (gotException == false ||
!isTlsMessage(cTOs, TLS_RECTYPE_ALERT, TLS_ALERT_LVL_FATAL, !isTlsMessage(cTOs, TLS_RECTYPE_ALERT, TLS_ALERT_LVL_FATAL,
TLS_ALERT_INTERNAL_ERROR)) { TLS_ALERT_UNEXPECTED_MSG)) {
throw new SSLException( throw new SSLException(
"Client failed to throw Alert:fatal:internal_error"); "Client failed to throw Alert:fatal:internal_error");
} }
...@@ -283,7 +283,7 @@ public class LengthCheckTest { ...@@ -283,7 +283,7 @@ public class LengthCheckTest {
// sent back to the client. // sent back to the client.
if (gotException == false || if (gotException == false ||
!isTlsMessage(sTOc, TLS_RECTYPE_ALERT, TLS_ALERT_LVL_FATAL, !isTlsMessage(sTOc, TLS_RECTYPE_ALERT, TLS_ALERT_LVL_FATAL,
TLS_ALERT_INTERNAL_ERROR)) { TLS_ALERT_UNEXPECTED_MSG)) {
throw new SSLException( throw new SSLException(
"Server failed to throw Alert:fatal:internal_error"); "Server failed to throw Alert:fatal:internal_error");
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册