From 2981485551237b52c75cc702d5dc0d17949b7707 Mon Sep 17 00:00:00 2001 From: Kevin Locke Date: Wed, 4 Sep 2013 15:29:17 -0600 Subject: [PATCH 1/2] Fix for servers with LOGINDISABLED before STARTTLS When connecting to a server that advertises LOGINDISABLED in its CAPABILITIES before STARTTLS, the connection raises an error and destroys the socket before completing STARTTLS. This is demonstrated in the following debug output: debug: [connection] Connected to host debug: <= '* OK [CAPABILITY IMAP4rev1 LITERAL+ SASL-IR LOGIN-REFERRALS ID ENABLE IDLE STARTTLS LOGINDISABLED] Dovecot ready.' debug: => 'A0 CAPABILITY' debug: <= '* CAPABILITY IMAP4rev1 LITERAL+ SASL-IR LOGIN-REFERRALS ID ENABLE IDLE STARTTLS LOGINDISABLED' debug: <= 'A0 OK Pre-login capabilities listed, post-login capabilities have more.' error: Error: Logging in is disabled on this server source=authentication debug: [connection] Closed It appears that a return after _starttls was overlooked (since _starttls will call _login again once the STARTTLS has completed). Signed-off-by: Kevin Locke --- lib/Connection.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/Connection.js b/lib/Connection.js index 11ea916..f60772e 100644 --- a/lib/Connection.js +++ b/lib/Connection.js @@ -1463,8 +1463,10 @@ Connection.prototype._login = function() { if (self.serverSupports('STARTTLS') && (self._config.autotls === 'always' || (self._config.autotls === 'required' - && self.serverSupports('LOGINDISABLED')))) + && self.serverSupports('LOGINDISABLED')))) { self._starttls(); + return; + } if (self.serverSupports('LOGINDISABLED')) { err = new Error('Logging in is disabled on this server'); From b73f325327b43bf1501208bc75f328d990bcf289 Mon Sep 17 00:00:00 2001 From: Kevin Locke Date: Wed, 4 Sep 2013 15:52:18 -0600 Subject: [PATCH 2/2] Reattach 'readable' event listener when changing streams Parser was not unregistering the 'readable' event listener from the old socket, nor registering it to the new socket when setSocket() was called. This caused event handling to stop during the STARTTLS handoff. Signed-off-by: Kevin Locke --- lib/Parser.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/lib/Parser.js b/lib/Parser.js index bed817d..4e8c807 100644 --- a/lib/Parser.js +++ b/lib/Parser.js @@ -40,8 +40,6 @@ function Parser(stream, debug) { this._ignoreReadable = false; this.debug = debug; - this.setStream(stream); - var self = this; this._cbReadable = function() { if (self._ignoreReadable) @@ -51,12 +49,18 @@ function Parser(stream, debug) { else self._tryread(); }; - this._stream.on('readable', this._cbReadable); + + this.setStream(stream); + process.nextTick(this._cbReadable); } inherits(Parser, EventEmitter); Parser.prototype.setStream = function(stream) { + if (this._stream) { + this._stream.removeListener('readable', this._cbReadable); + } + if (/^v0\.8\./.test(process.version)) { this._stream = (new ReadableStream()).wrap(stream); @@ -66,6 +70,8 @@ Parser.prototype.setStream = function(stream) { stream._events.error.pop(); } else this._stream = stream; + + this._stream.on('readable', this._cbReadable); }; Parser.prototype._tryread = function(n) {