From 4a434a6bc5c75588ce5a283382c4afee163a3a55 Mon Sep 17 00:00:00 2001 From: Nicholas Tay Date: Mon, 17 Apr 2023 19:11:24 +1000 Subject: Initial certose --- .gitignore | 4 +++ background.js | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ icons/def.png | Bin 0 -> 914 bytes icons/nope.png | Bin 0 -> 1046 bytes icons/ok.png | Bin 0 -> 992 bytes manifest.json | 31 ++++++++++++++++++++++ updates.json | 13 +++++++++ 7 files changed, 129 insertions(+) create mode 100644 .gitignore create mode 100644 background.js create mode 100644 icons/def.png create mode 100644 icons/nope.png create mode 100644 icons/ok.png create mode 100644 manifest.json create mode 100644 updates.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..41046bf --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +.DS_Store +*.swp +*.zip +*.xpi diff --git a/background.js b/background.js new file mode 100644 index 0000000..835ee51 --- /dev/null +++ b/background.js @@ -0,0 +1,81 @@ +// Based on https://github.com/mdn/webextensions-examples/blob/main/root-cert-stats/background.js + +// On header receive, inspect cert and update app icon as required +async function onHeaderReceive(details) { + if (details.tabId < 0) // tabId < 0 means non-user tab + return; + + try { + await certInspectUpdate(details.requestId, details.tabId); + } catch(error) { + console.error(error); + } +} + +function daysBetween(a, b) { + return Math.ceil((b - a) / (24 * 60 * 60 * 1000)); +} + +async function certInspectUpdate(requestId, tabId) { + let securityInfo = await browser.webRequest.getSecurityInfo(requestId, {}); + + // Not HTTPS + if (securityInfo.state !== "secure") + return; + + // Grab cert itself + let cert = securityInfo.certificates[0]; + + // Check expiry against 30 days + let in30d = new Date(); + in30d.setDate(in30d.getDate() + 30); + let expiry = new Date(cert.validity.end); + + // HACK: Schedule for this to run after a little later for 'blocking' element + // This is so that main_frame doesn't clear tabId-specific things again + setTimeout(() => { + let bad = expiry <= in30d; + setIcon(bad ? "nope" : "ok", tabId); + + let days = daysBetween(new Date(), expiry); + let daysShort = days + "d"; + if (days > 90) + daysShort = "3m+"; + else if (days > 180) + daysShort = "6m+"; + else if (days > 365) + daysShort = "1y+"; + + // Set expiry days as text + browser.browserAction.setBadgeText({ + text: daysShort, + tabId: tabId + }); + browser.browserAction.setTitle({ + title: "certose - " + cert.issuer + " - " + days + "d to validity end", + tabId: tabId + }); + if (!bad) + browser.browserAction.setBadgeBackgroundColor({ color: "blue" }); + }, 100); +} + +function setIcon(icon, tabId) { + browser.browserAction.setIcon({ + path: "icons/" + icon + ".png", + tabId: tabId + }); +} + +// Listen for all header receive events, which contain the cert details we want +// Firefox only supports onHeadersReceived at the moment, hence the hack above +browser.webRequest.onHeadersReceived.addListener( + onHeaderReceive, + { + urls: [""], + types: ["main_frame"] // Only for the top level website + }, + [ + "blocking" + ] +); diff --git a/icons/def.png b/icons/def.png new file mode 100644 index 0000000..b0ca670 Binary files /dev/null and b/icons/def.png differ diff --git a/icons/nope.png b/icons/nope.png new file mode 100644 index 0000000..8d2d5bd Binary files /dev/null and b/icons/nope.png differ diff --git a/icons/ok.png b/icons/ok.png new file mode 100644 index 0000000..0bdedb7 Binary files /dev/null and b/icons/ok.png differ diff --git a/manifest.json b/manifest.json new file mode 100644 index 0000000..08eeaa5 --- /dev/null +++ b/manifest.json @@ -0,0 +1,31 @@ +{ + "manifest_version": 2, + "name": "certose", + "description": "Cert-expiry-watching, just like people-watching.", + "author": "Nicholas Tay ", + "version": "0.1.0", + "permissions": [ "webRequest", "webRequestBlocking", "", "storage" ], + "background": { + "scripts": [ "background.js" ] + }, + "icons": { + "32": "icons/def.png" + }, + "browser_action": { + "default_icon": { + "32": "icons/def.png" + } + }, + "browser_specific_settings": { + "gecko": { + "strict_min_version": "62.0", + "id": "certose@nick.windblume.net", + "update_url": "https://git.windblume.net/pub/nick/certose/plain/updates.json" + } + }, + "options_ui": { + "page": "options.html", + "open_in_tab": true, + "browser_style": false + } +} diff --git a/updates.json b/updates.json new file mode 100644 index 0000000..640bde2 --- /dev/null +++ b/updates.json @@ -0,0 +1,13 @@ +{ + "addons": { + "certose@nick.windblume.net": { + "updates": [ + { + "version": "0.1.0", + "update_link": "https://users.windblume.net/~nick/upload/certose_0.1.0.xpi" + } + ] + } + } +} + -- cgit