3 use anyhow
::{bail, Error}
;
5 // from libcrypt1, 'lib/crypt.h.in'
6 const CRYPT_OUTPUT_SIZE
: usize = 384;
7 const CRYPT_MAX_PASSPHRASE_SIZE
: usize = 512;
8 const CRYPT_DATA_RESERVED_SIZE
: usize = 767;
9 const CRYPT_DATA_INTERNAL_SIZE
: usize = 30720;
13 output
: [libc
::c_char
; CRYPT_OUTPUT_SIZE
],
14 setting
: [libc
::c_char
; CRYPT_OUTPUT_SIZE
],
15 input
: [libc
::c_char
; CRYPT_MAX_PASSPHRASE_SIZE
],
16 reserved
: [libc
::c_char
; CRYPT_DATA_RESERVED_SIZE
],
17 initialized
: libc
::c_char
,
18 internal
: [libc
::c_char
; CRYPT_DATA_INTERNAL_SIZE
],
21 pub fn crypt(password
: &[u8], salt
: &[u8]) -> Result
<String
, Error
> {
22 #[link(name = "crypt")]
24 #[link_name = "crypt_r"]
26 key
: *const libc
::c_char
,
27 salt
: *const libc
::c_char
,
28 data
: *mut crypt_data
,
29 ) -> *mut libc
::c_char
;
32 let mut data
: crypt_data
= unsafe { std::mem::zeroed() }
;
33 for (i
, c
) in salt
.iter().take(data
.setting
.len() - 1).enumerate() {
34 data
.setting
[i
] = *c
as libc
::c_char
;
36 for (i
, c
) in password
.iter().take(data
.input
.len() - 1).enumerate() {
37 data
.input
[i
] = *c
as libc
::c_char
;
41 let status
= __crypt_r(
42 &data
.input
as *const _
,
43 &data
.setting
as *const _
,
47 bail
!("internal error: crypt_r returned null pointer");
49 CStr
::from_ptr(&data
.output
as *const _
)
51 Ok(String
::from(res
.to_str()?
))
54 pub fn encrypt_pw(password
: &str) -> Result
<String
, Error
> {
56 let salt
= proxmox
::sys
::linux
::random_data(8)?
;
57 let salt
= format
!("$5${}$", base64
::encode_config(&salt
, base64
::CRYPT
));
59 crypt(password
.as_bytes(), salt
.as_bytes())
62 pub fn verify_crypt_pw(password
: &str, enc_password
: &str) -> Result
<(), Error
> {
63 let verify
= crypt(password
.as_bytes(), enc_password
.as_bytes())?
;
64 if verify
!= enc_password
{
65 bail
!("invalid credentials");