1
0
mirror of https://github.com/bitwarden/browser synced 2026-01-04 09:33:27 +00:00

Make fingerprint validation optional, update readme with debug info for native messaging

This commit is contained in:
Hinton
2020-12-18 15:47:48 +01:00
parent 02a3fbde99
commit e639fa6674
7 changed files with 72 additions and 23 deletions

View File

@@ -98,6 +98,16 @@
</div>
<small class="help-block">{{'enableBrowserIntegrationDesc' | i18n}}</small>
</div>
<div class="form-group">
<div class="checkbox">
<label for="enableBrowserIntegrationFingerprint">
<input id="enableBrowserIntegrationFingerprint" type="checkbox" name="EnableBrowserIntegrationFingerprint"
[(ngModel)]="enableBrowserIntegrationFingerprint" (change)="saveBrowserIntegrationFingerprint()" [disabled]="!enableBrowserIntegration">
{{'enableBrowserIntegrationFingerprint' | i18n}}
</label>
</div>
<small class="help-block">{{'enableBrowserIntegrationFingerprintDesc' | i18n}}</small>
</div>
<div class="form-group">
<div class="checkbox">
<label for="enableTray">

View File

@@ -34,6 +34,7 @@ export class SettingsComponent implements OnInit {
pin: boolean = null;
disableFavicons: boolean = false;
enableBrowserIntegration: boolean = false;
enableBrowserIntegrationFingerprint: boolean = false;
enableMinToTray: boolean = false;
enableCloseToTray: boolean = false;
enableTray: boolean = false;
@@ -146,6 +147,7 @@ export class SettingsComponent implements OnInit {
this.disableFavicons = await this.storageService.get<boolean>(ConstantsService.disableFaviconKey);
this.enableBrowserIntegration = await this.storageService.get<boolean>(
ElectronConstants.enableBrowserIntegration);
this.enableBrowserIntegrationFingerprint = await this.storageService.get<boolean>(ElectronConstants.enableBrowserIntegrationFingerprint);
this.enableMinToTray = await this.storageService.get<boolean>(ElectronConstants.enableMinimizeToTrayKey);
this.enableCloseToTray = await this.storageService.get<boolean>(ElectronConstants.enableCloseToTrayKey);
this.enableTray = await this.storageService.get<boolean>(ElectronConstants.enableTrayKey);
@@ -329,6 +331,15 @@ export class SettingsComponent implements OnInit {
await this.storageService.save(ElectronConstants.enableBrowserIntegration, this.enableBrowserIntegration);
this.messagingService.send(this.enableBrowserIntegration ? 'enableBrowserIntegration' : 'disableBrowserIntegration');
if (!this.enableBrowserIntegration) {
this.enableBrowserIntegrationFingerprint = false;
this.saveBrowserIntegrationFingerprint();
}
}
async saveBrowserIntegrationFingerprint() {
await this.storageService.save(ElectronConstants.enableBrowserIntegrationFingerprint, this.enableBrowserIntegrationFingerprint);
}
private callAnalytics(name: string, enabled: boolean) {

View File

@@ -135,7 +135,7 @@ const eventService = new EventService(storageService, apiService, userService, c
const systemService = new SystemService(storageService, vaultTimeoutService, messagingService, platformUtilsService,
null);
const nativeMessagingService = new NativeMessagingService(cryptoFunctionService, cryptoService, platformUtilsService,
logService, i18nService, userService, messagingService, vaultTimeoutService);
logService, i18nService, userService, messagingService, vaultTimeoutService, storageService);
const analytics = new Analytics(window, () => isDev(), platformUtilsService, storageService, appIdService);
containerService.attachToGlobal(window);

View File

@@ -1453,6 +1453,12 @@
"browserIntegrationMasOnlyDesc": {
"message": "Unfortunately browser integration is only supported in the Mac App Store version for now."
},
"enableBrowserIntegrationFingerprint": {
"message": "Require verification for browser integration"
},
"enableBrowserIntegrationFingerprintDesc": {
"message": "Enable an additional layer of security by requiring fingerprint phrase validation when establishing a link between your desktop and browser. When enabled, this requires user intervention and verification each time a connection is established."
},
"approve": {
"message": "Approve"
},

View File

@@ -10,6 +10,7 @@ import { WindowMain } from 'jslib/electron/window.main';
export class NativeMessagingMain {
private connected = false;
private socket: any;
constructor(private logService: LogService, private windowMain: WindowMain, private userPath: string, private appPath: string) {}
@@ -19,15 +20,16 @@ export class NativeMessagingMain {
ipc.serve(() => {
ipc.server.on('message', (data: any, socket: any) => {
// This is a ugly hack until electron is updated 7.0.0 which supports ipcMain.invoke
this.socket = socket;
this.windowMain.win.webContents.send('nativeMessaging', data);
ipcMain.once('nativeMessagingReply', (event, msg) => {
if (msg != null) {
this.send(msg, socket);
}
});
});
ipcMain.on('nativeMessagingReply', (event, msg) => {
if (this.socket != null && msg != null) {
this.send(msg, this.socket);
}
})
ipc.server.on('connect', () => {
this.connected = true;
})
@@ -36,6 +38,7 @@ export class NativeMessagingMain {
'socket.disconnected',
(socket: any, destroyedSocketID: any) => {
this.connected = false;
this.socket = null;
ipc.log(
'client ' + destroyedSocketID + ' has disconnected!'
);

View File

@@ -12,6 +12,8 @@ import { VaultTimeoutService } from 'jslib/abstractions/vaultTimeout.service';
import { Utils } from 'jslib/misc/utils';
import { SymmetricCryptoKey } from 'jslib/models/domain/symmetricCryptoKey';
import { StorageService } from 'jslib/abstractions';
import { ElectronConstants } from 'jslib/electron/electronConstants';
const MessageValidTimeout = 10 * 1000;
const EncryptionAlgorithm = 'sha1';
@@ -21,7 +23,7 @@ export class NativeMessagingService {
constructor(private cryptoFunctionService: CryptoFunctionService, private cryptoService: CryptoService,
private platformUtilService: PlatformUtilsService, private logService: LogService, private i18nService: I18nService,
private userService: UserService, private messagingService: MessagingService, private vaultTimeoutService: VaultTimeoutService) {
private userService: UserService, private messagingService: MessagingService, private vaultTimeoutService: VaultTimeoutService, private storageService: StorageService) {
ipcRenderer.on('nativeMessaging', async (event: any, message: any) => {
this.messageHandler(message);
});
@@ -34,25 +36,30 @@ export class NativeMessagingService {
// Request to setup secure encryption
if (rawMessage.command === 'setupEncryption') {
const remotePublicKey = Utils.fromB64ToArray(rawMessage.publicKey).buffer;
const fingerprint = (await this.cryptoService.getFingerprint(await this.userService.getUserId(), remotePublicKey)).join(' ');
this.messagingService.send('setFocus');
if (await this.storageService.get<boolean>(ElectronConstants.enableBrowserIntegrationFingerprint)) {
ipcRenderer.send('nativeMessagingReply', {command: 'verifyFingerprint', appId: appId});
// Await confirmation that fingerprint is correct
const submitted = await Swal.fire({
title: this.i18nService.t('verifyBrowserTitle'),
html: `${this.i18nService.t('verifyBrowserDesc')}<br><br><strong>${fingerprint}</strong>`,
showCancelButton: true,
cancelButtonText: this.i18nService.t('cancel'),
showConfirmButton: true,
confirmButtonText: this.i18nService.t('approve'),
allowOutsideClick: false,
});
const fingerprint = (await this.cryptoService.getFingerprint(await this.userService.getUserId(), remotePublicKey)).join(' ');
if (submitted.value !== true) {
return;
this.messagingService.send('setFocus');
// Await confirmation that fingerprint is correct
const submitted = await Swal.fire({
title: this.i18nService.t('verifyBrowserTitle'),
html: `${this.i18nService.t('verifyBrowserDesc')}<br><br><strong>${fingerprint}</strong>`,
showCancelButton: true,
cancelButtonText: this.i18nService.t('cancel'),
showConfirmButton: true,
confirmButtonText: this.i18nService.t('approve'),
allowOutsideClick: false,
});
if (submitted.value !== true) {
return;
}
}
this.secureCommunication(remotePublicKey, appId);
return;
}