mssql-jdbc: [Azure] Failed to validate the server name in a certificate during Secure Sockets Layer (SSL) initialization

Driver version or jar name

6.3.6

SQL Server version

Microsoft SQL Azure (RTM) - 12.0.2000.8

Client operating system

Ubuntu 16.04

Java/JVM version

java version “1.8.0_161”

Table schema

N/A

Problem description

Using the mentioned version of the mssql-jdbc, and connecting to SQL Server on Azure with a jdbc string provided by Azure, which includes the following properties:

  • sqlserver
  • database
  • user
  • password
  • encrypt (with value ‘true’)
  • trustServerCertificate (with value ‘false’)
  • hostNameInCertificate (with value ‘*.database.windows.net’)
  • loginTimeout (with value ‘30’)

We are getting sometimes the following stacktrace:

com.microsoft.sqlserver.jdbc.SQLServerException: The driver could not establish a secure connection to SQL Server by using Secure Sockets Layer (SSL) encryption. Error: "java.security.cert.CertificateException: Failed to validate the server name in a certificate during Secure Sockets Layer (SSL) initialization.". ClientConnectionId:d5e13b9e-546d-417c-be63-abfece6929fe
	at com.microsoft.sqlserver.jdbc.SQLServerConnection.terminate(SQLServerConnection.java:2675)
	at com.microsoft.sqlserver.jdbc.TDSChannel.enableSSL(IOBuffer.java:1837)
	at com.microsoft.sqlserver.jdbc.SQLServerConnection.connectHelper(SQLServerConnection.java:2262)
	at com.microsoft.sqlserver.jdbc.SQLServerConnection.login(SQLServerConnection.java:1927)
	at com.microsoft.sqlserver.jdbc.SQLServerConnection.connectInternal(SQLServerConnection.java:1768)
	at com.microsoft.sqlserver.jdbc.SQLServerConnection.connect(SQLServerConnection.java:1076)
	at com.microsoft.sqlserver.jdbc.SQLServerConnection.checkClosed(SQLServerConnection.java:1011)
	at com.microsoft.sqlserver.jdbc.SQLServerConnection.createStatement(SQLServerConnection.java:3161)
	at com.microsoft.sqlserver.jdbc.SQLServerConnection.createStatement(SQLServerConnection.java:2843)
	at com.feedzai.commons.sql.abstraction.engine.impl.SqlServerEngine.checkConnection(SqlServerEngine.java:743)
	at com.feedzai.commons.sql.abstraction.engine.AbstractDatabaseEngine.getConnection(AbstractDatabaseEngine.java:273)
	at com.feedzai.commons.sql.abstraction.engine.AbstractDatabaseEngine.beginTransaction(AbstractDatabaseEngine.java:416)
	at com.feedzai.pulse.service.apps.util.ThreadScopeTransactionFun.beginTx(ThreadScopeTransactionFun.java:331)
	at com.feedzai.pulse.service.apps.util.ThreadScopeTransactionFun.transaction(ThreadScopeTransactionFun.java:280)
	at com.feedzai.pulse.service.apps.util.ThreadScopeTransactionFun.call(ThreadScopeTransactionFun.java:257)
	at com.feedzai.pulse.service.apps.database.TransactionInterceptor.invoke(TransactionInterceptor.java:91)
	at com.google.inject.internal.InterceptorStackCallback$InterceptedMethodInvocation.proceed(InterceptorStackCallback.java:77)
	at com.google.inject.internal.InterceptorStackCallback.intercept(InterceptorStackCallback.java:55)
	at com.feedzai.pulse.service.apps.manager.RoleManagerImpl$$EnhancerByGuice$$eba0945d.list(<generated>)
	at com.feedzai.pulse.service.security.projection.Projection.reload(Projection.java:72)
	at com.feedzai.pulse.service.security.PulseSecurityImpl.doReloadSecurity(PulseSecurityImpl.java:287)
	at com.feedzai.pulse.service.security.PulseSecurityImpl.lambda$reloadSecurityLocally$2(PulseSecurityImpl.java:349)
	at com.feedzai.pulse.service.security.PulseSecurityUtils.lambda$doAsSystemUser$0(PulseSecurityUtils.java:268)
	at com.feedzai.pulse.service.security.PulseSecurityUtils.getAsSystemUser(PulseSecurityUtils.java:286)
	at com.feedzai.pulse.service.security.PulseSecurityUtils.doAsSystemUser(PulseSecurityUtils.java:267)
	at com.feedzai.pulse.service.security.PulseSecurityImpl.reloadSecurityLocally(PulseSecurityImpl.java:341)
	at com.feedzai.pulse.service.security.PulseSecurityImpl.reloadSecurityInCluster(PulseSecurityImpl.java:506)
	at com.feedzai.pulse.service.security.PulseSecurityImpl.reloadSecurity(PulseSecurityImpl.java:272)
	at com.feedzai.pulse.service.apps.util.ThreadScopeTransactionFun.reloadSecurity(ThreadScopeTransactionFun.java:460)
	at com.feedzai.pulse.service.apps.util.ThreadScopeTransactionFun.commitTx(ThreadScopeTransactionFun.java:413)
	at com.feedzai.pulse.service.apps.util.ThreadScopeTransactionFun.transaction(ThreadScopeTransactionFun.java:294)
	at com.feedzai.pulse.service.apps.util.ThreadScopeTransactionFun.call(ThreadScopeTransactionFun.java:257)
	at com.feedzai.pulse.service.apps.database.TransactionInterceptor.invoke(TransactionInterceptor.java:91)
	at com.google.inject.internal.InterceptorStackCallback$InterceptedMethodInvocation.proceed(InterceptorStackCallback.java:77)
	at com.feedzai.pulse.service.security.guice.EnforcePermissionsInterceptor.invoke(EnforcePermissionsInterceptor.java:55)
	at com.google.inject.internal.InterceptorStackCallback$InterceptedMethodInvocation.proceed(InterceptorStackCallback.java:77)
	at com.google.inject.internal.InterceptorStackCallback.intercept(InterceptorStackCallback.java:55)
	at com.feedzai.pulse.service.apps.manager.datascience.AppDataScienceTagGroupManagerImpl$$EnhancerByGuice$$2b7a2b98.ensureTags(<generated>)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at com.feedzai.remote.autowire.remote.RemoteWrapperImpl.invokeRemotely(RemoteWrapperImpl.java:102)
	at sun.reflect.GeneratedMethodAccessor60.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:361)
	at sun.rmi.transport.Transport$1.run(Transport.java:200)
	at sun.rmi.transport.Transport$1.run(Transport.java:197)
	at java.security.AccessController.doPrivileged(Native Method)
	at sun.rmi.transport.Transport.serviceCall(Transport.java:196)
	at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:568)
	at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:826)
	at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:683)
	at java.security.AccessController.doPrivileged(Native Method)
	at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:682)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)
