Network: Fix NTLM (SSPI) with HTTP and HTTPS proxies

This commit should fix proxy authentication when NTLM is used.
NTLM differs from normal HTTP(S) authentication by having 2 roundtrips
instead of 1, some parts of our code however were not prepared for that.

I've tested this patch with Microsoft Forefront, both with normal
NTLM and with NTLM SSPI (in Windows domain).

I removed an optimization added in 3c3ea9a8, I could not see that behavior
anymore. That commit was the wrong fix in my opinion.

[ChangeLog][QtNetwork] Fix NTLM (SSPI) Proxy Authentication (HTTP/HTTPS)

Task-number: QTBUG-30829
Task-number: QTBUG-35101
Change-Id: Idcc9c0dbf388b011d49f2806e9a6dd55ebc35cec
Reviewed-by: Richard J. Moore <rich@kde.org>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Reviewed-by: Peter Hartmann <phartmann@blackberry.com>
bb10
Markus Goetz 2014-08-01 12:15:18 +02:00 committed by Olivier Goffart
parent 3862171315
commit 3e68148a4d
2 changed files with 7 additions and 7 deletions

View File

@ -430,9 +430,7 @@ void QAuthenticatorPrivate::parseHttpResponse(const QList<QPair<QByteArray, QByt
phase = Done;
break;
case Ntlm:
// #### extract from header
if (user.isEmpty() && password.isEmpty())
phase = Done;
// work is done in calculateResponse()
break;
case DigestMd5: {
this->options[QLatin1String("realm")] = realm = QString::fromLatin1(options.value("realm"));

View File

@ -594,16 +594,18 @@ void QHttpSocketEngine::slotSocketReadNotification()
priv = QAuthenticatorPrivate::getPrivate(d->authenticator);
priv->hasFailed = false;
} else if (statusCode == 407) {
if (d->credentialsSent) {
if (d->authenticator.isNull())
d->authenticator.detach();
priv = QAuthenticatorPrivate::getPrivate(d->authenticator);
if (d->credentialsSent && priv->phase != QAuthenticatorPrivate::Phase2) {
// Remember that (e.g.) NTLM is two-phase, so only reset when the authentication is not currently in progress.
//407 response again means the provided username/password were invalid.
d->authenticator = QAuthenticator(); //this is needed otherwise parseHttpResponse won't set the state, and then signal isn't emitted.
d->authenticator.detach();
priv = QAuthenticatorPrivate::getPrivate(d->authenticator);
priv->hasFailed = true;
}
else if (d->authenticator.isNull())
d->authenticator.detach();
priv = QAuthenticatorPrivate::getPrivate(d->authenticator);
priv->parseHttpResponse(d->reply->header(), true);