diff --git a/src/js/content.js b/src/js/content.js index 6e80ae1..e69de29 100644 --- a/src/js/content.js +++ b/src/js/content.js @@ -1,71 +0,0 @@ -var myRootCerts=new Set(); - -function onHeadersReceived(details,securityInfo){ - if( - securityInfo - && securityInfo.certificates - && securityInfo.certificates.length - ) { - rootCert=securityInfo.certificates[securityInfo.certificates.length-1]; - console.log("Adding",rootCert); - myRootCerts.add(rootCert.fingerprint.sha256); - console.log("Added!",myRootCerts); - } else { - console.log("This page has a bad connection..."); - myRootCerts.add(null); - } -} - -function onCompleted(details){ - let browserActionSpec=new Object(); - - try { - console.log(myRootCerts); - if(myRootCerts.size!=1) throw myRootCerts; - - for(let rootCert of myRootCerts){ -// if(!rootCert.isBuiltInRoot) throw rootCert; - -// fp=rootCert.fingerprint.sha256; -// if(!fp) throw rootCert.fingerprint.sha256; - - rootHost=sha256fp_host[rootCert]; - if(!rootHost) throw fp; - - browserActionSpec.Icon={path:`images/root_icons/${rootHost}.ico`}; - browserActionSpec.BadgeText={text:""}; - browserActionSpec.Title={text:rootHost}; - } - } catch(e) { - //TODO: more edge cases here (self-signed, etc.) - if(myRootCerts.size==0) myRootCerts.add(null); - for(let rootCert of myRootCerts){ - console.warn('Unknown root CA',rootCert); - } - browserActionSpec.Icon={path:"images/Twemoji12_26a0.svg"}; - browserActionSpec.BadgeText={text:"!"}; - browserActionSpec.BadgeBackgroundColor={color:"red"}; - browserActionSpec.Title={text:JSON.stringify(e)}; - } - - console.log(browserActionSpec); - return browserActionSpec; -} - -browser.runtime.onMessage.addListener( - (message) => { - if('onHeadersReceived' in message) { - let details=message.onHeadersReceived.details; - let securityInfo=message.securityInfo; - return onHeadersReceived(details,securityInfo); - } if('onCompleted' in message) { - let details=message.onCompleted.details; - let browserActionSpec=onCompleted(details); - console.log("Returning:",browserActionSpec); - return browserActionSpec;//WHY ISN'T THIS SHOWING UP ON THE OTHER SIDE AAARGH - } else { - return false; - } - } -); - diff --git a/src/js/main.js b/src/js/main.js index 3a22de3..d7dca95 100644 --- a/src/js/main.js +++ b/src/js/main.js @@ -1,42 +1,81 @@ -browser.webRequest.onHeadersReceived.addListener( - async function onHeadersReceivedListener(details) { -// console.log('onHeadersReceived event triggered!',{details:details}); +const rootCertsByTab=new Object(); - let tabId=details.tabId; - let requestId=details.requestId; +function genBrowserActionSpec(rootCerts){ + let browserActionSpec=new Object(); + for(let rootCert of (rootCerts.size?rootCerts:[null])){ + try { + rootHost=sha256fp_host[rootCert]; + if(!rootHost) throw rootCert; - let securityInfo = await browser.webRequest.getSecurityInfo(details.requestId,{certificateChain:true}); -// console.log({requestId:requestId,securityInfo:securityInfo}); + browserActionSpec.Icon={path:`images/root_icons/${rootHost}.ico`}; + browserActionSpec.BadgeText={text:""}; + browserActionSpec.Title={title:rootHost}; + } catch(e) { + //TODO: more edge cases here (self-signed, etc.) + browserActionSpec.Icon={path:"images/Twemoji12_26a0.svg"}; + browserActionSpec.BadgeText={text:"!"}; + browserActionSpec.BadgeBackgroundColor={color:"red"}; + browserActionSpec.Title={title:JSON.stringify(e)}; + break; + } + } - browser.tabs.sendMessage(tabId,{onHeadersReceived:details,securityInfo:securityInfo}); + //console.log(browserActionSpec); + return browserActionSpec; +} - return {};//TODO: maybe remove this line +function updateTabBrowserAction(tabId){ + let browserActionSpec=genBrowserActionSpec(rootCertsByTab[tabId]); + for(let prop in browserActionSpec){ + let cmd={tabId:tabId}; + Object.assign(cmd,browserActionSpec[prop]); + browser.browserAction['set'+prop](cmd); + } +} +browser.webRequest.onBeforeRequest.addListener( + //a new frame enters the tab; clear or create its rootCert set + async function onBeforeMainFrameRequestListener(details){ + let tabId=details.tabId; + if(rootCertsByTab[tabId]===undefined) rootCertsByTab[tabId]=new Set(); + else rootCertsByTab[tabId].clear(); + console.log(rootCertsByTab); + //TODO: fix memory leak }, { - types:['main_frame'],//TODO remove this, I just put it in for debugging + types:['main_frame'], urls:[''] }, - ['blocking'] //this has to be blocking, or getSecurityInfo doesn't work + ['blocking'] ); -browser.webRequest.onCompleted.addListener( - async function browserActionImageUpdate(details) { - console.log("Beginning onCompleted...",{details:details}); - +browser.webRequest.onHeadersReceived.addListener( + //this is the only point we can getSecurityInfo. + //add it to rootCertsByTab + async function onHeadersReceivedListener(details) { let tabId=details.tabId; - let browserActionSpec=( - await browser.tabs.sendMessage(tabId,{onCompleted:details}) ); - console.log("Tab returned:",browserActionSpec);//WHY IS THIS UNDEFINED AAARGH + let requestId=details.requestId; - for(let prop in browserActionSpec){ - let cmd={tabId:tabId}; - Object.assign(cmd,browserActionSpec[prop]); - browser.browserAction['set'+prop](cmd); + let securityInfo = await browser.webRequest.getSecurityInfo(details.requestId,{certificateChain:true}); + console.log({tabId:tabId,requestId:requestId,securityInfo:securityInfo}); + + try { + if(!(securityInfo.certificates.length>0)) throw securityInfo; + let rootCert=securityInfo.certificates[securityInfo.certificates.length-1]; + rootCertsByTab[tabId].add(rootCert.fingerprint.sha256||null); + console.log(rootCertsByTab); + } catch(e) { + rootCertsByTab[tabId].add(null); } + + updateTabBrowserAction(tabId); + + return {};//TODO: maybe remove this line + }, { - types:['main_frame'], - urls: [""] - } + urls:[''] + }, + ['blocking'] //this has to be blocking, or getSecurityInfo doesn't work ); + diff --git a/src/js/util.js b/src/js/util.js index 5f7a4ce..0d5016f 100644 --- a/src/js/util.js +++ b/src/js/util.js @@ -14,17 +14,21 @@ const host_country = new Object(); JSON.parse(data).forEach(ca=>{ let sha256fp=ca["SHA-256 Fingerprint"].replaceAll(/(\w{2})(?=\w)/g,'$1:'); - let hostParts=(new URL(ca["Certification Practice Statement (CPS)"])).hostname.split('.') + let hostParts=(new URL(ca["Company Website"])).hostname.split('.') //www isn't a real subdomain if(hostParts[0]=='www') hostParts.splice(0,1); //neither is pki if(hostParts[0]=='pki') hostParts.splice(0,1); - //*.gov. is just *from* that country - if(hostParts[hostParts.length-2]=='gov' && hostParts[hostParts.length-1].length==2){ - hostParts.splice(0,[hostParts.length-1]); - host_country[sha256fp]=hostParts[0]; + //. is from that country + let reducedHostname; + if(hostParts[hostParts.length-1].length==2){ + //gov is also a non-semantic subdomain + if(hostParts[hostParts.length-2]=='gov') hostParts.splice(0,hostParts.length-1); + reducedHostname=hostParts.join('.'); + host_country[reducedHostname]=hostParts[hostParts.length-1].toUpperCase(); + } else { + reducedHostname=hostParts.join('.'); } - let reducedHostname=hostParts.join('.'); sha256fp_host[sha256fp]=reducedHostname; }); diff --git a/src/manifest.json b/src/manifest.json index ab8a86d..fcc3fbc 100644 --- a/src/manifest.json +++ b/src/manifest.json @@ -1,7 +1,7 @@ { "manifest_version": 2, "name": "cerdicator", - "version": "0.0.3", + "version": "0.0.4", "description": "nice",