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::getMD5Digest() const {
00283 QString rc = "";
00284
00285 #ifdef KSSL_HAVE_SSL
00286 unsigned int n;
00287 unsigned char md[EVP_MAX_MD_SIZE];
00288
00289 if (!d->kossl->X509_digest(d->m_cert, d->kossl->EVP_md5(), md, &n)) {
00290 return rc;
00291 }
00292
00293 for (unsigned int j = 0; j < n; j++) {
00294 rc.append(hv[(md[j]&0xf0)>>4]);
00295 rc.append(hv[md[j]&0x0f]);
00296 }
00297
00298 #endif
00299
00300 return rc;
00301 }
00302
00303
00304
00305 QString KSSLCertificate::getKeyType() const {
00306 QString rc = "";
00307
00308 #ifdef KSSL_HAVE_SSL
00309 EVP_PKEY *pkey = d->kossl->X509_get_pubkey(d->m_cert);
00310 if (pkey) {
00311 #ifndef NO_RSA
00312 if (pkey->type == EVP_PKEY_RSA)
00313 rc = "RSA";
00314 else
00315 #endif
00316 #ifndef NO_DSA
00317 if (pkey->type == EVP_PKEY_DSA)
00318 rc = "DSA";
00319 else
00320 #endif
00321 rc = "Unknown";
00322 d->kossl->EVP_PKEY_free(pkey);
00323 }
00324 #endif
00325
00326 return rc;
00327 }
00328
00329
00330
00331 QString KSSLCertificate::getPublicKeyText() const {
00332 QString rc = "";
00333 char *x = NULL;
00334
00335 #ifdef KSSL_HAVE_SSL
00336 EVP_PKEY *pkey = d->kossl->X509_get_pubkey(d->m_cert);
00337 if (pkey) {
00338 rc = i18n("Unknown", "Unknown key algorithm");
00339 #ifndef NO_RSA
00340 if (pkey->type == EVP_PKEY_RSA) {
00341 rc = i18n("Key type: RSA (%1 bit)") + "\n";
00342
00343 x = d->kossl->BN_bn2hex(pkey->pkey.rsa->n);
00344 rc += i18n("Modulus: ");
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.rsa->e);
00357 rc += i18n("Exponent: 0x") + x + "\n";
00358 d->kossl->OPENSSL_free(x);
00359 }
00360 #endif
00361 #ifndef NO_DSA
00362 if (pkey->type == EVP_PKEY_DSA) {
00363 rc = i18n("Key type: DSA (%1 bit)") + "\n";
00364
00365 x = d->kossl->BN_bn2hex(pkey->pkey.dsa->p);
00366 rc += i18n("Prime: ");
00367
00368 rc = rc.arg(strlen(x)*4) ;
00369 for (unsigned int i = 0; i < strlen(x); i++) {
00370 if (i%40 != 0 && i%2 == 0)
00371 rc += ":";
00372 else if (i%40 == 0)
00373 rc += "\n";
00374 rc += x[i];
00375 }
00376 rc += "\n";
00377 d->kossl->OPENSSL_free(x);
00378
00379 x = d->kossl->BN_bn2hex(pkey->pkey.dsa->q);
00380 rc += i18n("160 bit prime factor: ");
00381 for (unsigned int i = 0; i < strlen(x); i++) {
00382 if (i%40 != 0 && i%2 == 0)
00383 rc += ":";
00384 else if (i%40 == 0)
00385 rc += "\n";
00386 rc += x[i];
00387 }
00388 rc += "\n";
00389 d->kossl->OPENSSL_free(x);
00390
00391 x = d->kossl->BN_bn2hex(pkey->pkey.dsa->g);
00392 rc += QString("g: ");
00393 for (unsigned int i = 0; i < strlen(x); i++) {
00394 if (i%40 != 0 && i%2 == 0)
00395 rc += ":";
00396 else if (i%40 == 0)
00397 rc += "\n";
00398 rc += x[i];
00399 }
00400 rc += "\n";
00401 d->kossl->OPENSSL_free(x);
00402
00403 x = d->kossl->BN_bn2hex(pkey->pkey.dsa->pub_key);
00404 rc += i18n("Public key: ");
00405 for (unsigned int i = 0; i < strlen(x); i++) {
00406 if (i%40 != 0 && i%2 == 0)
00407 rc += ":";
00408 else if (i%40 == 0)
00409 rc += "\n";
00410 rc += x[i];
00411 }
00412 rc += "\n";
00413 d->kossl->OPENSSL_free(x);
00414 }
00415 #endif
00416 d->kossl->EVP_PKEY_free(pkey);
00417 }
00418 #endif
00419
00420 return rc;
00421 }
00422
00423
00424
00425 QString KSSLCertificate::getIssuer() const {
00426 QString rc = "";
00427
00428 #ifdef KSSL_HAVE_SSL
00429 char *t = d->kossl->X509_NAME_oneline(d->kossl->X509_get_issuer_name(d->m_cert), 0, 0);
00430
00431 if (!t)
00432 return rc;
00433
00434 rc = t;
00435 d->kossl->OPENSSL_free(t);
00436 #endif
00437
00438 return rc;
00439 }
00440
00441 void KSSLCertificate::setChain(void *c) {
00442 #ifdef KSSL_HAVE_SSL
00443 d->_chain.setChain(c);
00444 #endif
00445 d->m_stateCached = false;
00446 d->m_stateCache = KSSLCertificate::Unknown;
00447 }
00448
00449 void KSSLCertificate::setCert(X509 *c) {
00450 #ifdef KSSL_HAVE_SSL
00451 d->m_cert = c;
00452 if (c) {
00453 d->_extensions.flags = 0;
00454 d->kossl->X509_check_purpose(c, -1, 0);
00455
00456 #if 0
00457 kdDebug(7029) << "---------------- Certificate ------------------"
00458 << endl;
00459 kdDebug(7029) << getSubject() << endl;
00460 #endif
00461
00462 for (int j = 0; j < d->kossl->X509_PURPOSE_get_count(); j++) {
00463 X509_PURPOSE *ptmp = d->kossl->X509_PURPOSE_get0(j);
00464 int id = d->kossl->X509_PURPOSE_get_id(ptmp);
00465 for (int ca = 0; ca < 2; ca++) {
00466 int idret = d->kossl->X509_check_purpose(c, id, ca);
00467 if (idret == 1 || idret == 2) {
00468
00469 if (!ca)
00470 d->_extensions.flags |= (1L <<(id-1));
00471 else d->_extensions.flags |= (1L <<(16+id-1));
00472 } else {
00473 if (!ca)
00474 d->_extensions.flags &= ~(1L <<(id-1));
00475 else d->_extensions.flags &= ~(1L <<(16+id-1));
00476 }
00477 }
00478 }
00479
00480 #if 0
00481 kdDebug(7029) << "flags: " << QString::number(c->ex_flags, 2)
00482 << "\nkeyusage: " << QString::number(c->ex_kusage, 2)
00483 << "\nxkeyusage: " << QString::number(c->ex_xkusage, 2)
00484 << "\nnscert: " << QString::number(c->ex_nscert, 2)
00485 << endl;
00486 if (c->ex_flags & EXFLAG_KUSAGE)
00487 kdDebug(7029) << " --- Key Usage extensions found" << endl;
00488 else kdDebug(7029) << " --- Key Usage extensions NOT found" << endl;
00489
00490 if (c->ex_flags & EXFLAG_XKUSAGE)
00491 kdDebug(7029) << " --- Extended key usage extensions found" << endl;
00492 else kdDebug(7029) << " --- Extended key usage extensions NOT found" << endl;
00493
00494 if (c->ex_flags & EXFLAG_NSCERT)
00495 kdDebug(7029) << " --- NS extensions found" << endl;
00496 else kdDebug(7029) << " --- NS extensions NOT found" << endl;
00497
00498 if (d->_extensions.certTypeSSLCA())
00499 kdDebug(7029) << "NOTE: this is an SSL CA file." << endl;
00500 else kdDebug(7029) << "NOTE: this is NOT an SSL CA file." << endl;
00501
00502 if (d->_extensions.certTypeEmailCA())
00503 kdDebug(7029) << "NOTE: this is an EMAIL CA file." << endl;
00504 else kdDebug(7029) << "NOTE: this is NOT an EMAIL CA file." << endl;
00505
00506 if (d->_extensions.certTypeCodeCA())
00507 kdDebug(7029) << "NOTE: this is a CODE CA file." << endl;
00508 else kdDebug(7029) << "NOTE: this is NOT a CODE CA file." << endl;
00509
00510 if (d->_extensions.certTypeSSLClient())
00511 kdDebug(7029) << "NOTE: this is an SSL client." << endl;
00512 else kdDebug(7029) << "NOTE: this is NOT an SSL client." << endl;
00513
00514 if (d->_extensions.certTypeSSLServer())
00515 kdDebug(7029) << "NOTE: this is an SSL server." << endl;
00516 else kdDebug(7029) << "NOTE: this is NOT an SSL server." << endl;
00517
00518 if (d->_extensions.certTypeNSSSLServer())
00519 kdDebug(7029) << "NOTE: this is a NETSCAPE SSL server." << endl;
00520 else kdDebug(7029) << "NOTE: this is NOT a NETSCAPE SSL server." << endl;
00521
00522 if (d->_extensions.certTypeSMIME())
00523 kdDebug(7029) << "NOTE: this is an SMIME certificate." << endl;
00524 else kdDebug(7029) << "NOTE: this is NOT an SMIME certificate." << endl;
00525
00526 if (d->_extensions.certTypeSMIMEEncrypt())
00527 kdDebug(7029) << "NOTE: this is an SMIME encrypt cert." << endl;
00528 else kdDebug(7029) << "NOTE: this is NOT an SMIME encrypt cert." << endl;
00529
00530 if (d->_extensions.certTypeSMIMESign())
00531 kdDebug(7029) << "NOTE: this is an SMIME sign cert." << endl;
00532 else kdDebug(7029) << "NOTE: this is NOT an SMIME sign cert." << endl;
00533
00534 if (d->_extensions.certTypeCRLSign())
00535 kdDebug(7029) << "NOTE: this is a CRL signer." << endl;
00536 else kdDebug(7029) << "NOTE: this is NOT a CRL signer." << endl;
00537
00538 kdDebug(7029) << "-----------------------------------------------"
00539 << endl;
00540 #endif
00541 }
00542 #endif
00543 d->m_stateCached = false;
00544 d->m_stateCache = KSSLCertificate::Unknown;
00545 }
00546
00547 X509 *KSSLCertificate::getCert() {
00548 #ifdef KSSL_HAVE_SSL
00549 return d->m_cert;
00550 #endif
00551 return 0;
00552 }
00553
00554
00555
00556
00557 #include "ksslcallback.c"
00558
00559
00560 bool KSSLCertificate::isValid(KSSLCertificate::KSSLPurpose p) {
00561 return (validate(p) == KSSLCertificate::Ok);
00562 }
00563
00564
00565 bool KSSLCertificate::isValid() {
00566 return isValid(KSSLCertificate::SSLServer);
00567 }
00568
00569
00570 int KSSLCertificate::purposeToOpenSSL(KSSLCertificate::KSSLPurpose p) const {
00571 int rc = 0;
00572 #ifdef KSSL_HAVE_SSL
00573 if (p == KSSLCertificate::SSLServer) {
00574 rc = X509_PURPOSE_SSL_SERVER;
00575 } else if (p == KSSLCertificate::SSLClient) {
00576 rc = X509_PURPOSE_SSL_CLIENT;
00577 } else if (p == KSSLCertificate::SMIMEEncrypt) {
00578 rc = X509_PURPOSE_SMIME_ENCRYPT;
00579 } else if (p == KSSLCertificate::SMIMESign) {
00580 rc = X509_PURPOSE_SMIME_SIGN;
00581 } else if (p == KSSLCertificate::Any) {
00582 rc = X509_PURPOSE_ANY;
00583 }
00584 #endif
00585 return rc;
00586 }
00587
00588
00589
00590 KSSLCertificate::KSSLValidation KSSLCertificate::validate() {
00591 return validate(KSSLCertificate::SSLServer);
00592 }
00593
00594 KSSLCertificate::KSSLValidation KSSLCertificate::validate(KSSLCertificate::KSSLPurpose purpose)
00595 {
00596 KSSLValidationList result = validateVerbose(purpose);
00597 if (result.isEmpty())
00598 return KSSLCertificate::Ok;
00599 else
00600 return result.first();
00601 }
00602
00603
00604
00605
00606
00607
00608 KSSLCertificate::KSSLValidationList KSSLCertificate::validateVerbose(KSSLCertificate::KSSLPurpose purpose)
00609 {
00610 return validateVerbose(purpose, 0);
00611 }
00612
00613 KSSLCertificate::KSSLValidationList KSSLCertificate::validateVerbose(KSSLCertificate::KSSLPurpose purpose, KSSLCertificate *ca)
00614 {
00615 KSSLValidationList errors;
00616 if (ca || (d->_lastPurpose != purpose)) {
00617 d->m_stateCached = false;
00618 }
00619
00620 if (!d->m_stateCached)
00621 d->_lastPurpose = purpose;
00622
00623 #ifdef KSSL_HAVE_SSL
00624 X509_STORE *certStore;
00625 X509_LOOKUP *certLookup;
00626 X509_STORE_CTX *certStoreCTX;
00627 int rc = 0;
00628
00629 if (!d->m_cert)
00630 {
00631 errors << KSSLCertificate::Unknown;
00632 return errors;
00633 }
00634
00635 if (d->m_stateCached) {
00636 errors << d->m_stateCache;
00637 return errors;
00638 }
00639
00640 QStringList qsl = KGlobal::dirs()->resourceDirs("kssl");
00641
00642 if (qsl.isEmpty()) {
00643 errors << KSSLCertificate::NoCARoot;
00644 return errors;
00645 }
00646
00647 KSSLCertificate::KSSLValidation ksslv = Unknown;
00648
00649 for (QStringList::Iterator j = qsl.begin(); j != qsl.end(); ++j) {
00650 struct stat sb;
00651 QString _j = (*j) + "ca-bundle.crt";
00652 if (-1 == stat(_j.ascii(), &sb)) {
00653 continue;
00654 }
00655
00656 certStore = d->kossl->X509_STORE_new();
00657 if (!certStore) {
00658 errors << KSSLCertificate::Unknown;
00659 return errors;
00660 }
00661
00662 X509_STORE_set_verify_cb_func(certStore, X509Callback);
00663
00664 certLookup = d->kossl->X509_STORE_add_lookup(certStore, d->kossl->X509_LOOKUP_file());
00665 if (!certLookup) {
00666 ksslv = KSSLCertificate::Unknown;
00667 d->kossl->X509_STORE_free(certStore);
00668 continue;
00669 }
00670
00671 if (!d->kossl->X509_LOOKUP_load_file(certLookup, _j.ascii(), X509_FILETYPE_PEM)) {
00672
00673 kdDebug(7029) << "KSSL couldn't read CA root: "
00674 << _j << endl;
00675 ksslv = KSSLCertificate::ErrorReadingRoot;
00676 d->kossl->X509_STORE_free(certStore);
00677 continue;
00678 }
00679
00680
00681 certStoreCTX = d->kossl->X509_STORE_CTX_new();
00682
00683
00684
00685 if (!certStoreCTX) {
00686 kdDebug(7029) << "KSSL couldn't create an X509 store context." << endl;
00687 d->kossl->X509_STORE_free(certStore);
00688 continue;
00689 }
00690
00691 d->kossl->X509_STORE_CTX_init(certStoreCTX, certStore, d->m_cert, NULL);
00692 if (d->_chain.isValid()) {
00693 d->kossl->X509_STORE_CTX_set_chain(certStoreCTX, (STACK_OF(X509)*)d->_chain.rawChain());
00694 }
00695
00696
00697
00698
00699 d->kossl->X509_STORE_CTX_set_purpose(certStoreCTX, purposeToOpenSSL(purpose));
00700
00701 KSSL_X509CallBack_ca = ca ? ca->d->m_cert : 0;
00702 KSSL_X509CallBack_ca_found = false;
00703
00704 certStoreCTX->error = X509_V_OK;
00705 rc = d->kossl->X509_verify_cert(certStoreCTX);
00706 int errcode = certStoreCTX->error;
00707 if (ca && !KSSL_X509CallBack_ca_found) {
00708 ksslv = KSSLCertificate::Irrelevant;
00709 } else {
00710 ksslv = processError(errcode);
00711 }
00712
00713 if ( (ksslv != KSSLCertificate::Ok) &&
00714 (ksslv != KSSLCertificate::Irrelevant) &&
00715 purpose == KSSLCertificate::SSLServer) {
00716 d->kossl->X509_STORE_CTX_set_purpose(certStoreCTX,
00717 X509_PURPOSE_NS_SSL_SERVER);
00718
00719 certStoreCTX->error = X509_V_OK;
00720 rc = d->kossl->X509_verify_cert(certStoreCTX);
00721 errcode = certStoreCTX->error;
00722 ksslv = processError(errcode);
00723 }
00724 d->kossl->X509_STORE_CTX_free(certStoreCTX);
00725 d->kossl->X509_STORE_free(certStore);
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736 if (ksslv != NoCARoot && ksslv != InvalidCA) {
00737 d->m_stateCached = true;
00738 d->m_stateCache = ksslv;
00739 }
00740 break;
00741 }
00742
00743 if (ksslv != KSSLCertificate::Ok)
00744 errors << ksslv;
00745 #else
00746 errors << KSSLCertificate::NoSSL;
00747 #endif
00748 return errors;
00749 }
00750
00751
00752
00753 KSSLCertificate::KSSLValidation KSSLCertificate::revalidate() {
00754 return revalidate(KSSLCertificate::SSLServer);
00755 }
00756
00757
00758 KSSLCertificate::KSSLValidation KSSLCertificate::revalidate(KSSLCertificate::KSSLPurpose p) {
00759 d->m_stateCached = false;
00760 return validate(p);
00761 }
00762
00763
00764 KSSLCertificate::KSSLValidation KSSLCertificate::processError(int ec) {
00765 KSSLCertificate::KSSLValidation rc;
00766
00767 rc = KSSLCertificate::Unknown;
00768 #ifdef KSSL_HAVE_SSL
00769 switch (ec) {
00770 case X509_V_OK:
00771 rc = KSSLCertificate::Ok;
00772 break;
00773
00774
00775 case X509_V_ERR_CERT_REJECTED:
00776 rc = KSSLCertificate::Rejected;
00777 break;
00778
00779
00780 case X509_V_ERR_CERT_UNTRUSTED:
00781 rc = KSSLCertificate::Untrusted;
00782 break;
00783
00784
00785 case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
00786 case X509_V_ERR_CERT_SIGNATURE_FAILURE:
00787 case X509_V_ERR_CRL_SIGNATURE_FAILURE:
00788 case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE:
00789 case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE:
00790 rc = KSSLCertificate::SignatureFailed;
00791 break;
00792
00793 case X509_V_ERR_INVALID_CA:
00794 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
00795 case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY:
00796 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
00797 rc = KSSLCertificate::InvalidCA;
00798 break;
00799
00800
00801 case X509_V_ERR_INVALID_PURPOSE:
00802 rc = KSSLCertificate::InvalidPurpose;
00803 break;
00804
00805
00806 case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
00807 rc = KSSLCertificate::SelfSigned;
00808 break;
00809
00810 case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
00811 rc = KSSLCertificate::SelfSignedChain;
00812 break;
00813
00814 case X509_V_ERR_CERT_REVOKED:
00815 rc = KSSLCertificate::Revoked;
00816 break;
00817
00818 case X509_V_ERR_PATH_LENGTH_EXCEEDED:
00819 rc = KSSLCertificate::PathLengthExceeded;
00820 break;
00821
00822 case X509_V_ERR_CERT_NOT_YET_VALID:
00823 case X509_V_ERR_CERT_HAS_EXPIRED:
00824 case X509_V_ERR_CRL_NOT_YET_VALID:
00825 case X509_V_ERR_CRL_HAS_EXPIRED:
00826 case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
00827 case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
00828 case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD:
00829 case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD:
00830 rc = KSSLCertificate::Expired;
00831 kdDebug(7029) << "KSSL apparently this is expired. Not after: "
00832 << getNotAfter() << endl;
00833 break;
00834
00835
00836 case X509_V_ERR_APPLICATION_VERIFICATION:
00837 case X509_V_ERR_OUT_OF_MEM:
00838 case X509_V_ERR_UNABLE_TO_GET_CRL:
00839 case X509_V_ERR_CERT_CHAIN_TOO_LONG:
00840 default:
00841 rc = KSSLCertificate::Unknown;
00842 break;
00843 }
00844
00845 d->m_stateCache = rc;
00846 d->m_stateCached = true;
00847 #endif
00848 return rc;
00849 }
00850
00851
00852 QString KSSLCertificate::getNotBefore() const {
00853 #ifdef KSSL_HAVE_SSL
00854 return ASN1_UTCTIME_QString(X509_get_notBefore(d->m_cert));
00855 #else
00856 return QString::null;
00857 #endif
00858 }
00859
00860
00861 QString KSSLCertificate::getNotAfter() const {
00862 #ifdef KSSL_HAVE_SSL
00863 return ASN1_UTCTIME_QString(X509_get_notAfter(d->m_cert));
00864 #else
00865 return QString::null;
00866 #endif
00867 }
00868
00869
00870 QDateTime KSSLCertificate::getQDTNotBefore() const {
00871 #ifdef KSSL_HAVE_SSL
00872 return ASN1_UTCTIME_QDateTime(X509_get_notBefore(d->m_cert), NULL);
00873 #else
00874 return QDateTime::currentDateTime();
00875 #endif
00876 }
00877
00878
00879 QDateTime KSSLCertificate::getQDTNotAfter() const {
00880 #ifdef KSSL_HAVE_SSL
00881 return ASN1_UTCTIME_QDateTime(X509_get_notAfter(d->m_cert), NULL);
00882 #else
00883 return QDateTime::currentDateTime();
00884 #endif
00885 }
00886
00887
00888 int operator==(KSSLCertificate &x, KSSLCertificate &y) {
00889 #ifndef KSSL_HAVE_SSL
00890 return 1;
00891 #else
00892 if (!KOSSL::self()->X509_cmp(x.getCert(), y.getCert())) return 1;
00893 return 0;
00894 #endif
00895 }
00896
00897
00898 KSSLCertificate *KSSLCertificate::replicate() {
00899
00900
00901 KSSLCertificate *newOne = new KSSLCertificate();
00902 #ifdef KSSL_HAVE_SSL
00903 newOne->setCert(d->kossl->X509_dup(getCert()));
00904 KSSLCertChain *c = d->_chain.replicate();
00905 newOne->setChain(c->rawChain());
00906 delete c;
00907 #endif
00908 return newOne;
00909 }
00910
00911
00912 QString KSSLCertificate::toString() {
00913 return KCodecs::base64Encode(toDer());
00914 }
00915
00916
00917 QString KSSLCertificate::verifyText(KSSLValidation x) {
00918 switch (x) {
00919 case KSSLCertificate::Ok:
00920 return i18n("The certificate is valid.");
00921 case KSSLCertificate::PathLengthExceeded:
00922 case KSSLCertificate::ErrorReadingRoot:
00923 case KSSLCertificate::NoCARoot:
00924 return i18n("Certificate signing authority root files could not be found so the certificate is not verified.");
00925 case KSSLCertificate::SelfSignedChain:
00926 case KSSLCertificate::InvalidCA:
00927 return i18n("Certificate signing authority is unknown or invalid.");
00928 case KSSLCertificate::SelfSigned:
00929 return i18n("Certificate is self-signed and thus may not be trustworthy.");
00930 case KSSLCertificate::Expired:
00931 return i18n("Certificate has expired.");
00932 case KSSLCertificate::Revoked:
00933 return i18n("Certificate has been revoked.");
00934 case KSSLCertificate::NoSSL:
00935 return i18n("SSL support was not found.");
00936 case KSSLCertificate::Untrusted:
00937 return i18n("Signature is untrusted.");
00938 case KSSLCertificate::SignatureFailed:
00939 return i18n("Signature test failed.");
00940 case KSSLCertificate::Rejected:
00941 case KSSLCertificate::InvalidPurpose:
00942 return i18n("Rejected, possibly due to an invalid purpose.");
00943 case KSSLCertificate::PrivateKeyFailed:
00944 return i18n("Private key test failed.");
00945 case KSSLCertificate::InvalidHost:
00946 return i18n("The certificate has not been issued for this host.");
00947 case KSSLCertificate::Irrelevant:
00948 return i18n("This certificate is not relevant.");
00949 default:
00950 break;
00951 }
00952
00953 return i18n("The certificate is invalid.");
00954 }
00955
00956
00957 QByteArray KSSLCertificate::toDer() {
00958 QByteArray qba;
00959 #ifdef KSSL_HAVE_SSL
00960 unsigned int certlen = d->kossl->i2d_X509(getCert(), NULL);
00961 unsigned char *cert = new unsigned char[certlen];
00962 unsigned char *p = cert;
00963
00964 d->kossl->i2d_X509(getCert(), &p);
00965
00966
00967 qba.duplicate((const char*)cert, certlen);
00968 delete[] cert;
00969 #endif
00970 return qba;
00971 }
00972
00973
00974
00975 QByteArray KSSLCertificate::toPem() {
00976 QByteArray qba;
00977 QString thecert = toString();
00978 const char *header = "-----BEGIN CERTIFICATE-----\n";
00979 const char *footer = "-----END CERTIFICATE-----\n";
00980
00981
00982
00983 unsigned int xx = thecert.length() - 1;
00984 for (unsigned int i = 0; i < xx/64; i++) {
00985 thecert.insert(64*(i+1)+i, '\n');
00986 }
00987
00988 thecert.prepend(header);
00989
00990 if (thecert[thecert.length()-1] != '\n')
00991 thecert += "\n";
00992
00993 thecert.append(footer);
00994
00995 qba.duplicate(thecert.local8Bit(), thecert.length());
00996 return qba;
00997 }
00998
00999
01000 #define NETSCAPE_CERT_HDR "certificate"
01001
01002
01003 QByteArray KSSLCertificate::toNetscape() {
01004 QByteArray qba;
01005 #ifdef KSSL_HAVE_SSL
01006 ASN1_HEADER ah;
01007 ASN1_OCTET_STRING os;
01008 KTempFile ktf;
01009
01010 os.data = (unsigned char *)NETSCAPE_CERT_HDR;
01011 os.length = strlen(NETSCAPE_CERT_HDR);
01012 ah.header = &os;
01013 ah.data = (char *)getCert();
01014 ah.meth = d->kossl->X509_asn1_meth();
01015
01016 d->kossl->ASN1_i2d_fp(ktf.fstream(),(unsigned char *)&ah);
01017
01018 ktf.close();
01019
01020 QFile qf(ktf.name());
01021 qf.open(IO_ReadOnly);
01022 char *buf = new char[qf.size()];
01023 qf.readBlock(buf, qf.size());
01024 qba.duplicate(buf, qf.size());
01025 qf.close();
01026 delete[] buf;
01027
01028 ktf.unlink();
01029
01030 #endif
01031 return qba;
01032 }
01033
01034
01035
01036 QString KSSLCertificate::toText() {
01037 QString text;
01038 #ifdef KSSL_HAVE_SSL
01039 KTempFile ktf;
01040
01041 d->kossl->X509_print(ktf.fstream(), getCert());
01042 ktf.close();
01043
01044 QFile qf(ktf.name());
01045 qf.open(IO_ReadOnly);
01046 char *buf = new char[qf.size()+1];
01047 qf.readBlock(buf, qf.size());
01048 buf[qf.size()] = 0;
01049 text = buf;
01050 delete[] buf;
01051 qf.close();
01052 ktf.unlink();
01053 #endif
01054 return text;
01055 }
01056
01057
01058 bool KSSLCertificate::setCert(QString& cert) {
01059 #ifdef KSSL_HAVE_SSL
01060 QByteArray qba, qbb = cert.local8Bit().copy();
01061 KCodecs::base64Decode(qbb, qba);
01062 unsigned char *qbap = reinterpret_cast<unsigned char *>(qba.data());
01063 X509 *x5c = KOSSL::self()->d2i_X509(NULL, &qbap, qba.size());
01064 if (x5c) {
01065 setCert(x5c);
01066 return true;
01067 }
01068 #endif
01069 return false;
01070 }
01071
01072
01073 KSSLX509V3& KSSLCertificate::x509V3Extensions() {
01074 return d->_extensions;
01075 }
01076
01077
01078 bool KSSLCertificate::isSigner() {
01079 return d->_extensions.certTypeCA();
01080 }
01081
01082
01083 QStringList KSSLCertificate::subjAltNames() const {
01084 QStringList rc;
01085 #ifdef KSSL_HAVE_SSL
01086 STACK_OF(GENERAL_NAME) *names;
01087 names = (STACK_OF(GENERAL_NAME)*)d->kossl->X509_get_ext_d2i(d->m_cert, NID_subject_alt_name, 0, 0);
01088
01089 if (!names) {
01090 return rc;
01091 }
01092
01093 int cnt = d->kossl->sk_GENERAL_NAME_num(names);
01094
01095 for (int i = 0; i < cnt; i++) {
01096 const GENERAL_NAME *val = (const GENERAL_NAME *)d->kossl->sk_value(names, i);
01097 if (val->type != GEN_DNS) {
01098 continue;
01099 }
01100
01101 QString s = (const char *)d->kossl->ASN1_STRING_data(val->d.ia5);
01102 if (!s.isEmpty()) {
01103 rc += s;
01104 }
01105 }
01106 d->kossl->sk_free(names);
01107 #endif
01108 return rc;
01109 }
01110
01111
01112 QDataStream& operator<<(QDataStream& s, const KSSLCertificate& r) {
01113 QStringList qsl;
01114 QPtrList<KSSLCertificate> cl = const_cast<KSSLCertificate&>(r).chain().getChain();
01115
01116 for (KSSLCertificate *c = cl.first(); c != 0; c = cl.next()) {
01117 qsl << c->toString();
01118 }
01119
01120 cl.setAutoDelete(true);
01121
01122 s << const_cast<KSSLCertificate&>(r).toString() << qsl;
01123
01124 return s;
01125 }
01126
01127
01128 QDataStream& operator>>(QDataStream& s, KSSLCertificate& r) {
01129 QStringList qsl;
01130 QString cert;
01131
01132 s >> cert >> qsl;
01133
01134 if (r.setCert(cert) && !qsl.isEmpty())
01135 r.chain().setCertChain(qsl);
01136
01137 return s;
01138 }
01139
01140
01141