Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

[B2G][Email] POP3 account creation hangs when an incorrect password is used with a POP3 server that immediately disconnects on incorrect password (ex: aol.com POP3 server) #283

Merged
merged 1 commit into from

1 participant

@mcav
Collaborator

No description provided.

@mcav mcav [B2G][Email] POP3 account creation hangs when an incorrect password i…
…s used with a POP3 server that immediately disconnects on incorrect password (ex: aol.com POP3 server) r=asuth
78755e5
@mcav mcav merged commit 4e359e8 into mozilla-b2g:master
@mcav mcav deleted the mcav:pop3-connection-drop branch
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Jan 22, 2014
  1. @mcav

    [B2G][Email] POP3 account creation hangs when an incorrect password i…

    mcav authored
    …s used with a POP3 server that immediately disconnects on incorrect password (ex: aol.com POP3 server) r=asuth
This page is out of date. Refresh to see the latest.
View
5 data/lib/pop3/pop3.js
@@ -195,6 +195,11 @@ function(module, exports, log, net, crypto,
});
}.bind(this));
+ this.socket.on('close', function() {
+ this.protocol.onclose();
+ this.die();
+ }.bind(this));
+
// To track requests/responses in the presence of a server
// greeting, store an empty request here. Our request/response
// matching logic will pair the server's greeting with this
View
36 data/lib/pop3/transport.js
@@ -237,6 +237,16 @@ define(['exports'], function(exports) {
}
/**
+ * Trigger the response callback with '-ERR desc\r\n'.
+ */
+ Request.prototype._respondWithError = function(desc) {
+ var rsp = new Response([textEncoder.encode(
+ '-ERR ' + desc + '\r\n')], false);
+ rsp.request = this;
+ this.onresponse(rsp, null);
+ }
+
+ /**
* Couple a POP3 parser with a request/response model, such that
* you can easily hook Pop3Protocol up to a socket (or other
* transport) to get proper request/response semantics.
@@ -253,6 +263,7 @@ define(['exports'], function(exports) {
this.unsentRequests = []; // if not pipelining, queue requests one at a time
this.pipeline = false;
this.pendingRequests = [];
+ this.closed = false;
}
exports.Response = Response;
@@ -280,6 +291,12 @@ define(['exports'], function(exports) {
} else {
req = new Request(cmd, args, expectMultiline, cb);
}
+
+ if (this.closed) {
+ req._respondWithError('(request sent after connection closed)');
+ return;
+ }
+
if (this.pipeline || this.pendingRequests.length === 0) {
this.onsend(req.toByteArray());
this.pendingRequests.push(req);
@@ -323,4 +340,23 @@ define(['exports'], function(exports) {
}
}
}
+
+ /**
+ * Call this function when the socket attached to this protocol is
+ * closed. Any current requests that have been enqueued but not yet
+ * responded to will be sent a dummy "-ERR" response, indicating
+ * that the underlying connection closed without actually
+ * responding. This avoids the case where we hang if we never
+ * receive a response from the server.
+ */
+ Pop3Protocol.prototype.onclose = function() {
+ this.closed = true;
+ var requestsToRespond = this.pendingRequests.concat(this.unsentRequests);
+ this.pendingRequests = [];
+ this.unsentRequests = [];
+ for (var i = 0; i < requestsToRespond.length; i++) {
+ var req = requestsToRespond[i];
+ req._respondWithError('(connection closed, no response)');
+ }
+ }
});
View
2  package.json
@@ -23,7 +23,7 @@
"url": "https://github.com/mozilla-b2g/gaia-email-libs-and-more/issues"
},
"devDependencies": {
- "mail-fakeservers": "~0.0.12",
+ "mail-fakeservers": "~0.0.13",
"mozilla-download": "~0.4"
}
}
View
8 test/unit/resources/fault_injecting_socket.js
@@ -225,8 +225,10 @@ FawltySocket.prototype = {
// from it.
this._queueEvent('close');
this._queueEvent('end');
- this._sock.end();
- this._sock = null;
+ if (this._sock) {
+ this._sock.end();
+ this._sock = null;
+ }
FawltySocketFactory.__deadSocket(this);
break;
case 'detach':
@@ -274,7 +276,7 @@ FawltySocket.prototype = {
if (!this._sock) {
sendText = new TextDecoder('utf-8').decode(data);
- console.log('Ignoring send beacuse no sock or watch:', sendText);
+ console.log('Ignoring send because no sock or watch:', sendText);
return null;
}
View
7 test/unit/resources/th_fake_pop3_server.js
@@ -289,6 +289,13 @@ var TestFakePOP3ServerMixins = {
credentials: newCreds
});
},
+
+ setDropOnAuthFailure: function(dropOnAuthFailure) {
+ return this._backdoor({
+ command: 'setDropOnAuthFailure',
+ dropOnAuthFailure: dropOnAuthFailure
+ });
+ }
};
View
48 test/unit/test_account_bad_password_error.js
@@ -49,6 +49,16 @@ TD.commonCase('reports bad password', function(T, RT) {
});
}
+ /**
+ * Set whether or not the server will drop the connection after
+ * failed authentication.
+ */
+ function setDropOnAuthFailure(dropOnAuthFailure) {
+ T.action('set dropOnAuthFailure = ', dropOnAuthFailure.toString(),
+ eCheck, function() {
+ testAccount.testServer.setDropOnAuthFailure(dropOnAuthFailure);
+ });
+ }
T.group('use bad password on initial connect');
changeServerPassword('newPassword1', 'mismatch');
@@ -80,6 +90,44 @@ TD.commonCase('reports bad password', function(T, RT) {
}).timeoutMS = 5000;
+ if (testAccount.type === 'pop3') {
+ T.group('pop3 handles connection drop on auth failure');
+ // clear problems from the previous failure so that we still
+ // receive proper onbadlogin events below
+ T.action('clear account problems', eCheck, function() {
+ var acct = testUniverse.allAccountsSlice.items[0];
+ acct.clearProblems();
+ });
+
+ setDropOnAuthFailure(true);
+ changeServerPassword('newPassword1', 'mismatch');
+ T.action('create connection, should fail, generate MailAPI event',
+ eCheck, testAccount.eBackoff, function() {
+ eCheck.expect_namedValue('accountCheck:err', true);
+ eCheck.expect_namedValue('account:enabled', false);
+ eCheck.expect_namedValue('account:problems',
+ ['bad-user-or-pass', 'connection']);
+ eCheck.expect_event('badlogin');
+
+ testUniverse.MailAPI.onbadlogin = function(acct) {
+ eCheck.event('badlogin');
+ };
+
+ testAccount.folderAccount.checkAccount(function(err) {
+ eCheck.namedValue('accountCheck:err', !!err);
+ eCheck.namedValue('account:enabled',
+ testAccount.folderAccount.enabled);
+ eCheck.namedValue('account:problems',
+ (testAccount.compositeAccount ||
+ testAccount.folderAccount).problems);
+ });
+
+ }).timeoutMS = 5000;
+
+ // reset it back to normal
+ setDropOnAuthFailure(false);
+ }
+
T.group('use good password on initial connect');
changeClientPassword('newPassword1', 'match');
View
48 test/unit/test_incoming_prober.js
@@ -381,6 +381,54 @@ TD.commonCase('POP3 selects preferredAuthMethod', function(T, RT) {
});
+/**
+ * Some servers (ex: aol.com) will hang-up on us on an auth error with a bad
+ * password.
+ */
+TD.commonCase('POP3 bad creds on server that hangs up', function(T, RT) {
+ if (RT.envOptions.type !== 'pop3') { return; }
+
+ $th_main.thunkConsoleForNonTestUniverse();
+ var eCheck = T.lazyLogger('check'),
+ prober = null;
+
+ var fireTimeout = thunkTimeouts(eCheck);
+ var cci = makeCredsAndConnInfo();
+
+ cci.connInfo.port = PORT;
+
+ T.action(eCheck, 'hangup gives bad-user-or-pass', function() {
+ var precommands = [];
+ precommands.push({
+ match: /AUTH/,
+ actions: [
+ {
+ cmd: 'fake-receive',
+ data: '-ERR\r\n',
+ },
+ {
+ cmd: 'instant-close',
+ }
+ ],
+ });
+ FawltySocketFactory.precommand(
+ HOST, PORT,
+ {
+ cmd: 'fake',
+ data: '+OK hey\r\n',
+ },
+ precommands);
+ eCheck.expect_namedValue('incoming:setTimeout', proberTimeout(RT));
+ prober = new (proberClass(RT))(cci.credentials, cci.connInfo, eCheck._logger);
+ prober.onresult = function(err, conn) {
+ eCheck.namedValue('err', err);
+ };
+ eCheck.expect_event('incoming:clearTimeout');
+ eCheck.expect_namedValue('err', 'bad-user-or-pass');
+ });
+});
+
+
var KEEP_ALIVE_TIMEOUT_MS = 10000;
function cannedLoginTest(T, RT, opts) {
Something went wrong with that request. Please try again.