Page Menu
Home
GnuPG
Search
Configure Global Search
Log In
Files
F18824736
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Size
14 KB
Subscribers
None
View Options
diff --git a/src/smartcard/p15card.cpp b/src/smartcard/p15card.cpp
index 5cd724e0c..027d9f558 100644
--- a/src/smartcard/p15card.cpp
+++ b/src/smartcard/p15card.cpp
@@ -1,82 +1,82 @@
/* smartcard/p15card.cpp
This file is part of Kleopatra, the KDE keymanager
- SPDX-FileCopyrightText: 2020 g10 Code GmbH
- SPDX-FileContributor: Andre Heinecke <aheinecke@ingo-kloecker.de>
+ SPDX-FileCopyrightText: 2021 g10 Code GmbH
+ SPDX-FileContributor: Andre Heinecke <aheinecke@g10code.com>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "p15card.h"
#include "kleopatra_debug.h"
using namespace Kleo;
using namespace Kleo::SmartCard;
// static
const std::string P15Card::AppName = "p15";
P15Card::P15Card(const Card &card)
: Card(card)
{
setAppName(AppName);
}
std::string P15Card::appKeyFingerprint(const std::string &appKeyRef) const
{
return mMetaInfo.value("KLEO-FPR-" + appKeyRef);
}
void P15Card::setCardInfo(const std::vector< std::pair<std::string, std::string> > &infos)
{
// XXX: This is a copy of OpenPGPCard::setCardInfo
qCDebug(KLEOPATRA_LOG) << "Card" << serialNumber().c_str() << "info:";
for (const auto &pair: infos) {
qCDebug(KLEOPATRA_LOG) << pair.first.c_str() << ":" << pair.second.c_str();
if (parseCardInfo(pair.first, pair.second)) {
continue;
}
if (pair.first == "KEY-FPR") {
const auto values = QString::fromStdString(pair.second).split(QLatin1Char(' '));
if (values.size() < 2) {
qCWarning(KLEOPATRA_LOG) << "Invalid entry.";
setStatus(Card::CardError);
continue;
}
const auto keyNumber = values[0];
const std::string keyRef = "OPENPGP." + keyNumber.toStdString();
const auto fpr = values[1].toStdString();
if (keyNumber == QLatin1Char('1') || keyNumber == QLatin1Char('2') || keyNumber == QLatin1Char('3')) {
mMetaInfo.insert("KLEO-FPR-" + keyRef, fpr);
} else {
// Maybe more keyslots in the future?
qCDebug(KLEOPATRA_LOG) << "Unhandled keyslot";
}
} else {
mMetaInfo.insert(pair.first, pair.second);
}
}
}
void P15Card::setManufacturer(const std::string &manufacturer)
{
mManufacturer = manufacturer;
}
std::string P15Card::manufacturer() const
{
return mManufacturer;
}
bool P15Card::operator == (const Card& rhs) const
{
const P15Card *other = dynamic_cast<const P15Card *>(&rhs);
if (!other) {
return false;
}
return Card::operator ==(rhs)
&& mMetaInfo == other->mMetaInfo
&& mManufacturer == other->mManufacturer;
}
diff --git a/src/smartcard/p15card.h b/src/smartcard/p15card.h
index 742b59a85..3d0b21cd7 100644
--- a/src/smartcard/p15card.h
+++ b/src/smartcard/p15card.h
@@ -1,57 +1,57 @@
-/* smartcard/pivcard.h
+/* smartcard/p15card.h
This file is part of Kleopatra, the KDE keymanager
- SPDX-FileCopyrightText: 2020 g10 Code GmbH
- SPDX-FileContributor: Ingo Klöcker <dev@ingo-kloecker.de>
+ SPDX-FileCopyrightText: 2021 g10 Code GmbH
+ SPDX-FileContributor: Andre Heinecke <aheinecke@g10code.com>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#pragma once
#include "card.h"
#include <QMap>
namespace Kleo
{
namespace SmartCard
{
/** Class to work with PKCS#15 smartcards or compatible tokens.
*
* A PKCS#15 card is pretty generic and there is no real standard
* for them. It all depends on the Apps running on the cards. This
* mostly tries to leave it to GnuPG to determine if there are usable
* things on the card. The generic info on all keys on the card is
* accessible through keyInfo from the parent class.
*
* The specialization is required for specific app support.
**/
class P15Card: public Card
{
public:
explicit P15Card(const Card &card);
static const std::string AppName;
void setAppKeyRef(const std::string &appKeyRef,
const std::string &value);
std::string appKeyRef(const std::string &appKeyRef) const;
/* Obtain an application specific fingerprint for a key
* stored on this card.
* e.g. An App Key Ref would be
* OpenPGPCard::pgpSigKeyRef */
std::string appKeyFingerprint(const std::string &appKeyRef) const;
void setCardInfo(const std::vector< std::pair<std::string, std::string> > &infos);
void setManufacturer(const std::string &manufacturer);
std::string manufacturer() const;
bool operator == (const Card& other) const override;
private:
QMap <std::string, std::string> mMetaInfo;
std::string mManufacturer;
};
} // namespace Smartcard
} // namespace Kleopatra
diff --git a/src/view/p15cardwidget.cpp b/src/view/p15cardwidget.cpp
index 61452ef56..0c38d4944 100644
--- a/src/view/p15cardwidget.cpp
+++ b/src/view/p15cardwidget.cpp
@@ -1,230 +1,230 @@
/* view/p15cardwiget.cpp
This file is part of Kleopatra, the KDE keymanager
- SPDX-FileCopyrightText: 2020 g10 Code GmbH
+ SPDX-FileCopyrightText: 2021 g10 Code GmbH
SPDX-FileContributor: Andre Heinecke <aheinecke@g10code.com>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "p15cardwidget.h"
#include "smartcard/p15card.h"
#include "smartcard/openpgpcard.h"
#include "smartcard/readerstatus.h"
#include <QVBoxLayout>
#include <QGridLayout>
#include <QScrollArea>
#include <QStringList>
#include <KLocalizedString>
#include <KSeparator>
#include <Libkleo/KeyCache>
#include <Libkleo/Formatting>
#include <QGpgME/Protocol>
#include <QGpgME/KeyListJob>
#include <QGpgME/ImportFromKeyserverJob>
#include <QGpgME/CryptoConfig>
#include <gpgme++/keylistresult.h>
#include <gpgme++/importresult.h>
#include <Libkleo/GnuPG>
#include "kleopatra_debug.h"
using namespace Kleo;
using namespace Kleo::SmartCard;
P15CardWidget::P15CardWidget(QWidget *parent)
: QWidget(parent)
, mSerialNumber(new QLabel(this))
, mVersionLabel(new QLabel(this))
, mSigFprLabel(new QLabel(this))
, mEncFprLabel(new QLabel(this))
, mStatusLabel(new QLabel(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);
cardInfoGrid->addWidget(new QLabel(i18n("Serial number:")), row, 0);
cardInfoGrid->addWidget(mSerialNumber, row++, 1);
mSerialNumber->setTextInteractionFlags(Qt::TextBrowserInteraction);
cardInfoGrid->setColumnStretch(cardInfoGrid->columnCount(), 1);
}
areaVLay->addLayout(cardInfoGrid);
areaVLay->addWidget(mStatusLabel);
mStatusLabel->setVisible(false);
areaVLay->addWidget(new KSeparator(Qt::Horizontal));
areaVLay->addWidget(new QLabel(QStringLiteral("<b>%1</b>").arg(i18n("OpenPGP keys:"))));
areaVLay->addWidget(mSigFprLabel);
areaVLay->addWidget(mEncFprLabel);
areaVLay->addWidget(new KSeparator(Qt::Horizontal));
areaVLay->addStretch(1);
}
P15CardWidget::~P15CardWidget()
{
}
void P15CardWidget::searchPGPFpr(const std::string &fpr)
{
/* Only do auto import from LDAP */
auto conf = QGpgME::cryptoConfig();
Q_ASSERT (conf);
const QString cmp = engineIsVersion(2, 3, 0) ? QStringLiteral("dirmngr") : QStringLiteral("gpg");
const auto entry = conf->entry(cmp, QStringLiteral("Keyserver"), QStringLiteral("keyserver"));
if (!entry || !entry->stringValue().startsWith(QStringLiteral("ldap"))) {
return;
}
static std::vector<std::string> fprs;
if (fpr.empty() || std::find(fprs.begin(), fprs.end(), fpr) != fprs.end()) {
qCDebug(KLEOPATRA_LOG) << "Already looked for " << fpr.c_str() << "on ldap server";
return;
}
mStatusLabel->setText(i18n("Searching in directory service..."));
mStatusLabel->setVisible(true);
fprs.push_back (fpr);
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();
updateSigKeyWidgets(fpr);
});
connect(job, &QGpgME::KeyListJob::result, job, [this](GpgME::KeyListResult, std::vector<GpgME::Key> 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::updateSigKeyWidgets(const std::string &fpr)
{
std::string keyid = fpr;
if (!keyid.empty()) {
QString text = i18n("Signing key:") +
QStringLiteral("\t%1 (%2)")
.arg(Formatting::prettyID(keyid.c_str()));
text += QStringLiteral("<br/><br/>");
keyid.erase(0, keyid.size() - 16);
const auto subkeys = KeyCache::instance()->findSubkeysByKeyID({keyid});
if (subkeys.empty() || subkeys[0].isNull()) {
text += i18n("Public key not found.");
} else {
QStringList toolTips;
toolTips.reserve(subkeys.size());
for (const auto &sub: subkeys) {
// Yep you can have one subkey associated with multiple
// primary keys.
toolTips << Formatting::toolTip(sub.parent(), Formatting::Validity |
Formatting::ExpiryDates |
Formatting::UserIDs |
Formatting::Fingerprint);
}
text += toolTips.join(QLatin1String("<br/>"));
}
mSigFprLabel->setText(text);
} else {
mSigFprLabel->setVisible(false);
}
}
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->appKeyFingerprint(OpenPGPCard::pgpSigKeyRef());
if (!pgpSigFpr.empty()) {
qCDebug(KLEOPATRA_LOG) << "Should be pgp key:" << pgpSigFpr.c_str();
searchPGPFpr(pgpSigFpr);
}
} else {
mStatusLabel->setVisible(false);
}
}
std::string keyid = card->appKeyFingerprint(OpenPGPCard::pgpSigKeyRef());
updateSigKeyWidgets(keyid);
keyid = card->appKeyFingerprint(OpenPGPCard::pgpEncKeyRef());
if (!keyid.empty()) {
mEncFprLabel->setText(i18n("Encryption key:") +
QStringLiteral(" %1 (%2)")
.arg(Formatting::prettyID(keyid.c_str()))
.arg(QString::fromStdString(card->encryptionKeyRef())));
keyid.erase(0, keyid.size() - 16);
const auto subkeys = KeyCache::instance()->findSubkeysByKeyID({keyid});
if (subkeys.empty() || subkeys[0].isNull()) {
mEncFprLabel->setToolTip(i18n("Public key not found."));
} else {
QStringList toolTips;
toolTips.reserve(subkeys.size());
for (const auto &sub: subkeys) {
// Yep you can have one subkey associated with multiple
// primary keys.
toolTips << Formatting::toolTip(sub.parent(), Formatting::Validity |
Formatting::StorageLocation |
Formatting::ExpiryDates |
Formatting::UserIDs |
Formatting::Fingerprint);
}
mEncFprLabel->setToolTip(toolTips.join(QLatin1String("<br/>")));
}
} else {
mEncFprLabel->setVisible(false);
}
// updateKeyWidgets(OpenPGPCard::pgpSigKeyRef(), card);
// updateKeyWidgets(OpenPGPCard::pgpEncKeyRef(), card);
}
diff --git a/src/view/p15cardwidget.h b/src/view/p15cardwidget.h
index cf5c7c099..9f596359c 100644
--- a/src/view/p15cardwidget.h
+++ b/src/view/p15cardwidget.h
@@ -1,43 +1,44 @@
/* view/p15cardwiget.h
This file is part of Kleopatra, the KDE keymanager
- SPDX-FileCopyrightText: 2020 g10 Code GmbH
+ SPDX-FileCopyrightText: 2021 g10 Code GmbH
SPDX-FileContributor: Andre Heinecke <aheinecke@g10code.com>
+
SPDX-License-Identifier: GPL-2.0-or-later
*/
#pragma once
#include <QWidget>
#include <QLabel>
class QLabel;
namespace Kleo
{
namespace SmartCard
{
struct KeyPairInfo;
class P15Card;
} // namespace SmartCard
class P15CardWidget: public QWidget
{
Q_OBJECT
public:
explicit P15CardWidget(QWidget *parent = nullptr);
~P15CardWidget();
void setCard(const SmartCard::P15Card* card);
private:
void searchPGPFpr(const std::string &fpr);
void updateSigKeyWidgets(const std::string &keyid);
std::string mCardSerialNumber;
QLabel *mSerialNumber = nullptr;
QLabel *mVersionLabel = nullptr;
QLabel *mSigFprLabel = nullptr;
QLabel *mEncFprLabel = nullptr;
QLabel *mStatusLabel = nullptr;
};
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Mon, Dec 23, 1:15 PM (12 m, 34 s)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
69/82/1a6a331b716563dc7dcaa0eeef71
Attached To
rKLEOPATRA Kleopatra
Event Timeline
Log In to Comment