Commit 40847c7a authored by Philip Rinn's avatar Philip Rinn

Imported Upstream version 1.0.6

parent e0ea7aa9
......@@ -10,12 +10,12 @@ after_build:
- cmd: copy LICENSE release\LICENSE.txt
- iscc qtpass.iss
artifacts:
- path: Output\QtPass_v*.exe
- path: Output\qtpass-*.exe
deploy:
provider: GitHub
auth_token:
secure: YfscG1DR0+kApThPXxQSr+ZEjUOUlIG0Tqc5+90IFsUInyICRRMdbJsbxR2qhq/p
artifact: /QtPass_v[0-9]+\.[0-9]+\.[0-9]+\.exe/
artifact: /qtpass-[0-9]+\.[0-9]+\.[0-9]+\.exe/
draft: true
prerelease: false
on:
......
platform: linux | osx
build:
- qmake
- make
analyzers:
- cpplint: true
include: ["*.cpp", "*.h", "*.hpp", "*.c"]
path: ./
filters:
- -whitespace
- +whitespace/braces
style: google
- markdownlint: true
......@@ -10,11 +10,13 @@ This document is stil in a very early stage and needs a lot more work.
## Translations
* Add you language to the `qtpass.pro` file under TRANSLATIONS and in the `resources.qrc` file.
* Add you language to the `qtpass.pro` file
under TRANSLATIONS and in the `resources.qrc` file.
* Next run the command `lupdate qtpass.pro` which will create the localization files.
* Edit your file with (let's imagine your language is sv_SE (Swedish) `linguist localization/localization_sv_SE.ts`
* Edit your file with (let's imagine your language is sv_SE (Swedish)
`linguist localization/localization_sv_SE.ts`
Qt Linguist has very nice in-context translation options https://doc-snapshots.qt.io/qt5-5.6/linguist-translators.html
Qt Linguist has very nice in-context translation options [for translators](https://doc-snapshots.qt.io/qt5-5.6/linguist-translators.html)
## IRC
......
#FAQ
# FAQ
## Issues
### Can't save a password
* Is folder initialised? Easiest way is to use the [Users] button and make sure you can encrypt for someone (eg. yourself)
* Is folder initialised? Easiest way is to use the [Users] button
and make sure you can encrypt for someone (eg. yourself)
* Are you using git? If not, make sure it is switched off.
### I have an issue with GNOME keyring
* Disable GNOME keyring
* Create a `~/.gnupg/gpg-agent.conf` containing:
```
enable-ssh-support
write-env-file
......@@ -17,7 +21,8 @@ default-cache-ttl 600
max-cache-ttl 7200
```
Also, the following is useful to add to your .bashrc if you are using Yubikey NEO on Ubuntu:
Also, the following is useful to add to
your .bashrc if you are using Yubikey NEO on Ubuntu:
```
# OpenPGP applet support for YubiKey NEO
......@@ -31,28 +36,38 @@ fi
* More info: [issue 60](https://github.com/IJHack/qtpass/issues/60) and [issue 73](https://github.com/IJHack/qtpass/issues/73)
### I don't get a passphrase / PIN dialog
* You'll need to install pinentry-qt (or -qt4 or -qt5 or even -gtk) and possibly set the full path to that executable in your `~/.gnupg/gpg-agent.conf` for example: `pinentry-program /usr/bin/pinentry-qt4`
* On some esotheric systems it might be necessary to create a symbolic link `/usr/bin/pinentry` to your pinentry application of choice eg: `ln -s /usr/bin/pinentry-qt5 /usr/bin/pinentry`
* You'll need to install pinentry-qt (or -qt4 or -qt5 or even -gtk) and
possibly set the full path to that executable in your `~/.gnupg/gpg-agent.conf`
for example: `pinentry-program /usr/bin/pinentry-qt4`
* On some esotheric systems it might be necessary to create a symbolic
link `/usr/bin/pinentry` to your pinentry application of choice
eg: `ln -s /usr/bin/pinentry-qt5 /usr/bin/pinentry`
### Where can I ask for help?
* Create an [issue](https://github.com/IJHack/qtpass/) issues on github.
* Send an email to [help@qtpass.org](help@qtpass.org)
### Can I import from KeePass, LastPass or X?
* Yes, check [passwordstore.org/#migration](http://www.passwordstore.org/#migration) for more info.
* Yes, check [passwordstore.org/#migration](http://www.passwordstore.org/#migration)
for more info.
### I don't like the design, what gives?
* It's all on github, clone, change and send a pull request.
* Open an issue and point out defects or better yet propose changes.
## How can I help improve QtPass?
###I would like to donate!
### I would like to donate!
* Time:
* Read [contributing](CONTRIBUTING.md) documentation.
* Fork, clone hack and send a pull request.
* Find an [issue](https://github.com/IJHack/qtpass/issues) to work on..
* Participate in our bug bounty, you submit an issue and help us fix it, I send you a bounty.
* Participate in our bug bounty, you submit an issue and help us
fix it, I send you a bounty.
* Money:
IJhack takes donations in [bitcoin](https://blockchain.info/address/146dqz8zXn9iNZMv5s7JVqwZKjrmumHBfb)
* IJhack takes donations in [bitcoin](https://blockchain.info/address/146dqz8zXn9iNZMv5s7JVqwZKjrmumHBfb)
QtPass [![Build Status](https://travis-ci.org/IJHack/qtpass.svg?branch=master)](https://travis-ci.org/IJHack/qtpass) [![Build status](https://ci.appveyor.com/api/projects/status/9rjnj72rdir7u9eg/branch/master?svg=true)](https://ci.appveyor.com/project/annejan/qtpass/branch/master)
QtPass
======
QtPass is a GUI for [pass](http://www.passwordstore.org/), the standard unix password manager.
[![Build Status](https://travis-ci.org/IJHack/qtpass.svg?branch=master)](https://travis-ci.org/IJHack/qtpass)
[![Build status](https://ci.appveyor.com/api/projects/status/9rjnj72rdir7u9eg/branch/master?svg=true)](https://ci.appveyor.com/project/annejan/qtpass/branch/master)
[![Coverity scan](https://scan.coverity.com/projects/5266/badge.svg)](https://scan.coverity.com/projects/ijhack-qtpass)
QtPass is a GUI for [pass](http://www.passwordstore.org/),
the standard unix password manager.
Features
--------
* Using pass or git and gpg2 directly
* Configurable shoulder surfing protection options
* Cross platform: Linux, BSD, OS X and Windows
* Per-folder user selection for multi recipient encryption
* Multiple profiles
Logo based on https://commons.wikimedia.org/wiki/File:Heart-padlock.svg by AnonMoos.
Logo based on [Heart-padlock by AnonMoos](https://commons.wikimedia.org/wiki/File:Heart-padlock.svg).
Installation
------------
On most systems all you need is:
`qmake && make && make install`
On Mac OS X:
`qmake && make && macdeployqt QtPass.app`
* Currently seems to only work with MacGPG2
Currently seems to only work with MacGPG2
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.
......@@ -39,6 +47,7 @@ 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.
......@@ -51,22 +60,28 @@ attack I can think of at least two options:
Known issues
------------
* Filtering (searching) breaks the tree/model sometimes
* Starting without a correctly set password-store folder give weird results in the tree view
* Filtering (searching) breaks the tree/model sometimes
* Starting without a correctly set password-store folder
gives weird results in the tree view
* On Mac OS X only the gpgtools MacGPG2 version works with passphrase or PIN
Planned features
----------------
* Re-encryption after users-change (optional of course)
* Plugins based on field name, plugins follow same format as password files
* Colour coding folders (possibly disabling folders you can't decrypt)
* WebDAV (configuration) support
* Optional table view of decrypted folder contents
* Opening of (basic auth) urls in default browser? Possibly with helper plugin for filling out forms?
* Some other form of remote storage that allows for accountability / auditing (web API to retrieve the .gpg files?)
* Opening of (basic auth) urls in default browser?
Possibly with helper plugin for filling out forms?
* Some other form of remote storage that allows for
accountability / auditing (web API to retrieve the .gpg files?)
Further reading
---------------
[FAQ](FAQ.md) and [CONTRIBUTING](CONTRIBUTING.md) documentation.
[Documentation](https://qtpass.org/)
......
This diff is collapsed.
#ifndef DIALOG_H
#define DIALOG_H
#ifndef CONFIGDIALOG_H_
#define CONFIGDIALOG_H_
#include <QDialog>
#include <QFileDialog>
#include "mainwindow.h"
#include <QTableWidgetItem>
#include <QCloseEvent>
#include "mainwindow.h"
namespace Ui {
struct UserInfo;
class ConfigDialog;
}
class ConfigDialog : public QDialog
{
Q_OBJECT
class ConfigDialog : public QDialog {
Q_OBJECT
public:
explicit ConfigDialog(MainWindow *parent);
~ConfigDialog();
void setPassPath(QString);
void setGitPath(QString);
void setGpgPath(QString);
void setStorePath(QString);
void setProfiles(QHash<QString, QString>, QString);
void usePass(bool);
void useClipboard(bool);
void useAutoclear(bool);
void setAutoclear(int);
void useAutoclearPanel(bool);
void setAutoclearPanel(int);
void hidePassword(bool);
void hideContent(bool);
void addGPGId(bool);
QString getPassPath();
QString getGitPath();
QString getGpgPath();
QString getStorePath();
QHash<QString,QString> getProfiles();
bool usePass();
bool useClipboard();
bool useAutoclear();
int getAutoclear();
bool useAutoclearPanel();
int getAutoclearPanel();
bool hidePassword();
bool hideContent();
bool addGPGId();
void wizard();
void genKey(QString, QDialog *);
bool useTrayIcon();
bool hideOnClose();
bool startMinimized();
void useTrayIcon(bool);
void hideOnClose(bool);
void startMinimized(bool);
void useGit(bool);
bool useGit();
QString getPwgenPath();
void setPwgenPath(QString);
void usePwgen(bool);
void useSymbols(bool);
void setPasswordLength(int);
void setPasswordChars(QString);
bool usePwgen();
bool useSymbols();
int getPasswordLength();
QString getPasswordChars();
bool useTemplate();
void useTemplate(bool);
QString getTemplate();
void setTemplate(QString);
void templateAllFields(bool);
bool templateAllFields();
bool autoPull();
void autoPull(bool);
bool autoPush();
void autoPush(bool);
public:
explicit ConfigDialog(MainWindow *parent);
~ConfigDialog();
void setPassPath(QString);
void setGitPath(QString);
void setGpgPath(QString);
void setStorePath(QString);
void setProfiles(QHash<QString, QString>, QString);
void usePass(bool usePass);
void useClipboard(MainWindow::clipBoardType);
void useAutoclear(bool useAutoclear);
void setAutoclear(int seconds);
void useAutoclearPanel(bool useAutoclearPanel);
void setAutoclearPanel(int seconds);
void hidePassword(bool hidePassword);
void hideContent(bool hideContent);
void addGPGId(bool addGPGId);
QString getPassPath();
QString getGitPath();
QString getGpgPath();
QString getStorePath();
QHash<QString, QString> getProfiles();
bool usePass();
MainWindow::clipBoardType useClipboard();
bool useAutoclear();
int getAutoclear();
bool useAutoclearPanel();
int getAutoclearPanel();
bool hidePassword();
bool hideContent();
bool addGPGId();
void wizard();
void genKey(QString, QDialog *);
bool useTrayIcon();
bool hideOnClose();
bool startMinimized();
void useTrayIcon(bool useTrayIdon);
void hideOnClose(bool hideOnClose);
void startMinimized(bool startMinimized);
void useGit(bool useGit);
bool useGit();
QString getPwgenPath();
void setPwgenPath(QString);
void usePwgen(bool usePwgen);
void useSymbols(bool useSymbols);
void setPasswordLength(int pwLen);
void setPasswordChars(QString);
bool usePwgen();
bool useSymbols();
int getPasswordLength();
QString getPasswordChars();
bool useTemplate();
void useTemplate(bool useTemplate);
QString getTemplate();
void setTemplate(QString);
void templateAllFields(bool templateAllFields);
bool templateAllFields();
bool autoPull();
void autoPull(bool autoPull);
bool autoPush();
void autoPush(bool autoPush);
bool alwaysOnTop();
void alwaysOnTop(bool alwaysOnTop);
protected:
void closeEvent(QCloseEvent *event);
protected:
void closeEvent(QCloseEvent *event);
private slots:
void on_radioButtonNative_clicked();
void on_radioButtonPass_clicked();
void on_toolButtonGit_clicked();
void on_toolButtonGpg_clicked();
void on_toolButtonPwgen_clicked();
void on_toolButtonPass_clicked();
void on_toolButtonStore_clicked();
void on_checkBoxClipboard_clicked();
void on_checkBoxAutoclear_clicked();
void on_checkBoxAutoclearPanel_clicked();
void on_addButton_clicked();
void on_deleteButton_clicked();
void on_checkBoxUseTrayIcon_clicked();
void on_checkBoxUseGit_clicked();
void on_checkBoxUsePwgen_clicked();
void on_checkBoxUseTemplate_clicked();
private slots:
void on_radioButtonNative_clicked();
void on_radioButtonPass_clicked();
void on_toolButtonGit_clicked();
void on_toolButtonGpg_clicked();
void on_toolButtonPwgen_clicked();
void on_toolButtonPass_clicked();
void on_toolButtonStore_clicked();
void on_comboBoxClipboard_activated();
void on_checkBoxAutoclear_clicked();
void on_checkBoxAutoclearPanel_clicked();
void on_addButton_clicked();
void on_deleteButton_clicked();
void on_checkBoxUseTrayIcon_clicked();
void on_checkBoxUseGit_clicked();
void on_checkBoxUsePwgen_clicked();
void on_checkBoxUseTemplate_clicked();
private:
QScopedPointer<Ui::ConfigDialog> ui;
void setGroupBoxState();
QString selectExecutable();
QString selectFolder();
// QMessageBox::critical with hack to avoid crashes with
// Qt 5.4.1 when QApplication::exec was not yet called
void criticalMessage(const QString &title, const QString &text);
MainWindow *mainWindow;
private:
QScopedPointer<Ui::ConfigDialog> ui;
void setGroupBoxState();
QString selectExecutable();
QString selectFolder();
// QMessageBox::critical with hack to avoid crashes with
// Qt 5.4.1 when QApplication::exec was not yet called
void criticalMessage(const QString &title, const QString &text);
MainWindow *mainWindow;
};
#endif // DIALOG_H
#endif // CONFIGDIALOG_H_
......@@ -245,13 +245,6 @@
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QCheckBox" name="checkBoxClipboard">
<property name="text">
<string>Use clipboard</string>
</property>
</widget>
</item>
<item row="0" column="3">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
......@@ -404,6 +397,16 @@
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QComboBox" name="comboBoxClipboard"/>
</item>
<item row="6" column="3">
<widget class="QCheckBox" name="checkBoxAlwaysOnTop">
<property name="text">
<string>Always on top</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
......@@ -589,7 +592,6 @@ url</string>
<tabstop>toolButtonPwgen</tabstop>
<tabstop>passPath</tabstop>
<tabstop>toolButtonPass</tabstop>
<tabstop>checkBoxClipboard</tabstop>
<tabstop>checkBoxAutoclear</tabstop>
<tabstop>spinBoxAutoclearSeconds</tabstop>
<tabstop>checkBoxAutoclearPanel</tabstop>
......
#include "keygendialog.h"
#include "ui_keygendialog.h"
#include "progressindicator.h"
#include <QDebug>
#include <QMessageBox>
#include "ui_keygendialog.h"
#include "qprogressindicator.h"
KeygenDialog::KeygenDialog(ConfigDialog *parent) :
QDialog(parent),
ui(new Ui::KeygenDialog)
{
ui->setupUi(this);
dialog = parent;
KeygenDialog::KeygenDialog(ConfigDialog *parent)
: QDialog(parent), ui(new Ui::KeygenDialog) {
ui->setupUi(this);
dialog = parent;
}
KeygenDialog::~KeygenDialog()
{
delete ui;
}
KeygenDialog::~KeygenDialog() { delete ui; }
void KeygenDialog::on_passphrase1_textChanged(const QString &arg1)
{
if (ui->passphrase1->text() == ui->passphrase2->text()) {
ui->buttonBox->setEnabled(true);
replace("Passphrase", arg1);
if (arg1 == "") {
no_protection(true);
} else {
no_protection(false);
}
} else {
ui->buttonBox->setEnabled(false);
}
void KeygenDialog::on_passphrase1_textChanged(const QString &arg1) {
if (ui->passphrase1->text() == ui->passphrase2->text()) {
ui->buttonBox->setEnabled(true);
replace("Passphrase", arg1);
if (arg1 == "")
no_protection(true);
else
no_protection(false);
} else {
ui->buttonBox->setEnabled(false);
}
}
void KeygenDialog::on_passphrase2_textChanged(const QString &arg1)
{
on_passphrase1_textChanged(arg1);
void KeygenDialog::on_passphrase2_textChanged(const QString &arg1) {
on_passphrase1_textChanged(arg1);
}
void KeygenDialog::on_checkBox_stateChanged(int arg1)
{
if (arg1) {
ui->plainTextEdit->setReadOnly(false);
ui->plainTextEdit->setEnabled(true);
} else {
ui->plainTextEdit->setReadOnly(true);
ui->plainTextEdit->setEnabled(false);
}
void KeygenDialog::on_checkBox_stateChanged(int arg1) {
if (arg1) {
ui->plainTextEdit->setReadOnly(false);
ui->plainTextEdit->setEnabled(true);
} else {
ui->plainTextEdit->setReadOnly(true);
ui->plainTextEdit->setEnabled(false);
}
}
void KeygenDialog::on_email_textChanged(const QString &arg1)
{
replace("Name-Email", arg1);
void KeygenDialog::on_email_textChanged(const QString &arg1) {
replace("Name-Email", arg1);
}
void KeygenDialog::on_name_textChanged(const QString &arg1)
{
replace("Name-Real", arg1);
void KeygenDialog::on_name_textChanged(const QString &arg1) {
replace("Name-Real", arg1);
}
/**
......@@ -63,85 +52,77 @@ void KeygenDialog::on_name_textChanged(const QString &arg1)
* @param key
* @param value
*/
void KeygenDialog::replace(QString key, QString value)
{
QStringList clear;
QString expert = ui->plainTextEdit->toPlainText();
QStringList lines = expert.split(QRegExp("[\r\n]"),QString::SkipEmptyParts);
foreach (QString line, lines) {
line.replace(QRegExp(key+":.*"), key + ": " + value);
if (key == "Passphrase") {
line.replace("%no-protection", "Passphrase: " + value);
}
clear.append(line);
}
ui->plainTextEdit->setPlainText(clear.join("\n"));
void KeygenDialog::replace(QString key, QString value) {
QStringList clear;
QString expert = ui->plainTextEdit->toPlainText();
QStringList lines = expert.split(QRegExp("[\r\n]"), QString::SkipEmptyParts);
foreach(QString line, lines) {
line.replace(QRegExp(key + ":.*"), key + ": " + value);
if (key == "Passphrase")
line.replace("%no-protection", "Passphrase: " + value);
clear.append(line);
}
ui->plainTextEdit->setPlainText(clear.join("\n"));
}
/**
* @brief KeygenDialog::no_protection
* @param enable
*/\
void KeygenDialog::no_protection(bool enable)
{
QStringList clear;
QString expert = ui->plainTextEdit->toPlainText();
QStringList lines = expert.split(QRegExp("[\r\n]"),QString::SkipEmptyParts);
foreach (QString line, lines) {
bool remove = false;
if (!enable) {
if (line.indexOf("%no-protection") == 0) {
remove = true;
}
} else {
if (line.indexOf("Passphrase") == 0) {
line = "%no-protection";
}
}
if (!remove) {
clear.append(line);
}
*/
void KeygenDialog::no_protection(bool enable) {
QStringList clear;
QString expert = ui->plainTextEdit->toPlainText();
QStringList lines = expert.split(QRegExp("[\r\n]"), QString::SkipEmptyParts);
foreach(QString line, lines) {
bool remove = false;
if (!enable) {
if (line.indexOf("%no-protection") == 0)
remove = true;
} else {
if (line.indexOf("Passphrase") == 0)
line = "%no-protection";
}
ui->plainTextEdit->setPlainText(clear.join("\n"));
if (!remove)
clear.append(line);
}
ui->plainTextEdit->setPlainText(clear.join("\n"));
}
/**
* @brief KeygenDialog::done
* @param r
*/
void KeygenDialog::done(int r)
{
if(QDialog::Accepted == r) // ok was pressed
{
ui->widget->setEnabled(false);
ui->buttonBox->setEnabled(false);
ui->checkBox->setEnabled(false);
ui->plainTextEdit->setEnabled(false);
void KeygenDialog::done(int r) {
if (QDialog::Accepted == r) { // ok was pressed
ui->widget->setEnabled(false);
ui->buttonBox->setEnabled(false);
ui->checkBox->setEnabled(false);
ui->plainTextEdit->setEnabled(false);
QProgressIndicator* pi = new QProgressIndicator();
pi->startAnimation();
pi->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
QProgressIndicator *pi = new QProgressIndicator();
pi->startAnimation();
pi->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
ui->frame->hide();
ui->label->setText(QString("This operation can take some minutes.<br />") +
"We need to generate a lot of random bytes. It is a good idea to perform "
"some other action (type on the keyboard, move the mouse, utilize the "
"disks) during the prime generation; this gives the random number "
"generator a better chance to gain enough entropy.");
ui->frame->hide();
ui->label->setText(
QString("This operation can take some minutes.<br />") +
"We need to generate a lot of random bytes. It is a good idea to "
"perform "
"some other action (type on the keyboard, move the mouse, utilize the "
"disks) during the prime generation; this gives the random number "
"generator a better chance to gain enough entropy.");
this->layout()->addWidget(pi);
this->layout()->addWidget(pi);
this->show();
dialog->genKey(ui->plainTextEdit->toPlainText(), this);
}
else // cancel, close or exc was pressed
{
QDialog::done(r);
return;
}
this->show();
dialog->genKey(ui->plainTextEdit->toPlainText(), this);
} else { // cancel, close or exc was pressed
QDialog::done(r);
return;
}
}
void KeygenDialog::closeEvent(QCloseEvent *event) {
// TODO save window size or somethign
event->accept();
// TODO(annejan) save window size or somethign
event->accept();
}
#ifndef KEYGENDIALOG_H
#define KEYGENDIALOG_H
#ifndef KEYGENDIALOG_H_
#define KEYGENDIALOG_H_
#include <QDialog>
#include <QCloseEvent>
......@@ -9,31 +9,29 @@ namespace Ui {
class KeygenDialog;
}
class KeygenDialog : public QDialog
{
Q_OBJECT
public:
explicit KeygenDialog(ConfigDialog *parent = 0);
~KeygenDialog();
protected:
void closeEvent(QCloseEvent *event);
private slots:
void on_passphrase1_textChanged(const QString &arg1);
void on_passphrase2_textChanged(const QString &arg1);
void on_checkBox_stateChanged(int arg1);
void on_email_textChanged(const QString &arg1);
void on_name_textChanged(const QString &arg1);
private:
Ui::KeygenDialog *ui;
void replace(QString, QString);
void done(int r);
void no_protection(bool enable);
ConfigDialog *dialog;
class KeygenDialog : public QDialog {
Q_OBJECT
public:
explicit KeygenDialog(ConfigDialog *parent = 0);
~KeygenDialog();
protected:
void closeEvent(QCloseEvent *event);
private slots:
void on_passphrase1_textChanged(const QString &arg1);
void on_passphrase2_textChanged(const QString &arg1);
void on_checkBox_stateChanged(int arg1);