00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifdef HAVE_CONFIG_H
00023 #include <config.h>
00024 #endif
00025
00026
00027
00028 #include <unistd.h>
00029 #include <qstring.h>
00030 #include <qstringlist.h>
00031 #include <qfile.h>
00032
00033 #include "kssldefs.h"
00034 #include "ksslcertificate.h"
00035 #include "ksslcertchain.h"
00036 #include "ksslutils.h"
00037
00038 #include <kstandarddirs.h>
00039 #include <kmdcodec.h>
00040 #include <klocale.h>
00041 #include <qdatetime.h>
00042 #include <ktempfile.h>
00043
00044 #include <sys/types.h>
00045
00046 #ifdef HAVE_SYS_STAT_H
00047 #include <sys/stat.h>
00048 #endif
00049
00050
00051
00052 #ifdef KSSL_HAVE_SSL
00053 #define crypt _openssl_crypt
00054 #include <openssl/ssl.h>
00055 #include <openssl/x509.h>
00056 #include <openssl/x509v3.h>
00057 #include <openssl/x509_vfy.h>
00058 #include <openssl/pem.h>
00059 #undef crypt
00060 #endif
00061
00062 #include <kopenssl.h>
00063 #include <qcstring.h>
00064 #include <kdebug.h>
00065 #include "ksslx509v3.h"
00066
00067
00068
00069 static char hv[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
00070
00071
00072 class KSSLCertificatePrivate {
00073 public:
00074 KSSLCertificatePrivate() {
00075 kossl = KOSSL::self();
00076 _lastPurpose = KSSLCertificate::None;
00077 }
00078
00079 ~KSSLCertificatePrivate() {
00080 }
00081
00082 KSSLCertificate::KSSLValidation m_stateCache;
00083 bool m_stateCached;
00084 #ifdef KSSL_HAVE_SSL
00085 X509 *m_cert;
00086 #endif
00087 KOSSL *kossl;
00088 KSSLCertChain _chain;
00089 KSSLX509V3 _extensions;
00090 KSSLCertificate::KSSLPurpose _lastPurpose;
00091 };
00092
00093 KSSLCertificate::KSSLCertificate() {
00094 d = new KSSLCertificatePrivate;
00095 d->m_stateCached = false;
00096 KGlobal::dirs()->addResourceType("kssl", KStandardDirs::kde_default("data") + "kssl");
00097 #ifdef KSSL_HAVE_SSL
00098 d->m_cert = NULL;
00099 #endif
00100 }
00101
00102
00103 KSSLCertificate::KSSLCertificate(const KSSLCertificate& x) {
00104 d = new KSSLCertificatePrivate;
00105 d->m_stateCached = false;
00106 KGlobal::dirs()->addResourceType("kssl", KStandardDirs::kde_default("data") + "kssl");
00107 #ifdef KSSL_HAVE_SSL
00108 d->m_cert = NULL;
00109 setCert(KOSSL::self()->X509_dup(const_cast<KSSLCertificate&>(x).getCert()));
00110 KSSLCertChain *c = x.d->_chain.replicate();
00111 setChain(c->rawChain());
00112 delete c;
00113 #endif
00114 }
00115
00116
00117
00118 KSSLCertificate::~KSSLCertificate() {
00119 #ifdef KSSL_HAVE_SSL
00120 if (d->m_cert)
00121 d->kossl->X509_free(d->m_cert);
00122 #endif
00123 delete d;
00124 }
00125
00126
00127 KSSLCertChain& KSSLCertificate::chain() {
00128 return d->_chain;
00129 }
00130
00131
00132 KSSLCertificate *KSSLCertificate::fromX509(X509 *x5) {
00133 KSSLCertificate *n = NULL;
00134 #ifdef KSSL_HAVE_SSL
00135 if (x5) {
00136 n = new KSSLCertificate;
00137 n->setCert(KOSSL::self()->X509_dup(x5));
00138 }
00139 #endif
00140 return n;
00141 }
00142
00143
00144 KSSLCertificate *KSSLCertificate::fromString(QCString cert) {
00145 KSSLCertificate *n = NULL;
00146 #ifdef KSSL_HAVE_SSL
00147 if (cert.length() == 0)
00148 return NULL;
00149
00150 QByteArray qba, qbb = cert.copy();
00151 KCodecs::base64Decode(qbb, qba);
00152 unsigned char *qbap = reinterpret_cast<unsigned char *>(qba.data());
00153 X509 *x5c = KOSSL::self()->d2i_X509(NULL, &qbap, qba.size());
00154 if (!x5c) {
00155 return NULL;
00156 }
00157
00158 n = new KSSLCertificate;
00159 n->setCert(x5c);
00160 #endif
00161 return n;
00162 }
00163
00164
00165
00166 QString KSSLCertificate::getSubject() const {
00167 QString rc = "";
00168
00169 #ifdef KSSL_HAVE_SSL
00170 char *t = d->kossl->X509_NAME_oneline(d->kossl->X509_get_subject_name(d->m_cert), 0, 0);
00171 if (!t)
00172 return rc;
00173 rc = t;
00174 d->kossl->OPENSSL_free(t);
00175 #endif
00176 return rc;
00177 }
00178
00179
00180 QString KSSLCertificate::getSerialNumber() const {
00181 QString rc = "";
00182
00183 #ifdef KSSL_HAVE_SSL
00184 ASN1_INTEGER *aint = d->kossl->X509_get_serialNumber(d->m_cert);
00185 if (aint) {
00186 rc = ASN1_INTEGER_QString(aint);
00187
00188 }
00189 #endif
00190 return rc;
00191 }
00192
00193
00194 QString KSSLCertificate::getSignatureText() const {
00195 QString rc = "";
00196
00197 #ifdef KSSL_HAVE_SSL
00198 char *s;
00199 int n, i;
00200
00201 i = d->kossl->OBJ_obj2nid(d->m_cert->sig_alg->algorithm);
00202 rc = i18n("Signature Algorithm: ");
00203 rc += (i == NID_undef)?i18n("Unknown"):QString(d->kossl->OBJ_nid2ln(i));
00204
00205 rc += "\n";
00206 rc += i18n("Signature Contents:");
00207 n = d->m_cert->signature->length;
00208 s = (char *)d->m_cert->signature->data;
00209 for (i = 0; i < n; i++) {
00210 if (i%20 != 0) rc += ":";
00211 else rc += "\n";
00212 rc.append(hv[(s[i]&0xf0)>>4]);
00213 rc.append(hv[s[i]&0x0f]);
00214 }
00215
00216 #endif
00217
00218 return rc;
00219 }
00220
00221
00222 void KSSLCertificate::getEmails(QStringList &to) const {
00223 to.clear();
00224 #ifdef KSSL_HAVE_SSL
00225 if (!d->m_cert)
00226 return;
00227
00228 STACK *s = d->kossl->X509_get1_email(d->m_cert);
00229 if (s) {
00230 for(int n=0; n < s->num; n++) {
00231 to.append(d->kossl->sk_value(s,n));
00232 }
00233 d->kossl->X509_email_free(s);
00234 }
00235 #endif
00236 }
00237
00238
00239 QString KSSLCertificate::getKDEKey() const {
00240 return getSubject() + " (" + getMD5DigestText() + ")";
00241 }
00242
00243
00244 QString KSSLCertificate::getMD5DigestFromKDEKey(const QString &k) {
00245 QString rc;
00246 int pos = k.findRev('(');
00247 if (pos != -1) {
00248 unsigned int len = k.length();
00249 if (k.at(len-1) == ')') {
00250 rc = k.mid(pos+1, len-pos-2);
00251 }
00252 }
00253 return rc;
00254 }
00255
00256
00257 QString KSSLCertificate::getMD5DigestText() const {
00258 QString rc = "";
00259
00260 #ifdef KSSL_HAVE_SSL
00261 unsigned int n;
00262 unsigned char md[EVP_MAX_MD_SIZE];
00263
00264 if (!d->kossl->X509_digest(d->m_cert, d->kossl->EVP_md5(), md, &n)) {
00265 return rc;
00266 }
00267
00268 for (unsigned int j = 0; j < n; j++) {
00269 if (j > 0)
00270 rc += ":";
00271 rc.append(hv[(md[j]&0xf0)>>4]);
00272 rc.append(hv[md[j]&0x0f]);
00273 }
00274
00275 #endif
00276
00277 return rc;
00278 }
00279
00280
00281
00282 QString KSSLCertificate::getKeyType() const {
00283 QString rc = "";
00284
00285 #ifdef KSSL_HAVE_SSL
00286 EVP_PKEY *pkey = d->kossl->X509_get_pubkey(d->m_cert);
00287 if (pkey) {
00288 #ifndef NO_RSA
00289 if (pkey->type == EVP_PKEY_RSA)
00290 rc = "RSA";
00291 else
00292 #endif
00293 #ifndef NO_DSA
00294 if (pkey->type == EVP_PKEY_DSA)
00295 rc = "DSA";
00296 else
00297 #endif
00298 rc = "Unknown";
00299 d->kossl->EVP_PKEY_free(pkey);
00300 }
00301 #endif
00302
00303 return rc;
00304 }
00305
00306
00307
00308 QString KSSLCertificate::getPublicKeyText() const {
00309 QString rc = "";
00310 char *x = NULL;
00311
00312 #ifdef KSSL_HAVE_SSL
00313 EVP_PKEY *pkey = d->kossl->X509_get_pubkey(d->m_cert);
00314 if (pkey) {
00315 rc = i18n("Unknown", "Unknown key algorithm");
00316 #ifndef NO_RSA
00317 if (pkey->type == EVP_PKEY_RSA) {
00318 rc = i18n("Key type: RSA (%1 bit)") + "\n";
00319
00320 x = d->kossl->BN_bn2hex(pkey->pkey.rsa->n);
00321 rc += i18n("Modulus: ");
00322 rc = rc.arg(strlen(x)*4);
00323 for (unsigned int i = 0; i < strlen(x); i++) {
00324 if (i%40 != 0 && i%2 == 0)
00325 rc += ":";
00326 else if (i%40 == 0)
00327 rc += "\n";
00328 rc += x[i];
00329 }
00330 rc += "\n";
00331 d->kossl->OPENSSL_free(x);
00332
00333 x = d->kossl->BN_bn2hex(pkey->pkey.rsa->e);
00334 rc += i18n("Exponent: 0x") + x + "\n";
00335 d->kossl->OPENSSL_free(x);
00336 }
00337 #endif
00338 #ifndef NO_DSA
00339 if (pkey->type == EVP_PKEY_DSA) {
00340 rc = i18n("Key type: DSA (%1 bit)") + "\n";
00341
00342 x = d->kossl->BN_bn2hex(pkey->pkey.dsa->p);
00343 rc += i18n("Prime: ");
00344
00345 rc = rc.arg(strlen(x)*4) ;
00346 for (unsigned int i = 0; i < strlen(x); i++) {
00347 if (i%40 != 0 && i%2 == 0)
00348 rc += ":";
00349 else if (i%40 == 0)
00350 rc += "\n";
00351 rc += x[i];
00352 }
00353 rc += "\n";
00354 d->kossl->OPENSSL_free(x);
00355
00356 x = d->kossl->BN_bn2hex(pkey->pkey.dsa->q);
00357 rc += i18n("160 bit prime factor: ");
00358 for (unsigned int i = 0; i < strlen(x); i++) {
00359 if (i%40 != 0 && i%2 == 0)
00360 rc += ":";
00361 else if (i%40 == 0)
00362 rc += "\n";
00363 rc += x[i];
00364 }
00365 rc += "\n";
00366 d->kossl->OPENSSL_free(x);
00367
00368 x = d->kossl->BN_bn2hex(pkey->pkey.dsa->g);
00369 rc += QString("g: ");
00370 for (unsigned int i = 0; i < strlen(x); i++) {
00371 if (i%40 != 0 && i%2 == 0)
00372 rc += ":";
00373 else if (i%40 == 0)
00374 rc += "\n";
00375 rc += x[i];
00376 }
00377 rc += "\n";
00378 d->kossl->OPENSSL_free(x);
00379
00380 x = d->kossl->BN_bn2hex(pkey->pkey.dsa->pub_key);
00381 rc += i18n("Public key: ");
00382 for (unsigned int i = 0; i < strlen(x); i++) {
00383 if (i%40 != 0 && i%2 == 0)
00384 rc += ":";
00385 else if (i%40 == 0)
00386 rc += "\n";
00387 rc += x[i];
00388 }
00389 rc += "\n";
00390 d->kossl->OPENSSL_free(x);
00391 }
00392 #endif
00393 d->kossl->EVP_PKEY_free(pkey);
00394 }
00395 #endif
00396
00397 return rc;
00398 }
00399
00400
00401
00402 QString KSSLCertificate::getIssuer() const {
00403 QString rc = "";
00404
00405 #ifdef KSSL_HAVE_SSL
00406 char *t = d->kossl->X509_NAME_oneline(d->kossl->X509_get_issuer_name(d->m_cert), 0, 0);
00407
00408 if (!t)
00409 return rc;
00410
00411 rc = t;
00412 d->kossl->OPENSSL_free(t);
00413 #endif
00414
00415 return rc;
00416 }
00417
00418 void KSSLCertificate::setChain(void *c) {
00419 #ifdef KSSL_HAVE_SSL
00420 d->_chain.setChain(c);
00421 #endif
00422 d->m_stateCached = false;
00423 d->m_stateCache = KSSLCertificate::Unknown;
00424 }
00425
00426 void KSSLCertificate::setCert(X509 *c) {
00427 #ifdef KSSL_HAVE_SSL
00428 d->m_cert = c;
00429 if (c) {
00430 d->_extensions.flags = 0;
00431 d->kossl->X509_check_purpose(c, -1, 0);
00432
00433 #if 0
00434 kdDebug(7029) << "---------------- Certificate ------------------"
00435 << endl;
00436 kdDebug(7029) << getSubject() << endl;
00437 #endif
00438
00439 for (int j = 0; j < d->kossl->X509_PURPOSE_get_count(); j++) {
00440 X509_PURPOSE *ptmp = d->kossl->X509_PURPOSE_get0(j);
00441 int id = d->kossl->X509_PURPOSE_get_id(ptmp);
00442 for (int ca = 0; ca < 2; ca++) {
00443 int idret = d->kossl->X509_check_purpose(c, id, ca);
00444 if (idret == 1 || idret == 2) {
00445
00446 if (!ca)
00447 d->_extensions.flags |= (1L <<(id-1));
00448 else d->_extensions.flags |= (1L <<(16+id-1));
00449 } else {
00450 if (!ca)
00451 d->_extensions.flags &= ~(1L <<(id-1));
00452 else d->_extensions.flags &= ~(1L <<(16+id-1));
00453 }
00454 }
00455 }
00456
00457 #if 0
00458 kdDebug(7029) << "flags: " << QString::number(c->ex_flags, 2)
00459 << "\nkeyusage: " << QString::number(c->ex_kusage, 2)
00460 << "\nxkeyusage: " << QString::number(c->ex_xkusage, 2)
00461 << "\nnscert: " << QString::number(c->ex_nscert, 2)
00462 << endl;
00463 if (c->ex_flags & EXFLAG_KUSAGE)
00464 kdDebug(7029) << " --- Key Usage extensions found" << endl;
00465 else kdDebug(7029) << " --- Key Usage extensions NOT found" << endl;
00466
00467 if (c->ex_flags & EXFLAG_XKUSAGE)
00468 kdDebug(7029) << " --- Extended key usage extensions found" << endl;
00469 else kdDebug(7029) << " --- Extended key usage extensions NOT found" << endl;
00470
00471 if (c->ex_flags & EXFLAG_NSCERT)
00472 kdDebug(7029) << " --- NS extensions found" << endl;
00473 else kdDebug(7029) << " --- NS extensions NOT found" << endl;
00474
00475 if (d->_extensions.certTypeSSLCA())
00476 kdDebug(7029) << "NOTE: this is an SSL CA file." << endl;
00477 else kdDebug(7029) << "NOTE: this is NOT an SSL CA file." << endl;
00478
00479 if (d->_extensions.certTypeEmailCA())
00480 kdDebug(7029) << "NOTE: this is an EMAIL CA file." << endl;
00481 else kdDebug(7029) << "NOTE: this is NOT an EMAIL CA file." << endl;
00482
00483 if (d->_extensions.certTypeCodeCA())
00484 kdDebug(7029) << "NOTE: this is a CODE CA file." << endl;
00485 else kdDebug(7029) << "NOTE: this is NOT a CODE CA file." << endl;
00486
00487 if (d->_extensions.certTypeSSLClient())
00488 kdDebug(7029) << "NOTE: this is an SSL client." << endl;
00489 else kdDebug(7029) << "NOTE: this is NOT an SSL client." << endl;
00490
00491 if (d->_extensions.certTypeSSLServer())
00492 kdDebug(7029) << "NOTE: this is an SSL server." << endl;
00493 else kdDebug(7029) << "NOTE: this is NOT an SSL server." << endl;
00494
00495 if (d->_extensions.certTypeNSSSLServer())
00496 kdDebug(7029) << "NOTE: this is a NETSCAPE SSL server." << endl;
00497 else kdDebug(7029) << "NOTE: this is NOT a NETSCAPE SSL server." << endl;
00498
00499 if (d->_extensions.certTypeSMIME())
00500 kdDebug(7029) << "NOTE: this is an SMIME certificate." << endl;
00501 else kdDebug(7029) << "NOTE: this is NOT an SMIME certificate." << endl;
00502
00503 if (d->_extensions.certTypeSMIMEEncrypt())
00504 kdDebug(7029) << "NOTE: this is an SMIME encrypt cert." << endl;
00505 else kdDebug(7029) << "NOTE: this is NOT an SMIME encrypt cert." << endl;
00506
00507 if (d->_extensions.certTypeSMIMESign())
00508 kdDebug(7029) << "NOTE: this is an SMIME sign cert." << endl;
00509 else kdDebug(7029) << "NOTE: this is NOT an SMIME sign cert." << endl;
00510
00511 if (d->_extensions.certTypeCRLSign())
00512 kdDebug(7029) << "NOTE: this is a CRL signer." << endl;
00513 else kdDebug(7029) << "NOTE: this is NOT a CRL signer." << endl;
00514
00515 kdDebug(7029) << "-----------------------------------------------"
00516 << endl;
00517 #endif
00518 }
00519 #endif
00520 d->m_stateCached = false;
00521 d->m_stateCache = KSSLCertificate::Unknown;
00522 }
00523
00524 X509 *KSSLCertificate::getCert() {
00525 #ifdef KSSL_HAVE_SSL
00526 return d->m_cert;
00527 #endif
00528 return 0;
00529 }
00530
00531
00532
00533
00534 #include "ksslcallback.c"
00535
00536
00537 bool KSSLCertificate::isValid(KSSLCertificate::KSSLPurpose p) {
00538 return (validate(p) == KSSLCertificate::Ok);
00539 }
00540
00541
00542 bool KSSLCertificate::isValid() {
00543 return isValid(KSSLCertificate::SSLServer);
00544 }
00545
00546
00547 int KSSLCertificate::purposeToOpenSSL(KSSLCertificate::KSSLPurpose p) const {
00548 int rc = 0;
00549 #ifdef KSSL_HAVE_SSL
00550 if (p == KSSLCertificate::SSLServer) {
00551 rc = X509_PURPOSE_SSL_SERVER;
00552 } else if (p == KSSLCertificate::SSLClient) {
00553 rc = X509_PURPOSE_SSL_CLIENT;
00554 } else if (p == KSSLCertificate::SMIMEEncrypt) {
00555 rc = X509_PURPOSE_SMIME_ENCRYPT;
00556 } else if (p == KSSLCertificate::SMIMESign) {
00557 rc = X509_PURPOSE_SMIME_SIGN;
00558 } else if (p == KSSLCertificate::Any) {
00559 rc = X509_PURPOSE_ANY;
00560 }
00561 #endif
00562 return rc;
00563 }
00564
00565
00566
00567 KSSLCertificate::KSSLValidation KSSLCertificate::validate() {
00568 return validate(KSSLCertificate::SSLServer);
00569 }
00570
00571 KSSLCertificate::KSSLValidation KSSLCertificate::validate(KSSLCertificate::KSSLPurpose purpose)
00572 {
00573 KSSLValidationList result = validateVerbose(purpose);
00574 if (result.isEmpty())
00575 return KSSLCertificate::Ok;
00576 else
00577 return result.first();
00578 }
00579
00580
00581
00582
00583
00584
00585 KSSLCertificate::KSSLValidationList KSSLCertificate::validateVerbose(KSSLCertificate::KSSLPurpose purpose)
00586 {
00587 return validateVerbose(purpose, 0);
00588 }
00589
00590 KSSLCertificate::KSSLValidationList KSSLCertificate::validateVerbose(KSSLCertificate::KSSLPurpose purpose, KSSLCertificate *ca)
00591 {
00592 KSSLValidationList errors;
00593 if (ca || (d->_lastPurpose != purpose)) {
00594 d->m_stateCached = false;
00595 }
00596
00597 if (!d->m_stateCached)
00598 d->_lastPurpose = purpose;
00599
00600 #ifdef KSSL_HAVE_SSL
00601 X509_STORE *certStore;
00602 X509_LOOKUP *certLookup;
00603 X509_STORE_CTX *certStoreCTX;
00604 int rc = 0;
00605
00606 if (!d->m_cert)
00607 {
00608 errors << KSSLCertificate::Unknown;
00609 return errors;
00610 }
00611
00612 if (d->m_stateCached) {
00613 errors << d->m_stateCache;
00614 return errors;
00615 }
00616
00617 QStringList qsl = KGlobal::dirs()->resourceDirs("kssl");
00618
00619 if (qsl.isEmpty()) {
00620 errors << KSSLCertificate::NoCARoot;
00621 return errors;
00622 }
00623
00624 KSSLCertificate::KSSLValidation ksslv = Unknown;
00625
00626 for (QStringList::Iterator j = qsl.begin(); j != qsl.end(); ++j) {
00627 struct stat sb;
00628 QString _j = (*j) + "ca-bundle.crt";
00629 if (-1 == stat(_j.ascii(), &sb)) {
00630 continue;
00631 }
00632
00633 certStore = d->kossl->X509_STORE_new();
00634 if (!certStore) {
00635 errors << KSSLCertificate::Unknown;
00636 return errors;
00637 }
00638
00639 X509_STORE_set_verify_cb_func(certStore, X509Callback);
00640
00641 certLookup = d->kossl->X509_STORE_add_lookup(certStore, d->kossl->X509_LOOKUP_file());
00642 if (!certLookup) {
00643 ksslv = KSSLCertificate::Unknown;
00644 d->kossl->X509_STORE_free(certStore);
00645 continue;
00646 }
00647
00648 if (!d->kossl->X509_LOOKUP_load_file(certLookup, _j.ascii(), X509_FILETYPE_PEM)) {
00649
00650 kdDebug(7029) << "KSSL couldn't read CA root: "
00651 << _j << endl;
00652 ksslv = KSSLCertificate::ErrorReadingRoot;
00653 d->kossl->X509_STORE_free(certStore);
00654 continue;
00655 }
00656
00657
00658 certStoreCTX = d->kossl->X509_STORE_CTX_new();
00659
00660
00661
00662 if (!certStoreCTX) {
00663 kdDebug(7029) << "KSSL couldn't create an X509 store context." << endl;
00664 d->kossl->X509_STORE_free(certStore);
00665 continue;
00666 }
00667
00668 d->kossl->X509_STORE_CTX_init(certStoreCTX, certStore, d->m_cert, NULL);
00669 if (d->_chain.isValid()) {
00670 d->kossl->X509_STORE_CTX_set_chain(certStoreCTX, (STACK_OF(X509)*)d->_chain.rawChain());
00671 }
00672
00673
00674
00675
00676 d->kossl->X509_STORE_CTX_set_purpose(certStoreCTX, purposeToOpenSSL(purpose));
00677
00678 KSSL_X509CallBack_ca = ca ? ca->d->m_cert : 0;
00679 KSSL_X509CallBack_ca_found = false;
00680
00681 certStoreCTX->error = X509_V_OK;
00682 rc = d->kossl->X509_verify_cert(certStoreCTX);
00683 int errcode = certStoreCTX->error;
00684 if (ca && !KSSL_X509CallBack_ca_found) {
00685 ksslv = KSSLCertificate::Irrelevant;
00686 } else {
00687 ksslv = processError(errcode);
00688 }
00689
00690 if ( (ksslv != KSSLCertificate::Ok) &&
00691 (ksslv != KSSLCertificate::Irrelevant) &&
00692 purpose == KSSLCertificate::SSLServer) {
00693 d->kossl->X509_STORE_CTX_set_purpose(certStoreCTX,
00694 X509_PURPOSE_NS_SSL_SERVER);
00695
00696 certStoreCTX->error = X509_V_OK;
00697 rc = d->kossl->X509_verify_cert(certStoreCTX);
00698 errcode = certStoreCTX->error;
00699 ksslv = processError(errcode);
00700 }
00701 d->kossl->X509_STORE_CTX_free(certStoreCTX);
00702 d->kossl->X509_STORE_free(certStore);
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713 if (ksslv != NoCARoot && ksslv != InvalidCA) {
00714 d->m_stateCached = true;
00715 d->m_stateCache = ksslv;
00716 }
00717 break;
00718 }
00719
00720 if (ksslv != KSSLCertificate::Ok)
00721 errors << ksslv;
00722 #else
00723 errors << KSSLCertificate::NoSSL;
00724 #endif
00725 return errors;
00726 }
00727
00728
00729
00730 KSSLCertificate::KSSLValidation KSSLCertificate::revalidate() {
00731 return revalidate(KSSLCertificate::SSLServer);
00732 }
00733
00734
00735 KSSLCertificate::KSSLValidation KSSLCertificate::revalidate(KSSLCertificate::KSSLPurpose p) {
00736 d->m_stateCached = false;
00737 return validate(p);
00738 }
00739
00740
00741 KSSLCertificate::KSSLValidation KSSLCertificate::processError(int ec) {
00742 KSSLCertificate::KSSLValidation rc;
00743
00744 rc = KSSLCertificate::Unknown;
00745 #ifdef KSSL_HAVE_SSL
00746 switch (ec) {
00747 case X509_V_OK:
00748 rc = KSSLCertificate::Ok;
00749 break;
00750
00751
00752 case X509_V_ERR_CERT_REJECTED:
00753 rc = KSSLCertificate::Rejected;
00754 break;
00755
00756
00757 case X509_V_ERR_CERT_UNTRUSTED:
00758 rc = KSSLCertificate::Untrusted;
00759 break;
00760
00761
00762 case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
00763 case X509_V_ERR_CERT_SIGNATURE_FAILURE:
00764 case X509_V_ERR_CRL_SIGNATURE_FAILURE:
00765 case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE:
00766 case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE:
00767 rc = KSSLCertificate::SignatureFailed;
00768 break;
00769
00770 case X509_V_ERR_INVALID_CA:
00771 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
00772 case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY:
00773 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
00774 rc = KSSLCertificate::InvalidCA;
00775 break;
00776
00777
00778 case X509_V_ERR_INVALID_PURPOSE:
00779 rc = KSSLCertificate::InvalidPurpose;
00780 break;
00781
00782
00783 case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
00784 case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
00785 rc = KSSLCertificate::SelfSigned;
00786 break;
00787
00788
00789 case X509_V_ERR_CERT_REVOKED:
00790 rc = KSSLCertificate::Revoked;
00791 break;
00792
00793 case X509_V_ERR_PATH_LENGTH_EXCEEDED:
00794 rc = KSSLCertificate::PathLengthExceeded;
00795 break;
00796
00797 case X509_V_ERR_CERT_NOT_YET_VALID:
00798 case X509_V_ERR_CERT_HAS_EXPIRED:
00799 case X509_V_ERR_CRL_NOT_YET_VALID:
00800 case X509_V_ERR_CRL_HAS_EXPIRED:
00801 case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
00802 case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
00803 case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD:
00804 case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD:
00805 rc = KSSLCertificate::Expired;
00806 kdDebug(7029) << "KSSL apparently this is expired. Not after: "
00807 << getNotAfter() << endl;
00808 break;
00809
00810
00811 case X509_V_ERR_APPLICATION_VERIFICATION:
00812 case X509_V_ERR_OUT_OF_MEM:
00813 case X509_V_ERR_UNABLE_TO_GET_CRL:
00814 case X509_V_ERR_CERT_CHAIN_TOO_LONG:
00815 default:
00816 rc = KSSLCertificate::Unknown;
00817 break;
00818 }
00819
00820 d->m_stateCache = rc;
00821 d->m_stateCached = true;
00822 #endif
00823 return rc;
00824 }
00825
00826
00827 QString KSSLCertificate::getNotBefore() const {
00828 #ifdef KSSL_HAVE_SSL
00829 return ASN1_UTCTIME_QString(X509_get_notBefore(d->m_cert));
00830 #else
00831 return QString::null;
00832 #endif
00833 }
00834
00835
00836 QString KSSLCertificate::getNotAfter() const {
00837 #ifdef KSSL_HAVE_SSL
00838 return ASN1_UTCTIME_QString(X509_get_notAfter(d->m_cert));
00839 #else
00840 return QString::null;
00841 #endif
00842 }
00843
00844
00845 QDateTime KSSLCertificate::getQDTNotBefore() const {
00846 #ifdef KSSL_HAVE_SSL
00847 return ASN1_UTCTIME_QDateTime(X509_get_notBefore(d->m_cert), NULL);
00848 #else
00849 return QDateTime::currentDateTime();
00850 #endif
00851 }
00852
00853
00854 QDateTime KSSLCertificate::getQDTNotAfter() const {
00855 #ifdef KSSL_HAVE_SSL
00856 return ASN1_UTCTIME_QDateTime(X509_get_notAfter(d->m_cert), NULL);
00857 #else
00858 return QDateTime::currentDateTime();
00859 #endif
00860 }
00861
00862
00863 int operator==(KSSLCertificate &x, KSSLCertificate &y) {
00864 #ifndef KSSL_HAVE_SSL
00865 return 1;
00866 #else
00867 if (!KOSSL::self()->X509_cmp(x.getCert(), y.getCert())) return 1;
00868 return 0;
00869 #endif
00870 }
00871
00872
00873 KSSLCertificate *KSSLCertificate::replicate() {
00874
00875
00876 KSSLCertificate *newOne = new KSSLCertificate();
00877 #ifdef KSSL_HAVE_SSL
00878 newOne->setCert(d->kossl->X509_dup(getCert()));
00879 KSSLCertChain *c = d->_chain.replicate();
00880 newOne->setChain(c->rawChain());
00881 delete c;
00882 #endif
00883 return newOne;
00884 }
00885
00886
00887 QString KSSLCertificate::toString() {
00888 return KCodecs::base64Encode(toDer());
00889 }
00890
00891
00892 QString KSSLCertificate::verifyText(KSSLValidation x) {
00893 switch (x) {
00894 case KSSLCertificate::Ok:
00895 return i18n("The certificate is valid.");
00896 case KSSLCertificate::PathLengthExceeded:
00897 case KSSLCertificate::ErrorReadingRoot:
00898 case KSSLCertificate::NoCARoot:
00899 return i18n("Certificate signing authority root files could not be found so the certificate is not verified.");
00900 case KSSLCertificate::InvalidCA:
00901 return i18n("Certificate signing authority is unknown or invalid.");
00902 case KSSLCertificate::SelfSigned:
00903 return i18n("Certificate is self-signed and thus may not be trustworthy.");
00904 case KSSLCertificate::Expired:
00905 return i18n("Certificate has expired.");
00906 case KSSLCertificate::Revoked:
00907 return i18n("Certificate has been revoked.");
00908 case KSSLCertificate::NoSSL:
00909 return i18n("SSL support was not found.");
00910 case KSSLCertificate::Untrusted:
00911 return i18n("Signature is untrusted.");
00912 case KSSLCertificate::SignatureFailed:
00913 return i18n("Signature test failed.");
00914 case KSSLCertificate::Rejected:
00915 case KSSLCertificate::InvalidPurpose:
00916 return i18n("Rejected, possibly due to an invalid purpose.");
00917 case KSSLCertificate::PrivateKeyFailed:
00918 return i18n("Private key test failed.");
00919 case KSSLCertificate::InvalidHost:
00920 return i18n("The certificate has not been issued for this host.");
00921 case KSSLCertificate::Irrelevant:
00922 return i18n("This certificate is not relevant.");
00923 default:
00924 break;
00925 }
00926
00927 return i18n("The certificate is invalid.");
00928 }
00929
00930
00931 QByteArray KSSLCertificate::toDer() {
00932 QByteArray qba;
00933 #ifdef KSSL_HAVE_SSL
00934 unsigned int certlen = d->kossl->i2d_X509(getCert(), NULL);
00935
00936
00937 char *cert = new char[certlen];
00938 char *p = cert;
00939
00940 d->kossl->i2d_X509(getCert(), (unsigned char **)&p);
00941
00942
00943 qba.duplicate(cert, certlen);
00944 delete[] cert;
00945 #endif
00946 return qba;
00947 }
00948
00949
00950
00951 QByteArray KSSLCertificate::toPem() {
00952 QByteArray qba;
00953 QString thecert = toString();
00954 const char *header = "-----BEGIN CERTIFICATE-----\n";
00955 const char *footer = "-----END CERTIFICATE-----\n";
00956
00957
00958
00959 unsigned int xx = thecert.length() - 1;
00960 for (unsigned int i = 0; i < xx/64; i++) {
00961 thecert.insert(64*(i+1)+i, '\n');
00962 }
00963
00964 thecert.prepend(header);
00965
00966 if (thecert[thecert.length()-1] != '\n')
00967 thecert += "\n";
00968
00969 thecert.append(footer);
00970
00971 qba.duplicate(thecert.local8Bit(), thecert.length());
00972 return qba;
00973 }
00974
00975
00976 #define NETSCAPE_CERT_HDR "certificate"
00977
00978
00979 QByteArray KSSLCertificate::toNetscape() {
00980 QByteArray qba;
00981 #ifdef KSSL_HAVE_SSL
00982 ASN1_HEADER ah;
00983 ASN1_OCTET_STRING os;
00984 KTempFile ktf;
00985
00986 os.data = (unsigned char *)NETSCAPE_CERT_HDR;
00987 os.length = strlen(NETSCAPE_CERT_HDR);
00988 ah.header = &os;
00989 ah.data = (char *)getCert();
00990 ah.meth = d->kossl->X509_asn1_meth();
00991
00992 d->kossl->ASN1_i2d_fp(ktf.fstream(),(unsigned char *)&ah);
00993
00994 ktf.close();
00995
00996 QFile qf(ktf.name());
00997 qf.open(IO_ReadOnly);
00998 char *buf = new char[qf.size()];
00999 qf.readBlock(buf, qf.size());
01000 qba.duplicate(buf, qf.size());
01001 qf.close();
01002 delete[] buf;
01003
01004 ktf.unlink();
01005
01006 #endif
01007 return qba;
01008 }
01009
01010
01011
01012 QString KSSLCertificate::toText() {
01013 QString text;
01014 #ifdef KSSL_HAVE_SSL
01015 KTempFile ktf;
01016
01017 d->kossl->X509_print(ktf.fstream(), getCert());
01018 ktf.close();
01019
01020 QFile qf(ktf.name());
01021 qf.open(IO_ReadOnly);
01022 char *buf = new char[qf.size()+1];
01023 qf.readBlock(buf, qf.size());
01024 buf[qf.size()] = 0;
01025 text = buf;
01026 delete[] buf;
01027 qf.close();
01028 ktf.unlink();
01029 #endif
01030 return text;
01031 }
01032
01033
01034 bool KSSLCertificate::setCert(QString& cert) {
01035 #ifdef KSSL_HAVE_SSL
01036 QByteArray qba, qbb = cert.local8Bit().copy();
01037 KCodecs::base64Decode(qbb, qba);
01038 unsigned char *qbap = reinterpret_cast<unsigned char *>(qba.data());
01039 X509 *x5c = KOSSL::self()->d2i_X509(NULL, &qbap, qba.size());
01040 if (x5c) {
01041 setCert(x5c);
01042 return true;
01043 }
01044 #endif
01045 return false;
01046 }
01047
01048
01049 KSSLX509V3& KSSLCertificate::x509V3Extensions() {
01050 return d->_extensions;
01051 }
01052
01053
01054 bool KSSLCertificate::isSigner() {
01055 return d->_extensions.certTypeCA();
01056 }
01057
01058
01059 QDataStream& operator<<(QDataStream& s, const KSSLCertificate& r) {
01060 QStringList qsl;
01061 QPtrList<KSSLCertificate> cl = const_cast<KSSLCertificate&>(r).chain().getChain();
01062
01063 for (KSSLCertificate *c = cl.first(); c != 0; c = cl.next()) {
01064 qsl << c->toString();
01065 }
01066
01067 cl.setAutoDelete(true);
01068
01069 s << const_cast<KSSLCertificate&>(r).toString() << qsl;
01070
01071 return s;
01072 }
01073
01074
01075 QDataStream& operator>>(QDataStream& s, KSSLCertificate& r) {
01076 QStringList qsl;
01077 QString cert;
01078
01079 s >> cert >> qsl;
01080
01081 if (r.setCert(cert) && !qsl.isEmpty())
01082 r.chain().setCertChain(qsl);
01083
01084 return s;
01085 }
01086
01087
01088