package sun.security.ssl;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.text.MessageFormat;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList;
import java.util.Locale;
import sun.security.ssl.SSLHandshake.HandshakeMessage;
import sun.misc.HexDumpEncoder;
enum SSLExtension implements SSLStringizer {
CH_SERVER_NAME (0x0000, "server_name",
SSLHandshake.CLIENT_HELLO,
ProtocolVersion.PROTOCOLS_TO_13,
ServerNameExtension.chNetworkProducer,
ServerNameExtension.chOnLoadConsumer,
null,
null,
null,
ServerNameExtension.chStringizer),
SH_SERVER_NAME (0x0000, "server_name",
SSLHandshake.SERVER_HELLO,
ProtocolVersion.PROTOCOLS_TO_12,
ServerNameExtension.shNetworkProducer,
ServerNameExtension.shOnLoadConsumer,
null,
null,
null,
ServerNameExtension.shStringizer),
EE_SERVER_NAME (0x0000, "server_name",
SSLHandshake.ENCRYPTED_EXTENSIONS,
ProtocolVersion.PROTOCOLS_OF_13,
ServerNameExtension.eeNetworkProducer,
ServerNameExtension.eeOnLoadConsumer,
null,
null,
null,
ServerNameExtension.shStringizer),
CH_MAX_FRAGMENT_LENGTH (0x0001, "max_fragment_length",
SSLHandshake.CLIENT_HELLO,
ProtocolVersion.PROTOCOLS_TO_13,
MaxFragExtension.chNetworkProducer,
MaxFragExtension.chOnLoadConsumer,
null,
null,
null,
MaxFragExtension.maxFragLenStringizer),
SH_MAX_FRAGMENT_LENGTH (0x0001, "max_fragment_length",
SSLHandshake.SERVER_HELLO,
ProtocolVersion.PROTOCOLS_TO_12,
MaxFragExtension.shNetworkProducer,
MaxFragExtension.shOnLoadConsumer,
null,
MaxFragExtension.shOnTradeConsumer,
null,
MaxFragExtension.maxFragLenStringizer),
EE_MAX_FRAGMENT_LENGTH (0x0001, "max_fragment_length",
SSLHandshake.ENCRYPTED_EXTENSIONS,
ProtocolVersion.PROTOCOLS_OF_13,
MaxFragExtension.eeNetworkProducer,
MaxFragExtension.eeOnLoadConsumer,
null,
MaxFragExtension.eeOnTradeConsumer,
null,
MaxFragExtension.maxFragLenStringizer),
CLIENT_CERTIFICATE_URL (0x0002, "client_certificate_url"),
TRUSTED_CA_KEYS (0x0003, "trusted_ca_keys"),
TRUNCATED_HMAC (0x0004, "truncated_hmac"),
CH_STATUS_REQUEST (0x0005, "status_request",
SSLHandshake.CLIENT_HELLO,
ProtocolVersion.PROTOCOLS_TO_13,
CertStatusExtension.chNetworkProducer,
CertStatusExtension.chOnLoadConsumer,
null,
null,
null,
CertStatusExtension.certStatusReqStringizer),
SH_STATUS_REQUEST (0x0005, "status_request",
SSLHandshake.SERVER_HELLO,
ProtocolVersion.PROTOCOLS_TO_12,
CertStatusExtension.shNetworkProducer,
CertStatusExtension.shOnLoadConsumer,
null,
null,
null,
CertStatusExtension.certStatusReqStringizer),
CR_STATUS_REQUEST (0x0005, "status_request"),
CT_STATUS_REQUEST (0x0005, "status_request",
SSLHandshake.CERTIFICATE,
ProtocolVersion.PROTOCOLS_OF_13,
CertStatusExtension.ctNetworkProducer,
CertStatusExtension.ctOnLoadConsumer,
null,
null,
null,
CertStatusExtension.certStatusRespStringizer),
USER_MAPPING (0x0006, "user_mapping"),
CLIENT_AUTHZ (0x0007, "client_authz"),
SERVER_AUTHZ (0x0008, "server_authz"),
CERT_TYPE (0x0009, "cert_type"),
CH_SUPPORTED_GROUPS (0x000A, "supported_groups",
SSLHandshake.CLIENT_HELLO,
ProtocolVersion.PROTOCOLS_TO_13,
SupportedGroupsExtension.chNetworkProducer,
SupportedGroupsExtension.chOnLoadConsumer,
null,
null,
null,
SupportedGroupsExtension.sgsStringizer),
EE_SUPPORTED_GROUPS (0x000A, "supported_groups",
SSLHandshake.ENCRYPTED_EXTENSIONS,
ProtocolVersion.PROTOCOLS_OF_13,
SupportedGroupsExtension.eeNetworkProducer,
SupportedGroupsExtension.eeOnLoadConsumer,
null,
null,
null,
SupportedGroupsExtension.sgsStringizer),
CH_EC_POINT_FORMATS (0x000B, "ec_point_formats",
SSLHandshake.CLIENT_HELLO,
ProtocolVersion.PROTOCOLS_TO_12,
ECPointFormatsExtension.chNetworkProducer,
ECPointFormatsExtension.chOnLoadConsumer,
null,
null,
null,
ECPointFormatsExtension.epfStringizer),
SH_EC_POINT_FORMATS (0x000B, "ec_point_formats",
SSLHandshake.SERVER_HELLO,
ProtocolVersion.PROTOCOLS_TO_12,
null,
ECPointFormatsExtension.shOnLoadConsumer,
null,
null,
null,
ECPointFormatsExtension.epfStringizer),
SRP (0x000C, "srp"),
CH_SIGNATURE_ALGORITHMS (0x000D, "signature_algorithms",
SSLHandshake.CLIENT_HELLO,
ProtocolVersion.PROTOCOLS_12_13,
SignatureAlgorithmsExtension.chNetworkProducer,
SignatureAlgorithmsExtension.chOnLoadConsumer,
SignatureAlgorithmsExtension.chOnLoadAbsence,
SignatureAlgorithmsExtension.chOnTradeConsumer,
SignatureAlgorithmsExtension.chOnTradeAbsence,
SignatureAlgorithmsExtension.ssStringizer),
CR_SIGNATURE_ALGORITHMS (0x000D, "signature_algorithms",
SSLHandshake.CERTIFICATE_REQUEST,
ProtocolVersion.PROTOCOLS_OF_13,
SignatureAlgorithmsExtension.crNetworkProducer,
SignatureAlgorithmsExtension.crOnLoadConsumer,
SignatureAlgorithmsExtension.crOnLoadAbsence,
SignatureAlgorithmsExtension.crOnTradeConsumer,
null,
SignatureAlgorithmsExtension.ssStringizer),
CH_SIGNATURE_ALGORITHMS_CERT (0x0032, "signature_algorithms_cert",
SSLHandshake.CLIENT_HELLO,
ProtocolVersion.PROTOCOLS_12_13,
CertSignAlgsExtension.chNetworkProducer,
CertSignAlgsExtension.chOnLoadConsumer,
null,
CertSignAlgsExtension.chOnTradeConsumer,
null,
CertSignAlgsExtension.ssStringizer),
CR_SIGNATURE_ALGORITHMS_CERT (0x0032, "signature_algorithms_cert",
SSLHandshake.CERTIFICATE_REQUEST,
ProtocolVersion.PROTOCOLS_OF_13,
CertSignAlgsExtension.crNetworkProducer,
CertSignAlgsExtension.crOnLoadConsumer,
null,
CertSignAlgsExtension.crOnTradeConsumer,
null,
CertSignAlgsExtension.ssStringizer),
USE_SRTP (0x000E, "use_srtp"),
HEARTBEAT (0x000E, "heartbeat"),
CH_ALPN (0x0010, "application_layer_protocol_negotiation",
SSLHandshake.CLIENT_HELLO,
ProtocolVersion.PROTOCOLS_TO_13,
AlpnExtension.chNetworkProducer,
AlpnExtension.chOnLoadConsumer,
AlpnExtension.chOnLoadAbsence,
null,
null,
AlpnExtension.alpnStringizer),
SH_ALPN (0x0010, "application_layer_protocol_negotiation",
SSLHandshake.SERVER_HELLO,
ProtocolVersion.PROTOCOLS_TO_12,
AlpnExtension.shNetworkProducer,
AlpnExtension.shOnLoadConsumer,
AlpnExtension.shOnLoadAbsence,
null,
null,
AlpnExtension.alpnStringizer),
EE_ALPN (0x0010, "application_layer_protocol_negotiation",
SSLHandshake.ENCRYPTED_EXTENSIONS,
ProtocolVersion.PROTOCOLS_OF_13,
AlpnExtension.shNetworkProducer,
AlpnExtension.shOnLoadConsumer,
AlpnExtension.shOnLoadAbsence,
null,
null,
AlpnExtension.alpnStringizer),
CH_STATUS_REQUEST_V2 (0x0011, "status_request_v2",
SSLHandshake.CLIENT_HELLO,
ProtocolVersion.PROTOCOLS_TO_12,
CertStatusExtension.chV2NetworkProducer,
CertStatusExtension.chV2OnLoadConsumer,
null,
null,
null,
CertStatusExtension.certStatusReqV2Stringizer),
SH_STATUS_REQUEST_V2 (0x0011, "status_request_v2",
SSLHandshake.SERVER_HELLO,
ProtocolVersion.PROTOCOLS_TO_12,
CertStatusExtension.shV2NetworkProducer,
CertStatusExtension.shV2OnLoadConsumer,
null,
null,
null,
CertStatusExtension.certStatusReqV2Stringizer),
SIGNED_CERT_TIMESTAMP (0x0012, "signed_certificate_timestamp"),
CLIENT_CERT_TYPE (0x0013, "padding"),
SERVER_CERT_TYPE (0x0014, "server_certificate_type"),
PADDING (0x0015, "client_certificate_type"),
ENCRYPT_THEN_MAC (0x0016, "encrypt_then_mac"),
CH_EXTENDED_MASTER_SECRET (0x0017, "extended_master_secret",
SSLHandshake.CLIENT_HELLO,
ProtocolVersion.PROTOCOLS_TO_12,
ExtendedMasterSecretExtension.chNetworkProducer,
ExtendedMasterSecretExtension.chOnLoadConsumer,
ExtendedMasterSecretExtension.chOnLoadAbsence,
null,
null,
ExtendedMasterSecretExtension.emsStringizer),
SH_EXTENDED_MASTER_SECRET (0x0017, "extended_master_secret",
SSLHandshake.SERVER_HELLO,
ProtocolVersion.PROTOCOLS_TO_12,
ExtendedMasterSecretExtension.shNetworkProducer,
ExtendedMasterSecretExtension.shOnLoadConsumer,
ExtendedMasterSecretExtension.shOnLoadAbsence,
null,
null,
ExtendedMasterSecretExtension.emsStringizer),
TOKEN_BINDING (0x0018, "token_binding "),
CACHED_INFO (0x0019, "cached_info"),
SESSION_TICKET (0x0023, "session_ticket"),
CH_EARLY_DATA (0x002A, "early_data"),
EE_EARLY_DATA (0x002A, "early_data"),
NST_EARLY_DATA (0x002A, "early_data"),
CH_SUPPORTED_VERSIONS (0x002B, "supported_versions",
SSLHandshake.CLIENT_HELLO,
ProtocolVersion.PROTOCOLS_TO_13,
SupportedVersionsExtension.chNetworkProducer,
SupportedVersionsExtension.chOnLoadConsumer,
null,
null,
null,
SupportedVersionsExtension.chStringizer),
SH_SUPPORTED_VERSIONS (0x002B, "supported_versions",
SSLHandshake.SERVER_HELLO,
ProtocolVersion.PROTOCOLS_OF_13,
SupportedVersionsExtension.shNetworkProducer,
SupportedVersionsExtension.shOnLoadConsumer,
null,
null,
null,
SupportedVersionsExtension.shStringizer),
HRR_SUPPORTED_VERSIONS (0x002B, "supported_versions",
SSLHandshake.HELLO_RETRY_REQUEST,
ProtocolVersion.PROTOCOLS_OF_13,
SupportedVersionsExtension.hrrNetworkProducer,
SupportedVersionsExtension.hrrOnLoadConsumer,
null,
null,
null,
SupportedVersionsExtension.hrrStringizer),
MH_SUPPORTED_VERSIONS (0x002B, "supported_versions",
SSLHandshake.MESSAGE_HASH,
ProtocolVersion.PROTOCOLS_OF_13,
SupportedVersionsExtension.hrrReproducer,
null, null, null,
null,
SupportedVersionsExtension.hrrStringizer),
CH_COOKIE (0x002C, "cookie",
SSLHandshake.CLIENT_HELLO,
ProtocolVersion.PROTOCOLS_OF_13,
CookieExtension.chNetworkProducer,
CookieExtension.chOnLoadConsumer,
null,
CookieExtension.chOnTradeConsumer,
null,
CookieExtension.cookieStringizer),
HRR_COOKIE (0x002C, "cookie",
SSLHandshake.HELLO_RETRY_REQUEST,
ProtocolVersion.PROTOCOLS_OF_13,
CookieExtension.hrrNetworkProducer,
CookieExtension.hrrOnLoadConsumer,
null, null,
null,
CookieExtension.cookieStringizer),
MH_COOKIE (0x002C, "cookie",
SSLHandshake.MESSAGE_HASH,
ProtocolVersion.PROTOCOLS_OF_13,
CookieExtension.hrrNetworkReproducer,
null, null, null,
null,
CookieExtension.cookieStringizer),
PSK_KEY_EXCHANGE_MODES (0x002D, "psk_key_exchange_modes",
SSLHandshake.CLIENT_HELLO,
ProtocolVersion.PROTOCOLS_OF_13,
PskKeyExchangeModesExtension.chNetworkProducer,
PskKeyExchangeModesExtension.chOnLoadConsumer,
PskKeyExchangeModesExtension.chOnLoadAbsence,
null,
PskKeyExchangeModesExtension.chOnTradeAbsence,
PskKeyExchangeModesExtension.pkemStringizer),
CERTIFICATE_AUTHORITIES (0x002F, "certificate_authorities"),
OID_FILTERS (0x0030, "oid_filters"),
POST_HANDSHAKE_AUTH (0x0030, "post_handshake_auth"),
CH_KEY_SHARE (0x0033, "key_share",
SSLHandshake.CLIENT_HELLO,
ProtocolVersion.PROTOCOLS_OF_13,
KeyShareExtension.chNetworkProducer,
KeyShareExtension.chOnLoadConsumer,
null, null, null,
KeyShareExtension.chStringizer),
SH_KEY_SHARE (0x0033, "key_share",
SSLHandshake.SERVER_HELLO,
ProtocolVersion.PROTOCOLS_OF_13,
KeyShareExtension.shNetworkProducer,
KeyShareExtension.shOnLoadConsumer,
KeyShareExtension.shOnLoadAbsence,
null,
null,
KeyShareExtension.shStringizer),
HRR_KEY_SHARE (0x0033, "key_share",
SSLHandshake.HELLO_RETRY_REQUEST,
ProtocolVersion.PROTOCOLS_OF_13,
KeyShareExtension.hrrNetworkProducer,
KeyShareExtension.hrrOnLoadConsumer,
null, null, null,
KeyShareExtension.hrrStringizer),
MH_KEY_SHARE (0x0033, "key_share",
SSLHandshake.MESSAGE_HASH,
ProtocolVersion.PROTOCOLS_OF_13,
KeyShareExtension.hrrNetworkReproducer,
null, null, null, null,
KeyShareExtension.hrrStringizer),
CH_RENEGOTIATION_INFO (0xff01, "renegotiation_info",
SSLHandshake.CLIENT_HELLO,
ProtocolVersion.PROTOCOLS_TO_12,
RenegoInfoExtension.chNetworkProducer,
RenegoInfoExtension.chOnLoadConsumer,
RenegoInfoExtension.chOnLoadAbsence,
null,
null,
RenegoInfoExtension.rniStringizer),
SH_RENEGOTIATION_INFO (0xff01, "renegotiation_info",
SSLHandshake.SERVER_HELLO,
ProtocolVersion.PROTOCOLS_TO_12,
RenegoInfoExtension.shNetworkProducer,
RenegoInfoExtension.shOnLoadConsumer,
RenegoInfoExtension.shOnLoadAbsence,
null,
null,
RenegoInfoExtension.rniStringizer),
CH_PRE_SHARED_KEY (0x0029, "pre_shared_key",
SSLHandshake.CLIENT_HELLO,
ProtocolVersion.PROTOCOLS_OF_13,
PreSharedKeyExtension.chNetworkProducer,
PreSharedKeyExtension.chOnLoadConsumer,
PreSharedKeyExtension.chOnLoadAbsence,
PreSharedKeyExtension.chOnTradeConsumer,
null,
PreSharedKeyExtension.chStringizer),
SH_PRE_SHARED_KEY (0x0029, "pre_shared_key",
SSLHandshake.SERVER_HELLO,
ProtocolVersion.PROTOCOLS_OF_13,
PreSharedKeyExtension.shNetworkProducer,
PreSharedKeyExtension.shOnLoadConsumer,
PreSharedKeyExtension.shOnLoadAbsence,
null, null,
PreSharedKeyExtension.shStringizer);
final int id;
final SSLHandshake handshakeType;
final String name;
final ProtocolVersion[] supportedProtocols;
final HandshakeProducer networkProducer;
final ExtensionConsumer onLoadConsumer;
final HandshakeAbsence onLoadAbsence;
final HandshakeConsumer onTradeConsumer;
final HandshakeAbsence onTradeAbsence;
final SSLStringizer stringizer;
private SSLExtension(int id, String name) {
this.id = id;
this.handshakeType = SSLHandshake.NOT_APPLICABLE;
this.name = name;
this.supportedProtocols = new ProtocolVersion[0];
this.networkProducer = null;
this.onLoadConsumer = null;
this.onLoadAbsence = null;
this.onTradeConsumer = null;
this.onTradeAbsence = null;
this.stringizer = null;
}
private SSLExtension(int id, String name, SSLHandshake handshakeType,
ProtocolVersion[] supportedProtocols,
HandshakeProducer producer,
ExtensionConsumer onLoadConsumer, HandshakeAbsence onLoadAbsence,
HandshakeConsumer onTradeConsumer, HandshakeAbsence onTradeAbsence,
SSLStringizer stringize) {
this.id = id;
this.handshakeType = handshakeType;
this.name = name;
this.supportedProtocols = supportedProtocols;
this.networkProducer = producer;
this.onLoadConsumer = onLoadConsumer;
this.onLoadAbsence = onLoadAbsence;
this.onTradeConsumer = onTradeConsumer;
this.onTradeAbsence = onTradeAbsence;
this.stringizer = stringize;
}
static SSLExtension valueOf(SSLHandshake handshakeType, int extensionType) {
for (SSLExtension ext : SSLExtension.values()) {
if (ext.id == extensionType &&
ext.handshakeType == handshakeType) {
return ext;
}
}
return null;
}
static String nameOf(int extensionType) {
for (SSLExtension ext : SSLExtension.values()) {
if (ext.id == extensionType) {
return ext.name;
}
}
return "unknown extension";
}
static boolean isConsumable(int extensionType) {
for (SSLExtension ext : SSLExtension.values()) {
if (ext.id == extensionType &&
ext.onLoadConsumer != null) {
return true;
}
}
return false;
}
public byte[] produce(ConnectionContext context,
HandshakeMessage message) throws IOException {
if (networkProducer != null) {
return networkProducer.produce(context, message);
} else {
throw new UnsupportedOperationException(
"Not yet supported extension producing.");
}
}
public void consumeOnLoad(ConnectionContext context,
HandshakeMessage message, ByteBuffer buffer) throws IOException {
if (onLoadConsumer != null) {
onLoadConsumer.consume(context, message, buffer);
} else {
throw new UnsupportedOperationException(
"Not yet supported extension loading.");
}
}
public void consumeOnTrade(ConnectionContext context,
HandshakeMessage message) throws IOException {
if (onTradeConsumer != null) {
onTradeConsumer.consume(context, message);
} else {
throw new UnsupportedOperationException(
"Not yet supported extension processing.");
}
}
void absentOnLoad(ConnectionContext context,
HandshakeMessage message) throws IOException {
if (onLoadAbsence != null) {
onLoadAbsence.absent(context, message);
} else {
throw new UnsupportedOperationException(
"Not yet supported extension absence processing.");
}
}
void absentOnTrade(ConnectionContext context,
HandshakeMessage message) throws IOException {
if (onTradeAbsence != null) {
onTradeAbsence.absent(context, message);
} else {
throw new UnsupportedOperationException(
"Not yet supported extension absence processing.");
}
}
public boolean isAvailable(ProtocolVersion protocolVersion) {
for (int i = 0; i < supportedProtocols.length; i++) {
if (supportedProtocols[i] == protocolVersion) {
return true;
}
}
return false;
}
@Override
public String toString() {
return name;
}
@Override
public String toString(ByteBuffer byteBuffer) {
MessageFormat messageFormat = new MessageFormat(
"\"{0} ({1})\": '{'\n" +
"{2}\n" +
"'}'",
Locale.ENGLISH);
String extData;
if (stringizer == null) {
HexDumpEncoder hexEncoder = new HexDumpEncoder();
String encoded = hexEncoder.encode(byteBuffer.duplicate());
extData = encoded;
} else {
extData = stringizer.toString(byteBuffer);
}
Object[] messageFields = {
this.name,
this.id,
Utilities.indent(extData)
};
return messageFormat.format(messageFields);
}
static interface ExtensionConsumer {
void consume(ConnectionContext context,
HandshakeMessage message, ByteBuffer buffer) throws IOException;
}
static interface SSLExtensionSpec {
}
static final class ClientExtensions {
static final Collection<SSLExtension> defaults;
static {
Collection<SSLExtension> extensions = new LinkedList<>();
for (SSLExtension extension : SSLExtension.values()) {
if (extension.handshakeType != SSLHandshake.NOT_APPLICABLE) {
extensions.add(extension);
}
}
boolean enableExtension =
Utilities.getBooleanProperty("jsse.enableSNIExtension", true);
if (!enableExtension) {
extensions.remove(CH_SERVER_NAME);
}
enableExtension =
Utilities.getBooleanProperty(
"jsse.enableMFLNExtension", false) ||
Utilities.getBooleanProperty(
"jsse.enableMFLExtension", false);
if (!enableExtension) {
extensions.remove(CH_MAX_FRAGMENT_LENGTH);
}
defaults = Collections.unmodifiableCollection(extensions);
}
}
static final class ServerExtensions {
static final Collection<SSLExtension> defaults;
static {
Collection<SSLExtension> extensions = new LinkedList<>();
for (SSLExtension extension : SSLExtension.values()) {
if (extension.handshakeType != SSLHandshake.NOT_APPLICABLE) {
extensions.add(extension);
}
}
defaults = Collections.unmodifiableCollection(extensions);
}
}
}