Revision control

Copy as Markdown

Other Tools

/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/**
* Server which advertises CRAM-MD5, but is impolite enough to just
* disconnect (close the TCP connection) when we try it.
*
* This is a tough one, because we may lose state on which auth schemes
* are allowed and which ones failed and may restart from scratch, and
* retry, never skipping the failed scheme.
* Dear server implementors, NEVER DO THAT! Be polite, give an error
* with explanation and by all means keep the connection open.
*
* I don't know if real servers do that, but bienvenu says they exist.
*
* TODO:
* This test shows that the current situation is not good.
* Problems:
* - We should reopen the connection, remember which auth scheme failed
* and start with the next in list, not trying the broken one again.
* We currently neither retry nor remember.
* - incomingServer thinks it is still running/busy although the connection is
* clearly done and over.
*
* @author Ben Bucksch
*/
var server;
var daemon;
var incomingServer;
test =
"Server which advertises CRAM-MD5, but closes the connection when it's tried";
// that's how it currently looks like (we fail to log in):
var expectedTransaction = ["AUTH", "CAPA", "AUTH CRAM-MD5"];
// TODO that's how it should look like (we start a new connection and try another scheme):
// const expectedTransaction = ["AUTH", "CAPA", "AUTH CRAM-MD5", "CAPA", "AUTH PLAIN", "STAT"];
var urlListener = {
OnStartRunningUrl() {},
OnStopRunningUrl(url, result) {
try {
// We should be getting an error here, because we couldn't log in.
Assert.equal(result, Cr.NS_ERROR_FAILURE);
var transaction = server.playTransaction();
do_check_transaction(transaction, expectedTransaction);
do_timeout(0, endTest);
} catch (e) {
server.stop();
var thread = Services.tm.currentThread;
while (thread.hasPendingEvents()) {
thread.processNextEvent(true);
}
do_throw(e);
}
},
};
function endTest() {
// No more tests, let everything finish
server.stop();
var thread = Services.tm.currentThread;
while (thread.hasPendingEvents()) {
thread.processNextEvent(true);
}
do_test_finished();
}
function CRAMFail_handler(daemon_) {
POP3_RFC5034_handler.call(this, daemon_);
this._kAuthSchemeStartFunction["CRAM-MD5"] = this.killConn;
}
CRAMFail_handler.prototype = {
__proto__: POP3_RFC5034_handler.prototype, // inherit
killConn() {
this.closing = true;
return "-ERR I don't feel like it";
},
};
function run_test() {
try {
do_test_pending();
// Disable new mail notifications
Services.prefs.setBoolPref("mail.biff.play_sound", false);
Services.prefs.setBoolPref("mail.biff.show_alert", false);
Services.prefs.setBoolPref("mail.biff.show_tray_icon", false);
Services.prefs.setBoolPref("mail.biff.animate_dock_icon", false);
daemon = new Pop3Daemon();
function createHandler(d) {
return new CRAMFail_handler(d);
}
server = new nsMailServer(createHandler, daemon);
server.start();
incomingServer = createPop3ServerAndLocalFolders(server.port);
const msgServer = incomingServer;
msgServer.QueryInterface(Ci.nsIMsgIncomingServer);
// Need to allow any auth here, although that's not use in TB really,
// because we need to fall back to something after CRAM-MD5 and
// check that login works after we fell back.
msgServer.authMethod = Ci.nsMsgAuthMethod.anything;
MailServices.pop3.GetNewMail(
null,
urlListener,
localAccountUtils.inboxFolder,
incomingServer
);
server.performTest();
} catch (e) {
server.stop();
do_throw(e);
} finally {
var thread = Services.tm.currentThread;
while (thread.hasPendingEvents()) {
thread.processNextEvent(true);
}
}
}