00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "ksslcertificate.h"
00023
00024 #include <config.h>
00025 #include <ksslconfig.h>
00026
00027
00028
00029 #include <unistd.h>
00030 #include <QtCore/QString>
00031 #include <QtCore/QStringList>
00032 #include <QtCore/QFile>
00033
00034 #include "kssldefs.h"
00035 #include "ksslcertchain.h"
00036 #include "ksslutils.h"
00037
00038 #include <kstandarddirs.h>
00039 #include <kcodecs.h>
00040 #include <kde_file.h>
00041 #include <klocale.h>
00042 #include <QtCore/QDate>
00043 #include <ktemporaryfile.h>
00044
00045 #include <sys/types.h>
00046
00047 #ifdef HAVE_SYS_STAT_H
00048 #include <sys/stat.h>
00049 #endif
00050
00051
00052
00053 #ifdef KSSL_HAVE_SSL
00054 #define crypt _openssl_crypt
00055 #include <openssl/ssl.h>
00056 #include <openssl/x509.h>
00057 #include <openssl/x509v3.h>
00058 #include <openssl/x509_vfy.h>
00059 #include <openssl/pem.h>
00060 #undef crypt
00061 #endif
00062
00063 #include <kopenssl.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", "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", "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 }
00123 #endif
00124 delete d;
00125 }
00126
00127
00128 KSSLCertChain& KSSLCertificate::chain() {
00129 return d->_chain;
00130 }
00131
00132
00133 KSSLCertificate *KSSLCertificate::fromX509(X509 *x5) {
00134 KSSLCertificate *n = NULL;
00135 #ifdef KSSL_HAVE_SSL
00136 if (x5) {
00137 n = new KSSLCertificate;
00138 n->setCert(KOSSL::self()->X509_dup(x5));
00139 }
00140 #endif
00141 return n;
00142 }
00143
00144
00145 KSSLCertificate *KSSLCertificate::fromString(const QByteArray &cert) {
00146 KSSLCertificate *n = NULL;
00147 #ifdef KSSL_HAVE_SSL
00148 if (cert.isEmpty()) {
00149 return NULL;
00150 }
00151
00152 QByteArray qba = QByteArray::fromBase64(cert);
00153 unsigned char *qbap = reinterpret_cast<unsigned char *>(qba.data());
00154 X509 *x5c = KOSSL::self()->d2i_X509(NULL, &qbap, qba.size());
00155 if (!x5c) {
00156 return NULL;
00157 }
00158
00159 n = new KSSLCertificate;
00160 n->setCert(x5c);
00161 #endif
00162 return n;
00163 }
00164
00165
00166
00167 QString KSSLCertificate::getSubject() const {
00168 QString rc = "";
00169
00170 #ifdef KSSL_HAVE_SSL
00171 char *t = d->kossl->X509_NAME_oneline(d->kossl->X509_get_subject_name(d->m_cert), 0, 0);
00172 if (!t) {
00173 return rc;
00174 }
00175 rc = t;
00176 d->kossl->OPENSSL_free(t);
00177 #endif
00178 return rc;
00179 }
00180
00181
00182 QString KSSLCertificate::getSerialNumber() const {
00183 QString rc = "";
00184
00185 #ifdef KSSL_HAVE_SSL
00186 ASN1_INTEGER *aint = d->kossl->X509_get_serialNumber(d->m_cert);
00187 if (aint) {
00188 rc = ASN1_INTEGER_QString(aint);
00189
00190 }
00191 #endif
00192 return rc;
00193 }
00194
00195
00196 QString KSSLCertificate::getSignatureText() const {
00197 QString rc = "";
00198
00199 #ifdef KSSL_HAVE_SSL
00200 char *s;
00201 int n, i;
00202
00203 i = d->kossl->OBJ_obj2nid(d->m_cert->sig_alg->algorithm);
00204 rc = i18n("Signature Algorithm: ");
00205 rc += (i == NID_undef)?i18n("Unknown"):QString(d->kossl->OBJ_nid2ln(i));
00206
00207 rc += '\n';
00208 rc += i18n("Signature Contents:");
00209 n = d->m_cert->signature->length;
00210 s = (char *)d->m_cert->signature->data;
00211 for (i = 0; i < n; i++) {
00212 if (i%20 != 0) {
00213 rc += ':';
00214 }
00215 else {
00216 rc += '\n';
00217 }
00218 rc.append(QChar(hv[(s[i]&0xf0)>>4]));
00219 rc.append(QChar(hv[s[i]&0x0f]));
00220 }
00221
00222 #endif
00223
00224 return rc;
00225 }
00226
00227
00228 void KSSLCertificate::getEmails(QStringList &to) const {
00229 to.clear();
00230 #ifdef KSSL_HAVE_SSL
00231 if (!d->m_cert) {
00232 return;
00233 }
00234
00235 STACK *s = d->kossl->X509_get1_email(d->m_cert);
00236 if (s) {
00237 for(int n=0; n < s->num; n++) {
00238 to.append(d->kossl->sk_value(s,n));
00239 }
00240 d->kossl->X509_email_free(s);
00241 }
00242 #endif
00243 }
00244
00245
00246 QString KSSLCertificate::getKDEKey() const {
00247 return getSubject() + " (" + getMD5DigestText() + ')';
00248 }
00249
00250
00251 QString KSSLCertificate::getMD5DigestFromKDEKey(const QString &k) {
00252 QString rc;
00253 int pos = k.lastIndexOf('(');
00254 if (pos != -1) {
00255 unsigned int len = k.length();
00256 if (k.at(len-1) == ')') {
00257 rc = k.mid(pos+1, len-pos-2);
00258 }
00259 }
00260 return rc;
00261 }
00262
00263
00264 QString KSSLCertificate::getMD5DigestText() const {
00265 QString rc = "";
00266
00267 #ifdef KSSL_HAVE_SSL
00268 unsigned int n;
00269 unsigned char md[EVP_MAX_MD_SIZE];
00270
00271 if (!d->kossl->X509_digest(d->m_cert, d->kossl->EVP_md5(), md, &n)) {
00272 return rc;
00273 }
00274
00275 for (unsigned int j = 0; j < n; j++) {
00276 if (j > 0) {
00277 rc += ':';
00278 }
00279 rc.append(QChar(hv[(md[j]&0xf0)>>4]));
00280 rc.append(QChar(hv[md[j]&0x0f]));
00281 }
00282
00283 #endif
00284
00285 return rc;
00286 }
00287
00288
00289
00290 QString KSSLCertificate::getMD5Digest() const {
00291 QString rc = "";
00292
00293 #ifdef KSSL_HAVE_SSL
00294 unsigned int n;
00295 unsigned char md[EVP_MAX_MD_SIZE];
00296
00297 if (!d->kossl->X509_digest(d->m_cert, d->kossl->EVP_md5(), md, &n)) {
00298 return rc;
00299 }
00300
00301 for (unsigned int j = 0; j < n; j++) {
00302 rc.append(QLatin1Char(hv[(md[j]&0xf0)>>4]));
00303 rc.append(QLatin1Char(hv[md[j]&0x0f]));
00304 }
00305
00306 #endif
00307
00308 return rc;
00309 }
00310
00311
00312
00313 QString KSSLCertificate::getKeyType() const {
00314 QString rc = "";
00315
00316 #ifdef KSSL_HAVE_SSL
00317 EVP_PKEY *pkey = d->kossl->X509_get_pubkey(d->m_cert);
00318 if (pkey) {
00319 #ifndef NO_RSA
00320 if (pkey->type == EVP_PKEY_RSA) {
00321 rc = "RSA";
00322 }
00323 else
00324 #endif
00325 #ifndef NO_DSA
00326 if (pkey->type == EVP_PKEY_DSA) {
00327 rc = "DSA";
00328 }
00329 else
00330 #endif
00331 rc = "Unknown";
00332 d->kossl->EVP_PKEY_free(pkey);
00333 }
00334 #endif
00335
00336 return rc;
00337 }
00338
00339
00340
00341 QString KSSLCertificate::getPublicKeyText() const {
00342 QString rc = "";
00343 char *x = NULL;
00344
00345 #ifdef KSSL_HAVE_SSL
00346 EVP_PKEY *pkey = d->kossl->X509_get_pubkey(d->m_cert);
00347 if (pkey) {
00348 rc = i18nc("Unknown", "Unknown key algorithm");
00349 #ifndef NO_RSA
00350 if (pkey->type == EVP_PKEY_RSA) {
00351 x = d->kossl->BN_bn2hex(pkey->pkey.rsa->n);
00352 rc = i18n("Key type: RSA (%1 bit)", strlen(x)*4) + '\n';
00353
00354 rc += i18n("Modulus: ");
00355 for (unsigned int i = 0; i < strlen(x); i++) {
00356 if (i%40 != 0 && i%2 == 0) {
00357 rc += ':';
00358 }
00359 else if (i%40 == 0) {
00360 rc += '\n';
00361 }
00362 rc += x[i];
00363 }
00364 rc += '\n';
00365 d->kossl->OPENSSL_free(x);
00366
00367 x = d->kossl->BN_bn2hex(pkey->pkey.rsa->e);
00368 rc += i18n("Exponent: 0x") + QLatin1String(x) +
00369 QLatin1String("\n");
00370 d->kossl->OPENSSL_free(x);
00371 }
00372 #endif
00373 #ifndef NO_DSA
00374 if (pkey->type == EVP_PKEY_DSA) {
00375 x = d->kossl->BN_bn2hex(pkey->pkey.dsa->p);
00376
00377 rc = i18n("Key type: DSA (%1 bit)", strlen(x)*4) + '\n';
00378
00379 rc += i18n("Prime: ");
00380 for (unsigned int i = 0; i < strlen(x); i++) {
00381 if (i%40 != 0 && i%2 == 0) {
00382 rc += ':';
00383 }
00384 else if (i%40 == 0) {
00385 rc += '\n';
00386 }
00387 rc += x[i];
00388 }
00389 rc += '\n';
00390 d->kossl->OPENSSL_free(x);
00391
00392 x = d->kossl->BN_bn2hex(pkey->pkey.dsa->q);
00393 rc += i18n("160 bit prime factor: ");
00394 for (unsigned int i = 0; i < strlen(x); i++) {
00395 if (i%40 != 0 && i%2 == 0) {
00396 rc += ':';
00397 }
00398 else if (i%40 == 0) {
00399 rc += '\n';
00400 }
00401 rc += x[i];
00402 }
00403 rc += '\n';
00404 d->kossl->OPENSSL_free(x);
00405
00406 x = d->kossl->BN_bn2hex(pkey->pkey.dsa->g);
00407 rc += QString("g: ");
00408 for (unsigned int i = 0; i < strlen(x); i++) {
00409 if (i%40 != 0 && i%2 == 0) {
00410 rc += ':';
00411 }
00412 else if (i%40 == 0) {
00413 rc += '\n';
00414 }
00415 rc += x[i];
00416 }
00417 rc += '\n';
00418 d->kossl->OPENSSL_free(x);
00419
00420 x = d->kossl->BN_bn2hex(pkey->pkey.dsa->pub_key);
00421 rc += i18n("Public key: ");
00422 for (unsigned int i = 0; i < strlen(x); i++) {
00423 if (i%40 != 0 && i%2 == 0) {
00424 rc += ':';
00425 }
00426 else if (i%40 == 0) {
00427 rc += '\n';
00428 }
00429 rc += x[i];
00430 }
00431 rc += '\n';
00432 d->kossl->OPENSSL_free(x);
00433 }
00434 #endif
00435 d->kossl->EVP_PKEY_free(pkey);
00436 }
00437 #endif
00438
00439 return rc;
00440 }
00441
00442
00443
00444 QString KSSLCertificate::getIssuer() const {
00445 QString rc = "";
00446
00447 #ifdef KSSL_HAVE_SSL
00448 char *t = d->kossl->X509_NAME_oneline(d->kossl->X509_get_issuer_name(d->m_cert), 0, 0);
00449
00450 if (!t) {
00451 return rc;
00452 }
00453
00454 rc = t;
00455 d->kossl->OPENSSL_free(t);
00456 #endif
00457
00458 return rc;
00459 }
00460
00461 void KSSLCertificate::setChain(void *c) {
00462 #ifdef KSSL_HAVE_SSL
00463 d->_chain.setChain(c);
00464 #endif
00465 d->m_stateCached = false;
00466 d->m_stateCache = KSSLCertificate::Unknown;
00467 }
00468
00469 void KSSLCertificate::setCert(X509 *c) {
00470 #ifdef KSSL_HAVE_SSL
00471 d->m_cert = c;
00472 if (c) {
00473 d->_extensions.flags = 0;
00474 d->kossl->X509_check_purpose(c, -1, 0);
00475
00476 #if 0
00477 kDebug(7029) << "---------------- Certificate ------------------"
00478 << endl;
00479 kDebug(7029) << getSubject();
00480 #endif
00481
00482 for (int j = 0; j < d->kossl->X509_PURPOSE_get_count(); j++) {
00483 X509_PURPOSE *ptmp = d->kossl->X509_PURPOSE_get0(j);
00484 int id = d->kossl->X509_PURPOSE_get_id(ptmp);
00485 for (int ca = 0; ca < 2; ca++) {
00486 int idret = d->kossl->X509_check_purpose(c, id, ca);
00487 if (idret == 1 || idret == 2) {
00488
00489 if (!ca) {
00490 d->_extensions.flags |= (1L <<(id-1));
00491 }
00492 else d->_extensions.flags |= (1L <<(16+id-1));
00493 } else {
00494 if (!ca) {
00495 d->_extensions.flags &= ~(1L <<(id-1));
00496 }
00497 else d->_extensions.flags &= ~(1L <<(16+id-1));
00498 }
00499 }
00500 }
00501
00502 #if 0
00503 kDebug(7029) << "flags: " << QString::number(c->ex_flags, 2)
00504 << "\nkeyusage: " << QString::number(c->ex_kusage, 2)
00505 << "\nxkeyusage: " << QString::number(c->ex_xkusage, 2)
00506 << "\nnscert: " << QString::number(c->ex_nscert, 2)
00507 << endl;
00508 if (c->ex_flags & EXFLAG_KUSAGE)
00509 kDebug(7029) << " --- Key Usage extensions found";
00510 else kDebug(7029) << " --- Key Usage extensions NOT found";
00511
00512 if (c->ex_flags & EXFLAG_XKUSAGE)
00513 kDebug(7029) << " --- Extended key usage extensions found";
00514 else kDebug(7029) << " --- Extended key usage extensions NOT found";
00515
00516 if (c->ex_flags & EXFLAG_NSCERT)
00517 kDebug(7029) << " --- NS extensions found";
00518 else kDebug(7029) << " --- NS extensions NOT found";
00519
00520 if (d->_extensions.certTypeSSLCA())
00521 kDebug(7029) << "NOTE: this is an SSL CA file.";
00522 else kDebug(7029) << "NOTE: this is NOT an SSL CA file.";
00523
00524 if (d->_extensions.certTypeEmailCA())
00525 kDebug(7029) << "NOTE: this is an EMAIL CA file.";
00526 else kDebug(7029) << "NOTE: this is NOT an EMAIL CA file.";
00527
00528 if (d->_extensions.certTypeCodeCA())
00529 kDebug(7029) << "NOTE: this is a CODE CA file.";
00530 else kDebug(7029) << "NOTE: this is NOT a CODE CA file.";
00531
00532 if (d->_extensions.certTypeSSLClient())
00533 kDebug(7029) << "NOTE: this is an SSL client.";
00534 else kDebug(7029) << "NOTE: this is NOT an SSL client.";
00535
00536 if (d->_extensions.certTypeSSLServer())
00537 kDebug(7029) << "NOTE: this is an SSL server.";
00538 else kDebug(7029) << "NOTE: this is NOT an SSL server.";
00539
00540 if (d->_extensions.certTypeNSSSLServer())
00541 kDebug(7029) << "NOTE: this is a NETSCAPE SSL server.";
00542 else kDebug(7029) << "NOTE: this is NOT a NETSCAPE SSL server.";
00543
00544 if (d->_extensions.certTypeSMIME())
00545 kDebug(7029) << "NOTE: this is an SMIME certificate.";
00546 else kDebug(7029) << "NOTE: this is NOT an SMIME certificate.";
00547
00548 if (d->_extensions.certTypeSMIMEEncrypt())
00549 kDebug(7029) << "NOTE: this is an SMIME encrypt cert.";
00550 else kDebug(7029) << "NOTE: this is NOT an SMIME encrypt cert.";
00551
00552 if (d->_extensions.certTypeSMIMESign())
00553 kDebug(7029) << "NOTE: this is an SMIME sign cert.";
00554 else kDebug(7029) << "NOTE: this is NOT an SMIME sign cert.";
00555
00556 if (d->_extensions.certTypeCRLSign())
00557 kDebug(7029) << "NOTE: this is a CRL signer.";
00558 else kDebug(7029) << "NOTE: this is NOT a CRL signer.";
00559
00560 kDebug(7029) << "-----------------------------------------------"
00561 << endl;
00562 #endif
00563 }
00564 #endif
00565 d->m_stateCached = false;
00566 d->m_stateCache = KSSLCertificate::Unknown;
00567 }
00568
00569 X509 *KSSLCertificate::getCert() {
00570 #ifdef KSSL_HAVE_SSL
00571 return d->m_cert;
00572 #endif
00573 return 0;
00574 }
00575
00576
00577
00578
00579 #include "ksslcallback.c"
00580
00581
00582 bool KSSLCertificate::isValid(KSSLCertificate::KSSLPurpose p) {
00583 return (validate(p) == KSSLCertificate::Ok);
00584 }
00585
00586
00587 bool KSSLCertificate::isValid() {
00588 return isValid(KSSLCertificate::SSLServer);
00589 }
00590
00591
00592 int KSSLCertificate::purposeToOpenSSL(KSSLCertificate::KSSLPurpose p) const {
00593 int rc = 0;
00594 #ifdef KSSL_HAVE_SSL
00595 if (p == KSSLCertificate::SSLServer) {
00596 rc = X509_PURPOSE_SSL_SERVER;
00597 } else if (p == KSSLCertificate::SSLClient) {
00598 rc = X509_PURPOSE_SSL_CLIENT;
00599 } else if (p == KSSLCertificate::SMIMEEncrypt) {
00600 rc = X509_PURPOSE_SMIME_ENCRYPT;
00601 } else if (p == KSSLCertificate::SMIMESign) {
00602 rc = X509_PURPOSE_SMIME_SIGN;
00603 } else if (p == KSSLCertificate::Any) {
00604 rc = X509_PURPOSE_ANY;
00605 }
00606 #endif
00607 return rc;
00608 }
00609
00610
00611
00612 KSSLCertificate::KSSLValidation KSSLCertificate::validate() {
00613 return validate(KSSLCertificate::SSLServer);
00614 }
00615
00616 KSSLCertificate::KSSLValidation KSSLCertificate::validate(KSSLCertificate::KSSLPurpose purpose)
00617 {
00618 KSSLValidationList result = validateVerbose(purpose);
00619 if (result.isEmpty()) {
00620 return KSSLCertificate::Ok;
00621 }
00622 else
00623 return result.first();
00624 }
00625
00626
00627
00628
00629
00630
00631 KSSLCertificate::KSSLValidationList KSSLCertificate::validateVerbose(KSSLCertificate::KSSLPurpose purpose)
00632 {
00633 return validateVerbose(purpose, 0);
00634 }
00635
00636 KSSLCertificate::KSSLValidationList KSSLCertificate::validateVerbose(KSSLCertificate::KSSLPurpose purpose, KSSLCertificate *ca)
00637 {
00638 KSSLValidationList errors;
00639 if (ca || (d->_lastPurpose != purpose)) {
00640 d->m_stateCached = false;
00641 }
00642
00643 if (!d->m_stateCached) {
00644 d->_lastPurpose = purpose;
00645 }
00646
00647 #ifdef KSSL_HAVE_SSL
00648 X509_STORE *certStore;
00649 X509_LOOKUP *certLookup;
00650 X509_STORE_CTX *certStoreCTX;
00651 int rc = 0;
00652
00653 if (!d->m_cert) {
00654 errors << KSSLCertificate::Unknown;
00655 return errors;
00656 }
00657
00658 if (d->m_stateCached) {
00659 errors << d->m_stateCache;
00660 return errors;
00661 }
00662
00663 const QStringList qsl = KGlobal::dirs()->resourceDirs("kssl");
00664
00665 if (qsl.isEmpty()) {
00666 errors << KSSLCertificate::NoCARoot;
00667 return errors;
00668 }
00669
00670 KSSLCertificate::KSSLValidation ksslv = Unknown;
00671
00672 for (QStringList::ConstIterator j = qsl.begin(); j != qsl.end(); ++j) {
00673 KDE_struct_stat sb;
00674 QString _j = (*j) + "ca-bundle.crt";
00675 if (-1 == KDE_stat(_j.toAscii().constData(), &sb)) {
00676 continue;
00677 }
00678
00679 certStore = d->kossl->X509_STORE_new();
00680 if (!certStore) {
00681 errors << KSSLCertificate::Unknown;
00682 return errors;
00683 }
00684
00685 X509_STORE_set_verify_cb_func(certStore, X509Callback);
00686
00687 certLookup = d->kossl->X509_STORE_add_lookup(certStore, d->kossl->X509_LOOKUP_file());
00688 if (!certLookup) {
00689 ksslv = KSSLCertificate::Unknown;
00690 d->kossl->X509_STORE_free(certStore);
00691 continue;
00692 }
00693
00694 if (!d->kossl->X509_LOOKUP_load_file(certLookup, _j.toAscii().constData(), X509_FILETYPE_PEM)) {
00695
00696 kDebug(7029) << "KSSL couldn't read CA root: "
00697 << _j << endl;
00698 ksslv = KSSLCertificate::ErrorReadingRoot;
00699 d->kossl->X509_STORE_free(certStore);
00700 continue;
00701 }
00702
00703
00704 certStoreCTX = d->kossl->X509_STORE_CTX_new();
00705
00706
00707
00708 if (!certStoreCTX) {
00709 kDebug(7029) << "KSSL couldn't create an X509 store context.";
00710 d->kossl->X509_STORE_free(certStore);
00711 continue;
00712 }
00713
00714 d->kossl->X509_STORE_CTX_init(certStoreCTX, certStore, d->m_cert, NULL);
00715 if (d->_chain.isValid()) {
00716 d->kossl->X509_STORE_CTX_set_chain(certStoreCTX, (STACK_OF(X509)*)d->_chain.rawChain());
00717 }
00718
00719
00720
00721
00722 d->kossl->X509_STORE_CTX_set_purpose(certStoreCTX, purposeToOpenSSL(purpose));
00723
00724 KSSL_X509CallBack_ca = ca ? ca->d->m_cert : 0;
00725 KSSL_X509CallBack_ca_found = false;
00726
00727 certStoreCTX->error = X509_V_OK;
00728 rc = d->kossl->X509_verify_cert(certStoreCTX);
00729 int errcode = certStoreCTX->error;
00730 if (ca && !KSSL_X509CallBack_ca_found) {
00731 ksslv = KSSLCertificate::Irrelevant;
00732 } else {
00733 ksslv = processError(errcode);
00734 }
00735
00736 if ((ksslv != KSSLCertificate::Ok) &&
00737 (ksslv != KSSLCertificate::Irrelevant) &&
00738 purpose == KSSLCertificate::SSLServer) {
00739 d->kossl->X509_STORE_CTX_set_purpose(certStoreCTX,
00740 X509_PURPOSE_NS_SSL_SERVER);
00741
00742 certStoreCTX->error = X509_V_OK;
00743 rc = d->kossl->X509_verify_cert(certStoreCTX);
00744 errcode = certStoreCTX->error;
00745 ksslv = processError(errcode);
00746 }
00747 d->kossl->X509_STORE_CTX_free(certStoreCTX);
00748 d->kossl->X509_STORE_free(certStore);
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759 if (ksslv != NoCARoot && ksslv != InvalidCA && ksslv != GetIssuerCertFailed && ksslv != DecodeIssuerPublicKeyFailed && ksslv != GetIssuerCertLocallyFailed ) {
00760 d->m_stateCached = true;
00761 d->m_stateCache = ksslv;
00762 }
00763 break;
00764 }
00765
00766 if (ksslv != KSSLCertificate::Ok) {
00767 errors << ksslv;
00768 }
00769 #else
00770 errors << KSSLCertificate::NoSSL;
00771 #endif
00772 return errors;
00773 }
00774
00775
00776
00777 KSSLCertificate::KSSLValidation KSSLCertificate::revalidate() {
00778 return revalidate(KSSLCertificate::SSLServer);
00779 }
00780
00781
00782 KSSLCertificate::KSSLValidation KSSLCertificate::revalidate(KSSLCertificate::KSSLPurpose p) {
00783 d->m_stateCached = false;
00784 return validate(p);
00785 }
00786
00787
00788 KSSLCertificate::KSSLValidation KSSLCertificate::processError(int ec) {
00789 KSSLCertificate::KSSLValidation rc;
00790
00791 rc = KSSLCertificate::Unknown;
00792 #ifdef KSSL_HAVE_SSL
00793 switch (ec) {
00794
00795
00796
00797
00798 case X509_V_OK:
00799 rc = KSSLCertificate::Ok;
00800 break;
00801
00802
00803
00804 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
00805 rc = KSSLCertificate::GetIssuerCertFailed;
00806 break;
00807
00808
00809 case X509_V_ERR_UNABLE_TO_GET_CRL:
00810 rc = KSSLCertificate::GetCRLFailed;
00811 break;
00812
00813
00814 case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE:
00815 rc = KSSLCertificate::DecryptCertificateSignatureFailed;
00816 break;
00817
00818
00819 case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE:
00820 rc = KSSLCertificate::DecryptCRLSignatureFailed;
00821 break;
00822
00823
00824 case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY:
00825 rc = KSSLCertificate::DecodeIssuerPublicKeyFailed;
00826 break;
00827
00828
00829 case X509_V_ERR_CERT_SIGNATURE_FAILURE:
00830 rc = KSSLCertificate::CertificateSignatureFailed;
00831 break;
00832
00833
00834 case X509_V_ERR_CRL_SIGNATURE_FAILURE:
00835 rc = KSSLCertificate::CRLSignatureFailed;
00836 break;
00837
00838
00839 case X509_V_ERR_CERT_NOT_YET_VALID:
00840 rc = KSSLCertificate::CertificateNotYetValid;
00841 break;
00842
00843
00844 case X509_V_ERR_CERT_HAS_EXPIRED:
00845 rc = KSSLCertificate::CertificateHasExpired;
00846 kDebug(7029) << "KSSL apparently this is expired. Not after: "
00847 << getNotAfter() << endl;
00848 break;
00849
00850
00851 case X509_V_ERR_CRL_NOT_YET_VALID:
00852 rc = KSSLCertificate::CRLNotYetValid;
00853 break;
00854
00855
00856 case X509_V_ERR_CRL_HAS_EXPIRED:
00857 rc = KSSLCertificate::CRLHasExpired;
00858 break;
00859
00860
00861 case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
00862 rc = KSSLCertificate::CertificateFieldNotBeforeErroneous;
00863 break;
00864
00865
00866 case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
00867 rc = KSSLCertificate::CertificateFieldNotAfterErroneous;
00868 break;
00869
00870
00871 case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD:
00872 rc = KSSLCertificate::CRLFieldLastUpdateErroneous;
00873 break;
00874
00875
00876 case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD:
00877 rc = KSSLCertificate::CRLFieldNextUpdateErroneous;
00878 break;
00879
00880
00881 case X509_V_ERR_OUT_OF_MEM:
00882 rc = KSSLCertificate::OutOfMemory;
00883 break;
00884
00885
00886 case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
00887 rc = KSSLCertificate::SelfSigned;
00888 break;
00889
00890
00891 case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
00892 rc = KSSLCertificate::SelfSignedInChain;
00893 break;
00894
00895
00896 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
00897 rc = KSSLCertificate::GetIssuerCertLocallyFailed;
00898 break;
00899
00900
00901 case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
00902 rc = KSSLCertificate::VerifyLeafSignatureFailed;
00903 break;
00904
00905
00906 case X509_V_ERR_CERT_CHAIN_TOO_LONG:
00907 rc = KSSLCertificate::CertificateChainTooLong;
00908 break;
00909
00910
00911 case X509_V_ERR_CERT_REVOKED:
00912 rc = KSSLCertificate::CertificateRevoked;
00913 break;
00914
00915
00916 case X509_V_ERR_INVALID_CA:
00917 rc = KSSLCertificate::InvalidCA;
00918 break;
00919
00920
00921 case X509_V_ERR_PATH_LENGTH_EXCEEDED:
00922 rc = KSSLCertificate::PathLengthExceeded;
00923 break;
00924
00925
00926 case X509_V_ERR_INVALID_PURPOSE:
00927 rc = KSSLCertificate::InvalidPurpose;
00928 break;
00929
00930
00931 case X509_V_ERR_CERT_UNTRUSTED:
00932 rc = KSSLCertificate::CertificateUntrusted;
00933 break;
00934
00935
00936 case X509_V_ERR_CERT_REJECTED:
00937 rc = KSSLCertificate::CertificateRejected;
00938 break;
00939
00940
00941 case X509_V_ERR_SUBJECT_ISSUER_MISMATCH:
00942 rc = KSSLCertificate::IssuerSubjectMismatched;
00943 break;
00944
00945
00946 case X509_V_ERR_AKID_SKID_MISMATCH:
00947 rc = KSSLCertificate::AuthAndSubjectKeyIDMismatched;
00948 break;
00949
00950
00951 case X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH:
00952 rc = KSSLCertificate::AuthAndSubjectKeyIDAndNameMismatched;
00953 break;
00954
00955
00956 case X509_V_ERR_KEYUSAGE_NO_CERTSIGN:
00957 rc = KSSLCertificate::KeyMayNotSignCertificate;
00958 break;
00959
00960
00961
00962 case X509_V_ERR_APPLICATION_VERIFICATION:
00963 rc = KSSLCertificate::ApplicationVerificationFailed;
00964 break;
00965
00966
00967 default:
00968 rc = KSSLCertificate::Unknown;
00969 break;
00970 }
00971
00972 d->m_stateCache = rc;
00973 d->m_stateCached = true;
00974 #endif
00975 return rc;
00976 }
00977
00978
00979 QString KSSLCertificate::getNotBefore() const {
00980 #ifdef KSSL_HAVE_SSL
00981 return ASN1_UTCTIME_QString(X509_get_notBefore(d->m_cert));
00982 #else
00983 return QString();
00984 #endif
00985 }
00986
00987
00988 QString KSSLCertificate::getNotAfter() const {
00989 #ifdef KSSL_HAVE_SSL
00990 return ASN1_UTCTIME_QString(X509_get_notAfter(d->m_cert));
00991 #else
00992 return QString();
00993 #endif
00994 }
00995
00996
00997 QDateTime KSSLCertificate::getQDTNotBefore() const {
00998 #ifdef KSSL_HAVE_SSL
00999 return ASN1_UTCTIME_QDateTime(X509_get_notBefore(d->m_cert), NULL);
01000 #else
01001 return QDateTime::currentDateTime();
01002 #endif
01003 }
01004
01005
01006 QDateTime KSSLCertificate::getQDTNotAfter() const {
01007 #ifdef KSSL_HAVE_SSL
01008 return ASN1_UTCTIME_QDateTime(X509_get_notAfter(d->m_cert), NULL);
01009 #else
01010 return QDateTime::currentDateTime();
01011 #endif
01012 }
01013
01014
01015 int operator==(KSSLCertificate &x, KSSLCertificate &y) {
01016 #ifndef KSSL_HAVE_SSL
01017 return 1;
01018 #else
01019 if (!KOSSL::self()->X509_cmp(x.getCert(), y.getCert())) {
01020 return 1;
01021 }
01022 return 0;
01023 #endif
01024 }
01025
01026
01027 KSSLCertificate *KSSLCertificate::replicate() {
01028
01029
01030 KSSLCertificate *newOne = new KSSLCertificate();
01031 #ifdef KSSL_HAVE_SSL
01032 newOne->setCert(d->kossl->X509_dup(getCert()));
01033 KSSLCertChain *c = d->_chain.replicate();
01034 newOne->setChain(c->rawChain());
01035 delete c;
01036 #endif
01037 return newOne;
01038 }
01039
01040
01041 QString KSSLCertificate::toString()
01042 {
01043 return toDer().toBase64();
01044 }
01045
01046
01047 QString KSSLCertificate::verifyText(KSSLValidation x) {
01048 switch (x) {
01049
01050 case KSSLCertificate::Ok:
01051 return i18n("The certificate is valid.");
01052 case KSSLCertificate::GetIssuerCertFailed:
01053 return i18n("Retrieval of the issuer certificate failed. This means the CA's (Certificate Authority) certificate can not be found.");
01054 case KSSLCertificate::GetCRLFailed:
01055 return i18n("Retrieval of the CRL (Certificate Revocation List) failed. This means the CA's (Certificate Authority) CRL can not be found.");
01056 case KSSLCertificate::DecryptCertificateSignatureFailed:
01057 return i18n("The decryption of the certificate's signature failed. This means it could not even be calculated as opposed to just not matching the expected result.");
01058 case KSSLCertificate::DecryptCRLSignatureFailed:
01059 return i18n("The decryption of the CRL's (Certificate Revocation List) signature failed. This means it could not even be calculated as opposed to just not matching the expected result.");
01060 case KSSLCertificate::DecodeIssuerPublicKeyFailed:
01061 return i18n("The decoding of the public key of the issuer failed. This means that the CA's (Certificate Authority) certificate can not be used to verify the certificate you wanted to use.");
01062 case KSSLCertificate::CertificateSignatureFailed:
01063 return i18n("The certificate's signature is invalid. This means that the certificate can not be verified.");
01064 case KSSLCertificate::CRLSignatureFailed:
01065 return i18n("The CRL's (Certificate Revocation List) signature is invalid. This means that the CRL can not be verified.");
01066 case KSSLCertificate::CertificateNotYetValid:
01067 return i18n("The certificate is not valid, yet.");
01068 case KSSLCertificate::CertificateHasExpired:
01069 return i18n("The certificate is not valid, any more.");
01070 case KSSLCertificate::CRLNotYetValid:
01071 return i18n("The CRL (Certificate Revocation List) is not valid, yet.");
01072 case KSSLCertificate::CRLHasExpired:
01073 return i18n("The CRL (Certificate Revocation List) is not valid, yet.");
01074 case KSSLCertificate::CertificateFieldNotBeforeErroneous:
01075 return i18n("The time format of the certificate's 'notBefore' field is invalid.");
01076 case KSSLCertificate::CertificateFieldNotAfterErroneous:
01077 return i18n("The time format of the certificate's 'notAfter' field is invalid.");
01078 case KSSLCertificate::CRLFieldLastUpdateErroneous:
01079 return i18n("The time format of the CRL's (Certificate Revocation List) 'lastUpdate' field is invalid.");
01080 case KSSLCertificate::CRLFieldNextUpdateErroneous:
01081 return i18n("The time format of the CRL's (Certificate Revocation List) 'nextUpdate' field is invalid.");
01082 case KSSLCertificate::OutOfMemory:
01083 return i18n("The OpenSSL process ran out of memory.");
01084 case KSSLCertificate::SelfSigned:
01085 return i18n("The certificate is self-signed and not in the list of trusted certificates. If you want to accept this certificate, import it into the list of trusted certificates.");
01086 case KSSLCertificate::SelfSignedChain:
01087 case KSSLCertificate::SelfSignedInChain:
01088 return i18n("The certificate is self-signed. While the trust chain could be built up, the root CA's (Certificate Authority) certificate can not be found.");
01089 case KSSLCertificate::GetIssuerCertLocallyFailed:
01090 return i18n("The CA's (Certificate Authority) certificate can not be found. Most likely, your trust chain is broken.");
01091 case KSSLCertificate::VerifyLeafSignatureFailed:
01092 return i18n("The certificate can not be verified as it is the only certificate in the trust chain and not self-signed. If you self-sign the certificate, make sure to import it into the list of trusted certificates.");
01093 case KSSLCertificate::CertificateChainTooLong:
01094 return i18n("The certificate chain is longer than the maximum depth specified.");
01095 case KSSLCertificate::Revoked:
01096 case KSSLCertificate::CertificateRevoked:
01097 return i18n("The certificate has been revoked.");
01098 case KSSLCertificate::InvalidCA:
01099 return i18n("The certificate's CA (Certificate Authority) is invalid.");
01100 case KSSLCertificate::PathLengthExceeded:
01101 return i18n("The length of the trust chain exceeded one of the CA's (Certificate Authority) 'pathlength' parameters, making all subsequent signatures invalid.");
01102 case KSSLCertificate::InvalidPurpose:
01103 return i18n("The certificate has not been signed for the purpose you tried to use it for. This means the CA (Certificate Authority) does not allow this usage.");
01104 case KSSLCertificate::Untrusted:
01105 case KSSLCertificate::CertificateUntrusted:
01106 return i18n("The root CA (Certificate Authority) is not trusted for the purpose you tried to use this certificate for.");
01107 case KSSLCertificate::Rejected:
01108 case KSSLCertificate::CertificateRejected:
01109 return i18n("The root CA (Certificate Authority) has been marked to be rejected for the purpose you tried to use it for.");
01110 case KSSLCertificate::IssuerSubjectMismatched:
01111 return i18n("The certificate's CA (Certificate Authority) does not match the CA name of the certificate.");
01112 case KSSLCertificate::AuthAndSubjectKeyIDMismatched:
01113 return i18n("The CA (Certificate Authority) certificate's key ID does not match the key ID in the 'Issuer' section of the certificate you are trying to use.");
01114 case KSSLCertificate::AuthAndSubjectKeyIDAndNameMismatched:
01115 return i18n("The CA (Certificate Authority) certificate's key ID and name do not match the key ID and name in the 'Issuer' section of the certificate you are trying to use.");
01116 case KSSLCertificate::KeyMayNotSignCertificate:
01117 return i18n("The certificate's CA (Certificate Authority) is not allowed to sign certificates.");
01118 case KSSLCertificate::ApplicationVerificationFailed:
01119 return i18n("OpenSSL could not be verified.");
01120
01121
01122
01123 case KSSLCertificate::SignatureFailed:
01124 return i18n("The signature test for this certificate failed. This could mean that the signature of this certificate or any in its trust path are invalid, could not be decoded or that the CRL (Certificate Revocation List) could not be verified. If you see this message, please let the author of the software you are using know that he or she should use the new, more specific error messages.");
01125 case KSSLCertificate::Expired:
01126 return i18n("This certificate, any in its trust path or its CA's (Certificate Authority) CRL (Certificate Revocation List) is not valid. Any of them could not be valid yet or not valid any more. If you see this message, please let the author of the software you are using know that he or she should use the new, more specific error messages.");
01127
01128
01129
01130 case KSSLCertificate::ErrorReadingRoot:
01131 case KSSLCertificate::NoCARoot:
01132 return i18n("Certificate signing authority root files could not be found so the certificate is not verified.");
01133 case KSSLCertificate::NoSSL:
01134 return i18n("SSL support was not found.");
01135 case KSSLCertificate::PrivateKeyFailed:
01136 return i18n("Private key test failed.");
01137 case KSSLCertificate::InvalidHost:
01138 return i18n("The certificate has not been issued for this host.");
01139 case KSSLCertificate::Irrelevant:
01140 return i18n("This certificate is not relevant.");
01141 default:
01142 break;
01143 }
01144
01145 return i18n("The certificate is invalid.");
01146 }
01147
01148
01149 QByteArray KSSLCertificate::toDer() {
01150 QByteArray qba;
01151 #ifdef KSSL_HAVE_SSL
01152 int certlen = d->kossl->i2d_X509(getCert(), NULL);
01153 if (certlen >= 0) {
01154
01155
01156 char *cert = new char[certlen];
01157 unsigned char *p = (unsigned char *)cert;
01158
01159 d->kossl->i2d_X509(getCert(), &p);
01160
01161
01162 qba = QByteArray(cert, certlen);
01163 delete[] cert;
01164 }
01165 #endif
01166 return qba;
01167 }
01168
01169
01170
01171 QByteArray KSSLCertificate::toPem() {
01172 QByteArray qba;
01173 QString thecert = toString();
01174 const char *header = "-----BEGIN CERTIFICATE-----\n";
01175 const char *footer = "-----END CERTIFICATE-----\n";
01176
01177
01178
01179 unsigned int xx = thecert.length() - 1;
01180 for (unsigned int i = 0; i < xx/64; i++) {
01181 thecert.insert(64*(i+1)+i, '\n');
01182 }
01183
01184 thecert.prepend(header);
01185
01186 if (thecert[thecert.length()-1] != '\n') {
01187 thecert += '\n';
01188 }
01189
01190 thecert.append(footer);
01191
01192 qba = thecert.toLocal8Bit();
01193 return qba;
01194 }
01195
01196
01197 #define NETSCAPE_CERT_HDR "certificate"
01198
01199 #if OPENSSL_VERSION_NUMBER < 0x00909000L
01200
01201 typedef struct NETSCAPE_X509_st
01202 {
01203 ASN1_OCTET_STRING *header;
01204 X509 *cert;
01205 } NETSCAPE_X509;
01206 #endif
01207
01208
01209 QByteArray KSSLCertificate::toNetscape() {
01210 QByteArray qba;
01211 #ifdef KSSL_HAVE_SSL
01212 NETSCAPE_X509 nx;
01213 ASN1_OCTET_STRING hdr;
01214 KTemporaryFile ktf;
01215 ktf.open();
01216 FILE *ktf_fs = fopen(ktf.fileName().toAscii(), "r+");
01217
01218 hdr.data = (unsigned char *)NETSCAPE_CERT_HDR;
01219 hdr.length = strlen(NETSCAPE_CERT_HDR);
01220 nx.header = &hdr;
01221 nx.cert = getCert();
01222
01223 d->kossl->ASN1_item_i2d_fp(ktf_fs,(unsigned char *)&nx);
01224 fclose(ktf_fs);
01225
01226 QFile qf(ktf.fileName());
01227 qf.open(QIODevice::ReadOnly);
01228 char *buf = new char[qf.size()];
01229 qf.read(buf, qf.size());
01230 qba = QByteArray(buf, qf.size());
01231 qf.close();
01232 delete[] buf;
01233
01234 #endif
01235 return qba;
01236 }
01237
01238
01239
01240 QString KSSLCertificate::toText() {
01241 QString text;
01242 #ifdef KSSL_HAVE_SSL
01243 KTemporaryFile ktf;
01244 ktf.open();
01245 FILE *ktf_fs = fopen(ktf.fileName().toAscii(), "r+");
01246
01247 d->kossl->X509_print(ktf_fs, getCert());
01248 fclose(ktf_fs);
01249
01250 QFile qf(ktf.fileName());
01251 qf.open(QIODevice::ReadOnly);
01252 char *buf = new char[qf.size()+1];
01253 qf.read(buf, qf.size());
01254 buf[qf.size()] = 0;
01255 text = buf;
01256 delete[] buf;
01257 qf.close();
01258 #endif
01259 return text;
01260 }
01261
01262 bool KSSLCertificate::setCert(const QString& cert) {
01263 #ifdef KSSL_HAVE_SSL
01264 QByteArray qba, qbb = cert.toLocal8Bit();
01265 qba = QByteArray::fromBase64(qbb);
01266 unsigned char *qbap = reinterpret_cast<unsigned char *>(qba.data());
01267 X509 *x5c = KOSSL::self()->d2i_X509(NULL, &qbap, qba.size());
01268 if (x5c) {
01269 setCert(x5c);
01270 return true;
01271 }
01272 #endif
01273 return false;
01274 }
01275
01276
01277 KSSLX509V3& KSSLCertificate::x509V3Extensions() {
01278 return d->_extensions;
01279 }
01280
01281
01282 bool KSSLCertificate::isSigner() {
01283 return d->_extensions.certTypeCA();
01284 }
01285
01286
01287 QStringList KSSLCertificate::subjAltNames() const {
01288 QStringList rc;
01289 #ifdef KSSL_HAVE_SSL
01290 STACK_OF(GENERAL_NAME) *names;
01291 names = (STACK_OF(GENERAL_NAME)*)d->kossl->X509_get_ext_d2i(d->m_cert, NID_subject_alt_name, 0, 0);
01292
01293 if (!names) {
01294 return rc;
01295 }
01296
01297 int cnt = d->kossl->sk_GENERAL_NAME_num(names);
01298
01299 for (int i = 0; i < cnt; i++) {
01300 const GENERAL_NAME *val = (const GENERAL_NAME *)d->kossl->sk_value(names, i);
01301 if (val->type != GEN_DNS) {
01302 continue;
01303 }
01304
01305 QString s = (const char *)d->kossl->ASN1_STRING_data(val->d.ia5);
01306 if (!s.isEmpty()) {
01307 rc += s;
01308 }
01309 }
01310 d->kossl->sk_free(names);
01311 #endif
01312 return rc;
01313 }
01314
01315
01316 QDataStream& operator<<(QDataStream& s, const KSSLCertificate& r) {
01317 QStringList qsl;
01318 QList<KSSLCertificate *> cl = const_cast<KSSLCertificate&>(r).chain().getChain();
01319
01320 foreach(KSSLCertificate *c, cl) {
01321 qsl << c->toString();
01322 }
01323
01324 qDeleteAll(cl);
01325 s << const_cast<KSSLCertificate&>(r).toString() << qsl;
01326
01327 return s;
01328 }
01329
01330
01331 QDataStream& operator>>(QDataStream& s, KSSLCertificate& r) {
01332 QStringList qsl;
01333 QString cert;
01334
01335 s >> cert >> qsl;
01336
01337 if (r.setCert(cert) && !qsl.isEmpty()) {
01338 r.chain().setCertChain(qsl);
01339 }
01340
01341 return s;
01342 }
01343
01344
01345