1
0
mirror of https://github.com/bitwarden/mobile.git synced 2024-12-27 17:08:00 +01:00

clear cipher cache when replacing ios autofill identities (#1112)

* clear cipher cache when replacing ios autofill identities

* changed to be service-centric

* support for multiple cache keys

* async suffix

* added cache keys for android
This commit is contained in:
Matt Portune 2020-10-13 15:39:36 -04:00 committed by GitHub
parent 37e19d9a60
commit 0b7e07ebab
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 66 additions and 39 deletions

View File

@ -41,7 +41,8 @@ namespace Bit.Droid
{ {
RegisterLocalServices(); RegisterLocalServices();
var deviceActionService = ServiceContainer.Resolve<IDeviceActionService>("deviceActionService"); var deviceActionService = ServiceContainer.Resolve<IDeviceActionService>("deviceActionService");
ServiceContainer.Init(deviceActionService.DeviceUserAgent); ServiceContainer.Init(deviceActionService.DeviceUserAgent, Constants.ClearCiphersCacheKey,
Constants.AndroidAllClearCipherCacheKeys);
} }
#if !FDROID #if !FDROID
if (Build.VERSION.SdkInt <= BuildVersionCodes.Kitkat) if (Build.VERSION.SdkInt <= BuildVersionCodes.Kitkat)

View File

@ -163,7 +163,6 @@ namespace Bit.App
{ {
System.Diagnostics.Debug.WriteLine("XF App: OnStart"); System.Diagnostics.Debug.WriteLine("XF App: OnStart");
await ClearCacheIfNeededAsync(); await ClearCacheIfNeededAsync();
await TryClearCiphersCacheAsync();
Prime(); Prime();
if (string.IsNullOrWhiteSpace(Options.Uri)) if (string.IsNullOrWhiteSpace(Options.Uri))
{ {
@ -214,7 +213,6 @@ namespace Bit.App
_messagingService.Send("cancelVaultTimeoutTimer"); _messagingService.Send("cancelVaultTimeoutTimer");
_messagingService.Send("startEventTimer"); _messagingService.Send("startEventTimer");
await ClearCacheIfNeededAsync(); await ClearCacheIfNeededAsync();
await TryClearCiphersCacheAsync();
Prime(); Prime();
SyncIfNeeded(); SyncIfNeeded();
if (Current.MainPage is NavigationPage navPage && navPage.CurrentPage is LockPage lockPage) if (Current.MainPage is NavigationPage navPage && navPage.CurrentPage is LockPage lockPage)
@ -390,20 +388,6 @@ namespace Bit.App
}); });
} }
private async Task TryClearCiphersCacheAsync()
{
if (Device.RuntimePlatform != Device.iOS)
{
return;
}
var clearCache = await _storageService.GetAsync<bool?>(Constants.ClearCiphersCacheKey);
if (clearCache.GetValueOrDefault())
{
_cipherService.ClearCache();
await _storageService.RemoveAsync(Constants.ClearCiphersCacheKey);
}
}
private async Task LockedAsync(bool autoPromptBiometric) private async Task LockedAsync(bool autoPromptBiometric)
{ {
await _stateService.PurgeAsync(); await _stateService.PurgeAsync();

View File

@ -32,6 +32,8 @@ namespace Bit.App.Services
Constants.MigratedFromV1AutofillPromptShown, Constants.MigratedFromV1AutofillPromptShown,
Constants.TriedV1Resync, Constants.TriedV1Resync,
Constants.ClearCiphersCacheKey, Constants.ClearCiphersCacheKey,
Constants.iOSAutoFillClearCiphersCacheKey,
Constants.iOSExtensionClearCiphersCacheKey,
Constants.EnvironmentUrlsKey, Constants.EnvironmentUrlsKey,
}; };

View File

