Remote wipe logic

This commit is contained in:
M66B 2022-03-07 08:21:19 +01:00
parent df874106ad
commit 7613ad6bbb
6 changed files with 34 additions and 73 deletions

View File

@ -19,17 +19,11 @@ package eu.faircode.email;
Copyright 2018-2022 by Marcel Bokhorst (M66B)
*/
import android.app.ActivityManager;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.text.method.LinkMovementMethod;
import android.view.View;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.TextView;
import java.util.List;
public class ActivityClear extends ActivityBase {
private Button btnClearAll;
@ -49,10 +43,7 @@ public class ActivityClear extends ActivityBase {
btnClearAll.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
am.clearApplicationUserData();
finish();
Helper.clearAll(v.getContext());
}
});

View File

@ -4505,6 +4505,14 @@ class Core {
EntityAccount account, EntityFolder folder, EntityMessage message,
List<EntityRule> rules) {
if (EntityFolder.INBOX.equals(folder.type)) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
String mnemonic = prefs.getString("wipe_mnemonic", null);
if (mnemonic != null && message.subject != null &&
message.subject.toLowerCase(Locale.ROOT).contains(mnemonic))
Helper.clearAll(context);
}
if (account.protocol == EntityAccount.TYPE_IMAP && folder.read_only)
return;
if (!ActivityBilling.isPro(context))

View File

@ -58,9 +58,14 @@ import androidx.preference.PreferenceManager;
import androidx.webkit.WebViewFeature;
import java.io.IOException;
import java.security.SecureRandom;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import io.github.novacrypto.bip39.MnemonicGenerator;
import io.github.novacrypto.bip39.Words;
import io.github.novacrypto.bip39.wordlists.English;
public class FragmentOptionsPrivacy extends FragmentBase implements SharedPreferences.OnSharedPreferenceChangeListener {
private SwitchCompat swConfirmLinks;
private SwitchCompat swCheckLinksDbl;
@ -458,9 +463,14 @@ public class FragmentOptionsPrivacy extends FragmentBase implements SharedPrefer
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean checked) {
if (checked) {
byte[] entropy = MnemonicHelper.generate();
String mnemonic = MnemonicHelper.get(entropy);
prefs.edit().putString("wipe_mnemonic", Helper.hex(entropy)).apply();
// https://github.com/NovaCrypto/BIP39
StringBuilder sb = new StringBuilder();
byte[] entropy = new byte[Words.TWELVE.byteLength()];
new SecureRandom().nextBytes(entropy);
new MnemonicGenerator(English.INSTANCE).createMnemonic(entropy, sb::append);
String mnemonic = sb.toString();
prefs.edit().putString("wipe_mnemonic", mnemonic).apply();
tvMnemonic.setText(mnemonic);
Context context = compoundButton.getContext();
@ -582,7 +592,7 @@ public class FragmentOptionsPrivacy extends FragmentBase implements SharedPrefer
String mnemonic = prefs.getString("wipe_mnemonic", null);
swMnemonic.setChecked(mnemonic != null);
tvMnemonic.setText(mnemonic == null ? null : MnemonicHelper.get(mnemonic));
tvMnemonic.setText(mnemonic);
}
public static class FragmentDialogPin extends FragmentDialogBase {

View File

@ -2570,4 +2570,9 @@ public class Helper {
bundle.writeToParcel(p, 0);
return p.dataSize();
}
static void clearAll(Context context) {
ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
am.clearApplicationUserData();
}
}

View File

@ -2015,8 +2015,12 @@ public class Log {
Map<String, ?> settings = prefs.getAll();
List<String> keys = new ArrayList<>(settings.keySet());
Collections.sort(keys);
for (String key : keys)
size += write(os, key + "=" + settings.get(key) + "\r\n");
for (String key : keys) {
Object value = settings.get(key);
if ("wipe_mnemonic".equals(key) && value != null)
value = "[redacted]";
size += write(os, key + "=" + value + "\r\n");
}
}
db.attachment().setDownloaded(attachment.id, size);

View File

@ -1,57 +0,0 @@
package eu.faircode.email;
/*
This file is part of FairEmail.
FairEmail is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
FairEmail is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with FairEmail. If not, see <http://www.gnu.org/licenses/>.
Copyright 2018-2022 by Marcel Bokhorst (M66B)
*/
import java.security.SecureRandom;
import io.github.novacrypto.bip39.MnemonicGenerator;
import io.github.novacrypto.bip39.Words;
import io.github.novacrypto.bip39.wordlists.English;
public class MnemonicHelper {
// https://github.com/NovaCrypto/BIP39
static String get(byte[] entropy) {
StringBuilder sb = new StringBuilder();
new MnemonicGenerator(English.INSTANCE).createMnemonic(entropy, sb::append);
return sb.toString();
}
static String get(String hex) {
return get(fromHex(hex));
}
static byte[] generate() {
byte[] entropy = new byte[Words.TWELVE.byteLength()];
new SecureRandom().nextBytes(entropy);
return entropy;
}
private static byte[] fromHex(String hex) {
int len = hex.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] =
(byte) ((Character.digit(hex.charAt(i), 16) << 4) +
Character.digit(hex.charAt(i + 1), 16));
}
return data;
}
}