Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  SafeBrowsing.sys.mjs   Sprache: unbekannt

 
/* 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/. */

const PREF_DEBUG_ENABLED = "browser.safebrowsing.debug";
let loggingEnabled = false;

// Log only if browser.safebrowsing.debug is true
function log(...stuff) {
  if (!loggingEnabled) {
    return;
  }

  var d = new Date();
  let msg = "SafeBrowsing: " + d.toTimeString() + ": " + stuff.join(" ");
  dump(Services.urlFormatter.trimSensitiveURLs(msg) + "\n");
}

function getLists(prefName) {
  log("getLists: " + prefName);
  let pref = Services.prefs.getCharPref(prefName, "");

  // Splitting an empty string returns [''], we really want an empty array.
  if (!pref) {
    return [];
  }

  return pref.split(",").map(value => value.trim());
}

const FEATURES = [
  {
    name: "phishing",
    list: ["urlclassifier.phishTable"],
    enabled() {
      return Services.prefs.getBoolPref(
        "browser.safebrowsing.phishing.enabled"
      );
    },
    update() {
      return Services.prefs.getBoolPref(
        "browser.safebrowsing.features.phishing.update",
        this.enabled()
      );
    },
  },
  {
    name: "malware",
    list: ["urlclassifier.malwareTable"],
    enabled() {
      return Services.prefs.getBoolPref("browser.safebrowsing.malware.enabled");
    },
    update() {
      return Services.prefs.getBoolPref(
        "browser.safebrowsing.features.malware.update",
        this.enabled()
      );
    },
  },
  {
    name: "blockedURIs",
    list: ["urlclassifier.blockedTable"],
    enabled() {
      return Services.prefs.getBoolPref(
        "browser.safebrowsing.blockedURIs.enabled"
      );
    },
    update() {
      return Services.prefs.getBoolPref(
        "browser.safebrowsing.features.blockedURIs.update",
        this.enabled()
      );
    },
  },
  {
    name: "downloads",
    list: [
      "urlclassifier.downloadBlockTable",
      "urlclassifier.downloadAllowTable",
    ],
    enabled() {
      return (
        Services.prefs.getBoolPref("browser.safebrowsing.downloads.enabled") &&
        Services.prefs.getBoolPref("browser.safebrowsing.malware.enabled")
      );
    },
    update() {
      return Services.prefs.getBoolPref(
        "browser.safebrowsing.features.downloads.update",
        this.enabled()
      );
    },
  },
  {
    name: "trackingAnnotation",
    list: [
      "urlclassifier.trackingAnnotationTable",
      "urlclassifier.trackingAnnotationWhitelistTable",
    ],
    enabled() {
      return Services.prefs.getBoolPref(
        "privacy.trackingprotection.annotate_channels"
      );
    },
    update() {
      return Services.prefs.getBoolPref(
        "browser.safebrowsing.features.trackingAnnotation.update",
        this.enabled()
      );
    },
  },
  {
    name: "trackingProtection",
    list: [
      "urlclassifier.trackingTable",
      "urlclassifier.trackingWhitelistTable",
    ],
    enabled() {
      return (
        Services.prefs.getBoolPref("privacy.trackingprotection.enabled") ||
        Services.prefs.getBoolPref("privacy.trackingprotection.pbmode.enabled")
      );
    },
    update() {
      return Services.prefs.getBoolPref(
        "browser.safebrowsing.features.trackingProtection.update",
        this.enabled()
      );
    },
  },
  {
    name: "fingerprinting-annotation",
    list: [
      "urlclassifier.features.fingerprinting.annotate.blacklistTables",
      "urlclassifier.features.fingerprinting.annotate.whitelistTables",
    ],
    enabled() {
      // Annotation features are enabled by default.
      return true;
    },
    update() {
      return Services.prefs.getBoolPref(
        "browser.safebrowsing.features.fingerprinting.annotate.update",
        this.enabled()
      );
    },
  },
  {
    name: "fingerprinting-protection",
    list: [
      "urlclassifier.features.fingerprinting.blacklistTables",
      "urlclassifier.features.fingerprinting.whitelistTables",
    ],
    enabled() {
      return Services.prefs.getBoolPref(
        "privacy.trackingprotection.fingerprinting.enabled",
        false
      );
    },
    update() {
      return Services.prefs.getBoolPref(
        "browser.safebrowsing.features.fingerprinting.update",
        this.enabled()
      );
    },
  },
  {
    name: "cryptomining-annotation",
    list: [
      "urlclassifier.features.cryptomining.annotate.blacklistTables",
      "urlclassifier.features.cryptomining.annotate.whitelistTables",
    ],
    enabled() {
      // Annotation features are enabled by default.
      return true;
    },
    update() {
      return Services.prefs.getBoolPref(
        "browser.safebrowsing.features.cryptomining.annotate.update",
        this.enabled()
      );
    },
  },
  {
    name: "cryptomining-protection",
    list: [
      "urlclassifier.features.cryptomining.blacklistTables",
      "urlclassifier.features.cryptomining.whitelistTables",
    ],
    enabled() {
      return Services.prefs.getBoolPref(
        "privacy.trackingprotection.cryptomining.enabled",
        false
      );
    },
    update() {
      return Services.prefs.getBoolPref(
        "browser.safebrowsing.features.cryptomining.update",
        this.enabled()
      );
    },
  },
  {
    name: "socialtracking-annotation",
    list: [
      "urlclassifier.features.socialtracking.annotate.blacklistTables",
      "urlclassifier.features.socialtracking.annotate.whitelistTables",
    ],
    enabled() {
      // Annotation features are enabled by default.
      return true;
    },
    update() {
      return Services.prefs.getBoolPref(
        "browser.safebrowsing.features.socialtracking.annotate.update",
        this.enabled()
      );
    },
  },
  {
    name: "socialtracking-protection",
    list: [
      "urlclassifier.features.socialtracking.blacklistTables",
      "urlclassifier.features.socialtracking.whitelistTables",
    ],
    enabled() {
      return Services.prefs.getBoolPref(
        "privacy.trackingprotection.socialtracking.enabled",
        false
      );
    },
    update() {
      return Services.prefs.getBoolPref(
        "browser.safebrowsing.features.socialtracking.update",
        this.enabled()
      );
    },
  },
  {
    name: "emailtracking-protection",
    list: [
      "urlclassifier.features.emailtracking.blocklistTables",
      "urlclassifier.features.emailtracking.allowlistTables",
    ],
    enabled() {
      return (
        Services.prefs.getBoolPref(
          "privacy.trackingprotection.emailtracking.enabled",
          false
        ) ||
        Services.prefs.getBoolPref(
          "privacy.trackingprotection.emailtracking.pbmode.enabled",
          false
        )
      );
    },
    update() {
      return Services.prefs.getBoolPref(
        "browser.safebrowsing.features.emailtracking.update",
        this.enabled()
      );
    },
  },
  {
    name: "emailtracking-data-collection",
    list: [
      "urlclassifier.features.emailtracking.datacollection.blocklistTables",
      "urlclassifier.features.emailtracking.datacollection.allowlistTables",
    ],
    enabled() {
      // Data collection features are enabled by default.
      return true;
    },
    update() {
      return Services.prefs.getBoolPref(
        "browser.safebrowsing.features.emailtracking.datacollection.update",
        this.enabled()
      );
    },
  },
];