@ -11,7 +11,7 @@ namespace Bit.Core.Abstractions
public interface ICipherService public interface ICipherService
{ {
Task ClearAsync(string userId); Task ClearAsync(string userId);
void ClearCache(); Task ClearCacheAsync();
Task DeleteAsync(List<string> ids); Task DeleteAsync(List<string> ids);
Task DeleteAsync(string id); Task DeleteAsync(string id);
Task DeleteAttachmentAsync(string id, string attachmentId); Task DeleteAttachmentAsync(string id, string attachmentId);

View File

@ -29,6 +29,8 @@
public static string OldUserIdKey = "userId"; public static string OldUserIdKey = "userId";
public static string AddSitePromptShownKey = "addSitePromptShown"; public static string AddSitePromptShownKey = "addSitePromptShown";
public static string ClearCiphersCacheKey = "clearCiphersCache"; public static string ClearCiphersCacheKey = "clearCiphersCache";
public static string iOSAutoFillClearCiphersCacheKey = "iOSAutoFillClearCiphersCache";
public static string iOSExtensionClearCiphersCacheKey = "iOSExtensionClearCiphersCache";
public static string MigratedFromV1 = "migratedFromV1"; public static string MigratedFromV1 = "migratedFromV1";
public static string MigratedFromV1AutofillPromptShown = "migratedV1AutofillPromptShown"; public static string MigratedFromV1AutofillPromptShown = "migratedV1AutofillPromptShown";
public static string TriedV1Resync = "triedV1Resync"; public static string TriedV1Resync = "triedV1Resync";
@ -37,5 +39,17 @@
public const int SelectFileRequestCode = 42; public const int SelectFileRequestCode = 42;
public const int SelectFilePermissionRequestCode = 43; public const int SelectFilePermissionRequestCode = 43;
public const int SaveFileRequestCode = 44; public const int SaveFileRequestCode = 44;
public static readonly string[] AndroidAllClearCipherCacheKeys =
{
ClearCiphersCacheKey
};
public static readonly string[] iOSAllClearCipherCacheKeys =
{
ClearCiphersCacheKey,
iOSAutoFillClearCiphersCacheKey,
iOSExtensionClearCiphersCacheKey
};
} }
} }

View File

