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"