mirror of
https://github.com/bitwarden/browser
synced 2025-12-30 07:03:26 +00:00
[BEEEP/PM-22958] Update russh version, and add sessionbind information (#14602)
* Update russh version, and add sessionbind information * Cargo fmt * Clean up to fix lint * Attempt to fix windows * Use expect instead of unwrap * Fix cargo toml
This commit is contained in:
@@ -3,10 +3,14 @@ use std::sync::{
|
||||
Arc,
|
||||
};
|
||||
|
||||
use base64::{engine::general_purpose::STANDARD, Engine as _};
|
||||
use tokio::sync::Mutex;
|
||||
use tokio_util::sync::CancellationToken;
|
||||
|
||||
use bitwarden_russh::ssh_agent::{self, Key};
|
||||
use bitwarden_russh::{
|
||||
session_bind::SessionBindResult,
|
||||
ssh_agent::{self, SshKey},
|
||||
};
|
||||
|
||||
#[cfg_attr(target_os = "windows", path = "windows.rs")]
|
||||
#[cfg_attr(target_os = "macos", path = "unix.rs")]
|
||||
@@ -20,8 +24,8 @@ pub mod peerinfo;
|
||||
mod request_parser;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct BitwardenDesktopAgent {
|
||||
keystore: ssh_agent::KeyStore,
|
||||
pub struct BitwardenDesktopAgent<Key> {
|
||||
keystore: ssh_agent::KeyStore<Key>,
|
||||
cancellation_token: CancellationToken,
|
||||
show_ui_request_tx: tokio::sync::mpsc::Sender<SshAgentUIRequest>,
|
||||
get_ui_response_rx: Arc<Mutex<tokio::sync::broadcast::Receiver<(u32, bool)>>>,
|
||||
@@ -40,8 +44,47 @@ pub struct SshAgentUIRequest {
|
||||
pub is_forwarding: bool,
|
||||
}
|
||||
|
||||
impl ssh_agent::Agent<peerinfo::models::PeerInfo> for BitwardenDesktopAgent {
|
||||
async fn confirm(&self, ssh_key: Key, data: &[u8], info: &peerinfo::models::PeerInfo) -> bool {
|
||||
#[derive(Clone)]
|
||||
pub struct BitwardenSshKey {
|
||||
pub private_key: Option<ssh_key::private::PrivateKey>,
|
||||
pub name: String,
|
||||
pub cipher_uuid: String,
|
||||
}
|
||||
|
||||
impl SshKey for BitwardenSshKey {
|
||||
fn name(&self) -> &str {
|
||||
&self.name
|
||||
}
|
||||
|
||||
fn public_key_bytes(&self) -> Vec<u8> {
|
||||
if let Some(ref private_key) = self.private_key {
|
||||
private_key
|
||||
.public_key()
|
||||
.to_bytes()
|
||||
.expect("Cipher private key is always correctly parsed")
|
||||
} else {
|
||||
Vec::new()
|
||||
}
|
||||
}
|
||||
|
||||
fn private_key(&self) -> Option<Box<dyn ssh_key::SigningKey>> {
|
||||
if let Some(ref private_key) = self.private_key {
|
||||
Some(Box::new(private_key.clone()))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ssh_agent::Agent<peerinfo::models::PeerInfo, BitwardenSshKey>
|
||||
for BitwardenDesktopAgent<BitwardenSshKey>
|
||||
{
|
||||
async fn confirm(
|
||||
&self,
|
||||
ssh_key: BitwardenSshKey,
|
||||
data: &[u8],
|
||||
info: &peerinfo::models::PeerInfo,
|
||||
) -> bool {
|
||||
if !self.is_running() {
|
||||
println!("[BitwardenDesktopAgent] Agent is not running, but tried to call confirm");
|
||||
return false;
|
||||
@@ -63,10 +106,11 @@ impl ssh_agent::Agent<peerinfo::models::PeerInfo> for BitwardenDesktopAgent {
|
||||
};
|
||||
|
||||
println!(
|
||||
"[SSH Agent] Confirming request from application: {}, is_forwarding: {}, namespace: {}",
|
||||
"[SSH Agent] Confirming request from application: {}, is_forwarding: {}, namespace: {}, host_key: {}",
|
||||
info.process_name(),
|
||||
info.is_forwarding(),
|
||||
namespace.clone().unwrap_or_default(),
|
||||
STANDARD.encode(info.host_key())
|
||||
);
|
||||
|
||||
let mut rx_channel = self.get_ui_response_rx.lock().await.resubscribe();
|
||||
@@ -117,19 +161,24 @@ impl ssh_agent::Agent<peerinfo::models::PeerInfo> for BitwardenDesktopAgent {
|
||||
false
|
||||
}
|
||||
|
||||
async fn set_is_forwarding(
|
||||
async fn set_sessionbind_info(
|
||||
&self,
|
||||
is_forwarding: bool,
|
||||
session_bind_info_result: &SessionBindResult,
|
||||
connection_info: &peerinfo::models::PeerInfo,
|
||||
) {
|
||||
// is_forwarding can only be added but never removed from a connection
|
||||
if is_forwarding {
|
||||
connection_info.set_forwarding(is_forwarding);
|
||||
match session_bind_info_result {
|
||||
SessionBindResult::Success(session_bind_info) => {
|
||||
connection_info.set_forwarding(session_bind_info.is_forwarding);
|
||||
connection_info.set_host_key(session_bind_info.host_key.clone());
|
||||
}
|
||||
SessionBindResult::SignatureFailure => {
|
||||
println!("[BitwardenDesktopAgent] Session bind failure: Signature failure");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl BitwardenDesktopAgent {
|
||||
impl BitwardenDesktopAgent<BitwardenSshKey> {
|
||||
pub fn stop(&self) {
|
||||
if !self.is_running() {
|
||||
println!("[BitwardenDesktopAgent] Tried to stop agent while it is not running");
|
||||
@@ -170,7 +219,7 @@ impl BitwardenDesktopAgent {
|
||||
.expect("Cipher private key is always correctly parsed");
|
||||
keystore.0.write().expect("RwLock is not poisoned").insert(
|
||||
public_key_bytes,
|
||||
Key {
|
||||
BitwardenSshKey {
|
||||
private_key: Some(private_key),
|
||||
name: name.clone(),
|
||||
cipher_uuid: cipher_id.clone(),
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
use std::sync::{atomic::AtomicBool, Arc};
|
||||
use std::sync::{atomic::AtomicBool, Arc, Mutex};
|
||||
|
||||
/**
|
||||
* Peerinfo represents the information of a peer process connecting over a socket.
|
||||
* This can be later extended to include more information (icon, app name) for the corresponding application.
|
||||
*/
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct PeerInfo {
|
||||
uid: u32,
|
||||
pid: u32,
|
||||
process_name: String,
|
||||
is_forwarding: Arc<AtomicBool>,
|
||||
host_key: Arc<Mutex<Vec<u8>>>,
|
||||
}
|
||||
|
||||
impl PeerInfo {
|
||||
@@ -19,6 +20,7 @@ impl PeerInfo {
|
||||
pid,
|
||||
process_name,
|
||||
is_forwarding: Arc::new(AtomicBool::new(false)),
|
||||
host_key: Arc::new(Mutex::new(Vec::new())),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +30,7 @@ impl PeerInfo {
|
||||
pid: 0,
|
||||
process_name: "Unknown application".to_string(),
|
||||
is_forwarding: Arc::new(AtomicBool::new(false)),
|
||||
host_key: Arc::new(Mutex::new(Vec::new())),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,4 +55,13 @@ impl PeerInfo {
|
||||
self.is_forwarding
|
||||
.store(value, std::sync::atomic::Ordering::Relaxed);
|
||||
}
|
||||
|
||||
pub fn set_host_key(&self, host_key: Vec<u8>) {
|
||||
let mut host_key_lock = self.host_key.lock().expect("Mutex is not poisoned");
|
||||
*host_key_lock = host_key;
|
||||
}
|
||||
|
||||
pub fn host_key(&self) -> Vec<u8> {
|
||||
self.host_key.lock().expect("Mutex is not poisoned").clone()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,9 +15,9 @@ use tokio_util::sync::CancellationToken;
|
||||
|
||||
use crate::ssh_agent::peercred_unix_listener_stream::PeercredUnixListenerStream;
|
||||
|
||||
use super::{BitwardenDesktopAgent, SshAgentUIRequest};
|
||||
use super::{BitwardenDesktopAgent, BitwardenSshKey, SshAgentUIRequest};
|
||||
|
||||
impl BitwardenDesktopAgent {
|
||||
impl BitwardenDesktopAgent<BitwardenSshKey> {
|
||||
pub async fn start_server(
|
||||
auth_request_tx: tokio::sync::mpsc::Sender<SshAgentUIRequest>,
|
||||
auth_response_rx: Arc<Mutex<tokio::sync::broadcast::Receiver<(u32, bool)>>>,
|
||||
|
||||
@@ -11,9 +11,9 @@ use std::{
|
||||
use tokio::sync::Mutex;
|
||||
use tokio_util::sync::CancellationToken;
|
||||
|
||||
use super::{BitwardenDesktopAgent, SshAgentUIRequest};
|
||||
use super::{BitwardenDesktopAgent, BitwardenSshKey, SshAgentUIRequest};
|
||||
|
||||
impl BitwardenDesktopAgent {
|
||||
impl BitwardenDesktopAgent<BitwardenSshKey> {
|
||||
pub async fn start_server(
|
||||
auth_request_tx: tokio::sync::mpsc::Sender<SshAgentUIRequest>,
|
||||
auth_response_rx: Arc<Mutex<tokio::sync::broadcast::Receiver<(u32, bool)>>>,
|
||||
|
||||
Reference in New Issue
Block a user