Added OPTIONS handler for CORS pre-flight requests

This commit is contained in:
Mauro D 2023-08-13 15:16:23 +02:00
parent d4fe318812
commit 9660f1f9e1
22 changed files with 66 additions and 36 deletions

View file

@ -72,7 +72,13 @@ pub async fn parse_jmap_request(
let (_in_flight, access_token) = match jmap.authenticate_headers(&req, remote_ip).await
{
Ok(Some(session)) => session,
Ok(None) => return RequestError::unauthorized().into_http_response(),
Ok(None) => {
return if req.method() != Method::OPTIONS {
RequestError::unauthorized().into_http_response()
} else {
().into_http_response()
}
}
Err(err) => return err.into_http_response(),
};
@ -164,6 +170,9 @@ pub async fn parse_jmap_request(
return upgrade_websocket_connection(jmap, req, access_token, instance.clone())
.await;
}
(_, &Method::OPTIONS) => {
return ().into_http_response();
}
_ => (),
}
}
@ -192,6 +201,9 @@ pub async fn parse_jmap_request(
Err(err) => err.into_http_response(),
};
}
(_, &Method::OPTIONS) => {
return ().into_http_response();
}
_ => (),
},
"auth" => {
@ -240,6 +252,9 @@ pub async fn parse_jmap_request(
Err(err) => err.into_http_response(),
}
}
(_, &Method::OPTIONS) => {
return ().into_http_response();
}
_ => (),
}
}
@ -610,3 +625,16 @@ impl ToHttpResponse for HtmlResponse {
.unwrap()
}
}
impl ToHttpResponse for () {
fn into_http_response(self) -> HttpResponse {
hyper::Response::builder()
.status(StatusCode::NO_CONTENT)
.body(
Full::new(Bytes::new())
.map_err(|never| match never {})
.boxed(),
)
.unwrap()
}
}

View file

