diff options
Diffstat (limited to 'src/network/ssl/qsslcontext_opensslpre11.cpp')
-rw-r--r-- | src/network/ssl/qsslcontext_opensslpre11.cpp | 56 |
1 files changed, 53 insertions, 3 deletions
diff --git a/src/network/ssl/qsslcontext_opensslpre11.cpp b/src/network/ssl/qsslcontext_opensslpre11.cpp index eea821804f..c8be2ecb31 100644 --- a/src/network/ssl/qsslcontext_opensslpre11.cpp +++ b/src/network/ssl/qsslcontext_opensslpre11.cpp @@ -56,11 +56,26 @@ QT_BEGIN_NAMESPACE extern int q_X509Callback(int ok, X509_STORE_CTX *ctx); extern QString getErrorsFromOpenSsl(); +#if QT_CONFIG(dtls) +// defined in qdtls_openssl.cpp: +namespace dtlscallbacks +{ +extern "C" int q_X509DtlsCallback(int ok, X509_STORE_CTX *ctx); +extern "C" int q_generate_cookie_callback(SSL *ssl, unsigned char *dst, + unsigned *cookieLength); +extern "C" int q_verify_cookie_callback(SSL *ssl, const unsigned char *cookie, + unsigned cookieLength); +} +#endif // dtls + static inline QString msgErrorSettingEllipticCurves(const QString &why) { return QSslSocket::tr("Error when setting the elliptic curves (%1)").arg(why); } +// Defined in qsslsocket.cpp +QList<QSslCipher> q_getDefaultDtlsCiphers(); + // static void QSslContext::initSslContext(QSslContext *sslContext, QSslSocket::SslMode mode, const QSslConfiguration &configuration, bool allowRootCertOnDemandLoading) { @@ -68,11 +83,28 @@ void QSslContext::initSslContext(QSslContext *sslContext, QSslSocket::SslMode mo sslContext->errorCode = QSslError::NoError; bool client = (mode == QSslSocket::SslClientMode); - bool reinitialized = false; bool unsupportedProtocol = false; + bool isDtls = false; init_context: switch (sslContext->sslConfiguration.protocol()) { +#if QT_CONFIG(dtls) + case QSsl::DtlsV1_0: + isDtls = true; + sslContext->ctx = q_SSL_CTX_new(client ? q_DTLSv1_client_method() : q_DTLSv1_server_method()); + break; + case QSsl::DtlsV1_2: + case QSsl::DtlsV1_2OrLater: + // OpenSSL 1.0.2 and below will probably never receive TLS 1.3, so + // technically 1.2 or later is 1.2 and will stay so. + isDtls = true; + sslContext->ctx = q_SSL_CTX_new(client ? q_DTLSv1_2_client_method() : q_DTLSv1_2_server_method()); + break; + case QSsl::DtlsV1_0OrLater: + isDtls = true; + sslContext->ctx = q_SSL_CTX_new(client ? q_DTLS_client_method() : q_DTLS_server_method()); + break; +#endif // dtls case QSsl::SslV2: #ifndef OPENSSL_NO_SSL2 sslContext->ctx = q_SSL_CTX_new(client ? q_SSLv2_client_method() : q_SSLv2_server_method()); @@ -138,6 +170,12 @@ init_context: break; } + if (!client && isDtls && configuration.peerVerifyMode() != QSslSocket::VerifyNone) { + sslContext->errorStr = QSslSocket::tr("DTLS server requires a 'VerifyNone' mode with your version of OpenSSL"); + sslContext->errorCode = QSslError::UnspecifiedError; + return; + } + if (!sslContext->ctx) { // After stopping Flash 10 the SSL library loses its ciphers. Try re-adding them // by re-initializing the library. @@ -155,6 +193,7 @@ init_context: } // Enable bug workarounds. + // DTLSTODO: check this setupOpenSslOptions ... long options = QSslSocketBackendPrivate::setupOpenSslOptions(configuration.protocol(), configuration.d->sslOptions); q_SSL_CTX_set_options(sslContext->ctx, options); @@ -170,7 +209,7 @@ init_context: bool first = true; QList<QSslCipher> ciphers = sslContext->sslConfiguration.ciphers(); if (ciphers.isEmpty()) - ciphers = QSslSocketPrivate::defaultCiphers(); + ciphers = isDtls ? q_getDefaultDtlsCiphers() : QSslSocketPrivate::defaultCiphers(); for (const QSslCipher &cipher : qAsConst(ciphers)) { if (first) first = false; @@ -277,8 +316,19 @@ init_context: if (sslContext->sslConfiguration.peerVerifyMode() == QSslSocket::VerifyNone) { q_SSL_CTX_set_verify(sslContext->ctx, SSL_VERIFY_NONE, 0); } else { - q_SSL_CTX_set_verify(sslContext->ctx, SSL_VERIFY_PEER, q_X509Callback); + q_SSL_CTX_set_verify(sslContext->ctx, SSL_VERIFY_PEER, +#if QT_CONFIG(dtls) + isDtls ? dtlscallbacks::q_X509DtlsCallback : +#endif // dtls + q_X509Callback); + } + +#if QT_CONFIG(dtls) + if (mode == QSslSocket::SslServerMode && isDtls && configuration.dtlsCookieVerificationEnabled()) { + q_SSL_CTX_set_cookie_generate_cb(sslContext->ctx, dtlscallbacks::q_generate_cookie_callback); + q_SSL_CTX_set_cookie_verify_cb(sslContext->ctx, CookieVerifyCallback(dtlscallbacks::q_verify_cookie_callback)); } +#endif // dtls // Set verification depth. if (sslContext->sslConfiguration.peerVerifyDepth() != 0) |