Throw CertificateValidationException if EXTERNAL authentication fails
This is done when the SASL EXTERNAL mechanism isn't advertised (indicating the possibility that the server did not accept the client certificate) or when the command for authenticating with SASL EXTERNAL fails. The CertificateValidationException will trigger a notification to the user that there's an authentication problem that needs addressing. Also, there were instances where CertificateValidationException was being thrown with a new CertificateException as the cause for the purpose of notifying the user when STARTTLS is not available. This has been slightly simplified by eliminating the need to include a new CertificateException as a cause.
This commit is contained in:
parent
b557ba008c
commit
301ac48a38
4 changed files with 55 additions and 26 deletions
|
@ -16,7 +16,11 @@ public class CertificateValidationException extends MessagingException {
|
|||
|
||||
public CertificateValidationException(String message) {
|
||||
super(message);
|
||||
scanForCause();
|
||||
/*
|
||||
* Instances created without a Throwable parameter as a cause are
|
||||
* presumed to need user attention.
|
||||
*/
|
||||
mNeedsUserAttention = true;
|
||||
}
|
||||
|
||||
public CertificateValidationException(final String message, Throwable throwable) {
|
||||
|
@ -45,10 +49,9 @@ public class CertificateValidationException extends MessagingException {
|
|||
*
|
||||
* The various mail protocol handlers (IMAP, POP3, ...) will catch an
|
||||
* SSLException and throw a CertificateValidationException (this class)
|
||||
* with the SSLException as the cause. They may also throw a
|
||||
* CertificateValidationException with a new CertificateException as the
|
||||
* cause when STARTTLS is not available, just for the purpose of
|
||||
* triggering a user notification.
|
||||
* with the SSLException as the cause. (They may also throw a
|
||||
* CertificateValidationException when STARTTLS is not available, just
|
||||
* for the purpose of triggering a user notification.)
|
||||
*
|
||||
* SSLHandshakeException is also known to occur if the *client*
|
||||
* certificate was not accepted by the server (unknown CA, certificate
|
||||
|
|
|
@ -26,7 +26,6 @@ import java.nio.charset.CharsetDecoder;
|
|||
import java.nio.charset.CodingErrorAction;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.security.Security;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
@ -2511,8 +2510,7 @@ public class ImapStore extends Store {
|
|||
* "STARTTLS (if available)" setting.
|
||||
*/
|
||||
throw new CertificateValidationException(
|
||||
"STARTTLS connection security not available",
|
||||
new CertificateException());
|
||||
"STARTTLS connection security not available");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2539,12 +2537,10 @@ public class ImapStore extends Store {
|
|||
|
||||
case EXTERNAL:
|
||||
if (hasCapability(CAPABILITY_AUTH_EXTERNAL)) {
|
||||
executeSimpleCommand(
|
||||
String.format("AUTHENTICATE EXTERNAL %s",
|
||||
Utility.base64Encode(mSettings.getUsername())), false);
|
||||
saslAuthExternal();
|
||||
} else {
|
||||
throw new MessagingException(
|
||||
"EXTERNAL authentication not advertised by server");
|
||||
// Provide notification to user of a problem authenticating using client certificates
|
||||
throw new CertificateValidationException(K9.app.getString(R.string.auth_external_error));
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -2729,6 +2725,23 @@ public class ImapStore extends Store {
|
|||
}
|
||||
}
|
||||
|
||||
private void saslAuthExternal() throws IOException, MessagingException {
|
||||
try {
|
||||
receiveCapabilities(executeSimpleCommand(
|
||||
String.format("AUTHENTICATE EXTERNAL %s",
|
||||
Utility.base64Encode(mSettings.getUsername())), false));
|
||||
} catch (ImapException e) {
|
||||
/*
|
||||
* Provide notification to the user of a problem authenticating
|
||||
* using client certificates. We don't use an
|
||||
* AuthenticationFailedException because that would trigger a
|
||||
* "Username or password incorrect" notification in
|
||||
* AccountSetupCheckSettings.
|
||||
*/
|
||||
throw new CertificateValidationException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
protected ImapResponse readContinuationResponse(String tag)
|
||||
throws IOException, MessagingException {
|
||||
ImapResponse response;
|
||||
|
|
|
@ -5,6 +5,7 @@ import android.util.Log;
|
|||
|
||||
import com.fsck.k9.Account;
|
||||
import com.fsck.k9.K9;
|
||||
import com.fsck.k9.R;
|
||||
import com.fsck.k9.controller.MessageRetrievalListener;
|
||||
import com.fsck.k9.helper.Utility;
|
||||
import com.fsck.k9.mail.*;
|
||||
|
@ -20,7 +21,6 @@ import java.net.*;
|
|||
import java.security.GeneralSecurityException;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
|
@ -354,8 +354,7 @@ public class Pop3Store extends Store {
|
|||
* "STARTTLS (if available)" setting.
|
||||
*/
|
||||
throw new CertificateValidationException(
|
||||
"STARTTLS connection security not available",
|
||||
new CertificateException());
|
||||
"STARTTLS connection security not available");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -378,13 +377,11 @@ public class Pop3Store extends Store {
|
|||
|
||||
case EXTERNAL:
|
||||
if (mCapabilities.external) {
|
||||
executeSimpleCommand(
|
||||
String.format("AUTH EXTERNAL %s",
|
||||
Utility.base64Encode(mUsername)), false);
|
||||
} else {
|
||||
throw new MessagingException(
|
||||
"EXTERNAL authentication not advertised by server");
|
||||
}
|
||||
authExternal();
|
||||
} else {
|
||||
// Provide notification to user of a problem authenticating using client certificates
|
||||
throw new CertificateValidationException(K9.app.getString(R.string.auth_external_error));
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -470,6 +467,24 @@ public class Pop3Store extends Store {
|
|||
}
|
||||
}
|
||||
|
||||
private void authExternal() throws MessagingException {
|
||||
try {
|
||||
executeSimpleCommand(
|
||||
String.format("AUTH EXTERNAL %s",
|
||||
Utility.base64Encode(mUsername)), false);
|
||||
} catch (Pop3ErrorResponse e) {
|
||||
/*
|
||||
* Provide notification to the user of a problem authenticating
|
||||
* using client certificates. We don't use an
|
||||
* AuthenticationFailedException because that would trigger a
|
||||
* "Username or password incorrect" notification in
|
||||
* AccountSetupCheckSettings.
|
||||
*/
|
||||
throw new CertificateValidationException(
|
||||
"POP3 client certificate authentication failed: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOpen() {
|
||||
return (mIn != null && mOut != null && mSocket != null
|
||||
|
|
|
@ -26,7 +26,6 @@ import java.io.OutputStream;
|
|||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.*;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.util.*;
|
||||
|
||||
public class SmtpTransport extends Transport {
|
||||
|
@ -300,8 +299,7 @@ public class SmtpTransport extends Transport {
|
|||
* "STARTTLS (if available)" setting.
|
||||
*/
|
||||
throw new CertificateValidationException(
|
||||
"STARTTLS connection security not available",
|
||||
new CertificateException());
|
||||
"STARTTLS connection security not available");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue