From 6f5388d11ca7552025496dc1e465ad003e94f27e Mon Sep 17 00:00:00 2001 From: deraadt <> Date: Tue, 2 Dec 2014 19:44:49 +0000 Subject: convert select() to poll(). This is one of the most complicated conversions in the tree, because the original code is very rotten and fragile. Please test and report any failures. Assistance from millert, bcook, and jsing. --- src/usr.bin/openssl/s_client.c | 67 ++++++++++++++++++++++++++---------------- 1 file changed, 41 insertions(+), 26 deletions(-) (limited to 'src/usr.bin/openssl/s_client.c') diff --git a/src/usr.bin/openssl/s_client.c b/src/usr.bin/openssl/s_client.c index 988d799b97..94e24dacaa 100644 --- a/src/usr.bin/openssl/s_client.c +++ b/src/usr.bin/openssl/s_client.c @@ -1,4 +1,4 @@ -/* $OpenBSD: s_client.c,v 1.8 2014/11/18 20:54:28 krw Exp $ */ +/* $OpenBSD: s_client.c,v 1.9 2014/12/02 19:44:49 deraadt Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -137,7 +137,6 @@ #include #include -#include #include #include @@ -150,6 +149,7 @@ #include #include #include +#include #include "apps.h" @@ -334,11 +334,10 @@ s_client_main(int argc, char **argv) { unsigned int off = 0, clr = 0; SSL *con = NULL; - int s, k, width, state = 0, af = AF_UNSPEC; + int s, k, state = 0, af = AF_UNSPEC; char *cbuf = NULL, *sbuf = NULL, *mbuf = NULL; int cbuf_len, cbuf_off; int sbuf_len, sbuf_off; - fd_set readfds, writefds; char *port = PORT_STR; int full_log = 1; char *host = SSL_HOST_NAME; @@ -361,7 +360,7 @@ s_client_main(int argc, char **argv) int socket_type = SOCK_STREAM; BIO *sbio; int mbuf_len = 0; - struct timeval timeout, *timeoutp; + struct timeval timeout; const char *errstr = NULL; #ifndef OPENSSL_NO_ENGINE char *engine_id = NULL; @@ -874,8 +873,6 @@ re_start: SSL_set_connect_state(con); /* ok, lets connect */ - width = SSL_get_fd(con) + 1; - read_tty = 1; write_tty = 0; tty_on = 0; @@ -991,14 +988,12 @@ re_start: mbuf[0] = 0; } for (;;) { - FD_ZERO(&readfds); - FD_ZERO(&writefds); + struct pollfd pfd[3]; /* stdin, stdout, socket */ + int ptimeout = -1; if ((SSL_version(con) == DTLS1_VERSION) && DTLSv1_get_timeout(con, &timeout)) - timeoutp = &timeout; - else - timeoutp = NULL; + ptimeout = timeout.tv_sec * 1000 + timeout.tv_usec / 1000; if (SSL_in_init(con) && !SSL_total_renegotiations(con)) { in_init = 1; @@ -1038,24 +1033,31 @@ re_start: ssl_pending = read_ssl && SSL_pending(con); - /* XXX should add tests for fd_set overflow */ - + pfd[0].fd = -1; + pfd[1].fd = -1; if (!ssl_pending) { if (tty_on) { - if (read_tty) - FD_SET(fileno(stdin), &readfds); - if (write_tty) - FD_SET(fileno(stdout), &writefds); + if (read_tty) { + pfd[0].fd = fileno(stdin); + pfd[0].events = POLLIN; + } + if (write_tty) { + pfd[1].fd = fileno(stdout); + pfd[1].events = POLLOUT; + } } + + pfd[2].fd = SSL_get_fd(con); + pfd[2].events = 0; if (read_ssl) - FD_SET(SSL_get_fd(con), &readfds); + pfd[2].events |= POLLIN; if (write_ssl) - FD_SET(SSL_get_fd(con), &writefds); + pfd[2].events |= POLLOUT; + /* printf("mode tty(%d %d%d) ssl(%d%d)\n", tty_on,read_tty,write_tty,read_ssl,write_ssl);*/ - i = select(width, &readfds, &writefds, - NULL, timeoutp); + i = poll(pfd, 3, ptimeout); if (i < 0) { BIO_printf(bio_err, "bad select %d\n", errno); @@ -1066,7 +1068,11 @@ re_start: if ((SSL_version(con) == DTLS1_VERSION) && DTLSv1_handle_timeout(con) > 0) { BIO_printf(bio_err, "TIMEOUT occured\n"); } - if (!ssl_pending && FD_ISSET(SSL_get_fd(con), &writefds)) { + if (!ssl_pending && (pfd[2].revents & (POLLOUT|POLLERR|POLLNVAL))) { + if (pfd[2].revents & (POLLERR|POLLNVAL)) { + BIO_printf(bio_err, "poll error"); + goto shut; + } k = SSL_write(con, &(cbuf[cbuf_off]), (unsigned int) cbuf_len); switch (SSL_get_error(con, k)) { @@ -1123,7 +1129,12 @@ re_start: ERR_print_errors(bio_err); goto shut; } - } else if (!ssl_pending && FD_ISSET(fileno(stdout), &writefds)) { + } else if (!ssl_pending && + (pfd[1].revents & (POLLOUT|POLLERR|POLLNVAL))) { + if (pfd[1].revents & (POLLERR|POLLNVAL)) { + BIO_printf(bio_err, "poll error"); + goto shut; + } i = write(fileno(stdout), &(sbuf[sbuf_off]), sbuf_len); if (i <= 0) { @@ -1138,7 +1149,7 @@ re_start: read_ssl = 1; write_tty = 0; } - } else if (ssl_pending || FD_ISSET(SSL_get_fd(con), &readfds)) { + } else if (ssl_pending || (pfd[2].revents & (POLLIN|POLLHUP))) { #ifdef RENEG { static int iiii; @@ -1188,7 +1199,11 @@ re_start: goto shut; /* break; */ } - } else if (FD_ISSET(fileno(stdin), &readfds)) { + } else if (pfd[0].revents) { + if (pfd[0].revents & (POLLERR|POLLNVAL)) { + BIO_printf(bio_err, "poll error"); + goto shut; + } if (crlf) { int j, lf_num; -- cgit v1.2.3-55-g6feb