1 | /* |
2 | This file is part of the KDE project |
3 | SPDX-FileCopyrightText: 2000, 2001 George Staikos <staikos@kde.org> |
4 | SPDX-FileCopyrightText: 2000 Malte Starostik <malte@kde.org> |
5 | |
6 | SPDX-License-Identifier: LGPL-2.0-or-later |
7 | */ |
8 | |
9 | #include "ksslinfodialog.h" |
10 | #include "ksslcertificatebox.h" |
11 | #include "ui_sslinfo.h" |
12 | |
13 | #include <QDialogButtonBox> |
14 | |
15 | #include <QSslCertificate> |
16 | |
17 | #include <KIconLoader> // BarIcon |
18 | #include <KLocalizedString> |
19 | |
20 | class Q_DECL_HIDDEN KSslInfoDialog::KSslInfoDialogPrivate |
21 | { |
22 | public: |
23 | QList<QSslCertificate> certificateChain; |
24 | QList<QList<QSslError::SslError>> certificateErrors; |
25 | |
26 | bool isMainPartEncrypted; |
27 | bool auxPartsEncrypted; |
28 | |
29 | Ui::SslInfo ui; |
30 | KSslCertificateBox *subject; |
31 | KSslCertificateBox *issuer; |
32 | }; |
33 | |
34 | KSslInfoDialog::KSslInfoDialog(QWidget *parent) |
35 | : QDialog(parent) |
36 | , d(new KSslInfoDialogPrivate) |
37 | { |
38 | setWindowTitle(i18n("KDE SSL Information" )); |
39 | setAttribute(Qt::WA_DeleteOnClose); |
40 | |
41 | QVBoxLayout *layout = new QVBoxLayout(this); |
42 | |
43 | QWidget *mainWidget = new QWidget(this); |
44 | d->ui.setupUi(mainWidget); |
45 | layout->addWidget(mainWidget); |
46 | |
47 | d->subject = new KSslCertificateBox(d->ui.certParties); |
48 | d->issuer = new KSslCertificateBox(d->ui.certParties); |
49 | d->ui.certParties->addTab(widget: d->subject, i18nc("The receiver of the SSL certificate" , "Subject" )); |
50 | d->ui.certParties->addTab(widget: d->issuer, i18nc("The authority that issued the SSL certificate" , "Issuer" )); |
51 | |
52 | d->isMainPartEncrypted = true; |
53 | d->auxPartsEncrypted = true; |
54 | updateWhichPartsEncrypted(); |
55 | |
56 | QDialogButtonBox *buttonBox = new QDialogButtonBox(this); |
57 | buttonBox->setStandardButtons(QDialogButtonBox::Close); |
58 | connect(sender: buttonBox, signal: &QDialogButtonBox::accepted, context: this, slot: &QDialog::accept); |
59 | connect(sender: buttonBox, signal: &QDialogButtonBox::rejected, context: this, slot: &QDialog::reject); |
60 | layout->addWidget(buttonBox); |
61 | } |
62 | |
63 | KSslInfoDialog::~KSslInfoDialog() = default; |
64 | |
65 | void KSslInfoDialog::setMainPartEncrypted(bool mainEncrypted) |
66 | { |
67 | d->isMainPartEncrypted = mainEncrypted; |
68 | updateWhichPartsEncrypted(); |
69 | } |
70 | |
71 | void KSslInfoDialog::setAuxiliaryPartsEncrypted(bool auxEncrypted) |
72 | { |
73 | d->auxPartsEncrypted = auxEncrypted; |
74 | updateWhichPartsEncrypted(); |
75 | } |
76 | |
77 | void KSslInfoDialog::updateWhichPartsEncrypted() |
78 | { |
79 | if (d->isMainPartEncrypted) { |
80 | if (d->auxPartsEncrypted) { |
81 | d->ui.encryptionIndicator->setPixmap(QIcon::fromTheme(QStringLiteral("security-high" )).pixmap(extent: KIconLoader::SizeSmallMedium)); |
82 | d->ui.explanation->setText(i18n("Current connection is secured with SSL." )); |
83 | } else { |
84 | d->ui.encryptionIndicator->setPixmap(QIcon::fromTheme(QStringLiteral("security-medium" )).pixmap(extent: KIconLoader::SizeSmallMedium)); |
85 | d->ui.explanation->setText( |
86 | i18n("The main part of this document is secured " |
87 | "with SSL, but some parts are not." )); |
88 | } |
89 | } else { |
90 | if (d->auxPartsEncrypted) { |
91 | d->ui.encryptionIndicator->setPixmap(QIcon::fromTheme(QStringLiteral("security-medium" )).pixmap(extent: KIconLoader::SizeSmallMedium)); |
92 | d->ui.explanation->setText( |
93 | i18n("Some of this document is secured with SSL, " |
94 | "but the main part is not." )); |
95 | } else { |
96 | d->ui.encryptionIndicator->setPixmap(QIcon::fromTheme(QStringLiteral("security-low" )).pixmap(extent: KIconLoader::SizeSmallMedium)); |
97 | d->ui.explanation->setText(i18n("Current connection is not secured with SSL." )); |
98 | } |
99 | } |
100 | } |
101 | |
102 | void KSslInfoDialog::setSslInfo(const QList<QSslCertificate> &certificateChain, |
103 | const QString &ip, |
104 | const QString &host, |
105 | const QString &sslProtocol, |
106 | const QString &cipher, |
107 | int usedBits, |
108 | int bits, |
109 | const QList<QList<QSslError::SslError>> &validationErrors) |
110 | { |
111 | d->certificateChain = certificateChain; |
112 | d->certificateErrors = validationErrors; |
113 | |
114 | d->ui.certSelector->clear(); |
115 | for (const QSslCertificate &cert : certificateChain) { |
116 | QString name; |
117 | static const QSslCertificate::SubjectInfo si[] = {QSslCertificate::CommonName, QSslCertificate::Organization, QSslCertificate::OrganizationalUnitName}; |
118 | for (int j = 0; j < 3 && name.isEmpty(); j++) { |
119 | name = cert.subjectInfo(info: si[j]).join(sep: QLatin1String(", " )); |
120 | } |
121 | d->ui.certSelector->addItem(atext: name); |
122 | } |
123 | if (certificateChain.size() < 2) { |
124 | d->ui.certSelector->setEnabled(false); |
125 | } |
126 | connect(sender: d->ui.certSelector, signal: &QComboBox::currentIndexChanged, context: this, slot: &KSslInfoDialog::displayFromChain); |
127 | if (d->certificateChain.isEmpty()) { |
128 | d->certificateChain.append(t: QSslCertificate()); |
129 | } |
130 | displayFromChain(0); |
131 | |
132 | d->ui.ip->setText(ip); |
133 | d->ui.address->setText(host); |
134 | d->ui.sslVersion->setText(sslProtocol); |
135 | |
136 | const QStringList cipherInfo = cipher.split(sep: QLatin1Char('\n'), behavior: Qt::SkipEmptyParts); |
137 | if (cipherInfo.size() >= 4) { |
138 | d->ui.encryption->setText(i18nc("%1, using %2 bits of a %3 bit key" , |
139 | "%1, %2 %3" , |
140 | cipherInfo[0], |
141 | i18ncp("Part of: %1, using %2 bits of a %3 bit key" , "using %1 bit" , "using %1 bits" , usedBits), |
142 | i18ncp("Part of: %1, using %2 bits of a %3 bit key" , "of a %1 bit key" , "of a %1 bit key" , bits))); |
143 | d->ui.details->setText(QStringLiteral("Auth = %1, Kx = %2, MAC = %3" ).arg(args: cipherInfo[1], args: cipherInfo[2], args: cipherInfo[3])); |
144 | } else { |
145 | d->ui.encryption->setText(QString()); |
146 | d->ui.details->setText(QString()); |
147 | } |
148 | } |
149 | |
150 | void KSslInfoDialog::displayFromChain(int i) |
151 | { |
152 | const QSslCertificate &cert = d->certificateChain[i]; |
153 | |
154 | QString trusted; |
155 | const QList<QSslError::SslError> errorsList = d->certificateErrors[i]; |
156 | if (!errorsList.isEmpty()) { |
157 | trusted = i18nc("The certificate is not trusted" , "NO, there were errors:" ); |
158 | for (QSslError::SslError e : errorsList) { |
159 | QSslError classError(e); |
160 | trusted += QLatin1Char('\n') + classError.errorString(); |
161 | } |
162 | } else { |
163 | trusted = i18nc("The certificate is trusted" , "Yes" ); |
164 | } |
165 | d->ui.trusted->setText(trusted); |
166 | |
167 | QString vp = |
168 | i18nc("%1 is the effective date of the certificate, %2 is the expiry date" , "%1 to %2" , cert.effectiveDate().toString(), cert.expiryDate().toString()); |
169 | d->ui.validityPeriod->setText(vp); |
170 | |
171 | d->ui.serial->setText(QString::fromUtf8(ba: cert.serialNumber())); |
172 | d->ui.digest->setText(QString::fromUtf8(ba: cert.digest().toHex())); |
173 | d->ui.sha1Digest->setText(QString::fromUtf8(ba: cert.digest(algorithm: QCryptographicHash::Sha1).toHex())); |
174 | |
175 | d->subject->setCertificate(cert, party: KSslCertificateBox::Subject); |
176 | d->issuer->setCertificate(cert, party: KSslCertificateBox::Issuer); |
177 | } |
178 | |
179 | // static |
180 | QList<QList<QSslError::SslError>> KSslInfoDialog::certificateErrorsFromString(const QString &) |
181 | { |
182 | const QStringList sl = errorsString.split(sep: QLatin1Char('\n'), behavior: Qt::KeepEmptyParts); |
183 | QList<QList<QSslError::SslError>> ret; |
184 | ret.reserve(asize: sl.size()); |
185 | for (const QString &s : sl) { |
186 | QList<QSslError::SslError> certErrors; |
187 | const QStringList sl2 = s.split(sep: QLatin1Char('\t'), behavior: Qt::SkipEmptyParts); |
188 | for (const QString &s2 : sl2) { |
189 | bool didConvert; |
190 | QSslError::SslError error = static_cast<QSslError::SslError>(s2.toInt(ok: &didConvert)); |
191 | if (didConvert) { |
192 | certErrors.append(t: error); |
193 | } |
194 | } |
195 | ret.append(t: certErrors); |
196 | } |
197 | return ret; |
198 | } |
199 | |
200 | #include "moc_ksslinfodialog.cpp" |
201 | |