sudo
This commit is contained in:
parent
7879d64e3a
commit
fbbf606631
11
Cargo.lock
generated
11
Cargo.lock
generated
@ -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"
|
||||
|
@ -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"] }
|
||||
|
64
src/lib.rs
64
src/lib.rs
@ -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,22 +100,24 @@ impl PamFido2Luks {
|
||||
.collect();
|
||||
let credentials: Vec<&FidoCredential> = credentials.iter().collect();
|
||||
if !credentials.is_empty() {
|
||||
let salt = util::sha256(&[password.as_bytes()]);
|
||||
let secret = util::sha256(&[
|
||||
&salt,
|
||||
&perform_challenge(
|
||||
&credentials[..],
|
||||
for _ in 0..attempts {
|
||||
let salt = util::sha256(&[password().expect("Password").as_bytes()]);
|
||||
let secret = util::sha256(&[
|
||||
&salt,
|
||||
Duration::from_secs(15),
|
||||
pin.map(AsRef::as_ref),
|
||||
)?
|
||||
.0[..],
|
||||
]);
|
||||
device.activate(name.as_str(), &secret[..], None)?;
|
||||
&perform_challenge(
|
||||
&credentials[..],
|
||||
&salt,
|
||||
Duration::from_secs(15),
|
||||
pin.map(AsRef::as_ref),
|
||||
)?
|
||||
.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
|
||||
|
Loading…
x
Reference in New Issue
Block a user