24#include "ui_masterpassworddialog.h"
30#define INTERNAL_SERVER_ID QLatin1String("falkon.internal")
34 , m_stateOfMasterPassword(UnKnownState)
35 , m_askPasswordDialogVisible(false)
36 , m_askMasterPassword(false)
39 if (!db.tables().contains(QLatin1String(
"autofill_encrypted"))) {
40 db.exec(
QSL(
"CREATE TABLE autofill_encrypted (data_encrypted TEXT, id INTEGER PRIMARY KEY,"
41 "password_encrypted TEXT, server TEXT, username_encrypted TEXT, last_used NUMERIC)"));
42 db.exec(
QSL(
"CREATE INDEX autofillEncryptedServer ON autofill_encrypted(server ASC)"));
51 if (!m_askMasterPassword) {
56 query.prepare(
QSL(
"SELECT username_encrypted FROM autofill_encrypted WHERE server=? ORDER BY last_used DESC"));
61 while (query.next()) {
62 list.append(
QSL(
"Encrypted %1").arg(list.size() + 1));
69 QVector<PasswordEntry> list;
76 query.prepare(
QSL(
"SELECT id, username_encrypted, password_encrypted, data_encrypted FROM autofill_encrypted "
77 "WHERE server=? ORDER BY last_used DESC"));
78 query.addBindValue(host);
84 data.
id = query.value(0);
86 data.
username = query.value(1).toString();
87 data.
password = query.value(2).toString();
88 data.
data = query.value(3).toByteArray();
102 QVector<PasswordEntry> list;
107 query.prepare(
QSL(
"SELECT id, server, username_encrypted, password_encrypted, data_encrypted FROM autofill_encrypted"));
113 data.
id = query.value(0);
114 data.
host = query.value(1).toString();
118 data.
username = query.value(2).toString();
119 data.
password = query.value(3).toString();
120 data.
data = query.value(4).toByteArray();
126 while (query.next());
151 m_masterPassword.clear();
159 if (entry.
data.isEmpty()) {
162 query.prepare(
QSL(
"SELECT username_encrypted FROM autofill_encrypted WHERE server=?"));
163 query.addBindValue(entry.
host);
176 query.prepare(
QSL(
"INSERT INTO autofill_encrypted (server, data_encrypted, username_encrypted, password_encrypted, last_used) "
177 "VALUES (?,?,?,?,strftime('%s', 'now'))"));
178 query.bindValue(0, encryptedEntry.
host);
179 query.bindValue(1, encryptedEntry.
data);
180 query.bindValue(2, encryptedEntry.
username);
181 query.bindValue(3, encryptedEntry.
password);
195 if (entry.
data.isEmpty()) {
196 query.prepare(
QSL(
"UPDATE autofill_encrypted SET username_encrypted=?, password_encrypted=? WHERE server=?"));
197 query.bindValue(0, encryptedEntry.
username);
198 query.bindValue(1, encryptedEntry.
password);
199 query.bindValue(2, encryptedEntry.
host);
202 query.prepare(
QSL(
"UPDATE autofill_encrypted SET data_encrypted=?, username_encrypted=?, password_encrypted=? WHERE id=?"));
203 query.addBindValue(encryptedEntry.
data);
204 query.addBindValue(encryptedEntry.
username);
205 query.addBindValue(encryptedEntry.
password);
206 query.addBindValue(encryptedEntry.
id);
218 query.prepare(
QSL(
"UPDATE autofill_encrypted SET last_used=strftime('%s', 'now') WHERE id=?"));
219 query.addBindValue(entry.
id);
230 query.prepare(
QSL(
"DELETE FROM autofill_encrypted WHERE id=?"));
231 query.addBindValue(entry.
id);
235 if (someDataFromDatabase().isEmpty()) {
247 query.prepare(
QSL(
"DELETE FROM autofill_encrypted"));
257 return AutoFill::tr(
"Database (encrypted)");
268 masterPasswordDialog->showSettingPage();
282 return m_masterPassword;
287 if (!m_askMasterPassword) {
291 if (m_askPasswordDialogVisible) {
295 m_askPasswordDialogVisible =
true;
299 bool authorized = dialog->exec() == QDialog::Accepted;
301 m_askPasswordDialogVisible =
false;
307 if (password.isEmpty()) {
311 if (m_masterPassword == password) {
314 else if (!m_masterPassword.isEmpty()) {
321 aes.
decrypt(someDataFromDatabase(), password);
323 m_masterPassword = password;
337 return aesInterface->
isOk();
346 return aesInterface->
isOk();
352 masterPasswordDialog->showSetMasterPasswordPage();
353 masterPasswordDialog->delayedExec();
358 if (m_masterPassword == newPassword) {
362 if (newPassword.isEmpty()) {
369 m_masterPassword = newPassword;
375 if (!m_masterPassword.isEmpty()) {
378 m_masterPassword.clear();
385 m_askMasterPassword = ask;
390 if (encryptorPassword == decryptorPassword) {
395 query.prepare(
QSL(
"SELECT id, data_encrypted, password_encrypted, username_encrypted, server FROM autofill_encrypted"));
401 while (query.next()) {
402 QString server = query.value(4).toString();
407 int id = query.value(0).toInt();
408 QByteArray data = query.value(1).toString().toUtf8();
409 QByteArray password = query.value(2).toString().toUtf8();
410 QByteArray username = query.value(3).toString().toUtf8();
412 if (!decryptorPassword.isEmpty()) {
413 data = decryptor.
decrypt(data, decryptorPassword);
414 password = decryptor.
decrypt(password, decryptorPassword);
415 username = decryptor.
decrypt(username, decryptorPassword);
418 if (!encryptorPassword.isEmpty()) {
419 data = encryptor.
encrypt(data, encryptorPassword);
420 password = encryptor.
encrypt(password, encryptorPassword);
421 username = encryptor.
encrypt(username, encryptorPassword);
425 updateQuery.prepare(
QSL(
"UPDATE autofill_encrypted SET data_encrypted = ?, password_encrypted = ?, username_encrypted = ? WHERE id = ?"));
426 updateQuery.addBindValue(data);
427 updateQuery.addBindValue(password);
428 updateQuery.addBindValue(username);
429 updateQuery.addBindValue(
id);
434QByteArray DatabaseEncryptedPasswordBackend::someDataFromDatabase()
436 if (m_stateOfMasterPassword !=
UnKnownState && !m_someDataStoredOnDataBase.isEmpty()) {
437 return m_someDataStoredOnDataBase;
441 query.prepare(
QSL(
"SELECT password_encrypted, data_encrypted, username_encrypted FROM autofill_encrypted"));
447 while (someData.isEmpty()) {
457 someData = query.value(
i).toByteArray();
462 m_someDataStoredOnDataBase = someData;
463 return m_someDataStoredOnDataBase;
469 query.prepare(
QSL(
"SELECT id FROM autofill_encrypted WHERE server = ?"));
473 if (!password.isEmpty()) {
478 query.prepare(
QSL(
"UPDATE autofill_encrypted SET password_encrypted = ? WHERE server=?"));
481 query.prepare(
QSL(
"INSERT INTO autofill_encrypted (password_encrypted, server) VALUES (?,?)"));
484 query.addBindValue(QString::fromUtf8(m_someDataStoredOnDataBase));
490 else if (query.next()) {
491 query.prepare(
QSL(
"DELETE FROM autofill_encrypted WHERE server = ?"));
496 m_someDataStoredOnDataBase.clear();
509 : QDialog(parent, Qt::WindowStaysOnTopHint | Qt::MSWindowsFixedSizeDialogHint)
513 setAttribute(Qt::WA_DeleteOnClose,
true);
521 connect(ui->buttonBox, SIGNAL(rejected()),
this, SLOT(
reject()));
522 connect(ui->buttonBoxMasterPassword, SIGNAL(rejected()),
this, SLOT(
reject()));
523 connect(ui->buttonBoxMasterPassword, SIGNAL(accepted()),
this, SLOT(
accept()));
533 QTimer::singleShot(0,
this, &QDialog::exec);
538 if (ui->stackedWidget->currentIndex() != 1) {
546 QMessageBox::information(
this, tr(
"Warning!"), tr(
"You entered a wrong password!"));
550 if (ui->newPassword->text() != ui->confirmPassword->text()) {
551 QMessageBox::information(
this, tr(
"Warning!"), tr(
"New/Confirm password fields do not match!"));
555 if (ui->newPassword->text().isEmpty()) {
578 QMessageBox::information(
this, AutoFill::tr(
"Warning!"),
579 AutoFill::tr(
"This backend needs a master password to be set! "
580 "Falkon just switches to its default backend"));
582 mApp->autoFill()->passwordManager()->switchBackend(
QSL(
"database"));
589 ui->stackedWidget->setCurrentIndex(0);
595 ui->stackedWidget->setCurrentIndex(1);
600 if (QMessageBox::information(
this, tr(
"Warning!"), tr(
"Are you sure you want to clear master password and decrypt data?"), QMessageBox::Yes | QMessageBox::No)
601 == QMessageBox::No) {
611 const QVector<PasswordEntry> list = m_backend->
getAllEntries();
612 PasswordBackend* databaseBackend =
mApp->autoFill()->passwordManager()->availableBackends().value(
QSL(
"database"));
613 if (!databaseBackend) {
617 const QVector<PasswordEntry> databaseList = databaseBackend->
getAllEntries();
618 bool allDataMoved =
true;
620 bool sameEntry =
false;
624 allDataMoved =
false;
640 mApp->autoFill()->passwordManager()->switchBackend(
QSL(
"database"));
643 QMessageBox::information(
this, tr(
"Warning!"), tr(
"Some data has not been decrypted. The master password was not cleared!"));
644 mApp->autoFill()->passwordManager()->switchBackend(
QSL(
"database"));
653 if ((entry1.
data.isEmpty() || entry2.
data.isEmpty()) && entry1.
host == entry2.
host) {
665 : QDialog(parent, Qt::WindowStaysOnTopHint | Qt::MSWindowsFixedSizeDialogHint)
668 setWindowModality(Qt::ApplicationModal);
669 setWindowTitle(AutoFill::tr(
"Enter Master Password"));
671 auto* verticalLayout =
new QVBoxLayout(
this);
672 auto* label =
new QLabel(
this);
673 label->setText(AutoFill::tr(
"Permission is required, please enter Master Password:"));
674 m_lineEdit =
new QLineEdit(
this);
675 m_lineEdit->setEchoMode(QLineEdit::Password);
676 m_buttonBox =
new QDialogButtonBox(
this);
677 m_buttonBox->setStandardButtons(QDialogButtonBox::Cancel | QDialogButtonBox::Ok);
678 m_labelWarning =
new QLabel(
this);
679 m_labelWarning->setText(AutoFill::tr(
"Entered password is wrong!"));
680 QPalette pal = m_labelWarning->palette();
681 pal.setBrush(QPalette::WindowText, Qt::red);
682 m_labelWarning->setPalette(pal);
683 m_labelWarning->hide();
685 verticalLayout->addWidget(label);
686 verticalLayout->addWidget(m_lineEdit);
687 verticalLayout->addWidget(m_labelWarning);
688 verticalLayout->addWidget(m_buttonBox);
689 setLayout(verticalLayout);
691 connect(m_lineEdit, &QLineEdit::returnPressed,
this, &AskMasterPassword::verifyPassword);
692 connect(m_buttonBox, &QDialogButtonBox::accepted,
this, &AskMasterPassword::verifyPassword);
693 connect(m_buttonBox, &QDialogButtonBox::rejected,
this, &QDialog::reject);
695 setAttribute(Qt::WA_DeleteOnClose);
698void AskMasterPassword::verifyPassword()
703 m_labelWarning->show();
705 m_lineEdit->setFocus();
static QByteArray createRandomData(int length)
QByteArray decrypt(const QByteArray &cipherData, const QByteArray &password)
QByteArray encrypt(const QByteArray &plainData, const QByteArray &password)
static QByteArray passwordToHash(const QString &masterPassword)
AskMasterPassword(DatabaseEncryptedPasswordBackend *backend, QWidget *parent=nullptr)
bool decryptPasswordEntry(PasswordEntry &entry, AesInterface *aesInterface)
QByteArray masterPassword() const
void setActive(bool active) override
QString name() const override
void removeMasterPassword()
bool isPasswordVerified(const QByteArray &password)
void showMasterPasswordDialog()
void updateSampleData(const QByteArray &password)
bool encryptPasswordEntry(PasswordEntry &entry, AesInterface *aesInterface)
void showSettings(QWidget *parent) override
bool updateEntry(const PasswordEntry &entry) override
void encryptDataBaseTableOnFly(const QByteArray &decryptorPassword, const QByteArray &encryptorPassword)
DatabaseEncryptedPasswordBackend()
void setAskMasterPasswordState(bool ask)
void removeAll() override
~DatabaseEncryptedPasswordBackend() override
QVector< PasswordEntry > getAllEntries() override
bool hasSettings() const override
void updateLastUsed(PasswordEntry &entry) override
bool isMasterPasswordSetted()
QVector< PasswordEntry > getEntries(const QUrl &url) override
void addEntry(const PasswordEntry &entry) override
void removeEntry(const PasswordEntry &entry) override
void tryToChangeMasterPassword(const QByteArray &newPassword)
QStringList getUsernames(const QUrl &url) override
bool samePasswordEntry(const PasswordEntry &entry1, const PasswordEntry &entry2)
void showSetMasterPasswordPage()
MasterPasswordDialog(DatabaseEncryptedPasswordBackend *backend, QWidget *parent=nullptr)
void clearMasterPasswordAndConvert(bool forcedAskPass=true)
~MasterPasswordDialog() override
virtual void addEntry(const PasswordEntry &entry)=0
virtual QVector< PasswordEntry > getAllEntries()=0
virtual QStringList getUsernames(const QUrl &url)
virtual void setActive(bool active)
static QString createHost(const QUrl &url)
static SqlDatabase * instance()
#define INTERNAL_SERVER_ID