/* * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ 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.security.util.HexDumpEncoder; enum SSLExtension implements SSLStringizer { // Extensions defined in RFC 6066 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), // extensions defined in RFC 4681 USER_MAPPING (0x0006, "user_mapping"), // extensions defined in RFC 5878 CLIENT_AUTHZ (0x0007, "client_authz"), SERVER_AUTHZ (0x0008, "server_authz"), // extensions defined in RFC 5081 CERT_TYPE (0x0009, "cert_type"), // extensions defined in RFC 4492 (ECC) CH_SUPPORTED_GROUPS (0x000A, "supported_groups", SSLHandshake.CLIENT_HELLO, ProtocolVersion.PROTOCOLS_TO_13, SupportedGroupsExtension.chNetworkProducer, SupportedGroupsExtension.chOnLoadConsumer, null, null, SupportedGroupsExtension.chOnTradAbsence, 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, // not use of the producer ECPointFormatsExtension.shOnLoadConsumer, null, null, null, ECPointFormatsExtension.epfStringizer), // extensions defined in RFC 5054 SRP (0x000C, "srp"), // extensions defined in RFC 5246 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), // extensions defined in RFC 5764 USE_SRTP (0x000E, "use_srtp"), // extensions defined in RFC 6520 HEARTBEAT (0x000E, "heartbeat"), // extension defined in RFC 7301 (ALPN) 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), // extensions defined in RFC 6961 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), // extensions defined in RFC 6962 SIGNED_CERT_TIMESTAMP (0x0012, "signed_certificate_timestamp"), // extensions defined in RFC 7250 CLIENT_CERT_TYPE (0x0013, "client_certificate_type"), SERVER_CERT_TYPE (0x0014, "server_certificate_type"), // extensions defined in RFC 7685 PADDING (0x0015, "padding"), // extensions defined in RFC 7366 ENCRYPT_THEN_MAC (0x0016, "encrypt_then_mac"), // extensions defined in RFC 7627 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), // extensions defined in RFC draft-ietf-tokbind-negotiation TOKEN_BINDING (0x0018, "token_binding "), // extensions defined in RFC 7924 CACHED_INFO (0x0019, "cached_info"), // extensions defined in RFC 5077 CH_SESSION_TICKET (0x0023, "session_ticket", SSLHandshake.CLIENT_HELLO, ProtocolVersion.PROTOCOLS_10_12, SessionTicketExtension.chNetworkProducer, SessionTicketExtension.chOnLoadConsumer, null, null, null, SessionTicketExtension.steStringizer), //null), SH_SESSION_TICKET (0x0023, "session_ticket", SSLHandshake.SERVER_HELLO, ProtocolVersion.PROTOCOLS_10_12, SessionTicketExtension.shNetworkProducer, SessionTicketExtension.shOnLoadConsumer, null, null, null, SessionTicketExtension.steStringizer), //null), // extensions defined in TLS 1.3 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, // and HelloRetryRequest 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), CH_CERTIFICATE_AUTHORITIES (0x002F, "certificate_authorities", SSLHandshake.CLIENT_HELLO, ProtocolVersion.PROTOCOLS_OF_13, CertificateAuthoritiesExtension.chNetworkProducer, CertificateAuthoritiesExtension.chOnLoadConsumer, null, null, null, CertificateAuthoritiesExtension.ssStringizer), CR_CERTIFICATE_AUTHORITIES (0x002F, "certificate_authorities", SSLHandshake.CERTIFICATE_REQUEST, ProtocolVersion.PROTOCOLS_OF_13, CertificateAuthoritiesExtension.crNetworkProducer, CertificateAuthoritiesExtension.crOnLoadConsumer, null, null, null, CertificateAuthoritiesExtension.ssStringizer), 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, KeyShareExtension.chOnTradAbsence, 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), // Extensions defined in RFC 5746 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), // TLS 1.3 PSK extension must be last CH_PRE_SHARED_KEY (0x0029, "pre_shared_key", SSLHandshake.CLIENT_HELLO, ProtocolVersion.PROTOCOLS_OF_13, PreSharedKeyExtension.chNetworkProducer, PreSharedKeyExtension.chOnLoadConsumer, PreSharedKeyExtension.chOnLoadAbsence, PreSharedKeyExtension.chOnTradeConsumer, PreSharedKeyExtension.chOnTradAbsence, 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; /* * networkProducer: produces outbound handshake data. * * onLoadConsumer: parses inbound data. It may not be appropriate * to act until all of the message inputs have * been parsed. (e.g. parsing keyShares and choosing * a local value without having seen the SupportedGroups * extension.) * * onLoadAbsence: if a missing message needs special handling * during the load phase. * * onTradeConsumer: act on the parsed message once all inbound data has * been traded and parsed. * * onTradeAbsence: if a missing message needs special handling * during the trade phase. */ final HandshakeProducer networkProducer; final ExtensionConsumer onLoadConsumer; final HandshakeAbsence onLoadAbsence; final HandshakeConsumer onTradeConsumer; final HandshakeAbsence onTradeAbsence; final SSLStringizer stringizer; // known but unsupported extension 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; } // supported extension 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( HandshakeContext handshakeContext, 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(handshakeContext, byteBuffer); } Object[] messageFields = { this.name, this.id, Utilities.indent(extData) }; return messageFormat.format(messageFields); } ////////////////////////////////////////////////////// // Nested extension, consumer and producer interfaces. static interface ExtensionConsumer { void consume(ConnectionContext context, HandshakeMessage message, ByteBuffer buffer) throws IOException; } /** * A (transparent) specification of extension data. * * This interface contains no methods or constants. Its only purpose is to * group all extension data. All extension data should implement this * interface if the data is expected to handle in the following handshake * processes. */ static interface SSLExtensionSpec { // blank } // Default enabled client extensions. static final class ClientExtensions { static final Collection defaults; static { Collection extensions = new LinkedList<>(); for (SSLExtension extension : SSLExtension.values()) { if (extension.handshakeType != SSLHandshake.NOT_APPLICABLE) { extensions.add(extension); } } // Switch off SNI extention? boolean enableExtension = Utilities.getBooleanProperty("jsse.enableSNIExtension", true); if (!enableExtension) { extensions.remove(CH_SERVER_NAME); } // To switch off the max_fragment_length extension. // // Note that "jsse.enableMFLNExtension" is the CSR approved // property name. However, "jsse.enableMFLExtension" was used // in the original implementation. Temporarily, if either of // the two properties set to true, the extension is switch on. // We may remove the "jsse.enableMFLExtension" property in the // future. Please don't continue to use the misspelling property. enableExtension = Utilities.getBooleanProperty( "jsse.enableMFLNExtension", false) || Utilities.getBooleanProperty( "jsse.enableMFLExtension", false); if (!enableExtension) { extensions.remove(CH_MAX_FRAGMENT_LENGTH); } // To switch on certificate_authorities extension in ClientHello. // // Note: Please be careful to enable this extension in ClientHello. // // In practice, if the server certificate cannot be validated by // the underlying programs, the user may manually check the // certificate in order to access the service. The certificate // could be accepted manually, and the handshake continues. For // example, the browsers provide the manual option to accept // untrusted server certificate. If this extension is enabled in // the ClientHello handshake message, and the server's certificate // does not chain back to any of the CAs in the extension, then the // server will terminate the handshake and close the connection. // There is no chance for the client to perform the manual check. // Therefore, enabling this extension in ClientHello may lead to // unexpected compatibility issues for such cases. // // According to TLS 1.3 specification [RFC 8446] the maximum size // of the certificate_authorities extension is 2^16 bytes. The // maximum TLS record size is 2^14 bytes. If the handshake // message is bigger than maximum TLS record size, it should be // splitted into several records. In fact, some server // implementations do not allow ClientHello messages bigger than // the maximum TLS record size and will immediately abort the // connection with a fatal alert. Therefore, if the client trusts // too many certificate authorities, there may be unexpected // interoperability issues. // // Furthermore, if the client trusts more CAs such that it exceeds // the size limit of the extension, enabling this extension in // client side does not really make sense any longer as there is // no way to indicate the server certificate selection accurately. // // In general, a server does not use multiple certificates issued // from different CAs. It is not expected to use this extension a // lot in practice. When there is a need to use this extension // in ClientHello handshake message, please take care of the // potential compatibility and interoperability issues above. enableExtension = Utilities.getBooleanProperty( "jdk.tls.client.enableCAExtension", false); if (!enableExtension) { extensions.remove(CH_CERTIFICATE_AUTHORITIES); } defaults = Collections.unmodifiableCollection(extensions); } } // Default enabled server extensions. static final class ServerExtensions { static final Collection defaults; static { Collection extensions = new LinkedList<>(); for (SSLExtension extension : SSLExtension.values()) { if (extension.handshakeType != SSLHandshake.NOT_APPLICABLE) { extensions.add(extension); } } defaults = Collections.unmodifiableCollection(extensions); } } }