diff options
author | Aron Rosenberg <aronrosenberg@gmail.com> | 2012-04-04 16:41:27 -0700 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2012-04-11 01:42:12 +0200 |
commit | 90520cd834d84f2b091fea94f1d44bc6cb863420 (patch) | |
tree | 721e2ef556f19faee93d3aa2e2ca0966c07761d2 /src | |
parent | c524bbbb8aa4ba10bac68292a3078534f1b51df5 (diff) |
Automatically query for Mac Proxy Server credentials
Add support for automatically searching the Mac System Preferences
for proxy server username/password. If a user has put credentials
in the SystemPreferences->Network->Interface->Proxies area, we
will now look in the KeyChain for those files. This will
automatically pop up a Permissions dialog from the OS if valid
credentials were found which match the server we are trying to
access.
Task-Number: QTBUG-22033
Change-Id: Ic7952afab4d16a65a87bb2f97a928c1c91167fe7
Reviewed-by: Shane Kearns <shane.kearns@accenture.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/network/access/access.pri | 2 | ||||
-rw-r--r-- | src/network/access/qnetworkaccessmanager.cpp | 70 |
2 files changed, 72 insertions, 0 deletions
diff --git a/src/network/access/access.pri b/src/network/access/access.pri index e0a0253b6c..590a37bf15 100644 --- a/src/network/access/access.pri +++ b/src/network/access/access.pri @@ -65,3 +65,5 @@ SOURCES += \ access/qhttpmultipart.cpp include($$PWD/../../3rdparty/zlib_dependency.pri) + +mac:LIBS_PRIVATE += -framework Security diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp index 397bb0535e..3a69ec4056 100644 --- a/src/network/access/qnetworkaccessmanager.cpp +++ b/src/network/access/qnetworkaccessmanager.cpp @@ -82,6 +82,64 @@ Q_GLOBAL_STATIC(QNetworkAccessFtpBackendFactory, ftpBackend) Q_GLOBAL_STATIC(QNetworkAccessDebugPipeBackendFactory, debugpipeBackend) #endif +#ifdef Q_OS_MAC + +#include <CoreServices/CoreServices.h> +#include <SystemConfiguration/SystemConfiguration.h> +#include <Security/SecKeychain.h> + +bool getProxyAuth(const QString& proxyHostname, const QString &scheme, QString& username, QString& password) +{ + OSStatus err; + SecKeychainItemRef itemRef; + bool retValue = false; + SecProtocolType protocolType = kSecProtocolTypeAny; + if (scheme.compare(QLatin1String("ftp"),Qt::CaseInsensitive)==0) { + protocolType = kSecProtocolTypeFTP; + } else if (scheme.compare(QLatin1String("http"),Qt::CaseInsensitive)==0) { + protocolType = kSecProtocolTypeHTTP; + } else if (scheme.compare(QLatin1String("https"),Qt::CaseInsensitive)==0) { + protocolType = kSecProtocolTypeHTTPS; + } + QByteArray proxyHostnameUtf8(proxyHostname.toUtf8()); + err = SecKeychainFindInternetPassword(NULL, + proxyHostnameUtf8.length(), proxyHostnameUtf8.constData(), + 0,NULL, + 0, NULL, + 0, NULL, + 0, + protocolType, + kSecAuthenticationTypeAny, + 0, NULL, + &itemRef); + if (err == noErr) { + + SecKeychainAttribute attr; + SecKeychainAttributeList attrList; + UInt32 length; + void *outData; + + attr.tag = kSecAccountItemAttr; + attr.length = 0; + attr.data = NULL; + + attrList.count = 1; + attrList.attr = &attr; + + if (SecKeychainItemCopyContent(itemRef, NULL, &attrList, &length, &outData) == noErr) { + username = QString::fromUtf8((const char*)attr.data, attr.length); + password = QString::fromUtf8((const char*)outData, length); + SecKeychainItemFreeContent(&attrList,outData); + retValue = true; + } + CFRelease(itemRef); + } + return retValue; +} +#endif + + + static void ensureInitialized() { #ifndef QT_NO_FTP @@ -1117,6 +1175,18 @@ void QNetworkAccessManagerPrivate::authenticationRequired(QAuthenticator *authen return; } } +#ifdef Q_OS_MAC + //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 // if we emit a signal here in synchronous mode, the user might spin // an event loop, which might recurse and lead to problems |