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 <tqstring.h>
00030 #include <tqstringlist.h>
00031 #include <tqfile.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 <tdelocale.h>
00041 #include <tqdatetime.h>
00042 #include <tdetempfile.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 <tqcstring.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 X509_CRL *m_cert_crl;
00087 #endif
00088 KOSSL *kossl;
00089 KSSLCertChain _chain;
00090 KSSLX509V3 _extensions;
00091 KSSLCertificate::KSSLPurpose _lastPurpose;
00092 };
00093
00094 KSSLCertificate::KSSLCertificate() {
00095 d = new KSSLCertificatePrivate;
00096 d->m_stateCached = false;
00097 TDEGlobal::dirs()->addResourceType("kssl", TDEStandardDirs::kde_default("data") + "kssl");
00098 #ifdef KSSL_HAVE_SSL
00099 d->m_cert = NULL;
00100 d->m_cert_crl = NULL;
00101 #endif
00102 }
00103
00104
00105 KSSLCertificate::KSSLCertificate(const KSSLCertificate& x) {
00106 d = new KSSLCertificatePrivate;
00107 d->m_stateCached = false;
00108 TDEGlobal::dirs()->addResourceType("kssl", TDEStandardDirs::kde_default("data") + "kssl");
00109 #ifdef KSSL_HAVE_SSL
00110 d->m_cert = NULL;
00111 d->m_cert_crl = NULL;
00112 setCert(KOSSL::self()->X509_dup(const_cast<KSSLCertificate&>(x).getCert()));
00113 KSSLCertChain *c = x.d->_chain.replicate();
00114 setChain(c->rawChain());
00115 delete c;
00116 #endif
00117 }
00118
00119
00120
00121 KSSLCertificate::~KSSLCertificate() {
00122 #ifdef KSSL_HAVE_SSL
00123 if (d->m_cert) {
00124 d->kossl->X509_free(d->m_cert);
00125 }
00126 if (d->m_cert_crl) {
00127 d->kossl->X509_CRL_free(d->m_cert_crl);
00128 }
00129 #endif
00130 delete d;
00131 }
00132
00133
00134 KSSLCertChain& KSSLCertificate::chain() {
00135 return d->_chain;
00136 }
00137
00138
00139 KSSLCertificate *KSSLCertificate::fromX509(X509 *x5) {
00140 KSSLCertificate *n = NULL;
00141 #ifdef KSSL_HAVE_SSL
00142 if (x5) {
00143 n = new KSSLCertificate;
00144 n->setCert(KOSSL::self()->X509_dup(x5));
00145 }
00146 #endif
00147 return n;
00148 }
00149
00150
00151 KSSLCertificate *KSSLCertificate::fromString(TQCString cert) {
00152 KSSLCertificate *n = NULL;
00153 #ifdef KSSL_HAVE_SSL
00154 if (cert.length() == 0)
00155 return NULL;
00156
00157 TQByteArray qba, qbb = cert.copy();
00158 KCodecs::base64Decode(qbb, qba);
00159 unsigned char *qbap = reinterpret_cast<unsigned char *>(qba.data());
00160 X509 *x5c = KOSSL::self()->d2i_X509(NULL, &qbap, qba.size());
00161 if (!x5c) {
00162 return NULL;
00163 }
00164
00165 n = new KSSLCertificate;
00166 n->setCert(x5c);
00167 #endif
00168 return n;
00169 }
00170
00171 KSSLCertificate *KSSLCertificate::crlFromString(TQCString cert) {
00172 KSSLCertificate *n = NULL;
00173 #ifdef KSSL_HAVE_SSL
00174 if (cert.length() == 0)
00175 return NULL;
00176
00177 TQByteArray qba, qbb = cert.copy();
00178 KCodecs::base64Decode(qbb, qba);
00179 unsigned char *qbap = reinterpret_cast<unsigned char *>(qba.data());
00180 X509_CRL *x5c = KOSSL::self()->d2i_X509_CRL(NULL, &qbap, qba.size());
00181 if (!x5c) {
00182 return NULL;
00183 }
00184
00185 n = new KSSLCertificate;
00186 n->setCRL(x5c);
00187 #endif
00188 return n;
00189 }
00190
00191
00192
00193 TQString KSSLCertificate::getSubject() const {
00194 TQString rc = "";
00195
00196 #ifdef KSSL_HAVE_SSL
00197 char *t = d->kossl->X509_NAME_oneline(d->kossl->X509_get_subject_name(d->m_cert), 0, 0);
00198 if (!t)
00199 return rc;
00200 rc = t;
00201 d->kossl->CRYPTO_free(t);
00202 #endif
00203 return rc;
00204 }
00205
00206
00207 TQString KSSLCertificate::getSerialNumber() const {
00208 TQString rc = "";
00209
00210 #ifdef KSSL_HAVE_SSL
00211 ASN1_INTEGER *aint = d->kossl->X509_get_serialNumber(d->m_cert);
00212 if (aint) {
00213 rc = ASN1_INTEGER_QString(aint);
00214
00215 }
00216 #endif
00217 return rc;
00218 }
00219
00220
00221 TQString KSSLCertificate::getSignatureText() const {
00222 TQString rc = "";
00223
00224 #ifdef KSSL_HAVE_SSL
00225 char *s;
00226 int n, i;
00227
00228 const ASN1_BIT_STRING *signature = 0L;
00229 const X509_ALGOR *sig_alg = 0L;
00230 d->kossl->X509_get0_signature(&signature, &sig_alg, d->m_cert);
00231 i = d->kossl->OBJ_obj2nid(sig_alg->algorithm);
00232 rc = i18n("Signature Algorithm: ");
00233 rc += (i == NID_undef)?i18n("Unknown"):TQString(d->kossl->OBJ_nid2ln(i));
00234
00235 rc += "\n";
00236 rc += i18n("Signature Contents:");
00237 n = signature->length;
00238 s = (char *)signature->data;
00239 for (i = 0; i < n; i++) {
00240 if (i%20 != 0) rc += ":";
00241 else rc += "\n";
00242 rc.append(hv[(s[i]&0xf0)>>4]);
00243 rc.append(hv[s[i]&0x0f]);
00244 }
00245
00246 #endif
00247
00248 return rc;
00249 }
00250
00251
00252 void KSSLCertificate::getEmails(TQStringList &to) const {
00253 to.clear();
00254 #ifdef KSSL_HAVE_SSL
00255 if (!d->m_cert)
00256 return;
00257
00258 STACK *s = d->kossl->X509_get1_email(d->m_cert);
00259 if (s) {
00260 for(int n=0; n < d->kossl->OPENSSL_sk_num(s); n++) {
00261 to.append(d->kossl->OPENSSL_sk_value(s,n));
00262 }
00263 d->kossl->X509_email_free(s);
00264 }
00265 #endif
00266 }
00267
00268
00269 TQString KSSLCertificate::getKDEKey() const {
00270 return getSubject() + " (" + getMD5DigestText() + ")";
00271 }
00272
00273
00274 TQString KSSLCertificate::getMD5DigestFromKDEKey(const TQString &k) {
00275 TQString rc;
00276 int pos = k.findRev('(');
00277 if (pos != -1) {
00278 unsigned int len = k.length();
00279 if (k.at(len-1) == ')') {
00280 rc = k.mid(pos+1, len-pos-2);
00281 }
00282 }
00283 return rc;
00284 }
00285
00286
00287 TQString KSSLCertificate::getMD5DigestText() const {
00288 TQString rc = "";
00289
00290 #ifdef KSSL_HAVE_SSL
00291 unsigned int n;
00292 unsigned char md[EVP_MAX_MD_SIZE];
00293
00294 if (!d->kossl->X509_digest(d->m_cert, d->kossl->EVP_md5(), md, &n)) {
00295 return rc;
00296 }
00297
00298 for (unsigned int j = 0; j < n; j++) {
00299 if (j > 0)
00300 rc += ":";
00301 rc.append(hv[(md[j]&0xf0)>>4]);
00302 rc.append(hv[md[j]&0x0f]);
00303 }
00304
00305 #endif
00306
00307 return rc;
00308 }
00309
00310
00311
00312 TQString KSSLCertificate::getMD5Digest() const {
00313 TQString rc = "";
00314
00315 #ifdef KSSL_HAVE_SSL
00316 unsigned int n;
00317 unsigned char md[EVP_MAX_MD_SIZE];
00318
00319 if (!d->kossl->X509_digest(d->m_cert, d->kossl->EVP_md5(), md, &n)) {
00320 return rc;
00321 }
00322
00323 for (unsigned int j = 0; j < n; j++) {
00324 rc.append(hv[(md[j]&0xf0)>>4]);
00325 rc.append(hv[md[j]&0x0f]);
00326 }
00327
00328 #endif
00329
00330 return rc;
00331 }
00332
00333
00334
00335 TQString KSSLCertificate::getKeyType() const {
00336 TQString rc = "";
00337
00338 #ifdef KSSL_HAVE_SSL
00339 EVP_PKEY *pkey = d->kossl->X509_get_pubkey(d->m_cert);
00340 if (pkey) {
00341 #ifndef NO_RSA
00342 if (d->kossl->EVP_PKEY_base_id(pkey) == EVP_PKEY_RSA)
00343 rc = "RSA";
00344 else
00345 #endif
00346 #ifndef NO_DSA
00347 if (d->kossl->EVP_PKEY_base_id(pkey) == EVP_PKEY_DSA)
00348 rc = "DSA";
00349 else
00350 #endif
00351 rc = "Unknown";
00352 d->kossl->EVP_PKEY_free(pkey);
00353 }
00354 #endif
00355
00356 return rc;
00357 }
00358
00359
00360
00361 TQString KSSLCertificate::getPublicKeyText() const {
00362 TQString rc = "";
00363 char *x = NULL;
00364
00365 #ifdef KSSL_HAVE_SSL
00366 EVP_PKEY *pkey = d->kossl->X509_get_pubkey(d->m_cert);
00367 if (pkey) {
00368 rc = i18n("Unknown", "Unknown key algorithm");
00369 #ifndef NO_RSA
00370 if (d->kossl->EVP_PKEY_base_id(pkey) == EVP_PKEY_RSA) {
00371 rc = i18n("Key type: RSA (%1 bit)") + "\n";
00372
00373 RSA *pkey_rsa = d->kossl->EVP_PKEY_get0_RSA(pkey);
00374 const BIGNUM *bn_n = 0L;
00375 const BIGNUM *bn_e = 0L;
00376 d->kossl->RSA_get0_key(pkey_rsa, &bn_n, &bn_e, NULL);
00377 x = d->kossl->BN_bn2hex(bn_n);
00378 rc += i18n("Modulus: ");
00379 rc = rc.arg(strlen(x)*4);
00380 for (unsigned int i = 0; i < strlen(x); i++) {
00381 if (i%40 != 0 && i%2 == 0)
00382 rc += ":";
00383 else if (i%40 == 0)
00384 rc += "\n";
00385 rc += x[i];
00386 }
00387 rc += "\n";
00388 d->kossl->CRYPTO_free(x);
00389
00390 x = d->kossl->BN_bn2hex(bn_e);
00391 rc += i18n("Exponent: 0x") + x + "\n";
00392 d->kossl->CRYPTO_free(x);
00393 }
00394 #endif
00395 #ifndef NO_DSA
00396 if (d->kossl->EVP_PKEY_base_id(pkey) == EVP_PKEY_DSA) {
00397 rc = i18n("Key type: DSA (%1 bit)") + "\n";
00398
00399 DSA *pkey_dsa = d->kossl->EVP_PKEY_get0_DSA(pkey);
00400 const BIGNUM *bn_p = 0L;
00401 const BIGNUM *bn_q = 0L;
00402 const BIGNUM *bn_g = 0L;
00403 const BIGNUM *bn_pub_key = 0L;
00404 d->kossl->DSA_get0_pqg(pkey_dsa, &bn_p, &bn_q, &bn_g);
00405 d->kossl->DSA_get0_key(pkey_dsa, &bn_pub_key, NULL);
00406
00407 x = d->kossl->BN_bn2hex(bn_p);
00408 rc += i18n("Prime: ");
00409
00410 rc = rc.arg(strlen(x)*4) ;
00411 for (unsigned int i = 0; i < strlen(x); i++) {
00412 if (i%40 != 0 && i%2 == 0)
00413 rc += ":";
00414 else if (i%40 == 0)
00415 rc += "\n";
00416 rc += x[i];
00417 }
00418 rc += "\n";
00419 d->kossl->CRYPTO_free(x);
00420
00421 x = d->kossl->BN_bn2hex(bn_q);
00422 rc += i18n("160 bit prime factor: ");
00423 for (unsigned int i = 0; i < strlen(x); i++) {
00424 if (i%40 != 0 && i%2 == 0)
00425 rc += ":";
00426 else if (i%40 == 0)
00427 rc += "\n";
00428 rc += x[i];
00429 }
00430 rc += "\n";
00431 d->kossl->CRYPTO_free(x);
00432
00433 x = d->kossl->BN_bn2hex(bn_g);
00434 rc += TQString("g: ");
00435 for (unsigned int i = 0; i < strlen(x); i++) {
00436 if (i%40 != 0 && i%2 == 0)
00437 rc += ":";
00438 else if (i%40 == 0)
00439 rc += "\n";
00440 rc += x[i];
00441 }
00442 rc += "\n";
00443 d->kossl->CRYPTO_free(x);
00444
00445 x = d->kossl->BN_bn2hex(bn_pub_key);
00446 rc += i18n("Public key: ");
00447 for (unsigned int i = 0; i < strlen(x); i++) {
00448 if (i%40 != 0 && i%2 == 0)
00449 rc += ":";
00450 else if (i%40 == 0)
00451 rc += "\n";
00452 rc += x[i];
00453 }
00454 rc += "\n";
00455 d->kossl->CRYPTO_free(x);
00456 }
00457 #endif
00458 d->kossl->EVP_PKEY_free(pkey);
00459 }
00460 #endif
00461
00462 return rc;
00463 }
00464
00465
00466
00467 TQString KSSLCertificate::getIssuer() const {
00468 TQString rc = "";
00469
00470 #ifdef KSSL_HAVE_SSL
00471 char *t = d->kossl->X509_NAME_oneline(d->kossl->X509_get_issuer_name(d->m_cert), 0, 0);
00472
00473 if (!t)
00474 return rc;
00475
00476 rc = t;
00477 d->kossl->CRYPTO_free(t);
00478 #endif
00479
00480 return rc;
00481 }
00482
00483 void KSSLCertificate::setChain(void *c) {
00484 #ifdef KSSL_HAVE_SSL
00485 d->_chain.setChain(c);
00486 #endif
00487 d->m_stateCached = false;
00488 d->m_stateCache = KSSLCertificate::Unknown;
00489 }
00490
00491 void KSSLCertificate::setCert(X509 *c) {
00492 #ifdef KSSL_HAVE_SSL
00493 d->m_cert = c;
00494 if (c) {
00495 d->_extensions.flags = 0;
00496 d->kossl->X509_check_purpose(c, -1, 0);
00497
00498 #if 0
00499 kdDebug(7029) << "---------------- Certificate ------------------"
00500 << endl;
00501 kdDebug(7029) << getSubject() << endl;
00502 #endif
00503
00504 for (int j = 0; j < d->kossl->X509_PURPOSE_get_count(); j++) {
00505 X509_PURPOSE *ptmp = d->kossl->X509_PURPOSE_get0(j);
00506 int id = d->kossl->X509_PURPOSE_get_id(ptmp);
00507 for (int ca = 0; ca < 2; ca++) {
00508 int idret = d->kossl->X509_check_purpose(c, id, ca);
00509 if (idret == 1 || idret == 2) {
00510
00511 if (!ca)
00512 d->_extensions.flags |= (1L <<(id-1));
00513 else d->_extensions.flags |= (1L <<(16+id-1));
00514 } else {
00515 if (!ca)
00516 d->_extensions.flags &= ~(1L <<(id-1));
00517 else d->_extensions.flags &= ~(1L <<(16+id-1));
00518 }
00519 }
00520 }
00521
00522 #if 0
00523 kdDebug(7029) << "flags: " << TQString::number(c->ex_flags, 2)
00524 << "\nkeyusage: " << TQString::number(c->ex_kusage, 2)
00525 << "\nxkeyusage: " << TQString::number(c->ex_xkusage, 2)
00526 << "\nnscert: " << TQString::number(c->ex_nscert, 2)
00527 << endl;
00528 if (c->ex_flags & EXFLAG_KUSAGE)
00529 kdDebug(7029) << " --- Key Usage extensions found" << endl;
00530 else kdDebug(7029) << " --- Key Usage extensions NOT found" << endl;
00531
00532 if (c->ex_flags & EXFLAG_XKUSAGE)
00533 kdDebug(7029) << " --- Extended key usage extensions found" << endl;
00534 else kdDebug(7029) << " --- Extended key usage extensions NOT found" << endl;
00535
00536 if (c->ex_flags & EXFLAG_NSCERT)
00537 kdDebug(7029) << " --- NS extensions found" << endl;
00538 else kdDebug(7029) << " --- NS extensions NOT found" << endl;
00539
00540 if (d->_extensions.certTypeSSLCA())
00541 kdDebug(7029) << "NOTE: this is an SSL CA file." << endl;
00542 else kdDebug(7029) << "NOTE: this is NOT an SSL CA file." << endl;
00543
00544 if (d->_extensions.certTypeEmailCA())
00545 kdDebug(7029) << "NOTE: this is an EMAIL CA file." << endl;
00546 else kdDebug(7029) << "NOTE: this is NOT an EMAIL CA file." << endl;
00547
00548 if (d->_extensions.certTypeCodeCA())
00549 kdDebug(7029) << "NOTE: this is a CODE CA file." << endl;
00550 else kdDebug(7029) << "NOTE: this is NOT a CODE CA file." << endl;
00551
00552 if (d->_extensions.certTypeSSLClient())
00553 kdDebug(7029) << "NOTE: this is an SSL client." << endl;
00554 else kdDebug(7029) << "NOTE: this is NOT an SSL client." << endl;
00555
00556 if (d->_extensions.certTypeSSLServer())
00557 kdDebug(7029) << "NOTE: this is an SSL server." << endl;
00558 else kdDebug(7029) << "NOTE: this is NOT an SSL server." << endl;
00559
00560 if (d->_extensions.certTypeNSSSLServer())
00561 kdDebug(7029) << "NOTE: this is a NETSCAPE SSL server." << endl;
00562 else kdDebug(7029) << "NOTE: this is NOT a NETSCAPE SSL server." << endl;
00563
00564 if (d->_extensions.certTypeSMIME())
00565 kdDebug(7029) << "NOTE: this is an SMIME certificate." << endl;
00566 else kdDebug(7029) << "NOTE: this is NOT an SMIME certificate." << endl;
00567
00568 if (d->_extensions.certTypeSMIMEEncrypt())
00569 kdDebug(7029) << "NOTE: this is an SMIME encrypt cert." << endl;
00570 else kdDebug(7029) << "NOTE: this is NOT an SMIME encrypt cert." << endl;
00571
00572 if (d->_extensions.certTypeSMIMESign())
00573 kdDebug(7029) << "NOTE: this is an SMIME sign cert." << endl;
00574 else kdDebug(7029) << "NOTE: this is NOT an SMIME sign cert." << endl;
00575
00576 if (d->_extensions.certTypeCRLSign())
00577 kdDebug(7029) << "NOTE: this is a CRL signer." << endl;
00578 else kdDebug(7029) << "NOTE: this is NOT a CRL signer." << endl;
00579
00580 kdDebug(7029) << "-----------------------------------------------"
00581 << endl;
00582 #endif
00583 }
00584 #endif
00585 d->m_stateCached = false;
00586 d->m_stateCache = KSSLCertificate::Unknown;
00587 }
00588
00589 void KSSLCertificate::setCRL(X509_CRL *c) {
00590 #ifdef KSSL_HAVE_SSL
00591 d->m_cert_crl = c;
00592 if (c) {
00593 d->_extensions.flags = 0;
00594 }
00595 #endif
00596 d->m_stateCached = false;
00597 d->m_stateCache = KSSLCertificate::Unknown;
00598 }
00599
00600 X509 *KSSLCertificate::getCert() {
00601 #ifdef KSSL_HAVE_SSL
00602 return d->m_cert;
00603 #endif
00604 return 0;
00605 }
00606
00607
00608
00609
00610 #include "ksslcallback.c"
00611
00612
00613 bool KSSLCertificate::isValid(KSSLCertificate::KSSLPurpose p) {
00614 return (validate(p) == KSSLCertificate::Ok);
00615 }
00616
00617
00618 bool KSSLCertificate::isValid() {
00619 return isValid(KSSLCertificate::SSLServer);
00620 }
00621
00622
00623 int KSSLCertificate::purposeToOpenSSL(KSSLCertificate::KSSLPurpose p) const {
00624 int rc = 0;
00625 #ifdef KSSL_HAVE_SSL
00626 if (p == KSSLCertificate::SSLServer) {
00627 rc = X509_PURPOSE_SSL_SERVER;
00628 } else if (p == KSSLCertificate::SSLClient) {
00629 rc = X509_PURPOSE_SSL_CLIENT;
00630 } else if (p == KSSLCertificate::SMIMEEncrypt) {
00631 rc = X509_PURPOSE_SMIME_ENCRYPT;
00632 } else if (p == KSSLCertificate::SMIMESign) {
00633 rc = X509_PURPOSE_SMIME_SIGN;
00634 } else if (p == KSSLCertificate::Any) {
00635 rc = X509_PURPOSE_ANY;
00636 }
00637 #endif
00638 return rc;
00639 }
00640
00641
00642
00643 KSSLCertificate::KSSLValidation KSSLCertificate::validate() {
00644 return validate(KSSLCertificate::SSLServer);
00645 }
00646
00647 KSSLCertificate::KSSLValidation KSSLCertificate::validate(KSSLCertificate::KSSLPurpose purpose)
00648 {
00649 KSSLValidationList result = validateVerbose(purpose);
00650 if (result.isEmpty())
00651 return KSSLCertificate::Ok;
00652 else
00653 return result.first();
00654 }
00655
00656
00657
00658
00659
00660
00661 KSSLCertificate::KSSLValidationList KSSLCertificate::validateVerbose(KSSLCertificate::KSSLPurpose purpose)
00662 {
00663 return validateVerbose(purpose, 0);
00664 }
00665
00666 KSSLCertificate::KSSLValidationList KSSLCertificate::validateVerbose(KSSLCertificate::KSSLPurpose purpose, KSSLCertificate *ca)
00667 {
00668 KSSLValidationList errors;
00669 if (ca || (d->_lastPurpose != purpose)) {
00670 d->m_stateCached = false;
00671 }
00672
00673 if (!d->m_stateCached)
00674 d->_lastPurpose = purpose;
00675
00676 #ifdef KSSL_HAVE_SSL
00677 X509_STORE *certStore;
00678 X509_LOOKUP *certLookup;
00679 X509_STORE_CTX *certStoreCTX;
00680
00681 if (!d->m_cert)
00682 {
00683 errors << KSSLCertificate::Unknown;
00684 return errors;
00685 }
00686
00687 if (d->m_stateCached) {
00688 errors << d->m_stateCache;
00689 return errors;
00690 }
00691
00692 TQStringList qsl = TDEGlobal::dirs()->resourceDirs("kssl");
00693
00694 if (qsl.isEmpty()) {
00695 errors << KSSLCertificate::NoCARoot;
00696 return errors;
00697 }
00698
00699 KSSLCertificate::KSSLValidation ksslv = Unknown;
00700
00701 for (TQStringList::Iterator j = qsl.begin(); j != qsl.end(); ++j) {
00702 struct stat sb;
00703 TQString _j = (*j) + "ca-bundle.crt";
00704 if (-1 == stat(_j.ascii(), &sb)) {
00705 continue;
00706 }
00707
00708 certStore = d->kossl->X509_STORE_new();
00709 if (!certStore) {
00710 errors << KSSLCertificate::Unknown;
00711 return errors;
00712 }
00713
00714 d->kossl->X509_STORE_set_verify_cb(certStore, X509Callback);
00715
00716 certLookup = d->kossl->X509_STORE_add_lookup(certStore, d->kossl->X509_LOOKUP_file());
00717 if (!certLookup) {
00718 ksslv = KSSLCertificate::Unknown;
00719 d->kossl->X509_STORE_free(certStore);
00720 continue;
00721 }
00722
00723 if (!d->kossl->X509_LOOKUP_load_file(certLookup, _j.ascii(), X509_FILETYPE_PEM)) {
00724
00725 kdDebug(7029) << "KSSL couldn't read CA root: "
00726 << _j << endl;
00727 ksslv = KSSLCertificate::ErrorReadingRoot;
00728 d->kossl->X509_STORE_free(certStore);
00729 continue;
00730 }
00731
00732
00733 certStoreCTX = d->kossl->X509_STORE_CTX_new();
00734
00735
00736
00737 if (!certStoreCTX) {
00738 kdDebug(7029) << "KSSL couldn't create an X509 store context." << endl;
00739 d->kossl->X509_STORE_free(certStore);
00740 continue;
00741 }
00742
00743 d->kossl->X509_STORE_CTX_init(certStoreCTX, certStore, d->m_cert, NULL);
00744 if (d->_chain.isValid()) {
00745 d->kossl->X509_STORE_CTX_set0_untrusted(certStoreCTX, (STACK_OF(X509)*)d->_chain.rawChain());
00746 }
00747
00748
00749
00750
00751 d->kossl->X509_STORE_CTX_set_purpose(certStoreCTX, purposeToOpenSSL(purpose));
00752
00753 KSSL_X509CallBack_ca = ca ? ca->d->m_cert : 0;
00754 KSSL_X509CallBack_ca_found = false;
00755
00756 d->kossl->X509_STORE_CTX_set_error(certStoreCTX, X509_V_OK);
00757 d->kossl->X509_verify_cert(certStoreCTX);
00758 int errcode = d->kossl->X509_STORE_CTX_get_error(certStoreCTX);
00759 if (ca && !KSSL_X509CallBack_ca_found) {
00760 ksslv = KSSLCertificate::Irrelevant;
00761 } else {
00762 ksslv = processError(errcode);
00763 }
00764
00765 if ( (ksslv != KSSLCertificate::Ok) &&
00766 (ksslv != KSSLCertificate::Irrelevant) &&
00767 purpose == KSSLCertificate::SSLServer) {
00768 d->kossl->X509_STORE_CTX_set_purpose(certStoreCTX,
00769 X509_PURPOSE_NS_SSL_SERVER);
00770
00771 d->kossl->X509_STORE_CTX_set_error(certStoreCTX, X509_V_OK);
00772 d->kossl->X509_verify_cert(certStoreCTX);
00773 errcode = d->kossl->X509_STORE_CTX_get_error(certStoreCTX);
00774 ksslv = processError(errcode);
00775 }
00776 d->kossl->X509_STORE_CTX_free(certStoreCTX);
00777 d->kossl->X509_STORE_free(certStore);
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788 if (ksslv != NoCARoot && ksslv != InvalidCA) {
00789 d->m_stateCached = true;
00790 d->m_stateCache = ksslv;
00791 }
00792 break;
00793 }
00794
00795 if (ksslv != KSSLCertificate::Ok)
00796 errors << ksslv;
00797 #else
00798 errors << KSSLCertificate::NoSSL;
00799 #endif
00800 return errors;
00801 }
00802
00803
00804
00805 KSSLCertificate::KSSLValidation KSSLCertificate::revalidate() {
00806 return revalidate(KSSLCertificate::SSLServer);
00807 }
00808
00809
00810 KSSLCertificate::KSSLValidation KSSLCertificate::revalidate(KSSLCertificate::KSSLPurpose p) {
00811 d->m_stateCached = false;
00812 return validate(p);
00813 }
00814
00815
00816 KSSLCertificate::KSSLValidation KSSLCertificate::processError(int ec) {
00817 KSSLCertificate::KSSLValidation rc;
00818
00819 rc = KSSLCertificate::Unknown;
00820 #ifdef KSSL_HAVE_SSL
00821 switch (ec) {
00822 case X509_V_OK:
00823 rc = KSSLCertificate::Ok;
00824 break;
00825
00826
00827 case X509_V_ERR_CERT_REJECTED:
00828 rc = KSSLCertificate::Rejected;
00829 break;
00830
00831
00832 case X509_V_ERR_CERT_UNTRUSTED:
00833 rc = KSSLCertificate::Untrusted;
00834 break;
00835
00836
00837 case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
00838 case X509_V_ERR_CERT_SIGNATURE_FAILURE:
00839 case X509_V_ERR_CRL_SIGNATURE_FAILURE:
00840 case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE:
00841 case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE:
00842 rc = KSSLCertificate::SignatureFailed;
00843 break;
00844
00845 case X509_V_ERR_INVALID_CA:
00846 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
00847 case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY:
00848 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
00849 rc = KSSLCertificate::InvalidCA;
00850 break;
00851
00852
00853 case X509_V_ERR_INVALID_PURPOSE:
00854 rc = KSSLCertificate::InvalidPurpose;
00855 break;
00856
00857
00858 case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
00859 rc = KSSLCertificate::SelfSigned;
00860 break;
00861
00862 case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
00863 rc = KSSLCertificate::SelfSignedChain;
00864 break;
00865
00866 case X509_V_ERR_CERT_REVOKED:
00867 rc = KSSLCertificate::Revoked;
00868 break;
00869
00870 case X509_V_ERR_PATH_LENGTH_EXCEEDED:
00871 rc = KSSLCertificate::PathLengthExceeded;
00872 break;
00873
00874 case X509_V_ERR_CERT_NOT_YET_VALID:
00875 case X509_V_ERR_CERT_HAS_EXPIRED:
00876 case X509_V_ERR_CRL_NOT_YET_VALID:
00877 case X509_V_ERR_CRL_HAS_EXPIRED:
00878 case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
00879 case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
00880 case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD:
00881 case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD:
00882 rc = KSSLCertificate::Expired;
00883 kdDebug(7029) << "KSSL apparently this is expired. Not after: "
00884 << getNotAfter() << endl;
00885 break;
00886
00887
00888 case X509_V_ERR_APPLICATION_VERIFICATION:
00889 case X509_V_ERR_OUT_OF_MEM:
00890 case X509_V_ERR_UNABLE_TO_GET_CRL:
00891 case X509_V_ERR_CERT_CHAIN_TOO_LONG:
00892 default:
00893 rc = KSSLCertificate::Unknown;
00894 break;
00895 }
00896
00897 d->m_stateCache = rc;
00898 d->m_stateCached = true;
00899 #endif
00900 return rc;
00901 }
00902
00903
00904 TQString KSSLCertificate::getNotBefore() const {
00905 #ifdef KSSL_HAVE_SSL
00906 return ASN1_UTCTIME_QString(d->kossl->X509_getm_notBefore(d->m_cert));
00907 #else
00908 return TQString::null;
00909 #endif
00910 }
00911
00912
00913 TQString KSSLCertificate::getNotAfter() const {
00914 #ifdef KSSL_HAVE_SSL
00915 return ASN1_UTCTIME_QString(d->kossl->X509_getm_notAfter(d->m_cert));
00916 #else
00917 return TQString::null;
00918 #endif
00919 }
00920
00921
00922 TQDateTime KSSLCertificate::getQDTNotBefore() const {
00923 #ifdef KSSL_HAVE_SSL
00924 return ASN1_UTCTIME_QDateTime(d->kossl->X509_getm_notBefore(d->m_cert), NULL);
00925 #else
00926 return TQDateTime::currentDateTime();
00927 #endif
00928 }
00929
00930
00931 TQDateTime KSSLCertificate::getQDTNotAfter() const {
00932 #ifdef KSSL_HAVE_SSL
00933 return ASN1_UTCTIME_QDateTime(d->kossl->X509_getm_notAfter(d->m_cert), NULL);
00934 #else
00935 return TQDateTime::currentDateTime();
00936 #endif
00937 }
00938
00939
00940 TQDateTime KSSLCertificate::getQDTLastUpdate() const {
00941 #ifdef KSSL_HAVE_SSL
00942 return ASN1_UTCTIME_QDateTime((ASN1_UTCTIME*)d->kossl->X509_CRL_get0_lastUpdate(d->m_cert_crl), NULL);
00943 #else
00944 return TQDateTime::currentDateTime();
00945 #endif
00946 }
00947
00948
00949 TQDateTime KSSLCertificate::getQDTNextUpdate() const {
00950 #ifdef KSSL_HAVE_SSL
00951 return ASN1_UTCTIME_QDateTime((ASN1_UTCTIME*)d->kossl->X509_CRL_get0_nextUpdate(d->m_cert_crl), NULL);
00952 #else
00953 return TQDateTime::currentDateTime();
00954 #endif
00955 }
00956
00957
00958 int operator==(KSSLCertificate &x, KSSLCertificate &y) {
00959 #ifndef KSSL_HAVE_SSL
00960 return 1;
00961 #else
00962 if (!KOSSL::self()->X509_cmp(x.getCert(), y.getCert())) return 1;
00963 return 0;
00964 #endif
00965 }
00966
00967
00968 KSSLCertificate *KSSLCertificate::replicate() {
00969
00970
00971 KSSLCertificate *newOne = new KSSLCertificate();
00972 #ifdef KSSL_HAVE_SSL
00973 newOne->setCert(d->kossl->X509_dup(getCert()));
00974 KSSLCertChain *c = d->_chain.replicate();
00975 newOne->setChain(c->rawChain());
00976 delete c;
00977 #endif
00978 return newOne;
00979 }
00980
00981
00982 TQString KSSLCertificate::toString() {
00983 return KCodecs::base64Encode(toDer());
00984 }
00985
00986
00987 TQString KSSLCertificate::verifyText(KSSLValidation x) {
00988 switch (x) {
00989 case KSSLCertificate::Ok:
00990 return i18n("The certificate is valid.");
00991 case KSSLCertificate::PathLengthExceeded:
00992 case KSSLCertificate::ErrorReadingRoot:
00993 case KSSLCertificate::NoCARoot:
00994 return i18n("Certificate signing authority root files could not be found so the certificate is not verified.");
00995 case KSSLCertificate::SelfSignedChain:
00996 case KSSLCertificate::InvalidCA:
00997 return i18n("Certificate signing authority is unknown or invalid.");
00998 case KSSLCertificate::SelfSigned:
00999 return i18n("Certificate is self-signed and thus may not be trustworthy.");
01000 case KSSLCertificate::Expired:
01001 return i18n("Certificate has expired.");
01002 case KSSLCertificate::Revoked:
01003 return i18n("Certificate has been revoked.");
01004 case KSSLCertificate::NoSSL:
01005 return i18n("SSL support was not found.");
01006 case KSSLCertificate::Untrusted:
01007 return i18n("Signature is untrusted.");
01008 case KSSLCertificate::SignatureFailed:
01009 return i18n("Signature test failed.");
01010 case KSSLCertificate::Rejected:
01011 case KSSLCertificate::InvalidPurpose:
01012 return i18n("Rejected, possibly due to an invalid purpose.");
01013 case KSSLCertificate::PrivateKeyFailed:
01014 return i18n("Private key test failed.");
01015 case KSSLCertificate::InvalidHost:
01016 return i18n("The certificate has not been issued for this host.");
01017 case KSSLCertificate::Irrelevant:
01018 return i18n("This certificate is not relevant.");
01019 default:
01020 break;
01021 }
01022
01023 return i18n("The certificate is invalid.");
01024 }
01025
01026
01027 TQByteArray KSSLCertificate::toDer() {
01028 TQByteArray qba;
01029 #ifdef KSSL_HAVE_SSL
01030 unsigned int certlen = d->kossl->i2d_X509(getCert(), NULL);
01031 unsigned char *cert = new unsigned char[certlen];
01032 unsigned char *p = cert;
01033
01034 d->kossl->i2d_X509(getCert(), &p);
01035
01036
01037 qba.duplicate((const char*)cert, certlen);
01038 delete[] cert;
01039 #endif
01040 return qba;
01041 }
01042
01043
01044
01045 TQByteArray KSSLCertificate::toPem() {
01046 TQByteArray qba;
01047 TQString thecert = toString();
01048 const char *header = "-----BEGIN CERTIFICATE-----\n";
01049 const char *footer = "-----END CERTIFICATE-----\n";
01050
01051
01052
01053 unsigned int xx = thecert.length() - 1;
01054 for (unsigned int i = 0; i < xx/64; i++) {
01055 thecert.insert(64*(i+1)+i, '\n');
01056 }
01057
01058 thecert.prepend(header);
01059
01060 if (thecert[thecert.length()-1] != '\n')
01061 thecert += "\n";
01062
01063 thecert.append(footer);
01064
01065 qba.duplicate(thecert.local8Bit(), thecert.length());
01066 return qba;
01067 }
01068
01069
01070 #define NETSCAPE_CERT_HDR "certificate"
01071 #ifdef KSSL_HAVE_SSL
01072 #if OPENSSL_VERSION_NUMBER >= 0x10100000L
01073 typedef struct NETSCAPE_X509_st
01074 {
01075 ASN1_OCTET_STRING *header;
01076 X509 *cert;
01077 } NETSCAPE_X509;
01078 #endif
01079 #endif
01080
01081
01082 TQByteArray KSSLCertificate::toNetscape() {
01083 TQByteArray qba;
01084 #ifdef KSSL_HAVE_SSL
01085 #if OPENSSL_VERSION_NUMBER >= 0x10000000L
01086 NETSCAPE_X509 nx;
01087 ASN1_OCTET_STRING hdr;
01088 #else
01089 ASN1_HEADER ah;
01090 ASN1_OCTET_STRING os;
01091 #endif
01092 KTempFile ktf;
01093
01094 #if OPENSSL_VERSION_NUMBER >= 0x10000000L
01095 hdr.data = (unsigned char *)NETSCAPE_CERT_HDR;
01096 hdr.length = strlen(NETSCAPE_CERT_HDR);
01097 nx.header = &hdr;
01098 nx.cert = getCert();
01099
01100 d->kossl->ASN1_i2d_fp(ktf.fstream(),(unsigned char *)&nx);
01101 #else
01102 os.data = (unsigned char *)NETSCAPE_CERT_HDR;
01103 os.length = strlen(NETSCAPE_CERT_HDR);
01104 ah.header = &os;
01105 ah.data = (char *)getCert();
01106 ah.meth = d->kossl->X509_asn1_meth();
01107
01108 d->kossl->ASN1_i2d_fp(ktf.fstream(),(unsigned char *)&ah);
01109 #endif
01110
01111 ktf.close();
01112
01113 TQFile qf(ktf.name());
01114 qf.open(IO_ReadOnly);
01115 char *buf = new char[qf.size()];
01116 qf.readBlock(buf, qf.size());
01117 qba.duplicate(buf, qf.size());
01118 qf.close();
01119 delete[] buf;
01120
01121 ktf.unlink();
01122
01123 #endif
01124 return qba;
01125 }
01126
01127
01128
01129 TQString KSSLCertificate::toText() {
01130 TQString text;
01131 #ifdef KSSL_HAVE_SSL
01132 KTempFile ktf;
01133
01134 d->kossl->X509_print(ktf.fstream(), getCert());
01135 ktf.close();
01136
01137 TQFile qf(ktf.name());
01138 qf.open(IO_ReadOnly);
01139 char *buf = new char[qf.size()+1];
01140 qf.readBlock(buf, qf.size());
01141 buf[qf.size()] = 0;
01142 text = buf;
01143 delete[] buf;
01144 qf.close();
01145 ktf.unlink();
01146 #endif
01147 return text;
01148 }
01149
01150
01151 bool KSSLCertificate::setCert(TQString& cert) {
01152 #ifdef KSSL_HAVE_SSL
01153 TQByteArray qba, qbb = cert.local8Bit().copy();
01154 KCodecs::base64Decode(qbb, qba);
01155 unsigned char *qbap = reinterpret_cast<unsigned char *>(qba.data());
01156 X509 *x5c = KOSSL::self()->d2i_X509(NULL, &qbap, qba.size());
01157 if (x5c) {
01158 setCert(x5c);
01159 return true;
01160 }
01161 #endif
01162 return false;
01163 }
01164
01165
01166 KSSLX509V3& KSSLCertificate::x509V3Extensions() {
01167 return d->_extensions;
01168 }
01169
01170
01171 bool KSSLCertificate::isSigner() {
01172 return d->_extensions.certTypeCA();
01173 }
01174
01175
01176 TQStringList KSSLCertificate::subjAltNames() const {
01177 TQStringList rc;
01178 #ifdef KSSL_HAVE_SSL
01179 STACK_OF(GENERAL_NAME) *names;
01180 names = (STACK_OF(GENERAL_NAME)*)d->kossl->X509_get_ext_d2i(d->m_cert, NID_subject_alt_name, 0, 0);
01181
01182 if (!names) {
01183 return rc;
01184 }
01185
01186 int cnt = d->kossl->OPENSSL_sk_num(names);
01187
01188 for (int i = 0; i < cnt; i++) {
01189 const GENERAL_NAME *val = (const GENERAL_NAME *)d->kossl->OPENSSL_sk_value(names, i);
01190 if (val->type != GEN_DNS) {
01191 continue;
01192 }
01193
01194 TQString s = (const char *)d->kossl->ASN1_STRING_data(val->d.ia5);
01195 if (!s.isEmpty() &&
01196
01197 s.length() == (unsigned int)d->kossl->ASN1_STRING_length(val->d.ia5)) {
01198 rc += s;
01199 }
01200 }
01201 d->kossl->OPENSSL_sk_free(names);
01202 #endif
01203 return rc;
01204 }
01205
01206
01207 TQDataStream& operator<<(TQDataStream& s, const KSSLCertificate& r) {
01208 TQStringList qsl;
01209 TQPtrList<KSSLCertificate> cl = const_cast<KSSLCertificate&>(r).chain().getChain();
01210
01211 for (KSSLCertificate *c = cl.first(); c != 0; c = cl.next()) {
01212 qsl << c->toString();
01213 }
01214
01215 cl.setAutoDelete(true);
01216
01217 s << const_cast<KSSLCertificate&>(r).toString() << qsl;
01218
01219 return s;
01220 }
01221
01222
01223 TQDataStream& operator>>(TQDataStream& s, KSSLCertificate& r) {
01224 TQStringList qsl;
01225 TQString cert;
01226
01227 s >> cert >> qsl;
01228
01229 if (r.setCert(cert) && !qsl.isEmpty())
01230 r.chain().setCertChain(qsl);
01231
01232 return s;
01233 }
01234
01235
01236