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