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_json",
"structopt",
"sudo",
]
[[package]]
@ -987,6 +988,16 @@ dependencies = [
"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]]
name = "syn"
version = "0.15.44"

View File

@ -25,6 +25,7 @@ serde_json = "1.0.51"
serde_derive = "1.0.106"
serde = "1.0.106"
pamsm = { version = "0.4.1", features = ["libpam"] }
sudo = "0.5.0"
[build-dependencies]
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::path::Path;
use std::str::FromStr;
use sudo::{self, RunningAs};
pub mod cli_args;
pub mod device;
@ -27,7 +28,12 @@ pub mod util;
struct 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
.into_iter()
.filter_map(|arg| {
@ -55,11 +61,26 @@ impl PamFido2Luks {
.get("name")
.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 !Path::new(&device).exists() || Path::new(&format!("/dev/mapper/{}", name)).exists()
{
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 additional_credentials: HashSet<String> = HashSet::new();
if device.is_luks2()? {
@ -79,7 +100,8 @@ impl PamFido2Luks {
.collect();
let credentials: Vec<&FidoCredential> = credentials.iter().collect();
if !credentials.is_empty() {
let salt = util::sha256(&[password.as_bytes()]);
for _ in 0..attempts {
let salt = util::sha256(&[password().expect("Password").as_bytes()]);
let secret = util::sha256(&[
&salt,
&perform_challenge(
@ -91,10 +113,11 @@ impl PamFido2Luks {
.0[..],
]);
device.activate(name.as_str(), &secret[..], None)?;
}
Ok(())
} else {
unimplemented!("custom error")
}
unimplemented!()
} else {
unimplemented!("custom error")
}
@ -107,12 +130,21 @@ impl PamServiceModule for PamFido2Luks {
Err(_) => return dbg!(PamError::AUTH_ERR),
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),
Ok(p) => p.map(|s| s.to_str().map(str::to_string).unwrap()),
};
if let (Some(user), Some(password)) = (user, password) {
match PamFido2Luks.open(user, password, args) {
if let Some(user) = user {
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,
Err(e) => match e {
//TODO: output more detailed error