comparison pam-sober/src/lib.rs @ 20:734ca62159fb

Refactor exported endpoings into pam_hooks macro
author Anthony Nowell <anthony@algorithmia.com>
date Tue, 26 Sep 2017 01:51:39 -0600
parents d654aa0655e5
children 4263c1d83d5b
comparison
equal deleted inserted replaced
19:d654aa0655e5 20:734ca62159fb
1 extern crate pam; 1 #[macro_use] extern crate pam;
2 extern crate rand; 2 extern crate rand;
3 3
4 pub mod ffi;
5
6 use pam::module::PamHandle; 4 use pam::module::PamHandle;
7 use pam::constants::{PamResultCode, PAM_PROMPT_ECHO_OFF}; 5 use pam::constants::{PamResultCode, PamFlag, PAM_PROMPT_ECHO_ON};
8 use pam::conv::PamConv; 6 use pam::conv::PamConv;
7 use pam::hooks::PamHooks;
9 use rand::Rng; 8 use rand::Rng;
10 use std::str::FromStr; 9 use std::str::FromStr;
10 use std::ffi::CStr;
11 11
12 macro_rules! pam_try { 12 macro_rules! pam_try {
13 ($e:expr) => ( 13 ($e:expr) => (
14 match $e { 14 match $e {
15 Ok(v) => v, 15 Ok(v) => v,
25 } 25 }
26 } 26 }
27 ); 27 );
28 } 28 }
29 29
30 // This function performs the task of authenticating the user. 30 struct PamSober;
31 pub fn sm_authenticate(pamh: &PamHandle, args: Vec<String>, silent: bool) -> PamResultCode { 31 pam_hooks!(PamSober);
32 println!("Let's auth over HTTP");
33 32
34 /* TODO: use args to change difficulty ;-) 33 impl PamHooks for PamSober {
35 let args: HashMap<&str, &str> = args.iter().map(|s| { 34 // This function performs the task of authenticating the user.
36 let mut parts = s.splitn(2, "="); 35 fn sm_authenticate(pamh: &PamHandle, _args: Vec<&CStr>, _flags: PamFlag) -> PamResultCode {
37 (parts.next().unwrap(), parts.next().unwrap_or("")) 36 println!("Let's auth over HTTP");
38 }).collect();
39 */
40 37
41 // TODO: maybe we can change difficulty base on user? 38 /* TODO: use args to change difficulty ;-)
42 // let user = pam_try!(pam.get_user(None)); 39 let args: HashMap<&str, &str> = args.iter().map(|s| {
40 let mut parts = s.splitn(2, "=");
41 (parts.next().unwrap(), parts.next().unwrap_or(""))
42 }).collect();
43 */
43 44
44 let conv = match pamh.get_item::<PamConv>() { 45 // TODO: maybe we can change difficulty base on user?
45 Ok(conv) => conv, 46 // let user = pam_try!(pam.get_user(None));
46 Err(err) => { 47
47 println!("Couldn't get pam_conv"); 48 let conv = match pamh.get_item::<PamConv>() {
48 return err; 49 Ok(conv) => conv,
50 Err(err) => {
51 println!("Couldn't get pam_conv");
52 return err;
53 }
54 };
55
56 let mut rng = rand::thread_rng();
57 let a = rng.gen::<u32>() % 100;
58 let b = rng.gen::<u32>() % 100;
59 let math = format!("{} + {} = ", a, b);
60
61 // This println kinda helps debugging since the test script doesn't echo
62 println!("{}", math);
63
64 let password = pam_try!(conv.send(PAM_PROMPT_ECHO_ON, &math));
65
66 if password.and_then(|p| u32::from_str(&p).ok()) == Some(a+b) {
67 return PamResultCode::PAM_SUCCESS;
49 } 68 }
50 };
51 69
52 let mut rng = rand::thread_rng(); 70 println!("You failed the PAM sobriety test.");
53 let a = rng.gen::<u32>() % 100; 71 return PamResultCode::PAM_AUTH_ERR;
54 let b = rng.gen::<u32>() % 100;
55 let math = format!("{} + {} = ", a, b);
56
57 // This println kinda helps debugging since the test script doesn't echo
58 println!("{}", math);
59
60 let password = pam_try!(conv.send(PAM_PROMPT_ECHO_OFF, &math));
61
62 if password.and_then(|p| u32::from_str(&p).ok()) == Some(a+b) {
63 return PamResultCode::PAM_SUCCESS;
64 } 72 }
65 73
66 println!("You failed the PAM sobriety test."); 74 fn sm_setcred(_pamh: &PamHandle, _args: Vec<&CStr>, _flags: PamFlag) -> PamResultCode {
67 return PamResultCode::PAM_AUTH_ERR; 75 println!("set credentials");
76 PamResultCode::PAM_SUCCESS
77 }
78
79 fn acct_mgmt(_pamh: &PamHandle, _args: Vec<&CStr>, _flags: PamFlag) -> PamResultCode {
80 println!("account management");
81 PamResultCode::PAM_SUCCESS
82 }
68 } 83 }
69
70 // This function performs the task of altering the credentials of the user with respect to the
71 // corresponding authorization scheme. Generally, an authentication module may have access to more
72 // information about a user than their authentication token. This function is used to make such
73 // information available to the application. It should only be called after the user has been
74 // authenticated but before a session has been established.
75 pub fn sm_setcred(_pamh: &PamHandle, _args: Vec<String>, _silent: bool) -> PamResultCode {
76 println!("set credentials");
77 PamResultCode::PAM_SUCCESS
78 }
79
80 // This function performs the task of establishing whether the user is permitted to gain access at
81 // this time. It should be understood that the user has previously been validated by an
82 // authentication module. This function checks for other things. Such things might be: the time of
83 // day or the date, the terminal line, remote hostname, etc. This function may also determine
84 // things like the expiration on passwords, and respond that the user change it before continuing.
85 pub fn acct_mgmt(_pamh: &PamHandle, _args: Vec<String>, _silent: bool) -> PamResultCode {
86 println!("account management");
87 PamResultCode::PAM_SUCCESS
88 }