summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnne Jan Brouwer <brouwer@annejan.com>2015-04-20 17:02:00 +0200
committerAnne Jan Brouwer <brouwer@annejan.com>2015-04-20 17:02:00 +0200
commit651a2aac88e47cc09a72d9dfa507fb1c99d23846 (patch)
tree6e1cbe26e8e023c38db79d0470f53515fe118027
parent180587a00de32253622e7977828a7a227126f186 (diff)
parent3f26c153662f6f27277abff889030d79e57c1924 (diff)
Merge pull request #29 from rdoeffinger/webdav
Add WebDAV support.
-rw-r--r--README.md25
-rw-r--r--mainwindow.cpp80
-rw-r--r--mainwindow.h6
3 files changed, 110 insertions, 1 deletions
diff --git a/README.md b/README.md
index 5851df0c..439c7116 100644
--- a/README.md
+++ b/README.md
@@ -3,6 +3,31 @@ qtpass
QtPass is a gui for [pass](http://www.passwordstore.org/)
+Security considerations
+-----------------------
+Using this program will not magically keep your passwords secure against
+compromised computers even if you use it in combination with a smartcard.
+It does protect future and changed passwords though against anyone with access to
+your password store only but not your keys.
+Used with a smartcard it also protects against anyone just monitoring/copying
+all files/keystrokes on that machine and such an attacker would only gain access
+to the passwords you actually use.
+Once you plug in your smartcard and enter your PIN (or due to CVE-2015-3298
+even without your PIN) all your passwords available to the machine can be
+decrypted by it, if there is malicious software targeted specifically against
+it installed (or at least one that knows how to use a smartcard).
+To get better protection out of use with a smartcard even against a targeted
+attack I can think of at least two options:
+* The smartcard must require explicit confirmation for each decryption operation.
+ Or if it just provides a counter for decrypted data you could at least notice
+ an attack afterwards, though at quite some effort on your part.
+* Use a different smartcard for each (group of) key.
+* If using a YubiKey or U2F module or similar that requires a "button" press for
+ other authentication methods you can use one OTP/U2F enabled WebDAV account per
+ password (or groups of passwords) as a quite inconvenient workaround.
+ Unfortunately I do not know of any WebDAV service with OTP support except ownCloud
+ (so you would have to run your own server).
+
Current state
-------------
* Using pass or directly with git and gpg2
diff --git a/mainwindow.cpp b/mainwindow.cpp
index b7495b13..3074249b 100644
--- a/mainwindow.cpp
+++ b/mainwindow.cpp
@@ -7,6 +7,10 @@
#include <QInputDialog>
#include <QMessageBox>
#include <QTimer>
+#ifdef Q_OS_WIN
+#include <windows.h>
+#undef DELETE
+#endif
/**
* @brief MainWindow::MainWindow
@@ -15,7 +19,8 @@
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow),
- process(new QProcess(this))
+ process(new QProcess(this)),
+ fusedav(this)
{
// connect(process.data(), SIGNAL(readyReadStandardOutput()), this, SLOT(readyRead()));
connect(process.data(), SIGNAL(error(QProcess::ProcessError)), this, SLOT(processError(QProcess::ProcessError)));
@@ -29,6 +34,14 @@ MainWindow::MainWindow(QWidget *parent) :
*/
MainWindow::~MainWindow()
{
+#ifdef Q_OS_WIN
+ if (useWebDav) WNetCancelConnection2A(passStore.toUtf8().constData(), 0, 1);
+#else
+ if (fusedav.state() == QProcess::Running) {
+ fusedav.terminate();
+ fusedav.waitForFinished(2000);
+ }
+#endif
}
void MainWindow::normalizePassStore() {
@@ -49,6 +62,59 @@ QSettings &MainWindow::getSettings() {
return *settings;
}
+void MainWindow::mountWebDav() {
+#ifdef Q_OS_WIN
+ char dst[20] = {0};
+ NETRESOURCEA netres;
+ memset(&netres, 0, sizeof(netres));
+ netres.dwType = RESOURCETYPE_DISK;
+ netres.lpLocalName = 0;
+ netres.lpRemoteName = webDavUrl.toUtf8().data();
+ DWORD size = sizeof(dst);
+ DWORD r = WNetUseConnectionA(reinterpret_cast<HWND>(effectiveWinId()), &netres, webDavPassword.toUtf8().constData(),
+ webDavUser.toUtf8().constData(), CONNECT_TEMPORARY | CONNECT_INTERACTIVE | CONNECT_REDIRECT,
+ dst, &size, 0);
+ if (r == NO_ERROR) {
+ passStore = dst;
+ } else {
+ char message[256] = {0};
+ FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, 0, r, 0, message, sizeof(message), 0);
+ ui->textBrowser->setTextColor(Qt::red);
+ ui->textBrowser->setText(tr("Failed to connect WebDAV:\n") + message + " (0x" + QString::number(r, 16) + ")");
+ }
+#else
+ fusedav.start("fusedav -o nonempty -u \"" + webDavUser + "\" " + webDavUrl + " \"" + passStore + '"');
+ fusedav.waitForStarted();
+ if (fusedav.state() == QProcess::Running) {
+ QString pwd = webDavPassword;
+ bool ok = true;
+ if (pwd.isEmpty()) {
+ pwd = QInputDialog::getText(this, tr("QtPass WebDAV password"),
+ tr("Enter password to connect to WebDAV:"), QLineEdit::Password, "", &ok);
+ }
+ if (ok && !pwd.isEmpty()) {
+ fusedav.write(pwd.toUtf8() + '\n');
+ fusedav.closeWriteChannel();
+ fusedav.waitForFinished(2000);
+ } else {
+ fusedav.terminate();
+ }
+ }
+ QString error = fusedav.readAllStandardError();
+ int prompt = error.indexOf("Password:");
+ if (prompt >= 0) {
+ error.remove(0, prompt + 10);
+ }
+ if (fusedav.state() != QProcess::Running) {
+ error = tr("fusedav exited unexpectedly\n") + error;
+ }
+ if (error.size() > 0) {
+ ui->textBrowser->setTextColor(Qt::red);
+ ui->textBrowser->setText(tr("Failed to start fusedav to connect WebDAV:\n") + error);
+ }
+#endif
+}
+
/**
* @brief MainWindow::checkConfig
*/
@@ -87,10 +153,22 @@ void MainWindow::checkConfig() {
}
gpgHome = settings.value("gpgHome").toString();
+ useWebDav = (settings.value("useWebDav") == "true");
+ webDavUrl = settings.value("webDavUrl").toString();
+ webDavUser = settings.value("webDavUser").toString();
+ webDavPassword = settings.value("webDavPassword").toString();
+
if (passExecutable == "" && (gitExecutable == "" || gpgExecutable == "")) {
config();
}
+ // TODO: this needs to be before we try to access the store,
+ // but it would be better to do it after the Window is shown,
+ // as the long delay it can cause is irritating otherwise.
+ if (useWebDav) {
+ mountWebDav();
+ }
+
model.setNameFilters(QStringList() << "*.gpg");
model.setNameFilterDisables(false);
diff --git a/mainwindow.h b/mainwindow.h
index b7fa84b5..19243556 100644
--- a/mainwindow.h
+++ b/mainwindow.h
@@ -70,6 +70,11 @@ private:
QString gitExecutable;
QString gpgExecutable;
QString gpgHome;
+ bool useWebDav;
+ QString webDavUrl;
+ QString webDavUser;
+ QString webDavPassword;
+ QProcess fusedav;
QString clippedPass;
actionType currentAction;
QString lastDecrypt;
@@ -87,6 +92,7 @@ private:
QSettings &getSettings();
QList<UserInfo> listKeys(QString keystring = "");
QString getRecipientString(QString for_file, QString separator = " ");
+ void mountWebDav();
};
#endif // MAINWINDOW_H