comparison libpam-sys/src/ffi.rs @ 127:c77846f3a979

GET CTEST WORKING. This will verify that the functions we're exporting are correct. It has been a nightmare.
author Paul Fisher <paul@pfish.zone>
date Mon, 30 Jun 2025 22:56:26 -0400
parents libpam-sys/src/structs.rs@2b255c92417b
children
comparison
equal deleted inserted replaced
126:57c812e308bd 127:c77846f3a979
1 #![allow(non_camel_case_types)]
2
3 use std::ffi::{c_char, c_int, c_void};
4 use std::fmt;
5 use std::marker::{PhantomData, PhantomPinned};
6
7 /// A marker struct to make whatever it's in `!Sync`, `!Send`, and `!Unpin`.
8 #[derive(Default, PartialOrd, PartialEq, Ord, Eq)]
9 #[repr(C)]
10 struct ExtremelyUnsafe {
11 _value: (),
12 _marker: PhantomData<(PhantomPinned, *mut c_void)>,
13 }
14
15 impl fmt::Debug for ExtremelyUnsafe {
16 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
17 f.write_str("ExtremelyUnsafe")
18 }
19 }
20
21 /// An opaque structure that PAM uses to communicate.
22 ///
23 /// This is only ever returned in pointer form and cannot be constructed.
24 #[repr(C)]
25 pub struct pam_handle(ExtremelyUnsafe);
26
27 impl fmt::Debug for pam_handle {
28 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
29 write!(f, "PamHandle({self:p}")
30 }
31 }
32
33 /// An opaque structure that is passed through PAM in a conversation.
34 #[repr(C)]
35 pub struct AppData(ExtremelyUnsafe);
36
37 impl fmt::Debug for AppData {
38 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
39 write!(f, "AppData({self:p}")
40 }
41 }
42
43 /// Just an alias for the type of [`pam_conv::conv`].
44 ///
45 /// For important details about the format of `messages`,
46 /// see the [`helpers`](crate::helpers) module.
47 ///
48 /// ```no_run
49 /// # use libpam_sys::{ConversationCallback, pam_conv};
50 /// fn convo() -> ConversationCallback {
51 /// // ...
52 /// # unimplemented!()
53 /// }
54 /// let conv = pam_conv{conv: convo(), appdata_ptr: std::ptr::null_mut()};
55 /// ```
56 pub type ConversationCallback = unsafe extern "C" fn(
57 num_msg: c_int,
58 msg: *const *const pam_message,
59 resp: *mut *mut pam_response,
60 appdata: *mut AppData,
61 ) -> c_int;
62
63 /// Alias for the callback to [`pam_set_data`](crate::pam_set_data).
64 ///
65 /// ```no_run
66 /// # use std::ffi::CString;
67 /// use libpam_sys::{CleanupCallback, pam_set_data};
68 /// # use libpam_sys::pam_handle;
69 /// # let handle: *mut pam_handle = std::ptr::null_mut();
70 /// # let mut my_data = 100;
71 /// # let data_ptr = &mut my_data as *mut i32;
72 /// fn cleanup() -> CleanupCallback {
73 /// // ...
74 /// # unimplemented!()
75 /// }
76 /// let name = CString::new("name").unwrap();
77 /// unsafe {
78 /// pam_set_data(handle, name.as_ptr().cast_mut(), data_ptr.cast(), cleanup());
79 /// }
80 /// ```
81 pub type CleanupCallback = unsafe extern "C" fn(
82 pamh: *mut pam_handle,
83 data: *mut c_void,
84 pam_end_status: c_int,
85 );
86
87 /// Used by PAM to communicate between the module and the application.
88 #[repr(C)]
89 pub struct pam_conv {
90 pub conv: unsafe extern "C" fn(
91 num_msg: c_int,
92 msg: *const *const pam_message,
93 resp: *mut *mut pam_response,
94 appdata: *mut AppData,
95 ) -> c_int,
96 pub appdata_ptr: *mut AppData,
97 }
98
99 /// A message sent into a PAM conversation.
100 #[repr(C)]
101 pub struct pam_message {
102 pub msg_style: c_int,
103 pub msg: *const c_char,
104 }
105
106 /// A response returned from a PAM conversation.
107 #[repr(C)]
108 pub struct pam_response {
109 pub resp: *mut c_char,
110 /// Completely unused.
111 pub resp_retcode: c_int,
112 }
113
114
115 // These are the functions specified in X/SSO. Everybody exports them.
116 extern "C" {
117 /// Account validation.
118 pub fn pam_acct_mgmt(pamh: *mut pam_handle, flags: c_int) -> c_int;
119
120 /// Authenticate a user.
121 pub fn pam_authenticate(pamh: *mut pam_handle, flags: c_int) -> c_int;
122
123 // Nobody implements pam_authenticate_secondary.
124
125 /// Manage authentication tokens.
126 pub fn pam_chauthtok(pamh: *mut pam_handle, flags: c_int) -> c_int;
127
128 /// Close an opened user session.
129 pub fn pam_close_session(pamh: *mut pam_handle, flags: c_int) -> c_int;
130
131 /// Ends the PAM transaction.
132 pub fn pam_end(pamh: *mut pam_handle, flags: c_int) -> c_int;
133
134 /// Gets module-specific data. PAM still owns the data.
135 pub fn pam_get_data(
136 pamh: *mut pam_handle,
137 module_data_name: *const c_char,
138 data: *mut *const c_void,
139 ) -> c_int;
140
141 /// Gets an environment variable. You own the return value.
142 pub fn pam_getenv(pamh: *mut pam_handle, name: *const c_char) -> *mut c_char;
143
144 /// Gets all the environment variables. You own everything it points to.
145 pub fn pam_getenvlist(pamh: *mut pam_handle) -> *mut *mut c_char;
146
147 /// Get information about the transaction.
148 ///
149 /// The item is owned by PAM.
150 pub fn pam_get_item(
151 pamh: *mut pam_handle,
152 item_type: c_int,
153 item: *mut *const c_void,
154 ) -> c_int;
155
156 // Nobody implements pam_get_mapped_authtok.
157 // Nobody implements pam_get_mapped_username.
158
159 /// Get the username. PAM owns it.
160 pub fn pam_get_user(
161 pamh: *mut pam_handle,
162 user: *mut *const c_char,
163 prompt: *const c_char,
164 ) -> c_int;
165
166 /// Opens a user session.
167 pub fn pam_open_session(pamh: *mut pam_handle, flags: c_int) -> c_int;
168
169 /// Sets the value of an environment variable. `namevalue` is copied.
170 pub fn pam_putenv(pamh: *mut pam_handle, namevalue: *const c_char) -> c_int;
171
172 /// Update or delete user credentials.
173 pub fn pam_setcred(pamh: *mut pam_handle, flags: c_int) -> c_int;
174
175 /// Set module-specific data. PAM will call `cleanup` when completed.
176 pub fn pam_set_data(
177 pamh: *mut pam_handle,
178 module_data_name: *const c_char,
179 data: *mut c_void,
180 cleanup: unsafe extern "C" fn(
181 pamh: *mut pam_handle,
182 data: *mut c_void,
183 pam_end_status: c_int,
184 ),
185 ) -> c_int;
186
187 /// Set information about the transaction. The `item` is copied.
188 pub fn pam_set_item(pamh: *mut pam_handle, item_type: c_int, item: *const c_void) -> c_int;
189
190 // Nobody implements pam_set_mapped_authtok.
191 // Nobody implements pam_set_mapped_username.
192
193 // The pam_sm_whatever functions are prototypes for the functions that
194 // a PAM module should implement, not symbols provided by PAM.
195
196 // Nobody implements pam_authenticate_secondary.
197
198 /// Starts a PAM transaction. The `conv` may or may not be copied.
199 pub fn pam_start(
200 service: *const c_char,
201 user: *const c_char,
202 pam_conv: *mut pam_conv,
203 pamh: *mut *mut pam_handle,
204 ) -> c_int;
205
206 /// Gets a statically-allocated error string.
207 ///
208 /// All implementations of PAM known to this library (Linux-PAM, OpenPAM,
209 /// and Sun) ignore `pamh` and will accept a null pointer.
210 pub fn pam_strerror(pamh: *const pam_handle, error_number: c_int) -> *mut c_char;
211 }
212
213 // We use `_private_pam_impl_hack` because ctest loses its mind
214 // when it comes across the `cfg_pam_impl` macro.
215 // This is a custom cfg variable set in our build.rs. Don't do this; just use
216 // cfg_pam_impl.
217 #[cfg(_private_pam_impl_hack = "LinuxPam")]
218 extern "C" {
219 pub fn pam_get_authtok(pamh: *mut pam_handle, x: c_int, token: *mut *const c_char, prompt: *const c_char) -> c_int;
220 }
221
222
223 // int (*)(struct pam_handle *, char *, void *, void (*)(struct pam_handle *, void *, int))
224 // int (*)(struct pam_handle *, char *, void *, int (*)(struct pam_handle *, void *, int))