implemented some extra functionality
This commit is contained in:
parent
533ed4b8be
commit
e493e5180d
@ -21,7 +21,7 @@ use sodiumoxide::crypto::{
|
||||
},
|
||||
};
|
||||
|
||||
use crate::{Result,Error};
|
||||
use crate::{Result,Error,KeyPair};
|
||||
|
||||
#[derive(Serialize,Deserialize,Debug)]
|
||||
pub struct KeyRing {
|
||||
@ -38,7 +38,7 @@ impl KeyRing {
|
||||
|
||||
pub fn load<P: AsRef<Path>>(path: P, passphrase: &str) -> Result<KeyRing> {
|
||||
let mut sbox = SecretBox::new(path.as_ref());
|
||||
sbox.read()?;
|
||||
sbox.read().map_err(|e| format_err!("Error reading keyring file: {}", e))?;
|
||||
let mut bytes = sbox.open(passphrase)?;
|
||||
let keyring = toml::from_slice::<KeyRing>(&bytes)?;
|
||||
bytes.iter_mut().for_each(|b| *b = 0);
|
||||
@ -51,7 +51,7 @@ impl KeyRing {
|
||||
}
|
||||
|
||||
fn get_cryptsetup_passphrase() -> Result<String> {
|
||||
let key = KernelKey::request_key("user", "cryptsetup")?;
|
||||
let key = KeyRing::get_key("cryptsetup")?;
|
||||
info!("Got key {}", key.0);
|
||||
let buf = key.read()?;
|
||||
match buf.split(|b| *b == 0).map(|bs| String::from_utf8_lossy(bs).to_string()).last() {
|
||||
@ -60,14 +60,38 @@ impl KeyRing {
|
||||
}
|
||||
}
|
||||
|
||||
fn get_key(name: &str) -> Result<KernelKey> {
|
||||
if let Ok(key) = KernelKey::user_keyring().search(name) {
|
||||
debug!("Found {} key in user keyring: (keyid: {:08x})", name, key.0);
|
||||
if let Err(e) = key.read() {
|
||||
info!("err tho on read: {}", e);
|
||||
} else {
|
||||
return Ok(key);
|
||||
}
|
||||
}
|
||||
if let Ok(key) = KernelKey::request_key("user", name) {
|
||||
info!("Found {} key with request_key", name);
|
||||
return Ok(key);
|
||||
}
|
||||
return Err(format_err!("kernel key '{}' not found", name))
|
||||
}
|
||||
|
||||
pub fn add_keys_to_kernel(&self) -> Result<()> {
|
||||
for (k,v) in self.keypairs.iter() {
|
||||
info!("Adding {} to kernel keystore", k.as_str());
|
||||
let _key = KernelKey::add_key("user", k.as_str(), v.as_bytes(), KEY_SPEC_USER_KEYRING)?;
|
||||
let bytes = hex::decode(v)?;
|
||||
let key = KernelKey::add_key("user", k.as_str(), &bytes, KEY_SPEC_USER_KEYRING)?;
|
||||
key.set_perm(0x3f030000)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn get_kernel_keypair(name: &str) -> Result<KeyPair> {
|
||||
let key = KeyRing::get_key(name)?;
|
||||
let data = key.read()?;
|
||||
KeyPair::from_bytes(&data)
|
||||
}
|
||||
|
||||
pub fn write<P: AsRef<Path>>(&self, path: P, passphrase: &str) -> Result<()> {
|
||||
let salt = pwhash::gen_salt();
|
||||
let nonce = secretbox::gen_nonce();
|
||||
@ -143,13 +167,23 @@ impl SecretBox {
|
||||
|
||||
}
|
||||
|
||||
const KEYCTL_GET_KEYRING_ID : c_int = 0; // ask for a keyring's ID
|
||||
const KEYCTL_SETPERM : c_int = 5; // set perms on a key
|
||||
const KEYCTL_DESCRIBE : c_int = 6; // describe a key
|
||||
const KEYCTL_SEARCH : c_int = 10; // search for a key in a keyring
|
||||
const KEYCTL_READ : c_int = 11; // read a key or keyring's contents
|
||||
|
||||
const KEY_SPEC_USER_KEYRING : c_int = -4; // - key ID for UID-specific keyring
|
||||
|
||||
|
||||
pub struct KernelKey(int32_t);
|
||||
|
||||
impl KernelKey {
|
||||
|
||||
pub fn user_keyring() -> KernelKey {
|
||||
KernelKey(KEY_SPEC_USER_KEYRING)
|
||||
}
|
||||
|
||||
pub fn request_key(key_type: &str, description: &str) -> Result<KernelKey> {
|
||||
let key_type = CString::new(key_type).unwrap();
|
||||
let description = CString::new(description).unwrap();
|
||||
@ -164,11 +198,40 @@ impl KernelKey {
|
||||
Ok(KernelKey(serial as i32))
|
||||
}
|
||||
|
||||
pub fn get_keyring_id(&self, create: bool) -> Result<KernelKey> {
|
||||
let serial = keyctl2(KEYCTL_GET_KEYRING_ID, self.id(), create as u64)?;
|
||||
Ok(KernelKey(serial as i32))
|
||||
}
|
||||
|
||||
pub fn set_perm(&self, perm: u32) -> Result<()> {
|
||||
keyctl2(KEYCTL_SETPERM, self.id(), perm as u64)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn describe(&self) -> Result<String> {
|
||||
let mut size = 0;
|
||||
loop {
|
||||
size = match self.buffer_request(KEYCTL_DESCRIBE, size) {
|
||||
BufferResult::Err(err) => return Err(format_err!("Error calling KEYCTL_DESCRIBE on key: {}", err)),
|
||||
BufferResult::Ok(vec) => return Ok(String::from_utf8(vec).expect("KEYCTL_DESCRIBE returned bad utf8")),
|
||||
BufferResult::TooSmall(sz) => sz,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn search(&self, description: &str) -> Result<KernelKey> {
|
||||
let key_type = CString::new("user").unwrap();
|
||||
let description = CString::new(description).unwrap();
|
||||
|
||||
let serial = keyctl4(KEYCTL_SEARCH, self.id(), key_type.as_ptr() as u64, description.as_ptr() as u64, 0)?;
|
||||
Ok(KernelKey(serial as i32))
|
||||
}
|
||||
|
||||
pub fn read(&self) -> Result<Vec<u8>> {
|
||||
let mut size = 0;
|
||||
loop {
|
||||
size = match self.buffer_request(KEYCTL_READ, size) {
|
||||
BufferResult::Err(err) => return Err(err),
|
||||
BufferResult::Err(err) => return Err(format_err!("Error reading key: {}", err)),
|
||||
BufferResult::Ok(buffer) => return Ok(buffer),
|
||||
BufferResult::TooSmall(sz) => sz + 1,
|
||||
}
|
||||
@ -212,14 +275,22 @@ enum BufferResult {
|
||||
|
||||
|
||||
fn keyctl1(command: c_int, arg2: c_ulong) -> Result<c_long> {
|
||||
_keyctl(command, arg2, 0, 0, 0)
|
||||
sys_keyctl(command, arg2, 0, 0, 0)
|
||||
}
|
||||
|
||||
fn keyctl2(command: c_int, arg2: c_ulong, arg3: c_ulong) -> Result<c_long> {
|
||||
sys_keyctl(command, arg2, arg3, 0, 0)
|
||||
}
|
||||
|
||||
fn keyctl3(command: c_int, arg2: c_ulong, arg3: c_ulong, arg4: c_ulong) -> Result<c_long> {
|
||||
_keyctl(command, arg2, arg3, arg4, 0)
|
||||
sys_keyctl(command, arg2, arg3, arg4, 0)
|
||||
}
|
||||
|
||||
fn _keyctl(command: c_int, arg2: c_ulong, arg3: c_ulong, arg4: c_ulong, arg5: c_ulong) -> Result<c_long> {
|
||||
fn keyctl4(command: c_int, arg2: c_ulong, arg3: c_ulong, arg4: c_ulong, arg5: c_ulong) -> Result<c_long> {
|
||||
sys_keyctl(command, arg2, arg3, arg4, arg5)
|
||||
}
|
||||
|
||||
fn sys_keyctl(command: c_int, arg2: c_ulong, arg3: c_ulong, arg4: c_ulong, arg5: c_ulong) -> Result<c_long> {
|
||||
unsafe {
|
||||
let r = libc::syscall(libc::SYS_keyctl, command, arg2, arg3, arg4, arg5);
|
||||
if r == -1 {
|
||||
|
Loading…
Reference in New Issue
Block a user