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();
var deviceActionService = ServiceContainer.Resolve<IDeviceActionService>("deviceActionService");
ServiceContainer.Init(deviceActionService.DeviceUserAgent);
ServiceContainer.Init(deviceActionService.DeviceUserAgent, Constants.ClearCiphersCacheKey,
Constants.AndroidAllClearCipherCacheKeys);
}
#if !FDROID
if (Build.VERSION.SdkInt <= BuildVersionCodes.Kitkat)

View File

@ -163,7 +163,6 @@ namespace Bit.App
{
System.Diagnostics.Debug.WriteLine("XF App: OnStart");
await ClearCacheIfNeededAsync();
await TryClearCiphersCacheAsync();
Prime();
if (string.IsNullOrWhiteSpace(Options.Uri))
{
@ -214,7 +213,6 @@ namespace Bit.App
_messagingService.Send("cancelVaultTimeoutTimer");
_messagingService.Send("startEventTimer");
await ClearCacheIfNeededAsync();
await TryClearCiphersCacheAsync();
Prime();
SyncIfNeeded();
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)
{
await _stateService.PurgeAsync();

View File

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

View File

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

View File

@ -29,6 +29,8 @@
public static string OldUserIdKey = "userId";
public static string AddSitePromptShownKey = "addSitePromptShown";
public static string ClearCiphersCacheKey = "clearCiphersCache";
public static string iOSAutoFillClearCiphersCacheKey = "iOSAutoFillClearCiphersCache";
public static string iOSExtensionClearCiphersCacheKey = "iOSExtensionClearCiphersCache";
public static string MigratedFromV1 = "migratedFromV1";
public static string MigratedFromV1AutofillPromptShown = "migratedV1AutofillPromptShown";
public static string TriedV1Resync = "triedV1Resync";
@ -37,5 +39,17 @@
public const int SelectFileRequestCode = 42;
public const int SelectFilePermissionRequestCode = 43;
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 II18nService _i18nService;
private readonly Func<ISearchService> _searchService;
private readonly string _clearCipherCacheKey;
private readonly string[] _allClearCipherCacheKeys;
private Dictionary<string, HashSet<string>> _domainMatchBlacklist = new Dictionary<string, HashSet<string>>
{
["google.com"] = new HashSet<string> { "script.google.com" }
@ -47,7 +49,9 @@ namespace Bit.Core.Services
IApiService apiService,
IStorageService storageService,
II18nService i18nService,
Func<ISearchService> searchService)
Func<ISearchService> searchService,
string clearCipherCacheKey,
string[] allClearCipherCacheKeys)
{
_cryptoService = cryptoService;
_userService = userService;
@ -56,6 +60,8 @@ namespace Bit.Core.Services
_storageService = storageService;
_i18nService = i18nService;
_searchService = searchService;
_clearCipherCacheKey = clearCipherCacheKey;
_allClearCipherCacheKeys = allClearCipherCacheKeys;
}
private List<CipherView> DecryptedCipherCache
@ -82,9 +88,16 @@ namespace Bit.Core.Services
}
}
public void ClearCache()
public async Task ClearCacheAsync()
{
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,
@ -218,15 +231,24 @@ namespace Bit.Core.Services
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)
{
return Task.FromResult(DecryptedCipherCache);
return DecryptedCipherCache;
}
if (_getAllDecryptedTask != null && !_getAllDecryptedTask.IsCompleted && !_getAllDecryptedTask.IsFaulted)
{
return _getAllDecryptedTask;
return await _getAllDecryptedTask;
}
async Task<List<CipherView>> doTask()
{
@ -257,7 +279,7 @@ namespace Bit.Core.Services
finally { }
}
_getAllDecryptedTask = doTask();
return _getAllDecryptedTask;
return await _getAllDecryptedTask;
}
public async Task<List<CipherView>> GetAllDecryptedForGroupingAsync(string groupingId, bool folder = true)
@ -569,7 +591,7 @@ namespace Bit.Core.Services
}
ciphers[cipher.Id] = cipher;
await _storageService.SaveAsync(storageKey, ciphers);
DecryptedCipherCache = null;
await ClearCacheAsync();
}
public async Task UpsertAsync(List<CipherData> cipher)
@ -590,20 +612,20 @@ namespace Bit.Core.Services
ciphers[c.Id] = c;
}
await _storageService.SaveAsync(storageKey, ciphers);
DecryptedCipherCache = null;
await ClearCacheAsync();
}
public async Task ReplaceAsync(Dictionary<string, CipherData> ciphers)
{
var userId = await _userService.GetUserIdAsync();
await _storageService.SaveAsync(string.Format(Keys_CiphersFormat, userId), ciphers);
DecryptedCipherCache = null;
await ClearCacheAsync();
}
public async Task ClearAsync(string userId)
{
await _storageService.RemoveAsync(string.Format(Keys_CiphersFormat, userId));
ClearCache();
await ClearCacheAsync();
}
public async Task DeleteAsync(string id)
@ -621,7 +643,7 @@ namespace Bit.Core.Services
}
ciphers.Remove(id);
await _storageService.SaveAsync(cipherKey, ciphers);
DecryptedCipherCache = null;
await ClearCacheAsync();
}
public async Task DeleteAsync(List<string> ids)
@ -642,7 +664,7 @@ namespace Bit.Core.Services
ciphers.Remove(id);
}
await _storageService.SaveAsync(cipherKey, ciphers);
DecryptedCipherCache = null;
await ClearCacheAsync();
}
public async Task DeleteWithServerAsync(string id)
@ -666,7 +688,7 @@ namespace Bit.Core.Services
ciphers[id].Attachments.Remove(attachment);
}
await _storageService.SaveAsync(cipherKey, ciphers);
DecryptedCipherCache = null;
await ClearCacheAsync();
}
public async Task DeleteAttachmentWithServerAsync(string id, string attachmentId)
@ -721,7 +743,7 @@ namespace Bit.Core.Services
await _apiService.PutDeleteCipherAsync(id);
ciphers[id].DeletedDate = DateTime.UtcNow;
await _storageService.SaveAsync(cipherKey, ciphers);
DecryptedCipherCache = null;
await ClearCacheAsync();
}
public async Task RestoreWithServerAsync(string id)
@ -740,7 +762,7 @@ namespace Bit.Core.Services
await _apiService.PutRestoreCipherAsync(id);
ciphers[id].DeletedDate = null;
await _storageService.SaveAsync(cipherKey, ciphers);
DecryptedCipherCache = null;
await ClearCacheAsync();
}
// Helpers

View File

@ -135,7 +135,7 @@ namespace Bit.Core.Services
_cryptoService.ClearEncKeyAsync(true));
_folderService.ClearCache();
_cipherService.ClearCache();
await _cipherService.ClearCacheAsync();
_collectionService.ClearCache();
_searchService.ClearIndex();
_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 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)
{
@ -40,7 +41,7 @@ namespace Bit.Core.Utilities
var userService = new UserService(storageService, tokenService);
var settingsService = new SettingsService(userService, storageService);
var cipherService = new CipherService(cryptoService, userService, settingsService, apiService,
storageService, i18nService, () => searchService);
storageService, i18nService, () => searchService, clearCipherCacheKey, allClearCipherCacheKeys);
var folderService = new FolderService(cryptoService, userService, apiService, storageService,
i18nService, cipherService);
var collectionService = new CollectionService(cryptoService, userService, storageService, i18nService);

View File

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

View File

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

View File

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