summaryrefslogtreecommitdiff
path: root/test/parallel
diff options
context:
space:
mode:
authorJames M Snell <jasnell@gmail.com>2018-01-03 13:34:45 -0800
committerJames M Snell <jasnell@gmail.com>2018-01-08 13:10:45 -0800
commit33039871c9ea941bb9a27e113739f6c628e4f3a8 (patch)
tree49bd4d54dbbb0cee4235ead3a8270571fd4ee2c2 /test/parallel
parent6aac05bf47bcbd521c7d18771b367d0bc48450a0 (diff)
downloadandroid-node-v8-33039871c9ea941bb9a27e113739f6c628e4f3a8.tar.gz
android-node-v8-33039871c9ea941bb9a27e113739f6c628e4f3a8.tar.bz2
android-node-v8-33039871c9ea941bb9a27e113739f6c628e4f3a8.zip
http2: verify flood error and unsolicited frames
* verify protections against ping and settings flooding * Strictly handle and verify handling of unsolicited ping and settings frame acks. PR-URL: https://github.com/nodejs/node/pull/17969 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Anatoli Papirovski <apapirovski@mac.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Diffstat (limited to 'test/parallel')
-rw-r--r--test/parallel/test-http2-ping-unsolicited-ack.js43
-rw-r--r--test/parallel/test-http2-settings-unsolicited-ack.js50
2 files changed, 93 insertions, 0 deletions
diff --git a/test/parallel/test-http2-ping-unsolicited-ack.js b/test/parallel/test-http2-ping-unsolicited-ack.js
new file mode 100644
index 0000000000..5a3a261cb0
--- /dev/null
+++ b/test/parallel/test-http2-ping-unsolicited-ack.js
@@ -0,0 +1,43 @@
+'use strict';
+
+const common = require('../common');
+if (!common.hasCrypto)
+ common.skip('missing crypto');
+
+const http2 = require('http2');
+const net = require('net');
+const http2util = require('../common/http2');
+
+// Test that ping flooding causes the session to be torn down
+
+const kSettings = new http2util.SettingsFrame();
+const kPingAck = new http2util.PingFrame(true);
+
+const server = http2.createServer();
+
+server.on('stream', common.mustNotCall());
+server.on('session', common.mustCall((session) => {
+ session.on('error', common.expectsError({
+ code: 'ERR_HTTP2_ERROR',
+ message: 'Protocol error'
+ }));
+ session.on('close', common.mustCall(() => server.close()));
+}));
+
+server.listen(0, common.mustCall(() => {
+ const client = net.connect(server.address().port);
+
+ client.on('connect', common.mustCall(() => {
+ client.write(http2util.kClientMagic, () => {
+ client.write(kSettings.data);
+ // Send an unsolicited ping ack
+ client.write(kPingAck.data);
+ });
+ }));
+
+ // An error event may or may not be emitted, depending on operating system
+ // and timing. We do not really care if one is emitted here or not, as the
+ // error on the server side is what we are testing for. Do not make this
+ // a common.mustCall() and there's no need to check the error details.
+ client.on('error', () => {});
+}));
diff --git a/test/parallel/test-http2-settings-unsolicited-ack.js b/test/parallel/test-http2-settings-unsolicited-ack.js
new file mode 100644
index 0000000000..fa63e9ee3f
--- /dev/null
+++ b/test/parallel/test-http2-settings-unsolicited-ack.js
@@ -0,0 +1,50 @@
+'use strict';
+
+const common = require('../common');
+if (!common.hasCrypto)
+ common.skip('missing crypto');
+
+const assert = require('assert');
+const http2 = require('http2');
+const net = require('net');
+const http2util = require('../common/http2');
+const Countdown = require('../common/countdown');
+
+// Test that an unsolicited settings ack is ignored.
+
+const kSettings = new http2util.SettingsFrame();
+const kSettingsAck = new http2util.SettingsFrame(true);
+
+const server = http2.createServer();
+let client;
+
+const countdown = new Countdown(3, () => {
+ client.destroy();
+ server.close();
+});
+
+server.on('stream', common.mustNotCall());
+server.on('session', common.mustCall((session) => {
+ session.on('remoteSettings', common.mustCall(() => countdown.dec()));
+}));
+
+server.listen(0, common.mustCall(() => {
+ client = net.connect(server.address().port);
+
+ // Ensures that the clients settings frames are not sent until the
+ // servers are received, so that the first ack is actually expected.
+ client.once('data', (chunk) => {
+ // The very first chunk of data we get from the server should
+ // be a settings frame.
+ assert.deepStrictEqual(chunk.slice(0, 9), kSettings.data);
+ // The first ack is expected.
+ client.write(kSettingsAck.data, () => countdown.dec());
+ // The second one is not and will be ignored.
+ client.write(kSettingsAck.data, () => countdown.dec());
+ });
+
+ client.on('connect', common.mustCall(() => {
+ client.write(http2util.kClientMagic);
+ client.write(kSettings.data);
+ }));
+}));