Mercurial > crates > nonstick
diff pam/src/module.rs @ 19:d654aa0655e5
Making PamHandle a struct with methods
author | Anthony Nowell <anthony@algorithmia.com> |
---|---|
date | Mon, 25 Sep 2017 23:42:35 -0600 |
parents | 27730595f1ea |
children | 4263c1d83d5b |
line wrap: on
line diff
--- 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