From d9b722397c2cd3af83923d29f774ffba7c5a9b22 Mon Sep 17 00:00:00 2001 From: Delta1925 Date: Sat, 20 May 2023 23:28:17 +0200 Subject: [PATCH] Check if uploaded key contains secret material --- backend/src/confirmation.rs | 7 ++++--- backend/src/errors.rs | 3 +++ backend/src/main.rs | 6 +++++- backend/src/utils.rs | 11 +++++------ 4 files changed, 17 insertions(+), 10 deletions(-) diff --git a/backend/src/confirmation.rs b/backend/src/confirmation.rs index 6617dba..08d52e7 100644 --- a/backend/src/confirmation.rs +++ b/backend/src/confirmation.rs @@ -6,7 +6,7 @@ use crate::errors::SpecialErrors; use crate::management::{delete_key, Action, Pending}; use crate::settings::{MAILER, SETTINGS}; use crate::utils::{get_email_from_cert, insert_key, parse_pem, read_file}; -use crate::{log_err, pending_path}; +use crate::{log_err, pending_path, validate_cert}; use anyhow::Result; use lettre::{AsyncTransport, Message}; @@ -25,8 +25,9 @@ pub fn confirm_action(token: &str) -> Result<(Action, String)> { let address = match key.action() { Action::Add => { let cert = parse_pem(key.data())?; - let email = get_email_from_cert(&cert)?; - log_err!(insert_key(&cert), warn)?; + let validcert = validate_cert!(cert)?; + let email = get_email_from_cert(&validcert)?; + log_err!(insert_key(&validcert), warn)?; email } Action::Delete => { diff --git a/backend/src/errors.rs b/backend/src/errors.rs index 903c5d9..fde8436 100644 --- a/backend/src/errors.rs +++ b/backend/src/errors.rs @@ -36,6 +36,8 @@ macro_rules! log_err { #[derive(Debug, DeriveError)] pub enum SpecialErrors { + #[error("Uploaded certificate contains a secret key!")] + ContainsSecret, #[error("Could not find any primay user email in the keyblock!")] EmailMissing, #[error("The request had expired!")] @@ -92,6 +94,7 @@ impl ResponseError for CompatErr { match self { Self::AnyhowErr(_) => StatusCode::INTERNAL_SERVER_ERROR, Self::SpecialErr(error) => match error { + SpecialErrors::ContainsSecret => StatusCode::BAD_REQUEST, SpecialErrors::ExpiredRequest => StatusCode::BAD_REQUEST, SpecialErrors::InexistingUser => StatusCode::NOT_FOUND, SpecialErrors::InvalidCert => StatusCode::BAD_REQUEST, diff --git a/backend/src/main.rs b/backend/src/main.rs index 255d1f3..c201749 100644 --- a/backend/src/main.rs +++ b/backend/src/main.rs @@ -101,7 +101,11 @@ async fn index(req: HttpRequest) -> Result { #[post("/api/submit")] async fn submit(pem: web::Form) -> Result { let cert = parse_pem(&pem.key)?; - let email = get_email_from_cert(&cert)?; + let validcert = validate_cert!(cert)?; + if validcert.is_tsk() { + Err(SpecialErrors::ContainsSecret)? + } + let email = get_email_from_cert(&validcert)?; debug!("Handling user {} request to add a key...", email); is_email_allowed(&email)?; let token = gen_random_token(); diff --git a/backend/src/utils.rs b/backend/src/utils.rs index b4a9f80..05d8fa6 100644 --- a/backend/src/utils.rs +++ b/backend/src/utils.rs @@ -15,6 +15,7 @@ use flexi_logger::{style, DeferredNow, FileSpec, FlexiLoggerError, Logger, Logge use log::debug; use log::error; use rand::{distributions::Alphanumeric, thread_rng, Rng}; +use sequoia_openpgp::cert::ValidCert; use sequoia_openpgp::serialize::Marshal; use sequoia_openpgp::types::HashAlgorithm; use sequoia_openpgp::{parse::Parse, Cert}; @@ -59,13 +60,12 @@ pub fn email_to_file_path(email: &str) -> Result { Ok(PathBuf::from(ROOT_FOLDER).join(directory)) } -pub fn insert_key(cert: &Cert) -> Result<()> { - let validcert = validate_cert!(cert)?; +pub fn insert_key(cert: &ValidCert) -> Result<()> { let path = email_to_file_path(&get_email_from_cert(cert)?)?; fs::create_dir_all(path.parent().unwrap())?; let mut file = fs::File::create(&path)?; - validcert.export(&mut file)?; + cert.export(&mut file)?; fs::OpenOptions::new() .write(true) @@ -115,9 +115,8 @@ pub fn gen_random_token() -> String { (0..10).map(|_| rng.sample(Alphanumeric) as char).collect() } -pub fn get_email_from_cert(cert: &Cert) -> Result { - let validcert = validate_cert!(cert)?; - let userid_opt = log_err!(validcert.primary_userid(), debug)?; +pub fn get_email_from_cert(cert: &ValidCert) -> Result { + let userid_opt = log_err!(cert.primary_userid(), debug)?; let email_opt = userid_opt.email()?; match email_opt { Some(email) => Ok(email),