mirror of
https://git.mentality.rip/numas13/xash3d-master.git
synced 2025-01-22 04:44:31 +00:00
Add admin program
This commit is contained in:
parent
ce742f091d
commit
3cc3e5815e
39
Cargo.lock
generated
39
Cargo.lock
generated
@ -2,6 +2,16 @@
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "admin"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"blake2b_simd",
|
||||
"getopts",
|
||||
"thiserror",
|
||||
"xash3d-protocol",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "android-tzdata"
|
||||
version = "0.1.1"
|
||||
@ -17,6 +27,18 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "arrayref"
|
||||
version = "0.3.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545"
|
||||
|
||||
[[package]]
|
||||
name = "arrayvec"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.1.0"
|
||||
@ -29,6 +51,17 @@ version = "2.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635"
|
||||
|
||||
[[package]]
|
||||
name = "blake2b_simd"
|
||||
version = "0.5.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "afa748e348ad3be8263be728124b24a24f268266f6f5d58af9d75f6a40b5c587"
|
||||
dependencies = [
|
||||
"arrayref",
|
||||
"arrayvec",
|
||||
"constant_time_eq",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.14.0"
|
||||
@ -62,6 +95,12 @@ dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "constant_time_eq"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc"
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation-sys"
|
||||
version = "0.8.4"
|
||||
|
@ -3,4 +3,5 @@ resolver = "2"
|
||||
members = [
|
||||
"protocol",
|
||||
"master",
|
||||
"admin",
|
||||
]
|
||||
|
13
admin/Cargo.toml
Normal file
13
admin/Cargo.toml
Normal file
@ -0,0 +1,13 @@
|
||||
[package]
|
||||
name = "admin"
|
||||
version = "0.1.0"
|
||||
license = "GPL-3.0-only"
|
||||
authors = ["Denis Drakhnia <numas13@gmail.com>"]
|
||||
edition = "2021"
|
||||
rust-version = "1.56"
|
||||
|
||||
[dependencies]
|
||||
thiserror = "1.0.49"
|
||||
getopts = "0.2.21"
|
||||
blake2b_simd = "<0.6"
|
||||
xash3d-protocol = { path = "../protocol", version = "0.1.0" }
|
106
admin/src/cli.rs
Normal file
106
admin/src/cli.rs
Normal file
@ -0,0 +1,106 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
// SPDX-FileCopyrightText: 2023 Denis Drakhnia <numas13@gmail.com>
|
||||
|
||||
use std::process;
|
||||
|
||||
use getopts::Options;
|
||||
use xash3d_protocol::admin;
|
||||
|
||||
const BIN_NAME: &str = env!("CARGO_BIN_NAME");
|
||||
const PKG_NAME: &str = env!("CARGO_PKG_NAME");
|
||||
const PKG_VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||
|
||||
const DEFAULT_HOST: &str = "mentality.rip";
|
||||
const DEFAULT_PORT: u16 = 27010;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Cli {
|
||||
pub address: String,
|
||||
pub command: String,
|
||||
pub hash_len: usize,
|
||||
pub hash_key: String,
|
||||
pub hash_personal: String,
|
||||
}
|
||||
|
||||
impl Default for Cli {
|
||||
fn default() -> Cli {
|
||||
Cli {
|
||||
address: format!("{}:{}", DEFAULT_HOST, DEFAULT_PORT),
|
||||
command: String::new(),
|
||||
hash_len: admin::HASH_LEN,
|
||||
hash_key: admin::HASH_KEY.to_owned(),
|
||||
hash_personal: admin::HASH_PERSONAL.to_owned(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn print_usage(opts: Options) {
|
||||
let brief = format!("Usage: {} [options]", BIN_NAME);
|
||||
print!("{}", opts.usage(&brief));
|
||||
}
|
||||
|
||||
fn print_version() {
|
||||
println!("{} v{}", PKG_NAME, PKG_VERSION);
|
||||
}
|
||||
|
||||
pub fn parse() -> Cli {
|
||||
let mut cli = Cli::default();
|
||||
|
||||
let args: Vec<_> = std::env::args().collect();
|
||||
let mut opts = Options::new();
|
||||
opts.optflag("h", "help", "print usage help");
|
||||
opts.optflag("v", "version", "print program version");
|
||||
let help = format!("address to connect [default: {}]", cli.address);
|
||||
opts.optopt("h", "host", &help, "ADDR");
|
||||
let help = format!("hash length [default: {}]", cli.hash_len);
|
||||
opts.optopt("l", "hash-length", &help, "N");
|
||||
let help = format!("hash key [default: {}]", cli.hash_key);
|
||||
opts.optopt("k", "hash-key", &help, "KEY");
|
||||
let help = format!("hash personalization [default: {}]", cli.hash_personal);
|
||||
opts.optopt("p", "hash-personal", &help, "PERSONAL");
|
||||
|
||||
let matches = match opts.parse(&args[1..]) {
|
||||
Ok(m) => m,
|
||||
Err(e) => {
|
||||
eprintln!("{}", e);
|
||||
process::exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
if matches.opt_present("help") {
|
||||
print_usage(opts);
|
||||
process::exit(0);
|
||||
}
|
||||
|
||||
if matches.opt_present("version") {
|
||||
print_version();
|
||||
process::exit(0);
|
||||
}
|
||||
|
||||
if let Some(mut s) = matches.opt_str("host") {
|
||||
if !s.contains(':') {
|
||||
s.push_str(":27010");
|
||||
}
|
||||
cli.address = s;
|
||||
}
|
||||
|
||||
match matches.opt_get("hash-length") {
|
||||
Ok(Some(n)) => cli.hash_len = n,
|
||||
Ok(None) => {}
|
||||
Err(_) => {
|
||||
eprintln!("Invalid key length");
|
||||
process::exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(s) = matches.opt_str("hash-key") {
|
||||
cli.hash_key = s;
|
||||
}
|
||||
|
||||
if let Some(s) = matches.opt_str("hash-personal") {
|
||||
cli.hash_personal = s;
|
||||
}
|
||||
|
||||
cli.command = matches.free.join(" ");
|
||||
cli
|
||||
}
|
66
admin/src/main.rs
Normal file
66
admin/src/main.rs
Normal file
@ -0,0 +1,66 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
// SPDX-FileCopyrightText: 2023 Denis Drakhnia <numas13@gmail.com>
|
||||
|
||||
mod cli;
|
||||
|
||||
use std::io;
|
||||
use std::net::UdpSocket;
|
||||
|
||||
use blake2b_simd::Params;
|
||||
use thiserror::Error;
|
||||
use xash3d_protocol::{admin, master};
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
enum Error {
|
||||
#[error("Unexpected response from master server")]
|
||||
UnexpectedPacket,
|
||||
#[error(transparent)]
|
||||
Protocol(#[from] xash3d_protocol::Error),
|
||||
#[error(transparent)]
|
||||
Io(#[from] io::Error),
|
||||
}
|
||||
|
||||
fn send_command(cli: &cli::Cli) -> Result<(), Error> {
|
||||
let sock = UdpSocket::bind("0.0.0.0:0")?;
|
||||
sock.connect(&cli.address)?;
|
||||
|
||||
let mut buf = [0; 512];
|
||||
let n = admin::AdminChallenge.encode(&mut buf)?;
|
||||
sock.send(&buf[..n])?;
|
||||
|
||||
let n = sock.recv(&mut buf)?;
|
||||
let challenge = match master::Packet::decode(&buf[..n])? {
|
||||
master::Packet::AdminChallengeResponse(p) => p.challenge,
|
||||
_ => return Err(Error::UnexpectedPacket),
|
||||
};
|
||||
|
||||
println!("Password:");
|
||||
let mut password = String::new();
|
||||
io::stdin().read_line(&mut password)?;
|
||||
if password.ends_with('\n') {
|
||||
password.pop();
|
||||
}
|
||||
|
||||
let hash = Params::new()
|
||||
.hash_length(cli.hash_len)
|
||||
.key(cli.hash_key.as_bytes())
|
||||
.personal(cli.hash_personal.as_bytes())
|
||||
.to_state()
|
||||
.update(password.as_bytes())
|
||||
.update(&challenge.to_le_bytes())
|
||||
.finalize();
|
||||
|
||||
let n = admin::AdminCommand::new(hash.as_bytes(), &cli.command).encode(&mut buf)?;
|
||||
sock.send(&buf[..n])?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let cli = cli::parse();
|
||||
|
||||
if let Err(e) = send_command(&cli) {
|
||||
eprintln!("error: {}", e);
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
@ -6,6 +6,8 @@ use crate::types::Str;
|
||||
use crate::Error;
|
||||
|
||||
pub const HASH_LEN: usize = 64;
|
||||
pub const HASH_KEY: &str = "Half-Life";
|
||||
pub const HASH_PERSONAL: &str = "Freeman";
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct AdminChallenge;
|
||||
|
Loading…
x
Reference in New Issue
Block a user