|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
|
|
package sun.security.ssl; |
|
|
|
import java.io.IOException; |
|
import java.nio.ByteBuffer; |
|
import sun.security.ssl.SSLHandshake.HandshakeMessage; |
|
|
|
|
|
|
|
*/ |
|
final class ServerHelloDone { |
|
static final SSLConsumer handshakeConsumer = |
|
new ServerHelloDoneConsumer(); |
|
static final HandshakeProducer handshakeProducer = |
|
new ServerHelloDoneProducer(); |
|
|
|
|
|
|
|
*/ |
|
static final class ServerHelloDoneMessage extends HandshakeMessage { |
|
ServerHelloDoneMessage(HandshakeContext handshakeContext) { |
|
super(handshakeContext); |
|
} |
|
|
|
ServerHelloDoneMessage(HandshakeContext handshakeContext, |
|
ByteBuffer m) throws IOException { |
|
super(handshakeContext); |
|
if (m.hasRemaining()) { |
|
throw handshakeContext.conContext.fatal(Alert.ILLEGAL_PARAMETER, |
|
"Error parsing ServerHelloDone message: not empty"); |
|
} |
|
} |
|
|
|
@Override |
|
public SSLHandshake handshakeType() { |
|
return SSLHandshake.SERVER_HELLO_DONE; |
|
} |
|
|
|
@Override |
|
public int messageLength() { |
|
return 0; |
|
} |
|
|
|
@Override |
|
public void send(HandshakeOutStream s) throws IOException { |
|
// empty, nothing to send |
|
} |
|
|
|
@Override |
|
public String toString() { |
|
return "<empty>"; |
|
} |
|
} |
|
|
|
|
|
|
|
*/ |
|
private static final |
|
class ServerHelloDoneProducer implements HandshakeProducer { |
|
|
|
private ServerHelloDoneProducer() { |
|
// blank |
|
} |
|
|
|
@Override |
|
public byte[] produce(ConnectionContext context, |
|
HandshakeMessage message) throws IOException { |
|
|
|
ServerHandshakeContext shc = (ServerHandshakeContext)context; |
|
|
|
ServerHelloDoneMessage shdm = new ServerHelloDoneMessage(shc); |
|
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { |
|
SSLLogger.fine( |
|
"Produced ServerHelloDone handshake message", shdm); |
|
} |
|
|
|
|
|
shdm.write(shc.handshakeOutput); |
|
shc.handshakeOutput.flush(); |
|
|
|
// |
|
// update |
|
|
|
shc.handshakeConsumers.put(SSLHandshake.CLIENT_KEY_EXCHANGE.id, |
|
SSLHandshake.CLIENT_KEY_EXCHANGE); |
|
shc.conContext.consumers.put(ContentType.CHANGE_CIPHER_SPEC.id, |
|
ChangeCipherSpec.t10Consumer); |
|
shc.handshakeConsumers.put(SSLHandshake.FINISHED.id, |
|
SSLHandshake.FINISHED); |
|
|
|
|
|
return null; |
|
} |
|
} |
|
|
|
|
|
|
|
*/ |
|
private static final |
|
class ServerHelloDoneConsumer implements SSLConsumer { |
|
|
|
private ServerHelloDoneConsumer() { |
|
// blank |
|
} |
|
|
|
@Override |
|
public void consume(ConnectionContext context, |
|
ByteBuffer message) throws IOException { |
|
|
|
ClientHandshakeContext chc = (ClientHandshakeContext)context; |
|
|
|
SSLConsumer certStatCons = chc.handshakeConsumers.remove( |
|
SSLHandshake.CERTIFICATE_STATUS.id); |
|
if (certStatCons != null) { |
|
// Stapling was active but no certificate status message |
|
// was sent. We need to run the absence handler which will |
|
|
|
CertificateStatus.handshakeAbsence.absent(context, null); |
|
} |
|
|
|
|
|
chc.handshakeConsumers.clear(); |
|
|
|
ServerHelloDoneMessage shdm = |
|
new ServerHelloDoneMessage(chc, message); |
|
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { |
|
SSLLogger.fine( |
|
"Consuming ServerHelloDone handshake message", shdm); |
|
} |
|
|
|
// |
|
// validate |
|
// |
|
// blank |
|
|
|
// |
|
// update |
|
|
|
chc.handshakeProducers.put(SSLHandshake.CLIENT_KEY_EXCHANGE.id, |
|
SSLHandshake.CLIENT_KEY_EXCHANGE); |
|
chc.handshakeProducers.put(SSLHandshake.FINISHED.id, |
|
SSLHandshake.FINISHED); |
|
// |
|
// produce |
|
|
|
SSLHandshake[] probableHandshakeMessages = new SSLHandshake[] { |
|
|
|
SSLHandshake.CERTIFICATE, |
|
SSLHandshake.CLIENT_KEY_EXCHANGE, |
|
SSLHandshake.CERTIFICATE_VERIFY, |
|
SSLHandshake.FINISHED |
|
}; |
|
|
|
for (SSLHandshake hs : probableHandshakeMessages) { |
|
HandshakeProducer handshakeProducer = |
|
chc.handshakeProducers.remove(hs.id); |
|
if (handshakeProducer != null) { |
|
handshakeProducer.produce(context, null); |
|
} |
|
} |
|
} |
|
} |
|
} |