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_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"
|
||||||
|
@ -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"] }
|
||||||
|
64
src/lib.rs
64
src/lib.rs
@ -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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user