File indexing completed on 2024-11-03 03:41:31

0001 /*
0002     This file is part of the KDE project
0003     SPDX-FileCopyrightText: 2000, 2001 George Staikos <staikos@kde.org>
0004     SPDX-FileCopyrightText: 2000 Malte Starostik <malte@kde.org>
0005 
0006     SPDX-License-Identifier: LGPL-2.0-or-later
0007 */
0008 
0009 #include "ksslinfodialog.h"
0010 #include "ksslcertificatebox.h"
0011 #include "ui_sslinfo.h"
0012 
0013 #include <QDialogButtonBox>
0014 
0015 #include <QSslCertificate>
0016 
0017 #include <KIconLoader> // BarIcon
0018 #include <KLocalizedString>
0019 
0020 class Q_DECL_HIDDEN KSslInfoDialog::KSslInfoDialogPrivate
0021 {
0022 public:
0023     QList<QSslCertificate> certificateChain;
0024     QList<QList<QSslError::SslError>> certificateErrors;
0025 
0026     bool isMainPartEncrypted;
0027     bool auxPartsEncrypted;
0028 
0029     Ui::SslInfo ui;
0030     KSslCertificateBox *subject;
0031     KSslCertificateBox *issuer;
0032 };
0033 
0034 KSslInfoDialog::KSslInfoDialog(QWidget *parent)
0035     : QDialog(parent)
0036     , d(new KSslInfoDialogPrivate)
0037 {
0038     setWindowTitle(i18n("KDE SSL Information"));
0039     setAttribute(Qt::WA_DeleteOnClose);
0040 
0041     QVBoxLayout *layout = new QVBoxLayout(this);
0042 
0043     QWidget *mainWidget = new QWidget(this);
0044     d->ui.setupUi(mainWidget);
0045     layout->addWidget(mainWidget);
0046 
0047     d->subject = new KSslCertificateBox(d->ui.certParties);
0048     d->issuer = new KSslCertificateBox(d->ui.certParties);
0049     d->ui.certParties->addTab(d->subject, i18nc("The receiver of the SSL certificate", "Subject"));
0050     d->ui.certParties->addTab(d->issuer, i18nc("The authority that issued the SSL certificate", "Issuer"));
0051 
0052     d->isMainPartEncrypted = true;
0053     d->auxPartsEncrypted = true;
0054     updateWhichPartsEncrypted();
0055 
0056     QDialogButtonBox *buttonBox = new QDialogButtonBox(this);
0057     buttonBox->setStandardButtons(QDialogButtonBox::Close);
0058     connect(buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
0059     connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
0060     layout->addWidget(buttonBox);
0061 }
0062 
0063 KSslInfoDialog::~KSslInfoDialog() = default;
0064 
0065 void KSslInfoDialog::setMainPartEncrypted(bool mainEncrypted)
0066 {
0067     d->isMainPartEncrypted = mainEncrypted;
0068     updateWhichPartsEncrypted();
0069 }
0070 
0071 void KSslInfoDialog::setAuxiliaryPartsEncrypted(bool auxEncrypted)
0072 {
0073     d->auxPartsEncrypted = auxEncrypted;
0074     updateWhichPartsEncrypted();
0075 }
0076 
0077 void KSslInfoDialog::updateWhichPartsEncrypted()
0078 {
0079     if (d->isMainPartEncrypted) {
0080         if (d->auxPartsEncrypted) {
0081             d->ui.encryptionIndicator->setPixmap(QIcon::fromTheme(QStringLiteral("security-high")).pixmap(KIconLoader::SizeSmallMedium));
0082             d->ui.explanation->setText(i18n("Current connection is secured with SSL."));
0083         } else {
0084             d->ui.encryptionIndicator->setPixmap(QIcon::fromTheme(QStringLiteral("security-medium")).pixmap(KIconLoader::SizeSmallMedium));
0085             d->ui.explanation->setText(
0086                 i18n("The main part of this document is secured "
0087                      "with SSL, but some parts are not."));
0088         }
0089     } else {
0090         if (d->auxPartsEncrypted) {
0091             d->ui.encryptionIndicator->setPixmap(QIcon::fromTheme(QStringLiteral("security-medium")).pixmap(KIconLoader::SizeSmallMedium));
0092             d->ui.explanation->setText(
0093                 i18n("Some of this document is secured with SSL, "
0094                      "but the main part is not."));
0095         } else {
0096             d->ui.encryptionIndicator->setPixmap(QIcon::fromTheme(QStringLiteral("security-low")).pixmap(KIconLoader::SizeSmallMedium));
0097             d->ui.explanation->setText(i18n("Current connection is not secured with SSL."));
0098         }
0099     }
0100 }
0101 
0102 void KSslInfoDialog::setSslInfo(const QList<QSslCertificate> &certificateChain,
0103                                 const QString &ip,
0104                                 const QString &host,
0105                                 const QString &sslProtocol,
0106                                 const QString &cipher,
0107                                 int usedBits,
0108                                 int bits,
0109                                 const QList<QList<QSslError::SslError>> &validationErrors)
0110 {
0111     d->certificateChain = certificateChain;
0112     d->certificateErrors = validationErrors;
0113 
0114     d->ui.certSelector->clear();
0115     for (const QSslCertificate &cert : certificateChain) {
0116         QString name;
0117         static const QSslCertificate::SubjectInfo si[] = {QSslCertificate::CommonName, QSslCertificate::Organization, QSslCertificate::OrganizationalUnitName};
0118         for (int j = 0; j < 3 && name.isEmpty(); j++) {
0119             name = cert.subjectInfo(si[j]).join(QLatin1String(", "));
0120         }
0121         d->ui.certSelector->addItem(name);
0122     }
0123     if (certificateChain.size() < 2) {
0124         d->ui.certSelector->setEnabled(false);
0125     }
0126     connect(d->ui.certSelector, &QComboBox::currentIndexChanged, this, &KSslInfoDialog::displayFromChain);
0127     if (d->certificateChain.isEmpty()) {
0128         d->certificateChain.append(QSslCertificate());
0129     }
0130     displayFromChain(0);
0131 
0132     d->ui.ip->setText(ip);
0133     d->ui.address->setText(host);
0134     d->ui.sslVersion->setText(sslProtocol);
0135 
0136     const QStringList cipherInfo = cipher.split(QLatin1Char('\n'), Qt::SkipEmptyParts);
0137     if (cipherInfo.size() >= 4) {
0138         d->ui.encryption->setText(i18nc("%1, using %2 bits of a %3 bit key",
0139                                         "%1, %2 %3",
0140                                         cipherInfo[0],
0141                                         i18ncp("Part of: %1, using %2 bits of a %3 bit key", "using %1 bit", "using %1 bits", usedBits),
0142                                         i18ncp("Part of: %1, using %2 bits of a %3 bit key", "of a %1 bit key", "of a %1 bit key", bits)));
0143         d->ui.details->setText(QStringLiteral("Auth = %1, Kx = %2, MAC = %3").arg(cipherInfo[1], cipherInfo[2], cipherInfo[3]));
0144     } else {
0145         d->ui.encryption->setText(QString());
0146         d->ui.details->setText(QString());
0147     }
0148 }
0149 
0150 void KSslInfoDialog::displayFromChain(int i)
0151 {
0152     const QSslCertificate &cert = d->certificateChain[i];
0153 
0154     QString trusted;
0155     const QList<QSslError::SslError> errorsList = d->certificateErrors[i];
0156     if (!errorsList.isEmpty()) {
0157         trusted = i18nc("The certificate is not trusted", "NO, there were errors:");
0158         for (QSslError::SslError e : errorsList) {
0159             QSslError classError(e);
0160             trusted += QLatin1Char('\n') + classError.errorString();
0161         }
0162     } else {
0163         trusted = i18nc("The certificate is trusted", "Yes");
0164     }
0165     d->ui.trusted->setText(trusted);
0166 
0167     QString vp =
0168         i18nc("%1 is the effective date of the certificate, %2 is the expiry date", "%1 to %2", cert.effectiveDate().toString(), cert.expiryDate().toString());
0169     d->ui.validityPeriod->setText(vp);
0170 
0171     d->ui.serial->setText(QString::fromUtf8(cert.serialNumber()));
0172     d->ui.digest->setText(QString::fromUtf8(cert.digest().toHex()));
0173     d->ui.sha1Digest->setText(QString::fromUtf8(cert.digest(QCryptographicHash::Sha1).toHex()));
0174 
0175     d->subject->setCertificate(cert, KSslCertificateBox::Subject);
0176     d->issuer->setCertificate(cert, KSslCertificateBox::Issuer);
0177 }
0178 
0179 // static
0180 QList<QList<QSslError::SslError>> KSslInfoDialog::certificateErrorsFromString(const QString &errorsString)
0181 {
0182     const QStringList sl = errorsString.split(QLatin1Char('\n'), Qt::KeepEmptyParts);
0183     QList<QList<QSslError::SslError>> ret;
0184     ret.reserve(sl.size());
0185     for (const QString &s : sl) {
0186         QList<QSslError::SslError> certErrors;
0187         const QStringList sl2 = s.split(QLatin1Char('\t'), Qt::SkipEmptyParts);
0188         for (const QString &s2 : sl2) {
0189             bool didConvert;
0190             QSslError::SslError error = static_cast<QSslError::SslError>(s2.toInt(&didConvert));
0191             if (didConvert) {
0192                 certErrors.append(error);
0193             }
0194         }
0195         ret.append(certErrors);
0196     }
0197     return ret;
0198 }
0199 
0200 #include "moc_ksslinfodialog.cpp"