Skip to content

Commit

Permalink
Add Polkit Quick Unlock mechanism
Browse files Browse the repository at this point in the history
This commit and subsequent pull request adds support for Quick Unlock on Linux via Polkit
Polkit allows for authentication of many means, including fingerprint scanning fixing Issue keepassxreboot#5991
Furthermore, a common interface for Quick Unlocking has been implemented, and has been replaced throughout to make implementing other mediums easier.
This also fixes keepassxreboot#3337, giving fingerprint reader support to the final major supported platform - Linux.
  • Loading branch information
HexF committed Aug 23, 2023
1 parent 6f14bec commit 7097517
Show file tree
Hide file tree
Showing 19 changed files with 471 additions and 103 deletions.
2 changes: 1 addition & 1 deletion cmake/CLangFormat.cmake
Expand Up @@ -18,7 +18,7 @@ set(EXCLUDED_DIRS
src/thirdparty
src/zxcvbn
# objective-c directories
src/touchid
src/quickunlock/touchid
src/autotype/mac
src/gui/osutils/macutils)

Expand Down
3 changes: 3 additions & 0 deletions share/CMakeLists.txt
Expand Up @@ -58,7 +58,10 @@ if(UNIX AND NOT APPLE AND NOT HAIKU)
EXCLUDE PATTERN "actions" EXCLUDE PATTERN "categories" EXCLUDE)
endif(KEEPASSXC_DIST_FLATPAK)
configure_file(linux/${APP_ID}.desktop.in ${CMAKE_CURRENT_BINARY_DIR}/linux/${APP_ID}.desktop @ONLY)
configure_file(linux/${APP_ID}.policy.in ${CMAKE_CURRENT_BINARY_DIR}/linux/${APP_ID}.policy @ONLY)

install(FILES ${CMAKE_CURRENT_BINARY_DIR}/linux/${APP_ID}.desktop DESTINATION ${CMAKE_INSTALL_DATADIR}/applications)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/linux/${APP_ID}.policy DESTINATION ${CMAKE_INSTALL_DATADIR}/polkit-1/actins)
install(FILES linux/${APP_ID}.appdata.xml DESTINATION ${CMAKE_INSTALL_DATADIR}/metainfo)
endif(UNIX AND NOT APPLE AND NOT HAIKU)

Expand Down
18 changes: 18 additions & 0 deletions share/linux/org.keepassxc.KeePassXC.policy.in
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE policyconfig PUBLIC
"-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
"http://www.freedesktop.org/standards/PolicyKit/1.0/policyconfig.dtd">
<policyconfig>
<vendor>KeePassXC Developers</vendor>
<vendor_url></vendor_url>
<icon_name>@APP_ICON_NAME@</icon_name>

<action id="org.keepassxc.KeePassXC.unlockDatabase">
<description>Quick Unlock for a KeePassXC Database</description>
<message>Unlocks a KeePassXC Database</message>
<defaults>
<allow_inactive>no</allow_inactive>
<allow_active>auth_self_one_shot</allow_active>
</defaults>
</action>
</policyconfig>
22 changes: 19 additions & 3 deletions src/CMakeLists.txt
Expand Up @@ -193,6 +193,7 @@ set(keepassx_SOURCES
streams/qtiocompressor.cpp
streams/StoreDataStream.cpp
streams/SymmetricCipherStream.cpp
quickunlock/QuickUnlockInterface.cpp
totp/totp.cpp)
if(APPLE)
set(keepassx_SOURCES
Expand All @@ -206,6 +207,8 @@ endif()
if(UNIX AND NOT APPLE)
set(keepassx_SOURCES
${keepassx_SOURCES}
quickunlock/Polkit.cpp
quickunlock/PolkitDbusTypes.cpp
gui/osutils/nixutils/ScreenLockListenerDBus.cpp
gui/osutils/nixutils/NixUtils.cpp)
if(WITH_XC_X11)
Expand All @@ -216,14 +219,26 @@ if(UNIX AND NOT APPLE)
gui/org.keepassxc.KeePassXC.MainWindow.xml
gui/MainWindow.h
MainWindow)

set_source_files_properties(
quickunlock/dbus/org.freedesktop.PolicyKit1.Authority.xml
PROPERTIES
INCLUDE "quickunlock/PolkitDbusTypes.h"
)
qt5_add_dbus_interface(keepassx_SOURCES
quickunlock/dbus/org.freedesktop.PolicyKit1.Authority.xml
polkit_dbus
)

