Page MenuHome GnuPG

No OneTemporary

diff --git a/src/dialogs/expirydialog.cpp b/src/dialogs/expirydialog.cpp
index cf3a09b62..b9915832c 100644
--- a/src/dialogs/expirydialog.cpp
+++ b/src/dialogs/expirydialog.cpp
@@ -1,228 +1,228 @@
/* -*- mode: c++; c-basic-offset:4 -*-
dialogs/expirydialog.cpp
This file is part of Kleopatra, the KDE keymanager
SPDX-FileCopyrightText: 2008 Klarälvdalens Datakonsult AB
SPDX-FileCopyrightText: 2021 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 "expirydialog.h"
#include "utils/expiration.h"
#include "utils/gui-helper.h"
#include "utils/qt-cxx20-compat.h"
#include <Libkleo/Formatting>
#include <KDateComboBox>
#include <KLocalizedString>
#include <KMessageBox>
#include <KStandardGuiItem>
#include <QCheckBox>
#include <QDate>
#include <QDialogButtonBox>
#include <QHBoxLayout>
#include <QLabel>
#include <QPushButton>
#include <QRadioButton>
#include <QVBoxLayout>
using namespace Kleo;
using namespace Kleo::Dialogs;
class ExpiryDialog::Private
{
friend class ::Kleo::Dialogs::ExpiryDialog;
ExpiryDialog *const q;
public:
Private(Mode mode, ExpiryDialog *qq)
: q{qq}
, ui{mode, qq}
{
ui.neverRB->setEnabled(unlimitedValidityAllowed());
ui.onRB->setEnabled(!fixedExpirationDate());
connect(ui.onCB, &KDateComboBox::dateChanged,
q, [this] () { slotOnDateChanged(); });
}
private:
void slotOnDateChanged();
private:
bool unlimitedValidityAllowed() const;
bool fixedExpirationDate() const;
void setInitialFocus();
private:
bool initialFocusWasSet = false;
struct UI {
QRadioButton *neverRB;
QRadioButton *onRB;
KDateComboBox *onCB;
QCheckBox *updateSubkeysCheckBox;
explicit UI(Mode mode, Dialogs::ExpiryDialog *qq)
{
auto mainLayout = new QVBoxLayout{qq};
auto mainWidget = new QWidget{qq};
auto vboxLayout = new QVBoxLayout{mainWidget};
vboxLayout->setContentsMargins(0, 0, 0, 0);
{
auto label = new QLabel{qq};
label->setText(mode == Mode::UpdateIndividualSubkey ?
i18n("Please select until when the subkey should be valid:") :
i18n("Please select until when the certificate should be valid:"));
vboxLayout->addWidget(label);
}
neverRB = new QRadioButton(i18n("Unlimited validity"), mainWidget);
neverRB->setChecked(false);
vboxLayout->addWidget(neverRB);
{
auto hboxLayout = new QHBoxLayout;
onRB = new QRadioButton{i18n("Valid until:"), mainWidget};
onRB->setChecked(true);
hboxLayout->addWidget(onRB);
onCB = new KDateComboBox{mainWidget};
setUpExpirationDateComboBox(onCB);
hboxLayout->addWidget(onCB);
hboxLayout->addStretch(1);
vboxLayout->addLayout(hboxLayout);
}
{
updateSubkeysCheckBox = new QCheckBox{i18n("Also update the validity period of the subkeys"), qq};
#if QGPGME_SUPPORTS_CHANGING_EXPIRATION_OF_COMPLETE_KEY
updateSubkeysCheckBox->setVisible(mode == Mode::UpdateCertificateWithSubkeys);
#else
updateSubkeysCheckBox->setVisible(false);
#endif
vboxLayout->addWidget(updateSubkeysCheckBox);
}
vboxLayout->addStretch(1);
mainLayout->addWidget(mainWidget);
auto buttonBox = new QDialogButtonBox{QDialogButtonBox::Ok | QDialogButtonBox::Cancel, qq};
auto okButton = buttonBox->button(QDialogButtonBox::Ok);
KGuiItem::assign(okButton, KStandardGuiItem::ok());
okButton->setDefault(true);
okButton->setShortcut(Qt::CTRL | Qt::Key_Return);
KGuiItem::assign(buttonBox->button(QDialogButtonBox::Cancel), KStandardGuiItem::cancel());
qq->connect(buttonBox, &QDialogButtonBox::accepted, qq, &ExpiryDialog::accept);
qq->connect(buttonBox, &QDialogButtonBox::rejected, qq, &QDialog::reject);
mainLayout->addWidget(buttonBox);
connect(onRB, &QRadioButton::toggled, onCB, &QWidget::setEnabled);
}
} ui;
};
void ExpiryDialog::Private::slotOnDateChanged()
{
ui.onRB->setAccessibleName(i18nc("Valid until DATE", "Valid until %1", Formatting::accessibleDate(ui.onCB->date())));
}
bool Kleo::Dialogs::ExpiryDialog::Private::unlimitedValidityAllowed() const
{
- return !ui.onCB->maximumDate().isValid();
+ return !Kleo::maximumExpirationDate().isValid();
}
bool Kleo::Dialogs::ExpiryDialog::Private::fixedExpirationDate() const
{
return ui.onCB->minimumDate() == ui.onCB->maximumDate();
}
void ExpiryDialog::Private::setInitialFocus()
{
if (initialFocusWasSet) {
return;
}
// give focus to the checked radio button
(void) focusFirstCheckedButton({ui.neverRB, ui.onRB});
initialFocusWasSet = true;
}
ExpiryDialog::ExpiryDialog(Mode mode, QWidget *p)
: QDialog{p}
, d{new Private{mode, this}}
{
setWindowTitle(i18nc("@title:window", "Change Validity Period"));
}
ExpiryDialog::~ExpiryDialog() = default;
void ExpiryDialog::setDateOfExpiry(const QDate &date)
{
const QDate current = QDate::currentDate();
if (date.isValid()) {
d->ui.onRB->setChecked(true);
if (date <= current) {
d->ui.onCB->setDate(defaultExpirationDate(ExpirationOnUnlimitedValidity::InternalDefaultExpiration));
} else {
d->ui.onCB->setDate(date);
}
} else {
if (d->unlimitedValidityAllowed()) {
d->ui.neverRB->setChecked(true);
} else {
d->ui.onRB->setChecked(true);
}
d->ui.onCB->setDate(defaultExpirationDate(ExpirationOnUnlimitedValidity::InternalDefaultExpiration));
}
}
QDate ExpiryDialog::dateOfExpiry() const
{
return d->ui.onRB->isChecked() ? d->ui.onCB->date() : QDate{};
}
void ExpiryDialog::setUpdateExpirationOfAllSubkeys(bool update)
{
d->ui.updateSubkeysCheckBox->setChecked(update);
}
bool ExpiryDialog::updateExpirationOfAllSubkeys() const
{
return d->ui.updateSubkeysCheckBox->isChecked();
}
void ExpiryDialog::accept()
{
const auto date = dateOfExpiry();
if (!Kleo::isValidExpirationDate(date)) {
KMessageBox::error(this, i18nc("@info", "Error: %1", Kleo::validityPeriodHint()));
return;
}
QDialog::accept();
}
void ExpiryDialog::showEvent(QShowEvent *event)
{
d->setInitialFocus();
QDialog::showEvent(event);
}
#include "moc_expirydialog.cpp"
diff --git a/src/newcertificatewizard/advancedsettingsdialog.cpp b/src/newcertificatewizard/advancedsettingsdialog.cpp
index 7e9a0e26a..398e56ae1 100644
--- a/src/newcertificatewizard/advancedsettingsdialog.cpp
+++ b/src/newcertificatewizard/advancedsettingsdialog.cpp
@@ -1,1021 +1,1021 @@
/* -*- 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 <QGpgME/CryptoConfig>
#include <QGpgME/Protocol>
#include <QCheckBox>
#include <QDialogButtonBox>
#include <QGridLayout>
#include <QGroupBox>
#include <QHBoxLayout>
#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)
{
const auto split = algoString.split(QLatin1Char('/'));
bool isEncrypt = split.size() == 2 && split[1].contains(QLatin1String("enc"));
// Normalize
const auto lowered = split[0].toLower().remove(QLatin1Char('-'));
if (!algo || !size) {
return;
}
*algo = Subkey::AlgoUnknown;
if (lowered.startsWith(QLatin1String("rsa"))) {
*algo = Subkey::AlgoRSA;
} else if (lowered.startsWith(QLatin1String("dsa"))) {
*algo = Subkey::AlgoDSA;
} else if (lowered.startsWith(QLatin1String("elg"))) {
*algo = Subkey::AlgoELG;
}
if (*algo != Subkey::AlgoUnknown) {
bool ok;
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
*size = lowered.rightRef(lowered.size() - 3).toInt(&ok);
#else
*size = QStringView(lowered).right(lowered.size() - 3).toInt(&ok);
#endif
if (!ok) {
qCWarning(KLEOPATRA_LOG) << "Could not extract size from: " << lowered;
*size = 3072;
}
return;
}
// Now the ECC Algorithms
if (lowered.startsWith(QLatin1String("ed25519"))) {
// Special handling for this as technically
// this is a cv25519 curve used for EDDSA
if (isEncrypt) {
curve = QLatin1String("cv25519");
*algo = Subkey::AlgoECDH;
} else {
curve = split[0];
*algo = Subkey::AlgoEDDSA;
}
return;
}
if (lowered.startsWith(QLatin1String("cv25519")) ||
lowered.startsWith(QLatin1String("nist")) ||
lowered.startsWith(QLatin1String("brainpool")) ||
lowered.startsWith(QLatin1String("secp"))) {
curve = split[0];
*algo = isEncrypt ? Subkey::AlgoECDH : Subkey::AlgoECDSA;
return;
}
qCWarning(KLEOPATRA_LOG) << "Failed to parse default_pubkey_algo:" << algoString;
}
}
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};
{
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);
rsaKeyStrengthCB = new QComboBox{groupBox};
rsaKeyStrengthCB->setEnabled(false);
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, &QDialog::accept);
connect(ui->buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
}
AdvancedSettingsDialog::~AdvancedSettingsDialog() = default;
bool AdvancedSettingsDialog::unlimitedValidityIsAllowed() const
{
- return !ui->expiryDE->maximumDate().isValid();
+ 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();
}
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);
}
}
Subkey::PubkeyAlgo AdvancedSettingsDialog::keyType() const
{
return
ui->dsaRB->isChecked() ? Subkey::AlgoDSA :
ui->rsaRB->isChecked() ? Subkey::AlgoRSA :
ui->ecdsaRB->isChecked() ?
ui->ecdsaKeyCurvesCB->currentText() == QLatin1String("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);
}
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() ? forceDateIntoAllowedRange(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()) {
setEncryptionAllowed(true);
}
}
void AdvancedSettingsDialog::slotEncryptionAllowedToggled(bool on)
{
if (!on && protocol == CMS && !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(), "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");
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);
}
}
}
void AdvancedSettingsDialog::loadDefaultKeyType()
{
if (protocol != CMS && protocol != OpenPGP) {
return;
}
const KConfigGroup config(KSharedConfig::openConfig(), "CertificateCreationWizard");
const QString entry = protocol == CMS ? QLatin1String(CMS_KEY_TYPE_ENTRY) : QLatin1String(PGP_KEY_TYPE_ENTRY);
const QString keyType = config.readEntry(entry).trimmed().toUpper();
if (protocol == OpenPGP && keyType == QLatin1String("DSA")) {
setKeyType(Subkey::AlgoDSA);
setSubkeyType(Subkey::AlgoUnknown);
} else if (protocol == OpenPGP && keyType == QLatin1String("DSA+ELG")) {
setKeyType(Subkey::AlgoDSA);
setSubkeyType(Subkey::AlgoELG_E);
} else if (keyType.isEmpty() && engineIsVersion(2, 1, 17)) {
loadDefaultGnuPGKeyType();
} else {
if (!keyType.isEmpty() && keyType != QLatin1String("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);
}
}
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})) {
return;
}
// finally, focus the OK button
ui->buttonBox->button(QDialogButtonBox::Ok)->setFocus();
}
void AdvancedSettingsDialog::showEvent(QShowEvent *event)
{
if (isFirstShowEvent) {
setInitialFocus();
isFirstShowEvent = false;
}
QDialog::showEvent(event);
}

File Metadata

Mime Type
text/x-diff
Expires
Mon, Dec 8, 3:27 AM (1 h, 58 m)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
2f/94/849a76fd7f6daac54e1dae97a49f

Event Timeline