diff -Nru qtpass-1.1.6/debian/changelog qtpass-1.1.6/debian/changelog --- qtpass-1.1.6/debian/changelog 2016-12-02 16:23:16.000000000 +0100 +++ qtpass-1.1.6/debian/changelog 2018-02-27 10:45:10.000000000 +0100 @@ -1,3 +1,12 @@ +qtpass (1.1.6-1ubuntu0.1) artful-security; urgency=low + + * SECURITY UPDATE: Insecure built-in password generator (LP: #1747954) + - debian/patches/01-fix-password-generator.patch: Fix password generator + - debian/NEWS: Warn users to eventually regenerate their passwords + - CVE-2017-18021 + + -- Philip Rinn Tue, 27 Feb 2018 10:45:10 +0100 + qtpass (1.1.6-1) unstable; urgency=medium * New upstream release diff -Nru qtpass-1.1.6/debian/NEWS qtpass-1.1.6/debian/NEWS --- qtpass-1.1.6/debian/NEWS 1970-01-01 01:00:00.000000000 +0100 +++ qtpass-1.1.6/debian/NEWS 2018-02-27 10:45:10.000000000 +0100 @@ -0,0 +1,15 @@ +qtpass (1.1.6-1ubuntu0.1) artful-security; urgency=low + + All passwords generated with QtPass' built-in password generator prior to + 1.1.6-1+deb9u1 are possibly predictable and enumerable by hackers. + The generator used libc's random(), seeded with srand(msecs), where msecs is + not the msecs since 1970 (not that that'd be secure anyway), but rather the + msecs since the last second. This means there are only 1000 different + sequences of generated passwords. + . + NB: QtPass uses `pwgen` to generate passwords by default. This means, if you + didn't change the configuration to use the built-in password generator your + passwords are safe. If you used the built-in password generator, change all + passwords you generated with QtPass. + + -- Philip Rinn Tue, 27 Feb 2018 10:45:10 +0100 diff -Nru qtpass-1.1.6/debian/patches/01-fix-password-generator.patch qtpass-1.1.6/debian/patches/01-fix-password-generator.patch --- qtpass-1.1.6/debian/patches/01-fix-password-generator.patch 1970-01-01 01:00:00.000000000 +0100 +++ qtpass-1.1.6/debian/patches/01-fix-password-generator.patch 2018-01-04 22:38:41.000000000 +0100 @@ -0,0 +1,67 @@ +--- a/mainwindow.cpp ++++ b/mainwindow.cpp +@@ -67,7 +67,6 @@ + connect(actionAddPassword, SIGNAL(triggered()), this, + SLOT(on_addButton_clicked())); + connect(actionAddFolder, SIGNAL(triggered()), this, SLOT(addFolder())); +- qsrand(static_cast(QTime::currentTime().msec())); + + #if QT_VERSION >= QT_VERSION_CHECK(5, 2, 0) + ui->lineEdit->setClearButtonEnabled(true); +@@ -1900,10 +1899,10 @@ + else + qDebug() << "pwgen fail"; + } else { +- int charsetLength = pwdConfig.Characters[selection].length(); ++ quint32 charsetLength = pwdConfig.Characters[selection].length(); + if (charsetLength > 0) { + for (int i = 0; i < length; ++i) { +- int index = qrand() % charsetLength; ++ quint32 index = Util::boundedRandom(charsetLength); + QChar nextChar = pwdConfig.Characters[selection].at(index); + passwd.append(nextChar); + } +--- a/util.cpp ++++ b/util.cpp +@@ -9,6 +9,9 @@ + #else + #include + #endif ++#include ++#include ++#include + QProcessEnvironment Util::_env; + bool Util::_envInitialised; + +@@ -137,3 +140,21 @@ + nanosleep(&ts, NULL); + #endif + } ++ ++quint32 Util::boundedRandom(quint32 bound) { ++ static int fd = -1; ++ if (bound < 2) ++ return 0; ++ ++ if (fd == -1) ++ assert((fd = open("/dev/urandom", O_RDONLY)) >= 0); ++ ++ quint32 randval; ++ const quint32 max_mod_bound = (1 + ~bound) % bound; ++ ++ do ++ assert(read(fd, &randval, sizeof(randval)) == sizeof(randval)); ++ while (randval < max_mod_bound); ++ ++ return randval % bound; ++} +--- a/util.h ++++ b/util.h +@@ -16,6 +16,7 @@ + static bool checkConfig(QString passStore, QString passExecutable, + QString gpgExecutable); + static void qSleep(int ms); ++ static quint32 boundedRandom(quint32 bound); + + private: + static void initialiseEnvironment(); diff -Nru qtpass-1.1.6/debian/patches/series qtpass-1.1.6/debian/patches/series --- qtpass-1.1.6/debian/patches/series 1970-01-01 01:00:00.000000000 +0100 +++ qtpass-1.1.6/debian/patches/series 2018-01-04 22:11:50.000000000 +0100 @@ -0,0 +1 @@ +01-fix-password-generator.patch