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);
|
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)
|
void QAuthenticatorPrivate::parseHttpResponse(const QList<QPair<QByteArray, QByteArray> > &values, bool isProxy, const QString &host)
|
||||||
{
|
{
|
||||||
#if !QT_CONFIG(gssapi)
|
#if !QT_CONFIG(gssapi)
|
||||||
@ -474,6 +489,10 @@ void QAuthenticatorPrivate::parseHttpResponse(const QList<QPair<QByteArray, QByt
|
|||||||
method = Ntlm;
|
method = Ntlm;
|
||||||
headerVal = current.second.mid(5);
|
headerVal = current.second.mid(5);
|
||||||
} else if (method < DigestMd5 && str.startsWith("digest")) {
|
} 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;
|
method = DigestMd5;
|
||||||
headerVal = current.second.mid(7);
|
headerVal = current.second.mid(7);
|
||||||
} else if (method < Negotiate && str.startsWith("negotiate")) {
|
} else if (method < Negotiate && str.startsWith("negotiate")) {
|
||||||
|
@ -48,6 +48,8 @@ private Q_SLOTS:
|
|||||||
void ntlmAuth_data();
|
void ntlmAuth_data();
|
||||||
void ntlmAuth();
|
void ntlmAuth();
|
||||||
|
|
||||||
|
void sha256AndMd5Digest();
|
||||||
|
|
||||||
void equalityOperators();
|
void equalityOperators();
|
||||||
|
|
||||||
void isMethodSupported();
|
void isMethodSupported();
|
||||||
@ -151,6 +153,35 @@ void tst_QAuthenticator::ntlmAuth()
|
|||||||
QVERIFY(priv->calculateResponse("GET", "/", "").startsWith("NTLM "));
|
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()
|
void tst_QAuthenticator::equalityOperators()
|
||||||
{
|
{
|
||||||
QAuthenticator s1, s2;
|
QAuthenticator s1, s2;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user