Mercurial > crates > nonstick
comparison libpam-sys/src/lib.rs @ 136:efbc235f01d3 default tip
Separate libpam-sys-helpers from libpam-sys.
This separates the parts of libpam-sys that don't need linking against libpam
from the parts that do need to link against libpam.
author | Paul Fisher <paul@pfish.zone> |
---|---|
date | Thu, 03 Jul 2025 14:28:04 -0400 |
parents | libpam-sys/src/ffi.rs@6c1e1bdb4164 |
children |
comparison
equal
deleted
inserted
replaced
135:b52594841480 | 136:efbc235f01d3 |
---|---|
1 #![doc = include_str!("../README.md")] | 1 //! `libpam-sys` provides low-level access to `libpam`. |
2 //! | 2 //! |
3 //! ## PAM implementation | 3 //! Everything in here is directly as exported from the `libpam` library or |
4 //! its header files, with limited exceptions: | |
4 //! | 5 //! |
5 #![doc = concat!("This documentation was built for the **", env!("LIBPAMSYS_IMPL"), "** implementation.")] | 6 //! - The [`pam_impl`] submodule (and the [`pam_impl_name!`] macro) contains |
6 | 7 //! tools for detecting the current PAM library. |
7 mod constants; | 8 //! - [`AppData`] is an opaque pointer newtype. |
8 mod ffi; | 9 //! - [`ConversationCallback`] and [`CleanupCallback`] are aliases for |
9 pub mod helpers; | 10 //! what are otherwise anonymous function types. |
10 pub mod pam_impl; | 11 //! |
12 #![doc = concat!("This documentation was built for the **", pam_impl_name!(), "** implementation.")] | |
13 //! | |
14 //! You can override this **at build time** by setting the `LIBPAMSYS_IMPL` | |
15 //! environment variable to one of the values of the [`pam_impl::PamImpl`] enum. | |
16 //! | |
17 //! For more information about configuration, see [the README](https://crates.io/crate/libpam-sys). | |
18 #![allow(non_camel_case_types)] | |
19 #![allow(unused_imports)] | |
11 | 20 |
12 #[doc(inline)] | 21 #[doc(inline)] |
13 pub use crate::{constants::*, ffi::*, pam_impl::*}; | 22 pub use libpam_sys_helpers::constants::*; |
23 #[doc(inline)] | |
24 pub use libpam_sys_helpers::{pam_impl, pam_impl_name}; | |
25 use num_enum::{IntoPrimitive, TryFromPrimitive}; | |
26 use std::ffi::{c_char, c_int, c_uint, c_void}; | |
27 use std::fmt; | |
28 use std::marker::{PhantomData, PhantomPinned}; | |
29 | |
30 /// A marker struct to make whatever it's in `!Sync`, `!Send`, and `!Unpin`. | |
31 #[derive(Default, PartialOrd, PartialEq, Ord, Eq)] | |
32 #[repr(C)] | |
33 struct ExtremelyUnsafe { | |
34 _value: (), | |
35 _marker: PhantomData<(PhantomPinned, *mut c_void)>, | |
36 } | |
37 | |
38 impl fmt::Debug for ExtremelyUnsafe { | |
39 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
40 write!(f, "ExtremelyUnsafe({self:p})") | |
41 } | |
42 } | |
43 | |
44 /// An opaque structure that PAM uses to communicate. | |
45 /// | |
46 /// This is only ever returned in pointer form and cannot be constructed. | |
47 #[repr(C)] | |
48 pub struct pam_handle(ExtremelyUnsafe); | |
49 | |
50 impl fmt::Debug for pam_handle { | |
51 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
52 write!(f, "pam_handle({self:p}") | |
53 } | |
54 } | |
55 | |
56 /// An opaque structure that is passed through PAM in a conversation. | |
57 #[repr(C)] | |
58 pub struct AppData(ExtremelyUnsafe); | |
59 | |
60 impl fmt::Debug for AppData { | |
61 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
62 write!(f, "AppData({self:p}") | |
63 } | |
64 } | |
65 | |
66 /// Just an alias for the type of [`pam_conv::conv`]. | |
67 /// | |
68 /// For important details about the format of `messages`, | |
69 /// see [`libpam_sys_helpers::memory::PtrPtrVec`]. | |
70 /// | |
71 /// ```no_run | |
72 /// # use libpam_sys::{ConversationCallback, pam_conv}; | |
73 /// fn convo() -> ConversationCallback { | |
74 /// // ... | |
75 /// # unimplemented!() | |
76 /// } | |
77 /// let conv = pam_conv{conv: convo(), appdata_ptr: std::ptr::null_mut()}; | |
78 /// ``` | |
79 pub type ConversationCallback = unsafe extern "C" fn( | |
80 num_msg: c_int, | |
81 msg: *const *const pam_message, | |
82 resp: *mut *mut pam_response, | |
83 appdata: *mut AppData, | |
84 ) -> c_int; | |
85 | |
86 /// Alias for the callback to [`pam_set_data`]. | |
87 /// | |
88 /// ```no_run | |
89 /// # use std::ffi::CString; | |
90 /// use libpam_sys::{CleanupCallback, pam_set_data}; | |
91 /// # use libpam_sys::pam_handle; | |
92 /// # let handle: *mut pam_handle = std::ptr::null_mut(); | |
93 /// # let mut my_data = 100; | |
94 /// # let data_ptr = &mut my_data as *mut i32; | |
95 /// fn cleanup() -> CleanupCallback { | |
96 /// // ... | |
97 /// # unimplemented!() | |
98 /// } | |
99 /// let name = CString::new("name").unwrap(); | |
100 /// unsafe { | |
101 /// pam_set_data(handle, name.as_ptr().cast_mut(), data_ptr.cast(), cleanup()); | |
102 /// } | |
103 /// ``` | |
104 pub type CleanupCallback = | |
105 unsafe extern "C" fn(pamh: *mut pam_handle, data: *mut c_void, pam_end_status: c_int); | |
106 | |
107 /// Used by PAM to communicate between the module and the application. | |
108 #[repr(C)] | |
109 pub struct pam_conv { | |
110 pub conv: unsafe extern "C" fn( | |
111 num_msg: c_int, | |
112 msg: *const *const pam_message, | |
113 resp: *mut *mut pam_response, | |
114 appdata: *mut AppData, | |
115 ) -> c_int, | |
116 pub appdata_ptr: *mut AppData, | |
117 } | |
118 | |
119 /// A message sent into a PAM conversation. | |
120 #[repr(C)] | |
121 pub struct pam_message { | |
122 pub msg_style: c_int, | |
123 pub msg: *const c_char, | |
124 } | |
125 | |
126 /// A response returned from a PAM conversation. | |
127 #[repr(C)] | |
128 pub struct pam_response { | |
129 pub resp: *mut c_char, | |
130 /// Completely unused. | |
131 pub resp_retcode: c_int, | |
132 } | |
133 | |
134 /// Definition of the PAM_XAUTHDATA item. Compatible with `xcb_auth_info_t`. | |
135 #[cfg(pam_impl = "LinuxPam")] | |
136 #[repr(C)] | |
137 pub struct pam_xauth_data { | |
138 pub namelen: c_int, | |
139 pub name: *mut c_char, | |
140 pub datalen: c_int, | |
141 pub data: *mut c_char, | |
142 } | |
143 | |
144 #[cfg(pam_impl = "LinuxPam")] | |
145 #[derive(Debug)] | |
146 #[repr(C)] | |
147 pub struct pam_modutil_privs { | |
148 pub grplist: *mut libc::gid_t, | |
149 pub number_of_groups: c_int, | |
150 pub allocated: c_int, | |
151 pub old_gid: libc::gid_t, | |
152 pub old_uid: libc::uid_t, | |
153 pub is_dropped: c_int, | |
154 } | |
155 | |
156 #[cfg(pam_impl = "OpenPam")] | |
157 pub type pam_func_t = unsafe extern "C" fn( | |
158 handle: *mut pam_handle, | |
159 flags: c_int, | |
160 argc: c_int, | |
161 argv: *const *const c_char, | |
162 ) -> c_int; | |
163 | |
164 #[cfg(pam_impl = "OpenPam")] | |
165 #[derive(Debug)] | |
166 #[repr(C)] | |
167 pub struct pam_module { | |
168 pub path: *mut c_char, | |
169 pub func: [pam_func_t; 6], | |
170 pub dlh: *mut c_void, | |
171 } | |
172 | |
173 #[cfg(pam_impl = "OpenPam")] | |
174 #[derive(Debug)] | |
175 #[repr(C)] | |
176 pub struct pam_repository { | |
177 pub typ: *mut c_char, | |
178 pub scope: *mut c_void, | |
179 pub scope_len: usize, | |
180 } | |
181 | |
182 // These are the functions specified in X/SSO. Everybody exports them. | |
183 #[link(name = "pam")] | |
184 extern "C" { | |
185 /// Account validation. | |
186 pub fn pam_acct_mgmt(pamh: *mut pam_handle, flags: c_int) -> c_int; | |
187 | |
188 /// Authenticate a user. | |
189 pub fn pam_authenticate(pamh: *mut pam_handle, flags: c_int) -> c_int; | |
190 | |
191 // Nobody implements pam_authenticate_secondary. | |
192 | |
193 /// Manage authentication tokens. | |
194 pub fn pam_chauthtok(pamh: *mut pam_handle, flags: c_int) -> c_int; | |
195 | |
196 /// Close an opened user session. | |
197 pub fn pam_close_session(pamh: *mut pam_handle, flags: c_int) -> c_int; | |
198 | |
199 /// Ends the PAM transaction. | |
200 pub fn pam_end(pamh: *mut pam_handle, flags: c_int) -> c_int; | |
201 | |
202 /// Gets module-specific data. PAM still owns the data. | |
203 pub fn pam_get_data( | |
204 pamh: *mut pam_handle, | |
205 module_data_name: *const c_char, | |
206 data: *mut *const c_void, | |
207 ) -> c_int; | |
208 | |
209 /// Gets an environment variable. You own the return value. | |
210 pub fn pam_getenv(pamh: *const pam_handle, name: *const c_char) -> *mut c_char; | |
211 | |
212 /// Gets all the environment variables. You own everything it points to. | |
213 pub fn pam_getenvlist(pamh: *const pam_handle) -> *mut *mut c_char; | |
214 | |
215 /// Get information about the transaction. | |
216 /// | |
217 /// The item is owned by PAM. | |
218 pub fn pam_get_item( | |
219 pamh: *const pam_handle, | |
220 item_type: c_int, | |
221 item: *mut *const c_void, | |
222 ) -> c_int; | |
223 | |
224 // Nobody implements pam_get_mapped_authtok. | |
225 // Nobody implements pam_get_mapped_username. | |
226 | |
227 /// Get the username. PAM owns it. | |
228 pub fn pam_get_user( | |
229 pamh: *mut pam_handle, | |
230 user: *mut *const c_char, | |
231 prompt: *const c_char, | |
232 ) -> c_int; | |
233 | |
234 /// Opens a user session. | |
235 pub fn pam_open_session(pamh: *mut pam_handle, flags: c_int) -> c_int; | |
236 | |
237 /// Sets the value of an environment variable. `namevalue` is copied. | |
238 pub fn pam_putenv(pamh: *mut pam_handle, namevalue: *const c_char) -> c_int; | |
239 | |
240 /// Update or delete user credentials. | |
241 pub fn pam_setcred(pamh: *mut pam_handle, flags: c_int) -> c_int; | |
242 | |
243 /// Set module-specific data. PAM will call `cleanup` when completed. | |
244 pub fn pam_set_data( | |
245 pamh: *mut pam_handle, | |
246 module_data_name: *const c_char, | |
247 data: *mut c_void, | |
248 cleanup: unsafe extern "C" fn( | |
249 pamh: *mut pam_handle, | |
250 data: *mut c_void, | |
251 pam_end_status: c_int, | |
252 ), | |
253 ) -> c_int; | |
254 | |
255 /// Set information about the transaction. The `item` is copied. | |
256 pub fn pam_set_item(pamh: *mut pam_handle, item_type: c_int, item: *const c_void) -> c_int; | |
257 | |
258 // Nobody implements pam_set_mapped_authtok. | |
259 // Nobody implements pam_set_mapped_username. | |
260 | |
261 // The pam_sm_whatever functions are prototypes for the functions that | |
262 // a PAM module should implement, not symbols provided by PAM. | |
263 | |
264 // Nobody implements pam_authenticate_secondary. | |
265 | |
266 /// Starts a PAM transaction. The `conv` may or may not be copied. | |
267 pub fn pam_start( | |
268 service: *const c_char, | |
269 user: *const c_char, | |
270 pam_conv: *mut pam_conv, | |
271 pamh: *mut *mut pam_handle, | |
272 ) -> c_int; | |
273 | |
274 /// Gets a statically-allocated error string. | |
275 /// | |
276 /// All implementations of PAM known to this library (Linux-PAM, OpenPAM, | |
277 /// and Sun) ignore `pamh` and will accept a null pointer. | |
278 pub fn pam_strerror(pamh: *const pam_handle, error_number: c_int) -> *mut c_char; | |
279 } | |
280 | |
281 #[cfg(any(pam_impl = "LinuxPam", pam_impl = "OpenPam"))] | |
282 extern "C" { | |
283 /// Gets `PAM_AUTHTOK`, or asks the user if that is unset. | |
284 pub fn pam_get_authtok( | |
285 pamh: *mut pam_handle, | |
286 item: c_int, | |
287 authtok: *mut *const c_char, | |
288 prompt: *const c_char, | |
289 ) -> c_int; | |
290 | |
291 pub fn pam_prompt( | |
292 pamh: *const pam_handle, | |
293 style: c_int, | |
294 response: *mut *mut c_char, | |
295 fmt: *const c_char, | |
296 ... | |
297 ) -> c_int; | |
298 | |
299 } | |
300 | |
301 #[cfg(pam_impl = "LinuxPam")] | |
302 extern "C" { | |
303 pub fn pam_fail_delay(pamh: *mut pam_handle, musec_delay: c_uint) -> c_int; | |
304 | |
305 /// Start a PAM transaction based on configuration in the given directory. | |
306 pub fn pam_start_confdir( | |
307 service_name: *const c_char, | |
308 user: *const c_char, | |
309 pam_conversation: *mut pam_conv, | |
310 confdir: *const c_char, | |
311 pamh: *mut *mut pam_handle, | |
312 ) -> c_int; | |
313 | |
314 // We don't export the v-variants of the formatting functions. | |
315 | |
316 pub fn pam_syslog(pamh: *const pam_handle, priority: c_int, fmt: *const c_char, ...); | |
317 | |
318 pub fn pam_get_authtok_noverify( | |
319 pamh: *const pam_handle, | |
320 authtok: *mut *const c_char, | |
321 prompt: *const c_char, | |
322 ) -> c_int; | |
323 | |
324 pub fn pam_get_authtok_verify( | |
325 pamh: *const pam_handle, | |
326 authtok: *mut *const c_char, | |
327 prompt: *const c_char, | |
328 ) -> c_int; | |
329 | |
330 // pam_modutil also lives in libpam for Linux. | |
331 | |
332 pub fn pam_modutil_check_user_in_passwd( | |
333 pamh: *mut pam_handle, | |
334 user_name: *const c_char, | |
335 file_name: *const c_char, | |
336 ) -> c_int; | |
337 | |
338 pub fn pam_modutil_getpwnam(pamh: *mut pam_handle, user: *const c_char) -> *mut libc::passwd; | |
339 | |
340 pub fn pam_modutil_getpwuid(pamh: *mut pam_handle, uid: libc::uid_t) -> *mut libc::passwd; | |
341 | |
342 pub fn pam_modutil_getgrnam(pamh: *mut pam_handle, group: *const c_char) -> *mut libc::group; | |
343 | |
344 pub fn pam_modutil_getgrgid(pamh: *mut pam_handle, gid: libc::gid_t) -> *mut libc::group; | |
345 | |
346 pub fn pam_modutil_getspnam(pamh: *mut pam_handle, user: *const c_char) -> *mut libc::spwd; | |
347 | |
348 pub fn pam_modutil_user_in_group_nam_nam( | |
349 pamh: *mut pam_handle, | |
350 user: *const c_char, | |
351 group: *const c_char, | |
352 ) -> c_int; | |
353 pub fn pam_modutil_user_in_group_nam_gid( | |
354 pamh: *mut pam_handle, | |
355 user: *const c_char, | |
356 group: libc::gid_t, | |
357 ) -> c_int; | |
358 | |
359 pub fn pam_modutil_user_in_group_uid_nam( | |
360 pamh: *mut pam_handle, | |
361 user: libc::uid_t, | |
362 group: *const c_char, | |
363 ) -> c_int; | |
364 | |
365 pub fn pam_modutil_user_in_group_uid_gid( | |
366 pamh: *mut pam_handle, | |
367 user: libc::uid_t, | |
368 group: libc::gid_t, | |
369 ) -> c_int; | |
370 | |
371 pub fn pam_modutil_getlogin(pamh: *mut pam_handle) -> *const c_char; | |
372 | |
373 pub fn pam_modutil_read(fd: c_int, buffer: *mut c_char, count: c_int) -> c_int; | |
374 | |
375 pub fn pam_modutil_write(fd: c_int, buffer: *const c_char, count: c_int) -> c_int; | |
376 | |
377 pub fn pam_modutil_audit_write( | |
378 pamh: *mut pam_handle, | |
379 typ: c_int, | |
380 message: *const c_char, | |
381 retval: c_int, | |
382 ) -> c_int; | |
383 | |
384 pub fn pam_modutil_drop_priv( | |
385 pamh: *mut pam_handle, | |
386 p: *mut pam_modutil_privs, | |
387 pw: *const libc::passwd, | |
388 ) -> c_int; | |
389 | |
390 pub fn pam_modutil_regain_priv(pamh: *mut pam_handle, p: *mut pam_modutil_privs) -> c_int; | |
391 | |
392 pub fn pam_modutil_sanitize_helper_fds( | |
393 pamh: *mut pam_handle, | |
394 redirect_stdin: pam_modutil_redirect_fd, | |
395 redirect_stdout: pam_modutil_redirect_fd, | |
396 redirect_stderr: pam_modutil_redirect_fd, | |
397 ) -> c_int; | |
398 | |
399 pub fn pam_modutil_search_key( | |
400 pamh: *mut pam_handle, | |
401 file_name: *const c_char, | |
402 key: *const c_char, | |
403 ) -> *mut c_char; | |
404 } | |
405 | |
406 #[cfg(pam_impl = "OpenPam")] | |
407 extern "C" { | |
408 pub fn openpam_borrow_cred(pamh: *mut pam_handle, passwd: *const libc::passwd) -> c_int; | |
409 | |
410 pub fn openpam_subst( | |
411 pamh: *const pam_handle, | |
412 buf: *mut c_char, | |
413 _bufsize: *mut usize, | |
414 _template: *const c_char, | |
415 ) -> c_int; | |
416 | |
417 pub fn openpam_free_data(pamh: *mut pam_handle, data: *mut c_void, status: c_int); | |
418 | |
419 pub fn openpam_free_envlist(_envlist: *mut *mut c_char); | |
420 | |
421 pub fn openpam_get_option(_pamh: *mut pam_handle, _option: *const c_char) -> *const c_char; | |
422 | |
423 pub fn openpam_restore_cred(pamh: *mut pam_handle) -> c_int; | |
424 | |
425 pub fn openpam_set_option( | |
426 _pamh: *mut pam_handle, | |
427 _option: *const c_char, | |
428 _value: *const c_char, | |
429 ) -> c_int; | |
430 | |
431 pub fn pam_error(pamh: *const pam_handle, _fmt: *const c_char, ...) -> c_int; | |
432 | |
433 pub fn pam_info(_pamh: *const pam_handle, _fmt: *const c_char, ...) -> c_int; | |
434 | |
435 pub fn openpam_readline( | |
436 _f: *mut libc::FILE, | |
437 _lineno: *mut c_int, | |
438 _lenp: *mut usize, | |
439 ) -> *mut c_char; | |
440 | |
441 pub fn openpam_readlinev( | |
442 _f: *mut libc::FILE, | |
443 _lineno: *mut c_int, | |
444 _lenp: *mut c_int, | |
445 ) -> *mut *mut c_char; | |
446 | |
447 pub fn openpam_readword( | |
448 _f: *mut libc::FILE, | |
449 _lineno: *mut c_int, | |
450 _lenp: *mut usize, | |
451 ) -> *mut c_char; | |
452 | |
453 pub fn openpam_straddch( | |
454 _str: *mut *mut c_char, | |
455 _sizep: *mut usize, | |
456 _lenp: *mut usize, | |
457 ch: c_int, | |
458 ) -> c_int; | |
459 | |
460 pub fn openpam_set_feature(_feature: c_int, _onoff: c_int) -> c_int; | |
461 | |
462 pub fn openpam_get_feature(_feature: c_int, _onoff: *mut c_int) -> c_int; | |
463 | |
464 pub fn _openpam_log(_level: c_int, _func: *const c_char, _fmt: *const c_char, ...); | |
465 | |
466 /// A premade conversation function that talks to the TTY. | |
467 /// | |
468 /// ```no_run | |
469 /// # use std::ffi::CString; | |
470 /// # use std::ptr; | |
471 /// use libpam_sys::*; | |
472 /// # let service = CString::new("whatever").unwrap(); | |
473 /// # let user = CString::new("whatever").unwrap(); | |
474 /// let mut handle: *mut pam_handle = ptr::null_mut(); | |
475 /// let mut conv = pam_conv{ | |
476 /// conv: openpam_ttyconv, | |
477 /// appdata_ptr: ptr::null_mut(), | |
478 /// }; | |
479 /// let result = unsafe { pam_start( | |
480 /// service.as_ptr(), user.as_ptr(), &mut conv, &mut handle | |
481 /// ) }; | |
482 /// ``` | |
483 pub fn openpam_ttyconv( | |
484 n: c_int, | |
485 _msg: *const *const pam_message, | |
486 _resp: *mut *mut pam_response, | |
487 _data: *mut AppData, | |
488 ) -> c_int; | |
489 | |
490 pub static mut openpam_ttyconv_timeout: c_int; | |
491 | |
492 /// A null conversation function. | |
493 /// | |
494 /// ```no_run | |
495 /// # use std::ffi::CString; | |
496 /// # use std::ptr; | |
497 /// use libpam_sys::*; | |
498 /// # let service = CString::new("whatever").unwrap(); | |
499 /// # let user = CString::new("whatever").unwrap(); | |
500 /// let mut handle: *mut pam_handle = ptr::null_mut(); | |
501 /// let mut conv = pam_conv{ | |
502 /// conv: openpam_nullconv, | |
503 /// appdata_ptr: ptr::null_mut(), | |
504 /// }; | |
505 /// let result = unsafe { pam_start( | |
506 /// service.as_ptr(), user.as_ptr(), &mut conv, &mut handle | |
507 /// ) }; | |
508 /// ``` | |
509 pub fn openpam_nullconv( | |
510 n: c_int, | |
511 _msg: *const *const pam_message, | |
512 _resp: *mut *mut pam_response, | |
513 _data: *mut AppData, | |
514 ) -> c_int; | |
515 } |