comparison libpam-sys/src/ffi.rs @ 176:0730f5f2ee2a

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