diff options
author | djm@openbsd.org <djm@openbsd.org> | 2018-12-27 03:25:24 +0000 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2018-12-27 14:38:22 +1100 |
commit | 0a843d9a0e805f14653a555f5c7a8ba99d62c12d (patch) | |
tree | 481f36e9fd1918be5449e369a97c086a1a8d2432 /misc.c | |
parent | 434b587afe41c19391821e7392005068fda76248 (diff) |
upstream: move client/server SSH-* banners to buffers under
ssh->kex and factor out the banner exchange. This eliminates some common code
from the client and server.
Also be more strict about handling \r characters - these should only
be accepted immediately before \n (pointed out by Jann Horn).
Inspired by a patch from Markus Schmidt.
(lots of) feedback and ok markus@
OpenBSD-Commit-ID: 1cc7885487a6754f63641d7d3279b0941890275b
Diffstat (limited to 'misc.c')
-rw-r--r-- | misc.c | 77 |
1 files changed, 76 insertions, 1 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: misc.c,v 1.135 2018/12/07 04:36:09 dtucker Exp $ */ | 1 | /* $OpenBSD: misc.c,v 1.136 2018/12/27 03:25:25 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. |
4 | * Copyright (c) 2005,2006 Damien Miller. All rights reserved. | 4 | * Copyright (c) 2005,2006 Damien Miller. All rights reserved. |
@@ -38,6 +38,7 @@ | |||
38 | #ifdef HAVE_LIBGEN_H | 38 | #ifdef HAVE_LIBGEN_H |
39 | # include <libgen.h> | 39 | # include <libgen.h> |
40 | #endif | 40 | #endif |
41 | #include <poll.h> | ||
41 | #include <signal.h> | 42 | #include <signal.h> |
42 | #include <stdarg.h> | 43 | #include <stdarg.h> |
43 | #include <stdio.h> | 44 | #include <stdio.h> |
@@ -234,6 +235,80 @@ set_rdomain(int fd, const char *name) | |||
234 | #endif | 235 | #endif |
235 | } | 236 | } |
236 | 237 | ||
238 | /* | ||
239 | * Wait up to *timeoutp milliseconds for fd to be readable. Updates | ||
240 | * *timeoutp with time remaining. | ||
241 | * Returns 0 if fd ready or -1 on timeout or error (see errno). | ||
242 | */ | ||
243 | int | ||
244 | waitrfd(int fd, int *timeoutp) | ||
245 | { | ||
246 | struct pollfd pfd; | ||
247 | struct timeval t_start; | ||
248 | int oerrno, r; | ||
249 | |||
250 | monotime_tv(&t_start); | ||
251 | pfd.fd = fd; | ||
252 | pfd.events = POLLIN; | ||
253 | for (; *timeoutp >= 0;) { | ||
254 | r = poll(&pfd, 1, *timeoutp); | ||
255 | oerrno = errno; | ||
256 | ms_subtract_diff(&t_start, timeoutp); | ||
257 | errno = oerrno; | ||
258 | if (r > 0) | ||
259 | return 0; | ||
260 | else if (r == -1 && errno != EAGAIN) | ||
261 | return -1; | ||
262 | else if (r == 0) | ||
263 | break; | ||
264 | } | ||
265 | /* timeout */ | ||
266 | errno = ETIMEDOUT; | ||
267 | return -1; | ||
268 | } | ||
269 | |||
270 | /* | ||
271 | * Attempt a non-blocking connect(2) to the specified address, waiting up to | ||
272 | * *timeoutp milliseconds for the connection to complete. If the timeout is | ||
273 | * <=0, then wait indefinitely. | ||
274 | * | ||
275 | * Returns 0 on success or -1 on failure. | ||
276 | */ | ||
277 | int | ||
278 | timeout_connect(int sockfd, const struct sockaddr *serv_addr, | ||
279 | socklen_t addrlen, int *timeoutp) | ||
280 | { | ||
281 | int optval = 0; | ||
282 | socklen_t optlen = sizeof(optval); | ||
283 | |||
284 | /* No timeout: just do a blocking connect() */ | ||
285 | if (timeoutp == NULL || *timeoutp <= 0) | ||
286 | return connect(sockfd, serv_addr, addrlen); | ||
287 | |||
288 | set_nonblock(sockfd); | ||
289 | if (connect(sockfd, serv_addr, addrlen) == 0) { | ||
290 | /* Succeeded already? */ | ||
291 | unset_nonblock(sockfd); | ||
292 | return 0; | ||
293 | } else if (errno != EINPROGRESS) | ||
294 | return -1; | ||
295 | |||
296 | if (waitrfd(sockfd, timeoutp) == -1) | ||
297 | return -1; | ||
298 | |||
299 | /* Completed or failed */ | ||
300 | if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &optval, &optlen) == -1) { | ||
301 | debug("getsockopt: %s", strerror(errno)); | ||
302 | return -1; | ||
303 | } | ||
304 | if (optval != 0) { | ||
305 | errno = optval; | ||
306 | return -1; | ||
307 | } | ||
308 | unset_nonblock(sockfd); | ||
309 | return 0; | ||
310 | } | ||
311 | |||
237 | /* Characters considered whitespace in strsep calls. */ | 312 | /* Characters considered whitespace in strsep calls. */ |
238 | #define WHITESPACE " \t\r\n" | 313 | #define WHITESPACE " \t\r\n" |
239 | #define QUOTE "\"" | 314 | #define QUOTE "\"" |