Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Driver rejects valid certificate of Azure SQL Database when encrypt=true is specified #816

Closed
jd3nn1s opened this issue Sep 29, 2018 · 7 comments
Assignees

Comments

@jd3nn1s
Copy link

jd3nn1s commented Sep 29, 2018

Driver version

6.2.2.jre8, 6.4.0.jre8, master (7.1.2-SNAPSHOT)

SQL Server version

SQL Azure

Client Operating System

Windows 10, Windows 2012 R2 and Linux

JAVA/JVM version

Oracle Java 1.8 and openjdk version "10.0.2" 2018-07-17

Table schema

N/A

Problem description

  1. Expected behaviour:

Able to connect to SQL Azure using TLS with only the encrypt=true option

  1. Actual behaviour:

Connection is not established and an exception is raised

  1. Error message/stack trace:

Received an error: "Failed to validate the server name in a certificate during Secure Sockets Layer (SSL) initialization."

  1. Any other details that can be helpful:

SQL Azure uses a wildcard subject alternative name of *.database.windows.net in its certificate. While HostNameOverrideX509TrustManager supports subject alternative names (SANs), it does not support checking against wildcard hostnames. Therefore the certificate provided by SQL Azure is rejected by the driver.

I created a PoC where, in the default case, the default Java X509TrustManager is used instead of the driver's own implementation, taking care to set the endpoint identification protocol in the SSLParameters to "HTTPS". This has an implementation of wildcard checking and did not reject the certificate.

JDBC trace logs

Reproduction code

import java.sql.Connection;
import java.sql.DriverManager;

public class Main {

    public static void main(String[] argv) throws Exception {
        String jdbcUrl = "jdbc:sqlserver://xxxxx.database.windows.net:1433;databaseName=jdbctest;username=user1;password=pass1;encrypt=true";
        Connection conn = DriverManager.getConnection(jdbcUrl);
        conn.close();
    }
}

@jd3nn1s
Copy link
Author

jd3nn1s commented Sep 29, 2018

Looks like this could be a duplicate of #623.

The issue is not intermittent for me - it happens every time.

@peterbae
Copy link
Contributor

peterbae commented Oct 1, 2018

Hi @jd3nn1s, thanks for contacting us. Could you try adding "hostNameInCertificate=*.database.windows.net;" to your connection string, and let me know if that solves your problem? The details can be found on this page: https://docs.microsoft.com/en-us/sql/connect/jdbc/setting-the-connection-properties?view=sql-server-2017

@jd3nn1s
Copy link
Author

jd3nn1s commented Oct 1, 2018

Yes this would workaround the issue, however I’m more interested in a fix.

I’d be willing to work on a PR to resolve the issue with more information on the current design. E.g. why a custom implementation of X509TrustManager is used in the default case.

@peterbae
Copy link
Contributor

peterbae commented Oct 3, 2018

Hi @jd3nn1s, I think we need our custom implementation of X509TrustManager because of the connection property that our driver provides (hostNameInCertificate). I see the option to change the driver's logic for certifying the serverName against the entries in the certificate (change it to respect the wildcard instead of doing exact match), but this would be categorized as an improvement for the driver.

That being said, the property hostNameInCertificate has been around for some time, and while the logic could be improved for now I don't believe this is a workaround (documentation can be found here: https://docs.microsoft.com/en-us/sql/connect/jdbc/connecting-with-ssl-encryption?view=sql-server-2017). Is this a blocking issue for your application?

@jd3nn1s
Copy link
Author

jd3nn1s commented Oct 6, 2018

Agreed, a custom X509TrustManager is required for some configurations:

HostNameOverrideX509TrustManager for hostNameInCertificate
PermissiveX509TrustManager for trustServerCertificate=true

Certainly there are some use-cases where a certificate validation hostname override is appropriate but I don't believe this is one of them. Setting hostNameInCertificate=*.database.windows.net is using knowledge of Azure-specific configuration (that a wildcard cert is in use), that is not guaranteed to be stable. For instance, if Azure switched to a model where each DNS alias had a SAN in the certificate, which would normally validate fine with this driver, the hostNameInCertificate will cause the certificate to be rejected.

If I use a native Windows driver I do not need to override the hostname used for certificate validation; it accepts the wildcard cert without error or additional configuration.

Principally the difficulty for apps is that special configuration is needed to connect to Azure SQL which isn't needed for a typical SQL Server. Currently the app in question does not present any "advanced" configuration options during install that would allow entering an alternative certificate subject, and even if it did the user would need to know what to specify. Alternatively we could string match on the entered SQL server name and if we see database.windows.net$ we add hostNameInCertificate, but again this is fragile.

I could not find any SQL Server protocol documentation that talked about rules for wildcard or general certificate validation but I did find this at https://docs.microsoft.com/en-us/sql/database-engine/configure-windows/enable-encrypted-connections-to-the-database-engine?view=sql-server-2017:

Beginning with SQL Server 2008, SQL Server and the SQL Server Native Client support wildcard certificates. Other clients might not support wildcard certificates. For more information, see the client documentation.

It would be good to know what wildcard rules Windows clients are applying. RFC 6125 sec 6.4.3 perhaps?

@peterbae
Copy link
Contributor

Hi @jd3nn1s, thanks for the detailed reply. I see the value in making this change to respect wildcard characters when SSL connecting to Azure, and we'll let you know soon when we have an update on this.

@peterbae
Copy link
Contributor

peterbae commented Jan 5, 2019

Fixed in #836. Closing issue.

@peterbae peterbae closed this as completed Jan 5, 2019
dineubr added a commit to dineubr/sql-docs that referenced this issue Sep 30, 2022
…ject Alternative Name

Information seems to be outdated as SQL Native Client, SQLClient, MSJDBC, MSODBCSQL/MSOLEDBSQL already support the feature.
Some public evidences about using SAN:

- SQLClient: dotnet/SqlClient#1437
- MSJDBC: microsoft/mssql-jdbc#816
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants