Skip to content

Commit

Permalink
Insert KeepassHTTP Auth Key into multiple DBs
Browse files Browse the repository at this point in the history
Basic implementation of allowing user to select which DBs to insert
KeepassHTTP Authentication Keys into.

For keepassxreboot#535
  • Loading branch information
duk3luk3 committed Sep 21, 2017
1 parent a44eb8c commit 2eec43e
Show file tree
Hide file tree
Showing 6 changed files with 139 additions and 48 deletions.
30 changes: 24 additions & 6 deletions src/http/KeyAcceptDialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,9 @@ KeyAcceptDialog::~KeyAcceptDialog()

void KeyAcceptDialog::setItems(const QList<QString> &items)
{
QStandardItemModel* listViewModel = (QStandardItemModel*) ui->databasesListView->model();
QStandardItemModel* listViewModel = qobject_cast<QStandardItemModel*>(ui->databasesListView->model());

listViewModel->clear();

for (QString item: items) {
QStandardItem* listItem = new QStandardItem(item);
Expand All @@ -54,9 +56,20 @@ void KeyAcceptDialog::setItems(const QList<QString> &items)
}
}

void KeyAcceptDialog::setItemEnabled(int itemIndex, bool enabled)
{
QStandardItemModel* listViewModel = qobject_cast<QStandardItemModel*>(ui->databasesListView->model());

QStandardItem* item = listViewModel->item(itemIndex);

if (item) {
item->setEnabled(enabled);
}
}

void KeyAcceptDialog::setItemChecked(int itemIndex, bool checked)
{
QStandardItemModel* listViewModel = (QStandardItemModel*) ui->databasesListView->model();
QStandardItemModel* listViewModel = qobject_cast<QStandardItemModel*>(ui->databasesListView->model());

QStandardItem* item = listViewModel->item(itemIndex);

Expand All @@ -69,19 +82,19 @@ void KeyAcceptDialog::setItemChecked(int itemIndex, bool checked)
}
}

QList<int>* KeyAcceptDialog::getCheckedItems()
QList<int> KeyAcceptDialog::getCheckedItems()
{
QStandardItemModel* listViewModel = (QStandardItemModel*) ui->databasesListView->model();
QStandardItemModel* listViewModel = qobject_cast<QStandardItemModel*>(ui->databasesListView->model());

int numRows = listViewModel->rowCount();

//XXX Memory Leak
QList<int>* resultList = new QList<int>;
QList<int> resultList;

for (int row = 0; row < numRows; row++) {
QStandardItem* item = listViewModel->item(row);
if (item->checkState() == Qt::Checked) {
resultList->append(row);
resultList << row;
}
}

Expand All @@ -92,3 +105,8 @@ QString KeyAcceptDialog::getKeyName()
{
return ui->keyNameLineEdit->text();
}

//TODO
//void KeyAcceptDialog::databaseUnlocked(DatabaseWidget* dbWidget)
//{
//}
8 changes: 7 additions & 1 deletion src/http/KeyAcceptDialog.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,16 @@ class KeyAcceptDialog : public QDialog

void setItems(const QList<QString> & items);
void setItemChecked(int itemIndex, bool checked);
QList<int>* getCheckedItems();
void setItemEnabled(int itemIndex, bool enabled);
QList<int> getCheckedItems();

QString getKeyName();

//TODO
//public slots:
// void databaseUnlocked(DatabaseWidget* dbWidget);
// void databaseLocked(DatabaseWidget* dbWidget);

private:
QScopedPointer<Ui::KeyAcceptDialog> ui;
};
Expand Down
9 changes: 6 additions & 3 deletions src/http/KeyAcceptDialog.ui
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>403</width>
<height>233</height>
<width>469</width>
<height>292</height>
</rect>
</property>
<property name="windowTitle">
Expand Down Expand Up @@ -39,7 +39,10 @@
</sizepolicy>
</property>
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Which databases should this key be valid for?&lt;br&gt;(The currently selected database is pre-selected)&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Which databases should this key be valid for?&lt;br&gt;(The currently selected database is pre-selected; grayed-out databases are not opened - open them to enable accepting key!)&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
Expand Down
4 changes: 3 additions & 1 deletion src/http/Server.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
#include <QtCore/QObject>
#include <QtCore/QList>

