ssh_utils_lib/ssh/
password_session.rs

1use 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// More SSH event handlers
13// can be defined in this trait
14// In this example, we're only using Channel, so these aren't needed.
15#[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}