use clap::Parser;
use linux_keyutils::{Key, KeyRing, KeyRingIdentifier, KeySerialId};
use linux_keyutils::{KeyPermissionsBuilder, Permission};
use std::error::Error;
use zeroize::Zeroizing;
#[derive(Parser, Debug)]
#[clap(author, version, about, long_about = None)]
#[command(arg_required_else_help(true))]
#[command(subcommand_required(true))]
struct Args {
#[clap(subcommand)]
subcommand: Command,
}
#[derive(clap::Subcommand, Debug, PartialEq)]
#[command(arg_required_else_help(true))]
enum Command {
Create {
#[clap(short, long)]
description: String,
#[clap(short, long)]
secret: String,
},
Read {
#[clap(short, long)]
description: String,
},
Chown {
#[clap(short, long)]
description: String,
#[clap(short, long)]
uid: Option<u32>,
#[clap(short, long)]
gid: Option<u32>,
},
Chmod {
#[clap(short, long)]
description: String,
},
Invalidate {
#[clap(short, long)]
description: String,
},
Instantiate {
#[clap(short, long)]
keyid: Option<i32>,
#[clap(short, long)]
payload: String,
#[clap(short, long)]
ring: Option<i32>,
},
}
fn main() -> Result<(), Box<dyn Error>> {
let args = Args::parse();
let ring = KeyRing::from_special_id(KeyRingIdentifier::Session, false)?;
_ = match args.subcommand {
Command::Create {
description,
secret,
} => {
let key = ring.add_key(&description, &secret)?;
println!("Created key with ID {:?}", key.get_id());
}
Command::Read { description } => {
let key = ring.search(&description)?;
let mut buf = Zeroizing::new([0u8; 2048]);
let len = key.read(&mut buf)?;
println!("Secret {:?}", std::str::from_utf8(&buf[..len])?);
}
Command::Chown {
description,
uid,
gid,
} => {
let key = ring.search(&description)?;
key.chown(uid, gid)?;
}
Command::Chmod { description } => {
let key = ring.search(&description)?;
let perms = KeyPermissionsBuilder::builder()
.user(Permission::ALL)
.build();
key.set_perms(perms)?;
}
Command::Invalidate { description } => {
let key = ring.search(&description)?;
key.invalidate()?;
println!("Removed key with ID {:?}", key.get_id());
}
Command::Instantiate {
keyid,
payload,
ring,
} => {
let key = Key::from_id(KeySerialId::new(keyid.unwrap_or(i32::MAX)));
key.instantiate(&payload, KeySerialId::new(ring.unwrap_or(i32::MAX)))?;
}
};
Ok(())
}