Mercurial > crates > nonstick
comparison pam-http/src/lib.rs @ 35:3b2ff50db010
Merge pull request #8 from bossmc/master
Various enhancements/fixes
| author | Anthony Nowell <anowell@gmail.com> |
|---|---|
| date | Wed, 08 Jun 2022 09:28:13 -0700 |
| parents | ec70822cbdef |
| children |
comparison
equal
deleted
inserted
replaced
| 33:86113e45f88f | 35:3b2ff50db010 |
|---|---|
| 1 #[macro_use] extern crate pam; | 1 extern crate pam; |
| 2 extern crate reqwest; | 2 extern crate reqwest; |
| 3 | 3 |
| 4 use pam::constants::{PamFlag, PamResultCode, PAM_PROMPT_ECHO_OFF}; | |
| 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_OFF}; | 7 use reqwest::blocking::Client; |
| 6 use pam::conv::PamConv; | 8 use reqwest::StatusCode; |
| 7 use std::collections::HashMap; | 9 use std::collections::HashMap; |
| 10 use std::ffi::CStr; | |
| 8 use std::time::Duration; | 11 use std::time::Duration; |
| 9 use reqwest::{Client, StatusCode}; | 12 use pam::pam_try; |
| 10 use std::ffi::CStr; | |
| 11 | |
| 12 | |
| 13 macro_rules! pam_try { | |
| 14 ($e:expr) => ( | |
| 15 match $e { | |
| 16 Ok(v) => v, | |
| 17 Err(e) => return e, | |
| 18 } | |
| 19 ); | |
| 20 ($e:expr, $err:expr) => ( | |
| 21 match $e { | |
| 22 Ok(v) => v, | |
| 23 Err(e) => { | |
| 24 println!("Error: {}", e); | |
| 25 return $err; | |
| 26 } | |
| 27 } | |
| 28 ); | |
| 29 } | |
| 30 | 13 |
| 31 struct PamHttp; | 14 struct PamHttp; |
| 32 pam_hooks!(PamHttp); | 15 pam::pam_hooks!(PamHttp); |
| 33 | 16 |
| 34 impl PamHooks for PamHttp { | 17 impl PamHooks for PamHttp { |
| 35 // This function performs the task of authenticating the user. | 18 // This function performs the task of authenticating the user. |
| 36 fn sm_authenticate(pamh: &PamHandle, args: Vec<&CStr>, _flags: PamFlag) -> PamResultCode { | 19 fn sm_authenticate(pamh: &mut PamHandle, args: Vec<&CStr>, _flags: PamFlag) -> PamResultCode { |
| 37 println!("Let's auth over HTTP"); | 20 println!("Let's auth over HTTP"); |
| 38 | 21 |
| 39 let args: Vec<_> = args.iter().map(|s| s.to_string_lossy().to_owned() ).collect(); | 22 let args: Vec<_> = args |
| 40 let args: HashMap<&str, &str> = args.iter().map(|s| { | 23 .iter() |
| 41 let mut parts = s.splitn(2, "="); | 24 .map(|s| s.to_string_lossy()) |
| 42 (parts.next().unwrap(), parts.next().unwrap_or("")) | 25 .collect(); |
| 43 }).collect(); | 26 let args: HashMap<&str, &str> = args |
| 27 .iter() | |
| 28 .map(|s| { | |
| 29 let mut parts = s.splitn(2, '='); | |
| 30 (parts.next().unwrap(), parts.next().unwrap_or("")) | |
| 31 }) | |
| 32 .collect(); | |
| 44 | 33 |
| 45 let user = pam_try!(pamh.get_user(None)); | 34 let user = pam_try!(pamh.get_user(None)); |
| 46 | 35 |
| 47 let url: &str = match args.get("url") { | 36 let url: &str = match args.get("url") { |
| 48 Some(url) => url, | 37 Some(url) => url, |
| 49 None => return PamResultCode::PAM_AUTH_ERR, | 38 None => return PamResultCode::PAM_AUTH_ERR, |
| 50 }; | 39 }; |
| 51 // let ca_file = args.get("ca_file"); | |
| 52 | 40 |
| 53 let conv = match pamh.get_item::<PamConv>() { | 41 let conv = match pamh.get_item::<Conv>() { |
| 54 Ok(conv) => conv, | 42 Ok(Some(conv)) => conv, |
| 43 Ok(None) => { | |
| 44 unreachable!("No conv available"); | |
| 45 } | |
| 55 Err(err) => { | 46 Err(err) => { |
| 56 println!("Couldn't get pam_conv"); | 47 println!("Couldn't get pam_conv"); |
| 57 return err; | 48 return err; |
| 58 } | 49 } |
| 59 }; | 50 }; |
| 60 let password = pam_try!(conv.send(PAM_PROMPT_ECHO_OFF, "Word, yo: ")); | 51 let password = pam_try!(conv.send(PAM_PROMPT_ECHO_OFF, "Word, yo: ")); |
| 52 let password = match password { | |
| 53 Some(password) => Some(pam_try!(password.to_str(), PamResultCode::PAM_AUTH_ERR)), | |
| 54 None => None, | |
| 55 }; | |
| 61 println!("Got a password {:?}", password); | 56 println!("Got a password {:?}", password); |
| 62 let status = pam_try!(get_url(url, &user, password.as_ref().map(|p|&**p)), PamResultCode::PAM_AUTH_ERR); | 57 let status = pam_try!( |
| 58 get_url(url, &user, password), | |
| 59 PamResultCode::PAM_AUTH_ERR | |
| 60 ); | |
| 63 | 61 |
| 64 if !status.is_success() { | 62 if !status.is_success() { |
| 65 println!("HTTP Error: {}", status); | 63 println!("HTTP Error: {}", status); |
| 66 return PamResultCode::PAM_AUTH_ERR; | 64 return PamResultCode::PAM_AUTH_ERR; |
| 67 } | 65 } |
| 68 | 66 |
| 69 PamResultCode::PAM_SUCCESS | 67 PamResultCode::PAM_SUCCESS |
| 70 } | 68 } |
| 71 | 69 |
| 72 fn sm_setcred(_pamh: &PamHandle, _args: Vec<&CStr>, _flags: PamFlag) -> PamResultCode { | 70 fn sm_setcred(_pamh: &mut PamHandle, _args: Vec<&CStr>, _flags: PamFlag) -> PamResultCode { |
| 73 println!("set credentials"); | 71 println!("set credentials"); |
| 74 PamResultCode::PAM_SUCCESS | 72 PamResultCode::PAM_SUCCESS |
| 75 } | 73 } |
| 76 | 74 |
| 77 fn acct_mgmt(_pamh: &PamHandle, _args: Vec<&CStr>, _flags: PamFlag) -> PamResultCode { | 75 fn acct_mgmt(_pamh: &mut PamHandle, _args: Vec<&CStr>, _flags: PamFlag) -> PamResultCode { |
| 78 println!("account management"); | 76 println!("account management"); |
| 79 PamResultCode::PAM_SUCCESS | 77 PamResultCode::PAM_SUCCESS |
| 80 } | 78 } |
| 81 } | 79 } |
| 82 | 80 |
| 83 | |
| 84 fn get_url(url: &str, user: &str, password: Option<&str>) -> reqwest::Result<StatusCode> { | 81 fn get_url(url: &str, user: &str, password: Option<&str>) -> reqwest::Result<StatusCode> { |
| 85 let client = Client::builder()?.timeout(Duration::from_secs(15)).build()?; | 82 let client = Client::builder().timeout(Duration::from_secs(15)).build()?; |
| 86 client.get(url)? | 83 client |
| 84 .get(url) | |
| 87 .basic_auth(user, password) | 85 .basic_auth(user, password) |
| 88 .send() | 86 .send() |
| 89 .map(|r| r.status()) | 87 .map(|r| r.status()) |
| 90 } | 88 } |
| 91 | |
| 92 |
