Skip to content

Commit

Permalink
Use env var to load cert/keys.
Browse files Browse the repository at this point in the history
* Change dotenv to dotenvy.
* Handle CRLF only data.
* Clean up code.
  • Loading branch information
anvie committed Jul 16, 2023
1 parent 46b5541 commit 584e8e8
Show file tree
Hide file tree
Showing 6 changed files with 36 additions and 82 deletions.
8 changes: 4 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ version = "0.0.1"
anyhow = "1.0.71"
async-std = {version = "1.12.0", features = ["attributes"]}
clap = {version = "4.0.13", features = ["derive"]}
dotenv = "0.15.0"
env_logger = "0.10.0"
imap-codec = "0.10"
log = "0.4"
Expand All @@ -24,4 +23,5 @@ rustls_19 = {package = "rustls", version = "0.19"}
rustls-pemfile = "1.0"
rustls_old = {package = "rustls", version = "0.20.8"}
tokio-rustls = "0.24.1"
dotenvy = "0.15.7"

5 changes: 5 additions & 0 deletions src/cert.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
use log::debug;
use rustls::{Certificate, PrivateKey};
use std::fs::File;
use std::io::BufReader;

pub(crate) fn load_certificates_from_pem(
path: &str,
) -> std::io::Result<Vec<Certificate>> {
debug!("loading cert from `{}`", path);

let file = File::open(path)?;
let mut reader = BufReader::new(file);
let certs = rustls_pemfile::certs(&mut reader)?;
Expand Down Expand Up @@ -34,6 +37,8 @@ pub(crate) fn load_private_key_from_file_pkcs(
pub(crate) fn load_private_key_from_file(
path: &str,
) -> Result<PrivateKey, Box<dyn std::error::Error>> {
debug!("Loading private key from `{}`", path);

let file = File::open(&path)?;
let mut reader = BufReader::new(file);
let mut keys = rustls_pemfile::rsa_private_keys(&mut reader)?;
Expand Down
5 changes: 5 additions & 0 deletions src/imap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ where
{
let mut imap_sock = IMAPServ::new(socket);

// if only CRLF ignore
if buf.len() == 2 && buf[0] == 13 && buf[1] == 10 {
return Ok(CommandPipe::Noop);
}

let cmd = command_decode(buf)?;

debug!(":< {}", &cmd.body.name());
Expand Down
1 change: 1 addition & 0 deletions src/imap_serv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use imap_codec::{command::Command, core::Tag};
pub enum CommandPipe<'a> {
// next and prev command
Next(Command<'a>, Option<Command<'a>>),
Noop,
Quit,
}

Expand Down
97 changes: 20 additions & 77 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,24 +13,23 @@

use clap::Parser;

use dotenvy::dotenv;
use tokio_rustls::TlsAcceptor;

use log::debug;
use result::Result;
use rustls::ServerConfig;
// use samotop::io::tls::RustlsProvider;
// use samotop::mail::smime::Accounts;
use serde::Deserialize;

use std::sync::Arc;
use std::{fs, io::ErrorKind, process::exit};
use std::{env, fs, io::ErrorKind, process::exit};

use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt};
use tokio::net::TcpListener;

mod cert;
mod handlers;
mod error;
mod handlers;
mod imap;
mod imap_serv;
mod result;
Expand All @@ -46,12 +45,6 @@ use crate::cert::{load_certificates_from_pem, load_private_key_from_file};
struct Args {
#[arg(short, long, default_value = "default.conf")]
config: String,

#[arg(short, long, default_value = "false")]
imap: bool,

#[arg(short, long, default_value = "false")]
smtp: bool,
}
#[derive(Deserialize, Debug)]
struct Config {
Expand All @@ -73,11 +66,10 @@ fn default_smtp_port() -> u16 {
// #[async_std::main]
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
dotenv::dotenv().ok();
dotenv()?;
env_logger::init();

let args = Args::parse();
println!("Value for config: {}", args.config);

let config: Config = match fs::read_to_string(&args.config) {
Ok(config) => toml::from_str(&config).unwrap(),
Expand All @@ -90,22 +82,10 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
}
}
};
println!("Config: {:#?}", config);

// start_smtp_server(config).await

if args.imap && args.smtp {
println!("Please specify either --imap or --smtp");
exit(2);
}

if args.imap {
let _ = start_imap_server(config).await;
// } else if args.smtp {
// start_smtp_server(config).await;
} else {
println!("Please specify either --imap or --smtp");
exit(2);
if let Err(err) = start_imap_server(config).await {
eprintln!("Error: {}", err);
exit(3);
}

Ok(())
Expand All @@ -115,15 +95,19 @@ async fn start_imap_server(
conf: Config,
) -> Result<(), Box<dyn std::error::Error>> {
let addr = format!("127.0.0.1:{}", conf.imap_port);
println!("Starting IMAP server at port {}...", conf.imap_port);

let listener = TcpListener::bind(addr).await?;

let cert_chain =
load_certificates_from_pem("keys/mail.nu.id/certificate.crt")
.expect("No cert file provided");
let mut keys =
vec![load_private_key_from_file("keys/mail.nu.id/private.key")
.expect("No private key provided")];
let cert_chain = load_certificates_from_pem(
&env::var("CAFILE").expect("No CAFILE env var"),
)
.expect("No cert file provided");

let mut keys = vec![load_private_key_from_file(
&env::var("KEYFILE").expect("No KEYFILE env var"),
)
.expect("No private key provided")];

// let mut keys = rsa_private_keys(key_file).unwrap();
// config.set_single_cert(cert_chain, keys.remove(0)).unwrap();

Expand All @@ -135,6 +119,8 @@ async fn start_imap_server(

let acceptor = TlsAcceptor::from(Arc::new(config));

println!("Starting IMAP server at port {}...", conf.imap_port);

loop {
let (socket, _) = listener.accept().await?;

Expand Down Expand Up @@ -190,11 +176,6 @@ async fn start_imap_server(
CommandPipe::Quit => return,
_ => {}
}

// if let Err(e) = socket.write_all(&buf[0..n]).await {
// eprintln!("Failed to write to socket; err = {:?}", e);
// return;
// }
}
});
}
Expand Down Expand Up @@ -223,41 +204,3 @@ where

Ok(())
}

// async fn start_smtp_server(conf: Config) {
// println!("Starting SMTP server at port {}...", conf.smtp_port);

// use samotop::mail::{spf::Spf, *};
// use samotop::server::*;
// use samotop::smtp::*;

// let mut cert_store = rustls_19::RootCertStore::empty();
// cert_store
// .add_pem_file(&mut BufReader::new(File::open("cert.pem").unwrap()))
// .unwrap();
// let key_der = &mut BufReader::new(File::open("key.pem").unwrap());
// let mut key_der = rustls_19::internal::pemfile::pkcs8_private_keys(key_der).unwrap();

// let mut tls_config = rustls_19::ServerConfig::new(rustls_19::NoClientAuth::new());
// tls_config
// .set_single_cert(
// vec![rustls_19::Certificate(cert_store.get_subjects()[0].0.clone())],
// key_der.remove(0),
// )
// .unwrap();

// let acceptor = async_tls_old::TlsAcceptor::from(Arc::new(tls_config));

// let mail = Builder
// + Accounts::new(PathBuf::from("accounts"))
// + SessionLogger
// + Spf
// + EsmtpStartTls.with(SmtpParser, RustlsProvider::from(acceptor.clone()));
// // + Esmtp.with(SmtpParser);

// let mail = mail.build();

// let srv = TcpServer::on(format!("localhost:{}", conf.smtp_port)).serve(mail);

// srv.await.expect("success")
// }

0 comments on commit 584e8e8

Please sign in to comment.