Compare commits
10 Commits
e0342a286e
...
98b49ec96f
Author | SHA256 | Date | |
---|---|---|---|
98b49ec96f | |||
f5e1c839f2 | |||
2d083583c0 | |||
8eeb6a8320 | |||
f6cb000be3 | |||
a3999ac2a7 | |||
a52fd358ee | |||
a03dbb07ed | |||
3ae33731c9 | |||
57718cd79b |
@@ -121,7 +121,7 @@ Index: node-v4.9.1/test/sequential/test-http-max-http-headers.js
|
||||
+ });
|
||||
+}
|
||||
+
|
||||
+function fillHeaders(headers, currentSize, valid = false) {
|
||||
+function fillHeaders(headers, currentSize, valid) {
|
||||
+ headers += 'a'.repeat(MAX - headers.length - 3);
|
||||
+ // Generate valid headers
|
||||
+ if (valid) {
|
||||
@@ -172,7 +172,7 @@ Index: node-v4.9.1/test/sequential/test-http-max-http-headers.js
|
||||
+
|
||||
+ // OK, Content-Length, 0, X-CRASH, aaa...
|
||||
+ const currentSize = 2 + 14 + 1 + 7;
|
||||
+ headers = fillHeaders(headers, currentSize);
|
||||
+ headers = fillHeaders(headers, currentSize, false);
|
||||
+
|
||||
+ const server = net.createServer((sock) => {
|
||||
+ sock.once('data', (chunk) => {
|
||||
@@ -202,7 +202,7 @@ Index: node-v4.9.1/test/sequential/test-http-max-http-headers.js
|
||||
+
|
||||
+ // /, Host, localhost, Agent, node, X-CRASH, a...
|
||||
+ const currentSize = 1 + 4 + 9 + 5 + 4 + 7;
|
||||
+ headers = fillHeaders(headers, currentSize);
|
||||
+ headers = fillHeaders(headers, currentSize, false);
|
||||
+
|
||||
+ const server = http.createServer(common.mustNotCall());
|
||||
+
|
||||
|
343
CVE-2018-12122.patch
Normal file
343
CVE-2018-12122.patch
Normal file
@@ -0,0 +1,343 @@
|
||||
Ported from:
|
||||
|
||||
From 618eebdd175b598a06bbc4d3d1efeb85e3fa1429 Mon Sep 17 00:00:00 2001
|
||||
From: Matteo Collina <hello@matteocollina.com>
|
||||
Date: Thu, 23 Aug 2018 16:46:07 +0200
|
||||
Subject: [PATCH] http,https: protect against slow headers attack
|
||||
|
||||
CVE-2018-12122
|
||||
|
||||
An attacker can send a char/s within headers and exahust the resources
|
||||
(file descriptors) of a system even with a tight max header length
|
||||
protection. This PR destroys a socket if it has not received the headers
|
||||
in 40s.
|
||||
|
||||
PR-URL: https://github.com/nodejs-private/node-private/pull/152
|
||||
Ref: https://github.com/nodejs-private/node-private/pull/144
|
||||
Reviewed-By: Sam Roberts <vieuxtech@gmail.com>
|
||||
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
|
||||
Reviewed-By: James M Snell <jasnell@gmail.com>
|
||||
|
||||
|
||||
Index: node-v4.9.1/doc/api/http.md
|
||||
===================================================================
|
||||
--- node-v4.9.1.orig/doc/api/http.md
|
||||
+++ node-v4.9.1/doc/api/http.md
|
||||
@@ -704,6 +704,26 @@ for handling socket timeouts.
|
||||
|
||||
Returns `server`.
|
||||
|
||||
+### server.headersTimeout
|
||||
+<!-- YAML
|
||||
+added: REPLACEME
|
||||
+-->
|
||||
+
|
||||
+* {number} **Default:** `40000`
|
||||
+
|
||||
+Limit the amount of time the parser will wait to receive the complete HTTP
|
||||
+headers.
|
||||
+
|
||||
+In case of inactivity, the rules defined in [server.timeout][] apply. However,
|
||||
+that inactivity based timeout would still allow the connection to be kept open
|
||||
+if the headers are being sent very slowly (by default, up to a byte per 2
|
||||
+minutes). In order to prevent this, whenever header data arrives an additional
|
||||
+check is made that more than `server.headersTimeout` milliseconds has not
|
||||
+passed since the connection was established. If the check fails, a `'timeout'`
|
||||
+event is emitted on the server object, and (by default) the socket is destroyed.
|
||||
+See [server.timeout][] for more information on how timeout behaviour can be
|
||||
+customised.
|
||||
+
|
||||
### server.timeout
|
||||
<!-- YAML
|
||||
added: v0.9.12
|
||||
Index: node-v4.9.1/doc/api/https.md
|
||||
===================================================================
|
||||
--- node-v4.9.1.orig/doc/api/https.md
|
||||
+++ node-v4.9.1/doc/api/https.md
|
||||
@@ -21,6 +21,12 @@ added: v0.3.4
|
||||
This class is a subclass of `tls.Server` and emits events same as
|
||||
[`http.Server`][]. See [`http.Server`][] for more information.
|
||||
|
||||
+### server.headersTimeout
|
||||
+
|
||||
+- {number} **Default:** `40000`
|
||||
+
|
||||
+See [`http.Server#headersTimeout`][].
|
||||
+
|
||||
### server.setTimeout(msecs, callback)
|
||||
<!-- YAML
|
||||
added: v0.11.2
|
||||
@@ -257,6 +263,7 @@ var req = https.request(options, (res) =
|
||||
[`Buffer`]: buffer.html#buffer_buffer
|
||||
[`globalAgent`]: #https_https_globalagent
|
||||
[`http.Agent`]: http.html#http_class_http_agent
|
||||
+[`http.Server#headersTimeout`]: http.html#http_server_headerstimeout
|
||||
[`http.close()`]: http.html#http_server_close_callback
|
||||
[`http.get()`]: http.html#http_http_get_options_callback
|
||||
[`http.listen()`]: http.html#http_server_listen_port_hostname_backlog_callback
|
||||
Index: node-v4.9.1/lib/_http_outgoing.js
|
||||
===================================================================
|
||||
--- node-v4.9.1.orig/lib/_http_outgoing.js
|
||||
+++ node-v4.9.1/lib/_http_outgoing.js
|
||||
@@ -31,20 +31,33 @@ const automaticHeaders = {
|
||||
};
|
||||
|
||||
|
||||
-var dateCache;
|
||||
+var nowCache;
|
||||
+var utcCache;
|
||||
+
|
||||
+function nowDate() {
|
||||
+ if (!nowCache) cache();
|
||||
+ return nowCache;
|
||||
+}
|
||||
+
|
||||
function utcDate() {
|
||||
- if (!dateCache) {
|
||||
- var d = new Date();
|
||||
- dateCache = d.toUTCString();
|
||||
- timers.enroll(utcDate, 1000 - d.getMilliseconds());
|
||||
- timers._unrefActive(utcDate);
|
||||
- }
|
||||
- return dateCache;
|
||||
+ if (!utcCache) cache();
|
||||
+ return utcCache;
|
||||
}
|
||||
-utcDate._onTimeout = function() {
|
||||
- dateCache = undefined;
|
||||
+
|
||||
+function cache() {
|
||||
+ const d = new Date();
|
||||
+ nowCache = d.valueOf();
|
||||
+ utcCache = d.toUTCString();
|
||||
+ timers.enroll(cache, 1000 - d.getMilliseconds());
|
||||
+ timers._unrefActive(cache);
|
||||
+}
|
||||
+
|
||||
+cache._onTimeout = function() {
|
||||
+ nowCache = undefined;
|
||||
+ utcCache = undefined;
|
||||
};
|
||||
|
||||
+exports.nowDate = nowDate;
|
||||
|
||||
function OutgoingMessage() {
|
||||
Stream.call(this);
|
||||
Index: node-v4.9.1/lib/_http_server.js
|
||||
===================================================================
|
||||
--- node-v4.9.1.orig/lib/_http_server.js
|
||||
+++ node-v4.9.1/lib/_http_server.js
|
||||
@@ -14,6 +14,7 @@ const continueExpression = common.contin
|
||||
const chunkExpression = common.chunkExpression;
|
||||
const httpSocketSetup = common.httpSocketSetup;
|
||||
const OutgoingMessage = require('_http_outgoing').OutgoingMessage;
|
||||
+const nowDate = require('_http_outgoing').nowDate;
|
||||
|
||||
const STATUS_CODES = exports.STATUS_CODES = {
|
||||
100: 'Continue',
|
||||
@@ -251,6 +252,7 @@ function Server(requestListener) {
|
||||
this.timeout = 2 * 60 * 1000;
|
||||
|
||||
this._pendingResponseData = 0;
|
||||
+ this.headersTimeout = 40 * 1000; // 40 seconds
|
||||
}
|
||||
util.inherits(Server, net.Server);
|
||||
|
||||
@@ -324,6 +326,9 @@ function connectionListener(socket) {
|
||||
var parser = parsers.alloc();
|
||||
parser.reinitialize(HTTPParser.REQUEST);
|
||||
parser.socket = socket;
|
||||
+
|
||||
+ // We are starting to wait for our headers.
|
||||
+ parser.parsingHeadersStart = nowDate();
|
||||
socket.parser = parser;
|
||||
parser.incoming = null;
|
||||
|
||||
@@ -376,6 +381,20 @@ function connectionListener(socket) {
|
||||
function onParserExecute(ret, d) {
|
||||
socket._unrefTimer();
|
||||
debug('SERVER socketOnParserExecute %d', ret);
|
||||
+
|
||||
+ var start = parser.parsingHeadersStart;
|
||||
+
|
||||
+ // If we have not parsed the headers, destroy the socket
|
||||
+ // after server.headersTimeout to protect from DoS attacks.
|
||||
+ // start === 0 means that we have parsed headers.
|
||||
+ if (start !== 0 && nowDate() - start > self.headersTimeout) {
|
||||
+ var serverTimeout = self.emit('timeout', socket);
|
||||
+
|
||||
+ if (!serverTimeout)
|
||||
+ socket.destroy();
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
onParserExecuteCommon(ret, undefined);
|
||||
}
|
||||
|
||||
@@ -444,7 +463,6 @@ function connectionListener(socket) {
|
||||
}
|
||||
}
|
||||
|
||||
-
|
||||
// The following callback is issued after the headers have been read on a
|
||||
// new message. In this callback we setup the response object and pass it
|
||||
// to the user.
|
||||
Index: node-v4.9.1/lib/https.js
|
||||
===================================================================
|
||||
--- node-v4.9.1.orig/lib/https.js
|
||||
+++ node-v4.9.1/lib/https.js
|
||||
@@ -34,6 +34,8 @@ function Server(opts, requestListener) {
|
||||
});
|
||||
|
||||
this.timeout = 2 * 60 * 1000;
|
||||
+
|
||||
+ this.headersTimeout = 40 * 1000; // 40 seconds
|
||||
}
|
||||
inherits(Server, tls.Server);
|
||||
exports.Server = Server;
|
||||
Index: node-v4.9.1/test/parallel/test-http-slow-headers.js
|
||||
===================================================================
|
||||
--- /dev/null
|
||||
+++ node-v4.9.1/test/parallel/test-http-slow-headers.js
|
||||
@@ -0,0 +1,56 @@
|
||||
+'use strict';
|
||||
+
|
||||
+const common = require('../common');
|
||||
+const assert = require('assert');
|
||||
+const createServer = require('http').createServer;
|
||||
+const connect = require('net').connect;
|
||||
+
|
||||
+// This test validates that the 'timeout' event fires
|
||||
+// after server.headersTimeout.
|
||||
+
|
||||
+const headers =
|
||||
+ 'GET / HTTP/1.1\r\n' +
|
||||
+ 'Host: localhost\r\n' +
|
||||
+ 'Agent: node\r\n';
|
||||
+
|
||||
+const server = createServer(common.mustNotCall());
|
||||
+let sendCharEvery = 1000;
|
||||
+
|
||||
+// 40 seconds is the default
|
||||
+assert.strictEqual(server.headersTimeout, 40 * 1000);
|
||||
+
|
||||
+// Pass a REAL env variable to shortening up the default
|
||||
+// value which is 40s otherwise this is useful for manual
|
||||
+// testing
|
||||
+if (!process.env.REAL) {
|
||||
+ sendCharEvery = common.platformTimeout(10);
|
||||
+ server.headersTimeout = 2 * sendCharEvery;
|
||||
+}
|
||||
+
|
||||
+server.once('timeout', common.mustCall((socket) => {
|
||||
+ socket.destroy();
|
||||
+}));
|
||||
+
|
||||
+server.listen(0, common.mustCall(() => {
|
||||
+ const client = connect(server.address().port);
|
||||
+ client.write(headers);
|
||||
+ client.write('X-CRASH: ');
|
||||
+
|
||||
+ const interval = setInterval(() => {
|
||||
+ client.write('a');
|
||||
+ }, sendCharEvery);
|
||||
+
|
||||
+ client.resume();
|
||||
+
|
||||
+ const onClose = common.mustCall(() => {
|
||||
+ client.removeListener('close', onClose);
|
||||
+ client.removeListener('error', onClose);
|
||||
+ client.removeListener('end', onClose);
|
||||
+ clearInterval(interval);
|
||||
+ server.close();
|
||||
+ });
|
||||
+
|
||||
+ client.on('error', onClose);
|
||||
+ client.on('close', onClose);
|
||||
+ client.on('end', onClose);
|
||||
+}));
|
||||
Index: node-v4.9.1/test/parallel/test-https-slow-headers.js
|
||||
===================================================================
|
||||
--- /dev/null
|
||||
+++ node-v4.9.1/test/parallel/test-https-slow-headers.js
|
||||
@@ -0,0 +1,80 @@
|
||||
+'use strict';
|
||||
+
|
||||
+const common = require('../common');
|
||||
+const path = require('path');
|
||||
+const fs = require('fs');
|
||||
+
|
||||
+const fixturesDir = path.join(__dirname, '..', 'fixtures');
|
||||
+
|
||||
+function fixturesPath(p1, p2) {
|
||||
+ return path.join(fixturesDir, p1, p2);
|
||||
+}
|
||||
+
|
||||
+function readKey(name, enc) {
|
||||
+ return fs.readFileSync(fixturesPath('keys', name), enc);
|
||||
+}
|
||||
+
|
||||
+if (!common.hasCrypto)
|
||||
+ common.skip('missing crypto');
|
||||
+
|
||||
+const assert = require('assert');
|
||||
+const createServer = require('https').createServer;
|
||||
+const connect = require('tls').connect;
|
||||
+
|
||||
+// This test validates that the 'timeout' event fires
|
||||
+// after server.headersTimeout.
|
||||
+
|
||||
+const headers =
|
||||
+ 'GET / HTTP/1.1\r\n' +
|
||||
+ 'Host: localhost\r\n' +
|
||||
+ 'Agent: node\r\n';
|
||||
+
|
||||
+const server = createServer({
|
||||
+ key: readKey('agent1-key.pem'),
|
||||
+ cert: readKey('agent1-cert.pem'),
|
||||
+ ca: readKey('ca1-cert.pem'),
|
||||
+}, common.mustNotCall());
|
||||
+
|
||||
+let sendCharEvery = 1000;
|
||||
+
|
||||
+// 40 seconds is the default
|
||||
+assert.strictEqual(server.headersTimeout, 40 * 1000);
|
||||
+
|
||||
+// pass a REAL env variable to shortening up the default
|
||||
+// value which is 40s otherwise
|
||||
+// this is useful for manual testing
|
||||
+if (!process.env.REAL) {
|
||||
+ sendCharEvery = common.platformTimeout(10);
|
||||
+ server.headersTimeout = 2 * sendCharEvery;
|
||||
+}
|
||||
+
|
||||
+server.once('timeout', common.mustCall((socket) => {
|
||||
+ socket.destroy();
|
||||
+}));
|
||||
+
|
||||
+server.listen(0, common.mustCall(() => {
|
||||
+ const client = connect({
|
||||
+ port: server.address().port,
|
||||
+ rejectUnauthorized: false
|
||||
+ });
|
||||
+ client.write(headers);
|
||||
+ client.write('X-CRASH: ');
|
||||
+
|
||||
+ const interval = setInterval(() => {
|
||||
+ client.write('a');
|
||||
+ }, sendCharEvery);
|
||||
+
|
||||
+ client.resume();
|
||||
+
|
||||
+ const onClose = common.mustCall(() => {
|
||||
+ client.removeListener('close', onClose);
|
||||
+ client.removeListener('error', onClose);
|
||||
+ client.removeListener('end', onClose);
|
||||
+ clearInterval(interval);
|
||||
+ server.close();
|
||||
+ });
|
||||
+
|
||||
+ client.on('error', onClose);
|
||||
+ client.on('close', onClose);
|
||||
+ client.on('end', onClose);
|
||||
+}));
|
28
CVE-2019-13173.patch
Normal file
28
CVE-2019-13173.patch
Normal file
@@ -0,0 +1,28 @@
|
||||
CVE-2019-13173
|
||||
|
||||
Backported from
|
||||
https://github.com/npm/fstream/commit/6a77d2fa6e1462693cf8e46f930da96ec1b0bb22
|
||||
|
||||
From 6a77d2fa6e1462693cf8e46f930da96ec1b0bb22 Mon Sep 17 00:00:00 2001
|
||||
From: isaacs <i@izs.me>
|
||||
Date: Tue, 14 May 2019 17:37:57 -0700
|
||||
Subject: [PATCH] Clobber a Link if it's in the way of a File
|
||||
|
||||
Fixes https://github.com/npm/node-tar/issues/212
|
||||
---
|
||||
lib/writer.js | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/lib/writer.js b/lib/writer.js
|
||||
index 140e449..3f10547 100644
|
||||
--- a/deps/npm/node_modules/fstream/lib/writer.js
|
||||
+++ b/deps/npm/node_modules/fstream/lib/writer.js
|
||||
@@ -147,7 +147,7 @@ Writer.prototype._stat = function (current) {
|
||||
|
||||
// if it's a type change, then we need to clobber or error.
|
||||
// if it's not a type change, then let the impl take care of it.
|
||||
- if (currentType !== self.type) {
|
||||
+ if (currentType !== self.type || self.type === 'File' && current.nlink > 1) {
|
||||
return rimraf(self._path, function (er) {
|
||||
if (er) return self.error(er)
|
||||
self._old = null
|
659
http-keep-alive.patch
Normal file
659
http-keep-alive.patch
Normal file
@@ -0,0 +1,659 @@
|
||||
commit b13b4a9ffb6038be1c21c20ece50d5fe367807b3
|
||||
Author: Matteo Collina <hello@matteocollina.com>
|
||||
Date: Sat Dec 1 16:29:13 2018 +0100
|
||||
|
||||
http: prevent slowloris with keepalive connections
|
||||
|
||||
Fixes: https://github.com/nodejs-private/security/issues/214
|
||||
PR-URL: https://github.com/nodejs-private/node-private/pull/162
|
||||
Reviewed-By: Rod Vagg <rod@vagg.org>
|
||||
Reviewed-By: Sam Roberts <vieuxtech@gmail.com>
|
||||
Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com>
|
||||
|
||||
|
||||
commit e9ae4aaaad5947075bdb3d1f558281aa1a729b36
|
||||
Author: Alexey Orlenko <eaglexrlnk@gmail.com>
|
||||
Date: Thu Jun 8 17:20:24 2017 +0300
|
||||
|
||||
http: fix timeout reset after keep-alive timeout
|
||||
|
||||
Fix the logic of resetting the socket timeout of keep-alive HTTP
|
||||
connections and add two tests:
|
||||
|
||||
* `test-http-server-keep-alive-timeout-slow-server` is a regression test
|
||||
for GH-13391. It ensures that the server-side keep-alive timeout will
|
||||
not fire during processing of a request.
|
||||
|
||||
* `test-http-server-keep-alive-timeout-slow-client-headers` ensures that
|
||||
the regular socket timeout is restored as soon as a client starts
|
||||
sending a new request, not as soon as the whole message is received,
|
||||
so that the keep-alive timeout will not fire while, e.g., the client
|
||||
is sending large cookies.
|
||||
|
||||
commit 06a208d3166493cc5bbc63b5cdbe473dbf4ad0ec
|
||||
Author: realwakka <realwakka@gmail.com>
|
||||
Date: Sun Jun 4 14:03:11 2017 +0900
|
||||
|
||||
test: refactor test-http-server-keep-alive-timeout
|
||||
|
||||
Make the same reliability changes that were applied to the https test in
|
||||
ce5745bf92f586c58366e9f738441d69118f2c18.
|
||||
|
||||
Refs: https://github.com/nodejs/node/pull/13312
|
||||
PR-URL: https://github.com/nodejs/node/pull/13448
|
||||
Reviewed-By: Rich Trott <rtrott@gmail.com>
|
||||
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
|
||||
Reviewed-By: Refael Ackermann <refack@gmail.com>
|
||||
Reviewed-By: James M Snell <jasnell@gmail.com>
|
||||
Reviewed-By: Alexey Orlenko <eaglexrlnk@gmail.com>
|
||||
|
||||
commit 1c7fbdc53bbf8bf43ca32b2c6e9f513508ac90fa
|
||||
Author: Rich Trott <rtrott@gmail.com>
|
||||
Date: Tue May 30 13:06:52 2017 -0700
|
||||
|
||||
test: improve test-https-server-keep-alive-timeout
|
||||
|
||||
The test is flaky under load. These changes greatly improve reliability.
|
||||
|
||||
* Use a recurring interval to determine when the test should end rather
|
||||
than a timer.
|
||||
* Increase server timeout to 500ms to allow for events being delayed by
|
||||
system load
|
||||
|
||||
Changing to an interval has the added benefit of reducing the test run
|
||||
time from over 2 seconds to under 1 second.
|
||||
|
||||
Fixes: https://github.com/nodejs/node/issues/13307
|
||||
|
||||
PR-URL: https://github.com/nodejs/node/pull/13312
|
||||
Reviewed-By: Refael Ackermann <refack@gmail.com>
|
||||
Reviewed-By: James M Snell <jasnell@gmail.com>
|
||||
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
|
||||
Reviewed-By: Alexey Orlenko <eaglexrlnk@gmail.com>
|
||||
|
||||
commit f23b3b6bad391cc3efe4cc815954f009c05fe63a
|
||||
Author: Timur Shemsedinov <timur.shemsedinov@gmail.com>
|
||||
Date: Thu Oct 29 21:53:43 2015 +0200
|
||||
|
||||
http: destroy sockets after keepAliveTimeout
|
||||
|
||||
Implement server.keepAliveTimeout in addition to server.timeout to
|
||||
prevent temporary socket/memory leaking in keep-alive mode.
|
||||
|
||||
PR-URL: https://github.com/nodejs/node/pull/2534
|
||||
Author: Timur Shemsedinov <timur.shemsedinov@gmail.com>
|
||||
Author: Alexey Orlenko <eaglexrlnk@gmail.com>
|
||||
Reviewed-By: James M Snell <jasnell@gmail.com>
|
||||
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
|
||||
Reviewed-By: Franziska Hinkelmann <franziska.hinkelmann@gmail.com>
|
||||
Reviewed-By: Refael Ackermann <refack@gmail.com>
|
||||
|
||||
|
||||
Index: node-v4.9.1/lib/_http_server.js
|
||||
===================================================================
|
||||
--- node-v4.9.1.orig/lib/_http_server.js
|
||||
+++ node-v4.9.1/lib/_http_server.js
|
||||
@@ -250,6 +250,7 @@ function Server(requestListener) {
|
||||
});
|
||||
|
||||
this.timeout = 2 * 60 * 1000;
|
||||
+ this.keepAliveTimeout = 5000;
|
||||
|
||||
this._pendingResponseData = 0;
|
||||
this.headersTimeout = 40 * 1000; // 40 seconds
|
||||
@@ -323,6 +324,8 @@ function connectionListener(socket) {
|
||||
socket.destroy();
|
||||
});
|
||||
|
||||
+ socket._keepAliveTimeoutSet = false;
|
||||
+
|
||||
var parser = parsers.alloc();
|
||||
parser.reinitialize(HTTPParser.REQUEST);
|
||||
parser.socket = socket;
|
||||
@@ -373,6 +376,15 @@ function connectionListener(socket) {
|
||||
function socketOnData(d) {
|
||||
assert(!socket._paused);
|
||||
debug('SERVER socketOnData %d', d.length);
|
||||
+
|
||||
+ if (socket._keepAliveTimeoutSet) {
|
||||
+ socket.setTimeout(0);
|
||||
+ if (self.timeout) {
|
||||
+ socket.setTimeout(self.timeout);
|
||||
+ }
|
||||
+ socket._keepAliveTimeoutSet = false;
|
||||
+ }
|
||||
+
|
||||
var ret = parser.execute(d);
|
||||
|
||||
onParserExecuteCommon(ret, d);
|
||||
@@ -399,6 +411,8 @@ function connectionListener(socket) {
|
||||
}
|
||||
|
||||
function onParserExecuteCommon(ret, d) {
|
||||
+ resetSocketTimeout(self, socket);
|
||||
+
|
||||
if (ret instanceof Error) {
|
||||
debug('parse error');
|
||||
socket.destroy(ret);
|
||||
@@ -481,8 +495,14 @@ function connectionListener(socket) {
|
||||
}
|
||||
|
||||
function parserOnIncoming(req, shouldKeepAlive) {
|
||||
+ resetSocketTimeout(self, socket);
|
||||
+
|
||||
incoming.push(req);
|
||||
|
||||
+ if (self.keepAliveTimeout > 0) {
|
||||
+ req.on('end', resetHeadersTimeoutOnReqEnd);
|
||||
+ }
|
||||
+
|
||||
// If the writable end isn't consuming, then stop reading
|
||||
// so that we don't become overwhelmed by a flood of
|
||||
// pipelined requests that may never be resolved.
|
||||
@@ -534,6 +554,12 @@ function connectionListener(socket) {
|
||||
|
||||
if (res._last) {
|
||||
socket.destroySoon();
|
||||
+ } else if (outgoing.length === 0) {
|
||||
+ if (self.keepAliveTimeout) {
|
||||
+ socket.setTimeout(0);
|
||||
+ socket.setTimeout(self.keepAliveTimeout);
|
||||
+ socket._keepAliveTimeoutSet = true;
|
||||
+ }
|
||||
} else {
|
||||
// start sending the next message
|
||||
var m = outgoing.shift();
|
||||
@@ -561,6 +587,14 @@ function connectionListener(socket) {
|
||||
}
|
||||
exports._connectionListener = connectionListener;
|
||||
|
||||
+function resetSocketTimeout(server, socket) {
|
||||
+ if (!socket._keepAliveTimeoutSet)
|
||||
+ return;
|
||||
+
|
||||
+ socket.setTimeout(server.timeout || 0);
|
||||
+ socket._keepAliveTimeoutSet = false;
|
||||
+}
|
||||
+
|
||||
function onSocketResume() {
|
||||
// It may seem that the socket is resumed, but this is an enemy's trick to
|
||||
// deceive us! `resume` is emitted asynchronously, and may be called from
|
||||
@@ -608,3 +642,15 @@ function socketOnWrap(ev, fn) {
|
||||
|
||||
return res;
|
||||
}
|
||||
+
|
||||
+function resetHeadersTimeoutOnReqEnd() {
|
||||
+ debug('resetHeadersTimeoutOnReqEnd');
|
||||
+
|
||||
+ var parser = this.socket.parser;
|
||||
+ // Parser can be null if the socket was destroyed
|
||||
+ // in that case, there is nothing to do.
|
||||
+ if (parser !== null) {
|
||||
+ parser.parsingHeadersStart = nowDate();
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
Index: node-v4.9.1/test/parallel/test-http-server-keep-alive-timeout-slow-client-headers.js
|
||||
===================================================================
|
||||
--- /dev/null
|
||||
+++ node-v4.9.1/test/parallel/test-http-server-keep-alive-timeout-slow-client-headers.js
|
||||
@@ -0,0 +1,57 @@
|
||||
+'use strict';
|
||||
+
|
||||
+const common = require('../common');
|
||||
+const assert = require('assert');
|
||||
+const http = require('http');
|
||||
+const net = require('net');
|
||||
+
|
||||
+const server = http.createServer(common.mustCall((req, res) => {
|
||||
+ res.end();
|
||||
+}, 2));
|
||||
+
|
||||
+server.keepAliveTimeout = common.platformTimeout(100);
|
||||
+
|
||||
+server.listen(0, common.mustCall(() => {
|
||||
+ const port = server.address().port;
|
||||
+ const socket = net.connect({ port }, common.mustCall(() => {
|
||||
+ request(common.mustCall(() => {
|
||||
+ // Make a second request on the same socket, after the keep-alive timeout
|
||||
+ // has been set on the server side.
|
||||
+ request(common.mustCall(() => {}));
|
||||
+ }));
|
||||
+ }));
|
||||
+
|
||||
+ server.on('timeout', common.mustCall(() => {
|
||||
+ socket.end();
|
||||
+ server.close();
|
||||
+ }));
|
||||
+
|
||||
+ function request(callback) {
|
||||
+ socket.setEncoding('utf8');
|
||||
+ socket.on('data', onData);
|
||||
+ let response = '';
|
||||
+
|
||||
+ // Simulate a client that sends headers slowly (with a period of inactivity
|
||||
+ // that is longer than the keep-alive timeout).
|
||||
+ socket.write('GET / HTTP/1.1\r\n' +
|
||||
+ `Host: localhost:${port}\r\n`);
|
||||
+ setTimeout(() => {
|
||||
+ socket.write('Connection: keep-alive\r\n' +
|
||||
+ '\r\n');
|
||||
+ }, common.platformTimeout(300));
|
||||
+
|
||||
+ function onData(chunk) {
|
||||
+ response += chunk;
|
||||
+ if (chunk.includes('\r\n')) {
|
||||
+ socket.removeListener('data', onData);
|
||||
+ onHeaders();
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ function onHeaders() {
|
||||
+ assert.ok(response.includes('HTTP/1.1 200 OK\r\n'));
|
||||
+ assert.ok(response.includes('Connection: keep-alive\r\n'));
|
||||
+ callback();
|
||||
+ }
|
||||
+ }
|
||||
+}));
|
||||
Index: node-v4.9.1/test/parallel/test-http-slow-headers-keepalive.js
|
||||
===================================================================
|
||||
--- /dev/null
|
||||
+++ node-v4.9.1/test/parallel/test-http-slow-headers-keepalive.js
|
||||
@@ -0,0 +1,59 @@
|
||||
+'use strict';
|
||||
+
|
||||
+const common = require('../common');
|
||||
+const http = require('http');
|
||||
+const net = require('net');
|
||||
+
|
||||
+const headers =
|
||||
+ 'GET / HTTP/1.1\r\n' +
|
||||
+ 'Host: localhost\r\n' +
|
||||
+ 'Connection: keep-alive' +
|
||||
+ 'Agent: node\r\n';
|
||||
+
|
||||
+let sendCharEvery = 1000;
|
||||
+
|
||||
+const server = http.createServer(common.mustCall((req, res) => {
|
||||
+ res.writeHead(200);
|
||||
+ res.end();
|
||||
+}));
|
||||
+
|
||||
+// Pass a REAL env variable to shortening up the default
|
||||
+// value which is 40s otherwise this is useful for manual
|
||||
+// testing
|
||||
+if (!process.env.REAL) {
|
||||
+ sendCharEvery = common.platformTimeout(10);
|
||||
+ server.headersTimeout = 2 * sendCharEvery;
|
||||
+}
|
||||
+
|
||||
+server.once('timeout', common.mustCall((socket) => {
|
||||
+ socket.destroy();
|
||||
+}));
|
||||
+
|
||||
+server.listen(0, () => {
|
||||
+ const client = net.connect(server.address().port);
|
||||
+ client.write(headers);
|
||||
+ // finish the first request
|
||||
+ client.write('\r\n');
|
||||
+ // second request
|
||||
+ client.write(headers);
|
||||
+ client.write('X-CRASH: ');
|
||||
+
|
||||
+ const interval = setInterval(() => {
|
||||
+ client.write('a');
|
||||
+ }, sendCharEvery);
|
||||
+
|
||||
+ client.resume();
|
||||
+
|
||||
+ const onClose = common.mustCall(() => {
|
||||
+ client.removeListener('close', onClose);
|
||||
+ client.removeListener('error', onClose);
|
||||
+ client.removeListener('end', onClose);
|
||||
+ clearInterval(interval);
|
||||
+ server.close();
|
||||
+ });
|
||||
+
|
||||
+ client.on('error', onClose);
|
||||
+ client.on('close', onClose);
|
||||
+ client.on('end', onClose);
|
||||
+});
|
||||
+
|
||||
Index: node-v4.9.1/test/parallel/test-http-server-keep-alive-timeout-slow-server.js
|
||||
===================================================================
|
||||
--- /dev/null
|
||||
+++ node-v4.9.1/test/parallel/test-http-server-keep-alive-timeout-slow-server.js
|
||||
@@ -0,0 +1,50 @@
|
||||
+'use strict';
|
||||
+
|
||||
+const common = require('../common');
|
||||
+const assert = require('assert');
|
||||
+const http = require('http');
|
||||
+
|
||||
+const server = http.createServer(common.mustCall((req, res) => {
|
||||
+ if (req.url === '/first') {
|
||||
+ res.end('ok');
|
||||
+ return;
|
||||
+ }
|
||||
+ setTimeout(() => {
|
||||
+ res.end('ok');
|
||||
+ }, common.platformTimeout(500));
|
||||
+}, 2));
|
||||
+
|
||||
+server.keepAliveTimeout = common.platformTimeout(200);
|
||||
+
|
||||
+const agent = new http.Agent({
|
||||
+ keepAlive: true,
|
||||
+ maxSockets: 1
|
||||
+});
|
||||
+
|
||||
+function request(path, callback) {
|
||||
+ const port = server.address().port;
|
||||
+ const req = http.request({ agent, path, port }, common.mustCall((res) => {
|
||||
+ assert.strictEqual(res.statusCode, 200);
|
||||
+
|
||||
+ res.setEncoding('utf8');
|
||||
+
|
||||
+ let result = '';
|
||||
+ res.on('data', (chunk) => {
|
||||
+ result += chunk;
|
||||
+ });
|
||||
+
|
||||
+ res.on('end', common.mustCall(() => {
|
||||
+ assert.strictEqual(result, 'ok');
|
||||
+ callback();
|
||||
+ }));
|
||||
+ }));
|
||||
+ req.end();
|
||||
+}
|
||||
+
|
||||
+server.listen(0, common.mustCall(() => {
|
||||
+ request('/first', () => {
|
||||
+ request('/second', () => {
|
||||
+ server.close();
|
||||
+ });
|
||||
+ });
|
||||
+}));
|
||||
Index: node-v4.9.1/doc/api/http.md
|
||||
===================================================================
|
||||
--- node-v4.9.1.orig/doc/api/http.md
|
||||
+++ node-v4.9.1/doc/api/http.md
|
||||
@@ -729,17 +729,33 @@ customised.
|
||||
added: v0.9.12
|
||||
-->
|
||||
|
||||
-* {Number} Default = 120000 (2 minutes)
|
||||
+* {number} Timeout in milliseconds. Defaults to 120000 (2 minutes).
|
||||
|
||||
The number of milliseconds of inactivity before a socket is presumed
|
||||
to have timed out.
|
||||
|
||||
-Note that the socket timeout logic is set up on connection, so
|
||||
-changing this value only affects *new* connections to the server, not
|
||||
-any existing connections.
|
||||
+A value of 0 will disable the timeout behavior on incoming connections.
|
||||
|
||||
-Set to 0 to disable any kind of automatic timeout behavior on incoming
|
||||
-connections.
|
||||
+*Note*: The socket timeout logic is set up on connection, so changing this
|
||||
+value only affects new connections to the server, not any existing connections.
|
||||
+
|
||||
+### server.keepAliveTimeout
|
||||
+<!-- YAML
|
||||
+added: REPLACEME
|
||||
+-->
|
||||
+
|
||||
+* {number} Timeout in milliseconds. Defaults to 5000 (5 seconds).
|
||||
+
|
||||
+The number of milliseconds of inactivity a server needs to wait for additional
|
||||
+incoming data, after it has finished writing the last response, before a socket
|
||||
+will be destroyed. If the server receives new data before the keep-alive
|
||||
+timeout has fired, it will reset the regular inactivity timeout, i.e.,
|
||||
+[`server.timeout`][].
|
||||
+
|
||||
+A value of 0 will disable the keep-alive timeout behavior on incoming connections.
|
||||
+
|
||||
+*Note*: The socket timeout logic is set up on connection, so changing this
|
||||
+value only affects new connections to the server, not any existing connections.
|
||||
|
||||
## Class: http.ServerResponse
|
||||
<!-- YAML
|
||||
@@ -1498,6 +1514,7 @@ There are a few special headers that sho
|
||||
[`response.write(data, encoding)`]: #http_response_write_chunk_encoding_callback
|
||||
[`response.writeContinue()`]: #http_response_writecontinue
|
||||
[`response.writeHead()`]: #http_response_writehead_statuscode_statusmessage_headers
|
||||
+[`server.timeout`]: #http_server_timeout
|
||||
[`socket.setKeepAlive()`]: net.html#net_socket_setkeepalive_enable_initialdelay
|
||||
[`socket.setNoDelay()`]: net.html#net_socket_setnodelay_nodelay
|
||||
[`socket.setTimeout()`]: net.html#net_socket_settimeout_timeout_callback
|
||||
Index: node-v4.9.1/doc/api/https.md
|
||||
===================================================================
|
||||
--- node-v4.9.1.orig/doc/api/https.md
|
||||
+++ node-v4.9.1/doc/api/https.md
|
||||
@@ -41,6 +41,14 @@ added: v0.11.2
|
||||
|
||||
See [`http.Server#timeout`][].
|
||||
|
||||
+### server.keepAliveTimeout
|
||||
+<!-- YAML
|
||||
+added: REPLACEME
|
||||
+-->
|
||||
+- {number} Defaults to 5000 (5 seconds).
|
||||
+
|
||||
+See [`http.Server#keepAliveTimeout`][].
|
||||
+
|
||||
## https.createServer(options[, requestListener])
|
||||
<!-- YAML
|
||||
added: v0.3.4
|
||||
@@ -264,6 +272,7 @@ var req = https.request(options, (res) =
|
||||
[`globalAgent`]: #https_https_globalagent
|
||||
[`http.Agent`]: http.html#http_class_http_agent
|
||||
[`http.Server#headersTimeout`]: http.html#http_server_headerstimeout
|
||||
+[`http.Server#keepAliveTimeout`]: http.html#http_server_keepalivetimeout
|
||||
[`http.close()`]: http.html#http_server_close_callback
|
||||
[`http.get()`]: http.html#http_http_get_options_callback
|
||||
[`http.listen()`]: http.html#http_server_listen_port_hostname_backlog_callback
|
||||
Index: node-v4.9.1/lib/https.js
|
||||
===================================================================
|
||||
--- node-v4.9.1.orig/lib/https.js
|
||||
+++ node-v4.9.1/lib/https.js
|
||||
@@ -34,7 +34,7 @@ function Server(opts, requestListener) {
|
||||
});
|
||||
|
||||
this.timeout = 2 * 60 * 1000;
|
||||
-
|
||||
+ this.keepAliveTimeout = 5000;
|
||||
this.headersTimeout = 40 * 1000; // 40 seconds
|
||||
}
|
||||
inherits(Server, tls.Server);
|
||||
Index: node-v4.9.1/test/parallel/test-http-server-keep-alive-timeout.js
|
||||
===================================================================
|
||||
--- /dev/null
|
||||
+++ node-v4.9.1/test/parallel/test-http-server-keep-alive-timeout.js
|
||||
@@ -0,0 +1,95 @@
|
||||
+'use strict';
|
||||
+
|
||||
+const common = require('../common');
|
||||
+const assert = require('assert');
|
||||
+const http = require('http');
|
||||
+const net = require('net');
|
||||
+
|
||||
+const tests = [];
|
||||
+
|
||||
+function test(fn) {
|
||||
+ if (!tests.length) {
|
||||
+ process.nextTick(run);
|
||||
+ }
|
||||
+ tests.push(fn);
|
||||
+}
|
||||
+
|
||||
+function run() {
|
||||
+ const fn = tests.shift();
|
||||
+ if (fn) fn(run);
|
||||
+}
|
||||
+
|
||||
+test(function serverEndKeepAliveTimeoutWithPipeline(cb) {
|
||||
+ let socket;
|
||||
+ let destroyedSockets = 0;
|
||||
+ let timeoutCount = 0;
|
||||
+ let requestCount = 0;
|
||||
+ process.on('exit', () => {
|
||||
+ assert.strictEqual(timeoutCount, 1);
|
||||
+ assert.strictEqual(requestCount, 3);
|
||||
+ assert.strictEqual(destroyedSockets, 1);
|
||||
+ });
|
||||
+ const server = http.createServer((req, res) => {
|
||||
+ socket = req.socket;
|
||||
+ requestCount++;
|
||||
+ res.end();
|
||||
+ });
|
||||
+ server.setTimeout(200, (socket) => {
|
||||
+ timeoutCount++;
|
||||
+ socket.destroy();
|
||||
+ });
|
||||
+ server.keepAliveTimeout = 50;
|
||||
+ server.listen(0, common.mustCall(() => {
|
||||
+ const options = {
|
||||
+ port: server.address().port,
|
||||
+ allowHalfOpen: true
|
||||
+ };
|
||||
+ const c = net.connect(options, () => {
|
||||
+ c.write('GET /1 HTTP/1.1\r\nHost: localhost\r\n\r\n');
|
||||
+ c.write('GET /2 HTTP/1.1\r\nHost: localhost\r\n\r\n');
|
||||
+ c.write('GET /3 HTTP/1.1\r\nHost: localhost\r\n\r\n');
|
||||
+ });
|
||||
+ setTimeout(() => {
|
||||
+ server.close();
|
||||
+ if (socket.destroyed) destroyedSockets++;
|
||||
+ cb();
|
||||
+ }, 1000);
|
||||
+ }));
|
||||
+});
|
||||
+
|
||||
+test(function serverNoEndKeepAliveTimeoutWithPipeline(cb) {
|
||||
+ let socket;
|
||||
+ let destroyedSockets = 0;
|
||||
+ let timeoutCount = 0;
|
||||
+ let requestCount = 0;
|
||||
+ process.on('exit', () => {
|
||||
+ assert.strictEqual(timeoutCount, 1);
|
||||
+ assert.strictEqual(requestCount, 3);
|
||||
+ assert.strictEqual(destroyedSockets, 1);
|
||||
+ });
|
||||
+ const server = http.createServer((req, res) => {
|
||||
+ socket = req.socket;
|
||||
+ requestCount++;
|
||||
+ });
|
||||
+ server.setTimeout(200, (socket) => {
|
||||
+ timeoutCount++;
|
||||
+ socket.destroy();
|
||||
+ });
|
||||
+ server.keepAliveTimeout = 50;
|
||||
+ server.listen(0, common.mustCall(() => {
|
||||
+ const options = {
|
||||
+ port: server.address().port,
|
||||
+ allowHalfOpen: true
|
||||
+ };
|
||||
+ const c = net.connect(options, () => {
|
||||
+ c.write('GET /1 HTTP/1.1\r\nHost: localhost\r\n\r\n');
|
||||
+ c.write('GET /2 HTTP/1.1\r\nHost: localhost\r\n\r\n');
|
||||
+ c.write('GET /3 HTTP/1.1\r\nHost: localhost\r\n\r\n');
|
||||
+ });
|
||||
+ setTimeout(() => {
|
||||
+ server.close();
|
||||
+ if (socket.destroyed) destroyedSockets++;
|
||||
+ cb();
|
||||
+ }, 1000);
|
||||
+ }));
|
||||
+});
|
||||
Index: node-v4.9.1/test/parallel/test-https-server-keep-alive-timeout.js
|
||||
===================================================================
|
||||
--- /dev/null
|
||||
+++ node-v4.9.1/test/parallel/test-https-server-keep-alive-timeout.js
|
||||
@@ -0,0 +1,85 @@
|
||||
+'use strict';
|
||||
+
|
||||
+const common = require('../common');
|
||||
+const assert = require('assert');
|
||||
+const https = require('https');
|
||||
+const tls = require('tls');
|
||||
+const fs = require('fs');
|
||||
+
|
||||
+const tests = [];
|
||||
+
|
||||
+const serverOptions = {
|
||||
+ key: fs.readFileSync(common.fixturesDir + '/keys/agent1-key.pem'),
|
||||
+ cert: fs.readFileSync(common.fixturesDir + '/keys/agent1-cert.pem')
|
||||
+};
|
||||
+
|
||||
+function test(fn) {
|
||||
+ if (!tests.length) {
|
||||
+ process.nextTick(run);
|
||||
+ }
|
||||
+ tests.push(fn);
|
||||
+}
|
||||
+
|
||||
+function run() {
|
||||
+ const fn = tests.shift();
|
||||
+ if (fn) fn(run);
|
||||
+}
|
||||
+
|
||||
+test(function serverKeepAliveTimeoutWithPipeline(cb) {
|
||||
+ let requestCount = 0;
|
||||
+ process.on('exit', function() {
|
||||
+ assert.strictEqual(requestCount, 3);
|
||||
+ });
|
||||
+ const server = https.createServer(serverOptions, (req, res) => {
|
||||
+ requestCount++;
|
||||
+ res.end();
|
||||
+ });
|
||||
+ server.setTimeout(500, common.mustCall((socket) => {
|
||||
+ // End this test and call `run()` for the next test (if any).
|
||||
+ socket.destroy();
|
||||
+ server.close();
|
||||
+ cb();
|
||||
+ }));
|
||||
+ server.keepAliveTimeout = 50;
|
||||
+ server.listen(0, common.mustCall(() => {
|
||||
+ const options = {
|
||||
+ port: server.address().port,
|
||||
+ allowHalfOpen: true,
|
||||
+ rejectUnauthorized: false
|
||||
+ };
|
||||
+ const c = tls.connect(options, () => {
|
||||
+ c.write('GET /1 HTTP/1.1\r\nHost: localhost\r\n\r\n');
|
||||
+ c.write('GET /2 HTTP/1.1\r\nHost: localhost\r\n\r\n');
|
||||
+ c.write('GET /3 HTTP/1.1\r\nHost: localhost\r\n\r\n');
|
||||
+ });
|
||||
+ }));
|
||||
+});
|
||||
+
|
||||
+test(function serverNoEndKeepAliveTimeoutWithPipeline(cb) {
|
||||
+ let requestCount = 0;
|
||||
+ process.on('exit', () => {
|
||||
+ assert.strictEqual(requestCount, 3);
|
||||
+ });
|
||||
+ const server = https.createServer(serverOptions, (req, res) => {
|
||||
+ requestCount++;
|
||||
+ });
|
||||
+ server.setTimeout(500, common.mustCall((socket) => {
|
||||
+ // End this test and call `run()` for the next test (if any).
|
||||
+ socket.destroy();
|
||||
+ server.close();
|
||||
+ cb();
|
||||
+ }));
|
||||
+ server.keepAliveTimeout = 50;
|
||||
+ server.listen(0, common.mustCall(() => {
|
||||
+ const options = {
|
||||
+ port: server.address().port,
|
||||
+ allowHalfOpen: true,
|
||||
+ rejectUnauthorized: false
|
||||
+ };
|
||||
+ const c = tls.connect(options, () => {
|
||||
+ c.write('GET /1 HTTP/1.1\r\nHost: localhost\r\n\r\n');
|
||||
+ c.write('GET /2 HTTP/1.1\r\nHost: localhost\r\n\r\n');
|
||||
+ c.write('GET /3 HTTP/1.1\r\nHost: localhost\r\n\r\n');
|
||||
+ });
|
||||
+ }));
|
||||
+});
|
@@ -219,12 +219,12 @@ Index: node-v4.9.1/test/parallel/test-http-max-header-size.js
|
||||
+
|
||||
+require('../common');
|
||||
+const assert = require('assert');
|
||||
+const { spawnSync } = require('child_process');
|
||||
+const spawnSync = require('child_process').spawnSync;
|
||||
+const http = require('http');
|
||||
+
|
||||
+assert.strictEqual(http.maxHeaderSize, 8 * 1024);
|
||||
+const child = spawnSync(process.execPath, ['--max-http-header-size=10', '-p',
|
||||
+ 'http.maxHeaderSize']);
|
||||
+ 'require("http").maxHeaderSize']);
|
||||
+assert.strictEqual(+child.stdout.toString().trim(), 10);
|
||||
Index: node-v4.9.1/doc/api/cli.md
|
||||
===================================================================
|
||||
@@ -520,7 +520,7 @@ Index: node-v4.9.1/test/sequential/test-set-http-max-http-headers.js
|
||||
+
|
||||
+const common = require('../common');
|
||||
+const assert = require('assert');
|
||||
+const { spawn } = require('child_process');
|
||||
+const spawn = require('child_process').spawn;
|
||||
+const path = require('path');
|
||||
+const testName = path.join(__dirname, 'test-http-max-http-headers.js');
|
||||
+
|
||||
@@ -665,3 +665,34 @@ Index: node-v4.9.1/src/node.cc
|
||||
} else if (strcmp(arg, "--v8-options") == 0) {
|
||||
new_v8_argv[new_v8_argc] = "--help";
|
||||
new_v8_argc += 1;
|
||||
Index: node-v4.9.1/test/common.js
|
||||
===================================================================
|
||||
--- node-v4.9.1.orig/test/common.js
|
||||
+++ node-v4.9.1/test/common.js
|
||||
@@ -410,6 +410,26 @@ exports.mustCall = function(fn, expected
|
||||
};
|
||||
};
|
||||
|
||||
+exports.getCallSite = function getCallSite(top) {
|
||||
+ const originalStackFormatter = Error.prepareStackTrace;
|
||||
+ Error.prepareStackTrace = (err, stack) =>
|
||||
+ `${stack[0].getFileName()}:${stack[0].getLineNumber()}`;
|
||||
+ const err = new Error();
|
||||
+ Error.captureStackTrace(err, top);
|
||||
+ // with the V8 Error API, the stack is not formatted until it is accessed
|
||||
+ err.stack;
|
||||
+ Error.prepareStackTrace = originalStackFormatter;
|
||||
+ return err.stack;
|
||||
+};
|
||||
+
|
||||
+exports.mustNotCall = function(msg) {
|
||||
+ const callSite = exports.getCallSite(exports.mustNotCall);
|
||||
+ return function mustNotCall() {
|
||||
+ assert.fail(
|
||||
+ `${msg || 'function should not have been called'} at ${callSite}`);
|
||||
+ };
|
||||
+};
|
||||
+
|
||||
var etcServicesFileName = path.join('/etc', 'services');
|
||||
if (exports.isWindows) {
|
||||
etcServicesFileName = path.join(process.env.SystemRoot, 'System32', 'drivers',
|
||||
|
BIN
nodejs.keyring
BIN
nodejs.keyring
Binary file not shown.
@@ -1,24 +1,78 @@
|
||||
-------------------------------------------------------------------
|
||||
Tue Jan 8 15:58:37 UTC 2019 - adam.majer@suse.de
|
||||
Tue Jan 7 13:12:10 UTC 2020 - Guillaume GARDET <guillaume.gardet@opensuse.org>
|
||||
|
||||
- Really disable LTO when required (nodejs < 12)
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Mon Jul 29 09:01:42 UTC 2019 - Adam Majer <adam.majer@suse.de>
|
||||
|
||||
- CVE-2019-13173.patch: fix potential file overwrite via hardlink
|
||||
in fstream.DirWriter() function (bsc#1140290, CVE-2019-13173)
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Fri Mar 1 13:53:57 UTC 2019 - Adam Majer <adam.majer@suse.de>
|
||||
|
||||
Backport security fixes from NodeJS 6.x:
|
||||
* deps: upgrade OpenSSL source to 1.0.2r. Under certain
|
||||
circumstances, a TLS server can be forced to respond differently
|
||||
to a client if a zero-byte record is received with an
|
||||
invalid padding compared to a zero-byte record with an
|
||||
invalid MAC. This can be used as the basis of a padding
|
||||
oracle attack to decrypt data.
|
||||
(openssl_1_0_2r.patch - CVE-2019-1559, bsc#1127080)
|
||||
* http: (http-keep-alive.patch)
|
||||
+ Backport server.keepAliveTimeout to prevent keep-alive
|
||||
HTTP and HTTPS connections remaining open and inactive for
|
||||
an extended period of time, leading to a potential
|
||||
Denial of Service (DoS).
|
||||
(CVE-2019-5739, bsc#1127533)
|
||||
+ Further prevention of "Slowloris" attacks on HTTP and HTTPS
|
||||
connections by consistently applying the receive timeout set
|
||||
by server.headersTimeout to connections in keep-alive mode.
|
||||
(CVE-2019-5737, bsc#1127532)
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Fri Feb 1 12:40:17 UTC 2019 - adam.majer@suse.de
|
||||
|
||||
- nodejs.keyring: update keyring to today's list as per
|
||||
https://github.com/nodejs/node
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Wed Jan 9 14:19:07 UTC 2019 - adam.majer@suse.de
|
||||
|
||||
Backport security fixes from NodeJS 6.x:
|
||||
* debugger: prevent the debugger from listening on 0.0.0.0.
|
||||
It now defaults to 127.0.0.1.
|
||||
CVE-2018-12120.patch - (CVE-2018-12120, bsc#1117625)
|
||||
* cli: add --max-http-header-size flag (max_header_size.patch)
|
||||
* deps: upgrade OpenSSL sources to 1.0.2q
|
||||
(openssl_1_0_2q.patch - CVE-2018-0734, bsc#1113652,
|
||||
CVE-2018-5407, bsc#1113534)
|
||||
* http:
|
||||
+ add maxHeaderSize property (max_header_size.patch)
|
||||
+ Headers received by HTTP servers must not exceed 8192 bytes
|
||||
in total to prevent possible Denial of Service attacks.
|
||||
CVE-2018-12121.patch - (CVE-2018-12121, bsc#1117626)
|
||||
(CVE-2018-12121.patch - CVE-2018-12121, bsc#1117626)
|
||||
+ A timeout of 40 seconds now applies to servers receiving
|
||||
HTTP headers. This value can be adjusted with
|
||||
server.headersTimeout. Where headers are not completely
|
||||
received within this period, the socket is destroyed on
|
||||
the next received chunk. In conjunction with
|
||||
server.setTimeout(), this aids in protecting against
|
||||
excessive resource retention and possible Denial of Service.
|
||||
(CVE-2018-12122.patch - CVE-2018-12122, bsc#1117627)
|
||||
+ Two-byte characters are now strictly disallowed for the path
|
||||
option in HTTP client requests. Paths containing characters
|
||||
outside of the range \u0021 - \u00ff will now be rejected
|
||||
with a TypeError. This behavior can be reverted if necessary
|
||||
by supplying the --security-revert=CVE-2018-12116 command
|
||||
line argument (this is not recommended).
|
||||
CVE-2018-12116.patch - (CVE-2018-12116, bsc#1117630)
|
||||
(CVE-2018-12116.patch - CVE-2018-12116, bsc#1117630)
|
||||
* util: Fix a bug that would allow a hostname being spoofed when
|
||||
parsing URLs with url.parse() with the 'javascript:' protocol.
|
||||
CVE-2018-12123.patch - (CVE-2018-12123, bnc#1117629)
|
||||
(CVE-2018-12123.patch - CVE-2018-12123, bnc#1117629)
|
||||
|
||||
- env_shebang.patch: dropped in favour of programmatic update
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Mon Nov 26 14:06:57 UTC 2018 - adam.majer@suse.de
|
||||
|
60
nodejs4.spec
60
nodejs4.spec
@@ -30,14 +30,28 @@ Release: 0
|
||||
|
||||
%define node_version_number 4
|
||||
|
||||
%if %node_version_number >= 12
|
||||
%define openssl_req_ver 1.1.1
|
||||
%else
|
||||
%if %node_version_number >= 10
|
||||
%define openssl_req_ver 1.1.0
|
||||
%else # node8 or older
|
||||
%define openssl_req_ver 1.0.2
|
||||
%endif
|
||||
%endif
|
||||
|
||||
%bcond_with valgrind_tests
|
||||
|
||||
%if %{node_version_number} >= 12
|
||||
%bcond_without nodejs_lto
|
||||
%else
|
||||
%bcond_with nodejs_lto
|
||||
%endif
|
||||
|
||||
%if !0%{?with nodejs_lto}
|
||||
%define _lto_cflags %{nil}
|
||||
%endif
|
||||
|
||||
%if 0%{?suse_version} == 1110
|
||||
%define _libexecdir %{_exec_prefix}/lib
|
||||
%endif
|
||||
@@ -125,6 +139,12 @@ Patch23: CVE-2018-12120.patch
|
||||
Patch24: CVE-2018-12116.patch
|
||||
Patch25: CVE-2018-12121.patch
|
||||
Patch26: max_header_size.patch
|
||||
Patch27: CVE-2018-12122.patch
|
||||
Patch28: openssl_1_0_2q.patch
|
||||
Patch29: openssl_1_0_2r.patch
|
||||
Patch30: http-keep-alive.patch
|
||||
|
||||
Patch31: CVE-2019-13173.patch
|
||||
|
||||
## Patches specific to SUSE and openSUSE
|
||||
# PATCH-FIX-OPENSUSE -- set correct path for dtrace if it is built
|
||||
@@ -148,6 +168,8 @@ Patch200: versioned.patch
|
||||
BuildRequires: binutils-gold
|
||||
%endif
|
||||
|
||||
BuildRequires: pkg-config
|
||||
|
||||
# Node.js 4/6/7 requires GCC 4.8.5+.
|
||||
#
|
||||
# For Node.js 8.x, upstream requires GCC 4.9.4+, as GCC 4.8 may have
|
||||
@@ -181,15 +203,19 @@ BuildRequires: gcc-c++
|
||||
%endif
|
||||
|
||||
BuildRequires: fdupes
|
||||
BuildRequires: pkg-config
|
||||
BuildRequires: procps
|
||||
BuildRequires: xz
|
||||
BuildRequires: zlib-devel
|
||||
|
||||
%if %node_version_number > 12
|
||||
BuildRequires: python3
|
||||
%else
|
||||
%if 0%{?suse_version} >= 1500
|
||||
BuildRequires: python2
|
||||
%else
|
||||
BuildRequires: python
|
||||
%endif
|
||||
%endif # python3
|
||||
|
||||
%if 0%{?suse_version} >= 1500 && %{node_version_number} >= 10
|
||||
BuildRequires: user(nobody)
|
||||
@@ -199,7 +225,7 @@ BuildRequires: group(nobody)
|
||||
%if ! 0%{with intree_openssl}
|
||||
|
||||
%if %node_version_number >= 8
|
||||
BuildRequires: openssl-devel >= %{openssl_req_ver}
|
||||
BuildRequires: pkgconfig(openssl) >= %{openssl_req_ver}
|
||||
%else # older node doesn't support OpenSSL 1.1
|
||||
|
||||
%if 0%{?suse_version} >= 1330
|
||||
@@ -280,7 +306,12 @@ Obsoletes: nodejs-npm < 4.0.0
|
||||
Provides: npm(npm) = 2.15.11
|
||||
Provides: npm = %{version}
|
||||
%if 0%{?suse_version} >= 1500
|
||||
%if %{node_version_number} >= 10
|
||||
Requires: user(nobody)
|
||||
Requires: group(nobody)
|
||||
%endif
|
||||
Recommends: python2
|
||||
Recommends: python3
|
||||
%else
|
||||
Recommends: python
|
||||
%endif
|
||||
@@ -308,6 +339,12 @@ echo "`grep node-v%{version}.tar.xz %{S:1} | head -n1 | cut -c1-64` %{S:0}" | s
|
||||
%setup -q -n node-%{version}
|
||||
%endif
|
||||
|
||||
%if %{node_version_number} == 6
|
||||
# Update NPM
|
||||
rm -r deps/npm
|
||||
tar Jxvf %{SOURCE10}
|
||||
%endif
|
||||
|
||||
%if %{node_version_number} >= 10
|
||||
tar Jxvf %{SOURCE11}
|
||||
%endif # node_version_number
|
||||
@@ -328,6 +365,11 @@ tar Jxvf %{SOURCE11}
|
||||
%patch24 -p1
|
||||
%patch25 -p1
|
||||
%patch26 -p1
|
||||
%patch27 -p1
|
||||
%patch28 -p1
|
||||
%patch29 -p1
|
||||
%patch30 -p1
|
||||
%patch31 -p1
|
||||
%patch101 -p1
|
||||
%patch102 -p1
|
||||
# Add check_output to configure script (not part of Python 2.6 in SLE11).
|
||||
@@ -338,8 +380,11 @@ tar Jxvf %{SOURCE11}
|
||||
%patch120 -p1
|
||||
%patch200 -p1
|
||||
|
||||
# remove backup files, if any
|
||||
find -name \*~ -print0 -delete
|
||||
|
||||
# abnormalities from patching
|
||||
find -name configure.js.orig -delete
|
||||
find \( -name \*.js.orig -or -name \*.md.orig \) -delete
|
||||
|
||||
%build
|
||||
# normalize shebang
|
||||
@@ -365,14 +410,10 @@ find deps/cares -name *.[ch] -delete
|
||||
|
||||
find deps/zlib -name *.[ch] -delete
|
||||
|
||||
# Annoying, over-repetitive patch updated just because lines in
|
||||
# documentation changes every version.
|
||||
find -name *.md.orig -delete
|
||||
|
||||
# percent-configure pulls in something that confuses node's configure
|
||||
# script, so we'll do it thus:
|
||||
export CFLAGS="%{optflags}"
|
||||
export CXXFLAGS="%{optflags}"
|
||||
export CXXFLAGS="%{optflags} -Wno-class-memaccess -Wno-error=return-type"
|
||||
|
||||
%if 0%{?cc_exec:1}
|
||||
export CC=%{?cc_exec}
|
||||
@@ -384,6 +425,9 @@ export CXX=%{?cpp_exec}
|
||||
|
||||
./configure \
|
||||
--prefix=%{_prefix} \
|
||||
%if 0%{?with nodejs_lto}
|
||||
--enable-lto \
|
||||
%endif
|
||||
%if ! 0%{with intree_openssl}
|
||||
--shared-openssl \
|
||||
%endif
|
||||
|
3245
openssl_1_0_2q.patch
Normal file
3245
openssl_1_0_2q.patch
Normal file
File diff suppressed because it is too large
Load Diff
3113
openssl_1_0_2r.patch
Normal file
3113
openssl_1_0_2r.patch
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user