Merge pull request #2144 from k9mail/GH-2134_authentication_failure_handling

Handle connection closing after authentication failure
This commit is contained in:
cketti 2017-01-31 20:17:57 +01:00 committed by GitHub
commit 3bd84de9c9
4 changed files with 59 additions and 5 deletions

View file

@ -465,6 +465,10 @@ class ImapConnection {
try {
saslAuthPlain();
} catch (AuthenticationFailedException e) {
if (!isConnected()) {
throw e;
}
login();
}
}
@ -486,6 +490,10 @@ class ImapConnection {
try {
extractCapabilities(responseParser.readStatusResponse(tag, command, getLogId(), null));
} catch (NegativeImapResponseException e) {
if (e.wasByeResponseReceived()) {
close();
}
throw new AuthenticationFailedException(e.getMessage());
}
}

View file

@ -118,8 +118,7 @@ class ImapResponseParser {
if (response.size() < 1 || !equalsIgnoreCase(response.get(0), Responses.OK)) {
String message = "Command: " + commandToLog + "; response: " + response.toString();
String alertText = AlertResponse.getAlertText(response);
throw new NegativeImapResponseException(message, alertText);
throw new NegativeImapResponseException(message, responses);
}
return responses;

View file

@ -1,18 +1,39 @@
package com.fsck.k9.mail.store.imap;
import java.util.List;
import com.fsck.k9.mail.MessagingException;
import static com.fsck.k9.mail.store.imap.ImapResponseParser.equalsIgnoreCase;
class NegativeImapResponseException extends MessagingException {
private static final long serialVersionUID = 3725007182205882394L;
private final String alertText;
private final List<ImapResponse> responses;
private String alertText;
public NegativeImapResponseException(String message, String alertText) {
public NegativeImapResponseException(String message, List<ImapResponse> responses) {
super(message, true);
this.alertText = alertText;
this.responses = responses;
}
public String getAlertText() {
if (alertText == null) {
ImapResponse lastResponse = responses.get(responses.size() - 1);
alertText = AlertResponse.getAlertText(lastResponse);
}
return alertText;
}
public boolean wasByeResponseReceived() {
for (ImapResponse response : responses) {
if (response.getTag() == null && response.size() >= 1 && equalsIgnoreCase(response.get(0), Responses.BYE)) {
return true;
}
}
return false;
}
}

View file

@ -199,6 +199,32 @@ public class ImapConnectionTest {
server.verifyInteractionCompleted();
}
@Test
public void open_authPlainWithByeResponseAndConnectionClose_shouldThrowAuthenticationFailedException()
throws Exception {
settings.setAuthType(AuthType.PLAIN);
MockImapServer server = new MockImapServer();
preAuthenticationDialog(server, "AUTH=PLAIN");
server.expect("2 AUTHENTICATE PLAIN");
server.output("+");
server.expect(ByteString.encodeUtf8("\000" + USERNAME + "\000" + PASSWORD).base64());
server.output("* BYE Go away");
server.output("2 NO Login Failure");
server.closeConnection();
ImapConnection imapConnection = startServerAndCreateImapConnection(server);
try {
imapConnection.open();
fail("Expected exception");
} catch (AuthenticationFailedException e) {
//FIXME: improve exception message
assertThat(e.getMessage(), containsString("Login Failure"));
}
server.verifyConnectionClosed();
server.verifyInteractionCompleted();
}
@Test
public void open_authPlainWithoutAuthPlainCapability_shouldUseLoginMethod() throws Exception {
settings.setAuthType(AuthType.PLAIN);