#include <boost/noncopyable.hpp>
#include <errno.h>
#include <fcntl.h>
-#include <openssl/err.h>
#include <openssl/asn1.h>
+#include <openssl/err.h>
#include <openssl/ssl.h>
#include <sys/types.h>
#include <chrono>
SSL_set_msg_callback_arg(ssl_, this);
}
+ clearOpenSSLErrors();
int ret = SSL_accept(ssl_);
if (ret <= 0) {
int sslError;
AsyncSocket::handleInitialReadWrite();
}
+void AsyncSSLSocket::clearOpenSSLErrors() {
+ // Normally clearing out the error before calling into an openssl method
+ // is a bad idea. However there might be other code that we don't control
+ // calling into openssl in the same thread, which doesn't use openssl
+ // correctly. We want to safe-guard ourselves from that code.
+ // However touching the ERR stack each and every time has a cost of taking
+ // a lock, so we only do this when we've opted in.
+ if (clearOpenSSLErrors_) {
+ ERR_clear_error();
+ }
+}
+
void
AsyncSSLSocket::handleConnect() noexcept {
VLOG(3) << "AsyncSSLSocket::handleConnect() this=" << this
sslState_ == STATE_CONNECTING);
assert(ssl_);
+ clearOpenSSLErrors();
auto originalState = state_;
int ret = SSL_connect(ssl_);
if (ret <= 0) {
return AsyncSocket::performRead(buf, buflen, offset);
}
+ clearOpenSSLErrors();
int bytes = 0;
if (!isBufferMovable_) {
bytes = SSL_read(ssl_, *buf, int(*buflen));
return sessionResumptionAttempted_;
}
+ /**
+ * Clears the ERR stack before invoking SSL methods.
+ * This is useful if unrelated code that runs in the same thread
+ * does not properly handle SSL error conditions, in which case
+ * it could cause SSL_* methods to fail with incorrect error codes.
+ */
+ void setClearOpenSSLErrors(bool clearErr) {
+ clearOpenSSLErrors_ = clearErr;
+ }
+
private:
void init();
+ void clearOpenSSLErrors();
protected:
// This virtual wrapper around SSL_write exists solely for testing/mockability
virtual int sslWriteImpl(SSL *ssl, const void *buf, int n) {
+ clearOpenSSLErrors();
return SSL_write(ssl, buf, n);
}
bool sessionResumptionAttempted_{false};
std::unique_ptr<IOBuf> preReceivedData_;
+ // Whether or not to clear the err stack before invocation of another
+ // SSL method
+ bool clearOpenSSLErrors_{false};
};
} // namespace