cf12defd28
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
118 lines
5.0 KiB
C++
118 lines
5.0 KiB
C++
/*
|
|
This file is part of the KDE project
|
|
SPDX-FileCopyrightText: 2009 Andreas Hartmetz <ahartmetz@gmail.com>
|
|
|
|
SPDX-License-Identifier: LGPL-2.0-or-later
|
|
*/
|
|
|
|
#include "sslui.h"
|
|
|
|
#include <KLocalizedString>
|
|
#include <KMessageBox>
|
|
#include <ksslcertificatemanager.h>
|
|
#include <ksslerroruidata_p.h>
|
|
#include <ksslinfodialog.h>
|
|
|
|
bool KIO::SslUi::askIgnoreSslErrors(const KSslErrorUiData &uiData, RulesStorage storedRules)
|
|
{
|
|
const KSslErrorUiData::Private *ud = KSslErrorUiData::Private::get(&uiData);
|
|
if (ud->sslErrors.isEmpty()) {
|
|
return true;
|
|
}
|
|
|
|
const QList<QSslError> fatalErrors = KSslCertificateManager::nonIgnorableErrors(ud->sslErrors);
|
|
if (!fatalErrors.isEmpty()) {
|
|
// TODO message "sorry, fatal error, you can't override it"
|
|
return false;
|
|
}
|
|
if (ud->certificateChain.isEmpty()) {
|
|
// SSL without certificates is quite useless and should never happen
|
|
KMessageBox::error(nullptr,
|
|
i18n("The remote host did not send any SSL certificates.\n"
|
|
"Aborting because the identity of the host cannot be established."));
|
|
return false;
|
|
}
|
|
|
|
KSslCertificateManager *const cm = KSslCertificateManager::self();
|
|
KSslCertificateRule rule(ud->certificateChain.first(), ud->host);
|
|
if (storedRules & RecallRules) {
|
|
rule = cm->rule(ud->certificateChain.first(), ud->host);
|
|
// remove previously seen and acknowledged errors
|
|
const QList<QSslError> remainingErrors = rule.filterErrors(ud->sslErrors);
|
|
if (remainingErrors.isEmpty()) {
|
|
// qDebug() << "Error list empty after removing errors to be ignored. Continuing.";
|
|
return true;
|
|
}
|
|
}
|
|
|
|
// ### We don't ask to permanently reject the certificate
|
|
|
|
QString message = i18n("The server failed the authenticity check (%1).\n\n", ud->host);
|
|
for (const QSslError &err : std::as_const(ud->sslErrors)) {
|
|
message.append(err.errorString() + QLatin1Char('\n'));
|
|
}
|
|
message = message.trimmed();
|
|
|
|
int msgResult;
|
|
do {
|
|
msgResult = KMessageBox::warningTwoActionsCancel(nullptr,
|
|
message,
|
|
i18n("Server Authentication"),
|
|
KGuiItem(i18n("&Details"), QStringLiteral("help-about")),
|
|
KGuiItem(i18n("Co&ntinue"), QStringLiteral("arrow-right")));
|
|
if (msgResult == KMessageBox::PrimaryAction) {
|
|
// Details was chosen - show the certificate and error details
|
|
|
|
QList<QList<QSslError::SslError>> meh; // parallel list to cert list :/
|
|
|
|
meh.reserve(ud->certificateChain.size());
|
|
for (const QSslCertificate &cert : std::as_const(ud->certificateChain)) {
|
|
QList<QSslError::SslError> errors;
|
|
for (const QSslError &error : std::as_const(ud->sslErrors)) {
|
|
if (error.certificate() == cert) {
|
|
// we keep only the error code enum here
|
|
errors.append(error.error());
|
|
}
|
|
}
|
|
meh.append(errors);
|
|
}
|
|
|
|
KSslInfoDialog *dialog = new KSslInfoDialog();
|
|
dialog->setSslInfo(ud->certificateChain, ud->ip, ud->host, ud->sslProtocol, ud->cipher, ud->usedBits, ud->bits, meh);
|
|
dialog->exec();
|
|
} else if (msgResult == KMessageBox::Cancel) {
|
|
return false;
|
|
}
|
|
// fall through on KMessageBox::SecondaryAction
|
|
} while (msgResult == KMessageBox::PrimaryAction);
|
|
|
|
if (storedRules & StoreRules) {
|
|
// Save the user's choice to ignore the SSL errors.
|
|
|
|
msgResult = KMessageBox::warningTwoActions(nullptr,
|
|
i18n("Would you like to accept this "
|
|
"certificate forever without "
|
|
"being prompted?"),
|
|
i18n("Server Authentication"),
|
|
KGuiItem(i18n("&Forever"), QStringLiteral("flag-green")),
|
|
KGuiItem(i18n("&Current Session only"), QStringLiteral("chronometer")));
|
|
QDateTime ruleExpiry = QDateTime::currentDateTime();
|
|
if (msgResult == KMessageBox::PrimaryAction) {
|
|
// accept forever ("for a very long time")
|
|
ruleExpiry = ruleExpiry.addYears(1000);
|
|
} else {
|
|
// accept "for a short time", half an hour.
|
|
ruleExpiry = ruleExpiry.addSecs(30 * 60);
|
|
}
|
|
|
|
// TODO special cases for wildcard domain name in the certificate!
|
|
// rule = KSslCertificateRule(d->socket.peerCertificateChain().first(), whatever);
|
|
|
|
rule.setExpiryDateTime(ruleExpiry);
|
|
rule.setIgnoredErrors(ud->sslErrors);
|
|
cm->setRule(rule);
|
|
}
|
|
|
|
return true;
|
|
}
|