1
0
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:
Bernd Schoolmann
2025-07-09 16:52:47 +02:00
committed by GitHub
parent 489cbd4856
commit e7d5cde105
7 changed files with 241 additions and 22 deletions

View File

@@ -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(),

View File

@@ -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()
}
}

View File

@@ -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)>>>,

View File

@@ -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)>>>,