From 740561102b3e415c468362485073f49ab9a57280 Mon Sep 17 00:00:00 2001 From: Adam Kloboucnik Date: Mon, 14 May 2018 10:21:06 +0200 Subject: [PATCH 1/4] Peer should send reject message upon receiving invalid command --- lib/peer.js | 17 +++++++++++++---- test/peer.js | 16 ++++++++++++++++ 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/lib/peer.js b/lib/peer.js index a8f4dc96..85f0778a 100644 --- a/lib/peer.js +++ b/lib/peer.js @@ -217,10 +217,19 @@ Peer.prototype._sendPong = function(nonce) { * Internal function that tries to read a message from the data buffer */ Peer.prototype._readMessage = function() { - var message = this.messages.parseBuffer(this.dataBuffer); - if (message) { - this.emit(message.command, message); - this._readMessage(); + try { + var message = this.messages.parseBuffer(this.dataBuffer); + if (message) { + this.emit(message.command, message); + this._readMessage(); + } + } catch (error) { + if (error.message.indexOf('Unsupported message command:') !== -1) { + this.sendMessage(this.messages.Reject({ + ccode: this.messages.Reject._constructor.CCODE.REJECT_INVALID, + reason: 'Unknown command', + })) + } } }; diff --git a/test/peer.js b/test/peer.js index 406eab62..6d1bcb92 100644 --- a/test/peer.js +++ b/test/peer.js @@ -240,4 +240,20 @@ describe('Peer', function() { }); }); + it('send reject message if invalid command is received', function(done) { + var peer = new Peer({host: 'localhost'}); + peer.sendMessage = function(message) { + message.command.should.equal('reject'); + message.reason.should.equal('Unknown command'); + message.ccode.should.equal(messages.Reject._constructor.CCODE.REJECT_INVALID); + done(); + }; + const rawData = 'f9beb4d9' + // bitcoin mainnet magic number + '6e6f65786973740000000000' + // command (padded to 16 bytes) + '20000000' + // payload length (32) + '31085cf0' + // digest - sha256(sha256(payloadBuf)).slice(0,4) + '177aace029c59e693bb46cbe028a05ed5b8c4615f7ce590626683e2f56a22b2d'; // payload (random bytes here) + peer.dataBuffer.push(new Buffer(rawData, 'hex')); + peer._readMessage(); + }); }); From b8571e8882223eba2fbf5fb8fa5c734584cf2f7b Mon Sep 17 00:00:00 2001 From: Adam Kloboucnik Date: Mon, 14 May 2018 10:46:00 +0200 Subject: [PATCH 2/4] Peer should send reject message upon receiving message with longer than declared payload --- lib/peer.js | 11 +++++++++++ test/peer.js | 21 ++++++++++++++++++++- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/lib/peer.js b/lib/peer.js index 85f0778a..68802aa6 100644 --- a/lib/peer.js +++ b/lib/peer.js @@ -229,7 +229,18 @@ Peer.prototype._readMessage = function() { ccode: this.messages.Reject._constructor.CCODE.REJECT_INVALID, reason: 'Unknown command', })) + return; } + + if (error.message.indexOf('Data still available after parsing') !== -1) { + this.sendMessage(this.messages.Reject({ + ccode: this.messages.Reject._constructor.CCODE.REJECT_MALFORMED, + reason: 'Malformed payload', + })) + return; + } + + throw error } }; diff --git a/test/peer.js b/test/peer.js index 6d1bcb92..2421b0d8 100644 --- a/test/peer.js +++ b/test/peer.js @@ -240,7 +240,7 @@ describe('Peer', function() { }); }); - it('send reject message if invalid command is received', function(done) { + it('send reject message if unknown command is received', function(done) { var peer = new Peer({host: 'localhost'}); peer.sendMessage = function(message) { message.command.should.equal('reject'); @@ -256,4 +256,23 @@ describe('Peer', function() { peer.dataBuffer.push(new Buffer(rawData, 'hex')); peer._readMessage(); }); + + describe('send reject message for malformed payload', function() { + it('declared payload length is lower than actual payload length', function(done) { + var peer = new Peer({host: 'localhost'}); + peer.sendMessage = function(message) { + message.command.should.equal('reject'); + message.reason.should.equal('Malformed payload'); + message.ccode.should.equal(messages.Reject._constructor.CCODE.REJECT_MALFORMED); + done(); + }; + const rawData = 'f9beb4d9' + // bitcoin mainnet magic number + '70696e670000000000000000' + // command (padded to 16 bytes) + '20000000' + // payload length (here we declare 32 but actually it is 34) + '31085cf0' + // digest - sha256(sha256(payloadBuf)).slice(0,4) of the declared payload slice + '177aace029c59e693bb46cbe028a05ed5b8c4615f7ce590626683e2f56a22b2d0e'; // payload (random bytes here + added 0e at the end) + peer.dataBuffer.push(new Buffer(rawData, 'hex')); + peer._readMessage(); + }); + }); }); From 1ec39631c738b9cbb8dac9addd5c28cc43481d77 Mon Sep 17 00:00:00 2001 From: Adam Kloboucnik Date: Mon, 14 May 2018 11:13:38 +0200 Subject: [PATCH 3/4] Make gulp:lint happy --- lib/peer.js | 6 +++--- test/peer.js | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/peer.js b/lib/peer.js index 68802aa6..ba0c1d69 100644 --- a/lib/peer.js +++ b/lib/peer.js @@ -228,7 +228,7 @@ Peer.prototype._readMessage = function() { this.sendMessage(this.messages.Reject({ ccode: this.messages.Reject._constructor.CCODE.REJECT_INVALID, reason: 'Unknown command', - })) + })); return; } @@ -236,11 +236,11 @@ Peer.prototype._readMessage = function() { this.sendMessage(this.messages.Reject({ ccode: this.messages.Reject._constructor.CCODE.REJECT_MALFORMED, reason: 'Malformed payload', - })) + })); return; } - throw error + throw error; } }; diff --git a/test/peer.js b/test/peer.js index 2421b0d8..e8467717 100644 --- a/test/peer.js +++ b/test/peer.js @@ -270,7 +270,8 @@ describe('Peer', function() { '70696e670000000000000000' + // command (padded to 16 bytes) '20000000' + // payload length (here we declare 32 but actually it is 34) '31085cf0' + // digest - sha256(sha256(payloadBuf)).slice(0,4) of the declared payload slice - '177aace029c59e693bb46cbe028a05ed5b8c4615f7ce590626683e2f56a22b2d0e'; // payload (random bytes here + added 0e at the end) + // payload (random bytes here + added 0e at the end) + '177aace029c59e693bb46cbe028a05ed5b8c4615f7ce590626683e2f56a22b2d0e'; peer.dataBuffer.push(new Buffer(rawData, 'hex')); peer._readMessage(); }); From 5c56eb7d52063f2cee56f45c580373550df8a4b7 Mon Sep 17 00:00:00 2001 From: Adam Kloboucnik Date: Mon, 14 May 2018 11:51:33 +0200 Subject: [PATCH 4/4] Reject message has to have message and data fields defined --- lib/peer.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/peer.js b/lib/peer.js index ba0c1d69..627ecf4d 100644 --- a/lib/peer.js +++ b/lib/peer.js @@ -228,6 +228,8 @@ Peer.prototype._readMessage = function() { this.sendMessage(this.messages.Reject({ ccode: this.messages.Reject._constructor.CCODE.REJECT_INVALID, reason: 'Unknown command', + message: 'Unknown command', + data: '' })); return; } @@ -236,6 +238,8 @@ Peer.prototype._readMessage = function() { this.sendMessage(this.messages.Reject({ ccode: this.messages.Reject._constructor.CCODE.REJECT_MALFORMED, reason: 'Malformed payload', + message: 'Unknown command', + data: '' })); return; }