https: Use host header as effective servername
This commit is contained in:
Родитель
9eddaebb79
Коммит
b0c0111b04
16
lib/http.js
16
lib/http.js
|
@ -1067,7 +1067,7 @@ Agent.prototype.addRequest = function(req, host, port, localAddress) {
|
|||
}
|
||||
if (this.sockets[name].length < this.maxSockets) {
|
||||
// If we are under maxSockets create a new one.
|
||||
req.onSocket(this.createSocket(name, host, port, localAddress));
|
||||
req.onSocket(this.createSocket(name, host, port, localAddress, req));
|
||||
} else {
|
||||
// We are over limit so we'll add it to the queue.
|
||||
if (!this.requests[name]) {
|
||||
|
@ -1076,12 +1076,21 @@ Agent.prototype.addRequest = function(req, host, port, localAddress) {
|
|||
this.requests[name].push(req);
|
||||
}
|
||||
};
|
||||
Agent.prototype.createSocket = function(name, host, port, localAddress) {
|
||||
Agent.prototype.createSocket = function(name, host, port, localAddress, req) {
|
||||
var self = this;
|
||||
var options = util._extend({}, self.options);
|
||||
options.port = port;
|
||||
options.host = host;
|
||||
options.localAddress = localAddress;
|
||||
|
||||
options.servername = host;
|
||||
if (req) {
|
||||
var hostHeader = req.getHeader('host');
|
||||
if (hostHeader) {
|
||||
options.servername = hostHeader.replace(/:.*$/, '');
|
||||
}
|
||||
}
|
||||
|
||||
var s = self.createConnection(options);
|
||||
if (!self.sockets[name]) {
|
||||
self.sockets[name] = [];
|
||||
|
@ -1122,8 +1131,9 @@ Agent.prototype.removeSocket = function(s, name, host, port, localAddress) {
|
|||
}
|
||||
}
|
||||
if (this.requests[name] && this.requests[name].length) {
|
||||
var req = this.requests[name][0];
|
||||
// If we have pending requests and a socket gets closed a new one
|
||||
this.createSocket(name, host, port, localAddress).emit('free');
|
||||
this.createSocket(name, host, port, localAddress, req).emit('free');
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,218 @@
|
|||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
if (!process.versions.openssl) {
|
||||
console.error('Skipping because node compiled without OpenSSL.');
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
var common = require('../common');
|
||||
var assert = require('assert');
|
||||
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
var https = require('https');
|
||||
|
||||
function file(fname) {
|
||||
return path.resolve(common.fixturesDir, 'keys', fname);
|
||||
}
|
||||
|
||||
function read(fname) {
|
||||
return fs.readFileSync(file(fname));
|
||||
}
|
||||
|
||||
// key1 is signed by ca1.
|
||||
var key1 = read('agent1-key.pem');
|
||||
var cert1 = read('agent1-cert.pem');
|
||||
|
||||
// key2 has a self signed cert
|
||||
var key2 = read('agent2-key.pem');
|
||||
var cert2 = read('agent2-cert.pem');
|
||||
|
||||
// key3 is signed by ca2.
|
||||
var key3 = read('agent3-key.pem');
|
||||
var cert3 = read('agent3-cert.pem');
|
||||
|
||||
var ca1 = read('ca1-cert.pem');
|
||||
var ca2 = read('ca2-cert.pem');
|
||||
|
||||
// different agents to use different CA lists.
|
||||
// this api is beyond bad.
|
||||
var agent0 = new https.Agent();
|
||||
var agent1 = new https.Agent({ ca: [ca1] });
|
||||
var agent2 = new https.Agent({ ca: [ca2] });
|
||||
var agent3 = new https.Agent({ ca: [ca1, ca2] });
|
||||
|
||||
var options1 = {
|
||||
key: key1,
|
||||
cert: cert1
|
||||
};
|
||||
|
||||
var options2 = {
|
||||
key: key2,
|
||||
cert: cert2
|
||||
};
|
||||
|
||||
var options3 = {
|
||||
key: key3,
|
||||
cert: cert3
|
||||
};
|
||||
|
||||
var server1 = server(options1);
|
||||
var server2 = server(options2);
|
||||
var server3 = server(options3);
|
||||
|
||||
var listenWait = 0;
|
||||
|
||||
var port = common.PORT;
|
||||
var port1 = port++;
|
||||
var port2 = port++;
|
||||
var port3 = port++;
|
||||
server1.listen(port1, listening());
|
||||
server2.listen(port2, listening());
|
||||
server3.listen(port3, listening());
|
||||
|
||||
var responseErrors = {};
|
||||
var expectResponseCount = 0;
|
||||
var responseCount = 0;
|
||||
var pending = 0;
|
||||
|
||||
|
||||
|
||||
function server(options, port) {
|
||||
var s = https.createServer(options, handler);
|
||||
s.requests = [];
|
||||
s.expectCount = 0;
|
||||
return s;
|
||||
}
|
||||
|
||||
function handler(req, res) {
|
||||
this.requests.push(req.url);
|
||||
res.statusCode = 200;
|
||||
res.setHeader('foo', 'bar');
|
||||
res.end('hello, world\n');
|
||||
}
|
||||
|
||||
function listening() {
|
||||
listenWait++;
|
||||
return function() {
|
||||
listenWait--;
|
||||
if (listenWait === 0) {
|
||||
allListening();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function makeReq(path, port, error, host, ca) {
|
||||
pending++;
|
||||
var options = {
|
||||
port: port,
|
||||
path: path,
|
||||
ca: ca
|
||||
};
|
||||
var whichCa = 0;
|
||||
if (!ca) {
|
||||
options.agent = agent0;
|
||||
} else {
|
||||
if (!Array.isArray(ca)) ca = [ca];
|
||||
if (-1 !== ca.indexOf(ca1) && -1 !== ca.indexOf(ca2)) {
|
||||
options.agent = agent3;
|
||||
} else if (-1 !== ca.indexOf(ca1)) {
|
||||
options.agent = agent1;
|
||||
} else if (-1 !== ca.indexOf(ca2)) {
|
||||
options.agent = agent2;
|
||||
} else {
|
||||
options.agent = agent0;
|
||||
}
|
||||
}
|
||||
|
||||
if (host) {
|
||||
options.headers = { host: host }
|
||||
}
|
||||
var req = https.get(options);
|
||||
expectResponseCount++;
|
||||
var server = port === port1 ? server1
|
||||
: port === port2 ? server2
|
||||
: port === port3 ? server3
|
||||
: null;
|
||||
|
||||
if (!server) throw new Error('invalid port: '+port);
|
||||
server.expectCount++;
|
||||
|
||||
req.on('response', function(res) {
|
||||
responseCount++;
|
||||
assert.equal(res.connection.authorizationError, error);
|
||||
responseErrors[path] = res.connection.authorizationError;
|
||||
pending--;
|
||||
if (pending === 0) {
|
||||
server1.close();
|
||||
server2.close();
|
||||
server3.close();
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function allListening() {
|
||||
// ok, ready to start the tests!
|
||||
|
||||
// server1: host 'agent1', signed by ca1
|
||||
makeReq('/inv1', port1, 'UNABLE_TO_VERIFY_LEAF_SIGNATURE');
|
||||
makeReq('/inv1-ca1', port1,
|
||||
'Hostname/IP doesn\'t match certificate\'s altnames',
|
||||
null, ca1);
|
||||
makeReq('/inv1-ca1ca2', port1,
|
||||
'Hostname/IP doesn\'t match certificate\'s altnames',
|
||||
null, [ca1, ca2]);
|
||||
makeReq('/val1-ca1', port1, null, 'agent1', ca1);
|
||||
makeReq('/val1-ca1ca2', port1, null, 'agent1', [ca1, ca2]);
|
||||
makeReq('/inv1-ca2', port1,
|
||||
'UNABLE_TO_VERIFY_LEAF_SIGNATURE', 'agent1', ca2);
|
||||
|
||||
// server2: self-signed, host = 'agent2'
|
||||
// doesn't matter that thename matches, all of these will error.
|
||||
makeReq('/inv2', port2, 'DEPTH_ZERO_SELF_SIGNED_CERT');
|
||||
makeReq('/inv2-ca1', port2, 'DEPTH_ZERO_SELF_SIGNED_CERT',
|
||||
'agent2', ca1);
|
||||
makeReq('/inv2-ca1ca2', port2, 'DEPTH_ZERO_SELF_SIGNED_CERT',
|
||||
'agent2', [ca1, ca2]);
|
||||
|
||||
// server3: host 'agent3', signed by ca2
|
||||
makeReq('/inv3', port3, 'UNABLE_TO_VERIFY_LEAF_SIGNATURE');
|
||||
makeReq('/inv3-ca2', port3,
|
||||
'Hostname/IP doesn\'t match certificate\'s altnames',
|
||||
null, ca2);
|
||||
makeReq('/inv3-ca1ca2', port3,
|
||||
'Hostname/IP doesn\'t match certificate\'s altnames',
|
||||
null, [ca1, ca2]);
|
||||
makeReq('/val3-ca2', port3, null, 'agent3', ca2);
|
||||
makeReq('/val3-ca1ca2', port3, null, 'agent3', [ca1, ca2]);
|
||||
makeReq('/inv3-ca1', port3,
|
||||
'UNABLE_TO_VERIFY_LEAF_SIGNATURE', 'agent1', ca1);
|
||||
|
||||
}
|
||||
|
||||
process.on('exit', function() {
|
||||
console.error(responseErrors);
|
||||
assert.equal(server1.requests.length, server1.expectCount);
|
||||
assert.equal(server2.requests.length, server2.expectCount);
|
||||
assert.equal(server3.requests.length, server3.expectCount);
|
||||
assert.equal(responseCount, expectResponseCount);
|
||||
});
|
Загрузка…
Ссылка в новой задаче