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

Server certificate Subject Alternative Name of type IP Address is not taken into account in server name verification #2529

Open
d-richter-qdt opened this issue Oct 16, 2024 · 3 comments
Labels
Enhancement An enhancement to the driver. Lower priority than bugs.

Comments

@d-richter-qdt
Copy link

Driver version

JDBC driver version (e.g. 12.8.1).

SQL Server version

Microsoft SQL Server 2022 (RTM-CU15-GDR) (KB5046059) - 16.0.4150.1 (X64)
Sep 25 2024 17:34:41
Copyright (C) 2022 Microsoft Corporation
Developer Edition (64-bit) on Linux (Ubuntu 22.04.5 LTS)

JAVA/JVM version

21.0.4

Problem description

Server certificate subject alternative name of type iPAddress is not taken into account in server name verification.

Expected behavior

If server address is entered as IP address and server certificate contain subject alternative name extension with that IP address defined connection attempt will be successful.

Actual behavior

Server name check fails.

Error message/stack trace

javax.net.ssl.SSLHandshakeException: Failed to validate the server name "<IP_ADDRESS>"in a certificate during Secure Sockets Layer (SSL) initialization. Name in certificate "<DNS_NAME>"
        at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:130)
        at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:378)
        at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:321)
        at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:316)
        at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.checkServerCerts(CertificateMessage.java:647)
        at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.onCertificate(CertificateMessage.java:467)
        at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.consume(CertificateMessage.java:363)
        at java.base/sun.security.ssl.SSLHandshake.consume(SSLHandshake.java:393)
        at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:476)
        at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:447)
        at java.base/sun.security.ssl.TransportContext.dispatch(TransportContext.java:201)
        at java.base/sun.security.ssl.SSLTransport.decode(SSLTransport.java:172)
        at java.base/sun.security.ssl.SSLSocketImpl.decode(SSLSocketImpl.java:1506)
        at java.base/sun.security.ssl.SSLSocketImpl.readHandshakeRecord(SSLSocketImpl.java:1421)
        at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:455)
        at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:426)
        at com.microsoft.sqlserver.jdbc.TDSChannel.enableSSL(IOBuffer.java:1854)
        ... 53 more
Caused by: java.security.cert.CertificateException: Failed to validate the server name "<IP_ADDRESS>"in a certificate during Secure Sockets Layer (SSL) initialization. Name in certificate "<DNS_NAME>"
        at com.microsoft.sqlserver.jdbc.SQLServerCertificateUtils.validateServerNameInCertificate(SQLServerCertificateUtils.java:269)
        at com.microsoft.sqlserver.jdbc.HostNameOverrideX509TrustManager.checkServerTrusted(SQLServerTrustManager.java:99)
        at java.base/sun.security.ssl.AbstractTrustManagerWrapper.checkServerTrusted(SSLContextImpl.java:1430)
        at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.checkServerCerts(CertificateMessage.java:631)
        ... 65 more

Any other details that can be helpful

com.microsoft.sqlserver.jdbc.SQLServerCertificateUtils.validateServerNameInCertificate
takes only constant 2 (DNS name) into account

JDBC URL: jdbc:sqlserver://<IP_ADDRESS>:<PORT>;databaseName=<DB_NAME>;socketTimeout=60000;encrypt=true;trustServerCertificate=false;trustStore=<PATH_TO_TRUSTSTORE>;trustStorePassword=<TRUSTSTORE_PWD>

possible work around using parameter hostNameInCertificate with DNS name used in certificate

@lilgreenbird
Copy link
Contributor

hi @d-richter-qdt

I'm not sure what the question is, did the hostNameInCertificate property work for you? That is what this property is used for, it can be used to specify the host name in situations where the name, or names, used in the certificate doesn't match the name passed in to the serverName property. For more information on descriptions of connection properties for the driver, please see the doc Setting the connection properties.

@d-richter-qdt
Copy link
Author

Hello @lilgreenbird,

thank you for your response. It is not question but bug report. I believe that driver should be able to connect without using that property in this case, as the certificate contains IP address of DB server in subjAltName extension (Even tho I agree it is kind of an edge case). As to your question yes the property works.

To be exact:
Here:

if ((key != null) && (key instanceof Integer) && ((Integer) key == 2)) {

is missing handling of key == 7 https://docs.oracle.com/javase/6/docs/api/java/security/cert/X509Certificate.html#getSubjectAlternativeNames()

@lilgreenbird
Copy link
Contributor

lilgreenbird commented Nov 1, 2024

thank you, I will add this as an enhancement request. In the mean time, please use the hostNameInCertificate property as a workaround.

@lilgreenbird lilgreenbird added the Enhancement An enhancement to the driver. Lower priority than bugs. label Nov 1, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Enhancement An enhancement to the driver. Lower priority than bugs.
Projects
Status: Backlog
Development

No branches or pull requests

2 participants