Skip to content

Commit 6f9d08b

Browse files
committed
WL#14805, Remove support for TLS 1.0 and 1.1.
1 parent d21d74f commit 6f9d08b

25 files changed

+1118
-806
lines changed

CHANGES

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33

44
Version 8.0.28
55

6+
- WL#14805, Remove support for TLS 1.0 and 1.1.
7+
68
- WL#14650, Support for MFA (multi factor authentication) authentication.
79

810
Version 8.0.27

src/main/core-api/java/com/mysql/cj/conf/PropertyDefinitions.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -361,11 +361,11 @@ public enum DatabaseTerm {
361361
new BooleanPropertyDefinition(PropertyKey.fallbackToSystemKeyStore, DEFAULT_VALUE_TRUE, RUNTIME_MODIFIABLE,
362362
Messages.getString("ConnectionProperties.fallbackToSystemKeyStore"), "8.0.22", CATEGORY_SECURITY, 12),
363363

364-
new StringPropertyDefinition(PropertyKey.enabledSSLCipherSuites, DEFAULT_VALUE_NULL_STRING, RUNTIME_MODIFIABLE,
365-
Messages.getString("ConnectionProperties.enabledSSLCipherSuites"), "5.1.35", CATEGORY_SECURITY, 13),
364+
new StringPropertyDefinition(PropertyKey.tlsCiphersuites, DEFAULT_VALUE_NULL_STRING, RUNTIME_MODIFIABLE,
365+
Messages.getString("ConnectionProperties.tlsCiphersuites"), "5.1.35", CATEGORY_SECURITY, 13),
366366

367-
new StringPropertyDefinition(PropertyKey.enabledTLSProtocols, DEFAULT_VALUE_NULL_STRING, RUNTIME_MODIFIABLE,
368-
Messages.getString("ConnectionProperties.enabledTLSProtocols"), "8.0.8", CATEGORY_SECURITY, 14),
367+
new StringPropertyDefinition(PropertyKey.tlsVersions, DEFAULT_VALUE_NULL_STRING, RUNTIME_MODIFIABLE,
368+
Messages.getString("ConnectionProperties.tlsVersions"), "8.0.8", CATEGORY_SECURITY, 14),
369369

370370
new BooleanPropertyDefinition(PropertyKey.allowLoadLocalInfile, DEFAULT_VALUE_FALSE, RUNTIME_MODIFIABLE,
371371
Messages.getString("ConnectionProperties.loadDataLocal"), "3.0.3", CATEGORY_SECURITY, Integer.MAX_VALUE),

src/main/core-api/java/com/mysql/cj/conf/PropertyKey.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,8 +115,6 @@ public enum PropertyKey {
115115
emptyStringsConvertToZero("emptyStringsConvertToZero", true), //
116116
emulateLocators("emulateLocators", true), //
117117
emulateUnsupportedPstmts("emulateUnsupportedPstmts", true), //
118-
enabledSSLCipherSuites("enabledSSLCipherSuites", true), //
119-
enabledTLSProtocols("enabledTLSProtocols", true), //
120118
enableEscapeProcessing("enableEscapeProcessing", true), //
121119
enablePacketDebug("enablePacketDebug", true), //
122120
enableQueryTimeouts("enableQueryTimeouts", true), //
@@ -225,6 +223,8 @@ public enum PropertyKey {
225223
tcpSndBuf("tcpSndBuf", true), //
226224
tcpTrafficClass("tcpTrafficClass", true), //
227225
tinyInt1isBit("tinyInt1isBit", true), //
226+
tlsCiphersuites("tlsCiphersuites", "enabledSSLCipherSuites", true), //
227+
tlsVersions("tlsVersions", "enabledTLSProtocols", true), //
228228
traceProtocol("traceProtocol", true), //
229229
trackSessionState("trackSessionState", true), //
230230
transformedBitIsBoolean("transformedBitIsBoolean", true), //

src/main/core-impl/java/com/mysql/cj/protocol/ExportControlled.java

Lines changed: 50 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -92,17 +92,16 @@
9292
import com.mysql.cj.conf.PropertyDefinitions.SslMode;
9393
import com.mysql.cj.conf.PropertyKey;
9494
import com.mysql.cj.conf.PropertySet;
95+
import com.mysql.cj.conf.RuntimeProperty;
9596
import com.mysql.cj.exceptions.CJCommunicationsException;
9697
import com.mysql.cj.exceptions.ExceptionFactory;
9798
import com.mysql.cj.exceptions.ExceptionInterceptor;
9899
import com.mysql.cj.exceptions.FeatureNotAvailableException;
99100
import com.mysql.cj.exceptions.RSAException;
100101
import com.mysql.cj.exceptions.SSLParamsException;
101-
import com.mysql.cj.exceptions.WrongArgumentException;
102102
import com.mysql.cj.log.Log;
103103
import com.mysql.cj.util.Base64Decoder;
104104
import com.mysql.cj.util.StringUtils;
105-
import com.mysql.cj.util.Util;
106105

107106
/**
108107
* Holds functionality that falls under export-control regulations.
@@ -112,7 +111,8 @@ public class ExportControlled {
112111
private static final String TLSv1_1 = "TLSv1.1";
113112
private static final String TLSv1_2 = "TLSv1.2";
114113
private static final String TLSv1_3 = "TLSv1.3";
115-
private static final String[] TLS_PROTOCOLS = new String[] { TLSv1_3, TLSv1_2, TLSv1_1, TLSv1 };
114+
private static final String[] KNOWN_TLS_PROTOCOLS = new String[] { TLSv1_3, TLSv1_2, TLSv1_1, TLSv1 };
115+
private static final String[] VALID_TLS_PROTOCOLS = new String[] { TLSv1_3, TLSv1_2 };
116116

117117
private static final String TLS_SETTINGS_RESOURCE = "/com/mysql/cj/TlsSettings.properties";
118118
private static final List<String> ALLOWED_CIPHERS = new ArrayList<>();
@@ -150,7 +150,7 @@ public static boolean enabled() {
150150
}
151151

152152
private static String[] getAllowedCiphers(PropertySet pset, List<String> socketCipherSuites) {
153-
String enabledSSLCipherSuites = pset.getStringProperty(PropertyKey.enabledSSLCipherSuites).getValue();
153+
String enabledSSLCipherSuites = pset.getStringProperty(PropertyKey.tlsCiphersuites).getValue();
154154
Stream<String> filterStream = StringUtils.isNullOrEmpty(enabledSSLCipherSuites) ? socketCipherSuites.stream()
155155
: Arrays.stream(enabledSSLCipherSuites.split("\\s*,\\s*")).filter(socketCipherSuites::contains);
156156

@@ -165,54 +165,66 @@ private static String[] getAllowedCiphers(PropertySet pset, List<String> socketC
165165
return allowedCiphers.toArray(new String[] {});
166166
}
167167

168-
private static String[] getAllowedProtocols(PropertySet pset, ServerVersion serverVersion, String[] socketProtocols) {
169-
String[] tryProtocols = null;
168+
private static String[] getAllowedProtocols(PropertySet pset, @SuppressWarnings("unused") ServerVersion serverVersion, String[] socketProtocols) {
169+
List<String> tryProtocols = null;
170170

171-
// If enabledTLSProtocols configuration option is set, overriding the default TLS version restrictions.
172-
// This allows enabling TLSv1.2 for self-compiled MySQL versions supporting it, as well as the ability
173-
// for users to restrict TLS connections to approved protocols (e.g., prohibiting TLSv1) on the client side.
174-
String enabledTLSProtocols = pset.getStringProperty(PropertyKey.enabledTLSProtocols).getValue();
175-
if (enabledTLSProtocols != null && enabledTLSProtocols.length() > 0) {
176-
tryProtocols = enabledTLSProtocols.split("\\s*,\\s*");
177-
}
178-
// It is problematic to enable TLSv1.2 on the client side when the server is compiled with yaSSL. When client attempts to connect with
179-
// TLSv1.2 yaSSL just closes the socket instead of re-attempting handshake with lower TLS version. So here we allow all protocols only
180-
// for server versions which are known to be compiled with OpenSSL.
181-
else if (serverVersion == null) {
182-
// X Protocol doesn't provide server version, but we prefer to use most recent TLS version, though it also means that X Protocol
183-
// connection to old MySQL 5.7 GPL releases will fail by default, user must use enabledTLSProtocols=TLSv1.1 to connect them.
184-
tryProtocols = TLS_PROTOCOLS;
185-
} else if (serverVersion.meetsMinimum(new ServerVersion(5, 7, 28))
186-
|| serverVersion.meetsMinimum(new ServerVersion(5, 6, 46)) && !serverVersion.meetsMinimum(new ServerVersion(5, 7, 0))
187-
|| serverVersion.meetsMinimum(new ServerVersion(5, 6, 0)) && Util.isEnterpriseEdition(serverVersion.toString())) {
188-
tryProtocols = TLS_PROTOCOLS;
171+
RuntimeProperty<String> tlsVersions = pset.getStringProperty(PropertyKey.tlsVersions);
172+
if (tlsVersions != null && tlsVersions.isExplicitlySet()) {
173+
// If tlsVersions configuration option is set then override the default TLS versions restriction.
174+
if (tlsVersions.getValue() == null) {
175+
throw ExceptionFactory.createException(SSLParamsException.class,
176+
"Specified list of TLS versions is empty. Accepted values are TLSv1.2 and TLSv1.3.");
177+
}
178+
tryProtocols = getValidProtocols(tlsVersions.getValue().split("\\s*,\\s*"));
189179
} else {
190-
// allow only TLSv1 and TLSv1.1 for other server versions by default
191-
tryProtocols = new String[] { TLSv1_1, TLSv1 };
180+
tryProtocols = new ArrayList<>(Arrays.asList(VALID_TLS_PROTOCOLS));
192181
}
193182

194-
List<String> configuredProtocols = new ArrayList<>(Arrays.asList(tryProtocols));
195183
List<String> jvmSupportedProtocols = Arrays.asList(socketProtocols);
196-
197184
List<String> allowedProtocols = new ArrayList<>();
198-
for (String protocol : TLS_PROTOCOLS) {
199-
if (jvmSupportedProtocols.contains(protocol) && configuredProtocols.contains(protocol)) {
185+
for (String protocol : tryProtocols) {
186+
if (jvmSupportedProtocols.contains(protocol)) {
200187
allowedProtocols.add(protocol);
201188
}
202189
}
203190
return allowedProtocols.toArray(new String[0]);
204-
205191
}
206192

207-
public static void checkValidProtocols(List<String> protocols) {
208-
List<String> validProtocols = Arrays.asList(TLS_PROTOCOLS);
209-
for (String protocol : protocols) {
210-
if (!validProtocols.contains(protocol)) {
211-
throw ExceptionFactory.createException(WrongArgumentException.class,
212-
"'" + protocol + "' not recognized as a valid TLS protocol version (should be one of "
213-
+ Arrays.stream(TLS_PROTOCOLS).collect(Collectors.joining(", ")) + ").");
193+
private static List<String> getValidProtocols(String[] protocols) {
194+
195+
List<String> requestedProtocols = Arrays.stream(protocols).filter(p -> !StringUtils.isNullOrEmpty(p.trim())).collect(Collectors.toList());
196+
if (requestedProtocols.size() == 0) {
197+
throw ExceptionFactory.createException(SSLParamsException.class,
198+
"Specified list of TLS versions is empty. Accepted values are TLSv1.2 and TLSv1.3.");
199+
}
200+
201+
List<String> sanitizedProtocols = new ArrayList<>();
202+
for (String protocol : KNOWN_TLS_PROTOCOLS) {
203+
if (requestedProtocols.contains(protocol)) {
204+
sanitizedProtocols.add(protocol);
214205
}
215206
}
207+
if (sanitizedProtocols.size() == 0) {
208+
throw ExceptionFactory.createException(SSLParamsException.class,
209+
"Specified list of TLS versions only contains non valid TLS protocols. Accepted values are TLSv1.2 and TLSv1.3.");
210+
}
211+
212+
List<String> validProtocols = new ArrayList<>();
213+
for (String protocol : VALID_TLS_PROTOCOLS) {
214+
if (sanitizedProtocols.contains(protocol)) {
215+
validProtocols.add(protocol);
216+
}
217+
}
218+
if (validProtocols.size() == 0) {
219+
throw ExceptionFactory.createException(SSLParamsException.class,
220+
"TLS protocols TLSv1 and TLSv1.1 are not supported. Accepted values are TLSv1.2 and TLSv1.3.");
221+
}
222+
223+
return validProtocols;
224+
}
225+
226+
public static void checkValidProtocols(List<String> protocols) {
227+
getValidProtocols(protocols.toArray(new String[0]));
216228
}
217229

218230
private static class KeyStoreConf {
@@ -333,14 +345,6 @@ public static Socket performTlsHandshake(Socket rawSocket, SocketConnection sock
333345
}
334346

335347
sslSocket.startHandshake();
336-
337-
if (log != null) {
338-
String tlsVersion = sslSocket.getSession().getProtocol();
339-
if (TLSv1.equalsIgnoreCase(tlsVersion) || TLSv1_1.equalsIgnoreCase(tlsVersion)) {
340-
log.logWarn("This connection is using " + tlsVersion + " which is now deprecated and will be removed in a future release of Connector/J.");
341-
}
342-
}
343-
344348
return sslSocket;
345349
}
346350

src/main/protocol-impl/java/com/mysql/cj/protocol/x/XProtocol.java

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -366,38 +366,28 @@ public void beforeHandshake() {
366366
}
367367

368368
RuntimeProperty<String> xdevapiTlsVersions = this.propertySet.getStringProperty(PropertyKey.xdevapiTlsVersions);
369-
RuntimeProperty<String> jdbcEnabledTlsProtocols = this.propertySet.getStringProperty(PropertyKey.enabledTLSProtocols);
369+
RuntimeProperty<String> jdbcEnabledTlsProtocols = this.propertySet.getStringProperty(PropertyKey.tlsVersions);
370370
if (xdevapiTlsVersions.isExplicitlySet()) {
371371
if (sslMode.getValue() == SslMode.DISABLED) {
372372
throw ExceptionFactory.createException(WrongArgumentException.class,
373373
"Option '" + PropertyKey.xdevapiTlsVersions.getKeyName() + "' can not be specified when SSL connections are disabled.");
374374
}
375-
if (xdevapiTlsVersions.getValue().trim().isEmpty()) {
376-
throw ExceptionFactory.createException(WrongArgumentException.class,
377-
"At least one TLS protocol version must be specified in '" + PropertyKey.xdevapiTlsVersions.getKeyName() + "' list.");
378-
}
379375

380376
String[] tlsVersions = xdevapiTlsVersions.getValue().split("\\s*,\\s*");
381377
List<String> tryProtocols = Arrays.asList(tlsVersions);
382378
ExportControlled.checkValidProtocols(tryProtocols);
383379
jdbcEnabledTlsProtocols.setValue(xdevapiTlsVersions.getValue());
384-
385-
} else if (!jdbcEnabledTlsProtocols.isExplicitlySet()) {
386-
jdbcEnabledTlsProtocols.setValue(xdevapiTlsVersions.getValue());
387380
}
388381

389382
RuntimeProperty<String> xdevapiTlsCiphersuites = this.propertySet.getStringProperty(PropertyKey.xdevapiTlsCiphersuites);
390-
RuntimeProperty<String> jdbcEnabledSslCipherSuites = this.propertySet.getStringProperty(PropertyKey.enabledSSLCipherSuites);
383+
RuntimeProperty<String> jdbcEnabledSslCipherSuites = this.propertySet.getStringProperty(PropertyKey.tlsCiphersuites);
391384
if (xdevapiTlsCiphersuites.isExplicitlySet()) {
392385
if (sslMode.getValue() == SslMode.DISABLED) {
393386
throw ExceptionFactory.createException(WrongArgumentException.class,
394387
"Option '" + PropertyKey.xdevapiTlsCiphersuites.getKeyName() + "' can not be specified when SSL connections are disabled.");
395388
}
396389

397390
jdbcEnabledSslCipherSuites.setValue(xdevapiTlsCiphersuites.getValue());
398-
399-
} else if (!jdbcEnabledSslCipherSuites.isExplicitlySet()) {
400-
jdbcEnabledSslCipherSuites.setValue(xdevapiTlsCiphersuites.getValue());
401391
}
402392

403393
boolean verifyServerCert = sslMode.getValue() == SslMode.VERIFY_CA || sslMode.getValue() == SslMode.VERIFY_IDENTITY;
@@ -425,7 +415,7 @@ public void beforeHandshake() {
425415
}
426416
}
427417

428-
if (xdevapiSslMode.getValue() != XdevapiSslMode.DISABLED) {
418+
if (jdbcSslMode.getValue() != SslMode.DISABLED) {
429419
negotiateSSLConnection();
430420
}
431421

0 commit comments

Comments
 (0)