diff options
author | bluhm <> | 2017-02-08 13:43:33 +0000 |
---|---|---|
committer | bluhm <> | 2017-02-08 13:43:33 +0000 |
commit | 25f0619016ce294504632b9617da6fbffe8a925b (patch) | |
tree | d04c8aec58d84cdb742cb37fc0e9f1ead8f6a1bd /src/usr.bin/nc/netcat.c | |
parent | 7015be7e487c936fda9b4981ba162c0cc1b837de (diff) | |
download | openbsd-25f0619016ce294504632b9617da6fbffe8a925b.tar.gz openbsd-25f0619016ce294504632b9617da6fbffe8a925b.tar.bz2 openbsd-25f0619016ce294504632b9617da6fbffe8a925b.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 'src/usr.bin/nc/netcat.c')
-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) |