diff --git a/assets/mail-template.html b/assets/mail-template.html index 446d229..de5faee 100644 --- a/assets/mail-template.html +++ b/assets/mail-template.html @@ -1,12 +1,7 @@ - - - - - Document - +
diff --git a/example.config.toml b/example.config.toml index 0c46953..d0d98cc 100644 --- a/example.config.toml +++ b/example.config.toml @@ -2,6 +2,7 @@ variant = "Advanced" root_folder = "data" max_age = 900 cleanup_interval = 21600 +allowed_domains = ["example.org", "example.com"] port = 8080 external_url = "http://localhost:8080" diff --git a/src/errors.rs b/src/errors.rs index e1f54b0..059eb31 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -3,32 +3,34 @@ use thiserror::Error; #[derive(Error, Debug, Clone, Copy)] pub enum Error { - #[error("EC1: Cert is invalid")] + #[error("(0x00) Cert is invalid")] InvalidCert, - #[error("EP1: Error while parsing cert")] + #[error("(0x01) Error while parsing cert")] ParseCert, - #[error("EP2: Error while parsing an E-Mail address")] + #[error("(0x02) Error while parsing an E-Mail address")] ParseEmail, - #[error("EM1: There is no pending request associated to this token")] + #[error("(0x03) There is no pending request associated to this token")] MissingPending, - #[error("EM2: Requested key does not exist")] + #[error("(0x04) Requested key does not exist")] MissingKey, - #[error("EM3: No E-Mail found in the certificate")] + #[error("(0x05) No E-Mail found in the certificate")] MissingMail, - #[error("EE1: Error while sending the E-Mail")] + #[error("(0x06) Error while sending the E-Mail")] SendMail, - #[error("ES1: rror while serializing data")] + #[error("(0x07) rror while serializing data")] SerializeData, - #[error("ES2: Error while deserializing data")] + #[error("(0x08) Error while deserializing data")] DeserializeData, - #[error("ES3: The file is inaccessible")] + #[error("(0x09) The file is inaccessible")] Inaccessible, - #[error("ES4: Error while adding a key to the wkd")] + #[error("(0x0A) Error while adding a key to the wkd")] AddingKey, - #[error("EG1: Error while generating the wkd path")] + #[error("(0x0B) Error while generating the wkd path")] PathGeneration, - #[error("EG2: Error while generating the email")] + #[error("(0x0C) Error while generating the email")] MailGeneration, + #[error("(0x0D) Wrong email domain")] + WrongDomain, } impl actix_web::ResponseError for Error { @@ -36,6 +38,7 @@ impl actix_web::ResponseError for Error { match self { Self::MissingPending => StatusCode::from_u16(404).unwrap(), Self::MissingKey => StatusCode::from_u16(404).unwrap(), + Self::WrongDomain => StatusCode::from_u16(401).unwrap(), _ => StatusCode::from_u16(500).unwrap(), } } diff --git a/src/main.rs b/src/main.rs index ccc8ce0..427c032 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,6 +5,7 @@ mod settings; mod utils; use crate::settings::SETTINGS; +use crate::utils::is_email_allowed; use self::confirmation::{confirm_action, send_confirmation_email}; use self::management::{clean_stale, store_pending_addition, store_pending_deletion, Action}; @@ -69,6 +70,7 @@ async fn main() -> std::io::Result<()> { async fn submit(pem: web::Form) -> Result { let cert = parse_pem(&pem.key)?; let email = get_email_from_cert(&cert)?; + is_email_allowed(&email)?; let token = gen_random_token(); store_pending_addition(pem.key.clone(), &email, &token)?; send_confirmation_email(&email, &Action::Add, &token)?; diff --git a/src/settings.rs b/src/settings.rs index a5382d5..08ebc1d 100644 --- a/src/settings.rs +++ b/src/settings.rs @@ -13,6 +13,7 @@ pub struct Settings { pub root_folder: String, pub max_age: i64, pub cleanup_interval: u64, + pub allowed_domains: Vec, pub port: u16, pub external_url: Url, pub mail_settings: MailSettings, diff --git a/src/utils.rs b/src/utils.rs index 6001073..1ccce72 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -4,7 +4,7 @@ use crate::settings::SETTINGS; use flexi_logger::{style, DeferredNow, FileSpec, FlexiLoggerError, Logger, LoggerHandle, Record}; use rand::{distributions::Alphanumeric, thread_rng, Rng}; use sequoia_net::wkd::Url; -use sequoia_openpgp::{parse::Parse, Cert, policy::NullPolicy}; +use sequoia_openpgp::{parse::Parse, policy::StandardPolicy, Cert}; use std::path::{Path, PathBuf}; #[macro_export] @@ -14,15 +14,26 @@ macro_rules! pending_path { }; } +pub fn is_email_allowed(email: &str) -> Result<(), Error> { + let allowed = match email.split('@').last() { + Some(domain) => SETTINGS.allowed_domains.contains(&domain.to_string()), + None => return Err(Error::ParseEmail), + }; + if !allowed { + return Err(Error::WrongDomain); + } + Ok(()) +} + pub fn parse_pem(pemfile: &str) -> Result { let cert = match sequoia_openpgp::Cert::from_bytes(pemfile.as_bytes()) { Ok(cert) => cert, Err(_) => return Err(Error::ParseCert), }; - let policy = NullPolicy::new(); + let policy = StandardPolicy::new(); if cert.with_policy(&policy, None).is_err() { - return Err(Error::InvalidCert) - } + return Err(Error::InvalidCert); + }; Ok(cert) } @@ -32,10 +43,10 @@ pub fn gen_random_token() -> String { } pub fn get_email_from_cert(cert: &Cert) -> Result { - let policy = NullPolicy::new(); + let policy = StandardPolicy::new(); let validcert = match cert.with_policy(&policy, None) { Ok(validcert) => validcert, - Err(_) => return Err(Error::InvalidCert) + Err(_) => return Err(Error::InvalidCert), }; let userid_opt = match validcert.primary_userid() { Ok(userid_opt) => userid_opt,