• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdelibs-4.14.38 API Reference
  • KDE Home
  • Contact Us
 

KDECore

  • kdecore
  • network
  • kssld
kssld.cpp
Go to the documentation of this file.
1/*
2 This file is part of the KDE libraries
3
4 Copyright (c) 2007, 2008, 2010 Andreas Hartmetz <ahartmetz@gmail.com>
5
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public
8 License as published by the Free Software Foundation; either
9 version 2 of the License, or (at your option) any later version.
10
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
15
16 You should have received a copy of the GNU Library General Public License
17 along with this library; see the file COPYING.LIB. If not, write to
18 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 Boston, MA 02110-1301, USA.
20
21*/
22
23#include "kssld.h"
24
25#include "ksslcertificatemanager.h"
26#include "kssld_adaptor.h"
27
28#include <kconfig.h>
29#include <kconfiggroup.h>
30#include <QtCore/QFile>
31#include <kglobal.h>
32#include <kstandarddirs.h>
33#include <kdebug.h>
34#include <QtCore/QDate>
35#include <kpluginfactory.h>
36#include <kpluginloader.h>
37
38
39
40K_PLUGIN_FACTORY(KSSLDFactory, registerPlugin<KSSLD>();)
41K_EXPORT_PLUGIN(KSSLDFactory("kssld"))
42//KDE_EXPORT void *__kde_do_unload; // TODO re-add support for this?
43
44
45class KSSLDPrivate
46{
47public:
48 KSSLDPrivate()
49 : config(QString::fromLatin1("ksslcertificatemanager"), KConfig::SimpleConfig)
50 {
51 struct strErr {
52 const char *str;
53 KSslError::Error err;
54 };
55
56 //hmmm, looks like these are all of the errors where it is possible to continue.
57 const static strErr strError[] = {
58 {"NoError", KSslError::NoError},
59 {"UnknownError", KSslError::UnknownError},
60 {"InvalidCertificateAuthority", KSslError::InvalidCertificateAuthorityCertificate},
61 {"InvalidCertificate", KSslError::InvalidCertificate},
62 {"CertificateSignatureFailed", KSslError::CertificateSignatureFailed},
63 {"SelfSignedCertificate", KSslError::SelfSignedCertificate},
64 {"RevokedCertificate", KSslError::RevokedCertificate},
65 {"InvalidCertificatePurpose", KSslError::InvalidCertificatePurpose},
66 {"RejectedCertificate", KSslError::RejectedCertificate},
67 {"UntrustedCertificate", KSslError::UntrustedCertificate},
68 {"ExpiredCertificate", KSslError::ExpiredCertificate},
69 {"HostNameMismatch", KSslError::HostNameMismatch}
70 };
71
72 for (int i = 0; i < int(sizeof(strError)/sizeof(strErr)); i++) {
73 QString s = QString::fromLatin1(strError[i].str);
74 KSslError::Error e = strError[i].err;
75 stringToSslError.insert(s, e);
76 sslErrorToString.insert(e, s);
77 }
78 }
79
80 KConfig config;
81 QHash<QString, KSslError::Error> stringToSslError;
82 QHash<KSslError::Error, QString> sslErrorToString;
83};
84
85
86
87KSSLD::KSSLD(QObject* parent, const QVariantList&)
88 : KDEDModule(parent),
89 d(new KSSLDPrivate())
90{
91 new KSSLDAdaptor(this);
92 pruneExpiredRules();
93}
94
95
96KSSLD::~KSSLD()
97{
98 delete d;
99}
100
101
102void KSSLD::setRule(const KSslCertificateRule &rule)
103{
104 if (rule.hostName().isEmpty()) {
105 return;
106 }
107 KConfigGroup group = d->config.group(rule.certificate().digest().toHex());
108
109 QStringList sl;
110
111 QString dtString = QString::fromLatin1("ExpireUTC ");
112 dtString.append(rule.expiryDateTime().toString(Qt::ISODate));
113 sl.append(dtString);
114
115 if (rule.isRejected()) {
116 sl.append(QString::fromLatin1("Reject"));
117 } else {
118 foreach (KSslError::Error e, rule.ignoredErrors())
119 sl.append(d->sslErrorToString.value(e));
120 }
121
122 if (!group.hasKey("CertificatePEM"))
123 group.writeEntry("CertificatePEM", rule.certificate().toPem());
124#ifdef PARANOIA
125 else
126 if (group.readEntry("CertificatePEM") != rule.certificate().toPem())
127 return;
128#endif
129 group.writeEntry(rule.hostName(), sl);
130 group.sync();
131}
132
133
134void KSSLD::clearRule(const KSslCertificateRule &rule)
135{
136 clearRule(rule.certificate(), rule.hostName());
137}
138
139
140void KSSLD::clearRule(const QSslCertificate &cert, const QString &hostName)
141{
142 KConfigGroup group = d->config.group(cert.digest().toHex());
143 group.deleteEntry(hostName);
144 if (group.keyList().size() < 2) {
145 group.deleteGroup();
146 }
147 group.sync();
148}
149
150
151void KSSLD::pruneExpiredRules()
152{
153 // expired rules are deleted when trying to load them, so we just try to load all rules.
154 // be careful about iterating over KConfig(Group) while changing it
155 foreach (const QString &groupName, d->config.groupList()) {
156 QByteArray certDigest = groupName.toLatin1();
157 foreach (const QString &key, d->config.group(groupName).keyList()) {
158 if (key == QLatin1String("CertificatePEM")) {
159 continue;
160 }
161 KSslCertificateRule r = rule(certDigest, key);
162 }
163 }
164}
165
166
167// check a domain name with subdomains for well-formedness and count the dot-separated parts
168static QString normalizeSubdomains(const QString &hostName, int *namePartsCount)
169{
170 QString ret;
171 int partsCount = 0;
172 bool wasPrevDot = true; // -> allow no dot at the beginning and count first name part
173 const int length = hostName.length();
174 for (int i = 0; i < length; i++) {
175 const QChar c = hostName.at(i);
176 if (c == QLatin1Char('.')) {
177 if (wasPrevDot || (i + 1 == hostName.length())) {
178 // consecutive dots or a dot at the end are forbidden
179 partsCount = 0;
180 ret.clear();
181 break;
182 }
183 wasPrevDot = true;
184 } else {
185 if (wasPrevDot) {
186 partsCount++;
187 }
188 wasPrevDot = false;
189 }
190 ret.append(c);
191 }
192
193 *namePartsCount = partsCount;
194 return ret;
195}
196
197
198KSslCertificateRule KSSLD::rule(const QSslCertificate &cert, const QString &hostName) const
199{
200 const QByteArray certDigest = cert.digest().toHex();
201 KConfigGroup group = d->config.group(certDigest);
202
203 KSslCertificateRule ret(cert, hostName);
204 bool foundHostName = false;
205
206 int needlePartsCount;
207 QString needle = normalizeSubdomains(hostName, &needlePartsCount);
208
209 // Find a rule for the hostname, either...
210 if (group.hasKey(needle)) {
211 // directly (host, site.tld, a.site.tld etc)
212 if (needlePartsCount >= 1) {
213 foundHostName = true;
214 }
215 } else {
216 // or with wildcards
217 // "tld" <- "*." and "site.tld" <- "*.tld" are not valid matches,
218 // "a.site.tld" <- "*.site.tld" is
219 while (--needlePartsCount >= 2) {
220 const int dotIndex = needle.indexOf(QLatin1Char('.'));
221 Q_ASSERT(dotIndex > 0); // if this fails normalizeSubdomains() failed
222 needle.remove(0, dotIndex - 1);
223 needle[0] = QChar::fromLatin1('*');
224 if (group.hasKey(needle)) {
225 foundHostName = true;
226 break;
227 }
228 needle.remove(0, 2); // remove "*."
229 }
230 }
231
232 if (!foundHostName) {
233 //Don't make a rule with the failed wildcard pattern - use the original hostname.
234 return KSslCertificateRule(cert, hostName);
235 }
236
237 //parse entry of the format "ExpireUTC <date>, Reject" or
238 //"ExpireUTC <date>, HostNameMismatch, ExpiredCertificate, ..."
239 QStringList sl = group.readEntry(needle, QStringList());
240
241 QDateTime expiryDt;
242 // the rule is well-formed if it contains at least the expire date and one directive
243 if (sl.size() >= 2) {
244 QString dtString = sl.takeFirst();
245 if (dtString.startsWith(QLatin1String("ExpireUTC "))) {
246 dtString.remove(0, 10/* length of "ExpireUTC " */);
247 expiryDt = QDateTime::fromString(dtString, Qt::ISODate);
248 }
249 }
250
251 if (!expiryDt.isValid() || expiryDt < QDateTime::currentDateTime()) {
252 //the entry is malformed or expired so we remove it
253 group.deleteEntry(needle);
254 //the group is useless once only the CertificatePEM entry left
255 if (group.keyList().size() < 2) {
256 group.deleteGroup();
257 }
258 return ret;
259 }
260
261 QList<KSslError::Error> ignoredErrors;
262 bool isRejected = false;
263 foreach (const QString &s, sl) {
264 if (s == QLatin1String("Reject")) {
265 isRejected = true;
266 ignoredErrors.clear();
267 break;
268 }
269 if (!d->stringToSslError.contains(s)) {
270 continue;
271 }
272 ignoredErrors.append(d->stringToSslError.value(s));
273 }
274
275 //Everything is checked and we can make ret valid
276 ret.setExpiryDateTime(expiryDt);
277 ret.setRejected(isRejected);
278 ret.setIgnoredErrors(ignoredErrors);
279 return ret;
280}
281
282
283#include "kssld.moc"
284#include "kssld_adaptor.moc"
KConfigGroup
A class for one specific group in a KConfig object.
Definition: kconfiggroup.h:54
KConfig
The central class of the KDE configuration data system.
Definition: kconfig.h:71
KDEDModule
The base class for KDED modules.
Definition: kdedmodule.h:48
KSSLDAdaptor
Definition: kssld_adaptor.h:34
KSSLD::rule
KSslCertificateRule rule(const QSslCertificate &cert, const QString &hostName) const
Definition: kssld.cpp:198
KSSLD::clearRule
void clearRule(const KSslCertificateRule &rule)
Definition: kssld.cpp:134
KSSLD::~KSSLD
~KSSLD()
Definition: kssld.cpp:96
KSSLD::pruneExpiredRules
void pruneExpiredRules()
Definition: kssld.cpp:151
KSSLD::setRule
void setRule(const KSslCertificateRule &rule)
Definition: kssld.cpp:102
KSSLD::KSSLD
KSSLD(QObject *parent, const QVariantList &)
Definition: kssld.cpp:87
KSslCertificateRule
Definition: ksslcertificatemanager.h:38
KSslCertificateRule::expiryDateTime
QDateTime expiryDateTime() const
Definition: ksslcertificatemanager.cpp:116
KSslCertificateRule::setRejected
void setRejected(bool rejected)
Definition: ksslcertificatemanager.cpp:122
KSslCertificateRule::hostName
QString hostName() const
Definition: ksslcertificatemanager.cpp:104
KSslCertificateRule::ignoredErrors
QList< KSslError::Error > ignoredErrors() const
Definition: ksslcertificatemanager.cpp:163
KSslCertificateRule::certificate
QSslCertificate certificate() const
Definition: ksslcertificatemanager.cpp:98
KSslCertificateRule::setExpiryDateTime
void setExpiryDateTime(const QDateTime &dateTime)
Definition: ksslcertificatemanager.cpp:110
KSslCertificateRule::isRejected
bool isRejected() const
Definition: ksslcertificatemanager.cpp:128
KSslCertificateRule::setIgnoredErrors
void setIgnoredErrors(const QList< KSslError::Error > &errors)
Definition: ksslcertificatemanager.cpp:144
KSslError::Error
Error
Definition: ktcpsocket.h:101
KSslError::NoError
@ NoError
Definition: ktcpsocket.h:102
KSslError::SelfSignedCertificate
@ SelfSignedCertificate
Definition: ktcpsocket.h:107
KSslError::UntrustedCertificate
@ UntrustedCertificate
Definition: ktcpsocket.h:112
KSslError::ExpiredCertificate
@ ExpiredCertificate
Definition: ktcpsocket.h:108
KSslError::UnknownError
@ UnknownError
Definition: ktcpsocket.h:103
KSslError::CertificateSignatureFailed
@ CertificateSignatureFailed
Definition: ktcpsocket.h:106
KSslError::InvalidCertificatePurpose
@ InvalidCertificatePurpose
Definition: ktcpsocket.h:110
KSslError::InvalidCertificateAuthorityCertificate
@ InvalidCertificateAuthorityCertificate
Definition: ktcpsocket.h:104
KSslError::RevokedCertificate
@ RevokedCertificate
Definition: ktcpsocket.h:109
KSslError::HostNameMismatch
@ HostNameMismatch
Definition: ktcpsocket.h:114
KSslError::RejectedCertificate
@ RejectedCertificate
Definition: ktcpsocket.h:111
KSslError::InvalidCertificate
@ InvalidCertificate
Definition: ktcpsocket.h:105
QDateTime
QHash
Definition: ksycocafactory.h:28
QList
Definition: kaboutdata.h:33
QObject
QStringList
QString
kconfig.h
kconfiggroup.h
kdebug.h
kglobal.h
kpluginfactory.h
kpluginloader.h
ksslcertificatemanager.h
normalizeSubdomains
static QString normalizeSubdomains(const QString &hostName, int *namePartsCount)
Definition: kssld.cpp:168
kssld.h
kssld_adaptor.h
kstandarddirs.h
KGlobal::config
KSharedConfigPtr config()
Returns the general config object.
Definition: kglobal.cpp:139
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Mon Feb 20 2023 00:00:00 by doxygen 1.9.6 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KDECore

Skip menu "KDECore"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Modules
  • Related Pages

kdelibs-4.14.38 API Reference

Skip menu "kdelibs-4.14.38 API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal