Don't try fallback authentication for non-authentication error responses
This commit is contained in:
parent
231b46f278
commit
c54b95b2c6
5 changed files with 109 additions and 10 deletions
|
@ -376,6 +376,7 @@ class ImapConnection {
|
|||
try {
|
||||
attemptXOAuth2();
|
||||
} catch (NegativeImapResponseException e) {
|
||||
//TODO: Check response code so we don't needlessly invalidate the token.
|
||||
oauthTokenProvider.invalidateToken(settings.getUsername());
|
||||
|
||||
if (!retryXoauth2WithNewToken) {
|
||||
|
@ -456,7 +457,7 @@ class ImapConnection {
|
|||
try {
|
||||
extractCapabilities(responseParser.readStatusResponse(tag, command, getLogId(), null));
|
||||
} catch (NegativeImapResponseException e) {
|
||||
throw new AuthenticationFailedException(e.getMessage());
|
||||
handleAuthenticationFailure(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -489,11 +490,7 @@ class ImapConnection {
|
|||
try {
|
||||
extractCapabilities(responseParser.readStatusResponse(tag, command, getLogId(), null));
|
||||
} catch (NegativeImapResponseException e) {
|
||||
if (e.wasByeResponseReceived()) {
|
||||
close();
|
||||
}
|
||||
|
||||
throw new AuthenticationFailedException(e.getMessage());
|
||||
handleAuthenticationFailure(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -514,7 +511,7 @@ class ImapConnection {
|
|||
String command = String.format(Commands.LOGIN + " \"%s\" \"%s\"", username, password);
|
||||
extractCapabilities(executeSimpleCommand(command, true));
|
||||
} catch (NegativeImapResponseException e) {
|
||||
throw new AuthenticationFailedException(e.getMessage());
|
||||
handleAuthenticationFailure(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -534,6 +531,23 @@ class ImapConnection {
|
|||
}
|
||||
}
|
||||
|
||||
private void handleAuthenticationFailure(NegativeImapResponseException e) throws MessagingException {
|
||||
ImapResponse lastResponse = e.getLastResponse();
|
||||
String responseCode = ResponseCodeExtractor.getResponseCode(lastResponse);
|
||||
|
||||
// If there's no response code we simply assume it was an authentication failure.
|
||||
if (responseCode == null || responseCode.equals(ResponseCodeExtractor.AUTHENTICATION_FAILED)) {
|
||||
if (e.wasByeResponseReceived()) {
|
||||
close();
|
||||
}
|
||||
|
||||
throw new AuthenticationFailedException(e.getMessage());
|
||||
} else {
|
||||
close();
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
private void enableCompressionIfRequested() throws IOException, MessagingException {
|
||||
if (hasCapability(Capabilities.COMPRESS_DEFLATE) && shouldEnableCompression()) {
|
||||
enableCompression();
|
||||
|
|
|
@ -20,7 +20,7 @@ class NegativeImapResponseException extends MessagingException {
|
|||
|
||||
public String getAlertText() {
|
||||
if (alertText == null) {
|
||||
ImapResponse lastResponse = responses.get(responses.size() - 1);
|
||||
ImapResponse lastResponse = getLastResponse();
|
||||
alertText = AlertResponse.getAlertText(lastResponse);
|
||||
}
|
||||
|
||||
|
@ -36,4 +36,8 @@ class NegativeImapResponseException extends MessagingException {
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
public ImapResponse getLastResponse() {
|
||||
return responses.get(responses.size() - 1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
package com.fsck.k9.mail.store.imap;
|
||||
|
||||
|
||||
class ResponseCodeExtractor {
|
||||
public static final String AUTHENTICATION_FAILED = "AUTHENTICATIONFAILED";
|
||||
|
||||
|
||||
private ResponseCodeExtractor() {
|
||||
}
|
||||
|
||||
public static String getResponseCode(ImapResponse response) {
|
||||
if (response.size() < 2 || !response.isList(1)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
ImapList responseTextCode = response.getList(1);
|
||||
return responseTextCode.size() != 1 ? null : responseTextCode.getString(0);
|
||||
}
|
||||
}
|
|
@ -197,6 +197,30 @@ public class ImapConnectionTest {
|
|||
server.verifyInteractionCompleted();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void open_authPlainFailureAndDisconnect_shouldThrow() 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("2 NO [UNAVAILABLE] Maximum number of connections from user+IP exceeded");
|
||||
server.closeConnection();
|
||||
ImapConnection imapConnection = startServerAndCreateImapConnection(server);
|
||||
|
||||
try {
|
||||
imapConnection.open();
|
||||
fail("Expected exception");
|
||||
} catch (NegativeImapResponseException e) {
|
||||
assertThat(e.getMessage(), containsString("Maximum number of connections from user+IP exceeded"));
|
||||
}
|
||||
|
||||
assertFalse(imapConnection.isConnected());
|
||||
server.verifyConnectionClosed();
|
||||
server.verifyInteractionCompleted();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void open_authPlainWithByeResponseAndConnectionClose_shouldThrowAuthenticationFailedException()
|
||||
throws Exception {
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
package com.fsck.k9.mail.store.imap;
|
||||
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static com.fsck.k9.mail.store.imap.ImapResponseHelper.createImapResponse;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
|
||||
|
||||
public class ResponseCodeExtractorTest {
|
||||
@Test
|
||||
public void getResponseCode_withResponseCode() throws Exception {
|
||||
ImapResponse imapResponse = createImapResponse("x NO [AUTHENTICATIONFAILED] No sir");
|
||||
|
||||
String result = ResponseCodeExtractor.getResponseCode(imapResponse);
|
||||
|
||||
assertEquals("AUTHENTICATIONFAILED", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getResponseCode_withoutResponseCode() throws Exception {
|
||||
ImapResponse imapResponse = createImapResponse("x NO Authentication failed");
|
||||
|
||||
String result = ResponseCodeExtractor.getResponseCode(imapResponse);
|
||||
|
||||
assertNull(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getResponseCode_withoutSingleItemResponse() throws Exception {
|
||||
ImapResponse imapResponse = createImapResponse("x NO");
|
||||
|
||||
String result = ResponseCodeExtractor.getResponseCode(imapResponse);
|
||||
|
||||
assertNull(result);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue