1
0
mirror of https://github.com/bitwarden/browser synced 2026-02-26 01:23:24 +00:00

Implement polkit support for flatpak

This commit is contained in:
Bernd Schoolmann
2024-11-15 16:17:28 +01:00
parent b0c5b5e9e6
commit 49e1b0cf29
10 changed files with 135 additions and 30 deletions

View File

@@ -658,7 +658,7 @@ export class SettingsComponent implements OnInit, OnDestroy {
this.form.controls.enableBrowserIntegration.setValue(false);
return;
} else if (ipc.platform.isSnapStore || ipc.platform.isFlatpak) {
} else if (ipc.platform.isSnapStore) {
await this.dialogService.openSimpleDialog({
title: { key: "browserIntegrationUnsupportedTitle" },
content: { key: "browserIntegrationLinuxDesc" },

View File

@@ -101,23 +101,32 @@ export default class BiometricUnixMain implements OsBiometricService {
async osBiometricsNeedsSetup(): Promise<boolean> {
// check whether the polkit policy is loaded via dbus call to polkit
return !(await biometrics.available());
return await biometrics.needsSetup();
}
async osBiometricsCanAutoSetup(): Promise<boolean> {
// We cannot auto setup on snap or flatpak since the filesystem is sandboxed.
// The user needs to manually set up the polkit policy outside of the sandbox
// since we allow access to polkit via dbus for the sandboxed clients, the authentication works from
// the sandbox, once the policy is set up outside of the sandbox.
return isLinux() && !isSnapStore() && !isFlatpak();
// We cannot auto setup on snap since the filesystem is sandboxed.
return isLinux() && !isSnapStore();
}
async osBiometricsSetup(): Promise<void> {
const process = spawn("pkexec", [
"bash",
"-c",
`echo '${polkitPolicy}' > ${policyPath + policyFileName} && chown root:root ${policyPath + policyFileName} && chcon system_u:object_r:usr_t:s0 ${policyPath + policyFileName}`,
]);
let process = null;
if (isFlatpak()) {
// To set up on flatpak, we escape the sandbox via the flatpak portal
process = spawn("flatpak-spawn", [
"--host",
"pkexec",
"bash",
"-c",
`echo '${polkitPolicy}' > ${policyPath + policyFileName} && chown root:root ${policyPath + policyFileName} && chcon system_u:object_r:usr_t:s0 ${policyPath + policyFileName}`,
]);
} else {
process = spawn("pkexec", [
"bash",
"-c",
`echo '${polkitPolicy}' > ${policyPath + policyFileName} && chown root:root ${policyPath + policyFileName} && chcon system_u:object_r:usr_t:s0 ${policyPath + policyFileName}`,
]);
}
await new Promise((resolve, reject) => {
process.on("close", (code) => {

View File

@@ -7,7 +7,7 @@ import { ipcMain } from "electron";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { ipc, windows_registry } from "@bitwarden/desktop-napi";
import { isDev } from "../utils";
import { isDev, isFlatpak } from "../utils";
import { WindowMain } from "./window.main";
@@ -134,7 +134,7 @@ export class NativeMessagingMain {
type: "stdio",
};
if (!existsSync(baseJson.path)) {
if (!existsSync(baseJson.path) && !isFlatpak()) {
throw new Error(`Unable to find binary: ${baseJson.path}`);
}
@@ -185,11 +185,29 @@ export class NativeMessagingMain {
for (const [key, value] of Object.entries(this.getLinuxNMHS())) {
if (existsSync(value)) {
if (key === "Firefox") {
if (isFlatpak()) {
const proxyScriptLocation = path.join(
value,
"native-messaging-hosts",
"com.8bit.bitwarden.sh",
);
await this.writeFlatpakProxyScript(proxyScriptLocation);
firefoxJson.path = proxyScriptLocation;
}
await this.writeManifest(
path.join(value, "native-messaging-hosts", "com.8bit.bitwarden.json"),
firefoxJson,
);
} else {
if (isFlatpak()) {
const proxyScriptLocation = path.join(
value,
"native-messaging-hosts",
"com.8bit.bitwarden.sh",
);
await this.writeFlatpakProxyScript(proxyScriptLocation);
chromeJson.path = proxyScriptLocation;
}
await this.writeManifest(
path.join(value, "NativeMessagingHosts", "com.8bit.bitwarden.json"),
chromeJson,
@@ -257,10 +275,16 @@ export class NativeMessagingMain {
await this.removeIfExists(
path.join(value, "native-messaging-hosts", "com.8bit.bitwarden.json"),
);
await this.removeIfExists(
path.join(value, "native-messaging-hosts", "com.8bit.bitwarden.sh"),
);
} else {
await this.removeIfExists(
path.join(value, "NativeMessagingHosts", "com.8bit.bitwarden.json"),
);
await this.removeIfExists(
path.join(value, "native-messaging-hosts", "com.8bit.bitwarden.sh"),
);
}
}
@@ -334,6 +358,16 @@ export class NativeMessagingMain {
await fs.writeFile(destination, JSON.stringify(manifest, null, 2));
}
private async writeFlatpakProxyScript(destination: string) {
const content =
"#!/bin/bash\n/usr/bin/flatpak run --command=desktop_proxy com.bitwarden.desktop $@";
if (!existsSync(path.dirname(destination))) {
await fs.mkdir(path.dirname(destination));
}
await fs.writeFile(destination, content);
await fs.chmod(destination, 0o755);
}
private async loadChromeIds(): Promise<string[]> {
const ids: Set<string> = new Set([
// Chrome extension