|
| 1 | +const Ci = Components.interfaces; |
| 2 | +const Cc = Components.classes; |
| 3 | +const Cr = Components.results; |
| 4 | + |
| 5 | +Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); |
| 6 | +const OS = Cc['@mozilla.org/observer-service;1'].getService(CI.nsIObserverService); |
| 7 | + |
| 8 | +const SERVICE_CTRID = "@eff.org/ssl-observatory;1"; |
| 9 | +const SERVICE_ID=Components.ID("{0f9ab521-986d-4ad8-9c1f-6934e195c15c}"); |
| 10 | +const SERVICE_NAME = "Anonymously Submits strange SSL certificates to EFF."; |
| 11 | + |
| 12 | +function SSLObservatory() { |
| 13 | + // XXX: Check prefs and save to boolean values |
| 14 | + // 1. use_tor |
| 15 | + // 2. use_nontor |
| 16 | + // 3. submit_private_certs |
| 17 | + |
| 18 | + try { |
| 19 | + // Check for torbutton |
| 20 | + this.logger = Components.classes["@torproject.org/torbutton-logger;1"] |
| 21 | + .getService(Components.interfaces.nsISupports).wrappedJSObject; |
| 22 | + this.torbutton_installed = true; |
| 23 | + // XXX: We probably want to run the full test of tor functionality here |
| 24 | + // but that involves a https request to check.torproject.org, so we shouldn't |
| 25 | + // do it every time... Or maybe we should? |
| 26 | + } catch(e) { |
| 27 | + dump("Torbutton not found\n"); |
| 28 | + this.torbutton_installed = false; |
| 29 | + } |
| 30 | + |
| 31 | + // Generate nonce for request |
| 32 | + this.csrf_nonce = "#"+Math.random().toString()+Math.random().toString(); |
| 33 | + |
| 34 | + // Register observer |
| 35 | + OS.addObserver(this, "http-on-examine-response", false); |
| 36 | + |
| 37 | + // Register protocolproxyfilter |
| 38 | + var pps = Components.classes["@mozilla.org/network/protocol-proxy-service;1"] |
| 39 | + .getService(Components.interfaces.nsIProtocolProxyService); |
| 40 | + |
| 41 | + pps.registerFilter(this, 0); |
| 42 | + this.wrappedJSObject = this; |
| 43 | +} |
| 44 | + |
| 45 | +SSLObservatory.prototype = { |
| 46 | + // QueryInterface implementation, e.g. using the generateQI helper |
| 47 | + QueryInterface: XPCOMUtils.generateQI( |
| 48 | + [ Components.interfaces.nsIObserver, |
| 49 | + Components.interfaces.nsIProtocolProxyFilter ]), |
| 50 | + |
| 51 | + wrappedJSObject: null, // Initialized by constructor |
| 52 | + |
| 53 | + // properties required for XPCOM registration: |
| 54 | + classDescription: SERVICE_NAME, |
| 55 | + classID: SERVICE_ID, |
| 56 | + contractID: SERVICE_CTRID, |
| 57 | + |
| 58 | + // https://developer.mozilla.org/En/How_to_check_the_security_state_of_an_XMLHTTPRequest_over_SSL |
| 59 | + getSSLCert: function(channel) { |
| 60 | + try { |
| 61 | + // Do we have a valid channel argument? |
| 62 | + if (!channel instanceof Ci.nsIChannel) { |
| 63 | + return null; |
| 64 | + } |
| 65 | + var secInfo = channel.securityInfo; |
| 66 | + |
| 67 | + // Print general connection security state |
| 68 | + if (secInfo instanceof Ci.nsITransportSecurityInfo) { |
| 69 | + secInfo.QueryInterface(Ci.nsITransportSecurityInfo); |
| 70 | + } else { |
| 71 | + return null; |
| 72 | + } |
| 73 | + |
| 74 | + if (secInfo instanceof Ci.nsISSLStatusProvider) { |
| 75 | + return secInfo.QueryInterface(Ci.nsISSLStatusProvider). |
| 76 | + SSLStatus.QueryInterface(Ci.nsISSLStatus).serverCert; |
| 77 | + } |
| 78 | + return null; |
| 79 | + } catch(err) { |
| 80 | + return null; |
| 81 | + } |
| 82 | + }, |
| 83 | + |
| 84 | + observe: function(subject, topic, data) { |
| 85 | + if ("http-on-examine-response" == topic) { |
| 86 | + aSubject.QueryInterface(Ci.nsIHttpChannel); |
| 87 | + cert = this.getSSLCert(aSubject); |
| 88 | + } |
| 89 | + }, |
| 90 | + |
| 91 | + applyFilter(aProxyService, aURI, aProxy) { |
| 92 | + // XXX: This check may be wrong. Have not tested it |
| 93 | + if (aURI.spec.search("^https://observatory.eff.org/submit.py") != -1 && |
| 94 | + aURI.path.search(this.nonce+"$") != -1) { |
| 95 | + // This is for us! |
| 96 | + // XXX: Send it through tor by creating an nsIProxy instance |
| 97 | + // for the torbutton proxy settings. |
| 98 | + } |
| 99 | + }, |
| 100 | + |
| 101 | + // [optional] an array of categories to register this component in. |
| 102 | + // Hack to cause us to get instantiate early |
| 103 | + _xpcom_categories: [ { category: "profile-after-change" }, ], |
| 104 | + |
| 105 | +}; |
| 106 | + |
| 107 | +/** |
| 108 | +* XPCOMUtils.generateNSGetFactory was introduced in Mozilla 2 (Firefox 4). |
| 109 | +* XPCOMUtils.generateNSGetModule is for Mozilla 1.9.2 (Firefox 3.6). |
| 110 | +*/ |
| 111 | +if (XPCOMUtils.generateNSGetFactory) |
| 112 | + var NSGetFactory = XPCOMUtils.generateNSGetFactory([SSLObservatory]); |
| 113 | +else |
| 114 | + var NSGetModule = XPCOMUtils.generateNSGetModule([SSLObservatory]); |
0 commit comments