Block accessibility services

This introduces a settings item to block the accessibility services from accessing sensitive fields (passwords, OTP secrets, ...)

TODO: Somehow handle this in the IntroScreenActivity as well.

Closes #210
This commit is contained in:
Jakob Nixdorf 2020-01-30 09:02:17 +01:00
parent 3511b51d1d
commit e65cf038fb
No known key found for this signature in database
GPG key ID: BE99BF86574A7DBC
10 changed files with 44 additions and 3 deletions

View file

@ -89,6 +89,9 @@ public class AuthenticateActivity extends ThemedActivity
TextInputLayout passwordLayout = v.findViewById(R.id.passwordLayout);
passwordInput = v.findViewById(R.id.passwordEdit);
if (settings.getBlockAccessibility())
passwordLayout.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
passwordLabel.setText(labelMsg);
authMethod = settings.getAuthMethod();

View file

@ -458,7 +458,7 @@ public class BackupActivity extends BaseActivity {
String password = settings.getBackupPasswordEnc();
if (password.isEmpty()) {
PasswordEntryDialog pwDialog = new PasswordEntryDialog(this, PasswordEntryDialog.Mode.ENTER, new PasswordEntryDialog.PasswordEnteredCallback() {
PasswordEntryDialog pwDialog = new PasswordEntryDialog(this, PasswordEntryDialog.Mode.ENTER, settings.getBlockAccessibility(), new PasswordEntryDialog.PasswordEnteredCallback() {
@Override
public void onPasswordEntered(String newPassword) {
doRestoreCryptWithPassword(uri, newPassword, old_format);
@ -514,7 +514,7 @@ public class BackupActivity extends BaseActivity {
String password = settings.getBackupPasswordEnc();
if (password.isEmpty()) {
PasswordEntryDialog pwDialog = new PasswordEntryDialog(this, PasswordEntryDialog.Mode.UPDATE, new PasswordEntryDialog.PasswordEnteredCallback() {
PasswordEntryDialog pwDialog = new PasswordEntryDialog(this, PasswordEntryDialog.Mode.UPDATE, settings.getBlockAccessibility(), new PasswordEntryDialog.PasswordEnteredCallback() {
@Override
public void onPasswordEntered(String newPassword) {
doBackupCryptWithPassword(uri, newPassword);

View file

@ -60,6 +60,9 @@ public class ManualEntryDialog {
ViewGroup container = callingActivity.findViewById(R.id.main_content);
View inputView = callingActivity.getLayoutInflater().inflate(R.layout.dialog_manual_entry, container, false);
if (settings.getBlockAccessibility())
inputView.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
final Spinner typeInput = inputView.findViewById(R.id.manual_type);
final EditText issuerInput = inputView.findViewById(R.id.manual_issuer);
final EditText labelInput = inputView.findViewById(R.id.manual_label);

View file

@ -2,6 +2,8 @@ package org.shadowice.flocke.andotp.Dialogs;
import android.content.Context;
import com.google.android.material.textfield.TextInputEditText;
import com.google.android.material.textfield.TextInputLayout;
import androidx.appcompat.app.AppCompatDialog;
import android.text.Editable;
import android.text.TextUtils;
@ -29,15 +31,21 @@ public class PasswordEntryDialog extends AppCompatDialog
private EditText passwordConfirm;
private Button okButton;
public PasswordEntryDialog(Context context, Mode newMode, PasswordEnteredCallback newCallback) {
public PasswordEntryDialog(Context context, Mode newMode, boolean blockAccessibility, PasswordEnteredCallback newCallback) {
super(context, Tools.getThemeResource(context, R.attr.dialogTheme));
setTitle(R.string.dialog_title_enter_password);
setContentView(R.layout.dialog_password_entry);
TextInputLayout passwordLayout = findViewById(R.id.passwordInputLayout);
passwordInput = findViewById(R.id.passwordInput);
passwordConfirm = findViewById(R.id.passwordConfirm);
if (blockAccessibility) {
passwordLayout.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
passwordConfirm.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
}
okButton = findViewById(R.id.buttonOk);
Button cancelButton = findViewById(R.id.buttonCancel);

View file

@ -127,6 +127,11 @@ public class CredentialsPreference extends DialogPreference
passwordInput = view.findViewById(R.id.passwordEdit);
passwordConfirm = view.findViewById(R.id.passwordConfirm);
if (settings.getBlockAccessibility()) {
passwordLayout.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
passwordConfirm.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
}
toShortWarning = view.findViewById(R.id.toShortWarning);
passwordInput.addTextChangedListener(this);

View file

@ -42,6 +42,7 @@ import org.shadowice.flocke.andotp.R;
import org.shadowice.flocke.andotp.Utilities.Constants;
import org.shadowice.flocke.andotp.Utilities.EncryptionHelper;
import org.shadowice.flocke.andotp.Utilities.KeyStoreHelper;
import org.shadowice.flocke.andotp.Utilities.Settings;
import java.nio.charset.StandardCharsets;
import java.security.KeyPair;
@ -92,10 +93,17 @@ public class PasswordEncryptedPreference extends DialogPreference
@Override
protected void onBindDialogView(View view) {
Settings settings = new Settings(getContext());
TextInputLayout passwordLayout = view.findViewById(R.id.passwordLayout);
passwordInput = view.findViewById(R.id.passwordEdit);
passwordConfirm = view.findViewById(R.id.passwordConfirm);
if (settings.getBlockAccessibility()) {
passwordLayout.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
passwordConfirm.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
}
Button btnCancel = view.findViewById(R.id.btnCancel);
btnSave = view.findViewById(R.id.btnSave);
btnSave.setEnabled(false);

View file

@ -311,6 +311,10 @@ public class Settings {
return getBoolean(R.string.settings_key_relock_screen_off, true);
}
public boolean getBlockAccessibility() {
return getBoolean(R.string.settings_key_block_accessibility, false);
}
public void setLocale(String locale) {
setString(R.string.settings_key_locale, locale);
}

View file

@ -16,6 +16,7 @@
<string name="settings_key_encryption" translatable="false">pref_encryption</string>
<string name="settings_key_panic" translatable="false">pref_panic</string>
<string name="settings_key_relock_screen_off" translatable="false">pref_relock_screen_off</string>
<string name="settings_key_block_accessibility" translatable="false">pref_block_accessibility</string>
<string name="settings_key_lang" translatable="false">pref_lang</string> <!-- Deprecated -->
<string name="settings_key_locale" translatable="false">pref_locale</string>

View file

@ -16,6 +16,7 @@
<string name="settings_title_encryption">Database encryption</string>
<string name="settings_title_panic">Panic Trigger</string>
<string name="settings_title_relock_screen_off">Re-lock on screen off</string>
<string name="settings_title_block_accessibility">Block accessibility services</string>
<string name="settings_title_lang">Language</string>
<string name="settings_title_theme">Theme</string>
@ -53,6 +54,8 @@
<string name="settings_desc_panic">Decide what happens when a Panic Trigger is received</string>
<string name="settings_desc_relock_screen_off">Require authentication after the devices screen
has been turned off</string>
<string name="settings_desc_block_accessibility">Hide sensitive fields from the accessibility
services. <b>DO NOT enable this if you rely on the accessibility services!</b></string>
<string name="settings_desc_label_scroll">Scroll overlong labels instead of truncating them</string>
<string name="settings_desc_search_includes">Specify which values should be included when searching</string>

View file

@ -48,6 +48,12 @@
android:summary="@string/settings_desc_relock_screen_off"
android:defaultValue="true" />
<CheckBoxPreference
android:key="@string/settings_key_block_accessibility"
android:title="@string/settings_title_block_accessibility"
android:summary="@string/settings_desc_block_accessibility"
android:defaultValue="false" />
</PreferenceCategory>
<PreferenceCategory