Mercurial > crates > nonstick
diff pam-sober/src/lib.rs @ 17:53efbcff805d
Add pam-sober
author | Anthony Nowell <anthony@algorithmia.com> |
---|---|
date | Sun, 24 Sep 2017 00:57:13 -0600 |
parents | |
children | d654aa0655e5 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pam-sober/src/lib.rs Sun Sep 24 00:57:13 2017 -0600 @@ -0,0 +1,90 @@ +extern crate pam; +extern crate rand; + +pub mod ffi; + +use pam::module::{PamHandleT, get_item, get_user}; +use pam::constants::{PamResultCode, PAM_PROMPT_ECHO_OFF}; +use pam::conv::PamConv; +use std::collections::HashMap; +use std::time::Duration; +use rand::Rng; +use std::str::FromStr; + +macro_rules! pam_try { + ($e:expr) => ( + match $e { + Ok(v) => v, + Err(e) => return e, + } + ); + ($e:expr, $err:expr) => ( + match $e { + Ok(v) => v, + Err(e) => { + println!("Error: {}", e); + return $err; + } + } + ); +} + +// This function performs the task of authenticating the user. +pub fn sm_authenticate(pamh: &PamHandleT, args: Vec<String>, silent: bool) -> PamResultCode { + println!("Let's auth over HTTP"); + + /* 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!(get_user(&pamh, None)); + + let conv = match get_item::<PamConv>(&pamh) { + Ok(conv) => conv, + 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 + println!("{}", math); + + let password = pam_try!(conv.send(PAM_PROMPT_ECHO_OFF, &math)); + + if password.and_then(|p| u32::from_str(&p).ok()) == Some(a+b) { + return PamResultCode::PAM_SUCCESS; + } + + println!("You failed the PAM sobriety test."); + return PamResultCode::PAM_AUTH_ERR; +} + +// This function performs the task of altering the credentials of the user with respect to the +// corresponding authorization scheme. Generally, an authentication module may have access to more +// information about a user than their authentication token. This function is used to make such +// information available to the application. It should only be called after the user has been +// authenticated but before a session has been established. +pub fn sm_setcred(_pamh: &PamHandleT, _args: Vec<String>, _silent: bool) -> PamResultCode { + println!("set credentials"); + PamResultCode::PAM_SUCCESS +} + +// This function performs the task of establishing whether the user is permitted to gain access at +// this time. It should be understood that the user has previously been validated by an +// authentication module. This function checks for other things. Such things might be: the time of +// day or the date, the terminal line, remote hostname, etc. This function may also determine +// things like the expiration on passwords, and respond that the user change it before continuing. +pub fn acct_mgmt(_pamh: &PamHandleT, _args: Vec<String>, _silent: bool) -> PamResultCode { + println!("account management"); + PamResultCode::PAM_SUCCESS +}