SSH key storage in scp/sftp file transfers

This commit is contained in:
ChristianVisintin
2020-12-24 17:27:57 +01:00
parent 920d3b4af4
commit 6bf503331e
3 changed files with 129 additions and 71 deletions

View File

@@ -30,6 +30,7 @@ extern crate ssh2;
// Locals
use super::{FileTransfer, FileTransferError, FileTransferErrorType};
use crate::fs::{FsDirectory, FsEntry, FsFile};
use crate::system::sshkey_storage::SshKeyStorage;
use crate::utils::parser::parse_lstime;
// Includes
@@ -46,22 +47,18 @@ use std::time::SystemTime;
pub struct ScpFileTransfer {
session: Option<Session>,
wrkdir: PathBuf,
}
impl Default for ScpFileTransfer {
fn default() -> Self {
Self::new()
}
key_storage: SshKeyStorage,
}
impl ScpFileTransfer {
/// ### new
///
/// Instantiates a new ScpFileTransfer
pub fn new() -> ScpFileTransfer {
pub fn new(key_storage: SshKeyStorage) -> ScpFileTransfer {
ScpFileTransfer {
session: None,
wrkdir: PathBuf::from("~"),
key_storage,
}
}
@@ -345,17 +342,36 @@ impl FileTransfer for ScpFileTransfer {
Some(u) => u,
None => String::from(""),
};
// Try authenticating with user agent
if session.userauth_agent(username.as_str()).is_err() {
// Try authentication with password then
if let Err(err) = session.userauth_password(
username.as_str(),
password.unwrap_or_else(|| String::from("")).as_str(),
) {
return Err(FileTransferError::new_ex(
FileTransferErrorType::AuthenticationFailed,
format!("{}", err),
));
// Check if it is possible to authenticate using a RSA key
match self
.key_storage
.resolve(address.as_str(), username.as_str())
{
Some(rsa_key) => {
// Authenticate with RSA key
if let Err(err) = session.userauth_pubkey_file(
username.as_str(),
None,
rsa_key.as_path(),
password.as_deref(),
) {
return Err(FileTransferError::new_ex(
FileTransferErrorType::AuthenticationFailed,
format!("{}", err),
));
}
}
None => {
// Proceeed with username/password authentication
if let Err(err) = session.userauth_password(
username.as_str(),
password.unwrap_or_else(|| String::from("")).as_str(),
) {
return Err(FileTransferError::new_ex(
FileTransferErrorType::AuthenticationFailed,
format!("{}", err),
));
}
}
}
// Get banner
@@ -823,14 +839,14 @@ mod tests {
#[test]
fn test_filetransfer_scp_new() {
let client: ScpFileTransfer = ScpFileTransfer::new();
let client: ScpFileTransfer = ScpFileTransfer::new(SshKeyStorage::empty());
assert!(client.session.is_none());
assert_eq!(client.is_connected(), false);
}
#[test]
fn test_filetransfer_scp_connect() {
let mut client: ScpFileTransfer = ScpFileTransfer::new();
let mut client: ScpFileTransfer = ScpFileTransfer::new(SshKeyStorage::empty());
assert_eq!(client.is_connected(), false);
assert!(client
.connect(
@@ -849,7 +865,7 @@ mod tests {
}
#[test]
fn test_filetransfer_scp_bad_auth() {
let mut client: ScpFileTransfer = ScpFileTransfer::new();
let mut client: ScpFileTransfer = ScpFileTransfer::new(SshKeyStorage::empty());
assert!(client
.connect(
String::from("test.rebex.net"),
@@ -862,7 +878,7 @@ mod tests {
#[test]
fn test_filetransfer_scp_no_credentials() {
let mut client: ScpFileTransfer = ScpFileTransfer::new();
let mut client: ScpFileTransfer = ScpFileTransfer::new(SshKeyStorage::empty());
assert!(client
.connect(String::from("test.rebex.net"), 22, None, None)
.is_err());
@@ -870,7 +886,7 @@ mod tests {
#[test]
fn test_filetransfer_scp_bad_server() {
let mut client: ScpFileTransfer = ScpFileTransfer::new();
let mut client: ScpFileTransfer = ScpFileTransfer::new(SshKeyStorage::empty());
assert!(client
.connect(
String::from("mybadserver.veryverybad.awful"),
@@ -882,7 +898,7 @@ mod tests {
}
#[test]
fn test_filetransfer_scp_pwd() {
let mut client: ScpFileTransfer = ScpFileTransfer::new();
let mut client: ScpFileTransfer = ScpFileTransfer::new(SshKeyStorage::empty());
assert!(client
.connect(
String::from("test.rebex.net"),
@@ -902,7 +918,7 @@ mod tests {
#[test]
#[cfg(any(target_os = "unix", target_os = "macos", target_os = "linux"))]
fn test_filetransfer_scp_cwd() {
let mut client: ScpFileTransfer = ScpFileTransfer::new();
let mut client: ScpFileTransfer = ScpFileTransfer::new(SshKeyStorage::empty());
assert!(client
.connect(
String::from("test.rebex.net"),
@@ -923,7 +939,7 @@ mod tests {
#[test]
fn test_filetransfer_scp_cwd_error() {
let mut client: ScpFileTransfer = ScpFileTransfer::new();
let mut client: ScpFileTransfer = ScpFileTransfer::new(SshKeyStorage::empty());
assert!(client
.connect(
String::from("test.rebex.net"),
@@ -946,7 +962,7 @@ mod tests {
#[test]
fn test_filetransfer_scp_ls() {
let mut client: ScpFileTransfer = ScpFileTransfer::new();
let mut client: ScpFileTransfer = ScpFileTransfer::new(SshKeyStorage::empty());
assert!(client
.connect(
String::from("test.rebex.net"),
@@ -967,7 +983,7 @@ mod tests {
#[test]
fn test_filetransfer_scp_stat() {
let mut client: ScpFileTransfer = ScpFileTransfer::new();
let mut client: ScpFileTransfer = ScpFileTransfer::new(SshKeyStorage::empty());
assert!(client
.connect(
String::from("test.rebex.net"),
@@ -991,7 +1007,7 @@ mod tests {
#[test]
fn test_filetransfer_scp_recv() {
let mut client: ScpFileTransfer = ScpFileTransfer::new();
let mut client: ScpFileTransfer = ScpFileTransfer::new(SshKeyStorage::empty());
assert!(client
.connect(
String::from("test.rebex.net"),
@@ -1023,7 +1039,7 @@ mod tests {
}
#[test]
fn test_filetransfer_scp_recv_failed_nosuchfile() {
let mut client: ScpFileTransfer = ScpFileTransfer::new();
let mut client: ScpFileTransfer = ScpFileTransfer::new(SshKeyStorage::empty());
assert!(client
.connect(
String::from("test.rebex.net"),
@@ -1058,7 +1074,7 @@ mod tests {
/* NOTE: the server doesn't allow you to create directories
#[test]
fn test_filetransfer_scp_mkdir() {
let mut client: ScpFileTransfer = ScpFileTransfer::new();
let mut client: ScpFileTransfer = ScpFileTransfer::new(SshKeyStorage::empty());
assert!(client.connect(String::from("test.rebex.net"), 22, Some(String::from("demo")), Some(String::from("password"))).is_ok());
let dir: String = String::from("foo");
// Mkdir
@@ -1087,7 +1103,7 @@ mod tests {
group: Some(0), // UNIX only
unix_pex: Some((6, 4, 4)), // UNIX only
};
let mut scp: ScpFileTransfer = ScpFileTransfer::new();
let mut scp: ScpFileTransfer = ScpFileTransfer::new(SshKeyStorage::empty());
assert!(scp.change_dir(Path::new("/tmp")).is_err());
assert!(scp.disconnect().is_err());
assert!(scp.list_dir(Path::new("/tmp")).is_err());