diff options
Diffstat (limited to 'src/network/ssl/qsslcontext_openssl11.cpp')
-rw-r--r-- | src/network/ssl/qsslcontext_openssl11.cpp | 86 |
1 files changed, 76 insertions, 10 deletions
diff --git a/src/network/ssl/qsslcontext_openssl11.cpp b/src/network/ssl/qsslcontext_openssl11.cpp index 5c68ed41db..7d11e51e8b 100644 --- a/src/network/ssl/qsslcontext_openssl11.cpp +++ b/src/network/ssl/qsslcontext_openssl11.cpp @@ -59,11 +59,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) { @@ -74,14 +89,27 @@ void QSslContext::initSslContext(QSslContext *sslContext, QSslSocket::SslMode mo bool reinitialized = false; bool unsupportedProtocol = false; + bool isDtls = false; init_context: if (sslContext->sslConfiguration.protocol() == QSsl::SslV2) { // SSL 2 is no longer supported, but chosen deliberately -> error sslContext->ctx = nullptr; unsupportedProtocol = true; } else { - // The ssl options will actually control the supported methods - sslContext->ctx = q_SSL_CTX_new(client ? q_TLS_client_method() : q_TLS_server_method()); + switch (sslContext->sslConfiguration.protocol()) { +#if QT_CONFIG(dtls) + case QSsl::DtlsV1_0: + case QSsl::DtlsV1_0OrLater: + case QSsl::DtlsV1_2: + case QSsl::DtlsV1_2OrLater: + isDtls = true; + sslContext->ctx = q_SSL_CTX_new(client ? q_DTLS_client_method() : q_DTLS_server_method()); + break; +#endif // dtls + default: + // The ssl options will actually control the supported methods + sslContext->ctx = q_SSL_CTX_new(client ? q_TLS_client_method() : q_TLS_server_method()); + } } if (!sslContext->ctx) { @@ -100,8 +128,15 @@ init_context: return; } - long minVersion = TLS_ANY_VERSION; - long maxVersion = TLS_ANY_VERSION; + const long anyVersion = +#if QT_CONFIG(dtls) + isDtls ? DTLS_ANY_VERSION : TLS_ANY_VERSION; +#else + TLS_ANY_VERSION; +#endif // dtls + long minVersion = anyVersion; + long maxVersion = anyVersion; + switch (sslContext->sslConfiguration.protocol()) { // The single-protocol versions first: case QSsl::SslV3: @@ -139,6 +174,24 @@ init_context: minVersion = TLS1_2_VERSION; maxVersion = TLS_MAX_VERSION; break; +#if QT_CONFIG(dtls) + case QSsl::DtlsV1_0: + minVersion = DTLS1_VERSION; + maxVersion = DTLS1_VERSION; + break; + case QSsl::DtlsV1_0OrLater: + minVersion = DTLS1_VERSION; + maxVersion = DTLS_MAX_VERSION; + break; + case QSsl::DtlsV1_2: + minVersion = DTLS1_2_VERSION; + maxVersion = DTLS1_2_VERSION; + break; + case QSsl::DtlsV1_2OrLater: + minVersion = DTLS1_2_VERSION; + maxVersion = DTLS_MAX_VERSION; + break; +#endif // dtls case QSsl::SslV2: // This protocol is not supported by OpenSSL 1.1 and we handle // it as an error (see the code above). @@ -148,14 +201,14 @@ init_context: break; } - if (minVersion != TLS_ANY_VERSION + if (minVersion != anyVersion && !q_SSL_CTX_set_min_proto_version(sslContext->ctx, minVersion)) { sslContext->errorStr = QSslSocket::tr("Error while setting the minimal protocol version"); sslContext->errorCode = QSslError::UnspecifiedError; return; } - if (maxVersion != TLS_ANY_VERSION + if (maxVersion != anyVersion && !q_SSL_CTX_set_max_proto_version(sslContext->ctx, maxVersion)) { sslContext->errorStr = QSslSocket::tr("Error while setting the maximum protocol version"); sslContext->errorCode = QSslError::UnspecifiedError; @@ -175,7 +228,8 @@ 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; @@ -282,8 +336,19 @@ init_context: if (sslContext->sslConfiguration.peerVerifyMode() == QSslSocket::VerifyNone) { q_SSL_CTX_set_verify(sslContext->ctx, SSL_VERIFY_NONE, nullptr); } 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, dtlscallbacks::q_verify_cookie_callback); } +#endif // dtls // Set verification depth. if (sslContext->sslConfiguration.peerVerifyDepth() != 0) @@ -305,8 +370,9 @@ init_context: if (!dhparams.isEmpty()) { const QByteArray ¶ms = dhparams.d->derData; const char *ptr = params.constData(); - DH *dh = q_d2i_DHparams(NULL, reinterpret_cast<const unsigned char **>(&ptr), params.length()); - if (dh == NULL) + DH *dh = q_d2i_DHparams(nullptr, reinterpret_cast<const unsigned char **>(&ptr), + params.length()); + if (dh == nullptr) qFatal("q_d2i_DHparams failed to convert QSslDiffieHellmanParameters to DER form"); q_SSL_CTX_set_tmp_dh(sslContext->ctx, dh); q_DH_free(dh); |