}
-BIO_METHOD sslBioMethod;
+// Note: This is a Leaky Meyer's Singleton. The reason we can't use a non-leaky
+// thing is because we will be setting this BIO_METHOD* inside BIOs owned by
+// various SSL objects which may get callbacks even during teardown. We may
+// eventually try to fix this
+static BIO_METHOD* getSSLBioMethod() {
+ static auto const instance = OpenSSLUtils::newSocketBioMethod().release();
+ return instance;
+}
void* initsslBioMethod(void) {
- memcpy(&sslBioMethod, BIO_s_socket(), sizeof(sslBioMethod));
+ auto sslBioMethod = getSSLBioMethod();
// override the bwrite method for MSG_EOR support
- OpenSSLUtils::setCustomBioWriteMethod(
- &sslBioMethod, AsyncSSLSocket::bioWrite);
- OpenSSLUtils::setCustomBioReadMethod(&sslBioMethod, AsyncSSLSocket::bioRead);
+ OpenSSLUtils::setCustomBioWriteMethod(sslBioMethod, AsyncSSLSocket::bioWrite);
+ OpenSSLUtils::setCustomBioReadMethod(sslBioMethod, AsyncSSLSocket::bioRead);
// Note that the sslBioMethod.type and sslBioMethod.name are not
// set here. openssl code seems to be checking ".type == BIO_TYPE_SOCKET" and
checkForImmediateRead();
}
-#if OPENSSL_VERSION_NUMBER >= 0x009080bfL
void AsyncSSLSocket::attachSSLContext(
const std::shared_ptr<SSLContext>& ctx) {
// We need to update the initial_ctx if necessary
auto sslCtx = ctx->getSSLCtx();
SSL_CTX_up_ref(sslCtx);
-#ifndef OPENSSL_NO_TLSEXT
- // note that detachSSLContext has already freed ssl_->initial_ctx
- ssl_->initial_ctx = sslCtx;
-#endif
+
+ // The 'initial_ctx' inside an SSL* points to the context that it was created
+ // with, which is also where session callbacks and servername callbacks
+ // happen.
+ // When we switch to a different SSL_CTX, we want to update the initial_ctx as
+ // well so that any callbacks don't go to a different object
+ // NOTE: this will only work if we have access to ssl_ internals, so it may
+ // not work on
+ // OpenSSL version >= 1.1.0
+ OpenSSLUtils::setSSLInitialCtx(ssl_, sslCtx);
// Detach sets the socket's context to the dummy context. Thus we must acquire
// this lock.
SpinLockGuard guard(dummyCtxLock);
if (!ssl_) {
return;
}
-// Detach the initial_ctx as well. Internally w/ OPENSSL_NO_TLSEXT
-// it is used for session info. It will be reattached in attachSSLContext
-#ifndef OPENSSL_NO_TLSEXT
- if (ssl_->initial_ctx) {
- SSL_CTX_free(ssl_->initial_ctx);
- ssl_->initial_ctx = nullptr;
+ // The 'initial_ctx' inside an SSL* points to the context that it was created
+ // with, which is also where session callbacks and servername callbacks
+ // happen.
+ // Detach the initial_ctx as well. It will be reattached in attachSSLContext
+ // it is used for session info.
+ // NOTE: this will only work if we have access to ssl_ internals, so it may
+ // not work on
+ // OpenSSL version >= 1.1.0
+ SSL_CTX* initialCtx = OpenSSLUtils::getSSLInitialCtx(ssl_);
+ if (initialCtx) {
+ SSL_CTX_free(initialCtx);
+ OpenSSLUtils::setSSLInitialCtx(ssl_, nullptr);
}
-#endif
+
SpinLockGuard guard(dummyCtxLock);
if (nullptr == dummyCtx) {
// We need to lazily initialize the dummy context so we don't
// would not be thread safe.
SSL_set_SSL_CTX(ssl_, dummyCtx->getSSLCtx());
}
-#endif
#if FOLLY_OPENSSL_HAS_SNI
void AsyncSSLSocket::switchServerSSLContext(
return false;
}
- if(!ss->tlsext_hostname) {
- return false;
- }
- return (tlsextHostname_.compare(ss->tlsext_hostname) ? false : true);
+ auto tlsextHostname = SSL_SESSION_get0_hostname(ss);
+ return (tlsextHostname && !tlsextHostname_.compare(tlsextHostname));
}
void AsyncSSLSocket::setServerName(std::string serverName) noexcept {
}
bool AsyncSSLSocket::setupSSLBio() {
- auto sslBio = BIO_new(&sslBioMethod);
+ auto sslBio = BIO_new(getSSLBioMethod());
if (!sslBio) {
return false;
const char *AsyncSSLSocket::getSSLCertSigAlgName() const {
X509 *cert = (ssl_ != nullptr) ? SSL_get_certificate(ssl_) : nullptr;
if (cert) {
- int nid = OBJ_obj2nid(cert->sig_alg->algorithm);
+ int nid = X509_get_signature_nid(cert);
return OBJ_nid2ln(nid);
}
return nullptr;