From 31255f0c520987f2f93c9e75d9a39b47d06cd1f7 Mon Sep 17 00:00:00 2001 From: Philipp Crocoll Date: Thu, 4 Jan 2024 19:09:24 +0100 Subject: [PATCH] move TOTP button on keyboard to third position (after User/Pwd) and disable TOTP "internal fields" closes #1341 closes #2394 closes #1844 --- .../Totp/KeeOtpPluginAdapter.cs | 4 ++- .../Totp/KeeWebOtpPluginAdapter.cs | 1 + .../Totp/Keepass2TotpPluginAdapter.cs | 32 +++++++++++++------ src/keepass2android/Totp/TotpData.cs | 4 ++- .../Totp/TrayTotpPluginAdapter.cs | 2 ++ .../services/CopyToClipboardService.cs | 12 ++++--- 6 files changed, 39 insertions(+), 16 deletions(-) diff --git a/src/keepass2android/Totp/KeeOtpPluginAdapter.cs b/src/keepass2android/Totp/KeeOtpPluginAdapter.cs index f91083434..d40d0a194 100644 --- a/src/keepass2android/Totp/KeeOtpPluginAdapter.cs +++ b/src/keepass2android/Totp/KeeOtpPluginAdapter.cs @@ -39,11 +39,13 @@ public TotpData GetData() { TotpData res = new TotpData(); string data; - if (!_entryFields.TryGetValue("otp", out data)) + var otpKey = "otp"; + if (!_entryFields.TryGetValue(otpKey, out data)) { return res; } NameValueCollection parameters = ParseQueryString(data); + res.InternalFields.Add(otpKey); if (parameters[KeyParameter] == null) { diff --git a/src/keepass2android/Totp/KeeWebOtpPluginAdapter.cs b/src/keepass2android/Totp/KeeWebOtpPluginAdapter.cs index b83d5edaa..d696cc68d 100644 --- a/src/keepass2android/Totp/KeeWebOtpPluginAdapter.cs +++ b/src/keepass2android/Totp/KeeWebOtpPluginAdapter.cs @@ -16,6 +16,7 @@ public TotpData GetTotpData(IDictionary entryFields, Context ctx { return res; } + res.InternalFields.Add("otp"); string otpUriStart = "otpauth://totp/"; diff --git a/src/keepass2android/Totp/Keepass2TotpPluginAdapter.cs b/src/keepass2android/Totp/Keepass2TotpPluginAdapter.cs index 10be80838..75422a959 100644 --- a/src/keepass2android/Totp/Keepass2TotpPluginAdapter.cs +++ b/src/keepass2android/Totp/Keepass2TotpPluginAdapter.cs @@ -13,14 +13,18 @@ class Keepass2TotpPluginAdapter : ITotpPluginAdapter public TotpData GetTotpData(IDictionary entryFields, Context ctx, bool muteWarnings) { TotpData res = new TotpData(); - byte[] pbSecret = (GetOtpSecret(entryFields, "TimeOtp-") ?? MemUtil.EmptyByteArray); + byte[] pbSecret = (GetOtpSecret(entryFields, "TimeOtp-", out string secretFieldKey) ?? MemUtil.EmptyByteArray); + if (pbSecret.Length == 0) return res; + res.InternalFields.Add(secretFieldKey); + string strPeriod; uint uPeriod = 0; if (entryFields.TryGetValue("TimeOtp-Period", out strPeriod)) { + res.InternalFields.Add("TimeOtp-Period"); uint.TryParse(strPeriod, out uPeriod); } @@ -33,6 +37,7 @@ public TotpData GetTotpData(IDictionary entryFields, Context ctx uint uLength = 0; if (entryFields.TryGetValue("TimeOtp-Length", out strLength)) { + res.InternalFields.Add("TimeOtp-Length"); uint.TryParse(strLength, out uLength); } @@ -41,6 +46,8 @@ public TotpData GetTotpData(IDictionary entryFields, Context ctx string strAlg; entryFields.TryGetValue("TimeOtp-Algorithm", out strAlg); + if (!string.IsNullOrEmpty(strAlg)) + res.InternalFields.Add("TimeOtp-Algorithm"); res.HashAlgorithm = strAlg; res.TotpSecret = pbSecret; @@ -51,32 +58,37 @@ public TotpData GetTotpData(IDictionary entryFields, Context ctx } - private static byte[] GetOtpSecret(IDictionary entryFields, string strPrefix) + private static byte[] GetOtpSecret(IDictionary entryFields, string strPrefix, out string secretFieldKey) { try { string str; - entryFields.TryGetValue(strPrefix + "Secret", out str); - if (!string.IsNullOrEmpty(str)) + secretFieldKey = strPrefix + "Secret"; + entryFields.TryGetValue(secretFieldKey, out str); + if (!string.IsNullOrEmpty(str)) return StrUtil.Utf8.GetBytes(str); - - entryFields.TryGetValue(strPrefix + "Secret-Hex", out str); + + secretFieldKey = strPrefix + "Secret-Hex"; + entryFields.TryGetValue(secretFieldKey, out str); if (!string.IsNullOrEmpty(str)) return MemUtil.HexStringToByteArray(str); - - entryFields.TryGetValue(strPrefix + "Secret-Base32", out str); + + secretFieldKey = strPrefix + "Secret-Base32"; + entryFields.TryGetValue(secretFieldKey, out str); if (!string.IsNullOrEmpty(str)) return MemUtil.ParseBase32(str); - entryFields.TryGetValue(strPrefix + "Secret-Base64", out str); + secretFieldKey = strPrefix + "Secret-Base64"; + entryFields.TryGetValue(secretFieldKey, out str); if (!string.IsNullOrEmpty(str)) return Convert.FromBase64String(str); + } catch (Exception e) { Kp2aLog.LogUnexpectedError(e); } - + secretFieldKey = null; return null; } } diff --git a/src/keepass2android/Totp/TotpData.cs b/src/keepass2android/Totp/TotpData.cs index 3d59fb8a4..cca4b214f 100644 --- a/src/keepass2android/Totp/TotpData.cs +++ b/src/keepass2android/Totp/TotpData.cs @@ -31,12 +31,14 @@ public string TotpSeed public string TimeCorrectionUrl { get; set; } public string HashAlgorithm { get; set; } - + public bool IsDefaultRfc6238 { get { return Length == "6" && Duration == "30" && (HashAlgorithm == null || HashAlgorithm == HashSha1); } } + public List InternalFields { get; set; } = new List(); + public static TotpData MakeDefaultRfc6238() { return new TotpData() diff --git a/src/keepass2android/Totp/TrayTotpPluginAdapter.cs b/src/keepass2android/Totp/TrayTotpPluginAdapter.cs index 1aeae561c..d4188ca3d 100644 --- a/src/keepass2android/Totp/TrayTotpPluginAdapter.cs +++ b/src/keepass2android/Totp/TrayTotpPluginAdapter.cs @@ -115,6 +115,8 @@ public TotpData GetTotpData(IDictionary entryFields) { bool NoTimeCorrection = false; string[] Settings = SettingsGet(entryFields); + res.InternalFields.Add(SettingsFieldName); + res.InternalFields.Add(SeedFieldName); res.Duration = Settings[0]; res.Length = Settings[1]; if (res.Length == "S") diff --git a/src/keepass2android/services/CopyToClipboardService.cs b/src/keepass2android/services/CopyToClipboardService.cs index 4d11cb83c..34d040f2e 100644 --- a/src/keepass2android/services/CopyToClipboardService.cs +++ b/src/keepass2android/services/CopyToClipboardService.cs @@ -546,6 +546,7 @@ private bool ClearNotifications() return hadKeyboardData; } + bool MakeAccessibleForKeyboard(PwEntryOutput entry, string searchUrl) { #if EXCLUDE_KEYBOARD @@ -554,38 +555,41 @@ bool MakeAccessibleForKeyboard(PwEntryOutput entry, string searchUrl) bool hasData = false; Keepass2android.Kbbridge.KeyboardDataBuilder kbdataBuilder = new Keepass2android.Kbbridge.KeyboardDataBuilder(); - String[] keys = {PwDefs.UserNameField, + String[] standardKeys = {PwDefs.UserNameField, PwDefs.PasswordField, + Kp2aTotp.TotpKey, PwDefs.UrlField, PwDefs.NotesField, PwDefs.TitleField }; int[] resIds = {Resource.String.entry_user_name, Resource.String.entry_password, + 0, Resource.String.entry_url, Resource.String.entry_comment, Resource.String.entry_title }; //add standard fields: int i = 0; - foreach (string key in keys) + foreach (string key in standardKeys) { String value = entry.OutputStrings.ReadSafe(key); if (value.Length > 0) { - kbdataBuilder.AddString(key, GetString(resIds[i]), value); + kbdataBuilder.AddString(key, resIds[i] > 0 ? GetString(resIds[i]) : key, value); hasData = true; } i++; } //add additional fields: + var totpData = new Kp2aTotp().TryGetTotpData(entry); foreach (var pair in entry.OutputStrings) { var key = pair.Key; var value = pair.Value.ReadString(); - if (!PwDefs.IsStandardField(key)) + if (!standardKeys.Contains(key) && totpData?.InternalFields.Contains(key) != true) { kbdataBuilder.AddString(pair.Key, pair.Key, value); hasData = true;