Fix error handling and add nixos test

This commit is contained in:
Tim Schubert 2024-12-29 13:38:29 +01:00
parent c06b3a7142
commit ef60878471
Signed by: dadada
SSH key fingerprint: SHA256:bFAjFH3hR8zRBaJjzQDjc3o4jqoq5EZ87l+KXEjxIz0
6 changed files with 335 additions and 20 deletions

View file

@ -1,11 +1,14 @@
use std::{collections::HashMap, env::temp_dir, ffi::CStr, fs::File};
use std::{collections::HashMap, ffi::CStr};
use log::{debug, info, trace, warn};
use pam::{
constants::{PamResultCode, PAM_PROMPT_ECHO_ON},
constants::{PamResultCode, PAM_PROMPT_ECHO_OFF},
conv::Conv,
items::User,
module::PamHooks,
pam_try,
};
use syslog::Facility;
struct PamHoneypot;
@ -15,12 +18,23 @@ impl PamHooks for PamHoneypot {
args: Vec<&CStr>,
_flags: pam::constants::PamFlag,
) -> pam::constants::PamResultCode {
let _ = syslog::init(
Facility::LOG_USER,
log::LevelFilter::Info,
Some("pam_honeypot"),
);
trace!("Running pam_honeypot");
let args: Vec<_> = args.iter().map(|s| s.to_string_lossy()).collect();
debug!("args = {args:?}");
let args: HashMap<&str, &str> = args
.iter()
.map(|s| {
let mut parts = s.splitn(2, '=');
(parts.next().unwrap(), parts.next().unwrap_or(""))
(
parts.next().expect("Failed to parse arguments"),
parts.next().unwrap_or(""),
)
})
.collect();
@ -28,13 +42,16 @@ impl PamHooks for PamHoneypot {
Some(user) => user,
_ => return PamResultCode::PAM_IGNORE,
};
debug!("honeypot user = {honey_user}");
let honey_password = match args.get("password") {
Some(password) => password,
_ => return PamResultCode::PAM_IGNORE,
};
let user = pam_try!(pamh.get_user(None));
if user != *honey_user {
trace!("Getting user from PAM");
let user: User = pam_try!(pamh.get_item()).unwrap_or(User(c""));
info!("Checking if entered username is honeypot user");
if user.to_string_lossy() != *honey_user {
return PamResultCode::PAM_IGNORE;
}
@ -47,20 +64,21 @@ impl PamHooks for PamHoneypot {
return err;
}
};
let password = pam_try!(conv.send(PAM_PROMPT_ECHO_ON, "Password"));
trace!("Getting password from PAM");
let password = pam_try!(conv.send(PAM_PROMPT_ECHO_OFF, "Password: "));
let password = match password {
Some(password) => Some(pam_try!(password.to_str(), PamResultCode::PAM_AUTH_ERR)),
_ => None,
};
if let Some(password) = password {
trace!("Checking if password is honeypot password");
if *honey_password == password {
let mut tmp = temp_dir();
tmp.push("honeypot");
let _ = File::create(tmp);
return PamResultCode::PAM_AUTH_ERR;
warn!("Someone tried to log in with the honeypot credentials");
} else {
info!("Entered username is not the honeypot user")
}
return PamResultCode::PAM_AUTH_ERR;
}
PamResultCode::PAM_IGNORE