Fixed DKIM public key format

This commit is contained in:
mdecimus 2024-04-08 11:09:02 +02:00
parent 44f531ecf9
commit 23edd40fd0
8 changed files with 62 additions and 27 deletions

1
Cargo.lock generated
View file

@ -2884,6 +2884,7 @@ dependencies = [
"mime",
"nlp",
"p256",
"pkcs8",
"rand",
"rasn",
"rasn-cms",

View file

@ -185,8 +185,8 @@ async fn oauth(url: &str) -> Credentials {
#[derive(Deserialize)]
#[serde(untagged)]
pub enum Response<T> {
Data { data: T },
Error(ManagementApiError),
Data { data: T },
}
#[derive(Deserialize)]
@ -283,11 +283,11 @@ impl Client {
}
}
match serde_json::from_slice::<Response<R>>(
&response.bytes().await.unwrap_result("fetch bytes"),
)
.unwrap_result("deserialize response")
{
let bytes = response.bytes().await.unwrap_result("fetch bytes");
match serde_json::from_slice::<Response<R>>(&bytes).unwrap_result(&format!(
"deserialize response {}",
String::from_utf8_lossy(bytes.as_ref())
)) {
Response::Data { data } => Some(data),
Response::Error(error) => {
eprintln!("Request failed: {error})");

View file

@ -27,6 +27,8 @@ use prettytable::{Attr, Cell, Row, Table};
use reqwest::Method;
use serde_json::Value;
use crate::modules::List;
use super::cli::{Client, DomainCommands};
impl DomainCommands {
@ -70,15 +72,15 @@ impl DomainCommands {
};
let domains = client
.http_request::<Vec<String>, String>(Method::GET, query.as_ref(), None)
.http_request::<List<String>, String>(Method::GET, query.as_ref(), None)
.await;
if !domains.is_empty() {
if !domains.items.is_empty() {
let mut table = Table::new();
table.add_row(Row::new(vec![
Cell::new("Domain Name").with_style(Attr::Bold)
]));
for domain in &domains {
for domain in &domains.items {
table.add_row(Row::new(vec![Cell::new(domain)]));
}
@ -89,8 +91,8 @@ impl DomainCommands {
eprintln!(
"\n\n{} domain{} found.\n",
domains.len(),
if domains.len() == 1 { "" } else { "s" }
domains.total,
if domains.total == 1 { "" } else { "s" }
);
}
}

View file

@ -93,8 +93,8 @@ impl Tracers {
level,
appender,
ansi: config
.property_or_default(("tracer", id, "ansi"), "true")
.unwrap_or(true),
.property_or_default(("tracer", id, "ansi"), "false")
.unwrap_or(false),
});
}
}

View file

@ -103,6 +103,7 @@ impl WebAdminManager {
{
"html" => "text/html",
"css" => "text/css",
"wasm" => "application/wasm",
"js" => "application/javascript",
"json" => "application/json",
"png" => "image/png",

View file

@ -80,7 +80,7 @@ impl<T: SessionStream> Session<T> {
// Send continuation response
self.write_bytes(b"+ Idling, send 'DONE' to stop.\r\n".to_vec())
.await?;
tracing::debug!(parent: &self.span, event = "stat", context = "idle", "Starting IDLE.");
tracing::debug!(parent: &self.span, event = "start", context = "idle", "Starting IDLE.");
let mut buf = vec![0; 1024];
loop {
tokio::select! {

View file

@ -47,6 +47,7 @@ aes = "0.8.3"
cbc = { version = "0.1.2", features = ["alloc"] }
sequoia-openpgp = { version = "1.16", default-features = false, features = ["crypto-rust", "allow-experimental-crypto", "allow-variable-time-crypto"] }
rand = "0.8.5"
pkcs8 = { version = "0.10.2", features = ["alloc", "std"] }
rasn = "0.10"
rasn-cms = "0.10"
rasn-pkix = "0.10"

View file

@ -32,6 +32,12 @@ use mail_auth::{
};
use mail_builder::encoders::base64::base64_encode;
use mail_parser::DateTime;
use pkcs8::{
der::{asn1::BitString, Encode},
spki::{AlgorithmIdentifier, SubjectPublicKeyInfoOwned},
Document,
};
use rsa::pkcs1::DecodeRsaPublicKey;
use serde::{Deserialize, Serialize};
use serde_json::json;
use store::write::now;
@ -238,20 +244,44 @@ impl JMAP {
pub fn obtain_dkim_public_key(algo: Algorithm, pk: &str) -> Result<String, &'static str> {
match simple_pem_parse(pk) {
Some(der) => match algo {
Algorithm::Rsa => match RsaKey::<Sha256>::from_der(&der) {
Ok(pk) => Ok(String::from_utf8(
base64_encode(&pk.public_key()).unwrap_or_default(),
)
.unwrap_or_default()),
Err(_) => Err("Failed to read RSA DER"),
},
Algorithm::Ed25519 => match Ed25519Key::from_pkcs8_der(&der) {
Ok(pk) => Ok(String::from_utf8(
base64_encode(&pk.public_key()).unwrap_or_default(),
)
.unwrap_or_default()),
Err(_) => Err("Failed to read ED25519 PKCS#8 DER"),
Algorithm::Rsa => match RsaKey::<Sha256>::from_der(&der).and_then(|key| {
Document::from_pkcs1_der(&key.public_key())
.map_err(|err| mail_auth::Error::CryptoError(err.to_string()))
}) {
Ok(pk) => Ok(
String::from_utf8(base64_encode(pk.as_bytes()).unwrap_or_default())
.unwrap_or_default(),
),
Err(err) => {
tracing::debug!("Failed to read RSA DER: {err}");
Err("Failed to read RSA DER")
}
},
Algorithm::Ed25519 => {
match Ed25519Key::from_pkcs8_maybe_unchecked_der(&der).and_then(|key| {
BitString::from_bytes(&key.public_key())
.and_then(|subject_public_key| {
SubjectPublicKeyInfoOwned {
algorithm: AlgorithmIdentifier {
oid: "1.3.101.112".parse().unwrap(),
parameters: None,
},
subject_public_key,
}
.to_der()
})
.map_err(|err| mail_auth::Error::CryptoError(err.to_string()))
}) {
Ok(pk) => Ok(String::from_utf8(base64_encode(&pk).unwrap_or_default())
.unwrap_or_default()),
Err(err) => {
tracing::debug!("Failed to read ED25519 DER: {err}");
Err("Failed to read ED25519 DER")
}
}
}
},
None => Err("Failed to decode private key"),
}