Bug 1592620 - Add whitelist for mDNS hostname obfuscation; r=bwc

This adds a whitelist of domains for which mDNS hostname obfuscation is
disabled. The implementation is an updated version of the old screensharing
whitelist code.

Differential Revision: https://phabricator.services.mozilla.com/D52012

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Dan Minor 2019-11-07 20:59:29 +00:00
parent e298526ed5
commit 4438d45346
3 changed files with 147 additions and 0 deletions

View File

@ -36,6 +36,7 @@ scheme=http
[test_dataChannel_basicAudioVideoNoBundle.html]
[test_dataChannel_basicAudioVideoCombined.html]
[test_dataChannel_basicDataOnly.html]
[test_dataChannel_hostnameObfuscationWhitelist.html]
scheme=http
[test_dataChannel_basicVideo.html]
[test_dataChannel_bug1013809.html]

View File

@ -0,0 +1,61 @@
<!DOCTYPE HTML>
<html>
<head>
<script type="application/javascript" src="pc.js"></script>
</head>
<body>
<pre id="test">
<script type="application/javascript">
createHTML({
bug: "1592620",
title: "Whitelist to disable hostname obfuscation"
});
async function testWhitelist(options, whitelistEntry, shouldBeObfuscated) {
let test = new PeerConnectionTest(options);
addInitialDataChannel(test.chain);
if (whitelistEntry !== null) {
await SpecialPowers.pushPrefEnv({
set: [
["media.peerconnection.ice.obfuscate_host_addresses.whitelist",
whitelistEntry]
]
});
}
test.chain.insertAfter('PC_LOCAL_WAIT_FOR_ICE_CONNECTED', [
async function CHECK_LOCAL_CANDIDATES() {
const stats = await test.pcLocal.getStats();
stats.forEach(s => {
if (s.type === 'local-candidate') {
if (shouldBeObfuscated) {
ok(s.address.includes(".local"), "address should be obfuscated");
} else {
ok(!s.address.includes(".local"), "address should not be obfuscated");
}
}
});
}]);
// This inlines test.run(), to allow for multiple tests to run.
test.updateChainSteps();
await test.chain.execute();
await test.close();
}
runNetworkTest(async (options) => {
await testWhitelist(options, null, true);
await testWhitelist(options, "", true);
await testWhitelist(options, "example.com", true);
await testWhitelist(options, "mochi.test", false);
await testWhitelist(options, "example.com,mochi.test", false);
await testWhitelist(options, "*.test", false);
networkTestFinished();
});
</script>
</pre>
</body>
</html>

View File

@ -17,6 +17,7 @@
#include "nsIURI.h"
#include "nsIScriptSecurityManager.h"
#include "nsICancelable.h"
#include "nsIIDNService.h"
#include "nsILoadInfo.h"
#include "nsIContentPolicy.h"
#include "nsIProxyInfo.h"
@ -312,6 +313,88 @@ bool PeerConnectionMedia::GetPrefDefaultAddressOnly() const {
return default_address_only;
}
static bool HostInDomain(const nsCString& aHost, const nsCString& aPattern) {
int32_t patternOffset = 0;
int32_t hostOffset = 0;
// Act on '*.' wildcard in the left-most position in a domain pattern.
if (aPattern.Length() > 2 && aPattern[0] == '*' && aPattern[1] == '.') {
patternOffset = 2;
// Ignore the lowest level sub-domain for the hostname.
hostOffset = aHost.FindChar('.') + 1;
if (hostOffset <= 1) {
// Reject a match between a wildcard and a TLD or '.foo' form.
return false;
}
}
nsDependentCString hostRoot(aHost, hostOffset);
return hostRoot.EqualsIgnoreCase(aPattern.BeginReading() + patternOffset);
}
static bool HostInObfuscationWhitelist(nsIURI* docURI) {
if (!docURI) {
return false;
}
nsCString hostName;
docURI->GetAsciiHost(hostName); // normalize UTF8 to ASCII equivalent
nsCString domainWhiteList;
nsresult nr = Preferences::GetCString(
"media.peerconnection.ice.obfuscate_host_addresses.whitelist",
domainWhiteList);
if (NS_FAILED(nr)) {
return false;
}
domainWhiteList.StripWhitespace();
if (domainWhiteList.IsEmpty() || hostName.IsEmpty()) {
return false;
}
// Get UTF8 to ASCII domain name normalization service
nsresult rv;
nsCOMPtr<nsIIDNService> idnService =
do_GetService("@mozilla.org/network/idn-service;1", &rv);
if (NS_WARN_IF(NS_FAILED(rv))) {
return false;
}
uint32_t begin = 0;
uint32_t end = 0;
nsCString domainName;
/*
Test each domain name in the comma separated list
after converting from UTF8 to ASCII. Each domain
must match exactly or have a single leading '*.' wildcard
*/
do {
end = domainWhiteList.FindChar(',', begin);
if (end == (uint32_t)-1) {
// Last or only domain name in the comma separated list
end = domainWhiteList.Length();
}
rv = idnService->ConvertUTF8toACE(
Substring(domainWhiteList, begin, end - begin), domainName);
if (NS_SUCCEEDED(rv)) {
if (HostInDomain(hostName, domainName)) {
return true;
}
} else {
NS_WARNING("Failed to convert UTF-8 host to ASCII");
}
begin = end + 1;
} while (end < domainWhiteList.Length());
return false;
}
bool PeerConnectionMedia::GetPrefObfuscateHostAddresses() const {
ASSERT_ON_THREAD(mMainThread); // will crash on STS thread
@ -321,6 +404,8 @@ bool PeerConnectionMedia::GetPrefObfuscateHostAddresses() const {
"media.peerconnection.ice.obfuscate_host_addresses", false);
obfuscate_host_addresses &=
!MediaManager::Get()->IsActivelyCapturingOrHasAPermission(winId);
obfuscate_host_addresses &=
!HostInObfuscationWhitelist(mParent->GetWindow()->GetDocBaseURI());
obfuscate_host_addresses &= XRE_IsContentProcess();
return obfuscate_host_addresses;