Mercurial > crates > nonstick
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 } |
