diff --git a/CMakeLists.txt b/CMakeLists.txt --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,6 +12,8 @@ # Standalone build. Find / include everything necessary. set(KF5_MIN_VERSION "5.56.0") +set(KIDENTITYMANAGEMENT_VERSION "5.11.3") +set(KMAILTRANSPORT_VERSION "5.11.3") set(KMIME_VERSION "5.11.3") set(LIBKLEO_VERSION "5.11.3") set(QT_REQUIRED_VERSION "5.10.0") @@ -80,6 +82,9 @@ # Kdepimlibs packages find_package(KF5Libkleo ${LIBKLEO_VERSION} CONFIG REQUIRED) find_package(KF5Mime ${KMIME_VERSION} CONFIG REQUIRED) +find_package(KF5IdentityManagement ${KIDENTITYMANAGEMENT_VERSION} CONFIG REQUIRED) +find_package(KF5MailTransport ${KMAILTRANSPORT_VERSION} CONFIG REQUIRED) +find_package(KF5MailTransportAkonadi ${KMAILTRANSPORT_VERSION} CONFIG REQUIRED) find_package(Qt5 ${QT_REQUIRED_VERSION} CONFIG REQUIRED Widgets Test Network PrintSupport) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -209,6 +209,7 @@ commands/selftestcommand.cpp commands/exportsecretkeycommand.cpp commands/exportopenpgpcertstoservercommand.cpp + commands/exportopenpgpcerttoprovidercommand.cpp commands/adduseridcommand.cpp commands/newcertificatecommand.cpp commands/setinitialpincommand.cpp @@ -306,6 +307,9 @@ KF5::CoreAddons KF5::ItemModels KF5::Crash + KF5::IdentityManagement # Export OpenPGP keys using WKS + KF5::MailTransport + KF5::MailTransportAkonadi Qt5::Network Qt5::PrintSupport # Printing secret keys ${_kleopatra_uiserver_extra_libs} diff --git a/src/commands/exportopenpgpcerttoprovidercommand.h b/src/commands/exportopenpgpcerttoprovidercommand.h new file mode 100644 --- /dev/null +++ b/src/commands/exportopenpgpcerttoprovidercommand.h @@ -0,0 +1,83 @@ +/* -*- mode: c++; c-basic-offset:4 -*- + commands/exportopenpgpcerttoprovidercommand.h + + This file is part of Kleopatra, the KDE keymanager + Copyright (c) 2008 Klarälvdalens Datakonsult AB + 2019 Felix Tiede + + Kleopatra 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. + + Kleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KLEOPATRA_COMMMANDS_EXPORTOPENPGPCERTTOPROVIDERCOMMAND_H__ +#define __KLEOPATRA_COMMMANDS_EXPORTOPENPGPCERTTOPROVIDERCOMMAND_H__ + +#include + +#include + +#include + +namespace Kleo +{ +namespace Commands +{ + +class ExportOpenPGPCertToProviderCommand : public GnuPGProcessCommand +{ + Q_OBJECT +public: + explicit ExportOpenPGPCertToProviderCommand(QAbstractItemView *view, KeyListController *parent); + explicit ExportOpenPGPCertToProviderCommand(KeyListController *parent); + explicit ExportOpenPGPCertToProviderCommand(const GpgME::Key &key); + + ~ExportOpenPGPCertToProviderCommand() override; + + static Restrictions restrictions() + { + return OnlyOneKey | NeedSecretKey | MustBeOpenPGP; + } + +private: + bool preStartHook(QWidget *) const override; + void postSuccessHook(QWidget *) override; + + QStringList arguments() const override; + + QString errorCaption() const override; + QString successCaption() const override; + + QString crashExitMessage(const QStringList &) const override; + QString errorExitMessage(const QStringList &) const override; + QString successMessage(const QStringList &) const override; + + QTemporaryFile wksMail; + static const KIdentityManagement::IdentityManager *mailIdManager; +}; + +} +} + +#endif // __KLEOPATRA_COMMMANDS_EXPORTOPENPGPCERTTOPROVIDERCOMMAND_H__ diff --git a/src/commands/exportopenpgpcerttoprovidercommand.cpp b/src/commands/exportopenpgpcerttoprovidercommand.cpp new file mode 100644 --- /dev/null +++ b/src/commands/exportopenpgpcerttoprovidercommand.cpp @@ -0,0 +1,192 @@ +/* -*- mode: c++; c-basic-offset:4 -*- + commands/exportopenpgpcerttoprovidercommand.cpp + + This file is part of Kleopatra, the KDE keymanager + Copyright (c) 2008 Klarälvdalens Datakonsult AB + 2019 Felix Tiede + + Kleopatra 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. + + Kleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#include + +#include "exportopenpgpcerttoprovidercommand.h" + +#include "command_p.h" + +#include + +#include + +#include +#include +#include + +#include +#include + +#include + +using namespace Kleo; +using namespace Kleo::Commands; +using namespace GpgME; + +const KIdentityManagement::IdentityManager *ExportOpenPGPCertToProviderCommand::mailIdManager = new KIdentityManagement::IdentityManager(true); + +ExportOpenPGPCertToProviderCommand::ExportOpenPGPCertToProviderCommand(KeyListController *c) + : GnuPGProcessCommand(c) +{ + wksMail.open(); + wksMail.close(); +} + +ExportOpenPGPCertToProviderCommand::ExportOpenPGPCertToProviderCommand(QAbstractItemView *v, KeyListController *c) + : GnuPGProcessCommand(v, c) +{ + wksMail.open(); + wksMail.close(); +} + +ExportOpenPGPCertToProviderCommand::ExportOpenPGPCertToProviderCommand(const Key &key) + : GnuPGProcessCommand(key) +{ + wksMail.open(); + wksMail.close(); +} + +ExportOpenPGPCertToProviderCommand::~ExportOpenPGPCertToProviderCommand() {} + +bool ExportOpenPGPCertToProviderCommand::preStartHook(QWidget *parent) const +{ + if (ExportOpenPGPCertToProviderCommand::mailIdManager->identityForAddress(QString::fromLatin1( + d->keys().at(0).userID(0).addrSpec().data())).transport().isEmpty()) { + KMessageBox::error(parent, + xi18nc("@warning", + "No viable transport for key's primary ID available, " + "WKS upload not possible."), + xi18nc("@title:window", "OpenPGP Certificate Export")); + return false; + } + return KMessageBox::warningContinueCancel(parent, + xi18nc("@info", + "Not every mail provider supports WKS, so any key being " + "exported this way may fail individually.If exported, " + "you will receive a confirmation request mail and need to " + "acknowledge this mail with your mail program to complete the " + "export process.KMail " + "can handle these mails, but not all mail programs can." + "Once exported, the standard does not (yet) allow for " + "automated removal of a published key." + "Are you sure you want to continue?"), + xi18nc("@title:window", "OpenPGP Certificate Export"), + KStandardGuiItem::cont(), KStandardGuiItem::cancel(), + QStringLiteral("warn-export-openpgp-wks-unsupported")) + == KMessageBox::Continue; +} + +void ExportOpenPGPCertToProviderCommand::postSuccessHook(QWidget *parent) +{ + QString sender = QString::fromLatin1(d->keys().at(0).userID(0).addrSpec().data()); + MailTransport::Transport *transport = MailTransport::TransportManager::self()->transportByName( + ExportOpenPGPCertToProviderCommand::mailIdManager->identityForAddress(sender).transport()); + + if (!transport) + return; + + wksMail.open(); + QByteArray in; + do { + in = wksMail.readLine(); + } while (!in.toLower().startsWith("to: ")); + wksMail.reset(); + + QString target = QString::fromLatin1(in.split(':').at(1).trimmed()); + + QByteArray header, body; + KMime::Message *msg = new KMime::Message(); + do { + in = wksMail.readLine(); + header.append(in); + } while (in.length() > 2); + body = wksMail.readAll(); + wksMail.close(); + + msg->setHead(header); + msg->setBody(body); + msg->parse(); + + MailTransport::MessageQueueJob *job = new MailTransport::MessageQueueJob(parent); + job->transportAttribute().setTransportId(transport->id()); + job->addressAttribute().setFrom(sender); + job->addressAttribute().setTo(QStringList() << target); + job->setMessage(KMime::Message::Ptr(msg)); + + job->start(); +} + +QStringList ExportOpenPGPCertToProviderCommand::arguments() const +{ + QStringList result; + result << gpgWksClientPath(); + result << QStringLiteral("--output") << wksMail.fileName(); + result << QStringLiteral("--create"); + Q_FOREACH (const Key &key, d->keys()) { + result << QLatin1String(key.primaryFingerprint()) << QLatin1String(key.userID(0).email()); + } + return result; +} + +QString ExportOpenPGPCertToProviderCommand::errorCaption() const +{ + return i18nc("@title:window", "OpenPGP Certificate Export Error"); +} + +QString ExportOpenPGPCertToProviderCommand::successCaption() const +{ + return i18nc("@title:window", "OpenPGP Certificate Export Finished"); +} + +QString ExportOpenPGPCertToProviderCommand::crashExitMessage(const QStringList &args) const +{ + return xi18nc("@info", + "The GPG process that tried to export OpenPGP certificates " + "ended prematurely because of an unexpected error." + "Please check the output of %1 for details.", args.join(QLatin1Char(' '))); +} + +QString ExportOpenPGPCertToProviderCommand::errorExitMessage(const QStringList &args) const +{ + return xi18nc("@info", + "An error occurred while trying to export OpenPGP certificates. " + "The output from %1 was: %2", + args[0], errorString()); +} + +QString ExportOpenPGPCertToProviderCommand::successMessage(const QStringList&) const +{ + return i18nc("@info", "OpenPGP certificates exported successfully."); +} + diff --git a/src/kleopatra.rc b/src/kleopatra.rc --- a/src/kleopatra.rc +++ b/src/kleopatra.rc @@ -12,6 +12,7 @@ + @@ -122,6 +123,7 @@ + diff --git a/src/utils/gnupg-helper.h b/src/utils/gnupg-helper.h --- a/src/utils/gnupg-helper.h +++ b/src/utils/gnupg-helper.h @@ -3,6 +3,7 @@ This file is part of Kleopatra, the KDE keymanager Copyright (c) 2008 Klarälvdalens Datakonsult AB + 2019 Felix Tiede Kleopatra is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -60,6 +61,7 @@ QString gnupgHomeDirectory(); +QString gpgWksClientPath(); QString gpgConfPath(); QString gpgSmPath(); QString gpgPath(); diff --git a/src/utils/gnupg-helper.cpp b/src/utils/gnupg-helper.cpp --- a/src/utils/gnupg-helper.cpp +++ b/src/utils/gnupg-helper.cpp @@ -5,6 +5,7 @@ Copyright (c) 2008 Klarälvdalens Datakonsult AB 2016 by Bundesamt für Sicherheit in der Informationstechnik Software engineering by Intevation GmbH + 2019 by Felix Tiede Kleopatra is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -90,6 +91,12 @@ return info.fileName() ? QFile::decodeName(info.fileName()) : QStandardPaths::findExecutable(exe); } +QString Kleo::gpgWksClientPath() +{ + static const auto path = QStandardPaths::findExecutable(QStringLiteral("gpg-wks-client"), QStringList(gpgConfListDir("libexecdir"))); + return path; +} + QString Kleo::gpgConfPath() { static const auto path = findGpgExe(GpgME::GpgConfEngine, QStringLiteral("gpgconf")); diff --git a/src/view/keylistcontroller.cpp b/src/view/keylistcontroller.cpp --- a/src/view/keylistcontroller.cpp +++ b/src/view/keylistcontroller.cpp @@ -3,6 +3,7 @@ This file is part of Kleopatra, the KDE keymanager Copyright (c) 2007 Klarälvdalens Datakonsult AB + 2019 Felix Tiede Kleopatra is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -43,6 +44,7 @@ #include "kleopatra_debug.h" #include "commands/exportcertificatecommand.h" #include "commands/exportopenpgpcertstoservercommand.h" +#include "commands/exportopenpgpcerttoprovidercommand.h" #include "commands/exportsecretkeycommand.h" #include "commands/importcertificatefromfilecommand.h" #include "commands/changepassphrasecommand.h" @@ -381,6 +383,10 @@ "file_export_certificates_to_server", i18n("Publish on Server..."), i18n("Publish the selected certificate (public key) on a public keyserver"), "view-certificate-export-server", nullptr, nullptr, QStringLiteral("Ctrl+Shift+E"), false, true }, + { + "file_export_certificate_to_provider", i18n("Publish on Mailprovider..."), i18n("Publish the selected certificate (public key) on mail provider's Web Key Directory if offered"), + "view-certificate-export-provider", nullptr, nullptr, QString(), false, true + }, { "file_export_secret_keys", i18n("Export Secret Keys..."), QString(), "view-certificate-export-secret", nullptr, nullptr, QString(), false, true @@ -510,6 +516,7 @@ registerActionForCommand(coll->action(QStringLiteral("file_export_secret_keys"))); registerActionForCommand(coll->action(QStringLiteral("file_export_paper_key"))); registerActionForCommand(coll->action(QStringLiteral("file_export_certificates_to_server"))); + registerActionForCommand(coll->action(QStringLiteral("file_export_certificate_to_provider"))); //--- registerActionForCommand(coll->action(QStringLiteral("file_decrypt_verify_files"))); registerActionForCommand(coll->action(QStringLiteral("file_sign_encrypt_files")));