Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-44096

QNetworkAuthenticationManager does not emit authenticationRequired when using NTLM

    XMLWordPrintable

    Details

      Description

      Test steps:
      1. Create a QNetworkAccessManager instance
      2. Connect its authenticationRequired() signal to a slot
      3. Call pMgr->get(QNetworkRequest(QUrl("https://a.com/ews/Exchange.asmx"))), where the supplied URL is to a server that uses NTLM authentication.

      Issue:
      If using Qt 4.7.3, the QNetworkAccessManager::authenticationRequired() signal is emitted to request the authentication credentials, as expected.

      However, using the same code but with Qt 5.4.0, the QNetworkAccessManager::authenticationRequired() signal is not emitted.

      Test code:

      class NetworkTest : public QObject
      {
          Q_OBJECT
      public:
          NetworkTest() : QObject(NULL)
          {
              m_pManager = new QNetworkAccessManager(this);
              connect(m_pManager, SIGNAL(sslErrors(QNetworkReply*, const QList<QSslError>&)), this, SLOT(onSslErrors(QNetworkReply*, const QList<QSslError>&)));
              connect(m_pManager, SIGNAL(authenticationRequired(QNetworkReply*, QAuthenticator*)), this, SLOT(authenticationRequired(QNetworkReply*, QAuthenticator*)));
      
              QTimer::singleShot(100, this, SLOT(testRequest()));
          }
      
      public slots:
          void testRequest()
          {
              qDebug("!!! testRequest\n");
              m_pManager->get(QNetworkRequest(QUrl("https://something.com/ews/Exchange.asmx")));
          }
      
          void authenticationRequired(QNetworkReply * reply, QAuthenticator * authenticator)
          {
              qDebug("!!! authenticationRequired\n");
          }
          void onSslErrors(QNetworkReply * reply, const QList<QSslError> & errors)
          {
              qDebug("!!! onSslErrors\n");
              reply->ignoreSslErrors();
          }
      
      private:
          QNetworkAccessManager *m_pManager;
      };
      

      Clues:
      I see that QHttpNetworkConnectionPrivate::handleAuthenticateChallenge() is being called, but the first time it is called, it executes the following block of code:

      } else if (priv->phase == QAuthenticatorPrivate::Start) {
          // If the url's authenticator has a 'user' set we will end up here (phase is only set to 'Done' by
          // parseHttpResponse above if 'user' is empty). So if credentials were supplied with the request,
          // such as in the case of an XMLHttpRequest, this is our only opportunity to cache them.
          emit reply->cacheCredentials(reply->request(), auth);
      }
      

      Based on the comment, I think that this might be incorrect, because at that point when using NTLM authentication, the url's authenticator does not have 'user' set. As a consequence of calling this code, an entry is added to the authentication cache with a blank username, blank password, and a domain of "/".

      Later, when QNetworkAccessManagerPrivate::authenticationRequired() is executed, it seemingly incorrectly bails out with the following block of code because the cached authentication is not null (since its domain is "/") but it also isn't correct:

      QNetworkAuthenticationCredential cred = authenticationManager->fetchCachedCredentials(url, authenticator);
      if (!cred.isNull()) {
      ...
                  return;
       }
      

        Attachments

          Issue Links

          For Gerrit Dashboard: QTBUG-44096
          # Subject Branch Project Status CR V

            Activity

              People

              • Assignee:
                vhilshei Volker Hilsheimer
                Reporter:
                zblair Zachary Blair
              • Votes:
                10 Vote for this issue
                Watchers:
                16 Start watching this issue

                Dates

                • Created:
                  Updated:

                  Gerrit Reviews

                  There is 1 open Gerrit change