@ -33,6 +33,8 @@ namespace Bit.Core.Services
private readonly IStorageService _storageService; private readonly IStorageService _storageService;
private readonly II18nService _i18nService; private readonly II18nService _i18nService;
private readonly Func<ISearchService> _searchService; private readonly Func<ISearchService> _searchService;
private readonly string _clearCipherCacheKey;
private readonly string[] _allClearCipherCacheKeys;
private Dictionary<string, HashSet<string>> _domainMatchBlacklist = new Dictionary<string, HashSet<string>> private Dictionary<string, HashSet<string>> _domainMatchBlacklist = new Dictionary<string, HashSet<string>>
{ {
["google.com"] = new HashSet<string> { "script.google.com" } ["google.com"] = new HashSet<string> { "script.google.com" }
@ -47,7 +49,9 @@ namespace Bit.Core.Services
IApiService apiService, IApiService apiService,
IStorageService storageService, IStorageService storageService,
II18nService i18nService, II18nService i18nService,
Func<ISearchService> searchService) Func<ISearchService> searchService,
string clearCipherCacheKey,
string[] allClearCipherCacheKeys)
{ {
_cryptoService = cryptoService; _cryptoService = cryptoService;
_userService = userService; _userService = userService;
@ -56,6 +60,8 @@ namespace Bit.Core.Services
_storageService = storageService; _storageService = storageService;
_i18nService = i18nService; _i18nService = i18nService;
_searchService = searchService; _searchService = searchService;
_clearCipherCacheKey = clearCipherCacheKey;
_allClearCipherCacheKeys = allClearCipherCacheKeys;
} }
private List<CipherView> DecryptedCipherCache private List<CipherView> DecryptedCipherCache
@ -82,9 +88,16 @@ namespace Bit.Core.Services
} }
} }
public void ClearCache() public async Task ClearCacheAsync()
{ {
DecryptedCipherCache = null; DecryptedCipherCache = null;
if (_allClearCipherCacheKeys != null && _allClearCipherCacheKeys.Length > 0)
{
foreach (var key in _allClearCipherCacheKeys)
{
await _storageService.SaveAsync(key, true);
}
}
} }
public async Task<Cipher> EncryptAsync(CipherView model, SymmetricCryptoKey key = null, public async Task<Cipher> EncryptAsync(CipherView model, SymmetricCryptoKey key = null,
@ -218,15 +231,24 @@ namespace Bit.Core.Services
return response?.ToList() ?? new List<Cipher>(); return response?.ToList() ?? new List<Cipher>();
} }
public Task<List<CipherView>> GetAllDecryptedAsync() public async Task<List<CipherView>> GetAllDecryptedAsync()
{ {
if (_clearCipherCacheKey != null)
{
var clearCache = await _storageService.GetAsync<bool?>(_clearCipherCacheKey);
if (clearCache.GetValueOrDefault())
{
DecryptedCipherCache = null;
await _storageService.RemoveAsync(_clearCipherCacheKey);
}
}
if (DecryptedCipherCache != null) if (DecryptedCipherCache != null)
{ {
return Task.FromResult(DecryptedCipherCache); return DecryptedCipherCache;
} }
if (_getAllDecryptedTask != null && !_getAllDecryptedTask.IsCompleted && !_getAllDecryptedTask.IsFaulted) if (_getAllDecryptedTask != null && !_getAllDecryptedTask.IsCompleted && !_getAllDecryptedTask.IsFaulted)
{ {
return _getAllDecryptedTask; return await _getAllDecryptedTask;
} }
async Task<List<CipherView>> doTask() async Task<List<CipherView>> doTask()
{ {
@ -257,7 +279,7 @@ namespace Bit.Core.Services
finally { } finally { }
} }
_getAllDecryptedTask = doTask(); _getAllDecryptedTask = doTask();
return _getAllDecryptedTask; return await _getAllDecryptedTask;
} }
public async Task<List<CipherView>> GetAllDecryptedForGroupingAsync(string groupingId, bool folder = true) public async Task<List<CipherView>> GetAllDecryptedForGroupingAsync(string groupingId, bool folder = true)
@ -569,7 +591,7 @@ namespace Bit.Core.Services
} }
ciphers[cipher.Id] = cipher; ciphers[cipher.Id] = cipher;
await _storageService.SaveAsync(storageKey, ciphers); await _storageService.SaveAsync(storageKey, ciphers);
DecryptedCipherCache = null; await ClearCacheAsync();
} }
public async Task UpsertAsync(List<CipherData> cipher) public async Task UpsertAsync(List<CipherData> cipher)
@ -590,20 +612,20 @@ namespace Bit.Core.Services
ciphers[c.Id] = c; ciphers[c.Id] = c;
} }
await _storageService.SaveAsync(storageKey, ciphers); await _storageService.SaveAsync(storageKey, ciphers);
DecryptedCipherCache = null; await ClearCacheAsync();
} }
public async Task ReplaceAsync(Dictionary<string, CipherData> ciphers) public async Task ReplaceAsync(Dictionary<string, CipherData> ciphers)
{ {
var userId = await _userService.GetUserIdAsync(); var userId = await _userService.GetUserIdAsync();
await _storageService.SaveAsync(string.Format(Keys_CiphersFormat, userId), ciphers); await _storageService.SaveAsync(string.Format(Keys_CiphersFormat, userId), ciphers);
DecryptedCipherCache = null; await ClearCacheAsync();
} }
public async Task ClearAsync(string userId) public async Task ClearAsync(string userId)
{ {
await _storageService.RemoveAsync(string.Format(Keys_CiphersFormat, userId)); await _storageService.RemoveAsync(string.Format(Keys_CiphersFormat, userId));
ClearCache(); await ClearCacheAsync();
} }
public async Task DeleteAsync(string id) public async Task DeleteAsync(string id)
@ -621,7 +643,7 @@ namespace Bit.Core.Services
} }
ciphers.Remove(id); ciphers.Remove(id);
await _storageService.SaveAsync(cipherKey, ciphers); await _storageService.SaveAsync(cipherKey, ciphers);
DecryptedCipherCache = null; await ClearCacheAsync();
} }
public async Task DeleteAsync(List<string> ids) public async Task DeleteAsync(List<string> ids)
@ -642,7 +664,7 @@ namespace Bit.Core.Services
ciphers.Remove(id); ciphers.Remove(id);
} }
await _storageService.SaveAsync(cipherKey, ciphers); await _storageService.SaveAsync(cipherKey, ciphers);
DecryptedCipherCache = null; await ClearCacheAsync();
} }
public async Task DeleteWithServerAsync(string id) public async Task DeleteWithServerAsync(string id)
@ -666,7 +688,7 @@ namespace Bit.Core.Services
ciphers[id].Attachments.Remove(attachment); ciphers[id].Attachments.Remove(attachment);
} }
await _storageService.SaveAsync(cipherKey, ciphers); await _storageService.SaveAsync(cipherKey, ciphers);
DecryptedCipherCache = null; await ClearCacheAsync();
} }
public async Task DeleteAttachmentWithServerAsync(string id, string attachmentId) public async Task DeleteAttachmentWithServerAsync(string id, string attachmentId)
@ -721,7 +743,7 @@ namespace Bit.Core.Services
await _apiService.PutDeleteCipherAsync(id); await _apiService.PutDeleteCipherAsync(id);
ciphers[id].DeletedDate = DateTime.UtcNow; ciphers[id].DeletedDate = DateTime.UtcNow;
await _storageService.SaveAsync(cipherKey, ciphers); await _storageService.SaveAsync(cipherKey, ciphers);
DecryptedCipherCache = null; await ClearCacheAsync();
} }
public async Task RestoreWithServerAsync(string id) public async Task RestoreWithServerAsync(string id)
@ -740,7 +762,7 @@ namespace Bit.Core.Services
await _apiService.PutRestoreCipherAsync(id); await _apiService.PutRestoreCipherAsync(id);
ciphers[id].DeletedDate = null; ciphers[id].DeletedDate = null;
await _storageService.SaveAsync(cipherKey, ciphers); await _storageService.SaveAsync(cipherKey, ciphers);
DecryptedCipherCache = null; await ClearCacheAsync();
} }
// Helpers // Helpers

