Mercurial > crates > nonstick
changeset 19:d654aa0655e5
Making PamHandle a struct with methods
author | Anthony Nowell <anthony@algorithmia.com> |
---|---|
date | Mon, 25 Sep 2017 23:42:35 -0600 |
parents | 0f5e9e8963ae |
children | 734ca62159fb |
files | pam-http/src/lib.rs pam-sober/src/ffi.rs pam-sober/src/lib.rs pam/src/module.rs |
diffstat | 4 files changed, 125 insertions(+), 122 deletions(-) [+] |
line wrap: on
line diff
--- a/pam-http/src/lib.rs Sun Sep 24 22:11:05 2017 -0600 +++ b/pam-http/src/lib.rs Mon Sep 25 23:42:35 2017 -0600 @@ -65,7 +65,7 @@ } fn get_url(url: &str, user: &str, password: Option<&str>) -> reqwest::Result<StatusCode> { - let client = Client::builder()?.timeout(Duration::from_secs(5)).build()?; + let client = Client::builder()?.timeout(Duration::from_secs(15)).build()?; client.get(url)? .basic_auth(user, password) .send()
--- a/pam-sober/src/ffi.rs Sun Sep 24 22:11:05 2017 -0600 +++ b/pam-sober/src/ffi.rs Mon Sep 25 23:42:35 2017 -0600 @@ -1,4 +1,4 @@ -use pam::module::{PamHandleT}; +use pam::module::{PamHandle}; use pam::constants::{PamFlag, PamResultCode, PAM_SILENT}; use std::ffi::CStr; use std::os::raw::{c_char, c_int}; @@ -17,7 +17,7 @@ #[no_mangle] pub extern "C" fn pam_sm_acct_mgmt( - pamh: &PamHandleT, + pamh: &PamHandle, flags: PamFlag, argc: c_int, argv: *const *const c_char, @@ -29,7 +29,7 @@ #[no_mangle] pub extern "C" fn pam_sm_authenticate( - pamh: &PamHandleT, + pamh: &PamHandle, flags: PamFlag, argc: c_int, argv: *const *const c_char, @@ -41,7 +41,7 @@ #[no_mangle] pub extern "C" fn pam_sm_chauthtok( - _: &PamHandleT, + _: &PamHandle, _: PamFlag, _: c_int, _: *const *const c_char, @@ -51,7 +51,7 @@ #[no_mangle] pub extern "C" fn pam_sm_close_session( - _: &PamHandleT, + _: &PamHandle, _: PamFlag, _: c_int, _: *const *const c_char, @@ -61,7 +61,7 @@ #[no_mangle] pub extern "C" fn pam_sm_open_session( - _: &PamHandleT, + _: &PamHandle, _: PamFlag, _: c_int, _: *const *const c_char, @@ -71,7 +71,7 @@ #[no_mangle] pub extern "C" fn pam_sm_setcred( - pamh: &PamHandleT, + pamh: &PamHandle, flags: PamFlag, argc: c_int, argv: *const *const c_char,
--- a/pam-sober/src/lib.rs Sun Sep 24 22:11:05 2017 -0600 +++ b/pam-sober/src/lib.rs Mon Sep 25 23:42:35 2017 -0600 @@ -3,11 +3,9 @@ pub mod ffi; -use pam::module::{PamHandleT, get_item, get_user}; +use pam::module::PamHandle; use pam::constants::{PamResultCode, PAM_PROMPT_ECHO_OFF}; use pam::conv::PamConv; -use std::collections::HashMap; -use std::time::Duration; use rand::Rng; use std::str::FromStr; @@ -30,7 +28,7 @@ } // This function performs the task of authenticating the user. -pub fn sm_authenticate(pamh: &PamHandleT, args: Vec<String>, silent: bool) -> PamResultCode { +pub fn sm_authenticate(pamh: &PamHandle, args: Vec<String>, silent: bool) -> PamResultCode { println!("Let's auth over HTTP"); /* TODO: use args to change difficulty ;-) @@ -41,9 +39,9 @@ */ // TODO: maybe we can change difficulty base on user? - // let user = pam_try!(get_user(&pamh, None)); + // let user = pam_try!(pam.get_user(None)); - let conv = match get_item::<PamConv>(&pamh) { + let conv = match pamh.get_item::<PamConv>() { Ok(conv) => conv, Err(err) => { println!("Couldn't get pam_conv"); @@ -74,7 +72,7 @@ // 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 { +pub fn sm_setcred(_pamh: &PamHandle, _args: Vec<String>, _silent: bool) -> PamResultCode { println!("set credentials"); PamResultCode::PAM_SUCCESS } @@ -84,7 +82,7 @@ // 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 { +pub fn acct_mgmt(_pamh: &PamHandle, _args: Vec<String>, _silent: bool) -> PamResultCode { println!("account management"); PamResultCode::PAM_SUCCESS }
--- a/pam/src/module.rs Sun Sep 24 22:11:05 2017 -0600 +++ b/pam/src/module.rs Mon Sep 25 23:42:35 2017 -0600 @@ -12,7 +12,7 @@ /// Such a call provides a pam handle pointer. The same pointer should be given /// as an argument when making API calls. #[allow(missing_copy_implementations)] -pub enum PamHandleT {} +pub enum PamHandle {} #[allow(missing_copy_implementations)] enum PamItemT {} @@ -22,35 +22,43 @@ #[link(name = "pam")] extern "C" { - fn pam_get_data(pamh: *const PamHandleT, + fn pam_get_data(pamh: *const PamHandle, module_data_name: *const c_char, data: &mut *const PamDataT) -> PamResultCode; - fn pam_set_data(pamh: *const PamHandleT, + fn pam_set_data(pamh: *const PamHandle, module_data_name: *const c_char, data: Box<PamDataT>, - cleanup: extern "C" fn(pamh: *const PamHandleT, + cleanup: extern "C" fn(pamh: *const PamHandle, data: Box<PamDataT>, error_status: PamResultCode)) -> PamResultCode; - fn pam_get_item(pamh: *const PamHandleT, + fn pam_get_item(pamh: *const PamHandle, item_type: PamItemType, item: &mut *const PamItemT) -> PamResultCode; - fn pam_set_item(pamh: *mut PamHandleT, + fn pam_set_item(pamh: *mut PamHandle, item_type: PamItemType, item: &PamItemT) -> PamResultCode; - fn pam_get_user(pamh: *const PamHandleT, + fn pam_get_user(pamh: *const PamHandle, user: &*mut c_char, prompt: *const c_char) -> PamResultCode; } +#[no_mangle] +pub extern "C" fn cleanup<T>(_: *const PamHandle, c_data: Box<PamDataT>, _: PamResultCode) { + unsafe { + let data: Box<T> = mem::transmute(c_data); + mem::drop(data); + } +} + pub type PamResult<T> = Result<T, PamResultCode>; /// Type-level mapping for safely retrieving values with `get_item`. @@ -67,113 +75,110 @@ fn item_type() -> PamItemType; } -/// Gets some value, identified by `key`, that has been set by the module -/// previously. -/// -/// See `pam_get_data` in -/// http://www.linux-pam.org/Linux-PAM-html/mwg-expected-by-module-item.html -pub unsafe fn get_data<'a, T>(pamh: &'a PamHandleT, key: &str) -> PamResult<&'a T> { - let c_key = CString::new(key).unwrap().as_ptr(); - let mut ptr: *const PamDataT = ptr::null(); - let res = pam_get_data(pamh, c_key, &mut ptr); - if PamResultCode::PAM_SUCCESS == res && !ptr.is_null() { - let typed_ptr: *const T = mem::transmute(ptr); - let data: &T = &*typed_ptr; - Ok(data) - } else { - Err(res) + +impl PamHandle { + /// Gets some value, identified by `key`, that has been set by the module + /// previously. + /// + /// See `pam_get_data` in + /// http://www.linux-pam.org/Linux-PAM-html/mwg-expected-by-module-item.html + pub unsafe fn get_data<'a, T>(&'a self, key: &str) -> PamResult<&'a T> { + let c_key = CString::new(key).unwrap().as_ptr(); + let mut ptr: *const PamDataT = ptr::null(); + let res = pam_get_data(self, c_key, &mut ptr); + if PamResultCode::PAM_SUCCESS == res && !ptr.is_null() { + let typed_ptr: *const T = mem::transmute(ptr); + let data: &T = &*typed_ptr; + Ok(data) + } else { + Err(res) + } } -} -/// Stores a value that can be retrieved later with `get_data`. The value lives -/// as long as the current pam cycle. -/// -/// See `pam_set_data` in -/// http://www.linux-pam.org/Linux-PAM-html/mwg-expected-by-module-item.html -pub fn set_data<T>(pamh: &PamHandleT, key: &str, data: Box<T>) -> PamResult<()> { - let c_key = CString::new(key).unwrap().as_ptr(); - let res = unsafe { - let c_data: Box<PamDataT> = mem::transmute(data); - pam_set_data(pamh, c_key, c_data, cleanup::<T>) - }; - if PamResultCode::PAM_SUCCESS == res { - Ok(()) - } else { - Err(res) + /// Stores a value that can be retrieved later with `get_data`. The value lives + /// as long as the current pam cycle. + /// + /// See `pam_set_data` in + /// http://www.linux-pam.org/Linux-PAM-html/mwg-expected-by-module-item.html + pub fn set_data<T>(&self, key: &str, data: Box<T>) -> PamResult<()> { + let c_key = CString::new(key).unwrap().as_ptr(); + let res = unsafe { + let c_data: Box<PamDataT> = mem::transmute(data); + pam_set_data(self, c_key, c_data, cleanup::<T>) + }; + if PamResultCode::PAM_SUCCESS == res { + Ok(()) + } else { + Err(res) + } } -} -#[no_mangle] -pub extern "C" fn cleanup<T>(_: *const PamHandleT, c_data: Box<PamDataT>, _: PamResultCode) { - unsafe { - let data: Box<T> = mem::transmute(c_data); - mem::drop(data); - } -} + -/// Retrieves a value that has been set, possibly by the pam client. This is -/// particularly useful for getting a `PamConv` reference. -/// -/// See `pam_get_item` in -/// http://www.linux-pam.org/Linux-PAM-html/mwg-expected-by-module-item.html -pub fn get_item<'a, T: PamItem>(pamh: &'a PamHandleT) -> PamResult<&'a T> { - let mut ptr: *const PamItemT = ptr::null(); - let (res, item) = unsafe { - let r = pam_get_item(pamh, T::item_type(), &mut ptr); - let typed_ptr: *const T = mem::transmute(ptr); - let t: &T = &*typed_ptr; - (r, t) - }; - if PamResultCode::PAM_SUCCESS == res { - Ok(item) - } else { - Err(res) + /// Retrieves a value that has been set, possibly by the pam client. This is + /// particularly useful for getting a `PamConv` reference. + /// + /// See `pam_get_item` in + /// http://www.linux-pam.org/Linux-PAM-html/mwg-expected-by-module-item.html + pub fn get_item<'a, T: PamItem>(&self) -> PamResult<&'a T> { + let mut ptr: *const PamItemT = ptr::null(); + let (res, item) = unsafe { + let r = pam_get_item(self, T::item_type(), &mut ptr); + let typed_ptr: *const T = mem::transmute(ptr); + let t: &T = &*typed_ptr; + (r, t) + }; + if PamResultCode::PAM_SUCCESS == res { + Ok(item) + } else { + Err(res) + } } -} -/// Sets a value in the pam context. The value can be retrieved using -/// `get_item`. -/// -/// Note that all items are strings, except `PAM_CONV` and `PAM_FAIL_DELAY`. -/// -/// See `pam_set_item` in -/// http://www.linux-pam.org/Linux-PAM-html/mwg-expected-by-module-item.html -pub fn set_item_str<'a, T: PamItem>(pamh: &'a mut PamHandleT, item: &str) -> PamResult<()> { - let c_item = CString::new(item).unwrap().as_ptr(); + /// Sets a value in the pam context. The value can be retrieved using + /// `get_item`. + /// + /// Note that all items are strings, except `PAM_CONV` and `PAM_FAIL_DELAY`. + /// + /// See `pam_set_item` in + /// http://www.linux-pam.org/Linux-PAM-html/mwg-expected-by-module-item.html + pub fn set_item_str<T: PamItem>(&mut self, item: &str) -> PamResult<()> { + let c_item = CString::new(item).unwrap().as_ptr(); + + let res = unsafe { + pam_set_item(self, + T::item_type(), - let res = unsafe { - pam_set_item(pamh, - T::item_type(), - - // unwrapping is okay here, as c_item will not be a NULL - // pointer - (c_item as *const PamItemT).as_ref().unwrap()) - }; - if PamResultCode::PAM_SUCCESS == res { - Ok(()) - } else { - Err(res) + // unwrapping is okay here, as c_item will not be a NULL + // pointer + (c_item as *const PamItemT).as_ref().unwrap()) + }; + if PamResultCode::PAM_SUCCESS == res { + Ok(()) + } else { + Err(res) + } } -} -/// Retrieves the name of the user who is authenticating or logging in. -/// -/// This is really a specialization of `get_item`. -/// -/// See `pam_get_user` in -/// http://www.linux-pam.org/Linux-PAM-html/mwg-expected-by-module-item.html -pub fn get_user<'a>(pamh: &'a PamHandleT, prompt: Option<&str>) -> PamResult<String> { - let ptr: *mut c_char = ptr::null_mut(); - let c_prompt = match prompt { - Some(p) => CString::new(p).unwrap().as_ptr(), - None => ptr::null(), - }; - let res = unsafe { pam_get_user(pamh, &ptr, c_prompt) }; - if PamResultCode::PAM_SUCCESS == res && !ptr.is_null() { - let const_ptr = ptr as *const c_char; - let bytes = unsafe { CStr::from_ptr(const_ptr).to_bytes() }; - String::from_utf8(bytes.to_vec()).map_err(|_| PamResultCode::PAM_CONV_ERR) - } else { - Err(res) + /// Retrieves the name of the user who is authenticating or logging in. + /// + /// This is really a specialization of `get_item`. + /// + /// See `pam_get_user` in + /// http://www.linux-pam.org/Linux-PAM-html/mwg-expected-by-module-item.html + pub fn get_user(&self, prompt: Option<&str>) -> PamResult<String> { + let ptr: *mut c_char = ptr::null_mut(); + let c_prompt = match prompt { + Some(p) => CString::new(p).unwrap().as_ptr(), + None => ptr::null(), + }; + let res = unsafe { pam_get_user(self, &ptr, c_prompt) }; + if PamResultCode::PAM_SUCCESS == res && !ptr.is_null() { + let const_ptr = ptr as *const c_char; + let bytes = unsafe { CStr::from_ptr(const_ptr).to_bytes() }; + String::from_utf8(bytes.to_vec()).map_err(|_| PamResultCode::PAM_CONV_ERR) + } else { + Err(res) + } } -} +} \ No newline at end of file