summaryrefslogtreecommitdiff
path: root/data/extensions/jsr@javascriptrestrictor/http_shield_firefox.js
diff options
context:
space:
mode:
Diffstat (limited to 'data/extensions/jsr@javascriptrestrictor/http_shield_firefox.js')
-rw-r--r--data/extensions/jsr@javascriptrestrictor/http_shield_firefox.js197
1 files changed, 197 insertions, 0 deletions
diff --git a/data/extensions/jsr@javascriptrestrictor/http_shield_firefox.js b/data/extensions/jsr@javascriptrestrictor/http_shield_firefox.js
new file mode 100644
index 0000000..56e5459
--- /dev/null
+++ b/data/extensions/jsr@javascriptrestrictor/http_shield_firefox.js
@@ -0,0 +1,197 @@
+/** \file
+ * \brief This file contains Firefox-specific functions for Network Boundary Shield.
+ *
+ * \author Copyright (C) 2020 Pavel Pohner
+ * \author Copyright (C) 2020-2021 Martin Bednář
+ *
+ * \license SPDX-License-Identifier: GPL-3.0-or-later
+ */
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <https://www.gnu.org/licenses/>.
+//
+
+/** \file
+ *
+ * \brief This file contains Firefox specific functions for Network Boundary Shield.
+ *
+ * \ingroup NBS
+ *
+ * This file contains webRequest API listeners. These listeners handle HTTP requests in the "before send headers" phase
+ * and handle messages (on message event).
+ *
+ * NBS for Firefox uses the DNS web extension API to resolve domain names. As the domain names are
+ * cached and needs to be resolved without NBS, the performance impact should be negligible.
+ */
+
+/**
+ * The event listener, hooked up to webRequest onBeforeSendHeaders event.
+ * Receives detail of HTTP request in requestDetail.
+ * Catches the request, analyzes its origin and target URLs and blocks it/permits it based
+ * on their IP adresses. Requests coming from public IP ranges targeting the private IPs are
+ * blocked by default. Others are permitted by default.
+ *
+ * \param requestDetail Details of HTTP request.
+ */
+async function beforeSendHeadersListener(requestDetail)
+{
+ //If either of information is undefined, permit it
+ //originUrl happens to be undefined for the first request of the page loading the document itself
+ if (requestDetail.originUrl === undefined || requestDetail.url === undefined || requestDetail.originUrl === "null" || requestDetail.url === "null")
+ {
+ return {cancel:false};
+ }
+ var sourceDomain = getEffectiveDomain(requestDetail.originUrl);
+ var fullSourceDomain = new URL(requestDetail.originUrl).hostname;
+
+ var targetDomain = getEffectiveDomain(requestDetail.url);
+ var fullTargetDomain = new URL(requestDetail.url).hostname;
+
+ var targetIP;
+ var sourceIP;
+ var isSourcePrivate = false;
+ var isDestinationPrivate = false;
+ var destinationResolution = "";
+ var sourceResolution = "";
+ var blockNotifications = false;
+
+ //Host found among user's trusted hosts, allow it right away
+ if (isNbsWhitelisted(sourceDomain))
+ {
+ return {cancel:false};
+ }
+
+ //Checking type of SOURCE URL
+ if (isIPV4(sourceDomain)) //SOURCE is IPV4 adddr
+ {
+ //Checking privacy of IPv4
+ if (isIPV4Private(sourceDomain))
+ {
+ //Source is IPv4 private
+ isSourcePrivate = true;
+ }
+ }
+ else if(isIPV6(sourceDomain)) //SOURCE is IPV6
+ {
+ //Checking privacy of IPv6
+ if (isIPV6Private(sourceDomain))
+ {
+ //Source is IPv6 private
+ isSourcePrivate = true;
+ }
+ }
+ else //SOURCE is hostname
+ {
+ //Resoluting DNS query for source domain
+ sourceResolution = browser.dns.resolve(fullSourceDomain).then((val) =>
+ {
+ //Assigning source IPs
+ sourceIP = val;
+ //More IPs could have been found, for each of them
+ for (let ip of sourceIP.addresses)
+ {
+ //Check whether it's IPv4
+ if (isIPV4(ip))
+ {
+ if (isIPV4Private(ip))
+ {
+ //Source is IPv4 private
+ isSourcePrivate = true;
+ }
+ }
+ else if (isIPV6(ip))
+ {
+ if (isIPV6Private(ip))
+ {
+ //Source is IPv6 private
+ isSourcePrivate = true;
+ }
+ }
+ }
+ });
+ }
+
+ //Analyzing targetDomain
+ //Check IPv4/IPv6 and privacy
+ if (isIPV4(targetDomain))
+ {
+ if (isIPV4Private(targetDomain))
+ {
+ isDestinationPrivate = true;
+ if (targetDomain === "0.0.0.0") {
+ blockNotifications = true;
+ }
+ }
+ }
+ else if(isIPV6(targetDomain))
+ {
+ if (isIPV6Private(targetDomain))
+ {
+ isDestinationPrivate = true;
+ if (ip === "[::]") {
+ blockNotifications = true;
+ }
+ }
+ }
+ else //Target is hostname
+ {
+ //Resoluting DNS query for destination domain
+ destinationResolution = browser.dns.resolve(fullTargetDomain).then((val) =>
+ {
+ //Assigning source IPs
+ targetIP = val;
+ //More IPs could have been found, for each of them
+ for (let ip of targetIP.addresses)
+ {
+ //Check whether it's IPv4
+ if (isIPV4(ip))
+ {
+ if (isIPV4Private(ip))
+ {
+ //Destination is IPv4 private
+ isDestinationPrivate = true;
+ if (ip === "0.0.0.0") {
+ blockNotifications = true;
+ }
+ }
+ }
+ else if (isIPV6(ip))
+ {
+ if (isIPV6Private(ip))
+ {
+ //Destination is IPv6 private
+ isDestinationPrivate = true;
+ if (ip === "[::]") {
+ blockNotifications = true;
+ }
+ }
+ }
+ }
+ });
+ }
+ //Wait till all DNS resolutions are done, because its neccessary for upcoming actions
+ await Promise.all([sourceResolution, destinationResolution]);
+
+ //Blocking direction Public -> Private
+ if (!isSourcePrivate && isDestinationPrivate)
+ {
+ if (!blockNotifications) {
+ notifyBlockedRequest(sourceDomain, targetDomain, requestDetail.tabId);
+ }
+ return {cancel: nbsSettings.blocking ? true : false}
+ }
+ else //Permitting others
+ {
+ return {cancel: false};
+ }
+}