comparison src/libpam/module.rs @ 173:46e8ce5cd5d1

Miscellaneous doc and code cleanups.
author Paul Fisher <paul@pfish.zone>
date Tue, 29 Jul 2025 16:52:32 -0400
parents 6727cbe56f4a
children 9e4ce1631bd3
comparison
equal deleted inserted replaced
172:6727cbe56f4a 173:46e8ce5cd5d1
4 use crate::{AuthnFlags, AuthtokAction, BaseFlags, CredAction}; 4 use crate::{AuthnFlags, AuthtokAction, BaseFlags, CredAction};
5 use std::ffi::{c_char, c_int, c_void, CStr}; 5 use std::ffi::{c_char, c_int, c_void, CStr};
6 6
7 /// Generates the dynamic library entry points for a PAM module 7 /// Generates the dynamic library entry points for a PAM module
8 /// 8 ///
9 /// Calling `pam_hooks!(SomeType)` on a type that implements 9 /// Calling `pam_export!(SomeType)` on a type that implements
10 /// [`PamModule`] will generate the exported 10 /// [`PamModule`] will generate the exported
11 /// `extern "C"` functions that PAM uses to call into your module. 11 /// `extern "C"` functions that PAM uses to call into your module.
12 /// 12 ///
13 /// ## Examples: 13 /// ## Examples:
14 /// 14 ///
15 /// Here is full example of a PAM module that would authenticate 15 /// Here is full example of a PAM module that would authenticate
16 /// and authorize everybody: 16 /// and authorize everybody:
17 /// 17 ///
18 /// ```no_run 18 /// ```no_run
19 /// use nonstick::{ 19 /// use nonstick::{
20 /// pam_hooks, ConversationAdapter, AuthnFlags, LibPamTransaction, ModuleClient, PamModule, 20 /// pam_export, ConversationAdapter, AuthnFlags, LibPamTransaction, ModuleClient, PamModule,
21 /// Result as PamResult, 21 /// Result as PamResult,
22 /// }; 22 /// };
23 /// use std::ffi::CStr; 23 /// use std::ffi::CStr;
24 /// # fn main() {} 24 /// # fn main() {}
25 /// 25 ///
26 /// struct MyPamModule; 26 /// struct MyPamModule;
27 /// pam_hooks!(MyPamModule); 27 /// pam_export!(MyPamModule);
28 /// 28 ///
29 /// impl<T: ModuleClient> PamModule<T> for MyPamModule { 29 /// impl<T: ModuleClient> PamModule<T> for MyPamModule {
30 /// fn authenticate(handle: &mut T, args: Vec<&CStr>, flags: AuthnFlags) -> PamResult<()> { 30 /// fn authenticate(handle: &mut T, args: Vec<&CStr>, flags: AuthnFlags) -> PamResult<()> {
31 /// let password = handle.authtok(Some("what's your password?".as_ref()))?; 31 /// let password = handle.authtok(Some("what's your password?".as_ref()))?;
32 /// let response = 32 /// let response =
42 /// Ok(()) 42 /// Ok(())
43 /// } 43 /// }
44 /// } 44 /// }
45 /// ``` 45 /// ```
46 #[macro_export] 46 #[macro_export]
47 macro_rules! pam_hooks { 47 macro_rules! pam_export {
48 ($ident:ident) => { 48 ($ident:ident) => {
49 mod _pam_hooks_scope { 49 mod __pam_export_scope {
50 use std::ffi::{c_char, c_int, c_void}; 50 use std::ffi::{c_char, c_int, c_void};
51 use $crate::constants::{RawFlags, ReturnCode}; 51 use $crate::constants::{RawFlags, ReturnCode};
52 use $crate::ModuleExporter; 52 use $crate::libpam::module;
53 53
54 macro_rules! export { 54 macro_rules! export {
55 ($func:ident) => { 55 ($func:ident) => {
56 #[no_mangle] 56 #[no_mangle]
57 unsafe extern "C" fn $func( 57 unsafe extern "C" fn $func(
59 flags: RawFlags, 59 flags: RawFlags,
60 argc: c_int, 60 argc: c_int,
61 argv: *const *const c_char, 61 argv: *const *const c_char,
62 ) -> c_int { 62 ) -> c_int {
63 let ret: ReturnCode = 63 let ret: ReturnCode =
64 ModuleExporter::$func::<super::$ident>(pamh, flags, argc, argv).into(); 64 module::$func::<super::$ident>(pamh, flags, argc, argv).into();
65 ret.into() 65 ret.into()
66 } 66 }
67 }; 67 };
68 } 68 }
69 69
76 } 76 }
77 }; 77 };
78 } 78 }
79 79
80 #[doc(hidden)] 80 #[doc(hidden)]
81 pub struct ModuleExporter; 81 pub unsafe fn pam_sm_acct_mgmt<M: PamModule<LibPamHandle>>(
82 pamh: *mut c_void,
83 flags: RawFlags,
84 argc: c_int,
85 argv: *const *const c_char,
86 ) -> Result<()> {
87 let handle = wrap(pamh)?;
88 let args = extract_argv(argc, argv);
89 M::account_management(handle, args, AuthnFlags::from(flags))
90 }
82 91
83 // All of the below are only intended to be called directly from C. 92 #[doc(hidden)]
84 #[allow(clippy::missing_safety_doc)] 93 pub unsafe fn pam_sm_authenticate<M: PamModule<LibPamHandle>>(
85 impl ModuleExporter { 94 pamh: *mut c_void,
86 pub unsafe fn pam_sm_acct_mgmt<M: PamModule<LibPamHandle>>( 95 flags: RawFlags,
87 pamh: *mut c_void, 96 argc: c_int,
88 flags: RawFlags, 97 argv: *const *const c_char,
89 argc: c_int, 98 ) -> Result<()> {
90 argv: *const *const c_char, 99 let handle = wrap(pamh)?;
91 ) -> Result<()> { 100 let args = extract_argv(argc, argv);
92 let handle = wrap(pamh)?; 101 M::authenticate(handle, args, AuthnFlags::from(flags))
93 let args = extract_argv(argc, argv); 102 }
94 M::account_management(handle, args, AuthnFlags::from(flags))
95 }
96 103
97 pub unsafe fn pam_sm_authenticate<M: PamModule<LibPamHandle>>( 104 #[doc(hidden)]
98 pamh: *mut c_void, 105 pub unsafe fn pam_sm_chauthtok<M: PamModule<LibPamHandle>>(
99 flags: RawFlags, 106 pamh: *mut c_void,
100 argc: c_int, 107 flags: RawFlags,
101 argv: *const *const c_char, 108 argc: c_int,
102 ) -> Result<()> { 109 argv: *const *const c_char,
103 let handle = wrap(pamh)?; 110 ) -> Result<()> {
104 let args = extract_argv(argc, argv); 111 let handle = wrap(pamh)?;
105 M::authenticate(handle, args, AuthnFlags::from(flags)) 112 let (action, flags) = AuthtokAction::extract(flags)?;
106 } 113 let args = extract_argv(argc, argv);
114 M::change_authtok(handle, args, action, flags)
115 }
107 116
108 pub unsafe fn pam_sm_chauthtok<M: PamModule<LibPamHandle>>( 117 #[doc(hidden)]
109 pamh: *mut c_void, 118 pub unsafe fn pam_sm_close_session<M: PamModule<LibPamHandle>>(
110 flags: RawFlags, 119 pamh: *mut c_void,
111 argc: c_int, 120 flags: RawFlags,
112 argv: *const *const c_char, 121 argc: c_int,
113 ) -> Result<()> { 122 argv: *const *const c_char,
114 let handle = wrap(pamh)?; 123 ) -> Result<()> {
115 let (action, flags) = AuthtokAction::extract(flags)?; 124 let handle = wrap(pamh)?;
116 let args = extract_argv(argc, argv); 125 let args = extract_argv(argc, argv);
117 M::change_authtok(handle, args, action, flags) 126 M::close_session(handle, args, BaseFlags::from(flags))
118 } 127 }
119 128
120 pub unsafe fn pam_sm_close_session<M: PamModule<LibPamHandle>>( 129 #[doc(hidden)]
121 pamh: *mut c_void, 130 pub unsafe fn pam_sm_open_session<M: PamModule<LibPamHandle>>(
122 flags: RawFlags, 131 pamh: *mut c_void,
123 argc: c_int, 132 flags: RawFlags,
124 argv: *const *const c_char, 133 argc: c_int,
125 ) -> Result<()> { 134 argv: *const *const c_char,
126 let handle = wrap(pamh)?; 135 ) -> Result<()> {
127 let args = extract_argv(argc, argv); 136 let handle = wrap(pamh)?;
128 M::close_session(handle, args, BaseFlags::from(flags)) 137 let args = extract_argv(argc, argv);
129 } 138 M::open_session(handle, args, BaseFlags::from(flags))
139 }
130 140
131 pub unsafe fn pam_sm_open_session<M: PamModule<LibPamHandle>>( 141 #[doc(hidden)]
132 pamh: *mut c_void, 142 pub unsafe fn pam_sm_setcred<M: PamModule<LibPamHandle>>(
133 flags: RawFlags, 143 pamh: *mut c_void,
134 argc: c_int, 144 flags: RawFlags,
135 argv: *const *const c_char, 145 argc: c_int,
136 ) -> Result<()> { 146 argv: *const *const c_char,
137 let handle = wrap(pamh)?; 147 ) -> Result<()> {
138 let args = extract_argv(argc, argv); 148 let handle = wrap(pamh)?;
139 M::open_session(handle, args, BaseFlags::from(flags)) 149 let (action, flags) = CredAction::extract(flags)?;
140 } 150 let args = extract_argv(argc, argv);
141 151 M::set_credentials(handle, args, action, flags)
142 pub unsafe fn pam_sm_setcred<M: PamModule<LibPamHandle>>(
143 pamh: *mut c_void,
144 flags: RawFlags,
145 argc: c_int,
146 argv: *const *const c_char,
147 ) -> Result<()> {
148 let handle = wrap(pamh)?;
149 let (action, flags) = CredAction::extract(flags)?;
150 let args = extract_argv(argc, argv);
151 M::set_credentials(handle, args, action, flags)
152 }
153 } 152 }
154 153
155 /// Turns `argc`/`argv` into a [Vec] of [CStr]s. 154 /// Turns `argc`/`argv` into a [Vec] of [CStr]s.
156 /// 155 ///
157 /// # Safety 156 /// # Safety
180 // Compile-time test that the `pam_hooks` macro compiles. 179 // Compile-time test that the `pam_hooks` macro compiles.
181 use crate::{ModuleClient, PamModule}; 180 use crate::{ModuleClient, PamModule};
182 struct Foo; 181 struct Foo;
183 impl<T: ModuleClient> PamModule<T> for Foo {} 182 impl<T: ModuleClient> PamModule<T> for Foo {}
184 183
185 pam_hooks!(Foo); 184 pam_export!(Foo);
186 } 185 }