diff --git a/bot-coreutils/Cargo.lock b/bot-coreutils/Cargo.lock index b92d663..2d0bc50 100644 --- a/bot-coreutils/Cargo.lock +++ b/bot-coreutils/Cargo.lock @@ -16,6 +16,12 @@ dependencies = [ "url", ] +[[package]] +name = "bytes" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b700ce4376041dcd0a327fd0097c41095743c4c8af8887265942faf1100bd040" + [[package]] name = "cfg-if" version = "1.0.0" @@ -43,6 +49,12 @@ dependencies = [ "unicode-normalization", ] +[[package]] +name = "libc" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9385f66bf6105b241aa65a61cb923ef20efc665cb9f9bb50ac2f0c4b7f378d41" + [[package]] name = "log" version = "0.4.14" @@ -58,6 +70,12 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" +[[package]] +name = "memchr" +version = "2.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525" + [[package]] name = "mime" version = "0.3.16" @@ -74,6 +92,43 @@ dependencies = [ "unicase", ] +[[package]] +name = "mio" +version = "0.7.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf80d3e903b34e0bd7282b218398aec54e082c840d9baf8339e0080a0c542956" +dependencies = [ + "libc", + "log", + "miow", + "ntapi", + "winapi", +] + +[[package]] +name = "miow" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21" +dependencies = [ + "winapi", +] + +[[package]] +name = "ntapi" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44" +dependencies = [ + "winapi", +] + +[[package]] +name = "once_cell" +version = "1.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af8b08b04175473088b46763e51ee54da5f9a164bc162f615b91bc179dbf15a3" + [[package]] name = "percent-encoding" version = "2.1.0" @@ -86,6 +141,15 @@ version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc0e1f259c92177c30a4c9d177246edd0a3568b25756a977d0632cf8fa37e905" +[[package]] +name = "signal-hook-registry" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16f1d0fef1604ba8f7a073c7e701f213e056707210e9020af4528e0101ce11a6" +dependencies = [ + "libc", +] + [[package]] name = "tinyvec" version = "1.2.0" @@ -108,7 +172,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "134af885d758d645f0f0505c9a8b3f9bf8a348fd822e112ab5248138348f1722" dependencies = [ "autocfg", + "bytes", + "libc", + "memchr", + "mio", + "once_cell", "pin-project-lite", + "signal-hook-registry", + "winapi", ] [[package]] @@ -155,3 +226,25 @@ name = "version_check" version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" + +[[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" diff --git a/bot-coreutils/Cargo.toml b/bot-coreutils/Cargo.toml index 96c3128..de19dcb 100644 --- a/bot-coreutils/Cargo.toml +++ b/bot-coreutils/Cargo.toml @@ -7,7 +7,7 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -tokio = "1.4.0" +tokio = {version = "1.4.0", features = ["process", "io-util"]} log = "0.4.14" url = "2.2.1" mime_guess = "2.0.3" \ No newline at end of file diff --git a/bot-coreutils/src/lib.rs b/bot-coreutils/src/lib.rs index 7f750f1..2e0c021 100644 --- a/bot-coreutils/src/lib.rs +++ b/bot-coreutils/src/lib.rs @@ -1,5 +1,6 @@ #[cfg(test)] mod tests; +pub mod process; /// Utilities to quickly check strings that represent urls pub mod url; diff --git a/bot-coreutils/src/process.rs b/bot-coreutils/src/process.rs new file mode 100644 index 0000000..17068b5 --- /dev/null +++ b/bot-coreutils/src/process.rs @@ -0,0 +1,24 @@ +use std::io; +use std::process::Stdio; +use tokio::io::AsyncReadExt; +use tokio::process::Command; + +/// Asynchronously runs a given command and returns the output +pub async fn run_command_async(command: &str, args: &[&str]) -> io::Result { + log::trace!("Running command '{}' with args {:?}", command, args); + let cmd = Command::new(command) + .args(args) + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .spawn()?; + let mut stderr = String::new(); + let mut output = String::new(); + cmd.stderr.unwrap().read_to_string(&mut stderr).await?; + if stderr.len() != 0 { + log::debug!("STDERR of command {}: {}", command, stderr); + } + cmd.stdout.unwrap().read_to_string(&mut output).await?; + log::trace!("Command output is {}", output); + + Ok(output) +} diff --git a/src/providers/music/youtube_dl.rs b/src/providers/music/youtube_dl.rs index a45b19e..9a4d345 100644 --- a/src/providers/music/youtube_dl.rs +++ b/src/providers/music/youtube_dl.rs @@ -1,7 +1,7 @@ use crate::providers::music::queue::Song; use crate::providers::music::responses::{PlaylistEntry, VideoInformation}; use crate::utils::error::BotResult; -use crate::utils::process::run_command_async; +use bot_coreutils::process::run_command_async; use futures::future::BoxFuture; use futures::FutureExt; use std::sync::atomic::{AtomicU8, Ordering}; diff --git a/src/providers/qalc.rs b/src/providers/qalc.rs index cc3bf1a..28adae4 100644 --- a/src/providers/qalc.rs +++ b/src/providers/qalc.rs @@ -1,9 +1,12 @@ use crate::utils::error::BotResult; -use crate::utils::process::{run_command_async, sanitize_argument}; +use bot_coreutils::process::run_command_async; /// Runs the qalc command with the given expression pub async fn qalc(expression: &str) -> BotResult { - let expression = sanitize_argument(expression, true)?; - let result = run_command_async("qalc", &["-m", "1000", &*expression]).await?; + let result = run_command_async( + "qalc", + &["-m", "1000", format!("\"{}\"", &*expression).as_str()], + ) + .await?; Ok(result) } diff --git a/src/utils/mod.rs b/src/utils/mod.rs index bf53d26..c0a9bbe 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -8,7 +8,6 @@ pub(crate) mod context_data; pub(crate) mod error; pub(crate) mod logging; pub(crate) mod messages; -pub(crate) mod process; /// Fisher-Yates shuffle for VecDeque pub fn shuffle_vec_deque(deque: &mut VecDeque) { diff --git a/src/utils/process.rs b/src/utils/process.rs deleted file mode 100644 index 750bb20..0000000 --- a/src/utils/process.rs +++ /dev/null @@ -1,51 +0,0 @@ -use crate::utils::error::{BotError, BotResult}; -use regex::Regex; -use std::io; -use std::process::Stdio; -use tokio::io::AsyncReadExt; -use tokio::process::Command; - -/// Asynchronously runs a given command and returns the output -pub async fn run_command_async(command: &str, args: &[&str]) -> io::Result { - log::trace!("Running command '{}' with args {:?}", command, args); - let cmd = Command::new(command) - .args(args) - .stdout(Stdio::piped()) - .stderr(Stdio::piped()) - .spawn()?; - let mut stderr = String::new(); - let mut output = String::new(); - cmd.stderr.unwrap().read_to_string(&mut stderr).await?; - if stderr.len() != 0 { - log::debug!("STDERR of command {}: {}", command, stderr); - } - cmd.stdout.unwrap().read_to_string(&mut output).await?; - log::trace!("Command output is {}", output); - - Ok(output) -} - -/// Sanitizes a command line argument and throws an error -/// on a possible injection attempt -pub fn sanitize_argument(arg: &str, detect_help: bool) -> BotResult { - log::debug!("Sanitizing argument '{}'", arg); - lazy_static::lazy_static! { - static ref HELP_FLAG: Regex = Regex::new(r"^\s*(-*)h(elp)?\s*$").unwrap(); - static ref FLAG_REGEX: Regex = Regex::new(r"^\s*-\w*\s*$").unwrap(); - } - if FLAG_REGEX.is_match(arg) { - log::debug!("Detected STDIN injection"); - return Err(BotError::CliInject); - } - if detect_help && HELP_FLAG.is_match(arg) { - log::debug!("Detected help injection"); - return Err(BotError::CliInject); - } - let arg = arg.replace("--", "\\-\\-"); - if arg.is_empty() { - return Err(BotError::CliInject); - } - log::debug!("Sanitized argument is '{}'", arg); - - Ok(arg) -}