TDE core libraries
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1237 lines
30KB

  1. /* This file is part of the KDE project
  2. *
  3. * Copyright (C) 2000-2003 George Staikos <staikos@kde.org>
  4. *
  5. * This library is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU Library General Public
  7. * License as published by the Free Software Foundation; either
  8. * version 2 of the License, or (at your option) any later version.
  9. *
  10. * This library is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13. * Library General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Library General Public License
  16. * along with this library; see the file COPYING.LIB. If not, write to
  17. * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  18. * Boston, MA 02110-1301, USA.
  19. */
  20. #ifdef HAVE_CONFIG_H
  21. #include <config.h>
  22. #endif
  23. #include <unistd.h>
  24. #include <tqstring.h>
  25. #include <tqstringlist.h>
  26. #include <tqfile.h>
  27. #include "kssldefs.h"
  28. #include "ksslcertificate.h"
  29. #include "ksslcertchain.h"
  30. #include "ksslutils.h"
  31. #include <kstandarddirs.h>
  32. #include <kmdcodec.h>
  33. #include <tdelocale.h>
  34. #include <tqdatetime.h>
  35. #include <tdetempfile.h>
  36. #include <sys/types.h>
  37. #ifdef HAVE_SYS_STAT_H
  38. #include <sys/stat.h>
  39. #endif
  40. // this hack provided by Malte Starostik to avoid glibc/openssl bug
  41. // on some systems
  42. #ifdef KSSL_HAVE_SSL
  43. #define crypt _openssl_crypt
  44. #include <openssl/ssl.h>
  45. #include <openssl/x509.h>
  46. #include <openssl/x509v3.h>
  47. #include <openssl/x509_vfy.h>
  48. #include <openssl/pem.h>
  49. #undef crypt
  50. #endif
  51. #include <kopenssl.h>
  52. #include <tqcstring.h>
  53. #include <kdebug.h>
  54. #include "ksslx509v3.h"
  55. static char hv[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
  56. class KSSLCertificatePrivate {
  57. public:
  58. KSSLCertificatePrivate() {
  59. kossl = KOSSL::self();
  60. _lastPurpose = KSSLCertificate::None;
  61. }
  62. ~KSSLCertificatePrivate() {
  63. }
  64. KSSLCertificate::KSSLValidation m_stateCache;
  65. bool m_stateCached;
  66. #ifdef KSSL_HAVE_SSL
  67. X509 *m_cert;
  68. X509_CRL *m_cert_crl;
  69. #endif
  70. KOSSL *kossl;
  71. KSSLCertChain _chain;
  72. KSSLX509V3 _extensions;
  73. KSSLCertificate::KSSLPurpose _lastPurpose;
  74. };
  75. KSSLCertificate::KSSLCertificate() {
  76. d = new KSSLCertificatePrivate;
  77. d->m_stateCached = false;
  78. TDEGlobal::dirs()->addResourceType("kssl", TDEStandardDirs::kde_default("data") + "kssl");
  79. #ifdef KSSL_HAVE_SSL
  80. d->m_cert = NULL;
  81. d->m_cert_crl = NULL;
  82. #endif
  83. }
  84. KSSLCertificate::KSSLCertificate(const KSSLCertificate& x) {
  85. d = new KSSLCertificatePrivate;
  86. d->m_stateCached = false;
  87. TDEGlobal::dirs()->addResourceType("kssl", TDEStandardDirs::kde_default("data") + "kssl");
  88. #ifdef KSSL_HAVE_SSL
  89. d->m_cert = NULL;
  90. d->m_cert_crl = NULL;
  91. setCert(KOSSL::self()->X509_dup(const_cast<KSSLCertificate&>(x).getCert()));
  92. KSSLCertChain *c = x.d->_chain.replicate();
  93. setChain(c->rawChain());
  94. delete c;
  95. #endif
  96. }
  97. KSSLCertificate::~KSSLCertificate() {
  98. #ifdef KSSL_HAVE_SSL
  99. if (d->m_cert) {
  100. d->kossl->X509_free(d->m_cert);
  101. }
  102. if (d->m_cert_crl) {
  103. d->kossl->X509_CRL_free(d->m_cert_crl);
  104. }
  105. #endif
  106. delete d;
  107. }
  108. KSSLCertChain& KSSLCertificate::chain() {
  109. return d->_chain;
  110. }
  111. KSSLCertificate *KSSLCertificate::fromX509(X509 *x5) {
  112. KSSLCertificate *n = NULL;
  113. #ifdef KSSL_HAVE_SSL
  114. if (x5) {
  115. n = new KSSLCertificate;
  116. n->setCert(KOSSL::self()->X509_dup(x5));
  117. }
  118. #endif
  119. return n;
  120. }
  121. KSSLCertificate *KSSLCertificate::fromString(TQCString cert) {
  122. KSSLCertificate *n = NULL;
  123. #ifdef KSSL_HAVE_SSL
  124. if (cert.length() == 0)
  125. return NULL;
  126. TQByteArray qba, qbb = cert.copy();
  127. KCodecs::base64Decode(qbb, qba);
  128. unsigned char *qbap = reinterpret_cast<unsigned char *>(qba.data());
  129. X509 *x5c = KOSSL::self()->d2i_X509(NULL, &qbap, qba.size());
  130. if (!x5c) {
  131. return NULL;
  132. }
  133. n = new KSSLCertificate;
  134. n->setCert(x5c);
  135. #endif
  136. return n;
  137. }
  138. KSSLCertificate *KSSLCertificate::crlFromString(TQCString cert) {
  139. KSSLCertificate *n = NULL;
  140. #ifdef KSSL_HAVE_SSL
  141. if (cert.length() == 0)
  142. return NULL;
  143. TQByteArray qba, qbb = cert.copy();
  144. KCodecs::base64Decode(qbb, qba);
  145. unsigned char *qbap = reinterpret_cast<unsigned char *>(qba.data());
  146. X509_CRL *x5c = KOSSL::self()->d2i_X509_CRL(NULL, &qbap, qba.size());
  147. if (!x5c) {
  148. return NULL;
  149. }
  150. n = new KSSLCertificate;
  151. n->setCRL(x5c);
  152. #endif
  153. return n;
  154. }
  155. TQString KSSLCertificate::getSubject() const {
  156. TQString rc = "";
  157. #ifdef KSSL_HAVE_SSL
  158. char *t = d->kossl->X509_NAME_oneline(d->kossl->X509_get_subject_name(d->m_cert), 0, 0);
  159. if (!t)
  160. return rc;
  161. rc = t;
  162. d->kossl->CRYPTO_free(t);
  163. #endif
  164. return rc;
  165. }
  166. TQString KSSLCertificate::getSerialNumber() const {
  167. TQString rc = "";
  168. #ifdef KSSL_HAVE_SSL
  169. ASN1_INTEGER *aint = d->kossl->X509_get_serialNumber(d->m_cert);
  170. if (aint) {
  171. rc = ASN1_INTEGER_QString(aint);
  172. // d->kossl->ASN1_INTEGER_free(aint); this makes the sig test fail
  173. }
  174. #endif
  175. return rc;
  176. }
  177. TQString KSSLCertificate::getSignatureText() const {
  178. TQString rc = "";
  179. #ifdef KSSL_HAVE_SSL
  180. char *s;
  181. int n, i;
  182. const ASN1_BIT_STRING *signature = 0L;
  183. const X509_ALGOR *sig_alg = 0L;
  184. d->kossl->X509_get0_signature(&signature, &sig_alg, d->m_cert);
  185. i = d->kossl->OBJ_obj2nid(sig_alg->algorithm);
  186. rc = i18n("Signature Algorithm: ");
  187. rc += (i == NID_undef)?i18n("Unknown"):TQString(d->kossl->OBJ_nid2ln(i));
  188. rc += "\n";
  189. rc += i18n("Signature Contents:");
  190. n = signature->length;
  191. s = (char *)signature->data;
  192. for (i = 0; i < n; i++) {
  193. if (i%20 != 0) rc += ":";
  194. else rc += "\n";
  195. rc.append(hv[(s[i]&0xf0)>>4]);
  196. rc.append(hv[s[i]&0x0f]);
  197. }
  198. #endif
  199. return rc;
  200. }
  201. void KSSLCertificate::getEmails(TQStringList &to) const {
  202. to.clear();
  203. #ifdef KSSL_HAVE_SSL
  204. if (!d->m_cert)
  205. return;
  206. STACK *s = d->kossl->X509_get1_email(d->m_cert);
  207. if (s) {
  208. for(int n=0; n < d->kossl->OPENSSL_sk_num(s); n++) {
  209. to.append(d->kossl->OPENSSL_sk_value(s,n));
  210. }
  211. d->kossl->X509_email_free(s);
  212. }
  213. #endif
  214. }
  215. TQString KSSLCertificate::getKDEKey() const {
  216. return getSubject() + " (" + getMD5DigestText() + ")";
  217. }
  218. TQString KSSLCertificate::getMD5DigestFromKDEKey(const TQString &k) {
  219. TQString rc;
  220. int pos = k.findRev('(');
  221. if (pos != -1) {
  222. unsigned int len = k.length();
  223. if (k.at(len-1) == ')') {
  224. rc = k.mid(pos+1, len-pos-2);
  225. }
  226. }
  227. return rc;
  228. }
  229. TQString KSSLCertificate::getMD5DigestText() const {
  230. TQString rc = "";
  231. #ifdef KSSL_HAVE_SSL
  232. unsigned int n;
  233. unsigned char md[EVP_MAX_MD_SIZE];
  234. if (!d->kossl->X509_digest(d->m_cert, d->kossl->EVP_md5(), md, &n)) {
  235. return rc;
  236. }
  237. for (unsigned int j = 0; j < n; j++) {
  238. if (j > 0)
  239. rc += ":";
  240. rc.append(hv[(md[j]&0xf0)>>4]);
  241. rc.append(hv[md[j]&0x0f]);
  242. }
  243. #endif
  244. return rc;
  245. }
  246. TQString KSSLCertificate::getMD5Digest() const {
  247. TQString rc = "";
  248. #ifdef KSSL_HAVE_SSL
  249. unsigned int n;
  250. unsigned char md[EVP_MAX_MD_SIZE];
  251. if (!d->kossl->X509_digest(d->m_cert, d->kossl->EVP_md5(), md, &n)) {
  252. return rc;
  253. }
  254. for (unsigned int j = 0; j < n; j++) {
  255. rc.append(hv[(md[j]&0xf0)>>4]);
  256. rc.append(hv[md[j]&0x0f]);
  257. }
  258. #endif
  259. return rc;
  260. }
  261. TQString KSSLCertificate::getKeyType() const {
  262. TQString rc = "";
  263. #ifdef KSSL_HAVE_SSL
  264. EVP_PKEY *pkey = d->kossl->X509_get_pubkey(d->m_cert);
  265. if (pkey) {
  266. #ifndef NO_RSA
  267. if (d->kossl->EVP_PKEY_base_id(pkey) == EVP_PKEY_RSA)
  268. rc = "RSA";
  269. else
  270. #endif
  271. #ifndef NO_DSA
  272. if (d->kossl->EVP_PKEY_base_id(pkey) == EVP_PKEY_DSA)
  273. rc = "DSA";
  274. else
  275. #endif
  276. rc = "Unknown";
  277. d->kossl->EVP_PKEY_free(pkey);
  278. }
  279. #endif
  280. return rc;
  281. }
  282. TQString KSSLCertificate::getPublicKeyText() const {
  283. TQString rc = "";
  284. char *x = NULL;
  285. #ifdef KSSL_HAVE_SSL
  286. EVP_PKEY *pkey = d->kossl->X509_get_pubkey(d->m_cert);
  287. if (pkey) {
  288. rc = i18n("Unknown", "Unknown key algorithm");
  289. #ifndef NO_RSA
  290. if (d->kossl->EVP_PKEY_base_id(pkey) == EVP_PKEY_RSA) {
  291. rc = i18n("Key type: RSA (%1 bit)") + "\n";
  292. RSA *pkey_rsa = d->kossl->EVP_PKEY_get0_RSA(pkey);
  293. const BIGNUM *bn_n = 0L;
  294. const BIGNUM *bn_e = 0L;
  295. d->kossl->RSA_get0_key(pkey_rsa, &bn_n, &bn_e, NULL);
  296. x = d->kossl->BN_bn2hex(bn_n);
  297. rc += i18n("Modulus: ");
  298. rc = rc.arg(strlen(x)*4);
  299. for (unsigned int i = 0; i < strlen(x); i++) {
  300. if (i%40 != 0 && i%2 == 0)
  301. rc += ":";
  302. else if (i%40 == 0)
  303. rc += "\n";
  304. rc += x[i];
  305. }
  306. rc += "\n";
  307. d->kossl->CRYPTO_free(x);
  308. x = d->kossl->BN_bn2hex(bn_e);
  309. rc += i18n("Exponent: 0x") + x + "\n";
  310. d->kossl->CRYPTO_free(x);
  311. }
  312. #endif
  313. #ifndef NO_DSA
  314. if (d->kossl->EVP_PKEY_base_id(pkey) == EVP_PKEY_DSA) {
  315. rc = i18n("Key type: DSA (%1 bit)") + "\n";
  316. DSA *pkey_dsa = d->kossl->EVP_PKEY_get0_DSA(pkey);
  317. const BIGNUM *bn_p = 0L;
  318. const BIGNUM *bn_q = 0L;
  319. const BIGNUM *bn_g = 0L;
  320. const BIGNUM *bn_pub_key = 0L;
  321. d->kossl->DSA_get0_pqg(pkey_dsa, &bn_p, &bn_q, &bn_g);
  322. d->kossl->DSA_get0_key(pkey_dsa, &bn_pub_key, NULL);
  323. x = d->kossl->BN_bn2hex(bn_p);
  324. rc += i18n("Prime: ");
  325. // hack - this may not be always accurate
  326. rc = rc.arg(strlen(x)*4) ;
  327. for (unsigned int i = 0; i < strlen(x); i++) {
  328. if (i%40 != 0 && i%2 == 0)
  329. rc += ":";
  330. else if (i%40 == 0)
  331. rc += "\n";
  332. rc += x[i];
  333. }
  334. rc += "\n";
  335. d->kossl->CRYPTO_free(x);
  336. x = d->kossl->BN_bn2hex(bn_q);
  337. rc += i18n("160 bit prime factor: ");
  338. for (unsigned int i = 0; i < strlen(x); i++) {
  339. if (i%40 != 0 && i%2 == 0)
  340. rc += ":";
  341. else if (i%40 == 0)
  342. rc += "\n";
  343. rc += x[i];
  344. }
  345. rc += "\n";
  346. d->kossl->CRYPTO_free(x);
  347. x = d->kossl->BN_bn2hex(bn_g);
  348. rc += TQString("g: ");
  349. for (unsigned int i = 0; i < strlen(x); i++) {
  350. if (i%40 != 0 && i%2 == 0)
  351. rc += ":";
  352. else if (i%40 == 0)
  353. rc += "\n";
  354. rc += x[i];
  355. }
  356. rc += "\n";
  357. d->kossl->CRYPTO_free(x);
  358. x = d->kossl->BN_bn2hex(bn_pub_key);
  359. rc += i18n("Public key: ");
  360. for (unsigned int i = 0; i < strlen(x); i++) {
  361. if (i%40 != 0 && i%2 == 0)
  362. rc += ":";
  363. else if (i%40 == 0)
  364. rc += "\n";
  365. rc += x[i];
  366. }
  367. rc += "\n";
  368. d->kossl->CRYPTO_free(x);
  369. }
  370. #endif
  371. d->kossl->EVP_PKEY_free(pkey);
  372. }
  373. #endif
  374. return rc;
  375. }
  376. TQString KSSLCertificate::getIssuer() const {
  377. TQString rc = "";
  378. #ifdef KSSL_HAVE_SSL
  379. char *t = d->kossl->X509_NAME_oneline(d->kossl->X509_get_issuer_name(d->m_cert), 0, 0);
  380. if (!t)
  381. return rc;
  382. rc = t;
  383. d->kossl->CRYPTO_free(t);
  384. #endif
  385. return rc;
  386. }
  387. void KSSLCertificate::setChain(void *c) {
  388. #ifdef KSSL_HAVE_SSL
  389. d->_chain.setChain(c);
  390. #endif
  391. d->m_stateCached = false;
  392. d->m_stateCache = KSSLCertificate::Unknown;
  393. }
  394. void KSSLCertificate::setCert(X509 *c) {
  395. #ifdef KSSL_HAVE_SSL
  396. d->m_cert = c;
  397. if (c) {
  398. d->_extensions.flags = 0;
  399. d->kossl->X509_check_purpose(c, -1, 0); // setup the fields (!!)
  400. #if 0
  401. kdDebug(7029) << "---------------- Certificate ------------------"
  402. << endl;
  403. kdDebug(7029) << getSubject() << endl;
  404. #endif
  405. for (int j = 0; j < d->kossl->X509_PURPOSE_get_count(); j++) {
  406. X509_PURPOSE *ptmp = d->kossl->X509_PURPOSE_get0(j);
  407. int id = d->kossl->X509_PURPOSE_get_id(ptmp);
  408. for (int ca = 0; ca < 2; ca++) {
  409. int idret = d->kossl->X509_check_purpose(c, id, ca);
  410. if (idret == 1 || idret == 2) { // have it
  411. // kdDebug() << "PURPOSE: " << id << (ca?" CA":"") << endl;
  412. if (!ca)
  413. d->_extensions.flags |= (1L <<(id-1));
  414. else d->_extensions.flags |= (1L <<(16+id-1));
  415. } else {
  416. if (!ca)
  417. d->_extensions.flags &= ~(1L <<(id-1));
  418. else d->_extensions.flags &= ~(1L <<(16+id-1));
  419. }
  420. }
  421. }
  422. #if 0
  423. kdDebug(7029) << "flags: " << TQString::number(c->ex_flags, 2)
  424. << "\nkeyusage: " << TQString::number(c->ex_kusage, 2)
  425. << "\nxkeyusage: " << TQString::number(c->ex_xkusage, 2)
  426. << "\nnscert: " << TQString::number(c->ex_nscert, 2)
  427. << endl;
  428. if (c->ex_flags & EXFLAG_KUSAGE)
  429. kdDebug(7029) << " --- Key Usage extensions found" << endl;
  430. else kdDebug(7029) << " --- Key Usage extensions NOT found" << endl;
  431. if (c->ex_flags & EXFLAG_XKUSAGE)
  432. kdDebug(7029) << " --- Extended key usage extensions found" << endl;
  433. else kdDebug(7029) << " --- Extended key usage extensions NOT found" << endl;
  434. if (c->ex_flags & EXFLAG_NSCERT)
  435. kdDebug(7029) << " --- NS extensions found" << endl;
  436. else kdDebug(7029) << " --- NS extensions NOT found" << endl;
  437. if (d->_extensions.certTypeSSLCA())
  438. kdDebug(7029) << "NOTE: this is an SSL CA file." << endl;
  439. else kdDebug(7029) << "NOTE: this is NOT an SSL CA file." << endl;
  440. if (d->_extensions.certTypeEmailCA())
  441. kdDebug(7029) << "NOTE: this is an EMAIL CA file." << endl;
  442. else kdDebug(7029) << "NOTE: this is NOT an EMAIL CA file." << endl;
  443. if (d->_extensions.certTypeCodeCA())
  444. kdDebug(7029) << "NOTE: this is a CODE CA file." << endl;
  445. else kdDebug(7029) << "NOTE: this is NOT a CODE CA file." << endl;
  446. if (d->_extensions.certTypeSSLClient())
  447. kdDebug(7029) << "NOTE: this is an SSL client." << endl;
  448. else kdDebug(7029) << "NOTE: this is NOT an SSL client." << endl;
  449. if (d->_extensions.certTypeSSLServer())
  450. kdDebug(7029) << "NOTE: this is an SSL server." << endl;
  451. else kdDebug(7029) << "NOTE: this is NOT an SSL server." << endl;
  452. if (d->_extensions.certTypeNSSSLServer())
  453. kdDebug(7029) << "NOTE: this is a NETSCAPE SSL server." << endl;
  454. else kdDebug(7029) << "NOTE: this is NOT a NETSCAPE SSL server." << endl;
  455. if (d->_extensions.certTypeSMIME())
  456. kdDebug(7029) << "NOTE: this is an SMIME certificate." << endl;
  457. else kdDebug(7029) << "NOTE: this is NOT an SMIME certificate." << endl;
  458. if (d->_extensions.certTypeSMIMEEncrypt())
  459. kdDebug(7029) << "NOTE: this is an SMIME encrypt cert." << endl;
  460. else kdDebug(7029) << "NOTE: this is NOT an SMIME encrypt cert." << endl;
  461. if (d->_extensions.certTypeSMIMESign())
  462. kdDebug(7029) << "NOTE: this is an SMIME sign cert." << endl;
  463. else kdDebug(7029) << "NOTE: this is NOT an SMIME sign cert." << endl;
  464. if (d->_extensions.certTypeCRLSign())
  465. kdDebug(7029) << "NOTE: this is a CRL signer." << endl;
  466. else kdDebug(7029) << "NOTE: this is NOT a CRL signer." << endl;
  467. kdDebug(7029) << "-----------------------------------------------"
  468. << endl;
  469. #endif
  470. }
  471. #endif
  472. d->m_stateCached = false;
  473. d->m_stateCache = KSSLCertificate::Unknown;
  474. }
  475. void KSSLCertificate::setCRL(X509_CRL *c) {
  476. #ifdef KSSL_HAVE_SSL
  477. d->m_cert_crl = c;
  478. if (c) {
  479. d->_extensions.flags = 0;
  480. }
  481. #endif
  482. d->m_stateCached = false;
  483. d->m_stateCache = KSSLCertificate::Unknown;
  484. }
  485. X509 *KSSLCertificate::getCert() {
  486. #ifdef KSSL_HAVE_SSL
  487. return d->m_cert;
  488. #endif
  489. return 0;
  490. }
  491. // pull in the callback. It's common across multiple files but we want
  492. // it to be hidden.
  493. #include "ksslcallback.c"
  494. bool KSSLCertificate::isValid(KSSLCertificate::KSSLPurpose p) {
  495. return (validate(p) == KSSLCertificate::Ok);
  496. }
  497. bool KSSLCertificate::isValid() {
  498. return isValid(KSSLCertificate::SSLServer);
  499. }
  500. int KSSLCertificate::purposeToOpenSSL(KSSLCertificate::KSSLPurpose p) const {
  501. int rc = 0;
  502. #ifdef KSSL_HAVE_SSL
  503. if (p == KSSLCertificate::SSLServer) {
  504. rc = X509_PURPOSE_SSL_SERVER;
  505. } else if (p == KSSLCertificate::SSLClient) {
  506. rc = X509_PURPOSE_SSL_CLIENT;
  507. } else if (p == KSSLCertificate::SMIMEEncrypt) {
  508. rc = X509_PURPOSE_SMIME_ENCRYPT;
  509. } else if (p == KSSLCertificate::SMIMESign) {
  510. rc = X509_PURPOSE_SMIME_SIGN;
  511. } else if (p == KSSLCertificate::Any) {
  512. rc = X509_PURPOSE_ANY;
  513. }
  514. #endif
  515. return rc;
  516. }
  517. // For backward compatibility
  518. KSSLCertificate::KSSLValidation KSSLCertificate::validate() {
  519. return validate(KSSLCertificate::SSLServer);
  520. }
  521. KSSLCertificate::KSSLValidation KSSLCertificate::validate(KSSLCertificate::KSSLPurpose purpose)
  522. {
  523. KSSLValidationList result = validateVerbose(purpose);
  524. if (result.isEmpty())
  525. return KSSLCertificate::Ok;
  526. else
  527. return result.first();
  528. }
  529. //
  530. // See apps/verify.c in OpenSSL for the source of most of this logic.
  531. //
  532. // CRL files? we don't do that yet
  533. KSSLCertificate::KSSLValidationList KSSLCertificate::validateVerbose(KSSLCertificate::KSSLPurpose purpose)
  534. {
  535. return validateVerbose(purpose, 0);
  536. }
  537. KSSLCertificate::KSSLValidationList KSSLCertificate::validateVerbose(KSSLCertificate::KSSLPurpose purpose, KSSLCertificate *ca)
  538. {
  539. KSSLValidationList errors;
  540. if (ca || (d->_lastPurpose != purpose)) {
  541. d->m_stateCached = false;
  542. }
  543. if (!d->m_stateCached)
  544. d->_lastPurpose = purpose;
  545. #ifdef KSSL_HAVE_SSL
  546. X509_STORE *certStore;
  547. X509_LOOKUP *certLookup;
  548. X509_STORE_CTX *certStoreCTX;
  549. if (!d->m_cert)
  550. {
  551. errors << KSSLCertificate::Unknown;
  552. return errors;
  553. }
  554. if (d->m_stateCached) {
  555. errors << d->m_stateCache;
  556. return errors;
  557. }
  558. TQStringList qsl = TDEGlobal::dirs()->resourceDirs("kssl");
  559. if (qsl.isEmpty()) {
  560. errors << KSSLCertificate::NoCARoot;
  561. return errors;
  562. }
  563. KSSLCertificate::KSSLValidation ksslv = Unknown;
  564. for (TQStringList::Iterator j = qsl.begin(); j != qsl.end(); ++j) {
  565. struct stat sb;
  566. TQString _j = (*j) + "ca-bundle.crt";
  567. if (-1 == stat(_j.ascii(), &sb)) {
  568. continue;
  569. }
  570. certStore = d->kossl->X509_STORE_new();
  571. if (!certStore) {
  572. errors << KSSLCertificate::Unknown;
  573. return errors;
  574. }
  575. d->kossl->X509_STORE_set_verify_cb(certStore, X509Callback);
  576. certLookup = d->kossl->X509_STORE_add_lookup(certStore, d->kossl->X509_LOOKUP_file());
  577. if (!certLookup) {
  578. ksslv = KSSLCertificate::Unknown;
  579. d->kossl->X509_STORE_free(certStore);
  580. continue;
  581. }
  582. if (!d->kossl->X509_LOOKUP_load_file(certLookup, _j.ascii(), X509_FILETYPE_PEM)) {
  583. // error accessing directory and loading pems
  584. kdDebug(7029) << "KSSL couldn't read CA root: "
  585. << _j << endl;
  586. ksslv = KSSLCertificate::ErrorReadingRoot;
  587. d->kossl->X509_STORE_free(certStore);
  588. continue;
  589. }
  590. // This is the checking code
  591. certStoreCTX = d->kossl->X509_STORE_CTX_new();
  592. // this is a bad error - could mean no free memory.
  593. // This may be the wrong thing to do here
  594. if (!certStoreCTX) {
  595. kdDebug(7029) << "KSSL couldn't create an X509 store context." << endl;
  596. d->kossl->X509_STORE_free(certStore);
  597. continue;
  598. }
  599. d->kossl->X509_STORE_CTX_init(certStoreCTX, certStore, d->m_cert, NULL);
  600. if (d->_chain.isValid()) {
  601. d->kossl->X509_STORE_CTX_set0_untrusted(certStoreCTX, (STACK_OF(X509)*)d->_chain.rawChain());
  602. }
  603. //kdDebug(7029) << "KSSL setting CRL.............." << endl;
  604. // int X509_STORE_add_crl(X509_STORE *ctx, X509_CRL *x);
  605. d->kossl->X509_STORE_CTX_set_purpose(certStoreCTX, purposeToOpenSSL(purpose));
  606. KSSL_X509CallBack_ca = ca ? ca->d->m_cert : 0;
  607. KSSL_X509CallBack_ca_found = false;
  608. d->kossl->X509_STORE_CTX_set_error(certStoreCTX, X509_V_OK);
  609. d->kossl->X509_verify_cert(certStoreCTX);
  610. int errcode = d->kossl->X509_STORE_CTX_get_error(certStoreCTX);
  611. if (ca && !KSSL_X509CallBack_ca_found) {
  612. ksslv = KSSLCertificate::Irrelevant;
  613. } else {
  614. ksslv = processError(errcode);
  615. }
  616. // For servers, we can try NS_SSL_SERVER too
  617. if ( (ksslv != KSSLCertificate::Ok) &&
  618. (ksslv != KSSLCertificate::Irrelevant) &&
  619. purpose == KSSLCertificate::SSLServer) {
  620. d->kossl->X509_STORE_CTX_set_purpose(certStoreCTX,
  621. X509_PURPOSE_NS_SSL_SERVER);
  622. d->kossl->X509_STORE_CTX_set_error(certStoreCTX, X509_V_OK);
  623. d->kossl->X509_verify_cert(certStoreCTX);
  624. errcode = d->kossl->X509_STORE_CTX_get_error(certStoreCTX);
  625. ksslv = processError(errcode);
  626. }
  627. d->kossl->X509_STORE_CTX_free(certStoreCTX);
  628. d->kossl->X509_STORE_free(certStore);
  629. // end of checking code
  630. //
  631. //kdDebug(7029) << "KSSL Validation procedure RC: "
  632. // << rc << endl;
  633. //kdDebug(7029) << "KSSL Validation procedure errcode: "
  634. // << errcode << endl;
  635. //kdDebug(7029) << "KSSL Validation procedure RESULTS: "
  636. // << ksslv << endl;
  637. if (ksslv != NoCARoot && ksslv != InvalidCA) {
  638. d->m_stateCached = true;
  639. d->m_stateCache = ksslv;
  640. }
  641. break;
  642. }
  643. if (ksslv != KSSLCertificate::Ok)
  644. errors << ksslv;
  645. #else
  646. errors << KSSLCertificate::NoSSL;
  647. #endif
  648. return errors;
  649. }
  650. KSSLCertificate::KSSLValidation KSSLCertificate::revalidate() {
  651. return revalidate(KSSLCertificate::SSLServer);
  652. }
  653. KSSLCertificate::KSSLValidation KSSLCertificate::revalidate(KSSLCertificate::KSSLPurpose p) {
  654. d->m_stateCached = false;
  655. return validate(p);
  656. }
  657. KSSLCertificate::KSSLValidation KSSLCertificate::processError(int ec) {
  658. KSSLCertificate::KSSLValidation rc;
  659. rc = KSSLCertificate::Unknown;
  660. #ifdef KSSL_HAVE_SSL
  661. switch (ec) {
  662. case X509_V_OK: // OK
  663. rc = KSSLCertificate::Ok;
  664. break;
  665. case X509_V_ERR_CERT_REJECTED:
  666. rc = KSSLCertificate::Rejected;
  667. break;
  668. case X509_V_ERR_CERT_UNTRUSTED:
  669. rc = KSSLCertificate::Untrusted;
  670. break;
  671. case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
  672. case X509_V_ERR_CERT_SIGNATURE_FAILURE:
  673. case X509_V_ERR_CRL_SIGNATURE_FAILURE:
  674. case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE:
  675. case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE:
  676. rc = KSSLCertificate::SignatureFailed;
  677. break;
  678. case X509_V_ERR_INVALID_CA:
  679. case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
  680. case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY:
  681. case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
  682. rc = KSSLCertificate::InvalidCA;
  683. break;
  684. case X509_V_ERR_INVALID_PURPOSE:
  685. rc = KSSLCertificate::InvalidPurpose;
  686. break;
  687. case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
  688. rc = KSSLCertificate::SelfSigned;
  689. break;
  690. case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
  691. rc = KSSLCertificate::SelfSignedChain;
  692. break;
  693. case X509_V_ERR_CERT_REVOKED:
  694. rc = KSSLCertificate::Revoked;
  695. break;
  696. case X509_V_ERR_PATH_LENGTH_EXCEEDED:
  697. rc = KSSLCertificate::PathLengthExceeded;
  698. break;
  699. case X509_V_ERR_CERT_NOT_YET_VALID:
  700. case X509_V_ERR_CERT_HAS_EXPIRED:
  701. case X509_V_ERR_CRL_NOT_YET_VALID:
  702. case X509_V_ERR_CRL_HAS_EXPIRED:
  703. case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
  704. case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
  705. case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD:
  706. case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD:
  707. rc = KSSLCertificate::Expired;
  708. kdDebug(7029) << "KSSL apparently this is expired. Not after: "
  709. << getNotAfter() << endl;
  710. break;
  711. //case 1:
  712. case X509_V_ERR_APPLICATION_VERIFICATION:
  713. case X509_V_ERR_OUT_OF_MEM:
  714. case X509_V_ERR_UNABLE_TO_GET_CRL:
  715. case X509_V_ERR_CERT_CHAIN_TOO_LONG:
  716. default:
  717. rc = KSSLCertificate::Unknown;
  718. break;
  719. }
  720. d->m_stateCache = rc;
  721. d->m_stateCached = true;
  722. #endif
  723. return rc;
  724. }
  725. TQString KSSLCertificate::getNotBefore() const {
  726. #ifdef KSSL_HAVE_SSL
  727. return ASN1_UTCTIME_QString(d->kossl->X509_getm_notBefore(d->m_cert));
  728. #else
  729. return TQString::null;
  730. #endif
  731. }
  732. TQString KSSLCertificate::getNotAfter() const {
  733. #ifdef KSSL_HAVE_SSL
  734. return ASN1_UTCTIME_QString(d->kossl->X509_getm_notAfter(d->m_cert));
  735. #else
  736. return TQString::null;
  737. #endif
  738. }
  739. TQDateTime KSSLCertificate::getQDTNotBefore() const {
  740. #ifdef KSSL_HAVE_SSL
  741. return ASN1_UTCTIME_QDateTime(d->kossl->X509_getm_notBefore(d->m_cert), NULL);
  742. #else
  743. return TQDateTime::currentDateTime();
  744. #endif
  745. }
  746. TQDateTime KSSLCertificate::getQDTNotAfter() const {
  747. #ifdef KSSL_HAVE_SSL
  748. return ASN1_UTCTIME_QDateTime(d->kossl->X509_getm_notAfter(d->m_cert), NULL);
  749. #else
  750. return TQDateTime::currentDateTime();
  751. #endif
  752. }
  753. TQDateTime KSSLCertificate::getQDTLastUpdate() const {
  754. #ifdef KSSL_HAVE_SSL
  755. return ASN1_UTCTIME_QDateTime((ASN1_UTCTIME*)d->kossl->X509_CRL_get0_lastUpdate(d->m_cert_crl), NULL);
  756. #else
  757. return TQDateTime::currentDateTime();
  758. #endif
  759. }
  760. TQDateTime KSSLCertificate::getQDTNextUpdate() const {
  761. #ifdef KSSL_HAVE_SSL
  762. return ASN1_UTCTIME_QDateTime((ASN1_UTCTIME*)d->kossl->X509_CRL_get0_nextUpdate(d->m_cert_crl), NULL);
  763. #else
  764. return TQDateTime::currentDateTime();
  765. #endif
  766. }
  767. int operator==(KSSLCertificate &x, KSSLCertificate &y) {
  768. #ifndef KSSL_HAVE_SSL
  769. return 1;
  770. #else
  771. if (!KOSSL::self()->X509_cmp(x.getCert(), y.getCert())) return 1;
  772. return 0;
  773. #endif
  774. }
  775. KSSLCertificate *KSSLCertificate::replicate() {
  776. // The new certificate doesn't have the cached value. It's probably
  777. // better this way. We can't anticipate every reason for doing this.
  778. KSSLCertificate *newOne = new KSSLCertificate();
  779. #ifdef KSSL_HAVE_SSL
  780. newOne->setCert(d->kossl->X509_dup(getCert()));
  781. KSSLCertChain *c = d->_chain.replicate();
  782. newOne->setChain(c->rawChain());
  783. delete c;
  784. #endif
  785. return newOne;
  786. }
  787. TQString KSSLCertificate::toString() {
  788. return KCodecs::base64Encode(toDer());
  789. }
  790. TQString KSSLCertificate::verifyText(KSSLValidation x) {
  791. switch (x) {
  792. case KSSLCertificate::Ok:
  793. return i18n("The certificate is valid.");
  794. case KSSLCertificate::PathLengthExceeded:
  795. case KSSLCertificate::ErrorReadingRoot:
  796. case KSSLCertificate::NoCARoot:
  797. return i18n("Certificate signing authority root files could not be found so the certificate is not verified.");
  798. case KSSLCertificate::SelfSignedChain:
  799. case KSSLCertificate::InvalidCA:
  800. return i18n("Certificate signing authority is unknown or invalid.");
  801. case KSSLCertificate::SelfSigned:
  802. return i18n("Certificate is self-signed and thus may not be trustworthy.");
  803. case KSSLCertificate::Expired:
  804. return i18n("Certificate has expired.");
  805. case KSSLCertificate::Revoked:
  806. return i18n("Certificate has been revoked.");
  807. case KSSLCertificate::NoSSL:
  808. return i18n("SSL support was not found.");
  809. case KSSLCertificate::Untrusted:
  810. return i18n("Signature is untrusted.");
  811. case KSSLCertificate::SignatureFailed:
  812. return i18n("Signature test failed.");
  813. case KSSLCertificate::Rejected:
  814. case KSSLCertificate::InvalidPurpose:
  815. return i18n("Rejected, possibly due to an invalid purpose.");
  816. case KSSLCertificate::PrivateKeyFailed:
  817. return i18n("Private key test failed.");
  818. case KSSLCertificate::InvalidHost:
  819. return i18n("The certificate has not been issued for this host.");
  820. case KSSLCertificate::Irrelevant:
  821. return i18n("This certificate is not relevant.");
  822. default:
  823. break;
  824. }
  825. return i18n("The certificate is invalid.");
  826. }
  827. TQByteArray KSSLCertificate::toDer() {
  828. TQByteArray qba;
  829. #ifdef KSSL_HAVE_SSL
  830. unsigned int certlen = d->kossl->i2d_X509(getCert(), NULL);
  831. unsigned char *cert = new unsigned char[certlen];
  832. unsigned char *p = cert;
  833. // FIXME: return code!
  834. d->kossl->i2d_X509(getCert(), &p);
  835. // encode it into a QString
  836. qba.duplicate((const char*)cert, certlen);
  837. delete[] cert;
  838. #endif
  839. return qba;
  840. }
  841. TQByteArray KSSLCertificate::toPem() {
  842. TQByteArray qba;
  843. TQString thecert = toString();
  844. const char *header = "-----BEGIN CERTIFICATE-----\n";
  845. const char *footer = "-----END CERTIFICATE-----\n";
  846. // We just do base64 on the ASN1
  847. // 64 character lines (unpadded)
  848. unsigned int xx = thecert.length() - 1;
  849. for (unsigned int i = 0; i < xx/64; i++) {
  850. thecert.insert(64*(i+1)+i, '\n');
  851. }
  852. thecert.prepend(header);
  853. if (thecert[thecert.length()-1] != '\n')
  854. thecert += "\n";
  855. thecert.append(footer);
  856. qba.duplicate(thecert.local8Bit(), thecert.length());
  857. return qba;
  858. }
  859. #define NETSCAPE_CERT_HDR "certificate"
  860. #ifdef KSSL_HAVE_SSL
  861. #if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
  862. typedef struct NETSCAPE_X509_st
  863. {
  864. ASN1_OCTET_STRING *header;
  865. X509 *cert;
  866. } NETSCAPE_X509;
  867. #endif
  868. #endif
  869. // what a piece of crap this is
  870. TQByteArray KSSLCertificate::toNetscape() {
  871. TQByteArray qba;
  872. #ifdef KSSL_HAVE_SSL
  873. #if OPENSSL_VERSION_NUMBER >= 0x10000000L
  874. NETSCAPE_X509 nx;
  875. ASN1_OCTET_STRING hdr;
  876. #else
  877. ASN1_HEADER ah;
  878. ASN1_OCTET_STRING os;
  879. #endif
  880. KTempFile ktf;
  881. #if OPENSSL_VERSION_NUMBER >= 0x10000000L
  882. hdr.data = (unsigned char *)NETSCAPE_CERT_HDR;
  883. hdr.length = strlen(NETSCAPE_CERT_HDR);
  884. nx.header = &hdr;
  885. nx.cert = getCert();
  886. d->kossl->ASN1_i2d_fp(ktf.fstream(),(unsigned char *)&nx);
  887. #else
  888. os.data = (unsigned char *)NETSCAPE_CERT_HDR;
  889. os.length = strlen(NETSCAPE_CERT_HDR);
  890. ah.header = &os;
  891. ah.data = (char *)getCert();
  892. ah.meth = d->kossl->X509_asn1_meth();
  893. d->kossl->ASN1_i2d_fp(ktf.fstream(),(unsigned char *)&ah);
  894. #endif
  895. ktf.close();
  896. TQFile qf(ktf.name());
  897. qf.open(IO_ReadOnly);
  898. char *buf = new char[qf.size()];
  899. qf.readBlock(buf, qf.size());
  900. qba.duplicate(buf, qf.size());
  901. qf.close();
  902. delete[] buf;
  903. ktf.unlink();
  904. #endif
  905. return qba;
  906. }
  907. TQString KSSLCertificate::toText() {
  908. TQString text;
  909. #ifdef KSSL_HAVE_SSL
  910. KTempFile ktf;
  911. d->kossl->X509_print(ktf.fstream(), getCert());
  912. ktf.close();
  913. TQFile qf(ktf.name());
  914. qf.open(IO_ReadOnly);
  915. char *buf = new char[qf.size()+1];
  916. qf.readBlock(buf, qf.size());
  917. buf[qf.size()] = 0;
  918. text = buf;
  919. delete[] buf;
  920. qf.close();
  921. ktf.unlink();
  922. #endif
  923. return text;
  924. }
  925. // KDE 4: Make it const TQString &
  926. bool KSSLCertificate::setCert(TQString& cert) {
  927. #ifdef KSSL_HAVE_SSL
  928. TQByteArray qba, qbb = cert.local8Bit().copy();
  929. KCodecs::base64Decode(qbb, qba);
  930. unsigned char *qbap = reinterpret_cast<unsigned char *>(qba.data());
  931. X509 *x5c = KOSSL::self()->d2i_X509(NULL, &qbap, qba.size());
  932. if (x5c) {
  933. setCert(x5c);
  934. return true;
  935. }
  936. #endif
  937. return false;
  938. }
  939. KSSLX509V3& KSSLCertificate::x509V3Extensions() {
  940. return d->_extensions;
  941. }
  942. bool KSSLCertificate::isSigner() {
  943. return d->_extensions.certTypeCA();
  944. }
  945. TQStringList KSSLCertificate::subjAltNames() const {
  946. TQStringList rc;
  947. #ifdef KSSL_HAVE_SSL
  948. STACK_OF(GENERAL_NAME) *names;
  949. names = (STACK_OF(GENERAL_NAME)*)d->kossl->X509_get_ext_d2i(d->m_cert, NID_subject_alt_name, 0, 0);
  950. if (!names) {
  951. return rc;
  952. }
  953. int cnt = d->kossl->OPENSSL_sk_num(names);
  954. for (int i = 0; i < cnt; i++) {
  955. const GENERAL_NAME *val = (const GENERAL_NAME *)d->kossl->OPENSSL_sk_value(names, i);
  956. if (val->type != GEN_DNS) {
  957. continue;
  958. }
  959. TQString s = (const char *)d->kossl->ASN1_STRING_data(val->d.ia5);
  960. if (!s.isEmpty() &&
  961. /* skip subjectAltNames with embedded NULs */
  962. s.length() == (unsigned int)d->kossl->ASN1_STRING_length(val->d.ia5)) {
  963. rc += s;
  964. }
  965. }
  966. d->kossl->OPENSSL_sk_free(names);
  967. #endif
  968. return rc;
  969. }
  970. TQDataStream& operator<<(TQDataStream& s, const KSSLCertificate& r) {
  971. TQStringList qsl;
  972. TQPtrList<KSSLCertificate> cl = const_cast<KSSLCertificate&>(r).chain().getChain();
  973. for (KSSLCertificate *c = cl.first(); c != 0; c = cl.next()) {
  974. qsl << c->toString();
  975. }
  976. cl.setAutoDelete(true);
  977. s << const_cast<KSSLCertificate&>(r).toString() << qsl;
  978. return s;
  979. }
  980. TQDataStream& operator>>(TQDataStream& s, KSSLCertificate& r) {
  981. TQStringList qsl;
  982. TQString cert;
  983. s >> cert >> qsl;
  984. if (r.setCert(cert) && !qsl.isEmpty())
  985. r.chain().setCertChain(qsl);
  986. return s;
  987. }