mirror of
https://github.com/bitwarden/browser
synced 2025-12-18 09:13:33 +00:00
[PM-10607] Require userId for getKeyForCipherKeyDecryption (#10509)
* updated cipher service to stop using the deprecated getUserKeyWithLegacySupport and use the version that requires a user id * Added account service mock * fixed cipher test * Fixed test * removed async from encryptCipher * updated encryptSharedCipher to pass userId to the encrypt function * Pass userId to getUserKeyWithLegacySupport on encryptSharedCipher * pass in userid when setting masterKeyEncryptedUserKey * Added activer usedId to new web refresh function
This commit is contained in:
@@ -1,3 +1,6 @@
|
||||
import { firstValueFrom, map } from "rxjs";
|
||||
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||
|
||||
import { Response } from "../../models/response";
|
||||
@@ -5,7 +8,10 @@ import { CliUtils } from "../../utils";
|
||||
import { CipherResponse } from "../../vault/models/cipher.response";
|
||||
|
||||
export class ShareCommand {
|
||||
constructor(private cipherService: CipherService) {}
|
||||
constructor(
|
||||
private cipherService: CipherService,
|
||||
private accountService: AccountService,
|
||||
) {}
|
||||
|
||||
async run(id: string, organizationId: string, requestJson: string): Promise<Response> {
|
||||
if (process.env.BW_SERVE !== "true" && (requestJson == null || requestJson === "")) {
|
||||
@@ -45,14 +51,18 @@ export class ShareCommand {
|
||||
if (cipher.organizationId != null) {
|
||||
return Response.badRequest("This item already belongs to an organization.");
|
||||
}
|
||||
|
||||
const activeUserId = await firstValueFrom(
|
||||
this.accountService.activeAccount$.pipe(map((a) => a?.id)),
|
||||
);
|
||||
const cipherView = await cipher.decrypt(
|
||||
await this.cipherService.getKeyForCipherKeyDecryption(cipher),
|
||||
await this.cipherService.getKeyForCipherKeyDecryption(cipher, activeUserId),
|
||||
);
|
||||
try {
|
||||
await this.cipherService.shareWithServer(cipherView, organizationId, req);
|
||||
await this.cipherService.shareWithServer(cipherView, organizationId, req, activeUserId);
|
||||
const updatedCipher = await this.cipherService.get(cipher.id);
|
||||
const decCipher = await updatedCipher.decrypt(
|
||||
await this.cipherService.getKeyForCipherKeyDecryption(updatedCipher),
|
||||
await this.cipherService.getKeyForCipherKeyDecryption(updatedCipher, activeUserId),
|
||||
);
|
||||
const res = new CipherResponse(decCipher);
|
||||
return Response.success(res);
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import { firstValueFrom, map } from "rxjs";
|
||||
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { SelectionReadOnlyRequest } from "@bitwarden/common/admin-console/models/request/selection-read-only.request";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { CipherExport } from "@bitwarden/common/models/export/cipher.export";
|
||||
import { CollectionExport } from "@bitwarden/common/models/export/collection.export";
|
||||
import { FolderExport } from "@bitwarden/common/models/export/folder.export";
|
||||
@@ -24,6 +27,7 @@ export class EditCommand {
|
||||
private cryptoService: CryptoService,
|
||||
private apiService: ApiService,
|
||||
private folderApiService: FolderApiServiceAbstraction,
|
||||
private accountService: AccountService,
|
||||
) {}
|
||||
|
||||
async run(
|
||||
@@ -77,18 +81,21 @@ export class EditCommand {
|
||||
return Response.notFound();
|
||||
}
|
||||
|
||||
const activeUserId = await firstValueFrom(
|
||||
this.accountService.activeAccount$.pipe(map((a) => a?.id)),
|
||||
);
|
||||
let cipherView = await cipher.decrypt(
|
||||
await this.cipherService.getKeyForCipherKeyDecryption(cipher),
|
||||
await this.cipherService.getKeyForCipherKeyDecryption(cipher, activeUserId),
|
||||
);
|
||||
if (cipherView.isDeleted) {
|
||||
return Response.badRequest("You may not edit a deleted item. Use the restore command first.");
|
||||
}
|
||||
cipherView = CipherExport.toView(req, cipherView);
|
||||
const encCipher = await this.cipherService.encrypt(cipherView);
|
||||
const encCipher = await this.cipherService.encrypt(cipherView, activeUserId);
|
||||
try {
|
||||
const updatedCipher = await this.cipherService.updateWithServer(encCipher);
|
||||
const decCipher = await updatedCipher.decrypt(
|
||||
await this.cipherService.getKeyForCipherKeyDecryption(updatedCipher),
|
||||
await this.cipherService.getKeyForCipherKeyDecryption(updatedCipher, activeUserId),
|
||||
);
|
||||
const res = new CipherResponse(decCipher);
|
||||
return Response.success(res);
|
||||
@@ -110,9 +117,12 @@ export class EditCommand {
|
||||
|
||||
cipher.collectionIds = req;
|
||||
try {
|
||||
const activeUserId = await firstValueFrom(
|
||||
this.accountService.activeAccount$.pipe(map((a) => a?.id)),
|
||||
);
|
||||
const updatedCipher = await this.cipherService.saveCollectionsWithServer(cipher);
|
||||
const decCipher = await updatedCipher.decrypt(
|
||||
await this.cipherService.getKeyForCipherKeyDecryption(updatedCipher),
|
||||
await this.cipherService.getKeyForCipherKeyDecryption(updatedCipher, activeUserId),
|
||||
);
|
||||
const res = new CipherResponse(decCipher);
|
||||
return Response.success(res);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { firstValueFrom } from "rxjs";
|
||||
import { firstValueFrom, map } from "rxjs";
|
||||
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { AuditService } from "@bitwarden/common/abstractions/audit.service";
|
||||
@@ -6,6 +6,7 @@ import { EventCollectionService } from "@bitwarden/common/abstractions/event/eve
|
||||
import { SearchService } from "@bitwarden/common/abstractions/search.service";
|
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service";
|
||||
import { EventType } from "@bitwarden/common/enums";
|
||||
import { CardExport } from "@bitwarden/common/models/export/card.export";
|
||||
@@ -62,6 +63,7 @@ export class GetCommand extends DownloadCommand {
|
||||
private organizationService: OrganizationService,
|
||||
private eventCollectionService: EventCollectionService,
|
||||
private accountProfileService: BillingAccountProfileStateService,
|
||||
private accountService: AccountService,
|
||||
) {
|
||||
super(cryptoService);
|
||||
}
|
||||
@@ -110,9 +112,12 @@ export class GetCommand extends DownloadCommand {
|
||||
let decCipher: CipherView = null;
|
||||
if (Utils.isGuid(id)) {
|
||||
const cipher = await this.cipherService.get(id);
|
||||
const activeUserId = await firstValueFrom(
|
||||
this.accountService.activeAccount$.pipe(map((a) => a?.id)),
|
||||
);
|
||||
if (cipher != null) {
|
||||
decCipher = await cipher.decrypt(
|
||||
await this.cipherService.getKeyForCipherKeyDecryption(cipher),
|
||||
await this.cipherService.getKeyForCipherKeyDecryption(cipher, activeUserId),
|
||||
);
|
||||
}
|
||||
} else if (id.trim() !== "") {
|
||||
|
||||
@@ -63,6 +63,7 @@ export class OssServeConfigurator {
|
||||
this.serviceContainer.organizationService,
|
||||
this.serviceContainer.eventCollectionService,
|
||||
this.serviceContainer.billingAccountProfileStateService,
|
||||
this.serviceContainer.accountService,
|
||||
);
|
||||
this.listCommand = new ListCommand(
|
||||
this.serviceContainer.cipherService,
|
||||
@@ -82,6 +83,7 @@ export class OssServeConfigurator {
|
||||
this.serviceContainer.folderApiService,
|
||||
this.serviceContainer.billingAccountProfileStateService,
|
||||
this.serviceContainer.organizationService,
|
||||
this.serviceContainer.accountService,
|
||||
);
|
||||
this.editCommand = new EditCommand(
|
||||
this.serviceContainer.cipherService,
|
||||
@@ -89,6 +91,7 @@ export class OssServeConfigurator {
|
||||
this.serviceContainer.cryptoService,
|
||||
this.serviceContainer.apiService,
|
||||
this.serviceContainer.folderApiService,
|
||||
this.serviceContainer.accountService,
|
||||
);
|
||||
this.generateCommand = new GenerateCommand(
|
||||
this.serviceContainer.passwordGenerationService,
|
||||
@@ -114,7 +117,10 @@ export class OssServeConfigurator {
|
||||
this.serviceContainer.organizationUserService,
|
||||
);
|
||||
this.restoreCommand = new RestoreCommand(this.serviceContainer.cipherService);
|
||||
this.shareCommand = new ShareCommand(this.serviceContainer.cipherService);
|
||||
this.shareCommand = new ShareCommand(
|
||||
this.serviceContainer.cipherService,
|
||||
this.serviceContainer.accountService,
|
||||
);
|
||||
this.lockCommand = new LockCommand(this.serviceContainer.vaultTimeoutService);
|
||||
this.unlockCommand = new UnlockCommand(
|
||||
this.serviceContainer.accountService,
|
||||
|
||||
@@ -714,6 +714,7 @@ export class ServiceContainer {
|
||||
this.collectionService,
|
||||
this.cryptoService,
|
||||
this.pinService,
|
||||
this.accountService,
|
||||
);
|
||||
|
||||
this.individualExportService = new IndividualVaultExportService(
|
||||
@@ -733,6 +734,7 @@ export class ServiceContainer {
|
||||
this.cryptoFunctionService,
|
||||
this.collectionService,
|
||||
this.kdfConfigService,
|
||||
this.accountService,
|
||||
);
|
||||
|
||||
this.exportService = new VaultExportService(
|
||||
|
||||
@@ -149,6 +149,7 @@ export class SendProgram extends BaseProgram {
|
||||
this.serviceContainer.organizationService,
|
||||
this.serviceContainer.eventCollectionService,
|
||||
this.serviceContainer.billingAccountProfileStateService,
|
||||
this.serviceContainer.accountService,
|
||||
);
|
||||
const response = await cmd.run("template", object, null);
|
||||
this.processResponse(response);
|
||||
|
||||
@@ -184,6 +184,7 @@ export class VaultProgram extends BaseProgram {
|
||||
this.serviceContainer.organizationService,
|
||||
this.serviceContainer.eventCollectionService,
|
||||
this.serviceContainer.billingAccountProfileStateService,
|
||||
this.serviceContainer.accountService,
|
||||
);
|
||||
const response = await command.run(object, id, cmd);
|
||||
this.processResponse(response);
|
||||
@@ -227,6 +228,7 @@ export class VaultProgram extends BaseProgram {
|
||||
this.serviceContainer.folderApiService,
|
||||
this.serviceContainer.billingAccountProfileStateService,
|
||||
this.serviceContainer.organizationService,
|
||||
this.serviceContainer.accountService,
|
||||
);
|
||||
const response = await command.run(object, encodedJson, cmd);
|
||||
this.processResponse(response);
|
||||
@@ -272,6 +274,7 @@ export class VaultProgram extends BaseProgram {
|
||||
this.serviceContainer.cryptoService,
|
||||
this.serviceContainer.apiService,
|
||||
this.serviceContainer.folderApiService,
|
||||
this.serviceContainer.accountService,
|
||||
);
|
||||
const response = await command.run(object, id, encodedJson, cmd);
|
||||
this.processResponse(response);
|
||||
@@ -375,7 +378,10 @@ export class VaultProgram extends BaseProgram {
|
||||
})
|
||||
.action(async (id, organizationId, encodedJson, cmd) => {
|
||||
await this.exitIfLocked();
|
||||
const command = new ShareCommand(this.serviceContainer.cipherService);
|
||||
const command = new ShareCommand(
|
||||
this.serviceContainer.cipherService,
|
||||
this.serviceContainer.accountService,
|
||||
);
|
||||
const response = await command.run(id, organizationId, encodedJson);
|
||||
this.processResponse(response);
|
||||
});
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import * as fs from "fs";
|
||||
import * as path from "path";
|
||||
|
||||
import { firstValueFrom } from "rxjs";
|
||||
import { firstValueFrom, map } from "rxjs";
|
||||
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { SelectionReadOnlyRequest } from "@bitwarden/common/admin-console/models/request/selection-read-only.request";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service";
|
||||
import { CipherExport } from "@bitwarden/common/models/export/cipher.export";
|
||||
import { CollectionExport } from "@bitwarden/common/models/export/collection.export";
|
||||
@@ -34,6 +35,7 @@ export class CreateCommand {
|
||||
private folderApiService: FolderApiServiceAbstraction,
|
||||
private accountProfileService: BillingAccountProfileStateService,
|
||||
private organizationService: OrganizationService,
|
||||
private accountService: AccountService,
|
||||
) {}
|
||||
|
||||
async run(
|
||||
@@ -80,11 +82,14 @@ export class CreateCommand {
|
||||
}
|
||||
|
||||
private async createCipher(req: CipherExport) {
|
||||
const cipher = await this.cipherService.encrypt(CipherExport.toView(req));
|
||||
const activeUserId = await firstValueFrom(
|
||||
this.accountService.activeAccount$.pipe(map((a) => a?.id)),
|
||||
);
|
||||
const cipher = await this.cipherService.encrypt(CipherExport.toView(req), activeUserId);
|
||||
try {
|
||||
const newCipher = await this.cipherService.createWithServer(cipher);
|
||||
const decCipher = await newCipher.decrypt(
|
||||
await this.cipherService.getKeyForCipherKeyDecryption(newCipher),
|
||||
await this.cipherService.getKeyForCipherKeyDecryption(newCipher, activeUserId),
|
||||
);
|
||||
const res = new CipherResponse(decCipher);
|
||||
return Response.success(res);
|
||||
@@ -143,13 +148,17 @@ export class CreateCommand {
|
||||
}
|
||||
|
||||
try {
|
||||
const activeUserId = await firstValueFrom(
|
||||
this.accountService.activeAccount$.pipe(map((a) => a?.id)),
|
||||
);
|
||||
const updatedCipher = await this.cipherService.saveAttachmentRawWithServer(
|
||||
cipher,
|
||||
fileName,
|
||||
new Uint8Array(fileBuf).buffer,
|
||||
activeUserId,
|
||||
);
|
||||
const decCipher = await updatedCipher.decrypt(
|
||||
await this.cipherService.getKeyForCipherKeyDecryption(updatedCipher),
|
||||
await this.cipherService.getKeyForCipherKeyDecryption(updatedCipher, activeUserId),
|
||||
);
|
||||
return Response.success(new CipherResponse(decCipher));
|
||||
} catch (e) {
|
||||
|
||||
Reference in New Issue
Block a user