mirror of
https://github.com/bitwarden/browser.git
synced 2024-11-25 12:15:18 +01:00
[PM-14270] Use rust to access windows registry (#11413)
This commit is contained in:
parent
f6755da15b
commit
2e6ed4a4fc
4
.github/renovate.json
vendored
4
.github/renovate.json
vendored
@ -73,7 +73,7 @@
|
||||
"reviewers": ["team:team-admin-console-dev"]
|
||||
},
|
||||
{
|
||||
"matchPackageNames": ["@types/node-ipc", "node-ipc", "qrious", "regedit"],
|
||||
"matchPackageNames": ["@types/node-ipc", "node-ipc", "qrious"],
|
||||
"description": "Auth owned dependencies",
|
||||
"commitMessagePrefix": "[deps] Auth:",
|
||||
"reviewers": ["team:team-auth-dev"]
|
||||
@ -258,5 +258,5 @@
|
||||
"reviewers": ["team:team-vault-dev"]
|
||||
}
|
||||
],
|
||||
"ignoreDeps": ["@types/koa-bodyparser", "bootstrap", "node-ipc", "node", "npm", "regedit"]
|
||||
"ignoreDeps": ["@types/koa-bodyparser", "bootstrap", "node-ipc", "node", "npm"]
|
||||
}
|
||||
|
32
apps/desktop/desktop_native/Cargo.lock
generated
32
apps/desktop/desktop_native/Cargo.lock
generated
@ -546,6 +546,7 @@ dependencies = [
|
||||
"napi-derive",
|
||||
"tokio",
|
||||
"tokio-util",
|
||||
"windows-registry",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2226,7 +2227,7 @@ checksum = "d2ed2439a290666cd67ecce2b0ffaad89c2a56b976b736e6ece670297897832d"
|
||||
dependencies = [
|
||||
"windows-implement",
|
||||
"windows-interface",
|
||||
"windows-result",
|
||||
"windows-result 0.1.2",
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
@ -2252,6 +2253,17 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-registry"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bafa604f2104cf5ae2cc2db1dee84b7e6a5d11b05f737b60def0ffdc398cbc0a"
|
||||
dependencies = [
|
||||
"windows-result 0.2.0",
|
||||
"windows-strings",
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-result"
|
||||
version = "0.1.2"
|
||||
@ -2261,6 +2273,24 @@ dependencies = [
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-result"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e"
|
||||
dependencies = [
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-strings"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "978d65aedf914c664c510d9de43c8fd85ca745eaff1ed53edf409b479e441663"
|
||||
dependencies = [
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.48.0"
|
||||
|
@ -21,5 +21,8 @@ napi-derive = "=2.16.12"
|
||||
tokio = { version = "1.38.0" }
|
||||
tokio-util = "0.7.11"
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
windows-registry = "=0.3.0"
|
||||
|
||||
[build-dependencies]
|
||||
napi-build = "=2.1.3"
|
||||
|
4
apps/desktop/desktop_native/napi/index.d.ts
vendored
4
apps/desktop/desktop_native/napi/index.d.ts
vendored
@ -51,6 +51,10 @@ export declare namespace powermonitors {
|
||||
export function onLock(callback: (err: Error | null, ) => any): Promise<void>
|
||||
export function isLockMonitorAvailable(): Promise<boolean>
|
||||
}
|
||||
export declare namespace windows_registry {
|
||||
export function createKey(key: string, subkey: string, value: string): Promise<void>
|
||||
export function deleteKey(key: string, subkey: string): Promise<void>
|
||||
}
|
||||
export declare namespace ipc {
|
||||
export interface IpcMessage {
|
||||
clientId: number
|
||||
|
@ -1,5 +1,8 @@
|
||||
#[macro_use]
|
||||
extern crate napi_derive;
|
||||
|
||||
mod registry;
|
||||
|
||||
#[napi]
|
||||
pub mod passwords {
|
||||
/// Fetch the stored password from the keychain.
|
||||
@ -190,6 +193,21 @@ pub mod powermonitors {
|
||||
|
||||
}
|
||||
|
||||
#[napi]
|
||||
pub mod windows_registry {
|
||||
#[napi]
|
||||
pub async fn create_key(key: String, subkey: String, value: String) -> napi::Result<()> {
|
||||
crate::registry::create_key(&key, &subkey, &value)
|
||||
.map_err(|e| napi::Error::from_reason(e.to_string()))
|
||||
}
|
||||
|
||||
#[napi]
|
||||
pub async fn delete_key(key: String, subkey: String) -> napi::Result<()> {
|
||||
crate::registry::delete_key(&key, &subkey)
|
||||
.map_err(|e| napi::Error::from_reason(e.to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
#[napi]
|
||||
pub mod ipc {
|
||||
use desktop_core::ipc::server::{Message, MessageType};
|
||||
|
9
apps/desktop/desktop_native/napi/src/registry/dummy.rs
Normal file
9
apps/desktop/desktop_native/napi/src/registry/dummy.rs
Normal file
@ -0,0 +1,9 @@
|
||||
use anyhow::{bail, Result};
|
||||
|
||||
pub fn create_key(_key: &str, _subkey: &str, _value: &str) -> Result<()> {
|
||||
bail!("Not implemented")
|
||||
}
|
||||
|
||||
pub fn delete_key(_key: &str, _subkey: &str) -> Result<()> {
|
||||
bail!("Not implemented")
|
||||
}
|
4
apps/desktop/desktop_native/napi/src/registry/mod.rs
Normal file
4
apps/desktop/desktop_native/napi/src/registry/mod.rs
Normal file
@ -0,0 +1,4 @@
|
||||
#[cfg_attr(target_os = "windows", path = "windows.rs")]
|
||||
#[cfg_attr(not(target_os = "windows"), path = "dummy.rs")]
|
||||
mod internal;
|
||||
pub use internal::*;
|
29
apps/desktop/desktop_native/napi/src/registry/windows.rs
Normal file
29
apps/desktop/desktop_native/napi/src/registry/windows.rs
Normal file
@ -0,0 +1,29 @@
|
||||
use anyhow::{bail, Result};
|
||||
|
||||
fn convert_key(key: &str) -> Result<&'static windows_registry::Key> {
|
||||
Ok(match key.to_uppercase().as_str() {
|
||||
"HKEY_CURRENT_USER" | "HKCU" => windows_registry::CURRENT_USER,
|
||||
"HKEY_LOCAL_MACHINE" | "HKLM" => windows_registry::LOCAL_MACHINE,
|
||||
"HKEY_CLASSES_ROOT" | "HKCR" => windows_registry::CLASSES_ROOT,
|
||||
_ => bail!("Invalid key"),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn create_key(key: &str, subkey: &str, value: &str) -> Result<()> {
|
||||
let key = convert_key(key)?;
|
||||
|
||||
let subkey = key.create(subkey)?;
|
||||
|
||||
const DEFAULT: &str = "";
|
||||
subkey.set_string(DEFAULT, value)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn delete_key(key: &str, subkey: &str) -> Result<()> {
|
||||
let key = convert_key(key)?;
|
||||
|
||||
key.remove_tree(subkey)?;
|
||||
|
||||
Ok(())
|
||||
}
|
@ -90,13 +90,6 @@
|
||||
"electronUpdaterCompatibility": ">=0.0.1",
|
||||
"target": ["portable", "nsis-web", "appx"],
|
||||
"sign": "./sign.js",
|
||||
"extraResources": [
|
||||
{
|
||||
"from": "../../node_modules/regedit/vbs",
|
||||
"to": "regedit/vbs",
|
||||
"filter": ["**/*"]
|
||||
}
|
||||
],
|
||||
"extraFiles": [
|
||||
{
|
||||
"from": "desktop_native/dist/desktop_proxy.${platform}-${arch}.exe",
|
||||
|
@ -1,12 +1,11 @@
|
||||
import { existsSync, promises as fs } from "fs";
|
||||
import { homedir, userInfo } from "os";
|
||||
import * as path from "path";
|
||||
import * as util from "util";
|
||||
|
||||
import { ipcMain } from "electron";
|
||||
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import { ipc } from "@bitwarden/desktop-napi";
|
||||
import { ipc, windows_registry } from "@bitwarden/desktop-napi";
|
||||
|
||||
import { isDev } from "../utils";
|
||||
|
||||
@ -142,12 +141,12 @@ export class NativeMessagingMain {
|
||||
await this.writeManifest(path.join(destination, "chrome.json"), chromeJson);
|
||||
|
||||
const nmhs = this.getWindowsNMHS();
|
||||
for (const [key, value] of Object.entries(nmhs)) {
|
||||
for (const [name, [key, subkey]] of Object.entries(nmhs)) {
|
||||
let manifestPath = path.join(destination, "chrome.json");
|
||||
if (key === "Firefox") {
|
||||
if (name === "Firefox") {
|
||||
manifestPath = path.join(destination, "firefox.json");
|
||||
}
|
||||
await this.createWindowsRegistry(value, manifestPath);
|
||||
await windows_registry.createKey(key, subkey, manifestPath);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -225,8 +224,8 @@ export class NativeMessagingMain {
|
||||
await this.removeIfExists(path.join(this.userPath, "browsers", "chrome.json"));
|
||||
|
||||
const nmhs = this.getWindowsNMHS();
|
||||
for (const [, value] of Object.entries(nmhs)) {
|
||||
await this.deleteWindowsRegistry(value);
|
||||
for (const [, [key, subkey]] of Object.entries(nmhs)) {
|
||||
await windows_registry.deleteKey(key, subkey);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -274,11 +273,14 @@ export class NativeMessagingMain {
|
||||
|
||||
private getWindowsNMHS() {
|
||||
return {
|
||||
Firefox: "HKCU\\SOFTWARE\\Mozilla\\NativeMessagingHosts\\com.8bit.bitwarden",
|
||||
Chrome: "HKCU\\SOFTWARE\\Google\\Chrome\\NativeMessagingHosts\\com.8bit.bitwarden",
|
||||
Chromium: "HKCU\\SOFTWARE\\Chromium\\NativeMessagingHosts\\com.8bit.bitwarden",
|
||||
Firefox: ["HKCU", "SOFTWARE\\Mozilla\\NativeMessagingHosts\\com.8bit.bitwarden"],
|
||||
Chrome: ["HKCU", "SOFTWARE\\Google\\Chrome\\NativeMessagingHosts\\com.8bit.bitwarden"],
|
||||
Chromium: ["HKCU", "SOFTWARE\\Chromium\\NativeMessagingHosts\\com.8bit.bitwarden"],
|
||||
// Edge uses the same registry key as Chrome as a fallback, but it's has its own separate key as well.
|
||||
"Microsoft Edge": "HKCU\\SOFTWARE\\Microsoft\\Edge\\NativeMessagingHosts\\com.8bit.bitwarden",
|
||||
"Microsoft Edge": [
|
||||
"HKCU",
|
||||
"SOFTWARE\\Microsoft\\Edge\\NativeMessagingHosts\\com.8bit.bitwarden",
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
@ -419,52 +421,6 @@ export class NativeMessagingMain {
|
||||
return path.join(path.dirname(this.exePath), `desktop_proxy${ext}`);
|
||||
}
|
||||
|
||||
private getRegeditInstance() {
|
||||
// eslint-disable-next-line
|
||||
const regedit = require("regedit");
|
||||
regedit.setExternalVBSLocation(path.join(path.dirname(this.exePath), "resources/regedit/vbs"));
|
||||
|
||||
return regedit;
|
||||
}
|
||||
|
||||
private async createWindowsRegistry(location: string, jsonFile: string) {
|
||||
const regedit = this.getRegeditInstance();
|
||||
|
||||
const createKey = util.promisify(regedit.createKey);
|
||||
const putValue = util.promisify(regedit.putValue);
|
||||
|
||||
this.logService.debug(`Adding registry: ${location}`);
|
||||
|
||||
await createKey(location);
|
||||
|
||||
// Insert path to manifest
|
||||
const obj: any = {};
|
||||
obj[location] = {
|
||||
default: {
|
||||
value: jsonFile,
|
||||
type: "REG_DEFAULT",
|
||||
},
|
||||
};
|
||||
|
||||
return putValue(obj);
|
||||
}
|
||||
|
||||
private async deleteWindowsRegistry(key: string) {
|
||||
const regedit = this.getRegeditInstance();
|
||||
|
||||
const list = util.promisify(regedit.list);
|
||||
const deleteKey = util.promisify(regedit.deleteKey);
|
||||
|
||||
this.logService.debug(`Removing registry: ${key}`);
|
||||
|
||||
try {
|
||||
await list(key);
|
||||
await deleteKey(key);
|
||||
} catch {
|
||||
this.logService.error(`Unable to delete registry key: ${key}`);
|
||||
}
|
||||
}
|
||||
|
||||
private homedir() {
|
||||
if (process.platform === "darwin") {
|
||||
return userInfo().homedir;
|
||||
|
66
package-lock.json
generated
66
package-lock.json
generated
@ -166,7 +166,6 @@
|
||||
"prettier": "3.3.3",
|
||||
"prettier-plugin-tailwindcss": "0.6.8",
|
||||
"process": "0.11.10",
|
||||
"regedit": "3.0.3",
|
||||
"remark-gfm": "4.0.0",
|
||||
"rimraf": "6.0.1",
|
||||
"sass": "1.74.1",
|
||||
@ -21943,13 +21942,6 @@
|
||||
],
|
||||
"license": "BSD-3-Clause"
|
||||
},
|
||||
"node_modules/if-async": {
|
||||
"version": "3.7.4",
|
||||
"resolved": "https://registry.npmjs.org/if-async/-/if-async-3.7.4.tgz",
|
||||
"integrity": "sha512-BFEH2mZyeF6KZKaKLVPZ0wMjIiWOdjvZ7zbx8ENec0qfZhJwKFbX/4jKM5LTKyJEc/GOqUKiiJ2IFKT9yWrZqA==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/ignore": {
|
||||
"version": "5.3.2",
|
||||
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
|
||||
@ -32402,57 +32394,6 @@
|
||||
"dev": true,
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"node_modules/regedit": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/regedit/-/regedit-3.0.3.tgz",
|
||||
"integrity": "sha512-SpHmMKOtiEYx0MiRRC48apBsmThoZ4svZNsYoK8leHd5bdUHV1nYb8pk8gh6Moou7/S9EDi1QsjBTpyXVQrPuQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"debug": "^4.1.0",
|
||||
"if-async": "^3.7.4",
|
||||
"stream-slicer": "0.0.6",
|
||||
"through2": "^0.6.3"
|
||||
}
|
||||
},
|
||||
"node_modules/regedit/node_modules/isarray": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
|
||||
"integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/regedit/node_modules/readable-stream": {
|
||||
"version": "1.0.34",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz",
|
||||
"integrity": "sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"core-util-is": "~1.0.0",
|
||||
"inherits": "~2.0.1",
|
||||
"isarray": "0.0.1",
|
||||
"string_decoder": "~0.10.x"
|
||||
}
|
||||
},
|
||||
"node_modules/regedit/node_modules/string_decoder": {
|
||||
"version": "0.10.31",
|
||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
|
||||
"integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/regedit/node_modules/through2": {
|
||||
"version": "0.6.5",
|
||||
"resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz",
|
||||
"integrity": "sha512-RkK/CCESdTKQZHdmKICijdKKsCRVHs5KsLZ6pACAmF/1GPUQhonHSXWNERctxEp7RmvjdNbZTL5z9V7nSCXKcg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"readable-stream": ">=1.0.33-1 <1.1.0-0",
|
||||
"xtend": ">=4.0.0 <4.1.0-0"
|
||||
}
|
||||
},
|
||||
"node_modules/regenerate": {
|
||||
"version": "1.4.2",
|
||||
"resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz",
|
||||
@ -35247,13 +35188,6 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/stream-slicer": {
|
||||
"version": "0.0.6",
|
||||
"resolved": "https://registry.npmjs.org/stream-slicer/-/stream-slicer-0.0.6.tgz",
|
||||
"integrity": "sha512-QsY0LbweYE5L+e+iBQgtkM5WUIf7+kCMA/m2VULv8rEEDDnlDPsPvOHH4nli6uaZOKQEt64u65h0l/eeZo7lCw==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/streaming-json-stringify": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/streaming-json-stringify/-/streaming-json-stringify-3.1.0.tgz",
|
||||
|
@ -127,7 +127,6 @@
|
||||
"prettier": "3.3.3",
|
||||
"prettier-plugin-tailwindcss": "0.6.8",
|
||||
"process": "0.11.10",
|
||||
"regedit": "3.0.3",
|
||||
"remark-gfm": "4.0.0",
|
||||
"rimraf": "6.0.1",
|
||||
"sass": "1.74.1",
|
||||
|
Loading…
Reference in New Issue
Block a user