set(keyutils_LIB keyutils)
endif()
if(WIN32)
set(keepassx_SOURCES
${keepassx_SOURCES}
gui/osutils/winutils/ScreenLockListenerWin.cpp
gui/osutils/winutils/WinUtils.cpp)
if (MSVC)
list(APPEND keepassx_SOURCES winhello/WindowsHello.cpp)
list(APPEND keepassx_SOURCES quickunlock/WindowsHello.cpp)
endif()
endif()

Expand Down Expand Up @@ -315,9 +330,9 @@ if(WITH_XC_NETWORKING)
endif()

if(APPLE)
list(APPEND keepassx_SOURCES touchid/TouchID.mm)
list(APPEND keepassx_SOURCES quickunlock/TouchID.mm)
# TODO: Remove -Wno-error once deprecation warnings have been resolved.
set_source_files_properties(touchid/TouchID.mm PROPERTY COMPILE_FLAGS "-Wno-old-style-cast")
set_source_files_properties(quickunlock/TouchID.mm PROPERTY COMPILE_FLAGS "-Wno-old-style-cast")
endif()

configure_file(config-keepassx.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-keepassx.h)
Expand All @@ -334,6 +349,7 @@ target_link_libraries(keepassx_core
${keepassxcbrowser_LIB}
${qrcode_LIB}
${fdosecrets_LIB}
${keyutils_LIB}
Qt5::Core
Qt5::Concurrent
Qt5::Network
Expand Down
9 changes: 3 additions & 6 deletions src/gui/ApplicationSettingsWidget.cpp
Expand Up @@ -29,15 +29,10 @@
#include "gui/Icons.h"
#include "gui/MainWindow.h"
#include "gui/osutils/OSUtils.h"
#include "quickunlock/QuickUnlockInterface.h"

#include "FileDialog.h"
#include "MessageBox.h"
#ifdef Q_OS_MACOS
#include "touchid/TouchID.h"
#endif
#ifdef Q_CC_MSVC
#include "winhello/WindowsHello.h"
#endif

class ApplicationSettingsWidget::ExtraPage
{
Expand Down Expand Up @@ -164,6 +159,8 @@ ApplicationSettingsWidget::ApplicationSettingsWidget(QWidget* parent)
m_generalUi->faviconTimeoutLabel->setVisible(false);
m_generalUi->faviconTimeoutSpinBox->setVisible(false);
#endif

m_secUi->quickUnlockCheckBox->setVisible(getQuickUnlock()->isAvailable());
}

ApplicationSettingsWidget::~ApplicationSettingsWidget() = default;
Expand Down
51 changes: 16 additions & 35 deletions src/gui/DatabaseOpenWidget.cpp
Expand Up @@ -26,13 +26,7 @@
#include "gui/MessageBox.h"
#include "keys/ChallengeResponseKey.h"
#include "keys/FileKey.h"

#ifdef Q_OS_MACOS
#include "touchid/TouchID.h"
#endif
#ifdef Q_CC_MSVC
#include "winhello/WindowsHello.h"
#endif
#include "quickunlock/QuickUnlockInterface.h"

#include <QCheckBox>
#include <QCloseEvent>
Expand All @@ -46,23 +40,15 @@ namespace
bool isQuickUnlockAvailable()
{
if (config()->get(Config::Security_QuickUnlock).toBool()) {
#if defined(Q_CC_MSVC)
return getWindowsHello()->isAvailable();
#elif defined(Q_OS_MACOS)
return TouchID::getInstance().isAvailable();
#endif
return getQuickUnlock()->isAvailable();
}
return false;
}

bool canPerformQuickUnlock(const QString& filename)
{
if (isQuickUnlockAvailable()) {
#if defined(Q_CC_MSVC)
return getWindowsHello()->hasKey(filename);
#elif defined(Q_OS_MACOS)
return TouchID::getInstance().containsKey(filename);
#endif
return getQuickUnlock()->hasKey(filename);
}
Q_UNUSED(filename);
return false;
Expand Down Expand Up @@ -283,17 +269,7 @@ void DatabaseOpenWidget::openDatabase()
// Save Quick Unlock credentials if available
if (!blockQuickUnlock && isQuickUnlockAvailable()) {
auto keyData = databaseKey->serialize();
#if defined(Q_CC_MSVC)
// Store the password using Windows Hello
if (!getWindowsHello()->storeKey(m_filename, keyData)) {
getMainWindow()->displayTabMessage(
tr("Windows Hello setup was canceled or failed. Quick unlock has not been enabled."),
MessageWidget::MessageType::Warning);
}
#elif defined(Q_OS_MACOS)
// Store the password using TouchID
TouchID::getInstance().storeKey(m_filename, keyData);
#endif
getQuickUnlock()->storeKey(m_filename, keyData);
m_ui->messageWidget->hideMessage();
}

Expand Down Expand Up @@ -341,6 +317,7 @@ QSharedPointer<CompositeKey> DatabaseOpenWidget::buildDatabaseKey()
if (canPerformQuickUnlock(m_filename)) {
// try to retrieve the stored password using Windows Hello
QByteArray keyData;
<<<<<<< HEAD
#ifdef Q_CC_MSVC
if (!getWindowsHello()->getKey(m_filename, keyData)) {
// Failed to retrieve Quick Unlock data
Expand All @@ -350,15 +327,12 @@ QSharedPointer<CompositeKey> DatabaseOpenWidget::buildDatabaseKey()
MessageWidget::Error);
resetQuickUnlock();
}
=======
if(!getQuickUnlock()->getKey(m_filename, keyData)){
m_ui->messageWidget->showMessage(tr("Failed to authenticate with Quick Unlock"), MessageWidget::Error);
>>>>>>> acdfa1fe (Add Polkit Quick Unlock mechanism)
return {};
}
#elif defined(Q_OS_MACOS)
if (!TouchID::getInstance().getKey(m_filename, keyData)) {
// Failed to retrieve Quick Unlock data
m_ui->messageWidget->showMessage(tr("Failed to authenticate with Touch ID"), MessageWidget::Error);
return {};
}
#endif
databaseKey->setRawKey(keyData);
return databaseKey;
}
Expand Down Expand Up @@ -553,10 +527,17 @@ void DatabaseOpenWidget::triggerQuickUnlock()
*/
void DatabaseOpenWidget::resetQuickUnlock()
{
<<<<<<< HEAD
#if defined(Q_CC_MSVC)
getWindowsHello()->reset(m_filename);
#elif defined(Q_OS_MACOS)
TouchID::getInstance().reset(m_filename);
#endif
=======
if (!isQuickUnlockAvailable()) {
return;
}
getQuickUnlock()->reset(m_filename);
>>>>>>> acdfa1fe (Add Polkit Quick Unlock mechanism)
load(m_filename);
}
13 changes: 2 additions & 11 deletions src/gui/dbsettings/DatabaseSettingsWidgetDatabaseKey.cpp
Expand Up @@ -25,13 +25,8 @@
#include "keys/ChallengeResponseKey.h"
#include "keys/FileKey.h"
#include "keys/PasswordKey.h"
#include "quickunlock/QuickUnlockInterface.h"

#ifdef Q_OS_MACOS
#include "touchid/TouchID.h"
#endif
#ifdef Q_CC_MSVC
#include "winhello/WindowsHello.h"
#endif

#include <QLayout>
#include <QPushButton>
Expand Down Expand Up @@ -198,11 +193,7 @@ bool DatabaseSettingsWidgetDatabaseKey::save()

m_db->setKey(newKey, true, false, false);

#if defined(Q_OS_MACOS)
TouchID::getInstance().reset(m_db->filePath());
#elif defined(Q_CC_MSVC)
getWindowsHello()->reset(m_db->filePath());
#endif
getQuickUnlock()->reset(m_db->filePath());

emit editFinished(true);
if (m_isDirty) {
Expand Down
2 changes: 1 addition & 1 deletion src/gui/reports/ReportsDialog.cpp
Expand Up @@ -31,7 +31,7 @@
#include "core/Global.h"
#include "core/Group.h"
#ifdef Q_OS_MACOS
#include "touchid/TouchID.h"
#include "quickunlock/TouchID.h"
#endif

class ReportsDialog::ExtraPage
Expand Down

0 comments on commit 7097517

Please sign in to comment.