sudo
Some checks failed
continuous-integration/drone/push Build is failing
continuous-integration/drone/pr Build is failing

This commit is contained in:
shimun 2020-09-29 18:28:22 +02:00
parent 7879d64e3a
commit fbbf606631
Signed by: shimun
GPG Key ID: E81D8382DC2F971B
3 changed files with 60 additions and 16 deletions

11
Cargo.lock generated
View File

@ -390,6 +390,7 @@ dependencies = [
"serde_derive", "serde_derive",
"serde_json", "serde_json",
"structopt", "structopt",
"sudo",
] ]
[[package]] [[package]]
@ -987,6 +988,16 @@ dependencies = [
"syn 1.0.40", "syn 1.0.40",
] ]
[[package]]
name = "sudo"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2a88e74edf206f281aff2820aa2066c781331044c770626dcafe19491f214e05"
dependencies = [
"libc",
"log",
]
[[package]] [[package]]
name = "syn" name = "syn"
version = "0.15.44" version = "0.15.44"

View File

@ -25,6 +25,7 @@ serde_json = "1.0.51"
serde_derive = "1.0.106" serde_derive = "1.0.106"
serde = "1.0.106" serde = "1.0.106"
pamsm = { version = "0.4.1", features = ["libpam"] } pamsm = { version = "0.4.1", features = ["libpam"] }
sudo = "0.5.0"
[build-dependencies] [build-dependencies]
ctap_hmac = { version="0.4.2", features = ["request_multiple"] } ctap_hmac = { version="0.4.2", features = ["request_multiple"] }

View File

@ -17,6 +17,7 @@ use std::collections::{HashMap, HashSet};
use std::ffi::CStr; use std::ffi::CStr;
use std::path::Path; use std::path::Path;
use std::str::FromStr; use std::str::FromStr;
use sudo::{self, RunningAs};
pub mod cli_args; pub mod cli_args;
pub mod device; pub mod device;
@ -27,7 +28,12 @@ pub mod util;
struct PamFido2Luks; struct PamFido2Luks;
impl PamFido2Luks { impl PamFido2Luks {
fn open(&self, user: String, password: String, args: Vec<String>) -> Fido2LuksResult<()> { fn open(
&self,
user: String,
mut password: impl FnMut() -> PamResult<String>,
args: Vec<String>,
) -> Fido2LuksResult<()> {
let args: HashMap<String, String> = args let args: HashMap<String, String> = args
.into_iter() .into_iter()
.filter_map(|arg| { .filter_map(|arg| {
@ -55,11 +61,26 @@ impl PamFido2Luks {
.get("name") .get("name")
.map(|name| name.replace("%user%", user.as_str())); .map(|name| name.replace("%user%", user.as_str()));
let attempts = args
.get("attempts")
.and_then(|a| a.parse::<usize>().ok())
.unwrap_or(3);
if let (Some(device), Some(name)) = (device, name) { if let (Some(device), Some(name)) = (device, name) {
if !Path::new(&device).exists() || Path::new(&format!("/dev/mapper/{}", name)).exists() if !Path::new(&device).exists() || Path::new(&format!("/dev/mapper/{}", name)).exists()
{ {
return Ok(()); return Ok(());
} }
// root required to mount luks
match sudo::check() {
RunningAs::User => {
//err
unimplemented!("no root")
}
_ => {
sudo::escalate_if_needed().unwrap();
}
}
let mut device = LuksDevice::load(device)?; let mut device = LuksDevice::load(device)?;
let mut additional_credentials: HashSet<String> = HashSet::new(); let mut additional_credentials: HashSet<String> = HashSet::new();
if device.is_luks2()? { if device.is_luks2()? {
@ -79,22 +100,24 @@ impl PamFido2Luks {
.collect(); .collect();
let credentials: Vec<&FidoCredential> = credentials.iter().collect(); let credentials: Vec<&FidoCredential> = credentials.iter().collect();
if !credentials.is_empty() { if !credentials.is_empty() {
let salt = util::sha256(&[password.as_bytes()]); for _ in 0..attempts {
let secret = util::sha256(&[ let salt = util::sha256(&[password().expect("Password").as_bytes()]);
&salt, let secret = util::sha256(&[
&perform_challenge(
&credentials[..],
&salt, &salt,
Duration::from_secs(15), &perform_challenge(
pin.map(AsRef::as_ref), &credentials[..],
)? &salt,
.0[..], Duration::from_secs(15),
]); pin.map(AsRef::as_ref),
device.activate(name.as_str(), &secret[..], None)?; )?
.0[..],
]);
device.activate(name.as_str(), &secret[..], None)?;
}
Ok(())
} else { } else {
unimplemented!("custom error") unimplemented!("custom error")
} }
unimplemented!()
} else { } else {
unimplemented!("custom error") unimplemented!("custom error")
} }
@ -107,12 +130,21 @@ impl PamServiceModule for PamFido2Luks {
Err(_) => return dbg!(PamError::AUTH_ERR), Err(_) => return dbg!(PamError::AUTH_ERR),
Ok(p) => p.map(|s| s.to_str().map(str::to_string).unwrap()), Ok(p) => p.map(|s| s.to_str().map(str::to_string).unwrap()),
}; };
let password = match pamh.get_authtok(None) { let mut password = match pamh.get_authtok(None) {
Err(_) => return dbg!(PamError::AUTH_ERR), Err(_) => return dbg!(PamError::AUTH_ERR),
Ok(p) => p.map(|s| s.to_str().map(str::to_string).unwrap()), Ok(p) => p.map(|s| s.to_str().map(str::to_string).unwrap()),
}; };
if let (Some(user), Some(password)) = (user, password) { if let Some(user) = user {
match PamFido2Luks.open(user, password, args) { match PamFido2Luks.open(
user,
move || match password.take() {
Some(pass) => Ok(pass),
None => pamh
.conv(Some("Fido2 salt: "), PamMsgStyle::PROMPT_ECHO_OFF)
.map(|s| s.map(|s| s.to_str().unwrap()).unwrap_or("").to_string()),
},
args,
) {
Ok(_) => PamError::SUCCESS, Ok(_) => PamError::SUCCESS,
Err(e) => match e { Err(e) => match e {
//TODO: output more detailed error //TODO: output more detailed error