[Qt] add BIP70 payment request size DoS protection for URIs

- current code only does this for payment request files, which are
  used on Mac
- also rename readPaymentRequest to readPaymentRequestFromFile, so it's
  obvious that function only handles payment request files and not URIs
- small logging changes in readPaymentRequestFromFile
This commit is contained in:
Philip Kaufmann 2014-11-19 12:53:57 +01:00
parent 2284ccbd13
commit 31f84944a5
2 changed files with 33 additions and 13 deletions

View File

@ -226,7 +226,7 @@ void PaymentServer::ipcParseCommandLine(int argc, char* argv[])
savedPaymentRequests.append(arg); savedPaymentRequests.append(arg);
PaymentRequestPlus request; PaymentRequestPlus request;
if (readPaymentRequest(arg, request)) if (readPaymentRequestFromFile(arg, request))
{ {
if (request.getDetails().network() == "main") if (request.getDetails().network() == "main")
{ {
@ -452,7 +452,7 @@ void PaymentServer::handleURIOrFile(const QString& s)
{ {
PaymentRequestPlus request; PaymentRequestPlus request;
SendCoinsRecipient recipient; SendCoinsRecipient recipient;
if (!readPaymentRequest(s, request)) if (!readPaymentRequestFromFile(s, request))
{ {
emit message(tr("Payment request file handling"), emit message(tr("Payment request file handling"),
tr("Payment request file cannot be read! This can be caused by an invalid payment request file."), tr("Payment request file cannot be read! This can be caused by an invalid payment request file."),
@ -486,18 +486,25 @@ void PaymentServer::handleURIConnection()
handleURIOrFile(msg); handleURIOrFile(msg);
} }
bool PaymentServer::readPaymentRequest(const QString& filename, PaymentRequestPlus& request) //
// Warning: readPaymentRequestFromFile() is used in ipcSendCommandLine()
// so don't use "emit message()", but "QMessageBox::"!
//
bool PaymentServer::readPaymentRequestFromFile(const QString& filename, PaymentRequestPlus& request)
{ {
QFile f(filename); QFile f(filename);
if (!f.open(QIODevice::ReadOnly)) if (!f.open(QIODevice::ReadOnly)) {
{ qWarning() << QString("PaymentServer::%1: Failed to open %2").arg(__func__).arg(filename);
qWarning() << "PaymentServer::readPaymentRequest : Failed to open " << filename;
return false; return false;
} }
if (f.size() > BIP70_MAX_PAYMENTREQUEST_SIZE) // BIP70 DoS protection
{ if (f.size() > BIP70_MAX_PAYMENTREQUEST_SIZE) {
qWarning() << "PaymentServer::readPaymentRequest : " << filename << " too large"; qWarning() << QString("PaymentServer::%1: Payment request %2 is too large (%3 bytes, allowed %4 bytes).")
.arg(__func__)
.arg(filename)
.arg(f.size())
.arg(BIP70_MAX_PAYMENTREQUEST_SIZE);
return false; return false;
} }
@ -657,13 +664,26 @@ void PaymentServer::fetchPaymentACK(CWallet* wallet, SendCoinsRecipient recipien
void PaymentServer::netRequestFinished(QNetworkReply* reply) void PaymentServer::netRequestFinished(QNetworkReply* reply)
{ {
reply->deleteLater(); reply->deleteLater();
if (reply->error() != QNetworkReply::NoError)
{ // BIP70 DoS protection
if (reply->size() > BIP70_MAX_PAYMENTREQUEST_SIZE) {
QString msg = tr("Payment request %2 is too large (%3 bytes, allowed %4 bytes).")
.arg(__func__)
.arg(reply->request().url().toString())
.arg(reply->size())
.arg(BIP70_MAX_PAYMENTREQUEST_SIZE);
qWarning() << QString("PaymentServer::%1:").arg(__func__) << msg;
emit message(tr("Payment request DoS protection"), msg, CClientUIInterface::MSG_ERROR);
return;
}
if (reply->error() != QNetworkReply::NoError) {
QString msg = tr("Error communicating with %1: %2") QString msg = tr("Error communicating with %1: %2")
.arg(reply->request().url().toString()) .arg(reply->request().url().toString())
.arg(reply->errorString()); .arg(reply->errorString());
qWarning() << "PaymentServer::netRequestFinished : " << msg; qWarning() << "PaymentServer::netRequestFinished: " << msg;
emit message(tr("Payment request error"), msg, CClientUIInterface::MSG_ERROR); emit message(tr("Payment request error"), msg, CClientUIInterface::MSG_ERROR);
return; return;
} }

View File

@ -118,7 +118,7 @@ protected:
bool eventFilter(QObject *object, QEvent *event); bool eventFilter(QObject *object, QEvent *event);
private: private:
static bool readPaymentRequest(const QString& filename, PaymentRequestPlus& request); static bool readPaymentRequestFromFile(const QString& filename, PaymentRequestPlus& request);
bool processPaymentRequest(PaymentRequestPlus& request, SendCoinsRecipient& recipient); bool processPaymentRequest(PaymentRequestPlus& request, SendCoinsRecipient& recipient);
void fetchRequest(const QUrl& url); void fetchRequest(const QUrl& url);