kio Library API Documentation

kssld.cpp

00001 /*
00002    This file is part of the KDE libraries
00003 
00004    Copyright (c) 2001-2003 George Staikos <staikos@kde.org>
00005 
00006    This library is free software; you can redistribute it and/or
00007    modify it under the terms of the GNU Library General Public
00008    License as published by the Free Software Foundation; either
00009    version 2 of the License, or (at your option) any later version.
00010 
00011    This library is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014    Library General Public License for more details.
00015 
00016    You should have received a copy of the GNU Library General Public License
00017    along with this library; see the file COPYING.LIB.  If not, write to
00018    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00019    Boston, MA 02111-1307, USA.
00020 
00021 */
00022 
00023 #ifdef HAVE_CONFIG_H
00024 #include <config.h>
00025 #endif
00026 
00027 #include <qtimer.h>
00028 
00029 #include "kssld.h"
00030 #include <kconfig.h>
00031 #include <ksimpleconfig.h>
00032 #include <ksslcertchain.h>
00033 #include <ksslcertificate.h>
00034 #include <ksslcertificatehome.h>
00035 #include <ksslpkcs12.h>
00036 #include <ksslx509map.h>
00037 #include <qptrlist.h>
00038 #include <sys/types.h>
00039 #include <sys/stat.h>
00040 #include <stdlib.h>
00041 #include <pwd.h>
00042 #include <unistd.h>
00043 #include <qfile.h>
00044 #include <qsortedlist.h>
00045 #include <kglobal.h>
00046 #include <kstandarddirs.h>
00047 #include <kdebug.h>
00048 #include <qdatetime.h>
00049 
00050 #include <kmdcodec.h>
00051 #include <kopenssl.h>
00052 
00053 // See design notes at end
00054 
00055 extern "C" {
00056     KDE_EXPORT KDEDModule *create_kssld(const QCString &name) {
00057         return new KSSLD(name);
00058     }
00059 
00060     KDE_EXPORT void *__kde_do_unload;
00061 }
00062 
00063 
00064 KSSLD::KSSLD(const QCString &name) : KDEDModule(name)
00065 {
00066 // ----------------------- FOR THE CACHE ------------------------------------   
00067     cfg = new KSimpleConfig("ksslpolicies", false);
00068     KGlobal::dirs()->addResourceType("kssl", KStandardDirs::kde_default("data") + "kssl");
00069     caVerifyUpdate();
00070     cacheLoadDefaultPolicies();
00071     certList.setAutoDelete(false);
00072     kossl = KOSSL::self();
00073 
00074 // ----------------------- FOR THE HOME -------------------------------------
00075 }
00076   
00077 
00078 KSSLD::~KSSLD()
00079 {
00080 // ----------------------- FOR THE CACHE ------------------------------------   
00081     cacheClearList();
00082     delete cfg;
00083 
00084 // ----------------------- FOR THE HOME -------------------------------------
00085 }
00086 
00087   
00088 
00089 
00090 // A node in the cache
00091 class KSSLCNode {
00092     public:
00093         KSSLCertificate *cert;
00094         KSSLCertificateCache::KSSLCertificatePolicy policy;
00095         bool permanent;
00096         QDateTime expires;
00097         QStringList hosts;
00098         KSSLCNode() { cert = 0L;
00099                 policy = KSSLCertificateCache::Unknown; 
00100                 permanent = true;
00101             }
00102         ~KSSLCNode() { delete cert; }
00103 };
00104 
00105 
00106 
00107 void KSSLD::cacheSaveToDisk() {
00108 KSSLCNode *node;
00109 
00110     for (node = certList.first(); node; node = certList.next()) {
00111         if (node->permanent ||
00112             node->expires > QDateTime::currentDateTime()) {
00113             // First convert to a binary format and then write the
00114             // kconfig entry write the (CN, policy, cert) to
00115             // KSimpleConfig
00116             cfg->setGroup(node->cert->getSubject());
00117             cfg->writeEntry("Certificate", node->cert->toString());
00118             cfg->writeEntry("Policy", node->policy);
00119             cfg->writeEntry("Expires", node->expires);
00120             cfg->writeEntry("Permanent", node->permanent);
00121             cfg->writeEntry("Hosts", node->hosts);
00122 
00123             // Also write the chain
00124             QStringList qsl;
00125             QPtrList<KSSLCertificate> cl =
00126                         node->cert->chain().getChain();
00127             for (KSSLCertificate *c = cl.first();
00128                             c != 0;
00129                             c = cl.next()) {
00130                 //kdDebug() << "Certificate in chain: "
00131                 //      <<  c->toString() << endl;
00132                 qsl << c->toString();
00133             }
00134 
00135             cl.setAutoDelete(true);
00136             cfg->writeEntry("Chain", qsl);
00137         }
00138     }  
00139 
00140     cfg->sync();
00141 
00142     // insure proper permissions -- contains sensitive data
00143     QString cfgName(KGlobal::dirs()->findResource("config", "ksslpolicies"));
00144 
00145     if (!cfgName.isEmpty()) {
00146         ::chmod(QFile::encodeName(cfgName), 0600);
00147     }
00148 }
00149 
00150 
00151 void KSSLD::cacheReload() {
00152     cacheClearList();
00153     delete cfg;
00154     cfg = new KSimpleConfig("ksslpolicies", false);
00155     cacheLoadDefaultPolicies();
00156 }
00157 
00158 
00159 void KSSLD::cacheClearList() {
00160 KSSLCNode *node;
00161 
00162     for (node = certList.first(); node; node = certList.next()) {
00163         certList.remove(node);
00164         delete node;
00165     }
00166 
00167     skEmail.clear();
00168     skMD5Digest.clear();
00169 }
00170 
00171 
00172 void KSSLD::cacheLoadDefaultPolicies() {
00173 QStringList groups = cfg->groupList();
00174 
00175     for (QStringList::Iterator i = groups.begin();
00176                 i != groups.end();
00177                 ++i) {
00178         if ((*i).length() == 0) {
00179             continue;
00180         }
00181 
00182         cfg->setGroup(*i);
00183 
00184         // remove it if it has expired
00185         if (!cfg->readBoolEntry("Permanent") &&
00186             cfg->readDateTimeEntry("Expires") <
00187                 QDateTime::currentDateTime()) {
00188             cfg->deleteGroup(*i);
00189             continue;
00190         }
00191 
00192         QCString encodedCert;
00193         KSSLCertificate *newCert;
00194 
00195         encodedCert = cfg->readEntry("Certificate").local8Bit();
00196             newCert = KSSLCertificate::fromString(encodedCert);
00197 
00198         if (!newCert) {
00199                continue;
00200         }
00201 
00202         KSSLCNode *n = new KSSLCNode;
00203         n->cert = newCert;
00204         n->policy = (KSSLCertificateCache::KSSLCertificatePolicy) cfg->readNumEntry("Policy");
00205         n->permanent = cfg->readBoolEntry("Permanent");
00206         n->expires = cfg->readDateTimeEntry("Expires");
00207         n->hosts = cfg->readListEntry("Hosts");
00208         newCert->chain().setCertChain(cfg->readListEntry("Chain"));
00209         certList.append(n); 
00210         searchAddCert(newCert);
00211     }
00212 }
00213 
00214 
00215 void KSSLD::cacheAddCertificate(KSSLCertificate cert, 
00216             KSSLCertificateCache::KSSLCertificatePolicy policy,
00217             bool permanent) {
00218 KSSLCNode *node;
00219 
00220     for (node = certList.first(); node; node = certList.next()) {
00221         if (cert == *(node->cert)) {
00222             node->policy = policy;
00223             node->permanent = permanent;
00224 
00225             if (!permanent) {
00226                 node->expires = QDateTime::currentDateTime();
00227                 // FIXME: make this configurable
00228                 node->expires = node->expires.addSecs(3600);
00229             }
00230 
00231             cacheSaveToDisk();
00232             return;
00233         }
00234     }
00235 
00236     KSSLCNode *n = new KSSLCNode;
00237     n->cert = cert.replicate();
00238     n->policy = policy;
00239     n->permanent = permanent;
00240     // remove the old one
00241     cacheRemoveBySubject(n->cert->getSubject());
00242     certList.prepend(n); 
00243 
00244     if (!permanent) {
00245         n->expires = QDateTime::currentDateTime();
00246         n->expires = n->expires.addSecs(3600);
00247     }
00248 
00249     searchAddCert(n->cert);
00250     cacheSaveToDisk();
00251 }
00252 
00253 
00254 KSSLCertificateCache::KSSLCertificatePolicy KSSLD::cacheGetPolicyByCN(QString cn) {
00255 KSSLCNode *node;
00256 
00257     for (node = certList.first(); node; node = certList.next()) {
00258         if (KSSLX509Map(node->cert->getSubject()).getValue("CN") == cn) {
00259             if (!node->permanent &&
00260                 node->expires < QDateTime::currentDateTime()) {
00261                 certList.remove(node);
00262                 cfg->deleteGroup(node->cert->getSubject());
00263                 delete node;
00264                 continue;
00265             }
00266 
00267             certList.remove(node);
00268             certList.prepend(node);
00269             cacheSaveToDisk();
00270             return node->policy;
00271         }
00272     }
00273 
00274     cacheSaveToDisk();
00275 
00276 return KSSLCertificateCache::Unknown;
00277 }
00278 
00279 
00280 KSSLCertificateCache::KSSLCertificatePolicy KSSLD::cacheGetPolicyByCertificate(KSSLCertificate cert) {
00281 KSSLCNode *node;
00282 
00283     for (node = certList.first(); node; node = certList.next()) {
00284         if (cert == *(node->cert)) {  
00285             if (!node->permanent &&
00286                 node->expires < QDateTime::currentDateTime()) {
00287                 certList.remove(node);
00288                 cfg->deleteGroup(node->cert->getSubject());
00289                 delete node;
00290                 cacheSaveToDisk();
00291                 return KSSLCertificateCache::Unknown;
00292             }
00293 
00294             certList.remove(node);
00295             certList.prepend(node);
00296             return node->policy;
00297         }
00298     }
00299 
00300 return KSSLCertificateCache::Unknown;
00301 }
00302 
00303 
00304 bool KSSLD::cacheSeenCN(QString cn) {
00305 KSSLCNode *node;
00306 
00307     for (node = certList.first(); node; node = certList.next()) {
00308         if (KSSLX509Map(node->cert->getSubject()).getValue("CN") == cn) {
00309             if (!node->permanent &&
00310                 node->expires < QDateTime::currentDateTime()) {
00311                 certList.remove(node);
00312                 cfg->deleteGroup(node->cert->getSubject());
00313                 delete node;
00314                 cacheSaveToDisk();
00315                 continue;
00316             }
00317 
00318             certList.remove(node);
00319             certList.prepend(node);
00320             return true;
00321         }
00322     }
00323 
00324 return false;
00325 }
00326 
00327 
00328 bool KSSLD::cacheSeenCertificate(KSSLCertificate cert) {
00329 KSSLCNode *node;
00330 
00331     for (node = certList.first(); node; node = certList.next()) {
00332         if (cert == *(node->cert)) {
00333             if (!node->permanent &&
00334                 node->expires < QDateTime::currentDateTime()) {
00335                 certList.remove(node);
00336                 cfg->deleteGroup(node->cert->getSubject());
00337                 delete node;
00338                 cacheSaveToDisk();
00339                 return false;
00340             }
00341 
00342             certList.remove(node);
00343             certList.prepend(node);
00344             return true;
00345         }
00346     }
00347 
00348 return false;
00349 }
00350 
00351 
00352 bool KSSLD::cacheIsPermanent(KSSLCertificate cert) {
00353 KSSLCNode *node;
00354 
00355     for (node = certList.first(); node; node = certList.next()) {
00356         if (cert == *(node->cert)) {
00357             if (!node->permanent && node->expires <
00358                     QDateTime::currentDateTime()) {
00359                 certList.remove(node);
00360                 cfg->deleteGroup(node->cert->getSubject());
00361                 delete node;
00362                 cacheSaveToDisk();
00363                 return false;
00364             }
00365 
00366             certList.remove(node);
00367             certList.prepend(node);
00368             return node->permanent;
00369         }
00370     }
00371 
00372 return false;
00373 }
00374 
00375 
00376 bool KSSLD::cacheRemoveBySubject(QString subject) {
00377 KSSLCNode *node;
00378 bool gotOne = false;
00379 
00380     for (node = certList.first(); node; node = certList.next()) {
00381         if (node->cert->getSubject() == subject) {
00382             certList.remove(node);
00383             cfg->deleteGroup(node->cert->getSubject());
00384             searchRemoveCert(node->cert);
00385             delete node;
00386             gotOne = true;
00387         }
00388     }
00389 
00390     cacheSaveToDisk();
00391 
00392 return gotOne;
00393 }
00394 
00395 
00396 bool KSSLD::cacheRemoveByCN(QString cn) {
00397 KSSLCNode *node;
00398 bool gotOne = false;
00399 
00400     for (node = certList.first(); node; node = certList.next()) {
00401         if (KSSLX509Map(node->cert->getSubject()).getValue("CN") == cn) {
00402             certList.remove(node);
00403             cfg->deleteGroup(node->cert->getSubject());
00404             searchRemoveCert(node->cert);
00405             delete node;
00406             gotOne = true;
00407         }
00408     }
00409 
00410     cacheSaveToDisk();
00411 
00412 return gotOne;
00413 }
00414 
00415 
00416 bool KSSLD::cacheRemoveByCertificate(KSSLCertificate cert) {
00417 KSSLCNode *node;
00418 
00419     for (node = certList.first(); node; node = certList.next()) {
00420         if (cert == *(node->cert)) {
00421             certList.remove(node);
00422             cfg->deleteGroup(node->cert->getSubject());
00423             searchRemoveCert(node->cert);
00424             delete node;
00425             cacheSaveToDisk();
00426             return true;
00427         }
00428     }
00429 
00430 return false;
00431 }
00432 
00433 
00434 bool KSSLD::cacheModifyByCN(QString cn,
00435                             KSSLCertificateCache::KSSLCertificatePolicy policy,                             bool permanent,
00436                             QDateTime expires) {
00437 KSSLCNode *node;
00438 
00439     for (node = certList.first(); node; node = certList.next()) {
00440         if (KSSLX509Map(node->cert->getSubject()).getValue("CN") == cn) {
00441             node->permanent = permanent;
00442             node->expires = expires;
00443             node->policy = policy;
00444             certList.remove(node);
00445             certList.prepend(node);
00446             cacheSaveToDisk();
00447             return true;
00448         }
00449     }
00450 
00451 return false;
00452 }
00453 
00454 
00455 bool KSSLD::cacheModifyByCertificate(KSSLCertificate cert,
00456                              KSSLCertificateCache::KSSLCertificatePolicy policy,
00457                  bool permanent,
00458                  QDateTime expires) {
00459 KSSLCNode *node;
00460 
00461     for (node = certList.first(); node; node = certList.next()) {
00462         if (cert == *(node->cert)) {
00463             node->permanent = permanent;
00464             node->expires = expires;
00465             node->policy = policy;
00466             certList.remove(node);
00467             certList.prepend(node);
00468             cacheSaveToDisk();
00469             return true;
00470         }
00471     }
00472 
00473 return false;
00474 }
00475 
00476 
00477 QStringList KSSLD::cacheGetHostList(KSSLCertificate cert) {
00478 KSSLCNode *node;
00479 
00480     for (node = certList.first(); node; node = certList.next()) {
00481         if (cert == *(node->cert)) {
00482             if (!node->permanent && node->expires <
00483                        QDateTime::currentDateTime()) {
00484                 certList.remove(node);
00485                 cfg->deleteGroup(node->cert->getSubject());
00486                 searchRemoveCert(node->cert);
00487                 delete node;
00488                 cacheSaveToDisk();
00489                 return QStringList();
00490             }
00491 
00492             certList.remove(node);
00493             certList.prepend(node);
00494             return node->hosts;
00495         }
00496     }
00497 
00498 return QStringList();
00499 }
00500 
00501 
00502 bool KSSLD::cacheAddHost(KSSLCertificate cert, QString host) {
00503 KSSLCNode *node;
00504 
00505     if (host.isEmpty())
00506         return true;
00507 
00508     for (node = certList.first(); node; node = certList.next()) {
00509         if (cert == *(node->cert)) {
00510             if (!node->permanent && node->expires <
00511                         QDateTime::currentDateTime()) {
00512                 certList.remove(node);
00513                 cfg->deleteGroup(node->cert->getSubject());
00514                 searchRemoveCert(node->cert);
00515                 delete node;
00516                 cacheSaveToDisk();
00517                 return false;
00518             }
00519 
00520             if (!node->hosts.contains(host)) {
00521                 node->hosts << host;
00522             }
00523 
00524             certList.remove(node);
00525             certList.prepend(node);
00526             cacheSaveToDisk();
00527             return true;
00528         }
00529     }
00530 
00531 return false;
00532 }
00533 
00534 
00535 bool KSSLD::cacheRemoveHost(KSSLCertificate cert, QString host) {
00536 KSSLCNode *node;
00537 
00538     for (node = certList.first(); node; node = certList.next()) {
00539         if (cert == *(node->cert)) {
00540             if (!node->permanent && node->expires <
00541                         QDateTime::currentDateTime()) {
00542                 certList.remove(node);
00543                 cfg->deleteGroup(node->cert->getSubject());
00544                 searchRemoveCert(node->cert);
00545                 delete node;
00546                 cacheSaveToDisk();
00547                 return false;
00548             }
00549             node->hosts.remove(host);
00550             certList.remove(node);
00551             certList.prepend(node);
00552             cacheSaveToDisk();
00553             return true;
00554         }
00555     }
00556 
00557 return false;
00558 }
00559 
00560 
00561 
00562 
00564 
00565 void KSSLD::caVerifyUpdate() {
00566     QString path = KGlobal::dirs()->saveLocation("kssl") + "/ca-bundle.crt";
00567     if (!QFile::exists(path))
00568         return;
00569     
00570     cfg->setGroup(QString::null);
00571     Q_UINT32 newStamp = KGlobal::dirs()->calcResourceHash("config", "ksslcalist", true);
00572     Q_UINT32 oldStamp = cfg->readUnsignedNumEntry("ksslcalistStamp");
00573     if (oldStamp != newStamp)
00574     {
00575         caRegenerate();
00576         cfg->writeEntry("ksslcalistStamp", newStamp);
00577         cfg->sync();
00578     }
00579 }
00580 
00581 bool KSSLD::caRegenerate() {
00582 QString path = KGlobal::dirs()->saveLocation("kssl") + "/ca-bundle.crt";
00583 
00584 QFile out(path);
00585 
00586     if (!out.open(IO_WriteOnly))
00587         return false;
00588 
00589 KConfig cfg("ksslcalist", true, false);
00590 
00591 QStringList x = cfg.groupList();
00592 
00593     for (QStringList::Iterator i = x.begin();
00594                    i != x.end();
00595                    ++i) {
00596         if ((*i).isEmpty() || *i == "<default>") continue;
00597 
00598         cfg.setGroup(*i);
00599 
00600         if (!cfg.readBoolEntry("site", false)) continue;
00601 
00602         QString cert = cfg.readEntry("x509", "");
00603         if (cert.length() <= 0) continue;
00604 
00605         unsigned int xx = cert.length() - 1;
00606         for (unsigned int j = 0; j < xx/64; j++) {
00607             cert.insert(64*(j+1)+j, '\n');
00608         }
00609         out.writeBlock("-----BEGIN CERTIFICATE-----\n", 28);
00610         out.writeBlock(cert.latin1(), cert.length());
00611         out.writeBlock("\n-----END CERTIFICATE-----\n\n", 28);
00612         out.flush();
00613     }
00614 
00615 return true;
00616 }
00617 
00618 
00619 
00620 bool KSSLD::caAdd(QString certificate, bool ssl, bool email, bool code) {
00621 KSSLCertificate *x = KSSLCertificate::fromString(certificate.local8Bit());
00622 
00623     if (!x) return false;
00624 
00625 KConfig cfg("ksslcalist", false, false);
00626 
00627     cfg.setGroup(x->getSubject());
00628     cfg.writeEntry("x509", certificate);
00629     cfg.writeEntry("site", ssl);
00630     cfg.writeEntry("email", email);
00631     cfg.writeEntry("code", code);
00632 
00633     cfg.sync();
00634     delete x;
00635 
00636 return true;
00637 }
00638 
00639 
00644 static QStringList caReadCerticatesFromFile(QString filename) {
00645 
00646     QStringList certificates;
00647     QString certificate, temp;
00648     QFile file(filename);
00649 
00650     if (!file.open(IO_ReadOnly))
00651         return certificates;
00652 
00653     while (!file.atEnd()) {
00654         file.readLine(temp, 999);
00655         if (temp.startsWith("-----BEGIN CERTIFICATE-----")) {
00656             certificate = QString::null;
00657             continue;
00658         }
00659 
00660         if (temp.startsWith("-----END CERTIFICATE-----")) {
00661             certificates.append(certificate);
00662             certificate = QString::null;
00663             continue;
00664         }
00665 
00666         certificate += temp.stripWhiteSpace();
00667     }
00668 
00669     file.close();
00670 
00671     return certificates;
00672 }
00673 
00674 bool KSSLD::caAddFromFile(QString filename, bool ssl, bool email, bool code) {
00675 
00676     QStringList certificates;
00677     certificates = caReadCerticatesFromFile(filename);
00678     if (certificates.isEmpty())
00679         return false;
00680 
00681     bool ok = true;
00682 
00683     for (QStringList::Iterator it = certificates.begin();
00684                     it != certificates.end(); ++it ) {
00685         ok &= caAdd(*it, ssl, email, code);
00686     }
00687 
00688     return ok;
00689 }
00690 
00691 bool KSSLD::caRemoveFromFile(QString filename) {
00692 
00693     QStringList certificates;
00694     certificates = caReadCerticatesFromFile(filename);
00695     if (certificates.isEmpty())
00696         return false;
00697 
00698     bool ok = true;
00699 
00700     for (QStringList::Iterator it = certificates.begin();
00701                     it != certificates.end(); ++it ) {
00702         QString certificate = *it;
00703         KSSLCertificate *x = KSSLCertificate::fromString(certificate.local8Bit());
00704         ok &= x && caRemove(x->getSubject());
00705         delete x;
00706     }
00707 
00708     return ok;
00709 }
00710 
00711 
00712 QStringList KSSLD::caList() {
00713 QStringList x;
00714 KConfig cfg("ksslcalist", true, false);
00715 
00716     x = cfg.groupList();
00717     x.remove("<default>");
00718 
00719 return x;
00720 }
00721 
00722 
00723 bool KSSLD::caUseForSSL(QString subject) {
00724 KConfig cfg("ksslcalist", true, false);
00725 
00726     if (!cfg.hasGroup(subject))
00727         return false;
00728 
00729     cfg.setGroup(subject);
00730 return cfg.readBoolEntry("site", false);
00731 }
00732 
00733 
00734 
00735 bool KSSLD::caUseForEmail(QString subject) {
00736 KConfig cfg("ksslcalist", true, false);
00737 
00738     if (!cfg.hasGroup(subject))
00739         return false;
00740 
00741     cfg.setGroup(subject);
00742 return cfg.readBoolEntry("email", false);
00743 }
00744 
00745 
00746 
00747 bool KSSLD::caUseForCode(QString subject) {
00748 KConfig cfg("ksslcalist", true, false);
00749 
00750     if (!cfg.hasGroup(subject))
00751         return false;
00752 
00753     cfg.setGroup(subject);
00754 return cfg.readBoolEntry("code", false);
00755 }
00756 
00757 
00758 bool KSSLD::caRemove(QString subject) {
00759 KConfig cfg("ksslcalist", false, false);
00760     if (!cfg.hasGroup(subject))
00761         return false;
00762 
00763     cfg.deleteGroup(subject);
00764     cfg.sync();
00765 
00766 return true;
00767 }
00768 
00769 
00770 QString KSSLD::caGetCert(QString subject) {
00771 KConfig cfg("ksslcalist", true, false);
00772     if (!cfg.hasGroup(subject))
00773         return QString::null;
00774 
00775     cfg.setGroup(subject);
00776 
00777 return cfg.readEntry("x509", QString::null);
00778 }
00779 
00780 
00781 bool KSSLD::caSetUse(QString subject, bool ssl, bool email, bool code) {
00782 KConfig cfg("ksslcalist", false, false);
00783     if (!cfg.hasGroup(subject))
00784         return false;
00785 
00786     cfg.setGroup(subject);
00787 
00788     cfg.writeEntry("site", ssl);
00789     cfg.writeEntry("email", email);
00790     cfg.writeEntry("code", code);
00791     cfg.sync();
00792 
00793 return true;
00794 }
00795 
00797 
00798 void KSSLD::searchAddCert(KSSLCertificate *cert) {
00799     skMD5Digest.insert(cert->getMD5DigestText(), cert, true);
00800 
00801     QStringList mails;
00802     cert->getEmails(mails);
00803     for(QStringList::const_iterator iter = mails.begin(); iter != mails.end(); iter++) {
00804         QString email = static_cast<const QString &>(*iter).lower();
00805         QMap<QString, QPtrVector<KSSLCertificate> >::iterator it = skEmail.find(email);
00806 
00807         if (it == skEmail.end())
00808             it = skEmail.insert(email, QPtrVector<KSSLCertificate>());
00809 
00810         QPtrVector<KSSLCertificate> &elem = *it;
00811         
00812         if (elem.findRef(cert) == -1) {
00813             unsigned int n = 0;
00814             for(; n < elem.size(); n++) {
00815                 if (!elem.at(n)) {
00816                     elem.insert(n, cert);
00817                     break;
00818                 }
00819             }
00820             if (n == elem.size()) {
00821                 elem.resize(n+1);
00822                 elem.insert(n, cert);
00823             }
00824         }
00825     }   
00826 }
00827 
00828 
00829 void KSSLD::searchRemoveCert(KSSLCertificate *cert) {
00830     skMD5Digest.remove(cert->getMD5DigestText());
00831 
00832     QStringList mails;
00833     cert->getEmails(mails);
00834     for(QStringList::const_iterator iter = mails.begin(); iter != mails.end(); iter++) {
00835         QMap<QString, QPtrVector<KSSLCertificate> >::iterator it = skEmail.find(static_cast<const QString &>(*iter).lower());
00836 
00837         if (it == skEmail.end())
00838                break;
00839 
00840         QPtrVector<KSSLCertificate> &elem = *it;
00841 
00842         int n = elem.findRef(cert);
00843         if (n != -1)
00844             elem.remove(n);
00845     }
00846 }   
00847 
00848 
00849 QStringList KSSLD::getKDEKeyByEmail(const QString &email) {
00850     QStringList rc;
00851     QMap<QString, QPtrVector<KSSLCertificate> >::iterator it = skEmail.find(email.lower());
00852 
00853     kdDebug() << "GETKDEKey " << email.latin1() << endl;
00854 
00855     if (it == skEmail.end())
00856         return rc;
00857 
00858     QPtrVector<KSSLCertificate> &elem = *it;
00859     for (unsigned int n = 0; n < elem.size(); n++) {
00860         KSSLCertificate *cert = elem.at(n);
00861         if (cert) {
00862             rc.append(cert->getKDEKey());
00863         }
00864     }
00865 
00866     kdDebug() << "ergebnisse: " << rc.size() << " " << elem.size() << endl;
00867     return rc;
00868 }
00869 
00870 
00871 KSSLCertificate KSSLD::getCertByMD5Digest(const QString &key) {
00872     QMap<QString, KSSLCertificate *>::iterator iter = skMD5Digest.find(key);
00873     
00874     kdDebug() << "Searching cert for " << key.latin1() << endl;
00875 
00876     if (iter != skMD5Digest.end())
00877         return **iter;
00878     
00879     KSSLCertificate rc; // FIXME: Better way to return a not found condition?
00880     kdDebug() << "Not found: " << rc.toString().latin1() << endl;
00881     return rc;
00882 }   
00883 
00884 
00886 
00887 //
00888 //  Certificate Home methods
00889 //
00890 
00891 QStringList KSSLD::getHomeCertificateList() {
00892     return KSSLCertificateHome::getCertificateList();
00893 }
00894 
00895 bool KSSLD::addHomeCertificateFile(QString filename, QString password, bool storePass) {
00896     return KSSLCertificateHome::addCertificate(filename, password, storePass);
00897 }
00898 
00899 bool KSSLD::addHomeCertificatePKCS12(QString base64cert, QString passToStore) {
00900     bool ok;
00901     KSSLPKCS12 *pkcs12 = KSSLPKCS12::fromString(base64cert, passToStore);
00902     ok = KSSLCertificateHome::addCertificate(pkcs12, passToStore);
00903     delete pkcs12;
00904     return ok;
00905 }
00906 
00907 bool KSSLD::deleteHomeCertificateByFile(QString filename, QString password) {
00908     return KSSLCertificateHome::deleteCertificate(filename, password);
00909 }
00910 
00911 bool KSSLD::deleteHomeCertificateByPKCS12(QString base64cert, QString password) {
00912     bool ok;
00913     KSSLPKCS12 *pkcs12 = KSSLPKCS12::fromString(base64cert, password);
00914     ok = KSSLCertificateHome::deleteCertificate(pkcs12);
00915     delete pkcs12;
00916     return ok;
00917 }
00918 
00919 bool KSSLD::deleteHomeCertificateByName(QString name) {
00920     return KSSLCertificateHome::deleteCertificateByName(name);
00921 }
00922 
00923 
00924 
00926 
00927 #include "kssld.moc"
00928 
00929 
00930 /*
00931 
00932   DESIGN     - KSSLCertificateCache
00933   ------
00934 
00935   This is the first implementation and I think this cache actually needs
00936   experimentation to determine which implementation works best.  My current
00937   options are:
00938 
00939    (1) Store copies of the X509 certificates in a QPtrList using a self
00940        organizing heuristic as described by Munro and Suwanda.
00941    (2) Store copies of the X509 certificates in a tree structure, perhaps
00942        a redblack tree, avl tree, or even just a simple binary tree.
00943    (3) Store the CN's in a tree or list and use them as a hash to retrieve
00944        the X509 certificates.
00945    (4) Create "nodes" containing the X509 certificate and place them in
00946        two structures concurrently, one organized by CN, the other by
00947        X509 serial number.
00948 
00949   This implementation uses (1).  (4) is definitely attractive, but I don't
00950   think it will be necessary to go so crazy with performance, and perhaps
00951   end up performing poorly in situations where there are very few entries in
00952   the cache (which is most likely the case most of the time).  The style of
00953   heuristic is move-to-front, not swap-forward.  This seems to make more
00954   sense because the typical user will hit a site at least a few times in a
00955   row before moving to a new one.
00956 
00957   What I worry about most with respect to performance is that cryptographic
00958   routines are expensive and if we have to perform them on each X509
00959   certificate until the right one is found, we will perform poorly.
00960 
00961   All in all, this code is actually quite crucial for performance on SSL
00962   website, especially those with many image files loaded via SSL.  If a
00963   site loads 15 images, we will have to run through this code 15 times.
00964   A heuristic for self organization will make each successive lookup faster.
00965   Sounds good, doesn't it?
00966 
00967   DO NOT ATTEMPT TO GUESS WHICH CERTIFICATES ARE ACCEPTIBLE IN YOUR CODE!!
00968   ALWAYS USE THE CACHE.  IT MAY CHECK THINGS THAT YOU DON'T THINK OF, AND
00969   ALSO IF THERE IS A BUG IN THE CHECKING CODE, IF IT IS ALL CONTAINED IN
00970   THIS LIBRARY, A MINOR FIX WILL FIX ALL APPLICATIONS.
00971  */
00972 
KDE Logo
This file is part of the documentation for kio Library Version 3.4.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Thu Apr 28 01:36:58 2005 by doxygen 1.3.9.1 written by Dimitri van Heesch, © 1997-2003