]>
git.proxmox.com Git - proxmox-backup.git/blob - src/auth_helpers.rs
4 use lazy_static
::lazy_static
;
6 use openssl
::rsa
::{Rsa}
;
7 use openssl
::pkey
::{PKey, Public, Private}
;
10 use std
::path
::PathBuf
;
12 fn compute_csrf_secret_digest(
18 let mut hasher
= sha
::Sha256
::new();
19 let data
= format
!("{:08X}:{}:", timestamp
, username
);
20 hasher
.update(data
.as_bytes());
21 hasher
.update(secret
);
23 base64
::encode_config(&hasher
.finish(), base64
::STANDARD_NO_PAD
)
26 pub fn assemble_csrf_prevention_token(
31 let epoch
= std
::time
::SystemTime
::now().duration_since(
32 std
::time
::SystemTime
::UNIX_EPOCH
).unwrap().as_secs() as i64;
34 let digest
= compute_csrf_secret_digest(epoch
, secret
, username
);
36 format
!("{:08X}:{}", epoch
, digest
)
39 pub fn verify_csrf_prevention_token(
45 ) -> Result
<i64, Error
> {
47 use std
::collections
::VecDeque
;
49 let mut parts
: VecDeque
<&str> = token
.split('
:'
).collect();
54 bail
!("format error - wrong number of parts.");
57 let timestamp
= parts
.pop_front().unwrap();
58 let sig
= parts
.pop_front().unwrap();
60 let ttime
= i64::from_str_radix(timestamp
, 16).
61 map_err(|err
| format_err
!("timestamp format error - {}", err
))?
;
63 let digest
= compute_csrf_secret_digest(ttime
, secret
, username
);
66 bail
!("invalid signature.");
69 let now
= std
::time
::SystemTime
::now().duration_since(
70 std
::time
::SystemTime
::UNIX_EPOCH
)?
.as_secs() as i64;
72 let age
= now
- ttime
;
74 bail
!("timestamp newer than expected.");
78 bail
!("timestamp too old.");
82 }).map_err(|err
| format_err
!("invalid csrf token - {}", err
))
85 pub fn generate_csrf_key() -> Result
<(), Error
> {
87 let path
= PathBuf
::from(configdir
!("/csrf.key"));
89 if path
.exists() { return Ok(()); }
91 let rsa
= Rsa
::generate(2048).unwrap();
93 let pem
= rsa
.private_key_to_pem()?
;
95 use nix
::sys
::stat
::Mode
;
97 let (_
, backup_gid
) = tools
::getpwnam_ugid("backup")?
;
98 let uid
= Some(nix
::unistd
::ROOT
);
99 let gid
= Some(nix
::unistd
::Gid
::from_raw(backup_gid
));
101 tools
::file_set_contents_full(
102 &path
, &pem
, Some(Mode
::from_bits_truncate(0o0640)), uid
, gid
)?
;
107 pub fn generate_auth_key() -> Result
<(), Error
> {
109 let priv_path
= PathBuf
::from(configdir
!("/authkey.key"));
111 let mut public_path
= priv_path
.clone();
112 public_path
.set_extension("pub");
114 if priv_path
.exists() && public_path
.exists() { return Ok(()); }
116 let rsa
= Rsa
::generate(4096).unwrap();
118 let priv_pem
= rsa
.private_key_to_pem()?
;
120 use nix
::sys
::stat
::Mode
;
122 tools
::file_set_contents(
123 &priv_path
, &priv_pem
, Some(Mode
::from_bits_truncate(0o0600)))?
;
126 let public_pem
= rsa
.public_key_to_pem()?
;
128 tools
::file_set_contents(&public_path
, &public_pem
, None
)?
;
133 pub fn csrf_secret() -> &'
static [u8] {
136 static ref SECRET
: Vec
<u8> =
137 tools
::file_get_contents(configdir
!("/csrf.key")).unwrap();
143 fn load_private_auth_key() -> Result
<PKey
<Private
>, Error
> {
145 let pem
= tools
::file_get_contents(configdir
!("/authkey.key"))?
;
146 let rsa
= Rsa
::private_key_from_pem(&pem
)?
;
147 let key
= PKey
::from_rsa(rsa
)?
;
152 pub fn private_auth_key() -> &'
static PKey
<Private
> {
155 static ref KEY
: PKey
<Private
> = load_private_auth_key().unwrap();
161 fn load_public_auth_key() -> Result
<PKey
<Public
>, Error
> {
163 let pem
= tools
::file_get_contents(configdir
!("/authkey.pub"))?
;
164 let rsa
= Rsa
::public_key_from_pem(&pem
)?
;
165 let key
= PKey
::from_rsa(rsa
)?
;
170 pub fn public_auth_key() -> &'
static PKey
<Public
> {
173 static ref KEY
: PKey
<Public
> = load_public_auth_key().unwrap();