Compare commits
5 commits
36a62018e5
...
32bce3dc4c
Author | SHA1 | Date | |
---|---|---|---|
32bce3dc4c | |||
7bbae7f21c | |||
bcc667f3ea | |||
0e4dd8a7a8 | |||
262c75d36d |
7 changed files with 81 additions and 15 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,3 +1,2 @@
|
||||||
/target
|
/target
|
||||||
.data/*.log
|
.data/*.log
|
||||||
*.pem*
|
|
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -3434,6 +3434,7 @@ dependencies = [
|
||||||
"directories",
|
"directories",
|
||||||
"futures",
|
"futures",
|
||||||
"human-panic",
|
"human-panic",
|
||||||
|
"indoc",
|
||||||
"json5",
|
"json5",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"libc",
|
"libc",
|
||||||
|
@ -3443,6 +3444,7 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"signal-hook",
|
"signal-hook",
|
||||||
|
"ssh-key",
|
||||||
"strip-ansi-escapes",
|
"strip-ansi-escapes",
|
||||||
"strum",
|
"strum",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
|
|
@ -26,6 +26,7 @@ derive_deref = "1.1.1"
|
||||||
directories = "5.0.1"
|
directories = "5.0.1"
|
||||||
futures = "0.3.31"
|
futures = "0.3.31"
|
||||||
human-panic = "2.0.2"
|
human-panic = "2.0.2"
|
||||||
|
indoc = "2.0.5"
|
||||||
json5 = "0.4.1"
|
json5 = "0.4.1"
|
||||||
lazy_static = "1.5.0"
|
lazy_static = "1.5.0"
|
||||||
libc = "0.2.161"
|
libc = "0.2.161"
|
||||||
|
@ -45,4 +46,5 @@ tracing-subscriber = { version = "0.3.18", features = ["env-filter", "serde"] }
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
anyhow = "1.0.90"
|
anyhow = "1.0.90"
|
||||||
|
ssh-key = { version = "0.6.7", features = ["getrandom", "crypto"] }
|
||||||
vergen-gix = { version = "1.0.2", features = ["build", "cargo"] }
|
vergen-gix = { version = "1.0.2", features = ["build", "cargo"] }
|
||||||
|
|
36
build.rs
36
build.rs
|
@ -1,7 +1,43 @@
|
||||||
|
use std::{env, path::PathBuf};
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
use ssh_key::{rand_core, Algorithm, EcdsaCurve, LineEnding, PrivateKey};
|
||||||
use vergen_gix::{BuildBuilder, CargoBuilder, Emitter, GixBuilder};
|
use vergen_gix::{BuildBuilder, CargoBuilder, Emitter, GixBuilder};
|
||||||
|
|
||||||
|
const SSH_KEY_ALGOS: &[(&'static str, Algorithm)] = &[
|
||||||
|
("rsa.pem", Algorithm::Rsa { hash: None }),
|
||||||
|
("ed25519.pem", Algorithm::Ed25519),
|
||||||
|
("ecdsa.pem", Algorithm::Ecdsa {
|
||||||
|
curve: EcdsaCurve::NistP256,
|
||||||
|
}),
|
||||||
|
];
|
||||||
|
|
||||||
fn main() -> Result<()> {
|
fn main() -> Result<()> {
|
||||||
|
println!("cargo:rerun-if-changed=build.rs");
|
||||||
|
|
||||||
|
// Generate openSSH host keys
|
||||||
|
let mut rng = rand_core::OsRng::default();
|
||||||
|
let keys = SSH_KEY_ALGOS
|
||||||
|
.iter()
|
||||||
|
.map(|(file_name, algo)| (*file_name, PrivateKey::random(&mut rng, algo.to_owned()).map_err(anyhow::Error::from)))
|
||||||
|
.collect::<Vec<(&str, Result<PrivateKey>)>>();
|
||||||
|
|
||||||
|
let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
|
||||||
|
for (file_name, key_res) in keys {
|
||||||
|
if let Ok(ref key) = key_res {
|
||||||
|
let path = out_dir.join(file_name);
|
||||||
|
if path.exists() {
|
||||||
|
println!("cargo:warning=Skipping existing host key: {:?}", path.file_stem());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
key.write_openssh_file(&path, LineEnding::default())?;
|
||||||
|
} else {
|
||||||
|
println!("cargo:warning=Failed to generate host key: {:?}", key_res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Emit the build information
|
||||||
let build = BuildBuilder::all_build()?;
|
let build = BuildBuilder::all_build()?;
|
||||||
let gix = GixBuilder::all_git()?;
|
let gix = GixBuilder::all_git()?;
|
||||||
let cargo = CargoBuilder::all_cargo()?;
|
let cargo = CargoBuilder::all_cargo()?;
|
||||||
|
|
21
src/cli.rs
21
src/cli.rs
|
@ -1,4 +1,5 @@
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
|
use indoc::formatdoc;
|
||||||
|
|
||||||
use crate::config::{get_config_dir, get_data_dir};
|
use crate::config::{get_config_dir, get_data_dir};
|
||||||
|
|
||||||
|
@ -12,6 +13,13 @@ pub struct Cli {
|
||||||
/// Frame rate, i.e. number of frames per second
|
/// Frame rate, i.e. number of frames per second
|
||||||
#[arg(short, long, value_name = "FLOAT", default_value_t = 60.0)]
|
#[arg(short, long, value_name = "FLOAT", default_value_t = 60.0)]
|
||||||
pub frame_rate: f64,
|
pub frame_rate: f64,
|
||||||
|
|
||||||
|
/// The host address to start the SSH server on
|
||||||
|
#[arg(short = 'H', long, value_name = "ADDRESS", default_value_t = String::from("127.0.0.1"))]
|
||||||
|
pub host: String,
|
||||||
|
/// The port to start the SSH server on
|
||||||
|
#[arg(short, long, value_name = "PORT", default_value_t = 2222)]
|
||||||
|
pub port: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
const VERSION_MESSAGE: &str = concat!(
|
const VERSION_MESSAGE: &str = concat!(
|
||||||
|
@ -30,13 +38,12 @@ pub fn version() -> String {
|
||||||
let config_dir_path = get_config_dir().display().to_string();
|
let config_dir_path = get_config_dir().display().to_string();
|
||||||
let data_dir_path = get_data_dir().display().to_string();
|
let data_dir_path = get_data_dir().display().to_string();
|
||||||
|
|
||||||
format!(
|
formatdoc! {"
|
||||||
"\
|
{VERSION_MESSAGE}
|
||||||
{VERSION_MESSAGE}
|
|
||||||
|
|
||||||
Authors: {author}
|
Authors: {author}
|
||||||
|
|
||||||
Config directory: {config_dir_path}
|
Config directory: {config_dir_path}
|
||||||
Data directory: {data_dir_path}"
|
Data directory: {data_dir_path}
|
||||||
)
|
"}
|
||||||
}
|
}
|
||||||
|
|
|
@ -110,6 +110,7 @@ impl KeyCodeExt for KeyCode {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use pretty_assertions::assert_eq;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_keycode_from_control_chars() {
|
fn test_keycode_from_control_chars() {
|
||||||
|
|
29
src/main.rs
29
src/main.rs
|
@ -24,23 +24,42 @@ mod ssh;
|
||||||
mod tui;
|
mod tui;
|
||||||
|
|
||||||
const SSH_KEYS: &[&[u8]] = &[
|
const SSH_KEYS: &[&[u8]] = &[
|
||||||
include_bytes!("../rsa.pem"),
|
include_bytes!(concat!(env!("OUT_DIR"), "/rsa.pem")),
|
||||||
include_bytes!("../ed25519.pem"),
|
include_bytes!(concat!(env!("OUT_DIR"), "/ecdsa.pem")),
|
||||||
|
include_bytes!(concat!(env!("OUT_DIR"), "/ed25519.pem")),
|
||||||
];
|
];
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
pub(crate) static ref OPTIONS: Cli = Cli::parse();
|
pub(crate) static ref OPTIONS: Cli = Cli::parse();
|
||||||
pub(crate) static ref SOCKET_ADDR: SocketAddr = SocketAddr::from(([127, 0, 0, 1], 2222));
|
pub(crate) static ref SOCKET_ADDR: Option<SocketAddr> = Some(SocketAddr::from((
|
||||||
|
// Convert the hostname IP to a fixed size array of [u8; 4]
|
||||||
|
TryInto::<[u8; 4]>::try_into(
|
||||||
|
OPTIONS
|
||||||
|
.host
|
||||||
|
.splitn(4, ".")
|
||||||
|
.map(|octet_str| u8::from_str_radix(octet_str, 10)
|
||||||
|
.map_err(|_| eyre!("Octet component out of range (expected u8)")))
|
||||||
|
.collect::<Result<Vec<u8>>>()
|
||||||
|
.ok()?
|
||||||
|
)
|
||||||
|
.ok()?,
|
||||||
|
|
||||||
|
// The port to listen on
|
||||||
|
OPTIONS.port
|
||||||
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<()> {
|
async fn main() -> Result<()> {
|
||||||
crate::errors::init()?;
|
crate::errors::init()?;
|
||||||
crate::logging::init()?;
|
crate::logging::init()?;
|
||||||
|
let _ = *OPTIONS; // force clap to run by evaluating it
|
||||||
|
|
||||||
|
let socket_addr = SOCKET_ADDR.ok_or(eyre!("Invalid host IP provided"))?;
|
||||||
let config = ssh_config();
|
let config = ssh_config();
|
||||||
tracing::info!("Attempting to listen on {}", *SOCKET_ADDR);
|
|
||||||
|
tracing::info!("Attempting to listen on {}", socket_addr);
|
||||||
SshServer::default()
|
SshServer::default()
|
||||||
.run_on_socket(Arc::new(config), &TcpListener::bind(*SOCKET_ADDR).await?)
|
.run_on_socket(Arc::new(config), &TcpListener::bind(socket_addr).await?)
|
||||||
.await
|
.await
|
||||||
.map_err(|err| eyre!(err))
|
.map_err(|err| eyre!(err))
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue