Make list messaging explicit
This commit is contained in:
parent
4283970b53
commit
6435845438
|
@ -17,7 +17,7 @@ pub mod importer;
|
||||||
pub struct BitwardenDesktopAgent {
|
pub struct BitwardenDesktopAgent {
|
||||||
keystore: ssh_agent::KeyStore,
|
keystore: ssh_agent::KeyStore,
|
||||||
cancellation_token: CancellationToken,
|
cancellation_token: CancellationToken,
|
||||||
show_ui_request_tx: tokio::sync::mpsc::Sender<(u32, String)>,
|
show_ui_request_tx: tokio::sync::mpsc::Sender<(u32, (String, bool))>,
|
||||||
get_ui_response_rx: Arc<Mutex<tokio::sync::broadcast::Receiver<(u32, bool)>>>,
|
get_ui_response_rx: Arc<Mutex<tokio::sync::broadcast::Receiver<(u32, bool)>>>,
|
||||||
request_id: Arc<Mutex<u32>>,
|
request_id: Arc<Mutex<u32>>,
|
||||||
/// before first unlock, or after account switching, listing keys should require an unlock to get a list of public keys
|
/// before first unlock, or after account switching, listing keys should require an unlock to get a list of public keys
|
||||||
|
@ -35,8 +35,9 @@ impl ssh_agent::Agent for BitwardenDesktopAgent {
|
||||||
let request_id = self.get_request_id().await;
|
let request_id = self.get_request_id().await;
|
||||||
|
|
||||||
let mut rx_channel = self.get_ui_response_rx.lock().await.resubscribe();
|
let mut rx_channel = self.get_ui_response_rx.lock().await.resubscribe();
|
||||||
|
let message = (request_id, (ssh_key.cipher_uuid.clone(), false));
|
||||||
self.show_ui_request_tx
|
self.show_ui_request_tx
|
||||||
.send((request_id, ssh_key.cipher_uuid.clone()))
|
.send(message)
|
||||||
.await
|
.await
|
||||||
.expect("Should send request to ui");
|
.expect("Should send request to ui");
|
||||||
while let Ok((id, response)) = rx_channel.recv().await {
|
while let Ok((id, response)) = rx_channel.recv().await {
|
||||||
|
@ -55,8 +56,9 @@ impl ssh_agent::Agent for BitwardenDesktopAgent {
|
||||||
let request_id = self.get_request_id().await;
|
let request_id = self.get_request_id().await;
|
||||||
|
|
||||||
let mut rx_channel = self.get_ui_response_rx.lock().await.resubscribe();
|
let mut rx_channel = self.get_ui_response_rx.lock().await.resubscribe();
|
||||||
|
let message = (request_id, ("".to_string(), true));
|
||||||
self.show_ui_request_tx
|
self.show_ui_request_tx
|
||||||
.send((request_id, "".to_string()))
|
.send(message)
|
||||||
.await
|
.await
|
||||||
.expect("Should send request to ui");
|
.expect("Should send request to ui");
|
||||||
while let Ok((id, response)) = rx_channel.recv().await {
|
while let Ok((id, response)) = rx_channel.recv().await {
|
||||||
|
|
|
@ -14,7 +14,7 @@ use super::BitwardenDesktopAgent;
|
||||||
|
|
||||||
impl BitwardenDesktopAgent {
|
impl BitwardenDesktopAgent {
|
||||||
pub async fn start_server(
|
pub async fn start_server(
|
||||||
auth_request_tx: tokio::sync::mpsc::Sender<(u32, String)>,
|
auth_request_tx: tokio::sync::mpsc::Sender<(u32, (String, bool))>,
|
||||||
auth_response_rx: Arc<Mutex<tokio::sync::broadcast::Receiver<(u32, bool)>>>,
|
auth_response_rx: Arc<Mutex<tokio::sync::broadcast::Receiver<(u32, bool)>>>,
|
||||||
) -> Result<Self, anyhow::Error> {
|
) -> Result<Self, anyhow::Error> {
|
||||||
let agent = BitwardenDesktopAgent {
|
let agent = BitwardenDesktopAgent {
|
||||||
|
|
|
@ -12,7 +12,7 @@ use super::BitwardenDesktopAgent;
|
||||||
|
|
||||||
impl BitwardenDesktopAgent {
|
impl BitwardenDesktopAgent {
|
||||||
pub async fn start_server(
|
pub async fn start_server(
|
||||||
auth_request_tx: tokio::sync::mpsc::Sender<(u32, String)>,
|
auth_request_tx: tokio::sync::mpsc::Sender<(u32, (String, bool))>,
|
||||||
auth_response_rx: Arc<Mutex<tokio::sync::broadcast::Receiver<(u32, bool)>>>,
|
auth_response_rx: Arc<Mutex<tokio::sync::broadcast::Receiver<(u32, bool)>>>,
|
||||||
) -> Result<Self, anyhow::Error> {
|
) -> Result<Self, anyhow::Error> {
|
||||||
let agent_state = BitwardenDesktopAgent {
|
let agent_state = BitwardenDesktopAgent {
|
||||||
|
|
|
@ -69,7 +69,7 @@ export declare namespace sshagent {
|
||||||
status: SshKeyImportStatus
|
status: SshKeyImportStatus
|
||||||
sshKey?: SshKey
|
sshKey?: SshKey
|
||||||
}
|
}
|
||||||
export function serve(callback: (err: Error | null, arg: string) => any): Promise<SshAgentState>
|
export function serve(callback: (err: Error | null, arg0: string, arg1: boolean) => any): Promise<SshAgentState>
|
||||||
export function stop(agentState: SshAgentState): void
|
export function stop(agentState: SshAgentState): void
|
||||||
export function isRunning(agentState: SshAgentState): boolean
|
export function isRunning(agentState: SshAgentState): boolean
|
||||||
export function setKeys(agentState: SshAgentState, newKeys: Array<PrivateKey>): void
|
export function setKeys(agentState: SshAgentState, newKeys: Array<PrivateKey>): void
|
||||||
|
|
|
@ -247,15 +247,15 @@ pub mod sshagent {
|
||||||
|
|
||||||
#[napi]
|
#[napi]
|
||||||
pub async fn serve(
|
pub async fn serve(
|
||||||
callback: ThreadsafeFunction<String, CalleeHandled>,
|
callback: ThreadsafeFunction<(String, bool), CalleeHandled>,
|
||||||
) -> napi::Result<SshAgentState> {
|
) -> napi::Result<SshAgentState> {
|
||||||
let (auth_request_tx, mut auth_request_rx) = tokio::sync::mpsc::channel::<(u32, String)>(32);
|
let (auth_request_tx, mut auth_request_rx) = tokio::sync::mpsc::channel::<(u32, (String, bool))>(32);
|
||||||
let (auth_response_tx, auth_response_rx) = tokio::sync::broadcast::channel::<(u32, bool)>(32);
|
let (auth_response_tx, auth_response_rx) = tokio::sync::broadcast::channel::<(u32, bool)>(32);
|
||||||
let auth_response_tx_arc = Arc::new(Mutex::new(auth_response_tx));
|
let auth_response_tx_arc = Arc::new(Mutex::new(auth_response_tx));
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
let _ = auth_response_rx;
|
let _ = auth_response_rx;
|
||||||
|
|
||||||
while let Some((request_id, cipher_uuid)) = auth_request_rx.recv().await {
|
while let Some((request_id, (cipher_uuid, is_list_request))) = auth_request_rx.recv().await {
|
||||||
let cloned_request_id = request_id.clone();
|
let cloned_request_id = request_id.clone();
|
||||||
let cloned_cipher_uuid = cipher_uuid.clone();
|
let cloned_cipher_uuid = cipher_uuid.clone();
|
||||||
let cloned_response_tx_arc = auth_response_tx_arc.clone();
|
let cloned_response_tx_arc = auth_response_tx_arc.clone();
|
||||||
|
@ -266,7 +266,7 @@ pub mod sshagent {
|
||||||
let auth_response_tx_arc = cloned_response_tx_arc;
|
let auth_response_tx_arc = cloned_response_tx_arc;
|
||||||
let callback = cloned_callback;
|
let callback = cloned_callback;
|
||||||
let promise_result: Result<Promise<bool>, napi::Error> =
|
let promise_result: Result<Promise<bool>, napi::Error> =
|
||||||
callback.call_async(Ok(cipher_uuid)).await;
|
callback.call_async(Ok((cipher_uuid, is_list_request))).await;
|
||||||
match promise_result {
|
match promise_result {
|
||||||
Ok(promise_result) => match promise_result.await {
|
Ok(promise_result) => match promise_result.await {
|
||||||
Ok(result) => {
|
Ok(result) => {
|
||||||
|
|
|
@ -27,7 +27,7 @@ export class MainSshAgentService {
|
||||||
init() {
|
init() {
|
||||||
// handle sign request passing to UI
|
// handle sign request passing to UI
|
||||||
sshagent
|
sshagent
|
||||||
.serve(async (err: Error, cipherId: string) => {
|
.serve(async (err: Error, cipherId: string, isListRequest: boolean) => {
|
||||||
// clear all old (> SIGN_TIMEOUT) requests
|
// clear all old (> SIGN_TIMEOUT) requests
|
||||||
this.requestResponses = this.requestResponses.filter(
|
this.requestResponses = this.requestResponses.filter(
|
||||||
(response) => response.timestamp > new Date(Date.now() - this.SIGN_TIMEOUT),
|
(response) => response.timestamp > new Date(Date.now() - this.SIGN_TIMEOUT),
|
||||||
|
@ -37,6 +37,7 @@ export class MainSshAgentService {
|
||||||
const id_for_this_request = this.request_id;
|
const id_for_this_request = this.request_id;
|
||||||
this.messagingService.send("sshagent.signrequest", {
|
this.messagingService.send("sshagent.signrequest", {
|
||||||
cipherId,
|
cipherId,
|
||||||
|
isListRequest,
|
||||||
requestId: id_for_this_request,
|
requestId: id_for_this_request,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -115,36 +115,33 @@ export class SshAgentService implements OnDestroy {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
// This concatMap handles showing the dialog to approve the request.
|
// This concatMap handles showing the dialog to approve the request.
|
||||||
concatMap(([message, ciphers]) => {
|
switchMap(([message, ciphers]) => {
|
||||||
const cipherId = message.cipherId as string;
|
const cipherId = message.cipherId as string;
|
||||||
|
const isListRequest = message.isListRequest as boolean;
|
||||||
const requestId = message.requestId as number;
|
const requestId = message.requestId as number;
|
||||||
|
|
||||||
// cipherid is empty has the special meaning of "unlock in order to list public keys"
|
if (isListRequest) {
|
||||||
if (cipherId == "") {
|
(async () => {
|
||||||
return of(true).pipe(
|
const sshCiphers = ciphers.filter(
|
||||||
switchMap(async (result) => {
|
(cipher) => cipher.type === CipherType.SshKey && !cipher.isDeleted,
|
||||||
const sshCiphers = ciphers.filter(
|
);
|
||||||
(cipher) => cipher.type === CipherType.SshKey && !cipher.isDeleted,
|
const keys = sshCiphers.map((cipher) => {
|
||||||
);
|
return {
|
||||||
const keys = sshCiphers.map((cipher) => {
|
name: cipher.name,
|
||||||
return {
|
privateKey: cipher.sshKey.privateKey,
|
||||||
name: cipher.name,
|
cipherId: cipher.id,
|
||||||
privateKey: cipher.sshKey.privateKey,
|
};
|
||||||
cipherId: cipher.id,
|
});
|
||||||
};
|
await ipc.platform.sshAgent.setKeys(keys);
|
||||||
});
|
await ipc.platform.sshAgent.signRequestResponse(requestId, true);
|
||||||
await ipc.platform.sshAgent.setKeys(keys);
|
})().catch((e) => this.logService.error("Failed to respond to SSH request", e));
|
||||||
await ipc.platform.sshAgent.signRequestResponse(requestId, Boolean(result));
|
return;
|
||||||
}),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ciphers === undefined) {
|
if (ciphers === undefined) {
|
||||||
return of(false).pipe(
|
ipc.platform.sshAgent
|
||||||
switchMap((result) =>
|
.signRequestResponse(requestId, false)
|
||||||
ipc.platform.sshAgent.signRequestResponse(requestId, Boolean(result)),
|
.catch((e) => this.logService.error("Failed to respond to SSH request", e));
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const cipher = ciphers.find((cipher) => cipher.id == cipherId);
|
const cipher = ciphers.find((cipher) => cipher.id == cipherId);
|
||||||
|
@ -158,7 +155,7 @@ export class SshAgentService implements OnDestroy {
|
||||||
|
|
||||||
return dialogRef.closed.pipe(
|
return dialogRef.closed.pipe(
|
||||||
switchMap((result) => {
|
switchMap((result) => {
|
||||||
return ipc.platform.sshAgent.signRequestResponse(requestId, Boolean(result));
|
return ipc.platform.sshAgent.signRequestResponse(requestId, result);
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
|
|
Loading…
Reference in New Issue