File indexing completed on 2023-09-24 04:05:19
0001 /* This file is part of the KDE project 0002 * 0003 * Copyright (C) 2000-2003 George Staikos <staikos@kde.org> 0004 * 2008 Richard Hartmann <richih-kde@net.in.tum.de> 0005 * 0006 * This library is free software; you can redistribute it and/or 0007 * modify it under the terms of the GNU Library General Public 0008 * License as published by the Free Software Foundation; either 0009 * version 2 of the License, or (at your option) any later version. 0010 * 0011 * This library is distributed in the hope that it will be useful, 0012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0014 * Library General Public License for more details. 0015 * 0016 * You should have received a copy of the GNU Library General Public License 0017 * along with this library; see the file COPYING.LIB. If not, write to 0018 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0019 * Boston, MA 02110-1301, USA. 0020 */ 0021 0022 #include "ksslcertificate.h" 0023 0024 #include <ksslconfig.h> // KSSL_HAVE_SSL 0025 0026 #include <unistd.h> 0027 #include <QString> 0028 #include <QStringList> 0029 #include <QFile> 0030 #include <QStandardPaths> 0031 #include <QDate> 0032 #include <QDebug> 0033 #include <QDataStream> 0034 #include <qplatformdefs.h> 0035 #include <qtemporaryfile.h> 0036 0037 #include "ksslcertchain.h" 0038 #include "ksslutils.h" 0039 0040 #include <klocalizedstring.h> 0041 0042 #include <sys/types.h> 0043 0044 #include <config-kdelibs4support.h> // HAVE_SYS_STAT_H 0045 0046 #if HAVE_SYS_STAT_H 0047 #include <sys/stat.h> 0048 #endif 0049 0050 // this hack provided by Malte Starostik to avoid glibc/openssl bug 0051 // on some systems 0052 #if KSSL_HAVE_SSL 0053 #define crypt _openssl_crypt 0054 #include <openssl/ssl.h> 0055 #include <openssl/x509.h> 0056 #include <openssl/x509v3.h> 0057 #include <openssl/x509_vfy.h> 0058 #include <openssl/pem.h> 0059 #undef crypt 0060 #endif 0061 0062 #include <kopenssl.h> 0063 #include "ksslx509v3.h" 0064 0065 static const char hv[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; 0066 0067 class KSSLCertificatePrivate 0068 { 0069 public: 0070 KSSLCertificatePrivate() 0071 { 0072 kossl = KOSSL::self(); 0073 _lastPurpose = KSSLCertificate::None; 0074 } 0075 0076 ~KSSLCertificatePrivate() 0077 { 0078 } 0079 0080 KSSLCertificate::KSSLValidation m_stateCache; 0081 bool m_stateCached; 0082 #if KSSL_HAVE_SSL 0083 X509 *m_cert; 0084 #endif 0085 KOSSL *kossl; 0086 KSSLCertChain _chain; 0087 KSSLX509V3 _extensions; 0088 KSSLCertificate::KSSLPurpose _lastPurpose; 0089 }; 0090 0091 KSSLCertificate::KSSLCertificate() 0092 { 0093 d = new KSSLCertificatePrivate; 0094 d->m_stateCached = false; 0095 #if KSSL_HAVE_SSL 0096 d->m_cert = nullptr; 0097 #endif 0098 } 0099 0100 KSSLCertificate::KSSLCertificate(const KSSLCertificate &x) 0101 { 0102 d = new KSSLCertificatePrivate; 0103 d->m_stateCached = false; 0104 #if KSSL_HAVE_SSL 0105 d->m_cert = nullptr; 0106 setCert(KOSSL::self()->X509_dup(const_cast<KSSLCertificate &>(x).getCert())); 0107 KSSLCertChain *c = x.d->_chain.replicate(); 0108 setChain(c->rawChain()); 0109 delete c; 0110 #endif 0111 } 0112 0113 KSSLCertificate::~KSSLCertificate() 0114 { 0115 #if KSSL_HAVE_SSL 0116 if (d->m_cert) { 0117 d->kossl->X509_free(d->m_cert); 0118 } 0119 #endif 0120 delete d; 0121 } 0122 0123 KSSLCertChain &KSSLCertificate::chain() 0124 { 0125 return d->_chain; 0126 } 0127 0128 KSSLCertificate *KSSLCertificate::fromX509(X509 *x5) 0129 { 0130 KSSLCertificate *n = nullptr; 0131 #if KSSL_HAVE_SSL 0132 if (x5) { 0133 n = new KSSLCertificate; 0134 n->setCert(KOSSL::self()->X509_dup(x5)); 0135 } 0136 #endif 0137 return n; 0138 } 0139 0140 KSSLCertificate *KSSLCertificate::fromString(const QByteArray &cert) 0141 { 0142 KSSLCertificate *n = nullptr; 0143 #if KSSL_HAVE_SSL 0144 if (cert.isEmpty()) { 0145 return nullptr; 0146 } 0147 0148 QByteArray qba = QByteArray::fromBase64(cert); 0149 unsigned char *qbap = reinterpret_cast<unsigned char *>(qba.data()); 0150 X509 *x5c = KOSSL::self()->d2i_X509(nullptr, &qbap, qba.size()); 0151 if (!x5c) { 0152 return nullptr; 0153 } 0154 0155 n = new KSSLCertificate; 0156 n->setCert(x5c); 0157 #endif 0158 return n; 0159 } 0160 0161 QString KSSLCertificate::getSubject() const 0162 { 0163 QString rc = ""; 0164 0165 #if KSSL_HAVE_SSL 0166 char *t = d->kossl->X509_NAME_oneline(d->kossl->X509_get_subject_name(d->m_cert), nullptr, 0); 0167 if (!t) { 0168 return rc; 0169 } 0170 rc = t; 0171 d->kossl->OPENSSL_free(t); 0172 #endif 0173 return rc; 0174 } 0175 0176 QString KSSLCertificate::getSerialNumber() const 0177 { 0178 QString rc = ""; 0179 0180 #if KSSL_HAVE_SSL 0181 ASN1_INTEGER *aint = d->kossl->X509_get_serialNumber(d->m_cert); 0182 if (aint) { 0183 rc = ASN1_INTEGER_QString(aint); 0184 // d->kossl->ASN1_INTEGER_free(aint); this makes the sig test fail 0185 } 0186 #endif 0187 return rc; 0188 } 0189 0190 QString KSSLCertificate::getSignatureText() const 0191 { 0192 QString rc = ""; 0193 0194 #if KSSL_HAVE_SSL 0195 char *s; 0196 int n, i; 0197 0198 const X509_ALGOR *algor; 0199 const ASN1_BIT_STRING *sig; 0200 d->kossl->X509_get0_signature(&sig, &algor, d->m_cert); 0201 i = d->kossl->OBJ_obj2nid(algor->algorithm); 0202 rc = i18n("Signature Algorithm: "); 0203 rc += (i == NID_undef) ? i18n("Unknown") : QString(d->kossl->OBJ_nid2ln(i)); 0204 0205 rc += '\n'; 0206 rc += i18n("Signature Contents:"); 0207 n = sig->length; 0208 s = (char *)sig->data; 0209 for (i = 0; i < n; ++i) { 0210 if (i % 20 != 0) { 0211 rc += ':'; 0212 } else { 0213 rc += '\n'; 0214 } 0215 rc.append(QChar(hv[(s[i] & 0xf0) >> 4])); 0216 rc.append(QChar(hv[s[i] & 0x0f])); 0217 } 0218 0219 #endif 0220 0221 return rc; 0222 } 0223 0224 void KSSLCertificate::getEmails(QStringList &to) const 0225 { 0226 to.clear(); 0227 #if KSSL_HAVE_SSL 0228 if (!d->m_cert) { 0229 return; 0230 } 0231 0232 STACK *s = d->kossl->X509_get1_email(d->m_cert); 0233 const int size = d->kossl->OPENSSL_sk_num(s); 0234 if (s) { 0235 for (int n = 0; n < size; n++) { 0236 to.append(d->kossl->OPENSSL_sk_value(s, n)); 0237 } 0238 d->kossl->X509_email_free(s); 0239 } 0240 #endif 0241 } 0242 0243 QString KSSLCertificate::getKDEKey() const 0244 { 0245 return getSubject() + " (" + getMD5DigestText() + ')'; 0246 } 0247 0248 QString KSSLCertificate::getMD5DigestFromKDEKey(const QString &k) 0249 { 0250 QString rc; 0251 int pos = k.lastIndexOf('('); 0252 if (pos != -1) { 0253 unsigned int len = k.length(); 0254 if (k.at(len - 1) == ')') { 0255 rc = k.mid(pos + 1, len - pos - 2); 0256 } 0257 } 0258 return rc; 0259 } 0260 0261 QString KSSLCertificate::getMD5DigestText() const 0262 { 0263 QString rc = ""; 0264 0265 #if KSSL_HAVE_SSL 0266 unsigned int n; 0267 unsigned char md[EVP_MAX_MD_SIZE]; 0268 0269 if (!d->kossl->X509_digest(d->m_cert, d->kossl->EVP_md5(), md, &n)) { 0270 return rc; 0271 } 0272 0273 for (unsigned int j = 0; j < n; j++) { 0274 if (j > 0) { 0275 rc += ':'; 0276 } 0277 rc.append(QChar(hv[(md[j] & 0xf0) >> 4])); 0278 rc.append(QChar(hv[md[j] & 0x0f])); 0279 } 0280 0281 #endif 0282 0283 return rc; 0284 } 0285 0286 QString KSSLCertificate::getMD5Digest() const 0287 { 0288 QString rc = ""; 0289 0290 #if KSSL_HAVE_SSL 0291 unsigned int n; 0292 unsigned char md[EVP_MAX_MD_SIZE]; 0293 0294 if (!d->kossl->X509_digest(d->m_cert, d->kossl->EVP_md5(), md, &n)) { 0295 return rc; 0296 } 0297 0298 for (unsigned int j = 0; j < n; j++) { 0299 rc.append(QLatin1Char(hv[(md[j] & 0xf0) >> 4])); 0300 rc.append(QLatin1Char(hv[md[j] & 0x0f])); 0301 } 0302 0303 #endif 0304 0305 return rc; 0306 } 0307 0308 QString KSSLCertificate::getKeyType() const 0309 { 0310 QString rc = ""; 0311 0312 #if KSSL_HAVE_SSL 0313 EVP_PKEY *pkey = d->kossl->X509_get_pubkey(d->m_cert); 0314 if (pkey) { 0315 #ifndef NO_RSA 0316 if (d->kossl->EVP_PKEY_base_id(pkey) == EVP_PKEY_RSA) { 0317 rc = "RSA"; 0318 } else 0319 #endif 0320 #ifndef NO_DSA 0321 if (d->kossl->EVP_PKEY_base_id(pkey) == EVP_PKEY_DSA) { 0322 rc = "DSA"; 0323 } else 0324 #endif 0325 rc = "Unknown"; 0326 d->kossl->EVP_PKEY_free(pkey); 0327 } 0328 #endif 0329 0330 return rc; 0331 } 0332 0333 QString KSSLCertificate::getPublicKeyText() const 0334 { 0335 QString rc = ""; 0336 char *x = nullptr; 0337 0338 #if KSSL_HAVE_SSL 0339 EVP_PKEY *pkey = d->kossl->X509_get_pubkey(d->m_cert); 0340 if (pkey) { 0341 rc = i18nc("Unknown", "Unknown key algorithm"); 0342 #ifndef NO_RSA 0343 if (d->kossl->EVP_PKEY_base_id(pkey) == EVP_PKEY_RSA) { 0344 const BIGNUM *n, *e; 0345 d->kossl->RSA_get0_key(d->kossl->EVP_PKEY_get0_RSA(pkey), &n, &e, nullptr); 0346 x = d->kossl->BN_bn2hex(n); 0347 rc = i18n("Key type: RSA (%1 bit)", strlen(x) * 4) + '\n'; 0348 0349 rc += i18n("Modulus: "); 0350 for (unsigned int i = 0; i < strlen(x); i++) { 0351 if (i % 40 != 0 && i % 2 == 0) { 0352 rc += ':'; 0353 } else if (i % 40 == 0) { 0354 rc += '\n'; 0355 } 0356 rc += x[i]; 0357 } 0358 rc += '\n'; 0359 d->kossl->OPENSSL_free(x); 0360 0361 x = d->kossl->BN_bn2hex(e); 0362 rc += i18n("Exponent: 0x") + QLatin1String(x) + 0363 QLatin1String("\n"); 0364 d->kossl->OPENSSL_free(x); 0365 } 0366 #endif 0367 #ifndef NO_DSA 0368 if (d->kossl->EVP_PKEY_base_id(pkey) == EVP_PKEY_DSA) { 0369 auto dsa = d->kossl->EVP_PKEY_get0_DSA(pkey); 0370 const BIGNUM *p, *q, *g; 0371 d->kossl->DSA_get0_pqg(dsa, &p, &q, &g); 0372 x = d->kossl->BN_bn2hex(p); 0373 // hack - this may not be always accurate 0374 rc = i18n("Key type: DSA (%1 bit)", strlen(x) * 4) + '\n'; 0375 0376 rc += i18n("Prime: "); 0377 for (unsigned int i = 0; i < strlen(x); i++) { 0378 if (i % 40 != 0 && i % 2 == 0) { 0379 rc += ':'; 0380 } else if (i % 40 == 0) { 0381 rc += '\n'; 0382 } 0383 rc += x[i]; 0384 } 0385 rc += '\n'; 0386 d->kossl->OPENSSL_free(x); 0387 0388 x = d->kossl->BN_bn2hex(q); 0389 rc += i18n("160 bit prime factor: "); 0390 for (unsigned int i = 0; i < strlen(x); i++) { 0391 if (i % 40 != 0 && i % 2 == 0) { 0392 rc += ':'; 0393 } else if (i % 40 == 0) { 0394 rc += '\n'; 0395 } 0396 rc += x[i]; 0397 } 0398 rc += '\n'; 0399 d->kossl->OPENSSL_free(x); 0400 0401 x = d->kossl->BN_bn2hex(g); 0402 rc += QString("g: "); 0403 for (unsigned int i = 0; i < strlen(x); i++) { 0404 if (i % 40 != 0 && i % 2 == 0) { 0405 rc += ':'; 0406 } else if (i % 40 == 0) { 0407 rc += '\n'; 0408 } 0409 rc += x[i]; 0410 } 0411 rc += '\n'; 0412 d->kossl->OPENSSL_free(x); 0413 0414 const BIGNUM *pub_key; 0415 d->kossl->DSA_get0_key(dsa, &pub_key, nullptr); 0416 x = d->kossl->BN_bn2hex(pub_key); 0417 rc += i18n("Public key: "); 0418 for (unsigned int i = 0; i < strlen(x); i++) { 0419 if (i % 40 != 0 && i % 2 == 0) { 0420 rc += ':'; 0421 } else if (i % 40 == 0) { 0422 rc += '\n'; 0423 } 0424 rc += x[i]; 0425 } 0426 rc += '\n'; 0427 d->kossl->OPENSSL_free(x); 0428 } 0429 #endif 0430 d->kossl->EVP_PKEY_free(pkey); 0431 } 0432 #endif 0433 0434 return rc; 0435 } 0436 0437 QString KSSLCertificate::getIssuer() const 0438 { 0439 QString rc = ""; 0440 0441 #if KSSL_HAVE_SSL 0442 char *t = d->kossl->X509_NAME_oneline(d->kossl->X509_get_issuer_name(d->m_cert), nullptr, 0); 0443 0444 if (!t) { 0445 return rc; 0446 } 0447 0448 rc = t; 0449 d->kossl->OPENSSL_free(t); 0450 #endif 0451 0452 return rc; 0453 } 0454 0455 void KSSLCertificate::setChain(void *c) 0456 { 0457 #if KSSL_HAVE_SSL 0458 d->_chain.setChain(c); 0459 #endif 0460 d->m_stateCached = false; 0461 d->m_stateCache = KSSLCertificate::Unknown; 0462 } 0463 0464 void KSSLCertificate::setCert(X509 *c) 0465 { 0466 #if KSSL_HAVE_SSL 0467 d->m_cert = c; 0468 if (c) { 0469 d->_extensions.flags = 0; 0470 d->kossl->X509_check_purpose(c, -1, 0); // setup the fields (!!) 0471 0472 #if 0 0473 qDebug() << "---------------- Certificate ------------------"; 0474 qDebug() << getSubject(); 0475 #endif 0476 0477 for (int j = 0; j < d->kossl->X509_PURPOSE_get_count(); j++) { 0478 X509_PURPOSE *ptmp = d->kossl->X509_PURPOSE_get0(j); 0479 int id = d->kossl->X509_PURPOSE_get_id(ptmp); 0480 for (int ca = 0; ca < 2; ca++) { 0481 int idret = d->kossl->X509_check_purpose(c, id, ca); 0482 if (idret == 1 || idret == 2) { // have it 0483 // qDebug() << "PURPOSE: " << id << (ca?" CA":""); 0484 if (!ca) { 0485 d->_extensions.flags |= (1L << (id - 1)); 0486 } else { 0487 d->_extensions.flags |= (1L << (16 + id - 1)); 0488 } 0489 } else { 0490 if (!ca) { 0491 d->_extensions.flags &= ~(1L << (id - 1)); 0492 } else { 0493 d->_extensions.flags &= ~(1L << (16 + id - 1)); 0494 } 0495 } 0496 } 0497 } 0498 0499 #if 0 0500 qDebug() << "flags: " << QString::number(c->ex_flags, 2) 0501 << "\nkeyusage: " << QString::number(c->ex_kusage, 2) 0502 << "\nxkeyusage: " << QString::number(c->ex_xkusage, 2) 0503 << "\nnscert: " << QString::number(c->ex_nscert, 2); 0504 if (c->ex_flags & EXFLAG_KUSAGE) { 0505 qDebug() << " --- Key Usage extensions found"; 0506 } else { 0507 qDebug() << " --- Key Usage extensions NOT found"; 0508 } 0509 0510 if (c->ex_flags & EXFLAG_XKUSAGE) { 0511 qDebug() << " --- Extended key usage extensions found"; 0512 } else { 0513 qDebug() << " --- Extended key usage extensions NOT found"; 0514 } 0515 0516 if (c->ex_flags & EXFLAG_NSCERT) { 0517 qDebug() << " --- NS extensions found"; 0518 } else { 0519 qDebug() << " --- NS extensions NOT found"; 0520 } 0521 0522 if (d->_extensions.certTypeSSLCA()) { 0523 qDebug() << "NOTE: this is an SSL CA file."; 0524 } else { 0525 qDebug() << "NOTE: this is NOT an SSL CA file."; 0526 } 0527 0528 if (d->_extensions.certTypeEmailCA()) { 0529 qDebug() << "NOTE: this is an EMAIL CA file."; 0530 } else { 0531 qDebug() << "NOTE: this is NOT an EMAIL CA file."; 0532 } 0533 0534 if (d->_extensions.certTypeCodeCA()) { 0535 qDebug() << "NOTE: this is a CODE CA file."; 0536 } else { 0537 qDebug() << "NOTE: this is NOT a CODE CA file."; 0538 } 0539 0540 if (d->_extensions.certTypeSSLClient()) { 0541 qDebug() << "NOTE: this is an SSL client."; 0542 } else { 0543 qDebug() << "NOTE: this is NOT an SSL client."; 0544 } 0545 0546 if (d->_extensions.certTypeSSLServer()) { 0547 qDebug() << "NOTE: this is an SSL server."; 0548 } else { 0549 qDebug() << "NOTE: this is NOT an SSL server."; 0550 } 0551 0552 if (d->_extensions.certTypeNSSSLServer()) { 0553 qDebug() << "NOTE: this is a NETSCAPE SSL server."; 0554 } else { 0555 qDebug() << "NOTE: this is NOT a NETSCAPE SSL server."; 0556 } 0557 0558 if (d->_extensions.certTypeSMIME()) { 0559 qDebug() << "NOTE: this is an SMIME certificate."; 0560 } else { 0561 qDebug() << "NOTE: this is NOT an SMIME certificate."; 0562 } 0563 0564 if (d->_extensions.certTypeSMIMEEncrypt()) { 0565 qDebug() << "NOTE: this is an SMIME encrypt cert."; 0566 } else { 0567 qDebug() << "NOTE: this is NOT an SMIME encrypt cert."; 0568 } 0569 0570 if (d->_extensions.certTypeSMIMESign()) { 0571 qDebug() << "NOTE: this is an SMIME sign cert."; 0572 } else { 0573 qDebug() << "NOTE: this is NOT an SMIME sign cert."; 0574 } 0575 0576 if (d->_extensions.certTypeCRLSign()) { 0577 qDebug() << "NOTE: this is a CRL signer."; 0578 } else { 0579 qDebug() << "NOTE: this is NOT a CRL signer."; 0580 } 0581 0582 qDebug() << "-----------------------------------------------"; 0583 #endif 0584 } 0585 #endif 0586 d->m_stateCached = false; 0587 d->m_stateCache = KSSLCertificate::Unknown; 0588 } 0589 0590 X509 *KSSLCertificate::getCert() 0591 { 0592 #if KSSL_HAVE_SSL 0593 return d->m_cert; 0594 #endif 0595 return nullptr; 0596 } 0597 0598 // pull in the callback. It's common across multiple files but we want 0599 // it to be hidden. 0600 0601 #include "ksslcallback.c" 0602 0603 bool KSSLCertificate::isValid(KSSLCertificate::KSSLPurpose p) 0604 { 0605 return (validate(p) == KSSLCertificate::Ok); 0606 } 0607 0608 bool KSSLCertificate::isValid() 0609 { 0610 return isValid(KSSLCertificate::SSLServer); 0611 } 0612 0613 int KSSLCertificate::purposeToOpenSSL(KSSLCertificate::KSSLPurpose p) const 0614 { 0615 int rc = 0; 0616 #if KSSL_HAVE_SSL 0617 if (p == KSSLCertificate::SSLServer) { 0618 rc = X509_PURPOSE_SSL_SERVER; 0619 } else if (p == KSSLCertificate::SSLClient) { 0620 rc = X509_PURPOSE_SSL_CLIENT; 0621 } else if (p == KSSLCertificate::SMIMEEncrypt) { 0622 rc = X509_PURPOSE_SMIME_ENCRYPT; 0623 } else if (p == KSSLCertificate::SMIMESign) { 0624 rc = X509_PURPOSE_SMIME_SIGN; 0625 } else if (p == KSSLCertificate::Any) { 0626 rc = X509_PURPOSE_ANY; 0627 } 0628 #endif 0629 return rc; 0630 } 0631 0632 // For backward compatibility 0633 KSSLCertificate::KSSLValidation KSSLCertificate::validate() 0634 { 0635 return validate(KSSLCertificate::SSLServer); 0636 } 0637 0638 KSSLCertificate::KSSLValidation KSSLCertificate::validate(KSSLCertificate::KSSLPurpose purpose) 0639 { 0640 KSSLValidationList result = validateVerbose(purpose); 0641 if (result.isEmpty()) { 0642 return KSSLCertificate::Ok; 0643 } else { 0644 return result.first(); 0645 } 0646 } 0647 0648 // 0649 // See apps/verify.c in OpenSSL for the source of most of this logic. 0650 // 0651 0652 // CRL files? we don't do that yet 0653 KSSLCertificate::KSSLValidationList KSSLCertificate::validateVerbose(KSSLCertificate::KSSLPurpose purpose) 0654 { 0655 return validateVerbose(purpose, nullptr); 0656 } 0657 0658 KSSLCertificate::KSSLValidationList KSSLCertificate::validateVerbose(KSSLCertificate::KSSLPurpose purpose, KSSLCertificate *ca) 0659 { 0660 KSSLValidationList errors; 0661 if (ca || (d->_lastPurpose != purpose)) { 0662 d->m_stateCached = false; 0663 } 0664 0665 if (!d->m_stateCached) { 0666 d->_lastPurpose = purpose; 0667 } 0668 0669 #if KSSL_HAVE_SSL 0670 X509_STORE *certStore; 0671 X509_LOOKUP *certLookup; 0672 X509_STORE_CTX *certStoreCTX; 0673 int rc = 0; 0674 0675 if (!d->m_cert) { 0676 errors << KSSLCertificate::Unknown; 0677 return errors; 0678 } 0679 0680 if (d->m_stateCached) { 0681 errors << d->m_stateCache; 0682 return errors; 0683 } 0684 0685 const QStringList qsl = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, "kf5/kssl", QStandardPaths::LocateDirectory); 0686 0687 if (qsl.isEmpty()) { 0688 errors << KSSLCertificate::NoCARoot; 0689 return errors; 0690 } 0691 0692 KSSLCertificate::KSSLValidation ksslv = Unknown; 0693 0694 for (QStringList::ConstIterator j = qsl.begin(); j != qsl.end(); ++j) { 0695 QString _j = (*j) + "ca-bundle.crt"; 0696 if (!QFile::exists(_j)) { 0697 continue; 0698 } 0699 0700 certStore = d->kossl->X509_STORE_new(); 0701 if (!certStore) { 0702 errors << KSSLCertificate::Unknown; 0703 return errors; 0704 } 0705 0706 d->kossl->X509_STORE_set_verify_cb(certStore, X509Callback); 0707 0708 certLookup = d->kossl->X509_STORE_add_lookup(certStore, d->kossl->X509_LOOKUP_file()); 0709 if (!certLookup) { 0710 ksslv = KSSLCertificate::Unknown; 0711 d->kossl->X509_STORE_free(certStore); 0712 continue; 0713 } 0714 0715 if (!d->kossl->X509_LOOKUP_load_file(certLookup, _j.toLatin1().constData(), X509_FILETYPE_PEM)) { 0716 // error accessing directory and loading pems 0717 qDebug() << "KSSL couldn't read CA root: " << _j; 0718 ksslv = KSSLCertificate::ErrorReadingRoot; 0719 d->kossl->X509_STORE_free(certStore); 0720 continue; 0721 } 0722 0723 // This is the checking code 0724 certStoreCTX = d->kossl->X509_STORE_CTX_new(); 0725 0726 // this is a bad error - could mean no free memory. 0727 // This may be the wrong thing to do here 0728 if (!certStoreCTX) { 0729 qDebug() << "KSSL couldn't create an X509 store context."; 0730 d->kossl->X509_STORE_free(certStore); 0731 continue; 0732 } 0733 0734 d->kossl->X509_STORE_CTX_init(certStoreCTX, certStore, d->m_cert, nullptr); 0735 if (d->_chain.isValid()) { 0736 d->kossl->X509_STORE_CTX_set_chain(certStoreCTX, (STACK_OF(X509) *)d->_chain.rawChain()); 0737 } 0738 0739 //qDebug() << "KSSL setting CRL.............."; 0740 // int X509_STORE_add_crl(X509_STORE *ctx, X509_CRL *x); 0741 0742 d->kossl->X509_STORE_CTX_set_purpose(certStoreCTX, purposeToOpenSSL(purpose)); 0743 0744 KSSL_X509CallBack_ca = ca ? ca->d->m_cert : nullptr; 0745 KSSL_X509CallBack_ca_found = false; 0746 0747 d->kossl->X509_STORE_CTX_set_error(certStoreCTX, X509_V_OK); 0748 rc = d->kossl->X509_verify_cert(certStoreCTX); 0749 int errcode = d->kossl->X509_STORE_CTX_get_error(certStoreCTX); 0750 if (ca && !KSSL_X509CallBack_ca_found) { 0751 ksslv = KSSLCertificate::Irrelevant; 0752 } else { 0753 ksslv = processError(errcode); 0754 } 0755 // For servers, we can try NS_SSL_SERVER too 0756 if ((ksslv != KSSLCertificate::Ok) && 0757 (ksslv != KSSLCertificate::Irrelevant) && 0758 purpose == KSSLCertificate::SSLServer) { 0759 d->kossl->X509_STORE_CTX_set_purpose(certStoreCTX, 0760 X509_PURPOSE_NS_SSL_SERVER); 0761 0762 d->kossl->X509_STORE_CTX_set_error(certStoreCTX, X509_V_OK); 0763 rc = d->kossl->X509_verify_cert(certStoreCTX); 0764 errcode = d->kossl->X509_STORE_CTX_get_error(certStoreCTX); 0765 ksslv = processError(errcode); 0766 } 0767 d->kossl->X509_STORE_CTX_free(certStoreCTX); 0768 d->kossl->X509_STORE_free(certStore); 0769 // end of checking code 0770 // 0771 0772 //qDebug() << "KSSL Validation procedure RC: " 0773 // << rc << endl; 0774 //qDebug() << "KSSL Validation procedure errcode: " 0775 // << errcode << endl; 0776 //qDebug() << "KSSL Validation procedure RESULTS: " 0777 // << ksslv << endl; 0778 0779 if (ksslv != NoCARoot && ksslv != InvalidCA && ksslv != GetIssuerCertFailed && ksslv != DecodeIssuerPublicKeyFailed && ksslv != GetIssuerCertLocallyFailed) { 0780 d->m_stateCached = true; 0781 d->m_stateCache = ksslv; 0782 } 0783 break; 0784 } 0785 0786 if (ksslv != KSSLCertificate::Ok) { 0787 errors << ksslv; 0788 } 0789 #else 0790 errors << KSSLCertificate::NoSSL; 0791 #endif 0792 return errors; 0793 } 0794 0795 KSSLCertificate::KSSLValidation KSSLCertificate::revalidate() 0796 { 0797 return revalidate(KSSLCertificate::SSLServer); 0798 } 0799 0800 KSSLCertificate::KSSLValidation KSSLCertificate::revalidate(KSSLCertificate::KSSLPurpose p) 0801 { 0802 d->m_stateCached = false; 0803 return validate(p); 0804 } 0805 0806 KSSLCertificate::KSSLValidation KSSLCertificate::processError(int ec) 0807 { 0808 KSSLCertificate::KSSLValidation rc; 0809 0810 rc = KSSLCertificate::Unknown; 0811 #if KSSL_HAVE_SSL 0812 switch (ec) { 0813 0814 // see man 1 verify for a detailed listing of all error codes 0815 0816 // error 0 0817 case X509_V_OK: 0818 rc = KSSLCertificate::Ok; 0819 break; 0820 0821 // error 2 0822 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: 0823 rc = KSSLCertificate::GetIssuerCertFailed; 0824 break; 0825 0826 // error 3 0827 case X509_V_ERR_UNABLE_TO_GET_CRL: 0828 rc = KSSLCertificate::GetCRLFailed; 0829 break; 0830 0831 // error 4 0832 case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE: 0833 rc = KSSLCertificate::DecryptCertificateSignatureFailed; 0834 break; 0835 0836 // error 5 0837 case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE: 0838 rc = KSSLCertificate::DecryptCRLSignatureFailed; 0839 break; 0840 0841 // error 6 0842 case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY: 0843 rc = KSSLCertificate::DecodeIssuerPublicKeyFailed; 0844 break; 0845 0846 // error 7 0847 case X509_V_ERR_CERT_SIGNATURE_FAILURE: 0848 rc = KSSLCertificate::CertificateSignatureFailed; 0849 break; 0850 0851 // error 8 0852 case X509_V_ERR_CRL_SIGNATURE_FAILURE: 0853 rc = KSSLCertificate::CRLSignatureFailed; 0854 break; 0855 0856 // error 9 0857 case X509_V_ERR_CERT_NOT_YET_VALID: 0858 rc = KSSLCertificate::CertificateNotYetValid; 0859 break; 0860 0861 // error 10 0862 case X509_V_ERR_CERT_HAS_EXPIRED: 0863 rc = KSSLCertificate::CertificateHasExpired; 0864 qDebug() << "KSSL apparently this is expired. Not after:" << getNotAfter(); 0865 break; 0866 0867 // error 11 0868 case X509_V_ERR_CRL_NOT_YET_VALID: 0869 rc = KSSLCertificate::CRLNotYetValid; 0870 break; 0871 0872 // error 12 0873 case X509_V_ERR_CRL_HAS_EXPIRED: 0874 rc = KSSLCertificate::CRLHasExpired; 0875 break; 0876 0877 // error 13 0878 case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: 0879 rc = KSSLCertificate::CertificateFieldNotBeforeErroneous; 0880 break; 0881 0882 // error 14 0883 case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: 0884 rc = KSSLCertificate::CertificateFieldNotAfterErroneous; 0885 break; 0886 0887 // error 15 - unused as of OpenSSL 0.9.8g 0888 case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD: 0889 rc = KSSLCertificate::CRLFieldLastUpdateErroneous; 0890 break; 0891 0892 // error 16 - unused as of OpenSSL 0.9.8g 0893 case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD: 0894 rc = KSSLCertificate::CRLFieldNextUpdateErroneous; 0895 break; 0896 0897 // error 17 0898 case X509_V_ERR_OUT_OF_MEM: 0899 rc = KSSLCertificate::OutOfMemory; 0900 break; 0901 0902 // error 18 0903 case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: 0904 rc = KSSLCertificate::SelfSigned; 0905 break; 0906 0907 // error 19 0908 case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN: 0909 rc = KSSLCertificate::SelfSignedInChain; 0910 break; 0911 0912 // error 20 0913 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY: 0914 rc = KSSLCertificate::GetIssuerCertLocallyFailed; 0915 break; 0916 0917 // error 21 0918 case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE: 0919 rc = KSSLCertificate::VerifyLeafSignatureFailed; 0920 break; 0921 0922 // error 22 - unused as of OpenSSL 0.9.8g 0923 case X509_V_ERR_CERT_CHAIN_TOO_LONG: 0924 rc = KSSLCertificate::CertificateChainTooLong; 0925 break; 0926 0927 // error 23 - unused as of OpenSSL 0.9.8g 0928 case X509_V_ERR_CERT_REVOKED: 0929 rc = KSSLCertificate::CertificateRevoked; 0930 break; 0931 0932 // error 24 0933 case X509_V_ERR_INVALID_CA: 0934 rc = KSSLCertificate::InvalidCA; 0935 break; 0936 0937 // error 25 0938 case X509_V_ERR_PATH_LENGTH_EXCEEDED: 0939 rc = KSSLCertificate::PathLengthExceeded; 0940 break; 0941 0942 // error 26 0943 case X509_V_ERR_INVALID_PURPOSE: 0944 rc = KSSLCertificate::InvalidPurpose; 0945 break; 0946 0947 // error 27 0948 case X509_V_ERR_CERT_UNTRUSTED: 0949 rc = KSSLCertificate::CertificateUntrusted; 0950 break; 0951 0952 // error 28 0953 case X509_V_ERR_CERT_REJECTED: 0954 rc = KSSLCertificate::CertificateRejected; 0955 break; 0956 0957 // error 29 - only used with -issuer_checks 0958 case X509_V_ERR_SUBJECT_ISSUER_MISMATCH: 0959 rc = KSSLCertificate::IssuerSubjectMismatched; 0960 break; 0961 0962 // error 30 - only used with -issuer_checks 0963 case X509_V_ERR_AKID_SKID_MISMATCH: 0964 rc = KSSLCertificate::AuthAndSubjectKeyIDMismatched; 0965 break; 0966 0967 // error 31 - only used with -issuer_checks 0968 case X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH: 0969 rc = KSSLCertificate::AuthAndSubjectKeyIDAndNameMismatched; 0970 break; 0971 0972 // error 32 0973 case X509_V_ERR_KEYUSAGE_NO_CERTSIGN: 0974 rc = KSSLCertificate::KeyMayNotSignCertificate; 0975 break; 0976 0977 // error 50 - unused as of OpenSSL 0.9.8g 0978 case X509_V_ERR_APPLICATION_VERIFICATION: 0979 rc = KSSLCertificate::ApplicationVerificationFailed; 0980 break; 0981 0982 default: 0983 rc = KSSLCertificate::Unknown; 0984 break; 0985 } 0986 0987 d->m_stateCache = rc; 0988 d->m_stateCached = true; 0989 #endif 0990 return rc; 0991 } 0992 0993 QString KSSLCertificate::getNotBefore() const 0994 { 0995 #if KSSL_HAVE_SSL 0996 return ASN1_UTCTIME_QString(d->kossl->X509_getm_notBefore(d->m_cert)); 0997 #else 0998 return QString(); 0999 #endif 1000 } 1001 1002 QString KSSLCertificate::getNotAfter() const 1003 { 1004 #if KSSL_HAVE_SSL 1005 return ASN1_UTCTIME_QString(d->kossl->X509_getm_notAfter(d->m_cert)); 1006 #else 1007 return QString(); 1008 #endif 1009 } 1010 1011 QDateTime KSSLCertificate::getQDTNotBefore() const 1012 { 1013 #if KSSL_HAVE_SSL 1014 return ASN1_UTCTIME_QDateTime(d->kossl->X509_getm_notBefore(d->m_cert), nullptr); 1015 #else 1016 return QDateTime::currentDateTime(); 1017 #endif 1018 } 1019 1020 QDateTime KSSLCertificate::getQDTNotAfter() const 1021 { 1022 #if KSSL_HAVE_SSL 1023 return ASN1_UTCTIME_QDateTime(d->kossl->X509_getm_notAfter(d->m_cert), nullptr); 1024 #else 1025 return QDateTime::currentDateTime(); 1026 #endif 1027 } 1028 1029 int operator==(KSSLCertificate &x, KSSLCertificate &y) 1030 { 1031 #if !KSSL_HAVE_SSL 1032 return 1; 1033 #else 1034 if (!KOSSL::self()->X509_cmp(x.getCert(), y.getCert())) { 1035 return 1; 1036 } 1037 return 0; 1038 #endif 1039 } 1040 1041 KSSLCertificate *KSSLCertificate::replicate() 1042 { 1043 // The new certificate doesn't have the cached value. It's probably 1044 // better this way. We can't anticipate every reason for doing this. 1045 KSSLCertificate *newOne = new KSSLCertificate(); 1046 #if KSSL_HAVE_SSL 1047 newOne->setCert(d->kossl->X509_dup(getCert())); 1048 KSSLCertChain *c = d->_chain.replicate(); 1049 newOne->setChain(c->rawChain()); 1050 delete c; 1051 #endif 1052 return newOne; 1053 } 1054 1055 QString KSSLCertificate::toString() 1056 { 1057 return toDer().toBase64(); 1058 } 1059 1060 QString KSSLCertificate::verifyText(KSSLValidation x) 1061 { 1062 switch (x) { 1063 // messages for errors defined in verify(1) 1064 case KSSLCertificate::Ok: 1065 return i18n("The certificate is valid."); 1066 case KSSLCertificate::GetIssuerCertFailed: 1067 return i18n("Retrieval of the issuer certificate failed. This means the CA's (Certificate Authority) certificate can not be found."); 1068 case KSSLCertificate::GetCRLFailed: 1069 return i18n("Retrieval of the CRL (Certificate Revocation List) failed. This means the CA's (Certificate Authority) CRL can not be found."); 1070 case KSSLCertificate::DecryptCertificateSignatureFailed: 1071 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."); 1072 case KSSLCertificate::DecryptCRLSignatureFailed: 1073 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."); 1074 case KSSLCertificate::DecodeIssuerPublicKeyFailed: 1075 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."); 1076 case KSSLCertificate::CertificateSignatureFailed: 1077 return i18n("The certificate's signature is invalid. This means that the certificate can not be verified."); 1078 case KSSLCertificate::CRLSignatureFailed: 1079 return i18n("The CRL's (Certificate Revocation List) signature is invalid. This means that the CRL can not be verified."); 1080 case KSSLCertificate::CertificateNotYetValid: 1081 return i18n("The certificate is not valid, yet."); 1082 case KSSLCertificate::CertificateHasExpired: 1083 return i18n("The certificate is not valid, any more."); 1084 case KSSLCertificate::CRLNotYetValid: 1085 return i18n("The CRL (Certificate Revocation List) is not valid, yet."); 1086 case KSSLCertificate::CRLHasExpired: 1087 return i18n("The CRL (Certificate Revocation List) is not valid, yet."); 1088 case KSSLCertificate::CertificateFieldNotBeforeErroneous: 1089 return i18n("The time format of the certificate's 'notBefore' field is invalid."); 1090 case KSSLCertificate::CertificateFieldNotAfterErroneous: 1091 return i18n("The time format of the certificate's 'notAfter' field is invalid."); 1092 case KSSLCertificate::CRLFieldLastUpdateErroneous: 1093 return i18n("The time format of the CRL's (Certificate Revocation List) 'lastUpdate' field is invalid."); 1094 case KSSLCertificate::CRLFieldNextUpdateErroneous: 1095 return i18n("The time format of the CRL's (Certificate Revocation List) 'nextUpdate' field is invalid."); 1096 case KSSLCertificate::OutOfMemory: 1097 return i18n("The OpenSSL process ran out of memory."); 1098 case KSSLCertificate::SelfSigned: 1099 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."); 1100 case KSSLCertificate::SelfSignedChain: // this is obsolete and kept around for backwards compatibility, only 1101 case KSSLCertificate::SelfSignedInChain: 1102 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."); 1103 case KSSLCertificate::GetIssuerCertLocallyFailed: 1104 return i18n("The CA's (Certificate Authority) certificate can not be found. Most likely, your trust chain is broken."); 1105 case KSSLCertificate::VerifyLeafSignatureFailed: 1106 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."); 1107 case KSSLCertificate::CertificateChainTooLong: 1108 return i18n("The certificate chain is longer than the maximum depth specified."); 1109 case KSSLCertificate::Revoked: // this is obsolete and kept around for backwards compatibility, only 1110 case KSSLCertificate::CertificateRevoked: 1111 return i18n("The certificate has been revoked."); 1112 case KSSLCertificate::InvalidCA: 1113 return i18n("The certificate's CA (Certificate Authority) is invalid."); 1114 case KSSLCertificate::PathLengthExceeded: 1115 return i18n("The length of the trust chain exceeded one of the CA's (Certificate Authority) 'pathlength' parameters, making all subsequent signatures invalid."); 1116 case KSSLCertificate::InvalidPurpose: 1117 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."); 1118 case KSSLCertificate::Untrusted: // this is obsolete and kept around for backwards compatibility, only 1119 case KSSLCertificate::CertificateUntrusted: 1120 return i18n("The root CA (Certificate Authority) is not trusted for the purpose you tried to use this certificate for."); 1121 case KSSLCertificate::Rejected: // this is obsolete and kept around for backwards compatibility, only // this is obsolete and kept around for backwards compatibility, onle 1122 case KSSLCertificate::CertificateRejected: 1123 return i18n("The root CA (Certificate Authority) has been marked to be rejected for the purpose you tried to use it for."); 1124 case KSSLCertificate::IssuerSubjectMismatched: 1125 return i18n("The certificate's CA (Certificate Authority) does not match the CA name of the certificate."); 1126 case KSSLCertificate::AuthAndSubjectKeyIDMismatched: 1127 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."); 1128 case KSSLCertificate::AuthAndSubjectKeyIDAndNameMismatched: 1129 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."); 1130 case KSSLCertificate::KeyMayNotSignCertificate: 1131 return i18n("The certificate's CA (Certificate Authority) is not allowed to sign certificates."); 1132 case KSSLCertificate::ApplicationVerificationFailed: 1133 return i18n("OpenSSL could not be verified."); 1134 1135 // this is obsolete and kept around for backwards compatibility, only 1136 case KSSLCertificate::SignatureFailed: 1137 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."); 1138 case KSSLCertificate::Expired: 1139 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."); 1140 // continue 'useful' messages 1141 1142 // other error messages 1143 case KSSLCertificate::ErrorReadingRoot: 1144 case KSSLCertificate::NoCARoot: 1145 return i18n("Certificate signing authority root files could not be found so the certificate is not verified."); 1146 case KSSLCertificate::NoSSL: 1147 return i18n("SSL support was not found."); 1148 case KSSLCertificate::PrivateKeyFailed: 1149 return i18n("Private key test failed."); 1150 case KSSLCertificate::InvalidHost: 1151 return i18n("The certificate has not been issued for this host."); 1152 case KSSLCertificate::Irrelevant: 1153 return i18n("This certificate is not relevant."); 1154 default: 1155 break; 1156 } 1157 1158 return i18n("The certificate is invalid."); 1159 } 1160 1161 QByteArray KSSLCertificate::toDer() 1162 { 1163 QByteArray qba; 1164 #if KSSL_HAVE_SSL 1165 int certlen = d->kossl->i2d_X509(getCert(), nullptr); 1166 if (certlen >= 0) { 1167 // These should technically be unsigned char * but it doesn't matter 1168 // for our purposes 1169 char *cert = new char[certlen]; 1170 unsigned char *p = (unsigned char *)cert; 1171 // FIXME: return code! 1172 d->kossl->i2d_X509(getCert(), &p); 1173 1174 // encode it into a QString 1175 qba = QByteArray(cert, certlen); 1176 delete[] cert; 1177 } 1178 #endif 1179 return qba; 1180 } 1181 1182 QByteArray KSSLCertificate::toPem() 1183 { 1184 QByteArray qba; 1185 QString thecert = toString(); 1186 const char *header = "-----BEGIN CERTIFICATE-----\n"; 1187 const char *footer = "-----END CERTIFICATE-----\n"; 1188 1189 // We just do base64 on the ASN1 1190 // 64 character lines (unpadded) 1191 unsigned int xx = thecert.length() - 1; 1192 for (unsigned int i = 0; i < xx / 64; i++) { 1193 thecert.insert(64 * (i + 1) + i, '\n'); 1194 } 1195 1196 thecert.prepend(header); 1197 1198 if (thecert[thecert.length() - 1] != '\n') { 1199 thecert += '\n'; 1200 } 1201 1202 thecert.append(footer); 1203 1204 qba = thecert.toLocal8Bit(); 1205 return qba; 1206 } 1207 1208 #define NETSCAPE_CERT_HDR "certificate" 1209 1210 #if KSSL_HAVE_SSL 1211 #if OPENSSL_VERSION_NUMBER < 0x00909000L 1212 1213 typedef struct NETSCAPE_X509_st { 1214 ASN1_OCTET_STRING *header; 1215 X509 *cert; 1216 } NETSCAPE_X509; 1217 #endif 1218 #endif 1219 1220 // what a piece of crap this is 1221 QByteArray KSSLCertificate::toNetscape() 1222 { 1223 QByteArray qba; 1224 // no equivalent in OpenSSL 1.1.0 (?), so behave as if we had no OpenSSL at all 1225 #if KSSL_HAVE_SSL && (OPENSSL_VERSION_NUMBER < 0x10100000L) 1226 NETSCAPE_X509 nx; 1227 ASN1_OCTET_STRING hdr; 1228 QTemporaryFile ktf; 1229 ktf.open(); 1230 FILE *ktf_fs = QT_FOPEN(QFile::encodeName(ktf.fileName()).constData(), "r+"); 1231 1232 hdr.data = (unsigned char *)NETSCAPE_CERT_HDR; 1233 hdr.length = strlen(NETSCAPE_CERT_HDR); 1234 nx.header = &hdr; 1235 nx.cert = getCert(); 1236 1237 d->kossl->ASN1_item_i2d_fp(ktf_fs, (unsigned char *)&nx); 1238 fclose(ktf_fs); 1239 1240 QFile qf(ktf.fileName()); 1241 if (qf.open(QIODevice::ReadOnly)) { 1242 qba = qf.readAll(); 1243 } 1244 #endif 1245 return qba; 1246 } 1247 1248 QString KSSLCertificate::toText() 1249 { 1250 QString text; 1251 #if KSSL_HAVE_SSL 1252 QTemporaryFile ktf; 1253 ktf.open(); 1254 FILE *ktf_fs = QT_FOPEN(QFile::encodeName(ktf.fileName()).constData(), "r+"); 1255 1256 d->kossl->X509_print(ktf_fs, getCert()); 1257 fclose(ktf_fs); 1258 1259 QFile qf(ktf.fileName()); 1260 if (!qf.open(QIODevice::ReadOnly)) { 1261 return text; 1262 } 1263 char *buf = new char[qf.size() + 1]; 1264 qf.read(buf, qf.size()); 1265 buf[qf.size()] = 0; 1266 text = buf; 1267 delete[] buf; 1268 qf.close(); 1269 #endif 1270 return text; 1271 } 1272 1273 bool KSSLCertificate::setCert(const QString &cert) 1274 { 1275 #if KSSL_HAVE_SSL 1276 QByteArray qba, qbb = cert.toLocal8Bit(); 1277 qba = QByteArray::fromBase64(qbb); 1278 unsigned char *qbap = reinterpret_cast<unsigned char *>(qba.data()); 1279 X509 *x5c = KOSSL::self()->d2i_X509(nullptr, &qbap, qba.size()); 1280 if (x5c) { 1281 setCert(x5c); 1282 return true; 1283 } 1284 #endif 1285 return false; 1286 } 1287 1288 KSSLX509V3 &KSSLCertificate::x509V3Extensions() 1289 { 1290 return d->_extensions; 1291 } 1292 1293 bool KSSLCertificate::isSigner() 1294 { 1295 return d->_extensions.certTypeCA(); 1296 } 1297 1298 QStringList KSSLCertificate::subjAltNames() const 1299 { 1300 QStringList rc; 1301 #if KSSL_HAVE_SSL 1302 STACK_OF(GENERAL_NAME) *names; 1303 names = (STACK_OF(GENERAL_NAME) *)d->kossl->X509_get_ext_d2i(d->m_cert, NID_subject_alt_name, nullptr, nullptr); 1304 1305 if (!names) { 1306 return rc; 1307 } 1308 1309 int cnt = d->kossl->OPENSSL_sk_num((STACK *)names); 1310 1311 for (int i = 0; i < cnt; i++) { 1312 const GENERAL_NAME *val = (const GENERAL_NAME *)d->kossl->OPENSSL_sk_value(names, i); 1313 if (val->type != GEN_DNS) { 1314 continue; 1315 } 1316 1317 QString s = (const char *)d->kossl->ASN1_STRING_data(val->d.ia5); 1318 if (!s.isEmpty() && 1319 /* skip subjectAltNames with embedded NULs */ 1320 s.length() == d->kossl->ASN1_STRING_length(val->d.ia5)) { 1321 rc += s; 1322 } 1323 } 1324 d->kossl->OPENSSL_sk_free(names); 1325 #endif 1326 return rc; 1327 } 1328 1329 QDataStream &operator<<(QDataStream &s, const KSSLCertificate &r) 1330 { 1331 QStringList qsl; 1332 QList<KSSLCertificate *> cl = const_cast<KSSLCertificate &>(r).chain().getChain(); 1333 1334 foreach (KSSLCertificate *c, cl) { 1335 qsl << c->toString(); 1336 } 1337 1338 qDeleteAll(cl); 1339 s << const_cast<KSSLCertificate &>(r).toString() << qsl; 1340 1341 return s; 1342 } 1343 1344 QDataStream &operator>>(QDataStream &s, KSSLCertificate &r) 1345 { 1346 QStringList qsl; 1347 QString cert; 1348 1349 s >> cert >> qsl; 1350 1351 if (r.setCert(cert) && !qsl.isEmpty()) { 1352 r.chain().setCertChain(qsl); 1353 } 1354 1355 return s; 1356 } 1357