From 8a19e82564ca7c9aae3eac80ba3b63826fa6144d Mon Sep 17 00:00:00 2001 From: Pierce Bartine Date: Fri, 17 Apr 2026 13:44:26 -0700 Subject: [PATCH] Add SSH agent set/get support --- libssh2-sys/lib.rs | 2 ++ src/agent.rs | 23 +++++++++++++++++++++++ src/sftp.rs | 16 ++-------------- src/util.rs | 14 +++++++++++++- 4 files changed, 40 insertions(+), 15 deletions(-) diff --git a/libssh2-sys/lib.rs b/libssh2-sys/lib.rs index cf61641d..f58613d4 100644 --- a/libssh2-sys/lib.rs +++ b/libssh2-sys/lib.rs @@ -404,6 +404,8 @@ extern "C" { username: *const c_char, identity: *mut libssh2_agent_publickey, ) -> c_int; + pub fn libssh2_agent_set_identity_path(agent: *mut LIBSSH2_AGENT, path: *const c_char); + pub fn libssh2_agent_get_identity_path(agent: *mut LIBSSH2_AGENT) -> *const c_char; // channels pub fn libssh2_channel_free(chan: *mut LIBSSH2_CHANNEL) -> c_int; diff --git a/src/agent.rs b/src/agent.rs index df3e95e3..27a1e7c6 100644 --- a/src/agent.rs +++ b/src/agent.rs @@ -1,10 +1,12 @@ use parking_lot::{Mutex, MutexGuard}; use std::ffi::{CStr, CString}; +use std::path::{Path, PathBuf}; use std::ptr::null_mut; use std::slice; use std::str; use std::sync::Arc; +use util; use {raw, Error, ErrorCode, SessionInner}; /// A structure representing a connection to an SSH agent. @@ -125,6 +127,27 @@ impl Agent { )) } } + + /// Set a custom agent socket path to connect to. + pub fn set_identity_path(&mut self, path: &Path) -> Result<(), Error> { + let path = CString::new(util::path2bytes(path)?)?; + unsafe { + raw::libssh2_agent_set_identity_path(self.raw, path.as_ptr()); + } + Ok(()) + } + + /// Get the custom agent socket path, if set. + pub fn identity_path(&self) -> Option { + unsafe { + let ptr = raw::libssh2_agent_get_identity_path(self.raw); + if ptr.is_null() { + None + } else { + Some(util::mkpath(CStr::from_ptr(ptr).to_bytes())) + } + } + } } impl Drop for Agent { diff --git a/src/sftp.rs b/src/sftp.rs index 4fb9d827..0c4394c5 100644 --- a/src/sftp.rs +++ b/src/sftp.rs @@ -388,7 +388,7 @@ impl Sftp { } Self::rc(&locked, rc).map(move |_| { unsafe { ret.set_len(rc as usize) } - mkpath(ret) + util::mkpath(&ret) }) } @@ -644,7 +644,7 @@ impl File { unsafe { buf.set_len(rc as usize); } - (mkpath(buf), FileStat::from_raw(&stat)) + (util::mkpath(&buf), FileStat::from_raw(&stat)) }) } } @@ -907,15 +907,3 @@ impl FileType { } } } - -#[cfg(unix)] -fn mkpath(v: Vec) -> PathBuf { - use std::ffi::OsStr; - use std::os::unix::prelude::*; - PathBuf::from(OsStr::from_bytes(&v)) -} -#[cfg(windows)] -fn mkpath(v: Vec) -> PathBuf { - use std::str; - PathBuf::from(str::from_utf8(&v).unwrap()) -} diff --git a/src/util.rs b/src/util.rs index 2a0adc62..1f5b85d3 100644 --- a/src/util.rs +++ b/src/util.rs @@ -1,5 +1,5 @@ use std::borrow::Cow; -use std::path::Path; +use std::path::{Path, PathBuf}; use {raw, Error, ErrorCode}; @@ -37,6 +37,18 @@ pub fn path2bytes(p: &Path) -> Result, Error> { .and_then(check) } +#[cfg(unix)] +pub fn mkpath(bytes: &[u8]) -> PathBuf { + use std::ffi::OsStr; + use std::os::unix::prelude::*; + PathBuf::from(OsStr::from_bytes(bytes)) +} +#[cfg(windows)] +pub fn mkpath(bytes: &[u8]) -> PathBuf { + use std::str; + PathBuf::from(str::from_utf8(bytes).unwrap()) +} + fn check(b: Cow<[u8]>) -> Result, Error> { if b.iter().any(|b| *b == 0) { Err(Error::new(