KIO
ksslcertificate.cpp
Go to the documentation of this file.
00001 /* This file is part of the KDE project 00002 * 00003 * Copyright (C) 2000-2003 George Staikos <staikos@kde.org> 00004 * 2008 Richard Hartmann <richih-kde@net.in.tum.de> 00005 * 00006 * This library is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU Library General Public 00008 * License as published by the Free Software Foundation; either 00009 * version 2 of the License, or (at your option) any later version. 00010 * 00011 * This library is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 * Library General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Library General Public License 00017 * along with this library; see the file COPYING.LIB. If not, write to 00018 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00019 * Boston, MA 02110-1301, USA. 00020 */ 00021 00022 #include "ksslcertificate.h" 00023 00024 #include <config.h> 00025 #include <ksslconfig.h> 00026 00027 00028 00029 #include <unistd.h> 00030 #include <QtCore/QString> 00031 #include <QtCore/QStringList> 00032 #include <QtCore/QFile> 00033 00034 #include "kssldefs.h" 00035 #include "ksslcertchain.h" 00036 #include "ksslutils.h" 00037 00038 #include <kstandarddirs.h> 00039 #include <kcodecs.h> 00040 #include <kde_file.h> 00041 #include <klocale.h> 00042 #include <QtCore/QDate> 00043 #include <ktemporaryfile.h> 00044 00045 #include <sys/types.h> 00046 00047 #ifdef HAVE_SYS_STAT_H 00048 #include <sys/stat.h> 00049 #endif 00050 00051 // this hack provided by Malte Starostik to avoid glibc/openssl bug 00052 // on some systems 00053 #ifdef KSSL_HAVE_SSL 00054 #define crypt _openssl_crypt 00055 #include <openssl/ssl.h> 00056 #include <openssl/x509.h> 00057 #include <openssl/x509v3.h> 00058 #include <openssl/x509_vfy.h> 00059 #include <openssl/pem.h> 00060 #undef crypt 00061 #endif 00062 00063 #include <kopenssl.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 #endif 00087 KOSSL *kossl; 00088 KSSLCertChain _chain; 00089 KSSLX509V3 _extensions; 00090 KSSLCertificate::KSSLPurpose _lastPurpose; 00091 }; 00092 00093 KSSLCertificate::KSSLCertificate() { 00094 d = new KSSLCertificatePrivate; 00095 d->m_stateCached = false; 00096 KGlobal::dirs()->addResourceType("kssl", "data", "kssl"); 00097 #ifdef KSSL_HAVE_SSL 00098 d->m_cert = NULL; 00099 #endif 00100 } 00101 00102 00103 KSSLCertificate::KSSLCertificate(const KSSLCertificate& x) { 00104 d = new KSSLCertificatePrivate; 00105 d->m_stateCached = false; 00106 KGlobal::dirs()->addResourceType("kssl", "data", "kssl"); 00107 #ifdef KSSL_HAVE_SSL 00108 d->m_cert = NULL; 00109 setCert(KOSSL::self()->X509_dup(const_cast<KSSLCertificate&>(x).getCert())); 00110 KSSLCertChain *c = x.d->_chain.replicate(); 00111 setChain(c->rawChain()); 00112 delete c; 00113 #endif 00114 } 00115 00116 00117 00118 KSSLCertificate::~KSSLCertificate() { 00119 #ifdef KSSL_HAVE_SSL 00120 if (d->m_cert) { 00121 d->kossl->X509_free(d->m_cert); 00122 } 00123 #endif 00124 delete d; 00125 } 00126 00127 00128 KSSLCertChain& KSSLCertificate::chain() { 00129 return d->_chain; 00130 } 00131 00132 00133 KSSLCertificate *KSSLCertificate::fromX509(X509 *x5) { 00134 KSSLCertificate *n = NULL; 00135 #ifdef KSSL_HAVE_SSL 00136 if (x5) { 00137 n = new KSSLCertificate; 00138 n->setCert(KOSSL::self()->X509_dup(x5)); 00139 } 00140 #endif 00141 return n; 00142 } 00143 00144 00145 KSSLCertificate *KSSLCertificate::fromString(const QByteArray &cert) { 00146 KSSLCertificate *n = NULL; 00147 #ifdef KSSL_HAVE_SSL 00148 if (cert.isEmpty()) { 00149 return NULL; 00150 } 00151 00152 QByteArray qba = QByteArray::fromBase64(cert); 00153 unsigned char *qbap = reinterpret_cast<unsigned char *>(qba.data()); 00154 X509 *x5c = KOSSL::self()->d2i_X509(NULL, &qbap, qba.size()); 00155 if (!x5c) { 00156 return NULL; 00157 } 00158 00159 n = new KSSLCertificate; 00160 n->setCert(x5c); 00161 #endif 00162 return n; 00163 } 00164 00165 00166 00167 QString KSSLCertificate::getSubject() const { 00168 QString rc = ""; 00169 00170 #ifdef KSSL_HAVE_SSL 00171 char *t = d->kossl->X509_NAME_oneline(d->kossl->X509_get_subject_name(d->m_cert), 0, 0); 00172 if (!t) { 00173 return rc; 00174 } 00175 rc = t; 00176 d->kossl->OPENSSL_free(t); 00177 #endif 00178 return rc; 00179 } 00180 00181 00182 QString KSSLCertificate::getSerialNumber() const { 00183 QString rc = ""; 00184 00185 #ifdef KSSL_HAVE_SSL 00186 ASN1_INTEGER *aint = d->kossl->X509_get_serialNumber(d->m_cert); 00187 if (aint) { 00188 rc = ASN1_INTEGER_QString(aint); 00189 // d->kossl->ASN1_INTEGER_free(aint); this makes the sig test fail 00190 } 00191 #endif 00192 return rc; 00193 } 00194 00195 00196 QString KSSLCertificate::getSignatureText() const { 00197 QString rc = ""; 00198 00199 #ifdef KSSL_HAVE_SSL 00200 char *s; 00201 int n, i; 00202 00203 i = d->kossl->OBJ_obj2nid(d->m_cert->sig_alg->algorithm); 00204 rc = i18n("Signature Algorithm: "); 00205 rc += (i == NID_undef)?i18n("Unknown"):QString(d->kossl->OBJ_nid2ln(i)); 00206 00207 rc += '\n'; 00208 rc += i18n("Signature Contents:"); 00209 n = d->m_cert->signature->length; 00210 s = (char *)d->m_cert->signature->data; 00211 for (i = 0; i < n; ++i) { 00212 if (i%20 != 0) { 00213 rc += ':'; 00214 } 00215 else { 00216 rc += '\n'; 00217 } 00218 rc.append(QChar(hv[(s[i]&0xf0)>>4])); 00219 rc.append(QChar(hv[s[i]&0x0f])); 00220 } 00221 00222 #endif 00223 00224 return rc; 00225 } 00226 00227 00228 void KSSLCertificate::getEmails(QStringList &to) const { 00229 to.clear(); 00230 #ifdef KSSL_HAVE_SSL 00231 if (!d->m_cert) { 00232 return; 00233 } 00234 00235 STACK *s = d->kossl->X509_get1_email(d->m_cert); 00236 if (s) { 00237 for(int n=0; n < s->num; n++) { 00238 to.append(d->kossl->sk_value(s,n)); 00239 } 00240 d->kossl->X509_email_free(s); 00241 } 00242 #endif 00243 } 00244 00245 00246 QString KSSLCertificate::getKDEKey() const { 00247 return getSubject() + " (" + getMD5DigestText() + ')'; 00248 } 00249 00250 00251 QString KSSLCertificate::getMD5DigestFromKDEKey(const QString &k) { 00252 QString rc; 00253 int pos = k.lastIndexOf('('); 00254 if (pos != -1) { 00255 unsigned int len = k.length(); 00256 if (k.at(len-1) == ')') { 00257 rc = k.mid(pos+1, len-pos-2); 00258 } 00259 } 00260 return rc; 00261 } 00262 00263 00264 QString KSSLCertificate::getMD5DigestText() const { 00265 QString rc = ""; 00266 00267 #ifdef KSSL_HAVE_SSL 00268 unsigned int n; 00269 unsigned char md[EVP_MAX_MD_SIZE]; 00270 00271 if (!d->kossl->X509_digest(d->m_cert, d->kossl->EVP_md5(), md, &n)) { 00272 return rc; 00273 } 00274 00275 for (unsigned int j = 0; j < n; j++) { 00276 if (j > 0) { 00277 rc += ':'; 00278 } 00279 rc.append(QChar(hv[(md[j]&0xf0)>>4])); 00280 rc.append(QChar(hv[md[j]&0x0f])); 00281 } 00282 00283 #endif 00284 00285 return rc; 00286 } 00287 00288 00289 00290 QString KSSLCertificate::getMD5Digest() const { 00291 QString rc = ""; 00292 00293 #ifdef KSSL_HAVE_SSL 00294 unsigned int n; 00295 unsigned char md[EVP_MAX_MD_SIZE]; 00296 00297 if (!d->kossl->X509_digest(d->m_cert, d->kossl->EVP_md5(), md, &n)) { 00298 return rc; 00299 } 00300 00301 for (unsigned int j = 0; j < n; j++) { 00302 rc.append(QLatin1Char(hv[(md[j]&0xf0)>>4])); 00303 rc.append(QLatin1Char(hv[md[j]&0x0f])); 00304 } 00305 00306 #endif 00307 00308 return rc; 00309 } 00310 00311 00312 00313 QString KSSLCertificate::getKeyType() const { 00314 QString rc = ""; 00315 00316 #ifdef KSSL_HAVE_SSL 00317 EVP_PKEY *pkey = d->kossl->X509_get_pubkey(d->m_cert); 00318 if (pkey) { 00319 #ifndef NO_RSA 00320 if (pkey->type == EVP_PKEY_RSA) { 00321 rc = "RSA"; 00322 } 00323 else 00324 #endif 00325 #ifndef NO_DSA 00326 if (pkey->type == EVP_PKEY_DSA) { 00327 rc = "DSA"; 00328 } 00329 else 00330 #endif 00331 rc = "Unknown"; 00332 d->kossl->EVP_PKEY_free(pkey); 00333 } 00334 #endif 00335 00336 return rc; 00337 } 00338 00339 00340 00341 QString KSSLCertificate::getPublicKeyText() const { 00342 QString rc = ""; 00343 char *x = NULL; 00344 00345 #ifdef KSSL_HAVE_SSL 00346 EVP_PKEY *pkey = d->kossl->X509_get_pubkey(d->m_cert); 00347 if (pkey) { 00348 rc = i18nc("Unknown", "Unknown key algorithm"); 00349 #ifndef NO_RSA 00350 if (pkey->type == EVP_PKEY_RSA) { 00351 x = d->kossl->BN_bn2hex(pkey->pkey.rsa->n); 00352 rc = i18n("Key type: RSA (%1 bit)", strlen(x)*4) + '\n'; 00353 00354 rc += i18n("Modulus: "); 00355 for (unsigned int i = 0; i < strlen(x); i++) { 00356 if (i%40 != 0 && i%2 == 0) { 00357 rc += ':'; 00358 } 00359 else if (i%40 == 0) { 00360 rc += '\n'; 00361 } 00362 rc += x[i]; 00363 } 00364 rc += '\n'; 00365 d->kossl->OPENSSL_free(x); 00366 00367 x = d->kossl->BN_bn2hex(pkey->pkey.rsa->e); 00368 rc += i18n("Exponent: 0x") + QLatin1String(x) + 00369 QLatin1String("\n"); 00370 d->kossl->OPENSSL_free(x); 00371 } 00372 #endif 00373 #ifndef NO_DSA 00374 if (pkey->type == EVP_PKEY_DSA) { 00375 x = d->kossl->BN_bn2hex(pkey->pkey.dsa->p); 00376 // hack - this may not be always accurate 00377 rc = i18n("Key type: DSA (%1 bit)", strlen(x)*4) + '\n'; 00378 00379 rc += i18n("Prime: "); 00380 for (unsigned int i = 0; i < strlen(x); i++) { 00381 if (i%40 != 0 && i%2 == 0) { 00382 rc += ':'; 00383 } 00384 else if (i%40 == 0) { 00385 rc += '\n'; 00386 } 00387 rc += x[i]; 00388 } 00389 rc += '\n'; 00390 d->kossl->OPENSSL_free(x); 00391 00392 x = d->kossl->BN_bn2hex(pkey->pkey.dsa->q); 00393 rc += i18n("160 bit prime factor: "); 00394 for (unsigned int i = 0; i < strlen(x); i++) { 00395 if (i%40 != 0 && i%2 == 0) { 00396 rc += ':'; 00397 } 00398 else if (i%40 == 0) { 00399 rc += '\n'; 00400 } 00401 rc += x[i]; 00402 } 00403 rc += '\n'; 00404 d->kossl->OPENSSL_free(x); 00405 00406 x = d->kossl->BN_bn2hex(pkey->pkey.dsa->g); 00407 rc += QString("g: "); 00408 for (unsigned int i = 0; i < strlen(x); i++) { 00409 if (i%40 != 0 && i%2 == 0) { 00410 rc += ':'; 00411 } 00412 else if (i%40 == 0) { 00413 rc += '\n'; 00414 } 00415 rc += x[i]; 00416 } 00417 rc += '\n'; 00418 d->kossl->OPENSSL_free(x); 00419 00420 x = d->kossl->BN_bn2hex(pkey->pkey.dsa->pub_key); 00421 rc += i18n("Public key: "); 00422 for (unsigned int i = 0; i < strlen(x); i++) { 00423 if (i%40 != 0 && i%2 == 0) { 00424 rc += ':'; 00425 } 00426 else if (i%40 == 0) { 00427 rc += '\n'; 00428 } 00429 rc += x[i]; 00430 } 00431 rc += '\n'; 00432 d->kossl->OPENSSL_free(x); 00433 } 00434 #endif 00435 d->kossl->EVP_PKEY_free(pkey); 00436 } 00437 #endif 00438 00439 return rc; 00440 } 00441 00442 00443 00444 QString KSSLCertificate::getIssuer() const { 00445 QString rc = ""; 00446 00447 #ifdef KSSL_HAVE_SSL 00448 char *t = d->kossl->X509_NAME_oneline(d->kossl->X509_get_issuer_name(d->m_cert), 0, 0); 00449 00450 if (!t) { 00451 return rc; 00452 } 00453 00454 rc = t; 00455 d->kossl->OPENSSL_free(t); 00456 #endif 00457 00458 return rc; 00459 } 00460 00461 void KSSLCertificate::setChain(void *c) { 00462 #ifdef KSSL_HAVE_SSL 00463 d->_chain.setChain(c); 00464 #endif 00465 d->m_stateCached = false; 00466 d->m_stateCache = KSSLCertificate::Unknown; 00467 } 00468 00469 void KSSLCertificate::setCert(X509 *c) { 00470 #ifdef KSSL_HAVE_SSL 00471 d->m_cert = c; 00472 if (c) { 00473 d->_extensions.flags = 0; 00474 d->kossl->X509_check_purpose(c, -1, 0); // setup the fields (!!) 00475 00476 #if 0 00477 kDebug(7029) << "---------------- Certificate ------------------" 00478 << endl; 00479 kDebug(7029) << getSubject(); 00480 #endif 00481 00482 for (int j = 0; j < d->kossl->X509_PURPOSE_get_count(); j++) { 00483 X509_PURPOSE *ptmp = d->kossl->X509_PURPOSE_get0(j); 00484 int id = d->kossl->X509_PURPOSE_get_id(ptmp); 00485 for (int ca = 0; ca < 2; ca++) { 00486 int idret = d->kossl->X509_check_purpose(c, id, ca); 00487 if (idret == 1 || idret == 2) { // have it 00488 // kDebug() << "PURPOSE: " << id << (ca?" CA":""); 00489 if (!ca) { 00490 d->_extensions.flags |= (1L <<(id-1)); 00491 } 00492 else d->_extensions.flags |= (1L <<(16+id-1)); 00493 } else { 00494 if (!ca) { 00495 d->_extensions.flags &= ~(1L <<(id-1)); 00496 } 00497 else d->_extensions.flags &= ~(1L <<(16+id-1)); 00498 } 00499 } 00500 } 00501 00502 #if 0 00503 kDebug(7029) << "flags: " << QString::number(c->ex_flags, 2) 00504 << "\nkeyusage: " << QString::number(c->ex_kusage, 2) 00505 << "\nxkeyusage: " << QString::number(c->ex_xkusage, 2) 00506 << "\nnscert: " << QString::number(c->ex_nscert, 2) 00507 << endl; 00508 if (c->ex_flags & EXFLAG_KUSAGE) 00509 kDebug(7029) << " --- Key Usage extensions found"; 00510 else kDebug(7029) << " --- Key Usage extensions NOT found"; 00511 00512 if (c->ex_flags & EXFLAG_XKUSAGE) 00513 kDebug(7029) << " --- Extended key usage extensions found"; 00514 else kDebug(7029) << " --- Extended key usage extensions NOT found"; 00515 00516 if (c->ex_flags & EXFLAG_NSCERT) 00517 kDebug(7029) << " --- NS extensions found"; 00518 else kDebug(7029) << " --- NS extensions NOT found"; 00519 00520 if (d->_extensions.certTypeSSLCA()) 00521 kDebug(7029) << "NOTE: this is an SSL CA file."; 00522 else kDebug(7029) << "NOTE: this is NOT an SSL CA file."; 00523 00524 if (d->_extensions.certTypeEmailCA()) 00525 kDebug(7029) << "NOTE: this is an EMAIL CA file."; 00526 else kDebug(7029) << "NOTE: this is NOT an EMAIL CA file."; 00527 00528 if (d->_extensions.certTypeCodeCA()) 00529 kDebug(7029) << "NOTE: this is a CODE CA file."; 00530 else kDebug(7029) << "NOTE: this is NOT a CODE CA file."; 00531 00532 if (d->_extensions.certTypeSSLClient()) 00533 kDebug(7029) << "NOTE: this is an SSL client."; 00534 else kDebug(7029) << "NOTE: this is NOT an SSL client."; 00535 00536 if (d->_extensions.certTypeSSLServer()) 00537 kDebug(7029) << "NOTE: this is an SSL server."; 00538 else kDebug(7029) << "NOTE: this is NOT an SSL server."; 00539 00540 if (d->_extensions.certTypeNSSSLServer()) 00541 kDebug(7029) << "NOTE: this is a NETSCAPE SSL server."; 00542 else kDebug(7029) << "NOTE: this is NOT a NETSCAPE SSL server."; 00543 00544 if (d->_extensions.certTypeSMIME()) 00545 kDebug(7029) << "NOTE: this is an SMIME certificate."; 00546 else kDebug(7029) << "NOTE: this is NOT an SMIME certificate."; 00547 00548 if (d->_extensions.certTypeSMIMEEncrypt()) 00549 kDebug(7029) << "NOTE: this is an SMIME encrypt cert."; 00550 else kDebug(7029) << "NOTE: this is NOT an SMIME encrypt cert."; 00551 00552 if (d->_extensions.certTypeSMIMESign()) 00553 kDebug(7029) << "NOTE: this is an SMIME sign cert."; 00554 else kDebug(7029) << "NOTE: this is NOT an SMIME sign cert."; 00555 00556 if (d->_extensions.certTypeCRLSign()) 00557 kDebug(7029) << "NOTE: this is a CRL signer."; 00558 else kDebug(7029) << "NOTE: this is NOT a CRL signer."; 00559 00560 kDebug(7029) << "-----------------------------------------------" 00561 << endl; 00562 #endif 00563 } 00564 #endif 00565 d->m_stateCached = false; 00566 d->m_stateCache = KSSLCertificate::Unknown; 00567 } 00568 00569 X509 *KSSLCertificate::getCert() { 00570 #ifdef KSSL_HAVE_SSL 00571 return d->m_cert; 00572 #endif 00573 return 0; 00574 } 00575 00576 // pull in the callback. It's common across multiple files but we want 00577 // it to be hidden. 00578 00579 #include "ksslcallback.c" 00580 00581 00582 bool KSSLCertificate::isValid(KSSLCertificate::KSSLPurpose p) { 00583 return (validate(p) == KSSLCertificate::Ok); 00584 } 00585 00586 00587 bool KSSLCertificate::isValid() { 00588 return isValid(KSSLCertificate::SSLServer); 00589 } 00590 00591 00592 int KSSLCertificate::purposeToOpenSSL(KSSLCertificate::KSSLPurpose p) const { 00593 int rc = 0; 00594 #ifdef KSSL_HAVE_SSL 00595 if (p == KSSLCertificate::SSLServer) { 00596 rc = X509_PURPOSE_SSL_SERVER; 00597 } else if (p == KSSLCertificate::SSLClient) { 00598 rc = X509_PURPOSE_SSL_CLIENT; 00599 } else if (p == KSSLCertificate::SMIMEEncrypt) { 00600 rc = X509_PURPOSE_SMIME_ENCRYPT; 00601 } else if (p == KSSLCertificate::SMIMESign) { 00602 rc = X509_PURPOSE_SMIME_SIGN; 00603 } else if (p == KSSLCertificate::Any) { 00604 rc = X509_PURPOSE_ANY; 00605 } 00606 #endif 00607 return rc; 00608 } 00609 00610 00611 // For backward compatibility 00612 KSSLCertificate::KSSLValidation KSSLCertificate::validate() { 00613 return validate(KSSLCertificate::SSLServer); 00614 } 00615 00616 KSSLCertificate::KSSLValidation KSSLCertificate::validate(KSSLCertificate::KSSLPurpose purpose) 00617 { 00618 KSSLValidationList result = validateVerbose(purpose); 00619 if (result.isEmpty()) { 00620 return KSSLCertificate::Ok; 00621 } 00622 else 00623 return result.first(); 00624 } 00625 00626 // 00627 // See apps/verify.c in OpenSSL for the source of most of this logic. 00628 // 00629 00630 // CRL files? we don't do that yet 00631 KSSLCertificate::KSSLValidationList KSSLCertificate::validateVerbose(KSSLCertificate::KSSLPurpose purpose) 00632 { 00633 return validateVerbose(purpose, 0); 00634 } 00635 00636 KSSLCertificate::KSSLValidationList KSSLCertificate::validateVerbose(KSSLCertificate::KSSLPurpose purpose, KSSLCertificate *ca) 00637 { 00638 KSSLValidationList errors; 00639 if (ca || (d->_lastPurpose != purpose)) { 00640 d->m_stateCached = false; 00641 } 00642 00643 if (!d->m_stateCached) { 00644 d->_lastPurpose = purpose; 00645 } 00646 00647 #ifdef KSSL_HAVE_SSL 00648 X509_STORE *certStore; 00649 X509_LOOKUP *certLookup; 00650 X509_STORE_CTX *certStoreCTX; 00651 int rc = 0; 00652 00653 if (!d->m_cert) { 00654 errors << KSSLCertificate::Unknown; 00655 return errors; 00656 } 00657 00658 if (d->m_stateCached) { 00659 errors << d->m_stateCache; 00660 return errors; 00661 } 00662 00663 const QStringList qsl = KGlobal::dirs()->resourceDirs("kssl"); 00664 00665 if (qsl.isEmpty()) { 00666 errors << KSSLCertificate::NoCARoot; 00667 return errors; 00668 } 00669 00670 KSSLCertificate::KSSLValidation ksslv = Unknown; 00671 00672 for (QStringList::ConstIterator j = qsl.begin(); j != qsl.end(); ++j) { 00673 KDE_struct_stat sb; 00674 QString _j = (*j) + "ca-bundle.crt"; 00675 if (-1 == KDE_stat(_j.toAscii().constData(), &sb)) { 00676 continue; 00677 } 00678 00679 certStore = d->kossl->X509_STORE_new(); 00680 if (!certStore) { 00681 errors << KSSLCertificate::Unknown; 00682 return errors; 00683 } 00684 00685 X509_STORE_set_verify_cb_func(certStore, X509Callback); 00686 00687 certLookup = d->kossl->X509_STORE_add_lookup(certStore, d->kossl->X509_LOOKUP_file()); 00688 if (!certLookup) { 00689 ksslv = KSSLCertificate::Unknown; 00690 d->kossl->X509_STORE_free(certStore); 00691 continue; 00692 } 00693 00694 if (!d->kossl->X509_LOOKUP_load_file(certLookup, _j.toAscii().constData(), X509_FILETYPE_PEM)) { 00695 // error accessing directory and loading pems 00696 kDebug(7029) << "KSSL couldn't read CA root: " 00697 << _j << endl; 00698 ksslv = KSSLCertificate::ErrorReadingRoot; 00699 d->kossl->X509_STORE_free(certStore); 00700 continue; 00701 } 00702 00703 // This is the checking code 00704 certStoreCTX = d->kossl->X509_STORE_CTX_new(); 00705 00706 // this is a bad error - could mean no free memory. 00707 // This may be the wrong thing to do here 00708 if (!certStoreCTX) { 00709 kDebug(7029) << "KSSL couldn't create an X509 store context."; 00710 d->kossl->X509_STORE_free(certStore); 00711 continue; 00712 } 00713 00714 d->kossl->X509_STORE_CTX_init(certStoreCTX, certStore, d->m_cert, NULL); 00715 if (d->_chain.isValid()) { 00716 d->kossl->X509_STORE_CTX_set_chain(certStoreCTX, (STACK_OF(X509)*)d->_chain.rawChain()); 00717 } 00718 00719 //kDebug(7029) << "KSSL setting CRL.............."; 00720 // int X509_STORE_add_crl(X509_STORE *ctx, X509_CRL *x); 00721 00722 d->kossl->X509_STORE_CTX_set_purpose(certStoreCTX, purposeToOpenSSL(purpose)); 00723 00724 KSSL_X509CallBack_ca = ca ? ca->d->m_cert : 0; 00725 KSSL_X509CallBack_ca_found = false; 00726 00727 certStoreCTX->error = X509_V_OK; 00728 rc = d->kossl->X509_verify_cert(certStoreCTX); 00729 int errcode = certStoreCTX->error; 00730 if (ca && !KSSL_X509CallBack_ca_found) { 00731 ksslv = KSSLCertificate::Irrelevant; 00732 } else { 00733 ksslv = processError(errcode); 00734 } 00735 // For servers, we can try NS_SSL_SERVER too 00736 if ((ksslv != KSSLCertificate::Ok) && 00737 (ksslv != KSSLCertificate::Irrelevant) && 00738 purpose == KSSLCertificate::SSLServer) { 00739 d->kossl->X509_STORE_CTX_set_purpose(certStoreCTX, 00740 X509_PURPOSE_NS_SSL_SERVER); 00741 00742 certStoreCTX->error = X509_V_OK; 00743 rc = d->kossl->X509_verify_cert(certStoreCTX); 00744 errcode = certStoreCTX->error; 00745 ksslv = processError(errcode); 00746 } 00747 d->kossl->X509_STORE_CTX_free(certStoreCTX); 00748 d->kossl->X509_STORE_free(certStore); 00749 // end of checking code 00750 // 00751 00752 //kDebug(7029) << "KSSL Validation procedure RC: " 00753 // << rc << endl; 00754 //kDebug(7029) << "KSSL Validation procedure errcode: " 00755 // << errcode << endl; 00756 //kDebug(7029) << "KSSL Validation procedure RESULTS: " 00757 // << ksslv << endl; 00758 00759 if (ksslv != NoCARoot && ksslv != InvalidCA && ksslv != GetIssuerCertFailed && ksslv != DecodeIssuerPublicKeyFailed && ksslv != GetIssuerCertLocallyFailed ) { 00760 d->m_stateCached = true; 00761 d->m_stateCache = ksslv; 00762 } 00763 break; 00764 } 00765 00766 if (ksslv != KSSLCertificate::Ok) { 00767 errors << ksslv; 00768 } 00769 #else 00770 errors << KSSLCertificate::NoSSL; 00771 #endif 00772 return errors; 00773 } 00774 00775 00776 00777 KSSLCertificate::KSSLValidation KSSLCertificate::revalidate() { 00778 return revalidate(KSSLCertificate::SSLServer); 00779 } 00780 00781 00782 KSSLCertificate::KSSLValidation KSSLCertificate::revalidate(KSSLCertificate::KSSLPurpose p) { 00783 d->m_stateCached = false; 00784 return validate(p); 00785 } 00786 00787 00788 KSSLCertificate::KSSLValidation KSSLCertificate::processError(int ec) { 00789 KSSLCertificate::KSSLValidation rc; 00790 00791 rc = KSSLCertificate::Unknown; 00792 #ifdef KSSL_HAVE_SSL 00793 switch (ec) { 00794 00795 // see man 1 verify for a detailed listing of all error codes 00796 00797 // error 0 00798 case X509_V_OK: 00799 rc = KSSLCertificate::Ok; 00800 break; 00801 00802 00803 // error 2 00804 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: 00805 rc = KSSLCertificate::GetIssuerCertFailed; 00806 break; 00807 00808 // error 3 00809 case X509_V_ERR_UNABLE_TO_GET_CRL: 00810 rc = KSSLCertificate::GetCRLFailed; 00811 break; 00812 00813 // error 4 00814 case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE: 00815 rc = KSSLCertificate::DecryptCertificateSignatureFailed; 00816 break; 00817 00818 // error 5 00819 case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE: 00820 rc = KSSLCertificate::DecryptCRLSignatureFailed; 00821 break; 00822 00823 // error 6 00824 case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY: 00825 rc = KSSLCertificate::DecodeIssuerPublicKeyFailed; 00826 break; 00827 00828 // error 7 00829 case X509_V_ERR_CERT_SIGNATURE_FAILURE: 00830 rc = KSSLCertificate::CertificateSignatureFailed; 00831 break; 00832 00833 // error 8 00834 case X509_V_ERR_CRL_SIGNATURE_FAILURE: 00835 rc = KSSLCertificate::CRLSignatureFailed; 00836 break; 00837 00838 // error 9 00839 case X509_V_ERR_CERT_NOT_YET_VALID: 00840 rc = KSSLCertificate::CertificateNotYetValid; 00841 break; 00842 00843 // error 10 00844 case X509_V_ERR_CERT_HAS_EXPIRED: 00845 rc = KSSLCertificate::CertificateHasExpired; 00846 kDebug(7029) << "KSSL apparently this is expired. Not after: " 00847 << getNotAfter() << endl; 00848 break; 00849 00850 // error 11 00851 case X509_V_ERR_CRL_NOT_YET_VALID: 00852 rc = KSSLCertificate::CRLNotYetValid; 00853 break; 00854 00855 // error 12 00856 case X509_V_ERR_CRL_HAS_EXPIRED: 00857 rc = KSSLCertificate::CRLHasExpired; 00858 break; 00859 00860 // error 13 00861 case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: 00862 rc = KSSLCertificate::CertificateFieldNotBeforeErroneous; 00863 break; 00864 00865 // error 14 00866 case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: 00867 rc = KSSLCertificate::CertificateFieldNotAfterErroneous; 00868 break; 00869 00870 // error 15 - unused as of OpenSSL 0.9.8g 00871 case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD: 00872 rc = KSSLCertificate::CRLFieldLastUpdateErroneous; 00873 break; 00874 00875 // error 16 - unused as of OpenSSL 0.9.8g 00876 case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD: 00877 rc = KSSLCertificate::CRLFieldNextUpdateErroneous; 00878 break; 00879 00880 // error 17 00881 case X509_V_ERR_OUT_OF_MEM: 00882 rc = KSSLCertificate::OutOfMemory; 00883 break; 00884 00885 // error 18 00886 case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: 00887 rc = KSSLCertificate::SelfSigned; 00888 break; 00889 00890 // error 19 00891 case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN: 00892 rc = KSSLCertificate::SelfSignedInChain; 00893 break; 00894 00895 // error 20 00896 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY: 00897 rc = KSSLCertificate::GetIssuerCertLocallyFailed; 00898 break; 00899 00900 // error 21 00901 case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE: 00902 rc = KSSLCertificate::VerifyLeafSignatureFailed; 00903 break; 00904 00905 // error 22 - unused as of OpenSSL 0.9.8g 00906 case X509_V_ERR_CERT_CHAIN_TOO_LONG: 00907 rc = KSSLCertificate::CertificateChainTooLong; 00908 break; 00909 00910 // error 23 - unused as of OpenSSL 0.9.8g 00911 case X509_V_ERR_CERT_REVOKED: 00912 rc = KSSLCertificate::CertificateRevoked; 00913 break; 00914 00915 // error 24 00916 case X509_V_ERR_INVALID_CA: 00917 rc = KSSLCertificate::InvalidCA; 00918 break; 00919 00920 // error 25 00921 case X509_V_ERR_PATH_LENGTH_EXCEEDED: 00922 rc = KSSLCertificate::PathLengthExceeded; 00923 break; 00924 00925 // error 26 00926 case X509_V_ERR_INVALID_PURPOSE: 00927 rc = KSSLCertificate::InvalidPurpose; 00928 break; 00929 00930 // error 27 00931 case X509_V_ERR_CERT_UNTRUSTED: 00932 rc = KSSLCertificate::CertificateUntrusted; 00933 break; 00934 00935 // error 28 00936 case X509_V_ERR_CERT_REJECTED: 00937 rc = KSSLCertificate::CertificateRejected; 00938 break; 00939 00940 // error 29 - only used with -issuer_checks 00941 case X509_V_ERR_SUBJECT_ISSUER_MISMATCH: 00942 rc = KSSLCertificate::IssuerSubjectMismatched; 00943 break; 00944 00945 // error 30 - only used with -issuer_checks 00946 case X509_V_ERR_AKID_SKID_MISMATCH: 00947 rc = KSSLCertificate::AuthAndSubjectKeyIDMismatched; 00948 break; 00949 00950 // error 31 - only used with -issuer_checks 00951 case X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH: 00952 rc = KSSLCertificate::AuthAndSubjectKeyIDAndNameMismatched; 00953 break; 00954 00955 // error 32 00956 case X509_V_ERR_KEYUSAGE_NO_CERTSIGN: 00957 rc = KSSLCertificate::KeyMayNotSignCertificate; 00958 break; 00959 00960 00961 // error 50 - unused as of OpenSSL 0.9.8g 00962 case X509_V_ERR_APPLICATION_VERIFICATION: 00963 rc = KSSLCertificate::ApplicationVerificationFailed; 00964 break; 00965 00966 00967 default: 00968 rc = KSSLCertificate::Unknown; 00969 break; 00970 } 00971 00972 d->m_stateCache = rc; 00973 d->m_stateCached = true; 00974 #endif 00975 return rc; 00976 } 00977 00978 00979 QString KSSLCertificate::getNotBefore() const { 00980 #ifdef KSSL_HAVE_SSL 00981 return ASN1_UTCTIME_QString(X509_get_notBefore(d->m_cert)); 00982 #else 00983 return QString(); 00984 #endif 00985 } 00986 00987 00988 QString KSSLCertificate::getNotAfter() const { 00989 #ifdef KSSL_HAVE_SSL 00990 return ASN1_UTCTIME_QString(X509_get_notAfter(d->m_cert)); 00991 #else 00992 return QString(); 00993 #endif 00994 } 00995 00996 00997 QDateTime KSSLCertificate::getQDTNotBefore() const { 00998 #ifdef KSSL_HAVE_SSL 00999 return ASN1_UTCTIME_QDateTime(X509_get_notBefore(d->m_cert), NULL); 01000 #else 01001 return QDateTime::currentDateTime(); 01002 #endif 01003 } 01004 01005 01006 QDateTime KSSLCertificate::getQDTNotAfter() const { 01007 #ifdef KSSL_HAVE_SSL 01008 return ASN1_UTCTIME_QDateTime(X509_get_notAfter(d->m_cert), NULL); 01009 #else 01010 return QDateTime::currentDateTime(); 01011 #endif 01012 } 01013 01014 01015 int operator==(KSSLCertificate &x, KSSLCertificate &y) { 01016 #ifndef KSSL_HAVE_SSL 01017 return 1; 01018 #else 01019 if (!KOSSL::self()->X509_cmp(x.getCert(), y.getCert())) { 01020 return 1; 01021 } 01022 return 0; 01023 #endif 01024 } 01025 01026 01027 KSSLCertificate *KSSLCertificate::replicate() { 01028 // The new certificate doesn't have the cached value. It's probably 01029 // better this way. We can't anticipate every reason for doing this. 01030 KSSLCertificate *newOne = new KSSLCertificate(); 01031 #ifdef KSSL_HAVE_SSL 01032 newOne->setCert(d->kossl->X509_dup(getCert())); 01033 KSSLCertChain *c = d->_chain.replicate(); 01034 newOne->setChain(c->rawChain()); 01035 delete c; 01036 #endif 01037 return newOne; 01038 } 01039 01040 01041 QString KSSLCertificate::toString() 01042 { 01043 return toDer().toBase64(); 01044 } 01045 01046 01047 QString KSSLCertificate::verifyText(KSSLValidation x) { 01048 switch (x) { 01049 // messages for errors defined in verify(1) 01050 case KSSLCertificate::Ok: 01051 return i18n("The certificate is valid."); 01052 case KSSLCertificate::GetIssuerCertFailed: 01053 return i18n("Retrieval of the issuer certificate failed. This means the CA's (Certificate Authority) certificate can not be found."); 01054 case KSSLCertificate::GetCRLFailed: 01055 return i18n("Retrieval of the CRL (Certificate Revocation List) failed. This means the CA's (Certificate Authority) CRL can not be found."); 01056 case KSSLCertificate::DecryptCertificateSignatureFailed: 01057 return i18n("The decryption of the certificate's signature failed. This means it could not even be calculated as opposed to just not matching the expected result."); 01058 case KSSLCertificate::DecryptCRLSignatureFailed: 01059 return i18n("The decryption of the CRL's (Certificate Revocation List) signature failed. This means it could not even be calculated as opposed to just not matching the expected result."); 01060 case KSSLCertificate::DecodeIssuerPublicKeyFailed: 01061 return i18n("The decoding of the public key of the issuer failed. This means that the CA's (Certificate Authority) certificate can not be used to verify the certificate you wanted to use."); 01062 case KSSLCertificate::CertificateSignatureFailed: 01063 return i18n("The certificate's signature is invalid. This means that the certificate can not be verified."); 01064 case KSSLCertificate::CRLSignatureFailed: 01065 return i18n("The CRL's (Certificate Revocation List) signature is invalid. This means that the CRL can not be verified."); 01066 case KSSLCertificate::CertificateNotYetValid: 01067 return i18n("The certificate is not valid, yet."); 01068 case KSSLCertificate::CertificateHasExpired: 01069 return i18n("The certificate is not valid, any more."); 01070 case KSSLCertificate::CRLNotYetValid: 01071 return i18n("The CRL (Certificate Revocation List) is not valid, yet."); 01072 case KSSLCertificate::CRLHasExpired: 01073 return i18n("The CRL (Certificate Revocation List) is not valid, yet."); 01074 case KSSLCertificate::CertificateFieldNotBeforeErroneous: 01075 return i18n("The time format of the certificate's 'notBefore' field is invalid."); 01076 case KSSLCertificate::CertificateFieldNotAfterErroneous: 01077 return i18n("The time format of the certificate's 'notAfter' field is invalid."); 01078 case KSSLCertificate::CRLFieldLastUpdateErroneous: 01079 return i18n("The time format of the CRL's (Certificate Revocation List) 'lastUpdate' field is invalid."); 01080 case KSSLCertificate::CRLFieldNextUpdateErroneous: 01081 return i18n("The time format of the CRL's (Certificate Revocation List) 'nextUpdate' field is invalid."); 01082 case KSSLCertificate::OutOfMemory: 01083 return i18n("The OpenSSL process ran out of memory."); 01084 case KSSLCertificate::SelfSigned: 01085 return i18n("The certificate is self-signed and not in the list of trusted certificates. If you want to accept this certificate, import it into the list of trusted certificates."); 01086 case KSSLCertificate::SelfSignedChain: // this is obsolete and kept around for backwards compatibility, only 01087 case KSSLCertificate::SelfSignedInChain: 01088 return i18n("The certificate is self-signed. While the trust chain could be built up, the root CA's (Certificate Authority) certificate can not be found."); 01089 case KSSLCertificate::GetIssuerCertLocallyFailed: 01090 return i18n("The CA's (Certificate Authority) certificate can not be found. Most likely, your trust chain is broken."); 01091 case KSSLCertificate::VerifyLeafSignatureFailed: 01092 return i18n("The certificate can not be verified as it is the only certificate in the trust chain and not self-signed. If you self-sign the certificate, make sure to import it into the list of trusted certificates."); 01093 case KSSLCertificate::CertificateChainTooLong: 01094 return i18n("The certificate chain is longer than the maximum depth specified."); 01095 case KSSLCertificate::Revoked: // this is obsolete and kept around for backwards compatibility, only 01096 case KSSLCertificate::CertificateRevoked: 01097 return i18n("The certificate has been revoked."); 01098 case KSSLCertificate::InvalidCA: 01099 return i18n("The certificate's CA (Certificate Authority) is invalid."); 01100 case KSSLCertificate::PathLengthExceeded: 01101 return i18n("The length of the trust chain exceeded one of the CA's (Certificate Authority) 'pathlength' parameters, making all subsequent signatures invalid."); 01102 case KSSLCertificate::InvalidPurpose: 01103 return i18n("The certificate has not been signed for the purpose you tried to use it for. This means the CA (Certificate Authority) does not allow this usage."); 01104 case KSSLCertificate::Untrusted: // this is obsolete and kept around for backwards compatibility, only 01105 case KSSLCertificate::CertificateUntrusted: 01106 return i18n("The root CA (Certificate Authority) is not trusted for the purpose you tried to use this certificate for."); 01107 case KSSLCertificate::Rejected: // this is obsolete and kept around for backwards compatibility, only // this is obsolete and kept around for backwards compatibility, onle 01108 case KSSLCertificate::CertificateRejected: 01109 return i18n("The root CA (Certificate Authority) has been marked to be rejected for the purpose you tried to use it for."); 01110 case KSSLCertificate::IssuerSubjectMismatched: 01111 return i18n("The certificate's CA (Certificate Authority) does not match the CA name of the certificate."); 01112 case KSSLCertificate::AuthAndSubjectKeyIDMismatched: 01113 return i18n("The CA (Certificate Authority) certificate's key ID does not match the key ID in the 'Issuer' section of the certificate you are trying to use."); 01114 case KSSLCertificate::AuthAndSubjectKeyIDAndNameMismatched: 01115 return i18n("The CA (Certificate Authority) certificate's key ID and name do not match the key ID and name in the 'Issuer' section of the certificate you are trying to use."); 01116 case KSSLCertificate::KeyMayNotSignCertificate: 01117 return i18n("The certificate's CA (Certificate Authority) is not allowed to sign certificates."); 01118 case KSSLCertificate::ApplicationVerificationFailed: 01119 return i18n("OpenSSL could not be verified."); 01120 01121 01122 // this is obsolete and kept around for backwards compatibility, only 01123 case KSSLCertificate::SignatureFailed: 01124 return i18n("The signature test for this certificate failed. This could mean that the signature of this certificate or any in its trust path are invalid, could not be decoded or that the CRL (Certificate Revocation List) could not be verified. If you see this message, please let the author of the software you are using know that he or she should use the new, more specific error messages."); 01125 case KSSLCertificate::Expired: 01126 return i18n("This certificate, any in its trust path or its CA's (Certificate Authority) CRL (Certificate Revocation List) is not valid. Any of them could not be valid yet or not valid any more. If you see this message, please let the author of the software you are using know that he or she should use the new, more specific error messages."); 01127 // continue 'useful' messages 01128 01129 // other error messages 01130 case KSSLCertificate::ErrorReadingRoot: 01131 case KSSLCertificate::NoCARoot: 01132 return i18n("Certificate signing authority root files could not be found so the certificate is not verified."); 01133 case KSSLCertificate::NoSSL: 01134 return i18n("SSL support was not found."); 01135 case KSSLCertificate::PrivateKeyFailed: 01136 return i18n("Private key test failed."); 01137 case KSSLCertificate::InvalidHost: 01138 return i18n("The certificate has not been issued for this host."); 01139 case KSSLCertificate::Irrelevant: 01140 return i18n("This certificate is not relevant."); 01141 default: 01142 break; 01143 } 01144 01145 return i18n("The certificate is invalid."); 01146 } 01147 01148 01149 QByteArray KSSLCertificate::toDer() { 01150 QByteArray qba; 01151 #ifdef KSSL_HAVE_SSL 01152 int certlen = d->kossl->i2d_X509(getCert(), NULL); 01153 if (certlen >= 0) { 01154 // These should technically be unsigned char * but it doesn't matter 01155 // for our purposes 01156 char *cert = new char[certlen]; 01157 unsigned char *p = (unsigned char *)cert; 01158 // FIXME: return code! 01159 d->kossl->i2d_X509(getCert(), &p); 01160 01161 // encode it into a QString 01162 qba = QByteArray(cert, certlen); 01163 delete[] cert; 01164 } 01165 #endif 01166 return qba; 01167 } 01168 01169 01170 01171 QByteArray KSSLCertificate::toPem() { 01172 QByteArray qba; 01173 QString thecert = toString(); 01174 const char *header = "-----BEGIN CERTIFICATE-----\n"; 01175 const char *footer = "-----END CERTIFICATE-----\n"; 01176 01177 // We just do base64 on the ASN1 01178 // 64 character lines (unpadded) 01179 unsigned int xx = thecert.length() - 1; 01180 for (unsigned int i = 0; i < xx/64; i++) { 01181 thecert.insert(64*(i+1)+i, '\n'); 01182 } 01183 01184 thecert.prepend(header); 01185 01186 if (thecert[thecert.length()-1] != '\n') { 01187 thecert += '\n'; 01188 } 01189 01190 thecert.append(footer); 01191 01192 qba = thecert.toLocal8Bit(); 01193 return qba; 01194 } 01195 01196 01197 #define NETSCAPE_CERT_HDR "certificate" 01198 01199 #ifdef KSSL_HAVE_SSL 01200 #if OPENSSL_VERSION_NUMBER < 0x00909000L 01201 01202 typedef struct NETSCAPE_X509_st 01203 { 01204 ASN1_OCTET_STRING *header; 01205 X509 *cert; 01206 } NETSCAPE_X509; 01207 #endif 01208 #endif 01209 01210 // what a piece of crap this is 01211 QByteArray KSSLCertificate::toNetscape() { 01212 QByteArray qba; 01213 #ifdef KSSL_HAVE_SSL 01214 NETSCAPE_X509 nx; 01215 ASN1_OCTET_STRING hdr; 01216 KTemporaryFile ktf; 01217 ktf.open(); 01218 FILE *ktf_fs = fopen(ktf.fileName().toAscii(), "r+"); 01219 01220 hdr.data = (unsigned char *)NETSCAPE_CERT_HDR; 01221 hdr.length = strlen(NETSCAPE_CERT_HDR); 01222 nx.header = &hdr; 01223 nx.cert = getCert(); 01224 01225 d->kossl->ASN1_item_i2d_fp(ktf_fs,(unsigned char *)&nx); 01226 fclose(ktf_fs); 01227 01228 QFile qf(ktf.fileName()); 01229 qf.open(QIODevice::ReadOnly); 01230 char *buf = new char[qf.size()]; 01231 qf.read(buf, qf.size()); 01232 qba = QByteArray(buf, qf.size()); 01233 qf.close(); 01234 delete[] buf; 01235 01236 #endif 01237 return qba; 01238 } 01239 01240 01241 01242 QString KSSLCertificate::toText() { 01243 QString text; 01244 #ifdef KSSL_HAVE_SSL 01245 KTemporaryFile ktf; 01246 ktf.open(); 01247 FILE *ktf_fs = fopen(ktf.fileName().toAscii(), "r+"); 01248 01249 d->kossl->X509_print(ktf_fs, getCert()); 01250 fclose(ktf_fs); 01251 01252 QFile qf(ktf.fileName()); 01253 qf.open(QIODevice::ReadOnly); 01254 char *buf = new char[qf.size()+1]; 01255 qf.read(buf, qf.size()); 01256 buf[qf.size()] = 0; 01257 text = buf; 01258 delete[] buf; 01259 qf.close(); 01260 #endif 01261 return text; 01262 } 01263 01264 bool KSSLCertificate::setCert(const QString& cert) { 01265 #ifdef KSSL_HAVE_SSL 01266 QByteArray qba, qbb = cert.toLocal8Bit(); 01267 qba = QByteArray::fromBase64(qbb); 01268 unsigned char *qbap = reinterpret_cast<unsigned char *>(qba.data()); 01269 X509 *x5c = KOSSL::self()->d2i_X509(NULL, &qbap, qba.size()); 01270 if (x5c) { 01271 setCert(x5c); 01272 return true; 01273 } 01274 #endif 01275 return false; 01276 } 01277 01278 01279 KSSLX509V3& KSSLCertificate::x509V3Extensions() { 01280 return d->_extensions; 01281 } 01282 01283 01284 bool KSSLCertificate::isSigner() { 01285 return d->_extensions.certTypeCA(); 01286 } 01287 01288 01289 QStringList KSSLCertificate::subjAltNames() const { 01290 QStringList rc; 01291 #ifdef KSSL_HAVE_SSL 01292 STACK_OF(GENERAL_NAME) *names; 01293 names = (STACK_OF(GENERAL_NAME)*)d->kossl->X509_get_ext_d2i(d->m_cert, NID_subject_alt_name, 0, 0); 01294 01295 if (!names) { 01296 return rc; 01297 } 01298 01299 int cnt = d->kossl->sk_GENERAL_NAME_num(names); 01300 01301 for (int i = 0; i < cnt; i++) { 01302 const GENERAL_NAME *val = (const GENERAL_NAME *)d->kossl->sk_value(names, i); 01303 if (val->type != GEN_DNS) { 01304 continue; 01305 } 01306 01307 QString s = (const char *)d->kossl->ASN1_STRING_data(val->d.ia5); 01308 if (!s.isEmpty() && 01309 /* skip subjectAltNames with embedded NULs */ 01310 s.length() == d->kossl->ASN1_STRING_length(val->d.ia5)) { 01311 rc += s; 01312 } 01313 } 01314 d->kossl->sk_free(names); 01315 #endif 01316 return rc; 01317 } 01318 01319 01320 QDataStream& operator<<(QDataStream& s, const KSSLCertificate& r) { 01321 QStringList qsl; 01322 QList<KSSLCertificate *> cl = const_cast<KSSLCertificate&>(r).chain().getChain(); 01323 01324 foreach(KSSLCertificate *c, cl) { 01325 qsl << c->toString(); 01326 } 01327 01328 qDeleteAll(cl); 01329 s << const_cast<KSSLCertificate&>(r).toString() << qsl; 01330 01331 return s; 01332 } 01333 01334 01335 QDataStream& operator>>(QDataStream& s, KSSLCertificate& r) { 01336 QStringList qsl; 01337 QString cert; 01338 01339 s >> cert >> qsl; 01340 01341 if (r.setCert(cert) && !qsl.isEmpty()) { 01342 r.chain().setCertChain(qsl); 01343 } 01344 01345 return s; 01346 } 01347 01348 01349
KDE 4.6 API Reference