diff options
| author | bluhm <> | 2017-02-08 13:43:33 +0000 |
|---|---|---|
| committer | bluhm <> | 2017-02-08 13:43:33 +0000 |
| commit | 22da9b1ce9d2622c9f1e478e15393cf54e1395fb (patch) | |
| tree | d04c8aec58d84cdb742cb37fc0e9f1ead8f6a1bd | |
| parent | aa3934f7783b0c9b04b6a76b332972ce4ce77e56 (diff) | |
| download | openbsd-22da9b1ce9d2622c9f1e478e15393cf54e1395fb.tar.gz openbsd-22da9b1ce9d2622c9f1e478e15393cf54e1395fb.tar.bz2 openbsd-22da9b1ce9d2622c9f1e478e15393cf54e1395fb.zip | |
Due to non-blocking sockets, tls_handshake() could wait in a busy
loop. Use an additional poll(2) during the handshake and also
respect the -w timeout option there.
From Shuo Chen; OK beck@
Diffstat (limited to '')
| -rw-r--r-- | src/usr.bin/nc/netcat.c | 63 |
1 files changed, 42 insertions, 21 deletions
diff --git a/src/usr.bin/nc/netcat.c b/src/usr.bin/nc/netcat.c index 5a6cb9dadd..8984e8f303 100644 --- a/src/usr.bin/nc/netcat.c +++ b/src/usr.bin/nc/netcat.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* $OpenBSD: netcat.c,v 1.172 2017/02/05 01:39:14 jca Exp $ */ | 1 | /* $OpenBSD: netcat.c,v 1.173 2017/02/08 13:43:33 bluhm Exp $ */ |
| 2 | /* | 2 | /* |
| 3 | * Copyright (c) 2001 Eric Jackson <ericj@monkey.org> | 3 | * Copyright (c) 2001 Eric Jackson <ericj@monkey.org> |
| 4 | * Copyright (c) 2015 Bob Beck. All rights reserved. | 4 | * Copyright (c) 2015 Bob Beck. All rights reserved. |
| @@ -121,6 +121,7 @@ int local_listen(char *, char *, struct addrinfo); | |||
| 121 | void readwrite(int, struct tls *); | 121 | void readwrite(int, struct tls *); |
| 122 | void fdpass(int nfd) __attribute__((noreturn)); | 122 | void fdpass(int nfd) __attribute__((noreturn)); |
| 123 | int remote_connect(const char *, const char *, struct addrinfo); | 123 | int remote_connect(const char *, const char *, struct addrinfo); |
| 124 | int timeout_handshake(int, struct tls *); | ||
| 124 | int timeout_connect(int, const struct sockaddr *, socklen_t); | 125 | int timeout_connect(int, const struct sockaddr *, socklen_t); |
| 125 | int socks_connect(const char *, const char *, struct addrinfo, | 126 | int socks_connect(const char *, const char *, struct addrinfo, |
| 126 | const char *, const char *, struct addrinfo, int, const char *); | 127 | const char *, const char *, struct addrinfo, int, const char *); |
| @@ -727,21 +728,48 @@ unix_bind(char *path, int flags) | |||
| 727 | return (s); | 728 | return (s); |
| 728 | } | 729 | } |
| 729 | 730 | ||
| 731 | int | ||
| 732 | timeout_handshake(int s, struct tls *tls_ctx) | ||
| 733 | { | ||
| 734 | struct pollfd pfd; | ||
| 735 | int ret; | ||
| 736 | |||
| 737 | while ((ret = tls_handshake(tls_ctx)) != 0) { | ||
| 738 | if (ret == TLS_WANT_POLLIN) | ||
| 739 | pfd.events = POLLIN; | ||
| 740 | else if (ret == TLS_WANT_POLLOUT) | ||
| 741 | pfd.events = POLLOUT; | ||
| 742 | else | ||
| 743 | break; | ||
| 744 | pfd.fd = s; | ||
| 745 | if ((ret = poll(&pfd, 1, timeout)) == 1) | ||
| 746 | continue; | ||
| 747 | else if (ret == 0) { | ||
| 748 | errno = ETIMEDOUT; | ||
| 749 | ret = -1; | ||
| 750 | break; | ||
| 751 | } else | ||
| 752 | err(1, "poll failed"); | ||
| 753 | } | ||
| 754 | |||
| 755 | return (ret); | ||
| 756 | } | ||
| 757 | |||
| 730 | void | 758 | void |
| 731 | tls_setup_client(struct tls *tls_ctx, int s, char *host) | 759 | tls_setup_client(struct tls *tls_ctx, int s, char *host) |
| 732 | { | 760 | { |
| 733 | int i; | 761 | const char *errstr; |
| 734 | 762 | ||
| 735 | if (tls_connect_socket(tls_ctx, s, | 763 | if (tls_connect_socket(tls_ctx, s, |
| 736 | tls_expectname ? tls_expectname : host) == -1) { | 764 | tls_expectname ? tls_expectname : host) == -1) { |
| 737 | errx(1, "tls connection failed (%s)", | 765 | errx(1, "tls connection failed (%s)", |
| 738 | tls_error(tls_ctx)); | 766 | tls_error(tls_ctx)); |
| 739 | } | 767 | } |
| 740 | do { | 768 | if (timeout_handshake(s, tls_ctx) == -1) { |
| 741 | if ((i = tls_handshake(tls_ctx)) == -1) | 769 | if ((errstr = tls_error(tls_ctx)) == NULL) |
| 742 | errx(1, "tls handshake failed (%s)", | 770 | errstr = strerror(errno); |
| 743 | tls_error(tls_ctx)); | 771 | errx(1, "tls handshake failed (%s)", errstr); |
| 744 | } while (i == TLS_WANT_POLLIN || i == TLS_WANT_POLLOUT); | 772 | } |
| 745 | if (vflag) | 773 | if (vflag) |
| 746 | report_tls(tls_ctx, host, tls_expectname); | 774 | report_tls(tls_ctx, host, tls_expectname); |
| 747 | if (tls_expecthash && tls_peer_cert_hash(tls_ctx) && | 775 | if (tls_expecthash && tls_peer_cert_hash(tls_ctx) && |
| @@ -753,22 +781,15 @@ struct tls * | |||
| 753 | tls_setup_server(struct tls *tls_ctx, int connfd, char *host) | 781 | tls_setup_server(struct tls *tls_ctx, int connfd, char *host) |
| 754 | { | 782 | { |
| 755 | struct tls *tls_cctx; | 783 | struct tls *tls_cctx; |
| 784 | const char *errstr; | ||
| 756 | 785 | ||
| 757 | if (tls_accept_socket(tls_ctx, &tls_cctx, | 786 | if (tls_accept_socket(tls_ctx, &tls_cctx, connfd) == -1) { |
| 758 | connfd) == -1) { | 787 | warnx("tls accept failed (%s)", tls_error(tls_ctx)); |
| 759 | warnx("tls accept failed (%s)", | 788 | } else if (timeout_handshake(connfd, tls_cctx) == -1) { |
| 760 | tls_error(tls_ctx)); | 789 | if ((errstr = tls_error(tls_ctx)) == NULL) |
| 761 | tls_cctx = NULL; | 790 | errstr = strerror(errno); |
| 791 | warnx("tls handshake failed (%s)", errstr); | ||
| 762 | } else { | 792 | } else { |
| 763 | int i; | ||
| 764 | |||
| 765 | do { | ||
| 766 | if ((i = tls_handshake(tls_cctx)) == -1) | ||
| 767 | warnx("tls handshake failed (%s)", | ||
| 768 | tls_error(tls_cctx)); | ||
| 769 | } while(i == TLS_WANT_POLLIN || i == TLS_WANT_POLLOUT); | ||
| 770 | } | ||
| 771 | if (tls_cctx) { | ||
| 772 | int gotcert = tls_peer_cert_provided(tls_cctx); | 793 | int gotcert = tls_peer_cert_provided(tls_cctx); |
| 773 | 794 | ||
| 774 | if (vflag && gotcert) | 795 | if (vflag && gotcert) |
