Page MenuHome GnuPG

No OneTemporary

diff --git a/src/ui/editdirectoryservicedialog.cpp b/src/ui/editdirectoryservicedialog.cpp
index ea8428f9..3e97df2e 100644
--- a/src/ui/editdirectoryservicedialog.cpp
+++ b/src/ui/editdirectoryservicedialog.cpp
@@ -1,424 +1,425 @@
/*
ui/editdirectoryservicedialog.cpp
This file is part of libkleopatra, the KDE keymanagement library
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-libkleo.h>
#include "editdirectoryservicedialog.h"
#include <libkleo/algorithm.h>
#include <libkleo/gnupg.h>
#include <libkleo/keyserverconfig.h>
#include <KCollapsibleGroupBox>
#include <KColorScheme>
#include <KConfigGroup>
#include <KGuiItem>
#include <KLocalizedString>
#include <KPasswordLineEdit>
#include <KSharedConfig>
#include <KStandardGuiItem>
#include <QButtonGroup>
#include <QCheckBox>
#include <QDialogButtonBox>
#include <QGridLayout>
#include <QGroupBox>
#include <QLabel>
#include <QLineEdit>
#include <QPushButton>
#include <QRadioButton>
#include <QSpinBox>
#include <QVBoxLayout>
using namespace Kleo;
namespace
{
int defaultPort(KeyserverConnection connection)
{
return connection == KeyserverConnection::TunnelThroughTLS ? 636 : 389;
}
}
class EditDirectoryServiceDialog::Private
{
EditDirectoryServiceDialog *const q;
struct Ui {
QLineEdit *hostEdit = nullptr;
QSpinBox *portSpinBox = nullptr;
QCheckBox *useDefaultPortCheckBox = nullptr;
QButtonGroup *authenticationGroup = nullptr;
QLineEdit *userEdit = nullptr;
KPasswordLineEdit *passwordEdit = nullptr;
QButtonGroup *connectionGroup = nullptr;
KCollapsibleGroupBox *advancedSettings = nullptr;
QLineEdit *baseDnEdit = nullptr;
QLineEdit *additionalFlagsEdit = nullptr;
QDialogButtonBox *buttonBox = nullptr;
QLabel *invalidHostLabel = nullptr;
Ui(QWidget *parent)
: hostEdit{new QLineEdit{parent}}
, portSpinBox{new QSpinBox{parent}}
, useDefaultPortCheckBox{new QCheckBox{parent}}
, authenticationGroup{new QButtonGroup{parent}}
, userEdit{new QLineEdit{parent}}
, passwordEdit{new KPasswordLineEdit{parent}}
, connectionGroup{new QButtonGroup{parent}}
, advancedSettings{new KCollapsibleGroupBox{parent}}
, baseDnEdit{new QLineEdit{parent}}
, additionalFlagsEdit{new QLineEdit{parent}}
, buttonBox{new QDialogButtonBox{parent}}
, invalidHostLabel{new QLabel{parent}}
{
#define SET_OBJECT_NAME(x) x->setObjectName(QStringLiteral(#x));
SET_OBJECT_NAME(hostEdit)
SET_OBJECT_NAME(portSpinBox)
SET_OBJECT_NAME(useDefaultPortCheckBox)
SET_OBJECT_NAME(authenticationGroup)
SET_OBJECT_NAME(userEdit)
SET_OBJECT_NAME(passwordEdit)
SET_OBJECT_NAME(connectionGroup)
SET_OBJECT_NAME(advancedSettings)
SET_OBJECT_NAME(baseDnEdit)
SET_OBJECT_NAME(additionalFlagsEdit)
SET_OBJECT_NAME(buttonBox)
#undef SET_OBJECT_NAME
auto mainLayout = new QVBoxLayout{parent};
auto serverWidget = new QWidget{parent};
{
auto layout = new QGridLayout{serverWidget};
layout->setColumnStretch(2, 1);
int row = 0;
layout->addWidget(new QLabel{i18n("Host:")}, row, 0);
hostEdit->setToolTip(i18nc("@info:tooltip", "Enter the name or IP address of the server hosting the directory service."));
hostEdit->setClearButtonEnabled(true);
layout->addWidget(hostEdit, row, 1, 1, -1);
++row;
const auto colors = KColorScheme(QPalette::Active, KColorScheme::View);
QPalette palette;
palette.setBrush(QPalette::Window, colors.background(KColorScheme::NegativeBackground));
palette.setBrush(QPalette::WindowText, colors.foreground(KColorScheme::NegativeText));
invalidHostLabel->setPalette(palette);
invalidHostLabel->setText(i18nc("@info:label", "Error: Enter a hostname in the correct format, like ldap.example.com."));
invalidHostLabel->setVisible(false);
layout->addWidget(invalidHostLabel, row, 1, 1, 2);
++row;
layout->addWidget(new QLabel{i18n("Port:")}, row, 0);
portSpinBox->setRange(1, USHRT_MAX);
portSpinBox->setToolTip(i18nc("@info:tooltip",
"<b>(Optional, the default is fine in most cases)</b> "
"Pick the port number the directory service is listening on."));
layout->addWidget(portSpinBox, row, 1);
useDefaultPortCheckBox->setText(i18n("Use default"));
useDefaultPortCheckBox->setChecked(true);
layout->addWidget(useDefaultPortCheckBox, row, 2);
}
mainLayout->addWidget(serverWidget);
auto authenticationWidget = new QGroupBox{i18n("Authentication"), parent};
{
auto layout = new QVBoxLayout{authenticationWidget};
{
auto radioButton = new QRadioButton{i18n("Anonymous")};
radioButton->setToolTip(i18nc("@info:tooltip", "Use an anonymous LDAP server that does not require authentication."));
radioButton->setChecked(true);
authenticationGroup->addButton(radioButton, static_cast<int>(KeyserverAuthentication::Anonymous));
layout->addWidget(radioButton);
}
{
auto radioButton = new QRadioButton{i18n("Authenticate via Active Directory")};
if (!engineIsVersion(2, 2, 28, GpgME::GpgSMEngine)) {
radioButton->setText(i18n("Authenticate via Active Directory (requires GnuPG 2.2.28 or later)"));
}
radioButton->setToolTip(
i18nc("@info:tooltip", "On Windows, authenticate to the LDAP server using the Active Directory with the current user."));
authenticationGroup->addButton(radioButton, static_cast<int>(KeyserverAuthentication::ActiveDirectory));
layout->addWidget(radioButton);
}
{
auto radioButton = new QRadioButton{i18n("Authenticate with user and password")};
radioButton->setToolTip(i18nc("@info:tooltip", "Authenticate to the LDAP server with your LDAP credentials."));
authenticationGroup->addButton(radioButton, static_cast<int>(KeyserverAuthentication::Password));
layout->addWidget(radioButton);
}
auto credentialsWidget = new QWidget{parent};
{
auto layout = new QGridLayout{credentialsWidget};
layout->setColumnStretch(1, 1);
int row = 0;
layout->addWidget(new QLabel{i18n("User:")}, row, 0);
userEdit->setToolTip(i18nc("@info:tooltip", "Enter your LDAP user resp. Bind DN for authenticating to the LDAP server."));
userEdit->setClearButtonEnabled(true);
layout->addWidget(userEdit, row, 1);
++row;
layout->addWidget(new QLabel{i18n("Password:")}, row, 0);
passwordEdit->setToolTip(xi18nc("@info:tooltip",
"Enter your password for authenticating to the LDAP server.<nl/>"
"<warning>The password will be saved in the clear "
"in a configuration file in your home directory.</warning>"));
passwordEdit->setClearButtonEnabled(true);
layout->addWidget(passwordEdit, row, 1);
}
layout->addWidget(credentialsWidget);
}
mainLayout->addWidget(authenticationWidget);
auto securityWidget = new QGroupBox{i18n("Connection Security"), parent};
if (!engineIsVersion(2, 2, 28, GpgME::GpgSMEngine)) {
securityWidget->setTitle(i18n("Connection Security (requires GnuPG 2.2.28 or later)"));
}
{
auto layout = new QVBoxLayout{securityWidget};
{
auto radioButton = new QRadioButton{i18n("Use default connection (probably not TLS secured)")};
radioButton->setToolTip(i18nc("@info:tooltip",
"Use GnuPG's default to connect to the LDAP server. "
"By default, GnuPG 2.3 and earlier use a plain, not TLS secured connection. "
"<b>(Not recommended)</b>"));
radioButton->setChecked(true);
connectionGroup->addButton(radioButton, static_cast<int>(KeyserverConnection::Default));
layout->addWidget(radioButton);
}
{
auto radioButton = new QRadioButton{i18n("Do not use a TLS secured connection")};
radioButton->setToolTip(i18nc("@info:tooltip",
"Use a plain, not TLS secured connection to connect to the LDAP server. "
"<b>(Not recommended)</b>"));
connectionGroup->addButton(radioButton, static_cast<int>(KeyserverConnection::Plain));
layout->addWidget(radioButton);
}
{
auto radioButton = new QRadioButton{i18n("Use TLS secured connection")};
radioButton->setToolTip(i18nc("@info:tooltip",
"Use a standard TLS secured connection (initiated with STARTTLS) "
"to connect to the LDAP server. "
"<b>(Recommended)</b>"));
connectionGroup->addButton(radioButton, static_cast<int>(KeyserverConnection::UseSTARTTLS));
layout->addWidget(radioButton);
}
{
auto radioButton = new QRadioButton{i18n("Tunnel LDAP through a TLS connection")};
radioButton->setToolTip(i18nc("@info:tooltip",
"Use a TLS secured connection through which the connection to the "
"LDAP server is tunneled. "
"<b>(Not recommended)</b>"));
connectionGroup->addButton(radioButton, static_cast<int>(KeyserverConnection::TunnelThroughTLS));
layout->addWidget(radioButton);
}
}
mainLayout->addWidget(securityWidget);
advancedSettings->setTitle(i18n("Advanced Settings"));
{
auto layout = new QGridLayout{advancedSettings};
layout->setColumnStretch(1, 1);
int row = 0;
layout->addWidget(new QLabel{i18n("Base DN:")}, row, 0);
baseDnEdit->setToolTip(i18nc("@info:tooltip",
"<b>(Optional, can usually be left empty)</b> "
"Enter the base DN for this LDAP server to limit searches "
"to only that subtree of the directory."));
baseDnEdit->setClearButtonEnabled(true);
layout->addWidget(baseDnEdit, row, 1);
++row;
layout->addWidget(new QLabel{i18n("Additional flags:")}, row, 0);
additionalFlagsEdit->setToolTip(i18nc("@info:tooltip",
"Here you can enter additional flags that are not yet (or no longer) "
"supported by Kleopatra. For example, older versions of GnuPG use "
"<code>ldaps</code> to request a TLS secured connection."));
additionalFlagsEdit->setClearButtonEnabled(true);
layout->addWidget(additionalFlagsEdit, row, 1);
}
mainLayout->addWidget(advancedSettings);
mainLayout->addStretch(1);
buttonBox->setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
QPushButton *okButton = buttonBox->button(QDialogButtonBox::Ok);
KGuiItem::assign(okButton, KStandardGuiItem::ok());
KGuiItem::assign(buttonBox->button(QDialogButtonBox::Cancel), KStandardGuiItem::cancel());
mainLayout->addWidget(buttonBox);
};
} ui;
QString host() const
{
return ui.hostEdit->text().trimmed();
}
int port() const
{
return ui.useDefaultPortCheckBox->isChecked() ? -1 : ui.portSpinBox->value();
}
KeyserverAuthentication authentication() const
{
return KeyserverAuthentication{ui.authenticationGroup->checkedId()};
}
QString user() const
{
return ui.userEdit->text().trimmed();
}
QString password() const
{
return ui.passwordEdit->password(); // not trimmed
}
KeyserverConnection connection() const
{
return KeyserverConnection{ui.connectionGroup->checkedId()};
}
QString baseDn() const
{
return ui.baseDnEdit->text().trimmed();
}
QStringList additionalFlags() const
{
return transformInPlace(ui.additionalFlagsEdit->text().split(QLatin1Char{','}, Qt::SkipEmptyParts), [](const auto &flag) {
return flag.trimmed();
});
}
bool inputIsAcceptable() const
{
const bool hostIsSet = !host().isEmpty();
- const bool hostIsValid = !host().contains(u":") && !host().contains(u"/");
- ui.invalidHostLabel->setVisible(!hostIsValid);
+ QUrl url;
+ url.setHost(host());
+ ui.invalidHostLabel->setVisible(!url.isValid());
const bool requiredCredentialsAreSet = authentication() != KeyserverAuthentication::Password || (!user().isEmpty() && !password().isEmpty());
- return hostIsSet && requiredCredentialsAreSet && hostIsValid;
+ return hostIsSet && requiredCredentialsAreSet && url.isValid();
}
void updateWidgets()
{
ui.portSpinBox->setEnabled(!ui.useDefaultPortCheckBox->isChecked());
if (ui.useDefaultPortCheckBox->isChecked()) {
ui.portSpinBox->setValue(defaultPort(connection()));
}
ui.userEdit->setEnabled(authentication() == KeyserverAuthentication::Password);
ui.passwordEdit->setEnabled(authentication() == KeyserverAuthentication::Password);
ui.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(inputIsAcceptable());
}
public:
Private(EditDirectoryServiceDialog *q)
: q{q}
, ui{q}
{
connect(ui.hostEdit, &QLineEdit::textEdited, q, [this]() {
updateWidgets();
});
connect(ui.useDefaultPortCheckBox, &QCheckBox::toggled, q, [this]() {
updateWidgets();
});
connect(ui.authenticationGroup, &QButtonGroup::idToggled, q, [this]() {
updateWidgets();
});
connect(ui.userEdit, &QLineEdit::textEdited, q, [this]() {
updateWidgets();
});
connect(ui.passwordEdit, &KPasswordLineEdit::passwordChanged, q, [this]() {
updateWidgets();
});
connect(ui.connectionGroup, &QButtonGroup::idToggled, q, [this]() {
updateWidgets();
});
connect(ui.buttonBox, &QDialogButtonBox::accepted, q, &EditDirectoryServiceDialog::accept);
connect(ui.buttonBox, &QDialogButtonBox::rejected, q, &EditDirectoryServiceDialog::reject);
updateWidgets();
restoreLayout();
}
~Private()
{
saveLayout();
}
void setKeyserver(const KeyserverConfig &keyserver)
{
ui.hostEdit->setText(keyserver.host());
ui.useDefaultPortCheckBox->setChecked(keyserver.port() == -1);
ui.portSpinBox->setValue(keyserver.port() == -1 ? defaultPort(keyserver.connection()) : keyserver.port());
ui.authenticationGroup->button(static_cast<int>(keyserver.authentication()))->setChecked(true);
ui.userEdit->setText(keyserver.user());
ui.passwordEdit->setPassword(keyserver.password());
ui.connectionGroup->button(static_cast<int>(keyserver.connection()))->setChecked(true);
ui.baseDnEdit->setText(keyserver.ldapBaseDn());
ui.additionalFlagsEdit->setText(keyserver.additionalFlags().join(QLatin1Char{','}));
ui.advancedSettings->setExpanded(!keyserver.ldapBaseDn().isEmpty() || !keyserver.additionalFlags().empty());
updateWidgets();
}
KeyserverConfig keyserver() const
{
KeyserverConfig keyserver;
keyserver.setHost(host());
keyserver.setPort(port());
keyserver.setAuthentication(authentication());
keyserver.setUser(user());
keyserver.setPassword(password());
keyserver.setConnection(connection());
keyserver.setLdapBaseDn(baseDn());
keyserver.setAdditionalFlags(additionalFlags());
return keyserver;
}
private:
void saveLayout()
{
KConfigGroup configGroup{KSharedConfig::openStateConfig(), QLatin1StringView("EditDirectoryServiceDialog")};
configGroup.writeEntry("Size", q->size());
configGroup.sync();
}
void restoreLayout()
{
const KConfigGroup configGroup{KSharedConfig::openStateConfig(), QLatin1StringView("EditDirectoryServiceDialog")};
const auto size = configGroup.readEntry("Size", QSize{});
if (size.isValid()) {
q->resize(size);
}
}
};
EditDirectoryServiceDialog::EditDirectoryServiceDialog(QWidget *parent, Qt::WindowFlags f)
: QDialog{parent, f}
, d{std::make_unique<Private>(this)}
{
setWindowTitle(i18nc("@title:window", "Edit Directory Service"));
}
EditDirectoryServiceDialog::~EditDirectoryServiceDialog() = default;
void EditDirectoryServiceDialog::setKeyserver(const KeyserverConfig &keyserver)
{
d->setKeyserver(keyserver);
}
KeyserverConfig EditDirectoryServiceDialog::keyserver() const
{
return d->keyserver();
}
#include "moc_editdirectoryservicedialog.cpp"

File Metadata

Mime Type
text/x-diff
Expires
Sat, Jan 17, 2:48 AM (11 h, 15 m)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
0f/4e/7e411a0e2343a7684fb3fb7b81ef

Event Timeline