comparison pam-sober/src/lib.rs @ 34:ec70822cbdef

Overhaul
author Andy Caldwell <andrew.caldwell@metaswitch.com>
date Sun, 24 Apr 2022 03:42:11 +0100
parents d5c842a50827
children
comparison
equal deleted inserted replaced
32:ea5f195f035f 34:ec70822cbdef
1 #[macro_use] extern crate pam; 1 extern crate pam;
2 extern crate rand; 2 extern crate rand;
3 3
4 use pam::constants::{PamFlag, PamResultCode, PAM_PROMPT_ECHO_ON};
5 use pam::conv::Conv;
4 use pam::module::{PamHandle, PamHooks}; 6 use pam::module::{PamHandle, PamHooks};
5 use pam::constants::{PamResultCode, PamFlag, PAM_PROMPT_ECHO_ON};
6 use pam::conv::PamConv;
7 use rand::Rng; 7 use rand::Rng;
8 use std::ffi::CStr;
8 use std::str::FromStr; 9 use std::str::FromStr;
9 use std::ffi::CStr; 10 use pam::pam_try;
10
11 macro_rules! pam_try {
12 ($e:expr) => (
13 match $e {
14 Ok(v) => v,
15 Err(e) => return e,
16 }
17 );
18 ($e:expr, $err:expr) => (
19 match $e {
20 Ok(v) => v,
21 Err(e) => {
22 println!("Error: {}", e);
23 return $err;
24 }
25 }
26 );
27 }
28 11
29 struct PamSober; 12 struct PamSober;
30 pam_hooks!(PamSober); 13 pam::pam_hooks!(PamSober);
31 14
32 impl PamHooks for PamSober { 15 impl PamHooks for PamSober {
33 // This function performs the task of authenticating the user. 16 // This function performs the task of authenticating the user.
34 fn sm_authenticate(pamh: &PamHandle, _args: Vec<&CStr>, _flags: PamFlag) -> PamResultCode { 17 fn sm_authenticate(pamh: &mut PamHandle, _args: Vec<&CStr>, _flags: PamFlag) -> PamResultCode {
35 println!("Let's make sure you're sober enough to perform basic addition"); 18 println!("Let's make sure you're sober enough to perform basic addition");
36 19
37 /* TODO: use args to change difficulty ;-) 20 /* TODO: use args to change difficulty ;-)
38 let args: HashMap<&str, &str> = args.iter().map(|s| { 21 let args: HashMap<&str, &str> = args.iter().map(|s| {
39 let mut parts = s.splitn(2, "="); 22 let mut parts = s.splitn(2, "=");
42 */ 25 */
43 26
44 // TODO: maybe we can change difficulty base on user? 27 // TODO: maybe we can change difficulty base on user?
45 // let user = pam_try!(pam.get_user(None)); 28 // let user = pam_try!(pam.get_user(None));
46 29
47 let conv = match pamh.get_item::<PamConv>() { 30 let conv = match pamh.get_item::<Conv>() {
48 Ok(conv) => conv, 31 Ok(Some(conv)) => conv,
32 Ok(None) => todo!(),
49 Err(err) => { 33 Err(err) => {
50 println!("Couldn't get pam_conv"); 34 println!("Couldn't get pam_conv");
51 return err; 35 return err;
52 } 36 }
53 }; 37 };
56 let a = rng.gen::<u32>() % 100; 40 let a = rng.gen::<u32>() % 100;
57 let b = rng.gen::<u32>() % 100; 41 let b = rng.gen::<u32>() % 100;
58 let math = format!("{} + {} = ", a, b); 42 let math = format!("{} + {} = ", a, b);
59 43
60 // This println kinda helps debugging since the test script doesn't echo 44 // This println kinda helps debugging since the test script doesn't echo
61 println!("{}", math); 45 eprintln!("[DEBUG]: {}{}", math, a + b);
62 46
63 let password = pam_try!(conv.send(PAM_PROMPT_ECHO_ON, &math)); 47 let password = pam_try!(conv.send(PAM_PROMPT_ECHO_ON, &math));
64 48
65 if password.and_then(|p| u32::from_str(&p).ok()) == Some(a+b) { 49 if let Some(password) = password {
66 return PamResultCode::PAM_SUCCESS; 50 let password = pam_try!(password.to_str(), PamResultCode::PAM_AUTH_ERR);
51 let answer = pam_try!(u32::from_str(password), PamResultCode::PAM_AUTH_ERR);
52 if answer == a + b {
53 PamResultCode::PAM_SUCCESS
54 } else {
55 println!("Wrong answer provided {} + {} != {}", a, b, answer);
56 PamResultCode::PAM_AUTH_ERR
57 }
58 } else {
59 println!("You failed the PAM sobriety test.");
60 PamResultCode::PAM_AUTH_ERR
67 } 61 }
68
69 println!("You failed the PAM sobriety test.");
70 return PamResultCode::PAM_AUTH_ERR;
71 } 62 }
72 63
73 fn sm_setcred(_pamh: &PamHandle, _args: Vec<&CStr>, _flags: PamFlag) -> PamResultCode { 64 fn sm_setcred(_pamh: &mut PamHandle, _args: Vec<&CStr>, _flags: PamFlag) -> PamResultCode {
74 println!("set credentials"); 65 println!("set credentials");
75 PamResultCode::PAM_SUCCESS 66 PamResultCode::PAM_SUCCESS
76 } 67 }
77 68
78 fn acct_mgmt(_pamh: &PamHandle, _args: Vec<&CStr>, _flags: PamFlag) -> PamResultCode { 69 fn acct_mgmt(_pamh: &mut PamHandle, _args: Vec<&CStr>, _flags: PamFlag) -> PamResultCode {
79 println!("account management"); 70 println!("account management");
80 PamResultCode::PAM_SUCCESS 71 PamResultCode::PAM_SUCCESS
81 } 72 }
82 } 73 }