SDA-3140 Insecure sites - Ability to allow insecure sites only once (#1352)

This commit is contained in:
Salah Benmoussati 2022-04-07 10:37:27 +02:00 committed by GitHub
parent 2fe326e378
commit 43df94f828
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 76 additions and 44 deletions

View File

@ -55,16 +55,19 @@ describe('dialog handler', () => {
});
describe('certificate-error', () => {
const urlMocked = 'https://symphony.corporate.com/';
let urlMocked;
const errorMocked = 'check for server certificate revocation';
const certificate = null;
it('should return false when buttonId is 1', async (done) => {
beforeEach(() => {
jest.clearAllMocks().resetModules();
});
it('should return true when buttonId is 0', async (done) => {
urlMocked = 'https://symphony.corporate.com/';
BrowserWindow.fromWebContents = jest.fn(() => {
return { isDestroyed: jest.fn(() => false) };
});
dialog.showMessageBox = jest.fn(() => {
return { response: 1 };
return { response: 0 };
});
await ipcRenderer.send(
'certificate-error',
@ -74,22 +77,6 @@ describe('dialog handler', () => {
certificate,
callbackMocked,
);
done(expect(callbackMocked).toBeCalledWith(false));
});
it('should return true when buttonId is not 1', async (done) => {
BrowserWindow.fromWebContents = jest.fn(() => {
return { isDestroyed: jest.fn(() => false) };
});
dialog.showMessageBox = jest.fn(() => 2);
await ipcRenderer.send(
'certificate-error',
webContentsMocked,
urlMocked,
errorMocked,
certificate,
callbackMocked,
);
expect(callbackMocked).toBeCalledWith(true);
await ipcRenderer.send(
'certificate-error',
@ -101,6 +88,34 @@ describe('dialog handler', () => {
);
done(expect(callbackMocked).toBeCalledWith(true));
});
it('should return false when buttonId is 1', async (done) => {
urlMocked = 'https://symphony2.corporate.com/';
BrowserWindow.fromWebContents = jest.fn(() => {
return { isDestroyed: jest.fn(() => false) };
});
dialog.showMessageBox = jest.fn(() => {
return { response: 1 };
});
await ipcRenderer.send(
'certificate-error',
webContentsMocked,
urlMocked,
errorMocked,
certificate,
callbackMocked,
);
expect(callbackMocked).toBeCalledWith(false);
await ipcRenderer.send(
'certificate-error',
webContentsMocked,
urlMocked,
errorMocked,
certificate,
callbackMocked,
);
done(expect(callbackMocked).toBeCalledWith(false));
});
});
});

View File

@ -2,6 +2,7 @@ import { app, BrowserWindow, dialog } from 'electron';
import { i18n } from '../common/i18n';
import { logger } from '../common/logger';
import { whitelistHandler } from '../common/whitelist-handler';
import { CloudConfigDataTypes, config } from './config-handler';
import { ICustomBrowserWindow, windowHandler } from './window-handler';
import { windowExists } from './window-utils';
@ -50,47 +51,47 @@ app.on('login', (event, webContents, request, authInfo, callback) => {
);
});
let ignoreAllCertErrors = false;
/**
* If certificate error occurs allow user to deny or allow particular certificate
* error. If user selects 'Ignore All', then all subsequent certificate errors
* will ignored during this session.
* error.
*
* Note: the dialog is synchronous so further processing is blocked until
* user provides a response.
*/
const siteNameAcceptedStatus = new Map<string, boolean>();
app.on(
'certificate-error',
async (event, webContents, url, error, _certificate, callback) => {
// TODO: Add logic verify custom certificate
event.preventDefault();
const { tld, domain, subdomain } = whitelistHandler.parseDomain(url);
let siteName = `${domain}${tld}`;
if (subdomain.length) {
siteName = `${subdomain}.${siteName}`;
}
logger.warn(`Certificate error: ${error} for url: ${siteName}`);
if (ignoreAllCertErrors) {
event.preventDefault();
callback(true);
const isSiteNameAccepted = siteNameAcceptedStatus.get(siteName);
if (isSiteNameAccepted !== undefined) {
callback(isSiteNameAccepted);
return;
}
logger.warn(`Certificate error: ${error} for url: ${url}`);
event.preventDefault();
const browserWin = BrowserWindow.fromWebContents(webContents);
if (browserWin && windowExists(browserWin)) {
const { response } = await dialog.showMessageBox(browserWin, {
type: 'warning',
buttons: [i18n.t('Allow')(), i18n.t('Deny')(), i18n.t('Ignore All')()],
buttons: [i18n.t('Allow once (risky)')(), i18n.t('Deny')()],
defaultId: 1,
cancelId: 1,
noLink: true,
title: i18n.t('Certificate Error')(),
message: `${i18n.t('Certificate Error')()}: ${error}\nURL: ${url}`,
message: `${siteName} ${i18n.t(
'Invalid security certificate',
)()}\n ${error}`,
});
if (response === 2) {
ignoreAllCertErrors = true;
}
callback(response !== 1);
siteNameAcceptedStatus.set(siteName, !response);
callback(!response);
}
},
);

View File

@ -216,5 +216,8 @@
"Your administrator has disabled": "Your administrator has disabled",
"Zoom": "Zoom",
"Zoom In": "Zoom In",
"Zoom Out": "Zoom Out"
"Zoom Out": "Zoom Out",
"Allow once (risky)": "Allow once (risky)",
"Deny": "Deny",
"Invalid security certificate": "has an invalid security certificate."
}

View File

@ -216,5 +216,8 @@
"Your administrator has disabled": "Your administrator has disabled",
"Zoom": "Zoom",
"Zoom In": "Zoom In",
"Zoom Out": "Zoom Out"
"Zoom Out": "Zoom Out",
"Allow once (risky)": "Allow once (risky)",
"Deny": "Deny",
"Invalid security certificate": "has an invalid security certificate."
}

View File

@ -216,5 +216,8 @@
"Your administrator has disabled": "Votre administrateur a désactivé",
"Zoom": "Zoom",
"Zoom In": "Zoom Avant",
"Zoom Out": "Zoom Arrière"
"Zoom Out": "Zoom Arrière",
"Allow once (risky)": "Autoriser une fois (risqué)",
"Deny": "Refuser",
"Invalid security certificate": "possède un certificat de sécurité non valide."
}

View File

@ -216,5 +216,8 @@
"Your administrator has disabled": "Votre administrateur a désactivé",
"Zoom": "Zoom",
"Zoom In": "Zoom Avant",
"Zoom Out": "Zoom Arrière"
"Zoom Out": "Zoom Arrière",
"Allow once (risky)": "Autoriser une fois (risqué)",
"Deny": "Refuser",
"Invalid security certificate": "possède un certificat de sécurité non valide."
}

View File

@ -216,5 +216,8 @@
"Your administrator has disabled": "管理者によて無効にされています",
"Zoom": "ズーム",
"Zoom In": "ズームイン",
"Zoom Out": "ズームアウト"
"Zoom Out": "ズームアウト",
"Allow once (risky)": "今回は許可(推奨されません)",
"Deny": "拒否",
"Invalid security certificate": "のセキュリティ証明書は無効です。"
}

View File

@ -216,5 +216,6 @@
"Your administrator has disabled": "管理者によて無効にされています",
"Zoom": "ズーム",
"Zoom In": "ズームイン",
"Zoom Out": "ズームアウト"
"Zoom Out": "ズームアウト",
"Invalid security certificate": "のセキュリティ証明書は無効です。"
}