mirror of
https://github.com/moparisthebest/k-9
synced 2024-11-30 13:12:25 -05:00
Fix Issue 2389: Self signed certificate expiry causes silent send/receive failure.
With this fix, a CertPathValidatorException or CertificateException will create a "Certificate error: Check your server settings" notification in the status bar. When the user clicks on the notification, they are taken to the appropriate server settings screen where they can review their settings and can accept a different server certificate.
This commit is contained in:
parent
ac6c48c2d8
commit
29f15d715d
@ -221,6 +221,8 @@ Please submit bug reports, contribute new features and ask questions at
|
||||
<string name="notification_action_reply">Reply</string>
|
||||
<string name="notification_action_read">Read</string>
|
||||
<string name="notification_action_delete">Delete</string>
|
||||
<string name="notification_certificate_error_title">Certificate error</string>
|
||||
<string name="notification_certificate_error_text">Check your server settings</string>
|
||||
|
||||
<string name="notification_bg_sync_ticker">Checking mail: <xliff:g id="account">%s</xliff:g>:<xliff:g id="folder">%s</xliff:g></string>
|
||||
<string name="notification_bg_sync_title">Checking mail</string>
|
||||
|
@ -345,12 +345,14 @@ public class K9 extends Application {
|
||||
|
||||
|
||||
|
||||
public static final int NOTIFICATION_LED_SENDING_FAILURE_COLOR = 0xffff0000;
|
||||
public static final int NOTIFICATION_LED_FAILURE_COLOR = 0xffff0000;
|
||||
|
||||
// Must not conflict with an account number
|
||||
public static final int FETCHING_EMAIL_NOTIFICATION = -5000;
|
||||
public static final int SEND_FAILED_NOTIFICATION = -1500;
|
||||
public static final int CONNECTIVITY_ID = -3;
|
||||
public static final int CERTIFICATE_EXCEPTION_NOTIFICATION_INCOMING = -4;
|
||||
public static final int CERTIFICATE_EXCEPTION_NOTIFICATION_OUTGOING = -5;
|
||||
|
||||
|
||||
public static class Intents {
|
||||
|
@ -3,6 +3,9 @@ package com.fsck.k9.activity.setup;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Application;
|
||||
import android.app.NotificationManager;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
@ -105,6 +108,7 @@ public class AccountSetupCheckSettings extends K9Activity implements OnClickList
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
clearCertificateErrorNotifications();
|
||||
if (mCheckIncoming) {
|
||||
store = mAccount.getRemoteStore();
|
||||
|
||||
@ -195,6 +199,19 @@ public class AccountSetupCheckSettings extends K9Activity implements OnClickList
|
||||
});
|
||||
}
|
||||
|
||||
private void clearCertificateErrorNotifications() {
|
||||
final Application app = getApplication();
|
||||
final NotificationManager notifMgr = (NotificationManager) app
|
||||
.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
final String uuid = mAccount.getUuid();
|
||||
if (mCheckOutgoing){
|
||||
notifMgr.cancel(uuid, K9.CERTIFICATE_EXCEPTION_NOTIFICATION_OUTGOING);
|
||||
}
|
||||
if (mCheckIncoming){
|
||||
notifMgr.cancel(uuid, K9.CERTIFICATE_EXCEPTION_NOTIFICATION_INCOMING);
|
||||
}
|
||||
}
|
||||
|
||||
private void showErrorDialog(final int msgResId, final Object... args) {
|
||||
mHandler.post(new Runnable() {
|
||||
public void run() {
|
||||
|
@ -33,7 +33,7 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class AccountSetupIncoming extends K9Activity implements OnClickListener {
|
||||
private static final String EXTRA_ACCOUNT = "account";
|
||||
public static final String EXTRA_ACCOUNT = "account";
|
||||
private static final String EXTRA_MAKE_DEFAULT = "makeDefault";
|
||||
|
||||
private static final int[] POP3_PORTS = {
|
||||
|
@ -26,7 +26,7 @@ import java.net.URLEncoder;
|
||||
|
||||
public class AccountSetupOutgoing extends K9Activity implements OnClickListener,
|
||||
OnCheckedChangeListener {
|
||||
private static final String EXTRA_ACCOUNT = "account";
|
||||
public static final String EXTRA_ACCOUNT = "account";
|
||||
|
||||
private static final String EXTRA_MAKE_DEFAULT = "makeDefault";
|
||||
|
||||
|
@ -3280,13 +3280,30 @@ public class MessagingController implements Runnable {
|
||||
PendingIntent pi = PendingIntent.getActivity(mApplication, 0, i, 0);
|
||||
builder.setContentIntent(pi);
|
||||
|
||||
configureNotification(builder, null, null, K9.NOTIFICATION_LED_SENDING_FAILURE_COLOR,
|
||||
configureNotification(builder, null, null, K9.NOTIFICATION_LED_FAILURE_COLOR,
|
||||
K9.NOTIFICATION_LED_BLINK_FAST, true);
|
||||
|
||||
notifMgr.notify(K9.SEND_FAILED_NOTIFICATION - account.getAccountNumber(),
|
||||
builder.build());
|
||||
}
|
||||
|
||||
public void notify(String tag, int id, String title, String text, PendingIntent pi) {
|
||||
final NotificationManager notifMgr = (NotificationManager) mApplication
|
||||
.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
NotificationCompat.Builder builder = new NotificationCompat.Builder(mApplication);
|
||||
builder.setSmallIcon(R.drawable.stat_notify_email_generic);
|
||||
builder.setWhen(System.currentTimeMillis());
|
||||
builder.setAutoCancel(true);
|
||||
builder.setTicker(title);
|
||||
builder.setContentTitle(title);
|
||||
builder.setContentText(text);
|
||||
builder.setContentIntent(pi);
|
||||
configureNotification(builder, null, null,
|
||||
K9.NOTIFICATION_LED_FAILURE_COLOR,
|
||||
K9.NOTIFICATION_LED_BLINK_FAST, true);
|
||||
notifMgr.notify(tag, id, builder.build());
|
||||
}
|
||||
|
||||
/**
|
||||
* Display an ongoing notification while checking for new messages on the server.
|
||||
*
|
||||
|
@ -1,6 +1,18 @@
|
||||
|
||||
package com.fsck.k9.mail;
|
||||
|
||||
import android.app.Application;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Intent;
|
||||
import com.fsck.k9.Account;
|
||||
import com.fsck.k9.K9;
|
||||
import com.fsck.k9.R;
|
||||
import com.fsck.k9.activity.setup.AccountSetupIncoming;
|
||||
import com.fsck.k9.activity.setup.AccountSetupOutgoing;
|
||||
import com.fsck.k9.controller.MessagingController;
|
||||
import java.security.cert.CertPathValidatorException;
|
||||
import java.security.cert.CertificateException;
|
||||
|
||||
public class CertificateValidationException extends MessagingException {
|
||||
public static final long serialVersionUID = -1;
|
||||
|
||||
@ -8,7 +20,44 @@ public class CertificateValidationException extends MessagingException {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public CertificateValidationException(String message, Throwable throwable) {
|
||||
public CertificateValidationException(final String message,
|
||||
Throwable throwable, final Account account, final boolean incoming) {
|
||||
super(message, throwable);
|
||||
/*
|
||||
* We get here because of an SSLException. We are only interested in
|
||||
* creating a notification if the underlying cause is certificate
|
||||
* related.
|
||||
*/
|
||||
while (throwable != null
|
||||
&& !(throwable instanceof CertPathValidatorException)
|
||||
&& !(throwable instanceof CertificateException)) {
|
||||
throwable = throwable.getCause();
|
||||
}
|
||||
if (throwable == null)
|
||||
return;
|
||||
final Application app = K9.app;
|
||||
final String title = app
|
||||
.getString(R.string.notification_certificate_error_title);
|
||||
final String text = app
|
||||
.getString(R.string.notification_certificate_error_text);
|
||||
final Class<?> className;
|
||||
final String extraName;
|
||||
final int id;
|
||||
if (incoming) {
|
||||
className = AccountSetupIncoming.class;
|
||||
extraName = AccountSetupIncoming.EXTRA_ACCOUNT;
|
||||
id = K9.CERTIFICATE_EXCEPTION_NOTIFICATION_INCOMING;
|
||||
} else {
|
||||
className = AccountSetupOutgoing.class;
|
||||
extraName = AccountSetupOutgoing.EXTRA_ACCOUNT;
|
||||
id = K9.CERTIFICATE_EXCEPTION_NOTIFICATION_OUTGOING;
|
||||
}
|
||||
final Intent i = new Intent(app, className);
|
||||
final String uuid = account.getUuid();
|
||||
i.setAction(Intent.ACTION_EDIT);
|
||||
i.putExtra(extraName, uuid);
|
||||
final PendingIntent pi = PendingIntent.getActivity(app, 0, i, 0);
|
||||
MessagingController controller = MessagingController.getInstance(app);
|
||||
controller.notify(uuid, id, title, text, pi);
|
||||
}
|
||||
}
|
@ -14,7 +14,7 @@ public abstract class Transport {
|
||||
public synchronized static Transport getInstance(Account account) throws MessagingException {
|
||||
String uri = account.getTransportUri();
|
||||
if (uri.startsWith("smtp")) {
|
||||
return new SmtpTransport(uri);
|
||||
return new SmtpTransport(account);
|
||||
} else if (uri.startsWith("webdav")) {
|
||||
return new WebDavTransport(account);
|
||||
} else {
|
||||
|
@ -429,6 +429,10 @@ public class ImapStore extends Store {
|
||||
mCombinedPrefix = prefix;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Account getAccount() {
|
||||
return mAccount;
|
||||
}
|
||||
}
|
||||
|
||||
private static final SimpleDateFormat RFC3501_DATE = new SimpleDateFormat("dd-MMM-yyyy", Locale.US);
|
||||
@ -2623,7 +2627,7 @@ public class ImapStore extends Store {
|
||||
|
||||
|
||||
} catch (SSLException e) {
|
||||
throw new CertificateValidationException(e.getMessage(), e);
|
||||
throw new CertificateValidationException(e.getMessage(), e, mSettings.getAccount(), true);
|
||||
} catch (GeneralSecurityException gse) {
|
||||
throw new MessagingException(
|
||||
"Unable to open connection to IMAP server due to security error.", gse);
|
||||
|
@ -391,7 +391,7 @@ public class Pop3Store extends Store {
|
||||
|
||||
mCapabilities = getCapabilities();
|
||||
} catch (SSLException e) {
|
||||
throw new CertificateValidationException(e.getMessage(), e);
|
||||
throw new CertificateValidationException(e.getMessage(), e, mAccount, true);
|
||||
} catch (GeneralSecurityException gse) {
|
||||
throw new MessagingException(
|
||||
"Unable to open connection to POP server due to security error.", gse);
|
||||
|
@ -848,7 +848,7 @@ public class WebDavStore extends Store {
|
||||
response.getStatusLine().toString());
|
||||
}
|
||||
} catch (SSLException e) {
|
||||
throw new CertificateValidationException(e.getMessage(), e);
|
||||
throw new CertificateValidationException(e.getMessage(), e, mAccount, true);
|
||||
} catch (IOException ioe) {
|
||||
Log.e(K9.LOG_TAG, "IOException: " + ioe + "\nTrace: " + processException(ioe));
|
||||
throw new MessagingException("IOException", ioe);
|
||||
|
@ -182,6 +182,7 @@ public class SmtpTransport extends Transport {
|
||||
}
|
||||
|
||||
|
||||
Account mAccount;
|
||||
String mHost;
|
||||
int mPort;
|
||||
String mUsername;
|
||||
@ -194,14 +195,15 @@ public class SmtpTransport extends Transport {
|
||||
private boolean m8bitEncodingAllowed;
|
||||
private int mLargestAcceptableMessage;
|
||||
|
||||
public SmtpTransport(String uri) throws MessagingException {
|
||||
public SmtpTransport(Account account) throws MessagingException {
|
||||
ServerSettings settings;
|
||||
try {
|
||||
settings = decodeUri(uri);
|
||||
settings = decodeUri(account.getTransportUri());
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new MessagingException("Error while decoding transport URI", e);
|
||||
}
|
||||
|
||||
mAccount = account;
|
||||
mHost = settings.host;
|
||||
mPort = settings.port;
|
||||
|
||||
@ -387,7 +389,7 @@ public class SmtpTransport extends Transport {
|
||||
}
|
||||
}
|
||||
} catch (SSLException e) {
|
||||
throw new CertificateValidationException(e.getMessage(), e);
|
||||
throw new CertificateValidationException(e.getMessage(), e, mAccount, false);
|
||||
} catch (GeneralSecurityException gse) {
|
||||
throw new MessagingException(
|
||||
"Unable to open connection to SMTP server due to security error.", gse);
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.fsck.k9.mail.transport.imap;
|
||||
|
||||
import com.fsck.k9.Account;
|
||||
import com.fsck.k9.mail.store.ImapStore;
|
||||
import com.fsck.k9.mail.store.ImapStore.AuthType;
|
||||
import com.fsck.k9.mail.store.ImapStore.ImapConnection;
|
||||
@ -34,4 +35,6 @@ public interface ImapSettings {
|
||||
|
||||
void setCombinedPrefix(String prefix);
|
||||
|
||||
Account getAccount();
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user