diff --git a/root-cert-stats/README.md b/root-cert-stats/README.md new file mode 100644 index 0000000..f2b3d32 --- /dev/null +++ b/root-cert-stats/README.md @@ -0,0 +1,15 @@ +# root-cert-stats + +## What it does ## + +The extension includes: + +* a background page which collects stats about the trusted root certs used when +browsing the web. It records the subject name of each root cert, and how many +times that particular root cert was used to establish a TLS connection. + +* a browser action with a popup. The popup displays the collected stats. + +## What it shows ## + +* how to use the webRequest.getSecurityInfo() API. diff --git a/root-cert-stats/background.js b/root-cert-stats/background.js new file mode 100644 index 0000000..59c70f3 --- /dev/null +++ b/root-cert-stats/background.js @@ -0,0 +1,38 @@ +"use strict"; + +var rootCertStats = {}; + +/* +On an onHeadersReceived event, if there was a successful TLS connection +established, fetch the root cert and look at its subject. + +If we haven't seen this subject before, add it. If we have, increment its stats. +*/ +async function logRootCert(details) { + try { + let securityInfo = await browser.webRequest.getSecurityInfo( + details.requestId, + {"certificateChain": true} + ); + if ((securityInfo.state == "secure" || securityInfo.state == "weak") && + !securityInfo.isUntrusted) { + let rootName = securityInfo.certificates[securityInfo.certificates.length - 1].subject; + if (rootCertStats[rootName] === undefined) { + rootCertStats[rootName] = 1; + } else { + rootCertStats[rootName] = rootCertStats[rootName] + 1; + } + } + } + catch(error) { + console.error(error); + } +} + +/* +Listen for all onHeadersReceived events. +*/ +browser.webRequest.onHeadersReceived.addListener(logRootCert, + {urls: [""]}, + ["blocking"] +); diff --git a/root-cert-stats/icons/LICENSE b/root-cert-stats/icons/LICENSE new file mode 100644 index 0000000..e878a43 --- /dev/null +++ b/root-cert-stats/icons/LICENSE @@ -0,0 +1 @@ +The icon "icon-32.png" is taken from the IconBeast Lite iconset, and used under the terms of its license (http://www.iconbeast.com/faq/), with a link back to the website: http://www.iconbeast.com/free/. diff --git a/root-cert-stats/icons/icon-32.png b/root-cert-stats/icons/icon-32.png new file mode 100644 index 0000000..b77538f Binary files /dev/null and b/root-cert-stats/icons/icon-32.png differ diff --git a/root-cert-stats/manifest.json b/root-cert-stats/manifest.json new file mode 100644 index 0000000..c82da2f --- /dev/null +++ b/root-cert-stats/manifest.json @@ -0,0 +1,25 @@ +{ + "manifest_version": 2, + "name": "Root Certificate Stats", + "description": "Track and display which CA root certificates are used and how often.", + "version": "0.1.0", + "browser_action": { + "default_icon": { + "32": "icons/icon-32.png" + }, + "default_title": "Root Certificate Stats", + "default_popup": "popup.html" + }, + "permissions": ["webRequest", "webRequestBlocking", ""], + "background": { + "scripts": [ "background.js" ] + }, + "icons": { + "32": "icons/icon-32.png" + }, + "applications": { + "gecko": { + "strict_min_version": "62.0b5" + } + } +} diff --git a/root-cert-stats/popup.css b/root-cert-stats/popup.css new file mode 100644 index 0000000..e590d0c --- /dev/null +++ b/root-cert-stats/popup.css @@ -0,0 +1,13 @@ +body { + font: 1rem/2 sans-serif; +} + +table, +td { + border: 1px solid #333; + padding: .3rem; +} + +.hidden { + display: none; +} diff --git a/root-cert-stats/popup.html b/root-cert-stats/popup.html new file mode 100644 index 0000000..6a705fc --- /dev/null +++ b/root-cert-stats/popup.html @@ -0,0 +1,21 @@ + + + + + + + Root cert stats + + + +
No data to display yet
+ + + + + + + + + + diff --git a/root-cert-stats/popup.js b/root-cert-stats/popup.js new file mode 100644 index 0000000..a7a582f --- /dev/null +++ b/root-cert-stats/popup.js @@ -0,0 +1,33 @@ +"use strict"; + +/* +Get the background page to access the rootCertStats object +*/ +const backgroundPage = browser.extension.getBackgroundPage(); + +let entries = Object.keys(backgroundPage.rootCertStats); + +/* +If there are any stats, show the table, and append one row for each entry. +Each row contains the name of the CA and the number of times it has been +used as a trust root. +*/ +if (entries.length > 0) { + + let noData = document.querySelector(".no-data"); + noData.classList.add("hidden"); + let entryTable = document.querySelector(".root-cert-table"); + entryTable.classList.remove("hidden"); + + for (let entry of entries) { + let entryTR = document.createElement("tr"); + let entryName = document.createElement("td"); + let entryValue = document.createElement("td"); + entryName.textContent = entry; + entryValue.textContent = backgroundPage.rootCertStats[entry]; + + entryTR.appendChild(entryName); + entryTR.appendChild(entryValue); + entryTable.appendChild(entryTR); + } +}