Skip to content

Commit

Permalink
Fix for Bug#27374581, CONNECTION FAILS WHEN GPL SERVER STARTED WITH T…
Browse files Browse the repository at this point in the history
…LS-VERSION=TLSV1.2.
  • Loading branch information
fjssilva committed Jan 27, 2018
1 parent f225df9 commit b79d648
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 60 deletions.
2 changes: 2 additions & 0 deletions CHANGES
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

Version 5.1.46

- Fix for Bug#27374581, CONNECTION FAILS WHEN GPL SERVER STARTED WITH TLS-VERSION=TLSV1.2.

- Fix for Bug#79612 (22362474), CONNECTION ATTRIBUTES LOST WHEN CONNECTING WITHOUT DEFAULT DATABASE.

Version 5.1.45
Expand Down
26 changes: 12 additions & 14 deletions src/com/mysql/jdbc/ExportControlled.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved.
Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
The MySQL Connector/J is licensed under the terms of the GPLv2
<http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>, like most MySQL Connectors.
Expand Down Expand Up @@ -107,27 +107,25 @@ protected static void transformSocketToSSLSocket(MysqlIO mysqlIO) throws SQLExce

String[] tryProtocols = null;

// If enabledTLSProtocols configuration option is set, overriding the default TLS version restrictions.
// This allows enabling TLSv1.2 for self-compiled MySQL versions supporting it, as well as the ability
// for users to restrict TLS connections to approved protocols (e.g., prohibiting TLSv1) on the client side.
// If enabledTLSProtocols configuration option is set then override the default TLS version restrictions. This allows enabling TLSv1.2 for
// self-compiled MySQL versions supporting it, as well as the ability for users to restrict TLS connections to approved protocols (e.g., prohibiting
// TLSv1) on the client side.
// Note that it is problematic to enable TLSv1.2 on the client side when the server is compiled with yaSSL. When client attempts to connect with
// TLSv1.2 yaSSL just closes the socket instead of re-attempting handshake with lower TLS version.
String enabledTLSProtocols = mysqlIO.connection.getEnabledTLSProtocols();
if (enabledTLSProtocols != null && enabledTLSProtocols.length() > 0) {
tryProtocols = enabledTLSProtocols.split("\\s*,\\s*");
} else if (mysqlIO.versionMeetsMinimum(8, 0, 4) || mysqlIO.versionMeetsMinimum(5, 6, 0) && Util.isEnterpriseEdition(mysqlIO.getServerVersion())) {
// allow all known TLS versions for this subset of server versions by default
tryProtocols = TLS_PROTOCOLS;
} else {
// Note that it is problematic to enable TLSv1.2 on the client side when the server is compiled with yaSSL.
// When client attempts to connect with TLSv1.2 yaSSL just closes the socket instead of re-attempting handshake with
// lower TLS version.
if (mysqlIO.versionMeetsMinimum(5, 6, 0) && Util.isEnterpriseEdition(mysqlIO.getServerVersion())) {
tryProtocols = new String[] { TLSv1_2, TLSv1_1, TLSv1 };
}
}
// allow TLSv1 and TLSv1.1 for all server versions by default
if (tryProtocols == null) {
// allow TLSv1 and TLSv1.1 for all server versions by default
tryProtocols = new String[] { TLSv1_1, TLSv1 };

}

List<String> configuredProtocols = new ArrayList<String>(Arrays.asList(tryProtocols));
List<String> jvmSupportedProtocols = Arrays.asList(((SSLSocket) mysqlIO.mysqlConnection).getSupportedProtocols());

