Skip to content

[Azure] Failed to validate the server name in a certificate during Secure Sockets Layer (SSL) initialization #623

@dspereira004

Description

@dspereira004

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.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions