diff libpam-sys/src/ffi.rs @ 131:a632a8874131

Get all the Linux-PAM functions into libpam-sys, and get tests right.
author Paul Fisher <paul@pfish.zone>
date Wed, 02 Jul 2025 02:24:21 -0400
parents 80c07e5ab22f
children 32b2a545ca3e
line wrap: on
line diff
--- a/libpam-sys/src/ffi.rs	Tue Jul 01 06:11:43 2025 -0400
+++ b/libpam-sys/src/ffi.rs	Wed Jul 02 02:24:21 2025 -0400
@@ -1,6 +1,12 @@
+//! The actual PAM FFI bindings.
+//!
+//! They live in this specific file rather than lib.rs because otherwise
+//! ctest gets very upset about some of the macros we use.
 #![allow(non_camel_case_types)]
+#![allow(unused_imports)]
 
-use std::ffi::{c_char, c_int, c_void};
+use num_enum::{IntoPrimitive, TryFromPrimitive};
+use std::ffi::{c_char, c_int, c_uint, c_void};
 use std::fmt;
 use std::marker::{PhantomData, PhantomPinned};
 
@@ -14,7 +20,7 @@
 
 impl fmt::Debug for ExtremelyUnsafe {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.write_str("ExtremelyUnsafe")
+        write!(f, "ExtremelyUnsafe({self:p})")
     }
 }
 
@@ -26,7 +32,7 @@
 
 impl fmt::Debug for pam_handle {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "PamHandle({self:p}")
+        write!(f, "pam_handle({self:p}")
     }
 }
 
@@ -108,6 +114,40 @@
     pub resp_retcode: c_int,
 }
 
+/// Definition of the PAM_XAUTHDATA item. Compatible with `xcb_auth_info_t`.
+#[cfg(_hack_impl = "LinuxPam")]
+#[repr(C)]
+pub struct pam_xauth_data {
+    namelen: c_int,
+    name: *mut c_char,
+    datalen: c_int,
+    data: *mut c_char,
+}
+
+#[cfg(_hack_impl = "LinuxPam")]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, TryFromPrimitive, IntoPrimitive)]
+#[repr(i32)]
+pub enum pam_modutil_redirect_fd {
+    PAM_MODUTIL_IGNORE_FD,
+    PAM_MODUTIL_PIPE_FD,
+    PAM_MODUTIL_NULL_FD,
+}
+
+#[cfg(_hack_impl = "LinuxPam")]
+pub use pam_modutil_redirect_fd::*;
+
+#[cfg(_hack_impl = "LinuxPam")]
+#[derive(Debug)]
+#[repr(C)]
+pub struct pam_modutil_privs {
+    grplist: *mut libc::gid_t,
+    number_of_groups: c_int,
+    allocated: c_int,
+    old_gid: libc::gid_t,
+    old_uid: libc::uid_t,
+    is_dropped: c_int,
+}
+
 // These are the functions specified in X/SSO. Everybody exports them.
 extern "C" {
     /// Account validation.
@@ -206,16 +246,130 @@
     pub fn pam_strerror(pamh: *const pam_handle, error_number: c_int) -> *mut c_char;
 }
 
-// We use `_private_pam_impl_hack` because ctest loses its mind
+// We use `_hack_impl` because ctest loses its mind
 // when it comes across the `cfg_pam_impl` macro.
 // This is a custom cfg variable set in our build.rs. Don't do this; just use
 // cfg_pam_impl.
-#[cfg(any(_private_pam_impl_hack = "LinuxPam", _private_pam_impl_hack = "OpenPam"))]
+#[cfg(any(_hack_impl = "LinuxPam", _hack_impl = "OpenPam"))]
 extern "C" {
+    /// Gets `PAM_AUTHTOK`, or asks the user if that is unset.
     pub fn pam_get_authtok(
         pamh: *mut pam_handle,
-        x: c_int,
-        token: *mut *const c_char,
+        item: c_int,
+        authtok: *mut *const c_char,
         prompt: *const c_char,
     ) -> c_int;
 }
+
+#[cfg(_hack_impl = "LinuxPam")]
+extern "C" {
+    pub fn pam_fail_delay(pamh: *mut pam_handle, musec_delay: c_uint) -> c_int;
+
+    /// Start a PAM transaction based on configuration in the given directory.
+    pub fn pam_start_confdir(
+        service_name: *const c_char,
+        user: *const c_char,
+        pam_conversation: *mut pam_conv,
+        confdir: *const c_char,
+        pamh: *mut *mut pam_handle,
+    ) -> c_int;
+
+    // We don't export the v-variants of the formatting functions.
+
+    pub fn pam_syslog(pamh: *const pam_handle, priority: c_int, fmt: *const c_char, ...);
+
+    pub fn pam_prompt(
+        pamh: *const pam_handle,
+        style: c_int,
+        response: *mut *mut c_char,
+        fmt: *const c_char,
+        ...
+    ) -> c_int;
+
+    pub fn pam_get_authtok_noverify(
+        pamh: *const pam_handle,
+        authtok: *mut *const c_char,
+        prompt: *const c_char,
+    ) -> c_int;
+
+    pub fn pam_get_authtok_verify(
+        pamh: *const pam_handle,
+        authtok: *mut *const c_char,
+        prompt: *const c_char,
+    ) -> c_int;
+
+    // pam_modutil also lives in libpam for Linux.
+
+    pub fn pam_modutil_check_user_in_passwd(
+        pamh: *mut pam_handle,
+        user_name: *const c_char,
+        file_name: *const c_char,
+    ) -> c_int;
+
+    pub fn pam_modutil_getpwnam(pamh: *mut pam_handle, user: *const c_char) -> *mut libc::passwd;
+
+    pub fn pam_modutil_getpwuid(pamh: *mut pam_handle, uid: libc::uid_t) -> *mut libc::passwd;
+
+    pub fn pam_modutil_getgrnam(pamh: *mut pam_handle, group: *const c_char) -> *mut libc::group;
+
+    pub fn pam_modutil_getgrgid(pamh: *mut pam_handle, gid: libc::gid_t) -> *mut libc::group;
+
+    pub fn pam_modutil_getspnam(pamh: *mut pam_handle, user: *const c_char) -> *mut libc::spwd;
+
+    pub fn pam_modutil_user_in_group_nam_nam(
+        pamh: *mut pam_handle,
+        user: *const c_char,
+        group: *const c_char,
+    ) -> c_int;
+    pub fn pam_modutil_user_in_group_nam_gid(
+        pamh: *mut pam_handle,
+        user: *const c_char,
+        group: libc::gid_t,
+    ) -> c_int;
+
+    pub fn pam_modutil_user_in_group_uid_nam(
+        pamh: *mut pam_handle,
+        user: libc::uid_t,
+        group: *const c_char,
+    ) -> c_int;
+
+    pub fn pam_modutil_user_in_group_uid_gid(
+        pamh: *mut pam_handle,
+        user: libc::uid_t,
+        group: libc::gid_t,
+    ) -> c_int;
+
+    pub fn pam_modutil_getlogin(pamh: *mut pam_handle) -> *const c_char;
+
+    pub fn pam_modutil_read(fd: c_int, buffer: *mut c_char, count: c_int) -> c_int;
+
+    pub fn pam_modutil_write(fd: c_int, buffer: *const c_char, count: c_int) -> c_int;
+
+    pub fn pam_modutil_audit_write(
+        pamh: *mut pam_handle,
+        typ: c_int,
+        message: *const c_char,
+        retval: c_int,
+    ) -> c_int;
+
+    pub fn pam_modutil_drop_priv(
+        pamh: *mut pam_handle,
+        p: *mut pam_modutil_privs,
+        pw: *const libc::passwd,
+    ) -> c_int;
+
+    pub fn pam_modutil_regain_priv(pamh: *mut pam_handle, p: *mut pam_modutil_privs) -> c_int;
+
+    pub fn pam_modutil_sanitize_helper_fds(
+        pamh: *mut pam_handle,
+        redirect_stdin: pam_modutil_redirect_fd,
+        redirect_stdout: pam_modutil_redirect_fd,
+        redirect_stderr: pam_modutil_redirect_fd,
+    ) -> c_int;
+
+    pub fn pam_modutil_search_key(
+        pamh: *mut pam_handle,
+        file_name: *const c_char,
+        key: *const c_char,
+    ) -> *mut c_char;
+}