michael@0: // -*- Mode: javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- michael@0: // This Source Code Form is subject to the terms of the Mozilla Public michael@0: // License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: // file, You can obtain one at http://mozilla.org/MPL/2.0/. michael@0: michael@0: "use strict"; michael@0: michael@0: do_get_profile(); // must be called before getting nsIX509CertDB michael@0: const certdb = Cc["@mozilla.org/security/x509certdb;1"] michael@0: .getService(Ci.nsIX509CertDB); michael@0: const certdb2 = Cc["@mozilla.org/security/x509certdb;1"] michael@0: .getService(Ci.nsIX509CertDB2); michael@0: michael@0: // This is the list of certificates needed for the test michael@0: // The certificates prefixed by 'int-' are intermediates michael@0: let certList = [ michael@0: 'ee', michael@0: 'ca-1', michael@0: 'ca-2', michael@0: ] michael@0: michael@0: function load_cert(cert_name, trust_string) { michael@0: var cert_filename = cert_name + ".der"; michael@0: addCertFromFile(certdb, "test_getchain/" + cert_filename, trust_string); michael@0: } michael@0: michael@0: // Since all the ca's are identical expect for the serial number michael@0: // I have to grab them by enumerating all the certs and then finding michael@0: // the ones that I am interested in. michael@0: function get_ca_array() { michael@0: let ret_array = new Array(); michael@0: let allCerts = certdb2.getCerts(); michael@0: let enumerator = allCerts.getEnumerator(); michael@0: while (enumerator.hasMoreElements()) { michael@0: let cert = enumerator.getNext().QueryInterface(Ci.nsIX509Cert); michael@0: if (cert.commonName == 'ca') { michael@0: ret_array[parseInt(cert.serialNumber)] = cert; michael@0: } michael@0: } michael@0: return ret_array; michael@0: } michael@0: michael@0: michael@0: function check_matching_issuer_and_getchain(expected_issuer_serial, cert) { michael@0: const nsIX509Cert = Components.interfaces.nsIX509Cert; michael@0: michael@0: do_check_eq(expected_issuer_serial, cert.issuer.serialNumber); michael@0: let chain = cert.getChain(); michael@0: let issuer_via_getchain = chain.queryElementAt(1, nsIX509Cert); michael@0: // The issuer returned by cert.issuer or cert.getchain should be consistent. michael@0: do_check_eq(cert.issuer.serialNumber, issuer_via_getchain.serialNumber); michael@0: } michael@0: michael@0: function check_getchain(ee_cert, ssl_ca, email_ca){ michael@0: // A certificate should first build a chain/issuer to michael@0: // a SSL trust domain, then an EMAIL trust domain and then michael@0: // and object signer trust domain michael@0: michael@0: const nsIX509Cert = Components.interfaces.nsIX509Cert; michael@0: certdb.setCertTrust(ssl_ca, nsIX509Cert.CA_CERT, michael@0: Ci.nsIX509CertDB.TRUSTED_SSL); michael@0: certdb.setCertTrust(email_ca, nsIX509Cert.CA_CERT, michael@0: Ci.nsIX509CertDB.TRUSTED_EMAIL); michael@0: check_matching_issuer_and_getchain(ssl_ca.serialNumber, ee_cert); michael@0: certdb.setCertTrust(ssl_ca, nsIX509Cert.CA_CERT, 0); michael@0: check_matching_issuer_and_getchain(email_ca.serialNumber, ee_cert); michael@0: certdb.setCertTrust(email_ca, nsIX509Cert.CA_CERT, 0); michael@0: // Do a final test on the case of no trust. The results must michael@0: // be cosistent (the actual value is non-deterministic). michael@0: check_matching_issuer_and_getchain(ee_cert.issuer.serialNumber, ee_cert); michael@0: } michael@0: michael@0: function run_test_in_mode(useMozillaPKIX) { michael@0: Services.prefs.setBoolPref("security.use_mozillapkix_verification", useMozillaPKIX); michael@0: clearOCSPCache(); michael@0: clearSessionCache(); michael@0: michael@0: for (let i = 0 ; i < certList.length; i++) { michael@0: load_cert(certList[i], ',,'); michael@0: } michael@0: michael@0: let ee_cert = certdb.findCertByNickname(null, 'ee'); michael@0: do_check_false(!ee_cert); michael@0: michael@0: let ca = get_ca_array(); michael@0: michael@0: check_getchain(ee_cert, ca[1], ca[2]); michael@0: // Swap ca certs to deal alternate trust settings. michael@0: check_getchain(ee_cert, ca[2], ca[1]); michael@0: } michael@0: michael@0: function run_test() { michael@0: run_test_in_mode(true); michael@0: run_test_in_mode(false); michael@0: }