ksslpkcs12.cc
00001 /* This file is part of the KDE project 00002 * 00003 * Copyright (C) 2001 George Staikos <staikos@kde.org> 00004 * 00005 * This library is free software; you can redistribute it and/or 00006 * modify it under the terms of the GNU Library General Public 00007 * License as published by the Free Software Foundation; either 00008 * version 2 of the License, or (at your option) any later version. 00009 * 00010 * This library is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 * Library General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU Library General Public License 00016 * along with this library; see the file COPYING.LIB. If not, write to 00017 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00018 * Boston, MA 02110-1301, USA. 00019 */ 00020 00021 00022 #ifdef HAVE_CONFIG_H 00023 #include <config.h> 00024 #endif 00025 00026 #include <kopenssl.h> 00027 00028 #include <tqstring.h> 00029 #include <tqfile.h> 00030 #include <ksslall.h> 00031 #include <kdebug.h> 00032 #include <tdetempfile.h> 00033 #include <kmdcodec.h> 00034 00035 #include <assert.h> 00036 00037 00038 KSSLPKCS12::KSSLPKCS12() { 00039 _pkcs = NULL; 00040 _pkey = NULL; 00041 _cert = NULL; 00042 _caStack = NULL; 00043 kossl = KOSSL::self(); 00044 } 00045 00046 00047 00048 KSSLPKCS12::~KSSLPKCS12() { 00049 #ifdef KSSL_HAVE_SSL 00050 if (_pkey) kossl->EVP_PKEY_free(_pkey); 00051 if (_caStack) { 00052 for (;;) { 00053 X509* x5 = reinterpret_cast<X509*>(kossl->OPENSSL_sk_pop(_caStack)); 00054 if (!x5) break; 00055 kossl->X509_free(x5); 00056 } 00057 kossl->OPENSSL_sk_free(_caStack); 00058 } 00059 if (_pkcs) kossl->PKCS12_free(_pkcs); 00060 #endif 00061 if (_cert) delete _cert; 00062 } 00063 00064 00065 KSSLPKCS12* KSSLPKCS12::fromString(TQString base64, TQString password) { 00066 #ifdef KSSL_HAVE_SSL 00067 KTempFile ktf; 00068 00069 if (base64.isEmpty()) return NULL; 00070 TQByteArray qba, qbb = TQCString(base64.latin1()).copy(); 00071 KCodecs::base64Decode(qbb, qba); 00072 ktf.file()->writeBlock(qba); 00073 ktf.close(); 00074 KSSLPKCS12* rc = loadCertFile(ktf.name(), password); 00075 ktf.unlink(); 00076 return rc; 00077 #endif 00078 return NULL; 00079 } 00080 00081 00082 00083 KSSLPKCS12* KSSLPKCS12::loadCertFile(TQString filename, TQString password) { 00084 #ifdef KSSL_HAVE_SSL 00085 TQFile qf(filename); 00086 PKCS12 *newpkcs = NULL; 00087 00088 if (!qf.open(IO_ReadOnly)) 00089 return NULL; 00090 00091 FILE *fp = fdopen(qf.handle(), "r"); 00092 if (!fp) return NULL; 00093 00094 newpkcs = KOSSL::self()->d2i_PKCS12_fp(fp, &newpkcs); 00095 00096 fclose(fp); 00097 if (!newpkcs) { 00098 KOSSL::self()->ERR_clear_error(); 00099 return NULL; 00100 } 00101 00102 KSSLPKCS12 *c = new KSSLPKCS12; 00103 c->setCert(newpkcs); 00104 00105 // Now we parse it to see if we can decrypt it and interpret it 00106 if (!c->parse(password)) { 00107 delete c; c = NULL; 00108 } 00109 00110 return c; 00111 #endif 00112 return NULL; 00113 } 00114 00115 00116 void KSSLPKCS12::setCert(PKCS12 *c) { 00117 #ifdef KSSL_HAVE_SSL 00118 _pkcs = c; 00119 #endif 00120 } 00121 00122 00123 bool KSSLPKCS12::changePassword(TQString pold, TQString pnew) { 00124 #ifdef KSSL_HAVE_SSL 00125 // OpenSSL makes me cast away the const here. argh 00126 return (0 == kossl->PKCS12_newpass(_pkcs, 00127 pold.isNull() ? (char *)"" : (char *)pold.latin1(), 00128 pnew.isNull() ? (char *)"" : (char *)pnew.latin1())); 00129 #endif 00130 return false; 00131 } 00132 00133 00134 bool KSSLPKCS12::parse(TQString pass) { 00135 #ifdef KSSL_HAVE_SSL 00136 X509 *x = NULL; 00137 00138 assert(_pkcs); // if you're calling this before pkcs gets set, it's a BUG! 00139 00140 if (_cert) delete _cert; 00141 if (_pkey) kossl->EVP_PKEY_free(_pkey); 00142 if (_caStack) { 00143 for (;;) { 00144 X509* x5 = reinterpret_cast<X509*>(kossl->OPENSSL_sk_pop(_caStack)); 00145 if (!x5) break; 00146 kossl->X509_free(x5); 00147 } 00148 kossl->OPENSSL_sk_free(_caStack); 00149 } 00150 _pkey = NULL; 00151 _caStack = NULL; 00152 _cert = NULL; 00153 00154 int rc = kossl->PKCS12_parse(_pkcs, pass.latin1(), &_pkey, &x, &_caStack); 00155 00156 if (rc == 1) { 00157 // kdDebug(7029) << "PKCS12_parse success" << endl; 00158 if (x) { 00159 _cert = new KSSLCertificate; 00160 _cert->setCert(x); 00161 if (_caStack) { 00162 _cert->setChain(_caStack); 00163 } 00164 return true; 00165 } 00166 } else { 00167 _caStack = NULL; 00168 _pkey = NULL; 00169 kossl->ERR_clear_error(); 00170 } 00171 #endif 00172 return false; 00173 } 00174 00175 00176 EVP_PKEY *KSSLPKCS12::getPrivateKey() { 00177 return _pkey; 00178 } 00179 00180 00181 KSSLCertificate *KSSLPKCS12::getCertificate() { 00182 return _cert; 00183 } 00184 00185 00186 TQString KSSLPKCS12::toString() { 00187 TQString base64; 00188 #ifdef KSSL_HAVE_SSL 00189 unsigned char *p; 00190 int len; 00191 00192 len = kossl->i2d_PKCS12(_pkcs, NULL); 00193 if (len >= 0) { 00194 char *buf = new char[len]; 00195 p = (unsigned char *)buf; 00196 kossl->i2d_PKCS12(_pkcs, &p); 00197 TQByteArray qba; 00198 qba.setRawData(buf, len); 00199 base64 = KCodecs::base64Encode(qba); 00200 qba.resetRawData(buf, len); 00201 delete[] buf; 00202 } 00203 #endif 00204 return base64; 00205 } 00206 00207 00208 00209 bool KSSLPKCS12::toFile(TQString filename) { 00210 #ifdef KSSL_HAVE_SSL 00211 TQFile out(filename); 00212 00213 if (!out.open(IO_WriteOnly)) return false; 00214 00215 int fd = out.handle(); 00216 FILE *fp = fdopen(fd, "w"); 00217 00218 if (!fp) { 00219 unlink(filename.latin1()); 00220 return false; 00221 } 00222 00223 kossl->i2d_PKCS12_fp(fp, _pkcs); 00224 00225 fclose(fp); 00226 return true; 00227 #endif 00228 return false; 00229 } 00230 00231 00232 KSSLCertificate::KSSLValidation KSSLPKCS12::validate() { 00233 return validate(KSSLCertificate::SSLServer); 00234 } 00235 00236 00237 KSSLCertificate::KSSLValidation KSSLPKCS12::validate(KSSLCertificate::KSSLPurpose p) { 00238 #ifdef KSSL_HAVE_SSL 00239 KSSLCertificate::KSSLValidation xx = _cert->validate(p); 00240 if (1 != kossl->X509_check_private_key(_cert->getCert(), _pkey)) { 00241 xx = KSSLCertificate::PrivateKeyFailed; 00242 } 00243 00244 return xx; 00245 #else 00246 return KSSLCertificate::NoSSL; 00247 #endif 00248 } 00249 00250 00251 KSSLCertificate::KSSLValidation KSSLPKCS12::revalidate() { 00252 return revalidate(KSSLCertificate::SSLServer); 00253 } 00254 00255 00256 KSSLCertificate::KSSLValidation KSSLPKCS12::revalidate(KSSLCertificate::KSSLPurpose p) { 00257 return _cert->revalidate(p); 00258 } 00259 00260 00261 bool KSSLPKCS12::isValid() { 00262 return isValid(KSSLCertificate::SSLServer); 00263 } 00264 00265 00266 bool KSSLPKCS12::isValid(KSSLCertificate::KSSLPurpose p) { 00267 return (validate(p) == KSSLCertificate::Ok); 00268 } 00269 00270 00271 TQString KSSLPKCS12::name() { 00272 return _cert->getSubject(); 00273 } 00274