ssh_utils_lib/ssh/
password_session.rs1use crate::ssh::ssh_session::{SshSession, AuthMethod};
2use std::sync::Arc;
3use anyhow::Result;
4use async_trait::async_trait;
5use russh::keys::*;
6use russh::*;
7use tokio::net::ToSocketAddrs;
8use super::common::{default_ssh_config, SshChannel};
9
10pub struct Client {}
11
12#[async_trait]
16impl client::Handler for Client {
17 type Error = russh::Error;
18
19 async fn check_server_key(
20 &mut self,
21 _server_public_key: &key::PublicKey,
22 ) -> Result<bool, Self::Error> {
23 Ok(true)
24 }
25}
26
27pub struct PasswordSession {
28 session: client::Handle<Client>
29}
30
31#[async_trait]
32impl SshSession for PasswordSession {
33 async fn connect<A: ToSocketAddrs + Send>(
34 user: impl Into<String> + Send,
35 auth: impl Into<AuthMethod> + Send,
36 addrs: A,
37 ) -> Result<Self> {
38 let config = default_ssh_config();
39 let config = Arc::new(config);
40 let sh = Client {};
41
42 let mut session = client::connect(config, addrs, sh).await?;
43
44 let user = user.into();
45 let auth = auth.into();
46
47 match auth {
48 AuthMethod::Password(password) => {
49 let auth_res = session.authenticate_password(user, password).await?;
50 if !auth_res {
51 anyhow::bail!("Authentication (with password) failed");
52 }
53 }
54 AuthMethod::Key(_) => {
55 anyhow::bail!("Key authentication not implemented for PasswordSession");
56 }
57 }
58 Ok(Self {
59 session
60 })
61 }
62
63 async fn call(&mut self, command: &str) -> Result<u32> {
64 let channel = self.session.channel_open_session().await?;
65 let mut ssh_channel = SshChannel::new(channel).await?;
66 ssh_channel.call(command).await
67 }
68
69 async fn close(&mut self) -> Result<()> {
70 self.session
71 .disconnect(Disconnect::ByApplication, "", "English")
72 .await?;
73 Ok(())
74 }
75}