nextcloud-desktop/src/gui/creds/webflowcredentials.h
Michael Schuster 0bcac1882a Make WebFlowCredentialsDialog cancellation- and deletion-safe
- Add new signal to let WebFlowCredentials know and emit asked() to also
  tell AccountState that the user won't authenticate, and triggering
  log-out state in the settings window.

- Use deleteLater() to safely delete WebFlowCredentialsDialog, so
  that Qt can free it at the right time and without crashes.
  Do the same with it's _webView and _flow2AuthWidget on closeEvent().

Signed-off-by: Michael Schuster <michael@schuster.ms>
2019-12-24 07:46:57 +01:00

140 lines
4.1 KiB
C++

#ifndef WEBFLOWCREDENTIALS_H
#define WEBFLOWCREDENTIALS_H
#include <QSslCertificate>
#include <QSslKey>
#include <QNetworkRequest>
#include <QQueue>
#include "creds/abstractcredentials.h"
class QDialog;
class QLabel;
class QNetworkReply;
class QAuthenticator;
namespace QKeychain {
class Job;
}
namespace OCC {
class WebFlowCredentialsDialog;
class WebFlowCredentials : public AbstractCredentials
{
Q_OBJECT
friend class WebFlowCredentialsAccessManager;
public:
/// Don't add credentials if this is set on a QNetworkRequest
static constexpr QNetworkRequest::Attribute DontAddCredentialsAttribute = QNetworkRequest::User;
explicit WebFlowCredentials();
WebFlowCredentials(
const QString &user,
const QString &password,
const QSslCertificate &certificate = QSslCertificate(),
const QSslKey &key = QSslKey(),
const QList<QSslCertificate> &caCertificates = QList<QSslCertificate>());
QString authType() const override;
QString user() const override;
QString password() const;
QNetworkAccessManager *createQNAM() const override;
bool ready() const override;
void fetchFromKeychain() override;
void askFromUser() override;
bool stillValid(QNetworkReply *reply) override;
void persist() override;
void invalidateToken() override;
void forgetSensitiveData() override;
// To fetch the user name as early as possible
void setAccount(Account *account) override;
private slots:
void slotAuthentication(QNetworkReply *reply, QAuthenticator *authenticator);
void slotFinished(QNetworkReply *reply);
void slotAskFromUserCredentialsProvided(const QString &user, const QString &pass, const QString &host);
void slotAskFromUserCancelled();
void slotReadClientCertPEMJobDone(QKeychain::Job *incomingJob);
void slotReadClientKeyPEMJobDone(QKeychain::Job *incomingJob);
void slotReadClientCaCertsPEMJobDone(QKeychain::Job *incommingJob);
void slotReadPasswordJobDone(QKeychain::Job *incomingJob);
void slotWriteClientCertPEMJobDone();
void slotWriteClientKeyPEMJobDone();
void slotWriteClientCaCertsPEMJobDone(QKeychain::Job *incomingJob);
void slotWriteJobDone(QKeychain::Job *);
private:
/*
* Windows: Workaround for CredWriteW used by QtKeychain
*
* Saving all client CA's within one credential may result in:
* Error: "Credential size exceeds maximum size of 2560"
*/
void readSingleClientCaCertPEM();
void writeSingleClientCaCertPEM();
/*
* Since we're limited by Windows limits, we just create our own
* limit to avoid evil things happening by endless recursion
*
* Better than storing the count and relying on maybe-hacked values
*/
static constexpr int _clientSslCaCertificatesMaxCount = 10;
QQueue<QSslCertificate> _clientSslCaCertificatesWriteQueue;
/*
* Workaround: ...and this time only on Windows:
*
* Split the private key into chunks of 2048 bytes,
* to allow 4k (4096 bit) keys to be saved (see limits above)
*/
void writeSingleClientKeyChunkPEM(QKeychain::Job *incomingJob);
static constexpr int _clientSslKeyChunkSize = 2048;
static constexpr int _clientSslKeyMaxChunks = 10;
int _clientSslKeyChunkCount = 0;
QByteArray _clientSslKeyChunkBufferPEM;
protected:
/** Reads data from keychain locations
*
* Goes through
* slotReadClientCertPEMJobDone to
* slotReadClientKeyPEMJobDone to
* slotReadClientCaCertsPEMJobDone to
* slotReadJobDone
*/
void fetchFromKeychainHelper();
/// Wipes legacy keychain locations
void deleteKeychainEntries(bool oldKeychainEntries = false);
QString fetchUser();
QString _user;
QString _password;
QSslKey _clientSslKey;
QSslCertificate _clientSslCertificate;
QList<QSslCertificate> _clientSslCaCertificates;
bool _ready;
bool _credentialsValid;
bool _keychainMigration;
bool _retryOnKeyChainError = true; // true if we haven't done yet any reading from keychain
WebFlowCredentialsDialog *_askDialog;
};
}
#endif // WEBFLOWCREDENTIALS_H