How I check if a certificate is added to Firefox

I’m developing an add-on that make request to a web service published under https and the certificate is auto signed, so it, users must add a permanent the certificate for my add-on work properly.

When the add-on start always check if the certificate is present making a request and if response.status == 0 [1] then I assume that it is not present but many times [1] not is valid.

I like know how can obtain all certificates added to Firefox or a best way to assume a bad environment.

Regards.

I think a better way to test for certificate is not not make any XHR requests, as what if the user is offline?

There has to be a way to do it without XHR I would start with this search on dxr: https://dxr.mozilla.org/mozilla-central/search?q=addException&case=false

interesting though, three is a checkCert function here and it looks like it does XHR too: https://dxr.mozilla.org/mozilla-central/source/security/manager/pki/resources/content/exceptionDialog.js#94

@noitidart thank you for provide those links.
Based on [2] I will be adapt my add-on and try always add the certificate through overrideService.rememberValidityOverride method.
The only think that I need is obtain the server cert that must be a nsIX509Cert and passed it with others options.

I found the way, thank you @noitidart.
I my add-on only want add a certificate and use the x509certdb service, building a Cert through base64 string of cert and some levels of trusted.
It is my code, if other persona can do something equal.
Some comments are in Spanish.

const timer = require('sdk/timers'),
    { Cc, Ci, Cu } = require('chrome'),
    XMLHttpRequest = require("sdk/net/xhr");

/**
 * Programa el chequeo del certificado para 6 segundos
 */
timer.setTimeout(function() {
    checkCert()
}, 6000)

/**
 * Se encarga de capturar los eventos relacionados con los errores en certificados
 */
function badCertListener() {}
badCertListener.prototype = {
    getInterface: function(aIID) {
        return this.QueryInterface(aIID)
    },
    QueryInterface: function(aIID) {
        if (aIID.equals(Ci.nsIBadCertListener2) ||
            aIID.equals(Ci.nsIInterfaceRequestor) ||
            aIID.equals(Ci.nsISupports))
            return this

        throw Components.results.NS_ERROR_NO_INTERFACE
    }
}

/**
 * Realiza una peticion a cuotas.uci.cu y si hay errores de certificado entonces se añade la excepción
 */
function checkCert() {
    let uri = getURI()
    let req = new XMLHttpRequest.XMLHttpRequest()
    try {
        if (uri) {
            req.open('GET', uri.prePath, false)
            req.channel.notificationCallbacks = new badCertListener()
            req.send(null)
        }
    } catch (e) {
        // We *expect* exceptions if there are problems with the certificate presented by the site
        Cu.reportError("Attempted to connect to a site with a bad certificate in the add exception dialog. " +
            "This results in a (mostly harmless) exception being thrown. " +
            "Logged for information purposes only: " + e)
        addException()
    }
}

/**
 * Anade UCICA a la BD de certificados a traves de su codigo en base64
 */
function addException() {
    // Los pases para acceder a las interfaces y servicios de Firefox
    let certdbService = Cc['@mozilla.org/security/x509certdb;1'].getService(Ci.nsIX509CertDB)
    let base64 = 'kk' // The base64 code present on the cert, not put the code because is to long
    // A traves de base64 y los parametros "TCu,TCu,TCu" se adiciona y modifican los niveles de confianza del certificado
    certdbService.addCertFromBase64(base64, "TCu,TCu,TCu", 'UCICA - UCI')
}

/**
 * Build and return a URI for do request
 */
function getURI() {
    // Use fixup service instead of just ioservice's newURI since it's quite likely
    // that the host will be supplied without a protocol prefix, resulting in malformed
    // uri exceptions being thrown.
    let fus = Cc["@mozilla.org/docshell/urifixup;1"].getService(Ci.nsIURIFixup)
    let uri = fus.createFixupURI('https://cuotas.uci.cu/servicios/v1/InetCuotasWS.php?wsdl', 0)

    if (!uri) {
        return null
    } else {
        return uri
    }
}
3 Likes

Fantastic! Thanks very much for sharing!