// // Load OpenSSL's list of root certificate authorities // void PaymentServer::LoadRootCAs(X509_STORE* _store) { // Unit tests mostly use this, to pass in fake root CAs: if (_store) { certStore.reset(_store); return; } // Normal execution, use either -rootcertificates or system certs: certStore.reset(X509_STORE_new()); // Note: use "-system-" default here so that users can pass -rootcertificates="" // and get 'I don't like X.509 certificates, don't trust anybody' behavior: QString certFile = QString::fromStdString(gArgs.GetArg("-rootcertificates", "-system-")); // Empty store if (certFile.isEmpty()) { qDebug() << QString("PaymentServer::%1: Payment request authentication via X.509 certificates disabled.").arg(__func__); return; } QList<QSslCertificate> certList; if (certFile != "-system-") { qDebug() << QString("PaymentServer::%1: Using \"%2\" as trusted root certificate.").arg(__func__).arg(certFile); certList = QSslCertificate::fromPath(certFile); // Use those certificates when fetching payment requests, too: QSslSocket::setDefaultCaCertificates(certList); } else certList = QSslSocket::systemCaCertificates(); int nRootCerts = 0; const QDateTime currentTime = QDateTime::currentDateTime(); for (const QSslCertificate& cert : certList) { // Don't log NULL certificates if (cert.isNull()) continue; // Not yet active/valid, or expired certificate if (currentTime < cert.effectiveDate() || currentTime > cert.expiryDate()) { ReportInvalidCertificate(cert); continue; } #if QT_VERSION >= 0x050000 // Blacklisted certificate if (cert.isBlacklisted()) { ReportInvalidCertificate(cert); continue; } #endif QByteArray certData = cert.toDer(); const unsigned char *data = (const unsigned char *)certData.data(); std::unique_ptr<X509, X509Deleter> x509(d2i_X509(0, &data, certData.size())); if (x509 && X509_STORE_add_cert(certStore.get(), x509.get())) { // Note: X509_STORE increases the reference count to the X509 object, // we still have to release our reference to it. ++nRootCerts; } else { ReportInvalidCertificate(cert); continue; } } qWarning() << "PaymentServer::LoadRootCAs: Loaded " << nRootCerts << " root certificates"; // Project for another day: // Fetch certificate revocation lists, and add them to certStore. // Issues to consider: // performance (start a thread to fetch in background?) // privacy (fetch through tor/proxy so IP address isn't revealed) // would it be easier to just use a compiled-in blacklist? // or use Qt's blacklist? // "certificate stapling" with server-side caching is more efficient }
// // Load OpenSSL's list of root certificate authorities // void PaymentServer::LoadRootCAs(X509_STORE* _store) { if (PaymentServer::certStore == NULL) atexit(PaymentServer::freeCertStore); else freeCertStore(); // Unit tests mostly use this, to pass in fake root CAs: if (_store) { PaymentServer::certStore = _store; return; } // Normal execution, use either -rootcertificates or system certs: PaymentServer::certStore = X509_STORE_new(); // Note: use "-system-" default here so that users can pass -rootcertificates="" // and get 'I don't like X.509 certificates, don't trust anybody' behavior: QString certFile = QString::fromStdString(GetArg("-rootcertificates", "-system-")); if (certFile.isEmpty()) return; // Empty store QList<QSslCertificate> certList; if (certFile != "-system-") { certList = QSslCertificate::fromPath(certFile); // Use those certificates when fetching payment requests, too: QSslSocket::setDefaultCaCertificates(certList); } else certList = QSslSocket::systemCaCertificates (); int nRootCerts = 0; const QDateTime currentTime = QDateTime::currentDateTime(); foreach (const QSslCertificate& cert, certList) { if (currentTime < cert.effectiveDate() || currentTime > cert.expiryDate()) { ReportInvalidCertificate(cert); continue; } #if QT_VERSION >= 0x050000 if (cert.isBlacklisted()) { ReportInvalidCertificate(cert); continue; } #endif QByteArray certData = cert.toDer(); const unsigned char *data = (const unsigned char *)certData.data(); X509* x509 = d2i_X509(0, &data, certData.size()); if (x509 && X509_STORE_add_cert(PaymentServer::certStore, x509)) { // Note: X509_STORE_free will free the X509* objects when // the PaymentServer is destroyed ++nRootCerts; } else { ReportInvalidCertificate(cert); continue; } } if (fDebug) qDebug() << "PaymentServer::LoadRootCAs : Loaded " << nRootCerts << " root certificates"; // Project for another day: // Fetch certificate revocation lists, and add them to certStore. // Issues to consider: // performance (start a thread to fetch in background?) // privacy (fetch through tor/proxy so IP address isn't revealed) // would it be easier to just use a compiled-in blacklist? // or use Qt's blacklist? // "certificate stapling" with server-side caching is more efficient }