Mercurial > crates > nonstick
comparison src/libpam/module.rs @ 166:2f5913131295
Separate flag/action flags into flags and action.
This also individualizes the type of flag for each PAM function,
so that you can only call a function with the right flags and values.
| author | Paul Fisher <paul@pfish.zone> |
|---|---|
| date | Tue, 15 Jul 2025 00:32:24 -0400 |
| parents | 1bc52025156b |
| children | e27c5c667a5a |
comparison
equal
deleted
inserted
replaced
| 165:c4b1e280463c | 166:2f5913131295 |
|---|---|
| 9 /// Here is full example of a PAM module that would authenticate | 9 /// Here is full example of a PAM module that would authenticate |
| 10 /// and authorize everybody: | 10 /// and authorize everybody: |
| 11 /// | 11 /// |
| 12 /// ```no_run | 12 /// ```no_run |
| 13 /// use nonstick::{ | 13 /// use nonstick::{ |
| 14 /// pam_hooks, ConversationAdapter, Flags, LibPamTransaction, ModuleClient, PamModule, | 14 /// pam_hooks, ConversationAdapter, AuthnFlags, LibPamTransaction, ModuleClient, PamModule, |
| 15 /// Result as PamResult, | 15 /// Result as PamResult, |
| 16 /// }; | 16 /// }; |
| 17 /// use std::ffi::CStr; | 17 /// use std::ffi::CStr; |
| 18 /// # fn main() {} | 18 /// # fn main() {} |
| 19 /// | 19 /// |
| 20 /// struct MyPamModule; | 20 /// struct MyPamModule; |
| 21 /// pam_hooks!(MyPamModule); | 21 /// pam_hooks!(MyPamModule); |
| 22 /// | 22 /// |
| 23 /// impl<T: ModuleClient> PamModule<T> for MyPamModule { | 23 /// impl<T: ModuleClient> PamModule<T> for MyPamModule { |
| 24 /// fn authenticate(handle: &mut T, args: Vec<&CStr>, flags: Flags) -> PamResult<()> { | 24 /// fn authenticate(handle: &mut T, args: Vec<&CStr>, flags: AuthnFlags) -> PamResult<()> { |
| 25 /// let password = handle.authtok(Some("what's your password?".as_ref()))?; | 25 /// let password = handle.authtok(Some("what's your password?".as_ref()))?; |
| 26 /// let response = | 26 /// let response = |
| 27 /// format!("If you say your password is {password:?}, who am I to disagree?"); | 27 /// format!("If you say your password is {password:?}, who am I to disagree?"); |
| 28 /// handle.info_msg(&response); | 28 /// handle.info_msg(&response); |
| 29 /// Ok(()) | 29 /// Ok(()) |
| 30 /// } | 30 /// } |
| 31 /// | 31 /// |
| 32 /// fn account_management(handle: &mut T, args: Vec<&CStr>, flags: Flags) -> PamResult<()> { | 32 /// fn account_management(handle: &mut T, args: Vec<&CStr>, flags: AuthnFlags) -> PamResult<()> { |
| 33 /// let username = handle.username(None)?; | 33 /// let username = handle.username(None)?; |
| 34 /// let response = format!("Hello {username:?}! I trust you unconditionally."); | 34 /// let response = format!("Hello {username:?}! I trust you unconditionally."); |
| 35 /// handle.info_msg(&response); | 35 /// handle.info_msg(&response); |
| 36 /// Ok(()) | 36 /// Ok(()) |
| 37 /// } | 37 /// } |
| 40 #[macro_export] | 40 #[macro_export] |
| 41 macro_rules! pam_hooks { | 41 macro_rules! pam_hooks { |
| 42 ($ident:ident) => { | 42 ($ident:ident) => { |
| 43 mod _pam_hooks_scope { | 43 mod _pam_hooks_scope { |
| 44 use std::ffi::{c_char, c_int, c_void, CStr}; | 44 use std::ffi::{c_char, c_int, c_void, CStr}; |
| 45 use $crate::{ErrorCode, Flags, LibPamHandle, PamModule}; | 45 use $crate::{ |
| 46 AuthnFlags, AuthtokAction, BaseFlags, CredAction, ErrorCode, LibPamHandle, | |
| 47 PamModule, | |
| 48 }; | |
| 49 | |
| 50 macro_rules! handle { | |
| 51 ($pamh:ident) => { | |
| 52 match unsafe { $pamh.cast::<LibPamHandle>().as_mut() } { | |
| 53 Some(handle) => handle, | |
| 54 None => return ErrorCode::Ignore.into(), | |
| 55 } | |
| 56 }; | |
| 57 } | |
| 46 | 58 |
| 47 #[no_mangle] | 59 #[no_mangle] |
| 48 extern "C" fn pam_sm_acct_mgmt( | 60 extern "C" fn pam_sm_acct_mgmt( |
| 49 pamh: *mut c_void, | 61 pamh: *mut c_void, |
| 50 flags: Flags, | 62 flags: AuthnFlags, |
| 51 argc: c_int, | 63 argc: c_int, |
| 52 argv: *const *const c_char, | 64 argv: *const *const c_char, |
| 53 ) -> c_int { | 65 ) -> c_int { |
| 54 if let Some(handle) = unsafe { pamh.cast::<LibPamHandle>().as_mut() } { | 66 let handle = handle!(pamh); |
| 55 let args = extract_argv(argc, argv); | 67 let args = extract_argv(argc, argv); |
| 56 ErrorCode::result_to_c(super::$ident::account_management(handle, args, flags)) | 68 ErrorCode::result_to_c(super::$ident::account_management(handle, args, flags)) |
| 57 } else { | |
| 58 ErrorCode::Ignore as c_int | |
| 59 } | |
| 60 } | 69 } |
| 61 | 70 |
| 62 #[no_mangle] | 71 #[no_mangle] |
| 63 extern "C" fn pam_sm_authenticate( | 72 extern "C" fn pam_sm_authenticate( |
| 64 pamh: *mut c_void, | 73 pamh: *mut c_void, |
| 65 flags: Flags, | 74 flags: AuthnFlags, |
| 66 argc: c_int, | 75 argc: c_int, |
| 67 argv: *const *const c_char, | 76 argv: *const *const c_char, |
| 68 ) -> c_int { | 77 ) -> c_int { |
| 69 if let Some(handle) = unsafe { pamh.cast::<LibPamHandle>().as_mut() } { | 78 let handle = handle!(pamh); |
| 70 let args = extract_argv(argc, argv); | 79 let args = extract_argv(argc, argv); |
| 71 ErrorCode::result_to_c(super::$ident::authenticate(handle, args, flags)) | 80 ErrorCode::result_to_c(super::$ident::authenticate(handle, args, flags)) |
| 72 } else { | |
| 73 ErrorCode::Ignore as c_int | |
| 74 } | |
| 75 } | 81 } |
| 76 | 82 |
| 77 #[no_mangle] | 83 #[no_mangle] |
| 78 extern "C" fn pam_sm_chauthtok( | 84 extern "C" fn pam_sm_chauthtok( |
| 79 pamh: *mut c_void, | 85 pamh: *mut c_void, |
| 80 flags: Flags, | 86 flags: c_int, |
| 81 argc: c_int, | 87 argc: c_int, |
| 82 argv: *const *const c_char, | 88 argv: *const *const c_char, |
| 83 ) -> c_int { | 89 ) -> c_int { |
| 84 if let Some(handle) = unsafe { pamh.cast::<LibPamHandle>().as_mut() } { | 90 let handle = handle!(pamh); |
| 85 let args = extract_argv(argc, argv); | 91 let (action, flags) = match AuthtokAction::extract(flags) { |
| 86 ErrorCode::result_to_c(super::$ident::change_authtok(handle, args, flags)) | 92 Ok(val) => val, |
| 87 } else { | 93 Err(e) => return e.into(), |
| 88 ErrorCode::Ignore as c_int | 94 }; |
| 89 } | 95 let args = extract_argv(argc, argv); |
| 96 ErrorCode::result_to_c(super::$ident::change_authtok(handle, args, action, flags)) | |
| 90 } | 97 } |
| 91 | 98 |
| 92 #[no_mangle] | 99 #[no_mangle] |
| 93 extern "C" fn pam_sm_close_session( | 100 extern "C" fn pam_sm_close_session( |
| 94 pamh: *mut c_void, | 101 pamh: *mut c_void, |
| 95 flags: Flags, | 102 flags: BaseFlags, |
| 96 argc: c_int, | 103 argc: c_int, |
| 97 argv: *const *const c_char, | 104 argv: *const *const c_char, |
| 98 ) -> c_int { | 105 ) -> c_int { |
| 99 if let Some(handle) = unsafe { pamh.cast::<LibPamHandle>().as_mut() } { | 106 let handle = handle!(pamh); |
| 100 let args = extract_argv(argc, argv); | 107 let args = extract_argv(argc, argv); |
| 101 ErrorCode::result_to_c(super::$ident::close_session(handle, args, flags)) | 108 ErrorCode::result_to_c(super::$ident::close_session(handle, args, flags)) |
| 102 } else { | |
| 103 ErrorCode::Ignore as c_int | |
| 104 } | |
| 105 } | 109 } |
| 106 | 110 |
| 107 #[no_mangle] | 111 #[no_mangle] |
| 108 extern "C" fn pam_sm_open_session( | 112 extern "C" fn pam_sm_open_session( |
| 109 pamh: *mut c_void, | 113 pamh: *mut c_void, |
| 110 flags: Flags, | 114 flags: BaseFlags, |
| 111 argc: c_int, | 115 argc: c_int, |
| 112 argv: *const *const c_char, | 116 argv: *const *const c_char, |
| 113 ) -> c_int { | 117 ) -> c_int { |
| 118 let handle = handle!(pamh); | |
| 114 let args = extract_argv(argc, argv); | 119 let args = extract_argv(argc, argv); |
| 115 if let Some(handle) = unsafe { pamh.cast::<LibPamHandle>().as_mut() } { | 120 ErrorCode::result_to_c(super::$ident::open_session(handle, args, flags)) |
| 116 ErrorCode::result_to_c(super::$ident::open_session(handle, args, flags)) | |
| 117 } else { | |
| 118 ErrorCode::Ignore as c_int | |
| 119 } | |
| 120 } | 121 } |
| 121 | 122 |
| 122 #[no_mangle] | 123 #[no_mangle] |
| 123 extern "C" fn pam_sm_setcred( | 124 extern "C" fn pam_sm_setcred( |
| 124 pamh: *mut c_void, | 125 pamh: *mut c_void, |
| 125 flags: Flags, | 126 flags: c_int, |
| 126 argc: c_int, | 127 argc: c_int, |
| 127 argv: *const *const c_char, | 128 argv: *const *const c_char, |
| 128 ) -> c_int { | 129 ) -> c_int { |
| 130 let handle = handle!(pamh); | |
| 131 let (action, flags) = match CredAction::extract(flags) { | |
| 132 Ok(val) => val, | |
| 133 Err(e) => return e.into(), | |
| 134 }; | |
| 129 let args = extract_argv(argc, argv); | 135 let args = extract_argv(argc, argv); |
| 130 if let Some(handle) = unsafe { pamh.cast::<LibPamHandle>().as_mut() } { | 136 ErrorCode::result_to_c(super::$ident::set_credentials(handle, args, action, flags)) |
| 131 ErrorCode::result_to_c(super::$ident::set_credentials(handle, args, flags)) | |
| 132 } else { | |
| 133 ErrorCode::Ignore as c_int | |
| 134 } | |
| 135 } | 137 } |
| 136 | 138 |
| 137 /// Turns `argc`/`argv` into a [Vec] of [CStr]s. | 139 /// Turns `argc`/`argv` into a [Vec] of [CStr]s. |
| 138 /// | 140 /// |
| 139 /// # Safety | 141 /// # Safety |
