diff --git a/mail/components/accountcreation/test/xpcshell/certs/cert9.db b/mail/components/accountcreation/test/xpcshell/certs/cert9.db deleted file mode 100644 index 920763c909..0000000000 Binary files a/mail/components/accountcreation/test/xpcshell/certs/cert9.db and /dev/null differ diff --git a/mail/components/accountcreation/test/xpcshell/certs/expired.ca b/mail/components/accountcreation/test/xpcshell/certs/expired.ca deleted file mode 100644 index 03dbfb0c5a..0000000000 --- a/mail/components/accountcreation/test/xpcshell/certs/expired.ca +++ /dev/null @@ -1,18 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIC/DCCAeSgAwIBAgIUZ24PLYfvmEYxivOfRLC9Z6w9SNUwDQYJKoZIhvcNAQEL -BQAwGTEXMBUGA1UEAwwORGVmYXVsdCBJc3N1ZXIwIhgPMjAxMDAxMDUwMDAwMDBa -GA8yMDEwMDEwNjAwMDAwMFowHDEaMBgGA1UEAwwRZXhwaXJlZC50ZXN0LnRlc3Qw -ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC6iFGoRI4W1kH9braIBjYQ -PTwT2erkNUq07PVoV2wke8HHJajg2B+9sZwGm24ahvJr4q9adWtqZHEIeqVap0WH -9xzVJJwCfs1D/B5p0DggKZOrIMNJ5Nu5TMJrbA7tFYIP8X6taRqx0wI6iypB7qdw -4A8Njf1mCyuwJJKkfbmIYXmQsVeQPdI7xeC4SB+oN9OIQ+8nFthVt2Zaqn4CkC86 -exCABiTMHGyXrZZhW7filhLAdTGjDJHdtMr3/K0dJdMJ77kXDqdo4bN7LyJvaeO0 -ipVhHe4m1iWdq5EITjbLHCQELL8Wiy/l8Y+ZFzG4s/5JI/pyUcQx1QOs2hgKNe2N -AgMBAAGjNTAzMBMGA1UdJQQMMAoGCCsGAQUFBwMBMBwGA1UdEQQVMBOCEWV4cGly -ZWQudGVzdC50ZXN0MA0GCSqGSIb3DQEBCwUAA4IBAQAPbvTgqriBAAk7dtDB9JuF -velUEQTWZnMz7iZSDNoWP3OcIVzEKrk0dVHZ4FGrokW5P08IA+gbQMfQ1vMiIOpF -7P9/8hK0jC//IPjv6ldscz7ioe6WntB2k3QNxdjhh1iMRX97S1mrexnZ03uD+6pE -dOo9iPyAgZ5lCKi/UU1lPha0PQdcCn7kRgi6zd8VPGFE0hdwSvdMB3aLZlCZmz/W -pkEHIMaLiGeIRKQCLP6RiTXiRFv6vEB0yXS695a9vwujCY1SVXLO2OF0f+PejFcd -QZYGFZ/q3YQJqTXZCNiP5tVhpzV51NbB6n7YUWP1/djyyK81vOK77IksjKTxpEmu ------END CERTIFICATE----- diff --git a/mail/components/accountcreation/test/xpcshell/certs/gencerts.py b/mail/components/accountcreation/test/xpcshell/certs/gencerts.py deleted file mode 100644 index 6498553677..0000000000 --- a/mail/components/accountcreation/test/xpcshell/certs/gencerts.py +++ /dev/null @@ -1,228 +0,0 @@ -#!/usr/bin/env python -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. - -# This script exists to generate the Certificate Authority and server -# certificates used for SSL testing. Adapted from build/pgo/genpgocert.py. - -# To use, run `mach python mail/components/accountcreation/test/xpcshell/certs/gencerts.py`. -# This will generate new certificates and database files. These need to be -# checked in with your patch. - -import os -import re -import shutil -import subprocess -import sys -from distutils.spawn import find_executable - -import mozinfo -from mozfile import NamedTemporaryFile, TemporaryDirectory - -from mozbuild.base import BinaryNotFoundException, MozbuildObject - -dbFiles = [ - re.compile("^cert[0-9]+\.db$"), - re.compile("^key[0-9]+\.db$"), -] - - -def unlinkDbFiles(path): - for root, dirs, files in os.walk(path): - for name in files: - for dbFile in dbFiles: - if dbFile.match(name) and os.path.exists(os.path.join(root, name)): - os.unlink(os.path.join(root, name)) - - -def dbFilesExist(path): - for root, dirs, files in os.walk(path): - for name in files: - for dbFile in dbFiles: - if dbFile.match(name) and os.path.exists(os.path.join(root, name)): - return True - return False - - -def runUtil(util, args, inputdata=None, outputstream=None): - env = os.environ.copy() - if mozinfo.os == "linux": - pathvar = "LD_LIBRARY_PATH" - app_path = os.path.dirname(util) - if pathvar in env: - env[pathvar] = "%s%s%s" % (app_path, os.pathsep, env[pathvar]) - else: - env[pathvar] = app_path - proc = subprocess.Popen( - [util] + args, - env=env, - stdin=subprocess.PIPE if inputdata else None, - stdout=outputstream, - universal_newlines=True, - ) - proc.communicate(inputdata) - return proc.returncode - - -def constructCertDatabase(build, srcDir): - try: - certutil = build.get_binary_path(what="certutil") - pk12util = build.get_binary_path(what="pk12util") - except BinaryNotFoundException as e: - print("{}\n\n{}\n".format(e, e.help())) - return 1 - openssl = find_executable("openssl") - pycert = os.path.join(build.topsrcdir, "security", "manager", "tools", "pycert.py") - pykey = os.path.join(build.topsrcdir, "security", "manager", "tools", "pykey.py") - - with NamedTemporaryFile(mode="wt+") as pwfile, TemporaryDirectory() as pemfolder: - pwfile.write("\n") - pwfile.flush() - - if dbFilesExist(srcDir): - # Make sure all DB files from src are really deleted - unlinkDbFiles(srcDir) - - # Copy all .certspec and .keyspec files to a temporary directory - for root, dirs, files in os.walk(srcDir): - for spec in [i for i in files if i.endswith(".certspec") or i.endswith(".keyspec")]: - shutil.copyfile(os.path.join(root, spec), os.path.join(pemfolder, spec)) - - # Generate certs for all certspecs - for root, dirs, files in os.walk(pemfolder): - for certspec in [i for i in files if i.endswith(".certspec")]: - name = certspec.split(".certspec")[0] - pem = os.path.join(pemfolder, "{}.cert.pem".format(name)) - - print("Generating public certificate {} (pem={})".format(name, pem)) - - with open(os.path.join(root, certspec), "r") as certspec_file: - certspec_data = certspec_file.read() - with open(pem, "w") as pem_file: - status = runUtil( - pycert, [], inputdata=certspec_data, outputstream=pem_file - ) - if status: - return status - - status = runUtil( - certutil, - [ - "-A", - "-n", - name, - "-t", - "P,,", - "-i", - pem, - "-d", - srcDir, - "-f", - pwfile.name, - ], - ) - if status: - return status - - shutil.copyfile(pem, os.path.join(srcDir, name)) - - for keyspec in [i for i in files if i.endswith(".keyspec")]: - parts = keyspec.split(".") - name = parts[0] - key_type = parts[1] - if key_type not in ["ca", "client", "server"]: - raise Exception( - "{}: keyspec filenames must be of the form XXX.client.keyspec " - "or XXX.ca.keyspec (key_type={})".format(keyspec, key_type) - ) - key_pem = os.path.join(pemfolder, "{}.key.pem".format(name)) - - print("Generating private key {} (pem={})".format(name, key_pem)) - - with open(os.path.join(root, keyspec), "r") as keyspec_file: - keyspec_data = keyspec_file.read() - with open(key_pem, "w") as pem_file: - status = runUtil(pykey, [], inputdata=keyspec_data, outputstream=pem_file) - if status: - return status - - cert_pem = os.path.join(pemfolder, "{}.cert.pem".format(name)) - if not os.path.exists(cert_pem): - raise Exception( - "There has to be a corresponding certificate named {} for " - "the keyspec {}".format(cert_pem, keyspec) - ) - - p12 = os.path.join(pemfolder, "{}.key.p12".format(name)) - print("Converting private key {} to PKCS12 (p12={})".format(key_pem, p12)) - status = runUtil( - openssl, - [ - "pkcs12", - "-export", - "-inkey", - key_pem, - "-in", - cert_pem, - "-name", - name, - "-out", - p12, - "-passout", - "file:" + pwfile.name, - ], - ) - if status: - return status - - print("Importing private key {} to database".format(key_pem)) - status = runUtil( - pk12util, - ["-i", p12, "-d", srcDir, "-w", pwfile.name, "-k", pwfile.name], - ) - if status: - return status - - shutil.copyfile(cert_pem, os.path.join(srcDir, "{}.ca".format(name))) - - for root, dirs, files in os.walk(srcDir): - for ca in [i for i in files if i.endswith(".ca")]: - print("Importing certificate authority {} to database".format(ca)) - name = ca.split(".ca")[0] - status = runUtil( - certutil, - [ - "-A", - "-n", - name, - "-t", - "CT,,", - "-i", - os.path.join(srcDir, ca), - "-d", - srcDir, - "-f", - pwfile.name, - ], - ) - if status: - return status - return 0 - - -build = MozbuildObject.from_environment() -certdir = os.path.join( - build.topsrcdir, - "comm", - "mail", - "components", - "accountcreation", - "test", - "xpcshell", - "certs", -) -certificateStatus = constructCertDatabase(build, certdir) -if certificateStatus: - print("TEST-UNEXPECTED-FAIL | SSL Server Certificate generation") -sys.exit(certificateStatus) diff --git a/mail/components/accountcreation/test/xpcshell/certs/key4.db b/mail/components/accountcreation/test/xpcshell/certs/key4.db deleted file mode 100644 index 996f91864d..0000000000 Binary files a/mail/components/accountcreation/test/xpcshell/certs/key4.db and /dev/null differ diff --git a/mail/components/accountcreation/test/xpcshell/certs/ok.ca b/mail/components/accountcreation/test/xpcshell/certs/ok.ca deleted file mode 100644 index 8e7aaa5c05..0000000000 --- a/mail/components/accountcreation/test/xpcshell/certs/ok.ca +++ /dev/null @@ -1,19 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDKzCCAhOgAwIBAgIURc2ZW7XgI1LS6QO1kNqm9e7AhMwwDQYJKoZIhvcNAQEL -BQAwGTEXMBUGA1UEAwwORGVmYXVsdCBJc3N1ZXIwIhgPMjAyMjExMjcwMDAwMDBa -GA8yMDI1MDIwNDAwMDAwMFowFDESMBAGA1UEAwwJdGVzdC50ZXN0MIIBIjANBgkq -hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuohRqESOFtZB/W62iAY2ED08E9nq5DVK -tOz1aFdsJHvBxyWo4NgfvbGcBptuGobya+KvWnVramRxCHqlWqdFh/cc1SScAn7N -Q/weadA4ICmTqyDDSeTbuUzCa2wO7RWCD/F+rWkasdMCOosqQe6ncOAPDY39Zgsr -sCSSpH25iGF5kLFXkD3SO8XguEgfqDfTiEPvJxbYVbdmWqp+ApAvOnsQgAYkzBxs -l62WYVu34pYSwHUxowyR3bTK9/ytHSXTCe+5Fw6naOGzey8ib2njtIqVYR3uJtYl -nauRCE42yxwkBCy/Fosv5fGPmRcxuLP+SSP6clHEMdUDrNoYCjXtjQIDAQABo2ww -ajATBgNVHSUEDDAKBggrBgEFBQcDATBTBgNVHREETDBKggl0ZXN0LnRlc3SCDWFs -dC50ZXN0LnRlc3SCDmltYXAudGVzdC50ZXN0gg5wb3AzLnRlc3QudGVzdIIOc210 -cC50ZXN0LnRlc3QwDQYJKoZIhvcNAQELBQADggEBAFKwEOkHNOJCf53q2NWC4DyY -TV1NDkt757pdCUwa4KVC5xTmZ3KH+htHPSwDdCclG8y8OS1LCrBCVypUnJbSBwg5 -w0LaiQo2y8oNPgLt+DObccvzQZypePD4vjlU1DpgmrJTjcACMK47NB5QCmSAOQU2 -MMVkGs8YiaoIgVIHmFyXOmIJVqR6lqaaxVC5qfhs4D6tWeDjwW121/wUG2GasDpb -df/QRLWM2x/U7cD0KvNWQupEsEqk/DS9pVPhyaWhsMRyBOplYzivVlSoQr/vXsu7 -SZ8X5auYUre+t8R2YlHfxcJKmgOuBVy+2jNr/Sanaj+PKDpbKPUtxUQgJKnb4bY= ------END CERTIFICATE----- diff --git a/mail/components/accountcreation/test/xpcshell/certs/ok.ca.keyspec b/mail/components/accountcreation/test/xpcshell/certs/ok.ca.keyspec deleted file mode 100644 index 4ad96d5159..0000000000 --- a/mail/components/accountcreation/test/xpcshell/certs/ok.ca.keyspec +++ /dev/null @@ -1 +0,0 @@ -default diff --git a/mail/components/accountcreation/test/xpcshell/test_guessConfig.js b/mail/components/accountcreation/test/xpcshell/test_guessConfig.js index caffa0509b..988621ec75 100644 --- a/mail/components/accountcreation/test/xpcshell/test_guessConfig.js +++ b/mail/components/accountcreation/test/xpcshell/test_guessConfig.js @@ -12,18 +12,14 @@ * connections using a test certificate. */ -const { IMAPServer } = ChromeUtils.importESModule( - "resource://testing-common/IMAPServer.sys.mjs" -); const { NetworkTestUtils } = ChromeUtils.import( "resource://testing-common/mailnews/NetworkTestUtils.jsm" ); -const { POP3Server } = ChromeUtils.importESModule( - "resource://testing-common/POP3Server.sys.mjs" -); -const { SMTPServer } = ChromeUtils.importESModule( - "resource://testing-common/SMTPServer.sys.mjs" +const { ServerTestUtils } = ChromeUtils.importESModule( + "resource://testing-common/mailnews/ServerTestUtils.sys.mjs" ); +const { createServers, getCertificate, serverDefs } = ServerTestUtils; + const { GuessConfig, GuessConfigForTests } = ChromeUtils.importESModule( "resource:///modules/accountcreation/GuessConfig.sys.mjs" ); @@ -35,124 +31,39 @@ const certOverrideService = Cc[ ].getService(Ci.nsICertOverrideService); let tlsCert, expiredCert; -let imapTLSServer, pop3TLSServer, smtpTLSServer; -// Change this for more server debugging output. See Maild.sys.mjs for values. -const serverDebugLevel = 0; - // Something in this test causes NSS shutdown to fail. Ignore it. Services.env.set("MOZ_IGNORE_NSS_SHUTDOWN_LEAKS", "1"); add_setup(async function () { - // Install the test certificate in the database, then set the exceptions. - const profile = do_get_profile(); - do_get_file("certs/cert9.db").copyTo(profile, "cert9.db"); - do_get_file("certs/key4.db").copyTo(profile, "key4.db"); + do_get_profile(); + tlsCert = await getCertificate("valid"); + expiredCert = await getCertificate("expired"); - tlsCert = await getCertificate("certs/ok"); - Assert.equal(tlsCert.commonName, "test.test"); - expiredCert = await getCertificate("certs/expired"); - Assert.equal(expiredCert.commonName, "expired.test.test"); - - const imapServer = new IMAPServer(this, { extensions: ["RFC2195"] }); - imapServer.server.setDebugLevel(serverDebugLevel); - NetworkTestUtils.configureProxy("test.test", 143, imapServer.port); - NetworkTestUtils.configureProxy("alt.test.test", 143, imapServer.port); - - const imapStartTLSServer = new IMAPServer(this, { - extensions: ["RFC2195"], - offerStartTLS: true, - }); - imapStartTLSServer.server.setDebugLevel(serverDebugLevel); - NetworkTestUtils.configureProxy( - "starttls.test.test", - 143, - imapStartTLSServer.port - ); - - imapTLSServer = new IMAPServer(this, { - extensions: ["RFC2195"], - tlsCert, - }); - imapTLSServer.server.setDebugLevel(serverDebugLevel); - NetworkTestUtils.configureProxy("test.test", 993, imapTLSServer.port); - NetworkTestUtils.configureProxy("alt.test.test", 993, imapTLSServer.port); - - // Serves a certificate that doesn't match the hostname. - NetworkTestUtils.configureProxy("mitm.test.test", 993, imapTLSServer.port); - - // Serves an expired certificate. - const imapExpiredTLSServer = new IMAPServer(this, { - extensions: ["RFC2195"], - tlsCert: expiredCert, - }); - imapExpiredTLSServer.server.setDebugLevel(serverDebugLevel); - NetworkTestUtils.configureProxy( - "expired.test.test", - 993, - imapExpiredTLSServer.port - ); - - const pop3Server = new POP3Server(this); - pop3Server.server.setDebugLevel(serverDebugLevel); - NetworkTestUtils.configureProxy("test.test", 110, pop3Server.port); - NetworkTestUtils.configureProxy("alt.test.test", 110, pop3Server.port); - - const pop3StartTLSServer = new POP3Server(this, { offerStartTLS: true }); - pop3StartTLSServer.server.setDebugLevel(serverDebugLevel); - NetworkTestUtils.configureProxy( - "starttls.test.test", - 110, - pop3StartTLSServer.port - ); - - pop3TLSServer = new POP3Server(this, { tlsCert }); - pop3TLSServer.server.setDebugLevel(serverDebugLevel); - NetworkTestUtils.configureProxy("test.test", 995, pop3TLSServer.port); - NetworkTestUtils.configureProxy("alt.test.test", 995, pop3TLSServer.port); - - const smtpServer = new SMTPServer(this); - smtpServer.server.setDebugLevel(serverDebugLevel); - NetworkTestUtils.configureProxy("test.test", 587, smtpServer.port); - NetworkTestUtils.configureProxy("alt.test.test", 587, smtpServer.port); - - const smtpStartTLSServer = new SMTPServer(this, { offerStartTLS: true }); - smtpStartTLSServer.server.setDebugLevel(serverDebugLevel); - NetworkTestUtils.configureProxy( - "starttls.test.test", - 587, - smtpStartTLSServer.port - ); - - smtpTLSServer = new SMTPServer(this, { tlsCert }); - smtpTLSServer.server.setDebugLevel(serverDebugLevel); - NetworkTestUtils.configureProxy("test.test", 465, smtpTLSServer.port); - NetworkTestUtils.configureProxy("alt.test.test", 465, smtpTLSServer.port); - - // Serves an expired certificate. - const smtpExpiredTLSServer = new SMTPServer(this, { tlsCert: expiredCert }); - smtpExpiredTLSServer.server.setDebugLevel(serverDebugLevel); - NetworkTestUtils.configureProxy( - "expired.test.test", - 465, - smtpExpiredTLSServer.port - ); + await createServers(this, [ + { ...serverDefs.imap.plain, aliases: [["alt.test.test", 143]] }, + serverDefs.imap.startTLS, + { + ...serverDefs.imap.tls, + aliases: [ + ["alt.test.test", 993], + ["mitm.test.test", 993], + ], + }, + serverDefs.imap.expiredTLS, + { ...serverDefs.pop3.plain, aliases: [["alt.test.test", 110]] }, + serverDefs.pop3.startTLS, + { ...serverDefs.pop3.tls, aliases: [["alt.test.test", 995]] }, + { ...serverDefs.smtp.plain, aliases: [["alt.test.test", 587]] }, + serverDefs.smtp.startTLS, + { ...serverDefs.smtp.tls, aliases: [["alt.test.test", 465]] }, + serverDefs.smtp.expiredTLS, + ]); }); registerCleanupFunction(function () { NetworkTestUtils.clearProxy(); }); -async function getCertificate(path) { - const certDB = Cc["@mozilla.org/security/x509certdb;1"].getService( - Ci.nsIX509CertDB - ); - let cert = await IOUtils.readUTF8(do_get_file(path).path); - cert = cert.replace("-----BEGIN CERTIFICATE-----", ""); - cert = cert.replace("-----END CERTIFICATE-----", ""); - cert = cert.replaceAll(/\s/g, ""); - return certDB.constructX509FromBase64(cert); -} - async function callSocketUtil(hostname, port, socketType, commands) { const proxy = await new Promise(resolve => doProxy(hostname, resolve)); const { promise, resolve, reject } = Promise.withResolvers(); @@ -867,9 +778,11 @@ add_task(async function testGuessConfig() { * the base domain. */ add_task(async function testGuessConfigKnownSubdomains() { - NetworkTestUtils.configureProxy("imap.test.test", 993, imapTLSServer.port); - NetworkTestUtils.configureProxy("pop3.test.test", 995, pop3TLSServer.port); - NetworkTestUtils.configureProxy("smtp.test.test", 465, smtpTLSServer.port); + const [imapServer, pop3Server, smtpServer] = await createServers(this, [ + { ...serverDefs.imap.tls, hostname: "imap.test.test" }, + { ...serverDefs.pop3.tls, hostname: "pop3.test.test" }, + { ...serverDefs.smtp.tls, hostname: "smtp.test.test" }, + ]); const { promise, resolve, reject } = Promise.withResolvers(); GuessConfig.guessConfig( @@ -920,6 +833,9 @@ add_task(async function testGuessConfigKnownSubdomains() { Assert.deepEqual(outgoingAlternatives, []); + imapServer.close(); + pop3Server.close(); + smtpServer.close(); NetworkTestUtils.unconfigureProxy("imap.test.test", 993); NetworkTestUtils.unconfigureProxy("pop3.test.test", 995); NetworkTestUtils.unconfigureProxy("smtp.test.test", 465); diff --git a/mail/components/accountcreation/test/xpcshell/xpcshell.ini b/mail/components/accountcreation/test/xpcshell/xpcshell.ini index a3de07d29d..b1a7e8448f 100644 --- a/mail/components/accountcreation/test/xpcshell/xpcshell.ini +++ b/mail/components/accountcreation/test/xpcshell/xpcshell.ini @@ -1,7 +1,7 @@ [DEFAULT] head = tail = -support-files = certs/* data/* +support-files = data/* prefs = mail.setup.loglevel=Debug diff --git a/mailnews/moz.build b/mailnews/moz.build index b274e45db7..4d15cf9ac0 100644 --- a/mailnews/moz.build +++ b/mailnews/moz.build @@ -58,6 +58,7 @@ TESTING_JS_MODULES.mailnews += [ "test/fakeserver/Maild.sys.mjs", "test/fakeserver/Nntpd.sys.mjs", "test/fakeserver/Pop3d.sys.mjs", + "test/fakeserver/ServerTestUtils.sys.mjs", "test/fakeserver/Smtpd.sys.mjs", "test/resources/IMAPpump.jsm", "test/resources/LocalAccountUtils.jsm", @@ -68,6 +69,12 @@ TESTING_JS_MODULES.mailnews += [ "test/resources/PromiseTestUtils.jsm", "test/resources/smimeUtils.jsm", ] +TESTING_JS_MODULES.mailnews.certs += [ + "test/fakeserver/certs/expired.cert", + "test/fakeserver/certs/expired.key", + "test/fakeserver/certs/valid.cert", + "test/fakeserver/certs/valid.key", +] if "comm" in CONFIG["MOZ_BUILD_APP"]: test_harness_base = TEST_HARNESS_FILES.xpcshell.comm diff --git a/mailnews/test/fakeserver/Pop3d.sys.mjs b/mailnews/test/fakeserver/Pop3d.sys.mjs index 5d6966dc49..4bb70c859c 100644 --- a/mailnews/test/fakeserver/Pop3d.sys.mjs +++ b/mailnews/test/fakeserver/Pop3d.sys.mjs @@ -111,8 +111,10 @@ export class POP3_RFC1939_handler { kUsername = "fred"; kPassword = "wilma"; - constructor(daemon) { + constructor(daemon, { username = "fred", password = "wilma" } = {}) { this._daemon = daemon; + this.kUsername = username; + this.kPassword = password; this.closing = false; this.dropOnAuthFailure = false; this._multiline = false; @@ -289,8 +291,8 @@ export class POP3_RFC5034_handler extends POP3_RFC2449_handler { kAuthSchemes = ["CRAM-MD5", "PLAIN", "LOGIN"]; // the test may adapt this as necessary _usedCRAMMD5Challenge = null; // not base64-encoded - constructor(daemon) { - super(daemon); + constructor(daemon, options) { + super(daemon, options); this._kAuthSchemeStartFunction = { "CRAM-MD5": this.authCRAMStart, diff --git a/mailnews/test/fakeserver/ServerTestUtils.sys.mjs b/mailnews/test/fakeserver/ServerTestUtils.sys.mjs new file mode 100644 index 0000000000..50bf45039c --- /dev/null +++ b/mailnews/test/fakeserver/ServerTestUtils.sys.mjs @@ -0,0 +1,225 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at http://mozilla.org/MPL/2.0/. */ + +/** + * Tools for starting test servers. A number of common configurations are + * defined for speedy test creation. + */ + +import { IMAPServer } from "resource://testing-common/IMAPServer.sys.mjs"; +import { POP3Server } from "resource://testing-common/POP3Server.sys.mjs"; +import { SMTPServer } from "resource://testing-common/SMTPServer.sys.mjs"; + +const { NetworkTestUtils } = ChromeUtils.import( + "resource://testing-common/mailnews/NetworkTestUtils.jsm" +); + +const serverConstructors = { + imap: IMAPServer, + pop3: POP3Server, + smtp: SMTPServer, +}; + +// Change this for more server debugging output. See Maild.sys.mjs for values. +const serverDebugLevel = 0; + +/** + * @typedef ServerDef + * @property {"imap"|"pop3"|"smtp"} type - What type of server do we want? + * @property {object} [baseOptions] - In a predefined server, the standard + * set of options to pass to the server's constructor. + * @property {object} [options] - More options, which can override those of a + * predefined server. + * @property {string} hostname - The main hostname for this server. + * @property {integer} port - The main port for this server. + * @property {array of [string, integer]} aliases - Extra hostnames and ports + * for this server. Each entry in this array is an array of [hostname, port]. + */ + +/** + * Create and start a single server. + * + * @param {object} testScope - The environment in which the test is running. + * @param {ServerDef} def - The server definition. + * @returns {IMAPServer|POP3Server|SMTPServer} + */ +async function createServer( + testScope, + { type, baseOptions = {}, options = {}, hostname, port, aliases = [] } +) { + options = { ...baseOptions, ...options }; + if (options.tlsCertFile && !options.tlsCert) { + options.tlsCert = await getCertificate(options.tlsCertFile); + } + + const server = new serverConstructors[type](testScope, options); + server.server.setDebugLevel(serverDebugLevel); + NetworkTestUtils.configureProxy(hostname, port, server.port); + for (const [aliasHostname, aliasPort] of aliases) { + NetworkTestUtils.configureProxy(aliasHostname, aliasPort, server.port); + } + return server; +} + +/** + * Create and start multiple servers. + * + * @param {object} testScope - The environment in which the test is running. + * @param {ServerDef[]} defs - The server definitions. + * @returns {array of IMAPServer|POP3Server|SMTPServer} - The created servers, + * in the same order as the definitions given. + */ +async function createServers(testScope, serverDefs) { + const servers = []; + for (const serverDef of serverDefs) { + servers.push(await createServer(testScope, serverDef)); + } + return servers; +} + +const certCache = new Map(); + +/** + * Load a certificate and key into the certificate database, and return the + * certificate. + * + * @param {string} name - The name of the files to load. There must be a + * corresponding `name.cert` and `name.key` file. + * @returns {nsIX509Cert} + */ +async function getCertificate(name) { + // Already seen this certificate? Just return it. + if (certCache.has(name)) { + return certCache.get(name); + } + + const certDB = Cc["@mozilla.org/security/x509certdb;1"].getService( + Ci.nsIX509CertDB + ); + + // Import `name.key`. We have to use the key file as an nsIFile, so get its + // resource URL and resolve that to a file. + const keyPath = Services.io + .getProtocolHandler("resource") + .QueryInterface(Ci.nsISubstitutingProtocolHandler) + .resolveURI( + Services.io.newURI(`resource://testing-common/mailnews/certs/${name}.key`) + ); + certDB.importPKCS12File( + Services.io.newURI(keyPath).QueryInterface(Ci.nsIFileURL).file, + "" + ); + + // Import `name.cert`. For this we can just fetch the contents. + const response = await fetch( + `resource://testing-common/mailnews/certs/${name}.cert` + ); + let certText = await response.text(); + certText = certText.replace("-----BEGIN CERTIFICATE-----", ""); + certText = certText.replace("-----END CERTIFICATE-----", ""); + certText = certText.replaceAll(/\s/g, ""); + const cert = certDB.addCertFromBase64(certText, "CT,,"); + certCache.set(name, cert); + + return cert; +} + +const serverDefs = { + imap: { + plain: { + type: "imap", + baseOptions: { extensions: ["RFC2195"] }, + hostname: "test.test", + port: 143, + }, + startTLS: { + type: "imap", + baseOptions: { extensions: ["RFC2195"], offerStartTLS: true }, + hostname: "starttls.test.test", + port: 143, + }, + tls: { + type: "imap", + baseOptions: { extensions: ["RFC2195"], tlsCertFile: "valid" }, + hostname: "test.test", + port: 993, + }, + expiredTLS: { + type: "imap", + baseOptions: { extensions: ["RFC2195"], tlsCertFile: "expired" }, + hostname: "expired.test.test", + port: 993, + }, + }, + pop3: { + plain: { + type: "pop3", + baseOptions: { username: "user", password: "password" }, + hostname: "test.test", + port: 110, + }, + startTLS: { + type: "pop3", + baseOptions: { + username: "user", + password: "password", + offerStartTLS: true, + }, + hostname: "starttls.test.test", + port: 110, + }, + tls: { + type: "pop3", + baseOptions: { + username: "user", + password: "password", + tlsCertFile: "valid", + }, + hostname: "test.test", + port: 995, + }, + expiredTLS: { + type: "pop3", + baseOptions: { + username: "user", + password: "password", + tlsCertFile: "expired", + }, + hostname: "expired.test.test", + port: 995, + }, + }, + smtp: { + plain: { + type: "smtp", + hostname: "test.test", + port: 587, + }, + startTLS: { + type: "smtp", + baseOptions: { offerStartTLS: true }, + hostname: "starttls.test.test", + port: 587, + }, + tls: { + type: "smtp", + baseOptions: { tlsCertFile: "valid" }, + hostname: "test.test", + port: 465, + }, + expiredTLS: { + type: "smtp", + baseOptions: { tlsCertFile: "expired" }, + hostname: "expired.test.test", + port: 465, + }, + }, +}; + +export const ServerTestUtils = { + createServer, + createServers, + getCertificate, + serverDefs, +}; diff --git a/mailnews/test/fakeserver/certs/ca.key b/mailnews/test/fakeserver/certs/ca.key new file mode 100644 index 0000000000..09e044f5e0 --- /dev/null +++ b/mailnews/test/fakeserver/certs/ca.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC6iFGoRI4W1kH9 +braIBjYQPTwT2erkNUq07PVoV2wke8HHJajg2B+9sZwGm24ahvJr4q9adWtqZHEI +eqVap0WH9xzVJJwCfs1D/B5p0DggKZOrIMNJ5Nu5TMJrbA7tFYIP8X6taRqx0wI6 +iypB7qdw4A8Njf1mCyuwJJKkfbmIYXmQsVeQPdI7xeC4SB+oN9OIQ+8nFthVt2Za +qn4CkC86exCABiTMHGyXrZZhW7filhLAdTGjDJHdtMr3/K0dJdMJ77kXDqdo4bN7 +LyJvaeO0ipVhHe4m1iWdq5EITjbLHCQELL8Wiy/l8Y+ZFzG4s/5JI/pyUcQx1QOs +2hgKNe2NAgMBAAECggEBAJ7LzjhhpFTsseD+j4XdQ8kvWCXOLpl4hNDhqUnaosWs +VZskBFDlrJ/gw+McDu+mUlpl8MIhlABO4atGPd6e6CKHzJPnRqkZKcXmrD2IdT9s +JbpZeec+XY+yOREaPNq4pLDN9fnKsF8SM6ODNcZLVWBSXn47kq18dQTPHcfLAFeI +r8vh6Pld90AqFRUw1YCDRoZOs3CqeZVqWHhiy1M3kTB/cNkcltItABppAJuSPGgz +iMnzbLm16+ZDAgQceNkIIGuHAJy4yrrK09vbJ5L7kRss9NtmA1hb6a4Mo7jmQXqg +SwbkcOoaO1gcoDpngckxW2KzDmAR8iRyWUbuxXxtlEECgYEA3W4dT//r9o2InE0R +TNqqnKpjpZN0KGyKXCmnF7umA3VkTVyqZ0xLi8cyY1hkYiDkVQ12CKwn1Vttt0+N +gSfvj6CQmLaRR94GVXNEfhg9Iv59iFrOtRPZWB3V4HwakPXOCHneExNx7O/JznLp +xD3BJ9I4GQ3oEXc8pdGTAfSMdCsCgYEA16dz2evDgKdn0v7Ak0rU6LVmckB3Gs3r +ta15b0eP7E1FmF77yVMpaCicjYkQL63yHzTi3UlA66jAnW0fFtzClyl3TEMnXpJR +3b5JCeH9O/Hkvt9Go5uLODMo70rjuVuS8gcK8myefFybWH/t3gXo59hspXiG+xZY +EKd7mEW8MScCgYEAlkcrQaYQwK3hryJmwWAONnE1W6QtS1oOtOnX6zWBQAul3RMs +2xpekyjHu8C7sBVeoZKXLt+X0SdR2Pz2rlcqMLHqMJqHEt1OMyQdse5FX8CT9byb +WS11bmYhR08ywHryL7J100B5KzK6JZC7smGu+5WiWO6lN2VTFb6cJNGRmS0CgYAo +tFCnp1qFZBOyvab3pj49lk+57PUOOCPvbMjo+ibuQT+LnRIFVA8Su+egx2got7pl +rYPMpND+KiIBFOGzXQPVqFv+Jwa9UPzmz83VcbRspiG47UfWBbvnZbCqSgZlrCU2 +TaIBVAMuEgS4VZ0+NPtbF3yaVv+TUQpaSmKHwVHeLQKBgCgGe5NVgB0u9S36ltit +tYlnPPjuipxv9yruq+nva+WKT0q/BfeIlH3IUf2qNFQhR6caJGv7BU7naqNGq80m +ks/J5ExR5vBpxzXgc7oBn2pyFJYckbJoccrqv48GRBigJpDjmo1f8wZ7fNt/ULH1 +NBinA5ZsT8d0v3QCr2xDJH9D +-----END PRIVATE KEY----- diff --git a/mail/components/accountcreation/test/xpcshell/certs/expired.ca.keyspec b/mailnews/test/fakeserver/certs/ca.key.keyspec similarity index 100% rename from mail/components/accountcreation/test/xpcshell/certs/expired.ca.keyspec rename to mailnews/test/fakeserver/certs/ca.key.keyspec diff --git a/mail/components/accountcreation/test/xpcshell/certs/expired b/mailnews/test/fakeserver/certs/expired.cert similarity index 100% rename from mail/components/accountcreation/test/xpcshell/certs/expired rename to mailnews/test/fakeserver/certs/expired.cert diff --git a/mail/components/accountcreation/test/xpcshell/certs/expired.certspec b/mailnews/test/fakeserver/certs/expired.cert.certspec similarity index 100% rename from mail/components/accountcreation/test/xpcshell/certs/expired.certspec rename to mailnews/test/fakeserver/certs/expired.cert.certspec diff --git a/mailnews/test/fakeserver/certs/expired.key b/mailnews/test/fakeserver/certs/expired.key new file mode 100644 index 0000000000..7593682da6 Binary files /dev/null and b/mailnews/test/fakeserver/certs/expired.key differ diff --git a/mailnews/test/fakeserver/certs/readme.txt b/mailnews/test/fakeserver/certs/readme.txt new file mode 100644 index 0000000000..dee672ef77 --- /dev/null +++ b/mailnews/test/fakeserver/certs/readme.txt @@ -0,0 +1,6 @@ +To add a new certificate, make a file names foo.cert.certspec, then run: +- mach generate-test-certs foo.cert.certspec +- openssl pkcs12 -export -inkey ca.key -in foo.cert -name foo -out foo.key + +This will generate foo.cert and foo.key. All three files should be checked in. +See ServerTestUtils.sys.mjs to see how to use the files. diff --git a/mail/components/accountcreation/test/xpcshell/certs/ok b/mailnews/test/fakeserver/certs/valid.cert similarity index 100% rename from mail/components/accountcreation/test/xpcshell/certs/ok rename to mailnews/test/fakeserver/certs/valid.cert diff --git a/mail/components/accountcreation/test/xpcshell/certs/ok.certspec b/mailnews/test/fakeserver/certs/valid.cert.certspec similarity index 100% rename from mail/components/accountcreation/test/xpcshell/certs/ok.certspec rename to mailnews/test/fakeserver/certs/valid.cert.certspec diff --git a/mailnews/test/fakeserver/certs/valid.key b/mailnews/test/fakeserver/certs/valid.key new file mode 100644 index 0000000000..f7189a36ab Binary files /dev/null and b/mailnews/test/fakeserver/certs/valid.key differ