mirror of
https://github.com/OutlineFoundation/outline-server.git
synced 2026-08-04 14:37:34 +00:00
fix: Limit trust anchor scope to a single host
This commit is contained in:
parent
44091547b1
commit
7dec0bd2bc
8 changed files with 42 additions and 13 deletions
|
|
@ -20,6 +20,7 @@ import * as path from 'path';
|
|||
import {URL, URLSearchParams} from 'url';
|
||||
|
||||
import * as menu from './menu';
|
||||
import {HostAnchor} from './util';
|
||||
|
||||
const app = electron.app;
|
||||
const ipcMain = electron.ipcMain;
|
||||
|
|
@ -239,14 +240,20 @@ function main() {
|
|||
});
|
||||
|
||||
// Handle request to trust the certificate from the renderer process.
|
||||
const trustedFingerprints = new Set<string>();
|
||||
ipcMain.on('trust-certificate', (event: IpcEvent, fingerprint: string) => {
|
||||
trustedFingerprints.add(`sha256/${fingerprint}`);
|
||||
const trustedFingerprints = new Map<string, string>();
|
||||
ipcMain.on('trust-certificate', (event: IpcEvent, anchor: HostAnchor) => {
|
||||
trustedFingerprints.set(anchor.host, `sha256/${anchor.fingerprint}`);
|
||||
event.returnValue = true;
|
||||
});
|
||||
app.on('certificate-error', (event, webContents, url, error, certificate, callback) => {
|
||||
event.preventDefault();
|
||||
callback(trustedFingerprints.has(certificate.fingerprint));
|
||||
try {
|
||||
const parsed = new URL(url);
|
||||
callback(trustedFingerprints.get(parsed.host) === certificate.fingerprint);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
callback(false);
|
||||
}
|
||||
});
|
||||
|
||||
// Restores the mainWindow if minimized and brings it into focus.
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ import {URL} from 'url';
|
|||
|
||||
import * as digitalocean_oauth from './digitalocean_oauth';
|
||||
import * as gcp_oauth from './gcp_oauth';
|
||||
import {redactManagerUrl} from './util';
|
||||
import {HostAnchor, redactManagerUrl} from './util';
|
||||
|
||||
// This file is run in the renderer process *before* nodeIntegration is disabled.
|
||||
//
|
||||
|
|
@ -47,8 +47,8 @@ if (sentryDsn) {
|
|||
});
|
||||
}
|
||||
|
||||
contextBridge.exposeInMainWorld('trustCertificate', (fingerprint: string) => {
|
||||
return ipcRenderer.sendSync('trust-certificate', fingerprint);
|
||||
contextBridge.exposeInMainWorld('trustCertificate', (anchor: HostAnchor) => {
|
||||
return ipcRenderer.sendSync('trust-certificate', anchor);
|
||||
});
|
||||
|
||||
contextBridge.exposeInMainWorld('openImage', (basename: string) => {
|
||||
|
|
|
|||
|
|
@ -25,3 +25,9 @@ import {URL} from 'url';
|
|||
export function redactManagerUrl(s: string) {
|
||||
return new URL(s).pathname.split('/').slice(2).join('/');
|
||||
}
|
||||
|
||||
/** Represents an additional trust anchor for a single host. */
|
||||
export interface HostAnchor {
|
||||
host: string;
|
||||
fingerprint: string;
|
||||
}
|
||||
|
|
|
|||
7
src/server_manager/types/preload.d.ts
vendored
7
src/server_manager/types/preload.d.ts
vendored
|
|
@ -14,7 +14,12 @@
|
|||
|
||||
// Functions made available to the renderer process via preload.ts.
|
||||
|
||||
declare function trustCertificate(fingerprint: string): boolean;
|
||||
interface HostAnchor {
|
||||
host: string;
|
||||
fingerprint: string;
|
||||
}
|
||||
|
||||
declare function trustCertificate(anchor: HostAnchor): boolean;
|
||||
declare function openImage(basename: string): void;
|
||||
declare function onUpdateDownloaded(callback: () => void): void;
|
||||
|
||||
|
|
|
|||
|
|
@ -13,8 +13,8 @@
|
|||
// limitations under the License.
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
(window as any).trustCertificate = (fingerprint: string) => {
|
||||
console.log(`Requested to trust certificate with fingerprint ${fingerprint}`);
|
||||
(window as any).trustCertificate = (anchor: HostAnchor) => {
|
||||
console.log(`Requested to trust certificate: ${anchor}`);
|
||||
};
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
|
|
@ -59,4 +59,5 @@
|
|||
console.info(`Requested bringToFront`);
|
||||
};
|
||||
|
||||
import {HostAnchor} from '../electron_app/util';
|
||||
import './main';
|
||||
|
|
|
|||
|
|
@ -185,8 +185,9 @@ export class DigitalOceanServer extends ShadowboxServer implements server.Manage
|
|||
// these methods throw exceptions if the fields are unavailable.
|
||||
const certificateFingerprint = this.getCertificateFingerprint();
|
||||
const apiAddress = this.getManagementApiAddress();
|
||||
const parsed = new URL(apiAddress);
|
||||
// Loaded both the cert and url without exceptions, they can be set.
|
||||
trustCertificate(certificateFingerprint);
|
||||
trustCertificate({host: parsed.host, fingerprint: certificateFingerprint});
|
||||
this.setManagementApiUrl(apiAddress);
|
||||
return true;
|
||||
} catch (e) {
|
||||
|
|
|
|||
|
|
@ -178,7 +178,14 @@ export class GcpServer extends ShadowboxServer implements server.ManagedServer {
|
|||
if (outlineGuestAttributes.has('apiUrl') && outlineGuestAttributes.has('certSha256')) {
|
||||
const certSha256 = outlineGuestAttributes.get('certSha256');
|
||||
const apiUrl = outlineGuestAttributes.get('apiUrl');
|
||||
trustCertificate(certSha256);
|
||||
try {
|
||||
const parsed = new URL(apiUrl);
|
||||
trustCertificate({host: parsed.host, fingerprint: certSha256});
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
this.setInstallState(InstallState.FAILED);
|
||||
break;
|
||||
}
|
||||
this.setManagementApiUrl(apiUrl);
|
||||
this.setInstallState(InstallState.COMPLETED);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -29,7 +29,9 @@ class ManualServer extends ShadowboxServer implements server.ManualServer {
|
|||
// Electron requires that this be decoded from hex (to unprintable binary),
|
||||
// then encoded as base64.
|
||||
try {
|
||||
trustCertificate(btoa(hexToString(manualServerConfig.certSha256)));
|
||||
const parsed = new URL(manualServerConfig.apiUrl);
|
||||
const fingerprint = btoa(hexToString(manualServerConfig.certSha256));
|
||||
trustCertificate({host: parsed.host, fingerprint});
|
||||
} catch (e) {
|
||||
// Error trusting certificate, may be due to bad user input.
|
||||
console.error('Error trusting certificate');
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue