1#![allow(
11 non_upper_case_globals,
12 non_camel_case_types,
13 non_snake_case,
14 deref_nullptr
15)]
16
17#[derive(Clone, Copy, Debug, PartialEq, Eq)]
18pub enum PamImplementation {
19 LinuxPAM,
20 OpenPAM,
21}
22
23pub const PAM_IMPLEMENTATION: PamImplementation = {
24 #[cfg(PAM_SYS_IMPL = "linux-pam")]
25 {
26 PamImplementation::LinuxPAM
27 }
28
29 #[cfg(PAM_SYS_IMPL = "openpam")]
30 {
31 PamImplementation::OpenPAM
32 }
33
34 #[cfg(not(any(PAM_SYS_IMPL = "linux-pam", PAM_SYS_IMPL = "openpam",)))]
35 compile_error!("No valid PAM implementation selected")
36};
37
38#[cfg(all(PAM_SYS_IMPL = "linux-pam", feature = "generate-bindings"))]
39pub mod linuxpam {
40 include!(concat!(env!("OUT_DIR"), "/linuxpam.rs"));
41}
42
43#[cfg(all(
44 PAM_SYS_IMPL = "linux-pam", not(feature = "generate-bindings"),
46))]
47pub mod linuxpam;
48
49#[cfg(all(any(doc, PAM_SYS_IMPL = "openpam"), feature = "generate-bindings"))]
50pub mod openpam {
51 include!(concat!(env!("OUT_DIR"), "/openpam.rs"));
52}
53
54#[cfg(all(any(doc, PAM_SYS_IMPL = "openpam"), not(feature = "generate-bindings")))]
55pub mod openpam;
56
57#[cfg(PAM_SYS_IMPL = "linux-pam")]
58pub use linuxpam::*;
59
60#[cfg(PAM_SYS_IMPL = "openpam")]
61pub use openpam::*;
62
63#[cfg(test)]
64mod tests {
65 use super::*;
66 #[test]
67 fn test_pam_implementation() {
68 match PAM_IMPLEMENTATION {
69 PamImplementation::LinuxPAM => {
70 assert!(cfg!(PAM_SYS_IMPL = "linux-pam"));
71 }
72 PamImplementation::OpenPAM => {
73 assert!(cfg!(PAM_SYS_IMPL = "openpam"));
74 }
75 }
76 }
77
78 #[test]
79 #[cfg(PAM_SYS_IMPL = "linux-pam")]
80 fn test_linuxpam_is_working() {
81 unsafe {
82 match PAM_IMPLEMENTATION {
83 PamImplementation::LinuxPAM => {
84 use std::ffi::CString;
85 let service = CString::new("test_service").unwrap();
86 let user = CString::new("test_user").unwrap();
87
88 extern "C" fn conv_func(
90 _num_msg: ::std::os::raw::c_int,
91 _msg: *mut *const pam_message,
92 _resp: *mut *mut pam_response,
93 _appdata_ptr: *mut ::std::os::raw::c_void,
94 ) -> ::std::os::raw::c_int {
95 PAM_SUCCESS
96 }
97
98 let conv = pam_conv {
99 conv: Some(conv_func),
100 appdata_ptr: std::ptr::null_mut(),
101 };
102
103 let mut pamh: *mut pam_handle_t = std::ptr::null_mut();
104 assert_eq!(
105 pam_start(service.as_ptr(), user.as_ptr(), &conv, &mut pamh),
106 PAM_SUCCESS
107 );
108 assert!(!pamh.is_null());
109 assert_eq!(pam_end(pamh, PAM_SUCCESS), PAM_SUCCESS);
110 }
111 PamImplementation::OpenPAM => {
112 panic!("pam_sys is not configured for OpenPAM");
113 }
114 }
115 }
116 }
117
118 #[test]
119 #[cfg(PAM_SYS_IMPL = "openpam")]
120 fn test_openpam_is_working() {
121 unsafe {
122 match PAM_IMPLEMENTATION {
123 PamImplementation::OpenPAM => {
124 use std::ffi::CString;
125 let service = CString::new("test_service").unwrap();
126 let user = CString::new("test_user").unwrap();
127
128 unsafe extern "C" fn conv_func(
130 _num_msg: ::std::os::raw::c_int,
131 _msg: *mut *const pam_message,
132 _resp: *mut *mut pam_response,
133 _appdata_ptr: *mut ::std::os::raw::c_void,
134 ) -> ::std::os::raw::c_int {
135 PAM_SUCCESS
136 }
137
138 let conv = pam_conv {
139 conv: Some(conv_func),
140 appdata_ptr: std::ptr::null_mut(),
141 };
142
143 let mut pamh: *mut pam_handle_t = std::ptr::null_mut();
144 assert_eq!(
145 pam_start(service.as_ptr(), user.as_ptr(), &conv, &mut pamh),
146 PAM_SUCCESS
147 );
148 assert!(!pamh.is_null());
149 assert_eq!(pam_end(pamh, PAM_SUCCESS), PAM_SUCCESS);
150 }
151 PamImplementation::LinuxPAM => {
152 panic!("pam_sys is not configured for LinuxPAM");
153 }
154 }
155 }
156 }
157}