From 3d47699cdf86ee68120f97814349099457b48242 Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Thu, 13 May 2010 16:08:14 -0700 Subject: [PATCH] stream-ssl: Flush OpenSSL error queue after calling SSL_shutdown(). The OpenSSL manpage for SSL_get_error() says this: In addition to ssl and ret, SSL_get_error() inspects the current thread's OpenSSL error queue. Thus, SSL_get_error() must be used in the same thread that performed the TLS/SSL I/O operation, and no other OpenSSL function calls should appear in between. The current thread's error queue must be empty before the TLS/SSL I/O operation is attempted, or SSL_get_error() will not work reliably. We weren't taking this advice literally enough, which meant that this would happen: 1. Call SSL_shutdown() on one connection. 2. Call SSL_read() on another connection, returning 0 bytes. (This is normal. It just means that no more data has arrived yet.) 3. Call SSL_get_error() for that second connection to check whether the 0-byte return value was a real error. (This should return SSL_ERROR_WANT_READ to indicate that more data is needed.) 4. Actually get some other error indicating that the SSL_shutdown() call returned an error. This commit fixes the problem by flushing the OpenSSL error queue after calling SSL_shutdown(). Without this commit, starting an ovsdb-server with two active SSL remotes, running two ovsdb-clients listening for connections from the ovsdb-server remotes, then killing one of the ovsdb-clients (with e.g. Control+C), will cause ovsdb-server to drop the other ovsdb-client connnection the next time that SSL_read() is called on it. With this commit, this scenario works correctly (e.g. ovsdb-server keeps the remaining connection up). CC: Jeremy Stribling --- lib/stream-ssl.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/stream-ssl.c b/lib/stream-ssl.c index 462ac428..c2a77a00 100644 --- a/lib/stream-ssl.c +++ b/lib/stream-ssl.c @@ -478,6 +478,11 @@ ssl_close(struct stream *stream) * background. */ SSL_shutdown(sslv->ssl); + /* SSL_shutdown() might have signaled an error, in which case we need to + * flush it out of the OpenSSL error queue or the next OpenSSL operation + * will falsely signal an error. */ + ERR_clear_error(); + SSL_free(sslv->ssl); close(sslv->fd); free(sslv); -- 2.30.2