KIO
ksslpkcs12.cpp
Go to the documentation of this file.
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 #include <config.h> 00023 #include <ksslconfig.h> 00024 00025 #include <kopenssl.h> 00026 00027 #include <QtCore/QString> 00028 #include <QtCore/QFile> 00029 00030 #include <ksslall.h> 00031 #include <kdebug.h> 00032 #include <ktemporaryfile.h> 00033 #include <kcodecs.h> 00034 00035 #include <assert.h> 00036 00037 #ifdef KSSL_HAVE_SSL 00038 #define sk_new kossl->sk_new 00039 #define sk_push kossl->sk_push 00040 #define sk_free kossl->sk_free 00041 #define sk_value kossl->sk_value 00042 #define sk_num kossl->sk_num 00043 #define sk_dup kossl->sk_dup 00044 #define sk_pop kossl->sk_pop 00045 #endif 00046 00047 00048 KSSLPKCS12::KSSLPKCS12() { 00049 _pkcs = NULL; 00050 _pkey = NULL; 00051 _cert = NULL; 00052 _caStack = NULL; 00053 kossl = KOSSL::self(); 00054 } 00055 00056 00057 00058 KSSLPKCS12::~KSSLPKCS12() { 00059 #ifdef KSSL_HAVE_SSL 00060 if (_pkey) kossl->EVP_PKEY_free(_pkey); 00061 if (_caStack) { 00062 for (;;) { 00063 X509* x5 = sk_X509_pop(_caStack); 00064 if (!x5) break; 00065 kossl->X509_free(x5); 00066 } 00067 sk_X509_free(_caStack); 00068 } 00069 if (_pkcs) kossl->PKCS12_free(_pkcs); 00070 #endif 00071 delete _cert; 00072 } 00073 00074 00075 KSSLPKCS12* KSSLPKCS12::fromString(const QString &base64, const QString &password) { 00076 #ifdef KSSL_HAVE_SSL 00077 KTemporaryFile ktf; 00078 ktf.open(); 00079 00080 if (base64.isEmpty()) return NULL; 00081 QByteArray qba = QByteArray::fromBase64(base64.toLatin1()); 00082 ktf.write(qba); 00083 ktf.flush(); 00084 KSSLPKCS12* rc = loadCertFile(ktf.fileName(), password); 00085 return rc; 00086 #endif 00087 return NULL; 00088 } 00089 00090 00091 00092 KSSLPKCS12* KSSLPKCS12::loadCertFile(const QString &filename, const QString &password) { 00093 #ifdef KSSL_HAVE_SSL 00094 QFile qf(filename); 00095 PKCS12 *newpkcs = NULL; 00096 00097 if (!qf.open(QIODevice::ReadOnly)) 00098 return NULL; 00099 00100 FILE *fp = fdopen(qf.handle(), "r"); 00101 if (!fp) return NULL; 00102 00103 newpkcs = KOSSL::self()->d2i_PKCS12_fp(fp, &newpkcs); 00104 00105 fclose(fp); 00106 if (!newpkcs) { 00107 KOSSL::self()->ERR_clear_error(); 00108 return NULL; 00109 } 00110 00111 KSSLPKCS12 *c = new KSSLPKCS12; 00112 c->setCert(newpkcs); 00113 00114 // Now we parse it to see if we can decrypt it and interpret it 00115 if (!c->parse(password)) { 00116 delete c; c = NULL; 00117 } 00118 00119 return c; 00120 #endif 00121 return NULL; 00122 } 00123 00124 00125 void KSSLPKCS12::setCert(PKCS12 *c) { 00126 #ifdef KSSL_HAVE_SSL 00127 _pkcs = c; 00128 #endif 00129 } 00130 00131 00132 bool KSSLPKCS12::changePassword(const QString &pold, const QString &pnew) { 00133 #ifdef KSSL_HAVE_SSL 00134 // OpenSSL makes me cast away the const here. argh 00135 return (0 == kossl->PKCS12_newpass(_pkcs, 00136 pold.isNull() ? (char *)"" : (char *)pold.toLatin1().constData(), 00137 pnew.isNull() ? (char *)"" : (char *)pnew.toLatin1().constData())); 00138 #endif 00139 return false; 00140 } 00141 00142 00143 bool KSSLPKCS12::parse(const QString &pass) { 00144 #ifdef KSSL_HAVE_SSL 00145 X509 *x = NULL; 00146 00147 assert(_pkcs); // if you're calling this before pkcs gets set, it's a BUG! 00148 00149 delete _cert; 00150 if (_pkey) kossl->EVP_PKEY_free(_pkey); 00151 if (_caStack) { 00152 for (;;) { 00153 X509* x5 = sk_X509_pop(_caStack); 00154 if (!x5) break; 00155 kossl->X509_free(x5); 00156 } 00157 sk_X509_free(_caStack); 00158 } 00159 _pkey = NULL; 00160 _caStack = NULL; 00161 _cert = NULL; 00162 00163 int rc = kossl->PKCS12_parse(_pkcs, pass.toLatin1(), &_pkey, &x, &_caStack); 00164 00165 if (rc == 1) { 00166 // kDebug(7029) << "PKCS12_parse success"; 00167 if (x) { 00168 _cert = new KSSLCertificate; 00169 _cert->setCert(x); 00170 if (_caStack) { 00171 _cert->setChain(_caStack); 00172 } 00173 return true; 00174 } 00175 } else { 00176 _caStack = NULL; 00177 _pkey = NULL; 00178 kossl->ERR_clear_error(); 00179 } 00180 #endif 00181 return false; 00182 } 00183 00184 00185 EVP_PKEY *KSSLPKCS12::getPrivateKey() { 00186 return _pkey; 00187 } 00188 00189 00190 KSSLCertificate *KSSLPKCS12::getCertificate() { 00191 return _cert; 00192 } 00193 00194 00195 QString KSSLPKCS12::toString() 00196 { 00197 QString base64; 00198 #ifdef KSSL_HAVE_SSL 00199 unsigned char *p; 00200 int len; 00201 00202 len = kossl->i2d_PKCS12(_pkcs, NULL); 00203 if (len > 0) { 00204 char *buf = new char[len]; 00205 p = (unsigned char *)buf; 00206 kossl->i2d_PKCS12(_pkcs, &p); 00207 base64 = QByteArray::fromRawData(buf, len).toBase64(); 00208 delete[] buf; 00209 } 00210 #endif 00211 return base64; 00212 } 00213 00214 00215 00216 bool KSSLPKCS12::toFile(const QString &filename) { 00217 #ifdef KSSL_HAVE_SSL 00218 QFile out(filename); 00219 00220 if (!out.open(QIODevice::WriteOnly)) return false; 00221 00222 int fd = out.handle(); 00223 FILE *fp = fdopen(fd, "w"); 00224 00225 if (!fp) { 00226 unlink(filename.toLatin1()); 00227 return false; 00228 } 00229 00230 kossl->i2d_PKCS12_fp(fp, _pkcs); 00231 00232 fclose(fp); 00233 return true; 00234 #endif 00235 return false; 00236 } 00237 00238 00239 KSSLCertificate::KSSLValidation KSSLPKCS12::validate() { 00240 return validate(KSSLCertificate::SSLServer); 00241 } 00242 00243 00244 KSSLCertificate::KSSLValidation KSSLPKCS12::validate(KSSLCertificate::KSSLPurpose p) { 00245 #ifdef KSSL_HAVE_SSL 00246 KSSLCertificate::KSSLValidation xx = _cert->validate(p); 00247 if (1 != kossl->X509_check_private_key(_cert->getCert(), _pkey)) { 00248 xx = KSSLCertificate::PrivateKeyFailed; 00249 } 00250 00251 return xx; 00252 #else 00253 return KSSLCertificate::NoSSL; 00254 #endif 00255 } 00256 00257 00258 KSSLCertificate::KSSLValidation KSSLPKCS12::revalidate() { 00259 return revalidate(KSSLCertificate::SSLServer); 00260 } 00261 00262 00263 KSSLCertificate::KSSLValidation KSSLPKCS12::revalidate(KSSLCertificate::KSSLPurpose p) { 00264 return _cert->revalidate(p); 00265 } 00266 00267 00268 bool KSSLPKCS12::isValid() { 00269 return isValid(KSSLCertificate::SSLServer); 00270 } 00271 00272 00273 bool KSSLPKCS12::isValid(KSSLCertificate::KSSLPurpose p) { 00274 return (validate(p) == KSSLCertificate::Ok); 00275 } 00276 00277 00278 QString KSSLPKCS12::name() const { 00279 return _cert->getSubject(); 00280 } 00281 00282 00283 #ifdef KSSL_HAVE_SSL 00284 #undef sk_new 00285 #undef sk_push 00286 #undef sk_free 00287 #undef sk_value 00288 #undef sk_num 00289 #undef sk_pop 00290 #undef sk_dup 00291 #endif 00292
KDE 4.6 API Reference