Helper function to extract the first DNS name from a certificate
(cert_der: &CertificateDer<'_>)
| 973 | |
| 974 | // Helper function to extract the first DNS name from a certificate |
| 975 | fn extract_first_dns_name(cert_der: &CertificateDer<'_>) -> Option<ServerName<'static>> { |
| 976 | let (_, cert) = X509Certificate::from_der(cert_der.as_ref()).ok()?; |
| 977 | |
| 978 | // Try Subject Alternative Names first |
| 979 | if let Ok(Some(san_ext)) = cert.subject_alternative_name() { |
| 980 | for name in &san_ext.value.general_names { |
| 981 | if let x509_parser::extensions::GeneralName::DNSName(dns) = name { |
| 982 | // Remove wildcard prefix if present (e.g., "*.example.com" → "example.com") |
| 983 | // This allows us to use the domain for certificate chain verification |
| 984 | // when check_hostname=False |
| 985 | let dns_str = dns.to_string(); |
| 986 | let normalized_dns = normalize_wildcard_hostname(&dns_str); |
| 987 | |
| 988 | match ServerName::try_from(normalized_dns.to_string()) { |
| 989 | Ok(server_name) => { |
| 990 | return Some(server_name); |
| 991 | } |
| 992 | Err(_e) => { |
| 993 | // Continue to next |
| 994 | } |
| 995 | } |
| 996 | } |
| 997 | } |
| 998 | } |
| 999 | |
| 1000 | // Fallback to Common Name |
| 1001 | for rdn in cert.subject().iter() { |
| 1002 | for attr in rdn.iter() { |
| 1003 | if attr.attr_type() == &x509_parser::oid_registry::OID_X509_COMMON_NAME |
| 1004 | && let Ok(cn) = attr.attr_value().as_str() |
| 1005 | { |
| 1006 | // Remove wildcard prefix if present |
| 1007 | let normalized_cn = normalize_wildcard_hostname(cn); |
| 1008 | |
| 1009 | match ServerName::try_from(normalized_cn.to_string()) { |
| 1010 | Ok(server_name) => { |
| 1011 | return Some(server_name); |
| 1012 | } |
| 1013 | Err(_e) => {} |
| 1014 | } |
| 1015 | } |
| 1016 | } |
| 1017 | } |
| 1018 | |
| 1019 | None |
| 1020 | } |
| 1021 | |
| 1022 | // Custom client certificate verifier for TLS 1.3 deferred validation |
| 1023 | // This verifier always succeeds during handshake but stores verification errors |
no test coverage detected