mirror of
https://github.com/stalwartlabs/mail-server.git
synced 2025-01-26 17:58:24 +08:00
Fixed setting to allow disabling STARTTLS
This commit is contained in:
parent
dc960fba63
commit
0c95388a70
2 changed files with 167 additions and 135 deletions
|
@ -668,116 +668,63 @@ impl DeliveryAttempt {
|
|||
};
|
||||
|
||||
// Try starting TLS
|
||||
smtp_client.timeout = *queue_config.timeout.tls.eval(&envelope).await;
|
||||
match try_start_tls(
|
||||
smtp_client,
|
||||
tls_connector,
|
||||
envelope.mx,
|
||||
&capabilties,
|
||||
)
|
||||
.await
|
||||
{
|
||||
StartTlsResult::Success { smtp_client } => {
|
||||
// Verify DANE
|
||||
if let Some(dane_policy) = &dane_policy {
|
||||
if let Err(status) = dane_policy.verify(
|
||||
&span,
|
||||
envelope.mx,
|
||||
smtp_client.tls_connection().peer_certificates(),
|
||||
) {
|
||||
// Report DANE verification failure
|
||||
if let Some(tls_report) = &tls_report {
|
||||
core.schedule_report(TlsEvent {
|
||||
policy: dane_policy.into(),
|
||||
domain: envelope.domain.to_string(),
|
||||
failure: FailureDetails::new(
|
||||
ResultType::ValidationFailure,
|
||||
)
|
||||
.with_receiving_mx_hostname(envelope.mx)
|
||||
.with_receiving_ip(remote_ip)
|
||||
.with_failure_reason_code(
|
||||
"No matching certificates found.",
|
||||
)
|
||||
.into(),
|
||||
tls_record: tls_report.record.clone(),
|
||||
interval: tls_report.interval,
|
||||
})
|
||||
.await;
|
||||
}
|
||||
|
||||
last_status = status;
|
||||
continue 'next_host;
|
||||
}
|
||||
}
|
||||
|
||||
// Report TLS success
|
||||
if let Some(tls_report) = &tls_report {
|
||||
core.schedule_report(TlsEvent {
|
||||
policy: (&mta_sts_policy, &dane_policy).into(),
|
||||
domain: envelope.domain.to_string(),
|
||||
failure: None,
|
||||
tls_record: tls_report.record.clone(),
|
||||
interval: tls_report.interval,
|
||||
})
|
||||
.await;
|
||||
}
|
||||
|
||||
// Deliver message over TLS
|
||||
self.message
|
||||
.deliver(
|
||||
smtp_client,
|
||||
recipients
|
||||
.iter_mut()
|
||||
.filter(|r| r.domain_idx == domain_idx),
|
||||
params,
|
||||
)
|
||||
.await
|
||||
}
|
||||
StartTlsResult::Unavailable {
|
||||
response,
|
||||
if tls_strategy.try_start_tls() {
|
||||
smtp_client.timeout =
|
||||
*queue_config.timeout.tls.eval(&envelope).await;
|
||||
match try_start_tls(
|
||||
smtp_client,
|
||||
} => {
|
||||
// Report unavailable STARTTLS
|
||||
let reason =
|
||||
response.as_ref().map(|r| r.to_string()).unwrap_or_else(
|
||||
|| "STARTTLS was not advertised by host".to_string(),
|
||||
);
|
||||
tls_connector,
|
||||
envelope.mx,
|
||||
&capabilties,
|
||||
)
|
||||
.await
|
||||
{
|
||||
StartTlsResult::Success { smtp_client } => {
|
||||
// Verify DANE
|
||||
if let Some(dane_policy) = &dane_policy {
|
||||
if let Err(status) = dane_policy.verify(
|
||||
&span,
|
||||
envelope.mx,
|
||||
smtp_client.tls_connection().peer_certificates(),
|
||||
) {
|
||||
// Report DANE verification failure
|
||||
if let Some(tls_report) = &tls_report {
|
||||
core.schedule_report(TlsEvent {
|
||||
policy: dane_policy.into(),
|
||||
domain: envelope.domain.to_string(),
|
||||
failure: FailureDetails::new(
|
||||
ResultType::ValidationFailure,
|
||||
)
|
||||
.with_receiving_mx_hostname(envelope.mx)
|
||||
.with_receiving_ip(remote_ip)
|
||||
.with_failure_reason_code(
|
||||
"No matching certificates found.",
|
||||
)
|
||||
.into(),
|
||||
tls_record: tls_report.record.clone(),
|
||||
interval: tls_report.interval,
|
||||
})
|
||||
.await;
|
||||
}
|
||||
|
||||
tracing::info!(
|
||||
parent: &span,
|
||||
context = "tls",
|
||||
event = "unavailable",
|
||||
mx = envelope.mx,
|
||||
reason = reason,
|
||||
);
|
||||
last_status = status;
|
||||
continue 'next_host;
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(tls_report) = &tls_report {
|
||||
core.schedule_report(TlsEvent {
|
||||
policy: (&mta_sts_policy, &dane_policy).into(),
|
||||
domain: envelope.domain.to_string(),
|
||||
failure: FailureDetails::new(
|
||||
ResultType::StartTlsNotSupported,
|
||||
)
|
||||
.with_receiving_mx_hostname(envelope.mx)
|
||||
.with_receiving_ip(remote_ip)
|
||||
.with_failure_reason_code(reason)
|
||||
.into(),
|
||||
tls_record: tls_report.record.clone(),
|
||||
interval: tls_report.interval,
|
||||
})
|
||||
.await;
|
||||
}
|
||||
// Report TLS success
|
||||
if let Some(tls_report) = &tls_report {
|
||||
core.schedule_report(TlsEvent {
|
||||
policy: (&mta_sts_policy, &dane_policy).into(),
|
||||
domain: envelope.domain.to_string(),
|
||||
failure: None,
|
||||
tls_record: tls_report.record.clone(),
|
||||
interval: tls_report.interval,
|
||||
})
|
||||
.await;
|
||||
}
|
||||
|
||||
if tls_strategy.is_tls_required()
|
||||
|| (self.message.flags & MAIL_REQUIRETLS) != 0
|
||||
|| mta_sts_policy.is_some()
|
||||
|| dane_policy.is_some()
|
||||
{
|
||||
last_status =
|
||||
Status::from_starttls_error(envelope.mx, response);
|
||||
continue 'next_host;
|
||||
} else {
|
||||
// TLS is not required, proceed in plain-text
|
||||
// Deliver message over TLS
|
||||
self.message
|
||||
.deliver(
|
||||
smtp_client,
|
||||
|
@ -788,38 +735,115 @@ impl DeliveryAttempt {
|
|||
)
|
||||
.await
|
||||
}
|
||||
}
|
||||
StartTlsResult::Error { error } => {
|
||||
tracing::info!(
|
||||
parent: &span,
|
||||
context = "tls",
|
||||
event = "failed",
|
||||
mx = envelope.mx,
|
||||
error = %error,
|
||||
);
|
||||
StartTlsResult::Unavailable {
|
||||
response,
|
||||
smtp_client,
|
||||
} => {
|
||||
// Report unavailable STARTTLS
|
||||
let reason = response
|
||||
.as_ref()
|
||||
.map(|r| r.to_string())
|
||||
.unwrap_or_else(|| {
|
||||
"STARTTLS was not advertised by host".to_string()
|
||||
});
|
||||
|
||||
// Report TLS failure
|
||||
if let (Some(tls_report), mail_send::Error::Tls(error)) =
|
||||
(&tls_report, &error)
|
||||
{
|
||||
core.schedule_report(TlsEvent {
|
||||
policy: (&mta_sts_policy, &dane_policy).into(),
|
||||
domain: envelope.domain.to_string(),
|
||||
failure: FailureDetails::new(
|
||||
ResultType::CertificateNotTrusted,
|
||||
)
|
||||
.with_receiving_mx_hostname(envelope.mx)
|
||||
.with_receiving_ip(remote_ip)
|
||||
.with_failure_reason_code(error.to_string())
|
||||
.into(),
|
||||
tls_record: tls_report.record.clone(),
|
||||
interval: tls_report.interval,
|
||||
})
|
||||
.await;
|
||||
tracing::info!(
|
||||
parent: &span,
|
||||
context = "tls",
|
||||
event = "unavailable",
|
||||
mx = envelope.mx,
|
||||
reason = reason,
|
||||
);
|
||||
|
||||
if let Some(tls_report) = &tls_report {
|
||||
core.schedule_report(TlsEvent {
|
||||
policy: (&mta_sts_policy, &dane_policy).into(),
|
||||
domain: envelope.domain.to_string(),
|
||||
failure: FailureDetails::new(
|
||||
ResultType::StartTlsNotSupported,
|
||||
)
|
||||
.with_receiving_mx_hostname(envelope.mx)
|
||||
.with_receiving_ip(remote_ip)
|
||||
.with_failure_reason_code(reason)
|
||||
.into(),
|
||||
tls_record: tls_report.record.clone(),
|
||||
interval: tls_report.interval,
|
||||
})
|
||||
.await;
|
||||
}
|
||||
|
||||
if tls_strategy.is_tls_required()
|
||||
|| (self.message.flags & MAIL_REQUIRETLS) != 0
|
||||
|| mta_sts_policy.is_some()
|
||||
|| dane_policy.is_some()
|
||||
{
|
||||
last_status =
|
||||
Status::from_starttls_error(envelope.mx, response);
|
||||
continue 'next_host;
|
||||
} else {
|
||||
// TLS is not required, proceed in plain-text
|
||||
self.message
|
||||
.deliver(
|
||||
smtp_client,
|
||||
recipients
|
||||
.iter_mut()
|
||||
.filter(|r| r.domain_idx == domain_idx),
|
||||
params,
|
||||
)
|
||||
.await
|
||||
}
|
||||
}
|
||||
StartTlsResult::Error { error } => {
|
||||
tracing::info!(
|
||||
parent: &span,
|
||||
context = "tls",
|
||||
event = "failed",
|
||||
mx = envelope.mx,
|
||||
error = %error,
|
||||
);
|
||||
|
||||
// Report TLS failure
|
||||
if let (Some(tls_report), mail_send::Error::Tls(error)) =
|
||||
(&tls_report, &error)
|
||||
{
|
||||
core.schedule_report(TlsEvent {
|
||||
policy: (&mta_sts_policy, &dane_policy).into(),
|
||||
domain: envelope.domain.to_string(),
|
||||
failure: FailureDetails::new(
|
||||
ResultType::CertificateNotTrusted,
|
||||
)
|
||||
.with_receiving_mx_hostname(envelope.mx)
|
||||
.with_receiving_ip(remote_ip)
|
||||
.with_failure_reason_code(error.to_string())
|
||||
.into(),
|
||||
tls_record: tls_report.record.clone(),
|
||||
interval: tls_report.interval,
|
||||
})
|
||||
.await;
|
||||
}
|
||||
last_status = Status::from_tls_error(envelope.mx, error);
|
||||
continue 'next_host;
|
||||
}
|
||||
last_status = Status::from_tls_error(envelope.mx, error);
|
||||
continue 'next_host;
|
||||
}
|
||||
} else {
|
||||
// TLS has been disabled in the configuration file
|
||||
tracing::info!(
|
||||
parent: &span,
|
||||
context = "tls",
|
||||
event = "disabled",
|
||||
mx = envelope.mx,
|
||||
reason = "TLS is disabled for this host",
|
||||
);
|
||||
|
||||
self.message
|
||||
.deliver(
|
||||
smtp_client,
|
||||
recipients
|
||||
.iter_mut()
|
||||
.filter(|r| r.domain_idx == domain_idx),
|
||||
params,
|
||||
)
|
||||
.await
|
||||
}
|
||||
} else {
|
||||
// Start TLS
|
||||
|
|
|
@ -610,6 +610,14 @@ impl TlsStrategy {
|
|||
)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn try_start_tls(&self) -> bool {
|
||||
matches!(
|
||||
self.tls,
|
||||
RequireOptional::Require | RequireOptional::Optional
|
||||
)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn is_dane_required(&self) -> bool {
|
||||
matches!(self.dane, RequireOptional::Require)
|
||||
|
|
Loading…
Reference in a new issue