aboutsummaryrefslogtreecommitdiff
path: root/src/qt/paymentserver.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/qt/paymentserver.cpp')
-rw-r--r--src/qt/paymentserver.cpp79
1 files changed, 56 insertions, 23 deletions
diff --git a/src/qt/paymentserver.cpp b/src/qt/paymentserver.cpp
index d642fdae36..96ceeb18a4 100644
--- a/src/qt/paymentserver.cpp
+++ b/src/qt/paymentserver.cpp
@@ -16,7 +16,6 @@
#include <cstdlib>
-#include <openssl/x509.h>
#include <openssl/x509_vfy.h>
#include <QApplication>
@@ -97,7 +96,7 @@ static QList<QString> savedPaymentRequests;
static void ReportInvalidCertificate(const QSslCertificate& cert)
{
- qDebug() << "ReportInvalidCertificate : Payment server found an invalid certificate: " << cert.subjectInfo(QSslCertificate::CommonName);
+ qDebug() << "ReportInvalidCertificate: Payment server found an invalid certificate: " << cert.subjectInfo(QSslCertificate::CommonName);
}
//
@@ -171,7 +170,7 @@ void PaymentServer::LoadRootCAs(X509_STORE* _store)
continue;
}
}
- qWarning() << "PaymentServer::LoadRootCAs : Loaded " << nRootCerts << " root certificates";
+ qWarning() << "PaymentServer::LoadRootCAs: Loaded " << nRootCerts << " root certificates";
// Project for another day:
// Fetch certificate revocation lists, and add them to certStore.
@@ -244,7 +243,7 @@ void PaymentServer::ipcParseCommandLine(int argc, char* argv[])
{
// Printing to debug.log is about the best we can do here, the
// GUI hasn't started yet so we can't pop up a message box.
- qWarning() << "PaymentServer::ipcSendCommandLine : Payment request file does not exist: " << arg;
+ qWarning() << "PaymentServer::ipcSendCommandLine: Payment request file does not exist: " << arg;
}
}
}
@@ -368,10 +367,10 @@ void PaymentServer::initNetManager()
if (optionsModel->getProxySettings(proxy)) {
netManager->setProxy(proxy);
- qDebug() << "PaymentServer::initNetManager : Using SOCKS5 proxy" << proxy.hostName() << ":" << proxy.port();
+ qDebug() << "PaymentServer::initNetManager: Using SOCKS5 proxy" << proxy.hostName() << ":" << proxy.port();
}
else
- qDebug() << "PaymentServer::initNetManager : No active proxy server found.";
+ qDebug() << "PaymentServer::initNetManager: No active proxy server found.";
connect(netManager, SIGNAL(finished(QNetworkReply*)),
this, SLOT(netRequestFinished(QNetworkReply*)));
@@ -415,12 +414,12 @@ void PaymentServer::handleURIOrFile(const QString& s)
if (fetchUrl.isValid())
{
- qDebug() << "PaymentServer::handleURIOrFile : fetchRequest(" << fetchUrl << ")";
+ qDebug() << "PaymentServer::handleURIOrFile: fetchRequest(" << fetchUrl << ")";
fetchRequest(fetchUrl);
}
else
{
- qWarning() << "PaymentServer::handleURIOrFile : Invalid URL: " << fetchUrl;
+ qWarning() << "PaymentServer::handleURIOrFile: Invalid URL: " << fetchUrl;
emit message(tr("URI handling"),
tr("Payment request fetch URL is invalid: %1").arg(fetchUrl.toString()),
CClientUIInterface::ICON_WARNING);
@@ -521,8 +520,6 @@ bool PaymentServer::processPaymentRequest(PaymentRequestPlus& request, SendCoins
return false;
if (request.IsInitialized()) {
- const payments::PaymentDetails& details = request.getDetails();
-
// Payment request network matches client network?
if (!verifyNetwork(request.getDetails())) {
emit message(tr("Payment request rejected"), tr("Payment request network doesn't match client network."),
@@ -531,16 +528,15 @@ bool PaymentServer::processPaymentRequest(PaymentRequestPlus& request, SendCoins
return false;
}
- // Expired payment request?
- if (details.has_expires() && (int64_t)details.expires() < GetTime())
- {
- emit message(tr("Payment request rejected"), tr("Payment request has expired."),
+ // Make sure any payment requests involved are still valid.
+ // This is re-checked just before sending coins in WalletModel::sendCoins().
+ if (verifyExpired(request.getDetails())) {
+ emit message(tr("Payment request rejected"), tr("Payment request expired."),
CClientUIInterface::MSG_ERROR);
return false;
}
- }
- else {
+ } else {
emit message(tr("Payment request error"), tr("Payment request is not initialized."),
CClientUIInterface::MSG_ERROR);
@@ -572,6 +568,14 @@ bool PaymentServer::processPaymentRequest(PaymentRequestPlus& request, SendCoins
return false;
}
+ // Bitcoin amounts are stored as (optional) uint64 in the protobuf messages (see paymentrequest.proto),
+ // but CAmount is defined as int64_t. Because of that we need to verify that amounts are in a valid range
+ // and no overflow has happened.
+ if (!verifyAmount(sendingTo.second)) {
+ emit message(tr("Payment request rejected"), tr("Invalid payment request."), CClientUIInterface::MSG_ERROR);
+ return false;
+ }
+
// Extract and check amounts
CTxOut txOut(sendingTo.second, sendingTo.first);
if (txOut.IsDust(::minRelayTxFee)) {
@@ -583,15 +587,20 @@ bool PaymentServer::processPaymentRequest(PaymentRequestPlus& request, SendCoins
}
recipient.amount += sendingTo.second;
+ // Also verify that the final amount is still in a valid range after adding additional amounts.
+ if (!verifyAmount(recipient.amount)) {
+ emit message(tr("Payment request rejected"), tr("Invalid payment request."), CClientUIInterface::MSG_ERROR);
+ return false;
+ }
}
// Store addresses and format them to fit nicely into the GUI
recipient.address = addresses.join("<br />");
if (!recipient.authenticatedMerchant.isEmpty()) {
- qDebug() << "PaymentServer::processPaymentRequest : Secure payment request from " << recipient.authenticatedMerchant;
+ qDebug() << "PaymentServer::processPaymentRequest: Secure payment request from " << recipient.authenticatedMerchant;
}
else {
- qDebug() << "PaymentServer::processPaymentRequest : Insecure payment request to " << addresses.join(", ");
+ qDebug() << "PaymentServer::processPaymentRequest: Insecure payment request to " << addresses.join(", ");
}
return true;
@@ -646,7 +655,7 @@ void PaymentServer::fetchPaymentACK(CWallet* wallet, SendCoinsRecipient recipien
else {
// This should never happen, because sending coins should have
// just unlocked the wallet and refilled the keypool.
- qWarning() << "PaymentServer::fetchPaymentACK : Error getting refund key, refund_to not set";
+ qWarning() << "PaymentServer::fetchPaymentACK: Error getting refund key, refund_to not set";
}
}
@@ -658,7 +667,7 @@ void PaymentServer::fetchPaymentACK(CWallet* wallet, SendCoinsRecipient recipien
}
else {
// This should never happen, either.
- qWarning() << "PaymentServer::fetchPaymentACK : Error serializing payment message";
+ qWarning() << "PaymentServer::fetchPaymentACK: Error serializing payment message";
}
}
@@ -697,7 +706,7 @@ void PaymentServer::netRequestFinished(QNetworkReply* reply)
SendCoinsRecipient recipient;
if (!request.parse(data))
{
- qWarning() << "PaymentServer::netRequestFinished : Error parsing payment request";
+ qWarning() << "PaymentServer::netRequestFinished: Error parsing payment request";
emit message(tr("Payment request error"),
tr("Payment request cannot be parsed!"),
CClientUIInterface::MSG_ERROR);
@@ -715,7 +724,7 @@ void PaymentServer::netRequestFinished(QNetworkReply* reply)
QString msg = tr("Bad response from server %1")
.arg(reply->request().url().toString());
- qWarning() << "PaymentServer::netRequestFinished : " << msg;
+ qWarning() << "PaymentServer::netRequestFinished: " << msg;
emit message(tr("Payment request error"), msg, CClientUIInterface::MSG_ERROR);
}
else
@@ -731,7 +740,7 @@ void PaymentServer::reportSslErrors(QNetworkReply* reply, const QList<QSslError>
QString errString;
foreach (const QSslError& err, errs) {
- qWarning() << "PaymentServer::reportSslErrors : " << err;
+ qWarning() << "PaymentServer::reportSslErrors: " << err;
errString += err.errorString() + "\n";
}
emit message(tr("Network request error"), errString, CClientUIInterface::MSG_ERROR);
@@ -759,3 +768,27 @@ bool PaymentServer::verifyNetwork(const payments::PaymentDetails& requestDetails
}
return fVerified;
}
+
+bool PaymentServer::verifyExpired(const payments::PaymentDetails& requestDetails)
+{
+ bool fVerified = (requestDetails.has_expires() && (int64_t)requestDetails.expires() < GetTime());
+ if (fVerified) {
+ const QString requestExpires = QString::fromStdString(DateTimeStrFormat("%Y-%m-%d %H:%M:%S", (int64_t)requestDetails.expires()));
+ qWarning() << QString("PaymentServer::%1: Payment request expired \"%2\".")
+ .arg(__func__)
+ .arg(requestExpires);
+ }
+ return fVerified;
+}
+
+bool PaymentServer::verifyAmount(const CAmount& requestAmount)
+{
+ bool fVerified = MoneyRange(requestAmount);
+ if (!fVerified) {
+ qWarning() << QString("PaymentServer::%1: Payment request amount out of allowed range (%2, allowed 0 - %3).")
+ .arg(__func__)
+ .arg(requestAmount)
+ .arg(MAX_MONEY);
+ }
+ return fVerified;
+}