summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRolf Eike Beer <kde@opensource.sf-tec.de>2012-03-08 21:46:09 (GMT)
committerRolf Eike Beer <kde@opensource.sf-tec.de>2012-03-08 22:22:16 (GMT)
commite2ac9db16bbab040e51ebdfb3c4e296644dc9a24 (patch)
tree86ab9a740561324ab07fc0ccf19e341726f00010
parenta030e4c15b6c1984d2698fe8d88b6bf56a841671 (diff)
fix password requests when using GnuPG 1.x
This all works well with GnuPG 2.x because that is using pinentry. Things were broken for older versions that require direct password supply. BUG:248161 FIXED-IN:4.8.2
-rw-r--r--transactions/kgpgchangepass.cpp32
-rw-r--r--transactions/kgpgchangepass.h1
-rw-r--r--transactions/kgpgdecrypt.cpp9
-rw-r--r--transactions/kgpgeditkeytransaction.cpp5
-rw-r--r--transactions/kgpggeneraterevoke.cpp5
-rw-r--r--transactions/kgpgtextorfiletransaction.cpp13
-rw-r--r--transactions/kgpgtextorfiletransaction.h1
-rw-r--r--transactions/kgpgtransaction.cpp38
-rw-r--r--transactions/kgpgtransaction.h19
9 files changed, 92 insertions, 31 deletions
diff --git a/transactions/kgpgchangepass.cpp b/transactions/kgpgchangepass.cpp
index 3155868..1847b47 100644
--- a/transactions/kgpgchangepass.cpp
+++ b/transactions/kgpgchangepass.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008,2009 Rolf Eike Beer <kde@opensource.sf-tec.de>
+ * Copyright (C) 2008,2009,2010,2011,2012 Rolf Eike Beer <kde@opensource.sf-tec.de>
*/
/***************************************************************************
@@ -14,9 +14,6 @@
#include "kgpgchangepass.h"
#include <KLocale>
-#include <KMessageBox>
-
-#include "detailedconsole.h"
KGpgChangePass::KGpgChangePass(QObject *parent, const QString &keyid)
: KGpgTransaction(parent)
@@ -61,15 +58,6 @@ KGpgChangePass::nextLine(const QString &line)
m_seenold = true;
} else if (line.contains(QLatin1String( "MISSING_PASSPHRASE" ))) {
setSuccess(TS_USER_ABORTED);
- } else if (line.contains(QLatin1String( "passphrase.enter" ))) {
- QString userIDs(getIdHints());
-
- if (!m_seenold) {
- if (askPassphrase(i18n("Enter old passphrase for <b>%1</b>", userIDs)))
- setSuccess(TS_USER_ABORTED);
- } else {
- askNewPassphrase(i18n("<qt>Enter new passphrase for <b>%1</b><br />If you forget this passphrase all your encrypted files and messages will be inaccessible.</qt>", userIDs));
- }
} else if (line.contains(QLatin1String( "GET_" ))) {
setSuccess(TS_MSG_SEQUENCE);
return true;
@@ -77,3 +65,21 @@ KGpgChangePass::nextLine(const QString &line)
return false;
}
+
+KGpgTransaction::ts_passphrase_actions
+KGpgChangePass::passphraseRequested()
+{
+ const QString userIDs = getIdHints();
+
+ if (!m_seenold) {
+ if (askPassphrase(i18n("Enter old passphrase for <b>%1</b>", userIDs))) {
+ return KGpgTransaction::PA_USER_ABORTED;
+ }
+ } else {
+ askNewPassphrase(i18n("<qt>Enter new passphrase for <b>%1</b><br />If you forget this passphrase all your encrypted files and messages will be inaccessible.</qt>", userIDs));
+ }
+
+ return KGpgTransaction::PA_NONE;
+}
+
+#include "kgpgchangepass.moc"
diff --git a/transactions/kgpgchangepass.h b/transactions/kgpgchangepass.h
index 56fa3ee..3a379e1 100644
--- a/transactions/kgpgchangepass.h
+++ b/transactions/kgpgchangepass.h
@@ -32,6 +32,7 @@ public:
protected:
virtual bool nextLine(const QString &line);
virtual bool preStart();
+ virtual KGpgTransaction::ts_passphrase_actions passphraseRequested();
private:
bool m_seenold; ///< old password correctly entered
diff --git a/transactions/kgpgdecrypt.cpp b/transactions/kgpgdecrypt.cpp
index 76deeaf..20231fa 100644
--- a/transactions/kgpgdecrypt.cpp
+++ b/transactions/kgpgdecrypt.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010,2011 Rolf Eike Beer <kde@opensource.sf-tec.de>
+ * Copyright (C) 2010,2011,2012 Rolf Eike Beer <kde@opensource.sf-tec.de>
*/
/***************************************************************************
@@ -13,6 +13,7 @@
#include "kgpgdecrypt.h"
+#include "gpgproc.h"
#include "kgpgsettings.h"
#include <KLocale>
@@ -48,7 +49,7 @@ KGpgDecrypt::command() const
{
QStringList ret;
- ret << QLatin1String("--decrypt");
+ ret << QLatin1String("--decrypt") << QLatin1String("--command-fd=0");
if (!m_outFilename.isEmpty())
ret << QLatin1String("-o") << m_outFilename;
@@ -127,6 +128,10 @@ KGpgDecrypt::nextLine(const QString& line)
m_plainLength = line.mid(26).toInt(&ok);
if (!ok)
m_plainLength = -1;
+ } else if (line == QLatin1String("[GNUPG:] BEGIN_DECRYPTION")) {
+ // close the command channel (if any) to signal GnuPG that it
+ // can start sending the output.
+ getProcess()->closeWriteChannel();
}
}
diff --git a/transactions/kgpgeditkeytransaction.cpp b/transactions/kgpgeditkeytransaction.cpp
index 8163686..e4c50ff 100644
--- a/transactions/kgpgeditkeytransaction.cpp
+++ b/transactions/kgpgeditkeytransaction.cpp
@@ -64,11 +64,6 @@ KGpgEditKeyTransaction::nextLine(const QString &line)
} else if (getSuccess() == TS_USER_ABORTED) {
if (line.contains(QLatin1String( "GET_" ) ))
return true;
- } else if (line.contains(QLatin1String( "passphrase.enter" ))) {
- if (!askPassphrase()) {
- setSuccess(TS_USER_ABORTED);
- return true;
- }
} else if ((getSuccess() == TS_OK) && line.contains(QLatin1String( "keyedit.prompt" ))) {
return true;
} else if (line.contains(QLatin1String( "NEED_PASSPHRASE" ))) {
diff --git a/transactions/kgpggeneraterevoke.cpp b/transactions/kgpggeneraterevoke.cpp
index ff8daa9..1331daf 100644
--- a/transactions/kgpggeneraterevoke.cpp
+++ b/transactions/kgpggeneraterevoke.cpp
@@ -60,11 +60,6 @@ KGpgGenerateRevoke::nextLine(const QString &line)
if (line.contains(QLatin1String( "GOOD_PASSPHRASE" ))) {
setSuccess(TS_OK);
- } else if (line.contains(QLatin1String( "passphrase.enter" ))) {
- if (!askPassphrase()) {
- setSuccess(TS_USER_ABORTED);
- return true;
- }
} else if (line.contains(QLatin1String( "NEED_PASSPHRASE" ))) {
setSuccess(TS_USER_ABORTED);
} else if (line.contains(QLatin1String( "ask_revocation_reason.code" ))) {
diff --git a/transactions/kgpgtextorfiletransaction.cpp b/transactions/kgpgtextorfiletransaction.cpp
index e2796d0..ab0049e 100644
--- a/transactions/kgpgtextorfiletransaction.cpp
+++ b/transactions/kgpgtextorfiletransaction.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008,2009,2010,2011 Rolf Eike Beer <kde@opensource.sf-tec.de>
+ * Copyright (C) 2008,2009,2010,2011,2012 Rolf Eike Beer <kde@opensource.sf-tec.de>
*/
/***************************************************************************
@@ -79,6 +79,14 @@ KGpgTextOrFileTransaction::preStart()
QStringList args(QLatin1String("--status-fd=1"));
args << command();
+ // if the input is not stdin set command-fd so GnuPG
+ // can ask if e.g. the file already exists
+ if (!locfiles.isEmpty() && !m_tempfiles.isEmpty()) {
+ args << QLatin1String("--command-fd=0");
+ m_closeInput = false;
+ } else {
+ m_closeInput = !args.contains(QLatin1String("--command-fd=0"));
+ }
if (locfiles.count() + m_tempfiles.count() > 1)
args << QLatin1String("--multifile");
args << locfiles << m_tempfiles;
@@ -93,7 +101,8 @@ KGpgTextOrFileTransaction::postStart()
if (!m_text.isEmpty()){
GPGProc *proc = getProcess();
proc->write(m_text.toUtf8());
- proc->closeWriteChannel();
+ if (m_closeInput)
+ proc->closeWriteChannel();
}
}
diff --git a/transactions/kgpgtextorfiletransaction.h b/transactions/kgpgtextorfiletransaction.h
index a7d6350..ed7f287 100644
--- a/transactions/kgpgtextorfiletransaction.h
+++ b/transactions/kgpgtextorfiletransaction.h
@@ -92,6 +92,7 @@ private:
KUrl::List m_inpfiles;
QString m_text;
QStringList m_messages;
+ bool m_closeInput; ///< if input channel of GnuPG should be closed after m_text is written
void cleanUrls();
diff --git a/transactions/kgpgtransaction.cpp b/transactions/kgpgtransaction.cpp
index 900b854..d3590e7 100644
--- a/transactions/kgpgtransaction.cpp
+++ b/transactions/kgpgtransaction.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008,2009 Rolf Eike Beer <kde@opensource.sf-tec.de>
+ * Copyright (C) 2008,2009,2010,2011,2012 Rolf Eike Beer <kde@opensource.sf-tec.de>
*/
/***************************************************************************
@@ -37,6 +37,7 @@ public:
int m_tries;
QString m_description;
bool m_chainingAllowed;
+ KGpgTransaction::ts_passphrase_actions m_passphraseAction; ///< ignore further request for passphrase
QStringList m_idhints;
@@ -75,6 +76,7 @@ KGpgTransactionPrivate::KGpgTransactionPrivate(KGpgTransaction *parent, bool all
m_success(KGpgTransaction::TS_OK),
m_tries(3),
m_chainingAllowed(allowChaining),
+ m_passphraseAction(KGpgTransaction::PA_NONE),
m_inputProcessDone(false),
m_inputProcessResult(KGpgTransaction::TS_OK),
m_ownProcessFinished(false),
@@ -122,6 +124,22 @@ KGpgTransactionPrivate::slotReadReady()
m_parent->addIdHint(line);
} else if (line.startsWith(QLatin1String("[GNUPG:] BAD_PASSPHRASE "))) {
m_success = KGpgTransaction::TS_BAD_PASSPHRASE;
+ } else if (line.startsWith(QLatin1String("[GNUPG:] GET_HIDDEN passphrase.enter"))) {
+ m_passphraseAction = m_parent->passphraseRequested();
+ switch (m_passphraseAction) {
+ case KGpgTransaction::PA_USER_ABORTED:
+ m_parent->setSuccess(KGpgTransaction::TS_USER_ABORTED);
+ // sending "quit" here is useless as it would be interpreted as the passphrase
+ m_process->closeWriteChannel();
+ break;
+ default:
+ break;
+ }
+ } else if ((m_passphraseAction == KGpgTransaction::PA_CLOSE_GOOD) &&
+ line.startsWith(QLatin1String("[GNUPG:] GOOD_PASSPHRASE"))) {
+ // signal GnuPG that there will be no further input and it can
+ // begin sending output.
+ m_process->closeWriteChannel();
} else if (line.startsWith(QLatin1String("[GNUPG:] GET_BOOL "))) {
switch (m_parent->boolQuestion(line.mid(18))) {
case KGpgTransaction::BA_YES:
@@ -168,7 +186,7 @@ KGpgTransactionPrivate::sendQuit(void)
kDebug(2100) << "tried" << m_quitTries << "times to quit the GnuPG session";
kDebug(2100) << "last input was" << m_quitLines;
kDebug(2100) << "please file a bug report at https://bugs.kde.org";
- m_process->kill();
+ m_process->closeWriteChannel();
m_success = KGpgTransaction::TS_MSG_SEQUENCE;
}
}
@@ -199,7 +217,7 @@ KGpgTransactionPrivate::slotPasswordAborted()
{
sender()->deleteLater();
m_passwordDialog = NULL;
- m_process->kill();
+ m_process->closeWriteChannel();
m_success = KGpgTransaction::TS_USER_ABORTED;
}
@@ -319,6 +337,15 @@ KGpgTransaction::unexpectedLine(const QString &line)
kDebug(2100) << this << "unexpected input line" << line << "for command" << d->m_process->program();
}
+KGpgTransaction::ts_passphrase_actions
+KGpgTransaction::passphraseRequested()
+{
+ if (!askPassphrase())
+ return PA_USER_ABORTED;
+ else
+ return PA_CLOSE_GOOD;
+}
+
bool
KGpgTransaction::preStart()
{
@@ -421,6 +448,9 @@ KGpgTransaction::addArgumentRef(int *ref)
bool
KGpgTransaction::askPassphrase(const QString &message)
{
+ if (d->m_passphraseAction == PA_USER_ABORTED)
+ return false;
+
QString passdlgmessage;
QString userIDs(getIdHints());
if (userIDs.isEmpty())
@@ -439,7 +469,7 @@ KGpgTransaction::askPassphrase(const QString &message)
--d->m_tries;
emit statusMessage(i18n("Requesting Passphrase"));
- return KgpgInterface::sendPassphrase(passdlgmessage, d->m_process, false, qobject_cast<QWidget *>(parent()));
+ return (KgpgInterface::sendPassphrase(passdlgmessage, d->m_process, false, qobject_cast<QWidget *>(parent())) == 0);
}
void
diff --git a/transactions/kgpgtransaction.h b/transactions/kgpgtransaction.h
index b8def9e..00c195b 100644
--- a/transactions/kgpgtransaction.h
+++ b/transactions/kgpgtransaction.h
@@ -74,6 +74,14 @@ public:
BA_YES = 1, ///< answer "YES"
BA_NO = 2 ///< answer "NO"
};
+ /**
+ * @brief actions to do after a passphrase was sent to GnuPG
+ */
+ enum ts_passphrase_actions {
+ PA_NONE = 0, ///< do nothing special
+ PA_CLOSE_GOOD = 1, ///< close command channel if passphrase was accepted
+ PA_USER_ABORTED = 2 ///< the user has cancelled the dialog, abort the transaction
+ };
/**
* @brief KGpgTransaction constructor
@@ -251,6 +259,17 @@ protected:
*/
void unexpectedLine(const QString &line);
+ /**
+ * @brief called when GnuPG asks for a passphrase
+ * @return true if "quit" should be sent to process
+ *
+ * This allows a transaction to implement special handling for
+ * passphrases, e.g. when both old and new passphrase must be
+ * requested when changing it. The default implementation will just
+ * call askPassphrase().
+ */
+ virtual ts_passphrase_actions passphraseRequested();
+
private:
KGpgTransactionPrivate* const d;