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 cacheRemoveByCN(KSSLX509Map(n->cert->getSubject()).getValue("CN"));
00210 certList.prepend(n);
00211 if (!permanent) {
00212 n->expires = QDateTime::currentDateTime();
00213 n->expires = n->expires.addSecs(3600);
00214 }
00215 cacheSaveToDisk();
00216 }
00217
00218
00219 KSSLCertificateCache::KSSLCertificatePolicy KSSLD::cacheGetPolicyByCN(QString cn) {
00220 KSSLCNode *node;
00221
00222 for (node = certList.first(); node; node = certList.next()) {
00223 if (KSSLX509Map(node->cert->getSubject()).getValue("CN") == cn) {
00224 if (!node->permanent && node->expires < QDateTime::currentDateTime()) {
00225 certList.remove(node);
00226 cfg->deleteGroup(node->cert->getSubject());
00227 delete node;
00228 continue;
00229 }
00230 certList.remove(node);
00231 certList.prepend(node);
00232 cacheSaveToDisk();
00233 return node->policy;
00234 }
00235 }
00236 cacheSaveToDisk();
00237 return KSSLCertificateCache::Unknown;
00238 }
00239
00240
00241 KSSLCertificateCache::KSSLCertificatePolicy KSSLD::cacheGetPolicyByCertificate(KSSLCertificate cert) {
00242 KSSLCNode *node;
00243
00244 for (node = certList.first(); node; node = certList.next()) {
00245 if (cert == *(node->cert)) {
00246 if (!node->permanent && node->expires < QDateTime::currentDateTime()) {
00247 certList.remove(node);
00248 cfg->deleteGroup(node->cert->getSubject());
00249 delete node;
00250 cacheSaveToDisk();
00251 return KSSLCertificateCache::Unknown;
00252 }
00253 certList.remove(node);
00254 certList.prepend(node);
00255 return node->policy;
00256 }
00257 }
00258 return KSSLCertificateCache::Unknown;
00259 }
00260
00261
00262 bool KSSLD::cacheSeenCN(QString cn) {
00263 KSSLCNode *node;
00264
00265 for (node = certList.first(); node; node = certList.next()) {
00266 if (KSSLX509Map(node->cert->getSubject()).getValue("CN") == cn) {
00267 if (!node->permanent && node->expires < QDateTime::currentDateTime()) {
00268 certList.remove(node);
00269 cfg->deleteGroup(node->cert->getSubject());
00270 delete node;
00271 cacheSaveToDisk();
00272 continue;
00273 }
00274 certList.remove(node);
00275 certList.prepend(node);
00276 return true;
00277 }
00278 }
00279 return false;
00280 }
00281
00282
00283 bool KSSLD::cacheSeenCertificate(KSSLCertificate cert) {
00284 KSSLCNode *node;
00285
00286 for (node = certList.first(); node; node = certList.next()) {
00287 if (cert == *(node->cert)) {
00288 if (!node->permanent && node->expires < QDateTime::currentDateTime()) {
00289 certList.remove(node);
00290 cfg->deleteGroup(node->cert->getSubject());
00291 delete node;
00292 cacheSaveToDisk();
00293 return false;
00294 }
00295 certList.remove(node);
00296 certList.prepend(node);
00297 return true;
00298 }
00299 }
00300 return false;
00301 }
00302
00303
00304 bool KSSLD::cacheIsPermanent(KSSLCertificate cert) {
00305 KSSLCNode *node;
00306
00307 for (node = certList.first(); node; node = certList.next()) {
00308 if (cert == *(node->cert)) {
00309 if (!node->permanent && node->expires < QDateTime::currentDateTime()) {
00310 certList.remove(node);
00311 cfg->deleteGroup(node->cert->getSubject());
00312 delete node;
00313 cacheSaveToDisk();
00314 return false;
00315 }
00316 certList.remove(node);
00317 certList.prepend(node);
00318 return node->permanent;
00319 }
00320 }
00321 return false;
00322 }
00323
00324
00325 bool KSSLD::cacheRemoveByCN(QString cn) {
00326 KSSLCNode *node;
00327 bool gotOne = false;
00328
00329 for (node = certList.first(); node; node = certList.next()) {
00330 if (KSSLX509Map(node->cert->getSubject()).getValue("CN") == cn) {
00331 certList.remove(node);
00332 cfg->deleteGroup(node->cert->getSubject());
00333 delete node;
00334 gotOne = true;
00335 }
00336 }
00337 cacheSaveToDisk();
00338 return gotOne;
00339 }
00340
00341
00342 bool KSSLD::cacheRemoveByCertificate(KSSLCertificate cert) {
00343 KSSLCNode *node;
00344
00345 for (node = certList.first(); node; node = certList.next()) {
00346 if (cert == *(node->cert)) {
00347 certList.remove(node);
00348 cfg->deleteGroup(node->cert->getSubject());
00349 delete node;
00350 cacheSaveToDisk();
00351 return true;
00352 }
00353 }
00354 return false;
00355 }
00356
00357
00358 bool KSSLD::cacheModifyByCN(QString cn,
00359 KSSLCertificateCache::KSSLCertificatePolicy policy, bool permanent,
00360 QDateTime expires) {
00361 KSSLCNode *node;
00362
00363 for (node = certList.first(); node; node = certList.next()) {
00364 if (KSSLX509Map(node->cert->getSubject()).getValue("CN") == cn) {
00365 node->permanent = permanent;
00366 node->expires = expires;
00367 node->policy = policy;
00368 certList.remove(node);
00369 certList.prepend(node);
00370 cacheSaveToDisk();
00371 return true;
00372 }
00373 }
00374 return false;
00375 }
00376
00377
00378 bool KSSLD::cacheModifyByCertificate(KSSLCertificate cert,
00379 KSSLCertificateCache::KSSLCertificatePolicy policy, bool permanent,
00380 QDateTime expires) {
00381 KSSLCNode *node;
00382
00383 for (node = certList.first(); node; node = certList.next()) {
00384 if (cert == *(node->cert)) {
00385 node->permanent = permanent;
00386 node->expires = expires;
00387 node->policy = policy;
00388 certList.remove(node);
00389 certList.prepend(node);
00390 cacheSaveToDisk();
00391 return true;
00392 }
00393 }
00394 return false;
00395 }
00396
00397
00398 QStringList KSSLD::cacheGetHostList(KSSLCertificate cert) {
00399 KSSLCNode *node;
00400
00401 for (node = certList.first(); node; node = certList.next()) {
00402 if (cert == *(node->cert)) {
00403 if (!node->permanent && node->expires < QDateTime::currentDateTime()) {
00404 certList.remove(node);
00405 cfg->deleteGroup(node->cert->getSubject());
00406 delete node;
00407 cacheSaveToDisk();
00408 return QStringList();
00409 }
00410 certList.remove(node);
00411 certList.prepend(node);
00412 return node->hosts;
00413 }
00414 }
00415 return QStringList();
00416 }
00417
00418
00419 bool KSSLD::cacheAddHost(KSSLCertificate cert, QString host) {
00420 KSSLCNode *node;
00421
00422 if (host.isEmpty())
00423 return true;
00424
00425 for (node = certList.first(); node; node = certList.next()) {
00426 if (cert == *(node->cert)) {
00427 if (!node->permanent && node->expires < QDateTime::currentDateTime()) {
00428 certList.remove(node);
00429 cfg->deleteGroup(node->cert->getSubject());
00430 delete node;
00431 cacheSaveToDisk();
00432 return false;
00433 }
00434 if (!node->hosts.contains(host))
00435 node->hosts << host;
00436 certList.remove(node);
00437 certList.prepend(node);
00438 cacheSaveToDisk();
00439 return true;
00440 }
00441 }
00442 return false;
00443 }
00444
00445
00446 bool KSSLD::cacheRemoveHost(KSSLCertificate cert, QString host) {
00447 KSSLCNode *node;
00448
00449 for (node = certList.first(); node; node = certList.next()) {
00450 if (cert == *(node->cert)) {
00451 if (!node->permanent && node->expires < QDateTime::currentDateTime()) {
00452 certList.remove(node);
00453 cfg->deleteGroup(node->cert->getSubject());
00454 delete node;
00455 cacheSaveToDisk();
00456 return false;
00457 }
00458 node->hosts.remove(host);
00459 certList.remove(node);
00460 certList.prepend(node);
00461 cacheSaveToDisk();
00462 return true;
00463 }
00464 }
00465 return false;
00466 }
00467
00468
00469
00470
00472
00473
00474 bool KSSLD::caRegenerate() {
00475 QString path = KGlobal::dirs()->saveLocation("kssl") + "/ca-bundle.crt";
00476
00477 QFile out(path);
00478
00479 if (!out.open(IO_WriteOnly))
00480 return false;
00481
00482 KConfig cfg("ksslcalist", true, false);
00483
00484 QStringList x = cfg.groupList();
00485
00486 for (QStringList::Iterator i = x.begin();
00487 i != x.end();
00488 ++i) {
00489 if ((*i).isEmpty() || *i == "<default>") continue;
00490
00491 cfg.setGroup(*i);
00492
00493 if (!cfg.readBoolEntry("site", false)) continue;
00494
00495 QString cert = cfg.readEntry("x509", "");
00496 if (cert.length() <= 0) continue;
00497
00498 unsigned int xx = cert.length() - 1;
00499 for (unsigned int j = 0; j < xx/64; j++) {
00500 cert.insert(64*(j+1)+j, '\n');
00501 }
00502 out.writeBlock("-----BEGIN CERTIFICATE-----\n", 28);
00503 out.writeBlock(cert.latin1(), cert.length());
00504 out.writeBlock("\n-----END CERTIFICATE-----\n\n", 28);
00505 out.flush();
00506 }
00507
00508 return true;
00509 }
00510
00511
00512
00513 bool KSSLD::caAdd(QString certificate, bool ssl, bool email, bool code) {
00514 KSSLCertificate *x = KSSLCertificate::fromString(certificate.local8Bit());
00515
00516 if (!x) return false;
00517
00518 KConfig cfg("ksslcalist", false, false);
00519
00520 cfg.setGroup(x->getSubject());
00521 cfg.writeEntry("x509", certificate);
00522 cfg.writeEntry("site", ssl);
00523 cfg.writeEntry("email", email);
00524 cfg.writeEntry("code", code);
00525
00526 cfg.sync();
00527 delete x;
00528
00529 return true;
00530 }
00531
00532
00533 QStringList KSSLD::caList() {
00534 QStringList x;
00535 KConfig cfg("ksslcalist", true, false);
00536
00537 x = cfg.groupList();
00538 x.remove("<default>");
00539
00540 return x;
00541 }
00542
00543
00544 bool KSSLD::caUseForSSL(QString subject) {
00545 KConfig cfg("ksslcalist", true, false);
00546
00547 if (!cfg.hasGroup(subject))
00548 return false;
00549
00550 cfg.setGroup(subject);
00551 return cfg.readBoolEntry("site", false);
00552 }
00553
00554
00555
00556 bool KSSLD::caUseForEmail(QString subject) {
00557 KConfig cfg("ksslcalist", true, false);
00558
00559 if (!cfg.hasGroup(subject))
00560 return false;
00561
00562 cfg.setGroup(subject);
00563 return cfg.readBoolEntry("email", false);
00564 }
00565
00566
00567
00568 bool KSSLD::caUseForCode(QString subject) {
00569 KConfig cfg("ksslcalist", true, false);
00570
00571 if (!cfg.hasGroup(subject))
00572 return false;
00573
00574 cfg.setGroup(subject);
00575 return cfg.readBoolEntry("code", false);
00576 }
00577
00578
00579 bool KSSLD::caRemove(QString subject) {
00580 KConfig cfg("ksslcalist", false, false);
00581 if (!cfg.hasGroup(subject))
00582 return false;
00583
00584 cfg.deleteGroup(subject);
00585 cfg.sync();
00586
00587 return true;
00588 }
00589
00590
00591 QString KSSLD::caGetCert(QString subject) {
00592 KConfig cfg("ksslcalist", true, false);
00593 if (!cfg.hasGroup(subject))
00594 return QString::null;
00595
00596 cfg.setGroup(subject);
00597
00598 return cfg.readEntry("x509", QString::null);
00599 }
00600
00601
00602 bool KSSLD::caSetUse(QString subject, bool ssl, bool email, bool code) {
00603 KConfig cfg("ksslcalist", false, false);
00604 if (!cfg.hasGroup(subject))
00605 return false;
00606
00607 cfg.setGroup(subject);
00608
00609 cfg.writeEntry("site", ssl);
00610 cfg.writeEntry("email", email);
00611 cfg.writeEntry("code", code);
00612 cfg.sync();
00613
00614 return true;
00615 }
00616
00617
00618
00620
00621
00622
00623
00624
00626
00627 #include "kssld.moc"
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
00672