Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,14 @@ All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](http://keepachangelog.com/)

## [12.10.1] Stable Release
## [12.10.2] Hotfix & Stable Release
### Fixed issues
- **Address a hostname validation vulnerability by securely parsing certificate common names.**
**What was fixed**: Secure hostname validation is enforced by replacing the vulnerable CN parsing logic in SQLServerCertificateUtils.java, preventing spoofing attacks.
**Who benefits**: All users of the SQL Server JDBC driver, especially those relying on TLS for secure connections, benefit from improved certificate validation.


## [12.10.1] Hotfix & Stable Release
### Fixed issues
- Make ibm security module optional [#2679] (https://github.com/microsoft/mssql-jdbc/pull/2679)
- Invalidate existing enclave session during connection (re)connect [#2680] (https://github.com/microsoft/mssql-jdbc/pull/2680)
Expand Down
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ We're now on the Maven Central Repository. Add the following to your POM file to
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
<version>12.10.1.jre11</version>
<version>12.10.2.jre11</version>
</dependency>
```
The driver can be downloaded from [Microsoft](https://aka.ms/downloadmssqljdbc). For driver version 12.1.0 and greater, please use the jre11 version when using Java 11 or greater, and the jre8 version when using Java 8.
Expand All @@ -94,7 +94,7 @@ To get the latest version of the driver, add the following to your POM file:
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
<version>12.10.1.jre11</version>
<version>12.10.2.jre11</version>
</dependency>
```

Expand Down Expand Up @@ -129,7 +129,7 @@ Projects that require either of the two features need to explicitly declare the
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
<version>12.10.1.jre11</version>
<version>12.10.2.jre11</version>
<scope>compile</scope>
</dependency>

Expand All @@ -147,7 +147,7 @@ Projects that require either of the two features need to explicitly declare the
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
<version>12.10.1.jre11</version>
<version>12.10.2.jre11</version>
<scope>compile</scope>
</dependency>

Expand All @@ -174,7 +174,7 @@ When setting 'useFmtOnly' property to 'true' for establishing a connection or cr
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
<version>12.10.1.jre11</version>
<version>12.10.2.jre11</version>
</dependency>

<dependency>
Expand Down
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

apply plugin: 'java'

version = '12.10.1'
version = '12.10.2'
def releaseExt = ''
def jreVersion = ""
def testOutputDir = file("build/classes/java/test")
Expand Down
2 changes: 1 addition & 1 deletion mssql-jdbc_auth_LICENSE
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
MICROSOFT SOFTWARE LICENSE TERMS
MICROSOFT JDBC DRIVER 12.10.1 FOR SQL SERVER
MICROSOFT JDBC DRIVER 12.10.2 FOR SQL SERVER

These license terms are an agreement between you and Microsoft Corporation (or one of its affiliates). They apply to the software named above and any Microsoft services or software updates (except to the extent such services or updates are accompanied by new or additional terms, in which case those different terms apply prospectively and do not alter your or Microsoft’s rights relating to pre-updated software or services). IF YOU COMPLY WITH THESE LICENSE TERMS, YOU HAVE THE RIGHTS BELOW. BY USING THE SOFTWARE, YOU ACCEPT THESE TERMS.

Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
<version>12.10.1</version>
<version>12.10.2</version>
<packaging>jar</packaging>
<name>Microsoft JDBC Driver for SQL Server</name>
<description>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
final class SQLJdbcVersion {
static final int MAJOR = 12;
static final int MINOR = 10;
static final int PATCH = 1;
static final int PATCH = 2;
static final int BUILD = 0;
/*
* Used to load mssql-jdbc_auth DLL.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@
import javax.crypto.spec.SecretKeySpec;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.naming.ldap.LdapName;
import javax.naming.ldap.Rdn;
import javax.security.auth.x500.X500Principal;

import org.bouncycastle.openssl.PEMDecryptorProvider;
import org.bouncycastle.openssl.PEMEncryptedKeyPair;
Expand Down Expand Up @@ -77,45 +80,6 @@ static KeyManager[] getKeyManagerFromFile(String certPath, String keyPath,
}
}

/**
* Parse name in RFC 2253 format Returns the common name if successful, null if failed to find the common name. The
* parser tuned to be safe than sorry so if it sees something it can't parse correctly it returns null
*
* @param distinguishedName
* server name to parse
* @return subject name
*/
static String parseCommonName(String distinguishedName) {
int index;
// canonical name converts entire name to lowercase
index = distinguishedName.indexOf("cn=");
if (index == -1) {
return null;
}
distinguishedName = distinguishedName.substring(index + 3);
// Parse until a comma or end is reached
// Note the parser will handle gracefully (essentially will return empty string) , inside the quotes (e.g
// cn="Foo, bar") however
// RFC 952 says that the hostName cant have commas however the parser should not (and will not) crash if it
// sees a , within quotes.
for (index = 0; index < distinguishedName.length(); index++) {
if (distinguishedName.charAt(index) == ',') {
break;
}
}
String commonName = distinguishedName.substring(0, index);
// strip any quotes
if (commonName.length() > 1 && ('\"' == commonName.charAt(0))) {
if ('\"' == commonName.charAt(commonName.length() - 1))
commonName = commonName.substring(1, commonName.length() - 1);
else {
// Be safe the name is not ended in " return null so the common Name wont match
commonName = null;
}
}
return commonName;
}

/**
* Validate server name in certificate matches hostname
*
Expand Down Expand Up @@ -183,7 +147,11 @@ static boolean validateServerName(String nameInCert, String hostName) {
* @throws CertificateException
*/
static void validateServerNameInCertificate(X509Certificate cert, String hostName) throws CertificateException {
String nameInCertDN = cert.getSubjectX500Principal().getName("canonical");
// Use RFC2253 format and secure CN parsing to avoid ambiguities introduced by
// the "canonical" format (which lowercases and reverses RDN order). We rely
// on LdapName/Rdn to securely parse the DN and extract the CN attribute only.
X500Principal subjectPrincipal = cert.getSubjectX500Principal();
String nameInCertDN = subjectPrincipal.getName(X500Principal.RFC2253);

if (logger.isLoggable(Level.FINER)) {
logger.finer(logContext + " Validating the server name:" + hostName);
Expand All @@ -194,7 +162,11 @@ static void validateServerNameInCertificate(X509Certificate cert, String hostNam
String dnsNameInSANCert = "";

// the name in cert is in RFC2253 format parse it to get the actual subject name
String subjectCN = parseCommonName(nameInCertDN);
String subjectCN = parseCommonNameSecure(cert);
// Normalize case for comparison using English locale to avoid Turkish i issues
if (subjectCN != null) {
subjectCN = subjectCN.toLowerCase(Locale.ENGLISH);
}

isServerNameValidated = validateServerName(subjectCN, hostName);

Expand Down Expand Up @@ -530,4 +502,35 @@ private static InputStream fileToStream(String fname) throws IOException, SQLSer
private static String getStringFromFile(String filePath) throws IOException {
return new String(Files.readAllBytes(Paths.get(filePath)));
}

/**
* Securely parse the Common Name (CN) from the certificate subject using
* LdapName/Rdn APIs and RFC2253 string representation to avoid mis-parsing
* values that appear inside other attributes when canonical form is used.
*/
static String parseCommonNameSecure(X509Certificate cert) {
try {
X500Principal subjectPrincipal = cert.getSubjectX500Principal();
String dn = subjectPrincipal.getName(X500Principal.RFC2253);

LdapName ldapDN = new LdapName(dn);
for (Rdn rdn : ldapDN.getRdns()) {
if ("CN".equalsIgnoreCase(rdn.getType())) {
String cnValue = rdn.getValue().toString();
return cnValue;
}
}

if (logger.isLoggable(Level.FINER)) {
logger.finer(logContext + " No CN found in certificate subject");
}
return null;

} catch (Exception e) {
if (logger.isLoggable(Level.WARNING)) {
logger.warning(logContext + " Error parsing certificate: " + e.getMessage());
}
return null;
}
}
}
2 changes: 1 addition & 1 deletion src/samples/adaptive/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
<version>12.10.1.jre11</version>
<version>12.10.2.jre11</version>
</dependency>
</dependencies>
<profiles>
Expand Down
2 changes: 1 addition & 1 deletion src/samples/alwaysencrypted/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
<version>12.10.1.jre11</version>
<version>12.10.2.jre11</version>
</dependency>
</dependencies>
<profiles>
Expand Down
2 changes: 1 addition & 1 deletion src/samples/azureactivedirectoryauthentication/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
<version>12.10.1.jre11</version>
<version>12.10.2.jre11</version>
</dependency>
</dependencies>
<profiles>
Expand Down
2 changes: 1 addition & 1 deletion src/samples/connections/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
<version>12.10.1.jre11</version>
<version>12.10.2.jre11</version>
</dependency>
</dependencies>
<profiles>
Expand Down
2 changes: 1 addition & 1 deletion src/samples/constrained/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
<version>12.10.1.jre11</version>
<version>12.10.2.jre11</version>
</dependency>
</dependencies>
<profiles>
Expand Down
2 changes: 1 addition & 1 deletion src/samples/dataclassification/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
<version>12.10.1.jre11</version>
<version>12.10.2.jre11</version>
</dependency>
</dependencies>
<profiles>
Expand Down
2 changes: 1 addition & 1 deletion src/samples/datatypes/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
<version>12.10.1.jre11</version>
<version>12.10.2.jre11</version>
</dependency>
</dependencies>
<profiles>
Expand Down
2 changes: 1 addition & 1 deletion src/samples/resultsets/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
<version>12.10.1.jre11</version>
<version>12.10.2.jre11</version>
</dependency>
</dependencies>
<profiles>
Expand Down
2 changes: 1 addition & 1 deletion src/samples/sparse/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
<version>12.10.1.jre11</version>
<version>12.10.2.jre11</version>
</dependency>
</dependencies>
<profiles>
Expand Down
Loading