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 Tue Apr 12 23:09:27 2005 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003