QAuthenticator: Don't reset phase on every set* call

In QAuthenticator "detach()" does not do what you expect.
First off it doesn't detach at all, and secondly it will reset the phase
that the authentication is in. This last part is intended, but it has
one issue: if setUser/setPassword is called with the same arguments
every time we ask for credentials then we never reach a fail-state since
it thinks we will have a new chance to authenticate.

Pick-to: 5.15
Change-Id: I02e2e42242220f3fced3572323e6492429cf173e
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
bb10
Mårten Nordheim 2020-09-04 20:35:25 +02:00
parent 5a47939d5c
commit 1cf84e7fd2
1 changed files with 30 additions and 11 deletions

View File

@ -249,9 +249,11 @@ QString QAuthenticator::user() const
*/
void QAuthenticator::setUser(const QString &user)
{
detach();
d->user = user;
d->updateCredentials();
if (!d || d->user != user) {
detach();
d->user = user;
d->updateCredentials();
}
}
/*!
@ -269,8 +271,10 @@ QString QAuthenticator::password() const
*/
void QAuthenticator::setPassword(const QString &password)
{
detach();
d->password = password;
if (!d || d->password != password) {
detach();
d->password = password;
}
}
/*!
@ -300,8 +304,10 @@ QString QAuthenticator::realm() const
*/
void QAuthenticator::setRealm(const QString &realm)
{
detach();
d->realm = realm;
if (!d || d->realm != realm) {
detach();
d->realm = realm;
}
}
/*!
@ -341,8 +347,10 @@ QVariantHash QAuthenticator::options() const
*/
void QAuthenticator::setOption(const QString &opt, const QVariant &value)
{
detach();
d->options.insert(opt, value);
if (option(opt) != value) {
detach();
d->options.insert(opt, value);
}
}
@ -453,9 +461,20 @@ void QAuthenticatorPrivate::parseHttpResponse(const QList<QPair<QByteArray, QByt
challenge = headerVal.trimmed();
QHash<QByteArray, QByteArray> options = parseDigestAuthenticationChallenge(challenge);
// Sets phase to Start if this updates our realm and sets the two locations where we store
// realm
auto privSetRealm = [this](QString newRealm) {
if (newRealm != realm) {
if (phase == Done)
phase = Start;
realm = newRealm;
this->options[QLatin1String("realm")] = realm;
}
};
switch(method) {
case Basic:
this->options[QLatin1String("realm")] = realm = QString::fromLatin1(options.value("realm"));
privSetRealm(QString::fromLatin1(options.value("realm")));
if (user.isEmpty() && password.isEmpty())
phase = Done;
break;
@ -464,7 +483,7 @@ void QAuthenticatorPrivate::parseHttpResponse(const QList<QPair<QByteArray, QByt
// work is done in calculateResponse()
break;
case DigestMd5: {
this->options[QLatin1String("realm")] = realm = QString::fromLatin1(options.value("realm"));
privSetRealm(QString::fromLatin1(options.value("realm")));
if (options.value("stale").compare("true", Qt::CaseInsensitive) == 0) {
phase = Start;
nonceCount = 0;