1 /* 2 * Copyright (C) 2015 by Christian Kamm <kamm@incasoftware.de> 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, but 10 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 11 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * for more details. 13 */ 14 15 #pragma once 16 17 #include "owncloudgui.h" 18 #include <QObject> 19 #include <QString> 20 #include <QNetworkProxy> 21 #include <QAuthenticator> 22 #include <QPointer> 23 #include <QScopedPointer> 24 #include <QSettings> 25 #include <QSet> 26 27 namespace QKeychain { 28 class Job; 29 class ReadPasswordJob; 30 } 31 32 namespace OCC { 33 34 class ConfigFile; 35 class ProxyAuthDialog; 36 37 /** 38 * @brief Handle proxyAuthenticationRequired signals from our QNetworkAccessManagers. 39 * 40 * The main complication here is that the slot needs to return credential information 41 * synchronously - but running a dialog or getting password data from synchronous 42 * storage are asynchronous operations. This leads to reentrant calls that are 43 * fairly complicated to handle. 44 */ 45 class ProxyAuthHandler : public QObject 46 { 47 Q_OBJECT 48 49 public: 50 static ProxyAuthHandler *instance(); 51 52 ~ProxyAuthHandler() override; 53 54 public slots: 55 /// Intended for QNetworkAccessManager::proxyAuthenticationRequired() 56 void handleProxyAuthenticationRequired(const QNetworkProxy &proxy, 57 QAuthenticator *authenticator); 58 59 private slots: 60 void slotSenderDestroyed(QObject *); 61 62 private: 63 ProxyAuthHandler(); 64 65 /// Runs the ProxyAuthDialog and returns true if new credentials were entered. 66 bool getCredsFromDialog(); 67 68 /// Checks the keychain for credentials of the current proxy. 69 bool getCredsFromKeychain(); 70 71 /// Stores the current credentials in the keychain. 72 void storeCredsInKeychain(); 73 74 template<class T, typename PointerToMemberFunction> 75 void execAwait(const T *sender, 76 PointerToMemberFunction signal, 77 int &counter, 78 const QEventLoop::ProcessEventsFlags flags = QEventLoop::AllEvents); 79 80 QString keychainUsernameKey() const; 81 QString keychainPasswordKey() const; 82 83 /// The hostname:port of the current proxy, used for detecting switches 84 /// to a different proxy. 85 QString _proxy; 86 87 QString _username; 88 QString _password; 89 90 /// If the user cancels the credential dialog, blocked will be set to 91 /// true and we won't bother him again. 92 bool _blocked = false; 93 94 /// In several instances handleProxyAuthenticationRequired() can be called 95 /// while it is still running. These counters detect what we're currently 96 /// waiting for. 97 int _waitingForDialog = 0; 98 int _waitingForKeychain = 0; 99 100 QPointer<ProxyAuthDialog> _dialog; 101 102 /// The QSettings instance to securely store username/password in the keychain. 103 QScopedPointer<QSettings> _settings; 104 105 /// Pointer to the most-recently-run ReadPasswordJob, needed due to reentrancy. 106 QScopedPointer<QKeychain::ReadPasswordJob> _readPasswordJob; 107 108 /// For checking the proxy config settings. 109 QScopedPointer<ConfigFile> _configFile; 110 111 /// To distinguish between a new QNAM asking for credentials and credentials 112 /// failing for an existing QNAM, we keep track of the senders of the 113 /// proxyAuthRequired signal here. 114 QSet<QObject *> _gaveCredentialsTo; 115 }; 116 117 } // namespace OCC 118