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 slotKeychainJobDone(); 61 void slotSenderDestroyed(QObject *); 62 63 private: 64 ProxyAuthHandler(); 65 66 /// Runs the ProxyAuthDialog and returns true if new credentials were entered. 67 bool getCredsFromDialog(); 68 69 /// Checks the keychain for credentials of the current proxy. 70 bool getCredsFromKeychain(); 71 72 /// Stores the current credentials in the keychain. 73 void storeCredsInKeychain(); 74 75 QString keychainUsernameKey() const; 76 QString keychainPasswordKey() const; 77 78 /// The hostname:port of the current proxy, used for detecting switches 79 /// to a different proxy. 80 QString _proxy; 81 82 QString _username; 83 QString _password; 84 85 /// If the user cancels the credential dialog, blocked will be set to 86 /// true and we won't bother him again. 87 bool _blocked; 88 89 /// In several instances handleProxyAuthenticationRequired() can be called 90 /// while it is still running. These counters detect what we're currently 91 /// waiting for. 92 int _waitingForDialog; 93 int _waitingForKeychain; 94 bool _keychainJobRunning; 95 96 QPointer<ProxyAuthDialog> _dialog; 97 98 /// The QSettings instance to securely store username/password in the keychain. 99 QScopedPointer<QSettings> _settings; 100 101 /// Pointer to the most-recently-run ReadPasswordJob, needed due to reentrancy. 102 QScopedPointer<QKeychain::ReadPasswordJob> _readPasswordJob; 103 104 /// For checking the proxy config settings. 105 QScopedPointer<ConfigFile> _configFile; 106 107 /// To distinguish between a new QNAM asking for credentials and credentials 108 /// failing for an existing QNAM, we keep track of the senders of the 109 /// proxyAuthRequired signal here. 110 QSet<QObject *> _gaveCredentialsTo; 111 }; 112 113 } // namespace OCC 114