#include "gui/DatabaseTabWidget.h"

namespace qhttp {
namespace server {
class QHttpServer;
Expand All @@ -44,7 +46,7 @@ class Server : public QObject
public:
explicit Server(QObject *parent = 0);

virtual bool isDatabaseOpened() const = 0;
virtual bool isDatabaseOpened(DatabaseWidget* dbWidget = NULL) const = 0;
virtual bool openDatabase() = 0;
virtual QString getDatabaseRootUuid() = 0;
virtual QString getDatabaseRecycleBinUuid() = 0;
Expand Down
131 changes: 95 additions & 36 deletions src/http/Service.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,36 @@ Entry* Service::getConfigEntry(bool create)
return NULL;
}

bool Service::isDatabaseOpened() const
QList<Entry*> Service::getConfigEntries(bool create)
{
if (DatabaseWidget* dbWidget = m_dbTabWidget->currentDatabaseWidget())
QList<Entry*> entries;

for (int i = 0; i < m_dbTabWidget->count(); i++)
if (DatabaseWidget* dbWidget = qobject_cast<DatabaseWidget*>(m_dbTabWidget->widget(i)))
if (Database* db = dbWidget->database()) {
Entry* entry = db->resolveEntry(KEEPASSHTTP_UUID);
if (!entry && create) {
entry = new Entry();
entry->setTitle(QLatin1String(KEEPASSHTTP_NAME));
entry->setUuid(KEEPASSHTTP_UUID);
entry->setAutoTypeEnabled(false);
entry->setGroup(db->rootGroup());
} else if (entry && entry->group() == db->metadata()->recycleBin()) {
if (create)
entry->setGroup(db->rootGroup());
else
entry = NULL;
}
entries << entry;
}
return entries;
}

bool Service::isDatabaseOpened(DatabaseWidget* dbWidget) const
{
if (!dbWidget)
dbWidget = m_dbTabWidget->currentDatabaseWidget();
if (dbWidget)
switch(dbWidget->currentMode()) {
case DatabaseWidget::None:
case DatabaseWidget::LockedMode:
Expand Down Expand Up @@ -147,46 +174,78 @@ QString Service::getKey(const QString &id)
return QString();
}

QString Service::storeKey(const QString &key)
QList<QString> Service::getKeys(const QString &id)
{
QString id;
if (DatabaseWidget* dbWidget = m_dbTabWidget->currentDatabaseWidget())
if (Database* db = dbWidget->database())
if (Entry* config = getConfigEntry(true)) {
KeyAcceptDialog dlg;
QList<QString> dbNames;

//TODO get more databases in
dbNames.append(m_dbTabWidget->tabText(m_dbTabWidget->currentIndex()));

dlg.setItems(dbNames);


QList<QString> keys;
QList<Entry*> entries = getConfigEntries();
for (Entry* config : entries) {
keys << config->attributes()->value(QLatin1String(ASSOCIATE_KEY_PREFIX) + id);
}
return keys;
}

do {
bool ok;
//Indicate who wants to associate, and request user to enter the 'name' of association key
//XXX
//bool Service::attributeExists(QList<Entry*> entries, const QString &attribute)
bool Service::attributeExists(QList<Entry*> entries, const QString attribute)
{
for (Entry* entry: entries)
if (entry->attributes()->contains(attribute))
return true;
return false;
}

int res = dlg.exec();
QString Service::storeKey(const QString &key)
{
QString id;
QList<DatabaseWidget*> dbWidgets;
QList<QString> dbTexts;
DatabaseWidget* currDbWidget = m_dbTabWidget->currentDatabaseWidget();
for (int i = 0; i < m_dbTabWidget->count(); i++) {
dbWidgets << qobject_cast<DatabaseWidget*>(m_dbTabWidget->widget(i));
dbTexts << m_dbTabWidget->tabText(i);
}

if (res == QDialog::Accepted) {
QList<Entry*> configs = getConfigEntries(true);

//TODO use this
QList<int>* databases = dlg.getCheckedItems();
id = dlg.getKeyName();
} else {
return QString();
}
if (dbWidgets.count() && configs.count()) {

KeyAcceptDialog dlg;
QList<QString> dbNames;

//Warn if association key already exists
} while(config->attributes()->contains(QLatin1String(ASSOCIATE_KEY_PREFIX) + id) &&
QMessageBox::warning(0, tr("KeePassXC: Overwrite existing key?"),
tr("A shared encryption-key with the name \"%1\" already exists.\nDo you want to overwrite it?").arg(id),
QMessageBox::Yes | QMessageBox::No) == QMessageBox::No);
dlg.setItems(dbTexts);
for (int i=0; i<dbWidgets.count(); i++) {
if (!isDatabaseOpened(dbWidgets.at(i)))
dlg.setItemEnabled(i, false);
if (dbWidgets.at(i) == currDbWidget)
dlg.setItemChecked(i, true);
}

config->attributes()->set(QLatin1String(ASSOCIATE_KEY_PREFIX) + id, key, true);
}
do {
bool ok;
//Indicate who wants to associate, and request user to enter the 'name' of association key

int res = dlg.exec();

if (res != QDialog::Accepted)
return QString();

//Warn if association key already exists
} while(attributeExists(configs, QLatin1String(ASSOCIATE_KEY_PREFIX) + id) &&
QMessageBox::warning(0, tr("KeePassXC: Overwrite existing key?"),
tr("A shared encryption-key with the name \"%1\" already exists.\nDo you want to overwrite it?").arg(id),
QMessageBox::Yes | QMessageBox::No) == QMessageBox::No);
QList<int> selectedDatabases = dlg.getCheckedItems();
id = dlg.getKeyName();
// for (int i=0; i<selectedDatabases.count(); i++) {
// int dbIdx = selectedDatabases.at(i);
// qWarning("adding key to db: %d", dbIdx);
// configs.at(dbIdx)->attributes()->set(QLatin1String(ASSOCIATE_KEY_PREFIX) + id, key, true);
// }
for (int dbIdx: selectedDatabases) {
qWarning("adding key to db: %d", dbIdx);
configs.at(dbIdx)->attributes()->set(QLatin1String(ASSOCIATE_KEY_PREFIX) + id, key, true);
}
}
return id;
}

Expand Down Expand Up @@ -534,7 +593,7 @@ QString Service::generatePassword()

void Service::removeSharedEncryptionKeys()
{
if (!isDatabaseOpened()) {
if (!isDatabaseOpened(NULL)) {
QMessageBox::critical(0, tr("KeePassXC: Database locked!"),
tr("The active database is locked!\n"
"Please unlock the selected database or choose another one which is unlocked."),
Expand Down Expand Up @@ -573,7 +632,7 @@ void Service::removeSharedEncryptionKeys()

void Service::removeStoredPermissions()
{
if (!isDatabaseOpened()) {
if (!isDatabaseOpened(NULL)) {
QMessageBox::critical(0, tr("KeePassXC: Database locked!"),
tr("The active database is locked!\n"
"Please unlock the selected database or choose another one which is unlocked."),
Expand Down
5 changes: 4 additions & 1 deletion src/http/Service.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,12 @@ class Service : public KeepassHttpProtocol::Server
public:
explicit Service(DatabaseTabWidget* parent = 0);

virtual bool isDatabaseOpened() const;
virtual bool isDatabaseOpened(DatabaseWidget* dbWidget) const;
virtual bool openDatabase();
virtual QString getDatabaseRootUuid();
virtual QString getDatabaseRecycleBinUuid();
virtual QString getKey(const QString& id);
virtual QList<QString> getKeys(const QString& id);
virtual QString storeKey(const QString& key);
virtual QList<KeepassHttpProtocol::Entry> findMatchingEntries(const QString& id, const QString& url, const QString& submitUrl, const QString& realm);
virtual int countMatchingEntries(const QString& id, const QString& url, const QString& submitUrl, const QString& realm);
Expand All @@ -49,7 +50,9 @@ public slots:

private:
enum Access { Denied, Unknown, Allowed};
QList<Entry*> getConfigEntries(bool create = false);
Entry* getConfigEntry(bool create = false);
bool attributeExists(QList<Entry*> entries, const QString attribute);
bool matchUrlScheme(const QString& url);
Access checkAccess(const Entry* entry, const QString& host, const QString& submitHost, const QString& realm);
bool removeFirstDomain(QString& hostname);
Expand Down

0 comments on commit 2eec43e

Please sign in to comment.