| 65 | } |
| 66 | |
| 67 | bool PaymentRequestPlus::getMerchant(X509_STORE* certStore, QString& merchant) const |
| 68 | { |
| 69 | merchant.clear(); |
| 70 | |
| 71 | if (!IsInitialized()) |
| 72 | return false; |
| 73 | |
| 74 | // One day we'll support more PKI types, but just |
| 75 | // x509 for now: |
| 76 | const EVP_MD* digestAlgorithm = NULL; |
| 77 | if (paymentRequest.pki_type() == "x509+sha256") { |
| 78 | digestAlgorithm = EVP_sha256(); |
| 79 | } else if (paymentRequest.pki_type() == "x509+sha1") { |
| 80 | digestAlgorithm = EVP_sha1(); |
| 81 | } else if (paymentRequest.pki_type() == "none") { |
| 82 | qWarning() << "PaymentRequestPlus::getMerchant : Payment request: pki_type == none"; |
| 83 | return false; |
| 84 | } else { |
| 85 | qWarning() << "PaymentRequestPlus::getMerchant : Payment request: unknown pki_type " << QString::fromStdString(paymentRequest.pki_type()); |
| 86 | return false; |
| 87 | } |
| 88 | |
| 89 | payments::X509Certificates certChain; |
| 90 | if (!certChain.ParseFromString(paymentRequest.pki_data())) { |
| 91 | qWarning() << "PaymentRequestPlus::getMerchant : Payment request: error parsing pki_data"; |
| 92 | return false; |
| 93 | } |
| 94 | |
| 95 | std::vector<X509*> certs; |
| 96 | const QDateTime currentTime = QDateTime::currentDateTime(); |
| 97 | for (int i = 0; i < certChain.certificate_size(); i++) { |
| 98 | QByteArray certData(certChain.certificate(i).data(), certChain.certificate(i).size()); |
| 99 | QSslCertificate qCert(certData, QSsl::Der); |
| 100 | if (currentTime < qCert.effectiveDate() || currentTime > qCert.expiryDate()) { |
| 101 | qWarning() << "PaymentRequestPlus::getMerchant : Payment request: certificate expired or not yet active: " << qCert; |
| 102 | return false; |
| 103 | } |
| 104 | #if QT_VERSION >= 0x050000 |
| 105 | if (qCert.isBlacklisted()) { |
| 106 | qWarning() << "PaymentRequestPlus::getMerchant : Payment request: certificate blacklisted: " << qCert; |
| 107 | return false; |
| 108 | } |
| 109 | #endif |
| 110 | const unsigned char* data = (const unsigned char*)certChain.certificate(i).data(); |
| 111 | X509* cert = d2i_X509(NULL, &data, certChain.certificate(i).size()); |
| 112 | if (cert) |
| 113 | certs.push_back(cert); |
| 114 | } |
| 115 | if (certs.empty()) { |
| 116 | qWarning() << "PaymentRequestPlus::getMerchant : Payment request: empty certificate chain"; |
| 117 | return false; |
| 118 | } |
| 119 | |
| 120 | // The first cert is the signing cert, the rest are untrusted certs that chain |
| 121 | // to a valid root authority. OpenSSL needs them separately. |
| 122 | STACK_OF(X509)* chain = sk_X509_new_null(); |
| 123 | for (int i = certs.size() - 1; i > 0; i--) { |
| 124 | sk_X509_push(chain, certs[i]); |