Page Menu
Home
GnuPG
Search
Configure Global Search
Log In
Files
F34572505
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Size
18 KB
Subscribers
None
View Options
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
Details
Attached
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
Attached To
rLIBKLEO Libkleo
Event Timeline
Log In to Comment