From 937a4c9010978129c41fef550691d280436f3032 Mon Sep 17 00:00:00 2001 From: 0xf8 <0xf8.dev@proton.me> Date: Tue, 30 May 2023 10:13:42 -0400 Subject: [PATCH] Add SSH config validation --- Cargo.lock | 218 ++++++++++++++++++++++++++++++++++++++++++++++-- Cargo.toml | 3 + src/config.rs | 5 +- src/main.rs | 3 +- src/platform.rs | 20 ++++- 5 files changed, 234 insertions(+), 15 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2d10c26..2ad8970 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -14,6 +14,17 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f8ebf5827e4ac4fd5946560e6a99776ea73b596d80898f357007317a7141e47" +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi 0.1.19", + "libc", + "winapi", +] + [[package]] name = "autocfg" version = "1.1.0" @@ -38,6 +49,12 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitflags" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6776fc96284a0bb647b615056fc496d1fe1644a7ab01829818a6d91cae888b84" + [[package]] name = "block-buffer" version = "0.9.0" @@ -62,6 +79,12 @@ version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +[[package]] +name = "bytes" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" + [[package]] name = "cassowary" version = "0.3.0" @@ -80,6 +103,17 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "colored" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3616f750b84d8f0de8a58bda93e08e2a81ad3f523089b05f1dffecab48c6cbd" +dependencies = [ + "atty", + "lazy_static", + "winapi", +] + [[package]] name = "console" version = "0.15.7" @@ -188,13 +222,33 @@ dependencies = [ "subtle", ] +[[package]] +name = "dirs" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" +dependencies = [ + "dirs-sys 0.3.7", +] + [[package]] name = "dirs" version = "5.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" dependencies = [ - "dirs-sys", + "dirs-sys 0.4.1", +] + +[[package]] +name = "dirs-sys" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" +dependencies = [ + "libc", + "redox_users", + "winapi", ] [[package]] @@ -333,7 +387,7 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "15d14128f06405808ce75bfebe11e9b0f9da18719ede6d7bdb1702d6bfe0f7e8" dependencies = [ - "bitflags", + "bitflags 1.3.2", "byteorder", "num_enum", "serde", @@ -398,6 +452,15 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + [[package]] name = "hermit-abi" version = "0.3.1" @@ -438,7 +501,7 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" dependencies = [ - "hermit-abi", + "hermit-abi 0.3.1", "libc", "windows-sys 0.48.0", ] @@ -449,12 +512,15 @@ version = "0.1.0" dependencies = [ "anyhow", "argparse", + "colored", "dialoguer", - "dirs", + "dirs 5.0.1", "flexbuffers", "mktemp", + "openssh", "serde", "ssh-key", + "ssh2-config", "termion 2.0.1", "toml", "tui", @@ -493,6 +559,17 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +[[package]] +name = "mio" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eebffdb73fe72e917997fad08bdbf31ac50b0fa91cec93e69a0662e4264d454c" +dependencies = [ + "libc", + "wasi 0.11.0+wasi-snapshot-preview1", + "windows-sys 0.48.0", +] + [[package]] name = "mktemp" version = "0.5.0" @@ -590,6 +667,22 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" +[[package]] +name = "openssh" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ca6c277973fb549b36dd8980941b5ea3ecebea026f5b1f0060acde74d893c22" +dependencies = [ + "dirs 4.0.0", + "libc", + "once_cell", + "shell-escape", + "tempfile", + "thiserror", + "tokio", + "tokio-pipe", +] + [[package]] name = "option-ext" version = "0.2.0" @@ -627,6 +720,12 @@ dependencies = [ "base64ct", ] +[[package]] +name = "pin-project-lite" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" + [[package]] name = "pkcs1" version = "0.4.1" @@ -760,7 +859,7 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] @@ -769,7 +868,7 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] @@ -830,7 +929,7 @@ version = "0.37.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "acf8729d8542766f1b2cf77eb034d52f40d375bb8b615d0b147089946e16613d" dependencies = [ - "bitflags", + "bitflags 1.3.2", "errno", "io-lifetimes", "libc", @@ -916,12 +1015,27 @@ dependencies = [ "digest 0.10.7", ] +[[package]] +name = "shell-escape" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45bb67a18fa91266cc7807181f62f9178a6873bfad7dc788c42e6430db40184f" + [[package]] name = "shell-words" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde" +[[package]] +name = "signal-hook-registry" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +dependencies = [ + "libc", +] + [[package]] name = "signature" version = "1.6.4" @@ -938,6 +1052,16 @@ version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" +[[package]] +name = "socket2" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" +dependencies = [ + "libc", + "winapi", +] + [[package]] name = "spin" version = "0.5.2" @@ -986,6 +1110,18 @@ dependencies = [ "zeroize", ] +[[package]] +name = "ssh2-config" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e31d9bb8e97972d6541ccf32ed51294e4e16feeef06a0e77a6272d041f0f5bc7" +dependencies = [ + "bitflags 2.3.1", + "dirs 5.0.1", + "thiserror", + "wildmatch", +] + [[package]] name = "subtle" version = "2.5.0" @@ -1081,6 +1217,44 @@ dependencies = [ "once_cell", ] +[[package]] +name = "tokio" +version = "1.28.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94d7b1cfd2aa4011f2de74c2c4c63665e27a71006b0a192dcd2710272e73dfa2" +dependencies = [ + "autocfg", + "bytes", + "libc", + "mio", + "pin-project-lite", + "signal-hook-registry", + "socket2", + "tokio-macros", + "windows-sys 0.48.0", +] + +[[package]] +name = "tokio-macros" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.18", +] + +[[package]] +name = "tokio-pipe" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f213a84bffbd61b8fa0ba8a044b4bbe35d471d0b518867181e82bd5c15542784" +dependencies = [ + "libc", + "tokio", +] + [[package]] name = "toml" version = "0.7.4" @@ -1121,7 +1295,7 @@ version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccdd26cbd674007e649a272da4475fb666d3aa0ad0531da7136db6fab0e5bad1" dependencies = [ - "bitflags", + "bitflags 1.3.2", "cassowary", "termion 1.5.6", "unicode-segmentation", @@ -1179,6 +1353,34 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wildmatch" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee583bdc5ff1cf9db20e9db5bb3ff4c3089a8f6b8b31aff265c9aba85812db86" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + [[package]] name = "windows-sys" version = "0.45.0" diff --git a/Cargo.toml b/Cargo.toml index 11d72c5..f70c7e4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,12 +8,15 @@ edition = "2021" [dependencies] anyhow = "1.0.71" argparse = "0.2.2" +colored = "2.0.0" dialoguer = { version = "0.10.4", features = ["fuzzy-select"] } dirs = "5.0.1" flexbuffers = "2.0.0" mktemp = "0.5.0" +openssh = "0.9.9" serde = { version = "1.0.163", features = ["derive"] } ssh-key = { version = "0.5.1", features = ["rsa", "ed25519", "dsa", "p256", "p384"] } +ssh2-config = "0.2.0" termion = "2.0.1" toml = "0.7.4" tui = { version = "0.19.0", default-features = false, features = ["termion"] } diff --git a/src/config.rs b/src/config.rs index cf3b7c0..8a15ac6 100644 --- a/src/config.rs +++ b/src/config.rs @@ -24,19 +24,18 @@ impl std::fmt::Display for Host { } impl Host { - // todo: validate ssh config pub fn edit(&mut self) -> Result { let mut data = toml::to_string_pretty(self)?; { let t = mktemp::Temp::new_file().unwrap(); fs::write(t.to_owned(), data)?; - + let editor = std::env::var("EDITOR").expect("EDITOR is not set"); std::process::Command::new(editor) .arg(t.to_owned().to_string_lossy().to_string()) .spawn()?.wait()?; - + data = fs::read_to_string(t)?; } diff --git a/src/main.rs b/src/main.rs index b4a35ab..7268668 100644 --- a/src/main.rs +++ b/src/main.rs @@ -22,7 +22,8 @@ fn main() -> Result<()> { parser.add_option(&["-V", "--version"], argparse::Print(env!("CARGO_PKG_VERSION").to_string()), "Show version"); parser.refer(&mut search_path).add_option(&["-s", "--search"], argparse::StoreOption, "Search path for keys"); parser.refer(&mut config_root).add_option(&["-c", "--config"], argparse::StoreOption, "Path to keyman's config dir"); - // todo: actual dryrun + // TODO: actual dryrun + // TODO: add back option to disable alt screen // parser.refer(&mut dry_run).add_option(&["-d", "--dry-run", "--dryrun"], argparse::StoreTrue, "Do a dry run"); parser.parse_args_or_exit(); diff --git a/src/platform.rs b/src/platform.rs index 4dc8cc2..6bcc6f2 100644 --- a/src/platform.rs +++ b/src/platform.rs @@ -1,7 +1,9 @@ use anyhow::Result; +use colored::Colorize; use crate::{ ConfigManager, config::Host, input }; use dialoguer::{ Select, Input, Confirm, Editor, theme::ColorfulTheme }; use serde::{ Serialize, Deserialize }; +use ssh2_config::{ SshConfig, ParseRule }; use ssh_key::PrivateKey; use std::fs; @@ -74,7 +76,7 @@ Host {host} // New host fn ssh_new_host(&self, config: &mut ConfigManager) -> Result { - println!("- Creating new host entry"); + println!(" ## Creating new SSH host entry ## "); let keyid = input::get_key(config, self.to_owned())?; let userhost = loop { @@ -86,7 +88,7 @@ Host {host} let split: Vec = split.map(|a| a.to_string()).collect(); if split.len() < 2 { - println!("Incorrect user@host given. Example: paul@example.com:34; @[:port]"); + println!("{} Example: paul@example.com:34 - @[:port]", "Incorrect user@host given.".red()); } else { break split } @@ -170,10 +172,22 @@ Host {host} // if let Some(cnf) = Editor::new().edit(fs::read_to_string(config.config_dir.join("config"))?.as_str())? { // fs::write(config.config_dir.join("config"), cnf)?; // } + let t = mktemp::Temp::new_file()?; + fs::copy(&host.config, &t)?; + let editor = std::env::var("EDITOR").expect("EDITOR is not set"); std::process::Command::new(editor) - .arg(host.config.to_owned()) + .arg(&t.to_str().unwrap()) .spawn()?.wait()?; + + let mut file = std::io::BufReader::new(fs::File::open(&t).expect(&format!("Couldn't open config ({})", &host.config))); + match SshConfig::default().parse(&mut file, ParseRule::STRICT) { + Ok(_) => { + println!(" ## {} ## ", "Config OK".green()); + fs::copy(&t, &host.config)?; + }, + Err(e) => println!(" ## {}: {} ## ", "Rejecting config".red(), e), + } } 2 => { // Edit definition let edited_host = host.edit()?;