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