mirror of
https://github.com/bitwarden/browser
synced 2025-12-20 02:03:39 +00:00
* [deps] Platform: Update napi to v3 * fix: upgrade required dependencies * fix: deprecated syntax in package.json * fix: TS code after napi changes * fix: lint * fix: floating promise * fix: libsqlite musl compilation * feat: remove support for musl * fix: sorting lint * fix: logging not working * fix: pre-emptive fix for passkey autofill * fix: rust lint * fix: package-lock * fix: linux type error * fix: windows type error --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Andreas Coroiu <andreas.coroiu@gmail.com> Co-authored-by: Andreas Coroiu <acoroiu@bitwarden.com>
121 lines
3.8 KiB
TypeScript
121 lines
3.8 KiB
TypeScript
// FIXME: Update this file to be type safe and remove this and next line
|
|
// @ts-strict-ignore
|
|
import { ipcMain } from "electron";
|
|
import { concatMap, delay, filter, firstValueFrom, from, race, take, timer } from "rxjs";
|
|
|
|
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
|
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
|
|
import { sshagent } from "@bitwarden/desktop-napi";
|
|
|
|
class AgentResponse {
|
|
requestId: number;
|
|
accepted: boolean;
|
|
timestamp: Date;
|
|
}
|
|
|
|
export class MainSshAgentService {
|
|
SIGN_TIMEOUT = 60_000;
|
|
REQUEST_POLL_INTERVAL = 50;
|
|
|
|
private requestResponses: AgentResponse[] = [];
|
|
private request_id = 0;
|
|
private agentState: sshagent.SshAgentState;
|
|
|
|
constructor(
|
|
private logService: LogService,
|
|
private messagingService: MessagingService,
|
|
) {
|
|
ipcMain.handle("sshagent.init", async (event: any, message: any) => {
|
|
this.init();
|
|
});
|
|
|
|
ipcMain.handle("sshagent.isloaded", async (event: any) => {
|
|
return this.agentState != null;
|
|
});
|
|
}
|
|
|
|
init() {
|
|
// handle sign request passing to UI
|
|
sshagent
|
|
.serve(async (err: Error | null, sshUiRequest: sshagent.SshUiRequest): Promise<boolean> => {
|
|
// clear all old (> SIGN_TIMEOUT) requests
|
|
this.requestResponses = this.requestResponses.filter(
|
|
(response) => response.timestamp > new Date(Date.now() - this.SIGN_TIMEOUT),
|
|
);
|
|
|
|
this.request_id += 1;
|
|
const id_for_this_request = this.request_id;
|
|
this.messagingService.send("sshagent.signrequest", {
|
|
cipherId: sshUiRequest.cipherId,
|
|
isListRequest: sshUiRequest.isList,
|
|
requestId: id_for_this_request,
|
|
processName: sshUiRequest.processName,
|
|
isAgentForwarding: sshUiRequest.isForwarding,
|
|
namespace: sshUiRequest.namespace,
|
|
});
|
|
|
|
const result = await firstValueFrom(
|
|
race(
|
|
from([false]).pipe(delay(this.SIGN_TIMEOUT)),
|
|
|
|
//poll for response
|
|
timer(0, this.REQUEST_POLL_INTERVAL).pipe(
|
|
concatMap(() => from(this.requestResponses)),
|
|
filter((response) => response.requestId == id_for_this_request),
|
|
take(1),
|
|
concatMap(() => from([true])),
|
|
),
|
|
),
|
|
);
|
|
|
|
if (!result) {
|
|
return false;
|
|
}
|
|
|
|
const response = this.requestResponses.find(
|
|
(response) => response.requestId == id_for_this_request,
|
|
);
|
|
|
|
this.requestResponses = this.requestResponses.filter(
|
|
(response) => response.requestId != id_for_this_request,
|
|
);
|
|
|
|
return response.accepted;
|
|
})
|
|
.then((agentState: sshagent.SshAgentState) => {
|
|
this.agentState = agentState;
|
|
this.logService.info("SSH agent started");
|
|
})
|
|
.catch((e) => {
|
|
this.logService.error("SSH agent encountered an error: ", e);
|
|
});
|
|
|
|
ipcMain.handle(
|
|
"sshagent.setkeys",
|
|
async (event: any, keys: { name: string; privateKey: string; cipherId: string }[]) => {
|
|
if (this.agentState != null && (await sshagent.isRunning(this.agentState))) {
|
|
sshagent.setKeys(this.agentState, keys);
|
|
}
|
|
},
|
|
);
|
|
ipcMain.handle(
|
|
"sshagent.signrequestresponse",
|
|
async (event: any, { requestId, accepted }: { requestId: number; accepted: boolean }) => {
|
|
this.requestResponses.push({ requestId, accepted, timestamp: new Date() });
|
|
},
|
|
);
|
|
|
|
ipcMain.handle("sshagent.lock", async (event: any) => {
|
|
if (this.agentState != null && (await sshagent.isRunning(this.agentState))) {
|
|
sshagent.lock(this.agentState);
|
|
}
|
|
});
|
|
|
|
ipcMain.handle("sshagent.clearkeys", async (event: any) => {
|
|
if (this.agentState != null) {
|
|
sshagent.clearKeys(this.agentState);
|
|
}
|
|
});
|
|
}
|
|
}
|