summaryrefslogtreecommitdiffstats
path: root/kio/misc/kssld
diff options
context:
space:
mode:
Diffstat (limited to 'kio/misc/kssld')
-rw-r--r--kio/misc/kssld/Makefile.am33
-rw-r--r--kio/misc/kssld/kssld.cpp1027
-rw-r--r--kio/misc/kssld/kssld.desktop156
-rw-r--r--kio/misc/kssld/kssld.h154
4 files changed, 1370 insertions, 0 deletions
diff --git a/kio/misc/kssld/Makefile.am b/kio/misc/kssld/Makefile.am
new file mode 100644
index 000000000..63252f46c
--- /dev/null
+++ b/kio/misc/kssld/Makefile.am
@@ -0,0 +1,33 @@
+# This file is part of the KDE libraries
+# Copyright (C) 2001 George Staikos <staikos@kde.org>
+
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Library General Public License for more details.
+
+# You should have received a copy of the GNU Library General Public License
+# along with this library; see the file COPYING.LIB. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301, USA.
+
+INCLUDES= -I$(srcdir)/.. -I$(top_srcdir) $(SSL_INCLUDES) -I$(top_srcdir)/kio/kssl -I$(top_builddir)/kio/kssl $(all_includes)
+
+kde_module_LTLIBRARIES = kded_kssld.la
+
+kded_kssld_la_LDFLAGS = $(all_libraries) -module -avoid-version
+kded_kssld_la_LIBADD = $(LIB_KIO) $(LIB_KDED)
+kded_kssld_la_SOURCES = kssld.cpp kssld.skel
+
+METASOURCES = AUTO
+
+noinst_HEADERS = kssld.h
+
+services_DATA = kssld.desktop
+servicesdir = $(kde_servicesdir)/kded
+
diff --git a/kio/misc/kssld/kssld.cpp b/kio/misc/kssld/kssld.cpp
new file mode 100644
index 000000000..ff96681e2
--- /dev/null
+++ b/kio/misc/kssld/kssld.cpp
@@ -0,0 +1,1027 @@
+/*
+ This file is part of the KDE libraries
+
+ Copyright (c) 2001-2005 George Staikos <staikos@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <qtimer.h>
+
+#include "kssld.h"
+#include <kconfig.h>
+#include <ksimpleconfig.h>
+#include <ksslcertchain.h>
+#include <ksslcertificate.h>
+#include <ksslcertificatehome.h>
+#include <ksslpkcs12.h>
+#include <ksslx509map.h>
+#include <qptrlist.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <pwd.h>
+#include <unistd.h>
+#include <qfile.h>
+#include <qsortedlist.h>
+#include <kglobal.h>
+#include <kstandarddirs.h>
+#include <kdebug.h>
+#include <qdatetime.h>
+
+#include <kmdcodec.h>
+#include <kopenssl.h>
+
+// See design notes at end
+
+extern "C" {
+ KDE_EXPORT KDEDModule *create_kssld(const QCString &name) {
+ return new KSSLD(name);
+ }
+
+ KDE_EXPORT void *__kde_do_unload;
+}
+
+
+static void updatePoliciesConfig(KConfig *cfg) {
+ QStringList groups = cfg->groupList();
+
+ for (QStringList::Iterator i = groups.begin(); i != groups.end(); ++i) {
+ if ((*i).isEmpty() || *i == "General") {
+ continue;
+ }
+
+ cfg->setGroup(*i);
+
+ // remove it if it has expired
+ if (!cfg->readBoolEntry("Permanent") && cfg->readDateTimeEntry("Expires") < QDateTime::currentDateTime()) {
+ cfg->deleteGroup(*i);
+ continue;
+ }
+
+ QString encodedCertStr = cfg->readEntry("Certificate");
+ QCString encodedCert = encodedCertStr.local8Bit();
+ KSSLCertificate *newCert = KSSLCertificate::fromString(encodedCert);
+ if (!newCert) {
+ cfg->deleteGroup(*i);
+ continue;
+ }
+
+ KSSLCertificateCache::KSSLCertificatePolicy policy = (KSSLCertificateCache::KSSLCertificatePolicy) cfg->readNumEntry("Policy");
+ bool permanent = cfg->readBoolEntry("Permanent");
+ QDateTime expires = cfg->readDateTimeEntry("Expires");
+ QStringList hosts = cfg->readListEntry("Hosts");
+ QStringList chain = cfg->readListEntry("Chain");
+ cfg->deleteGroup(*i);
+
+ cfg->setGroup(newCert->getMD5Digest());
+ cfg->writeEntry("Certificate", encodedCertStr);
+ cfg->writeEntry("Policy", policy);
+ cfg->writeEntry("Permanent", permanent);
+ cfg->writeEntry("Expires", expires);
+ cfg->writeEntry("Hosts", hosts);
+ cfg->writeEntry("Chain", chain);
+ delete newCert;
+ }
+
+ cfg->setGroup("General");
+ cfg->writeEntry("policies version", 2);
+
+ cfg->sync();
+}
+
+
+KSSLD::KSSLD(const QCString &name) : KDEDModule(name)
+{
+// ----------------------- FOR THE CACHE ------------------------------------
+ cfg = new KSimpleConfig("ksslpolicies", false);
+ cfg->setGroup("General");
+ if (2 != cfg->readNumEntry("policies version", 0)) {
+ ::updatePoliciesConfig(cfg);
+ }
+ KGlobal::dirs()->addResourceType("kssl", KStandardDirs::kde_default("data") + "kssl");
+ caVerifyUpdate();
+ cacheLoadDefaultPolicies();
+ certList.setAutoDelete(false);
+ kossl = KOSSL::self();
+
+// ----------------------- FOR THE HOME -------------------------------------
+}
+
+
+KSSLD::~KSSLD()
+{
+// ----------------------- FOR THE CACHE ------------------------------------
+ cacheClearList();
+ delete cfg;
+
+// ----------------------- FOR THE HOME -------------------------------------
+}
+
+
+
+
+// A node in the cache
+class KSSLCNode {
+ public:
+ KSSLCertificate *cert;
+ KSSLCertificateCache::KSSLCertificatePolicy policy;
+ bool permanent;
+ QDateTime expires;
+ QStringList hosts;
+ KSSLCNode() { cert = 0L;
+ policy = KSSLCertificateCache::Unknown;
+ permanent = true;
+ }
+ ~KSSLCNode() { delete cert; }
+};
+
+
+
+void KSSLD::cacheSaveToDisk() {
+KSSLCNode *node;
+
+ cfg->setGroup("General");
+ cfg->writeEntry("policies version", 2);
+
+ for (node = certList.first(); node; node = certList.next()) {
+ if (node->permanent ||
+ node->expires > QDateTime::currentDateTime()) {
+ // First convert to a binary format and then write the
+ // kconfig entry write the (CN, policy, cert) to
+ // KSimpleConfig
+ cfg->setGroup(node->cert->getMD5Digest());
+ cfg->writeEntry("Certificate", node->cert->toString());
+ cfg->writeEntry("Policy", node->policy);
+ cfg->writeEntry("Expires", node->expires);
+ cfg->writeEntry("Permanent", node->permanent);
+ cfg->writeEntry("Hosts", node->hosts);
+
+ // Also write the chain
+ QStringList qsl;
+ QPtrList<KSSLCertificate> cl =
+ node->cert->chain().getChain();
+ for (KSSLCertificate *c = cl.first();
+ c != 0;
+ c = cl.next()) {
+ //kdDebug() << "Certificate in chain: "
+ // << c->toString() << endl;
+ qsl << c->toString();
+ }
+
+ cl.setAutoDelete(true);
+ cfg->writeEntry("Chain", qsl);
+ }
+ }
+
+ cfg->sync();
+
+ // insure proper permissions -- contains sensitive data
+ QString cfgName(KGlobal::dirs()->findResource("config", "ksslpolicies"));
+
+ if (!cfgName.isEmpty()) {
+ ::chmod(QFile::encodeName(cfgName), 0600);
+ }
+}
+
+
+void KSSLD::cacheReload() {
+ cacheClearList();
+ delete cfg;
+ cfg = new KSimpleConfig("ksslpolicies", false);
+ cacheLoadDefaultPolicies();
+}
+
+
+void KSSLD::cacheClearList() {
+KSSLCNode *node;
+
+ for (node = certList.first(); node; node = certList.next()) {
+ certList.remove(node);
+ delete node;
+ }
+
+ skEmail.clear();
+ skMD5Digest.clear();
+}
+
+
+void KSSLD::cacheLoadDefaultPolicies() {
+QStringList groups = cfg->groupList();
+
+ for (QStringList::Iterator i = groups.begin();
+ i != groups.end();
+ ++i) {
+ if ((*i).isEmpty() || *i == "General") {
+ continue;
+ }
+
+ cfg->setGroup(*i);
+
+ // remove it if it has expired
+ if (!cfg->readBoolEntry("Permanent") &&
+ cfg->readDateTimeEntry("Expires") <
+ QDateTime::currentDateTime()) {
+ cfg->deleteGroup(*i);
+ continue;
+ }
+
+ QCString encodedCert;
+ KSSLCertificate *newCert;
+
+ encodedCert = cfg->readEntry("Certificate").local8Bit();
+ newCert = KSSLCertificate::fromString(encodedCert);
+
+ if (!newCert) {
+ continue;
+ }
+
+ KSSLCNode *n = new KSSLCNode;
+ n->cert = newCert;
+ n->policy = (KSSLCertificateCache::KSSLCertificatePolicy) cfg->readNumEntry("Policy");
+ n->permanent = cfg->readBoolEntry("Permanent");
+ n->expires = cfg->readDateTimeEntry("Expires");
+ n->hosts = cfg->readListEntry("Hosts");
+ newCert->chain().setCertChain(cfg->readListEntry("Chain"));
+ certList.append(n);
+ searchAddCert(newCert);
+ }
+}
+
+
+void KSSLD::cacheAddCertificate(KSSLCertificate cert,
+ KSSLCertificateCache::KSSLCertificatePolicy policy,
+ bool permanent) {
+KSSLCNode *node;
+
+ for (node = certList.first(); node; node = certList.next()) {
+ if (cert == *(node->cert)) {
+ node->policy = policy;
+ node->permanent = permanent;
+
+ if (!permanent) {
+ node->expires = QDateTime::currentDateTime();
+ // FIXME: make this configurable
+ node->expires = node->expires.addSecs(3600);
+ }
+
+ cacheSaveToDisk();
+ return;
+ }
+ }
+
+ KSSLCNode *n = new KSSLCNode;
+ n->cert = cert.replicate();
+ n->policy = policy;
+ n->permanent = permanent;
+ // remove the old one
+ cacheRemoveByCertificate(*(n->cert));
+ certList.prepend(n);
+
+ if (!permanent) {
+ n->expires = QDateTime::currentDateTime();
+ n->expires = n->expires.addSecs(3600);
+ }
+
+ searchAddCert(n->cert);
+ cacheSaveToDisk();
+}
+
+
+KSSLCertificateCache::KSSLCertificatePolicy KSSLD::cacheGetPolicyByCN(QString cn) {
+KSSLCNode *node;
+
+ for (node = certList.first(); node; node = certList.next()) {
+ if (KSSLX509Map(node->cert->getSubject()).getValue("CN") == cn) {
+ if (!node->permanent &&
+ node->expires < QDateTime::currentDateTime()) {
+ certList.remove(node);
+ cfg->deleteGroup(node->cert->getMD5Digest());
+ delete node;
+ continue;
+ }
+
+ certList.remove(node);
+ certList.prepend(node);
+ cacheSaveToDisk();
+ return node->policy;
+ }
+ }
+
+ cacheSaveToDisk();
+
+return KSSLCertificateCache::Unknown;
+}
+
+
+KSSLCertificateCache::KSSLCertificatePolicy KSSLD::cacheGetPolicyByCertificate(KSSLCertificate cert) {
+KSSLCNode *node;
+
+ for (node = certList.first(); node; node = certList.next()) {
+ if (cert == *(node->cert)) {
+ if (!node->permanent &&
+ node->expires < QDateTime::currentDateTime()) {
+ certList.remove(node);
+ cfg->deleteGroup(node->cert->getMD5Digest());
+ delete node;
+ cacheSaveToDisk();
+ return KSSLCertificateCache::Unknown;
+ }
+
+ certList.remove(node);
+ certList.prepend(node);
+ return node->policy;
+ }
+ }
+
+return KSSLCertificateCache::Unknown;
+}
+
+
+bool KSSLD::cacheSeenCN(QString cn) {
+KSSLCNode *node;
+
+ for (node = certList.first(); node; node = certList.next()) {
+ if (KSSLX509Map(node->cert->getSubject()).getValue("CN") == cn) {
+ if (!node->permanent &&
+ node->expires < QDateTime::currentDateTime()) {
+ certList.remove(node);
+ cfg->deleteGroup(node->cert->getMD5Digest());
+ delete node;
+ cacheSaveToDisk();
+ continue;
+ }
+
+ certList.remove(node);
+ certList.prepend(node);
+ return true;
+ }
+ }
+
+return false;
+}
+
+
+bool KSSLD::cacheSeenCertificate(KSSLCertificate cert) {
+KSSLCNode *node;
+
+ for (node = certList.first(); node; node = certList.next()) {
+ if (cert == *(node->cert)) {
+ if (!node->permanent &&
+ node->expires < QDateTime::currentDateTime()) {
+ certList.remove(node);
+ cfg->deleteGroup(node->cert->getMD5Digest());
+ delete node;
+ cacheSaveToDisk();
+ return false;
+ }
+
+ certList.remove(node);
+ certList.prepend(node);
+ return true;
+ }
+ }
+
+return false;
+}
+
+
+bool KSSLD::cacheIsPermanent(KSSLCertificate cert) {
+KSSLCNode *node;
+
+ for (node = certList.first(); node; node = certList.next()) {
+ if (cert == *(node->cert)) {
+ if (!node->permanent && node->expires <
+ QDateTime::currentDateTime()) {
+ certList.remove(node);
+ cfg->deleteGroup(node->cert->getMD5Digest());
+ delete node;
+ cacheSaveToDisk();
+ return false;
+ }
+
+ certList.remove(node);
+ certList.prepend(node);
+ return node->permanent;
+ }
+ }
+
+return false;
+}
+
+
+bool KSSLD::cacheRemoveBySubject(QString subject) {
+KSSLCNode *node;
+bool gotOne = false;
+
+ for (node = certList.first(); node; node = certList.next()) {
+ if (node->cert->getSubject() == subject) {
+ certList.remove(node);
+ cfg->deleteGroup(node->cert->getMD5Digest());
+ searchRemoveCert(node->cert);
+ delete node;
+ gotOne = true;
+ }
+ }
+
+ cacheSaveToDisk();
+
+return gotOne;
+}
+
+
+bool KSSLD::cacheRemoveByCN(QString cn) {
+KSSLCNode *node;
+bool gotOne = false;
+
+ for (node = certList.first(); node; node = certList.next()) {
+ if (KSSLX509Map(node->cert->getSubject()).getValue("CN") == cn) {
+ certList.remove(node);
+ cfg->deleteGroup(node->cert->getMD5Digest());
+ searchRemoveCert(node->cert);
+ delete node;
+ gotOne = true;
+ }
+ }
+
+ cacheSaveToDisk();
+
+return gotOne;
+}
+
+
+bool KSSLD::cacheRemoveByCertificate(KSSLCertificate cert) {
+KSSLCNode *node;
+
+ for (node = certList.first(); node; node = certList.next()) {
+ if (cert == *(node->cert)) {
+ certList.remove(node);
+ cfg->deleteGroup(node->cert->getMD5Digest());
+ searchRemoveCert(node->cert);
+ delete node;
+ cacheSaveToDisk();
+ return true;
+ }
+ }
+
+return false;
+}
+
+
+bool KSSLD::cacheModifyByCN(QString cn,
+ KSSLCertificateCache::KSSLCertificatePolicy policy, bool permanent,
+ QDateTime expires) {
+KSSLCNode *node;
+
+ for (node = certList.first(); node; node = certList.next()) {
+ if (KSSLX509Map(node->cert->getSubject()).getValue("CN") == cn) {
+ node->permanent = permanent;
+ node->expires = expires;
+ node->policy = policy;
+ certList.remove(node);
+ certList.prepend(node);
+ cacheSaveToDisk();
+ return true;
+ }
+ }
+
+return false;
+}
+
+
+bool KSSLD::cacheModifyByCertificate(KSSLCertificate cert,
+ KSSLCertificateCache::KSSLCertificatePolicy policy,
+ bool permanent,
+ QDateTime expires) {
+KSSLCNode *node;
+
+ for (node = certList.first(); node; node = certList.next()) {
+ if (cert == *(node->cert)) {
+ node->permanent = permanent;
+ node->expires = expires;
+ node->policy = policy;
+ certList.remove(node);
+ certList.prepend(node);
+ cacheSaveToDisk();
+ return true;
+ }
+ }
+
+return false;
+}
+
+
+QStringList KSSLD::cacheGetHostList(KSSLCertificate cert) {
+KSSLCNode *node;
+
+ for (node = certList.first(); node; node = certList.next()) {
+ if (cert == *(node->cert)) {
+ if (!node->permanent && node->expires <
+ QDateTime::currentDateTime()) {
+ certList.remove(node);
+ cfg->deleteGroup(node->cert->getMD5Digest());
+ searchRemoveCert(node->cert);
+ delete node;
+ cacheSaveToDisk();
+ return QStringList();
+ }
+
+ certList.remove(node);
+ certList.prepend(node);
+ return node->hosts;
+ }
+ }
+
+return QStringList();
+}
+
+
+bool KSSLD::cacheAddHost(KSSLCertificate cert, QString host) {
+KSSLCNode *node;
+
+ if (host.isEmpty())
+ return true;
+
+ for (node = certList.first(); node; node = certList.next()) {
+ if (cert == *(node->cert)) {
+ if (!node->permanent && node->expires <
+ QDateTime::currentDateTime()) {
+ certList.remove(node);
+ cfg->deleteGroup(node->cert->getMD5Digest());
+ searchRemoveCert(node->cert);
+ delete node;
+ cacheSaveToDisk();
+ return false;
+ }
+
+ if (!node->hosts.contains(host)) {
+ node->hosts << host;
+ }
+
+ certList.remove(node);
+ certList.prepend(node);
+ cacheSaveToDisk();
+ return true;
+ }
+ }
+
+return false;
+}
+
+
+bool KSSLD::cacheRemoveHost(KSSLCertificate cert, QString host) {
+KSSLCNode *node;
+
+ for (node = certList.first(); node; node = certList.next()) {
+ if (cert == *(node->cert)) {
+ if (!node->permanent && node->expires <
+ QDateTime::currentDateTime()) {
+ certList.remove(node);
+ cfg->deleteGroup(node->cert->getMD5Digest());
+ searchRemoveCert(node->cert);
+ delete node;
+ cacheSaveToDisk();
+ return false;
+ }
+ node->hosts.remove(host);
+ certList.remove(node);
+ certList.prepend(node);
+ cacheSaveToDisk();
+ return true;
+ }
+ }
+
+return false;
+}
+
+
+
+
+///////////////////////////////////////////////////////////////////////////
+
+void KSSLD::caVerifyUpdate() {
+ QString path = KGlobal::dirs()->saveLocation("kssl") + "/ca-bundle.crt";
+ if (!QFile::exists(path))
+ return;
+
+ cfg->setGroup(QString::null);
+ Q_UINT32 newStamp = KGlobal::dirs()->calcResourceHash("config", "ksslcalist", true);
+ Q_UINT32 oldStamp = cfg->readUnsignedNumEntry("ksslcalistStamp");
+ if (oldStamp != newStamp)
+ {
+ caRegenerate();
+ cfg->writeEntry("ksslcalistStamp", newStamp);
+ cfg->sync();
+ }
+}
+
+bool KSSLD::caRegenerate() {
+QString path = KGlobal::dirs()->saveLocation("kssl") + "/ca-bundle.crt";
+
+QFile out(path);
+
+ if (!out.open(IO_WriteOnly))
+ return false;
+
+KConfig cfg("ksslcalist", true, false);
+
+QStringList x = cfg.groupList();
+
+ for (QStringList::Iterator i = x.begin();
+ i != x.end();
+ ++i) {
+ if ((*i).isEmpty() || *i == "<default>") continue;
+
+ cfg.setGroup(*i);
+
+ if (!cfg.readBoolEntry("site", false)) continue;
+
+ QString cert = cfg.readEntry("x509", "");
+ if (cert.length() <= 0) continue;
+
+ unsigned int xx = cert.length() - 1;
+ for (unsigned int j = 0; j < xx/64; j++) {
+ cert.insert(64*(j+1)+j, '\n');
+ }
+ out.writeBlock("-----BEGIN CERTIFICATE-----\n", 28);
+ out.writeBlock(cert.latin1(), cert.length());
+ out.writeBlock("\n-----END CERTIFICATE-----\n\n", 28);
+ out.flush();
+ }
+
+return true;
+}
+
+
+
+bool KSSLD::caAdd(QString certificate, bool ssl, bool email, bool code) {
+KSSLCertificate *x = KSSLCertificate::fromString(certificate.local8Bit());
+
+ if (!x) return false;
+
+KConfig cfg("ksslcalist", false, false);
+
+ cfg.setGroup(x->getSubject());
+ cfg.writeEntry("x509", certificate);
+ cfg.writeEntry("site", ssl);
+ cfg.writeEntry("email", email);
+ cfg.writeEntry("code", code);
+
+ cfg.sync();
+ delete x;
+
+return true;
+}
+
+
+/**
+ * @internal
+ * Returns a list of certificates as QStrings read from the given file
+ */
+static QStringList caReadCerticatesFromFile(QString filename) {
+
+ QStringList certificates;
+ QString certificate, temp;
+ QFile file(filename);
+
+ if (!file.open(IO_ReadOnly))
+ return certificates;
+
+ while (!file.atEnd()) {
+ file.readLine(temp, 999);
+ if (temp.startsWith("-----BEGIN CERTIFICATE-----")) {
+ certificate = QString::null;
+ continue;
+ }
+
+ if (temp.startsWith("-----END CERTIFICATE-----")) {
+ certificates.append(certificate);
+ certificate = QString::null;
+ continue;
+ }
+
+ certificate += temp.stripWhiteSpace();
+ }
+
+ file.close();
+
+ return certificates;
+}
+
+bool KSSLD::caAddFromFile(QString filename, bool ssl, bool email, bool code) {
+
+ QStringList certificates;
+ certificates = caReadCerticatesFromFile(filename);
+ if (certificates.isEmpty())
+ return false;
+
+ bool ok = true;
+
+ for (QStringList::Iterator it = certificates.begin();
+ it != certificates.end(); ++it ) {
+ ok &= caAdd(*it, ssl, email, code);
+ }
+
+ return ok;
+}
+
+bool KSSLD::caRemoveFromFile(QString filename) {
+
+ QStringList certificates;
+ certificates = caReadCerticatesFromFile(filename);
+ if (certificates.isEmpty())
+ return false;
+
+ bool ok = true;
+
+ for (QStringList::Iterator it = certificates.begin();
+ it != certificates.end(); ++it ) {
+ QString certificate = *it;
+ KSSLCertificate *x = KSSLCertificate::fromString(certificate.local8Bit());
+ ok &= x && caRemove(x->getSubject());
+ delete x;
+ }
+
+ return ok;
+}
+
+
+QStringList KSSLD::caList() {
+QStringList x;
+KConfig cfg("ksslcalist", true, false);
+
+ x = cfg.groupList();
+ x.remove("<default>");
+
+return x;
+}
+
+
+bool KSSLD::caUseForSSL(QString subject) {
+KConfig cfg("ksslcalist", true, false);
+
+ if (!cfg.hasGroup(subject))
+ return false;
+
+ cfg.setGroup(subject);
+return cfg.readBoolEntry("site", false);
+}
+
+
+
+bool KSSLD::caUseForEmail(QString subject) {
+KConfig cfg("ksslcalist", true, false);
+
+ if (!cfg.hasGroup(subject))
+ return false;
+
+ cfg.setGroup(subject);
+return cfg.readBoolEntry("email", false);
+}
+
+
+
+bool KSSLD::caUseForCode(QString subject) {
+KConfig cfg("ksslcalist", true, false);
+
+ if (!cfg.hasGroup(subject))
+ return false;
+
+ cfg.setGroup(subject);
+return cfg.readBoolEntry("code", false);
+}
+
+
+bool KSSLD::caRemove(QString subject) {
+KConfig cfg("ksslcalist", false, false);
+ if (!cfg.hasGroup(subject))
+ return false;
+
+ cfg.deleteGroup(subject);
+ cfg.sync();
+
+return true;
+}
+
+
+QString KSSLD::caGetCert(QString subject) {
+KConfig cfg("ksslcalist", true, false);
+ if (!cfg.hasGroup(subject))
+ return QString::null;
+
+ cfg.setGroup(subject);
+
+return cfg.readEntry("x509", QString::null);
+}
+
+
+bool KSSLD::caSetUse(QString subject, bool ssl, bool email, bool code) {
+KConfig cfg("ksslcalist", false, false);
+ if (!cfg.hasGroup(subject))
+ return false;
+
+ cfg.setGroup(subject);
+
+ cfg.writeEntry("site", ssl);
+ cfg.writeEntry("email", email);
+ cfg.writeEntry("code", code);
+ cfg.sync();
+
+return true;
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+void KSSLD::searchAddCert(KSSLCertificate *cert) {
+ skMD5Digest.insert(cert->getMD5Digest(), cert, true);
+
+ QStringList mails;
+ cert->getEmails(mails);
+ for(QStringList::const_iterator iter = mails.begin(); iter != mails.end(); ++iter) {
+ QString email = static_cast<const QString &>(*iter).lower();
+ QMap<QString, QPtrVector<KSSLCertificate> >::iterator it = skEmail.find(email);
+
+ if (it == skEmail.end())
+ it = skEmail.insert(email, QPtrVector<KSSLCertificate>());
+
+ QPtrVector<KSSLCertificate> &elem = *it;
+
+ if (elem.findRef(cert) == -1) {
+ unsigned int n = 0;
+ for(; n < elem.size(); n++) {
+ if (!elem.at(n)) {
+ elem.insert(n, cert);
+ break;
+ }
+ }
+ if (n == elem.size()) {
+ elem.resize(n+1);
+ elem.insert(n, cert);
+ }
+ }
+ }
+}
+
+
+void KSSLD::searchRemoveCert(KSSLCertificate *cert) {
+ skMD5Digest.remove(cert->getMD5Digest());
+
+ QStringList mails;
+ cert->getEmails(mails);
+ for(QStringList::const_iterator iter = mails.begin(); iter != mails.end(); ++iter) {
+ QMap<QString, QPtrVector<KSSLCertificate> >::iterator it = skEmail.find(static_cast<const QString &>(*iter).lower());
+
+ if (it == skEmail.end())
+ break;
+
+ QPtrVector<KSSLCertificate> &elem = *it;
+
+ int n = elem.findRef(cert);
+ if (n != -1)
+ elem.remove(n);
+ }
+}
+
+
+QStringList KSSLD::getKDEKeyByEmail(const QString &email) {
+ QStringList rc;
+ QMap<QString, QPtrVector<KSSLCertificate> >::iterator it = skEmail.find(email.lower());
+
+ kdDebug() << "GETKDEKey " << email.latin1() << endl;
+
+ if (it == skEmail.end())
+ return rc;
+
+ QPtrVector<KSSLCertificate> &elem = *it;
+ for (unsigned int n = 0; n < elem.size(); n++) {
+ KSSLCertificate *cert = elem.at(n);
+ if (cert) {
+ rc.append(cert->getKDEKey());
+ }
+ }
+
+ kdDebug() << "ergebnisse: " << rc.size() << " " << elem.size() << endl;
+ return rc;
+}
+
+
+KSSLCertificate KSSLD::getCertByMD5Digest(const QString &key) {
+ QMap<QString, KSSLCertificate *>::iterator iter = skMD5Digest.find(key);
+
+ kdDebug() << "Searching cert for " << key.latin1() << endl;
+
+ if (iter != skMD5Digest.end())
+ return **iter;
+
+ KSSLCertificate rc; // FIXME: Better way to return a not found condition?
+ kdDebug() << "Not found: " << rc.toString().latin1() << endl;
+ return rc;
+}
+
+
+///////////////////////////////////////////////////////////////////////////
+
+//
+// Certificate Home methods
+//
+
+QStringList KSSLD::getHomeCertificateList() {
+ return KSSLCertificateHome::getCertificateList();
+}
+
+bool KSSLD::addHomeCertificateFile(QString filename, QString password, bool storePass) {
+ return KSSLCertificateHome::addCertificate(filename, password, storePass);
+}
+
+bool KSSLD::addHomeCertificatePKCS12(QString base64cert, QString passToStore) {
+ bool ok;
+ KSSLPKCS12 *pkcs12 = KSSLPKCS12::fromString(base64cert, passToStore);
+ ok = KSSLCertificateHome::addCertificate(pkcs12, passToStore);
+ delete pkcs12;
+ return ok;
+}
+
+bool KSSLD::deleteHomeCertificateByFile(QString filename, QString password) {
+ return KSSLCertificateHome::deleteCertificate(filename, password);
+}
+
+bool KSSLD::deleteHomeCertificateByPKCS12(QString base64cert, QString password) {
+ bool ok;
+ KSSLPKCS12 *pkcs12 = KSSLPKCS12::fromString(base64cert, password);
+ ok = KSSLCertificateHome::deleteCertificate(pkcs12);
+ delete pkcs12;
+ return ok;
+}
+
+bool KSSLD::deleteHomeCertificateByName(QString name) {
+ return KSSLCertificateHome::deleteCertificateByName(name);
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////
+
+#include "kssld.moc"
+
+
+/*
+
+ DESIGN - KSSLCertificateCache
+ ------
+
+ This is the first implementation and I think this cache actually needs
+ experimentation to determine which implementation works best. My current
+ options are:
+
+ (1) Store copies of the X509 certificates in a QPtrList using a self
+ organizing heuristic as described by Munro and Suwanda.
+ (2) Store copies of the X509 certificates in a tree structure, perhaps
+ a redblack tree, avl tree, or even just a simple binary tree.
+ (3) Store the CN's in a tree or list and use them as a hash to retrieve
+ the X509 certificates.
+ (4) Create "nodes" containing the X509 certificate and place them in
+ two structures concurrently, one organized by CN, the other by
+ X509 serial number.
+
+ This implementation uses (1). (4) is definitely attractive, but I don't
+ think it will be necessary to go so crazy with performance, and perhaps
+ end up performing poorly in situations where there are very few entries in
+ the cache (which is most likely the case most of the time). The style of
+ heuristic is move-to-front, not swap-forward. This seems to make more
+ sense because the typical user will hit a site at least a few times in a
+ row before moving to a new one.
+
+ What I worry about most with respect to performance is that cryptographic
+ routines are expensive and if we have to perform them on each X509
+ certificate until the right one is found, we will perform poorly.
+
+ All in all, this code is actually quite crucial for performance on SSL
+ website, especially those with many image files loaded via SSL. If a
+ site loads 15 images, we will have to run through this code 15 times.
+ A heuristic for self organization will make each successive lookup faster.
+ Sounds good, doesn't it?
+
+ DO NOT ATTEMPT TO GUESS WHICH CERTIFICATES ARE ACCEPTIBLE IN YOUR CODE!!
+ ALWAYS USE THE CACHE. IT MAY CHECK THINGS THAT YOU DON'T THINK OF, AND
+ ALSO IF THERE IS A BUG IN THE CHECKING CODE, IF IT IS ALL CONTAINED IN
+ THIS LIBRARY, A MINOR FIX WILL FIX ALL APPLICATIONS.
+ */
+
diff --git a/kio/misc/kssld/kssld.desktop b/kio/misc/kssld/kssld.desktop
new file mode 100644
index 000000000..bbabf17a1
--- /dev/null
+++ b/kio/misc/kssld/kssld.desktop
@@ -0,0 +1,156 @@
+[Desktop Entry]
+Type=Service
+ServiceTypes=KDEDModule
+X-KDE-ModuleType=Library
+X-KDE-Library=kssld
+X-KDE-FactoryName=kssld
+X-KDE-Kded-autoload=false
+X-KDE-Kded-load-on-demand=true
+Name=KSSL Daemon Module
+Name[af]=Kssl Bediener Module
+Name[ar]=وحدة مراقب KSSL
+Name[az]=KSSL Demon Modulu
+Name[be]=Модуль сервіса KSSL
+Name[bg]=Демон KSSL
+Name[bn]=KSSL ডিমন মডিউল
+Name[br]=Mollad an diaoul KSSL
+Name[ca]=Mòdul del dimoni KSSL
+Name[cs]=Modul démona KSSL
+Name[csb]=KSSL
+Name[cy]=Modiwl Daemon KSSL
+Name[da]=KSSL Dæmonmodul
+Name[de]=SSL-Dienst
+Name[el]=Άρθρωμα δαίμονα KSSL
+Name[eo]=SSL-demono-modulo
+Name[es]=Módulo de demonio KSSL
+Name[et]=KSSL deemoni moodul
+Name[eu]=KSSL daemon modulua
+Name[fa]=پیمانۀ شبح KSSL
+Name[fi]=KSSL-palvelinmoduuli
+Name[fr]=Module démon KSSL
+Name[ga]=Modúl Deamhain KSSL
+Name[gl]=Módulo do Demo KSSL
+Name[he]=מודול תהליך הרקע של SSL
+Name[hi]=KSSL ङेमन घटक
+Name[hr]=Modul KSSL demona
+Name[hu]=KSSL szolgáltatásmodul
+Name[id]=Modul Daemon KSSL
+Name[is]=KSSL þjónseining
+Name[it]=Modulo demone KSSL
+Name[ja]=KSSL デーモンモジュール
+Name[ka]=KSSL გუშაგის მოდული
+Name[kk]=KSSL қызметтің модулі
+Name[km]=ម៉ូឌុល Daemon KSSL
+Name[ko]=KSSL 데몬 모듈
+Name[lb]=KSSL-Dämonmodul
+Name[lt]=KSSL tarnybos modulis
+Name[lv]=KSSL Dēmona Modulis
+Name[mn]=KSSL Daemon Modul
+Name[ms]=Modul Daemon KSSL
+Name[mt]=Modulu daemon KSSL
+Name[nb]=KSSL nisse-modul
+Name[nds]=KSSL-Dämoon
+Name[ne]=KSSL डेइमन मोड्युल
+Name[nl]=KSSL daemon-module
+Name[nn]=KSSL-nissemodul
+Name[nso]=Seripa sa Daemon ya KSSL
+Name[pa]=KSSL ਡਾਇਮੋਨ ਮੈਡੀਊਲ
+Name[pl]=KSSL
+Name[pt]=Módulo do Servidor de KSSL
+Name[pt_BR]=Módulo do Serviço do KSSL
+Name[ro]=Modul demon KSSL
+Name[ru]=Служба KSSL
+Name[rw]=Igice Dayimoni KSSL
+Name[se]=KSSL-bálvámoduvla
+Name[sk]=Modul démona KSSL
+Name[sl]=Strežniški modul KSSL
+Name[sq]=Demoni për Modulin KSSL
+Name[sr]=KSSL демон модул
+Name[sr@Latn]=KSSL demon modul
+Name[sv]=KSSL-demonmodul
+Name[ta]=KSSL டெமான் பகுதி
+Name[te]=కెఎస్ ఎస్ ఎల్ సూత్రధారి మాడ్యూల్
+Name[tg]=Модули Демон KSSL
+Name[th]=โมดูลเดมอน KSSL
+Name[tr]=KSSL Program Modülü
+Name[tt]=KSSL Xezmäteneñ Modulı
+Name[uk]=Модуль демону KSSL
+Name[uz]=KSSL xizmatining moduli
+Name[uz@cyrillic]=KSSL хизматининг модули
+Name[ven]=Modulu wa Daemon wa KSSL
+Name[vi]=Mô-đun trình nền KSSL
+Name[xh]=Isicatshulwa se KSSL Daemon
+Name[zh_CN]=KSSL 守护进程模块
+Name[zh_HK]=KSSL 伺服程式模組
+Name[zh_TW]=KSSL 伺服程式模組
+Name[zu]=Ingxenye ye-daemon ye-KSSL
+Comment=KSSL daemon module for KDED
+Comment[af]=KSSL bediener module vir KDED
+Comment[be]=Модуль сервіса KSSL для KDED
+Comment[bg]=Модул демон за KSSL за KDED
+Comment[bn]=KDED-র জন্য KSSL ডিমন মডিউল
+Comment[br]=Mollad an diaoul KSSL evit KDED
+Comment[bs]=KSSL Daemon Module za KDED
+Comment[ca]=Mòdul del dimoni KSSL per a KDED
+Comment[cs]=Modul démona KSSL pro KDED
+Comment[csb]=Ùsłëżnota SSL w KDED
+Comment[da]=KSSL Dæmonmodul for KDED
+Comment[de]=Unterstützung für SSL-Verschlüsselung in KDE
+Comment[el]=Άρθρωμα δαίμονα KSSL για το KDED
+Comment[eo]=SSL-demono-modulo por KDED
+Comment[es]=Módulo de demonio KSSL para KDED
+Comment[et]=KDED KSSL deemoni moodul
+Comment[eu]=KSSL daemon modulua KDEDrako
+Comment[fa]=پیمانۀ شبح KSSL برای KDED
+Comment[fi]=KSSL-palvelinmoduuli KDED:lle
+Comment[fr]=Module démon KSSL pour KDED
+Comment[fy]=KSSL daemon module foar KDED
+Comment[ga]=Modúl deamhain KSSL le haghaidh KDED
+Comment[gl]=Módulo do Demo KSSL para KDED
+Comment[he]=מודול תהליך רקע של SSL עבור KDED
+Comment[hi]=केडीईडी के लिए केएसएसएल डेमन मॉड्यूल
+Comment[hr]=KSSL demon modul za KDED
+Comment[hu]=KSSL szolgáltatásmodul a KDED-hez
+Comment[id]=Modul daemon KSSL untuk KDED
+Comment[is]=KSSL þjónseining fyrir KDED
+Comment[it]=Modulo demone KSSL per KDED
+Comment[ja]=KDED 用 の KSSL デーモンモジュール
+Comment[ka]=KSSL გუშაგის მოდული KDED-სთვის
+Comment[kk]=KDED KSSL куәліктерді басқару қызметтің модулі
+Comment[km]=ម៉ូឌុល daemon KSSL សម្រាប់ KDED
+Comment[lb]=KSSL-Dämonmodul fir KDED
+Comment[lt]=KSSL tarnybos modulis, skirtas KDED
+Comment[lv]=KSSL Dēmona Modulis priekš KDED
+Comment[mk]=KSSL даемон модул за KDED
+Comment[ms]=Modul Daemon KSSL untuk KDED
+Comment[nb]=KSSL nissemodul for KDED
+Comment[nds]=KSSL-Dämoonmoduul för KDED
+Comment[ne]=KDED का लागि डेइमन मोड्युल KSSL
+Comment[nl]=KSSL daemon-module voor KDED
+Comment[nn]=KSSL-nissemodul for KDED
+Comment[pa]=KDED ਲਈ KSSL ਪੇਸ਼ਕਾਰੀ
+Comment[pl]=Obsługa SSL w KDED
+Comment[pt]=Módulo servidor de KSSL para o KDED
+Comment[pt_BR]=Módulo de serviço KSSL para o KDE
+Comment[ro]=Modul demon KSSL pentru KDED
+Comment[ru]=Управление сертификатами SSL
+Comment[rw]=Igice cya dayimoni KSSL cya KDED
+Comment[se]=KDED:a KSSL-bálvámoduvla
+Comment[sk]=Modul démona KSSL pre KDED
+Comment[sl]=Strežniški modul KSSL za KDED
+Comment[sr]=KSSL демон модул за KDED
+Comment[sr@Latn]=KSSL demon modul za KDED
+Comment[sv]=KSSL-demonmodul för KDED
+Comment[ta]=KDEDக்கான KSSL டெமான் பகுதி
+Comment[te]=కెడిఈడి కొరకు కెఎస్ ఎస్ ఎల్ సూత్రధారి మాడ్యూల్
+Comment[tg]=Модули Демон KSSL брои KDED
+Comment[th]=โมดูลเดมอน KSSL สำหรับ KDED
+Comment[tr]=KDED için KSSL program biirmi
+Comment[tt]=KDED öçen KSSL xezmät
+Comment[uk]=Модуль демону KSSL для KDED
+Comment[uz]=KDED uchun KSSL xizmatining moduli
+Comment[uz@cyrillic]=KDED учун KSSL хизматининг модули
+Comment[vi]=Mô-đun trình nền KSSL cho KDED.
+Comment[zh_CN]=KDED 的 KSSL 守护进程模块
+Comment[zh_HK]=KDED 使用的 SSL 伺服程式模組
+Comment[zh_TW]=KDED 使用的 KSSL 伺服程式模組
diff --git a/kio/misc/kssld/kssld.h b/kio/misc/kssld/kssld.h
new file mode 100644
index 000000000..94cbe3972
--- /dev/null
+++ b/kio/misc/kssld/kssld.h
@@ -0,0 +1,154 @@
+/*
+ This file is part of the KDE libraries
+
+ Copyright (c) 2001-2005 George Staikos <staikos@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+
+*/
+#ifndef __KSSLD_H__
+#define __KSSLD_H__
+
+#include <kded/kdedmodule.h>
+#include <ksslcertificate.h>
+#include <ksslcertificatecache.h>
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qvaluelist.h>
+#include <qmap.h>
+#include <qptrvector.h>
+
+
+class KSimpleConfig;
+class KSSLCNode;
+class KOpenSSLProxy;
+
+class KSSLD : public KDEDModule
+{
+ Q_OBJECT
+ K_DCOP
+
+public:
+
+ KSSLD(const QCString &name);
+
+ virtual ~KSSLD();
+
+k_dcop:
+ //
+ // Certificate Cache methods
+ //
+ void cacheAddCertificate(KSSLCertificate cert,
+ KSSLCertificateCache::KSSLCertificatePolicy policy,
+ bool permanent = true);
+ KSSLCertificateCache::KSSLCertificatePolicy cacheGetPolicyByCN(QString cn);
+
+ KSSLCertificateCache::KSSLCertificatePolicy cacheGetPolicyByCertificate(KSSLCertificate cert);
+
+ bool cacheSeenCN(QString cn);
+ bool cacheSeenCertificate(KSSLCertificate cert);
+
+ bool cacheRemoveByCN(QString cn);
+ bool cacheRemoveBySubject(QString subject);
+ bool cacheRemoveByCertificate(KSSLCertificate cert);
+
+ bool cacheIsPermanent(KSSLCertificate cert);
+
+ void cacheReload();
+
+ bool cacheModifyByCN(QString cn,
+ KSSLCertificateCache::KSSLCertificatePolicy policy,
+ bool permanent,
+ QDateTime expires);
+
+ bool cacheModifyByCertificate(KSSLCertificate cert,
+ KSSLCertificateCache::KSSLCertificatePolicy policy,
+ bool permanent,
+ QDateTime expires);
+
+ QStringList cacheGetHostList(KSSLCertificate cert);
+
+ bool cacheAddHost(KSSLCertificate cert, QString host);
+
+ bool cacheRemoveHost(KSSLCertificate cert, QString host);
+
+ /* Certificate Authorities */
+ void caVerifyUpdate();
+ bool caRegenerate();
+
+ QStringList caList();
+
+ bool caUseForSSL(QString subject);
+
+ bool caUseForEmail(QString subject);
+
+ bool caUseForCode(QString subject);
+
+ bool caAdd(QString certificate, bool ssl, bool email, bool code);
+
+ bool caAddFromFile(QString filename, bool ssl, bool email, bool code);
+
+ bool caRemove(QString subject);
+
+ bool caRemoveFromFile(QString filename);
+
+ QString caGetCert(QString subject);
+
+ bool caSetUse(QString subject, bool ssl, bool email, bool code);
+
+ QStringList getKDEKeyByEmail(const QString &email);
+
+ KSSLCertificate getCertByMD5Digest(const QString &key);
+
+ //
+ // Certificate Home methods
+ //
+
+ QStringList getHomeCertificateList();
+
+ bool addHomeCertificateFile(QString filename, QString password, bool storePass /*=false*/);
+
+ bool addHomeCertificatePKCS12(QString base64cert, QString passToStore);
+
+ bool deleteHomeCertificateByFile(QString filename, QString password);
+
+ bool deleteHomeCertificateByPKCS12(QString base64cert, QString password);
+
+ bool deleteHomeCertificateByName(QString name);
+
+private:
+
+ void cacheClearList();
+ void cacheSaveToDisk();
+ void cacheLoadDefaultPolicies();
+
+ // for the cache portion:
+ KSimpleConfig *cfg;
+ QPtrList<KSSLCNode> certList;
+
+ // Our pointer to OpenSSL
+ KOpenSSLProxy *kossl;
+
+ //
+ void searchAddCert(KSSLCertificate *cert);
+ void searchRemoveCert(KSSLCertificate *cert);
+
+ QMap<QString, QPtrVector<KSSLCertificate> > skEmail;
+ QMap<QString, KSSLCertificate *> skMD5Digest;
+};
+
+
+#endif