feat: clone from: https://github.com/anowell/pam-rs
This commit is contained in:
12
pam-sober/Cargo.toml
Normal file
12
pam-sober/Cargo.toml
Normal file
@@ -0,0 +1,12 @@
|
||||
[package]
|
||||
name = "pam-sober"
|
||||
version = "0.1.0"
|
||||
authors = ["Anthony Nowell <anowell@gmail.com>"]
|
||||
|
||||
[lib]
|
||||
name = "pam_sober"
|
||||
crate-type = ["cdylib"]
|
||||
|
||||
[dependencies]
|
||||
pam-bindings = { path = "../pam/" }
|
||||
rand = "0.8.4"
|
||||
12
pam-sober/Justfile
Normal file
12
pam-sober/Justfile
Normal file
@@ -0,0 +1,12 @@
|
||||
|
||||
all:
|
||||
cargo build
|
||||
|
||||
install:
|
||||
@cargo build --release
|
||||
sudo cp conf/sober-auth /etc/pam.d/
|
||||
sudo cp ../target/release/libpam_sober.so /lib/security/pam_sober.so
|
||||
|
||||
test:
|
||||
@just install
|
||||
gcc -o ../target/pam_test test.c -lpam -lpam_misc
|
||||
2
pam-sober/conf/sober-auth
Normal file
2
pam-sober/conf/sober-auth
Normal file
@@ -0,0 +1,2 @@
|
||||
auth sufficient pam_sober.so
|
||||
account sufficient pam_sober.so
|
||||
73
pam-sober/src/lib.rs
Normal file
73
pam-sober/src/lib.rs
Normal file
@@ -0,0 +1,73 @@
|
||||
extern crate pam;
|
||||
extern crate rand;
|
||||
|
||||
use pam::constants::{PamFlag, PamResultCode, PAM_PROMPT_ECHO_ON};
|
||||
use pam::conv::Conv;
|
||||
use pam::module::{PamHandle, PamHooks};
|
||||
use rand::Rng;
|
||||
use std::ffi::CStr;
|
||||
use std::str::FromStr;
|
||||
use pam::pam_try;
|
||||
|
||||
struct PamSober;
|
||||
pam::pam_hooks!(PamSober);
|
||||
|
||||
impl PamHooks for PamSober {
|
||||
// This function performs the task of authenticating the user.
|
||||
fn sm_authenticate(pamh: &mut PamHandle, _args: Vec<&CStr>, _flags: PamFlag) -> PamResultCode {
|
||||
println!("Let's make sure you're sober enough to perform basic addition");
|
||||
|
||||
/* TODO: use args to change difficulty ;-)
|
||||
let args: HashMap<&str, &str> = args.iter().map(|s| {
|
||||
let mut parts = s.splitn(2, "=");
|
||||
(parts.next().unwrap(), parts.next().unwrap_or(""))
|
||||
}).collect();
|
||||
*/
|
||||
|
||||
// TODO: maybe we can change difficulty base on user?
|
||||
// let user = pam_try!(pam.get_user(None));
|
||||
|
||||
let conv = match pamh.get_item::<Conv>() {
|
||||
Ok(Some(conv)) => conv,
|
||||
Ok(None) => todo!(),
|
||||
Err(err) => {
|
||||
println!("Couldn't get pam_conv");
|
||||
return err;
|
||||
}
|
||||
};
|
||||
|
||||
let mut rng = rand::thread_rng();
|
||||
let a = rng.gen::<u32>() % 100;
|
||||
let b = rng.gen::<u32>() % 100;
|
||||
let math = format!("{} + {} = ", a, b);
|
||||
|
||||
// This println kinda helps debugging since the test script doesn't echo
|
||||
eprintln!("[DEBUG]: {}{}", math, a + b);
|
||||
|
||||
let password = pam_try!(conv.send(PAM_PROMPT_ECHO_ON, &math));
|
||||
|
||||
if let Some(password) = password {
|
||||
let password = pam_try!(password.to_str(), PamResultCode::PAM_AUTH_ERR);
|
||||
let answer = pam_try!(u32::from_str(password), PamResultCode::PAM_AUTH_ERR);
|
||||
if answer == a + b {
|
||||
PamResultCode::PAM_SUCCESS
|
||||
} else {
|
||||
println!("Wrong answer provided {} + {} != {}", a, b, answer);
|
||||
PamResultCode::PAM_AUTH_ERR
|
||||
}
|
||||
} else {
|
||||
println!("You failed the PAM sobriety test.");
|
||||
PamResultCode::PAM_AUTH_ERR
|
||||
}
|
||||
}
|
||||
|
||||
fn sm_setcred(_pamh: &mut PamHandle, _args: Vec<&CStr>, _flags: PamFlag) -> PamResultCode {
|
||||
println!("set credentials");
|
||||
PamResultCode::PAM_SUCCESS
|
||||
}
|
||||
|
||||
fn acct_mgmt(_pamh: &mut PamHandle, _args: Vec<&CStr>, _flags: PamFlag) -> PamResultCode {
|
||||
println!("account management");
|
||||
PamResultCode::PAM_SUCCESS
|
||||
}
|
||||
}
|
||||
53
pam-sober/test.c
Normal file
53
pam-sober/test.c
Normal file
@@ -0,0 +1,53 @@
|
||||
#include <security/pam_appl.h>
|
||||
#include <security/pam_misc.h>
|
||||
#include <stdio.h>
|
||||
|
||||
const struct pam_conv conv = {
|
||||
misc_conv,
|
||||
NULL
|
||||
};
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
pam_handle_t* pamh = NULL;
|
||||
int retval;
|
||||
const char* user = "nobody";
|
||||
|
||||
if(argc != 2) {
|
||||
printf("Usage: app [username]\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
user = argv[1];
|
||||
|
||||
retval = pam_start("sober-auth", user, &conv, &pamh);
|
||||
|
||||
// Are the credentials correct?
|
||||
if (retval == PAM_SUCCESS) {
|
||||
printf("PAM module initialized\n");
|
||||
retval = pam_authenticate(pamh, 0);
|
||||
}
|
||||
|
||||
// Can the accound be used at this time?
|
||||
if (retval == PAM_SUCCESS) {
|
||||
printf("Credentials accepted.\n");
|
||||
retval = pam_acct_mgmt(pamh, 0);
|
||||
}
|
||||
|
||||
// Did everything work?
|
||||
if (retval == PAM_SUCCESS) {
|
||||
printf("Account is valid.\n");
|
||||
printf("Authenticated\n");
|
||||
} else {
|
||||
printf("Not Authenticated\n");
|
||||
}
|
||||
|
||||
// close PAM (end session)
|
||||
if (pam_end(pamh, retval) != PAM_SUCCESS) {
|
||||
pamh = NULL;
|
||||
printf("check_user: failed to release authenticator\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return retval == PAM_SUCCESS ? 0 : 1;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user