00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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 <ksslx509map.h>
00035 #include <qptrlist.h>
00036 #include <sys/types.h>
00037 #include <sys/stat.h>
00038 #include <stdlib.h>
00039 #include <pwd.h>
00040 #include <unistd.h>
00041 #include <qfile.h>
00042 #include <qsortedlist.h>
00043 #include <kglobal.h>
00044 #include <kstandarddirs.h>
00045 #include <kdebug.h>
00046 #include <qdatetime.h>
00047
00048 #include <kmdcodec.h>
00049 #include <kopenssl.h>
00050
00051
00052
00053 extern "C" {
00054 KDEDModule *create_kssld(const QCString &name) {
00055 return new KSSLD(name);
00056 }
00057
00058 void *__kde_do_unload;
00059 }
00060
00061
00062 KSSLD::KSSLD(const QCString &name) : KDEDModule(name)
00063 {
00064
00065 cfg = new KSimpleConfig("ksslpolicies", false);
00066 if (!KGlobal::dirs()->addResourceType("kssl", KStandardDirs::kde_default("data") + "kssl")) {
00067
00068 }
00069 cacheLoadDefaultPolicies();
00070 certList.setAutoDelete(false);
00071 kossl = KOSSL::self();
00072
00073
00074 }
00075
00076
00077 KSSLD::~KSSLD()
00078 {
00079
00080 cacheClearList();
00081 delete cfg;
00082
00083
00084 }
00085
00086
00087
00088
00089
00090 class KSSLCNode {
00091 public:
00092 KSSLCertificate *cert;
00093 KSSLCertificateCache::KSSLCertificatePolicy policy;
00094 bool permanent;
00095 QDateTime expires;
00096 QStringList hosts;
00097 KSSLCNode() { cert = NULL; policy = KSSLCertificateCache::Unknown;
00098 permanent = true; }
00099 ~KSSLCNode() { if (cert) delete cert; }
00100 };
00101
00102
00103
00104 void KSSLD::cacheSaveToDisk() {
00105 KSSLCNode *node;
00106
00107 for (node = certList.first(); node; node = certList.next()) {
00108 if (node->permanent || node->expires > QDateTime::currentDateTime()) {
00109
00110
00111 cfg->setGroup(node->cert->getSubject());
00112 cfg->writeEntry("Certificate", node->cert->toString());
00113 cfg->writeEntry("Policy", node->policy);
00114 cfg->writeEntry("Expires", node->expires);
00115 cfg->writeEntry("Permanent", node->permanent);
00116 cfg->writeEntry("Hosts", node->hosts);
00117
00118 QStringList qsl;
00119 QPtrList<KSSLCertificate> cl = node->cert->chain().getChain();
00120 for (KSSLCertificate *c = cl.first(); c != 0; c = cl.next()) {
00121
00122 qsl << c->toString();
00123 }
00124 cl.setAutoDelete(true);
00125 cfg->writeEntry("Chain", qsl);
00126 }
00127 }
00128
00129 cfg->sync();
00130
00131
00132 QString cfgName(KGlobal::dirs()->findResource("config", "ksslpolicies"));
00133 if (!cfgName.isEmpty())
00134 ::chmod(QFile::encodeName(cfgName), 0600);
00135 }
00136
00137
00138 void KSSLD::cacheReload() {
00139 cacheClearList();
00140 delete cfg;
00141 cfg = new KSimpleConfig("ksslpolicies", false);
00142 cacheLoadDefaultPolicies();
00143 }
00144
00145
00146 void KSSLD::cacheClearList() {
00147 KSSLCNode *node;
00148
00149 for (node = certList.first(); node; node = certList.next()) {
00150 certList.remove(node);
00151 delete node;
00152 }
00153 }
00154
00155
00156 void KSSLD::cacheLoadDefaultPolicies() {
00157 QStringList groups = cfg->groupList();
00158
00159 for (QStringList::Iterator i = groups.begin();
00160 i != groups.end();
00161 ++i) {
00162 if ((*i).length() == 0) continue;
00163 cfg->setGroup(*i);
00164
00165
00166 if (!cfg->readBoolEntry("Permanent") && cfg->readDateTimeEntry("Expires") < QDateTime::currentDateTime()) {
00167 cfg->deleteGroup(*i);
00168 continue;
00169 }
00170
00171 QCString encodedCert = cfg->readEntry("Certificate").local8Bit();
00172 KSSLCertificate *newCert = KSSLCertificate::fromString(encodedCert);
00173 if (!newCert) continue;
00174 KSSLCNode *n = new KSSLCNode;
00175 n->cert = newCert;
00176 n->policy = (KSSLCertificateCache::KSSLCertificatePolicy)
00177 cfg->readNumEntry("Policy");
00178 n->permanent = cfg->readBoolEntry("Permanent");
00179 n->expires = cfg->readDateTimeEntry("Expires");
00180 n->hosts = cfg->readListEntry("Hosts");
00181 newCert->chain().setChain(cfg->readListEntry("Chain"));
00182 certList.append(n);
00183 }
00184 }
00185
00186
00187 void KSSLD::cacheAddCertificate(KSSLCertificate cert,
00188 KSSLCertificateCache::KSSLCertificatePolicy policy, bool permanent) {
00189 KSSLCNode *node;
00190
00191 for (node = certList.first(); node; node = certList.next()) {
00192 if (cert == *(node->cert)) {
00193 node->policy = policy;
00194 node->permanent = permanent;
00195 if (!permanent) {
00196 node->expires = QDateTime::currentDateTime();
00197
00198 node->expires = node->expires.addSecs(3600);
00199 }
00200 cacheSaveToDisk();
00201 return;
00202 }
00203 }
00204
00205 KSSLCNode *n = new KSSLCNode;
00206 n->cert = cert.replicate();
00207 n->policy = policy;
00208 n->permanent = permanent;
00209 certList.prepend(n);
00210 if (!permanent) {
00211 n->expires = QDateTime::currentDateTime();
00212 n->expires = n->expires.addSecs(3600);
00213 }
00214 cacheSaveToDisk();
00215 }
00216
00217
00218 KSSLCertificateCache::KSSLCertificatePolicy KSSLD::cacheGetPolicyByCN(QString cn) {
00219 KSSLCNode *node;
00220
00221 for (node = certList.first(); node; node = certList.next()) {
00222 if (KSSLX509Map(node->cert->getSubject()).getValue("CN") == cn) {
00223 if (!node->permanent && node->expires < QDateTime::currentDateTime()) {
00224 certList.remove(node);
00225 cfg->deleteGroup(node->cert->getSubject());
00226 delete node;
00227 continue;
00228 }
00229 certList.remove(node);
00230 certList.prepend(node);
00231 cacheSaveToDisk();
00232 return node->policy;
00233 }
00234 }
00235 cacheSaveToDisk();
00236 return KSSLCertificateCache::Unknown;
00237 }
00238
00239
00240 KSSLCertificateCache::KSSLCertificatePolicy KSSLD::cacheGetPolicyByCertificate(KSSLCertificate cert) {
00241 KSSLCNode *node;
00242
00243 for (node = certList.first(); node; node = certList.next()) {
00244 if (cert == *(node->cert)) {
00245 if (!node->permanent && node->expires < QDateTime::currentDateTime()) {
00246 certList.remove(node);
00247 cfg->deleteGroup(node->cert->getSubject());
00248 delete node;
00249 cacheSaveToDisk();
00250 return KSSLCertificateCache::Unknown;
00251 }
00252 certList.remove(node);
00253 certList.prepend(node);
00254 return node->policy;
00255 }
00256 }
00257 return KSSLCertificateCache::Unknown;
00258 }
00259
00260
00261 bool KSSLD::cacheSeenCN(QString cn) {
00262 KSSLCNode *node;
00263
00264 for (node = certList.first(); node; node = certList.next()) {
00265 if (KSSLX509Map(node->cert->getSubject()).getValue("CN") == cn) {
00266 if (!node->permanent && node->expires < QDateTime::currentDateTime()) {
00267 certList.remove(node);
00268 cfg->deleteGroup(node->cert->getSubject());
00269 delete node;
00270 cacheSaveToDisk();
00271 continue;
00272 }
00273 certList.remove(node);
00274 certList.prepend(node);
00275 return true;
00276 }
00277 }
00278 return false;
00279 }
00280
00281
00282 bool KSSLD::cacheSeenCertificate(KSSLCertificate cert) {
00283 KSSLCNode *node;
00284
00285 for (node = certList.first(); node; node = certList.next()) {
00286 if (cert == *(node->cert)) {
00287 if (!node->permanent && node->expires < QDateTime::currentDateTime()) {
00288 certList.remove(node);
00289 cfg->deleteGroup(node->cert->getSubject());
00290 delete node;
00291 cacheSaveToDisk();
00292 return false;
00293 }
00294 certList.remove(node);
00295 certList.prepend(node);
00296 return true;
00297 }
00298 }
00299 return false;
00300 }
00301
00302
00303 bool KSSLD::cacheIsPermanent(KSSLCertificate cert) {
00304 KSSLCNode *node;
00305
00306 for (node = certList.first(); node; node = certList.next()) {
00307 if (cert == *(node->cert)) {
00308 if (!node->permanent && node->expires < QDateTime::currentDateTime()) {
00309 certList.remove(node);
00310 cfg->deleteGroup(node->cert->getSubject());
00311 delete node;
00312 cacheSaveToDisk();
00313 return false;
00314 }
00315 certList.remove(node);
00316 certList.prepend(node);
00317 return node->permanent;
00318 }
00319 }
00320 return false;
00321 }
00322
00323
00324 bool KSSLD::cacheRemoveByCN(QString cn) {
00325 KSSLCNode *node;
00326 bool gotOne = false;
00327
00328 for (node = certList.first(); node; node = certList.next()) {
00329 if (KSSLX509Map(node->cert->getSubject()).getValue("CN") == cn) {
00330 certList.remove(node);
00331 cfg->deleteGroup(node->cert->getSubject());
00332 delete node;
00333 gotOne = true;
00334 }
00335 }
00336 cacheSaveToDisk();
00337 return gotOne;
00338 }
00339
00340
00341 bool KSSLD::cacheRemoveByCertificate(KSSLCertificate cert) {
00342 KSSLCNode *node;
00343
00344 for (node = certList.first(); node; node = certList.next()) {
00345 if (cert == *(node->cert)) {
00346 certList.remove(node);
00347 cfg->deleteGroup(node->cert->getSubject());
00348 delete node;
00349 cacheSaveToDisk();
00350 return true;
00351 }
00352 }
00353 return false;
00354 }
00355
00356
00357 bool KSSLD::cacheModifyByCN(QString cn,
00358 KSSLCertificateCache::KSSLCertificatePolicy policy, bool permanent,
00359 QDateTime expires) {
00360 KSSLCNode *node;
00361
00362 for (node = certList.first(); node; node = certList.next()) {
00363 if (KSSLX509Map(node->cert->getSubject()).getValue("CN") == cn) {
00364 node->permanent = permanent;
00365 node->expires = expires;
00366 node->policy = policy;
00367 certList.remove(node);
00368 certList.prepend(node);
00369 cacheSaveToDisk();
00370 return true;
00371 }
00372 }
00373 return false;
00374 }
00375
00376
00377 bool KSSLD::cacheModifyByCertificate(KSSLCertificate cert,
00378 KSSLCertificateCache::KSSLCertificatePolicy policy, bool permanent,
00379 QDateTime expires) {
00380 KSSLCNode *node;
00381
00382 for (node = certList.first(); node; node = certList.next()) {
00383 if (cert == *(node->cert)) {
00384 node->permanent = permanent;
00385 node->expires = expires;
00386 node->policy = policy;
00387 certList.remove(node);
00388 certList.prepend(node);
00389 cacheSaveToDisk();
00390 return true;
00391 }
00392 }
00393 return false;
00394 }
00395
00396
00397 QStringList KSSLD::cacheGetHostList(KSSLCertificate cert) {
00398 KSSLCNode *node;
00399
00400 for (node = certList.first(); node; node = certList.next()) {
00401 if (cert == *(node->cert)) {
00402 if (!node->permanent && node->expires < QDateTime::currentDateTime()) {
00403 certList.remove(node);
00404 cfg->deleteGroup(node->cert->getSubject());
00405 delete node;
00406 cacheSaveToDisk();
00407 return QStringList();
00408 }
00409 certList.remove(node);
00410 certList.prepend(node);
00411 return node->hosts;
00412 }
00413 }
00414 return QStringList();
00415 }
00416
00417
00418 bool KSSLD::cacheAddHost(KSSLCertificate cert, QString host) {
00419 KSSLCNode *node;
00420
00421 if (host.isEmpty())
00422 return true;
00423
00424 for (node = certList.first(); node; node = certList.next()) {
00425 if (cert == *(node->cert)) {
00426 if (!node->permanent && node->expires < QDateTime::currentDateTime()) {
00427 certList.remove(node);
00428 cfg->deleteGroup(node->cert->getSubject());
00429 delete node;
00430 cacheSaveToDisk();
00431 return false;
00432 }
00433 if (!node->hosts.contains(host))
00434 node->hosts << host;
00435 certList.remove(node);
00436 certList.prepend(node);
00437 cacheSaveToDisk();
00438 return true;
00439 }
00440 }
00441 return false;
00442 }
00443
00444
00445 bool KSSLD::cacheRemoveHost(KSSLCertificate cert, QString host) {
00446 KSSLCNode *node;
00447
00448 for (node = certList.first(); node; node = certList.next()) {
00449 if (cert == *(node->cert)) {
00450 if (!node->permanent && node->expires < QDateTime::currentDateTime()) {
00451 certList.remove(node);
00452 cfg->deleteGroup(node->cert->getSubject());
00453 delete node;
00454 cacheSaveToDisk();
00455 return false;
00456 }
00457 node->hosts.remove(host);
00458 certList.remove(node);
00459 certList.prepend(node);
00460 cacheSaveToDisk();
00461 return true;
00462 }
00463 }
00464 return false;
00465 }
00466
00467
00468
00469
00471
00472
00473 bool KSSLD::caRegenerate() {
00474 QString path = KGlobal::dirs()->saveLocation("kssl") + "/ca-bundle.crt";
00475
00476 QFile out(path);
00477
00478 if (!out.open(IO_WriteOnly))
00479 return false;
00480
00481 KConfig cfg("ksslcalist", true, false);
00482
00483 QStringList x = cfg.groupList();
00484
00485 for (QStringList::Iterator i = x.begin();
00486 i != x.end();
00487 ++i) {
00488 if ((*i).isEmpty() || *i == "<default>") continue;
00489
00490 cfg.setGroup(*i);
00491
00492 if (!cfg.readBoolEntry("site", false)) continue;
00493
00494 QString cert = cfg.readEntry("x509", "");
00495 if (cert.length() <= 0) continue;
00496
00497 unsigned int xx = cert.length() - 1;
00498 for (unsigned int j = 0; j < xx/64; j++) {
00499 cert.insert(64*(j+1)+j, '\n');
00500 }
00501 out.writeBlock("-----BEGIN CERTIFICATE-----\n", 28);
00502 out.writeBlock(cert.latin1(), cert.length());
00503 out.writeBlock("\n-----END CERTIFICATE-----\n\n", 28);
00504 out.flush();
00505 }
00506
00507 return true;
00508 }
00509
00510
00511
00512 bool KSSLD::caAdd(QString certificate, bool ssl, bool email, bool code) {
00513 KSSLCertificate *x = KSSLCertificate::fromString(certificate.local8Bit());
00514
00515 if (!x) return false;
00516
00517 KConfig cfg("ksslcalist", false, false);
00518
00519 cfg.setGroup(x->getSubject());
00520 cfg.writeEntry("x509", certificate);
00521 cfg.writeEntry("site", ssl);
00522 cfg.writeEntry("email", email);
00523 cfg.writeEntry("code", code);
00524
00525 cfg.sync();
00526 delete x;
00527
00528 return true;
00529 }
00530
00531
00532 QStringList KSSLD::caList() {
00533 QStringList x;
00534 KConfig cfg("ksslcalist", true, false);
00535
00536 x = cfg.groupList();
00537 x.remove("<default>");
00538
00539 return x;
00540 }
00541
00542
00543 bool KSSLD::caUseForSSL(QString subject) {
00544 KConfig cfg("ksslcalist", true, false);
00545
00546 if (!cfg.hasGroup(subject))
00547 return false;
00548
00549 cfg.setGroup(subject);
00550 return cfg.readBoolEntry("site", false);
00551 }
00552
00553
00554
00555 bool KSSLD::caUseForEmail(QString subject) {
00556 KConfig cfg("ksslcalist", true, false);
00557
00558 if (!cfg.hasGroup(subject))
00559 return false;
00560
00561 cfg.setGroup(subject);
00562 return cfg.readBoolEntry("email", false);
00563 }
00564
00565
00566
00567 bool KSSLD::caUseForCode(QString subject) {
00568 KConfig cfg("ksslcalist", true, false);
00569
00570 if (!cfg.hasGroup(subject))
00571 return false;
00572
00573 cfg.setGroup(subject);
00574 return cfg.readBoolEntry("code", false);
00575 }
00576
00577
00578 bool KSSLD::caRemove(QString subject) {
00579 KConfig cfg("ksslcalist", false, false);
00580 if (!cfg.hasGroup(subject))
00581 return false;
00582
00583 cfg.deleteGroup(subject);
00584 cfg.sync();
00585
00586 return true;
00587 }
00588
00589
00590 QString KSSLD::caGetCert(QString subject) {
00591 KConfig cfg("ksslcalist", true, false);
00592 if (!cfg.hasGroup(subject))
00593 return QString::null;
00594
00595 cfg.setGroup(subject);
00596
00597 return cfg.readEntry("x509", QString::null);
00598 }
00599
00600
00601 bool KSSLD::caSetUse(QString subject, bool ssl, bool email, bool code) {
00602 KConfig cfg("ksslcalist", false, false);
00603 if (!cfg.hasGroup(subject))
00604 return false;
00605
00606 cfg.setGroup(subject);
00607
00608 cfg.writeEntry("site", ssl);
00609 cfg.writeEntry("email", email);
00610 cfg.writeEntry("code", code);
00611 cfg.sync();
00612
00613 return true;
00614 }
00615
00616
00617
00619
00620
00621
00622
00623
00625
00626 #include "kssld.moc"
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671