List<String> allowedProtocols = new ArrayList<String>();
for (String protocol : TLS_PROTOCOLS) {
if (jvmSupportedProtocols.contains(protocol) && configuredProtocols.contains(protocol)) {
Expand Down
103 changes: 57 additions & 46 deletions src/testsuite/regression/ConnectionRegressionTest.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved.
Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
The MySQL Connector/J is licensed under the terms of the GPLv2
<http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>, like most MySQL Connectors.
Expand Down Expand Up @@ -87,6 +87,7 @@
import javax.management.MBeanServer;
import javax.management.MBeanServerInvocationHandler;
import javax.management.ObjectName;
import javax.net.ssl.SSLContext;
import javax.sql.XAConnection;
import javax.transaction.xa.XAException;
import javax.transaction.xa.XAResource;
Expand Down Expand Up @@ -8481,15 +8482,16 @@ public ResultSetInternalMethods preProcess(String sql, com.mysql.jdbc.Statement
/**
* Tests fix for WL#8196, Support for TLSv1.2 Protocol.
*
* This test requires community server (with yaSSL) in -Dcom.mysql.jdbc.testsuite.url and
* commercial server (with OpenSSL) in -Dcom.mysql.jdbc.testsuite.url.sha256default
* This test requires community server (preferably compiled with yaSSL) in -Dcom.mysql.jdbc.testsuite.url and commercial server (with OpenSSL) in
* -Dcom.mysql.jdbc.testsuite.url.sha256default
*
* Test certificates from testsuite/ssl-test-certs must be installed on both servers.
*
* @throws Exception
* if the test fails.
*/
public void testTLSVersion() throws Exception {
// Find out which TLS protocol versions are supported by this JVM.
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, null, null);
List<String> jvmSupportedProtocols = Arrays.asList(sslContext.createSSLEngine().getSupportedProtocols());

final String[] testDbUrls;
Properties props = new Properties();
Expand All @@ -8508,51 +8510,55 @@ public void testTLSVersion() throws Exception {

for (String testDbUrl : testDbUrls) {
System.out.println(testDbUrl);
System.out.println(System.getProperty("java.version"));
System.out.println("JVM version: " + System.getProperty("java.version"));
System.out.println("JVM supports TLS protocols: " + jvmSupportedProtocols);
Connection sslConn = getConnectionWithProps(testDbUrl, props);
assertTrue(((MySQLConnection) sslConn).getIO().isSSLEstablished());

ResultSet rset = sslConn.createStatement().executeQuery("SHOW STATUS LIKE 'ssl_version'");
assertTrue(rset.next());
String tlsVersion = rset.getString(2);
System.out.println("TLS version: " + tlsVersion);
System.out.println();
System.out.println("MySQL version: " + ((MySQLConnection) sslConn).getServerVersion());
String etp = ((MySQLConnection) sslConn).getEnabledTLSProtocols();
System.out.println("enabledTLSProtocols: " + etp);
System.out.println();
System.out.println("JVM version: " + Util.getJVMVersion());
System.out.println();
this.rs = sslConn.createStatement().executeQuery("SHOW STATUS LIKE 'ssl_version'");
assertTrue(this.rs.next());
String tlsVersionUsed = this.rs.getString(2);
System.out.println("TLS version used: " + tlsVersionUsed);

if (((MySQLConnection) sslConn).versionMeetsMinimum(5, 7, 10) && Util.getJVMVersion() > 6) {
if (Util.isEnterpriseEdition(((MySQLConnection) sslConn).getServerVersion())) {
assertEquals("TLSv1.2", tlsVersion);
} else {
assertEquals("TLSv1.1", tlsVersion);
if (((MySQLConnection) sslConn).versionMeetsMinimum(5, 7, 10)) {
this.rs = sslConn.createStatement().executeQuery("SHOW GLOBAL VARIABLES LIKE 'tls_version'");
assertTrue(this.rs.next());
List<String> serverSupportedProtocols = Arrays.asList(this.rs.getString(2).trim().split("\\s*,\\s*"));
String highestCommonTlsVersion = "";
for (String p : new String[] { "TLSv1.2", "TLSv1.1", "TLSv1" }) {
if (jvmSupportedProtocols.contains(p) && serverSupportedProtocols.contains(p)) {
highestCommonTlsVersion = p;
break;
}
}
System.out.println("Server supports TLS protocols: " + serverSupportedProtocols);
System.out.println("Highest common TLS protocol: " + highestCommonTlsVersion);

assertEquals(highestCommonTlsVersion, tlsVersionUsed);
} else {
assertEquals("TLSv1", tlsVersion);
assertEquals("TLSv1", tlsVersionUsed);
}
System.out.println();

sslConn.close();
}
}

/**
* Tests fix for Bug#87379. This allows TLS version to be overridden through a new configuration
* option - enabledTLSProtocols. When set to some combination of TLSv1, TLSv1.1, or TLSv1.2 (comma-
* separated, no spaces), the default behaviour restricting the TLS version based on JRE and MySQL
* Server version is bypassed to enable or restrict specific TLS versions.
* Tests fix for Bug#87379. This allows TLS version to be overridden through a new configuration option - enabledTLSProtocols. When set to some combination
* of TLSv1, TLSv1.1, or TLSv1.2 (comma-separated, no spaces), the default behavior restricting the TLS version based on JRE and MySQL Server version is
* bypassed to enable or restrict specific TLS versions.
*
* This test requires community server (with yaSSL) in -Dcom.mysql.jdbc.testsuite.url and
* commercial server (with OpenSSL) in -Dcom.mysql.jdbc.testsuite.url.sha256default
* This test requires community server (preferably compiled with yaSSL) in -Dcom.mysql.jdbc.testsuite.url and commercial server (with OpenSSL) in
* -Dcom.mysql.jdbc.testsuite.url.sha256default
*
* Test certificates from testsuite/ssl-test-certs must be installed on both servers.
*
* @throws Exception
* if the test fails.
*/
public void testEnableTLSVersion() throws Exception {
// Find out which TLS protocol versions are supported by this JVM.
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, null, null);
List<String> jvmSupportedProtocols = Arrays.asList(sslContext.createSSLEngine().getSupportedProtocols());

final String[] testDbUrls;
Properties props = new Properties();
Expand All @@ -8571,42 +8577,47 @@ public void testEnableTLSVersion() throws Exception {

for (String testDbUrl : testDbUrls) {
System.out.println(testDbUrl);
System.out.println(System.getProperty("java.version"));
System.out.println("JVM version: " + System.getProperty("java.version"));
System.out.println("JVM supports TLS protocols: " + jvmSupportedProtocols);
Connection sslConn = getConnectionWithProps(testDbUrl, props);
assertTrue(((MySQLConnection) sslConn).getIO().isSSLEstablished());
List<String> expectedProtocols = new ArrayList<String>();
expectedProtocols.add("TLSv1");
if (Util.getJVMVersion() > 6 && ((MySQLConnection) sslConn).versionMeetsMinimum(5, 7, 10)) {
ResultSet rs1 = sslConn.createStatement().executeQuery("SELECT @@global.tls_version");
assertTrue(rs1.next());
String supportedTLSVersions = rs1.getString(1);
System.out.println("Server reported TLS version support: " + supportedTLSVersions);
expectedProtocols.addAll(Arrays.asList(supportedTLSVersions.split("\\s*,\\s*")));
System.out.println("MySQL version: " + ((MySQLConnection) sslConn).getServerVersion());
List<String> commonSupportedProtocols = new ArrayList<String>();
if (((MySQLConnection) sslConn).versionMeetsMinimum(5, 7, 10)) {
this.rs = sslConn.createStatement().executeQuery("SHOW GLOBAL VARIABLES LIKE 'tls_version'");
assertTrue(this.rs.next());
List<String> serverSupportedProtocols = Arrays.asList(this.rs.getString(2).trim().split("\\s*,\\s*"));
System.out.println("Server supports TLS protocols: " + serverSupportedProtocols);
commonSupportedProtocols.addAll(serverSupportedProtocols);
commonSupportedProtocols.retainAll(jvmSupportedProtocols);
} else {
commonSupportedProtocols.add("TLSv1");
}

String[] testingProtocols = { "TLSv1.2", "TLSv1.1", "TLSv1" };
for (String protocol : testingProtocols) {
Properties testProps = new Properties();
testProps.putAll(props);
testProps.put("enabledTLSProtocols", protocol);
System.out.println("Testing " + protocol + " expecting connection: " + expectedProtocols.contains(protocol));
System.out.println("Testing " + protocol + " expecting connection: " + commonSupportedProtocols.contains(protocol));
try {
Connection tlsConn = getConnectionWithProps(testDbUrl, testProps);
if (!expectedProtocols.contains(protocol)) {
fail("Expected to fail connection with " + protocol + " due to lack of server support.");
if (!commonSupportedProtocols.contains(protocol)) {
fail("Expected to fail connection with " + protocol + " due to lack of jvm/server support.");
}
ResultSet rset = tlsConn.createStatement().executeQuery("SHOW STATUS LIKE 'ssl_version'");
assertTrue(rset.next());
String tlsVersion = rset.getString(2);
assertEquals(protocol, tlsVersion);
tlsConn.close();
} catch (Exception e) {
if (expectedProtocols.contains(protocol)) {
if (commonSupportedProtocols.contains(protocol)) {
e.printStackTrace();
fail("Expected to be able to connect with " + protocol + " protocol, but failed.");
}
}
}
System.out.println();
sslConn.close();
}
}
Expand Down

0 comments on commit b79d648

Please sign in to comment.