diff options
Diffstat (limited to 'kgpg/transactions/kgpgverify.cpp')
-rw-r--r-- | kgpg/transactions/kgpgverify.cpp | 204 |
1 files changed, 204 insertions, 0 deletions
diff --git a/kgpg/transactions/kgpgverify.cpp b/kgpg/transactions/kgpgverify.cpp new file mode 100644 index 0000000..e9dbb36 --- /dev/null +++ b/kgpg/transactions/kgpgverify.cpp @@ -0,0 +1,204 @@ +/* + * Copyright (C) 2012 Rolf Eike Beer <[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 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "kgpgverify.h" + +#include "../gpgproc.h" +#include "../core/KGpgKeyNode.h" +//#include "../model/kgpgitemmodel.h" + +//#include <KGlobal> +//#include <KLocale> + +KGpgVerify::KGpgVerify(QObject *parent, const QString &text) + : KGpgTextOrFileTransaction(parent, text), + m_fileIndex(-1) +{ +} + +KGpgVerify::KGpgVerify(QObject *parent, const QList<QUrl> &files) + : KGpgTextOrFileTransaction(parent, files), + m_fileIndex(0) +{ +} + +KGpgVerify::~KGpgVerify() +{ +} + +QStringList +KGpgVerify::command() const +{ + QStringList ret(QLatin1String("--verify")); + + return ret; +} + +bool +KGpgVerify::nextLine(const QString &line) +{ + if (line.startsWith(QLatin1String("[GNUPG:] NO_PUBKEY "))) { + setSuccess(TS_MISSING_KEY); + m_missingId = line.mid(19).simplified(); + return false; + } + + if (line.startsWith(QLatin1String("[GNUPG:] ")) && + line.contains(QLatin1String("SIG"))) { + if (line.startsWith(QLatin1String("[GNUPG:] BADSIG"))) + setSuccess(KGpgVerify::TS_BAD_SIGNATURE); + else + setSuccess(KGpgTransaction::TS_OK); + } + + return KGpgTextOrFileTransaction::nextLine(line); +} + +void +KGpgVerify::finish() +{ + // GnuPG will return error code 2 if it wasn't able to verify the file. + // If it complained about a missing signature before that is fine. + if (((getProcess()->exitCode() == 2) && (getSuccess() == TS_MISSING_KEY)) || + ((getProcess()->exitCode() == 1) && (getSuccess() == TS_BAD_SIGNATURE))) + return; + + KGpgTextOrFileTransaction::finish(); +} + +static QString +sigTimeMessage(const QString &sigtime) +{ + QDateTime stamp; + if (sigtime.contains(QLatin1Char('T'))) { + stamp = QDateTime::fromString(sigtime, Qt::ISODate); + } else { + bool ok; + qint64 secs = sigtime.toLongLong(&ok); + if (ok) + stamp = QDateTime::fromMSecsSinceEpoch(secs * 1000); + } + + if (!stamp.isValid()) + return QString(); + +/* return tr("first argument is formatted date, second argument is formatted time", + "The signature was created at %1 %2", + KGlobal::locale()->formatDate(stamp.date(), KLocale::LongDate), + KGlobal::locale()->formatTime(stamp.time(), KLocale::LongDate)) + + QLatin1String("<br/>");*/ + return "todo"; +} + +/* +QString +KGpgVerify::getReport(const QStringList &log, const KGpgItemModel *model) +{ + QString result; + // newer versions of GnuPG emit both VALIDSIG and GOODSIG + // for a good signature. Since VALIDSIG has more information + // we use that. + const QRegExp validsig(QLatin1String("^\\[GNUPG:\\] VALIDSIG([ ]+[^ ]+){10,}.*$")); + const bool useGoodSig = (model != NULL) && (log.indexOf(validsig) == -1); + QString sigtime; // timestamp of signature creation + + foreach (const QString &line, log) { + if (!line.startsWith(QLatin1String("[GNUPG:] "))) + continue; + + const QString msg = line.mid(9); + + if (msg.startsWith(QLatin1String("VALIDSIG ")) && !useGoodSig) { + // from GnuPG source, doc/DETAILS: + // VALIDSIG <fingerprint in hex> <sig_creation_date> <sig-timestamp> + // <expire-timestamp> <sig-version> <reserved> <pubkey-algo> + // <hash-algo> <sig-class> <primary-key-fpr> + const QStringList vsig = msg.mid(9).split(QLatin1Char(' '), QString::SkipEmptyParts); + Q_ASSERT(vsig.count() >= 10); + + const KGpgKeyNode *node = model->findKeyNode(vsig[9]); + + if (node != NULL) { + // ignore for now if this is signed with the primary id (vsig[0] == vsig[9]) or not + if (node->getEmail().isEmpty()) + result += tr("<qt>Good signature from:<br /><b>%1</b><br />Key ID: %2<br /></qt>") + .arg(node->getName()).arg(vsig[9]); + else + result += tr("Good signature from: NAME <EMAIL>, Key ID: HEXID", + "<qt>Good signature from:<br /><b>%1 <%2></b><br />Key ID: %3<br /></qt>") + .arg(node->getName()).arg(node->getEmail()).arg(vsig[9]); + + result += sigTimeMessage(vsig[2]); + } else { + // this should normally never happen, but one could delete + // the key just after the verification. Brute force solution: + // do the whole report generation again, but this time make + // sure GOODSIG is used. + return getReport(log, NULL); + } + } else if (msg.startsWith(QLatin1String("UNEXPECTED")) || + msg.startsWith(QLatin1String("NODATA"))) { + result += tr("No signature found.") + QLatin1Char('\n'); + } else if (useGoodSig && msg.startsWith(QLatin1String("GOODSIG "))) { + int sigpos = msg.indexOf( ' ' , 8); + const QString keyid = msg.mid(8, sigpos - 8); + + // split the name/email pair to give translators more power to handle this + QString email; + QString name = msg.mid(sigpos + 1); + + int oPos = name.indexOf(QLatin1Char('<')); + int cPos = name.indexOf(QLatin1Char('>')); + if ((oPos >= 0) && (cPos >= 0)) { + email = name.mid(oPos + 1, cPos - oPos - 1); + name = name.left(oPos).simplified(); + } + + if (email.isEmpty()) + result += tr("<qt>Good signature from:<br /><b>%1</b><br />Key ID: %2<br /></qt>") + .arg(name).arg(keyid); + else + result += tr("Good signature from: NAME <EMAIL>, Key ID: HEXID", + "<qt>Good signature from:<br /><b>%1 <%2></b><br />Key ID: %3<br /></qt>") + .arg(name).arg(email).arg(keyid); + if (!sigtime.isEmpty()) { + result += sigTimeMessage(sigtime); + sigtime.clear(); + } + } else if (msg.startsWith(QLatin1String("SIG_ID "))) { + const QStringList parts = msg.simplified().split(QLatin1Char(' ')); + if (parts.count() > 2) + sigtime = parts[2]; + } else if (msg.startsWith(QLatin1String("BADSIG"))) { + int sigpos = msg.indexOf( ' ', 7); + result += tr("<qt><b>BAD signature</b> from:<br /> %1<br />Key id: %2<br /><br /><b>The file is corrupted</b><br /></qt>") + .arg(msg.mid(sigpos + 1).replace(QLatin1Char('<'), QLatin1String("<"))) + .arg(msg.mid(7, sigpos - 7)); + } else if (msg.startsWith(QLatin1String("TRUST_UNDEFINED"))) { + result += tr("<qt>The signature is valid, but the key is untrusted<br /></qt>"); + } else if (msg.startsWith(QLatin1String("TRUST_ULTIMATE"))) { + result += tr("<qt>The signature is valid, and the key is ultimately trusted<br /></qt>"); + } + } + + return result; +} +*/ + +QString +KGpgVerify::missingId() const +{ + return m_missingId; +} + +//#include "kgpgverify.moc" |