diff --git a/worker.js b/worker.js index c47caad..3766d3c 100644 --- a/worker.js +++ b/worker.js @@ -26,39 +26,39 @@ async function process_request(details) { try { let hostname = (new URL(details.url)).hostname; let securityInfo = await browser.webRequest.getSecurityInfo(details.requestId, { certificateChain: true, rawDER: true }); - if (securityInfo.state !== "insecure") { - const fingerprint = securityInfo.certificates[0].fingerprint.sha256; - - let fpData = localStorage.getItem(fingerprint); - + if (securityInfo.certificates.length > 0) { const currentTime = Date.now(); - if (fpData) { - fpData = JSON.parse(fpData); - // If the last request was less than 10 minutes ago, don't spam the API - if (fpData.lastCheck && currentTime - fpData.lastCheck < 10 * 60 * 1000) { - return; - } - // If the last response was less than 12 hours ago, don't check again - if (fpData.lastResponse && currentTime - fpData.lastResponse < 12 * 60 * 60 * 1000) { - return; - } - } else { - fpData = {}; - } - - fpData.lastCheck = currentTime; - localStorage.setItem(fingerprint, JSON.stringify(fpData)); - - const tab = details.tabId; - if (!send_buffer[tab]) { - send_buffer[tab] = {}; - } - if (!send_buffer[tab][hostname]) { - send_buffer[tab][hostname] = {}; - } - securityInfo.certificates.forEach(cert => { - send_buffer[tab][hostname][cert.fingerprint.sha256] = cert.rawDER; + const fingerprint = cert.fingerprint.sha256; + + let fpData = localStorage.getItem(fingerprint); + + if (fpData) { + fpData = JSON.parse(fpData); + // If the last request was less than 10 minutes ago, don't spam the API + if (fpData.lastCheck && currentTime - fpData.lastCheck < 10 * 60 * 1000) { + return; + } + // If the last response was less than 12 hours ago, don't check again + if (fpData.lastResponse && currentTime - fpData.lastResponse < 12 * 60 * 60 * 1000) { + return; + } + } else { + fpData = {}; + } + + fpData.lastCheck = currentTime; + localStorage.setItem(fingerprint, JSON.stringify(fpData)); + + const tab = details.tabId; + if (!send_buffer[tab]) { + send_buffer[tab] = {}; + } + if (!send_buffer[tab][hostname]) { + send_buffer[tab][hostname] = {}; + } + + send_buffer[tab][hostname][fingerprint] = cert.rawDER; }); } } catch (error) { @@ -66,6 +66,20 @@ async function process_request(details) { } } +function generate_alerts(fingerprints) { + fingerprints.forEach(fingerprint => { + let fpData = localStorage.getItem(fingerprint); + fpData = JSON.parse(fpData); + if (fpData.alert === true) { + browser.notifications.create({ + "type": "basic", + "iconUrl": browser.runtime.getURL("icons/crowdtls-48.png"), + "title": "CrowdTLS Alert", + "message": fpData.alertMsg + }); + } + }); +} /** * Checks the fingerprint and sends a REST GET request to the API. @@ -95,12 +109,28 @@ async function do_checks(buffer) { const data = await response.json(); + if (data["anomalies"]) { + const currentTime = Date.now(); + Object.keys(data["anomalies"]).forEach(fingerprint => { + let fpData = localStorage.getItem(fingerprint); + fpData = JSON.parse(fpData); + fpData.lastCheck = currentTime; + fpData.lastResponse = currentTime; + fpData.alert = true; + fpData.alertTime = currentTime; + fpData.alertMsg = data["anomalies"][fingerprint]; + localStorage.setItem(fingerprint, JSON.stringify(fpData)); + }); + generate_alerts(Object.keys(data["anomalies"])); + } + + Object.keys(buffer).forEach(hostname => { if (!data[hostname]) { delete buffer[hostname]; } }); - send_certificate_chain(buffer); + await send_certificate_chain(buffer); } catch (error) { console.error(error); @@ -182,7 +212,7 @@ browser.webRequest.onHeadersReceived.addListener( // When a tab update happens (i.e., page load complete), send the buffered data browser.tabs.onUpdated.addListener(async (tabId, changeInfo, tab) => { - if (changeInfo.status === "complete" && send_buffer[tabId]) { + if ((changeInfo.status || tab.status) == 'complete' && send_buffer[tabId]) { await do_checks(send_buffer[tabId]); delete send_buffer[tabId]; }