@@ -23,6 +23,10 @@ ASN_PRIVATE = -1; // Do not record the ASN this cert was seen on
2323ASN_IMPLICIT = - 2 ; // ASN can be learned from connecting IP
2424ASN_UNKNOWABLE = - 3 ; // Cert was seen in the absence of [trustworthy] Internet access
2525
26+ HASHLENGTH = 64 ; // hex(sha1 + md5)
27+ MIN_WHITELIST = 1000 ; // do not tolerate whitelists outside these bounds
28+ MAX_WHITELIST = 10000 ;
29+
2630// XXX: We should make the _observatory tree relative.
2731LLVAR = "extensions.https_everywhere.LogLevel" ;
2832
@@ -130,6 +134,8 @@ function SSLObservatory() {
130134
131135 this . testProxySettings ( ) ;
132136
137+ this . updateCertWhitelist ( ) ;
138+
133139 this . log ( DBUG , "Loaded observatory component!" ) ;
134140}
135141
@@ -445,6 +451,67 @@ SSLObservatory.prototype = {
445451 return this . prefs . getBoolPref ( "extensions.https_everywhere._observatory." + prefstring ) ;
446452 } ,
447453
454+ loadCertWhitelist : function ( ) {
455+ var loc = "chrome://https-everywhere/content/code/X509ChainWhitelist.json" ;
456+ var file =
457+ CC [ "@mozilla.org/file/local;1" ]
458+ . createInstance ( CI . nsILocalFile ) ;
459+ file . initWithPath ( this . HTTPSEverywhere . rw . chromeToPath ( loc ) ) ;
460+ var data = this . HTTPSEverywhere . rw . read ( file ) ;
461+ this . whitelist = JSON . parse ( data ) ;
462+ this . log ( DBUG , "yay\n" + data ) ;
463+ } ,
464+
465+ saveCertWhitelist : function ( ) {
466+ var loc = "chrome://https-everywhere/content/code/X509ChainWhitelist.json" ;
467+ var file =
468+ CC [ "@mozilla.org/file/local;1" ]
469+ . createInstance ( CI . nsILocalFile ) ;
470+ file . initWithPath ( this . HTTPSEverywhere . rw . chromeToPath ( loc ) ) ;
471+ var data = this . HTTPSEverywhere . rw . write ( file , JSON . stringify ( this . whitelist ) ) ;
472+ } ,
473+
474+
475+ updateCertWhitelist : function ( ) {
476+ var req = Cc [ "@mozilla.org/xmlextras/xmlhttprequest;1" ]
477+ . createInstance ( Ci . nsIXMLHttpRequest ) ;
478+
479+ req . open ( "GET" , "https://s.eff.org/files/X509ChainWhitelist.json" , true ) ;
480+ req . responseType = "json" ;
481+
482+ var that = this ;
483+ req . onreadystatechange = function ( ) {
484+ if ( req . status == 200 ) {
485+ if ( typeof req . response != "object" ) {
486+ that . log ( 5 , "INSUFFICIENT WHITELIST OBJECTIVITY" ) ;
487+ return false ;
488+ }
489+ var whitelist = req . response ;
490+ var c = 0 ;
491+ for ( var hash in whitelist ) {
492+ c ++ ;
493+ if ( typeof hash != "string" || hash . length != 64 ) {
494+ that . log ( 5 , "UNACCEPTABLE WHITELIST HASH " + hash ) ;
495+ return false ;
496+ }
497+ }
498+ if ( c < MIN_WHITELIST || c > MAX_WHITELIST ) {
499+ that . log ( 5 , "Invalid chain whitelist of size " + c ) ;
500+ return false ;
501+ }
502+ that . log ( 4 , "Replacing chain whitelist..." ) ;
503+ that . whitelist = whitelist ;
504+ that . log ( 5 , "Got valid whitelist..." + JSON . stringify ( whitelist ) ) ;
505+ that . saveCertWhitelist ( ) ;
506+ } else {
507+ that . log ( 4 , "Unexpected response status " + req . status + " fetching chain whitelist" ) ;
508+ return false ;
509+ }
510+ }
511+ req . send ( ) ;
512+
513+ } ,
514+
448515 isChainWhitelisted : function ( chainhash ) {
449516 if ( X509ChainWhitelist == null ) {
450517 this . log ( WARN , "Could not find whitelist of popular certificate chains, so ignoring whitelist" ) ;
0 commit comments