generated from PlexSheep/rs-base
feat: proper cli
cargo devel CI / cargo CI (push) Successful in 2m16s
Details
cargo devel CI / cargo CI (push) Successful in 2m16s
Details
This commit is contained in:
parent
19b81e2631
commit
f00aa8b4e9
14
Cargo.toml
14
Cargo.toml
|
@ -14,5 +14,15 @@ repository = "https://git.cscherr.de/PlexSheep/wooly-vault"
|
|||
[dependencies]
|
||||
anyhow = "1.0.86"
|
||||
async-trait = "0.1.82"
|
||||
libpt = { version = "0.6.0", features = ["log"] }
|
||||
tokio = { version = "1.40.0", features = ["macros", "net", "time", "io-util", "rt", "sync"] }
|
||||
clap = { version = "4.5.17", features = ["derive"] }
|
||||
libpt = { version = "0.7.1", features = ["cli", "log"] }
|
||||
serde = { version = "1.0.209", features = ["derive"] }
|
||||
serde_json = "1.0.128"
|
||||
tokio = { version = "1.40.0", features = [
|
||||
"macros",
|
||||
"net",
|
||||
"time",
|
||||
"io-util",
|
||||
"rt",
|
||||
"sync",
|
||||
] }
|
||||
|
|
|
@ -4,8 +4,9 @@ use tokio::io::AsyncWriteExt;
|
|||
use tokio::net::TcpListener;
|
||||
|
||||
use super::Challenge;
|
||||
use crate::config::Config;
|
||||
use crate::has_won;
|
||||
use crate::vault::{Config, VaultRef};
|
||||
use crate::vault::VaultRef;
|
||||
|
||||
pub struct C1 {
|
||||
config: Config,
|
||||
|
@ -19,9 +20,15 @@ impl Challenge for C1 {
|
|||
fn new(config: Config, vault: VaultRef) -> Self {
|
||||
Self { config, vault }
|
||||
}
|
||||
|
||||
fn hints() -> Vec<String> {
|
||||
vec![String::from("TCP connect to 1337")]
|
||||
vec![String::from("TCP connect to 1337.")]
|
||||
}
|
||||
|
||||
fn solution() -> String {
|
||||
String::from("Connect by TCP, then the secret will be sent to you.")
|
||||
}
|
||||
|
||||
async fn serve(self) -> anyhow::Result<()> {
|
||||
info!("serving challenge 1");
|
||||
let listener = TcpListener::bind(self.config.addr).await?;
|
||||
|
|
|
@ -5,8 +5,9 @@ use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
|||
use tokio::net::{TcpListener, TcpStream};
|
||||
|
||||
use super::Challenge;
|
||||
use crate::config::Config;
|
||||
use crate::has_won;
|
||||
use crate::vault::{Config, VaultRef};
|
||||
use crate::vault::VaultRef;
|
||||
|
||||
pub struct C2 {
|
||||
config: Config,
|
||||
|
@ -37,11 +38,17 @@ impl Challenge for C2 {
|
|||
fn new(config: Config, vault: VaultRef) -> Self {
|
||||
Self { config, vault }
|
||||
}
|
||||
|
||||
fn hints() -> Vec<String> {
|
||||
vec![String::from(
|
||||
"TCP connect to 1337 and give me a special u16",
|
||||
)]
|
||||
}
|
||||
|
||||
fn solution() -> String {
|
||||
String::from("Connect by TCP, send 1337 as bytes (not text).")
|
||||
}
|
||||
|
||||
async fn serve(self) -> anyhow::Result<()> {
|
||||
info!("serving challenge 2");
|
||||
let listener = TcpListener::bind(self.config.addr).await?;
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
use anyhow::anyhow;
|
||||
use async_trait::async_trait;
|
||||
|
||||
use crate::vault::{Config, VaultRef};
|
||||
use crate::config::Config;
|
||||
use crate::vault::VaultRef;
|
||||
|
||||
pub mod c1;
|
||||
pub mod c2;
|
||||
|
@ -13,6 +14,7 @@ where
|
|||
{
|
||||
fn new(config: Config, vault: VaultRef) -> Self;
|
||||
fn hints() -> Vec<String>;
|
||||
fn solution() -> String;
|
||||
async fn serve(self) -> anyhow::Result<()>;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
use std::fmt::{Debug, Display};
|
||||
use std::net::SocketAddr;
|
||||
use std::str::FromStr;
|
||||
|
||||
use clap::Parser;
|
||||
use libpt::cli::args::VerbosityLevel;
|
||||
use serde::Serialize;
|
||||
|
||||
pub const ENV_SECRET: &str = "WOOLY_SECRET";
|
||||
|
||||
/// Wooly Vault --- A few small hacking challenges
|
||||
///
|
||||
/// # Configuration
|
||||
/// Each challenge requires some basic information to host:
|
||||
///
|
||||
/// * secret - a string that if found signifies that the challenge was solved
|
||||
///
|
||||
/// * addr - the network adress plus port the challenge should run on
|
||||
///
|
||||
/// * verbosity - how verbose the logging should be
|
||||
///
|
||||
/// * challenge - which challenge to host (there are a few)
|
||||
///
|
||||
/// The secret cannot be inputted with a command line argument, because the arguments can often be
|
||||
/// seen in the process view. You may either specify a secret in the 'WOOLY_SECRET' environment
|
||||
/// variable or input it interactively on start.
|
||||
///
|
||||
/// # Challenges
|
||||
///
|
||||
/// There are a number of challenges:
|
||||
///
|
||||
/// 1. Connect by TCP
|
||||
///
|
||||
/// 2. Connect by TCP and send a special u16
|
||||
#[derive(Parser, Clone, PartialEq, Eq, Hash, Serialize)]
|
||||
#[command(
|
||||
author,
|
||||
version,
|
||||
about,
|
||||
long_about,
|
||||
help_template = libpt::cli::args::HELP_TEMPLATE)]
|
||||
|
||||
pub struct Config {
|
||||
/// Index of the challenge
|
||||
pub challenge: u16,
|
||||
/// Network address to host the challenge on
|
||||
pub addr: SocketAddr,
|
||||
#[command(flatten)]
|
||||
pub verbosity: VerbosityLevel,
|
||||
}
|
||||
|
||||
impl Default for Config {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
challenge: 1,
|
||||
addr: SocketAddr::from_str("127.0.0.1:1337").unwrap(),
|
||||
verbosity: VerbosityLevel::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for Config {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_struct("Config")
|
||||
.field("addr", &self.addr)
|
||||
.field("verbosity", &self.verbosity.level())
|
||||
.finish()
|
||||
}
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
pub mod challenge;
|
||||
pub mod config;
|
||||
pub mod vault;
|
||||
|
||||
#[inline]
|
||||
|
|
43
src/main.rs
43
src/main.rs
|
@ -1,30 +1,41 @@
|
|||
use wooly_vault::challenge::select_and_start;
|
||||
use wooly_vault::vault::{Config, Vault};
|
||||
use anyhow::Result;
|
||||
use clap::Parser;
|
||||
use libpt::log::{debug, info};
|
||||
|
||||
use wooly_vault::config::ENV_SECRET;
|
||||
use wooly_vault::{challenge::select_and_start, config::Config, vault::Vault};
|
||||
|
||||
#[tokio::main(flavor = "current_thread")]
|
||||
async fn main() -> anyhow::Result<()> {
|
||||
async fn main() -> Result<()> {
|
||||
let conf = Config::parse();
|
||||
|
||||
let _logger = libpt::log::Logger::builder()
|
||||
.set_level(libpt::log::Level::TRACE)
|
||||
.set_level(conf.verbosity.level())
|
||||
.display_time(false)
|
||||
.build()?;
|
||||
debug!("logger active");
|
||||
info!("Configuration: {conf:?}");
|
||||
|
||||
println!("Input the secret and press enter");
|
||||
let mut buf: String = String::new();
|
||||
std::io::stdin().read_line(&mut buf)?;
|
||||
let secret = buf.trim();
|
||||
let secret = get_secret()?;
|
||||
let v = Vault::new(&secret);
|
||||
|
||||
let conf = Config::default();
|
||||
|
||||
let v = Vault::new(secret);
|
||||
|
||||
println!("What challenge to serve?");
|
||||
let i = select_challenge()?;
|
||||
select_and_start(i, conf, v).await?;
|
||||
select_and_start(conf.challenge, conf, v).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn select_challenge() -> anyhow::Result<u16> {
|
||||
fn get_secret() -> Result<String> {
|
||||
if let Ok(v) = std::env::var(ENV_SECRET) {
|
||||
return Ok(v);
|
||||
}
|
||||
|
||||
println!("Input the secret and press enter");
|
||||
let mut buf: String = String::new();
|
||||
std::io::stdin().read_line(&mut buf)?;
|
||||
Ok(buf.trim().to_string())
|
||||
}
|
||||
|
||||
fn select_challenge() -> Result<u16> {
|
||||
let mut buf: String = String::new();
|
||||
std::io::stdin().read_line(&mut buf)?;
|
||||
Ok(buf.trim().parse()?)
|
||||
|
|
15
src/vault.rs
15
src/vault.rs
|
@ -1,22 +1,7 @@
|
|||
use std::net::SocketAddr;
|
||||
use std::str::FromStr;
|
||||
use std::sync::Arc;
|
||||
|
||||
pub type VaultRef = Arc<Vault>;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Copy)]
|
||||
pub struct Config {
|
||||
pub addr: SocketAddr,
|
||||
}
|
||||
|
||||
impl Default for Config {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
addr: SocketAddr::from_str("127.0.0.1:1337").unwrap(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct Vault {
|
||||
secret: String,
|
||||
|
|
Loading…
Reference in New Issue