@@ -27,39 +27,21 @@ function SSLObservatory() {
2727 this . prefs = Components . classes [ "@mozilla.org/preferences-service;1" ]
2828 . getService ( Components . interfaces . nsIPrefBranch ) ;
2929
30- dump ( "Dump: Loaded observatory component\n" ) ;
31- this . log ( DBUG , "Loaded observatory component!" ) ;
32-
3330 try {
3431 // Check for torbutton
3532 this . tor_logger = Components . classes [ "@torproject.org/torbutton-logger;1" ]
3633 . getService ( Components . interfaces . nsISupports ) . wrappedJSObject ;
37-
3834 this . torbutton_installed = true ;
39-
40- // If the user wants to use their Tor proxy, grab it automatically
41- if ( this . prefs . getBoolPref ( "extensions.https_everywhere._prefs.use_tor_proxy" ) ) {
42- // extract torbutton proxy settings
43- this . proxy_port = this . prefs . getIntPref ( "extensions.torbutton.https_port" ) ;
44- this . proxy_host = this . prefs . getCharPref ( "extensions.torbutton.https_proxy" ) ;
45- this . proxy_type = "http" ;
46-
47- if ( ! this . proxy_port ) {
48- this . proxy_host = this . prefs . getCharPref ( "extensions.torbutton.socks_host" ) ;
49- this . proxy_port = this . prefs . getIntPref ( "extensions.torbutton.socks_port" ) ;
50- this . proxy_type = "socks" ;
51- }
52- }
5335 } catch ( e ) {
54- dump ( "Torbutton not found\n" ) ;
5536 this . torbutton_installed = false ;
5637 }
5738
58- if ( this . prefs . getBoolPref ( "extensions.https_everywhere._observatory_prefs.use_custom_proxy" ) ) {
59- this . proxy_host = this . prefs . getCharPref ( "extensions.https_everywhere._observatory_prefs.proxy_host" ) ;
60- this . proxy_port = this . prefs . getIntPref ( "extensions.https_everywhere._observatory_prefs.proxy_port" ) ;
61- this . proxy_type = this . prefs . getCharPref ( "extensions.https_everywhere._observatory_prefs.proxy_type" ) ;
62- }
39+ // XXX: Clear this on cookies-cleared observer event?
40+ this . already_submitted = { } ;
41+
42+ // XXX: Read these two from a file? Or hardcode them?
43+ this . public_roots = { } ;
44+ this . popular_fps = { } ;
6345
6446 // The url to submit to
6547 this . submit_url = "https://observatory.eff.org/submit_cert" ;
@@ -79,6 +61,7 @@ function SSLObservatory() {
7961
8062 this . pps . registerFilter ( this , 0 ) ;
8163 this . wrappedJSObject = this ;
64+ this . log ( DBUG , "Loaded observatory component!" ) ;
8265}
8366
8467SSLObservatory . prototype = {
@@ -132,21 +115,31 @@ SSLObservatory.prototype = {
132115 && ! this . prefs . getBoolPref ( "extensions.torbutton.tor_enabled" ) ) {
133116 return ;
134117 }
118+ } else if ( ! this . prefs . getBoolPref ( "extensions.https_everywhere._observatory_prefs.use_custom_proxy" ) ) {
119+ this . log ( WARN , "No torbutton installed, but no custom proxies either. Not submitting certs" ) ;
120+ return ;
135121 }
136122
137123 if ( "http-on-examine-response" == topic ) {
138124 subject . QueryInterface ( Ci . nsIHttpChannel ) ;
139125 var certchain = this . getSSLCert ( subject ) ;
140- if ( certchain ) {
126+ if ( certchain ) {
141127 var chainEnum = certchain . getChain ( ) ;
142128 var chainArray = [ ] ;
129+ // XXX: We get chains for requests that have never completed if they
130+ // match cached certs!
131+ if ( chainEnum . length && subject . status != 0 ) {
132+ this . log ( NOTE , "Got a certificate chain for "
133+ + subject . URI . host + " despite error " + subject . status ) ;
134+ return ;
135+ }
143136 for ( var i = 0 ; i < chainEnum . length ; i ++ ) {
144137 var cert = chainEnum . queryElementAt ( i , Ci . nsIX509Cert ) ;
145138 chainArray . push ( cert ) ;
146139 }
147140
148141 if ( subject . URI . port == - 1 ) {
149- this . submitChain ( chainArray , subject . URI . host ) ;
142+ this . submitChain ( chainArray , new String ( subject . URI . host ) ) ;
150143 } else {
151144 this . submitChain ( chainArray , subject . URI . host + ":" + subject . URI . port ) ;
152145 }
@@ -161,14 +154,36 @@ SSLObservatory.prototype = {
161154 for ( var i = 0 ; i < certArray . length ; i ++ ) {
162155 var fp = ( certArray [ i ] . md5Fingerprint + certArray [ i ] . sha1Fingerprint ) . replace ( ":" , "" , "g" ) ;
163156 fps . push ( fp ) ;
157+ }
158+
159+ // XXX: is 0 the root? or is the last one the root?
160+ /*
161+ if (!(fps[0] in this.public_roots)) {
162+ this.log(INFO, "Got a private root cert. Ignoring");
163+ return;
164+ }
165+ */
166+
167+ if ( fps [ fps . length - 1 ] in this . already_submitted ) {
168+ this . log ( INFO , "Already submitted cert for " + domain + ". Ignoring" ) ;
169+ return ;
170+ }
164171
172+ if ( fps [ fps . length - 1 ] in this . popular_fps ) {
173+ this . log ( INFO , "Excluding popuar cert for " + domain ) ;
174+ return ;
175+ }
176+
177+ for ( var i = 0 ; i < certArray . length ; i ++ ) {
165178 var len = new Object ( ) ;
166179 var derData = certArray [ i ] . getRawDER ( len ) ;
167180 base64Certs . push ( this . base64_encode ( derData , false , false ) ) ;
168181 }
169182
170- // XXX: AS number??
171- // XXX: Server ip??
183+ // TODO: Refetch AS number every time one of these two changes:
184+ // https://developer.mozilla.org/en/online_and_offline_events
185+ // https://developer.mozilla.org/En/Monitoring_WiFi_access_points
186+ // TODO: Server ip??
172187 var reqParams = [ ] ;
173188 reqParams . push ( "domain=" + domain ) ;
174189 reqParams . push ( "server_ip=-1" ) ;
@@ -180,16 +195,18 @@ SSLObservatory.prototype = {
180195 var params = reqParams . join ( "&" ) + "&padding=0" ;
181196 var tot_len = 1024 ;
182197
183- this . log ( DBUG , "Params: " + params ) ;
198+ this . log ( INFO , "Submitting cert for " + domain ) ;
199+ this . log ( DBUG , "submit_cert params: " + params ) ;
184200
185- // Pad to exp scale
201+ // Pad to exp scale. This is done because the distribution of cert sizes
202+ // is almost certainly pareto, and definitely not uniform.
186203 for ( tot_len = 1024 ; tot_len < params . length ; tot_len *= 2 ) ;
187204
188205 while ( params . length != tot_len ) {
189206 params += "0" ;
190207 }
191208
192- this . log ( DBUG , "Padded params: " + params ) ;
209+ // this.log(DBUG, "Padded params: "+params);
193210
194211 var req = Cc [ "@mozilla.org/xmlextras/xmlhttprequest;1" ]
195212 . createInstance ( Ci . nsIXMLHttpRequest ) ;
@@ -201,35 +218,76 @@ SSLObservatory.prototype = {
201218 req . setRequestHeader ( "Content-length" , params . length ) ;
202219 req . setRequestHeader ( "Connection" , "close" ) ;
203220
221+ var that = this ; // We have neither SSLObservatory nor this in scope in the lambda
204222 req . onreadystatechange = function ( evt ) {
205223 if ( req . readyState == 4 ) {
206224 // XXX: Handle errors properly?
207- // XXX: We have neither SSLObservatory nor this in scope.
208225 if ( req . status == 200 ) {
209226 dump ( "Got ReadyStateChange == 4\n" ) ;
210- //SSLObservatory.log(INFO, "Successful cert submission");
227+ that . log ( INFO , "Successful cert submission" ) ;
228+ if ( ! that . prefs . getBoolPref ( "extensions.https_everywhere._observatory_prefs.cache_submitted" ) ) {
229+ if ( fps [ fps . length - 1 ] in that . already_submitted )
230+ delete that . already_submitted [ fps [ fps . length - 1 ] ] ;
231+ }
211232 } else {
212233 dump ( "Fail ReadyStateChange == 4\n" ) ;
213- //SSLObservatory.log(WARN, "Cert submission failure");
234+ that . log ( WARN , "Cert submission failure: " + req . status ) ;
235+ if ( fps [ fps . length - 1 ] in that . already_submitted )
236+ delete that . already_submitted [ fps [ fps . length - 1 ] ] ;
214237 }
215238 }
216239 } ;
217240
241+ // Cache this here to prevent multiple submissions for all the content elements.
242+ that . already_submitted [ fps [ fps . length - 1 ] ] = true ;
218243 req . send ( params ) ;
219244 } ,
220245
246+ getProxySettings : function ( ) {
247+ var proxy_settings = [ "direct" , "" , 0 ] ;
248+ if ( this . torbutton_installed &&
249+ this . prefs . getBoolPref ( "extensions.https_everywhere._observatory_prefs.use_tor_proxy" ) ) {
250+ // extract torbutton proxy settings
251+ proxy_settings [ 0 ] = "http" ;
252+ proxy_settings [ 1 ] = this . prefs . getCharPref ( "extensions.torbutton.https_proxy" ) ;
253+ proxy_settings [ 2 ] = this . prefs . getIntPref ( "extensions.torbutton.https_port" ) ;
254+
255+ if ( proxy_settings [ 2 ] == 0 ) {
256+ proxy_settings [ 0 ] = "socks" ;
257+ proxy_settings [ 1 ] = this . prefs . getCharPref ( "extensions.torbutton.socks_host" ) ;
258+ proxy_settings [ 2 ] = this . prefs . getIntPref ( "extensions.torbutton.socks_port" ) ;
259+ }
260+ } else if ( this . prefs . getBoolPref ( "extensions.https_everywhere._observatory_prefs.use_custom_proxy" ) ) {
261+ proxy_settings [ 0 ] = this . prefs . getCharPref ( "extensions.https_everywhere._observatory_prefs.proxy_type" ) ;
262+ proxy_settings [ 1 ] = this . prefs . getCharPref ( "extensions.https_everywhere._observatory_prefs.proxy_host" ) ;
263+ proxy_settings [ 2 ] = this . prefs . getIntPref ( "extensions.https_everywhere._observatory_prefs.proxy_port" ) ;
264+ } else {
265+ this . log ( WARN , "Proxy settings are strange: No Torbutton found, but no proxy specified. Using direct." ) ;
266+ }
267+ return proxy_settings ;
268+ } ,
269+
221270 applyFilter : function ( aProxyService , aURI , aProxy ) {
222271 if ( aURI . spec . search ( "^" + this . submit_url ) != - 1 &&
223272 aURI . path . search ( this . csrf_nonce + "$" ) != - 1 ) {
224273
225274 this . log ( INFO , "Got observatory url + nonce: " + aURI . spec ) ;
275+ var proxy_settings = null ;
276+ var proxy = null ;
226277
227278 // Send it through tor by creating an nsIProxy instance
228279 // for the torbutton proxy settings.
229- var proxy = this . pps . newProxyInfo ( this . proxy_type , this . proxy_host ,
230- this . proxy_port ,
280+ try {
281+ proxy_settings = this . getProxySettings ( ) ;
282+ proxy = this . pps . newProxyInfo ( proxy_settings [ 0 ] , proxy_settings [ 1 ] ,
283+ proxy_settings [ 2 ] ,
231284 Ci . nsIProxyInfo . TRANSPARENT_PROXY_RESOLVES_HOST ,
232285 0xFFFFFFFF , null ) ;
286+ } catch ( e ) {
287+ this . log ( WARN , "Error specifying proxy for observatory: " + e ) ;
288+ }
289+
290+ this . log ( INFO , "Specifying proxy: " + proxy ) ;
233291
234292 // TODO: Use new identity or socks u/p to ensure we get a unique
235293 // tor circuit for this request
0 commit comments