Implement mcookie

This commit is contained in:
alxndrv
2025-03-18 19:50:06 +02:00
parent 44b603e4c0
commit a7e9f39c40
6 changed files with 211 additions and 0 deletions

72
Cargo.lock generated
View File

@@ -88,6 +88,15 @@ version = "2.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36"
[[package]]
name = "block-buffer"
version = "0.10.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
dependencies = [
"generic-array",
]
[[package]]
name = "bumpalo"
version = "3.17.0"
@@ -240,6 +249,16 @@ version = "0.8.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
[[package]]
name = "crypto-common"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
dependencies = [
"generic-array",
"typenum",
]
[[package]]
name = "deranged"
version = "0.3.11"
@@ -255,6 +274,16 @@ version = "0.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8"
[[package]]
name = "digest"
version = "0.10.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
dependencies = [
"block-buffer",
"crypto-common",
]
[[package]]
name = "dns-lookup"
version = "2.0.4"
@@ -295,6 +324,16 @@ version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be"
[[package]]
name = "generic-array"
version = "0.14.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
dependencies = [
"typenum",
"version_check",
]
[[package]]
name = "getrandom"
version = "0.3.1"
@@ -404,6 +443,16 @@ version = "0.4.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04cbf5b083de1c7e0222a7a51dbfdba1cbe1c6ab0b15e29fff3f6c077fd9cd9f"
[[package]]
name = "md-5"
version = "0.10.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf"
dependencies = [
"cfg-if",
"digest",
]
[[package]]
name = "memchr"
version = "2.7.4"
@@ -916,6 +965,12 @@ dependencies = [
"time-core",
]
[[package]]
name = "typenum"
version = "1.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f"
[[package]]
name = "unicode-ident"
version = "1.0.16"
@@ -975,6 +1030,7 @@ dependencies = [
"uu_lscpu",
"uu_lslocks",
"uu_lsmem",
"uu_mcookie",
"uu_mesg",
"uu_mountpoint",
"uu_renice",
@@ -1068,6 +1124,16 @@ dependencies = [
"uucore",
]
[[package]]
name = "uu_mcookie"
version = "0.0.1"
dependencies = [
"clap",
"md-5",
"rand 0.9.0",
"uucore",
]
[[package]]
name = "uu_mesg"
version = "0.0.1"
@@ -1149,6 +1215,12 @@ version = "0.0.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0bb6d972f580f8223cb7052d8580aea2b7061e368cf476de32ea9457b19459ed"
[[package]]
name = "version_check"
version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
[[package]]
name = "wasi"
version = "0.13.3+wasi-0.2.2"

View File

@@ -34,6 +34,7 @@ feat_common_core = [
"lscpu",
"lslocks",
"lsmem",
"mcookie",
"mesg",
"mountpoint",
"renice",
@@ -48,6 +49,7 @@ clap_mangen = "0.2"
dns-lookup = "2.0.4"
libc = "0.2.152"
linux-raw-sys = { version = "0.9.0", features = ["ioctl"] }
md-5 = "0.10.6"
nix = { version = "0.29", default-features = false }
phf = "0.11.2"
phf_codegen = "0.11.2"
@@ -81,6 +83,7 @@ last = { optional = true, version = "0.0.1", package = "uu_last", path = "src/uu
lscpu = { optional = true, version = "0.0.1", package = "uu_lscpu", path = "src/uu/lscpu" }
lslocks = { optional = true, version = "0.0.1", package = "uu_lslocks", path = "src/uu/lslocks" }
lsmem = { optional = true, version = "0.0.1", package = "uu_lsmem", path = "src/uu/lsmem" }
mcookie = { optional = true, version = "0.0.1", package = "uu_mcookie", path = "src/uu/mcookie" }
mesg = { optional = true, version = "0.0.1", package = "uu_mesg", path = "src/uu/mesg" }
mountpoint = { optional = true, version = "0.0.1", package = "uu_mountpoint", path = "src/uu/mountpoint" }
renice = { optional = true, version = "0.0.1", package = "uu_renice", path = "src/uu/renice" }

17
src/uu/mcookie/Cargo.toml Normal file
View File

@@ -0,0 +1,17 @@
[package]
name = "uu_mcookie"
version = "0.0.1"
edition = "2021"
[lib]
path = "src/mcookie.rs"
[[bin]]
name = "mcookie"
path = "src/main.rs"
[dependencies]
uucore = { workspace = true }
clap = { workspace = true }
md-5 = { workspace = true }
rand = { workspace = true }

View File

@@ -0,0 +1,7 @@
# mcookie
```
mcookie [OPTION]...
```
Generate magic cookies for xauth.

View File

@@ -0,0 +1 @@
uucore::bin!(uu_mcookie);

View File

@@ -0,0 +1,111 @@
// This file is part of the uutils util-linux package.
//
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code.
use std::{fs::File, io::Read};
use clap::{crate_version, Arg, ArgAction, Command};
use md5::{Digest, Md5};
use rand::RngCore;
use uucore::{error::UResult, format_usage, help_about, help_usage};
mod options {
pub const FILE: &str = "file";
pub const MAX_SIZE: &str = "max-size";
pub const VERBOSE: &str = "verbose";
}
const ABOUT: &str = help_about!("mcookie.md");
const USAGE: &str = help_usage!("mcookie.md");
#[uucore::main]
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
let matches: clap::ArgMatches = uu_app().try_get_matches_from(args)?;
let verbose = matches.get_flag(options::VERBOSE);
let seed_files: Vec<&str> = matches
.get_many::<String>(options::FILE)
.unwrap_or_default()
.map(|v| v.as_str())
.collect();
// TODO: Parse max size from human-readable strings (KiB, MiB, GiB etc.)
let max_size = matches
.get_one::<String>(options::MAX_SIZE)
.map(|v| v.parse::<u64>().expect("Failed to parse max-size value"));
let mut hasher = Md5::new();
for file in seed_files {
let mut f = File::open(file)?;
let mut buffer: Vec<u8> = Vec::new();
if let Some(max_bytes) = &max_size {
let mut handle = f.take(*max_bytes);
handle.read_to_end(&mut buffer)?;
} else {
f.read_to_end(&mut buffer)?;
}
if verbose {
eprintln!("Got {} bytes from {}", buffer.len(), file);
}
hasher.update(&buffer);
}
const RANDOM_BYTES: usize = 128;
let mut rng = rand::rng();
let mut rand_bytes = [0u8; RANDOM_BYTES];
rng.fill_bytes(&mut rand_bytes);
hasher.update(rand_bytes);
if verbose {
eprintln!("Got {} bytes from randomness source", RANDOM_BYTES);
}
let result = hasher.finalize();
let output = result
.iter()
.map(|byte| format!("{:02x}", byte))
.collect::<Vec<_>>()
.join("");
println!("{}", output);
Ok(())
}
pub fn uu_app() -> Command {
Command::new(uucore::util_name())
.version(crate_version!())
.about(ABOUT)
.override_usage(format_usage(USAGE))
.infer_long_args(true)
.arg(
Arg::new(options::FILE)
.short('f')
.long("file")
.value_name("file")
.action(ArgAction::Append)
.help("use file as a cookie seed"),
)
.arg(
Arg::new(options::MAX_SIZE)
.short('m')
.long("max-size")
.value_name("num")
.action(ArgAction::Set)
.help("limit how much is read from seed files"),
)
.arg(
Arg::new(options::VERBOSE)
.short('v')
.long("verbose")
.action(ArgAction::SetTrue)
.help("explain what is being done"),
)
}