View File

@ -135,7 +135,7 @@ namespace Bit.Core.Services
_cryptoService.ClearEncKeyAsync(true)); _cryptoService.ClearEncKeyAsync(true));
_folderService.ClearCache(); _folderService.ClearCache();
_cipherService.ClearCache(); await _cipherService.ClearCacheAsync();
_collectionService.ClearCache(); _collectionService.ClearCache();
_searchService.ClearIndex(); _searchService.ClearIndex();
_messagingService.Send("locked", userInitiated); _messagingService.Send("locked", userInitiated);

View File

@ -11,7 +11,8 @@ namespace Bit.Core.Utilities
public static Dictionary<string, object> RegisteredServices { get; set; } = new Dictionary<string, object>(); public static Dictionary<string, object> RegisteredServices { get; set; } = new Dictionary<string, object>();
public static bool Inited { get; set; } public static bool Inited { get; set; }
public static void Init(string customUserAgent = null) public static void Init(string customUserAgent = null, string clearCipherCacheKey = null,
string[] allClearCipherCacheKeys = null)
{ {
if (Inited) if (Inited)
{ {
@ -40,7 +41,7 @@ namespace Bit.Core.Utilities
var userService = new UserService(storageService, tokenService); var userService = new UserService(storageService, tokenService);
var settingsService = new SettingsService(userService, storageService); var settingsService = new SettingsService(userService, storageService);
var cipherService = new CipherService(cryptoService, userService, settingsService, apiService, var cipherService = new CipherService(cryptoService, userService, settingsService, apiService,
storageService, i18nService, () => searchService); storageService, i18nService, () => searchService, clearCipherCacheKey, allClearCipherCacheKeys);
var folderService = new FolderService(cryptoService, userService, apiService, storageService, var folderService = new FolderService(cryptoService, userService, apiService, storageService,
i18nService, cipherService); i18nService, cipherService);
var collectionService = new CollectionService(cryptoService, userService, storageService, i18nService); var collectionService = new CollectionService(cryptoService, userService, storageService, i18nService);

View File

@ -273,7 +273,8 @@ namespace Bit.iOS.Autofill
iOSCoreHelpers.RegisterLocalServices(); iOSCoreHelpers.RegisterLocalServices();
var deviceActionService = ServiceContainer.Resolve<IDeviceActionService>("deviceActionService"); var deviceActionService = ServiceContainer.Resolve<IDeviceActionService>("deviceActionService");
var messagingService = ServiceContainer.Resolve<IMessagingService>("messagingService"); var messagingService = ServiceContainer.Resolve<IMessagingService>("messagingService");
ServiceContainer.Init(deviceActionService.DeviceUserAgent); ServiceContainer.Init(deviceActionService.DeviceUserAgent,
Bit.Core.Constants.iOSAutoFillClearCiphersCacheKey, Bit.Core.Constants.iOSAllClearCipherCacheKeys);
if (!_initedAppCenter) if (!_initedAppCenter)
{ {
iOSCoreHelpers.RegisterAppCenter(); iOSCoreHelpers.RegisterAppCenter();

View File

@ -395,7 +395,8 @@ namespace Bit.iOS.Extension
iOSCoreHelpers.RegisterLocalServices(); iOSCoreHelpers.RegisterLocalServices();
var deviceActionService = ServiceContainer.Resolve<IDeviceActionService>("deviceActionService"); var deviceActionService = ServiceContainer.Resolve<IDeviceActionService>("deviceActionService");
var messagingService = ServiceContainer.Resolve<IMessagingService>("messagingService"); var messagingService = ServiceContainer.Resolve<IMessagingService>("messagingService");
ServiceContainer.Init(deviceActionService.DeviceUserAgent); ServiceContainer.Init(deviceActionService.DeviceUserAgent,
Bit.Core.Constants.iOSExtensionClearCiphersCacheKey, Bit.Core.Constants.iOSAllClearCipherCacheKeys);
if (!_initedAppCenter) if (!_initedAppCenter)
{ {
iOSCoreHelpers.RegisterAppCenter(); iOSCoreHelpers.RegisterAppCenter();

View File

@ -301,7 +301,8 @@ namespace Bit.iOS
iOSCoreHelpers.RegisterLocalServices(); iOSCoreHelpers.RegisterLocalServices();
RegisterPush(); RegisterPush();
var deviceActionService = ServiceContainer.Resolve<IDeviceActionService>("deviceActionService"); var deviceActionService = ServiceContainer.Resolve<IDeviceActionService>("deviceActionService");
ServiceContainer.Init(deviceActionService.DeviceUserAgent); ServiceContainer.Init(deviceActionService.DeviceUserAgent, Constants.ClearCiphersCacheKey,
Constants.iOSAllClearCipherCacheKeys);
iOSCoreHelpers.RegisterAppCenter(); iOSCoreHelpers.RegisterAppCenter();
_pushHandler = new iOSPushNotificationHandler( _pushHandler = new iOSPushNotificationHandler(
ServiceContainer.Resolve<IPushNotificationListenerService>("pushNotificationListenerService")); ServiceContainer.Resolve<IPushNotificationListenerService>("pushNotificationListenerService"));