Skip to content

Commit

Permalink
Add QR code generator for TOTP export (keepassxreboot#1167)
Browse files Browse the repository at this point in the history
* Resolves keepassxreboot#764
* Add libqrencode and qtsvg dependencies 
* Ensure QR code remains square
* Auto-close QR code dialog when database is locked
* Add databaseLocked() Signal to databaseWidget
* Correct otpauth URI output in Totp::writeSettings(...)
  • Loading branch information
adolfogc authored and droidmonkey committed Oct 19, 2018
1 parent 8074995 commit bb16dc6
Show file tree
Hide file tree
Showing 21 changed files with 584 additions and 16 deletions.
8 changes: 5 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -294,16 +294,16 @@ endif(WITH_TESTS)
include(CLangFormat)

if(UNIX AND NOT APPLE)
find_package(Qt5 COMPONENTS Core Network Concurrent Widgets Test LinguistTools DBus REQUIRED)
find_package(Qt5 COMPONENTS Core Network Concurrent Widgets Svg Test LinguistTools DBus REQUIRED)
elseif(APPLE)
find_package(Qt5 COMPONENTS Core Network Concurrent Widgets Test LinguistTools REQUIRED
find_package(Qt5 COMPONENTS Core Network Concurrent Widgets Svg Test LinguistTools REQUIRED
HINTS /usr/local/Cellar/qt/*/lib/cmake ENV PATH
)
find_package(Qt5 COMPONENTS MacExtras
HINTS /usr/local/Cellar/qt/*/lib/cmake ENV PATH
)
else()
find_package(Qt5 COMPONENTS Core Network Concurrent Widgets Test LinguistTools REQUIRED)
find_package(Qt5 COMPONENTS Core Network Concurrent Widgets Svg Test LinguistTools REQUIRED)
endif()

if(Qt5Core_VERSION VERSION_LESS "5.2.0")
Expand Down Expand Up @@ -339,6 +339,8 @@ find_package(Argon2 REQUIRED)

find_package(ZLIB REQUIRED)

find_package(QREncode REQUIRED)

set(CMAKE_REQUIRED_INCLUDES ${ZLIB_INCLUDE_DIR})

if(ZLIB_VERSION_STRING VERSION_LESS "1.2.0")
Expand Down
6 changes: 4 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

FROM ubuntu:14.04

ENV REBUILD_COUNTER=8
ENV REBUILD_COUNTER=10

ENV QT5_VERSION=qt510
ENV QT5_PPA_VERSION=qt-5.10.1
Expand Down Expand Up @@ -50,12 +50,14 @@ RUN set -x \
${QT5_VERSION}x11extras \
${QT5_VERSION}translations \
${QT5_VERSION}imageformats \
${QT5_VERSION}svg \
zlib1g-dev \
libxi-dev \
libxtst-dev \
mesa-common-dev \
libyubikey-dev \
libykpers-1-dev
libykpers-1-dev \
libqrencode-dev

ENV PATH="/opt/${QT5_VERSION}/bin:${PATH}"
ENV CMAKE_PREFIX_PATH="/opt/${QT5_VERSION}/lib/cmake"
Expand Down
4 changes: 3 additions & 1 deletion ci/trusty/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

FROM ubuntu:14.04

ENV REBUILD_COUNTER=4
ENV REBUILD_COUNTER=5

ENV QT5_VERSION=qt53
ENV QT5_PPA_VERSION=${QT5_VERSION}2
Expand Down Expand Up @@ -49,11 +49,13 @@ RUN set -x \
${QT5_VERSION}tools \
${QT5_VERSION}x11extras \
${QT5_VERSION}translations \
${QT5_VERSION}svg \
zlib1g-dev \
libyubikey-dev \
libykpers-1-dev \
libxi-dev \
libxtst-dev \
libqrencode-dev \
xvfb

ENV PATH="/opt/${QT5_VERSION}/bin:${PATH}"
Expand Down
22 changes: 22 additions & 0 deletions cmake/FindQREncode.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Copyright (C) 2017 KeePassXC Team <[email protected]>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 or (at your option)
# version 3 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

find_path(QRENCODE_INCLUDE_DIR qrencode.h)
find_library(QRENCODE_LIBRARY qrencode)

mark_as_advanced(QRENCODE_LIBRARY QRENCODE_INCLUDE_DIR)

include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(QREncode DEFAULT_MSG QRENCODE_LIBRARY QRENCODE_INCLUDE_DIR)
2 changes: 2 additions & 0 deletions snapcraft.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ parts:
- libgcrypt20-dev
- libqt5x11extras5-dev
- qtbase5-dev
- qtsvg5-dev
- qttools5-dev
- qttools5-dev-tools
- zlib1g-dev
Expand All @@ -48,6 +49,7 @@ parts:
- libykpers-1-dev
- libsodium-dev
- libargon2-0-dev
- libqrencode-dev
stage-packages:
- dbus
- qttranslations5-l10n # common translations
Expand Down
11 changes: 9 additions & 2 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,10 @@ set(keepassx_SOURCES
gui/ApplicationSettingsWidget.cpp
gui/SearchWidget.cpp
gui/SortFilterHideProxyModel.cpp
gui/SquareSvgWidget.cpp
gui/TotpSetupDialog.cpp
gui/TotpDialog.cpp
gui/TotpExportSettingsDialog.cpp
gui/UnlockDatabaseWidget.cpp
gui/UnlockDatabaseDialog.cpp
gui/WelcomeWidget.cpp
Expand Down Expand Up @@ -225,6 +227,8 @@ endif()

add_subdirectory(autotype)
add_subdirectory(cli)
add_subdirectory(qrcode)
set(qrcode_LIB qrcode)

add_subdirectory(sshagent)
if(WITH_XC_SSHAGENT)
Expand Down Expand Up @@ -270,17 +274,20 @@ target_link_libraries(keepassx_core
autotype
${keepassxcbrowser_LIB}
${sshagent_LIB}
${qrcode_LIB}
Qt5::Core
Qt5::Network
Qt5::Concurrent
Qt5::Network
Qt5::Widgets
${CURL_LIBRARIES}
${YUBIKEY_LIBRARIES}
${ZXCVBN_LIBRARIES}
${ARGON2_LIBRARIES}
${GCRYPT_LIBRARIES}
${GPGERROR_LIBRARIES}
${ZLIB_LIBRARIES})
${YUBIKEY_LIBRARIES}
${ZLIB_LIBRARIES}
${ZXCVBN_LIBRARIES})

if(APPLE)
target_link_libraries(keepassx_core "-framework Foundation")
Expand Down
2 changes: 1 addition & 1 deletion src/core/Entry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -369,7 +369,7 @@ void Entry::setTotp(QSharedPointer<Totp::Settings> settings)
beginUpdate();
m_data.totpSettings = settings;

auto text = Totp::writeSettings(m_data.totpSettings);
auto text = Totp::writeSettings(m_data.totpSettings, title(), username());
if (m_attributes->hasKey(Totp::ATTRIBUTE_OTP)) {
m_attributes->set(Totp::ATTRIBUTE_OTP, text, true);
} else {
Expand Down
14 changes: 14 additions & 0 deletions src/gui/DatabaseWidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
#include "gui/MessageBox.h"
#include "gui/TotpSetupDialog.h"
#include "gui/TotpDialog.h"
#include "gui/TotpExportSettingsDialog.h"
#include "gui/UnlockDatabaseDialog.h"
#include "gui/UnlockDatabaseWidget.h"
#include "gui/entry/EditEntryWidget.h"
Expand Down Expand Up @@ -572,6 +573,18 @@ void DatabaseWidget::copyAttribute(QAction* action)
currentEntry->resolveMultiplePlaceholders(currentEntry->attributes()->value(action->data().toString())));
}

void DatabaseWidget::showTotpKeyQrCode()
{
Entry* currentEntry = m_entryView->currentEntry();
Q_ASSERT(currentEntry);
if (!currentEntry) {
return;
}

auto totpDisplayDialog = new TotpExportSettingsDialog(this, currentEntry);
totpDisplayDialog->open();
}

void DatabaseWidget::setClipboardTextAndMinimize(const QString& text)
{
clipboard()->setText(text);
Expand Down Expand Up @@ -1171,6 +1184,7 @@ void DatabaseWidget::lock()
Database* newDb = new Database();
newDb->metadata()->setName(m_db->metadata()->name());
replaceDatabase(newDb);
emit lockedDatabase();
}

void DatabaseWidget::updateFilePath(const QString& filePath)
Expand Down
2 changes: 2 additions & 0 deletions src/gui/DatabaseWidget.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ class DatabaseWidget : public QStackedWidget
void pressedEntry(Entry* selectedEntry);
void pressedGroup(Group* selectedGroup);
void unlockedDatabase();
void lockedDatabase();
void listModeAboutToActivate();
void listModeActivated();
void searchModeAboutToActivate();
Expand All @@ -146,6 +147,7 @@ public slots:
void copyNotes();
void copyAttribute(QAction* action);
void showTotp();
void showTotpKeyQrCode();
void copyTotp();
void setupTotp();
void performAutoType();
Expand Down
2 changes: 2 additions & 0 deletions src/gui/MainWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,7 @@ MainWindow::MainWindow()
m_actionMultiplexer.connect(m_ui->actionEntrySetupTotp, SIGNAL(triggered()), SLOT(setupTotp()));

m_actionMultiplexer.connect(m_ui->actionEntryCopyTotp, SIGNAL(triggered()), SLOT(copyTotp()));
m_actionMultiplexer.connect(m_ui->actionEntryTotpQRCode, SIGNAL(triggered()), SLOT(showTotpKeyQrCode()));
m_actionMultiplexer.connect(m_ui->actionEntryCopyTitle, SIGNAL(triggered()), SLOT(copyTitle()));
m_actionMultiplexer.connect(m_ui->actionEntryCopyUsername, SIGNAL(triggered()), SLOT(copyUsername()));
m_actionMultiplexer.connect(m_ui->actionEntryCopyPassword, SIGNAL(triggered()), SLOT(copyPassword()));
Expand Down Expand Up @@ -478,6 +479,7 @@ void MainWindow::setMenuActionState(DatabaseWidget::Mode mode)
m_ui->actionEntryTotp->setEnabled(singleEntrySelected && dbWidget->currentEntryHasTotp());
m_ui->actionEntryCopyTotp->setEnabled(singleEntrySelected && dbWidget->currentEntryHasTotp());
m_ui->actionEntrySetupTotp->setEnabled(singleEntrySelected);
m_ui->actionEntryTotpQRCode->setEnabled(singleEntrySelected && dbWidget->currentEntryHasTotp());
m_ui->actionGroupNew->setEnabled(groupSelected);
m_ui->actionGroupEdit->setEnabled(groupSelected);
m_ui->actionGroupDelete->setEnabled(groupSelected && dbWidget->canDeleteCurrentGroup());
Expand Down
8 changes: 7 additions & 1 deletion src/gui/MainWindow.ui
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,7 @@
</property>
<addaction name="actionEntryCopyTotp"/>
<addaction name="actionEntryTotp"/>
<addaction name="actionEntryTotpQRCode"/>
<addaction name="actionEntrySetupTotp"/>
</widget>
<addaction name="actionEntryCopyUsername"/>
Expand Down Expand Up @@ -577,7 +578,12 @@
</action>
<action name="actionEntryTotp">
<property name="text">
<string>Show TOTP</string>
<string>Show TOTP...</string>
</property>
</action>
<action name="actionEntryTotpQRCode">
<property name="text">
<string>Show TOTP QR Code...</string>
</property>
</action>
<action name="actionEntrySetupTotp">
Expand Down
28 changes: 28 additions & 0 deletions src/gui/SquareSvgWidget.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* Copyright (C) 2018 KeePassXC Team <[email protected]>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 or (at your option)
* version 3 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#include "SquareSvgWidget.h"

bool SquareSvgWidget::hasHeightForWidth() const
{
return true;
}

int SquareSvgWidget::heightForWidth(int width) const
{
return width;
}
33 changes: 33 additions & 0 deletions src/gui/SquareSvgWidget.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Copyright (C) 2018 KeePassXC Team <[email protected]>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 or (at your option)
* version 3 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef KEEPASSX_SquareSvgWidget_H
#define KEEPASSX_SquareSvgWidget_H

#include <QtSvg/QSvgWidget>

class SquareSvgWidget : public QSvgWidget
{
public:
SquareSvgWidget() = default;
~SquareSvgWidget() override = default;

bool hasHeightForWidth() const override;
int heightForWidth(int width) const override;
};

#endif // KEEPASSX_SquareSvgWidget_H
Loading

0 comments on commit bb16dc6

Please sign in to comment.