From e3007dfe8b6f9c414674ca596b22b52af74051d4 Mon Sep 17 00:00:00 2001 From: guenther Date: Thu, 8 Oct 2015 20:13:45 +0000 Subject: [PATCH] If getaddrinfo() succeeds, then don't try look ups with other flags, even if the connect()s failed. In concert with some resolver fixes in libc, this lets ntpd be tame()ed problem isolated by theo, who had fun untangling the libc and libtls behaviors to place blame for not being able to tame ntpd ok beck@ deraadt@ jsing@ --- lib/libtls/tls_client.c | 80 ++++++++++++++++++++--------------------- 1 file changed, 39 insertions(+), 41 deletions(-) diff --git a/lib/libtls/tls_client.c b/lib/libtls/tls_client.c index af1b05ab713..68b0f32226f 100644 --- a/lib/libtls/tls_client.c +++ b/lib/libtls/tls_client.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tls_client.c,v 1.30 2015/09/29 13:10:53 jsing Exp $ */ +/* $OpenBSD: tls_client.c,v 1.31 2015/10/08 20:13:45 guenther Exp $ */ /* * Copyright (c) 2014 Joel Sing * @@ -44,42 +44,6 @@ tls_client(void) return (ctx); } -static int -tls_connect_host(struct tls *ctx, const char *host, const char *port, - int af, int flag) -{ - struct addrinfo hints, *res, *res0; - int s = -1; - - memset(&hints, 0, sizeof(hints)); - hints.ai_family = af; - hints.ai_socktype = SOCK_STREAM; - hints.ai_flags = flag; - - if ((s = getaddrinfo(host, port, &hints, &res0)) != 0) { - tls_set_error(ctx, "%s", gai_strerror(s)); - return (-1); - } - for (res = res0; res; res = res->ai_next) { - s = socket(res->ai_family, res->ai_socktype, res->ai_protocol); - if (s == -1) { - tls_set_error(ctx, "socket"); - continue; - } - if (connect(s, res->ai_addr, res->ai_addrlen) == -1) { - tls_set_error(ctx, "connect"); - close(s); - s = -1; - continue; - } - - break; /* Connected. */ - } - freeaddrinfo(res0); - - return (s); -} - int tls_connect(struct tls *ctx, const char *host, const char *port) { @@ -90,6 +54,7 @@ int tls_connect_servername(struct tls *ctx, const char *host, const char *port, const char *servername) { + struct addrinfo hints, *res, *res0; const char *h = NULL, *p = NULL; char *hs = NULL, *ps = NULL; int rv = -1, s = -1, ret; @@ -132,10 +97,43 @@ tls_connect_servername(struct tls *ctx, const char *host, const char *port, * sure that connection attempts to numeric addresses and especially * 127.0.0.1 or ::1 loopback addresses are always possible. */ - if ((s = tls_connect_host(ctx, h, p, AF_INET, AI_NUMERICHOST)) == -1 && - (s = tls_connect_host(ctx, h, p, AF_INET6, AI_NUMERICHOST)) == -1 && - (s = tls_connect_host(ctx, h, p, AF_UNSPEC, AI_ADDRCONFIG)) == -1) - goto err; + memset(&hints, 0, sizeof(hints)); + hints.ai_socktype = SOCK_STREAM; + + /* try as an IPv4 literal */ + hints.ai_family = AF_INET; + hints.ai_flags = AI_NUMERICHOST; + if (getaddrinfo(h, p, &hints, &res0) != 0) { + /* try again as an IPv6 literal */ + hints.ai_family = AF_INET6; + if (getaddrinfo(h, p, &hints, &res0) != 0) { + /* last try, with name resolution and save the error */ + hints.ai_family = AF_UNSPEC; + hints.ai_flags = AI_ADDRCONFIG; + if ((s = getaddrinfo(h, p, &hints, &res0)) != 0) { + tls_set_error(ctx, "%s", gai_strerror(s)); + goto err; + } + } + } + + /* It was resolved somehow; now try connecting to what we got */ + for (res = res0; res; res = res->ai_next) { + s = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + if (s == -1) { + tls_set_error(ctx, "socket"); + continue; + } + if (connect(s, res->ai_addr, res->ai_addrlen) == -1) { + tls_set_error(ctx, "connect"); + close(s); + s = -1; + continue; + } + + break; /* Connected. */ + } + freeaddrinfo(res0); if (servername == NULL) servername = h; -- 2.20.1