summaryrefslogtreecommitdiff
path: root/src/usr.bin/nc/netcat.c
diff options
context:
space:
mode:
authorbluhm <>2017-02-08 13:43:33 +0000
committerbluhm <>2017-02-08 13:43:33 +0000
commit25f0619016ce294504632b9617da6fbffe8a925b (patch)
treed04c8aec58d84cdb742cb37fc0e9f1ead8f6a1bd /src/usr.bin/nc/netcat.c
parent7015be7e487c936fda9b4981ba162c0cc1b837de (diff)
downloadopenbsd-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.c63
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);
121void readwrite(int, struct tls *); 121void readwrite(int, struct tls *);
122void fdpass(int nfd) __attribute__((noreturn)); 122void fdpass(int nfd) __attribute__((noreturn));
123int remote_connect(const char *, const char *, struct addrinfo); 123int remote_connect(const char *, const char *, struct addrinfo);
124int timeout_handshake(int, struct tls *);
124int timeout_connect(int, const struct sockaddr *, socklen_t); 125int timeout_connect(int, const struct sockaddr *, socklen_t);
125int socks_connect(const char *, const char *, struct addrinfo, 126int 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
731int
732timeout_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
730void 758void
731tls_setup_client(struct tls *tls_ctx, int s, char *host) 759tls_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 *
753tls_setup_server(struct tls *tls_ctx, int connfd, char *host) 781tls_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)