diff options
Diffstat (limited to 'src/network/kernel/qauthenticator.cpp')
-rw-r--r-- | src/network/kernel/qauthenticator.cpp | 35 |
1 files changed, 30 insertions, 5 deletions
diff --git a/src/network/kernel/qauthenticator.cpp b/src/network/kernel/qauthenticator.cpp index 86242b011f..93b323f0bd 100644 --- a/src/network/kernel/qauthenticator.cpp +++ b/src/network/kernel/qauthenticator.cpp @@ -50,6 +50,7 @@ #include <qstring.h> #include <qdatetime.h> #include <qrandom.h> +#include "private/qsystemlibrary_p.h" #ifdef Q_OS_WIN #include <qmutex.h> @@ -423,6 +424,22 @@ void QAuthenticatorPrivate::updateCredentials() } } +static bool verifyDigestMD5(const QByteArray &value) +{ + auto opts = QAuthenticatorPrivate::parseDigestAuthenticationChallenge(value); + auto it = opts.constFind("algorithm"); + if (it != opts.cend()) { + QByteArray alg = it.value(); + if (alg.size() < 3) + return false; + // Just compare the first 3 characters, that way we match other subvariants as well, such as + // "MD5-sess" + auto view = QByteArray::fromRawData(alg.data(), 3); + return view.compare("MD5", Qt::CaseInsensitive) == 0; + } + return true; // assume it's ok if algorithm is not specified +} + void QAuthenticatorPrivate::parseHttpResponse(const QList<QPair<QByteArray, QByteArray> > &values, bool isProxy, const QString &host) { #if !QT_CONFIG(gssapi) @@ -454,8 +471,13 @@ void QAuthenticatorPrivate::parseHttpResponse(const QList<QPair<QByteArray, QByt method = Ntlm; headerVal = current.second.mid(5); } else if (method < DigestMd5 && str.startsWith("digest")) { + // Make sure the algorithm is actually MD5 before committing to it: + QByteArray fieldValue = current.second.mid(7); + if (!verifyDigestMD5(fieldValue)) + continue; + method = DigestMd5; - headerVal = current.second.mid(7); + headerVal = fieldValue; } else if (method < Negotiate && str.startsWith("negotiate")) { #if QT_CONFIG(sspi) || QT_CONFIG(gssapi) // if it's not supported then we shouldn't try to use it #if QT_CONFIG(gssapi) @@ -599,9 +621,11 @@ QByteArray QAuthenticatorPrivate::calculateResponse(const QByteArray &requestMet } else { QByteArray phase3Token; #if QT_CONFIG(sspi) // SSPI - phase3Token = qSspiContinue(this, method, host, QByteArray::fromBase64(challenge)); + if (sspiWindowsHandles) + phase3Token = qSspiContinue(this, method, host, QByteArray::fromBase64(challenge)); #elif QT_CONFIG(gssapi) // GSSAPI - phase3Token = qGssapiContinue(this, QByteArray::fromBase64(challenge)); + if (gssApiHandles) + phase3Token = qGssapiContinue(this, QByteArray::fromBase64(challenge)); #endif if (!phase3Token.isEmpty()) { response = phase3Token.toBase64(); @@ -1542,7 +1566,7 @@ static bool q_SSPI_library_load() // Initialize security interface if (pSecurityFunctionTable == nullptr) { - securityDLLHandle = LoadLibrary(L"secur32.dll"); + securityDLLHandle = QSystemLibrary::load(L"secur32"); if (securityDLLHandle != nullptr) { INIT_SECURITY_INTERFACE pInitSecurityInterface = reinterpret_cast<INIT_SECURITY_INTERFACE>( @@ -1568,7 +1592,8 @@ static QByteArray qSspiStartup(QAuthenticatorPrivate *ctx, QAuthenticatorPrivate if (!ctx->sspiWindowsHandles) ctx->sspiWindowsHandles.reset(new QSSPIWindowsHandles); - memset(&ctx->sspiWindowsHandles->credHandle, 0, sizeof(CredHandle)); + SecInvalidateHandle(&ctx->sspiWindowsHandles->credHandle); + SecInvalidateHandle(&ctx->sspiWindowsHandles->ctxHandle); SEC_WINNT_AUTH_IDENTITY auth; auth.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE; |