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", "mime",
"nlp", "nlp",
"p256", "p256",
"pkcs8",
"rand", "rand",
"rasn", "rasn",
"rasn-cms", "rasn-cms",

View file

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

View file

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

View file

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

View file

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

View file

@ -80,7 +80,7 @@ impl<T: SessionStream> Session<T> {
// Send continuation response // Send continuation response
self.write_bytes(b"+ Idling, send 'DONE' to stop.\r\n".to_vec()) self.write_bytes(b"+ Idling, send 'DONE' to stop.\r\n".to_vec())
.await?; .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]; let mut buf = vec![0; 1024];
loop { loop {
tokio::select! { tokio::select! {

View file

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

View file

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