use crate::certificates::parser::CertificateInfo;
use std::collections::HashSet;
pub struct DnsOnlyMode;
impl DnsOnlyMode {
pub fn extract_domains(cert: &CertificateInfo) -> Vec<String> {
let mut domains = HashSet::new();
if !cert.subject.is_empty()
&& let Some(cn) = Self::extract_cn(&cert.subject)
{
domains.insert(Self::normalize_domain(&cn));
}
for san in &cert.san {
let normalized = Self::normalize_domain(san);
domains.insert(normalized);
}
let mut result: Vec<String> = domains.into_iter().collect();
result.sort();
result
}
fn extract_cn(subject: &str) -> Option<String> {
for part in subject.split(',') {
let part = part.trim();
if let Some(cn) = part.strip_prefix("CN=") {
return Some(cn.to_string());
}
}
None
}
fn normalize_domain(domain: &str) -> String {
let mut normalized = domain.to_lowercase().trim().to_string();
if normalized.starts_with("dns:") {
normalized = normalized[4..].to_string();
}
if normalized.starts_with("*.") {
normalized = normalized[2..].to_string();
}
normalized.trim().to_string()
}
pub fn format_output(leaf_cert: &CertificateInfo) -> String {
let domains = Self::extract_domains(leaf_cert);
if domains.is_empty() {
String::new()
} else {
domains.join("\n")
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_normalize_domain() {
assert_eq!(DnsOnlyMode::normalize_domain("Example.COM"), "example.com");
assert_eq!(
DnsOnlyMode::normalize_domain(" example.com "),
"example.com"
);
assert_eq!(
DnsOnlyMode::normalize_domain("*.example.com"),
"example.com"
);
assert_eq!(
DnsOnlyMode::normalize_domain("*.EXAMPLE.COM"),
"example.com"
);
assert_eq!(
DnsOnlyMode::normalize_domain("DNS:example.com"),
"example.com"
);
assert_eq!(
DnsOnlyMode::normalize_domain("DNS:*.EXAMPLE.COM "),
"example.com"
);
}
#[test]
fn test_extract_cn() {
assert_eq!(
DnsOnlyMode::extract_cn("CN=example.com,O=Org,C=US"),
Some("example.com".to_string())
);
assert_eq!(
DnsOnlyMode::extract_cn("C=US, O=Org, CN=example.com"),
Some("example.com".to_string())
);
assert_eq!(DnsOnlyMode::extract_cn("O=Org,C=US"), None);
assert_eq!(
DnsOnlyMode::extract_cn("C=US,CN=example.com"),
Some("example.com".to_string())
);
}
}