diff --git a/src/kcfg/settings.kcfg b/src/kcfg/settings.kcfg
index c9bce9492..c9549c29e 100644
--- a/src/kcfg/settings.kcfg
+++ b/src/kcfg/settings.kcfg
@@ -1,164 +1,170 @@
This text will be used as placeholder text for the common name (CN) field of S/MIME certificates.If true, then the common name (CN) field of S/MIME certificates will be prefilled with information gathered from the system,
e.g., from the email settings of the desktop or, on Windows, from the Active Directory.trueThis text will be used as placeholder text for the email address field of OpenPGP and S/MIME certificates.If true, then the email address field of OpenPGP and S/MIME certificates will be prefilled with information gathered from the system,
e.g., from the email settings of the desktop or, on Windows, from the Active Directory.trueThis text will be used as placeholder text for the name field of OpenPGP certificates.If true, then the name field of OpenPGP certificates will be prefilled with information gathered from the system,
e.g., from the email settings of the desktop or, on Windows, from the Active Directory.trueSpecifies the default validity period of new OpenPGP keys in days.This setting specifies how many days a new OpenPGP key is valid by default, or, in other words, after how many days the key will expire. Set this to 0 for unlimited validity. If this setting is not set or if it is set to a negative value, then new OpenPGP keys will be valid for two years (possibly clamped to the allowed minimum or maximum validity period) by default.-1Specifies the minimum validity period of new OpenPGP keys in days.This setting specifies how many days a new OpenPGP key is valid at least, or, in other words, after how many days the new key will expire at the earliest.0Specifies the maximum validity period of new OpenPGP keys in days.This setting specifies how many days a new OpenPGP key is valid at most, or, in other words, after how many days the new key will expire at the latest. If this setting is not set or if it is set to a negative value, then unlimited validity is allowed.-1If true, hides the advanced settings button in the new certificate wizard.falsesha256sumEnables support for S/MIME (CMS).If false, then Kleopatra's main UI will not offer any functionality related to S/MIME (CMS).trueAllows the creation of S/MIME certificate signing requests.If false, then Kleopatra will not offer the creation of S/MIME certificate signing requests.trueAllows signing of text or files with S/MIME certificates.If false, then Kleopatra will not offer functionality for creating signatures with S/MIME certificates.true
+
+
+ Automatically load S/MIME certificates from PKCS#15 (CardOS) smartcards
+ If true, then Kleopatra will call gpgsm --learn if a PKCS#15 Smartcard is inserted with unkown certificates. This can take a while and blocks the smartcard while the command is running.
+ true
+ truetruetruetruetruetrueSpecifies the display order of the DN attributes of X.509 certificates.Enable usage of groups of keys.Enable usage of groups of keys to create lists of recipients.trueIf enabled, then Kleopatra will automatically try to retrieve the keys
that were used to certify the user ids of newly imported OpenPGP keys. This is
useful in combination with trusted introducers.falseThis is a list of URL schemes that shall be blocked by the application.
This can be used to prevent the application from opening external applications for certain URLs.Searches for the certificates belonging the smartcard keys on the configured keyserver.Searches on keyservers regardless of the protocol for the smartcards key, regardless
of the keyserver protocol. Default behavior is to only do this for LDAP keyservers.falsefalse
diff --git a/src/view/p15cardwidget.cpp b/src/view/p15cardwidget.cpp
index ffdaaf376..60d364033 100644
--- a/src/view/p15cardwidget.cpp
+++ b/src/view/p15cardwidget.cpp
@@ -1,219 +1,195 @@
/* view/p15cardwiget.cpp
This file is part of Kleopatra, the KDE keymanager
SPDX-FileCopyrightText: 2021 g10 Code GmbH
SPDX-FileContributor: Andre Heinecke
SPDX-FileContributor: Ingo Klöcker
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "p15cardwidget.h"
#include "openpgpkeycardwidget.h"
#include "settings.h"
#include "smartcard/p15card.h"
#include "smartcard/openpgpcard.h"
#include "smartcard/readerstatus.h"
#include "commands/learncardkeyscommand.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "kleopatra_debug.h"
using namespace Kleo;
using namespace Kleo::SmartCard;
using namespace Kleo::Commands;
P15CardWidget::P15CardWidget(QWidget *parent)
: QWidget{parent}
, mVersionLabel{new QLabel{this}}
, mSerialNumber{new QLabel{this}}
, mStatusLabel{new QLabel{this}}
, mOpenPGPKeysSection{new QWidget{this}}
- , mCMSKeysSection{new QWidget{this}}
, mOpenPGPKeysWidget{new OpenPGPKeyCardWidget{this}}
{
// Set up the scroll area
auto myLayout = new QVBoxLayout(this);
myLayout->setContentsMargins(0, 0, 0, 0);
auto area = new QScrollArea;
area->setFrameShape(QFrame::NoFrame);
area->setWidgetResizable(true);
myLayout->addWidget(area);
auto areaWidget = new QWidget;
area->setWidget(areaWidget);
auto areaVLay = new QVBoxLayout(areaWidget);
auto cardInfoGrid = new QGridLayout;
{
int row = 0;
// Version and Serialnumber
cardInfoGrid->addWidget(mVersionLabel, row++, 0, 1, 2);
mVersionLabel->setTextInteractionFlags(Qt::TextBrowserInteraction | Qt::TextSelectableByKeyboard);
cardInfoGrid->addWidget(new QLabel(i18n("Serial number:")), row, 0);
cardInfoGrid->addWidget(mSerialNumber, row++, 1);
mSerialNumber->setTextInteractionFlags(Qt::TextBrowserInteraction | Qt::TextSelectableByKeyboard);
cardInfoGrid->setColumnStretch(cardInfoGrid->columnCount(), 1);
}
areaVLay->addLayout(cardInfoGrid);
areaVLay->addWidget(mStatusLabel);
mStatusLabel->setVisible(false);
areaVLay->addWidget(new KSeparator(Qt::Horizontal));
{
auto l = new QVBoxLayout{mOpenPGPKeysSection};
l->setContentsMargins(0, 0, 0, 0);
l->addWidget(new QLabel(QStringLiteral("%1").arg(i18n("OpenPGP keys:"))));
mOpenPGPKeysWidget->setAllowedActions(OpenPGPKeyCardWidget::NoAction);
l->addWidget(mOpenPGPKeysWidget);
l->addWidget(new KSeparator(Qt::Horizontal));
}
- {
- auto l = new QVBoxLayout{mCMSKeysSection};
- /* For an improvement we need to make a hybrid of
- * the NetKeyWidget with the treeview and all the
- * CMS Related actions here, too. For now it
- * is just a button that is shown when we can
- * learn additional CMS keys from the smartcard. */
- auto hl = new QHBoxLayout;
- auto learnBtn = new QPushButton(i18n("Load additional certificates"));
- learnBtn->setToolTip(i18n("Search for additional certificates on the card and add them to the list. "
- "The certificates might be usable for S/MIME."));
- auto learnLbl = new QLabel();
- learnLbl->setVisible(false);
- hl->addWidget(learnBtn);
- hl->addStretch(1);
- l->addLayout(hl);
- l->addWidget(learnLbl);
- connect(learnBtn, &QPushButton::clicked, this, [this, learnBtn, learnLbl] () {
- learnBtn->setEnabled(false);
- auto cmd = new LearnCardKeysCommand(GpgME::CMS);
- cmd->setParentWidget(this);
- cmd->start();
- learnLbl->setVisible(true);
- learnLbl->setText(i18n("Loading certificates..."));
-
- connect(cmd, &Command::finished, this, [learnBtn, learnLbl] () {
- learnLbl->setText(i18n("Certificates added to the certificate list."));
- });
- });
- l->addWidget(new KSeparator(Qt::Horizontal));
- }
mOpenPGPKeysSection->setVisible(false);
- mCMSKeysSection->setVisible(false);
areaVLay->addWidget(mOpenPGPKeysSection);
- areaVLay->addWidget(mCMSKeysSection);
areaVLay->addStretch(1);
}
P15CardWidget::~P15CardWidget() = default;
void P15CardWidget::searchPGPFpr(const std::string &fpr)
{
/* Only do auto import from LDAP */
auto conf = QGpgME::cryptoConfig();
Q_ASSERT (conf);
if (!Settings().alwaysSearchCardOnKeyserver() && !Kleo::keyserver().startsWith(QLatin1String{"ldap"})) {
return;
}
mStatusLabel->setText(i18n("Searching in directory service..."));
mStatusLabel->setVisible(true);
qCDebug(KLEOPATRA_LOG) << "Looking for:" << fpr.c_str() << "on ldap server";
QGpgME::KeyListJob *job = QGpgME::openpgp()->keyListJob(true);
connect(KeyCache::instance().get(), &KeyCache::keysMayHaveChanged, this, [this, fpr] () {
qCDebug(KLEOPATRA_LOG) << "Updating key info after changes";
ReaderStatus::mutableInstance()->updateStatus();
mOpenPGPKeysWidget->update(nullptr);
});
connect(job, &QGpgME::KeyListJob::result, job, [this](GpgME::KeyListResult, std::vector keys, QString, GpgME::Error) {
if (keys.size() == 1) {
auto importJob = QGpgME::openpgp()->importFromKeyserverJob();
qCDebug(KLEOPATRA_LOG) << "Importing: " << keys[0].primaryFingerprint();
connect(importJob, &QGpgME::ImportFromKeyserverJob::result, importJob, [this](GpgME::ImportResult, QString, GpgME::Error) {
qCDebug(KLEOPATRA_LOG) << "import job done";
mStatusLabel->setText(i18n("Automatic import finished."));
});
importJob->start(keys);
} else if (keys.size() > 1) {
qCDebug(KLEOPATRA_LOG) << "Multiple keys found on server";
mStatusLabel->setText(i18n("Error multiple keys found on server."));
} else {
qCDebug(KLEOPATRA_LOG) << "No key found";
mStatusLabel->setText(i18n("Key not found in directory service."));
}
});
job->start(QStringList() << QString::fromStdString(fpr));
}
void P15CardWidget::setCard(const P15Card *card)
{
mCardSerialNumber = card->serialNumber();
mVersionLabel->setText(i18nc("%1 is a smartcard manufacturer", "%1 PKCS#15 card",
QString::fromStdString(card->manufacturer())));
mSerialNumber->setText(card->displaySerialNumber());
mSerialNumber->setToolTip(QString::fromStdString(card->serialNumber()));
const auto sigInfo = card->keyInfo(card->signingKeyRef());
if (!sigInfo.grip.empty()) {
const auto key = KeyCache::instance()->findSubkeyByKeyGrip(sigInfo.grip, GpgME::OpenPGP).parent();
if (key.isNull()) {
qCDebug(KLEOPATRA_LOG) << "Failed to find key for grip:" << sigInfo.grip.c_str();
const auto pgpSigFpr = card->keyFingerprint(OpenPGPCard::pgpSigKeyRef());
if (!pgpSigFpr.empty()) {
qCDebug(KLEOPATRA_LOG) << "Should be pgp key:" << pgpSigFpr.c_str();
searchPGPFpr(pgpSigFpr);
}
} else {
mStatusLabel->setVisible(false);
}
}
const bool cardHasOpenPGPKeys = !card->keyFingerprint(OpenPGPCard::pgpSigKeyRef()).empty()
|| !card->keyFingerprint(OpenPGPCard::pgpEncKeyRef()).empty();
mOpenPGPKeysSection->setVisible(cardHasOpenPGPKeys);
if (cardHasOpenPGPKeys) {
mOpenPGPKeysWidget->update(card);
}
/* Check if additional keys could be available */
+ if (!Settings().autoLoadP15Certs()) {
+ return;
+ }
for (const auto &info: card->keyInfos()) {
const auto key = KeyCache::instance()->findSubkeyByKeyGrip(info.grip);
if (key.isNull()) {
- mCMSKeysSection->setVisible(true);
- break;
+ auto cmd = new LearnCardKeysCommand(GpgME::CMS);
+ cmd->setParentWidget(this);
+ cmd->setShowsOutputWindow(false);
+ qCDebug(KLEOPATRA_LOG) << "Did not find:" << info.grip.c_str() << "Starting gpgsm --learn.";
+ cmd->start();
+ connect(cmd, &Command::finished, this, [] () {
+ qCDebug(KLEOPATRA_LOG) << "Learn command finished.";
+ });
+ return;
}
}
-
+ qCDebug(KLEOPATRA_LOG) << "All certificates from card cached - Not learning.";
}
diff --git a/src/view/p15cardwidget.h b/src/view/p15cardwidget.h
index 0848a88f4..9f99026ef 100644
--- a/src/view/p15cardwidget.h
+++ b/src/view/p15cardwidget.h
@@ -1,48 +1,47 @@
/* view/p15cardwiget.h
This file is part of Kleopatra, the KDE keymanager
SPDX-FileCopyrightText: 2021 g10 Code GmbH
SPDX-FileContributor: Andre Heinecke
SPDX-FileContributor: Ingo Klöcker
SPDX-License-Identifier: GPL-2.0-or-later
*/
#pragma once
#include
class QLabel;
namespace Kleo
{
class OpenPGPKeyCardWidget;
namespace SmartCard
{
struct KeyPairInfo;
class P15Card;
}
class P15CardWidget: public QWidget
{
Q_OBJECT
public:
explicit P15CardWidget(QWidget *parent = nullptr);
~P15CardWidget() override;
void setCard(const SmartCard::P15Card* card);
private:
void searchPGPFpr(const std::string &fpr);
private:
std::string mCardSerialNumber;
QLabel *mVersionLabel = nullptr;
QLabel *mSerialNumber = nullptr;
QLabel *mStatusLabel = nullptr;
QWidget *mOpenPGPKeysSection = nullptr;
- QWidget *mCMSKeysSection = nullptr;
OpenPGPKeyCardWidget *mOpenPGPKeysWidget = nullptr;
};
}