Page MenuHome GnuPG

No OneTemporary

diff --git a/src/newcertificatewizard/advancedsettingsdialog.cpp b/src/newcertificatewizard/advancedsettingsdialog.cpp
index 7c69932b5..aad747844 100644
--- a/src/newcertificatewizard/advancedsettingsdialog.cpp
+++ b/src/newcertificatewizard/advancedsettingsdialog.cpp
@@ -1,1017 +1,439 @@
/* -*- mode: c++; c-basic-offset:4 -*-
newcertificatewizard/advancedsettingsdialog.cpp
This file is part of Kleopatra, the KDE keymanager
SPDX-FileCopyrightText: 2008 Klarälvdalens Datakonsult AB
SPDX-FileCopyrightText: 2016, 2017 Bundesamt für Sicherheit in der Informationstechnik
SPDX-FileContributor: Intevation GmbH
SPDX-FileCopyrightText: 2022 g10 Code GmbH
SPDX-FileContributor: Ingo Klöcker <dev@ingo-kloecker.de>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include <config-kleopatra.h>
#include "advancedsettingsdialog_p.h"
-#include "keyalgo_p.h"
#include "listwidget.h"
-#include "utils/expiration.h"
#include "utils/gui-helper.h"
#include "utils/scrollarea.h"
#include <settings.h>
#include <Libkleo/Compat>
#include <Libkleo/Compliance>
#include <Libkleo/GnuPG>
-#include <KDateComboBox>
#include <KLocalizedString>
-#include <KMessageBox>
#include <QGpgME/CryptoConfig>
#include <QGpgME/Protocol>
#include <QCheckBox>
+#include <QComboBox>
#include <QDialogButtonBox>
#include <QGridLayout>
#include <QGroupBox>
#include <QHBoxLayout>
+#include <QLabel>
#include <QPushButton>
-#include <QRadioButton>
#include <QTabWidget>
#include <QVBoxLayout>
#include "kleopatra_debug.h"
using namespace Kleo;
using namespace Kleo::NewCertificateUi;
using namespace GpgME;
static const char RSA_KEYSIZES_ENTRY[] = "RSAKeySizes";
-static const char DSA_KEYSIZES_ENTRY[] = "DSAKeySizes";
-static const char ELG_KEYSIZES_ENTRY[] = "ELGKeySizes";
-
static const char RSA_KEYSIZE_LABELS_ENTRY[] = "RSAKeySizeLabels";
-static const char DSA_KEYSIZE_LABELS_ENTRY[] = "DSAKeySizeLabels";
-static const char ELG_KEYSIZE_LABELS_ENTRY[] = "ELGKeySizeLabels";
-
-static const char PGP_KEY_TYPE_ENTRY[] = "PGPKeyType";
static const char CMS_KEY_TYPE_ENTRY[] = "CMSKeyType";
-// This should come from gpgme in the future
-// For now we only support the basic 2.1 curves and check
-// for GnuPG 2.1. The whole subkey / usage generation needs
-// new api and a reworked dialog. (ah 10.3.16)
-// EDDSA should be supported, too.
-static const QStringList curveNames{
- {QStringLiteral("brainpoolP256r1")},
- {QStringLiteral("brainpoolP384r1")},
- {QStringLiteral("brainpoolP512r1")},
- {QStringLiteral("NIST P-256")},
- {QStringLiteral("NIST P-384")},
- {QStringLiteral("NIST P-521")},
-};
-
namespace
{
static void set_keysize(QComboBox *cb, unsigned int strength)
{
if (!cb) {
return;
}
const int idx = cb->findData(static_cast<int>(strength));
if (idx >= 0) {
cb->setCurrentIndex(idx);
}
}
static unsigned int get_keysize(const QComboBox *cb)
{
if (!cb) {
return 0;
}
const int idx = cb->currentIndex();
if (idx < 0) {
return 0;
}
return cb->itemData(idx).toInt();
}
-static void set_curve(QComboBox *cb, const QString &curve)
-{
- if (!cb) {
- return;
- }
- const int idx = cb->findText(curve, Qt::MatchFixedString);
- if (idx >= 0) {
- cb->setCurrentIndex(idx);
- }
-}
-
-static QString get_curve(const QComboBox *cb)
-{
- if (!cb) {
- return QString();
- }
- return cb->currentText();
-}
-
-// Extract the algo information from default_pubkey_algo format
-//
-// and put it into the return values size, algo and curve.
-//
-// Values look like:
-// RSA-2048
-// rsa2048/cert,sign+rsa2048/enc
-// brainpoolP256r1+brainpoolP256r1
-static void parseAlgoString(const QString &algoString, int *size, Subkey::PubkeyAlgo *algo, QString &curve)
+static int parseSize(const QString &algoString)
{
const auto split = algoString.split(QLatin1Char('/'));
- bool isEncrypt = split.size() == 2 && split[1].contains(QLatin1StringView("enc"));
-
- // Normalize
const auto lowered = split[0].toLower().remove(QLatin1Char('-'));
- if (!algo || !size) {
- return;
- }
- *algo = Subkey::AlgoUnknown;
- if (lowered.startsWith(QLatin1StringView("rsa"))) {
- *algo = Subkey::AlgoRSA;
- } else if (lowered.startsWith(QLatin1StringView("dsa"))) {
- *algo = Subkey::AlgoDSA;
- } else if (lowered.startsWith(QLatin1StringView("elg"))) {
- *algo = Subkey::AlgoELG;
- }
-
- if (*algo != Subkey::AlgoUnknown) {
- bool ok;
- *size = QStringView(lowered).right(lowered.size() - 3).toInt(&ok);
- if (!ok) {
- qCWarning(KLEOPATRA_LOG) << "Could not extract size from: " << lowered;
- *size = 3072;
- }
- return;
- }
- // Now the ECC Algorithms
- if (lowered.startsWith(QLatin1StringView("ed25519"))) {
- // Special handling for this as technically
- // this is a cv25519 curve used for EDDSA
- if (isEncrypt) {
- curve = QLatin1StringView("cv25519");
- *algo = Subkey::AlgoECDH;
- } else {
- curve = split[0];
- *algo = Subkey::AlgoEDDSA;
- }
- return;
+ bool ok;
+ auto size = lowered.right(lowered.size() - 3).toInt(&ok);
+ if (ok) {
+ return size;
}
- if (lowered.startsWith(QLatin1StringView("cv25519")) //
- || lowered.startsWith(QLatin1StringView("nist")) //
- || lowered.startsWith(QLatin1StringView("brainpool")) //
- || lowered.startsWith(QLatin1StringView("secp"))) {
- curve = split[0];
- *algo = isEncrypt ? Subkey::AlgoECDH : Subkey::AlgoECDSA;
- return;
- }
-
- qCWarning(KLEOPATRA_LOG) << "Failed to parse default_pubkey_algo:" << algoString;
+ qCWarning(KLEOPATRA_LOG) << "Could not extract size from: " << lowered;
+ return 3072;
}
}
struct AdvancedSettingsDialog::UI {
QTabWidget *tabWidget = nullptr;
- QRadioButton *rsaRB = nullptr;
QComboBox *rsaKeyStrengthCB = nullptr;
- QCheckBox *rsaSubCB = nullptr;
- QComboBox *rsaKeyStrengthSubCB = nullptr;
- QRadioButton *dsaRB = nullptr;
- QComboBox *dsaKeyStrengthCB = nullptr;
- QCheckBox *elgCB = nullptr;
- QComboBox *elgKeyStrengthCB = nullptr;
- QRadioButton *ecdsaRB = nullptr;
- QComboBox *ecdsaKeyCurvesCB = nullptr;
- QCheckBox *ecdhCB = nullptr;
- QComboBox *ecdhKeyCurvesCB = nullptr;
- QCheckBox *certificationCB = nullptr;
QCheckBox *signingCB = nullptr;
QCheckBox *encryptionCB = nullptr;
- QCheckBox *authenticationCB = nullptr;
- QCheckBox *expiryCB = nullptr;
- KDateComboBox *expiryDE = nullptr;
ScrollArea *personalTab = nullptr;
- QGroupBox *uidGB = nullptr;
- Kleo::NewCertificateUi::ListWidget *uidLW = nullptr;
QGroupBox *emailGB = nullptr;
Kleo::NewCertificateUi::ListWidget *emailLW = nullptr;
QGroupBox *dnsGB = nullptr;
Kleo::NewCertificateUi::ListWidget *dnsLW = nullptr;
QGroupBox *uriGB = nullptr;
Kleo::NewCertificateUi::ListWidget *uriLW = nullptr;
QDialogButtonBox *buttonBox = nullptr;
UI(QDialog *parent)
{
parent->setWindowTitle(i18nc("@title:window", "Advanced Settings"));
auto mainLayout = new QVBoxLayout{parent};
tabWidget = new QTabWidget{parent};
+ tabWidget->setDocumentMode(true);
{
auto technicalTab = new ScrollArea{tabWidget};
technicalTab->setFocusPolicy(Qt::NoFocus);
technicalTab->setFrameStyle(QFrame::NoFrame);
technicalTab->setBackgroundRole(parent->backgroundRole());
technicalTab->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
technicalTab->setSizeAdjustPolicy(QScrollArea::AdjustToContents);
auto tabLayout = qobject_cast<QVBoxLayout *>(technicalTab->widget()->layout());
{
auto groupBox = new QGroupBox{i18nc("@title:group", "Key Material"), technicalTab};
auto groupBoxGrid = new QGridLayout{groupBox};
int row = 0;
- rsaRB = new QRadioButton{i18nc("@option:radio", "RSA"), groupBox};
- rsaRB->setChecked(false);
- groupBoxGrid->addWidget(rsaRB, row, 0, 1, 2);
+ auto label = new QLabel(i18nc("@info:label", "RSA key strength:"));
+ groupBoxGrid->addWidget(label, row, 0, 1, 1);
rsaKeyStrengthCB = new QComboBox{groupBox};
- rsaKeyStrengthCB->setEnabled(false);
+ rsaKeyStrengthCB->setEnabled(true);
groupBoxGrid->addWidget(rsaKeyStrengthCB, row, 2, 1, 1);
row++;
auto subKeyIndentation = new QSpacerItem(13, 13, QSizePolicy::Fixed, QSizePolicy::Minimum);
groupBoxGrid->addItem(subKeyIndentation, row, 0, 1, 1);
- rsaSubCB = new QCheckBox{i18nc("@option:check", "+ RSA"), groupBox};
- rsaSubCB->setEnabled(true);
- groupBoxGrid->addWidget(rsaSubCB, row, 1, 1, 1);
-
- rsaKeyStrengthSubCB = new QComboBox{groupBox};
- rsaKeyStrengthSubCB->setEnabled(false);
- groupBoxGrid->addWidget(rsaKeyStrengthSubCB, row, 2, 1, 1);
-
- row++;
- dsaRB = new QRadioButton{i18nc("@option:radio", "DSA"), groupBox};
- groupBoxGrid->addWidget(dsaRB, row, 0, 1, 2);
-
- dsaKeyStrengthCB = new QComboBox{groupBox};
- dsaKeyStrengthCB->setEnabled(false);
- groupBoxGrid->addWidget(dsaKeyStrengthCB, row, 2, 1, 1);
-
- row++;
- elgCB = new QCheckBox{i18nc("@option:check", "+ Elgamal"), groupBox};
- elgCB->setToolTip(i18nc("@info:tooltip", "This subkey is required for encryption."));
- elgCB->setEnabled(true);
- groupBoxGrid->addWidget(elgCB, row, 1, 1, 1);
-
- elgKeyStrengthCB = new QComboBox{groupBox};
- elgKeyStrengthCB->setEnabled(false);
- groupBoxGrid->addWidget(elgKeyStrengthCB, row, 2, 1, 1);
-
- row++;
- ecdsaRB = new QRadioButton{i18nc("@option:radio", "ECDSA"), groupBox};
- groupBoxGrid->addWidget(ecdsaRB, row, 0, 1, 2);
-
- ecdsaKeyCurvesCB = new QComboBox{groupBox};
- ecdsaKeyCurvesCB->setEnabled(false);
- groupBoxGrid->addWidget(ecdsaKeyCurvesCB, row, 2, 1, 1);
-
- row++;
- ecdhCB = new QCheckBox{i18nc("@option:check", "+ ECDH"), groupBox};
- ecdhCB->setToolTip(i18nc("@info:tooltip", "This subkey is required for encryption."));
- ecdhCB->setEnabled(true);
- groupBoxGrid->addWidget(ecdhCB, row, 1, 1, 1);
-
- ecdhKeyCurvesCB = new QComboBox{groupBox};
- ecdhKeyCurvesCB->setEnabled(false);
- groupBoxGrid->addWidget(ecdhKeyCurvesCB, row, 2, 1, 1);
-
groupBoxGrid->setColumnStretch(3, 1);
tabLayout->addWidget(groupBox);
}
{
auto groupBox = new QGroupBox{i18nc("@title:group", "Certificate Usage"), technicalTab};
auto groupBoxGrid = new QGridLayout{groupBox};
int row = 0;
signingCB = new QCheckBox{i18nc("@option:check", "Signing"), groupBox};
signingCB->setChecked(true);
groupBoxGrid->addWidget(signingCB, row, 0, 1, 1);
- certificationCB = new QCheckBox{i18nc("@option:check", "Certification"), groupBox};
- groupBoxGrid->addWidget(certificationCB, row, 1, 1, 1);
-
row++;
encryptionCB = new QCheckBox{i18nc("@option:check", "Encryption"), groupBox};
encryptionCB->setChecked(true);
groupBoxGrid->addWidget(encryptionCB, row, 0, 1, 1);
- authenticationCB = new QCheckBox{i18nc("@option:check", "Authentication"), groupBox};
- groupBoxGrid->addWidget(authenticationCB, row, 1, 1, 1);
-
row++;
{
auto hbox = new QHBoxLayout;
-
- expiryCB = new QCheckBox{i18nc("@option:check", "Valid until:"), groupBox};
- hbox->addWidget(expiryCB);
-
- expiryDE = new KDateComboBox(groupBox);
- hbox->addWidget(expiryDE, 1);
-
groupBoxGrid->addLayout(hbox, row, 0, 1, 2);
}
tabLayout->addWidget(groupBox);
}
tabLayout->addStretch(1);
tabWidget->addTab(technicalTab, i18nc("@title:tab", "Technical Details"));
}
{
personalTab = new ScrollArea{tabWidget};
personalTab->setFocusPolicy(Qt::NoFocus);
personalTab->setFrameStyle(QFrame::NoFrame);
personalTab->setBackgroundRole(parent->backgroundRole());
personalTab->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
personalTab->setSizeAdjustPolicy(QScrollArea::AdjustToContents);
auto scrollAreaLayout = qobject_cast<QVBoxLayout *>(personalTab->widget()->layout());
auto tabGrid = new QGridLayout;
- uidGB = new QGroupBox{i18nc("@title:group", "Additional User IDs"), personalTab};
- {
- auto layout = new QVBoxLayout{uidGB};
- uidLW = new Kleo::NewCertificateUi::ListWidget{uidGB};
- layout->addWidget(uidLW);
- }
- tabGrid->addWidget(uidGB, 0, 0, 1, 2);
-
emailGB = new QGroupBox{i18nc("@title:group", "EMail Addresses"), personalTab};
{
auto layout = new QVBoxLayout{emailGB};
emailLW = new Kleo::NewCertificateUi::ListWidget{emailGB};
layout->addWidget(emailLW);
}
tabGrid->addWidget(emailGB, 2, 0, 2, 1);
dnsGB = new QGroupBox{i18nc("@title:group", "DNS Names"), personalTab};
{
auto layout = new QVBoxLayout{dnsGB};
dnsLW = new Kleo::NewCertificateUi::ListWidget{dnsGB};
layout->addWidget(dnsLW);
}
tabGrid->addWidget(dnsGB, 2, 1, 1, 1);
uriGB = new QGroupBox{i18nc("@title:group", "URIs"), personalTab};
{
auto layout = new QVBoxLayout{uriGB};
uriLW = new Kleo::NewCertificateUi::ListWidget{uriGB};
layout->addWidget(uriLW);
}
tabGrid->addWidget(uriGB, 3, 1, 1, 1);
scrollAreaLayout->addLayout(tabGrid);
tabWidget->addTab(personalTab, i18nc("@title:tab", "Personal Details"));
}
mainLayout->addWidget(tabWidget);
buttonBox = new QDialogButtonBox{parent};
buttonBox->setStandardButtons(QDialogButtonBox::Cancel | QDialogButtonBox::Ok);
mainLayout->addWidget(buttonBox);
}
};
AdvancedSettingsDialog::AdvancedSettingsDialog(QWidget *parent)
: QDialog{parent}
, ui{new UI{this}}
- , mECCSupported{engineIsVersion(2, 1, 0)}
- , mEdDSASupported{engineIsVersion(2, 1, 15)}
{
qRegisterMetaType<Subkey::PubkeyAlgo>("Subkey::PubkeyAlgo");
- Kleo::setUpExpirationDateComboBox(ui->expiryDE);
- if (unlimitedValidityIsAllowed()) {
- ui->expiryDE->setEnabled(ui->expiryCB->isChecked());
- } else {
- ui->expiryCB->setEnabled(false);
- ui->expiryCB->setChecked(true);
- }
ui->emailLW->setDefaultValue(i18n("new email"));
ui->dnsLW->setDefaultValue(i18n("new dns name"));
ui->uriLW->setDefaultValue(i18n("new uri"));
fillKeySizeComboBoxen();
- connect(ui->rsaRB, &QAbstractButton::toggled, ui->rsaKeyStrengthCB, &QWidget::setEnabled);
- connect(ui->rsaRB, &QAbstractButton::toggled, this, &AdvancedSettingsDialog::slotKeyMaterialSelectionChanged);
- connect(ui->rsaSubCB, &QAbstractButton::toggled, ui->rsaKeyStrengthSubCB, &QWidget::setEnabled);
- connect(ui->rsaSubCB, &QAbstractButton::toggled, this, &AdvancedSettingsDialog::slotKeyMaterialSelectionChanged);
-
- connect(ui->dsaRB, &QAbstractButton::toggled, ui->dsaKeyStrengthCB, &QWidget::setEnabled);
- connect(ui->dsaRB, &QAbstractButton::toggled, this, &AdvancedSettingsDialog::slotKeyMaterialSelectionChanged);
- connect(ui->elgCB, &QAbstractButton::toggled, ui->elgKeyStrengthCB, &QWidget::setEnabled);
- connect(ui->elgCB, &QAbstractButton::toggled, this, &AdvancedSettingsDialog::slotKeyMaterialSelectionChanged);
-
- connect(ui->ecdsaRB, &QAbstractButton::toggled, ui->ecdsaKeyCurvesCB, &QWidget::setEnabled);
- connect(ui->ecdsaRB, &QAbstractButton::toggled, this, &AdvancedSettingsDialog::slotKeyMaterialSelectionChanged);
- connect(ui->ecdhCB, &QAbstractButton::toggled, ui->ecdhKeyCurvesCB, &QWidget::setEnabled);
- connect(ui->ecdhCB, &QAbstractButton::toggled, this, &AdvancedSettingsDialog::slotKeyMaterialSelectionChanged);
-
connect(ui->signingCB, &QAbstractButton::toggled, this, &AdvancedSettingsDialog::slotSigningAllowedToggled);
connect(ui->encryptionCB, &QAbstractButton::toggled, this, &AdvancedSettingsDialog::slotEncryptionAllowedToggled);
- connect(ui->expiryCB, &QAbstractButton::toggled, this, [this](bool checked) {
- ui->expiryDE->setEnabled(checked);
- if (checked && !ui->expiryDE->isValid()) {
- setExpiryDate(defaultExpirationDate(ExpirationOnUnlimitedValidity::InternalDefaultExpiration));
- }
- });
-
connect(ui->buttonBox, &QDialogButtonBox::accepted, this, &AdvancedSettingsDialog::accept);
connect(ui->buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
-}
-
-AdvancedSettingsDialog::~AdvancedSettingsDialog() = default;
-bool AdvancedSettingsDialog::unlimitedValidityIsAllowed() const
-{
- return !Kleo::maximumExpirationDate().isValid();
-}
-
-void AdvancedSettingsDialog::setProtocol(GpgME::Protocol proto)
-{
- if (protocol == proto) {
- return;
- }
- protocol = proto;
loadDefaults();
}
-void AdvancedSettingsDialog::setAdditionalUserIDs(const QStringList &items)
-{
- ui->uidLW->setItems(items);
-}
-
-QStringList AdvancedSettingsDialog::additionalUserIDs() const
-{
- return ui->uidLW->items();
-}
+AdvancedSettingsDialog::~AdvancedSettingsDialog() = default;
void AdvancedSettingsDialog::setAdditionalEMailAddresses(const QStringList &items)
{
ui->emailLW->setItems(items);
}
QStringList AdvancedSettingsDialog::additionalEMailAddresses() const
{
return ui->emailLW->items();
}
void AdvancedSettingsDialog::setDnsNames(const QStringList &items)
{
ui->dnsLW->setItems(items);
}
QStringList AdvancedSettingsDialog::dnsNames() const
{
return ui->dnsLW->items();
}
void AdvancedSettingsDialog::setUris(const QStringList &items)
{
ui->uriLW->setItems(items);
}
QStringList AdvancedSettingsDialog::uris() const
{
return ui->uriLW->items();
}
void AdvancedSettingsDialog::setKeyStrength(unsigned int strength)
{
set_keysize(ui->rsaKeyStrengthCB, strength);
- set_keysize(ui->dsaKeyStrengthCB, strength);
}
unsigned int AdvancedSettingsDialog::keyStrength() const
{
- return ui->dsaRB->isChecked() ? get_keysize(ui->dsaKeyStrengthCB) : ui->rsaRB->isChecked() ? get_keysize(ui->rsaKeyStrengthCB) : 0;
-}
-
-void AdvancedSettingsDialog::setKeyType(Subkey::PubkeyAlgo algo)
-{
- QRadioButton *const rb = is_rsa(algo) ? ui->rsaRB : is_dsa(algo) ? ui->dsaRB : is_ecdsa(algo) || is_eddsa(algo) ? ui->ecdsaRB : nullptr;
- if (rb) {
- rb->setChecked(true);
- }
+ return get_keysize(ui->rsaKeyStrengthCB);
}
Subkey::PubkeyAlgo AdvancedSettingsDialog::keyType() const
{
- return ui->dsaRB->isChecked() ? Subkey::AlgoDSA
- : ui->rsaRB->isChecked() ? Subkey::AlgoRSA
- : ui->ecdsaRB->isChecked() ? ui->ecdsaKeyCurvesCB->currentText() == QLatin1StringView("ed25519") ? Subkey::AlgoEDDSA : Subkey::AlgoECDSA
- : Subkey::AlgoUnknown;
-}
-
-void AdvancedSettingsDialog::setKeyCurve(const QString &curve)
-{
- set_curve(ui->ecdsaKeyCurvesCB, curve);
-}
-
-QString AdvancedSettingsDialog::keyCurve() const
-{
- return get_curve(ui->ecdsaKeyCurvesCB);
-}
-
-void AdvancedSettingsDialog::setSubkeyType(Subkey::PubkeyAlgo algo)
-{
- ui->elgCB->setChecked(is_elg(algo));
- ui->rsaSubCB->setChecked(is_rsa(algo));
- ui->ecdhCB->setChecked(is_ecdh(algo));
-}
-
-Subkey::PubkeyAlgo AdvancedSettingsDialog::subkeyType() const
-{
- if (ui->elgCB->isChecked()) {
- return Subkey::AlgoELG_E;
- } else if (ui->rsaSubCB->isChecked()) {
- return Subkey::AlgoRSA;
- } else if (ui->ecdhCB->isChecked()) {
- return Subkey::AlgoECDH;
- }
- return Subkey::AlgoUnknown;
-}
-
-void AdvancedSettingsDialog::setSubkeyCurve(const QString &curve)
-{
- set_curve(ui->ecdhKeyCurvesCB, curve);
-}
-
-QString AdvancedSettingsDialog::subkeyCurve() const
-{
- return get_curve(ui->ecdhKeyCurvesCB);
-}
-
-void AdvancedSettingsDialog::setSubkeyStrength(unsigned int strength)
-{
- if (subkeyType() == Subkey::AlgoRSA) {
- set_keysize(ui->rsaKeyStrengthSubCB, strength);
- } else {
- set_keysize(ui->elgKeyStrengthCB, strength);
- }
-}
-
-unsigned int AdvancedSettingsDialog::subkeyStrength() const
-{
- if (subkeyType() == Subkey::AlgoRSA) {
- return get_keysize(ui->rsaKeyStrengthSubCB);
- }
- return get_keysize(ui->elgKeyStrengthCB);
+ return Subkey::AlgoRSA;
}
void AdvancedSettingsDialog::setSigningAllowed(bool on)
{
ui->signingCB->setChecked(on);
}
bool AdvancedSettingsDialog::signingAllowed() const
{
return ui->signingCB->isChecked();
}
void AdvancedSettingsDialog::setEncryptionAllowed(bool on)
{
ui->encryptionCB->setChecked(on);
}
bool AdvancedSettingsDialog::encryptionAllowed() const
{
return ui->encryptionCB->isChecked();
}
-void AdvancedSettingsDialog::setCertificationAllowed(bool on)
-{
- ui->certificationCB->setChecked(on);
-}
-
-bool AdvancedSettingsDialog::certificationAllowed() const
-{
- return ui->certificationCB->isChecked();
-}
-
-void AdvancedSettingsDialog::setAuthenticationAllowed(bool on)
-{
- ui->authenticationCB->setChecked(on);
-}
-
-bool AdvancedSettingsDialog::authenticationAllowed() const
-{
- return ui->authenticationCB->isChecked();
-}
-
-QDate AdvancedSettingsDialog::forceDateIntoAllowedRange(QDate date) const
-{
- const auto minDate = ui->expiryDE->minimumDate();
- if (minDate.isValid() && date < minDate) {
- date = minDate;
- }
- const auto maxDate = ui->expiryDE->maximumDate();
- if (maxDate.isValid() && date > maxDate) {
- date = maxDate;
- }
- return date;
-}
-
-void AdvancedSettingsDialog::setExpiryDate(QDate date)
-{
- if (date.isValid()) {
- ui->expiryDE->setDate(forceDateIntoAllowedRange(date));
- } else {
- // check if unlimited validity is allowed
- if (unlimitedValidityIsAllowed()) {
- ui->expiryDE->setDate(date);
- }
- }
- if (ui->expiryCB->isEnabled()) {
- ui->expiryCB->setChecked(ui->expiryDE->isValid());
- }
-}
-
-QDate AdvancedSettingsDialog::expiryDate() const
-{
- return ui->expiryCB->isChecked() ? ui->expiryDE->date() : QDate{};
-}
-
-void AdvancedSettingsDialog::slotKeyMaterialSelectionChanged()
-{
- const unsigned int algo = keyType();
- const unsigned int sk_algo = subkeyType();
-
- if (protocol == OpenPGP) {
- // first update the enabled state, but only if key type is not forced
- if (!keyTypeImmutable) {
- ui->elgCB->setEnabled(is_dsa(algo));
- ui->rsaSubCB->setEnabled(is_rsa(algo));
- ui->ecdhCB->setEnabled(is_ecdsa(algo) || is_eddsa(algo));
- if (is_rsa(algo)) {
- ui->encryptionCB->setEnabled(true);
- ui->signingCB->setEnabled(true);
- ui->authenticationCB->setEnabled(true);
- if (is_rsa(sk_algo)) {
- ui->encryptionCB->setEnabled(false);
- } else {
- ui->encryptionCB->setEnabled(true);
- }
- } else if (is_dsa(algo)) {
- ui->encryptionCB->setEnabled(false);
- } else if (is_ecdsa(algo) || is_eddsa(algo)) {
- ui->signingCB->setEnabled(true);
- ui->authenticationCB->setEnabled(true);
- ui->encryptionCB->setEnabled(false);
- }
- }
- // then update the checked state
- if (sender() == ui->dsaRB || sender() == ui->rsaRB || sender() == ui->ecdsaRB) {
- ui->elgCB->setChecked(is_dsa(algo));
- ui->ecdhCB->setChecked(is_ecdsa(algo) || is_eddsa(algo));
- ui->rsaSubCB->setChecked(is_rsa(algo));
- }
- if (is_rsa(algo)) {
- ui->encryptionCB->setChecked(true);
- ui->signingCB->setChecked(true);
- if (is_rsa(sk_algo)) {
- ui->encryptionCB->setChecked(true);
- }
- } else if (is_dsa(algo)) {
- if (is_elg(sk_algo)) {
- ui->encryptionCB->setChecked(true);
- } else {
- ui->encryptionCB->setChecked(false);
- }
- } else if (is_ecdsa(algo) || is_eddsa(algo)) {
- ui->signingCB->setChecked(true);
- ui->encryptionCB->setChecked(is_ecdh(sk_algo));
- }
- } else {
- // assert( is_rsa( keyType() ) ); // it can happen through misconfiguration by the admin that no key type is selectable at all
- }
-}
-
void AdvancedSettingsDialog::slotSigningAllowedToggled(bool on)
{
- if (!on && protocol == CMS && !encryptionAllowed()) {
+ if (!on && !encryptionAllowed()) {
setEncryptionAllowed(true);
}
}
void AdvancedSettingsDialog::slotEncryptionAllowedToggled(bool on)
{
- if (!on && protocol == CMS && !signingAllowed()) {
+ if (!on && !signingAllowed()) {
setSigningAllowed(true);
}
}
static void fill_combobox(QComboBox &cb, const QList<int> &sizes, const QStringList &labels)
{
cb.clear();
for (int i = 0, end = sizes.size(); i != end; ++i) {
const int size = std::abs(sizes[i]);
/* As we respect the defaults configurable in GnuPG, and we also have configurable
* defaults in Kleopatra its difficult to print out "default" here. To avoid confusion
* about that its better not to show any default indication. */
cb.addItem(i < labels.size() && !labels[i].trimmed().isEmpty()
? i18ncp("%2: some admin-supplied text, %1: key size in bits", "%2 (1 bit)", "%2 (%1 bits)", size, labels[i].trimmed())
: i18ncp("%1: key size in bits", "1 bit", "%1 bits", size),
size);
if (sizes[i] < 0) {
cb.setCurrentIndex(cb.count() - 1);
}
}
}
void AdvancedSettingsDialog::fillKeySizeComboBoxen()
{
const KConfigGroup config(KSharedConfig::openConfig(), QStringLiteral("CertificateCreationWizard"));
QList<int> rsaKeySizes = config.readEntry(RSA_KEYSIZES_ENTRY, QList<int>() << 2048 << -3072 << 4096);
if (DeVSCompliance::isActive()) {
rsaKeySizes = config.readEntry(RSA_KEYSIZES_ENTRY, QList<int>() << -3072 << 4096);
}
- const QList<int> dsaKeySizes = config.readEntry(DSA_KEYSIZES_ENTRY, QList<int>() << -2048);
- const QList<int> elgKeySizes = config.readEntry(ELG_KEYSIZES_ENTRY, QList<int>() << -2048 << 3072 << 4096);
const QStringList rsaKeySizeLabels = config.readEntry(RSA_KEYSIZE_LABELS_ENTRY, QStringList());
- const QStringList dsaKeySizeLabels = config.readEntry(DSA_KEYSIZE_LABELS_ENTRY, QStringList());
- const QStringList elgKeySizeLabels = config.readEntry(ELG_KEYSIZE_LABELS_ENTRY, QStringList());
fill_combobox(*ui->rsaKeyStrengthCB, rsaKeySizes, rsaKeySizeLabels);
- fill_combobox(*ui->rsaKeyStrengthSubCB, rsaKeySizes, rsaKeySizeLabels);
- fill_combobox(*ui->dsaKeyStrengthCB, dsaKeySizes, dsaKeySizeLabels);
- fill_combobox(*ui->elgKeyStrengthCB, elgKeySizes, elgKeySizeLabels);
- if (mEdDSASupported) {
- // If supported we recommend cv25519
- ui->ecdsaKeyCurvesCB->addItem(QStringLiteral("ed25519"));
- ui->ecdhKeyCurvesCB->addItem(QStringLiteral("cv25519"));
- }
- ui->ecdhKeyCurvesCB->addItems(curveNames);
- ui->ecdsaKeyCurvesCB->addItems(curveNames);
}
// Try to load the default key type from GnuPG
void AdvancedSettingsDialog::loadDefaultGnuPGKeyType()
{
const auto conf = QGpgME::cryptoConfig();
if (!conf) {
qCWarning(KLEOPATRA_LOG) << "Failed to obtain cryptoConfig.";
return;
}
- const auto entry = getCryptoConfigEntry(conf, protocol == CMS ? "gpgsm" : "gpg", "default_pubkey_algo");
+ const auto entry = getCryptoConfigEntry(conf, "gpgsm", "default_pubkey_algo");
if (!entry) {
qCDebug(KLEOPATRA_LOG) << "GnuPG does not have default key type. Fallback to RSA";
- setKeyType(Subkey::AlgoRSA);
- setSubkeyType(Subkey::AlgoRSA);
return;
}
qCDebug(KLEOPATRA_LOG) << "Have default key type: " << entry->stringValue();
// Format is <primarytype>[/usage]+<subkeytype>[/usage]
const auto split = entry->stringValue().split(QLatin1Char('+'));
- int size = 0;
- Subkey::PubkeyAlgo algo = Subkey::AlgoUnknown;
- QString curve;
-
- parseAlgoString(split[0], &size, &algo, curve);
- if (algo == Subkey::AlgoUnknown) {
- setSubkeyType(Subkey::AlgoRSA);
- return;
- }
-
- setKeyType(algo);
-
- if (is_rsa(algo) || is_elg(algo) || is_dsa(algo)) {
- setKeyStrength(size);
- } else {
- setKeyCurve(curve);
- }
-
- {
- auto algoString = (split.size() == 2) ? split[1] : split[0];
- // If it has no usage we assume encrypt subkey
- if (!algoString.contains(QLatin1Char('/'))) {
- algoString += QStringLiteral("/enc");
- }
-
- parseAlgoString(algoString, &size, &algo, curve);
-
- if (algo == Subkey::AlgoUnknown) {
- setSubkeyType(Subkey::AlgoRSA);
- return;
- }
-
- setSubkeyType(algo);
-
- if (is_rsa(algo) || is_elg(algo)) {
- setSubkeyStrength(size);
- } else {
- setSubkeyCurve(curve);
- }
- }
+ setKeyStrength(parseSize(split[0]));
}
void AdvancedSettingsDialog::loadDefaultKeyType()
{
- if (protocol != CMS && protocol != OpenPGP) {
- return;
- }
-
const KConfigGroup config(KSharedConfig::openConfig(), QStringLiteral("CertificateCreationWizard"));
- const QString entry = protocol == CMS ? QLatin1StringView(CMS_KEY_TYPE_ENTRY) : QLatin1String(PGP_KEY_TYPE_ENTRY);
+ const QString entry = QLatin1StringView(CMS_KEY_TYPE_ENTRY);
const QString keyType = config.readEntry(entry).trimmed().toUpper();
- if (protocol == OpenPGP && keyType == QLatin1StringView("DSA")) {
- setKeyType(Subkey::AlgoDSA);
- setSubkeyType(Subkey::AlgoUnknown);
- } else if (protocol == OpenPGP && keyType == QLatin1StringView("DSA+ELG")) {
- setKeyType(Subkey::AlgoDSA);
- setSubkeyType(Subkey::AlgoELG_E);
- } else if (keyType.isEmpty() && engineIsVersion(2, 1, 17)) {
+ if (keyType.isEmpty() && engineIsVersion(2, 1, 17)) {
loadDefaultGnuPGKeyType();
} else {
if (!keyType.isEmpty() && keyType != QLatin1StringView("RSA"))
qCWarning(KLEOPATRA_LOG) << "invalid value \"" << qPrintable(keyType) << "\" for entry \"[CertificateCreationWizard]" << qPrintable(entry) << "\"";
- setKeyType(Subkey::AlgoRSA);
- setSubkeyType(Subkey::AlgoRSA);
}
keyTypeImmutable = config.isEntryImmutable(entry);
}
-void AdvancedSettingsDialog::loadDefaultExpiration()
-{
- if (protocol != OpenPGP) {
- return;
- }
-
- if (unlimitedValidityIsAllowed()) {
- setExpiryDate(defaultExpirationDate(ExpirationOnUnlimitedValidity::NoExpiration));
- } else {
- setExpiryDate(defaultExpirationDate(ExpirationOnUnlimitedValidity::InternalDefaultExpiration));
- }
-}
-
void AdvancedSettingsDialog::loadDefaults()
{
loadDefaultKeyType();
- loadDefaultExpiration();
-
updateWidgetVisibility();
}
void AdvancedSettingsDialog::updateWidgetVisibility()
{
- // Personal Details Page
- if (protocol == OpenPGP) { // ### hide until multi-uid is implemented
- if (ui->tabWidget->indexOf(ui->personalTab) != -1) {
- ui->tabWidget->removeTab(ui->tabWidget->indexOf(ui->personalTab));
- }
- } else {
- if (ui->tabWidget->indexOf(ui->personalTab) == -1) {
- ui->tabWidget->addTab(ui->personalTab, i18nc("@title:tab", "Personal Details"));
- }
- }
- ui->uidGB->setVisible(protocol == OpenPGP);
- ui->uidGB->setEnabled(false);
- ui->uidGB->setToolTip(i18nc("@info:tooltip", "Adding more than one user ID is not yet implemented."));
- ui->emailGB->setVisible(protocol == CMS);
- ui->dnsGB->setVisible(protocol == CMS);
- ui->uriGB->setVisible(protocol == CMS);
-
- // Technical Details Page
- ui->ecdhCB->setVisible(mECCSupported);
- ui->ecdhKeyCurvesCB->setVisible(mECCSupported);
- ui->ecdsaKeyCurvesCB->setVisible(mECCSupported);
- ui->ecdsaRB->setVisible(mECCSupported);
- if (mEdDSASupported) {
- // We use the same radio button for EdDSA as we use for
- // ECDSA GnuPG does the same and this is really super technical
- // land.
- ui->ecdsaRB->setText(QStringLiteral("ECDSA/EdDSA"));
- }
-
- const bool deVsHack = DeVSCompliance::isActive();
-
- if (deVsHack) {
- // GnuPG Provides no API to query which keys are compliant for
- // a mode. If we request a different one it will error out so
- // we have to remove the options.
- //
- // Does anyone want to use NIST anyway?
- int i;
- while ((i = ui->ecdsaKeyCurvesCB->findText(QStringLiteral("NIST"), Qt::MatchStartsWith)) != -1
- || (i = ui->ecdsaKeyCurvesCB->findText(QStringLiteral("25519"), Qt::MatchEndsWith)) != -1) {
- ui->ecdsaKeyCurvesCB->removeItem(i);
- }
- while ((i = ui->ecdhKeyCurvesCB->findText(QStringLiteral("NIST"), Qt::MatchStartsWith)) != -1
- || (i = ui->ecdhKeyCurvesCB->findText(QStringLiteral("25519"), Qt::MatchEndsWith)) != -1) {
- ui->ecdhKeyCurvesCB->removeItem(i);
- }
- }
- ui->certificationCB->setVisible(protocol == OpenPGP); // gpgsm limitation?
- ui->authenticationCB->setVisible(protocol == OpenPGP);
-
if (keyTypeImmutable) {
- ui->rsaRB->setEnabled(false);
- ui->rsaSubCB->setEnabled(false);
- ui->dsaRB->setEnabled(false);
- ui->elgCB->setEnabled(false);
- ui->ecdsaRB->setEnabled(false);
- ui->ecdhCB->setEnabled(false);
-
// force usage if key type is forced
- ui->certificationCB->setEnabled(false);
ui->signingCB->setEnabled(false);
ui->encryptionCB->setEnabled(false);
- ui->authenticationCB->setEnabled(false);
} else {
- ui->rsaRB->setEnabled(true);
- ui->rsaSubCB->setEnabled(protocol == OpenPGP);
- ui->dsaRB->setEnabled(protocol == OpenPGP && !deVsHack);
- ui->elgCB->setEnabled(protocol == OpenPGP && !deVsHack);
- ui->ecdsaRB->setEnabled(protocol == OpenPGP);
- ui->ecdhCB->setEnabled(protocol == OpenPGP);
-
- if (protocol == OpenPGP) {
- // OpenPGP keys must have certify capability
- ui->certificationCB->setEnabled(false);
- }
- if (protocol == CMS) {
- ui->encryptionCB->setEnabled(true);
- ui->rsaKeyStrengthSubCB->setEnabled(false);
- }
+ ui->encryptionCB->setEnabled(true);
}
- if (protocol == OpenPGP) {
- // OpenPGP keys must have certify capability
- ui->certificationCB->setChecked(true);
- }
- if (protocol == CMS) {
- ui->rsaSubCB->setChecked(false);
- }
-
- ui->expiryDE->setVisible(protocol == OpenPGP);
- ui->expiryCB->setVisible(protocol == OpenPGP);
-
- slotKeyMaterialSelectionChanged();
}
void AdvancedSettingsDialog::setInitialFocus()
{
- // first try the key type radio buttons
- if (focusFirstCheckedButton({ui->rsaRB, ui->dsaRB, ui->ecdsaRB})) {
- return;
- }
// then try the usage check boxes and the expiration check box
- if (focusFirstEnabledButton({ui->signingCB, ui->certificationCB, ui->encryptionCB, ui->authenticationCB, ui->expiryCB})) {
+ if (focusFirstEnabledButton({ui->signingCB, ui->encryptionCB})) {
return;
}
// finally, focus the OK button
ui->buttonBox->button(QDialogButtonBox::Ok)->setFocus();
}
void AdvancedSettingsDialog::accept()
{
- if (!Kleo::isValidExpirationDate(expiryDate())) {
- KMessageBox::error(this, i18nc("@info", "Error: %1", Kleo::validityPeriodHint()));
- return;
- }
-
QDialog::accept();
}
void AdvancedSettingsDialog::showEvent(QShowEvent *event)
{
if (isFirstShowEvent) {
setInitialFocus();
isFirstShowEvent = false;
}
QDialog::showEvent(event);
}
#include "moc_advancedsettingsdialog_p.cpp"
diff --git a/src/newcertificatewizard/advancedsettingsdialog_p.h b/src/newcertificatewizard/advancedsettingsdialog_p.h
index 4bfa95e29..7d7f106f4 100644
--- a/src/newcertificatewizard/advancedsettingsdialog_p.h
+++ b/src/newcertificatewizard/advancedsettingsdialog_p.h
@@ -1,129 +1,84 @@
/* -*- mode: c++; c-basic-offset:4 -*-
newcertificatewizard/advancedsettingsdialog_p.h
This file is part of Kleopatra, the KDE keymanager
SPDX-FileCopyrightText: 2008 Klarälvdalens Datakonsult AB
SPDX-FileCopyrightText: 2016, 2017 Bundesamt für Sicherheit in der Informationstechnik
SPDX-FileContributor: Intevation GmbH
SPDX-FileCopyrightText: 2022 g10 Code GmbH
SPDX-FileContributor: Ingo Klöcker <dev@ingo-kloecker.de>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#pragma once
#include "utils/metatypes_for_gpgmepp_key.h"
#include <QDialog>
#include <gpgme++/key.h>
#include <memory>
class AdvancedSettingsDialog : public QDialog
{
Q_OBJECT
- Q_PROPERTY(QStringList additionalUserIDs READ additionalUserIDs WRITE setAdditionalUserIDs)
Q_PROPERTY(QStringList additionalEMailAddresses READ additionalEMailAddresses WRITE setAdditionalEMailAddresses)
Q_PROPERTY(QStringList dnsNames READ dnsNames WRITE setDnsNames)
Q_PROPERTY(QStringList uris READ uris WRITE setUris)
Q_PROPERTY(uint keyStrength READ keyStrength WRITE setKeyStrength)
- Q_PROPERTY(GpgME::Subkey::PubkeyAlgo keyType READ keyType WRITE setKeyType)
- Q_PROPERTY(QString keyCurve READ keyCurve WRITE setKeyCurve)
- Q_PROPERTY(uint subkeyStrength READ subkeyStrength WRITE setSubkeyStrength)
- Q_PROPERTY(QString subkeyCurve READ subkeyCurve WRITE setSubkeyCurve)
- Q_PROPERTY(GpgME::Subkey::PubkeyAlgo subkeyType READ subkeyType WRITE setSubkeyType)
+ Q_PROPERTY(GpgME::Subkey::PubkeyAlgo keyType READ keyType)
Q_PROPERTY(bool signingAllowed READ signingAllowed WRITE setSigningAllowed)
Q_PROPERTY(bool encryptionAllowed READ encryptionAllowed WRITE setEncryptionAllowed)
- Q_PROPERTY(bool certificationAllowed READ certificationAllowed WRITE setCertificationAllowed)
- Q_PROPERTY(bool authenticationAllowed READ authenticationAllowed WRITE setAuthenticationAllowed)
- Q_PROPERTY(QDate expiryDate READ expiryDate WRITE setExpiryDate)
public:
explicit AdvancedSettingsDialog(QWidget *parent = nullptr);
~AdvancedSettingsDialog() override;
- bool unlimitedValidityIsAllowed() const;
-
- void setProtocol(GpgME::Protocol proto);
-
- void setAdditionalUserIDs(const QStringList &items);
- QStringList additionalUserIDs() const;
-
void setAdditionalEMailAddresses(const QStringList &items);
QStringList additionalEMailAddresses() const;
void setDnsNames(const QStringList &items);
QStringList dnsNames() const;
void setUris(const QStringList &items);
QStringList uris() const;
void setKeyStrength(unsigned int strength);
unsigned int keyStrength() const;
- void setKeyType(GpgME::Subkey::PubkeyAlgo algo);
GpgME::Subkey::PubkeyAlgo keyType() const;
- void setKeyCurve(const QString &curve);
- QString keyCurve() const;
-
- void setSubkeyType(GpgME::Subkey::PubkeyAlgo algo);
- GpgME::Subkey::PubkeyAlgo subkeyType() const;
-
- void setSubkeyCurve(const QString &curve);
- QString subkeyCurve() const;
-
- void setSubkeyStrength(unsigned int strength);
- unsigned int subkeyStrength() const;
-
void setSigningAllowed(bool on);
bool signingAllowed() const;
void setEncryptionAllowed(bool on);
bool encryptionAllowed() const;
- void setCertificationAllowed(bool on);
- bool certificationAllowed() const;
-
- void setAuthenticationAllowed(bool on);
- bool authenticationAllowed() const;
-
- QDate forceDateIntoAllowedRange(QDate date) const;
-
- void setExpiryDate(QDate date);
- QDate expiryDate() const;
-
Q_SIGNALS:
void changed();
private Q_SLOTS:
- void slotKeyMaterialSelectionChanged();
void slotSigningAllowedToggled(bool on);
void slotEncryptionAllowedToggled(bool on);
private:
void fillKeySizeComboBoxen();
void loadDefaultKeyType();
- void loadDefaultExpiration();
void loadDefaultGnuPGKeyType();
void loadDefaults();
void updateWidgetVisibility();
void setInitialFocus();
protected:
void accept() override;
void showEvent(QShowEvent *event) override;
private:
struct UI;
std::unique_ptr<UI> ui;
- GpgME::Protocol protocol = GpgME::UnknownProtocol;
- unsigned int pgpDefaultAlgorithm = GpgME::Subkey::AlgoELG_E;
unsigned int cmsDefaultAlgorithm = GpgME::Subkey::AlgoRSA;
bool keyTypeImmutable = false;
- bool mECCSupported;
- bool mEdDSASupported;
bool isFirstShowEvent = true;
};
diff --git a/src/newcertificatewizard/enterdetailspage.cpp b/src/newcertificatewizard/enterdetailspage.cpp
index e31cfcfc2..ea2c43549 100644
--- a/src/newcertificatewizard/enterdetailspage.cpp
+++ b/src/newcertificatewizard/enterdetailspage.cpp
@@ -1,538 +1,529 @@
/* -*- mode: c++; c-basic-offset:4 -*-
newcertificatewizard/enterdetailspage.cpp
This file is part of Kleopatra, the KDE keymanager
SPDX-FileCopyrightText: 2008 Klarälvdalens Datakonsult AB
SPDX-FileCopyrightText: 2016, 2017 Bundesamt für Sicherheit in der Informationstechnik
SPDX-FileContributor: Intevation GmbH
SPDX-FileCopyrightText: 2022 g10 Code GmbH
SPDX-FileContributor: Ingo Klöcker <dev@ingo-kloecker.de>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include <config-kleopatra.h>
#include "enterdetailspage_p.h"
#include "advancedsettingsdialog_p.h"
#include "utils/scrollarea.h"
#include "utils/userinfo.h"
#include "utils/validation.h"
#include <settings.h>
#include <Libkleo/Compat>
#include <Libkleo/Dn>
#include <Libkleo/Formatting>
#include <Libkleo/OidMap>
#include <Libkleo/Stl_Util>
#include <KLocalizedString>
#include <QGpgME/CryptoConfig>
#include <QGpgME/Protocol>
#include <QCheckBox>
#include <QHBoxLayout>
#include <QLabel>
#include <QLineEdit>
#include <QMetaProperty>
#include <QPushButton>
#include <QSpacerItem>
#include <QVBoxLayout>
#include <QValidator>
#include "kleopatra_debug.h"
using namespace Kleo;
using namespace Kleo::NewCertificateUi;
using namespace GpgME;
static void set_tab_order(const QList<QWidget *> &wl)
{
kdtools::for_each_adjacent_pair(wl.begin(), wl.end(), [](QWidget *w1, QWidget *w2) {
QWidget::setTabOrder(w1, w2);
});
}
static QString pgpLabel(const QString &attr)
{
if (attr == QLatin1StringView("NAME")) {
return i18n("Name");
}
if (attr == QLatin1StringView("EMAIL")) {
return i18n("EMail");
}
return QString();
}
static QString attributeLabel(const QString &attr, bool pgp)
{
if (attr.isEmpty()) {
return QString();
}
const QString label = pgp ? pgpLabel(attr) : Kleo::DN::attributeNameToLabel(attr);
if (!label.isEmpty())
if (pgp) {
return label;
} else
return i18nc("Format string for the labels in the \"Your Personal Data\" page", "%1 (%2)", label, attr);
else {
return attr;
}
}
static QString attributeFromKey(QString key)
{
return key.remove(QLatin1Char('!'));
}
struct EnterDetailsPage::UI {
QGridLayout *gridLayout = nullptr;
QLabel *nameLB = nullptr;
QLineEdit *nameLE = nullptr;
QLabel *nameRequiredLB = nullptr;
QLabel *emailLB = nullptr;
QLineEdit *emailLE = nullptr;
QLabel *emailRequiredLB = nullptr;
QCheckBox *withPassCB = nullptr;
QLineEdit *resultLE = nullptr;
QLabel *errorLB = nullptr;
QPushButton *advancedPB = nullptr;
UI(QWizardPage *parent)
{
parent->setTitle(i18nc("@title", "Enter Details"));
auto mainLayout = new QVBoxLayout{parent};
const auto margins = mainLayout->contentsMargins();
mainLayout->setContentsMargins(margins.left(), 0, margins.right(), 0);
auto scrollArea = new ScrollArea{parent};
scrollArea->setFocusPolicy(Qt::NoFocus);
scrollArea->setFrameStyle(QFrame::NoFrame);
scrollArea->setBackgroundRole(parent->backgroundRole());
scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
scrollArea->setSizeAdjustPolicy(QScrollArea::AdjustToContents);
auto scrollAreaLayout = qobject_cast<QBoxLayout *>(scrollArea->widget()->layout());
scrollAreaLayout->setContentsMargins(0, margins.top(), 0, margins.bottom());
gridLayout = new QGridLayout;
int row = 0;
nameLB = new QLabel{i18n("Real name:"), parent};
nameLE = new QLineEdit{parent};
nameRequiredLB = new QLabel{i18n("(required)"), parent};
gridLayout->addWidget(nameLB, row, 0, 1, 1);
gridLayout->addWidget(nameLE, row, 1, 1, 1);
gridLayout->addWidget(nameRequiredLB, row, 2, 1, 1);
row++;
emailLB = new QLabel{i18n("EMail address:"), parent};
emailLE = new QLineEdit{parent};
emailRequiredLB = new QLabel{i18n("(required)"), parent};
gridLayout->addWidget(emailLB, row, 0, 1, 1);
gridLayout->addWidget(emailLE, row, 1, 1, 1);
gridLayout->addWidget(emailRequiredLB, row, 2, 1, 1);
row++;
withPassCB = new QCheckBox{i18n("Protect the generated key with a passphrase."), parent};
withPassCB->setToolTip(i18n("Encrypts the secret key with an unrecoverable passphrase. You will be asked for the passphrase during key generation."));
gridLayout->addWidget(withPassCB, row, 1, 1, 2);
scrollAreaLayout->addLayout(gridLayout);
auto verticalSpacer = new QSpacerItem{20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding};
scrollAreaLayout->addItem(verticalSpacer);
resultLE = new QLineEdit{parent};
resultLE->setFrame(false);
resultLE->setAlignment(Qt::AlignCenter);
resultLE->setReadOnly(true);
scrollAreaLayout->addWidget(resultLE);
auto horizontalLayout = new QHBoxLayout;
errorLB = new QLabel{parent};
QSizePolicy sizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);
sizePolicy.setHorizontalStretch(0);
sizePolicy.setVerticalStretch(0);
sizePolicy.setHeightForWidth(errorLB->sizePolicy().hasHeightForWidth());
errorLB->setSizePolicy(sizePolicy);
QPalette palette;
QBrush brush(QColor(255, 0, 0, 255));
brush.setStyle(Qt::SolidPattern);
palette.setBrush(QPalette::Active, QPalette::WindowText, brush);
palette.setBrush(QPalette::Inactive, QPalette::WindowText, brush);
QBrush brush1(QColor(114, 114, 114, 255));
brush1.setStyle(Qt::SolidPattern);
palette.setBrush(QPalette::Disabled, QPalette::WindowText, brush1);
errorLB->setPalette(palette);
errorLB->setTextFormat(Qt::RichText);
horizontalLayout->addWidget(errorLB);
advancedPB = new QPushButton{i18n("Advanced Settings..."), parent};
advancedPB->setAutoDefault(false);
horizontalLayout->addWidget(advancedPB);
scrollAreaLayout->addLayout(horizontalLayout);
mainLayout->addWidget(scrollArea);
}
};
EnterDetailsPage::EnterDetailsPage(QWidget *p)
: WizardPage{p}
, ui{new UI{this}}
, dialog{new AdvancedSettingsDialog{this}}
{
setObjectName(QLatin1StringView("Kleo__NewCertificateUi__EnterDetailsPage"));
Settings settings;
if (settings.hideAdvanced()) {
setSubTitle(i18n("Please enter your personal details below."));
} else {
setSubTitle(i18n("Please enter your personal details below. If you want more control over the parameters, click on the Advanced Settings button."));
}
ui->advancedPB->setVisible(!settings.hideAdvanced());
ui->resultLE->setFocusPolicy(Qt::NoFocus);
// set errorLB to have a fixed height of two lines:
ui->errorLB->setText(QStringLiteral("2<br>1"));
ui->errorLB->setFixedHeight(ui->errorLB->minimumSizeHint().height());
ui->errorLB->clear();
connect(ui->advancedPB, &QPushButton::clicked, this, &EnterDetailsPage::slotAdvancedSettingsClicked);
connect(ui->resultLE, &QLineEdit::textChanged, this, &QWizardPage::completeChanged);
// The email doesn't necessarily show up in ui->resultLE:
connect(ui->emailLE, &QLineEdit::textChanged, this, &QWizardPage::completeChanged);
registerDialogPropertiesAsFields();
registerField(QStringLiteral("dn"), ui->resultLE);
registerField(QStringLiteral("name"), ui->nameLE);
registerField(QStringLiteral("email"), ui->emailLE);
registerField(QStringLiteral("protectedKey"), ui->withPassCB);
setCommitPage(true);
setButtonText(QWizard::CommitButton, i18nc("@action", "Create"));
const auto conf = QGpgME::cryptoConfig();
if (!conf) {
qCWarning(KLEOPATRA_LOG) << "Failed to obtain cryptoConfig.";
return;
}
const auto entry = getCryptoConfigEntry(conf, "gpg-agent", "enforce-passphrase-constraints");
if (entry && entry->boolValue()) {
qCDebug(KLEOPATRA_LOG) << "Disabling passphrace cb because of agent config.";
ui->withPassCB->setEnabled(false);
ui->withPassCB->setChecked(true);
} else {
const KConfigGroup config(KSharedConfig::openConfig(), QStringLiteral("CertificateCreationWizard"));
ui->withPassCB->setChecked(config.readEntry("WithPassphrase", false));
ui->withPassCB->setEnabled(!config.isEntryImmutable("WithPassphrase"));
}
}
EnterDetailsPage::~EnterDetailsPage() = default;
void EnterDetailsPage::initializePage()
{
updateForm();
- ui->withPassCB->setVisible(pgp());
- dialog->setProtocol(pgp() ? OpenPGP : CMS);
+ ui->withPassCB->setVisible(false);
}
void EnterDetailsPage::cleanupPage()
{
saveValues();
}
void EnterDetailsPage::registerDialogPropertiesAsFields()
{
const QMetaObject *const mo = dialog->metaObject();
for (unsigned int i = mo->propertyOffset(), end = i + mo->propertyCount(); i != end; ++i) {
const QMetaProperty mp = mo->property(i);
if (mp.isValid()) {
registerField(QLatin1StringView(mp.name()), dialog, mp.name(), SIGNAL(accepted()));
}
}
}
void EnterDetailsPage::saveValues()
{
for (const Line &line : std::as_const(lineList)) {
savedValues[attributeFromKey(line.attr)] = line.edit->text().trimmed();
}
}
void EnterDetailsPage::clearForm()
{
qDeleteAll(dynamicWidgets);
dynamicWidgets.clear();
lineList.clear();
ui->nameLE->hide();
ui->nameLE->clear();
ui->nameLB->hide();
ui->nameRequiredLB->hide();
ui->emailLE->hide();
ui->emailLE->clear();
ui->emailLB->hide();
ui->emailRequiredLB->hide();
}
static int row_index_of(QWidget *w, QGridLayout *l)
{
const int idx = l->indexOf(w);
int r, c, rs, cs;
l->getItemPosition(idx, &r, &c, &rs, &cs);
return r;
}
static QLineEdit *
adjust_row(QGridLayout *l, int row, const QString &label, const QString &preset, const std::shared_ptr<QValidator> &validator, bool readonly, bool required)
{
Q_ASSERT(l);
Q_ASSERT(row >= 0);
Q_ASSERT(row < l->rowCount());
auto lb = qobject_cast<QLabel *>(l->itemAtPosition(row, 0)->widget());
Q_ASSERT(lb);
auto le = qobject_cast<QLineEdit *>(l->itemAtPosition(row, 1)->widget());
Q_ASSERT(le);
lb->setBuddy(le); // For better accessibility
auto reqLB = qobject_cast<QLabel *>(l->itemAtPosition(row, 2)->widget());
Q_ASSERT(reqLB);
lb->setText(i18nc("interpunctation for labels", "%1:", label));
le->setText(preset);
reqLB->setText(required ? i18n("(required)") : i18n("(optional)"));
if (validator) {
le->setValidator(validator.get());
}
le->setReadOnly(readonly && le->hasAcceptableInput());
lb->show();
le->show();
reqLB->show();
return le;
}
static int add_row(QGridLayout *l, QList<QWidget *> *wl)
{
Q_ASSERT(l);
Q_ASSERT(wl);
const int row = l->rowCount();
QWidget *w1, *w2, *w3;
l->addWidget(w1 = new QLabel(l->parentWidget()), row, 0);
l->addWidget(w2 = new QLineEdit(l->parentWidget()), row, 1);
l->addWidget(w3 = new QLabel(l->parentWidget()), row, 2);
wl->push_back(w1);
wl->push_back(w2);
wl->push_back(w3);
return row;
}
void EnterDetailsPage::updateForm()
{
clearForm();
const auto settings = Kleo::Settings{};
const KConfigGroup config(KSharedConfig::openConfig(), QStringLiteral("CertificateCreationWizard"));
- QStringList attrOrder = config.readEntry(pgp() ? "OpenPGPAttributeOrder" : "DNAttributeOrder", QStringList());
+ QStringList attrOrder = config.readEntry("DNAttributeOrder", QStringList());
if (attrOrder.empty()) {
- if (pgp()) {
- attrOrder << QStringLiteral("NAME") << QStringLiteral("EMAIL");
- } else {
- attrOrder << QStringLiteral("CN!") << QStringLiteral("L") << QStringLiteral("OU") << QStringLiteral("O") << QStringLiteral("C")
- << QStringLiteral("EMAIL!");
- }
+ attrOrder << QStringLiteral("CN!") << QStringLiteral("L") << QStringLiteral("OU") << QStringLiteral("O") << QStringLiteral("C")
+ << QStringLiteral("EMAIL!");
}
QList<QWidget *> widgets;
widgets.push_back(ui->nameLE);
widgets.push_back(ui->emailLE);
QMap<int, Line> lines;
for (const QString &rawKey : std::as_const(attrOrder)) {
const QString key = rawKey.trimmed().toUpper();
const QString attr = attributeFromKey(key);
if (attr.isEmpty()) {
continue;
}
const QString preset = savedValues.value(attr, config.readEntry(attr, QString()));
const bool required = key.endsWith(QLatin1Char('!'));
const bool readonly = config.isEntryImmutable(attr);
- const QString label = config.readEntry(attr + QLatin1StringView("_label"), attributeLabel(attr, pgp()));
+ const QString label = config.readEntry(attr + QLatin1StringView("_label"), attributeLabel(attr, false));
const QString regex = config.readEntry(attr + QLatin1StringView("_regex"));
const QString placeholder = config.readEntry(attr + QLatin1StringView{"_placeholder"});
int row;
bool known = true;
std::shared_ptr<QValidator> validator;
if (attr == QLatin1StringView("EMAIL")) {
row = row_index_of(ui->emailLE, ui->gridLayout);
validator = regex.isEmpty() ? Validation::email() : Validation::email(regex);
} else if (attr == QLatin1StringView("NAME") || attr == QLatin1String("CN")) {
- if ((pgp() && attr == QLatin1StringView("CN")) || (!pgp() && attr == QLatin1String("NAME"))) {
+ if (attr == QLatin1String("NAME")) {
continue;
}
- if (pgp()) {
- validator = regex.isEmpty() ? Validation::pgpName() : Validation::pgpName(regex);
- }
row = row_index_of(ui->nameLE, ui->gridLayout);
} else {
known = false;
row = add_row(ui->gridLayout, &dynamicWidgets);
}
if (!validator && !regex.isEmpty()) {
validator = std::make_shared<QRegularExpressionValidator>(QRegularExpression{regex});
}
QLineEdit *le = adjust_row(ui->gridLayout, row, label, preset, validator, readonly, required);
le->setPlaceholderText(placeholder);
const Line line = {key, label, regex, le, validator};
lines[row] = line;
if (!known) {
widgets.push_back(le);
}
// don't connect twice:
disconnect(le, &QLineEdit::textChanged, this, &EnterDetailsPage::slotUpdateResultLabel);
connect(le, &QLineEdit::textChanged, this, &EnterDetailsPage::slotUpdateResultLabel);
}
// create lineList in visual order, so requirementsAreMet()
// complains from top to bottom:
lineList.reserve(lines.count());
std::copy(lines.cbegin(), lines.cend(), std::back_inserter(lineList));
widgets.push_back(ui->withPassCB);
widgets.push_back(ui->advancedPB);
- const bool prefillName = (pgp() && settings.prefillName()) || (!pgp() && settings.prefillCN());
- if (ui->nameLE->text().isEmpty() && prefillName) {
+ if (ui->nameLE->text().isEmpty() && settings.prefillCN()) {
ui->nameLE->setText(userFullName());
}
if (ui->emailLE->text().isEmpty() && settings.prefillEmail()) {
ui->emailLE->setText(userEmailAddress());
}
slotUpdateResultLabel();
set_tab_order(widgets);
}
QString EnterDetailsPage::cmsDN() const
{
DN dn;
for (QList<Line>::const_iterator it = lineList.begin(), end = lineList.end(); it != end; ++it) {
const QString text = it->edit->text().trimmed();
if (text.isEmpty()) {
continue;
}
QString attr = attributeFromKey(it->attr);
if (attr == QLatin1StringView("EMAIL")) {
continue;
}
if (const char *const oid = oidForAttributeName(attr)) {
attr = QString::fromUtf8(oid);
}
dn.append(DN::Attribute(attr, text));
}
return dn.dn();
}
QString EnterDetailsPage::pgpUserID() const
{
return Formatting::prettyNameAndEMail(OpenPGP, QString(), ui->nameLE->text().trimmed(), ui->emailLE->text().trimmed(), QString());
}
static bool has_intermediate_input(const QLineEdit *le)
{
QString text = le->text();
int pos = le->cursorPosition();
const QValidator *const v = le->validator();
return v && v->validate(text, pos) == QValidator::Intermediate;
}
static bool requirementsAreMet(const QList<EnterDetailsPage::Line> &list, QString &error)
{
bool allEmpty = true;
for (const auto &line : list) {
const QLineEdit *le = line.edit;
if (!le) {
continue;
}
const QString key = line.attr;
qCDebug(KLEOPATRA_LOG) << "requirementsAreMet(): checking" << key << "against" << le->text() << ":";
if (le->text().trimmed().isEmpty()) {
if (key.endsWith(QLatin1Char('!'))) {
if (line.regex.isEmpty()) {
error = xi18nc("@info", "<interface>%1</interface> is required, but empty.", line.label);
} else
error = xi18nc("@info",
"<interface>%1</interface> is required, but empty.<nl/>"
"Local Admin rule: <icode>%2</icode>",
line.label,
line.regex);
return false;
}
} else if (has_intermediate_input(le)) {
if (line.regex.isEmpty()) {
error = xi18nc("@info", "<interface>%1</interface> is incomplete.", line.label);
} else
error = xi18nc("@info",
"<interface>%1</interface> is incomplete.<nl/>"
"Local Admin rule: <icode>%2</icode>",
line.label,
line.regex);
return false;
} else if (!le->hasAcceptableInput()) {
if (line.regex.isEmpty()) {
error = xi18nc("@info", "<interface>%1</interface> is invalid.", line.label);
} else
error = xi18nc("@info",
"<interface>%1</interface> is invalid.<nl/>"
"Local Admin rule: <icode>%2</icode>",
line.label,
line.regex);
return false;
} else {
allEmpty = false;
}
}
// Ensure that at least one value is acceptable
return !allEmpty;
}
bool EnterDetailsPage::isComplete() const
{
QString error;
const bool ok = requirementsAreMet(lineList, error);
ui->errorLB->setText(error);
return ok;
}
void EnterDetailsPage::slotAdvancedSettingsClicked()
{
dialog->exec();
}
void EnterDetailsPage::slotUpdateResultLabel()
{
- ui->resultLE->setText(pgp() ? pgpUserID() : cmsDN());
+ ui->resultLE->setText(cmsDN());
}
#include "moc_enterdetailspage_p.cpp"
diff --git a/src/newcertificatewizard/keycreationpage.cpp b/src/newcertificatewizard/keycreationpage.cpp
index 92697652e..1da1718c2 100644
--- a/src/newcertificatewizard/keycreationpage.cpp
+++ b/src/newcertificatewizard/keycreationpage.cpp
@@ -1,249 +1,175 @@
/* -*- mode: c++; c-basic-offset:4 -*-
newcertificatewizard/keycreationpage.cpp
This file is part of Kleopatra, the KDE keymanager
SPDX-FileCopyrightText: 2008 Klarälvdalens Datakonsult AB
SPDX-FileCopyrightText: 2016, 2017 Bundesamt für Sicherheit in der Informationstechnik
SPDX-FileContributor: Intevation GmbH
SPDX-FileCopyrightText: 2022 g10 Code GmbH
SPDX-FileContributor: Ingo Klöcker <dev@ingo-kloecker.de>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include <config-kleopatra.h>
#include "keycreationpage_p.h"
-#include "keyalgo_p.h"
-
#include "kleopatraapplication.h"
#include "utils/keyparameters.h"
#include <Libkleo/Formatting>
#include <Libkleo/KeyCache>
#include <Libkleo/KeyUsage>
#include <KConfigGroup>
#include <KLocalizedString>
#include <KSharedConfig>
#include <QGpgME/KeyGenerationJob>
#include <QGpgME/Protocol>
#include <QLabel>
#include <QUrl>
#include <QVBoxLayout>
#include <gpgme++/context.h>
#include <gpgme++/keygenerationresult.h>
#include "kleopatra_debug.h"
using namespace Kleo;
using namespace Kleo::NewCertificateUi;
using namespace GpgME;
struct KeyCreationPage::UI {
UI(QWizardPage *parent)
{
parent->setTitle(i18nc("@title", "Creating Key Pair..."));
auto mainLayout = new QVBoxLayout{parent};
auto label = new QLabel{i18n("The process of creating a key requires large amounts of random numbers. This may require several minutes..."), parent};
label->setWordWrap(true);
mainLayout->addWidget(label);
}
};
KeyCreationPage::KeyCreationPage(QWidget *p)
: WizardPage{p}
, ui{new UI{this}}
{
setObjectName(QString::fromUtf8("Kleo__NewCertificateUi__KeyCreationPage"));
}
KeyCreationPage::~KeyCreationPage() = default;
bool KeyCreationPage::isComplete() const
{
return !job;
}
void KeyCreationPage::initializePage()
{
startJob();
}
void KeyCreationPage::startJob()
{
- const auto proto = pgp() ? QGpgME::openpgp() : QGpgME::smime();
- if (!proto) {
- return;
- }
- QGpgME::KeyGenerationJob *const j = proto->keyGenerationJob();
+ auto j = QGpgME::smime()->keyGenerationJob();
if (!j) {
return;
}
- if (!protectedKey() && pgp()) {
- auto ctx = QGpgME::Job::context(j);
- ctx->setPassphraseProvider(&mEmptyPassphraseProvider);
- ctx->setPinentryMode(Context::PinentryLoopback);
- }
connect(j, &QGpgME::KeyGenerationJob::result, this, &KeyCreationPage::slotResult);
if (const Error err = j->start(createGnupgKeyParms()))
setField(QStringLiteral("error"), i18n("Could not start key pair creation: %1", Formatting::errorAsString(err)));
else {
job = j;
}
}
KeyUsage KeyCreationPage::keyUsage() const
{
KeyUsage usage;
if (signingAllowed()) {
usage.setCanSign(true);
}
- if (encryptionAllowed() && !is_ecdh(subkeyType()) && !is_dsa(keyType()) && !is_rsa(subkeyType())) {
- usage.setCanEncrypt(true);
- }
- if (authenticationAllowed()) {
- usage.setCanAuthenticate(true);
- }
- if (!usage.value() && certificationAllowed()) {
- /* Empty usages cause an error so we need to
- * add at least certify if nothing else is selected */
- usage.setCanCertify(true);
- }
- return usage;
-}
-
-KeyUsage KeyCreationPage::subkeyUsage() const
-{
- KeyUsage usage;
- if (encryptionAllowed() && (is_dsa(keyType()) || is_rsa(subkeyType()) || is_ecdh(subkeyType()))) {
- Q_ASSERT(subkeyType());
+ if (encryptionAllowed()) {
usage.setCanEncrypt(true);
}
return usage;
}
QString KeyCreationPage::createGnupgKeyParms() const
{
- KeyParameters keyParameters(pgp() ? KeyParameters::OpenPGP : KeyParameters::CMS);
+ KeyParameters keyParameters(KeyParameters::CMS);
keyParameters.setKeyType(keyType());
- if (is_ecdsa(keyType()) || is_eddsa(keyType())) {
- keyParameters.setKeyCurve(keyCurve());
- } else if (const unsigned int strength = keyStrength()) {
+ if (const unsigned int strength = keyStrength()) {
keyParameters.setKeyLength(strength);
}
keyParameters.setKeyUsage(keyUsage());
- if (subkeyType()) {
- keyParameters.setSubkeyType(subkeyType());
- if (is_ecdh(subkeyType())) {
- keyParameters.setSubkeyCurve(subkeyCurve());
- } else if (const unsigned int strength = subkeyStrength()) {
- keyParameters.setSubkeyLength(strength);
- }
- keyParameters.setSubkeyUsage(subkeyUsage());
+ keyParameters.setDN(dn());
+ keyParameters.setEmail(email());
+ const auto addesses{additionalEMailAddresses()};
+ for (const QString &email : addesses) {
+ keyParameters.addEmail(email);
}
-
- if (pgp()) {
- if (expiryDate().isValid()) {
- keyParameters.setExpirationDate(expiryDate());
- }
- if (!name().isEmpty()) {
- keyParameters.setName(name());
- }
- if (!email().isEmpty()) {
- keyParameters.setEmail(email());
- }
- } else {
- keyParameters.setDN(dn());
- keyParameters.setEmail(email());
- const auto addesses{additionalEMailAddresses()};
- for (const QString &email : addesses) {
- keyParameters.addEmail(email);
- }
- const auto dnsN{dnsNames()};
- for (const QString &dns : dnsN) {
- keyParameters.addDomainName(dns);
- }
- const auto urisList{uris()};
- for (const QString &uri : urisList) {
- keyParameters.addURI(uri);
- }
+ const auto dnsN{dnsNames()};
+ for (const QString &dns : dnsN) {
+ keyParameters.addDomainName(dns);
+ }
+ const auto urisList{uris()};
+ for (const QString &uri : urisList) {
+ keyParameters.addURI(uri);
}
const QString result = keyParameters.toString();
qCDebug(KLEOPATRA_LOG) << '\n' << result;
return result;
}
void KeyCreationPage::slotResult(const GpgME::KeyGenerationResult &result, const QByteArray &request, const QString &auditLog)
{
Q_UNUSED(auditLog)
- if (result.error().code() || (pgp() && !result.fingerprint())) {
+ if (result.error().code()) {
setField(QStringLiteral("error"),
result.error().isCanceled() ? i18n("Operation canceled.") : i18n("Could not create key pair: %1", Formatting::errorAsString(result.error())));
setField(QStringLiteral("url"), QString());
setField(QStringLiteral("result"), QString());
- } else if (pgp()) {
- setField(QStringLiteral("error"), QString());
- setField(QStringLiteral("url"), QString());
- setField(QStringLiteral("result"),
- i18n("Key pair created successfully.\n"
- "Fingerprint: %1",
- Formatting::prettyID(result.fingerprint())));
} else {
QFile file(tmpDir().absoluteFilePath(QStringLiteral("request.p10")));
if (!file.open(QIODevice::WriteOnly)) {
setField(QStringLiteral("error"), i18n("Could not write output file %1: %2", file.fileName(), file.errorString()));
setField(QStringLiteral("url"), QString());
setField(QStringLiteral("result"), QString());
} else {
file.write(request);
setField(QStringLiteral("error"), QString());
setField(QStringLiteral("url"), QUrl::fromLocalFile(file.fileName()).toString());
setField(QStringLiteral("result"), i18n("Key pair created successfully."));
}
}
- // Ensure that we have the key in the keycache
- if (pgp() && !result.error().code() && result.fingerprint()) {
- auto ctx = Context::createForProtocol(OpenPGP);
- if (ctx) {
- // Check is pretty useless something very buggy in that case.
- Error e;
- const auto key = ctx->key(result.fingerprint(), e, true);
- if (!key.isNull()) {
- KeyCache::mutableInstance()->insert(key);
- } else {
- qCDebug(KLEOPATRA_LOG) << "Failed to find newly generated key.";
- }
- delete ctx;
- }
- }
+
setField(QStringLiteral("fingerprint"), result.fingerprint() ? QString::fromLatin1(result.fingerprint()) : QString());
job = nullptr;
Q_EMIT completeChanged();
const KConfigGroup config(KSharedConfig::openConfig(), QStringLiteral("CertificateCreationWizard"));
if (config.readEntry("SkipResultPage", false)) {
if (result.fingerprint()) {
KleopatraApplication::instance()->slotActivateRequested(QStringList() << QStringLiteral("kleopatra") << QStringLiteral("--query")
<< QLatin1StringView(result.fingerprint()),
QString());
QMetaObject::invokeMethod(wizard(), "close", Qt::QueuedConnection);
} else {
QMetaObject::invokeMethod(wizard(), "next", Qt::QueuedConnection);
}
} else {
QMetaObject::invokeMethod(wizard(), "next", Qt::QueuedConnection);
}
}
#include "moc_keycreationpage_p.cpp"
diff --git a/src/newcertificatewizard/keycreationpage_p.h b/src/newcertificatewizard/keycreationpage_p.h
index 41b086ab1..db69bd1b9 100644
--- a/src/newcertificatewizard/keycreationpage_p.h
+++ b/src/newcertificatewizard/keycreationpage_p.h
@@ -1,59 +1,58 @@
/* -*- mode: c++; c-basic-offset:4 -*-
newcertificatewizard/keycreationpage_p.h
This file is part of Kleopatra, the KDE keymanager
SPDX-FileCopyrightText: 2008 Klarälvdalens Datakonsult AB
SPDX-FileCopyrightText: 2016, 2017 Bundesamt für Sicherheit in der Informationstechnik
SPDX-FileContributor: Intevation GmbH
SPDX-FileCopyrightText: 2022 g10 Code GmbH
SPDX-FileContributor: Ingo Klöcker <dev@ingo-kloecker.de>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#pragma once
#include "wizardpage_p.h"
#include "utils/emptypassphraseprovider.h"
namespace GpgME
{
class KeyGenerationResult;
}
namespace QGpgME
{
class KeyGenerationJob;
}
namespace Kleo
{
class KeyUsage;
}
class KeyCreationPage : public Kleo::NewCertificateUi::WizardPage
{
Q_OBJECT
public:
explicit KeyCreationPage(QWidget *p = nullptr);
~KeyCreationPage() override;
bool isComplete() const override;
void initializePage() override;
private:
void startJob();
Kleo::KeyUsage keyUsage() const;
- Kleo::KeyUsage subkeyUsage() const;
QString createGnupgKeyParms() const;
private Q_SLOTS:
void slotResult(const GpgME::KeyGenerationResult &result, const QByteArray &request, const QString &auditLog);
private:
struct UI;
std::unique_ptr<UI> ui;
EmptyPassphraseProvider mEmptyPassphraseProvider;
QPointer<QGpgME::KeyGenerationJob> job;
};
diff --git a/src/newcertificatewizard/resultpage.cpp b/src/newcertificatewizard/resultpage.cpp
index 5f8abd98d..ae773d3b6 100644
--- a/src/newcertificatewizard/resultpage.cpp
+++ b/src/newcertificatewizard/resultpage.cpp
@@ -1,369 +1,286 @@
/* -*- mode: c++; c-basic-offset:4 -*-
newcertificatewizard/resultpage.cpp
This file is part of Kleopatra, the KDE keymanager
SPDX-FileCopyrightText: 2008 Klarälvdalens Datakonsult AB
SPDX-FileCopyrightText: 2016, 2017 Bundesamt für Sicherheit in der Informationstechnik
SPDX-FileContributor: Intevation GmbH
SPDX-FileCopyrightText: 2022 g10 Code GmbH
SPDX-FileContributor: Ingo Klöcker <dev@ingo-kloecker.de>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include <config-kleopatra.h>
#include "resultpage_p.h"
#include "commands/exportcertificatecommand.h"
#include "commands/exportopenpgpcertstoservercommand.h"
#include "commands/exportsecretkeycommand.h"
#include "utils/dragqueen.h"
#include "utils/email.h"
#include "utils/filedialog.h"
#include "utils/scrollarea.h"
#include <Libkleo/KeyCache>
#include <KConfigGroup>
#include <KLocalizedString>
#include <KMessageBox>
#include <KSharedConfig>
#include <QGroupBox>
#include <QHBoxLayout>
#include <QLineEdit>
#include <QPushButton>
#include <QTextBrowser>
#include <QVBoxLayout>
#include <gpgme++/key.h>
#include "kleopatra_debug.h"
using namespace Kleo;
using namespace Kleo::Commands;
using namespace Kleo::NewCertificateUi;
using namespace GpgME;
struct ResultPage::UI {
QTextBrowser *resultTB = nullptr;
QTextBrowser *errorTB = nullptr;
DragQueen *dragQueen = nullptr;
QPushButton *restartWizardPB = nullptr;
QGroupBox *nextStepsGB = nullptr;
QPushButton *saveRequestToFilePB = nullptr;
QPushButton *sendRequestByEMailPB = nullptr;
- QPushButton *makeBackupPB = nullptr;
- QPushButton *sendCertificateByEMailPB = nullptr;
- QPushButton *uploadToKeyserverPB = nullptr;
- QPushButton *createRevocationRequestPB = nullptr;
QPushButton *createSigningCertificatePB = nullptr;
QPushButton *createEncryptionCertificatePB = nullptr;
UI(QWizardPage *parent)
{
auto mainLayout = new QVBoxLayout{parent};
const auto margins = mainLayout->contentsMargins();
mainLayout->setContentsMargins(margins.left(), 0, margins.right(), 0);
auto scrollArea = new ScrollArea{parent};
scrollArea->setFocusPolicy(Qt::NoFocus);
scrollArea->setFrameStyle(QFrame::NoFrame);
scrollArea->setBackgroundRole(parent->backgroundRole());
scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
scrollArea->setSizeAdjustPolicy(QScrollArea::AdjustToContents);
auto scrollAreaLayout = qobject_cast<QBoxLayout *>(scrollArea->widget()->layout());
scrollAreaLayout->setContentsMargins(0, margins.top(), 0, margins.bottom());
auto resultGB = new QGroupBox{i18nc("@title:group", "Result"), parent};
auto resultGBLayout = new QHBoxLayout{resultGB};
resultTB = new QTextBrowser{resultGB};
resultGBLayout->addWidget(resultTB);
errorTB = new QTextBrowser{resultGB};
resultGBLayout->addWidget(errorTB);
dragQueen = new Kleo::DragQueen{resultGB};
dragQueen->setToolTip(i18n("Drag this icon to your mail application's composer to attach the request to a mail."));
dragQueen->setAlignment(Qt::AlignCenter);
resultGBLayout->addWidget(dragQueen);
scrollAreaLayout->addWidget(resultGB);
restartWizardPB = new QPushButton{i18n("Restart This Wizard (Keeps Your Parameters)"), parent};
scrollAreaLayout->addWidget(restartWizardPB);
nextStepsGB = new QGroupBox{i18nc("@title:group", "Next Steps"), parent};
auto nextStepsGBLayout = new QVBoxLayout{nextStepsGB};
saveRequestToFilePB = new QPushButton{i18n("Save Certificate Request To File..."), nextStepsGB};
nextStepsGBLayout->addWidget(saveRequestToFilePB);
sendRequestByEMailPB = new QPushButton{i18n("Send Certificate Request By EMail..."), nextStepsGB};
nextStepsGBLayout->addWidget(sendRequestByEMailPB);
- makeBackupPB = new QPushButton{i18n("Make a Backup Of Your Key Pair..."), nextStepsGB};
- nextStepsGBLayout->addWidget(makeBackupPB);
-
- sendCertificateByEMailPB = new QPushButton{i18n("Send Public Key By EMail..."), nextStepsGB};
- nextStepsGBLayout->addWidget(sendCertificateByEMailPB);
-
- uploadToKeyserverPB = new QPushButton{i18n("Upload Public Key To Directory Service..."), nextStepsGB};
- nextStepsGBLayout->addWidget(uploadToKeyserverPB);
-
- createRevocationRequestPB = new QPushButton{i18n("Create Revocation Request..."), nextStepsGB};
- nextStepsGBLayout->addWidget(createRevocationRequestPB);
-
createSigningCertificatePB = new QPushButton{i18n("Create Signing Certificate With Same Parameters"), nextStepsGB};
nextStepsGBLayout->addWidget(createSigningCertificatePB);
createEncryptionCertificatePB = new QPushButton{i18n("Create Encryption Certificate With Same Parameters"), nextStepsGB};
nextStepsGBLayout->addWidget(createEncryptionCertificatePB);
scrollAreaLayout->addWidget(nextStepsGB);
mainLayout->addWidget(scrollArea);
}
};
ResultPage::ResultPage(QWidget *p)
: WizardPage{p}
, ui{new UI{this}}
, initialized{false}
, successfullyCreatedSigningCertificate{false}
, successfullyCreatedEncryptionCertificate{false}
{
setObjectName(QString::fromUtf8("Kleo__NewCertificateUi__ResultPage"));
connect(ui->saveRequestToFilePB, &QPushButton::clicked, this, &ResultPage::slotSaveRequestToFile);
connect(ui->sendRequestByEMailPB, &QPushButton::clicked, this, &ResultPage::slotSendRequestByEMail);
- connect(ui->sendCertificateByEMailPB, &QPushButton::clicked, this, &ResultPage::slotSendCertificateByEMail);
- connect(ui->uploadToKeyserverPB, &QPushButton::clicked, this, &ResultPage::slotUploadCertificateToDirectoryServer);
- connect(ui->makeBackupPB, &QPushButton::clicked, this, &ResultPage::slotBackupCertificate);
- connect(ui->createRevocationRequestPB, &QPushButton::clicked, this, &ResultPage::slotCreateRevocationRequest);
connect(ui->createSigningCertificatePB, &QPushButton::clicked, this, &ResultPage::slotCreateSigningCertificate);
connect(ui->createEncryptionCertificatePB, &QPushButton::clicked, this, &ResultPage::slotCreateEncryptionCertificate);
ui->dragQueen->setPixmap(QIcon::fromTheme(QStringLiteral("kleopatra")).pixmap(64, 64));
registerField(QStringLiteral("error"), ui->errorTB, "plainText");
registerField(QStringLiteral("result"), ui->resultTB, "plainText");
registerField(QStringLiteral("url"), ui->dragQueen, "url");
// hidden field, since QWizard can't deal with non-widget-backed fields...
auto le = new QLineEdit(this);
le->hide();
registerField(QStringLiteral("fingerprint"), le);
}
ResultPage::~ResultPage() = default;
void ResultPage::initializePage()
{
const bool error = isError();
if (error) {
setTitle(i18nc("@title", "Key Creation Failed"));
setSubTitle(i18n("Key pair creation failed. Please find details about the failure below."));
} else {
setTitle(i18nc("@title", "Key Pair Successfully Created"));
setSubTitle(i18n("Your new key pair was created successfully. Please find details on the result and some suggested next steps below."));
}
ui->resultTB->setVisible(!error);
ui->errorTB->setVisible(error);
- ui->dragQueen->setVisible(!error && !pgp());
+ ui->dragQueen->setVisible(!error);
ui->restartWizardPB->setVisible(error);
ui->nextStepsGB->setVisible(!error);
- ui->saveRequestToFilePB->setVisible(!pgp());
- ui->makeBackupPB->setVisible(pgp());
- ui->createRevocationRequestPB->setVisible(pgp() && false); // not implemented
-
- ui->sendCertificateByEMailPB->setVisible(pgp());
- ui->sendRequestByEMailPB->setVisible(!pgp());
- ui->uploadToKeyserverPB->setVisible(pgp());
+ ui->saveRequestToFilePB->setVisible(true);
+ ui->sendRequestByEMailPB->setVisible(true);
- if (!error && !pgp()) {
+ if (!error) {
if (signingAllowed() && !encryptionAllowed()) {
successfullyCreatedSigningCertificate = true;
} else if (!signingAllowed() && encryptionAllowed()) {
successfullyCreatedEncryptionCertificate = true;
} else {
successfullyCreatedEncryptionCertificate = successfullyCreatedSigningCertificate = true;
}
}
ui->createSigningCertificatePB->setVisible(successfullyCreatedEncryptionCertificate && !successfullyCreatedSigningCertificate);
ui->createEncryptionCertificatePB->setVisible(successfullyCreatedSigningCertificate && !successfullyCreatedEncryptionCertificate);
if (error) {
wizard()->setOptions(wizard()->options() & ~QWizard::NoCancelButtonOnLastPage);
} else {
wizard()->setOptions(wizard()->options() | QWizard::NoCancelButtonOnLastPage);
}
if (!initialized) {
connect(ui->restartWizardPB, &QAbstractButton::clicked, this, [this]() {
restartAtEnterDetailsPage();
});
}
initialized = true;
}
bool ResultPage::isError() const
{
return !ui->errorTB->document()->isEmpty();
}
bool ResultPage::isComplete() const
{
return !isError();
}
Key ResultPage::key() const
{
return KeyCache::instance()->findByFingerprint(fingerprint().toLatin1().constData());
}
void ResultPage::slotSaveRequestToFile()
{
QString fileName = FileDialog::getSaveFileName(this, i18nc("@title", "Save Request"), QStringLiteral("imp"), i18n("PKCS#10 Requests (*.p10)"));
if (fileName.isEmpty()) {
return;
}
if (!fileName.endsWith(QLatin1StringView(".p10"), Qt::CaseInsensitive)) {
fileName += QLatin1StringView(".p10");
}
QFile src(QUrl(url()).toLocalFile());
if (!src.copy(fileName))
KMessageBox::error(this,
xi18nc("@info",
"Could not copy temporary file <filename>%1</filename> "
"to file <filename>%2</filename>: <message>%3</message>",
src.fileName(),
fileName,
src.errorString()),
i18nc("@title", "Error Saving Request"));
else
KMessageBox::information(this,
xi18nc("@info",
"<para>Successfully wrote request to <filename>%1</filename>.</para>"
"<para>You should now send the request to the Certification Authority (CA).</para>",
fileName),
i18nc("@title", "Request Saved"));
}
void ResultPage::slotSendRequestByEMail()
{
- if (pgp()) {
- return;
- }
const KConfigGroup config(KSharedConfig::openConfig(), QStringLiteral("CertificateCreationWizard"));
invokeMailer(config.readEntry("CAEmailAddress"), // to
i18n("Please process this certificate."), // subject
i18n("Please process this certificate and inform the sender about the location to fetch the resulting certificate.\n\nThanks,\n"), // body
QFileInfo{QUrl(url()).toLocalFile()}); // attachment
KMessageBox::information(this,
xi18nc("@info",
"<para><application>Kleopatra</application> tried to send a mail via your default mail client.</para>"
"<para>Some mail clients are known not to support attachments when invoked this way.</para>"
"<para>If your mail client does not have an attachment, then drag the <application>Kleopatra</application> icon and drop "
"it on the message compose window of your mail client.</para>"
"<para>If that does not work, either, save the request to a file, and then attach that.</para>"),
i18nc("@title", "Sending Mail"),
QStringLiteral("newcertificatewizard-mailto-troubles"));
}
-void ResultPage::slotSendCertificateByEMail()
-{
- if (!pgp() || exportCertificateCommand) {
- return;
- }
- auto cmd = new ExportCertificateCommand(key());
- connect(cmd, &ExportCertificateCommand::finished, this, &ResultPage::slotSendCertificateByEMailContinuation);
- cmd->setOpenPGPFileName(tmpDir().absoluteFilePath(fingerprint() + QLatin1StringView(".asc")));
- cmd->start();
- exportCertificateCommand = cmd;
-}
-
-void ResultPage::slotSendCertificateByEMailContinuation()
-{
- if (!exportCertificateCommand) {
- return;
- }
- // ### better error handling?
- const QString fileName = exportCertificateCommand->openPGPFileName();
- qCDebug(KLEOPATRA_LOG) << "fileName" << fileName;
- exportCertificateCommand = nullptr;
- if (fileName.isEmpty()) {
- return;
- }
- invokeMailer(i18n("My new public OpenPGP key"), // subject
- i18n("Please find attached my new public OpenPGP key."), // body
- QFileInfo{fileName});
- KMessageBox::information(this,
- xi18nc("@info",
- "<para><application>Kleopatra</application> tried to send a mail via your default mail client.</para>"
- "<para>Some mail clients are known not to support attachments when invoked this way.</para>"
- "<para>If your mail client does not have an attachment, then attach the file <filename>%1</filename> manually.</para>",
- fileName),
- i18nc("@title", "Sending Mail"),
- QStringLiteral("newcertificatewizard-openpgp-mailto-troubles"));
-}
-
-void ResultPage::slotUploadCertificateToDirectoryServer()
-{
- if (pgp()) {
- (new ExportOpenPGPCertsToServerCommand(key()))->start();
- }
-}
-
-void ResultPage::slotBackupCertificate()
-{
- if (pgp()) {
- (new ExportSecretKeyCommand(key()))->start();
- }
-}
-
-void ResultPage::slotCreateRevocationRequest()
-{
-}
-
void ResultPage::slotCreateSigningCertificate()
{
if (successfullyCreatedSigningCertificate) {
return;
}
toggleSignEncryptAndRestart();
}
void ResultPage::slotCreateEncryptionCertificate()
{
if (successfullyCreatedEncryptionCertificate) {
return;
}
toggleSignEncryptAndRestart();
}
void ResultPage::toggleSignEncryptAndRestart()
{
if (!wizard()) {
return;
}
if (KMessageBox::warningContinueCancel(this,
i18nc("@info",
"This operation will delete the certification request. "
"Please make sure that you have sent or saved it before proceeding."),
i18nc("@title", "Certification Request About To Be Deleted"))
!= KMessageBox::Continue) {
return;
}
const bool sign = signingAllowed();
const bool encr = encryptionAllowed();
setField(QStringLiteral("signingAllowed"), !sign);
setField(QStringLiteral("encryptionAllowed"), !encr);
restartAtEnterDetailsPage();
}
#include "moc_resultpage_p.cpp"
diff --git a/src/newcertificatewizard/resultpage_p.h b/src/newcertificatewizard/resultpage_p.h
index c155595ad..2ee757140 100644
--- a/src/newcertificatewizard/resultpage_p.h
+++ b/src/newcertificatewizard/resultpage_p.h
@@ -1,67 +1,62 @@
/* -*- mode: c++; c-basic-offset:4 -*-
newcertificatewizard/resultpage_p.h
This file is part of Kleopatra, the KDE keymanager
SPDX-FileCopyrightText: 2008 Klarälvdalens Datakonsult AB
SPDX-FileCopyrightText: 2016, 2017 Bundesamt für Sicherheit in der Informationstechnik
SPDX-FileContributor: Intevation GmbH
SPDX-FileCopyrightText: 2022 g10 Code GmbH
SPDX-FileContributor: Ingo Klöcker <dev@ingo-kloecker.de>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#pragma once
#include "wizardpage_p.h"
namespace GpgME
{
class Key;
}
namespace Kleo
{
class ExportCertificateCommand;
}
namespace Kleo::NewCertificateUi
{
class ResultPage : public WizardPage
{
Q_OBJECT
public:
explicit ResultPage(QWidget *p = nullptr);
~ResultPage() override;
void initializePage() override;
bool isError() const;
bool isComplete() const override;
private:
GpgME::Key key() const;
private Q_SLOTS:
void slotSaveRequestToFile();
void slotSendRequestByEMail();
- void slotSendCertificateByEMail();
- void slotSendCertificateByEMailContinuation();
- void slotUploadCertificateToDirectoryServer();
- void slotBackupCertificate();
- void slotCreateRevocationRequest();
void slotCreateSigningCertificate();
void slotCreateEncryptionCertificate();
private:
void toggleSignEncryptAndRestart();
private:
struct UI;
std::unique_ptr<UI> ui;
bool initialized : 1;
bool successfullyCreatedSigningCertificate : 1;
bool successfullyCreatedEncryptionCertificate : 1;
QPointer<Kleo::ExportCertificateCommand> exportCertificateCommand;
};
}
diff --git a/src/newcertificatewizard/wizardpage_p.h b/src/newcertificatewizard/wizardpage_p.h
index 1096cb7ea..a0543f040 100644
--- a/src/newcertificatewizard/wizardpage_p.h
+++ b/src/newcertificatewizard/wizardpage_p.h
@@ -1,100 +1,85 @@
/* -*- mode: c++; c-basic-offset:4 -*-
newcertificatewizard/wizardpage_p.h
This file is part of Kleopatra, the KDE keymanager
SPDX-FileCopyrightText: 2008 Klarälvdalens Datakonsult AB
SPDX-FileCopyrightText: 2016, 2017 Bundesamt für Sicherheit in der Informationstechnik
SPDX-FileContributor: Intevation GmbH
SPDX-License-Identifier: GPL-2.0-or-later
*/
#pragma once
#include "newcertificatewizard.h"
#include "utils/metatypes_for_gpgmepp_key.h"
#include <QDate>
#include <QDir>
#include <QVariant>
#include <QWizardPage>
#include <gpgme++/key.h>
namespace Kleo
{
namespace NewCertificateUi
{
class WizardPage : public QWizardPage
{
Q_OBJECT
protected:
explicit WizardPage(QWidget *parent = nullptr)
: QWizardPage(parent)
{
}
NewCertificateWizard *wizard() const
{
Q_ASSERT(static_cast<NewCertificateWizard *>(QWizardPage::wizard()) == qobject_cast<NewCertificateWizard *>(QWizardPage::wizard()));
return static_cast<NewCertificateWizard *>(QWizardPage::wizard());
}
- bool pgp() const
- {
- return wizard()->protocol() == GpgME::OpenPGP;
- }
-
void restartAtEnterDetailsPage()
{
wizard()->restartAtEnterDetailsPage();
}
QDir tmpDir() const
{
return wizard()->tmpDir();
}
protected:
#define FIELD(type, name) \
type name() const \
{ \
return field(QStringLiteral(#name)).value<type>(); \
}
FIELD(bool, signingAllowed)
FIELD(bool, encryptionAllowed)
- FIELD(bool, certificationAllowed)
- FIELD(bool, authenticationAllowed)
FIELD(QString, name)
FIELD(QString, email)
FIELD(QString, dn)
FIELD(bool, protectedKey)
FIELD(GpgME::Subkey::PubkeyAlgo, keyType)
FIELD(int, keyStrength)
- FIELD(QString, keyCurve)
-
- FIELD(GpgME::Subkey::PubkeyAlgo, subkeyType)
- FIELD(int, subkeyStrength)
- FIELD(QString, subkeyCurve)
-
- FIELD(QDate, expiryDate)
- FIELD(QStringList, additionalUserIDs)
FIELD(QStringList, additionalEMailAddresses)
FIELD(QStringList, dnsNames)
FIELD(QStringList, uris)
FIELD(QString, url)
FIELD(QString, error)
FIELD(QString, result)
FIELD(QString, fingerprint)
#undef FIELD
};
} // namespace NewCertificateUi
} // namespace Kleo

File Metadata

Mime Type
text/x-diff
Expires
Mon, Jan 12, 11:47 PM (1 d, 12 h)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
fc/9e/c77695669895adf764f617d7491a

Event Timeline