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.

275 lines
5.8KB

  1. /* This file is part of the KDE project
  2. *
  3. * Copyright (C) 2001 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 <kopenssl.h>
  24. #include <tqstring.h>
  25. #include <tqfile.h>
  26. #include <ksslall.h>
  27. #include <kdebug.h>
  28. #include <tdetempfile.h>
  29. #include <kmdcodec.h>
  30. #include <assert.h>
  31. KSSLPKCS12::KSSLPKCS12() {
  32. _pkcs = NULL;
  33. _pkey = NULL;
  34. _cert = NULL;
  35. _caStack = NULL;
  36. kossl = KOSSL::self();
  37. }
  38. KSSLPKCS12::~KSSLPKCS12() {
  39. #ifdef KSSL_HAVE_SSL
  40. if (_pkey) kossl->EVP_PKEY_free(_pkey);
  41. if (_caStack) {
  42. for (;;) {
  43. X509* x5 = reinterpret_cast<X509*>(kossl->OPENSSL_sk_pop(_caStack));
  44. if (!x5) break;
  45. kossl->X509_free(x5);
  46. }
  47. kossl->OPENSSL_sk_free(_caStack);
  48. }
  49. if (_pkcs) kossl->PKCS12_free(_pkcs);
  50. #endif
  51. if (_cert) delete _cert;
  52. }
  53. KSSLPKCS12* KSSLPKCS12::fromString(TQString base64, TQString password) {
  54. #ifdef KSSL_HAVE_SSL
  55. KTempFile ktf;
  56. if (base64.isEmpty()) return NULL;
  57. TQByteArray qba, qbb = TQCString(base64.latin1()).copy();
  58. KCodecs::base64Decode(qbb, qba);
  59. ktf.file()->writeBlock(qba);
  60. ktf.close();
  61. KSSLPKCS12* rc = loadCertFile(ktf.name(), password);
  62. ktf.unlink();
  63. return rc;
  64. #endif
  65. return NULL;
  66. }
  67. KSSLPKCS12* KSSLPKCS12::loadCertFile(TQString filename, TQString password) {
  68. #ifdef KSSL_HAVE_SSL
  69. TQFile qf(filename);
  70. PKCS12 *newpkcs = NULL;
  71. if (!qf.open(IO_ReadOnly))
  72. return NULL;
  73. FILE *fp = fdopen(qf.handle(), "r");
  74. if (!fp) return NULL;
  75. newpkcs = KOSSL::self()->d2i_PKCS12_fp(fp, &newpkcs);
  76. fclose(fp);
  77. if (!newpkcs) {
  78. KOSSL::self()->ERR_clear_error();
  79. return NULL;
  80. }
  81. KSSLPKCS12 *c = new KSSLPKCS12;
  82. c->setCert(newpkcs);
  83. // Now we parse it to see if we can decrypt it and interpret it
  84. if (!c->parse(password)) {
  85. delete c; c = NULL;
  86. }
  87. return c;
  88. #endif
  89. return NULL;
  90. }
  91. void KSSLPKCS12::setCert(PKCS12 *c) {
  92. #ifdef KSSL_HAVE_SSL
  93. _pkcs = c;
  94. #endif
  95. }
  96. bool KSSLPKCS12::changePassword(TQString pold, TQString pnew) {
  97. #ifdef KSSL_HAVE_SSL
  98. // OpenSSL makes me cast away the const here. argh
  99. return (0 == kossl->PKCS12_newpass(_pkcs,
  100. pold.isNull() ? (char *)"" : (char *)pold.latin1(),
  101. pnew.isNull() ? (char *)"" : (char *)pnew.latin1()));
  102. #endif
  103. return false;
  104. }
  105. bool KSSLPKCS12::parse(TQString pass) {
  106. #ifdef KSSL_HAVE_SSL
  107. X509 *x = NULL;
  108. assert(_pkcs); // if you're calling this before pkcs gets set, it's a BUG!
  109. if (_cert) delete _cert;
  110. if (_pkey) kossl->EVP_PKEY_free(_pkey);
  111. if (_caStack) {
  112. for (;;) {
  113. X509* x5 = reinterpret_cast<X509*>(kossl->OPENSSL_sk_pop(_caStack));
  114. if (!x5) break;
  115. kossl->X509_free(x5);
  116. }
  117. kossl->OPENSSL_sk_free(_caStack);
  118. }
  119. _pkey = NULL;
  120. _caStack = NULL;
  121. _cert = NULL;
  122. int rc = kossl->PKCS12_parse(_pkcs, pass.latin1(), &_pkey, &x, &_caStack);
  123. if (rc == 1) {
  124. // kdDebug(7029) << "PKCS12_parse success" << endl;
  125. if (x) {
  126. _cert = new KSSLCertificate;
  127. _cert->setCert(x);
  128. if (_caStack) {
  129. _cert->setChain(_caStack);
  130. }
  131. return true;
  132. }
  133. } else {
  134. _caStack = NULL;
  135. _pkey = NULL;
  136. kossl->ERR_clear_error();
  137. }
  138. #endif
  139. return false;
  140. }
  141. EVP_PKEY *KSSLPKCS12::getPrivateKey() {
  142. return _pkey;
  143. }
  144. KSSLCertificate *KSSLPKCS12::getCertificate() {
  145. return _cert;
  146. }
  147. TQString KSSLPKCS12::toString() {
  148. TQString base64;
  149. #ifdef KSSL_HAVE_SSL
  150. unsigned char *p;
  151. int len;
  152. len = kossl->i2d_PKCS12(_pkcs, NULL);
  153. if (len >= 0) {
  154. char *buf = new char[len];
  155. p = (unsigned char *)buf;
  156. kossl->i2d_PKCS12(_pkcs, &p);
  157. TQByteArray qba;
  158. qba.setRawData(buf, len);
  159. base64 = KCodecs::base64Encode(qba);
  160. qba.resetRawData(buf, len);
  161. delete[] buf;
  162. }
  163. #endif
  164. return base64;
  165. }
  166. bool KSSLPKCS12::toFile(TQString filename) {
  167. #ifdef KSSL_HAVE_SSL
  168. TQFile out(filename);
  169. if (!out.open(IO_WriteOnly)) return false;
  170. int fd = out.handle();
  171. FILE *fp = fdopen(fd, "w");
  172. if (!fp) {
  173. unlink(filename.latin1());
  174. return false;
  175. }
  176. kossl->i2d_PKCS12_fp(fp, _pkcs);
  177. fclose(fp);
  178. return true;
  179. #endif
  180. return false;
  181. }
  182. KSSLCertificate::KSSLValidation KSSLPKCS12::validate() {
  183. return validate(KSSLCertificate::SSLServer);
  184. }
  185. KSSLCertificate::KSSLValidation KSSLPKCS12::validate(KSSLCertificate::KSSLPurpose p) {
  186. #ifdef KSSL_HAVE_SSL
  187. KSSLCertificate::KSSLValidation xx = _cert->validate(p);
  188. if (1 != kossl->X509_check_private_key(_cert->getCert(), _pkey)) {
  189. xx = KSSLCertificate::PrivateKeyFailed;
  190. }
  191. return xx;
  192. #else
  193. return KSSLCertificate::NoSSL;
  194. #endif
  195. }
  196. KSSLCertificate::KSSLValidation KSSLPKCS12::revalidate() {
  197. return revalidate(KSSLCertificate::SSLServer);
  198. }
  199. KSSLCertificate::KSSLValidation KSSLPKCS12::revalidate(KSSLCertificate::KSSLPurpose p) {
  200. return _cert->revalidate(p);
  201. }
  202. bool KSSLPKCS12::isValid() {
  203. return isValid(KSSLCertificate::SSLServer);
  204. }
  205. bool KSSLPKCS12::isValid(KSSLCertificate::KSSLPurpose p) {
  206. return (validate(p) == KSSLCertificate::Ok);
  207. }
  208. TQString KSSLPKCS12::name() {
  209. return _cert->getSubject();
  210. }