From 13035fa666c546330e9809691374e4fd0415eccc Mon Sep 17 00:00:00 2001 From: Brent Cook Date: Sat, 6 Dec 2014 11:20:56 -0600 Subject: simplify building the apps Makefile Remove extra machinery in favor of a plain-old Makefile.am. Tighten up what files are copied on build, package a simple openssl.cnf. --- apps/Makefile.am | 82 +++++++++++++ apps/Makefile.am.tpl | 21 ---- apps/poll.c | 334 --------------------------------------------------- apps/poll_win.c | 334 +++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 416 insertions(+), 355 deletions(-) create mode 100644 apps/Makefile.am delete mode 100644 apps/Makefile.am.tpl delete mode 100644 apps/poll.c create mode 100644 apps/poll_win.c (limited to 'apps') diff --git a/apps/Makefile.am b/apps/Makefile.am new file mode 100644 index 0000000..769a033 --- /dev/null +++ b/apps/Makefile.am @@ -0,0 +1,82 @@ +include $(top_srcdir)/Makefile.am.common + +bin_PROGRAMS = openssl + +openssl_CFLAGS = $(USER_CFLAGS) +openssl_LDADD = $(PLATFORM_LDADD) $(PROG_LDADD) +openssl_LDADD += $(top_builddir)/ssl/libssl.la +openssl_LDADD += $(top_builddir)/crypto/libcrypto.la + +openssl_SOURCES = apps.c +openssl_SOURCES += asn1pars.c +openssl_SOURCES += ca.c +openssl_SOURCES += ciphers.c +openssl_SOURCES += cms.c +openssl_SOURCES += crl.c +openssl_SOURCES += crl2p7.c +openssl_SOURCES += dgst.c +openssl_SOURCES += dh.c +openssl_SOURCES += dhparam.c +openssl_SOURCES += dsa.c +openssl_SOURCES += dsaparam.c +openssl_SOURCES += ec.c +openssl_SOURCES += ecparam.c +openssl_SOURCES += enc.c +openssl_SOURCES += engine.c +openssl_SOURCES += errstr.c +openssl_SOURCES += gendh.c +openssl_SOURCES += gendsa.c +openssl_SOURCES += genpkey.c +openssl_SOURCES += genrsa.c +openssl_SOURCES += nseq.c +openssl_SOURCES += ocsp.c +openssl_SOURCES += openssl.c +openssl_SOURCES += passwd.c +openssl_SOURCES += pkcs12.c +openssl_SOURCES += pkcs7.c +openssl_SOURCES += pkcs8.c +openssl_SOURCES += pkey.c +openssl_SOURCES += pkeyparam.c +openssl_SOURCES += pkeyutl.c +openssl_SOURCES += prime.c +openssl_SOURCES += rand.c +openssl_SOURCES += req.c +openssl_SOURCES += rsa.c +openssl_SOURCES += rsautl.c +openssl_SOURCES += s_cb.c +openssl_SOURCES += s_client.c +openssl_SOURCES += s_server.c +openssl_SOURCES += s_socket.c +openssl_SOURCES += s_time.c +openssl_SOURCES += sess_id.c +openssl_SOURCES += smime.c +openssl_SOURCES += speed.c +openssl_SOURCES += spkac.c +openssl_SOURCES += ts.c +openssl_SOURCES += verify.c +openssl_SOURCES += version.c +openssl_SOURCES += x509.c + +if HOST_WIN +openssl_SOURCES += apps_win.c +else +openssl_SOURCES += apps_posix.c +endif + +if !HAVE_POLL +if HOST_WIN +openssl_SOURCES += poll_win.c +endif +endif + +if !HAVE_STRTONUM +openssl_SOURCES += strtonum.c +endif + +noinst_HEADERS = apps.h +noinst_HEADERS += progs.h +noinst_HEADERS += s_apps.h +noinst_HEADERS += testdsa.h +noinst_HEADERS += testrsa.h +noinst_HEADERS += timeouts.h +noinst_HEADERS += openssl.cnf diff --git a/apps/Makefile.am.tpl b/apps/Makefile.am.tpl deleted file mode 100644 index 16b3d8b..0000000 --- a/apps/Makefile.am.tpl +++ /dev/null @@ -1,21 +0,0 @@ -include $(top_srcdir)/Makefile.am.common - -bin_PROGRAMS = openssl - -openssl_CFLAGS = $(USER_CFLAGS) -openssl_LDADD = $(PLATFORM_LDADD) $(PROG_LDADD) -openssl_LDADD += $(top_builddir)/ssl/libssl.la -openssl_LDADD += $(top_builddir)/crypto/libcrypto.la - -openssl_SOURCES = -noinst_HEADERS = - -if !HAVE_STRTONUM -openssl_SOURCES += strtonum.c -endif - -if !HAVE_POLL -if HOST_WIN -openssl_SOURCES += poll.c -endif -endif diff --git a/apps/poll.c b/apps/poll.c deleted file mode 100644 index bf30ccf..0000000 --- a/apps/poll.c +++ /dev/null @@ -1,334 +0,0 @@ -/* - * Public domain - * - * poll(2) emulation for Windows - * - * This emulates just-enough poll functionality on Windows to work in the - * context of the openssl(1) program. This is not a replacement for - * POSIX.1-2001 poll(2), though it may come closer than I care to admit. - * - * Dongsheng Song - * Brent Cook - */ - -#include -#include -#include -#include -#include - -static int -conn_is_closed(int fd) -{ - char buf[1]; - int ret = recv(fd, buf, 1, MSG_PEEK); - if (ret == -1) { - switch (WSAGetLastError()) { - case WSAECONNABORTED: - case WSAECONNRESET: - case WSAENETRESET: - case WSAESHUTDOWN: - return 1; - } - } - return 0; -} - -static int -conn_has_oob_data(int fd) -{ - char buf[1]; - return (recv(fd, buf, 1, MSG_PEEK | MSG_OOB) == 1); -} - -static int -is_socket(int fd) -{ - WSANETWORKEVENTS events; - return (WSAEnumNetworkEvents((SOCKET)fd, NULL, &events) == 0); -} - -static int -compute_select_revents(int fd, short events, - fd_set *rfds, fd_set *wfds, fd_set *efds) -{ - int rc = 0; - - if ((events & (POLLIN | POLLRDNORM | POLLRDBAND)) && - FD_ISSET(fd, rfds)) { - if (conn_is_closed(fd)) - rc |= POLLHUP; - else - rc |= POLLIN | POLLRDNORM; - } - - if ((events & (POLLOUT | POLLWRNORM | POLLWRBAND)) && - FD_ISSET(fd, wfds)) - rc |= POLLOUT; - - if (FD_ISSET(fd, efds)) { - if (conn_is_closed(fd)) - rc |= POLLHUP; - else if (conn_has_oob_data(fd)) - rc |= POLLRDBAND | POLLPRI; - } - - return rc; -} - -static int -compute_wait_revents(HANDLE h, short events, int object, int wait_rc) -{ - int rc = 0; - INPUT_RECORD record; - DWORD num_read; - - /* - * Assume we can always write to file handles (probably a bad - * assumption but works for now, at least it doesn't block). - */ - if (events & (POLLOUT | POLLWRNORM)) - rc |= POLLOUT; - - /* - * Check if this handle was signaled by WaitForMultipleObjects - */ - if (wait_rc >= WAIT_OBJECT_0 && (object == (wait_rc - WAIT_OBJECT_0)) - && (events & (POLLIN | POLLRDNORM))) { - - /* - * Check if this file is stdin, and if so, if it is a console. - */ - if (h == GetStdHandle(STD_INPUT_HANDLE) && - PeekConsoleInput(h, &record, 1, &num_read) == 1) { - - /* - * Handle the input console buffer differently, - * since it can signal on other events like - * window and mouse, but read can still block. - */ - if (record.EventType == KEY_EVENT && - record.Event.KeyEvent.bKeyDown) { - rc |= POLLIN; - } else { - /* - * Flush non-character events from the - * console buffer. - */ - ReadConsoleInput(h, &record, 1, &num_read); - } - } else { - rc |= POLLIN; - } - } - - return rc; -} - -static int -wsa_select_errno(int err) -{ - switch (err) { - case WSAEINTR: - case WSAEINPROGRESS: - errno = EINTR; - break; - case WSAEFAULT: - /* - * Windows uses WSAEFAULT for both resource allocation failures - * and arguments not being contained in the user's address - * space. So, we have to choose EFAULT or ENOMEM. - */ - errno = EFAULT; - break; - case WSAEINVAL: - errno = EINVAL; - break; - case WSANOTINITIALISED: - errno = EPERM; - break; - case WSAENETDOWN: - errno = ENOMEM; - break; - } - return -1; -} - -int -poll(struct pollfd *pfds, nfds_t nfds, int timeout_ms) -{ - nfds_t i; - int timespent_ms, looptime_ms; - -#define FD_IS_SOCKET (1 << 0) - int fd_state[FD_SETSIZE]; - int num_fds; - - /* - * select machinery - */ - fd_set rfds, wfds, efds; - int rc; - int num_sockets; - - /* - * wait machinery - */ - DWORD wait_rc; - HANDLE handles[FD_SETSIZE]; - int num_handles; - - if (pfds == NULL) { - errno = EINVAL; - return -1; - } - - if (nfds <= 0) { - return 0; - } - - FD_ZERO(&rfds); - FD_ZERO(&wfds); - FD_ZERO(&efds); - num_fds = 0; - num_sockets = 0; - num_handles = 0; - - for (i = 0; i < nfds; i++) { - if ((int)pfds[i].fd < 0) { - continue; - } - - if (is_socket(pfds[i].fd)) { - if (num_sockets >= FD_SETSIZE) { - errno = EINVAL; - return -1; - } - - fd_state[num_fds] = FD_IS_SOCKET; - - FD_SET(pfds[i].fd, &efds); - - if (pfds[i].events & - (POLLIN | POLLRDNORM | POLLRDBAND)) { - FD_SET(pfds[i].fd, &rfds); - } - - if (pfds[i].events & - (POLLOUT | POLLWRNORM | POLLWRBAND)) { - FD_SET(pfds[i].fd, &wfds); - } - num_sockets++; - - } else { - if (num_handles >= FD_SETSIZE) { - errno = EINVAL; - return -1; - } - - handles[num_handles++] = - (HANDLE)_get_osfhandle(pfds[i].fd); - } - - num_fds++; - } - - /* - * Determine if the files, pipes, sockets, consoles, etc. have signaled. - * - * Do this by alternating a loop between WaitForMultipleObjects for - * non-sockets and and select for sockets. - * - * I tried to implement this all in terms of WaitForMultipleObjects - * with a select-based 'poll' of the sockets at the end to get extra - * specific socket status. - * - * However, the cost of setting up an event handle for each socket and - * cleaning them up reliably was pretty high. Since the event handle - * associated with a socket is also global, creating a new one here - * cancels one that may exist externally to this function. - * - * At any rate, even if global socket event handles were not an issue, - * the 'FD_WRITE' status of a socket event handle does not behave in an - * expected fashion, being triggered by an edge on a write buffer rather - * than simply triggering if there is space available. - */ - timespent_ms = 0; - wait_rc = 0; - - if (timeout_ms < 0) { - timeout_ms = INFINITE; - } - looptime_ms = timeout_ms > 100 ? 100 : timeout_ms; - - do { - struct timeval tv = {0, looptime_ms * 1000}; - - /* - * Check if any file handles have signaled - */ - if (num_handles) { - wait_rc = WaitForMultipleObjects(num_handles, handles, FALSE, 0); - if (wait_rc == WAIT_FAILED) { - /* - * The documentation for WaitForMultipleObjects - * does not specify what values GetLastError - * may return here. Rather than enumerate - * badness like for wsa_select_errno, assume a - * general errno value. - */ - errno = ENOMEM; - return 0; - } - } - - /* - * If we signaled on a file handle, don't wait on the sockets. - */ - if (wait_rc >= WAIT_OBJECT_0) - tv.tv_usec = 0; - - /* - * Check if any sockets have signaled - */ - rc = select(0, &rfds, &wfds, &efds, &tv); - if (rc == SOCKET_ERROR) { - return wsa_select_errno(WSAGetLastError()); - } - - if (wait_rc >= WAIT_OBJECT_0 || (num_sockets && rc > 0)) - break; - - timespent_ms += looptime_ms; - - } while (timespent_ms < timeout_ms); - - rc = 0; - num_handles = 0; - num_fds = 0; - for (i = 0; i < nfds; i++) { - pfds[i].revents = 0; - - if ((int)pfds[i].fd < 0) - continue; - - if (fd_state[num_fds] & FD_IS_SOCKET) { - pfds[i].revents = compute_select_revents(pfds[i].fd, - pfds[i].events, &rfds, &wfds, &efds); - - } else { - pfds[i].revents = compute_wait_revents( - handles[num_handles], pfds[i].events, num_handles, - wait_rc); - num_handles++; - } - - num_fds++; - - if (pfds[i].revents) - rc++; - } - - return rc; -} - diff --git a/apps/poll_win.c b/apps/poll_win.c new file mode 100644 index 0000000..bf30ccf --- /dev/null +++ b/apps/poll_win.c @@ -0,0 +1,334 @@ +/* + * Public domain + * + * poll(2) emulation for Windows + * + * This emulates just-enough poll functionality on Windows to work in the + * context of the openssl(1) program. This is not a replacement for + * POSIX.1-2001 poll(2), though it may come closer than I care to admit. + * + * Dongsheng Song + * Brent Cook + */ + +#include +#include +#include +#include +#include + +static int +conn_is_closed(int fd) +{ + char buf[1]; + int ret = recv(fd, buf, 1, MSG_PEEK); + if (ret == -1) { + switch (WSAGetLastError()) { + case WSAECONNABORTED: + case WSAECONNRESET: + case WSAENETRESET: + case WSAESHUTDOWN: + return 1; + } + } + return 0; +} + +static int +conn_has_oob_data(int fd) +{ + char buf[1]; + return (recv(fd, buf, 1, MSG_PEEK | MSG_OOB) == 1); +} + +static int +is_socket(int fd) +{ + WSANETWORKEVENTS events; + return (WSAEnumNetworkEvents((SOCKET)fd, NULL, &events) == 0); +} + +static int +compute_select_revents(int fd, short events, + fd_set *rfds, fd_set *wfds, fd_set *efds) +{ + int rc = 0; + + if ((events & (POLLIN | POLLRDNORM | POLLRDBAND)) && + FD_ISSET(fd, rfds)) { + if (conn_is_closed(fd)) + rc |= POLLHUP; + else + rc |= POLLIN | POLLRDNORM; + } + + if ((events & (POLLOUT | POLLWRNORM | POLLWRBAND)) && + FD_ISSET(fd, wfds)) + rc |= POLLOUT; + + if (FD_ISSET(fd, efds)) { + if (conn_is_closed(fd)) + rc |= POLLHUP; + else if (conn_has_oob_data(fd)) + rc |= POLLRDBAND | POLLPRI; + } + + return rc; +} + +static int +compute_wait_revents(HANDLE h, short events, int object, int wait_rc) +{ + int rc = 0; + INPUT_RECORD record; + DWORD num_read; + + /* + * Assume we can always write to file handles (probably a bad + * assumption but works for now, at least it doesn't block). + */ + if (events & (POLLOUT | POLLWRNORM)) + rc |= POLLOUT; + + /* + * Check if this handle was signaled by WaitForMultipleObjects + */ + if (wait_rc >= WAIT_OBJECT_0 && (object == (wait_rc - WAIT_OBJECT_0)) + && (events & (POLLIN | POLLRDNORM))) { + + /* + * Check if this file is stdin, and if so, if it is a console. + */ + if (h == GetStdHandle(STD_INPUT_HANDLE) && + PeekConsoleInput(h, &record, 1, &num_read) == 1) { + + /* + * Handle the input console buffer differently, + * since it can signal on other events like + * window and mouse, but read can still block. + */ + if (record.EventType == KEY_EVENT && + record.Event.KeyEvent.bKeyDown) { + rc |= POLLIN; + } else { + /* + * Flush non-character events from the + * console buffer. + */ + ReadConsoleInput(h, &record, 1, &num_read); + } + } else { + rc |= POLLIN; + } + } + + return rc; +} + +static int +wsa_select_errno(int err) +{ + switch (err) { + case WSAEINTR: + case WSAEINPROGRESS: + errno = EINTR; + break; + case WSAEFAULT: + /* + * Windows uses WSAEFAULT for both resource allocation failures + * and arguments not being contained in the user's address + * space. So, we have to choose EFAULT or ENOMEM. + */ + errno = EFAULT; + break; + case WSAEINVAL: + errno = EINVAL; + break; + case WSANOTINITIALISED: + errno = EPERM; + break; + case WSAENETDOWN: + errno = ENOMEM; + break; + } + return -1; +} + +int +poll(struct pollfd *pfds, nfds_t nfds, int timeout_ms) +{ + nfds_t i; + int timespent_ms, looptime_ms; + +#define FD_IS_SOCKET (1 << 0) + int fd_state[FD_SETSIZE]; + int num_fds; + + /* + * select machinery + */ + fd_set rfds, wfds, efds; + int rc; + int num_sockets; + + /* + * wait machinery + */ + DWORD wait_rc; + HANDLE handles[FD_SETSIZE]; + int num_handles; + + if (pfds == NULL) { + errno = EINVAL; + return -1; + } + + if (nfds <= 0) { + return 0; + } + + FD_ZERO(&rfds); + FD_ZERO(&wfds); + FD_ZERO(&efds); + num_fds = 0; + num_sockets = 0; + num_handles = 0; + + for (i = 0; i < nfds; i++) { + if ((int)pfds[i].fd < 0) { + continue; + } + + if (is_socket(pfds[i].fd)) { + if (num_sockets >= FD_SETSIZE) { + errno = EINVAL; + return -1; + } + + fd_state[num_fds] = FD_IS_SOCKET; + + FD_SET(pfds[i].fd, &efds); + + if (pfds[i].events & + (POLLIN | POLLRDNORM | POLLRDBAND)) { + FD_SET(pfds[i].fd, &rfds); + } + + if (pfds[i].events & + (POLLOUT | POLLWRNORM | POLLWRBAND)) { + FD_SET(pfds[i].fd, &wfds); + } + num_sockets++; + + } else { + if (num_handles >= FD_SETSIZE) { + errno = EINVAL; + return -1; + } + + handles[num_handles++] = + (HANDLE)_get_osfhandle(pfds[i].fd); + } + + num_fds++; + } + + /* + * Determine if the files, pipes, sockets, consoles, etc. have signaled. + * + * Do this by alternating a loop between WaitForMultipleObjects for + * non-sockets and and select for sockets. + * + * I tried to implement this all in terms of WaitForMultipleObjects + * with a select-based 'poll' of the sockets at the end to get extra + * specific socket status. + * + * However, the cost of setting up an event handle for each socket and + * cleaning them up reliably was pretty high. Since the event handle + * associated with a socket is also global, creating a new one here + * cancels one that may exist externally to this function. + * + * At any rate, even if global socket event handles were not an issue, + * the 'FD_WRITE' status of a socket event handle does not behave in an + * expected fashion, being triggered by an edge on a write buffer rather + * than simply triggering if there is space available. + */ + timespent_ms = 0; + wait_rc = 0; + + if (timeout_ms < 0) { + timeout_ms = INFINITE; + } + looptime_ms = timeout_ms > 100 ? 100 : timeout_ms; + + do { + struct timeval tv = {0, looptime_ms * 1000}; + + /* + * Check if any file handles have signaled + */ + if (num_handles) { + wait_rc = WaitForMultipleObjects(num_handles, handles, FALSE, 0); + if (wait_rc == WAIT_FAILED) { + /* + * The documentation for WaitForMultipleObjects + * does not specify what values GetLastError + * may return here. Rather than enumerate + * badness like for wsa_select_errno, assume a + * general errno value. + */ + errno = ENOMEM; + return 0; + } + } + + /* + * If we signaled on a file handle, don't wait on the sockets. + */ + if (wait_rc >= WAIT_OBJECT_0) + tv.tv_usec = 0; + + /* + * Check if any sockets have signaled + */ + rc = select(0, &rfds, &wfds, &efds, &tv); + if (rc == SOCKET_ERROR) { + return wsa_select_errno(WSAGetLastError()); + } + + if (wait_rc >= WAIT_OBJECT_0 || (num_sockets && rc > 0)) + break; + + timespent_ms += looptime_ms; + + } while (timespent_ms < timeout_ms); + + rc = 0; + num_handles = 0; + num_fds = 0; + for (i = 0; i < nfds; i++) { + pfds[i].revents = 0; + + if ((int)pfds[i].fd < 0) + continue; + + if (fd_state[num_fds] & FD_IS_SOCKET) { + pfds[i].revents = compute_select_revents(pfds[i].fd, + pfds[i].events, &rfds, &wfds, &efds); + + } else { + pfds[i].revents = compute_wait_revents( + handles[num_handles], pfds[i].events, num_handles, + wait_rc); + num_handles++; + } + + num_fds++; + + if (pfds[i].revents) + rc++; + } + + return rc; +} + -- cgit v1.2.3-55-g6feb