aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorQuentin Dufour <quentin@deuxfleurs.fr>2023-11-23 15:04:47 +0100
committerQuentin Dufour <quentin@deuxfleurs.fr>2023-11-23 15:04:47 +0100
commit14c7a96c282e20ff0d5343a7a378554f34983d21 (patch)
tree5bca5a6ecc0084a5a094445519e74491e241272f
parenta7c9d554f6523c384cc0a14a789e0c8d9070e605 (diff)
downloadaerogramme-14c7a96c282e20ff0d5343a7a378554f34983d21.tar.gz
aerogramme-14c7a96c282e20ff0d5343a7a378554f34983d21.zip
extract setup logic
-rw-r--r--src/future_rest_admin_api.txt174
-rw-r--r--src/mail/user.rs4
-rw-r--r--src/main.rs249
-rw-r--r--src/server.rs2
4 files changed, 179 insertions, 250 deletions
diff --git a/src/future_rest_admin_api.txt b/src/future_rest_admin_api.txt
new file mode 100644
index 0000000..19ece27
--- /dev/null
+++ b/src/future_rest_admin_api.txt
@@ -0,0 +1,174 @@
+ Command::FirstLogin {
+ creds,
+ user_secrets,
+ } => {
+ let creds = make_storage_creds(creds);
+ let user_secrets = make_user_secrets(user_secrets);
+
+ println!("Please enter your password for key decryption.");
+ println!("If you are using LDAP login, this must be your LDAP password.");
+ println!("If you are using the static login provider, enter any password, and this will also become your password for local IMAP access.");
+ let password = rpassword::prompt_password("Enter password: ")?;
+ let password_confirm = rpassword::prompt_password("Confirm password: ")?;
+ if password != password_confirm {
+ bail!("Passwords don't match.");
+ }
+
+ CryptoKeys::init(&creds, &user_secrets, &password).await?;
+
+ println!("");
+ println!("Cryptographic key setup is complete.");
+ println!("");
+ println!("If you are using the static login provider, add the following section to your .toml configuration file:");
+ println!("");
+ dump_config(&password, &creds);
+ }
+ Command::InitializeLocalKeys { creds } => {
+ let creds = make_storage_creds(creds);
+
+ println!("Please enter a password for local IMAP access.");
+ println!("This password is not used for key decryption, your keys will be printed below (do not lose them!)");
+ println!(
+ "If you plan on using LDAP login, stop right here and use `first-login` instead"
+ );
+ let password = rpassword::prompt_password("Enter password: ")?;
+ let password_confirm = rpassword::prompt_password("Confirm password: ")?;
+ if password != password_confirm {
+ bail!("Passwords don't match.");
+ }
+
+ let master = gen_key();
+ let (_, secret) = gen_keypair();
+ let keys = CryptoKeys::init_without_password(&creds, &master, &secret).await?;
+
+ println!("");
+ println!("Cryptographic key setup is complete.");
+ println!("");
+ println!("Add the following section to your .toml configuration file:");
+ println!("");
+ dump_config(&password, &creds);
+ dump_keys(&keys);
+ }
+ Command::AddPassword {
+ creds,
+ user_secrets,
+ gen,
+ } => {
+ let creds = make_storage_creds(creds);
+ let user_secrets = make_user_secrets(user_secrets);
+
+ let existing_password =
+ rpassword::prompt_password("Enter existing password to decrypt keys: ")?;
+ let new_password = if gen {
+ let password = base64::encode_config(
+ &u128::to_be_bytes(thread_rng().gen())[..10],
+ base64::URL_SAFE_NO_PAD,
+ );
+ println!("Your new password: {}", password);
+ println!("Keep it safe!");
+ password
+ } else {
+ let password = rpassword::prompt_password("Enter new password: ")?;
+ let password_confirm = rpassword::prompt_password("Confirm new password: ")?;
+ if password != password_confirm {
+ bail!("Passwords don't match.");
+ }
+ password
+ };
+
+ let keys = CryptoKeys::open(&creds, &user_secrets, &existing_password).await?;
+ keys.add_password(&creds, &user_secrets, &new_password)
+ .await?;
+ println!("");
+ println!("New password added successfully.");
+ }
+ Command::DeletePassword {
+ creds,
+ user_secrets,
+ allow_delete_all,
+ } => {
+ let creds = make_storage_creds(creds);
+ let user_secrets = make_user_secrets(user_secrets);
+
+ let existing_password = rpassword::prompt_password("Enter password to delete: ")?;
+
+ let keys = match allow_delete_all {
+ true => Some(CryptoKeys::open(&creds, &user_secrets, &existing_password).await?),
+ false => None,
+ };
+
+ CryptoKeys::delete_password(&creds, &existing_password, allow_delete_all).await?;
+
+ println!("");
+ println!("Password was deleted successfully.");
+
+ if let Some(keys) = keys {
+ println!("As a reminder, here are your cryptographic keys:");
+ dump_keys(&keys);
+ }
+ }
+ Command::ShowKeys {
+ creds,
+ user_secrets,
+ } => {
+ let creds = make_storage_creds(creds);
+ let user_secrets = make_user_secrets(user_secrets);
+
+ let existing_password = rpassword::prompt_password("Enter key decryption password: ")?;
+
+ let keys = CryptoKeys::open(&creds, &user_secrets, &existing_password).await?;
+ dump_keys(&keys);
+ }
+ }
+
+ Ok(())
+}
+
+fn make_storage_creds(c: StorageCredsArgs) -> StorageCredentials {
+ let s3_region = Region {
+ name: c.region.clone(),
+ endpoint: c.s3_endpoint,
+ };
+ let k2v_region = Region {
+ name: c.region,
+ endpoint: c.k2v_endpoint,
+ };
+ StorageCredentials {
+ k2v_region,
+ s3_region,
+ aws_access_key_id: c.aws_access_key_id,
+ aws_secret_access_key: c.aws_secret_access_key,
+ bucket: c.bucket,
+ }
+}
+
+fn make_user_secrets(c: UserSecretsArgs) -> UserSecrets {
+ UserSecrets {
+ user_secret: c.user_secret,
+ alternate_user_secrets: c
+ .alternate_user_secrets
+ .split(',')
+ .map(|x| x.trim())
+ .filter(|x| !x.is_empty())
+ .map(|x| x.to_string())
+ .collect(),
+ }
+}
+
+fn dump_config(password: &str, creds: &StorageCredentials) {
+ println!("[login_static.users.<username>]");
+ println!(
+ "password = \"{}\"",
+ hash_password(password).expect("unable to hash password")
+ );
+ println!("aws_access_key_id = \"{}\"", creds.aws_access_key_id);
+ println!(
+ "aws_secret_access_key = \"{}\"",
+ creds.aws_secret_access_key
+ );
+}
+
+fn dump_keys(keys: &CryptoKeys) {
+ println!("master_key = \"{}\"", base64::encode(&keys.master));
+ println!("secret_key = \"{}\"", base64::encode(&keys.secret));
+}
diff --git a/src/mail/user.rs b/src/mail/user.rs
index 7a3e5c7..bdfb30c 100644
--- a/src/mail/user.rs
+++ b/src/mail/user.rs
@@ -7,7 +7,7 @@ use serde::{Deserialize, Serialize};
use tokio::sync::watch;
use crate::cryptoblob::{open_deserialize, seal_serialize};
-use crate::login::{Credentials, StorageCredentials};
+use crate::login::Credentials;
use crate::mail::incoming::incoming_mail_watch_process;
use crate::mail::mailbox::Mailbox;
use crate::mail::uidindex::ImapUidvalidity;
@@ -309,7 +309,7 @@ impl User {
Some(x) => self.k2v.from_orphan(x).expect("Source & target must be same storage"),
None => self.k2v.row(MAILBOX_LIST_PK, MAILBOX_LIST_SK),
};
- rref.set_value(list_blob).push().await?;
+ rref.set_value(&list_blob).push().await?;
Ok(())
}
}
diff --git a/src/main.rs b/src/main.rs
index f395143..9efd9a5 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -14,13 +14,10 @@ mod storage;
use std::path::PathBuf;
-use anyhow::{bail, Result};
+use anyhow::Result;
use clap::{Parser, Subcommand};
-use rand::prelude::*;
use config::*;
-use cryptoblob::*;
-use login::{static_provider::*, *};
use server::Server;
#[derive(Parser, Debug)]
@@ -36,74 +33,7 @@ enum Command {
Server {
#[clap(short, long, env = "CONFIG_FILE", default_value = "aerogramme.toml")]
config_file: PathBuf,
- },
- /// TEST TEST TEST
- Test {
- #[clap(short, long, env = "CONFIG_FILE", default_value = "aerogramme.toml")]
- config_file: PathBuf,
- },
- /// Initializes key pairs for a user and adds a key decryption password
- FirstLogin {
- #[clap(flatten)]
- creds: StorageCredsArgs,
- #[clap(flatten)]
- user_secrets: UserSecretsArgs,
- },
- /// Initializes key pairs for a user and dumps keys to stdout for usage with static
- /// login provider
- InitializeLocalKeys {
- #[clap(flatten)]
- creds: StorageCredsArgs,
- },
- /// Adds a key decryption password for a user
- AddPassword {
- #[clap(flatten)]
- creds: StorageCredsArgs,
- #[clap(flatten)]
- user_secrets: UserSecretsArgs,
- /// Automatically generate password
- #[clap(short, long)]
- gen: bool,
- },
- /// Deletes a key decription password for a user
- DeletePassword {
- #[clap(flatten)]
- creds: StorageCredsArgs,
- #[clap(flatten)]
- user_secrets: UserSecretsArgs,
- /// Allow to delete all passwords
- #[clap(long)]
- allow_delete_all: bool,
- },
- /// Dumps all encryption keys for user
- ShowKeys {
- #[clap(flatten)]
- creds: StorageCredsArgs,
- #[clap(flatten)]
- user_secrets: UserSecretsArgs,
- },
-}
-
-#[derive(Parser, Debug)]
-struct StorageCredsArgs {
- /// Name of the region to use
- #[clap(short = 'r', long, env = "AWS_REGION")]
- region: String,
- /// Url of the endpoint to connect to for K2V
- #[clap(short = 'k', long, env = "K2V_ENDPOINT")]
- k2v_endpoint: String,
- /// Url of the endpoint to connect to for S3
- #[clap(short = 's', long, env = "S3_ENDPOINT")]
- s3_endpoint: String,
- /// Access key ID
- #[clap(short = 'A', long, env = "AWS_ACCESS_KEY_ID")]
- aws_access_key_id: String,
- /// Access key ID
- #[clap(short = 'S', long, env = "AWS_SECRET_ACCESS_KEY")]
- aws_secret_access_key: String,
- /// Bucket name
- #[clap(short = 'b', long, env = "BUCKET")]
- bucket: String,
+ }
}
#[derive(Parser, Debug)]
@@ -140,183 +70,8 @@ async fn main() -> Result<()> {
let server = Server::new(config).await?;
server.run().await?;
}
- Command::Test { config_file } => {
- let config = read_config(config_file)?;
-
- let _server = Server::new(config).await?;
- //server.test().await?;
- }
- Command::FirstLogin {
- creds,
- user_secrets,
- } => {
- let creds = make_storage_creds(creds);
- let user_secrets = make_user_secrets(user_secrets);
-
- println!("Please enter your password for key decryption.");
- println!("If you are using LDAP login, this must be your LDAP password.");
- println!("If you are using the static login provider, enter any password, and this will also become your password for local IMAP access.");
- let password = rpassword::prompt_password("Enter password: ")?;
- let password_confirm = rpassword::prompt_password("Confirm password: ")?;
- if password != password_confirm {
- bail!("Passwords don't match.");
- }
-
- CryptoKeys::init(&creds, &user_secrets, &password).await?;
-
- println!("");
- println!("Cryptographic key setup is complete.");
- println!("");
- println!("If you are using the static login provider, add the following section to your .toml configuration file:");
- println!("");
- dump_config(&password, &creds);
- }
- Command::InitializeLocalKeys { creds } => {
- let creds = make_storage_creds(creds);
-
- println!("Please enter a password for local IMAP access.");
- println!("This password is not used for key decryption, your keys will be printed below (do not lose them!)");
- println!(
- "If you plan on using LDAP login, stop right here and use `first-login` instead"
- );
- let password = rpassword::prompt_password("Enter password: ")?;
- let password_confirm = rpassword::prompt_password("Confirm password: ")?;
- if password != password_confirm {
- bail!("Passwords don't match.");
- }
-
- let master = gen_key();
- let (_, secret) = gen_keypair();
- let keys = CryptoKeys::init_without_password(&creds, &master, &secret).await?;
-
- println!("");
- println!("Cryptographic key setup is complete.");
- println!("");
- println!("Add the following section to your .toml configuration file:");
- println!("");
- dump_config(&password, &creds);
- dump_keys(&keys);
- }
- Command::AddPassword {
- creds,
- user_secrets,
- gen,
- } => {
- let creds = make_storage_creds(creds);
- let user_secrets = make_user_secrets(user_secrets);
-
- let existing_password =
- rpassword::prompt_password("Enter existing password to decrypt keys: ")?;
- let new_password = if gen {
- let password = base64::encode_config(
- &u128::to_be_bytes(thread_rng().gen())[..10],
- base64::URL_SAFE_NO_PAD,
- );
- println!("Your new password: {}", password);
- println!("Keep it safe!");
- password
- } else {
- let password = rpassword::prompt_password("Enter new password: ")?;
- let password_confirm = rpassword::prompt_password("Confirm new password: ")?;
- if password != password_confirm {
- bail!("Passwords don't match.");
- }
- password
- };
-
- let keys = CryptoKeys::open(&creds, &user_secrets, &existing_password).await?;
- keys.add_password(&creds, &user_secrets, &new_password)
- .await?;
- println!("");
- println!("New password added successfully.");
- }
- Command::DeletePassword {
- creds,
- user_secrets,
- allow_delete_all,
- } => {
- let creds = make_storage_creds(creds);
- let user_secrets = make_user_secrets(user_secrets);
-
- let existing_password = rpassword::prompt_password("Enter password to delete: ")?;
-
- let keys = match allow_delete_all {
- true => Some(CryptoKeys::open(&creds, &user_secrets, &existing_password).await?),
- false => None,
- };
-
- CryptoKeys::delete_password(&creds, &existing_password, allow_delete_all).await?;
-
- println!("");
- println!("Password was deleted successfully.");
-
- if let Some(keys) = keys {
- println!("As a reminder, here are your cryptographic keys:");
- dump_keys(&keys);
- }
- }
- Command::ShowKeys {
- creds,
- user_secrets,
- } => {
- let creds = make_storage_creds(creds);
- let user_secrets = make_user_secrets(user_secrets);
-
- let existing_password = rpassword::prompt_password("Enter key decryption password: ")?;
-
- let keys = CryptoKeys::open(&creds, &user_secrets, &existing_password).await?;
- dump_keys(&keys);
- }
}
Ok(())
}
-fn make_storage_creds(c: StorageCredsArgs) -> StorageCredentials {
- let s3_region = Region {
- name: c.region.clone(),
- endpoint: c.s3_endpoint,
- };
- let k2v_region = Region {
- name: c.region,
- endpoint: c.k2v_endpoint,
- };
- StorageCredentials {
- k2v_region,
- s3_region,
- aws_access_key_id: c.aws_access_key_id,
- aws_secret_access_key: c.aws_secret_access_key,
- bucket: c.bucket,
- }
-}
-
-fn make_user_secrets(c: UserSecretsArgs) -> UserSecrets {
- UserSecrets {
- user_secret: c.user_secret,
- alternate_user_secrets: c
- .alternate_user_secrets
- .split(',')
- .map(|x| x.trim())
- .filter(|x| !x.is_empty())
- .map(|x| x.to_string())
- .collect(),
- }
-}
-
-fn dump_config(password: &str, creds: &StorageCredentials) {
- println!("[login_static.users.<username>]");
- println!(
- "password = \"{}\"",
- hash_password(password).expect("unable to hash password")
- );
- println!("aws_access_key_id = \"{}\"", creds.aws_access_key_id);
- println!(
- "aws_secret_access_key = \"{}\"",
- creds.aws_secret_access_key
- );
-}
-
-fn dump_keys(keys: &CryptoKeys) {
- println!("master_key = \"{}\"", base64::encode(&keys.master));
- println!("secret_key = \"{}\"", base64::encode(&keys.secret));
-}
diff --git a/src/server.rs b/src/server.rs
index 3485a61..eca11ad 100644
--- a/src/server.rs
+++ b/src/server.rs
@@ -9,7 +9,7 @@ use crate::config::*;
use crate::imap;
use crate::lmtp::*;
use crate::login::ArcLoginProvider;
-use crate::login::{ldap_provider::*, static_provider::*, Region};
+use crate::login::{ldap_provider::*, static_provider::*};
pub struct Server {
lmtp_server: Option<Arc<LmtpServer>>,