summaryrefslogtreecommitdiff
path: root/misc.c
diff options
context:
space:
mode:
authordjm@openbsd.org <djm@openbsd.org>2018-12-27 03:25:24 +0000
committerDamien Miller <djm@mindrot.org>2018-12-27 14:38:22 +1100
commit0a843d9a0e805f14653a555f5c7a8ba99d62c12d (patch)
tree481f36e9fd1918be5449e369a97c086a1a8d2432 /misc.c
parent434b587afe41c19391821e7392005068fda76248 (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.c77
1 files changed, 76 insertions, 1 deletions
diff --git a/misc.c b/misc.c
index 275e68141..bfd786ef8 100644
--- a/misc.c
+++ b/misc.c
@@ -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 */
243int
244waitrfd(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 */
277int
278timeout_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 "\""