Skip to content

Commit

Permalink
Merge pull request #422 from ulvii/TLSVersionFix
Browse files Browse the repository at this point in the history
New connection property: sslProtocol
  • Loading branch information
ulvii authored Aug 18, 2017
2 parents 8abe96c + 94cc5e2 commit 93e087c
Show file tree
Hide file tree
Showing 6 changed files with 172 additions and 4 deletions.
7 changes: 4 additions & 3 deletions src/main/java/com/microsoft/sqlserver/jdbc/IOBuffer.java
Original file line number Diff line number Diff line change
Expand Up @@ -1580,6 +1580,7 @@ void enableSSL(String host,
boolean isFips = false;
String trustStoreType = null;
String fipsProvider = null;
String sslProtocol = null;

// If anything in here fails, terminate the connection and throw an exception
try {
Expand All @@ -1599,6 +1600,7 @@ void enableSSL(String host,

fipsProvider = con.activeConnectionProperties.getProperty(SQLServerDriverStringProperty.FIPS_PROVIDER.toString());
isFips = Boolean.valueOf(con.activeConnectionProperties.getProperty(SQLServerDriverBooleanProperty.FIPS.toString()));
sslProtocol = con.activeConnectionProperties.getProperty(SQLServerDriverStringProperty.SSL_PROTOCOL.toString());

if (isFips) {
validateFips(fipsProvider, trustStoreType, trustStoreFileName);
Expand Down Expand Up @@ -1728,7 +1730,7 @@ void enableSSL(String host,
if (logger.isLoggable(Level.FINEST))
logger.finest(toString() + " Getting TLS or better SSL context");

sslContext = SSLContext.getInstance("TLS");
sslContext = SSLContext.getInstance(sslProtocol);
sslContextProvider = sslContext.getProvider();

if (logger.isLoggable(Level.FINEST))
Expand All @@ -1745,8 +1747,7 @@ void enableSSL(String host,
logger.finest(toString() + " Creating SSL socket");

sslSocket = (SSLSocket) sslContext.getSocketFactory().createSocket(proxySocket, host, port, false); // don't close proxy when SSL socket
// is closed

// is closed
// At long last, start the SSL handshake ...
if (logger.isLoggable(Level.FINER))
logger.finer(toString() + " Starting SSL handshake");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1694,6 +1694,16 @@ else if (0 == requestedPacketSize)
setEnablePrepareOnFirstPreparedStatementCall(booleanPropertyOn(sPropKey, sPropValue));
}

sPropKey = SQLServerDriverStringProperty.SSL_PROTOCOL.toString();
sPropValue = activeConnectionProperties.getProperty(sPropKey);
if (null == sPropValue) {
sPropValue = SQLServerDriverStringProperty.SSL_PROTOCOL.getDefaultValue().toString();
activeConnectionProperties.setProperty(sPropKey, sPropValue);
}
else {
activeConnectionProperties.setProperty(sPropKey, SSLProtocol.valueOfString(sPropValue).toString());
}

FailoverInfo fo = null;
String databaseNameProperty = SQLServerDriverStringProperty.DATABASE_NAME.toString();
String serverNameProperty = SQLServerDriverStringProperty.SERVER_NAME.toString();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -593,6 +593,15 @@ public void setFIPSProvider(String fipsProvider) {
public String getFIPSProvider() {
return getStringProperty(connectionProps, SQLServerDriverStringProperty.FIPS_PROVIDER.toString(), null);
}

public void setSSLProtocol(String sslProtocol) {
setStringProperty(connectionProps, SQLServerDriverStringProperty.SSL_PROTOCOL.toString(), sslProtocol);
}

public String getSSLProtocol() {
return getStringProperty(connectionProps, SQLServerDriverStringProperty.SSL_PROTOCOL.toString(),
SQLServerDriverStringProperty.SSL_PROTOCOL.getDefaultValue());
}

// The URL property is exposed for backwards compatibility reasons. Also, several
// Java Application servers expect a setURL function on the DataSource and set it
Expand Down
42 changes: 42 additions & 0 deletions src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDriver.java
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,46 @@ else if (value.toLowerCase(Locale.US).equalsIgnoreCase(ColumnEncryptionSetting.D
}
}

enum SSLProtocol {
TLS("TLS"),
TLS_V10("TLSv1"),
TLS_V11("TLSv1.1"),
TLS_V12("TLSv1.2"),;

private final String name;

private SSLProtocol(String name) {
this.name = name;
}

public String toString() {
return name;
}

static SSLProtocol valueOfString(String value) throws SQLServerException {
SSLProtocol protocol = null;

if (value.toLowerCase(Locale.ENGLISH).equalsIgnoreCase(SSLProtocol.TLS.toString())) {
protocol = SSLProtocol.TLS;
}
else if (value.toLowerCase(Locale.ENGLISH).equalsIgnoreCase(SSLProtocol.TLS_V10.toString())) {
protocol = SSLProtocol.TLS_V10;
}
else if (value.toLowerCase(Locale.ENGLISH).equalsIgnoreCase(SSLProtocol.TLS_V11.toString())) {
protocol = SSLProtocol.TLS_V11;
}
else if (value.toLowerCase(Locale.ENGLISH).equalsIgnoreCase(SSLProtocol.TLS_V12.toString())) {
protocol = SSLProtocol.TLS_V12;
}
else {
MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_invalidSSLProtocol"));
Object[] msgArgs = {value};
throw new SQLServerException(null, form.format(msgArgs), null, 0, false);
}
return protocol;
}
}

enum KeyStoreAuthentication {
JavaKeyStorePassword;

Expand Down Expand Up @@ -247,6 +287,7 @@ enum SQLServerDriverStringProperty
KEY_STORE_SECRET ("keyStoreSecret", ""),
KEY_STORE_LOCATION ("keyStoreLocation", ""),
FIPS_PROVIDER ("fipsProvider", ""),
SSL_PROTOCOL ("sslProtocol", SSLProtocol.TLS.toString()),
;

private final String name;
Expand Down Expand Up @@ -384,6 +425,7 @@ public final class SQLServerDriver implements java.sql.Driver {
new SQLServerDriverPropertyInfo(SQLServerDriverIntProperty.SERVER_PREPARED_STATEMENT_DISCARD_THRESHOLD.toString(), Integer.toString(SQLServerDriverIntProperty.SERVER_PREPARED_STATEMENT_DISCARD_THRESHOLD.getDefaultValue()), false, null),
new SQLServerDriverPropertyInfo(SQLServerDriverIntProperty.STATEMENT_POOLING_CACHE_SIZE.toString(), Integer.toString(SQLServerDriverIntProperty.STATEMENT_POOLING_CACHE_SIZE.getDefaultValue()), false, null),
new SQLServerDriverPropertyInfo(SQLServerDriverStringProperty.JAAS_CONFIG_NAME.toString(), SQLServerDriverStringProperty.JAAS_CONFIG_NAME.getDefaultValue(), false, null),
new SQLServerDriverPropertyInfo(SQLServerDriverStringProperty.SSL_PROTOCOL.toString(), SQLServerDriverStringProperty.SSL_PROTOCOL.getDefaultValue(), false, new String[] {SSLProtocol.TLS.toString(), SSLProtocol.TLS_V10.toString(), SSLProtocol.TLS_V11.toString(), SSLProtocol.TLS_V12.toString()}),
};

// Properties that can only be set by using Properties.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -390,5 +390,7 @@ protected Object[][] getContents() {
{"R_invalidProbbytes", "SQL_VARIANT: invalid probBytes for {0} type."},
{"R_invalidStringValue", "SQL_VARIANT does not support string values more than 8000 length."},
{"R_invalidValueForTVPWithSQLVariant", "Inserting null value with column type sql_variant in TVP is not supported."},
{"R_sslProtocolPropertyDescription", "SSL protocol label from TLS, TLSv1, TLSv1.1 & TLSv1.2. The default is TLS."},
{"R_invalidSSLProtocol", "SSL Protocol {0} label is not valid. Only TLS, TLSv1, TLSv1.1 & TLSv1.2 are supported."},
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
/*
* Microsoft JDBC Driver for SQL Server
*
* Copyright(c) Microsoft Corporation All rights reserved.
*
* This program is made available under the terms of the MIT License. See the LICENSE file in the project root for more information.
*/
package com.microsoft.sqlserver.jdbc.connection;

import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.sql.Statement;

import org.junit.jupiter.api.Test;
import org.junit.platform.runner.JUnitPlatform;
import org.junit.runner.RunWith;

import com.microsoft.sqlserver.jdbc.SQLServerException;
import com.microsoft.sqlserver.jdbc.StringUtils;
import com.microsoft.sqlserver.testframework.AbstractTest;

/**
* Tests new connection property sslProtocol
*/
@RunWith(JUnitPlatform.class)
public class SSLProtocolTest extends AbstractTest {

Connection con = null;
Statement stmt = null;

/**
* Connect with supported protocol
*
* @param sslProtocol
* @throws Exception
*/
public void testWithSupportedProtocols(String sslProtocol) throws Exception {
String url = connectionString + ";sslProtocol=" + sslProtocol;
try {
con = DriverManager.getConnection(url);
DatabaseMetaData dbmd = con.getMetaData();
assertNotNull(dbmd);
assertTrue(!StringUtils.isEmpty(dbmd.getDatabaseProductName()));
}
catch (SQLServerException e) {
// Some older versions of SQLServer might not have all the TLS protocol versions enabled.
// Example, if the highest TLS version enabled in the server is TLSv1.1,
// the connection will fail if we enable only TLSv1.2
assertTrue(e.getMessage().contains("protocol version is not enabled or not supported by the client."));
}
}


/**
* Connect with unsupported protocol
*
* @param sslProtocol
* @throws Exception
*/
public void testWithUnSupportedProtocols(String sslProtocol) throws Exception {
try {
String url = connectionString + ";sslProtocol=" + sslProtocol;
con = DriverManager.getConnection(url);
assertFalse(true, "Any protocol other than TLSv1, TLSv1.1 & TLSv1.2 should throw Exception");
}
catch (SQLServerException e) {
assertTrue(true, "Should throw exception");
String errMsg = "SSL Protocol " + sslProtocol + " label is not valid. Only TLS, TLSv1, TLSv1.1 & TLSv1.2 are supported.";
assertTrue(errMsg.equals(e.getMessage()), "Message should be from SQL Server resources : " + e.getMessage());
}
}

/**
* Test with unsupported protocols.
*
* @throws Exception
*/
@Test
public void testConnectWithWrongProtocols() throws Exception {
String[] wrongProtocols = {"SSLv1111", "SSLv2222", "SSLv3111", "SSLv2Hello1111", "TLSv1.11", "TLSv2.4", "random"};
for (String wrongProtocol : wrongProtocols) {
testWithUnSupportedProtocols(wrongProtocol);
}
}

/**
* Test with supported protocols.
*
* @throws Exception
*/
@Test
public void testConnectWithSupportedProtocols() throws Exception {
String[] supportedProtocols = {"TLS", "TLSv1", "TLSv1.1", "TLSv1.2"};
for (String supportedProtocol : supportedProtocols) {
testWithSupportedProtocols(supportedProtocol);
}
}
}

0 comments on commit 93e087c

Please sign in to comment.