diff --git a/src/auth.rs b/src/auth.rs index db33b2e4..3272dd6d 100644 --- a/src/auth.rs +++ b/src/auth.rs @@ -4,7 +4,7 @@ use std::process::{Command, Stdio}; use std::io::Write; -use std::ffi::CStr; +use std::ffi::{CString, CStr}; use anyhow::{bail, format_err, Error}; use serde_json::json; @@ -70,51 +70,24 @@ impl ProxmoxAuthenticator for PAM { pub struct PBS(); -// from libcrypt1, 'lib/crypt.h.in' -const CRYPT_OUTPUT_SIZE: usize = 384; -const CRYPT_MAX_PASSPHRASE_SIZE: usize = 512; -const CRYPT_DATA_RESERVED_SIZE: usize = 767; -const CRYPT_DATA_INTERNAL_SIZE: usize = 30720; +pub fn crypt(password: &[u8], salt: &str) -> Result { -#[repr(C)] -struct crypt_data { - output: [libc::c_char; CRYPT_OUTPUT_SIZE], - setting: [libc::c_char; CRYPT_OUTPUT_SIZE], - input: [libc::c_char; CRYPT_MAX_PASSPHRASE_SIZE], - reserved: [libc::c_char; CRYPT_DATA_RESERVED_SIZE], - initialized: libc::c_char, - internal: [libc::c_char; CRYPT_DATA_INTERNAL_SIZE], -} - -pub fn crypt(password: &[u8], salt: &[u8]) -> Result { - #[link(name = "crypt")] + #[link(name="crypt")] extern "C" { - #[link_name = "crypt_r"] - fn __crypt_r( - key: *const libc::c_char, - salt: *const libc::c_char, - data: *mut crypt_data, - ) -> *mut libc::c_char; + #[link_name = "crypt"] + fn __crypt(key: *const libc::c_char, salt: *const libc::c_char) -> * mut libc::c_char; } - let mut data: crypt_data = unsafe { std::mem::zeroed() }; - for (i, c) in salt.iter().take(data.setting.len() - 1).enumerate() { - data.setting[i] = *c as libc::c_char; - } - for (i, c) in password.iter().take(data.input.len() - 1).enumerate() { - data.input[i] = *c as libc::c_char; - } + let salt = CString::new(salt)?; + let password = CString::new(password)?; let res = unsafe { - let status = __crypt_r( - &data.input as *const _, - &data.setting as *const _, - &mut data as *mut _, - ); - if status.is_null() { - bail!("internal error: crypt_r returned null pointer"); - } - CStr::from_ptr(&data.output as *const _) + CStr::from_ptr( + __crypt( + password.as_c_str().as_ptr(), + salt.as_c_str().as_ptr() + ) + ) }; Ok(String::from(res.to_str()?)) } @@ -125,11 +98,11 @@ pub fn encrypt_pw(password: &str) -> Result { let salt = proxmox::sys::linux::random_data(8)?; let salt = format!("$5${}$", base64::encode_config(&salt, base64::CRYPT)); - crypt(password.as_bytes(), salt.as_bytes()) + crypt(password.as_bytes(), &salt) } pub fn verify_crypt_pw(password: &str, enc_password: &str) -> Result<(), Error> { - let verify = crypt(password.as_bytes(), enc_password.as_bytes())?; + let verify = crypt(password.as_bytes(), enc_password)?; if verify != enc_password { bail!("invalid credentials"); }