mirror of
https://github.com/bitwarden/jslib
synced 2025-12-26 21:23:53 +00:00
[bug] Allow the lock message handler to manipulate a specific acount
This commit is contained in:
@@ -11,7 +11,7 @@ import { CipherView } from '../models/view/cipherView';
|
||||
import { FieldView } from '../models/view/fieldView';
|
||||
|
||||
export abstract class CipherService {
|
||||
clearCache: () => Promise<void>;
|
||||
clearCache: (userId?: string) => Promise<void>;
|
||||
encrypt: (model: CipherView, key?: SymmetricCryptoKey, originalCipher?: Cipher) => Promise<Cipher>;
|
||||
encryptFields: (fieldsModel: FieldView[], key: SymmetricCryptoKey) => Promise<Field[]>;
|
||||
encryptField: (fieldModel: FieldView, key: SymmetricCryptoKey) => Promise<Field>;
|
||||
|
||||
@@ -6,7 +6,7 @@ import { TreeNode } from '../models/domain/treeNode';
|
||||
import { CollectionView } from '../models/view/collectionView';
|
||||
|
||||
export abstract class CollectionService {
|
||||
clearCache: () => Promise<void>;
|
||||
clearCache: (userId?: string) => Promise<void>;
|
||||
encrypt: (model: CollectionView) => Promise<Collection>;
|
||||
decryptMany: (collections: Collection[]) => Promise<CollectionView[]>;
|
||||
get: (id: string) => Promise<Collection>;
|
||||
|
||||
@@ -17,7 +17,7 @@ export abstract class CryptoService {
|
||||
setEncPrivateKey: (encPrivateKey: string) => Promise<void>;
|
||||
setOrgKeys: (orgs: ProfileOrganizationResponse[], providerOrgs: ProfileProviderOrganizationResponse[]) => Promise<void>;
|
||||
setProviderKeys: (orgs: ProfileProviderResponse[]) => Promise<void>;
|
||||
getKey: (keySuffix?: KeySuffixOptions) => Promise<SymmetricCryptoKey>;
|
||||
getKey: (keySuffix?: KeySuffixOptions, userId?: string) => Promise<SymmetricCryptoKey>;
|
||||
getKeyFromStorage: (keySuffix: KeySuffixOptions) => Promise<SymmetricCryptoKey>;
|
||||
getKeyHash: () => Promise<string>;
|
||||
compareAndUpdateKeyHash: (masterPassword: string, key: SymmetricCryptoKey) => Promise<boolean>;
|
||||
@@ -30,13 +30,13 @@ export abstract class CryptoService {
|
||||
getProviderKey: (providerId: string) => Promise<SymmetricCryptoKey>;
|
||||
hasKey: () => Promise<boolean>;
|
||||
hasKeyInMemory: () => Promise<boolean>;
|
||||
hasKeyStored: (keySuffix?: KeySuffixOptions) => Promise<boolean>;
|
||||
hasKeyStored: (keySuffix?: KeySuffixOptions, userId?: string) => Promise<boolean>;
|
||||
hasEncKey: () => Promise<boolean>;
|
||||
clearKey: (clearSecretStorage?: boolean) => Promise<any>;
|
||||
clearKey: (clearSecretStorage?: boolean, userId?: string) => Promise<any>;
|
||||
clearKeyHash: () => Promise<any>;
|
||||
clearEncKey: (memoryOnly?: boolean) => Promise<any>;
|
||||
clearKeyPair: (memoryOnly?: boolean) => Promise<any>;
|
||||
clearOrgKeys: (memoryOnly?: boolean) => Promise<any>;
|
||||
clearEncKey: (memoryOnly?: boolean, userId?: string) => Promise<any>;
|
||||
clearKeyPair: (memoryOnly?: boolean, userId?: string) => Promise<any>;
|
||||
clearOrgKeys: (memoryOnly?: boolean, userId?: string) => Promise<any>;
|
||||
clearProviderKeys: (memoryOnly?: boolean) => Promise<any>;
|
||||
clearPinProtectedKey: () => Promise<any>;
|
||||
clearKeys: () => Promise<any>;
|
||||
|
||||
@@ -7,7 +7,7 @@ import { TreeNode } from '../models/domain/treeNode';
|
||||
import { FolderView } from '../models/view/folderView';
|
||||
|
||||
export abstract class FolderService {
|
||||
clearCache: () => Promise<void>;
|
||||
clearCache: (userId?: string) => Promise<void>;
|
||||
encrypt: (model: FolderView, key?: SymmetricCryptoKey) => Promise<Folder>;
|
||||
get: (id: string) => Promise<Folder>;
|
||||
getAll: () => Promise<Folder[]>;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
export abstract class VaultTimeoutService {
|
||||
isLocked: () => Promise<boolean>;
|
||||
isLocked: (userId?: string) => Promise<boolean>;
|
||||
checkVaultTimeout: () => Promise<void>;
|
||||
lock: (allowSoftLock?: boolean) => Promise<void>;
|
||||
lock: (allowSoftLock?: boolean, userId?: string) => Promise<void>;
|
||||
logOut: () => Promise<void>;
|
||||
setVaultTimeoutOptions: (vaultTimeout: number, vaultTimeoutAction: string) => Promise<void>;
|
||||
getVaultTimeout: () => Promise<number>;
|
||||
|
||||
@@ -81,8 +81,8 @@ export class CipherService implements CipherServiceAbstraction {
|
||||
}
|
||||
}
|
||||
|
||||
async clearCache(): Promise<void> {
|
||||
await this.clearDecryptedCiphersState();
|
||||
async clearCache(userId?: string): Promise<void> {
|
||||
await this.clearDecryptedCiphersState(userId);
|
||||
}
|
||||
|
||||
async encrypt(model: CipherView, key?: SymmetricCryptoKey, originalCipher: Cipher = null): Promise<Cipher> {
|
||||
@@ -1098,8 +1098,8 @@ export class CipherService implements CipherServiceAbstraction {
|
||||
await this.stateService.setEncryptedCiphers(null);
|
||||
}
|
||||
|
||||
private async clearDecryptedCiphersState() {
|
||||
await this.stateService.setDecryptedCiphers(null);
|
||||
private async clearDecryptedCiphersState(userId?: string) {
|
||||
await this.stateService.setDecryptedCiphers(null, { userId });
|
||||
this.clearSortedCiphers();
|
||||
}
|
||||
|
||||
|
||||
@@ -20,8 +20,8 @@ export class CollectionService implements CollectionServiceAbstraction {
|
||||
private stateService: StateService) {
|
||||
}
|
||||
|
||||
async clearCache(): Promise<void> {
|
||||
await this.stateService.setDecryptedCollections(null);
|
||||
async clearCache(userId?: string): Promise<void> {
|
||||
await this.stateService.setDecryptedCollections(null, { userId });
|
||||
}
|
||||
|
||||
async encrypt(model: CollectionView): Promise<Collection> {
|
||||
|
||||
@@ -30,11 +30,14 @@ export class CryptoService implements CryptoServiceAbstraction {
|
||||
protected logService: LogService, protected stateService: StateService) {
|
||||
}
|
||||
|
||||
async setKey(key: SymmetricCryptoKey): Promise<any> {
|
||||
await this.stateService.setCryptoMasterKey(key);
|
||||
async setKey(key: SymmetricCryptoKey, userId?: string): Promise<any> {
|
||||
const storageOptions = userId ?
|
||||
{ userId, storageLocation: StorageLocation.Memory } :
|
||||
null;
|
||||
await this.stateService.setCryptoMasterKey(key, storageOptions);
|
||||
const suffix = await this.getSuffix();
|
||||
if (suffix != null) {
|
||||
await this.stateService.setCryptoMasterKeyB64(key.keyB64, { keySuffix: suffix });
|
||||
await this.stateService.setCryptoMasterKeyB64(key.keyB64, { keySuffix: suffix, userId });
|
||||
} else {
|
||||
await this.clearSecretKeyStore();
|
||||
}
|
||||
@@ -89,30 +92,34 @@ export class CryptoService implements CryptoServiceAbstraction {
|
||||
return await this.stateService.setEncryptedProviderKeys(providerKeys);
|
||||
}
|
||||
|
||||
async getKey(keySuffix?: KeySuffixOptions): Promise<SymmetricCryptoKey> {
|
||||
const inMemoryKey = await this.stateService.getCryptoMasterKey();
|
||||
async getKey(keySuffix?: KeySuffixOptions, userId?: string): Promise<SymmetricCryptoKey> {
|
||||
const inMemoryKey = await this.stateService.getCryptoMasterKey(
|
||||
userId ? { userId } :
|
||||
null
|
||||
);
|
||||
|
||||
if (inMemoryKey != null) {
|
||||
return inMemoryKey;
|
||||
}
|
||||
|
||||
keySuffix ||= KeySuffixOptions.Auto;
|
||||
const symmetricKey = await this.getKeyFromStorage(keySuffix);
|
||||
const symmetricKey = await this.getKeyFromStorage(keySuffix, userId);
|
||||
|
||||
if (symmetricKey != null) {
|
||||
this.setKey(symmetricKey);
|
||||
this.setKey(symmetricKey, userId);
|
||||
}
|
||||
|
||||
return symmetricKey;
|
||||
}
|
||||
|
||||
async getKeyFromStorage(keySuffix: KeySuffixOptions): Promise<SymmetricCryptoKey> {
|
||||
const key = await this.retrieveKeyFromStorage(keySuffix);
|
||||
async getKeyFromStorage(keySuffix: KeySuffixOptions, userId?: string): Promise<SymmetricCryptoKey> {
|
||||
const key = await this.retrieveKeyFromStorage(keySuffix, userId);
|
||||
if (key != null) {
|
||||
const symmetricKey = new SymmetricCryptoKey(Utils.fromB64ToArray(key).buffer);
|
||||
|
||||
if (!await this.validateKey(symmetricKey)) {
|
||||
this.logService.warning('Wrong key, throwing away stored key');
|
||||
await this.clearSecretKeyStore();
|
||||
await this.clearSecretKeyStore(userId);
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -333,19 +340,19 @@ export class CryptoService implements CryptoServiceAbstraction {
|
||||
return await this.stateService.getCryptoMasterKey() != null;
|
||||
}
|
||||
|
||||
async hasKeyStored(keySuffix: KeySuffixOptions): Promise<boolean> {
|
||||
return await this.stateService.getCryptoMasterKeyB64({ keySuffix: keySuffix }) != null;
|
||||
async hasKeyStored(keySuffix: KeySuffixOptions, userId?: string): Promise<boolean> {
|
||||
return await this.stateService.getCryptoMasterKeyB64({ keySuffix: keySuffix, userId }) != null;
|
||||
}
|
||||
|
||||
async hasEncKey(): Promise<boolean> {
|
||||
return await this.stateService.getDecryptedCryptoSymmetricKey() != null;
|
||||
}
|
||||
|
||||
async clearKey(clearSecretStorage: boolean = true): Promise<any> {
|
||||
await this.stateService.setCryptoMasterKey(null);
|
||||
await this.stateService.setLegacyEtmKey(null);
|
||||
async clearKey(clearSecretStorage: boolean = true, userId?: string): Promise<any> {
|
||||
await this.stateService.setCryptoMasterKey(null, { userId });
|
||||
await this.stateService.setLegacyEtmKey(null, { userId });
|
||||
if (clearSecretStorage) {
|
||||
await this.clearSecretKeyStore();
|
||||
await this.clearSecretKeyStore(userId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -357,28 +364,28 @@ export class CryptoService implements CryptoServiceAbstraction {
|
||||
return await this.stateService.setKeyHash(null);
|
||||
}
|
||||
|
||||
async clearEncKey(memoryOnly?: boolean): Promise<void> {
|
||||
await this.stateService.setDecryptedCryptoSymmetricKey(null);
|
||||
async clearEncKey(memoryOnly?: boolean, userId?: string): Promise<void> {
|
||||
await this.stateService.setDecryptedCryptoSymmetricKey(null, { userId });
|
||||
if (!memoryOnly) {
|
||||
await this.stateService.setEncryptedCryptoSymmetricKey(null);
|
||||
await this.stateService.setEncryptedCryptoSymmetricKey(null, { userId });
|
||||
}
|
||||
}
|
||||
|
||||
async clearKeyPair(memoryOnly?: boolean): Promise<any> {
|
||||
async clearKeyPair(memoryOnly?: boolean, userId?: string): Promise<any> {
|
||||
const keysToClear: Promise<void>[] = [
|
||||
this.stateService.setDecryptedPrivateKey(null),
|
||||
this.stateService.setPublicKey(null),
|
||||
this.stateService.setDecryptedPrivateKey(null, { userId }),
|
||||
this.stateService.setPublicKey(null, { userId }),
|
||||
];
|
||||
if (!memoryOnly) {
|
||||
keysToClear.push(this.stateService.setEncryptedPrivateKey(null));
|
||||
keysToClear.push(this.stateService.setEncryptedPrivateKey(null, { userId }));
|
||||
}
|
||||
return Promise.all(keysToClear);
|
||||
}
|
||||
|
||||
async clearOrgKeys(memoryOnly?: boolean): Promise<void> {
|
||||
await this.stateService.setDecryptedOrganizationKeys(null);
|
||||
async clearOrgKeys(memoryOnly?: boolean, userId?: string): Promise<void> {
|
||||
await this.stateService.setDecryptedOrganizationKeys(null, { userId });
|
||||
if (!memoryOnly) {
|
||||
await this.stateService.setEncryptedOrganizationKeys(null);
|
||||
await this.stateService.setEncryptedOrganizationKeys(null, { userId });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -716,8 +723,8 @@ export class CryptoService implements CryptoServiceAbstraction {
|
||||
return shouldStoreKey;
|
||||
}
|
||||
|
||||
protected async retrieveKeyFromStorage(keySuffix: KeySuffixOptions) {
|
||||
return await this.stateService.getCryptoMasterKeyB64({ keySuffix: keySuffix });
|
||||
protected async retrieveKeyFromStorage(keySuffix: KeySuffixOptions, userId?: string) {
|
||||
return await this.stateService.getCryptoMasterKeyB64({ keySuffix: keySuffix, userId });
|
||||
}
|
||||
|
||||
private async aesEncrypt(data: ArrayBuffer, key: SymmetricCryptoKey): Promise<EncryptedObject> {
|
||||
@@ -876,8 +883,8 @@ export class CryptoService implements CryptoServiceAbstraction {
|
||||
null;
|
||||
}
|
||||
|
||||
private async clearSecretKeyStore(): Promise<void> {
|
||||
await this.stateService.setCryptoMasterKeyB64(null, { keySuffix: KeySuffixOptions.Auto });
|
||||
await this.stateService.setCryptoMasterKeyB64(null, { keySuffix: KeySuffixOptions.Biometric });
|
||||
private async clearSecretKeyStore(userId?: string): Promise<void> {
|
||||
await this.stateService.setCryptoMasterKeyB64(null, { keySuffix: KeySuffixOptions.Auto, userId });
|
||||
await this.stateService.setCryptoMasterKeyB64(null, { keySuffix: KeySuffixOptions.Biometric, userId });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,8 +29,8 @@ export class FolderService implements FolderServiceAbstraction {
|
||||
private i18nService: I18nService, private cipherService: CipherService,
|
||||
private stateService: StateService) { }
|
||||
|
||||
async clearCache(): Promise<void> {
|
||||
await this.stateService.setDecryptedFolders(null);
|
||||
async clearCache(userId?: string): Promise<void> {
|
||||
await this.stateService.setDecryptedFolders(null, { userId });
|
||||
}
|
||||
|
||||
async encrypt(model: FolderView, key?: SymmetricCryptoKey): Promise<Folder> {
|
||||
|
||||
@@ -12,6 +12,7 @@ import { VaultTimeoutService as VaultTimeoutServiceAbstraction } from '../abstra
|
||||
import { KeySuffixOptions } from '../enums/keySuffixOptions';
|
||||
|
||||
import { PolicyType } from '../enums/policyType';
|
||||
import { StorageLocation } from '../enums/storageLocation';
|
||||
|
||||
|
||||
export class VaultTimeoutService implements VaultTimeoutServiceAbstraction {
|
||||
@@ -42,10 +43,11 @@ export class VaultTimeoutService implements VaultTimeoutServiceAbstraction {
|
||||
}
|
||||
|
||||
// Keys aren't stored for a device that is locked or logged out.
|
||||
async isLocked(): Promise<boolean> {
|
||||
// Handle never lock startup situation
|
||||
if (await this.cryptoService.hasKeyStored(KeySuffixOptions.Auto) && !(await this.stateService.getEverBeenUnlocked())) {
|
||||
await this.cryptoService.getKey(KeySuffixOptions.Auto);
|
||||
async isLocked(userId?: string): Promise<boolean> {
|
||||
const neverLock = await this.cryptoService.hasKeyStored(KeySuffixOptions.Auto, userId) &&
|
||||
!(await this.stateService.getEverBeenUnlocked(userId ? {userId: userId, storageLocation: StorageLocation.Disk} : null));
|
||||
if (neverLock) {
|
||||
return (await this.cryptoService.getKey(KeySuffixOptions.Auto, userId)) != null;
|
||||
}
|
||||
|
||||
return !(await this.cryptoService.hasKeyInMemory());
|
||||
@@ -86,24 +88,24 @@ export class VaultTimeoutService implements VaultTimeoutServiceAbstraction {
|
||||
}
|
||||
}
|
||||
|
||||
async lock(allowSoftLock = false): Promise<void> {
|
||||
const authed = await this.stateService.getIsAuthenticated();
|
||||
async lock(allowSoftLock = false, userId?: string): Promise<void> {
|
||||
const authed = await this.stateService.getIsAuthenticated({ userId: userId });
|
||||
if (!authed) {
|
||||
return;
|
||||
}
|
||||
|
||||
await this.stateService.setBiometricLocked(true);
|
||||
await this.stateService.setEverBeenUnlocked(true);
|
||||
await this.cryptoService.clearKey(false);
|
||||
await this.cryptoService.clearOrgKeys(true);
|
||||
await this.cryptoService.clearKeyPair(true);
|
||||
await this.cryptoService.clearEncKey(true);
|
||||
await this.stateService.setBiometricLocked(true, { userId: userId });
|
||||
await this.stateService.setEverBeenUnlocked(true, { userId: userId });
|
||||
await this.cryptoService.clearKey(false, userId);
|
||||
await this.cryptoService.clearOrgKeys(true, userId);
|
||||
await this.cryptoService.clearKeyPair(true, userId);
|
||||
await this.cryptoService.clearEncKey(true, userId);
|
||||
|
||||
await this.folderService.clearCache();
|
||||
await this.cipherService.clearCache();
|
||||
await this.collectionService.clearCache();
|
||||
await this.folderService.clearCache(userId);
|
||||
await this.cipherService.clearCache(userId);
|
||||
await this.collectionService.clearCache(userId);
|
||||
this.searchService.clearIndex();
|
||||
this.messagingService.send('locked');
|
||||
this.messagingService.send('locked', { userId });
|
||||
if (this.lockedCallback != null) {
|
||||
await this.lockedCallback();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user