Skip to content

Commit

Permalink
Merge pull request #14531 from nextcloud/backport/14509/stable-3.31
Browse files Browse the repository at this point in the history
[stable-3.31] Increase PIN Enter Delay
  • Loading branch information
tobiasKaminsky authored Feb 11, 2025
2 parents 27ae04d + 1a65831 commit 5ccac3b
Show file tree
Hide file tree
Showing 4 changed files with 125 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -409,4 +409,7 @@ default void onDarkThemeModeChanged(DarkMode mode) {

boolean isAutoUploadGPlayNotificationShown();
void setAutoUploadGPlayNotificationShown(boolean value);

int getPassCodeDelay();
void setPassCodeDelay(int value);
}
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,8 @@ public final class AppPreferencesImpl implements AppPreferences {
private static final String PREF__AUTO_UPLOAD_GPLAY_WARNING2_SHOWN = "auto_upload_gplay_warning2_shown";
private static final String PREF__AUTO_UPLOAD_GPLAY_NOTIFICATION_SHOWN = "auto_upload_gplay_notification_shown";

private static final String PREF__PASSCODE_DELAY_IN_SECONDS = "passcode_delay_in_seconds";

private static final String LOG_ENTRY = "log_entry";

private final Context context;
Expand Down Expand Up @@ -859,4 +861,14 @@ public boolean isAutoUploadGPlayNotificationShown() {
public void setAutoUploadGPlayNotificationShown(boolean value) {
preferences.edit().putBoolean(PREF__AUTO_UPLOAD_GPLAY_NOTIFICATION_SHOWN, value).apply();
}

@Override
public int getPassCodeDelay() {
return preferences.getInt(PREF__PASSCODE_DELAY_IN_SECONDS, 0);
}

@Override
public void setPassCodeDelay(int value) {
preferences.edit().putInt(PREF__PASSCODE_DELAY_IN_SECONDS, value).apply();
}
}
108 changes: 86 additions & 22 deletions app/src/main/java/com/owncloud/android/ui/activity/PassCodeActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import com.google.android.material.snackbar.Snackbar
import com.nextcloud.android.common.ui.theme.utils.ColorRole
import com.nextcloud.client.di.Injectable
import com.nextcloud.client.preferences.AppPreferences
import com.nextcloud.utils.extensions.setVisibleIf
import com.owncloud.android.R
import com.owncloud.android.authentication.PassCodeManager
import com.owncloud.android.databinding.PasscodelockBinding
Expand Down Expand Up @@ -73,9 +74,11 @@ class PassCodeActivity : AppCompatActivity(), Injectable {
private var passCodeDigits: Array<String> = arrayOf("", "", "", "")
private var confirmingPassCode = false
private var changed = true // to control that only one blocks jump
private var delayInSeconds = 0

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
delayInSeconds = preferences.passCodeDelay
binding = PasscodelockBinding.inflate(layoutInflater)
setContentView(binding.root)

Expand Down Expand Up @@ -221,6 +224,7 @@ class PassCodeActivity : AppCompatActivity(), Injectable {
if (ACTION_CHECK == intent.action) {
if (checkPassCode()) {
preferences.resetPinWrongAttempts()
preferences.passCodeDelay = 0

// / pass code accepted in request, user is allowed to access the app
passCodeManager.updateLockTimestamp()
Expand Down Expand Up @@ -274,6 +278,7 @@ class PassCodeActivity : AppCompatActivity(), Injectable {
binding.header.setText(headerMessage) // TODO check if really needed
binding.explanation.visibility = explanationVisibility // TODO check if really needed
clearBoxes()
increaseAndSaveDelayTime()
showDelay()
}

Expand Down Expand Up @@ -337,33 +342,92 @@ class PassCodeActivity : AppCompatActivity(), Injectable {
finish()
}

private fun showDelay() {
val delayValue = preferences.pinBruteForceDelay()
@Suppress("MagicNumber")
private fun increaseAndSaveDelayTime() {
val maxDelayTimeInSeconds = 300
val delayIncrementation = 15

if (delayInSeconds < maxDelayTimeInSeconds) {
delayInSeconds += delayIncrementation
preferences.passCodeDelay = delayInSeconds
preferences.increasePinWrongAttempts()
}
}

@Suppress("MagicNumber")
private fun getExplanationText(timeInSecond: Int): String {
return when {
timeInSecond < 60 -> resources.getQuantityString(
R.plurals.delay_message,
timeInSecond,
timeInSecond
)
else -> {
val minutes = timeInSecond / 60
val remainingSeconds = timeInSecond % 60

when {
remainingSeconds == 0 -> resources.getQuantityString(
R.plurals.delay_message_minutes,
minutes,
minutes
)
else -> {
val minuteText = resources.getQuantityString(
R.plurals.delay_message_minutes_part,
minutes,
minutes
)
val secondText = resources.getQuantityString(
R.plurals.delay_message_seconds_part,
remainingSeconds,
remainingSeconds
)

val prefixText = "$minuteText $secondText"
getString(R.string.due_to_too_many_wrong_attempts, prefixText)
}
}
}
}
}

if (delayValue <= 0) {
@Suppress("MagicNumber")
private fun showDelay() {
val pinBruteForceCount = preferences.pinBruteForceDelay()
if (pinBruteForceCount <= 0) {
return
}

binding.explanation.setText(R.string.brute_force_delay)
binding.explanation.visibility = View.VISIBLE
binding.txt0.isEnabled = false
binding.txt1.isEnabled = false
binding.txt2.isEnabled = false
binding.txt3.isEnabled = false

lifecycleScope.launch(Dispatchers.IO) {
delay(delayValue * 1000L)

launch(Dispatchers.Main) {
binding.explanation.visibility = View.INVISIBLE
binding.txt0.isEnabled = true
binding.txt1.isEnabled = true
binding.txt2.isEnabled = true
binding.txt3.isEnabled = true

binding.txt0.requestFocus()
binding.txt0.showKeyboard()
enableInputFields(false)

var counter = delayInSeconds
lifecycleScope.launch(Dispatchers.Main) {
while (counter != 0) {
binding.explanation.text = getExplanationText(counter)
delay(1000)
counter -= 1
}

enableInputFields(true)
focusFirstInputField()
}
}

private fun enableInputFields(enabled: Boolean) {
binding.run {
explanation.setVisibleIf(!enabled)
txt0.isEnabled = enabled
txt1.isEnabled = enabled
txt2.isEnabled = enabled
txt3.isEnabled = enabled
}
}

private fun focusFirstInputField() {
binding.run {
txt0.requestFocus()
txt0.showKeyboard()
}
}

Expand Down
25 changes: 24 additions & 1 deletion app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1132,7 +1132,30 @@
<string name="e2e_signature_does_not_match">Signature does not match</string>

<string name="login_url_helper_text">The link to your %1$s web interface when you open it in the browser.</string>
<string name="brute_force_delay">Delayed due to too many wrong attempts</string>

<plurals name="delay_message">
<item quantity="one">Delayed %d second due to too many wrong attempts</item>
<item quantity="other">Delayed %d seconds due to too many wrong attempts</item>
</plurals>

<plurals name="delay_message_minutes">
<item quantity="one">Delayed %d minute due to too many wrong attempts</item>
<item quantity="other">Delayed %d minutes due to too many wrong attempts</item>
</plurals>

<plurals name="delay_message_minutes_part">
<item quantity="one">Delayed %d minute</item>
<item quantity="other">Delayed %d minutes</item>
</plurals>

<plurals name="delay_message_seconds_part">
<item quantity="one">%d second</item>
<item quantity="other">%d seconds</item>
</plurals>

<string name="due_to_too_many_wrong_attempts">%s due to too many wrong attempts</string>


<string name="create">Create</string>
<string name="select_one_template">Please select one template</string>
<string name="choose_template_helper_text">Please choose a template and enter a file name.</string>
Expand Down

0 comments on commit 5ccac3b

Please sign in to comment.