You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

541 lines
16 KiB

'use strict';
const common = require('../common');
if (!common.hasCrypto) {
common.skip('missing crypto');
return;
}
if (!process.features.tls_alpn || !process.features.tls_npn) {
common.skip('Skipping because node compiled without NPN or ALPN' +
' feature of OpenSSL.');
return;
}
const assert = require('assert');
const fs = require('fs');
const tls = require('tls');
function filenamePEM(n) {
return require('path').join(common.fixturesDir, 'keys', n + '.pem');
}
function loadPEM(n) {
return fs.readFileSync(filenamePEM(n));
}
const serverIP = common.localhostIPv4;
function checkResults(result, expected) {
assert.strictEqual(result.server.ALPN, expected.server.ALPN);
assert.strictEqual(result.server.NPN, expected.server.NPN);
assert.strictEqual(result.client.ALPN, expected.client.ALPN);
assert.strictEqual(result.client.NPN, expected.client.NPN);
}
function runTest(clientsOptions, serverOptions, cb) {
serverOptions.key = loadPEM('agent2-key');
serverOptions.cert = loadPEM('agent2-cert');
const results = [];
let index = 0;
const server = tls.createServer(serverOptions, function(c) {
results[index].server = {ALPN: c.alpnProtocol, NPN: c.npnProtocol};
});
server.listen(0, serverIP, function() {
connectClient(clientsOptions);
});
function connectClient(options) {
const opt = options.shift();
opt.port = server.address().port;
opt.host = serverIP;
opt.rejectUnauthorized = false;
results[index] = {};
const client = tls.connect(opt, function() {
results[index].client = {ALPN: client.alpnProtocol,
NPN: client.npnProtocol};
client.destroy();
if (options.length) {
index++;
connectClient(options);
} else {
server.close();
cb(results);
}
});
}
}
// Server: ALPN/NPN, Client: ALPN/NPN
function Test1() {
const serverOptions = {
ALPNProtocols: ['a', 'b', 'c'],
NPNProtocols: ['a', 'b', 'c']
};
const clientsOptions = [{
ALPNProtocols: ['a', 'b', 'c'],
NPNProtocols: ['a', 'b', 'c']
}, {
ALPNProtocols: ['c', 'b', 'e'],
NPNProtocols: ['c', 'b', 'e']
}, {
ALPNProtocols: ['first-priority-unsupported', 'x', 'y'],
NPNProtocols: ['first-priority-unsupported', 'x', 'y']
}];
runTest(clientsOptions, serverOptions, function(results) {
// 'a' is selected by ALPN
checkResults(results[0],
{server: {ALPN: 'a', NPN: false},
client: {ALPN: 'a', NPN: undefined}});
// 'b' is selected by ALPN
checkResults(results[1],
{server: {ALPN: 'b', NPN: false},
client: {ALPN: 'b', NPN: undefined}});
// nothing is selected by ALPN
checkResults(results[2],
{server: {ALPN: false, NPN: 'first-priority-unsupported'},
client: {ALPN: false, NPN: false}});
// execute next test
Test2();
});
}
// Server: ALPN/NPN, Client: ALPN
function Test2() {
const serverOptions = {
ALPNProtocols: ['a', 'b', 'c'],
NPNProtocols: ['a', 'b', 'c']
};
const clientsOptions = [{
ALPNProtocols: ['a', 'b', 'c']
}, {
ALPNProtocols: ['c', 'b', 'e']
}, {
ALPNProtocols: ['first-priority-unsupported', 'x', 'y']
}];
runTest(clientsOptions, serverOptions, function(results) {
// 'a' is selected by ALPN
checkResults(results[0],
{server: {ALPN: 'a', NPN: false},
client: {ALPN: 'a', NPN: undefined}});
// 'b' is selected by ALPN
checkResults(results[1],
{server: {ALPN: 'b', NPN: false},
client: {ALPN: 'b', NPN: undefined}});
// nothing is selected by ALPN
checkResults(results[2],
{server: {ALPN: false, NPN: 'http/1.1'},
client: {ALPN: false, NPN: false}});
// execute next test
Test3();
});
}
// Server: ALPN/NPN, Client: NPN
function Test3() {
const serverOptions = {
ALPNProtocols: ['a', 'b', 'c'],
NPNProtocols: ['a', 'b', 'c']
};
const clientsOptions = [{
NPNProtocols: ['a', 'b', 'c']
}, {
NPPNProtocols: ['c', 'b', 'e']
}, {
NPPNProtocols: ['first-priority-unsupported', 'x', 'y']
}];
runTest(clientsOptions, serverOptions, function(results) {
// 'a' is selected by NPN
checkResults(results[0],
{server: {ALPN: false, NPN: 'a'},
client: {ALPN: false, NPN: 'a'}});
// nothing is selected by ALPN
checkResults(results[1],
{server: {ALPN: false, NPN: 'http/1.1'},
client: {ALPN: false, NPN: false}});
// nothing is selected by ALPN
checkResults(results[2],
{server: {ALPN: false, NPN: 'http/1.1'},
client: {ALPN: false, NPN: false}});
// execute next test
Test4();
});
}
// Server: ALPN/NPN, Client: Nothing
function Test4() {
const serverOptions = {
ALPNProtocols: ['a', 'b', 'c'],
NPNProtocols: ['a', 'b', 'c']
};
const clientsOptions = [{}, {}, {}];
runTest(clientsOptions, serverOptions, function(results) {
// nothing is selected by ALPN
checkResults(results[0],
{server: {ALPN: false, NPN: 'http/1.1'},
client: {ALPN: false, NPN: false}});
// nothing is selected by ALPN
checkResults(results[1],
{server: {ALPN: false, NPN: 'http/1.1'},
client: {ALPN: false, NPN: false}});
// nothing is selected by ALPN
checkResults(results[2],
{server: {ALPN: false, NPN: 'http/1.1'},
client: {ALPN: false, NPN: false}});
// execute next test
Test5();
});
}
// Server: ALPN, Client: ALPN/NPN
function Test5() {
const serverOptions = {
ALPNProtocols: ['a', 'b', 'c']
};
const clientsOptions = [{
ALPNProtocols: ['a', 'b', 'c'],
NPNProtocols: ['a', 'b', 'c']
}, {
ALPNProtocols: ['c', 'b', 'e'],
NPNProtocols: ['c', 'b', 'e']
}, {
ALPNProtocols: ['first-priority-unsupported', 'x', 'y'],
NPNProtocols: ['first-priority-unsupported', 'x', 'y']
}];
runTest(clientsOptions, serverOptions, function(results) {
// 'a' is selected by ALPN
checkResults(results[0], {server: {ALPN: 'a', NPN: false},
client: {ALPN: 'a', NPN: undefined}});
// 'b' is selected by ALPN
checkResults(results[1], {server: {ALPN: 'b', NPN: false},
client: {ALPN: 'b', NPN: undefined}});
// nothing is selected by ALPN
checkResults(results[2], {server: {ALPN: false,
NPN: 'first-priority-unsupported'},
client: {ALPN: false, NPN: false}});
// execute next test
Test6();
});
}
// Server: ALPN, Client: ALPN
function Test6() {
const serverOptions = {
ALPNProtocols: ['a', 'b', 'c']
};
const clientsOptions = [{
ALPNProtocols: ['a', 'b', 'c']
}, {
ALPNProtocols: ['c', 'b', 'e']
}, {
ALPNProtocols: ['first-priority-unsupported', 'x', 'y']
}];
runTest(clientsOptions, serverOptions, function(results) {
// 'a' is selected by ALPN
checkResults(results[0], {server: {ALPN: 'a', NPN: false},
client: {ALPN: 'a', NPN: undefined}});
// 'b' is selected by ALPN
checkResults(results[1], {server: {ALPN: 'b', NPN: false},
client: {ALPN: 'b', NPN: undefined}});
// nothing is selected by ALPN
checkResults(results[2], {server: {ALPN: false, NPN: 'http/1.1'},
client: {ALPN: false, NPN: false}});
// execute next test
Test7();
});
}
// Server: ALPN, Client: NPN
function Test7() {
const serverOptions = {
ALPNProtocols: ['a', 'b', 'c']
};
const clientsOptions = [{
NPNProtocols: ['a', 'b', 'c']
}, {
NPNProtocols: ['c', 'b', 'e']
}, {
NPNProtocols: ['first-priority-unsupported', 'x', 'y']
}];
runTest(clientsOptions, serverOptions, function(results) {
// nothing is selected by ALPN
checkResults(results[0], {server: {ALPN: false, NPN: 'a'},
client: {ALPN: false, NPN: false}});
// nothing is selected by ALPN
checkResults(results[1], {server: {ALPN: false, NPN: 'c'},
client: {ALPN: false, NPN: false}});
// nothing is selected by ALPN
checkResults(results[2],
{server: {ALPN: false, NPN: 'first-priority-unsupported'},
client: {ALPN: false, NPN: false}});
// execute next test
Test8();
});
}
// Server: ALPN, Client: Nothing
function Test8() {
const serverOptions = {
ALPNProtocols: ['a', 'b', 'c']
};
const clientsOptions = [{}, {}, {}];
runTest(clientsOptions, serverOptions, function(results) {
// nothing is selected by ALPN
checkResults(results[0], {server: {ALPN: false, NPN: 'http/1.1'},
client: {ALPN: false, NPN: false}});
// nothing is selected by ALPN
checkResults(results[1], {server: {ALPN: false, NPN: 'http/1.1'},
client: {ALPN: false, NPN: false}});
// nothing is selected by ALPN
checkResults(results[2],
{server: {ALPN: false, NPN: 'http/1.1'},
client: {ALPN: false, NPN: false}});
// execute next test
Test9();
});
}
// Server: NPN, Client: ALPN/NPN
function Test9() {
const serverOptions = {
NPNProtocols: ['a', 'b', 'c']
};
const clientsOptions = [{
ALPNrotocols: ['a', 'b', 'c'],
NPNProtocols: ['a', 'b', 'c']
}, {
ALPNProtocols: ['c', 'b', 'e'],
NPNProtocols: ['c', 'b', 'e']
}, {
ALPNProtocols: ['first-priority-unsupported', 'x', 'y'],
NPNProtocols: ['first-priority-unsupported', 'x', 'y']
}];
runTest(clientsOptions, serverOptions, function(results) {
// 'a' is selected by NPN
checkResults(results[0], {server: {ALPN: false, NPN: 'a'},
client: {ALPN: false, NPN: 'a'}});
// 'b' is selected by NPN
checkResults(results[1], {server: {ALPN: false, NPN: 'b'},
client: {ALPN: false, NPN: 'b'}});
// nothing is selected
checkResults(results[2],
{server: {ALPN: false, NPN: 'first-priority-unsupported'},
client: {ALPN: false, NPN: false}});
// execute next test
Test10();
});
}
// Server: NPN, Client: ALPN
function Test10() {
const serverOptions = {
NPNProtocols: ['a', 'b', 'c']
};
const clientsOptions = [{
ALPNProtocols: ['a', 'b', 'c']
}, {
ALPNProtocols: ['c', 'b', 'e']
}, {
ALPNProtocols: ['first-priority-unsupported', 'x', 'y']
}];
runTest(clientsOptions, serverOptions, function(results) {
// nothing is selected
checkResults(results[0], {server: {ALPN: false, NPN: 'http/1.1'},
client: {ALPN: false, NPN: false}});
// nothing is selected
checkResults(results[1], {server: {ALPN: false, NPN: 'http/1.1'},
client: {ALPN: false, NPN: false}});
// nothing is selected
checkResults(results[2], {server: {ALPN: false, NPN: 'http/1.1'},
client: {ALPN: false, NPN: false}});
// execute next test
Test11();
});
}
// Server: NPN, Client: NPN
function Test11() {
const serverOptions = {
NPNProtocols: ['a', 'b', 'c']
};
const clientsOptions = [{
NPNProtocols: ['a', 'b', 'c']
}, {
NPNProtocols: ['c', 'b', 'e']
}, {
NPNProtocols: ['first-priority-unsupported', 'x', 'y']
}];
runTest(clientsOptions, serverOptions, function(results) {
// 'a' is selected by NPN
checkResults(results[0], {server: {ALPN: false, NPN: 'a'},
client: {ALPN: false, NPN: 'a'}});
// 'b' is selected by NPN
checkResults(results[1], {server: {ALPN: false, NPN: 'b'},
client: {ALPN: false, NPN: 'b'}});
// nothing is selected
checkResults(results[2],
{server: {ALPN: false, NPN: 'first-priority-unsupported'},
client: {ALPN: false, NPN: false}});
// execute next test
Test12();
});
}
// Server: NPN, Client: Nothing
function Test12() {
const serverOptions = {
NPNProtocols: ['a', 'b', 'c']
};
const clientsOptions = [{}, {}, {}];
runTest(clientsOptions, serverOptions, function(results) {
// nothing is selected
checkResults(results[0], {server: {ALPN: false, NPN: 'http/1.1'},
client: {ALPN: false, NPN: false}});
// nothing is selected
checkResults(results[1], {server: {ALPN: false, NPN: 'http/1.1'},
client: {ALPN: false, NPN: false}});
// nothing is selected
checkResults(results[2],
{server: {ALPN: false, NPN: 'http/1.1'},
client: {ALPN: false, NPN: false}});
// execute next test
Test13();
});
}
// Server: Nothing, Client: ALPN/NPN
function Test13() {
const serverOptions = {};
const clientsOptions = [{
ALPNrotocols: ['a', 'b', 'c'],
NPNProtocols: ['a', 'b', 'c']
}, {
ALPNProtocols: ['c', 'b', 'e'],
NPNProtocols: ['c', 'b', 'e']
}, {
ALPNProtocols: ['first-priority-unsupported', 'x', 'y'],
NPNProtocols: ['first-priority-unsupported', 'x', 'y']
}];
runTest(clientsOptions, serverOptions, function(results) {
// nothing is selected
checkResults(results[0], {server: {ALPN: false, NPN: 'a'},
client: {ALPN: false, NPN: false}});
// nothing is selected
checkResults(results[1], {server: {ALPN: false, NPN: 'c'},
client: {ALPN: false, NPN: false}});
// nothing is selected
checkResults(results[2],
{server: {ALPN: false, NPN: 'first-priority-unsupported'},
client: {ALPN: false, NPN: false}});
// execute next test
Test14();
});
}
// Server: Nothing, Client: ALPN
function Test14() {
const serverOptions = {};
const clientsOptions = [{
ALPNrotocols: ['a', 'b', 'c']
}, {
ALPNProtocols: ['c', 'b', 'e']
}, {
ALPNProtocols: ['first-priority-unsupported', 'x', 'y']
}];
runTest(clientsOptions, serverOptions, function(results) {
// nothing is selected
checkResults(results[0], {server: {ALPN: false, NPN: 'http/1.1'},
client: {ALPN: false, NPN: false}});
// nothing is selected
checkResults(results[1], {server: {ALPN: false, NPN: 'http/1.1'},
client: {ALPN: false, NPN: false}});
// nothing is selected
checkResults(results[2],
{server: {ALPN: false, NPN: 'http/1.1'},
client: {ALPN: false, NPN: false}});
// execute next test
Test15();
});
}
// Server: Nothing, Client: NPN
function Test15() {
const serverOptions = {};
const clientsOptions = [{
NPNProtocols: ['a', 'b', 'c']
}, {
NPNProtocols: ['c', 'b', 'e']
}, {
NPNProtocols: ['first-priority-unsupported', 'x', 'y']
}];
runTest(clientsOptions, serverOptions, function(results) {
// nothing is selected
checkResults(results[0], {server: {ALPN: false, NPN: 'a'},
client: {ALPN: false, NPN: false}});
// nothing is selected
checkResults(results[1], {server: {ALPN: false, NPN: 'c'},
client: {ALPN: false, NPN: false}});
// nothing is selected
checkResults(results[2],
{server: {ALPN: false, NPN: 'first-priority-unsupported'},
client: {ALPN: false, NPN: false}});
// execute next test
Test16();
});
}
// Server: Nothing, Client: Nothing
function Test16() {
const serverOptions = {};
const clientsOptions = [{}, {}, {}];
runTest(clientsOptions, serverOptions, function(results) {
// nothing is selected
checkResults(results[0], {server: {ALPN: false, NPN: 'http/1.1'},
client: {ALPN: false, NPN: false}});
// nothing is selected
checkResults(results[1], {server: {ALPN: false, NPN: 'http/1.1'},
client: {ALPN: false, NPN: false}});
// nothing is selected
checkResults(results[2],
{server: {ALPN: false, NPN: 'http/1.1'},
client: {ALPN: false, NPN: false}});
});
}
Test1();