forked from mirrors/gecko-dev
Initially reported and discussed in Bug 610896.
The simple solution of just flipping the pref `network.proxy.socks_remote_dns`
is risky due to potentially breaking SOCKS4 proxy users. Proxying
DNS on SOCKS4 isn't supported. Therefore we speak the incompatible
SOCKS4a protocol when `socks_remote_dns` is enabled, potentially
breaking users setup.
To keep backwards compatibility on SOCKS4 proxy users, that don't have
SOCKS4a support, the pref `network.proxy.socks_remote_dns` is split into
two prefs:
* `network.proxy.socks_remote_dns`: remote DNS for SOCKS4
* `network.proxy.socks5_remote_dns`: remote DNS for SOCKS5.
This way we proxy DNS by default on SOCKS5 while keeping user settings
on SOCKS4. This is a similar approach to the one described in
[Bug 610896 comment 17].
Proxying DNS in SOCKS4 by default is desireable (See [Bug 610896 comment 11]),
but out of scope for this patch. [Telemetry] on proxy usage by socks
version indicated that changing the default for SOCKS4 is likely break
some users setup and needs to be taken with more care.
The default values of [proxyDNS] now defaults to true for SOCKS5 proxies.
When creating nsIProxyInfo objects of SOCKS4 proxies, the default value
false is kept. Setting proxyDNS affects both SOCKS4 and SOCKS5 proxy by
modifying both `socks_remote_dns` and `socks5_remote_dns`. Therefore no
extension breakage is expected.
The enterprise policy can also modify the new pref
`network.proxy.socks5_remote_dns`.
Follow up bugs filed while implementing:
* Bug 1890542 - Also disable Prefetch non-manual configurations of socks
proxy
* Bug 1890554 - Use `ProxyInfo::TRANSPARENT_PROXY_RESOLVES_HOST` flag in
`nsHttpChannel::GetProxyDNSStrategy`
* Bug 1890549 - nsHttpChannel implementation DNS resolve strategy for
proxies incomplete
* Bug 1893670 - Proxy DNS by default for SOCK4 proxies. Defaulting to
SOCKS4a
[Bug 610896 comment 17]: https://bugzilla.mozilla.org/show_bug.cgi?id=610896#c17
[Bug 610896 comment 11]: https://bugzilla.mozilla.org/show_bug.cgi?id=610896#c11
[Telemetry]: https://bugzilla.mozilla.org/show_bug.cgi?id=1741375#c27
[proxyDNS]: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/proxy/settings#proxydns
Differential Revision: https://phabricator.services.mozilla.com/D207532
1071 lines
28 KiB
JavaScript
1071 lines
28 KiB
JavaScript
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
|
/* vim:set ts=2 sw=2 sts=2 et: */
|
|
/* 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
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
// This testcase exercises the Protocol Proxy Service
|
|
|
|
// These are the major sub tests:
|
|
// run_filter_test();
|
|
// run_filter_test2()
|
|
// run_filter_test3()
|
|
// run_pref_test();
|
|
// run_pac_test();
|
|
// run_pac_cancel_test();
|
|
// run_proxy_host_filters_test();
|
|
// run_myipaddress_test();
|
|
// run_failed_script_test();
|
|
// run_isresolvable_test();
|
|
|
|
"use strict";
|
|
|
|
var ios = Services.io;
|
|
var pps = Cc["@mozilla.org/network/protocol-proxy-service;1"].getService();
|
|
var prefs = Services.prefs;
|
|
var again = true;
|
|
|
|
/**
|
|
* Test nsIProtocolHandler that allows proxying, but doesn't allow HTTP
|
|
* proxying.
|
|
*/
|
|
function TestProtocolHandler() {}
|
|
TestProtocolHandler.prototype = {
|
|
QueryInterface: ChromeUtils.generateQI(["nsIProtocolHandler"]),
|
|
scheme: "moz-test",
|
|
defaultPort: -1,
|
|
protocolFlags:
|
|
Ci.nsIProtocolHandler.URI_NOAUTH |
|
|
Ci.nsIProtocolHandler.URI_NORELATIVE |
|
|
Ci.nsIProtocolHandler.ALLOWS_PROXY |
|
|
Ci.nsIProtocolHandler.URI_DANGEROUS_TO_LOAD,
|
|
newChannel() {
|
|
throw Components.Exception("", Cr.NS_ERROR_NOT_IMPLEMENTED);
|
|
},
|
|
allowPort() {
|
|
return true;
|
|
},
|
|
};
|
|
|
|
function TestProtocolHandlerFactory() {}
|
|
TestProtocolHandlerFactory.prototype = {
|
|
createInstance(iid) {
|
|
return new TestProtocolHandler().QueryInterface(iid);
|
|
},
|
|
};
|
|
|
|
function register_test_protocol_handler() {
|
|
var reg = Components.manager.QueryInterface(Ci.nsIComponentRegistrar);
|
|
reg.registerFactory(
|
|
Components.ID("{4ea7dd3a-8cae-499c-9f18-e1de773ca25b}"),
|
|
"TestProtocolHandler",
|
|
"@mozilla.org/network/protocol;1?name=moz-test",
|
|
new TestProtocolHandlerFactory()
|
|
);
|
|
}
|
|
|
|
function check_proxy(pi, type, host, port, flags, timeout, hasNext) {
|
|
Assert.notEqual(pi, null);
|
|
Assert.equal(pi.type, type);
|
|
Assert.equal(pi.host, host);
|
|
Assert.equal(pi.port, port);
|
|
if (flags != -1) {
|
|
Assert.equal(pi.flags, flags);
|
|
}
|
|
if (timeout != -1) {
|
|
Assert.equal(pi.failoverTimeout, timeout);
|
|
}
|
|
if (hasNext) {
|
|
Assert.notEqual(pi.failoverProxy, null);
|
|
} else {
|
|
Assert.equal(pi.failoverProxy, null);
|
|
}
|
|
}
|
|
|
|
function TestFilter(type, host, port, flags, timeout) {
|
|
this._type = type;
|
|
this._host = host;
|
|
this._port = port;
|
|
this._flags = flags;
|
|
this._timeout = timeout;
|
|
}
|
|
TestFilter.prototype = {
|
|
_type: "",
|
|
_host: "",
|
|
_port: -1,
|
|
_flags: 0,
|
|
_timeout: 0,
|
|
QueryInterface: ChromeUtils.generateQI(["nsIProtocolProxyFilter"]),
|
|
applyFilter(uri, pi, cb) {
|
|
var pi_tail = pps.newProxyInfo(
|
|
this._type,
|
|
this._host,
|
|
this._port,
|
|
"",
|
|
"",
|
|
this._flags,
|
|
this._timeout,
|
|
null
|
|
);
|
|
if (pi) {
|
|
pi.failoverProxy = pi_tail;
|
|
} else {
|
|
pi = pi_tail;
|
|
}
|
|
cb.onProxyFilterResult(pi);
|
|
},
|
|
};
|
|
|
|
function BasicFilter() {}
|
|
BasicFilter.prototype = {
|
|
QueryInterface: ChromeUtils.generateQI(["nsIProtocolProxyFilter"]),
|
|
applyFilter(uri, pi, cb) {
|
|
cb.onProxyFilterResult(
|
|
pps.newProxyInfo(
|
|
"http",
|
|
"localhost",
|
|
8080,
|
|
"",
|
|
"",
|
|
0,
|
|
10,
|
|
pps.newProxyInfo("direct", "", -1, "", "", 0, 0, null)
|
|
)
|
|
);
|
|
},
|
|
};
|
|
|
|
function BasicChannelFilter() {}
|
|
BasicChannelFilter.prototype = {
|
|
QueryInterface: ChromeUtils.generateQI(["nsIProtocolProxyChannelFilter"]),
|
|
applyFilter(channel, pi, cb) {
|
|
cb.onProxyFilterResult(
|
|
pps.newProxyInfo(
|
|
"http",
|
|
channel.URI.host,
|
|
7777,
|
|
"",
|
|
"",
|
|
0,
|
|
10,
|
|
pps.newProxyInfo("direct", "", -1, "", "", 0, 0, null)
|
|
)
|
|
);
|
|
},
|
|
};
|
|
|
|
function resolveCallback() {}
|
|
resolveCallback.prototype = {
|
|
nextFunction: null,
|
|
|
|
QueryInterface: ChromeUtils.generateQI(["nsIProtocolProxyCallback"]),
|
|
|
|
onProxyAvailable(req, channel, pi) {
|
|
this.nextFunction(pi);
|
|
},
|
|
};
|
|
|
|
function run_filter_test() {
|
|
var channel = NetUtil.newChannel({
|
|
uri: "http://www.mozilla.org/",
|
|
loadUsingSystemPrincipal: true,
|
|
});
|
|
|
|
// Verify initial state
|
|
var cb = new resolveCallback();
|
|
cb.nextFunction = filter_test0_1;
|
|
pps.asyncResolve(channel, 0, cb);
|
|
}
|
|
|
|
var filter01;
|
|
var filter02;
|
|
|
|
function filter_test0_1(pi) {
|
|
Assert.equal(pi, null);
|
|
|
|
// Push a filter and verify the results
|
|
|
|
filter01 = new BasicFilter();
|
|
filter02 = new BasicFilter();
|
|
pps.registerFilter(filter01, 10);
|
|
pps.registerFilter(filter02, 20);
|
|
|
|
var cb = new resolveCallback();
|
|
cb.nextFunction = filter_test0_2;
|
|
var channel = NetUtil.newChannel({
|
|
uri: "http://www.mozilla.org/",
|
|
loadUsingSystemPrincipal: true,
|
|
});
|
|
pps.asyncResolve(channel, 0, cb);
|
|
}
|
|
|
|
function filter_test0_2(pi) {
|
|
check_proxy(pi, "http", "localhost", 8080, 0, 10, true);
|
|
check_proxy(pi.failoverProxy, "direct", "", -1, 0, 0, false);
|
|
|
|
pps.unregisterFilter(filter02);
|
|
|
|
var cb = new resolveCallback();
|
|
cb.nextFunction = filter_test0_3;
|
|
var channel = NetUtil.newChannel({
|
|
uri: "http://www.mozilla.org/",
|
|
loadUsingSystemPrincipal: true,
|
|
});
|
|
pps.asyncResolve(channel, 0, cb);
|
|
}
|
|
|
|
function filter_test0_3(pi) {
|
|
check_proxy(pi, "http", "localhost", 8080, 0, 10, true);
|
|
check_proxy(pi.failoverProxy, "direct", "", -1, 0, 0, false);
|
|
|
|
// Remove filter and verify that we return to the initial state
|
|
|
|
pps.unregisterFilter(filter01);
|
|
|
|
var cb = new resolveCallback();
|
|
cb.nextFunction = filter_test0_4;
|
|
var channel = NetUtil.newChannel({
|
|
uri: "http://www.mozilla.org/",
|
|
loadUsingSystemPrincipal: true,
|
|
});
|
|
pps.asyncResolve(channel, 0, cb);
|
|
}
|
|
|
|
var filter03;
|
|
|
|
function filter_test0_4(pi) {
|
|
Assert.equal(pi, null);
|
|
filter03 = new BasicChannelFilter();
|
|
pps.registerChannelFilter(filter03, 10);
|
|
var cb = new resolveCallback();
|
|
cb.nextFunction = filter_test0_5;
|
|
var channel = NetUtil.newChannel({
|
|
uri: "http://www.mozilla.org/",
|
|
loadUsingSystemPrincipal: true,
|
|
});
|
|
pps.asyncResolve(channel, 0, cb);
|
|
}
|
|
|
|
function filter_test0_5(pi) {
|
|
pps.unregisterChannelFilter(filter03);
|
|
check_proxy(pi, "http", "www.mozilla.org", 7777, 0, 10, true);
|
|
check_proxy(pi.failoverProxy, "direct", "", -1, 0, 0, false);
|
|
run_filter_test_uri();
|
|
}
|
|
|
|
function run_filter_test_uri() {
|
|
var cb = new resolveCallback();
|
|
cb.nextFunction = filter_test_uri0_1;
|
|
var uri = ios.newURI("http://www.mozilla.org/");
|
|
pps.asyncResolve(uri, 0, cb);
|
|
}
|
|
|
|
function filter_test_uri0_1(pi) {
|
|
Assert.equal(pi, null);
|
|
|
|
// Push a filter and verify the results
|
|
|
|
filter01 = new BasicFilter();
|
|
filter02 = new BasicFilter();
|
|
pps.registerFilter(filter01, 10);
|
|
pps.registerFilter(filter02, 20);
|
|
|
|
var cb = new resolveCallback();
|
|
cb.nextFunction = filter_test_uri0_2;
|
|
var uri = ios.newURI("http://www.mozilla.org/");
|
|
pps.asyncResolve(uri, 0, cb);
|
|
}
|
|
|
|
function filter_test_uri0_2(pi) {
|
|
check_proxy(pi, "http", "localhost", 8080, 0, 10, true);
|
|
check_proxy(pi.failoverProxy, "direct", "", -1, 0, 0, false);
|
|
|
|
pps.unregisterFilter(filter02);
|
|
|
|
var cb = new resolveCallback();
|
|
cb.nextFunction = filter_test_uri0_3;
|
|
var uri = ios.newURI("http://www.mozilla.org/");
|
|
pps.asyncResolve(uri, 0, cb);
|
|
}
|
|
|
|
function filter_test_uri0_3(pi) {
|
|
check_proxy(pi, "http", "localhost", 8080, 0, 10, true);
|
|
check_proxy(pi.failoverProxy, "direct", "", -1, 0, 0, false);
|
|
|
|
// Remove filter and verify that we return to the initial state
|
|
|
|
pps.unregisterFilter(filter01);
|
|
|
|
var cb = new resolveCallback();
|
|
cb.nextFunction = filter_test_uri0_4;
|
|
var uri = ios.newURI("http://www.mozilla.org/");
|
|
pps.asyncResolve(uri, 0, cb);
|
|
}
|
|
|
|
function filter_test_uri0_4(pi) {
|
|
Assert.equal(pi, null);
|
|
run_filter_test2();
|
|
}
|
|
|
|
var filter11;
|
|
var filter12;
|
|
|
|
function run_filter_test2() {
|
|
// Push a filter and verify the results
|
|
|
|
filter11 = new TestFilter("http", "foo", 8080, 0, 10);
|
|
filter12 = new TestFilter("http", "bar", 8090, 0, 10);
|
|
pps.registerFilter(filter11, 20);
|
|
pps.registerFilter(filter12, 10);
|
|
|
|
var cb = new resolveCallback();
|
|
cb.nextFunction = filter_test1_1;
|
|
var channel = NetUtil.newChannel({
|
|
uri: "http://www.mozilla.org/",
|
|
loadUsingSystemPrincipal: true,
|
|
});
|
|
pps.asyncResolve(channel, 0, cb);
|
|
}
|
|
|
|
function filter_test1_1(pi) {
|
|
check_proxy(pi, "http", "bar", 8090, 0, 10, true);
|
|
check_proxy(pi.failoverProxy, "http", "foo", 8080, 0, 10, false);
|
|
|
|
pps.unregisterFilter(filter12);
|
|
|
|
var cb = new resolveCallback();
|
|
cb.nextFunction = filter_test1_2;
|
|
var channel = NetUtil.newChannel({
|
|
uri: "http://www.mozilla.org/",
|
|
loadUsingSystemPrincipal: true,
|
|
});
|
|
pps.asyncResolve(channel, 0, cb);
|
|
}
|
|
|
|
function filter_test1_2(pi) {
|
|
check_proxy(pi, "http", "foo", 8080, 0, 10, false);
|
|
|
|
// Remove filter and verify that we return to the initial state
|
|
|
|
pps.unregisterFilter(filter11);
|
|
|
|
var cb = new resolveCallback();
|
|
cb.nextFunction = filter_test1_3;
|
|
var channel = NetUtil.newChannel({
|
|
uri: "http://www.mozilla.org/",
|
|
loadUsingSystemPrincipal: true,
|
|
});
|
|
pps.asyncResolve(channel, 0, cb);
|
|
}
|
|
|
|
function filter_test1_3(pi) {
|
|
Assert.equal(pi, null);
|
|
run_filter_test3();
|
|
}
|
|
|
|
var filter_3_1;
|
|
|
|
function run_filter_test3() {
|
|
var channel = NetUtil.newChannel({
|
|
uri: "http://www.mozilla.org/",
|
|
loadUsingSystemPrincipal: true,
|
|
});
|
|
// Push a filter and verify the results asynchronously
|
|
|
|
filter_3_1 = new TestFilter("http", "foo", 8080, 0, 10);
|
|
pps.registerFilter(filter_3_1, 20);
|
|
|
|
var cb = new resolveCallback();
|
|
cb.nextFunction = filter_test3_1;
|
|
pps.asyncResolve(channel, 0, cb);
|
|
}
|
|
|
|
function filter_test3_1(pi) {
|
|
check_proxy(pi, "http", "foo", 8080, 0, 10, false);
|
|
pps.unregisterFilter(filter_3_1);
|
|
run_pref_test();
|
|
}
|
|
|
|
function run_pref_test() {
|
|
var channel = NetUtil.newChannel({
|
|
uri: "http://www.mozilla.org/",
|
|
loadUsingSystemPrincipal: true,
|
|
});
|
|
// Verify 'direct' setting
|
|
|
|
prefs.setIntPref("network.proxy.type", 0);
|
|
|
|
var cb = new resolveCallback();
|
|
cb.nextFunction = pref_test1_1;
|
|
pps.asyncResolve(channel, 0, cb);
|
|
}
|
|
|
|
function pref_test1_1(pi) {
|
|
Assert.equal(pi, null);
|
|
|
|
// Verify 'manual' setting
|
|
prefs.setIntPref("network.proxy.type", 1);
|
|
|
|
var cb = new resolveCallback();
|
|
cb.nextFunction = pref_test1_2;
|
|
var channel = NetUtil.newChannel({
|
|
uri: "http://www.mozilla.org/",
|
|
loadUsingSystemPrincipal: true,
|
|
});
|
|
pps.asyncResolve(channel, 0, cb);
|
|
}
|
|
|
|
function pref_test1_2(pi) {
|
|
// nothing yet configured
|
|
Assert.equal(pi, null);
|
|
|
|
// try HTTP configuration
|
|
prefs.setCharPref("network.proxy.http", "foopy");
|
|
prefs.setIntPref("network.proxy.http_port", 8080);
|
|
|
|
var cb = new resolveCallback();
|
|
cb.nextFunction = pref_test1_3;
|
|
var channel = NetUtil.newChannel({
|
|
uri: "http://www.mozilla.org/",
|
|
loadUsingSystemPrincipal: true,
|
|
});
|
|
pps.asyncResolve(channel, 0, cb);
|
|
}
|
|
|
|
function pref_test1_3(pi) {
|
|
check_proxy(pi, "http", "foopy", 8080, 0, -1, false);
|
|
|
|
prefs.setCharPref("network.proxy.http", "");
|
|
prefs.setIntPref("network.proxy.http_port", 0);
|
|
|
|
// try SOCKS configuration
|
|
prefs.setCharPref("network.proxy.socks", "barbar");
|
|
prefs.setIntPref("network.proxy.socks_port", 1203);
|
|
|
|
var cb = new resolveCallback();
|
|
cb.nextFunction = pref_test1_4;
|
|
var channel = NetUtil.newChannel({
|
|
uri: "http://www.mozilla.org/",
|
|
loadUsingSystemPrincipal: true,
|
|
});
|
|
pps.asyncResolve(channel, 0, cb);
|
|
}
|
|
|
|
function pref_test1_4(pi) {
|
|
check_proxy(pi, "socks", "barbar", 1203, 1, -1, false);
|
|
run_pac_test();
|
|
}
|
|
|
|
function TestResolveCallback(type, nexttest) {
|
|
this.type = type;
|
|
this.nexttest = nexttest;
|
|
}
|
|
TestResolveCallback.prototype = {
|
|
QueryInterface: ChromeUtils.generateQI(["nsIProtocolProxyCallback"]),
|
|
|
|
onProxyAvailable: function TestResolveCallback_onProxyAvailable(
|
|
req,
|
|
channel,
|
|
pi,
|
|
status
|
|
) {
|
|
dump("*** channelURI=" + channel.URI.spec + ", status=" + status + "\n");
|
|
|
|
if (this.type == null) {
|
|
Assert.equal(pi, null);
|
|
} else {
|
|
Assert.notEqual(req, null);
|
|
Assert.notEqual(channel, null);
|
|
Assert.equal(status, 0);
|
|
Assert.notEqual(pi, null);
|
|
check_proxy(pi, this.type, "foopy", 8080, 1, -1, true);
|
|
check_proxy(pi.failoverProxy, "direct", "", -1, -1, -1, false);
|
|
}
|
|
|
|
this.nexttest();
|
|
},
|
|
};
|
|
|
|
var originalTLSProxy;
|
|
|
|
function run_pac_test() {
|
|
var pac =
|
|
"data:text/plain," +
|
|
"function FindProxyForURL(url, host) {" +
|
|
' return "PROXY foopy:8080; DIRECT";' +
|
|
"}";
|
|
var channel = NetUtil.newChannel({
|
|
uri: "http://www.mozilla.org/",
|
|
loadUsingSystemPrincipal: true,
|
|
});
|
|
// Configure PAC
|
|
|
|
prefs.setIntPref("network.proxy.type", 2);
|
|
prefs.setCharPref("network.proxy.autoconfig_url", pac);
|
|
pps.asyncResolve(channel, 0, new TestResolveCallback("http", run_pac2_test));
|
|
}
|
|
|
|
function run_pac2_test() {
|
|
var pac =
|
|
"data:text/plain," +
|
|
"function FindProxyForURL(url, host) {" +
|
|
' return "HTTPS foopy:8080; DIRECT";' +
|
|
"}";
|
|
var channel = NetUtil.newChannel({
|
|
uri: "http://www.mozilla.org/",
|
|
loadUsingSystemPrincipal: true,
|
|
});
|
|
// Configure PAC
|
|
originalTLSProxy = prefs.getBoolPref("network.proxy.proxy_over_tls");
|
|
|
|
prefs.setCharPref("network.proxy.autoconfig_url", pac);
|
|
prefs.setBoolPref("network.proxy.proxy_over_tls", true);
|
|
|
|
pps.asyncResolve(channel, 0, new TestResolveCallback("https", run_pac3_test));
|
|
}
|
|
|
|
function run_pac3_test() {
|
|
var pac =
|
|
"data:text/plain," +
|
|
"function FindProxyForURL(url, host) {" +
|
|
' return "HTTPS foopy:8080; DIRECT";' +
|
|
"}";
|
|
var channel = NetUtil.newChannel({
|
|
uri: "http://www.mozilla.org/",
|
|
loadUsingSystemPrincipal: true,
|
|
});
|
|
// Configure PAC
|
|
prefs.setCharPref("network.proxy.autoconfig_url", pac);
|
|
prefs.setBoolPref("network.proxy.proxy_over_tls", false);
|
|
|
|
pps.asyncResolve(channel, 0, new TestResolveCallback(null, run_pac4_test));
|
|
}
|
|
|
|
function run_pac4_test() {
|
|
// Bug 1251332
|
|
let wRange = [
|
|
["SUN", "MON", "SAT", "MON"], // for Sun
|
|
["SUN", "TUE", "SAT", "TUE"], // for Mon
|
|
["MON", "WED", "SAT", "WED"], // for Tue
|
|
["TUE", "THU", "SAT", "THU"], // for Wed
|
|
["WED", "FRI", "WED", "SUN"], // for Thu
|
|
["THU", "SAT", "THU", "SUN"], // for Fri
|
|
["FRI", "SAT", "FRI", "SUN"], // for Sat
|
|
];
|
|
let today = new Date().getDay();
|
|
var pac =
|
|
"data:text/plain," +
|
|
"function FindProxyForURL(url, host) {" +
|
|
' if (weekdayRange("' +
|
|
wRange[today][0] +
|
|
'", "' +
|
|
wRange[today][1] +
|
|
'") &&' +
|
|
' weekdayRange("' +
|
|
wRange[today][2] +
|
|
'", "' +
|
|
wRange[today][3] +
|
|
'")) {' +
|
|
' return "PROXY foopy:8080; DIRECT";' +
|
|
" }" +
|
|
"}";
|
|
var channel = NetUtil.newChannel({
|
|
uri: "http://www.mozilla.org/",
|
|
loadUsingSystemPrincipal: true,
|
|
});
|
|
// Configure PAC
|
|
|
|
prefs.setIntPref("network.proxy.type", 2);
|
|
prefs.setCharPref("network.proxy.autoconfig_url", pac);
|
|
pps.asyncResolve(
|
|
channel,
|
|
0,
|
|
new TestResolveCallback("http", run_utf8_pac_test)
|
|
);
|
|
}
|
|
|
|
function run_utf8_pac_test() {
|
|
var pac =
|
|
"data:text/plain;charset=UTF-8," +
|
|
"function FindProxyForURL(url, host) {" +
|
|
" /*" +
|
|
" U+00A9 COPYRIGHT SIGN: %C2%A9," +
|
|
" U+0B87 TAMIL LETTER I: %E0%AE%87," +
|
|
" U+10398 UGARITIC LETTER THANNA: %F0%90%8E%98 " +
|
|
" */" +
|
|
' var multiBytes = "%C2%A9 %E0%AE%87 %F0%90%8E%98"; ' +
|
|
" /* 6 UTF-16 units above if PAC script run as UTF-8; 11 units if run as Latin-1 */ " +
|
|
" return multiBytes.length === 6 " +
|
|
' ? "PROXY foopy:8080; DIRECT" ' +
|
|
' : "PROXY epicfail-utf8:12345; DIRECT";' +
|
|
"}";
|
|
|
|
var channel = NetUtil.newChannel({
|
|
uri: "http://www.mozilla.org/",
|
|
loadUsingSystemPrincipal: true,
|
|
});
|
|
|
|
// Configure PAC
|
|
prefs.setIntPref("network.proxy.type", 2);
|
|
prefs.setCharPref("network.proxy.autoconfig_url", pac);
|
|
|
|
pps.asyncResolve(
|
|
channel,
|
|
0,
|
|
new TestResolveCallback("http", run_latin1_pac_test)
|
|
);
|
|
}
|
|
|
|
function run_latin1_pac_test() {
|
|
var pac =
|
|
"data:text/plain," +
|
|
"function FindProxyForURL(url, host) {" +
|
|
" /* A too-long encoding of U+0000, so not valid UTF-8 */ " +
|
|
' var multiBytes = "%C0%80"; ' +
|
|
" /* 2 UTF-16 units because interpreted as Latin-1 */ " +
|
|
" return multiBytes.length === 2 " +
|
|
' ? "PROXY foopy:8080; DIRECT" ' +
|
|
' : "PROXY epicfail-latin1:12345; DIRECT";' +
|
|
"}";
|
|
|
|
var channel = NetUtil.newChannel({
|
|
uri: "http://www.mozilla.org/",
|
|
loadUsingSystemPrincipal: true,
|
|
});
|
|
|
|
// Configure PAC
|
|
prefs.setIntPref("network.proxy.type", 2);
|
|
prefs.setCharPref("network.proxy.autoconfig_url", pac);
|
|
|
|
pps.asyncResolve(
|
|
channel,
|
|
0,
|
|
new TestResolveCallback("http", finish_pac_test)
|
|
);
|
|
}
|
|
|
|
function finish_pac_test() {
|
|
prefs.setBoolPref("network.proxy.proxy_over_tls", originalTLSProxy);
|
|
run_pac_cancel_test();
|
|
}
|
|
|
|
function TestResolveCancelationCallback() {}
|
|
TestResolveCancelationCallback.prototype = {
|
|
QueryInterface: ChromeUtils.generateQI(["nsIProtocolProxyCallback"]),
|
|
|
|
onProxyAvailable: function TestResolveCancelationCallback_onProxyAvailable(
|
|
req,
|
|
channel,
|
|
pi,
|
|
status
|
|
) {
|
|
dump("*** channelURI=" + channel.URI.spec + ", status=" + status + "\n");
|
|
|
|
Assert.notEqual(req, null);
|
|
Assert.notEqual(channel, null);
|
|
Assert.equal(status, Cr.NS_ERROR_ABORT);
|
|
Assert.equal(pi, null);
|
|
|
|
prefs.setCharPref("network.proxy.autoconfig_url", "");
|
|
prefs.setIntPref("network.proxy.type", 0);
|
|
|
|
run_proxy_host_filters_test();
|
|
},
|
|
};
|
|
|
|
function run_pac_cancel_test() {
|
|
var channel = NetUtil.newChannel({
|
|
uri: "http://www.mozilla.org/",
|
|
loadUsingSystemPrincipal: true,
|
|
});
|
|
// Configure PAC
|
|
var pac =
|
|
"data:text/plain," +
|
|
"function FindProxyForURL(url, host) {" +
|
|
' return "PROXY foopy:8080; DIRECT";' +
|
|
"}";
|
|
prefs.setIntPref("network.proxy.type", 2);
|
|
prefs.setCharPref("network.proxy.autoconfig_url", pac);
|
|
|
|
var req = pps.asyncResolve(channel, 0, new TestResolveCancelationCallback());
|
|
req.cancel(Cr.NS_ERROR_ABORT);
|
|
}
|
|
|
|
var hostList;
|
|
var hostIDX;
|
|
var bShouldBeFiltered;
|
|
var hostNextFX;
|
|
|
|
function check_host_filters(hl, shouldBe, nextFX) {
|
|
hostList = hl;
|
|
hostIDX = 0;
|
|
bShouldBeFiltered = shouldBe;
|
|
hostNextFX = nextFX;
|
|
|
|
if (hostList.length > hostIDX) {
|
|
check_host_filter(hostIDX);
|
|
}
|
|
}
|
|
|
|
function check_host_filters_cb() {
|
|
hostIDX++;
|
|
if (hostList.length > hostIDX) {
|
|
check_host_filter(hostIDX);
|
|
} else {
|
|
hostNextFX();
|
|
}
|
|
}
|
|
|
|
function check_host_filter(i) {
|
|
dump(
|
|
"*** uri=" + hostList[i] + " bShouldBeFiltered=" + bShouldBeFiltered + "\n"
|
|
);
|
|
var channel = NetUtil.newChannel({
|
|
uri: hostList[i],
|
|
loadUsingSystemPrincipal: true,
|
|
});
|
|
var cb = new resolveCallback();
|
|
cb.nextFunction = host_filter_cb;
|
|
pps.asyncResolve(channel, 0, cb);
|
|
}
|
|
|
|
function host_filter_cb(proxy) {
|
|
if (bShouldBeFiltered) {
|
|
Assert.equal(proxy, null);
|
|
} else {
|
|
Assert.notEqual(proxy, null);
|
|
// Just to be sure, let's check that the proxy is correct
|
|
// - this should match the proxy setup in the calling function
|
|
check_proxy(proxy, "http", "foopy", 8080, 0, -1, false);
|
|
}
|
|
check_host_filters_cb();
|
|
}
|
|
|
|
// Verify that hists in the host filter list are not proxied
|
|
// refers to "network.proxy.no_proxies_on"
|
|
|
|
var uriStrUseProxyList;
|
|
var hostFilterList;
|
|
var uriStrFilterList;
|
|
|
|
function run_proxy_host_filters_test() {
|
|
// Get prefs object from DOM
|
|
// Setup a basic HTTP proxy configuration
|
|
// - pps.resolve() needs this to return proxy info for non-filtered hosts
|
|
prefs.setIntPref("network.proxy.type", 1);
|
|
prefs.setCharPref("network.proxy.http", "foopy");
|
|
prefs.setIntPref("network.proxy.http_port", 8080);
|
|
|
|
// Setup host filter list string for "no_proxies_on"
|
|
hostFilterList =
|
|
"www.mozilla.org, www.google.com, www.apple.com, " +
|
|
".domain, .domain2.org";
|
|
prefs.setCharPref("network.proxy.no_proxies_on", hostFilterList);
|
|
Assert.equal(
|
|
prefs.getCharPref("network.proxy.no_proxies_on"),
|
|
hostFilterList
|
|
);
|
|
|
|
// Check the hosts that should be filtered out
|
|
uriStrFilterList = [
|
|
"http://www.mozilla.org/",
|
|
"http://www.google.com/",
|
|
"http://www.apple.com/",
|
|
"http://somehost.domain/",
|
|
"http://someotherhost.domain/",
|
|
"http://somehost.domain2.org/",
|
|
"http://somehost.subdomain.domain2.org/",
|
|
];
|
|
check_host_filters(uriStrFilterList, true, host_filters_1);
|
|
}
|
|
|
|
function host_filters_1() {
|
|
// Check the hosts that should be proxied
|
|
uriStrUseProxyList = [
|
|
"http://www.mozilla.com/",
|
|
"http://mail.google.com/",
|
|
"http://somehost.domain.co.uk/",
|
|
"http://somelocalhost/",
|
|
];
|
|
check_host_filters(uriStrUseProxyList, false, host_filters_2);
|
|
}
|
|
|
|
function host_filters_2() {
|
|
// Set no_proxies_on to include local hosts
|
|
prefs.setCharPref(
|
|
"network.proxy.no_proxies_on",
|
|
hostFilterList + ", <local>"
|
|
);
|
|
Assert.equal(
|
|
prefs.getCharPref("network.proxy.no_proxies_on"),
|
|
hostFilterList + ", <local>"
|
|
);
|
|
// Amend lists - move local domain to filtered list
|
|
uriStrFilterList.push(uriStrUseProxyList.pop());
|
|
check_host_filters(uriStrFilterList, true, host_filters_3);
|
|
}
|
|
|
|
function host_filters_3() {
|
|
check_host_filters(uriStrUseProxyList, false, host_filters_4);
|
|
}
|
|
|
|
function host_filters_4() {
|
|
// Cleanup
|
|
prefs.setCharPref("network.proxy.no_proxies_on", "");
|
|
Assert.equal(prefs.getCharPref("network.proxy.no_proxies_on"), "");
|
|
|
|
run_myipaddress_test();
|
|
}
|
|
|
|
function run_myipaddress_test() {
|
|
// This test makes sure myIpAddress() comes up with some valid
|
|
// IP address other than localhost. The DUT must be configured with
|
|
// an Internet route for this to work - though no Internet traffic
|
|
// should be created.
|
|
|
|
var pac =
|
|
"data:text/plain," +
|
|
"var pacUseMultihomedDNS = true;\n" +
|
|
"function FindProxyForURL(url, host) {" +
|
|
' return "PROXY " + myIpAddress() + ":1234";' +
|
|
"}";
|
|
|
|
// no traffic to this IP is ever sent, it is just a public IP that
|
|
// does not require DNS to determine a route.
|
|
var channel = NetUtil.newChannel({
|
|
uri: "http://192.0.43.10/",
|
|
loadUsingSystemPrincipal: true,
|
|
});
|
|
prefs.setIntPref("network.proxy.type", 2);
|
|
prefs.setCharPref("network.proxy.autoconfig_url", pac);
|
|
|
|
var cb = new resolveCallback();
|
|
cb.nextFunction = myipaddress_callback;
|
|
pps.asyncResolve(channel, 0, cb);
|
|
}
|
|
|
|
function myipaddress_callback(pi) {
|
|
Assert.notEqual(pi, null);
|
|
Assert.equal(pi.type, "http");
|
|
Assert.equal(pi.port, 1234);
|
|
|
|
// make sure we didn't return localhost
|
|
Assert.notEqual(pi.host, null);
|
|
Assert.notEqual(pi.host, "127.0.0.1");
|
|
Assert.notEqual(pi.host, "::1");
|
|
|
|
run_myipaddress_test_2();
|
|
}
|
|
|
|
function run_myipaddress_test_2() {
|
|
// test that myIPAddress() can be used outside of the scope of
|
|
// FindProxyForURL(). bug 829646.
|
|
|
|
var pac =
|
|
"data:text/plain," +
|
|
"var pacUseMultihomedDNS = true;\n" +
|
|
"var myaddr = myIpAddress(); " +
|
|
"function FindProxyForURL(url, host) {" +
|
|
' return "PROXY " + myaddr + ":5678";' +
|
|
"}";
|
|
|
|
var channel = NetUtil.newChannel({
|
|
uri: "http://www.mozilla.org/",
|
|
loadUsingSystemPrincipal: true,
|
|
});
|
|
prefs.setIntPref("network.proxy.type", 2);
|
|
prefs.setCharPref("network.proxy.autoconfig_url", pac);
|
|
|
|
var cb = new resolveCallback();
|
|
cb.nextFunction = myipaddress2_callback;
|
|
pps.asyncResolve(channel, 0, cb);
|
|
}
|
|
|
|
function myipaddress2_callback(pi) {
|
|
Assert.notEqual(pi, null);
|
|
Assert.equal(pi.type, "http");
|
|
Assert.equal(pi.port, 5678);
|
|
|
|
// make sure we didn't return localhost
|
|
Assert.notEqual(pi.host, null);
|
|
Assert.notEqual(pi.host, "127.0.0.1");
|
|
Assert.notEqual(pi.host, "::1");
|
|
|
|
run_failed_script_test();
|
|
}
|
|
|
|
function run_failed_script_test() {
|
|
// test to make sure we go direct with invalid PAC
|
|
// eslint-disable-next-line no-useless-concat
|
|
var pac = "data:text/plain," + "\nfor(;\n";
|
|
|
|
var channel = NetUtil.newChannel({
|
|
uri: "http://www.mozilla.org/",
|
|
loadUsingSystemPrincipal: true,
|
|
});
|
|
prefs.setIntPref("network.proxy.type", 2);
|
|
prefs.setCharPref("network.proxy.autoconfig_url", pac);
|
|
|
|
var cb = new resolveCallback();
|
|
cb.nextFunction = failed_script_callback;
|
|
pps.asyncResolve(channel, 0, cb);
|
|
}
|
|
|
|
var directFilter;
|
|
const TEST_URI = "http://127.0.0.1:7247/";
|
|
|
|
function failed_script_callback(pi) {
|
|
// we should go direct
|
|
Assert.equal(pi, null);
|
|
|
|
// test that we honor filters when configured to go direct
|
|
prefs.setIntPref("network.proxy.type", 0);
|
|
directFilter = new TestFilter("http", "127.0.0.1", 7246, 0, 0);
|
|
pps.registerFilter(directFilter, 10);
|
|
|
|
// test that on-modify-request contains the proxy info too
|
|
var obs = Cc["@mozilla.org/observer-service;1"].getService();
|
|
obs = obs.QueryInterface(Ci.nsIObserverService);
|
|
obs.addObserver(directFilterListener, "http-on-modify-request");
|
|
|
|
var ssm = Services.scriptSecurityManager;
|
|
let uri = TEST_URI;
|
|
var chan = NetUtil.newChannel({
|
|
uri,
|
|
loadingPrincipal: ssm.createContentPrincipal(Services.io.newURI(uri), {}),
|
|
securityFlags: Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_INHERITS_SEC_CONTEXT,
|
|
contentPolicyType: Ci.nsIContentPolicy.TYPE_DOCUMENT,
|
|
});
|
|
|
|
chan.asyncOpen(directFilterListener);
|
|
}
|
|
|
|
var directFilterListener = {
|
|
onModifyRequestCalled: false,
|
|
|
|
onStartRequest: function test_onStart() {},
|
|
onDataAvailable: function test_OnData() {},
|
|
|
|
onStopRequest: function test_onStop(request) {
|
|
// check on the PI from the channel itself
|
|
request.QueryInterface(Ci.nsIProxiedChannel);
|
|
check_proxy(request.proxyInfo, "http", "127.0.0.1", 7246, 0, 0, false);
|
|
pps.unregisterFilter(directFilter);
|
|
|
|
// check on the PI from on-modify-request
|
|
Assert.ok(this.onModifyRequestCalled);
|
|
var obs = Cc["@mozilla.org/observer-service;1"].getService();
|
|
obs = obs.QueryInterface(Ci.nsIObserverService);
|
|
obs.removeObserver(this, "http-on-modify-request");
|
|
|
|
run_isresolvable_test();
|
|
},
|
|
|
|
observe(subject, topic) {
|
|
if (
|
|
topic === "http-on-modify-request" &&
|
|
subject instanceof Ci.nsIHttpChannel &&
|
|
subject instanceof Ci.nsIProxiedChannel
|
|
) {
|
|
info("check proxy in observe uri=" + subject.URI.spec);
|
|
if (subject.URI.spec != TEST_URI) {
|
|
return;
|
|
}
|
|
check_proxy(subject.proxyInfo, "http", "127.0.0.1", 7246, 0, 0, false);
|
|
this.onModifyRequestCalled = true;
|
|
}
|
|
},
|
|
};
|
|
|
|
function run_isresolvable_test() {
|
|
// test a non resolvable host in the pac file
|
|
|
|
var pac =
|
|
"data:text/plain," +
|
|
"function FindProxyForURL(url, host) {" +
|
|
' if (isResolvable("nonexistant.lan.onion"))' +
|
|
' return "DIRECT";' +
|
|
' return "PROXY 127.0.0.1:1234";' +
|
|
"}";
|
|
|
|
var channel = NetUtil.newChannel({
|
|
uri: "http://www.mozilla.org/",
|
|
loadUsingSystemPrincipal: true,
|
|
});
|
|
prefs.setIntPref("network.proxy.type", 2);
|
|
prefs.setCharPref("network.proxy.autoconfig_url", pac);
|
|
|
|
var cb = new resolveCallback();
|
|
cb.nextFunction = isresolvable_callback;
|
|
pps.asyncResolve(channel, 0, cb);
|
|
}
|
|
|
|
function isresolvable_callback(pi) {
|
|
Assert.notEqual(pi, null);
|
|
Assert.equal(pi.type, "http");
|
|
Assert.equal(pi.port, 1234);
|
|
Assert.equal(pi.host, "127.0.0.1");
|
|
|
|
run_localhost_pac();
|
|
}
|
|
|
|
function run_localhost_pac() {
|
|
// test localhost in the pac file
|
|
|
|
var pac =
|
|
"data:text/plain," +
|
|
"function FindProxyForURL(url, host) {" +
|
|
' return "PROXY totallycrazy:1234";' +
|
|
"}";
|
|
|
|
// Use default filter list string for "no_proxies_on" ("localhost, 127.0.0.1")
|
|
prefs.clearUserPref("network.proxy.no_proxies_on");
|
|
var channel = NetUtil.newChannel({
|
|
uri: "http://localhost/",
|
|
loadUsingSystemPrincipal: true,
|
|
});
|
|
prefs.setIntPref("network.proxy.type", 2);
|
|
prefs.setCharPref("network.proxy.autoconfig_url", pac);
|
|
|
|
var cb = new resolveCallback();
|
|
cb.nextFunction = localhost_callback;
|
|
pps.asyncResolve(channel, 0, cb);
|
|
}
|
|
|
|
function localhost_callback(pi) {
|
|
Assert.equal(pi, null); // no proxy!
|
|
|
|
prefs.setIntPref("network.proxy.type", 0);
|
|
|
|
if (mozinfo.socketprocess_networking && again) {
|
|
info("run test again");
|
|
again = false;
|
|
cleanUp();
|
|
prefs.setBoolPref("network.proxy.parse_pac_on_socket_process", true);
|
|
run_filter_test();
|
|
} else {
|
|
cleanUp();
|
|
do_test_finished();
|
|
}
|
|
}
|
|
|
|
function cleanUp() {
|
|
prefs.clearUserPref("network.proxy.type");
|
|
prefs.clearUserPref("network.proxy.http");
|
|
prefs.clearUserPref("network.proxy.http_port");
|
|
prefs.clearUserPref("network.proxy.socks");
|
|
prefs.clearUserPref("network.proxy.socks_port");
|
|
prefs.clearUserPref("network.proxy.autoconfig_url");
|
|
prefs.clearUserPref("network.proxy.proxy_over_tls");
|
|
prefs.clearUserPref("network.proxy.no_proxies_on");
|
|
prefs.clearUserPref("network.proxy.parse_pac_on_socket_process");
|
|
}
|
|
|
|
function run_test() {
|
|
register_test_protocol_handler();
|
|
|
|
prefs.setBoolPref("network.proxy.parse_pac_on_socket_process", false);
|
|
// start of asynchronous test chain
|
|
run_filter_test();
|
|
do_test_pending();
|
|
}
|