On Sun, May 30, 2021 at 02:31:55PM -0000, Stuart Henderson wrote:
> On 2021-05-30, Theo Buehler <[email protected]> wrote:
> > On Sat, May 29, 2021 at 10:37:18PM -0400, Daniel Jakots wrote:
> >> Hi,
> >>
> >> $ nc -zvc openbsd.org 443 # works as expected
> >> Connection to openbsd.org (129.128.5.194) 443 port [tcp/https] succeeded!
> >> TLS handshake negotiated TLSv1.3/AEAD-AES256-GCM-SHA384 with host
> >> openbsd.org
> >> [...]
> >>
> >> $ nc -zvc openbsd.org. 443 # fails
> >> Connection to openbsd.org. (129.128.5.194) 443 port [tcp/https] succeeded!
> >> nc: tls handshake failed (handshake failed: error:1404B42E:SSL
> >> routines:ST_CONNECT:tlsv1 alert protocol version)
> >
> > $ nc -cvz -e openbsd.org openbsd.org. 443 # works
> >
> > Unless -e is given, nc uses 'destination' in its server name indication
> > (SNI) extension. By its specification, (RFC 6066, section 3) the SNI
> > does not contain the trailing dot.
>
> Should something (libtls perhaps; ftp(1) is affected too) strip the dot?
> curl does handle this.
>
Unsure. If people really think this is useful and necessary, I can be
convinced. It's easy enough to do. And you're right, curl strips the
trailing dot after resolving a host name for SNI and HTTP host header.
I would be against doing it server side since contrary to sending IP
addresses it doesn't seem to be common, but doing this client side seems
innocuous.
Index: tls_client.c
===================================================================
RCS file: /cvs/src/lib/libtls/tls_client.c,v
retrieving revision 1.45
diff -u -p -r1.45 tls_client.c
--- tls_client.c 19 Mar 2018 16:34:47 -0000 1.45
+++ tls_client.c 30 May 2021 15:26:54 -0000
@@ -279,6 +279,7 @@ static int
tls_connect_common(struct tls *ctx, const char *servername)
{
union tls_addr addrbuf;
+ size_t servername_len;
int rv = -1;
if ((ctx->flags & TLS_CLIENT) == 0) {
@@ -291,6 +292,12 @@ tls_connect_common(struct tls *ctx, cons
tls_set_errorx(ctx, "out of memory");
goto err;
}
+
+ /* If there's a trailing dot, strip it. */
+ servername_len = strlen(servername);
+ if (servername_len > 0 &&
+ ctx->servername[servername_len - 1] == '.')
+ ctx->servername[servername_len - 1] = '\0';
}
if ((ctx->ssl_ctx = SSL_CTX_new(SSLv23_client_method())) == NULL) {
@@ -306,7 +313,7 @@ tls_connect_common(struct tls *ctx, cons
goto err;
if (ctx->config->verify_name) {
- if (servername == NULL) {
+ if (ctx->servername == NULL) {
tls_set_errorx(ctx, "server name not specified");
goto err;
}
@@ -353,10 +360,11 @@ tls_connect_common(struct tls *ctx, cons
* RFC4366 (SNI): Literal IPv4 and IPv6 addresses are not
* permitted in "HostName".
*/
- if (servername != NULL &&
- inet_pton(AF_INET, servername, &addrbuf) != 1 &&
- inet_pton(AF_INET6, servername, &addrbuf) != 1) {
- if (SSL_set_tlsext_host_name(ctx->ssl_conn, servername) == 0) {
+ if (ctx->servername != NULL &&
+ inet_pton(AF_INET, ctx->servername, &addrbuf) != 1 &&
+ inet_pton(AF_INET6, ctx->servername, &addrbuf) != 1) {
+ if (SSL_set_tlsext_host_name(ctx->ssl_conn,
+ ctx->servername) == 0) {
tls_set_errorx(ctx, "server name indication failure");
goto err;
}
Index: tls_server.c
===================================================================
RCS file: /cvs/src/lib/libtls/tls_server.c,v
retrieving revision 1.45
diff -u -p -r1.45 tls_server.c
--- tls_server.c 13 May 2019 22:36:01 -0000 1.45
+++ tls_server.c 30 May 2021 15:28:10 -0000
@@ -109,7 +109,7 @@ tls_servername_cb(SSL *ssl, int *al, voi
inet_pton(AF_INET6, name, &addrbuf) == 1)
return (SSL_TLSEXT_ERR_NOACK);
- free((char *)conn_ctx->servername);
+ free(conn_ctx->servername);
if ((conn_ctx->servername = strdup(name)) == NULL)
goto err;