diff pam-http/src/lib.rs @ 20:734ca62159fb

Refactor exported endpoings into pam_hooks macro
author Anthony Nowell <anthony@algorithmia.com>
date Tue, 26 Sep 2017 01:51:39 -0600
parents d654aa0655e5
children 4263c1d83d5b
line wrap: on
line diff
--- a/pam-http/src/lib.rs	Mon Sep 25 23:42:35 2017 -0600
+++ b/pam-http/src/lib.rs	Tue Sep 26 01:51:39 2017 -0600
@@ -1,14 +1,15 @@
-extern crate pam;
+#[macro_use] 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::module::PamHandle;
+use pam::constants::{PamResultCode, PamFlag, PAM_PROMPT_ECHO_OFF};
 use pam::conv::PamConv;
+use pam::hooks::PamHooks;
 use std::collections::HashMap;
 use std::time::Duration;
 use reqwest::{Client, StatusCode};
+use std::ffi::CStr;
+
 
 macro_rules! pam_try {
     ($e:expr) => (
@@ -28,42 +29,59 @@
     );
 }
 
-// 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");
+struct PamHttp;
+pam_hooks!(PamHttp);
+
+impl PamHooks for PamHttp {
+    // This function performs the task of authenticating the user.
+    fn sm_authenticate(pamh: &PamHandle, args: Vec<&CStr>, _flags: PamFlag) -> 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 args: Vec<_> = args.iter().map(|s| s.to_string_lossy().to_owned() ).collect();
+        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 user = pam_try!(pamh.get_user(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 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 conv = match pamh.get_item::<PamConv>() {
+            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;
         }
-    };
-    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
     }
 
-    PamResultCode::PAM_SUCCESS
+    fn sm_setcred(_pamh: &PamHandle, _args: Vec<&CStr>, _flags: PamFlag) -> PamResultCode {
+        println!("set credentials");
+        PamResultCode::PAM_SUCCESS
+    }
+
+    fn acct_mgmt(_pamh: &PamHandle, _args: Vec<&CStr>, _flags: PamFlag) -> PamResultCode {
+        println!("account management");
+        PamResultCode::PAM_SUCCESS
+    }
 }
 
+
 fn get_url(url: &str, user: &str, password: Option<&str>) -> reqwest::Result<StatusCode> {
     let client = Client::builder()?.timeout(Duration::from_secs(15)).build()?;
     client.get(url)?
@@ -72,22 +90,4 @@
         .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
-}