📄 ksslcertificate.cc
字号:
#ifdef KSSL_HAVE_SSL if (p == KSSLCertificate::SSLServer) { rc = X509_PURPOSE_SSL_SERVER; } else if (p == KSSLCertificate::SSLClient) { rc = X509_PURPOSE_SSL_CLIENT; } else if (p == KSSLCertificate::SMIMEEncrypt) { rc = X509_PURPOSE_SMIME_ENCRYPT; } else if (p == KSSLCertificate::SMIMESign) { rc = X509_PURPOSE_SMIME_SIGN; } else if (p == KSSLCertificate::Any) { rc = X509_PURPOSE_ANY; }#endifreturn rc; }// For backward compatibilityKSSLCertificate::KSSLValidation KSSLCertificate::validate() { return validate(KSSLCertificate::SSLServer);}KSSLCertificate::KSSLValidation KSSLCertificate::validate(KSSLCertificate::KSSLPurpose purpose){ KSSLValidationList result = validateVerbose(purpose); if (result.isEmpty()) return KSSLCertificate::Ok; else return result.first();} //// See apps/verify.c in OpenSSL for the source of most of this logic.//// CRL files? we don't do that yetKSSLCertificate::KSSLValidationList KSSLCertificate::validateVerbose(KSSLCertificate::KSSLPurpose purpose) { return validateVerbose(purpose, 0);}KSSLCertificate::KSSLValidationList KSSLCertificate::validateVerbose(KSSLCertificate::KSSLPurpose purpose, KSSLCertificate *ca){ KSSLValidationList errors; if (ca || (d->_lastPurpose != purpose)) { d->m_stateCached = false; } if (!d->m_stateCached) d->_lastPurpose = purpose;#ifdef KSSL_HAVE_SSL X509_STORE *certStore; X509_LOOKUP *certLookup; X509_STORE_CTX *certStoreCTX; int rc = 0; if (!d->m_cert) { errors << KSSLCertificate::Unknown; return errors; } if (d->m_stateCached) { errors << d->m_stateCache; return errors; } QStringList qsl = KGlobal::dirs()->resourceDirs("kssl"); if (qsl.isEmpty()) { errors << KSSLCertificate::NoCARoot; return errors; } KSSLCertificate::KSSLValidation ksslv = Unknown; for (QStringList::Iterator j = qsl.begin(); j != qsl.end(); ++j) { struct stat sb; QString _j = (*j) + "ca-bundle.crt"; if (-1 == stat(_j.ascii(), &sb)) { continue; } certStore = d->kossl->X509_STORE_new(); if (!certStore) { errors << KSSLCertificate::Unknown; return errors; } X509_STORE_set_verify_cb_func(certStore, X509Callback); certLookup = d->kossl->X509_STORE_add_lookup(certStore, d->kossl->X509_LOOKUP_file()); if (!certLookup) { ksslv = KSSLCertificate::Unknown; d->kossl->X509_STORE_free(certStore); continue; } if (!d->kossl->X509_LOOKUP_load_file(certLookup, _j.ascii(), X509_FILETYPE_PEM)) { // error accessing directory and loading pems kdDebug(7029) << "KSSL couldn't read CA root: " << _j << endl; ksslv = KSSLCertificate::ErrorReadingRoot; d->kossl->X509_STORE_free(certStore); continue; } // This is the checking code certStoreCTX = d->kossl->X509_STORE_CTX_new(); // this is a bad error - could mean no free memory. // This may be the wrong thing to do here if (!certStoreCTX) { kdDebug(7029) << "KSSL couldn't create an X509 store context." << endl; d->kossl->X509_STORE_free(certStore); continue; } d->kossl->X509_STORE_CTX_init(certStoreCTX, certStore, d->m_cert, NULL); if (d->_chain.isValid()) { d->kossl->X509_STORE_CTX_set_chain(certStoreCTX, (STACK_OF(X509)*)d->_chain.rawChain()); } //kdDebug(7029) << "KSSL setting CRL.............." << endl; // int X509_STORE_add_crl(X509_STORE *ctx, X509_CRL *x); d->kossl->X509_STORE_CTX_set_purpose(certStoreCTX, purposeToOpenSSL(purpose)); KSSL_X509CallBack_ca = ca ? ca->d->m_cert : 0; KSSL_X509CallBack_ca_found = false; certStoreCTX->error = X509_V_OK; rc = d->kossl->X509_verify_cert(certStoreCTX); int errcode = certStoreCTX->error; if (ca && !KSSL_X509CallBack_ca_found) { ksslv = KSSLCertificate::Irrelevant; } else { ksslv = processError(errcode); } // For servers, we can try NS_SSL_SERVER too if ( (ksslv != KSSLCertificate::Ok) && (ksslv != KSSLCertificate::Irrelevant) && purpose == KSSLCertificate::SSLServer) { d->kossl->X509_STORE_CTX_set_purpose(certStoreCTX, X509_PURPOSE_NS_SSL_SERVER); certStoreCTX->error = X509_V_OK; rc = d->kossl->X509_verify_cert(certStoreCTX); errcode = certStoreCTX->error; ksslv = processError(errcode); } d->kossl->X509_STORE_CTX_free(certStoreCTX); d->kossl->X509_STORE_free(certStore); // end of checking code // //kdDebug(7029) << "KSSL Validation procedure RC: " // << rc << endl; //kdDebug(7029) << "KSSL Validation procedure errcode: " // << errcode << endl; //kdDebug(7029) << "KSSL Validation procedure RESULTS: " // << ksslv << endl; if (ksslv != NoCARoot && ksslv != InvalidCA) { d->m_stateCached = true; d->m_stateCache = ksslv; } break; } if (ksslv != KSSLCertificate::Ok) errors << ksslv;#else errors << KSSLCertificate::NoSSL;#endif return errors;}KSSLCertificate::KSSLValidation KSSLCertificate::revalidate() { return revalidate(KSSLCertificate::SSLServer);}KSSLCertificate::KSSLValidation KSSLCertificate::revalidate(KSSLCertificate::KSSLPurpose p) { d->m_stateCached = false; return validate(p);}KSSLCertificate::KSSLValidation KSSLCertificate::processError(int ec) {KSSLCertificate::KSSLValidation rc;rc = KSSLCertificate::Unknown;#ifdef KSSL_HAVE_SSL switch (ec) { case X509_V_OK: // OK rc = KSSLCertificate::Ok; break; case X509_V_ERR_CERT_REJECTED: rc = KSSLCertificate::Rejected; break; case X509_V_ERR_CERT_UNTRUSTED: rc = KSSLCertificate::Untrusted; break; case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE: case X509_V_ERR_CERT_SIGNATURE_FAILURE: case X509_V_ERR_CRL_SIGNATURE_FAILURE: case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE: case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE: rc = KSSLCertificate::SignatureFailed; break; case X509_V_ERR_INVALID_CA: case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY: case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY: rc = KSSLCertificate::InvalidCA; break; case X509_V_ERR_INVALID_PURPOSE: rc = KSSLCertificate::InvalidPurpose; break; case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: rc = KSSLCertificate::SelfSigned; break; case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN: rc = KSSLCertificate::SelfSignedChain; break; case X509_V_ERR_CERT_REVOKED: rc = KSSLCertificate::Revoked; break; case X509_V_ERR_PATH_LENGTH_EXCEEDED: rc = KSSLCertificate::PathLengthExceeded; break; case X509_V_ERR_CERT_NOT_YET_VALID: case X509_V_ERR_CERT_HAS_EXPIRED: case X509_V_ERR_CRL_NOT_YET_VALID: case X509_V_ERR_CRL_HAS_EXPIRED: case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD: case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD: rc = KSSLCertificate::Expired; kdDebug(7029) << "KSSL apparently this is expired. Not after: " << getNotAfter() << endl; break; //case 1: case X509_V_ERR_APPLICATION_VERIFICATION: case X509_V_ERR_OUT_OF_MEM: case X509_V_ERR_UNABLE_TO_GET_CRL: case X509_V_ERR_CERT_CHAIN_TOO_LONG: default: rc = KSSLCertificate::Unknown; break;}d->m_stateCache = rc;d->m_stateCached = true;#endifreturn rc;}QString KSSLCertificate::getNotBefore() const {#ifdef KSSL_HAVE_SSLreturn ASN1_UTCTIME_QString(X509_get_notBefore(d->m_cert));#elsereturn QString::null;#endif}QString KSSLCertificate::getNotAfter() const {#ifdef KSSL_HAVE_SSLreturn ASN1_UTCTIME_QString(X509_get_notAfter(d->m_cert));#elsereturn QString::null;#endif}QDateTime KSSLCertificate::getQDTNotBefore() const {#ifdef KSSL_HAVE_SSLreturn ASN1_UTCTIME_QDateTime(X509_get_notBefore(d->m_cert), NULL);#elsereturn QDateTime::currentDateTime();#endif}QDateTime KSSLCertificate::getQDTNotAfter() const {#ifdef KSSL_HAVE_SSLreturn ASN1_UTCTIME_QDateTime(X509_get_notAfter(d->m_cert), NULL);#elsereturn QDateTime::currentDateTime();#endif}int operator==(KSSLCertificate &x, KSSLCertificate &y) {#ifndef KSSL_HAVE_SSL return 1;#else if (!KOSSL::self()->X509_cmp(x.getCert(), y.getCert())) return 1; return 0;#endif}KSSLCertificate *KSSLCertificate::replicate() {// The new certificate doesn't have the cached value. It's probably// better this way. We can't anticipate every reason for doing this.KSSLCertificate *newOne = new KSSLCertificate();#ifdef KSSL_HAVE_SSL newOne->setCert(d->kossl->X509_dup(getCert())); KSSLCertChain *c = d->_chain.replicate(); newOne->setChain(c->rawChain()); delete c;#endifreturn newOne;}QString KSSLCertificate::toString() {return KCodecs::base64Encode(toDer());}QString KSSLCertificate::verifyText(KSSLValidation x) {switch (x) {case KSSLCertificate::Ok: return i18n("The certificate is valid.");case KSSLCertificate::PathLengthExceeded:case KSSLCertificate::ErrorReadingRoot:case KSSLCertificate::NoCARoot: return i18n("Certificate signing authority root files could not be found so the certificate is not verified.");case KSSLCertificate::SelfSignedChain:case KSSLCertificate::InvalidCA: return i18n("Certificate signing authority is unknown or invalid.");case KSSLCertificate::SelfSigned: return i18n("Certificate is self-signed and thus may not be trustworthy.");case KSSLCertificate::Expired: return i18n("Certificate has expired.");case KSSLCertificate::Revoked: return i18n("Certificate has been revoked.");case KSSLCertificate::NoSSL: return i18n("SSL support was not found.");case KSSLCertificate::Untrusted: return i18n("Signature is untrusted.");case KSSLCertificate::SignatureFailed: return i18n("Signature test failed.");case KSSLCertificate::Rejected:case KSSLCertificate::InvalidPurpose: return i18n("Rejected, possibly due to an invalid purpose.");case KSSLCertificate::PrivateKeyFailed: return i18n("Private key test failed.");case KSSLCertificate::InvalidHost: return i18n("The certificate has not been issued for this host.");case KSSLCertificate::Irrelevant: return i18n("This certificate is not relevant.");default:break;}return i18n("The certificate is invalid.");}QByteArray KSSLCertificate::toDer() {QByteArray qba;#ifdef KSSL_HAVE_SSLunsigned int certlen = d->kossl->i2d_X509(getCert(), NULL);unsigned char *cert = new unsigned char[certlen];unsigned char *p = cert; // FIXME: return code! d->kossl->i2d_X509(getCert(), &p); // encode it into a QString qba.duplicate((const char*)cert, certlen); delete[] cert;#endifreturn qba;}QByteArray KSSLCertificate::toPem() {QByteArray qba;QString thecert = toString();const char *header = "-----BEGIN CERTIFICATE-----\n";const char *footer = "-----END CERTIFICATE-----\n"; // We just do base64 on the ASN1 // 64 character lines (unpadded) unsigned int xx = thecert.length() - 1; for (unsigned int i = 0; i < xx/64; i++) { thecert.insert(64*(i+1)+i, '\n'); } thecert.prepend(header); if (thecert[thecert.length()-1] != '\n') thecert += "\n"; thecert.append(footer); qba.duplicate(thecert.local8Bit(), thecert.length());return qba;}#define NETSCAPE_CERT_HDR "certificate"// what a piece of crap this isQByteArray KSSLCertificate::toNetscape() {QByteArray qba;#ifdef KSSL_HAVE_SSLASN1_HEADER ah;ASN1_OCTET_STRING os;KTempFile ktf; os.data = (unsigned char *)NETSCAPE_CERT_HDR; os.length = strlen(NETSCAPE_CERT_HDR); ah.header = &os; ah.data = (char *)getCert(); ah.meth = d->kossl->X509_asn1_meth(); d->kossl->ASN1_i2d_fp(ktf.fstream(),(unsigned char *)&ah); ktf.close(); QFile qf(ktf.name()); qf.open(IO_ReadOnly); char *buf = new char[qf.size()]; qf.readBlock(buf, qf.size()); qba.duplicate(buf, qf.size()); qf.close(); delete[] buf; ktf.unlink();#endifreturn qba;}QString KSSLCertificate::toText() {QString text;#ifdef KSSL_HAVE_SSLKTempFile ktf; d->kossl->X509_print(ktf.fstream(), getCert()); ktf.close(); QFile qf(ktf.name()); qf.open(IO_ReadOnly); char *buf = new char[qf.size()+1]; qf.readBlock(buf, qf.size()); buf[qf.size()] = 0; text = buf; delete[] buf; qf.close(); ktf.unlink();#endifreturn text;}// KDE 4: Make it const QString &bool KSSLCertificate::setCert(QString& cert) {#ifdef KSSL_HAVE_SSLQByteArray qba, qbb = cert.local8Bit().copy(); KCodecs::base64Decode(qbb, qba); unsigned char *qbap = reinterpret_cast<unsigned char *>(qba.data()); X509 *x5c = KOSSL::self()->d2i_X509(NULL, &qbap, qba.size()); if (x5c) { setCert(x5c); return true; }#endifreturn false;}KSSLX509V3& KSSLCertificate::x509V3Extensions() {return d->_extensions;}bool KSSLCertificate::isSigner() {return d->_extensions.certTypeCA();}QStringList KSSLCertificate::subjAltNames() const { QStringList rc;#ifdef KSSL_HAVE_SSL STACK_OF(GENERAL_NAME) *names; names = (STACK_OF(GENERAL_NAME)*)d->kossl->X509_get_ext_d2i(d->m_cert, NID_subject_alt_name, 0, 0); if (!names) { return rc; } int cnt = d->kossl->sk_GENERAL_NAME_num(names); for (int i = 0; i < cnt; i++) { const GENERAL_NAME *val = (const GENERAL_NAME *)d->kossl->sk_value(names, i); if (val->type != GEN_DNS) { continue; } QString s = (const char *)d->kossl->ASN1_STRING_data(val->d.ia5); if (!s.isEmpty()) { rc += s; } } d->kossl->sk_free(names);#endif return rc;}QDataStream& operator<<(QDataStream& s, const KSSLCertificate& r) {QStringList qsl;QPtrList<KSSLCertificate> cl = const_cast<KSSLCertificate&>(r).chain().getChain(); for (KSSLCertificate *c = cl.first(); c != 0; c = cl.next()) { qsl << c->toString(); } cl.setAutoDelete(true); s << const_cast<KSSLCertificate&>(r).toString() << qsl;return s;}QDataStream& operator>>(QDataStream& s, KSSLCertificate& r) {QStringList qsl;QString cert;s >> cert >> qsl; if (r.setCert(cert) && !qsl.isEmpty()) r.chain().setCertChain(qsl);return s;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -