QAuthenticator: Filter out algorithms we don't support
Which is anything other than MD5 Pick-to: 6.2 5.15 Fixes: QTBUG-98280 Change-Id: Ifbf143f233ee5602fed1594e3316e6b2adec1461 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io> Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
This commit is contained in:
parent
8a883dea1c
commit
a92619d950
@ -443,6 +443,21 @@ bool QAuthenticatorPrivate::isMethodSupported(QByteArrayView method)
|
||||
return std::any_of(methods, methods + std::size(methods), isSupported);
|
||||
}
|
||||
|
||||
static bool verifyDigestMD5(QByteArrayView value)
|
||||
{
|
||||
auto opts = QAuthenticatorPrivate::parseDigestAuthenticationChallenge(value.toByteArray());
|
||||
if (auto it = opts.constFind("algorithm"); 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 = QByteArrayView(alg).first(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)
|
||||
@ -474,6 +489,10 @@ 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:
|
||||
if (!verifyDigestMD5(QByteArrayView(current.second).sliced(7)))
|
||||
continue;
|
||||
|
||||
method = DigestMd5;
|
||||
headerVal = current.second.mid(7);
|
||||
} else if (method < Negotiate && str.startsWith("negotiate")) {
|
||||
|
@ -48,6 +48,8 @@ private Q_SLOTS:
|
||||
void ntlmAuth_data();
|
||||
void ntlmAuth();
|
||||
|
||||
void sha256AndMd5Digest();
|
||||
|
||||
void equalityOperators();
|
||||
|
||||
void isMethodSupported();
|
||||
@ -151,6 +153,35 @@ void tst_QAuthenticator::ntlmAuth()
|
||||
QVERIFY(priv->calculateResponse("GET", "/", "").startsWith("NTLM "));
|
||||
}
|
||||
|
||||
// We don't (currently) support SHA256. So, when presented with the option of MD5 or SHA256,
|
||||
// we should always pick MD5.
|
||||
void tst_QAuthenticator::sha256AndMd5Digest()
|
||||
{
|
||||
QByteArray md5 = "Digest realm=\"\", nonce=\"\", algorithm=MD5, qop=\"auth\"";
|
||||
QByteArray sha256 = "Digest realm=\"\", nonce=\"\", algorithm=SHA-256, qop=\"auth\"";
|
||||
|
||||
QAuthenticator auth;
|
||||
auth.setUser("unimportant");
|
||||
auth.setPassword("unimportant");
|
||||
|
||||
QAuthenticatorPrivate *priv = QAuthenticatorPrivate::getPrivate(auth);
|
||||
QVERIFY(priv->isMethodSupported("digest")); // sanity check
|
||||
|
||||
QCOMPARE(priv->phase, QAuthenticatorPrivate::Start);
|
||||
QList<QPair<QByteArray, QByteArray>> headers;
|
||||
// Put sha256 first, so that its parsed first...
|
||||
headers.emplace_back("WWW-Authenticate", sha256);
|
||||
headers.emplace_back("WWW-Authenticate", md5);
|
||||
priv->parseHttpResponse(headers, false, QString());
|
||||
|
||||
QByteArray response = priv->calculateResponse("GET", "/index", {});
|
||||
QCOMPARE(priv->phase, QAuthenticatorPrivate::Done);
|
||||
|
||||
QVERIFY(!response.isEmpty());
|
||||
QVERIFY(!response.contains("algorithm=SHA-256"));
|
||||
QVERIFY(response.contains("algorithm=MD5"));
|
||||
}
|
||||
|
||||
void tst_QAuthenticator::equalityOperators()
|
||||
{
|
||||
QAuthenticator s1, s2;
|
||||
|
Loading…
x
Reference in New Issue
Block a user