Source code
Revision control
Copy as Markdown
Other Tools
Test Info:
-
CI results over the last 21 days
- Manifest: netwerk/test/unit/xpcshell.toml
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
"use strict";
const { HttpServer } = ChromeUtils.importESModule(
);
let httpServer;
// Resolves with NS_OK once connected, or with the error the transport failed
// with.
function connectTo(host, port) {
return new Promise(resolve => {
let transport = Cc["@mozilla.org/network/socket-transport-service;1"]
.getService(Ci.nsISocketTransportService)
.createTransport([], host, port, null, null);
let done = result => {
transport.close(Cr.NS_OK);
resolve(result);
};
transport.setEventSink(
{
onTransportStatus(aTransport, status) {
if (status == Ci.nsISocketTransport.STATUS_CONNECTED_TO) {
done(Cr.NS_OK);
}
},
},
Services.tm.currentThread
);
let input = transport.openInputStream(0, 0, 0);
input.asyncWait(
{
onInputStreamReady(stream) {
try {
stream.available();
done(Cr.NS_ERROR_UNEXPECTED);
} catch (e) {
done(e.result);
}
},
},
0,
0,
Services.tm.currentThread
);
});
}
function resolveMyHostName() {
return new Promise(resolve => {
Services.dns.asyncResolve(
Services.dns.myHostName,
Ci.nsIDNSService.RESOLVE_TYPE_DEFAULT,
Ci.nsIDNSService.RESOLVE_DISABLE_IPV6,
null,
{
onLookupComplete(request, record, status) {
let addresses = [];
if (Components.isSuccessCode(status)) {
record.QueryInterface(Ci.nsIDNSAddrRecord);
while (record.hasMore()) {
addresses.push(record.getNextAddrAsString());
}
}
resolve(addresses);
},
},
Services.tm.currentThread,
{}
);
});
}
function isPrivateIPv4(addr) {
return (
/^10\./.test(addr) ||
/^192\.168\./.test(addr) ||
/^172\.(1[6-9]|2[0-9]|3[01])\./.test(addr)
);
}
add_setup(() => {
httpServer = new HttpServer();
httpServer.registerPathHandler("/", (request, response) => {
response.setHeader("Connection", "close", false);
response.write("ok");
});
httpServer.start(-1);
registerCleanupFunction(async () => {
await httpServer.stop();
});
});
add_task(async function test_invalid_ports() {
for (let port of [-1, 0, 65536]) {
Assert.throws(
() => Services.io.addBlockedLocalPort(port),
e => e.result == Cr.NS_ERROR_INVALID_ARG,
`Blocking port ${port} should throw`
);
}
});
add_task(async function test_http_to_blocked_local_port() {
let port = httpServer.identity.primaryPort;
let [req, buffer] = await channelOpenPromise(
);
Assert.equal(req.status, Cr.NS_OK);
Assert.equal(buffer, "ok");
Services.io.addBlockedLocalPort(port);
for (let host of ["localhost", "127.0.0.1", "127.0.0.2", "[::1]"]) {
[req] = await channelOpenPromise(
CL_EXPECT_FAILURE
);
Assert.equal(
req.status,
Cr.NS_ERROR_PORT_ACCESS_NOT_ALLOWED,
`Connection to ${host}:${port} should be blocked`
);
}
Services.io.removeBlockedLocalPort(port);
[req, buffer] = await channelOpenPromise(
);
Assert.equal(req.status, Cr.NS_OK);
Assert.equal(buffer, "ok");
});
add_task(async function test_socket_to_blocked_local_port() {
let port = httpServer.identity.primaryPort;
Assert.equal(await connectTo("127.0.0.1", port), Cr.NS_OK);
Services.io.addBlockedLocalPort(port);
for (let host of ["127.0.0.1", "::1", "0.0.0.0", "::"]) {
Assert.equal(
await connectTo(host, port),
Cr.NS_ERROR_PORT_ACCESS_NOT_ALLOWED,
`Connection to ${host}:${port} should be blocked`
);
}
Services.io.removeBlockedLocalPort(port);
Assert.equal(await connectTo("127.0.0.1", port), Cr.NS_OK);
});
add_task(async function test_only_blocked_port_is_affected() {
let port = httpServer.identity.primaryPort;
Services.io.addBlockedLocalPort(port === 65535 ? port - 1 : port + 1);
let [req, buffer] = await channelOpenPromise(
);
Assert.equal(req.status, Cr.NS_OK);
Assert.equal(buffer, "ok");
Services.io.removeBlockedLocalPort(port === 65535 ? port - 1 : port + 1);
});
add_task(async function test_socket_to_blocked_port_on_interface_address() {
let addresses = await resolveMyHostName();
let address = addresses.find(isPrivateIPv4);
if (!address) {
info("No private IPv4 interface address available, skipping");
return;
}
let server = Cc["@mozilla.org/network/server-socket;1"].createInstance(
Ci.nsIServerSocket
);
let accepted = [];
server.init(-1, false, -1);
server.asyncListen({
onSocketAccepted(socket, transport) {
accepted.push(transport);
},
onStopListening() {},
});
registerCleanupFunction(() => {
accepted.forEach(t => t.close(Cr.NS_OK));
server.close();
});
Assert.equal(await connectTo(address, server.port), Cr.NS_OK);
Services.io.addBlockedLocalPort(server.port);
Assert.equal(
await connectTo(address, server.port),
Cr.NS_ERROR_PORT_ACCESS_NOT_ALLOWED,
`Connection to ${address}:${server.port} should be blocked`
);
Services.io.removeBlockedLocalPort(server.port);
Assert.equal(await connectTo(address, server.port), Cr.NS_OK);
});