diff options
author | Theo de Raadt <deraadt@cvs.openbsd.org> | 2014-12-02 19:44:50 +0000 |
---|---|---|
committer | Theo de Raadt <deraadt@cvs.openbsd.org> | 2014-12-02 19:44:50 +0000 |
commit | eed9dcb825905471e4cc4a3f1e2570d610554c79 (patch) | |
tree | 9ddbd7ee27cfdb0305b16ee18dd88eff028162b0 | |
parent | 1f7da40c302ab4440dc517e5cd98755d8a334664 (diff) |
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.
-rw-r--r-- | usr.bin/openssl/s_client.c | 67 | ||||
-rw-r--r-- | usr.bin/openssl/s_server.c | 36 |
2 files changed, 63 insertions, 40 deletions
diff --git a/usr.bin/openssl/s_client.c b/usr.bin/openssl/s_client.c index 988d799b97c..94e24dacaae 100644 --- a/usr.bin/openssl/s_client.c +++ b/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 <sys/types.h> #include <sys/ioctl.h> -#include <sys/select.h> #include <sys/socket.h> #include <netinet/in.h> @@ -150,6 +149,7 @@ #include <stdlib.h> #include <string.h> #include <unistd.h> +#include <poll.h> #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; diff --git a/usr.bin/openssl/s_server.c b/usr.bin/openssl/s_server.c index 1e6f85f9fbb..b3cdb30a61f 100644 --- a/usr.bin/openssl/s_server.c +++ b/usr.bin/openssl/s_server.c @@ -1,4 +1,4 @@ -/* $OpenBSD: s_server.c,v 1.6 2014/11/06 14:50:12 jsing Exp $ */ +/* $OpenBSD: s_server.c,v 1.7 2014/12/02 19:44:49 deraadt Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -148,7 +148,6 @@ #include <sys/types.h> #include <sys/ioctl.h> -#include <sys/select.h> #include <sys/socket.h> #include <assert.h> @@ -158,6 +157,7 @@ #include <limits.h> #include <string.h> #include <unistd.h> +#include <poll.h> #include "apps.h" @@ -1279,14 +1279,12 @@ static int sv_body(char *hostname, int s, unsigned char *context) { char *buf = NULL; - fd_set readfds; - int ret = 1, width; + int ret = 1; int k, i; unsigned long l; SSL *con = NULL; BIO *sbio; struct timeval timeout; - struct timeval *timeoutp; if ((buf = malloc(bufsize)) == NULL) { BIO_printf(bio_err, "out of memory\n"); @@ -1366,35 +1364,45 @@ sv_body(char *hostname, int s, unsigned char *context) SSL_set_tlsext_debug_arg(con, bio_s_out); } - width = s + 1; for (;;) { int read_from_terminal; int read_from_sslcon; + struct pollfd pfd[2]; + int ptimeout; read_from_terminal = 0; read_from_sslcon = SSL_pending(con); if (!read_from_sslcon) { - FD_ZERO(&readfds); - FD_SET(fileno(stdin), &readfds); - FD_SET(s, &readfds); + pfd[0].fd = fileno(stdin); + pfd[0].events = POLLIN; + pfd[1].fd = s; + pfd[1].events = POLLIN; + if ((SSL_version(con) == DTLS1_VERSION) && DTLSv1_get_timeout(con, &timeout)) - timeoutp = &timeout; + ptimeout = timeout.tv_sec * 1000 + + timeout.tv_usec / 1000; else - timeoutp = NULL; + ptimeout = -1; - i = select(width, &readfds, NULL, NULL, timeoutp); + i = poll(pfd, 2, ptimeout); if ((SSL_version(con) == DTLS1_VERSION) && DTLSv1_handle_timeout(con) > 0) { BIO_printf(bio_err, "TIMEOUT occured\n"); } if (i <= 0) continue; - if (FD_ISSET(fileno(stdin), &readfds)) + if (pfd[0].revents) { + if ((pfd[0].revents & (POLLERR|POLLNVAL))) + continue; read_from_terminal = 1; - if (FD_ISSET(s, &readfds)) + } + if (pfd[1].revents) { + if ((pfd[1].revents & (POLLERR|POLLNVAL))) + continue; read_from_sslcon = 1; + } } if (read_from_terminal) { if (s_crlf) { |