diff options
Diffstat (limited to 'Swiften/TLS/OpenSSL/OpenSSLContext.cpp')
-rw-r--r-- | Swiften/TLS/OpenSSL/OpenSSLContext.cpp | 38 |
1 files changed, 38 insertions, 0 deletions
diff --git a/Swiften/TLS/OpenSSL/OpenSSLContext.cpp b/Swiften/TLS/OpenSSL/OpenSSLContext.cpp index f90b4a8..47e7175 100644 --- a/Swiften/TLS/OpenSSL/OpenSSLContext.cpp +++ b/Swiften/TLS/OpenSSL/OpenSSLContext.cpp @@ -92,6 +92,11 @@ OpenSSLContext::OpenSSLContext(Mode mode) : mode_(mode), state_(State::Start) { context_ = createSSL_CTX(mode_); SSL_CTX_set_options(context_.get(), SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); + if (mode_ == Mode::Server) { + SSL_CTX_set_tlsext_servername_arg(context_.get(), this); + SSL_CTX_set_tlsext_servername_callback(context_.get(), OpenSSLContext::handleServerNameCallback); + } + // TODO: implement CRL checking // TODO: download CRL (HTTP transport) // TODO: cache CRL downloads for configurable time period @@ -176,6 +181,10 @@ void OpenSSLContext::accept() { } void OpenSSLContext::connect() { + connect(std::string()); +} + +void OpenSSLContext::connect(const std::string& requestedServerName) { assert(mode_ == Mode::Client); handle_ = std::unique_ptr<SSL>(SSL_new(context_.get())); if (!handle_) { @@ -184,6 +193,12 @@ void OpenSSLContext::connect() { return; } + if (!requestedServerName.empty()) { + if (SSL_set_tlsext_host_name(handle_.get(), const_cast<char*>(requestedServerName.c_str())) != 1) { + SWIFT_LOG(error) << "Failed on SSL_set_tlsext_host_name()." << std::endl; + } + } + // Ownership of BIOs is transferred to the SSL_CTX instance in handle_. initAndSetBIOs(); @@ -215,6 +230,7 @@ void OpenSSLContext::doAccept() { SWIFT_LOG(warning) << openSSLInternalErrorToString() << std::endl; state_ = State::Error; onError(std::make_shared<TLSError>()); + sendPendingDataToNetwork(); } } @@ -240,6 +256,24 @@ void OpenSSLContext::doConnect() { } } +int OpenSSLContext::handleServerNameCallback(SSL* ssl, int*, void* arg) { + if (ssl == nullptr) + return SSL_TLSEXT_ERR_NOACK; + + const char* servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name); + if (servername) { + auto serverNameString = std::string(servername); + auto context = reinterpret_cast<OpenSSLContext*>(arg); + context->onServerNameRequested(serverNameString); + + if (context->abortTLSHandshake_) { + context->abortTLSHandshake_ = false; + return SSL_TLSEXT_ERR_ALERT_FATAL; + } + } + return SSL_TLSEXT_ERR_OK; +} + void OpenSSLContext::sendPendingDataToNetwork() { int size = BIO_pending(writeBIO_); if (size > 0) { @@ -385,6 +419,10 @@ bool OpenSSLContext::setPrivateKey(const PrivateKey::ref& privateKey) { return true; } +void OpenSSLContext::setAbortTLSHandshake(bool abort) { + abortTLSHandshake_ = abort; +} + bool OpenSSLContext::setClientCertificate(CertificateWithKey::ref certificate) { std::shared_ptr<PKCS12Certificate> pkcs12Certificate = std::dynamic_pointer_cast<PKCS12Certificate>(certificate); if (!pkcs12Certificate || pkcs12Certificate->isNull()) { |