|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
|
|
package sun.security.ssl; |
|
|
|
import java.io.IOException; |
|
import java.nio.ByteBuffer; |
|
import java.text.MessageFormat; |
|
import java.util.Locale; |
|
import sun.security.ssl.SSLHandshake.HandshakeMessage; |
|
|
|
|
|
|
|
*/ |
|
final class EncryptedExtensions { |
|
static final HandshakeProducer handshakeProducer = |
|
new EncryptedExtensionsProducer(); |
|
static final SSLConsumer handshakeConsumer = |
|
new EncryptedExtensionsConsumer(); |
|
|
|
|
|
|
|
*/ |
|
static final class EncryptedExtensionsMessage extends HandshakeMessage { |
|
private final SSLExtensions extensions; |
|
|
|
EncryptedExtensionsMessage( |
|
HandshakeContext handshakeContext) throws IOException { |
|
super(handshakeContext); |
|
this.extensions = new SSLExtensions(this); |
|
} |
|
|
|
EncryptedExtensionsMessage(HandshakeContext handshakeContext, |
|
ByteBuffer m) throws IOException { |
|
super(handshakeContext); |
|
|
|
// struct { |
|
// Extension extensions<0..2^16-1>; |
|
|
|
if (m.remaining() < 2) { |
|
throw handshakeContext.conContext.fatal(Alert.ILLEGAL_PARAMETER, |
|
"Invalid EncryptedExtensions handshake message: " + |
|
"no sufficient data"); |
|
} |
|
|
|
SSLExtension[] encryptedExtensions = |
|
handshakeContext.sslConfig.getEnabledExtensions( |
|
SSLHandshake.ENCRYPTED_EXTENSIONS); |
|
this.extensions = new SSLExtensions(this, m, encryptedExtensions); |
|
} |
|
|
|
@Override |
|
SSLHandshake handshakeType() { |
|
return SSLHandshake.ENCRYPTED_EXTENSIONS; |
|
} |
|
|
|
@Override |
|
int messageLength() { |
|
int extLen = extensions.length(); |
|
if (extLen == 0) { |
|
extLen = 2; |
|
} |
|
return extLen; |
|
} |
|
|
|
@Override |
|
void send(HandshakeOutStream hos) throws IOException { |
|
|
|
if (extensions.length() == 0) { |
|
hos.putInt16(0); |
|
} else { |
|
extensions.send(hos); |
|
} |
|
} |
|
|
|
@Override |
|
public String toString() { |
|
MessageFormat messageFormat = new MessageFormat( |
|
"\"EncryptedExtensions\": [\n" + |
|
"{0}\n" + |
|
"]", |
|
Locale.ENGLISH); |
|
Object[] messageFields = { |
|
Utilities.indent(extensions.toString()) |
|
}; |
|
|
|
return messageFormat.format(messageFields); |
|
} |
|
} |
|
|
|
|
|
|
|
*/ |
|
private static final class EncryptedExtensionsProducer |
|
implements HandshakeProducer { |
|
|
|
private EncryptedExtensionsProducer() { |
|
// blank |
|
} |
|
|
|
@Override |
|
public byte[] produce(ConnectionContext context, |
|
HandshakeMessage message) throws IOException { |
|
|
|
ServerHandshakeContext shc = (ServerHandshakeContext)context; |
|
|
|
EncryptedExtensionsMessage eem = |
|
new EncryptedExtensionsMessage(shc); |
|
SSLExtension[] extTypes = |
|
shc.sslConfig.getEnabledExtensions( |
|
SSLHandshake.ENCRYPTED_EXTENSIONS, |
|
shc.negotiatedProtocol); |
|
eem.extensions.produce(shc, extTypes); |
|
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { |
|
SSLLogger.fine("Produced EncryptedExtensions message", eem); |
|
} |
|
|
|
|
|
eem.write(shc.handshakeOutput); |
|
shc.handshakeOutput.flush(); |
|
|
|
|
|
return null; |
|
} |
|
} |
|
|
|
|
|
|
|
*/ |
|
private static final class EncryptedExtensionsConsumer |
|
implements SSLConsumer { |
|
|
|
private EncryptedExtensionsConsumer() { |
|
// blank |
|
} |
|
|
|
@Override |
|
public void consume(ConnectionContext context, |
|
ByteBuffer message) throws IOException { |
|
|
|
ClientHandshakeContext chc = (ClientHandshakeContext)context; |
|
|
|
|
|
chc.handshakeConsumers.remove(SSLHandshake.ENCRYPTED_EXTENSIONS.id); |
|
|
|
EncryptedExtensionsMessage eem = |
|
new EncryptedExtensionsMessage(chc, message); |
|
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { |
|
SSLLogger.fine( |
|
"Consuming EncryptedExtensions handshake message", eem); |
|
} |
|
|
|
// |
|
// validate |
|
|
|
SSLExtension[] extTypes = chc.sslConfig.getEnabledExtensions( |
|
SSLHandshake.ENCRYPTED_EXTENSIONS); |
|
eem.extensions.consumeOnLoad(chc, extTypes); |
|
|
|
// |
|
// update |
|
|
|
eem.extensions.consumeOnTrade(chc, extTypes); |
|
|
|
// |
|
// produce |
|
// |
|
// Need no new handshake message producers here. |
|
} |
|
} |
|
} |