use std::{env::args, ffi::CString, io}; use libc::syscall; fn usage() -> &'static str { "Usage: add-to-persistent-keyring \n\ \tKEY_DESCRIPTION: Kernel keyring key description\n\ \tKEY_DATA: Secret data associated with the key description" } fn parse_args() -> Result<(String, String), &'static str> { let args: Vec<_> = args().collect(); if args.len() != 3 { println!("{}", usage()); return Err("Incorrect arguments provided"); } let key_desc = args.get(1).ok_or("No key description provided")?; let key_data = args.get(2).ok_or("No key data provided")?; Ok((key_desc.to_owned(), key_data.to_owned())) } fn add_to_persistent_keyring(key_desc: String, key_data: String) -> Result<(), io::Error> { let persistent_id = match unsafe { syscall( libc::SYS_keyctl, libc::KEYCTL_GET_PERSISTENT, 0, libc::KEY_SPEC_SESSION_KEYRING, ) } { i if i < 0 => return Err(io::Error::last_os_error()), i => i, }; if unsafe { syscall(libc::SYS_keyctl, libc::KEYCTL_CLEAR, persistent_id) } < 0 { return Err(io::Error::last_os_error()); } let key_desc_cstring = CString::new(key_desc)?; if unsafe { libc::syscall( libc::SYS_add_key, concat!("user", "\0").as_ptr(), key_desc_cstring.as_ptr(), key_data.as_ptr(), key_data.len(), persistent_id, ) } < 0 { Err(io::Error::last_os_error()) } else { Ok(()) } } fn main() -> Result<(), String> { let (key_desc, key_data) = parse_args()?; add_to_persistent_keyring(key_desc, key_data).map_err(|e| e.to_string())?; Ok(()) }