Validate password before saving in the intro

Fixes #593
This commit is contained in:
Jakob Nixdorf 2021-03-11 20:21:15 +01:00
parent c14f842718
commit 74c4add564
No known key found for this signature in database
GPG key ID: BE99BF86574A7DBC
5 changed files with 93 additions and 31 deletions

View file

@ -25,12 +25,13 @@ package org.shadowice.flocke.andotp.Activities;
import android.animation.ArgbEvaluator;
import android.animation.ObjectAnimator;
import android.app.KeyguardManager;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.os.Bundle;
import android.text.Editable;
import android.text.InputType;
import android.text.TextWatcher;
import android.text.method.PasswordTransformationMethod;
import android.util.SparseArray;
import android.view.KeyEvent;
import android.view.LayoutInflater;
@ -42,10 +43,11 @@ import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.Spinner;
import android.widget.Switch;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.widget.SwitchCompat;
import androidx.fragment.app.Fragment;
import androidx.viewpager.widget.ViewPager;
import com.google.android.material.textfield.TextInputEditText;
@ -69,23 +71,53 @@ public class IntroScreenActivity extends IntroActivity {
private AuthenticationFragment authenticationFragment;
private AndroidSyncFragment androidSyncFragment;
private boolean setupFinished = false;
private void saveSettings() {
Constants.EncryptionType encryptionType = encryptionFragment.getEncryptionType();
Constants.AuthMethod authMethod = authenticationFragment.getAuthMethod();
String password = null;
if (authMethod == Constants.AuthMethod.PASSWORD || authMethod == Constants.AuthMethod.PIN) {
password = authenticationFragment.getPassword();
if (password == null || password.isEmpty()) {
SimpleSlide finalSlide = (SimpleSlide) getSlide(getCount() - 1);
if (finalSlide != null) {
Fragment finalFragment = finalSlide.getFragment();
if (finalFragment != null) {
View finalView = finalFragment.getView();
if (finalView != null) {
TextView title = finalView.findViewById(R.id.mi_title);
TextView desc = finalView.findViewById(R.id.mi_description);
title.setText(R.string.intro_slide4_title_failed);
desc.setText(R.string.intro_slide4_desc_failed);
}
}
}
return;
}
}
settings.setEncryption(encryptionType);
settings.setAuthMethod(authMethod);
settings.setAndroidBackupServiceEnabled(androidSyncFragment.getSyncEnabled());
if (authMethod == Constants.AuthMethod.PASSWORD || authMethod == Constants.AuthMethod.PIN) {
String password = authenticationFragment.getPassword();
if (authMethod == Constants.AuthMethod.PASSWORD || authMethod == Constants.AuthMethod.PIN)
settings.setAuthCredentials(password);
}
settings.setFirstTimeWarningShown(true);
setupFinished = true;
}
@Override protected void onCreate(Bundle savedInstanceState){
@Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
settings = new Settings(this);
@ -141,7 +173,6 @@ public class IntroScreenActivity extends IntroActivity {
.build()
);
addOnNavigationBlockedListener((position, direction) -> {
if (position == 2)
authenticationFragment.flashWarning();
@ -150,7 +181,7 @@ public class IntroScreenActivity extends IntroActivity {
addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageSelected(int position) {
if (position == getSlides().size() - 1)
if (position == getCount() - 1)
saveSettings();
}
@ -164,6 +195,13 @@ public class IntroScreenActivity extends IntroActivity {
});
}
@Override
public Intent onSendActivityResult(int result) {
Intent data = new Intent();
data.putExtra(Constants.EXTRA_INTRO_FINISHED, setupFinished);
return data;
}
@Override
public void onBackPressed() {
// We don't want users to quit the intro screen and end up in an uninitialized state
@ -236,8 +274,8 @@ public class IntroScreenActivity extends IntroActivity {
}
public static class AndroidSyncFragment extends SlideFragment {
private Switch introAndroidSync;
private EncryptionFragment encryptionFragment;
private SwitchCompat introAndroidSync;
private final EncryptionFragment encryptionFragment;
public AndroidSyncFragment(EncryptionFragment encryptionFragment) {
this.encryptionFragment = encryptionFragment;
@ -254,12 +292,10 @@ public class IntroScreenActivity extends IntroActivity {
View root = inflater.inflate(R.layout.component_intro_android_sync, container, false);
introAndroidSync = root.findViewById(R.id.introAndroidSync);
introAndroidSync.setOnCheckedChangeListener((compoundButton, b) -> {
compoundButton.setText( b ?
R.string.settings_toast_android_sync_enabled :
R.string.settings_toast_android_sync_disabled
);
});
introAndroidSync.setOnCheckedChangeListener((compoundButton, b) -> compoundButton.setText( b ?
R.string.settings_toast_android_sync_enabled :
R.string.settings_toast_android_sync_disabled
));
introAndroidSync.setChecked(encryptionFragment.getEncryptionType() != Constants.EncryptionType.KEYSTORE);
introAndroidSync.setEnabled(encryptionFragment.getEncryptionType() != Constants.EncryptionType.KEYSTORE);
@ -322,6 +358,7 @@ public class IntroScreenActivity extends IntroActivity {
selectionMapping.put(i, authValues[i]);
}
@SuppressWarnings("SameParameterValue")
private void updateWarning(int resId) {
updateWarning(getString(resId));
}
@ -355,7 +392,10 @@ public class IntroScreenActivity extends IntroActivity {
}
public String getPassword() {
return passwordInput.getText().toString();
if (passwordInput.getText() != null)
return passwordInput.getText().toString();
else
return null;
}
@Override
@ -502,13 +542,11 @@ public class IntroScreenActivity extends IntroActivity {
if (EditorActionHelper.isActionDoneOrKeyboardEnter(actionId, event)) {
nextSlide();
return true;
} else if (EditorActionHelper.isActionUpKeyboardEnter(event)) {
} else {
// Ignore action up after keyboard enter. Otherwise the go-back button would be selected
// after pressing enter with an invalid password.
return true;
return EditorActionHelper.isActionUpKeyboardEnter(event);
}
return false;
}
@Override
@ -516,20 +554,26 @@ public class IntroScreenActivity extends IntroActivity {
Constants.AuthMethod authMethod = selectionMapping.get(selection.getSelectedItemPosition());
if (authMethod == Constants.AuthMethod.PIN || authMethod == Constants.AuthMethod.PASSWORD) {
String password = passwordInput.getText().toString();
String password = null;
if (passwordInput.getText() != null)
password = passwordInput.getText().toString();
String confirm = passwordConfirm.getText().toString();
if (! password.isEmpty()) {
if (password != null && !password.isEmpty()) {
if (password.length() < minLength) {
updateWarning(lengthWarning);
return false;
} else {
if (! confirm.isEmpty() && confirm.equals(password)) {
hideWarning();
return true;
} else if (! confirm.isEmpty() && ! confirm.equals(password)) {
updateWarning(passwordMismatchWarning);
return false;
if (!confirm.isEmpty()) {
if (confirm.equals(password)) {
hideWarning();
return true;
} else {
updateWarning(passwordMismatchWarning);
return false;
}
} else {
updateWarning(confirmPasswordWarning);
return false;
@ -540,7 +584,11 @@ public class IntroScreenActivity extends IntroActivity {
return false;
}
} else if (authMethod == Constants.AuthMethod.DEVICE) {
KeyguardManager km = (KeyguardManager) getContext().getSystemService(KEYGUARD_SERVICE);
Context context = getContext();
if (context == null)
return false;
KeyguardManager km = (KeyguardManager) context.getSystemService(KEYGUARD_SERVICE);
if (! km.isKeyguardSecure()) {
updateWarning(R.string.settings_toast_auth_device_not_secure);

View file

@ -538,6 +538,14 @@ public class MainActivity extends BaseActivity
if (intent != null) {
addQRCode(ScanQRCodeFromFile.scanQRImage(this, intent.getData()));
}
} else if (requestCode == Constants.INTENT_MAIN_INTRO) {
boolean setupFinished = false;
if (resultCode == RESULT_OK && intent != null)
setupFinished = intent.getBooleanExtra(Constants.EXTRA_INTRO_FINISHED, false);
if (!setupFinished)
finishAndRemoveTask();
}
}

View file

@ -99,6 +99,8 @@ public class Constants {
public final static String EXTRA_BACKUP_ENCRYPTION_KEY = "encryption_key";
public final static String EXTRA_INTRO_FINISHED = "setup_finished";
public final static String EXTRA_SETTINGS_ENCRYPTION_CHANGED = "encryption_changed";
public final static String EXTRA_SETTINGS_ENCRYPTION_KEY = "encryption_key";

View file

@ -26,7 +26,7 @@
android:layout_marginTop="@dimen/activity_margin"
android:text="@string/intro_slide_android_backup_desc"/>
<Switch
<androidx.appcompat.widget.SwitchCompat
android:id="@+id/introAndroidSync"
android:layout_width="match_parent"
android:layout_height="wrap_content"

View file

@ -38,7 +38,11 @@
<string name="intro_slide3_warn_pin_mismatch">Pins must match!</string>
<string name="intro_slide4_title">Finished</string>
<string name="intro_slide4_title_failed">Setup failed</string>
<string name="intro_slide4_desc_failed">Failed to set a password, this intro will be shown again
the next time!</string>
<string name="intro_slide4_desc">Your settings have been saved, you are now all set to use
<b>andOTP</b>!</string>
<string name="intro_slide_android_backup_desc">Android sync is a feature built in to android used to back up app data to a 3rd party service (usually Google). Backups are always encrypted and unaccessible to 3rd parties without your master password. Requires use of Password encryption method.</string>
</resources>