Files
safetynet/tests/broker-tls-authority.test.mjs
T

43 lines
3.1 KiB
JavaScript

import test from 'node:test';
import assert from 'node:assert/strict';
import {createRequire} from 'node:module';
const {parseAuthority,bindConnectAuthority,verifyInnerAuthority}=createRequire(import.meta.url)('../apps/network-broker/tls-authority.cjs');
test('canonical DNS, IPv4 and bracketed IPv6 ports and default 443',()=>{
assert.equal(parseAuthority('Example.COM').authority,'example.com:443');
assert.equal(parseAuthority('example.com:443').authority,'example.com:443');
assert.equal(parseAuthority('127.0.0.1:8443').authority,'127.0.0.1:8443');
assert.equal(parseAuthority('[2001:0DB8:0:0::1]').authority,'[2001:db8::1]:443');
assert.equal(parseAuthority('xn--bcher-kva.example:65535').port,65535);
assert.throws(()=>bindConnectAuthority('example.com'),{code:'missing-port'});
});
test('reject legacy IP aliases, controls, userinfo, paths and ambiguous ports',()=>{
for(const value of ['127.1:443','0177.0.0.1:443','2130706433:443','0x7f000001:443','0x7f.0.0.1:443','example.com:0','example.com:0443','example.com:65536','example.com:+443','example.com:','example.com:443:4','[email protected]:443','example.com/path','example.com?x',' example.com','example.com\r\n','example.com.','-bad.example','bad_.example','[fe80::1%25eth0]:443','::1:443','https://example.com:443']) {
assert.throws(()=>parseAuthority(value),error=>error.name==='AuthorityError'&&!error.message.includes(value));
}
});
test('inner Host, absolute URL and SNI bind to authenticated CONNECT',()=>{
const binding=bindConnectAuthority('EXAMPLE.com:443');
assert.equal(verifyInnerAuthority(binding,{rawHeaders:['Host','example.com'],url:'/submit?x=1',servername:'example.com'}),binding);
assert.equal(verifyInnerAuthority(binding,{rawHeaders:['host','EXAMPLE.com:443'],url:'https://example.com/submit',servername:'EXAMPLE.COM'}),binding);
assert.ok(Object.isFrozen(binding));
});
test('cross authority reuse and missing/duplicate Host or mismatched SNI fail closed',()=>{
const binding=bindConnectAuthority('example.com:443');
const valid={rawHeaders:['Host','example.com'],url:'/',servername:'example.com'};
for(const changed of [
{rawHeaders:[]},{rawHeaders:['Host','example.com','host','example.com']},
{rawHeaders:['Host','evil.com']},{rawHeaders:['Host','example.com:8443']},
{url:'https://evil.com/'},{url:'https://example.com:8443/'},
{url:'https://[email protected]/'},{url:'http://example.com/'},
{url:'//evil.com/'},{url:'/x#fragment'},{url:'/x\r\n'},
{servername:'evil.com'},{servername:'example.com:443'},{servername:undefined}
])assert.throws(()=>verifyInnerAuthority(binding,{...valid,...changed}));
assert.throws(()=>verifyInnerAuthority({...binding},valid),{code:'invalid-binding'});
});
test('IP CONNECT binding accepts absent SNI but does not accept a different IP',()=>{
const binding=bindConnectAuthority('[::1]:443');
assert.equal(verifyInnerAuthority(binding,{rawHeaders:['Host','[0:0:0:0:0:0:0:1]'],url:'https://[::1]/'}),binding);
assert.throws(()=>verifyInnerAuthority(binding,{rawHeaders:['Host','[::1]'],url:'/',servername:'::2'}),{code:'sni-mismatch'});
});