diff options
author | tb <> | 2021-06-01 20:14:17 +0000 |
---|---|---|
committer | tb <> | 2021-06-01 20:14:17 +0000 |
commit | 9e887183c2a90e6f5fe6b6767d78096483dd5345 (patch) | |
tree | b6a01471dc4ae0b369c7831798a6388d9723e393 | |
parent | d9330d78516c910d1d1883d9da890f600bce7a02 (diff) | |
download | openbsd-9e887183c2a90e6f5fe6b6767d78096483dd5345.tar.gz openbsd-9e887183c2a90e6f5fe6b6767d78096483dd5345.tar.bz2 openbsd-9e887183c2a90e6f5fe6b6767d78096483dd5345.zip |
Avoid sending a trailing dot in SNI as a client
While an FQDN includes a trailing dot for the zero-length label of
the root, SNI explicitly does not contain it. Contrary to other TLS
implementations, our tlsext_sni_is_valid_hostname() rejects a trailing
dot. The result is that LibreSSL TLS servers encountering an SNI with
trailing dot abort the connection with an illegal_parameter alert.
This fixes an issue reported by danj in nc(1) and by sthen in ftp(1).
DNS cluebat from florian.
ok jsing
-rw-r--r-- | src/lib/libtls/tls_client.c | 25 |
1 files changed, 19 insertions, 6 deletions
diff --git a/src/lib/libtls/tls_client.c b/src/lib/libtls/tls_client.c index 04e44020ef..701bb6fc81 100644 --- a/src/lib/libtls/tls_client.c +++ b/src/lib/libtls/tls_client.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: tls_client.c,v 1.45 2018/03/19 16:34:47 jsing Exp $ */ | 1 | /* $OpenBSD: tls_client.c,v 1.46 2021/06/01 20:14:17 tb Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2014 Joel Sing <jsing@openbsd.org> | 3 | * Copyright (c) 2014 Joel Sing <jsing@openbsd.org> |
4 | * | 4 | * |
@@ -279,6 +279,7 @@ static int | |||
279 | tls_connect_common(struct tls *ctx, const char *servername) | 279 | tls_connect_common(struct tls *ctx, const char *servername) |
280 | { | 280 | { |
281 | union tls_addr addrbuf; | 281 | union tls_addr addrbuf; |
282 | size_t servername_len; | ||
282 | int rv = -1; | 283 | int rv = -1; |
283 | 284 | ||
284 | if ((ctx->flags & TLS_CLIENT) == 0) { | 285 | if ((ctx->flags & TLS_CLIENT) == 0) { |
@@ -291,6 +292,17 @@ tls_connect_common(struct tls *ctx, const char *servername) | |||
291 | tls_set_errorx(ctx, "out of memory"); | 292 | tls_set_errorx(ctx, "out of memory"); |
292 | goto err; | 293 | goto err; |
293 | } | 294 | } |
295 | |||
296 | /* | ||
297 | * If there's a trailing dot, remove it. While an FQDN includes | ||
298 | * the terminating dot representing the zero-length label of | ||
299 | * the root (RFC 8499, section 2), the SNI explicitly does not | ||
300 | * include it (RFC 6066, section 3). | ||
301 | */ | ||
302 | servername_len = strlen(ctx->servername); | ||
303 | if (servername_len > 0 && | ||
304 | ctx->servername[servername_len - 1] == '.') | ||
305 | ctx->servername[servername_len - 1] = '\0'; | ||
294 | } | 306 | } |
295 | 307 | ||
296 | if ((ctx->ssl_ctx = SSL_CTX_new(SSLv23_client_method())) == NULL) { | 308 | if ((ctx->ssl_ctx = SSL_CTX_new(SSLv23_client_method())) == NULL) { |
@@ -306,7 +318,7 @@ tls_connect_common(struct tls *ctx, const char *servername) | |||
306 | goto err; | 318 | goto err; |
307 | 319 | ||
308 | if (ctx->config->verify_name) { | 320 | if (ctx->config->verify_name) { |
309 | if (servername == NULL) { | 321 | if (ctx->servername == NULL) { |
310 | tls_set_errorx(ctx, "server name not specified"); | 322 | tls_set_errorx(ctx, "server name not specified"); |
311 | goto err; | 323 | goto err; |
312 | } | 324 | } |
@@ -353,10 +365,11 @@ tls_connect_common(struct tls *ctx, const char *servername) | |||
353 | * RFC4366 (SNI): Literal IPv4 and IPv6 addresses are not | 365 | * RFC4366 (SNI): Literal IPv4 and IPv6 addresses are not |
354 | * permitted in "HostName". | 366 | * permitted in "HostName". |
355 | */ | 367 | */ |
356 | if (servername != NULL && | 368 | if (ctx->servername != NULL && |
357 | inet_pton(AF_INET, servername, &addrbuf) != 1 && | 369 | inet_pton(AF_INET, ctx->servername, &addrbuf) != 1 && |
358 | inet_pton(AF_INET6, servername, &addrbuf) != 1) { | 370 | inet_pton(AF_INET6, ctx->servername, &addrbuf) != 1) { |
359 | if (SSL_set_tlsext_host_name(ctx->ssl_conn, servername) == 0) { | 371 | if (SSL_set_tlsext_host_name(ctx->ssl_conn, |
372 | ctx->servername) == 0) { | ||
360 | tls_set_errorx(ctx, "server name indication failure"); | 373 | tls_set_errorx(ctx, "server name indication failure"); |
361 | goto err; | 374 | goto err; |
362 | } | 375 | } |