我正在为firefox编写一个插件,但是我似乎在通道方面有一些问题。我正试图写一个程序,接收一个网站的证书信息,并保存在一个特定的格式。它没有收集到我需要的信息。下面是我的代码:(抱歉在那里放了很多东西,但这都是必要的。)
const {Cc,Ci,Cu} = require("chrome");
let console = (Cu.import("resource://gre/modules/devtools/Console.jsm", {})).console;
console.log("Importing console.n");
// Cu.import("resource://gre/modules/XPCOMUtils.jsm");
this._loadHandler = function(e) {myExtension.onPageLoad(e); };
var utils = require('sdk/window/utils');
var gBrowser = utils.getMostRecentBrowserWindow().getBrowser();
gBrowser.addEventListener("load", this._loadHandler, true);
// We register an observer on page load, through page load event listener. Is this round-about?
// Can we register it directly?
var myExtension = {
onPageLoad: function(aEvent) {
var doc = aEvent.originalTarget; // doc is document that triggered "onload" event
var i = 0;
console.log("Page has been loaded.n");
this.registerObserver("http-on-examine-response");
this.initialized = true;
},
onPageUnload: function(aEvent) {
console.log("Page has been unloaded.n");
this.unregisterObserver("http-on-examine-response");
},
registerObserver: function(topic) {
var observerService = Cc["@mozilla.org/observer-service;1"]
.getService(Ci.nsIObserverService);
observerService.addObserver(this, topic, false);
console.log("Observer Registered.n");
},
unregisterObserver: function(topic) {
var observerService = Cc["@mozilla.org/observer-service;1"]
.getService(Ci.nsIObserverService);
observerService.removeObserver(this, topic);
console.log("Observer Unregistered.n");
},
//Observation Function
observe: function(channel, topic, data) {
console.log("Running Observe....n");
this.examine_cert(channel);
},
examine_cert: function(channel) {
channel.QueryInterface(Ci.nsIHttpChannel);
//Assigns the channel of the http resource in the host port
var host = channel.URI.hostPort;
//Checks for security info
var si = channel.securityInfo;
if (!si){
console.log("No securityInfo for "+ host +" , returningn");
return;
}
//Gets Certificates status
si.QueryInterface(Ci.nsISSLStatusProvider);
var st = si.SSLStatus;
if (!st){
console.log(st + "n");
console.log("No SSLStatus for "+ host +" , returningn");
return;
}
st.QueryInterface(Ci.nsISSLStatus);
var cert = st.serverCert;
if (!cert){
console.log("No serverCert for "+ host +" , returningn");
return;
}
// by now we must have a non-empty cert, print it and the status
console.log( "status: " + st + "n");
console.log( "cert : " + cert.commonName + "n");
//certobj.ciphername = st.cipherName; // apparently, parsed out of cert when SSLStatus is made
//certobj.keyLength = st.keyLength;
//certobj.secretKeyLength = st.secretKeyLength;
},
// Recursively descend into the object, looking for displayName matching re;
// also, validate objects as we go.
findASN1Object: function (struc, re) {
if (!struc){
console.log("nCertificate does not have a valid structure.n");
return;
}
// Shortcut: object with displayName matching re found, return it immediately
if (re.test(struc.displayName)) return struc;
var s = Ci;
try {
s = struc.QueryInterface(Ci.nsIASN1Sequence);
}
catch (e) {
console.log("nCertificate failed nsIASN1Sequence conversionn");
}
if ( !s || ! s.isValidContainer) {
console.log("nCertificate does not have a valid container.n");
return;
}
// check all the objects recursively
for (var i=0; i<s.ASN1Objects.length; i++) {
struc = s.ASN1Objects.queryElementAt(i, Ci.nsIASN1Object);
var res = this.findASN1Object(struc, re);
if (res) return res;
}
},
//------ Object containment:
// nsIHttpChannel > securityInfo (nsISSLStatusProvider) > SSLStatus (nsISSLStatus) > serverCert (nsIX509Cert)
fillCertObj: function(obj, cert) {
obj.cert = cert;
console.log("nCert:" + cert + "n");
obj.notBefore = cert.validity.notBefore;
obj.notAfter = cert.validity.notAfter;
if (cert.issuer) {
obj.issuerMd5Fingerprint = cert.issuer.md5Fingerprint;
obj.issuerSha1Fingerprint = cert.issuer.sha1Fingerprint;
}
else {
//console.log("no issuer: "+ [cert.commonName, cert.issuer, cert.sha1Fingerprint]);
console.log("nThe Certificate doesn't have an Issuer.n");
}
var keys = ["commonName", "organization", "organizationalUnit", "serialNumber","emailAddress",
"issuerCommonName", "issuerOrganization", "issuerOrganizationUnit","md5Fingerprint", "sha1Fingerprint" ];
for (var i in keys){
obj[keys[i]] = cert[keys[i]];
}
obj.subjectAltName = [];
var san = this.findASN1Object(cert.ASN1Structure, /^Certificate Subject Alt Name$/);
if (san) {
//this.log("SAN:", [san.displayName, san.displayValue]);
var m, re = /DNS Name: ((?:*.)?[a-z0-9.-]+)/g;
// *.smth1.smth2.smth3....smthn where smth has only a-z,0-9,or - or
// smth1.smth2.smth3....smthn where smth has only a-z,0-9,or -
// push domain names contained in displayValue onto the list subjectAltName
while (m = re.exec(san.displayValue))
obj.subjectAltName.push(m[1]);
}
console.log("Filled Certificate.n");
},
init_cert: function(){
var certobj = this.newCertObj();
//certobj.host = host;
//certobj.ciphername = st.cipherName;
//certobj.keyLength = st.keyLength;
//certobj.secretKeyLength = st.secretKeyLength;
//this.fillCertObj(certobj.now, cert);
console.log(certobj);
},
newCertObj: function() {
console.log("Creating Empty Certificate.n");
return {
flags: 0,
host: "",
warn: {},
now: {
commonName: "",
organization: "",
organizationalUnit: "",
serialNumber: "",
emailAddress: "",
notBefore: "",
notAfter: "",
issuerCommonName: "",
issuerOrganization: "",
issuerOrganizationUnit: "",
md5Fingerprint: "",
sha1Fingerprint: "",
issuerMd5Fingerprint: "",
issuerSha1Fingerprint: "",
cert: null,
},
old: {
commonName: "",
organization: "",
organizationalUnit: "",
serialNumber: "",
emailAddress: "",
notBefore: "",
notAfter: "",
issuerCommonName: "",
issuerOrganization: "",
issuerOrganizationUnit: "",
md5Fingerprint: "",
sha1Fingerprint: "",
issuerMd5Fingerprint: "",
issuerSha1Fingerprint: "",
cert: null,
},
};
},
}
在页面加载时注册和取消注册observer是不明智的,因为它会从任何地方捕获http请求。所以在启动插件时注册它,在关闭/卸载插件时注销它。
你应该检查loadContext,看看是哪个窗口/标签/框架/ajax/背景发出请求。有关loadContext的更多信息,请参阅此处:https://stackoverflow.com/a/25223307/1828637
但是无论如何,这应该按照你的方式工作意思是页面加载时使用reg页面卸载时使用unreg页面
const {
Cc, Ci, Cu
} = require("chrome");
let console = (Cu.import("resource://gre/modules/devtools/Console.jsm", {})).console;
console.log("Importing console.n");
// Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
this._loadHandler = function(e) {
myExtension.onPageLoad(e);
};
var utils = require('sdk/window/utils');
var gBrowser = utils.getMostRecentBrowserWindow().getBrowser();
gBrowser.addEventListener("load", this._loadHandler, true);
// We register an observer on page load, through page load event listener. Is this round-about?
// Can we register it directly?
var myExtension = {
observers: {
'http-on-examine-response': {
observe: function(aSubject, aTopic, aData) {
console.log("Running Observe....n");
myExtension.examine_cert(aSubject);
},
reg: function() {
Services.obs.addObserver(myExtension.observers['http-on-examine-response'], 'http-on-examine-response', false);
},
unreg: function() {
Services.obs.removeObserver(myExtension.observers['http-on-examine-response'], 'http-on-examine-response');
}
}
},
onPageLoad: function(aEvent) {
var doc = aEvent.originalTarget; // doc is document that triggered "onload" event
var i = 0;
console.log("Page has been loaded.n");
myExtension.observers['http-on-examine-response'].reg();
this.initialized = true;
},
onPageUnload: function(aEvent) {
console.log("Page has been unloaded.n");
myExtension.observers['http-on-examine-response'].unreg();
},
examine_cert: function(channel) {
channel.QueryInterface(Ci.nsIHttpChannel);
//Assigns the channel of the http resource in the host port
var host = channel.URI.hostPort;
//Checks for security info
var si = channel.securityInfo;
if (!si) {
console.log("No securityInfo for " + host + " , returningn");
return;
}
//Gets Certificates status
si.QueryInterface(Ci.nsISSLStatusProvider);
var st = si.SSLStatus;
if (!st) {
console.log(st + "n");
console.log("No SSLStatus for " + host + " , returningn");
return;
}
st.QueryInterface(Ci.nsISSLStatus);
var cert = st.serverCert;
if (!cert) {
console.log("No serverCert for " + host + " , returningn");
return;
}
// by now we must have a non-empty cert, print it and the status
console.log("status: " + st + "n");
console.log("cert : " + cert.commonName + "n");
//certobj.ciphername = st.cipherName; // apparently, parsed out of cert when SSLStatus is made
//certobj.keyLength = st.keyLength;
//certobj.secretKeyLength = st.secretKeyLength;
},
// Recursively descend into the object, looking for displayName matching re;
// also, validate objects as we go.
findASN1Object: function(struc, re) {
if (!struc) {
console.log("nCertificate does not have a valid structure.n");
return;
}
// Shortcut: object with displayName matching re found, return it immediately
if (re.test(struc.displayName)) return struc;
var s = Ci;
try {
s = struc.QueryInterface(Ci.nsIASN1Sequence);
} catch (e) {
console.log("nCertificate failed nsIASN1Sequence conversionn");
}
if (!s || !s.isValidContainer) {
console.log("nCertificate does not have a valid container.n");
return;
}
// check all the objects recursively
for (var i = 0; i < s.ASN1Objects.length; i++) {
struc = s.ASN1Objects.queryElementAt(i, Ci.nsIASN1Object);
var res = this.findASN1Object(struc, re);
if (res) return res;
}
},
//------ Object containment:
// nsIHttpChannel > securityInfo (nsISSLStatusProvider) > SSLStatus (nsISSLStatus) > serverCert (nsIX509Cert)
fillCertObj: function(obj, cert) {
obj.cert = cert;
console.log("nCert:" + cert + "n");
obj.notBefore = cert.validity.notBefore;
obj.notAfter = cert.validity.notAfter;
if (cert.issuer) {
obj.issuerMd5Fingerprint = cert.issuer.md5Fingerprint;
obj.issuerSha1Fingerprint = cert.issuer.sha1Fingerprint;
} else {
//console.log("no issuer: "+ [cert.commonName, cert.issuer, cert.sha1Fingerprint]);
console.log("nThe Certificate doesn't have an Issuer.n");
}
var keys = ["commonName", "organization", "organizationalUnit", "serialNumber", "emailAddress",
"issuerCommonName", "issuerOrganization", "issuerOrganizationUnit", "md5Fingerprint", "sha1Fingerprint"
];
for (var i in keys) {
obj[keys[i]] = cert[keys[i]];
}
obj.subjectAltName = [];
var san = this.findASN1Object(cert.ASN1Structure, /^Certificate Subject Alt Name$/);
if (san) {
//this.log("SAN:", [san.displayName, san.displayValue]);
var m, re = /DNS Name: ((?:*.)?[a-z0-9.-]+)/g;
// *.smth1.smth2.smth3....smthn where smth has only a-z,0-9,or - or
// smth1.smth2.smth3....smthn where smth has only a-z,0-9,or -
// push domain names contained in displayValue onto the list subjectAltName
while (m = re.exec(san.displayValue))
obj.subjectAltName.push(m[1]);
}
console.log("Filled Certificate.n");
},
init_cert: function() {
var certobj = this.newCertObj();
//certobj.host = host;
//certobj.ciphername = st.cipherName;
//certobj.keyLength = st.keyLength;
//certobj.secretKeyLength = st.secretKeyLength;
//this.fillCertObj(certobj.now, cert);
console.log(certobj);
},
newCertObj: function() {
console.log("Creating Empty Certificate.n");
return {
flags: 0,
host: "",
warn: {},
now: {
commonName: "",
organization: "",
organizationalUnit: "",
serialNumber: "",
emailAddress: "",
notBefore: "",
notAfter: "",
issuerCommonName: "",
issuerOrganization: "",
issuerOrganizationUnit: "",
md5Fingerprint: "",
sha1Fingerprint: "",
issuerMd5Fingerprint: "",
issuerSha1Fingerprint: "",
cert: null,
},
old: {
commonName: "",
organization: "",
organizationalUnit: "",
serialNumber: "",
emailAddress: "",
notBefore: "",
notAfter: "",
issuerCommonName: "",
issuerOrganization: "",
issuerOrganizationUnit: "",
md5Fingerprint: "",
sha1Fingerprint: "",
issuerMd5Fingerprint: "",
issuerSha1Fingerprint: "",
cert: null,
},
};
},
}
最后,为什么要在伪类myExtension
中包装?当做插件sdk或引导插件时,你不必再这样做了。