Mercurial > crates > nonstick
comparison pam-http/src/lib.rs @ 34:ec70822cbdef
Overhaul
author | Andy Caldwell <andrew.caldwell@metaswitch.com> |
---|---|
date | Sun, 24 Apr 2022 03:42:11 +0100 |
parents | 4263c1d83d5b |
children |
comparison
equal
deleted
inserted
replaced
32:ea5f195f035f | 34:ec70822cbdef |
---|---|
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 |