pam module
Some checks failed
continuous-integration/drone/push Build is failing

This commit is contained in:
2020-09-25 00:23:36 +02:00
parent 55bae4161e
commit 63f29249d3
3 changed files with 129 additions and 0 deletions

111
src/lib.rs Normal file
View File

@@ -0,0 +1,111 @@
#[macro_use]
extern crate failure;
extern crate ctap_hmac as ctap;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate pamsm;
use crate::cli_args::{CommaSeparated, HexEncoded};
use crate::device::*;
use crate::error::*;
use crate::luks::*;
use ctap::FidoCredential;
use failure::_core::time::Duration;
use pamsm::PamLibExt;
use pamsm::*;
use std::collections::{HashMap, HashSet};
use std::ffi::CStr;
use std::str::FromStr;
pub mod cli_args;
pub mod device;
pub mod error;
pub mod luks;
pub mod util;
struct PamFido2Luks;
impl PamFido2Luks {
fn open(&self, password: String, args: Vec<String>) -> Fido2LuksResult<()> {
let args: HashMap<String, String> = args
.into_iter()
.filter_map(|arg| {
let mut parts = arg.split("=");
parts
.by_ref()
.next()
.map(|key| (key.to_string(), parts.collect::<Vec<_>>().join("=")))
})
.collect();
let credentials = args
.get("credentials")
.map(|creds| {
<CommaSeparated<String>>::from_str(creds)
.expect("Invalid credentials")
.0 //TODO: proper error handling
})
.unwrap_or_default();
let pin = args.get("pin");
let device = args.get("device");
let name = args.get("name");
if let (Some(device), Some(name)) = (device, name) {
let mut device = LuksDevice::load(device)?;
let mut additional_credentials: HashSet<String> = HashSet::new();
if device.is_luks2()? {
for token in device.tokens()? {
let (_, token) = token?;
additional_credentials.extend(token.credential.into_iter());
}
}
let credentials: Vec<FidoCredential> = credentials
.into_iter()
.chain(additional_credentials.into_iter())
.map(|cred| HexEncoded::from_str(cred.as_str()))
.map(|cred| FidoCredential {
id: cred.unwrap().0,
public_key: None,
})
.collect();
let credentials: Vec<&FidoCredential> = credentials.iter().collect();
if !credentials.is_empty() {
let secret = util::sha256(&[&perform_challenge(
&credentials[..],
&util::sha256(&[password.as_bytes()]),
Duration::from_secs(15),
pin.map(AsRef::as_ref),
)?
.0[..]]);
device.activate(name.as_str(), &secret[..], None)?;
} else {
unimplemented!("custom error")
}
unimplemented!()
} else {
unimplemented!("custom error")
}
}
}
impl PamServiceModule for PamFido2Luks {
fn authenticate(pamh: Pam, flag: PamFlag, args: Vec<String>) -> PamError {
let password = match pamh.get_authtok(None) {
Err(_) => return PamError::AUTH_ERR,
Ok(p) => p.map(|s| s.to_str().map(str::to_string).unwrap()),
};
if let Some(password) = password {
match PamFido2Luks.open(password, args) {
Ok(_) => PamError::SUCCESS,
Err(e) => match e {
//TODO: output more detailed error
_ => PamError::AUTH_ERR,
},
}
} else {
PamError::AUTH_ERR
}
}
}
pam_module!(PamFido2Luks);