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

QNetworkAccessManager is mistakenly checking keychain in authenticationRequired signal

    XMLWordPrintable

Details

    • f46ce0a0b819b74c4f25b5d9fcbb8a83b62dd417, dfc1e23972136e8d86c45d43f3bf9048aa02c59a

    Description

      I use QNetworkAccessManager to send requests to an service requiring authentication. If a specify the invalid credentials, qNetworkAccessManager is supposed to emit a authenticationRequired. However, I noticed it incorrectly checks keychain for proxy authentication and only if that fails; it will emit the authenticationRequired.

      I synced to the latest QT code from just to understand what it is doing, and to my surprise I found some really interesting stuff...

      My theory is that this buf has been caused by change https://bugreports.qt-project.org/browse/QTBUG-22033 that has been shipped with QT5.

      Here is the problematic code at line 1248 of QNetworkAccessManager.cpp:

      #ifndef QT_NO_NETWORKPROXY
      #if defined(Q_OS_MAC) && !defined(Q_OS_IOS)
      //now we try to get the username and password from keychain
      //if not successful signal will be emitted
      QString username;
      QString password;
      if (getProxyAuth(proxy.hostName(),reply-request().url().scheme(),username,password))

      { authenticator->setUser(username); authenticator->setPassword(password); authenticationManager->cacheProxyCredentials(proxy, authenticator); return; }

      #endif
      #endif //QT_NO_NETWORKPROXY

      In my mind, this "keychain" check supposed to happen in QNetworkAccessManagerPrivate::proxyAuthenticationRequired() , but instead it happens in QNetworkAccessManagerPrivate::authenticationRequired().

      Now the fun part. Above mentioned piece of code is actually causing an infinite loop! I don't have any application proxy set. So my proxy hostname is set to blank. So that means that string passed to "SecKeychainFindInternetPassword" in getProxyAuth() method on line 105 is going to find the first entry in the keychain matchin "HTTPS" protocol, which I had in my list. And because it found it, it will try to use those credentials with my HTTP request that I sent. If those credentials are incorrect, and 99.9% the will be, authenticationRequired signal will be emitted again which will again attempt to access keychain... There is your infinite loop.

      I am surprised this has not come up in any of your tests, because it is pretty common scenario on MacOSX with an app that use QNetworkAccessManager sending requests to an HTTP service with authentication.

      SOLUTION: just move the above mention code from authenticationRequired to proxyAuthenticationRequired signal; and the bug will be fixed.

      Attachments

        Issue Links

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

          Activity

            People

              peter-har Peter Hartmann
              acolovic Aki Colovic
              Votes:
              12 Vote for this issue
              Watchers:
              14 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved:

                Gerrit Reviews

                  There are no open Gerrit changes