diff options
author | guenther <> | 2015-10-08 20:13:45 +0000 |
---|---|---|
committer | guenther <> | 2015-10-08 20:13:45 +0000 |
commit | 92b71dd957251375dfc9dbd99f6bf56b6d38859f (patch) | |
tree | 5f7853a5034e4a35bd5516dde7eb47278631871f /src | |
parent | da19b923ec32060e1d52bb5b8ccfbe22ba01f96f (diff) | |
download | openbsd-92b71dd957251375dfc9dbd99f6bf56b6d38859f.tar.gz openbsd-92b71dd957251375dfc9dbd99f6bf56b6d38859f.tar.bz2 openbsd-92b71dd957251375dfc9dbd99f6bf56b6d38859f.zip |
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@
Diffstat (limited to 'src')
-rw-r--r-- | src/lib/libtls/tls_client.c | 80 |
1 files changed, 39 insertions, 41 deletions
diff --git a/src/lib/libtls/tls_client.c b/src/lib/libtls/tls_client.c index af1b05ab71..68b0f32226 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.30 2015/09/29 13:10:53 jsing Exp $ */ | 1 | /* $OpenBSD: tls_client.c,v 1.31 2015/10/08 20:13:45 guenther Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2014 Joel Sing <jsing@openbsd.org> | 3 | * Copyright (c) 2014 Joel Sing <jsing@openbsd.org> |
4 | * | 4 | * |
@@ -44,42 +44,6 @@ tls_client(void) | |||
44 | return (ctx); | 44 | return (ctx); |
45 | } | 45 | } |
46 | 46 | ||
47 | static int | ||
48 | tls_connect_host(struct tls *ctx, const char *host, const char *port, | ||
49 | int af, int flag) | ||
50 | { | ||
51 | struct addrinfo hints, *res, *res0; | ||
52 | int s = -1; | ||
53 | |||
54 | memset(&hints, 0, sizeof(hints)); | ||
55 | hints.ai_family = af; | ||
56 | hints.ai_socktype = SOCK_STREAM; | ||
57 | hints.ai_flags = flag; | ||
58 | |||
59 | if ((s = getaddrinfo(host, port, &hints, &res0)) != 0) { | ||
60 | tls_set_error(ctx, "%s", gai_strerror(s)); | ||
61 | return (-1); | ||
62 | } | ||
63 | for (res = res0; res; res = res->ai_next) { | ||
64 | s = socket(res->ai_family, res->ai_socktype, res->ai_protocol); | ||
65 | if (s == -1) { | ||
66 | tls_set_error(ctx, "socket"); | ||
67 | continue; | ||
68 | } | ||
69 | if (connect(s, res->ai_addr, res->ai_addrlen) == -1) { | ||
70 | tls_set_error(ctx, "connect"); | ||
71 | close(s); | ||
72 | s = -1; | ||
73 | continue; | ||
74 | } | ||
75 | |||
76 | break; /* Connected. */ | ||
77 | } | ||
78 | freeaddrinfo(res0); | ||
79 | |||
80 | return (s); | ||
81 | } | ||
82 | |||
83 | int | 47 | int |
84 | tls_connect(struct tls *ctx, const char *host, const char *port) | 48 | tls_connect(struct tls *ctx, const char *host, const char *port) |
85 | { | 49 | { |
@@ -90,6 +54,7 @@ int | |||
90 | tls_connect_servername(struct tls *ctx, const char *host, const char *port, | 54 | tls_connect_servername(struct tls *ctx, const char *host, const char *port, |
91 | const char *servername) | 55 | const char *servername) |
92 | { | 56 | { |
57 | struct addrinfo hints, *res, *res0; | ||
93 | const char *h = NULL, *p = NULL; | 58 | const char *h = NULL, *p = NULL; |
94 | char *hs = NULL, *ps = NULL; | 59 | char *hs = NULL, *ps = NULL; |
95 | int rv = -1, s = -1, ret; | 60 | int rv = -1, s = -1, ret; |
@@ -132,10 +97,43 @@ tls_connect_servername(struct tls *ctx, const char *host, const char *port, | |||
132 | * sure that connection attempts to numeric addresses and especially | 97 | * sure that connection attempts to numeric addresses and especially |
133 | * 127.0.0.1 or ::1 loopback addresses are always possible. | 98 | * 127.0.0.1 or ::1 loopback addresses are always possible. |
134 | */ | 99 | */ |
135 | if ((s = tls_connect_host(ctx, h, p, AF_INET, AI_NUMERICHOST)) == -1 && | 100 | memset(&hints, 0, sizeof(hints)); |
136 | (s = tls_connect_host(ctx, h, p, AF_INET6, AI_NUMERICHOST)) == -1 && | 101 | hints.ai_socktype = SOCK_STREAM; |
137 | (s = tls_connect_host(ctx, h, p, AF_UNSPEC, AI_ADDRCONFIG)) == -1) | 102 | |
138 | goto err; | 103 | /* try as an IPv4 literal */ |
104 | hints.ai_family = AF_INET; | ||
105 | hints.ai_flags = AI_NUMERICHOST; | ||
106 | if (getaddrinfo(h, p, &hints, &res0) != 0) { | ||
107 | /* try again as an IPv6 literal */ | ||
108 | hints.ai_family = AF_INET6; | ||
109 | if (getaddrinfo(h, p, &hints, &res0) != 0) { | ||
110 | /* last try, with name resolution and save the error */ | ||
111 | hints.ai_family = AF_UNSPEC; | ||
112 | hints.ai_flags = AI_ADDRCONFIG; | ||
113 | if ((s = getaddrinfo(h, p, &hints, &res0)) != 0) { | ||
114 | tls_set_error(ctx, "%s", gai_strerror(s)); | ||
115 | goto err; | ||
116 | } | ||
117 | } | ||
118 | } | ||
119 | |||
120 | /* It was resolved somehow; now try connecting to what we got */ | ||
121 | for (res = res0; res; res = res->ai_next) { | ||
122 | s = socket(res->ai_family, res->ai_socktype, res->ai_protocol); | ||
123 | if (s == -1) { | ||
124 | tls_set_error(ctx, "socket"); | ||
125 | continue; | ||
126 | } | ||
127 | if (connect(s, res->ai_addr, res->ai_addrlen) == -1) { | ||
128 | tls_set_error(ctx, "connect"); | ||
129 | close(s); | ||
130 | s = -1; | ||
131 | continue; | ||
132 | } | ||
133 | |||
134 | break; /* Connected. */ | ||
135 | } | ||
136 | freeaddrinfo(res0); | ||
139 | 137 | ||
140 | if (servername == NULL) | 138 | if (servername == NULL) |
141 | servername = h; | 139 | servername = h; |