Refactor passwords/pins/patterns to byte[]
Relating to packages/apps/Settings Bug: 120484642 Test: manual - test setting and unlocking passwords/pins/patterns. automated - 20 of about 500 tests fail due to fragile synthetic password test code. Change-Id: Idec8338d141c185bef67ade12035fdb2fa9d17ea
This commit is contained in:
@@ -78,6 +78,7 @@ import com.google.android.setupcompat.template.FooterButton;
|
||||
import com.google.android.setupdesign.GlifLayout;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class ChooseLockPassword extends SettingsActivity {
|
||||
@@ -123,7 +124,7 @@ public class ChooseLockPassword extends SettingsActivity {
|
||||
return this;
|
||||
}
|
||||
|
||||
public IntentBuilder setPassword(String password) {
|
||||
public IntentBuilder setPassword(byte[] password) {
|
||||
mIntent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD, password);
|
||||
return this;
|
||||
}
|
||||
@@ -185,8 +186,8 @@ public class ChooseLockPassword extends SettingsActivity {
|
||||
private static final String KEY_CURRENT_PASSWORD = "current_password";
|
||||
private static final String FRAGMENT_TAG_SAVE_AND_FINISH = "save_and_finish_worker";
|
||||
|
||||
private String mCurrentPassword;
|
||||
private String mChosenPassword;
|
||||
private byte[] mCurrentPassword;
|
||||
private byte[] mChosenPassword;
|
||||
private boolean mHasChallenge;
|
||||
private long mChallenge;
|
||||
private ImeAwareEditText mPasswordEntry;
|
||||
@@ -215,7 +216,7 @@ public class ChooseLockPassword extends SettingsActivity {
|
||||
protected boolean mForFingerprint;
|
||||
protected boolean mForFace;
|
||||
|
||||
private String mFirstPin;
|
||||
private byte[] mFirstPin;
|
||||
private RecyclerView mPasswordRestrictionView;
|
||||
protected boolean mIsAlphaMode;
|
||||
protected FooterButton mSkipOrClearButton;
|
||||
@@ -234,7 +235,7 @@ public class ChooseLockPassword extends SettingsActivity {
|
||||
private static final int MIN_NUMBER_IN_PASSWORD = 4;
|
||||
private static final int MIN_NON_LETTER_IN_PASSWORD = 5;
|
||||
|
||||
// Error code returned from {@link #validatePassword(String)}.
|
||||
// Error code returned from {@link #validatePassword(byte[])}.
|
||||
static final int NO_ERROR = 0;
|
||||
static final int CONTAIN_INVALID_CHARACTERS = 1 << 0;
|
||||
static final int TOO_SHORT = 1 << 1;
|
||||
@@ -394,12 +395,13 @@ public class ChooseLockPassword extends SettingsActivity {
|
||||
SaveAndFinishWorker w = new SaveAndFinishWorker();
|
||||
final boolean required = getActivity().getIntent().getBooleanExtra(
|
||||
EncryptionInterstitial.EXTRA_REQUIRE_PASSWORD, true);
|
||||
String current = intent.getStringExtra(
|
||||
byte[] currentBytes = intent.getByteArrayExtra(
|
||||
ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD);
|
||||
|
||||
w.setBlocking(true);
|
||||
w.setListener(this);
|
||||
w.start(mChooseLockSettingsHelper.utils(), required,
|
||||
false, 0, current, current, mRequestedQuality, mUserId);
|
||||
w.start(mChooseLockSettingsHelper.utils(), required, false, 0,
|
||||
currentBytes, currentBytes, mRequestedQuality, mUserId);
|
||||
}
|
||||
mTextChangedHandler = new TextChangedHandler();
|
||||
}
|
||||
@@ -474,7 +476,8 @@ public class ChooseLockPassword extends SettingsActivity {
|
||||
Intent intent = getActivity().getIntent();
|
||||
final boolean confirmCredentials = intent.getBooleanExtra(
|
||||
ChooseLockGeneric.CONFIRM_CREDENTIALS, true);
|
||||
mCurrentPassword = intent.getStringExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD);
|
||||
mCurrentPassword = intent.getByteArrayExtra(
|
||||
ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD);
|
||||
mHasChallenge = intent.getBooleanExtra(
|
||||
ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, false);
|
||||
mChallenge = intent.getLongExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, 0);
|
||||
@@ -486,8 +489,9 @@ public class ChooseLockPassword extends SettingsActivity {
|
||||
mUserId);
|
||||
}
|
||||
} else {
|
||||
|
||||
// restore from previous state
|
||||
mFirstPin = savedInstanceState.getString(KEY_FIRST_PIN);
|
||||
mFirstPin = savedInstanceState.getByteArray(KEY_FIRST_PIN);
|
||||
final String state = savedInstanceState.getString(KEY_UI_STAGE);
|
||||
if (state != null) {
|
||||
mUiStage = Stage.valueOf(state);
|
||||
@@ -495,7 +499,7 @@ public class ChooseLockPassword extends SettingsActivity {
|
||||
}
|
||||
|
||||
if (mCurrentPassword == null) {
|
||||
mCurrentPassword = savedInstanceState.getString(KEY_CURRENT_PASSWORD);
|
||||
mCurrentPassword = savedInstanceState.getByteArray(KEY_CURRENT_PASSWORD);
|
||||
}
|
||||
|
||||
// Re-attach to the exiting worker if there is one.
|
||||
@@ -553,8 +557,8 @@ public class ChooseLockPassword extends SettingsActivity {
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
outState.putString(KEY_UI_STAGE, mUiStage.name());
|
||||
outState.putString(KEY_FIRST_PIN, mFirstPin);
|
||||
outState.putString(KEY_CURRENT_PASSWORD, mCurrentPassword);
|
||||
outState.putByteArray(KEY_FIRST_PIN, mFirstPin);
|
||||
outState.putByteArray(KEY_CURRENT_PASSWORD, mCurrentPassword);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -567,7 +571,7 @@ public class ChooseLockPassword extends SettingsActivity {
|
||||
getActivity().setResult(RESULT_FINISHED);
|
||||
getActivity().finish();
|
||||
} else {
|
||||
mCurrentPassword = data.getStringExtra(
|
||||
mCurrentPassword = data.getByteArrayExtra(
|
||||
ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD);
|
||||
}
|
||||
break;
|
||||
@@ -712,22 +716,22 @@ public class ChooseLockPassword extends SettingsActivity {
|
||||
* @return the validation result.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
int validatePassword(String password) {
|
||||
int validatePassword(byte[] password) {
|
||||
int errorCode = NO_ERROR;
|
||||
final PasswordMetrics metrics = PasswordMetrics.computeForPassword(password);
|
||||
mergeMinComplexityAndDpmRequirements(metrics.quality);
|
||||
|
||||
if (password.length() < mPasswordMinLength) {
|
||||
if (password == null || password.length < mPasswordMinLength) {
|
||||
if (mPasswordMinLength > mPasswordMinLengthToFulfillAllPolicies) {
|
||||
errorCode |= TOO_SHORT;
|
||||
}
|
||||
} else if (password.length() > mPasswordMaxLength) {
|
||||
} else if (password.length > mPasswordMaxLength) {
|
||||
errorCode |= TOO_LONG;
|
||||
} else {
|
||||
// The length requirements are fulfilled.
|
||||
if (!mPasswordNumSequenceAllowed
|
||||
&& !requiresLettersOrSymbols()
|
||||
&& metrics.numeric == password.length()) {
|
||||
&& metrics.numeric == password.length) {
|
||||
// Check for repeated characters or sequences (e.g. '1234', '0000', '2468')
|
||||
// if DevicePolicyManager or min password complexity requires a complex numeric
|
||||
// password. There can be two cases in the UI: 1. User chooses to enroll a
|
||||
@@ -757,8 +761,8 @@ public class ChooseLockPassword extends SettingsActivity {
|
||||
}
|
||||
|
||||
// Allow non-control Latin-1 characters only.
|
||||
for (int i = 0; i < password.length(); i++) {
|
||||
char c = password.charAt(i);
|
||||
for (int i = 0; i < password.length; i++) {
|
||||
char c = (char) password[i];
|
||||
if (c < 32 || c > 127) {
|
||||
errorCode |= CONTAIN_INVALID_CHARACTERS;
|
||||
break;
|
||||
@@ -809,8 +813,9 @@ public class ChooseLockPassword extends SettingsActivity {
|
||||
|
||||
public void handleNext() {
|
||||
if (mSaveAndFinishWorker != null) return;
|
||||
mChosenPassword = mPasswordEntry.getText().toString();
|
||||
if (TextUtils.isEmpty(mChosenPassword)) {
|
||||
// TODO(b/120484642): This is a point of entry for passwords from the UI
|
||||
mChosenPassword = LockPatternUtils.charSequenceToByteArray(mPasswordEntry.getText());
|
||||
if (mChosenPassword == null || mChosenPassword.length == 0) {
|
||||
return;
|
||||
}
|
||||
if (mUiStage == Stage.Introduction) {
|
||||
@@ -818,9 +823,11 @@ public class ChooseLockPassword extends SettingsActivity {
|
||||
mFirstPin = mChosenPassword;
|
||||
mPasswordEntry.setText("");
|
||||
updateStage(Stage.NeedToConfirm);
|
||||
} else {
|
||||
Arrays.fill(mChosenPassword, (byte) 0);
|
||||
}
|
||||
} else if (mUiStage == Stage.NeedToConfirm) {
|
||||
if (mFirstPin.equals(mChosenPassword)) {
|
||||
if (Arrays.equals(mFirstPin, mChosenPassword)) {
|
||||
startSaveAndFinish();
|
||||
} else {
|
||||
CharSequence tmp = mPasswordEntry.getText();
|
||||
@@ -828,6 +835,7 @@ public class ChooseLockPassword extends SettingsActivity {
|
||||
Selection.setSelection((Spannable) tmp, 0, tmp.length());
|
||||
}
|
||||
updateStage(Stage.ConfirmWrong);
|
||||
Arrays.fill(mChosenPassword, (byte) 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -940,8 +948,8 @@ public class ChooseLockPassword extends SettingsActivity {
|
||||
*/
|
||||
protected void updateUi() {
|
||||
final boolean canInput = mSaveAndFinishWorker == null;
|
||||
String password = mPasswordEntry.getText().toString();
|
||||
final int length = password.length();
|
||||
byte[] password = LockPatternUtils.charSequenceToByteArray(mPasswordEntry.getText());
|
||||
final int length = password.length;
|
||||
if (mUiStage == Stage.Introduction) {
|
||||
mPasswordRestrictionView.setVisibility(View.VISIBLE);
|
||||
final int errorCode = validatePassword(password);
|
||||
@@ -967,6 +975,7 @@ public class ChooseLockPassword extends SettingsActivity {
|
||||
|
||||
setNextText(mUiStage.buttonText);
|
||||
mPasswordEntryInputDisabler.setInputEnabled(canInput);
|
||||
Arrays.fill(password, (byte) 0);
|
||||
}
|
||||
|
||||
protected int toVisibility(boolean visibleOrGone) {
|
||||
@@ -1025,6 +1034,18 @@ public class ChooseLockPassword extends SettingsActivity {
|
||||
public void onChosenLockSaveFinished(boolean wasSecureBefore, Intent resultData) {
|
||||
getActivity().setResult(RESULT_FINISHED, resultData);
|
||||
|
||||
if (mChosenPassword != null) {
|
||||
Arrays.fill(mChosenPassword, (byte) 0);
|
||||
}
|
||||
if (mCurrentPassword != null) {
|
||||
Arrays.fill(mCurrentPassword, (byte) 0);
|
||||
}
|
||||
if (mFirstPin != null) {
|
||||
Arrays.fill(mFirstPin, (byte) 0);
|
||||
}
|
||||
|
||||
mPasswordEntry.setText("");
|
||||
|
||||
if (!wasSecureBefore) {
|
||||
Intent intent = getRedactionInterstitialIntent(getActivity());
|
||||
if (intent != null) {
|
||||
@@ -1061,13 +1082,13 @@ public class ChooseLockPassword extends SettingsActivity {
|
||||
|
||||
public static class SaveAndFinishWorker extends SaveChosenLockWorkerBase {
|
||||
|
||||
private String mChosenPassword;
|
||||
private String mCurrentPassword;
|
||||
private byte[] mChosenPassword;
|
||||
private byte[] mCurrentPassword;
|
||||
private int mRequestedQuality;
|
||||
|
||||
public void start(LockPatternUtils utils, boolean required,
|
||||
boolean hasChallenge, long challenge,
|
||||
String chosenPassword, String currentPassword, int requestedQuality, int userId) {
|
||||
byte[] chosenPassword, byte[] currentPassword, int requestedQuality, int userId) {
|
||||
prepare(utils, required, hasChallenge, challenge, userId);
|
||||
|
||||
mChosenPassword = chosenPassword;
|
||||
|
Reference in New Issue
Block a user