2 use lazy_static
::lazy_static
;
4 use openssl
::rsa
::{Rsa}
;
5 use openssl
::pkey
::{PKey, Public, Private}
;
8 use std
::path
::PathBuf
;
12 fs
::{file_get_contents, replace_file, CreateOptions}
,
15 fn compute_csrf_secret_digest(
21 let mut hasher
= sha
::Sha256
::new();
22 let data
= format
!("{:08X}:{}:", timestamp
, username
);
23 hasher
.update(data
.as_bytes());
24 hasher
.update(secret
);
26 base64
::encode_config(&hasher
.finish(), base64
::STANDARD_NO_PAD
)
29 pub fn assemble_csrf_prevention_token(
34 let epoch
= std
::time
::SystemTime
::now().duration_since(
35 std
::time
::SystemTime
::UNIX_EPOCH
).unwrap().as_secs() as i64;
37 let digest
= compute_csrf_secret_digest(epoch
, secret
, username
);
39 format
!("{:08X}:{}", epoch
, digest
)
42 pub fn verify_csrf_prevention_token(
48 ) -> Result
<i64, Error
> {
50 use std
::collections
::VecDeque
;
52 let mut parts
: VecDeque
<&str> = token
.split('
:'
).collect();
57 bail
!("format error - wrong number of parts.");
60 let timestamp
= parts
.pop_front().unwrap();
61 let sig
= parts
.pop_front().unwrap();
63 let ttime
= i64::from_str_radix(timestamp
, 16).
64 map_err(|err
| format_err
!("timestamp format error - {}", err
))?
;
66 let digest
= compute_csrf_secret_digest(ttime
, secret
, username
);
69 bail
!("invalid signature.");
72 let now
= std
::time
::SystemTime
::now().duration_since(
73 std
::time
::SystemTime
::UNIX_EPOCH
)?
.as_secs() as i64;
75 let age
= now
- ttime
;
77 bail
!("timestamp newer than expected.");
81 bail
!("timestamp too old.");
85 }).map_err(|err
| format_err
!("invalid csrf token - {}", err
))
88 pub fn generate_csrf_key() -> Result
<(), Error
> {
90 let path
= PathBuf
::from(configdir
!("/csrf.key"));
92 if path
.exists() { return Ok(()); }
94 let rsa
= Rsa
::generate(2048).unwrap();
96 let pem
= rsa
.private_key_to_pem()?
;
98 use nix
::sys
::stat
::Mode
;
100 let backup_user
= crate::backup
::backup_user()?
;
106 .perm(Mode
::from_bits_truncate(0o0640))
107 .owner(nix
::unistd
::ROOT
)
108 .group(backup_user
.gid
),
114 pub fn generate_auth_key() -> Result
<(), Error
> {
116 let priv_path
= PathBuf
::from(configdir
!("/authkey.key"));
118 let mut public_path
= priv_path
.clone();
119 public_path
.set_extension("pub");
121 if priv_path
.exists() && public_path
.exists() { return Ok(()); }
123 let rsa
= Rsa
::generate(4096).unwrap();
125 let priv_pem
= rsa
.private_key_to_pem()?
;
127 use nix
::sys
::stat
::Mode
;
130 &priv_path
, &priv_pem
, CreateOptions
::new().perm(Mode
::from_bits_truncate(0o0600)))?
;
132 let public_pem
= rsa
.public_key_to_pem()?
;
134 let backup_user
= crate::backup
::backup_user()?
;
140 .perm(Mode
::from_bits_truncate(0o0640))
141 .owner(nix
::unistd
::ROOT
)
142 .group(backup_user
.gid
),
148 pub fn csrf_secret() -> &'
static [u8] {
151 static ref SECRET
: Vec
<u8> =
152 file_get_contents(configdir
!("/csrf.key")).unwrap();
158 fn load_private_auth_key() -> Result
<PKey
<Private
>, Error
> {
160 let pem
= file_get_contents(configdir
!("/authkey.key"))?
;
161 let rsa
= Rsa
::private_key_from_pem(&pem
)?
;
162 let key
= PKey
::from_rsa(rsa
)?
;
167 pub fn private_auth_key() -> &'
static PKey
<Private
> {
170 static ref KEY
: PKey
<Private
> = load_private_auth_key().unwrap();
176 fn load_public_auth_key() -> Result
<PKey
<Public
>, Error
> {
178 let pem
= file_get_contents(configdir
!("/authkey.pub"))?
;
179 let rsa
= Rsa
::public_key_from_pem(&pem
)?
;
180 let key
= PKey
::from_rsa(rsa
)?
;
185 pub fn public_auth_key() -> &'
static PKey
<Public
> {
188 static ref KEY
: PKey
<Public
> = load_public_auth_key().unwrap();