Caused by: javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: Failed to validate the server name in a certificate during Secure Sockets Layer (SSL) initialization.
	at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
	at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1959)
	at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:328)
	at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:322)
	at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1614)
	at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:216)
	at sun.security.ssl.Handshaker.processLoop(Handshaker.java:1052)
	at sun.security.ssl.Handshaker.process_record(Handshaker.java:987)
	at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1072)
	at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1385)
	at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1413)
	at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1397)
	at com.microsoft.sqlserver.jdbc.TDSChannel.enableSSL(IOBuffer.java:1767)
	... 57 common frames omitted
Caused by: java.security.cert.CertificateException: Failed to validate the server name in a certificate during Secure Sockets Layer (SSL) initialization.
	at com.microsoft.sqlserver.jdbc.TDSChannel$HostNameOverrideX509TrustManager.validateServerNameInCertificate(IOBuffer.java:1547)
	at com.microsoft.sqlserver.jdbc.TDSChannel$HostNameOverrideX509TrustManager.checkServerTrusted(IOBuffer.java:1462)
	at sun.security.ssl.AbstractTrustManagerWrapper.checkServerTrusted(SSLContextImpl.java:985)
	at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1596)
	... 65 common frames omitted
    

This problem happens when the “hostNameInCertificate” property is changed by the driver on the SQLServerConnection class (because of a ENVCHANGE_ROUTING).

In that case, the original “hostNameInCertificate” (which comes from the jdbc string provided by Azure) is replaced by the routing server name.

This will trigger an exception on the method validateServerNameInCertificate since the routing server name does not exist on the certificate.

Expected behavior and actual behavior

Probably, the “hostNameInCertificate” property shouldn’t be changed the way it is currently being done, because there are no guarantees that afterward, we will validate the server name in the certificate successfully.

The expected behavior is that this error shouldn’t happen since we are providing a correct “hostNameInCertificate” (and which works fine until we have that ENVCHANGE_ROUTING event).

Repro code

Setup on an Azure account both a SQL Server/Database and a VM with a client that uses the mssql-jdbc lib and perform operations with it.

As said previously, this happens from time to time so it may take a little bit to reproduce this behavior.

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Comments: 15 (9 by maintainers)

Most upvoted comments

Hi @rangala, thanks for the detailed information. The response from multiple customers over the past week and their inability to reproduce the issue all of a sudden leads me to believe that this problem might’ve been coming from the server’s (Azure) end. That said, I can see that your SSL certificate has the entry *.database.secure.windows, instead of *.database.windows.net. this page as well as other resources suggest to me that your server might have security/auditing features on, in which case could try putting *.database.secure.windows in your hostNameInCertificate connecting string. Could you let me know if this solves your problem?