How can I get the SSL Certificate info for the *current* page in a Firefox Add On

前端 未结 2 1477
[愿得一人]
[愿得一人] 2020-12-30 15:43

I\'m trying to develop a Firefox extension/add-on that needs access to the SSL Certificate information of the page that is currently loaded. Once I have this information I

相关标签:
2条回答
  • 2020-12-30 16:08

    Building on this answer:

    The trick is to register a progress listener and check aState when the onSecurityChange function is called. If the Ci.nsIWebProgressListener.STATE_IS_SECURE flag is set then the page is using an SSL connection. That isn't enough however, the aRequest parameter may not be an instance of Ci.nsIChannel, that should be verified first with if (aRequest instanceof Ci.nsIChannel).

    Here is the working code:

    function dumpSecurityInfo(channel) {
    
        const Cc = Components.classes
        const Ci = Components.interfaces;
    
        // Do we have a valid channel argument?
        if (! channel instanceof  Ci.nsIChannel) {
            dump("No channel available\n");
            return;
        }
    
        var secInfo = channel.securityInfo;
    
        // Print general connection security state
        if (secInfo instanceof Ci.nsITransportSecurityInfo) {
            dump("name: " + channel.name + "\n");
            secInfo.QueryInterface(Ci.nsITransportSecurityInfo);
    
            dump("\tSecurity state: ");
    
            // Check security state flags
            if ((secInfo.securityState & Ci.nsIWebProgressListener.STATE_IS_SECURE) == Ci.nsIWebProgressListener.STATE_IS_SECURE)
                dump("secure\n");
    
            else if ((secInfo.securityState & Ci.nsIWebProgressListener.STATE_IS_INSECURE) == Ci.nsIWebProgressListener.STATE_IS_INSECURE)
                dump("insecure\n");
    
            else if ((secInfo.securityState & Ci.nsIWebProgressListener.STATE_IS_BROKEN) == Ci.nsIWebProgressListener.STATE_IS_BROKEN)
                dump("unknown\n");
    
            dump("\tSecurity description: " + secInfo.shortSecurityDescription + "\n");
            dump("\tSecurity error message: " + secInfo.errorMessage + "\n");
        }
        else {
    
            dump("\tNo security info available for this channel\n");
        }
    
        // Print SSL certificate details
        if (secInfo instanceof Ci.nsISSLStatusProvider) {
    
            var cert = secInfo.QueryInterface(Ci.nsISSLStatusProvider).
            SSLStatus.QueryInterface(Ci.nsISSLStatus).serverCert;
    
            dump("\nCertificate Status:\n");
    
            var verificationResult = cert.verifyForUsage(Ci.nsIX509Cert.CERT_USAGE_SSLServer);
            dump("\tVerification: ");
    
            switch (verificationResult) {
                case Ci.nsIX509Cert.VERIFIED_OK:
                    dump("OK");
                    break;
                case Ci.nsIX509Cert.NOT_VERIFIED_UNKNOWN:
                    dump("not verfied/unknown");
                    break;
                case Ci.nsIX509Cert.CERT_REVOKED:
                    dump("revoked");
                    break;
                case Ci.nsIX509Cert.CERT_EXPIRED:
                    dump("expired");
                    break;
                case Ci.nsIX509Cert.CERT_NOT_TRUSTED:
                    dump("not trusted");
                    break;
                case Ci.nsIX509Cert.ISSUER_NOT_TRUSTED:
                    dump("issuer not trusted");
                    break;
                case Ci.nsIX509Cert.ISSUER_UNKNOWN:
                    dump("issuer unknown");
                    break;
                case Ci.nsIX509Cert.INVALID_CA:
                    dump("invalid CA");
                    break;
                default:
                    dump("unexpected failure");
                    break;
            }
            dump("\n");
    
            dump("\tCommon name (CN) = " + cert.commonName + "\n");
            dump("\tOrganisation = " + cert.organization + "\n");
            dump("\tIssuer = " + cert.issuerOrganization + "\n");
            dump("\tSHA1 fingerprint = " + cert.sha1Fingerprint + "\n");
    
            var validity = cert.validity.QueryInterface(Ci.nsIX509CertValidity);
            dump("\tValid from " + validity.notBeforeGMT + "\n");
            dump("\tValid until " + validity.notAfterGMT + "\n");
        }
    }
    
    var myListener =
    {
        QueryInterface: function(aIID)
        {
            if (aIID.equals(Components.interfaces.nsIWebProgressListener) ||
               aIID.equals(Components.interfaces.nsISupportsWeakReference) ||
               aIID.equals(Components.interfaces.nsISupports))
                return this;
            throw Components.results.NS_NOINTERFACE;
        },
    
        onStateChange: function(aWebProgress, aRequest, aFlag, aStatus) { },
    
        onLocationChange: function(aProgress, aRequest, aURI) { },
    
        onProgressChange: function(aWebProgress, aRequest, curSelf, maxSelf, curTot, maxTot) { },
        onStatusChange: function(aWebProgress, aRequest, aStatus, aMessage) { },
        onSecurityChange: function(aWebProgress, aRequest, aState) 
        {
            // check if the state is secure or not
            if(aState & Ci.nsIWebProgressListener.STATE_IS_SECURE)
            {
                // this is a secure page, check if aRequest is a channel,
                // since only channels have security information
                if (aRequest instanceof Ci.nsIChannel)
                {
                    dumpSecurityInfo(aRequest);
                }
            }    
        }
    }
    
    var test =
    {
        run: function() {
            dump("run\n");
            gBrowser.addProgressListener(myListener);
        }
    };
    
    window.addEventListener("load", function () { test.run(); }, false);
    
    0 讨论(0)
  • 2020-12-30 16:11

    The way you query the channel to get its security info seems sane. I suspect that your problem is actually timing - you query it at the wrong time. Tracing all requests is really the wrong approach if security info is all you are interested in. It makes far more sense to register a progress listener (there are examples) and to look at the channel whenever onSecurityChange is being called. You are likely to be only interested in requests where aState contains STATE_IS_SECURE flag. Note that aRequest parameter is usually an nsIChannel instance but could also be a plain nsIRequest - instanceof check is required.

    0 讨论(0)
提交回复
热议问题