From 94f6127711fe26606aa46a2207859b3fbfca3cb8 Mon Sep 17 00:00:00 2001 From: Thomas Lamprecht Date: Mon, 26 Jul 2021 16:38:16 +0200 Subject: [PATCH] Revert "auth: 'crypt' is not thread safe" With this I'm getting coredumps on every log in: > Process 20957 (proxmox-backup-) of user 34 dumped core. > > Stack trace of thread 20987: > #0 0x0000563dec9ac37f _ZN3std3sys4unix14stack_overflow3imp14signal_handler17ha95ed06a038ca319E.llvm.11547235952357801165 (proxmox-backup-proxy) > #1 0x00007f2638de9840 __restore_rt (libc.so.6) > #2 0x00007f2638e51dac __stpncpy_sse2_unaligned (libc.so.6) > #3 0x00007f26393b1340 __sha256_crypt_r (libcrypt.so.1) > #4 0x00007f26393b0553 __crypt_r (libcrypt.so.1) > #5 0x0000563dec6e44df _ZN14proxmox_backup4auth5crypt17hd5165f960093dfe7E (proxmox-backup-proxy) This reverts commit acefa2bb6e91371039ff6040f3cf538b478a24d3. --- src/auth.rs | 57 ++++++++++++++--------------------------------------- 1 file changed, 15 insertions(+), 42 deletions(-) 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"); }