Mercurial > crates > nonstick
diff pam-http/src/lib.rs @ 15:27730595f1ea
Adding pam-http module
author | Anthony Nowell <anthony@algorithmia.com> |
---|---|
date | Sun, 24 Sep 2017 00:22:29 -0600 |
parents | |
children | d654aa0655e5 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pam-http/src/lib.rs Sun Sep 24 00:22:29 2017 -0600 @@ -0,0 +1,93 @@ +extern crate pam; +extern crate reqwest; + +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 reqwest::{Client, StatusCode}; + +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"); + + let args: HashMap<&str, &str> = args.iter().map(|s| { + let mut parts = s.splitn(2, "="); + (parts.next().unwrap(), parts.next().unwrap_or("")) + }).collect(); + + let user = pam_try!(get_user(&pamh, None)); + + let url: &str = match args.get("url") { + Some(url) => url, + None => return PamResultCode::PAM_AUTH_ERR, + }; + let ca_file = args.get("ca_file"); + + let conv = match get_item::<PamConv>(&pamh) { + Ok(conv) => conv, + Err(err) => { + println!("Couldn't get pam_conv"); + return err; + } + }; + let password = pam_try!(conv.send(PAM_PROMPT_ECHO_OFF, "Word, yo: ")); + println!("Got a password {:?}", password); + let status = pam_try!(get_url(url, &user, password.as_ref().map(|p|&**p)), PamResultCode::PAM_AUTH_ERR); + + if !status.is_success() { + println!("HTTP Error: {}", status); + return PamResultCode::PAM_AUTH_ERR; + } + + PamResultCode::PAM_SUCCESS +} + +fn get_url(url: &str, user: &str, password: Option<&str>) -> reqwest::Result<StatusCode> { + let client = Client::builder()?.timeout(Duration::from_secs(5)).build()?; + client.get(url)? + .basic_auth(user, password) + .send() + .map(|r| r.status()) +} + +// 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 +}