@ -175,7 +175,7 @@ impl<T: AsyncWrite + AsyncRead + Unpin + IsTls> Session<T> {
.into_value(self)
.map(|s| s.into_owned())
{
let mut mail_from = self.data.mail_from.as_mut().unwrap();
let mail_from = self.data.mail_from.as_mut().unwrap();
if new_address.contains('@') {
mail_from.address_lcase = new_address.to_lowercase();
mail_from.domain = mail_from.address_lcase.domain_part().to_string();

View file

@ -124,7 +124,7 @@ impl<T: AsyncWrite + AsyncRead + Unpin> Session<T> {
.into_value(self)
.map(|s| s.into_owned())
{
let mut rcpt = self.data.rcpt_to.last_mut().unwrap();
let rcpt = self.data.rcpt_to.last_mut().unwrap();
if new_address.contains('@') {
rcpt.address_lcase = new_address.to_lowercase();
rcpt.domain = rcpt.address_lcase.domain_part().to_string();

View file

@ -105,7 +105,9 @@ private-key = "file://./tests/resources/tls_privatekey.pem"
directory = "local"
[jmap.http]
headers = ["Access-Control-Allow-Origin: *", "Access-Control-Allow-Methods: POST, GET, HEAD"]
headers = ["Access-Control-Allow-Origin: *",
"Access-Control-Allow-Methods: POST, GET, HEAD, OPTIONS",
"Access-Control-Allow-Headers: *"]
[jmap.protocol]
set.max-objects = 100000

View file

@ -61,7 +61,7 @@ async fn auth() {
let mut ctx = ConfigContext::new(&[]);
ctx.directory = Config::parse(DIRECTORY).unwrap().parse_directory().unwrap();
let mut config = &mut core.session.config.auth;
let config = &mut core.session.config.auth;
config.require = r"[{if = 'remote-ip', eq = '10.0.0.1', then = true},
{else = false}]"

View file

@ -80,12 +80,12 @@ async fn data() {
// Create temp dir for queue
let mut qr = core.init_test_queue("smtp_data_test");
let directory = Config::parse(DIRECTORY).unwrap().parse_directory().unwrap();
let mut config = &mut core.session.config.rcpt;
let config = &mut core.session.config.rcpt;
config.directory = IfBlock::new(Some(MaybeDynValue::Static(
directory.directories.get("local").unwrap().clone(),
)));
let mut config = &mut core.session.config;
let config = &mut core.session.config;
config.data.add_auth_results = "[{if = 'remote-ip', eq = '10.0.0.3', then = true},
{else = false}]"
.parse_if(&ConfigContext::new(&[]));

View file

@ -135,12 +135,12 @@ async fn dmarc() {
// Create report channels
let mut rr = core.init_test_report();
let directory = Config::parse(DIRECTORY).unwrap().parse_directory().unwrap();
let mut config = &mut core.session.config.rcpt;
let config = &mut core.session.config.rcpt;
config.directory = IfBlock::new(Some(MaybeDynValue::Static(
directory.directories.get("local").unwrap().clone(),
)));
let mut config = &mut core.session.config;
let config = &mut core.session.config;
config.data.add_auth_results = IfBlock::new(true);
config.data.add_date = IfBlock::new(true);
config.data.add_message_id = IfBlock::new(true);
@ -148,7 +148,7 @@ async fn dmarc() {
config.data.add_return_path = IfBlock::new(true);
config.data.add_received_spf = IfBlock::new(true);
let mut config = &mut core.report.config;
let config = &mut core.report.config;
config.dkim.send = IfBlock::new(Some(Rate {
requests: 1,
period: Duration::from_secs(1),
@ -157,7 +157,7 @@ async fn dmarc() {
config.spf.send = config.dkim.send.clone();
config.dmarc_aggregate.send = IfBlock::new(AggregateFrequency::Daily);
let mut config = &mut core.mail_auth;
let config = &mut core.mail_auth;
config.spf.verify_ehlo = "[{if = 'remote-ip', eq = '10.0.0.2', then = 'strict'},
{ else = 'relaxed' }]"
.parse_if(&ConfigContext::new(&[]));
@ -168,7 +168,7 @@ async fn dmarc() {
{ else = 'strict' }]"
.parse_if(&ConfigContext::new(&[]));
let mut config = &mut core.report.config;
let config = &mut core.report.config;
config.spf.sign = "['rsa']"
.parse_if::<Vec<DynValue<EnvelopeKey>>>(&ctx)
.map_if_block(&ctx.signers, "", "")

View file

@ -65,7 +65,7 @@ async fn dnsrbl() {
);
let mut qr = core.init_test_queue("smtp_dnsrbl_test");
let mut config = &mut core.mail_auth.dnsbl;
let config = &mut core.mail_auth.dnsbl;
config.ip_lookup = vec![
"zen.spamhaus.org".to_string(),
"bl.spamcop.net".to_string(),

View file

@ -48,7 +48,7 @@ async fn ehlo() {
Instant::now() + Duration::from_secs(5),
);
let mut config = &mut core.session.config;
let config = &mut core.session.config;
config.data.max_message_size = r"[{if = 'remote-ip', eq = '10.0.0.1', then = 1024},
{else = 2048}]"
.parse_if(&ConfigContext::new(&[]));

View file

@ -37,7 +37,7 @@ use smtp::{
#[tokio::test]
async fn limits() {
let mut core = SMTP::test();
let mut config = &mut core.session.config;
let config = &mut core.session.config;
config.transfer_limit = r"[{if = 'remote-ip', eq = '10.0.0.1', then = 10},
{else = 1024}]"
.parse_if(&ConfigContext::new(&[]));

View file

@ -67,7 +67,7 @@ async fn mail() {
Instant::now() + Duration::from_secs(5),
);
let mut config = &mut core.session.config;
let config = &mut core.session.config;
config.ehlo.require = IfBlock::new(true);
core.mail_auth.spf.verify_ehlo = IfBlock::new(VerifyStrategy::Relaxed);
core.mail_auth.spf.verify_mail_from = r"[{if = 'remote-ip', eq = '10.0.0.2', then = 'strict'},

View file

@ -68,7 +68,7 @@ async fn milter_session() {
tokio::time::sleep(Duration::from_millis(100)).await;
let mut core = SMTP::test();
let mut qr = core.init_test_queue("smtp_milter_test");
let mut config = &mut core.session.config;
let config = &mut core.session.config;
config.rcpt.relay = IfBlock::new(true);
config.data.milters = r#"[[session.data.milter]]
hostname = "127.0.0.1"

View file

@ -72,9 +72,9 @@ domains = ["foobar.org"]
async fn rcpt() {
let mut core = SMTP::test();
let mut config_ext = &mut core.session.config.extensions;
let config_ext = &mut core.session.config.extensions;
let directory = Config::parse(DIRECTORY).unwrap().parse_directory().unwrap();
let mut config = &mut core.session.config.rcpt;
let config = &mut core.session.config.rcpt;
config.directory = IfBlock::new(Some(MaybeDynValue::Static(
directory.directories.get("local").unwrap().clone(),
)));

View file

@ -155,12 +155,12 @@ async fn sign_and_seal() {
);
let directory = Config::parse(DIRECTORY).unwrap().parse_directory().unwrap();
let mut config = &mut core.session.config.rcpt;
let config = &mut core.session.config.rcpt;
config.directory = IfBlock::new(Some(MaybeDynValue::Static(
directory.directories.get("local").unwrap().clone(),
)));
let mut config = &mut core.session.config;
let config = &mut core.session.config;
config.data.add_auth_results = IfBlock::new(true);
config.data.add_date = IfBlock::new(true);
config.data.add_message_id = IfBlock::new(true);
@ -168,7 +168,7 @@ async fn sign_and_seal() {
config.data.add_return_path = IfBlock::new(true);
config.data.add_received_spf = IfBlock::new(true);
let mut config = &mut core.mail_auth;
let config = &mut core.mail_auth;
let ctx = ConfigContext::new(&[]).parse_signatures();
config.spf.verify_ehlo = IfBlock::new(VerifyStrategy::Relaxed);
config.spf.verify_mail_from = config.spf.verify_ehlo.clone();

View file

@ -32,7 +32,7 @@ use smtp::{
#[tokio::test]
async fn throttle_inbound() {
let mut core = SMTP::test();
let mut config = &mut core.session.config;
let config = &mut core.session.config;
config.throttle.connect = r"[[throttle]]
match = {if = 'remote-ip', eq = '10.0.0.1'}
key = 'remote-ip'

View file

@ -66,12 +66,12 @@ async fn vrfy_expn() {
let ctx = ConfigContext::new(&[]);
let directory = Config::parse(DIRECTORY).unwrap().parse_directory().unwrap();
let mut config = &mut core.session.config.rcpt;
let config = &mut core.session.config.rcpt;
config.directory = IfBlock::new(Some(MaybeDynValue::Static(
directory.directories.get("local").unwrap().clone(),
)));
let mut config = &mut core.session.config.extensions;
let config = &mut core.session.config.extensions;
config.vrfy = r"[{if = 'remote-ip', eq = '10.0.0.1', then = true},
{else = false}]"
.parse_if(&ctx);

View file

@ -113,7 +113,7 @@ async fn lookup_sql() {
}
// Enable AUTH
let mut config = &mut core.session.config.auth;
let config = &mut core.session.config.auth;
config.directory = r"'sql'"
.parse_if::<Option<DynValue<EnvelopeKey>>>(&ctx)
.map_if_block(&ctx.directory.directories, "", "")
@ -122,7 +122,7 @@ async fn lookup_sql() {
config.errors_wait = IfBlock::new(Duration::from_millis(5));
// Enable VRFY/EXPN/RCPT
let mut config = &mut core.session.config.rcpt;
let config = &mut core.session.config.rcpt;
config.directory = r"'sql'"
.parse_if::<Option<DynValue<EnvelopeKey>>>(&ctx)
.map_if_block(&ctx.directory.directories, "", "")

View file

@ -90,7 +90,7 @@ async fn lmtp_delivery() {
core.session.config.rcpt.relay = IfBlock::new(true);
core.session.config.rcpt.max_recipients = IfBlock::new(100);
core.session.config.extensions.dsn = IfBlock::new(true);
let mut config = &mut core.queue.config;
let config = &mut core.queue.config;
config.retry = IfBlock::new(vec![Duration::from_millis(100)]);
config.notify = "[{if = 'rcpt-domain', eq = 'foobar.org', then = ['100ms', '200ms']},
{else = ['100ms']}]"

View file

@ -108,7 +108,7 @@ async fn smtp_delivery() {
core.session.config.rcpt.relay = IfBlock::new(true);
core.session.config.rcpt.max_recipients = IfBlock::new(100);
core.session.config.extensions.dsn = IfBlock::new(true);
let mut config = &mut core.queue.config;
let config = &mut core.queue.config;
config.retry = IfBlock::new(vec![Duration::from_millis(100)]);
config.notify = "[{if = 'rcpt-domain', eq = 'foobar.org', then = ['100ms', '200ms']},
{else = ['100ms']}]"

View file

@ -108,7 +108,7 @@ async fn generate_dsn() {
// Load config
let mut core = SMTP::test();
let ctx = ConfigContext::new(&[]).parse_signatures();
let mut config = &mut core.queue.config.dsn;
let config = &mut core.queue.config.dsn;
config.sign = "['rsa']"
.parse_if::<Vec<DynValue<EnvelopeKey>>>(&ctx)
.map_if_block(&ctx.signers, "", "")

View file

@ -51,12 +51,12 @@ async fn queue_retry() {
// Create temp dir for queue
let mut qr = core.init_test_queue("smtp_queue_retry_test");
let mut config = &mut core.session.config.rcpt;
let config = &mut core.session.config.rcpt;
config.relay = IfBlock::new(true);
let mut config = &mut core.session.config.extensions;
let config = &mut core.session.config.extensions;
config.deliver_by = IfBlock::new(Some(Duration::from_secs(86400)));
config.future_release = IfBlock::new(Some(Duration::from_secs(86400)));
let mut config = &mut core.queue.config;
let config = &mut core.queue.config;
config.retry = IfBlock::new(vec![
Duration::from_millis(100),
Duration::from_millis(200),

View file

@ -39,11 +39,11 @@ async fn report_analyze() {
let mut qr = core.init_test_queue("smtp_analyze_report_test");
let report_dir = make_temp_dir("smtp_report_incoming", true);
let mut config = &mut core.session.config.rcpt;
let config = &mut core.session.config.rcpt;
config.relay = IfBlock::new(true);
let mut config = &mut core.session.config.data;
let config = &mut core.session.config.data;
config.max_messages = IfBlock::new(1024);
let mut config = &mut core.report.config.analysis;
let config = &mut core.report.config.analysis;
config.addresses = vec![
AddressMatch::StartsWith("reports@".to_string()),
AddressMatch::EndsWith("@dmarc.foobar.org".to_string()),