0
0
Fork 0
mirror of https://git.verdigado.com/NB-Public/simple-wkd.git synced 2024-12-05 02:52:50 +01:00

Add allowed domains

This commit is contained in:
Delta1925 2023-04-15 21:08:24 +02:00
parent 6d65c5ffc3
commit e621a735f5
No known key found for this signature in database
GPG key ID: 1C21ACE44193CB25
6 changed files with 38 additions and 25 deletions

View file

@ -1,12 +1,7 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head></head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body> <body>
<div style="width: 100%; text-align: center; display: flex; flex-direction: column;"> <div style="width: 100%; text-align: center; display: flex; flex-direction: column;">

View file

@ -2,6 +2,7 @@ variant = "Advanced"
root_folder = "data" root_folder = "data"
max_age = 900 max_age = 900
cleanup_interval = 21600 cleanup_interval = 21600
allowed_domains = ["example.org", "example.com"]
port = 8080 port = 8080
external_url = "http://localhost:8080" external_url = "http://localhost:8080"

View file

@ -3,32 +3,34 @@ use thiserror::Error;
#[derive(Error, Debug, Clone, Copy)] #[derive(Error, Debug, Clone, Copy)]
pub enum Error { pub enum Error {
#[error("EC1: Cert is invalid")] #[error("(0x00) Cert is invalid")]
InvalidCert, InvalidCert,
#[error("EP1: Error while parsing cert")] #[error("(0x01) Error while parsing cert")]
ParseCert, ParseCert,
#[error("EP2: Error while parsing an E-Mail address")] #[error("(0x02) Error while parsing an E-Mail address")]
ParseEmail, ParseEmail,
#[error("EM1: There is no pending request associated to this token")] #[error("(0x03) There is no pending request associated to this token")]
MissingPending, MissingPending,
#[error("EM2: Requested key does not exist")] #[error("(0x04) Requested key does not exist")]
MissingKey, MissingKey,
#[error("EM3: No E-Mail found in the certificate")] #[error("(0x05) No E-Mail found in the certificate")]
MissingMail, MissingMail,
#[error("EE1: Error while sending the E-Mail")] #[error("(0x06) Error while sending the E-Mail")]
SendMail, SendMail,
#[error("ES1: rror while serializing data")] #[error("(0x07) rror while serializing data")]
SerializeData, SerializeData,
#[error("ES2: Error while deserializing data")] #[error("(0x08) Error while deserializing data")]
DeserializeData, DeserializeData,
#[error("ES3: The file is inaccessible")] #[error("(0x09) The file is inaccessible")]
Inaccessible, Inaccessible,
#[error("ES4: Error while adding a key to the wkd")] #[error("(0x0A) Error while adding a key to the wkd")]
AddingKey, AddingKey,
#[error("EG1: Error while generating the wkd path")] #[error("(0x0B) Error while generating the wkd path")]
PathGeneration, PathGeneration,
#[error("EG2: Error while generating the email")] #[error("(0x0C) Error while generating the email")]
MailGeneration, MailGeneration,
#[error("(0x0D) Wrong email domain")]
WrongDomain,
} }
impl actix_web::ResponseError for Error { impl actix_web::ResponseError for Error {
@ -36,6 +38,7 @@ impl actix_web::ResponseError for Error {
match self { match self {
Self::MissingPending => StatusCode::from_u16(404).unwrap(), Self::MissingPending => StatusCode::from_u16(404).unwrap(),
Self::MissingKey => StatusCode::from_u16(404).unwrap(), Self::MissingKey => StatusCode::from_u16(404).unwrap(),
Self::WrongDomain => StatusCode::from_u16(401).unwrap(),
_ => StatusCode::from_u16(500).unwrap(), _ => StatusCode::from_u16(500).unwrap(),
} }
} }

View file

@ -5,6 +5,7 @@ mod settings;
mod utils; mod utils;
use crate::settings::SETTINGS; use crate::settings::SETTINGS;
use crate::utils::is_email_allowed;
use self::confirmation::{confirm_action, send_confirmation_email}; use self::confirmation::{confirm_action, send_confirmation_email};
use self::management::{clean_stale, store_pending_addition, store_pending_deletion, Action}; 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<Pem>) -> Result<String> { async fn submit(pem: web::Form<Pem>) -> Result<String> {
let cert = parse_pem(&pem.key)?; let cert = parse_pem(&pem.key)?;
let email = get_email_from_cert(&cert)?; let email = get_email_from_cert(&cert)?;
is_email_allowed(&email)?;
let token = gen_random_token(); let token = gen_random_token();
store_pending_addition(pem.key.clone(), &email, &token)?; store_pending_addition(pem.key.clone(), &email, &token)?;
send_confirmation_email(&email, &Action::Add, &token)?; send_confirmation_email(&email, &Action::Add, &token)?;

View file

@ -13,6 +13,7 @@ pub struct Settings {
pub root_folder: String, pub root_folder: String,
pub max_age: i64, pub max_age: i64,
pub cleanup_interval: u64, pub cleanup_interval: u64,
pub allowed_domains: Vec<String>,
pub port: u16, pub port: u16,
pub external_url: Url, pub external_url: Url,
pub mail_settings: MailSettings, pub mail_settings: MailSettings,

View file

@ -4,7 +4,7 @@ use crate::settings::SETTINGS;
use flexi_logger::{style, DeferredNow, FileSpec, FlexiLoggerError, Logger, LoggerHandle, Record}; use flexi_logger::{style, DeferredNow, FileSpec, FlexiLoggerError, Logger, LoggerHandle, Record};
use rand::{distributions::Alphanumeric, thread_rng, Rng}; use rand::{distributions::Alphanumeric, thread_rng, Rng};
use sequoia_net::wkd::Url; 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}; use std::path::{Path, PathBuf};
#[macro_export] #[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<Cert, Error> { pub fn parse_pem(pemfile: &str) -> Result<Cert, Error> {
let cert = match sequoia_openpgp::Cert::from_bytes(pemfile.as_bytes()) { let cert = match sequoia_openpgp::Cert::from_bytes(pemfile.as_bytes()) {
Ok(cert) => cert, Ok(cert) => cert,
Err(_) => return Err(Error::ParseCert), Err(_) => return Err(Error::ParseCert),
}; };
let policy = NullPolicy::new(); let policy = StandardPolicy::new();
if cert.with_policy(&policy, None).is_err() { if cert.with_policy(&policy, None).is_err() {
return Err(Error::InvalidCert) return Err(Error::InvalidCert);
} };
Ok(cert) Ok(cert)
} }
@ -32,10 +43,10 @@ pub fn gen_random_token() -> String {
} }
pub fn get_email_from_cert(cert: &Cert) -> Result<String, Error> { pub fn get_email_from_cert(cert: &Cert) -> Result<String, Error> {
let policy = NullPolicy::new(); let policy = StandardPolicy::new();
let validcert = match cert.with_policy(&policy, None) { let validcert = match cert.with_policy(&policy, None) {
Ok(validcert) => validcert, Ok(validcert) => validcert,
Err(_) => return Err(Error::InvalidCert) Err(_) => return Err(Error::InvalidCert),
}; };
let userid_opt = match validcert.primary_userid() { let userid_opt = match validcert.primary_userid() {
Ok(userid_opt) => userid_opt, Ok(userid_opt) => userid_opt,