diff pam/src/conv.rs @ 15:27730595f1ea

Adding pam-http module
author Anthony Nowell <anthony@algorithmia.com>
date Sun, 24 Sep 2017 00:22:29 -0600
parents
children 0ceeffe67ec4
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pam/src/conv.rs	Sun Sep 24 00:22:29 2017 -0600
@@ -0,0 +1,81 @@
+use libc::{c_char, c_int};
+use std::ptr;
+use std::ffi::{CStr, CString};
+
+use constants::PamResultCode;
+use constants::*;
+use module::{PamItem, PamResult};
+
+#[allow(missing_copy_implementations)]
+pub enum AppDataPtr {}
+
+#[repr(C)]
+struct PamMessage {
+    msg_style: PamMessageStyle,
+    msg: *const c_char,
+}
+
+#[repr(C)]
+struct PamResponse {
+    resp: *const c_char,
+    resp_retcode: AlwaysZero,
+}
+
+/// `PamConv` acts as a channel for communicating with user.
+///
+/// Communication is mediated by the pam client (the application that invoked
+/// pam).  Messages sent will be relayed to the user by the client, and response
+/// will be relayed back.
+#[repr(C)]
+pub struct PamConv {
+    conv: extern "C" fn(num_msg: c_int,
+                        pam_message: &&PamMessage,
+                        pam_response: &mut *const PamResponse,
+                        appdata_ptr: *const AppDataPtr)
+                        -> PamResultCode,
+    appdata_ptr: *const AppDataPtr,
+}
+
+impl PamConv {
+    /// Sends a message to the pam client.
+    ///
+    /// This will typically result in the user seeing a message or a prompt.
+    /// There are several message styles available:
+    ///
+    /// - PAM_PROMPT_ECHO_OFF
+    /// - PAM_PROMPT_ECHO_ON
+    /// - PAM_ERROR_MSG
+    /// - PAM_TEXT_INFO
+    /// - PAM_RADIO_TYPE
+    /// - PAM_BINARY_PROMPT
+    ///
+    /// Note that the user experience will depend on how the client implements
+    /// these message styles - and not all applications implement all message
+    /// styles.
+    pub fn send(&self, style: PamMessageStyle, msg: &str) -> PamResult<Option<String>> {
+        let mut resp_ptr: *const PamResponse = ptr::null();
+        let msg = PamMessage {
+            msg_style: style,
+            msg: CString::new(msg).unwrap().as_ptr(),
+        };
+
+        let ret = (self.conv)(1, &&msg, &mut resp_ptr, self.appdata_ptr);
+
+        if PamResultCode::PAM_SUCCESS == ret {
+            if resp_ptr.is_null() {
+                Ok(None)
+            } else {
+                let bytes = unsafe { CStr::from_ptr((*resp_ptr).resp).to_bytes() };
+                Ok(String::from_utf8(bytes.to_vec()).ok())
+            }
+        } else {
+            Err(ret)
+        }
+    }
+}
+
+impl PamItem for PamConv {
+    fn item_type() -> PamItemType {
+        PAM_CONV
+    }
+}