Skip to content

SSL SNI hostname with trailing dot unable to connect #653

@seanmcnealy

Description

@seanmcnealy

Bug Report

Versions

  • Driver: n/a
  • Database: n/a
  • Java: n/a
  • OS: n/a

Current Behavior

SSL SNI hostname with trailing dot unable to connect. Throws a bit of a weird error.

Disabling SNI works fine. So this is a minor issue. But the same hostnames worked in the previous version using default settings and do not work in the current version with default settings.

Stack trace
java.lang.RuntimeException: java.lang.IllegalArgumentException: Server name value of host_name cannot have the trailing dot
	at io.r2dbc.postgresql.client.ReactorNettyClient.registerSslHandler(ReactorNettyClient.java:422)
	at io.r2dbc.postgresql.client.ReactorNettyClient.lambda$connect$11(ReactorNettyClient.java:402)
	at reactor.netty.transport.TransportConfig$TransportChannelInitializer.initChannel(TransportConfig.java:418)
	at io.netty.channel.ChannelInitializer.initChannel(ChannelInitializer.java:129)
	at io.netty.channel.ChannelInitializer.handlerAdded(ChannelInitializer.java:112)
	at io.netty.channel.AbstractChannelHandlerContext.callHandlerAdded(AbstractChannelHandlerContext.java:1130)
	at io.netty.channel.DefaultChannelPipeline.callHandlerAdded0(DefaultChannelPipeline.java:609)
	at io.netty.channel.DefaultChannelPipeline.access$100(DefaultChannelPipeline.java:46)
	at io.netty.channel.DefaultChannelPipeline$PendingHandlerAddedTask.execute(DefaultChannelPipeline.java:1463)
	at io.netty.channel.DefaultChannelPipeline.callHandlerAddedForAllHandlers(DefaultChannelPipeline.java:1115)
	at io.netty.channel.DefaultChannelPipeline.invokeHandlerAddedIfNeeded(DefaultChannelPipeline.java:650)
	at io.netty.channel.AbstractChannel$AbstractUnsafe.register0(AbstractChannel.java:514)
	at io.netty.channel.AbstractChannel$AbstractUnsafe.access$200(AbstractChannel.java:429)
	at io.netty.channel.AbstractChannel$AbstractUnsafe$1.run(AbstractChannel.java:486)
	at io.netty.util.concurrent.AbstractEventExecutor.runTask$$$capture(AbstractEventExecutor.java:173)
	at io.netty.util.concurrent.AbstractEventExecutor.runTask(AbstractEventExecutor.java)
	at io.netty.util.concurrent.AbstractEventExecutor.safeExecute$$$capture(AbstractEventExecutor.java:166)
	at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java)
	at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:470)
	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:569)
	at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997)
	at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
	at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: java.lang.IllegalArgumentException: Server name value of host_name cannot have the trailing dot
	at java.base/javax.net.ssl.SNIHostName.checkHostName(SNIHostName.java:320)
	at java.base/javax.net.ssl.SNIHostName.<init>(SNIHostName.java:108)
	at io.r2dbc.postgresql.PostgresqlConnectionConfiguration$Builder.appendSniHost(PostgresqlConnectionConfiguration.java:1201)
	at io.r2dbc.postgresql.PostgresqlConnectionConfiguration$Builder.lambda$getSslParametersFactory$3(PostgresqlConnectionConfiguration.java:1189)
	at io.r2dbc.postgresql.client.AbstractPostgresSSLHandlerAdapter.<init>(AbstractPostgresSSLHandlerAdapter.java:50)
	at io.r2dbc.postgresql.client.SSLSessionHandlerAdapter.<init>(SSLSessionHandlerAdapter.java:41)
	at io.r2dbc.postgresql.client.ReactorNettyClient.registerSslHandler(ReactorNettyClient.java:416)
	... 23 common frames omitted
io.r2dbc.postgresql.PostgresqlConnectionFactory$PostgresConnectionException: [08003] Cannot connect to database.internal./<unresolved>:5432
	at io.r2dbc.postgresql.PostgresqlConnectionFactory.cannotConnect(PostgresqlConnectionFactory.java:188)
	at io.r2dbc.postgresql.PostgresqlConnectionFactory.lambda$doCreateConnection$7(PostgresqlConnectionFactory.java:153)
	at reactor.core.publisher.Mono.lambda$onErrorMap$28(Mono.java:3783)
	at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onError(FluxOnErrorResume.java:94)
	at reactor.core.publisher.MonoFlatMap$FlatMapMain.onError(MonoFlatMap.java:180)
	at reactor.core.publisher.MonoDelayUntil$DelayUntilCoordinator.onError(MonoDelayUntil.java:200)
	at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onError(FluxMapFuseable.java:142)
	at reactor.core.publisher.MonoFlatMap$FlatMapMain.onError(MonoFlatMap.java:180)
	at reactor.core.publisher.MonoCreate$DefaultMonoSink.error(MonoCreate.java:201)
	at reactor.netty.resources.NewConnectionProvider$DisposableConnect.onError(NewConnectionProvider.java:156)
	at reactor.core.publisher.MonoFlatMap$FlatMapMain.secondError(MonoFlatMap.java:241)
Caused by: io.netty.channel.StacklessClosedChannelException
	at io.netty.channel.AbstractChannel$AbstractUnsafe.ensureOpen(ChannelPromise)(Unknown Source)

Steps to reproduce

Use a hostname with a trailing .

Input Code
import io.r2dbc.postgresql.PostgresqlConnectionConfiguration
import io.r2dbc.postgresql.PostgresqlConnectionFactory
import io.r2dbc.postgresql.client.SSLMode

val config =
    PostgresqlConnectionConfiguration.builder()
        .host("database.internal.")
        .port(5432)
        .database("reporting")
        .username("user")
        .password("xxxx")
        .sslMode(SSLMode.REQUIRE)
        .build()
val factory = PostgresqlConnectionFactory(config)

factory.create().block()

Expected behavior/code

I expected the new 1.0.5 version to work like 1.0.4. But my hostnames conflicted with the new SNI feature.

Possible Solution

Configuring SNI to OFF works fine.

Extend SSLConfig.isValidSniHostname function to check for trailing . like SNIHostName does.

Additional context

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions