libpam_sys/
ffi.rs

1use std::ffi::{c_char, c_int, c_uint, c_void};
2use std::fmt;
3use 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)]
9pub struct pam_handle {
10    _value: (),
11    _marker: PhantomData<(PhantomPinned, *mut c_void)>,
12}
13
14impl 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)]
23pub 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)]
36pub 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)]
44pub 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)]
53pub 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)]
63pub 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")]
73pub 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)]
83pub 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)]
92pub 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.
99extern "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"))]
195extern "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")]
215extern "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")]
321extern "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")]
428extern "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}