| /* |
| * 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, "padding"), |
| SERVER_CERT_TYPE (0x0014, "server_certificate_type"), |
| |
| // extensions defined in RFC 7685 |
| PADDING (0x0015, "client_certificate_type"), |
| |
| // 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 4507/5077 |
| SESSION_TICKET (0x0023, "session_ticket"), |
| |
| // 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(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); |
| } |
| |
| ////////////////////////////////////////////////////// |
| // 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<SSLExtension> defaults; |
| |
| static { |
| Collection<SSLExtension> 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<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); |
| } |
| } |
| } |