@@ -13,6 +13,7 @@ use ssh2::{MethodType as SshMethodType, Session};
1313
1414use super :: config:: Config ;
1515use super :: SshOpts ;
16+ use crate :: SshAgentIdentity ;
1617
1718// -- connect
1819
@@ -79,29 +80,45 @@ pub fn connect(opts: &SshOpts) -> RemoteResult<Session> {
7980 error ! ( "SSH handshake failed: {}" , err) ;
8081 return Err ( RemoteError :: new_ex ( RemoteErrorType :: ProtocolError , err) ) ;
8182 }
82- // Authenticate with password or key
83- match opts. key_storage . as_ref ( ) . and_then ( |x| {
84- x. resolve ( ssh_config. host . as_str ( ) , ssh_config. username . as_str ( ) )
85- . or ( x. resolve (
86- ssh_config. resolved_host . as_str ( ) ,
87- ssh_config. username . as_str ( ) ,
88- ) )
89- } ) {
90- Some ( rsa_key) => {
91- session_auth_with_rsakey (
92- & mut session,
93- & ssh_config. username ,
94- rsa_key. as_path ( ) ,
95- opts. password . as_deref ( ) ,
96- ssh_config. params . identity_file . as_deref ( ) ,
97- ) ?;
83+
84+ // if use_ssh_agent is enabled, try to authenticate with ssh agent
85+ if let Some ( ssh_agent_config) = & opts. ssh_agent_identity {
86+ match session_auth_with_agent ( & mut session, & ssh_config. username , ssh_agent_config) {
87+ Ok ( _) => {
88+ info ! ( "Authenticated with ssh agent" ) ;
89+ return Ok ( session) ;
90+ }
91+ Err ( err) => {
92+ error ! ( "Could not authenticate with ssh agent: {}" , err) ;
93+ }
9894 }
99- None => {
100- session_auth_with_password (
101- & mut session,
102- & ssh_config. username ,
103- opts. password . as_deref ( ) ,
104- ) ?;
95+ }
96+
97+ // Authenticate with password or key
98+ if !session. authenticated ( ) {
99+ match opts. key_storage . as_ref ( ) . and_then ( |x| {
100+ x. resolve ( ssh_config. host . as_str ( ) , ssh_config. username . as_str ( ) )
101+ . or ( x. resolve (
102+ ssh_config. resolved_host . as_str ( ) ,
103+ ssh_config. username . as_str ( ) ,
104+ ) )
105+ } ) {
106+ Some ( rsa_key) => {
107+ session_auth_with_rsakey (
108+ & mut session,
109+ & ssh_config. username ,
110+ rsa_key. as_path ( ) ,
111+ opts. password . as_deref ( ) ,
112+ ssh_config. params . identity_file . as_deref ( ) ,
113+ ) ?;
114+ }
115+ None => {
116+ session_auth_with_password (
117+ & mut session,
118+ & ssh_config. username ,
119+ opts. password . as_deref ( ) ,
120+ ) ?;
121+ }
105122 }
106123 }
107124 // Return session
@@ -179,6 +196,58 @@ fn set_algo_prefs(session: &mut Session, opts: &SshOpts, config: &Config) -> Rem
179196 Ok ( ( ) )
180197}
181198
199+ /// Authenticate on session with ssh agent
200+ fn session_auth_with_agent (
201+ session : & mut Session ,
202+ username : & str ,
203+ ssh_agent_config : & SshAgentIdentity ,
204+ ) -> RemoteResult < ( ) > {
205+ let mut agent = session
206+ . agent ( )
207+ . map_err ( |err| RemoteError :: new_ex ( RemoteErrorType :: ConnectionError , err) ) ?;
208+
209+ agent
210+ . connect ( )
211+ . map_err ( |err| RemoteError :: new_ex ( RemoteErrorType :: ConnectionError , err) ) ?;
212+
213+ agent
214+ . list_identities ( )
215+ . map_err ( |err| RemoteError :: new_ex ( RemoteErrorType :: ConnectionError , err) ) ?;
216+
217+ let mut connection_result = Err ( RemoteError :: new ( RemoteErrorType :: AuthenticationFailed ) ) ;
218+
219+ for identity in agent
220+ . identities ( )
221+ . map_err ( |err| RemoteError :: new_ex ( RemoteErrorType :: ConnectionError , err) ) ?
222+ {
223+ if ssh_agent_config. pubkey_matches ( identity. blob ( ) ) {
224+ debug ! ( "Trying to authenticate with ssh agent with key: {identity:?}" ) ;
225+ } else {
226+ continue ;
227+ }
228+ match agent. userauth ( username, & identity) {
229+ Ok ( ( ) ) => {
230+ connection_result = Ok ( ( ) ) ;
231+ debug ! ( "Authenticated with ssh agent with key: {identity:?}" ) ;
232+ break ;
233+ }
234+ Err ( err) => {
235+ debug ! ( "SSH agent auth failed: {err}" ) ;
236+ connection_result = Err ( RemoteError :: new_ex (
237+ RemoteErrorType :: AuthenticationFailed ,
238+ err,
239+ ) ) ;
240+ }
241+ }
242+ }
243+
244+ if let Err ( err) = agent. disconnect ( ) {
245+ warn ! ( "Could not disconnect from ssh agent: {err}" ) ;
246+ }
247+
248+ connection_result
249+ }
250+
182251/// Authenticate on session with private key
183252fn session_auth_with_rsakey (
184253 session : & mut Session ,
0 commit comments