export var SafeBrowsing = {
  init() {
    if (this.initialized) {
      log("Already initialized");
      return;
    }

    Services.prefs.addObserver("browser.safebrowsing", this);
    Services.prefs.addObserver("privacy.trackingprotection", this);
    Services.prefs.addObserver("urlclassifier", this);

    this.readPrefs();

    this.controlUpdateChecking();
    this.initialized = true;

    log("init() finished");
  },

  registerTableWithURLs(listname) {
    let listManager = Cc[
      "@mozilla.org/url-classifier/listmanager;1"
    ].getService(Ci.nsIUrlListManager);

    let providerName = this.listToProvider[listname];
    let provider = this.providers[providerName];

    if (!providerName || !provider) {
      log("No provider info found for " + listname);
      log("Check browser.safebrowsing.provider.[google/mozilla].lists");
      return;
    }

    if (!provider.updateURL) {
      log("Invalid update url " + listname);
      return;
    }

    listManager.registerTable(
      listname,
      providerName,
      provider.updateURL,
      provider.gethashURL
    );
  },

  registerTables() {
    this.features.forEach(feature => {
      feature.list.forEach(table => {
        this.registerTableWithURLs(table);
      });
    });
  },

  unregisterTables(obsoleteLists) {
    let listManager = Cc[
      "@mozilla.org/url-classifier/listmanager;1"
    ].getService(Ci.nsIUrlListManager);

    obsoleteLists.forEach(list => {
      list.forEach(table => {
        listManager.unregisterTable(table);
      });
    });
  },

  initialized: false,

  features: [],

  updateURL: null,
  gethashURL: null,
  reportURL: null,

  getReportURL(kind, info) {
    let pref;
    switch (kind) {
      case "Phish":
        pref = "browser.safebrowsing.reportPhishURL";
        break;

      case "PhishMistake":
      case "MalwareMistake":
        pref =
          "browser.safebrowsing.provider." +
          info.provider +
          ".report" +
          kind +
          "URL";
        break;

      default:
        let err =
          "SafeBrowsing getReportURL() called with unknown kind: " + kind;
        console.error(err);
        throw err;
    }

    // The "Phish" reports are about submitting new phishing URLs to Google so
    // they don't have an associated list URL
    if (kind != "Phish" && (!info.list || !info.uri)) {
      return null;
    }

    let reportUrl = Services.urlFormatter.formatURLPref(pref);
    // formatURLPref might return "about:blank" if getting the pref fails
    if (reportUrl == "about:blank") {
      reportUrl = null;
    }

    if (reportUrl) {
      reportUrl += encodeURIComponent(info.uri);
    }
    return reportUrl;
  },

  observe(aSubject, aTopic, aData) {
    // skip nextupdatetime and lastupdatetime
    if (aData.includes("lastupdatetime") || aData.includes("nextupdatetime")) {
      return;
    }

    if (aData == PREF_DEBUG_ENABLED) {
      loggingEnabled = Services.prefs.getBoolPref(PREF_DEBUG_ENABLED);
      return;
    }

    this.readPrefs();
  },

  readPrefs() {
    loggingEnabled = Services.prefs.getBoolPref(PREF_DEBUG_ENABLED);
    log("reading prefs");

    let obsoleteLists = [];
    // Make a copy of the original lists before we re-read the prefs.
    if (this.initialized) {
      obsoleteLists = this.features.map(feature => {
        return feature.list;
      });
    }

    // Allow to disable all feature updates with a single preference for tests.
    let update = Services.prefs.getBoolPref(
      "browser.safebrowsing.update.enabled",
      true
    );

    this.features = [];
    for (let i = 0; i < FEATURES.length; ++i) {
      this.features[i] = {
        name: FEATURES[i].name,
        list: [],
        enabled: FEATURES[i].enabled(),
        update: FEATURES[i].update() && update,
      };

      FEATURES[i].list.forEach(pref => {
        this.features[i].list.push(...getLists(pref));
      });
    }

    for (let i = 0; i < obsoleteLists.length; ++i) {
      obsoleteLists[i] = obsoleteLists[i].filter(
        list => !this.features[i].list.includes(list)
      );
    }

    this.updateProviderURLs();
    this.registerTables();
    if (obsoleteLists) {
      this.unregisterTables(obsoleteLists);
    }

    // XXX The listManager backend gets confused if this is called before the
    // lists are registered. So only call it here when a pref changes, and not
    // when doing initialization. I expect to refactor this later, so pardon the hack.
    if (this.initialized) {
      this.controlUpdateChecking();
    }
  },

  updateProviderURLs() {
    try {
      var clientID = Services.prefs.getCharPref("browser.safebrowsing.id");
    } catch (e) {
      clientID = Services.appinfo.name;
    }

    log("initializing safe browsing URLs, client id", clientID);

    // Get the different providers
    let branch = Services.prefs.getBranch("browser.safebrowsing.provider.");
    let children = branch.getChildList("");
    this.providers = {};
    this.listToProvider = {};

    for (let child of children) {
      log("Child: " + child);
      let prefComponents = child.split(".");
      let providerName = prefComponents[0];
      this.providers[providerName] = {};
    }

    if (loggingEnabled) {
      let providerStr = "";
      Object.keys(this.providers).forEach(function (provider) {
        if (providerStr === "") {
          providerStr = provider;
        } else {
          providerStr += ", " + provider;
        }
      });
      log("Providers: " + providerStr);
    }

    Object.keys(this.providers).forEach(function (provider) {
      if (provider == "test") {
        return; // skip
      }
      let updateURL = Services.urlFormatter.formatURLPref(
        "browser.safebrowsing.provider." + provider + ".updateURL"
      );
      let gethashURL = Services.urlFormatter.formatURLPref(
        "browser.safebrowsing.provider." + provider + ".gethashURL"
      );
      updateURL = updateURL.replace("SAFEBROWSING_ID", clientID);
      gethashURL = gethashURL.replace("SAFEBROWSING_ID", clientID);

      // Disable updates and gethash if the Google API key is missing.
      let googleSafebrowsingKey = Services.urlFormatter
        .formatURL("%GOOGLE_SAFEBROWSING_API_KEY%")
        .trim();
      if (
        (provider == "google" || provider == "google4") &&
        (!googleSafebrowsingKey ||
          googleSafebrowsingKey == "no-google-safebrowsing-api-key")
      ) {
        log(
          "Missing Google SafeBrowsing API key, clearing updateURL and gethashURL."
        );
        updateURL = "";
        gethashURL = "";
      }

      log("Provider: " + provider + " updateURL=" + updateURL);
      log("Provider: " + provider + " gethashURL=" + gethashURL);

      // Urls used to update DB
      this.providers[provider].updateURL = updateURL;
      this.providers[provider].gethashURL = gethashURL;

      // Get lists this provider manages
      let lists = getLists(
        "browser.safebrowsing.provider." + provider + ".lists"
      );
      if (lists) {
        lists.forEach(function (list) {
          this.listToProvider[list] = provider;
        }, this);
      } else {
        log("Update URL given but no lists managed for provider: " + provider);
      }
    }, this);
  },

  controlUpdateChecking() {
    if (loggingEnabled) {
      this.features.forEach(feature => {
        log("feature " + feature.name + ":");
        log("  enabled:" + feature.enabled);
        log("  update:" + feature.update);
        log("  tables:" + feature.list);
      });
    }

    let listManager = Cc[
      "@mozilla.org/url-classifier/listmanager;1"
    ].getService(Ci.nsIUrlListManager);

    listManager.disableAllUpdates();

    this.features.forEach(feature => {
      if (feature.update) {
        feature.list.forEach(table => {
          listManager.enableUpdate(table);
        });
      }
    });

    listManager.maybeToggleUpdateChecking();
  },
};

[ Dauer der Verarbeitung: 0.28 Sekunden  (vorverarbeitet)  ]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge