sptp/certificate_request/
mod.rs

1use std::str::FromStr;
2
3use argon2::{password_hash::PasswordHashString, Argon2, PasswordHash, PasswordVerifier};
4use rcgen::{Certificate, CertificateParams, CertificateSigningRequest, KeyPair};
5use serde::{Deserialize, Serialize};
6use time::{ext::NumericalDuration, OffsetDateTime};
7
8use crate::{error::{self, FulfillRequest}, message::package::Package};
9
10#[derive(Serialize, Deserialize)]
11pub struct CertificateRequest {
12    certificate_request_pem: String,
13}
14
15impl Package for CertificateRequest {
16    fn pack(self) -> Result<String, error::PackToMessageError> {
17        ron::to_string(&self).expect("This serializes hard coded values, it should always work")[..]
18            .pack()
19    }
20}
21
22impl CertificateRequest {
23    pub fn new(certificate_request_pem: String) -> Self {
24        Self {
25            certificate_request_pem,
26        }
27    }
28
29    pub fn fulfill_request(
30        self,
31        ca_certificate_pem: &String,
32        ca_certificate_private_key_pem: &String,
33        duration: i64,
34    ) -> Result<String, FulfillRequest> {
35        let mut certificate_signing_request =
36            CertificateSigningRequest::from_pem(&self.certificate_request_pem)?;
37
38        let time_now = OffsetDateTime::now_utc();
39
40        certificate_signing_request.params.not_after = time_now.saturating_add(duration.days());
41        certificate_signing_request.params.not_before = time_now;
42
43        let ca_certificate_key = KeyPair::from_pem(&ca_certificate_private_key_pem)?;
44
45        let ca_certificate_params =
46            CertificateParams::from_ca_cert_pem(&ca_certificate_pem, ca_certificate_key)?;
47        let ca_certificate = Certificate::from_params(ca_certificate_params)?;
48
49        let signed_certificate_str =
50            certificate_signing_request.serialize_pem_with_signer(&ca_certificate)?;
51
52        Ok(signed_certificate_str)
53    }
54}
55
56#[derive(Serialize, Deserialize)]
57pub struct PasswordAuthorizationRequest {
58    username: String,
59    password: String,
60}
61
62impl Package for PasswordAuthorizationRequest {
63    fn pack(self) -> Result<String, error::PackToMessageError> {
64        ron::to_string(&self).expect("This serializes hard coded values, it should always work")[..]
65            .pack()
66    }
67}
68
69impl PasswordAuthorizationRequest {
70    pub fn new(username: String, password: String) -> Self {
71        Self { username, password }
72    }
73    pub fn verify_request(&self, allowed_users: &Vec<User>) -> bool {
74        allowed_users.iter().any(|user| {
75            (user.username == self.username)
76                && Argon2::default()
77                    .verify_password(
78                        self.password.as_bytes(),
79                        &user.password_hash.password_hash(),
80                    )
81                    .is_ok()
82        })
83    }
84}
85
86pub struct User {
87    username: String,
88    password_hash: PasswordHashString,
89}
90
91impl User {
92    pub fn new(username: String, password_hash: PasswordHashString) -> Self {
93        Self {
94            username,
95            password_hash,
96        }
97    }
98}
99impl FromStr for User {
100    type Err = error::UserParsing;
101
102    fn from_str(s: &str) -> Result<Self, Self::Err> {
103        let split_string: Vec<_> = s.split_ascii_whitespace().collect();
104        if split_string.len() != 2 {
105            if split_string.len() < 2 {
106                return Err(error::UserParsing::ToShort());
107            } else {
108                return Err(error::UserParsing::ToLong());
109            }
110        } else {
111            let username = split_string.get(0).expect("We checked the length above");
112            let password_hash_string = split_string.get(1).expect("We checked the length above");
113            let password_hash = PasswordHash::new(password_hash_string)?;
114            Ok(User {
115                username: username.to_string(),
116                password_hash: password_hash.serialize(),
117            })
118        }
119    }
120}
121
122#[cfg(test)]
123mod tests {}