use ssh2::Session;
use std::path::Path;
use std::{io::Error, net::TcpStream};
pub struct SshCred<'a> {
auth: AuthOption<'a>,
host: String,
port: String,
}
pub enum AuthOption<'a> {
UserauthPassword(String, String),
UserauthAgent(String),
UserauthPubkeyFile(String, Option<&'a Path>, &'a Path, Option<&'a str>),
}
impl SshCred<'static> {
pub fn new(auth: AuthOption<'static>, host: String, port: String) -> Self {
SshCred { auth, host, port }
}
pub fn connect(&self) -> Result<Session, Error> {
let url_host = format!("{}:{}", self.host, self.port);
let tcp = TcpStream::connect(url_host)?;
let mut sess = Session::new()?;
sess.set_tcp_stream(tcp);
sess.handshake()?;
match &self.auth {
AuthOption::UserauthAgent(username) => sess.userauth_agent(&username)?,
AuthOption::UserauthPassword(username, password) => {
sess.userauth_password(&username, &password)?
}
AuthOption::UserauthPubkeyFile(username, pubkey, privatekey, passphrase) => {
sess.userauth_pubkey_file(&username, *pubkey, privatekey, *passphrase)?
}
};
Ok(sess)
}
}
#[cfg(test)]
mod tests {
use super::{AuthOption, SshCred};
use std::env;
#[test]
fn test_create_tcp_connection() {
match env::var_os("NAME") {
Some(u) => match env::var_os("PASS") {
Some(p) => {
let ssh = SshCred::new(
AuthOption::UserauthPassword(
u.to_str().unwrap().to_string(),
p.to_str().unwrap().to_string(),
),
"127.0.0.1".to_string(),
"22".to_string(),
);
let session = ssh.connect();
assert!(session.unwrap().authenticated())
}
None => {
println!("skipping create_tcp_connection() test...")
}
},
None => {
println!("skipping create_tcp_connection() test...")
}
};
}
}