From c67bd767dbe2fe3413607595ffb47fdb79708485 Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Sun, 22 Dec 2024 17:39:16 +0100 Subject: [PATCH] Add context in name validation errors --- src/error.rs | 34 +++++++- src/subject_name/dns_name.rs | 54 +++++++++---- src/subject_name/ip_address.rs | 51 ++++++++---- src/subject_name/verify.rs | 138 +++++++++++++++++++++++++++++++++ tests/generate.py | 14 +++- tests/tls_server_certs.rs | 128 ++++++++++++++++++++++++------ 6 files changed, 359 insertions(+), 60 deletions(-) diff --git a/src/error.rs b/src/error.rs index 8b0e3449..2b26efa4 100644 --- a/src/error.rs +++ b/src/error.rs @@ -12,9 +12,16 @@ // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +#[cfg(feature = "alloc")] +use alloc::string::String; +#[cfg(feature = "alloc")] +use alloc::vec::Vec; use core::fmt; use core::ops::ControlFlow; +#[cfg(feature = "alloc")] +use pki_types::ServerName; + /// An error that occurs during certificate validation or name validation. #[derive(Clone, Debug, PartialEq, Eq)] #[non_exhaustive] @@ -32,9 +39,6 @@ pub enum Error { /// later than the certificate's notAfter time. CertExpired, - /// The certificate is not valid for the name it is being validated for. - CertNotValidForName, - /// The certificate is not valid yet; i.e. the time it is being validated /// for is earlier than the certificate's notBefore time. CertNotValidYet, @@ -127,6 +131,26 @@ pub enum Error { /// Trailing data was found while parsing DER-encoded input for the named type. TrailingData(DerTypeId), + /// The certificate is not valid for the name it is being validated for. + /// + /// Variant without context for use in no-`alloc` environments. See `UnexpectedCertName` for + /// the variant that is used in `alloc` environments. + UnexpectedCertNameSimple, + + /// The certificate is not valid for the name it is being validated for. + /// + /// Variant with context for use in `alloc` environments. See `UnexpectedCertNameSimple` + /// for the variant that is used in no-`alloc` environments. + #[cfg(feature = "alloc")] + UnexpectedCertName { + /// Expected server name. + expected: ServerName<'static>, + /// The names presented in the end entity certificate. + /// + /// Unlike `expected`, these names might contain wildcard labels. + presented: Vec, + }, + /// A valid issuer for the certificate could not be found. UnknownIssuer, @@ -216,7 +240,6 @@ impl Error { match &self { // Errors related to certificate validity Self::CertNotValidYet | Self::CertExpired => 290, - Self::CertNotValidForName => 280, Self::CertRevoked | Self::UnknownRevocationStatus | Self::CrlExpired => 270, Self::InvalidCrlSignatureForPublicKey | Self::InvalidSignatureForPublicKey => 260, Self::SignatureAlgorithmMismatch => 250, @@ -225,6 +248,9 @@ impl Error { Self::PathLenConstraintViolated => 220, Self::CaUsedAsEndEntity | Self::EndEntityUsedAsCa => 210, Self::IssuerNotCrlSigner => 200, + Self::UnexpectedCertNameSimple => 280, + #[cfg(feature = "alloc")] + Self::UnexpectedCertName { .. } => 280, // Errors related to supported features used in an invalid way. Self::InvalidCertValidity => 190, diff --git a/src/subject_name/dns_name.rs b/src/subject_name/dns_name.rs index 6e4a3bbb..80b3dc32 100644 --- a/src/subject_name/dns_name.rs +++ b/src/subject_name/dns_name.rs @@ -12,8 +12,12 @@ // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +#[cfg(feature = "alloc")] +use alloc::format; use core::fmt::Write; +#[cfg(feature = "alloc")] +use pki_types::ServerName; use pki_types::{DnsName, InvalidDnsNameError}; use super::verify::{GeneralName, NameIterator}; @@ -21,25 +25,43 @@ use crate::{Cert, Error}; pub(crate) fn verify_dns_names(reference: &DnsName<'_>, cert: &Cert<'_>) -> Result<(), Error> { let dns_name = untrusted::Input::from(reference.as_ref().as_bytes()); - NameIterator::new(Some(cert.subject), cert.subject_alt_name) - .find_map(|result| { - let name = match result { - Ok(name) => name, - Err(err) => return Some(Err(err)), - }; + let result = NameIterator::new(Some(cert.subject), cert.subject_alt_name).find_map(|result| { + let name = match result { + Ok(name) => name, + Err(err) => return Some(Err(err)), + }; - let presented_id = match name { - GeneralName::DnsName(presented) => presented, - _ => return None, - }; + let presented_id = match name { + GeneralName::DnsName(presented) => presented, + _ => return None, + }; - match presented_id_matches_reference_id(presented_id, IdRole::Reference, dns_name) { - Ok(true) => Some(Ok(())), - Ok(false) | Err(Error::MalformedDnsIdentifier) => None, - Err(e) => Some(Err(e)), - } + match presented_id_matches_reference_id(presented_id, IdRole::Reference, dns_name) { + Ok(true) => Some(Ok(())), + Ok(false) | Err(Error::MalformedDnsIdentifier) => None, + Err(e) => Some(Err(e)), + } + }); + + match result { + Some(result) => return result, + #[cfg(feature = "alloc")] + None => {} + #[cfg(not(feature = "alloc"))] + None => return Err(Error::UnexpectedCertNameSimple), + } + + // Try to yield a more useful error. To avoid allocating on the happy path, + // we reconstruct the same `NameIterator` and replay it. + #[cfg(feature = "alloc")] + { + Err(Error::UnexpectedCertName { + expected: ServerName::DnsName(reference.to_owned()), + presented: NameIterator::new(Some(cert.subject), cert.subject_alt_name) + .filter_map(|result| Some(format!("{:?}", result.ok()?))) + .collect(), }) - .unwrap_or(Err(Error::CertNotValidForName)) + } } /// A reference to a DNS Name presented by a server that may include a wildcard. diff --git a/src/subject_name/ip_address.rs b/src/subject_name/ip_address.rs index 64285bc3..6d9c5bc9 100644 --- a/src/subject_name/ip_address.rs +++ b/src/subject_name/ip_address.rs @@ -12,7 +12,12 @@ // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +#[cfg(feature = "alloc")] +use alloc::format; + use pki_types::IpAddr; +#[cfg(feature = "alloc")] +use pki_types::ServerName; use super::verify::{GeneralName, NameIterator}; use crate::{Cert, Error}; @@ -23,24 +28,40 @@ pub(crate) fn verify_ip_address_names(reference: &IpAddr, cert: &Cert<'_>) -> Re IpAddr::V6(ip) => untrusted::Input::from(ip.as_ref()), }; - NameIterator::new(None, cert.subject_alt_name) - .find_map(|result| { - let name = match result { - Ok(name) => name, - Err(err) => return Some(Err(err)), - }; + let result = NameIterator::new(None, cert.subject_alt_name).find_map(|result| { + let name = match result { + Ok(name) => name, + Err(err) => return Some(Err(err)), + }; - let presented_id = match name { - GeneralName::IpAddress(presented) => presented, - _ => return None, - }; + let presented_id = match name { + GeneralName::IpAddress(presented) => presented, + _ => return None, + }; - match presented_id_matches_reference_id(presented_id, ip_address) { - true => Some(Ok(())), - false => None, - } + match presented_id_matches_reference_id(presented_id, ip_address) { + true => Some(Ok(())), + false => None, + } + }); + + match result { + Some(result) => return result, + #[cfg(feature = "alloc")] + None => {} + #[cfg(not(feature = "alloc"))] + None => Err(Error::UnexpectedCertNameSimple), + } + + #[cfg(feature = "alloc")] + { + Err(Error::UnexpectedCertName { + expected: ServerName::from(*reference), + presented: NameIterator::new(None, cert.subject_alt_name) + .filter_map(|result| Some(format!("{:?}", result.ok()?))) + .collect(), }) - .unwrap_or(Err(Error::CertNotValidForName)) + } } // https://tools.ietf.org/html/rfc5280#section-4.2.1.6 says: diff --git a/src/subject_name/verify.rs b/src/subject_name/verify.rs index 17b178e1..f9e49d2a 100644 --- a/src/subject_name/verify.rs +++ b/src/subject_name/verify.rs @@ -12,6 +12,11 @@ // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +#[cfg(feature = "alloc")] +use alloc::string::String; +#[cfg(feature = "alloc")] +use core::fmt; + use super::dns_name::{self, IdRole}; use super::ip_address; use crate::der::{self, FromDer}; @@ -295,3 +300,136 @@ impl<'a> FromDer<'a> for GeneralName<'a> { const TYPE_ID: DerTypeId = DerTypeId::GeneralName; } + +#[cfg(feature = "alloc")] +impl fmt::Debug for GeneralName<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + GeneralName::DnsName(name) => write!( + f, + "DnsName(\"{}\")", + String::from_utf8_lossy(name.as_slice_less_safe()) + ), + GeneralName::DirectoryName => write!(f, "DirectoryName"), + GeneralName::IpAddress(ip) => { + write!(f, "IpAddress({:?})", IpAddrSlice(ip.as_slice_less_safe())) + } + GeneralName::UniformResourceIdentifier(uri) => write!( + f, + "UniformResourceIdentifier(\"{}\")", + String::from_utf8_lossy(uri.as_slice_less_safe()) + ), + GeneralName::Unsupported(tag) => write!(f, "Unsupported({})", tag), + } + } +} + +#[cfg(feature = "alloc")] +struct IpAddrSlice<'a>(&'a [u8]); + +#[cfg(feature = "alloc")] +impl fmt::Debug for IpAddrSlice<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self.0.len() { + 4 => { + let mut first = true; + for byte in self.0 { + match first { + true => first = false, + false => f.write_str(".")?, + } + + write!(f, "{}", byte)?; + } + + Ok(()) + } + 16 => { + let mut first = true; + for group in self.0.chunks_exact(2) { + match first { + true => first = false, + false => f.write_str(":")?, + } + + match group { + [0, 0] => f.write_str("0")?, + _ => write!(f, "{:02x}{:02x}", group[0], group[1])?, + } + } + Ok(()) + } + _ => { + f.write_str("[invalid: ")?; + let mut first = true; + for byte in self.0 { + match first { + true => first = false, + false => f.write_str(", ")?, + } + write!(f, "{:02x}", byte)?; + } + f.write_str("]") + } + } + } +} + +#[cfg(all(test, feature = "alloc"))] +mod tests { + use super::*; + + #[test] + fn debug_names() { + assert_eq!( + format!( + "{:?}", + GeneralName::DnsName(untrusted::Input::from(b"example.com")) + ), + "DnsName(\"example.com\")" + ); + + assert_eq!(format!("{:?}", GeneralName::DirectoryName), "DirectoryName"); + + assert_eq!( + format!( + "{:?}", + GeneralName::IpAddress(untrusted::Input::from(&[192, 0, 2, 1][..])) + ), + "IpAddress(192.0.2.1)" + ); + + assert_eq!( + format!( + "{:?}", + GeneralName::IpAddress(untrusted::Input::from( + &[0x20, 0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0d, 0xb8][..] + )) + ), + "IpAddress(2001:0:0:0:0:0:0:0db8)" + ); + + assert_eq!( + format!( + "{:?}", + GeneralName::IpAddress(untrusted::Input::from(&[1, 2, 3, 4, 5, 6][..])) + ), + "IpAddress([invalid: 01, 02, 03, 04, 05, 06])" + ); + + assert_eq!( + format!( + "{:?}", + GeneralName::UniformResourceIdentifier(untrusted::Input::from( + b"https://example.com" + )) + ), + "UniformResourceIdentifier(\"https://example.com\")" + ); + + assert_eq!( + format!("{:?}", GeneralName::Unsupported(0x42)), + "Unsupported(66)" + ); + } +} diff --git a/tests/generate.py b/tests/generate.py index 954b8281..d829b968 100755 --- a/tests/generate.py +++ b/tests/generate.py @@ -286,6 +286,18 @@ def generate_tls_server_cert_test( valid_names_str: str = ", ".join('"' + name + '"' for name in valid_names) invalid_names_str: str = ", ".join('"' + name + '"' for name in invalid_names) + presented_names_str: str = "" + for san in sans if sans is not None else []: + if presented_names_str: + presented_names_str += ", " + if isinstance(san, x509.DNSName): + presented_names_str += f'"DnsName(\\"{san.value}\\")"' + elif isinstance(san, x509.IPAddress): + presented_names_str += f'"IpAddress({san.value})"' + if subject_common_name: + if presented_names_str: + presented_names_str += ", " + presented_names_str += 'DirectoryName' print( """ @@ -294,7 +306,7 @@ def generate_tls_server_cert_test( let ee = include_bytes!("%(ee_cert_path)s"); let ca = include_bytes!("%(ca_cert_path)s"); assert_eq!( - check_cert(ee, ca, &[%(valid_names_str)s], &[%(invalid_names_str)s]), + check_cert(ee, ca, &[%(valid_names_str)s], &[%(invalid_names_str)s], &[%(presented_names_str)s]), %(expected)s ); }""" diff --git a/tests/tls_server_certs.rs b/tests/tls_server_certs.rs index 7ab25d68..1be13da8 100644 --- a/tests/tls_server_certs.rs +++ b/tests/tls_server_certs.rs @@ -23,6 +23,7 @@ fn check_cert( ca: &[u8], valid_names: &[&str], invalid_names: &[&str], + presented_names: &[&str], ) -> Result<(), webpki::Error> { let ca_cert_der = CertificateDer::from(ca); let anchors = [anchor_from_trusted_cert(&ca_cert_der).unwrap()]; @@ -49,7 +50,10 @@ fn check_cert( let name = ServerName::try_from(*invalid).unwrap(); assert_eq!( cert.verify_is_valid_for_subject_name(&name), - Err(webpki::Error::CertNotValidForName) + Err(webpki::Error::UnexpectedCertName { + expected: name.to_owned(), + presented: presented_names.iter().map(|n| n.to_string()).collect(), + }) ); } @@ -63,7 +67,13 @@ fn no_name_constraints() { let ee = include_bytes!("tls_server_certs/no_name_constraints.ee.der"); let ca = include_bytes!("tls_server_certs/no_name_constraints.ca.der"); assert_eq!( - check_cert(ee, ca, &["dns.example.com"], &["subject.example.com"]), + check_cert( + ee, + ca, + &["dns.example.com"], + &["subject.example.com"], + &["DnsName(\"dns.example.com\")", "DirectoryName"], + ), Ok(()) ); } @@ -77,7 +87,12 @@ fn additional_dns_labels() { ee, ca, &["host1.example.com", "host2.example.com"], - &["subject.example.com"] + &["subject.example.com"], + &[ + "DnsName(\"host1.example.com\")", + "DnsName(\"host2.example.com\")", + "DirectoryName" + ], ), Ok(()) ); @@ -88,7 +103,13 @@ fn disallow_dns_san() { let ee = include_bytes!("tls_server_certs/disallow_dns_san.ee.der"); let ca = include_bytes!("tls_server_certs/disallow_dns_san.ca.der"); assert_eq!( - check_cert(ee, ca, &[], &[]), + check_cert( + ee, + ca, + &[], + &[], + &["DnsName(\"disallowed.example.com\")", "DirectoryName"] + ), Err(webpki::Error::NameConstraintViolation) ); } @@ -97,14 +118,26 @@ fn disallow_dns_san() { fn allow_subject_common_name() { let ee = include_bytes!("tls_server_certs/allow_subject_common_name.ee.der"); let ca = include_bytes!("tls_server_certs/allow_subject_common_name.ca.der"); - assert_eq!(check_cert(ee, ca, &[], &["allowed.example.com"]), Ok(())); + assert_eq!( + check_cert(ee, ca, &[], &["allowed.example.com"], &["DirectoryName"]), + Ok(()) + ); } #[test] fn allow_dns_san() { let ee = include_bytes!("tls_server_certs/allow_dns_san.ee.der"); let ca = include_bytes!("tls_server_certs/allow_dns_san.ca.der"); - assert_eq!(check_cert(ee, ca, &["allowed.example.com"], &[]), Ok(())); + assert_eq!( + check_cert( + ee, + ca, + &["allowed.example.com"], + &[], + &["DnsName(\"allowed.example.com\")", "DirectoryName"] + ), + Ok(()) + ); } #[test] @@ -116,7 +149,8 @@ fn allow_dns_san_and_subject_common_name() { ee, ca, &["allowed-san.example.com"], - &["allowed-cn.example.com"] + &["allowed-cn.example.com"], + &["DnsName(\"allowed-san.example.com\")", "DirectoryName"], ), Ok(()) ); @@ -129,7 +163,16 @@ fn disallow_dns_san_and_allow_subject_common_name() { let ca = include_bytes!("tls_server_certs/disallow_dns_san_and_allow_subject_common_name.ca.der"); assert_eq!( - check_cert(ee, ca, &[], &[]), + check_cert( + ee, + ca, + &[], + &[], + &[ + "DnsName(\"allowed-san.example.com\")", + "DnsName(\"disallowed-san.example.com\")" + ] + ), Err(webpki::Error::NameConstraintViolation) ); } @@ -142,7 +185,7 @@ fn we_incorrectly_ignore_name_constraints_on_name_in_subject() { let ca = include_bytes!( "tls_server_certs/we_incorrectly_ignore_name_constraints_on_name_in_subject.ca.der" ); - assert_eq!(check_cert(ee, ca, &[], &[]), Ok(())); + assert_eq!(check_cert(ee, ca, &[], &[], &[]), Ok(())); } #[test] @@ -150,7 +193,7 @@ fn reject_constraints_on_unimplemented_names() { let ee = include_bytes!("tls_server_certs/reject_constraints_on_unimplemented_names.ee.der"); let ca = include_bytes!("tls_server_certs/reject_constraints_on_unimplemented_names.ca.der"); assert_eq!( - check_cert(ee, ca, &[], &[]), + check_cert(ee, ca, &[], &[], &[]), Err(webpki::Error::NameConstraintViolation) ); } @@ -164,7 +207,13 @@ fn we_ignore_constraints_on_names_that_do_not_appear_in_cert() { "tls_server_certs/we_ignore_constraints_on_names_that_do_not_appear_in_cert.ca.der" ); assert_eq!( - check_cert(ee, ca, &["notexample.com"], &["example.com"]), + check_cert( + ee, + ca, + &["notexample.com"], + &["example.com"], + &["DnsName(\"notexample.com\")", "DirectoryName"], + ), Ok(()) ); } @@ -178,7 +227,8 @@ fn wildcard_san_accepted_if_in_subtree() { ee, ca, &["bob.example.com", "jane.example.com"], - &["example.com", "uh.oh.example.com"] + &["example.com", "uh.oh.example.com"], + &["DnsName(\"*.example.com\")", "DirectoryName"], ), Ok(()) ); @@ -189,7 +239,13 @@ fn wildcard_san_rejected_if_in_excluded_subtree() { let ee = include_bytes!("tls_server_certs/wildcard_san_rejected_if_in_excluded_subtree.ee.der"); let ca = include_bytes!("tls_server_certs/wildcard_san_rejected_if_in_excluded_subtree.ca.der"); assert_eq!( - check_cert(ee, ca, &[], &[]), + check_cert( + ee, + ca, + &[], + &[], + &["DnsName(\"*.example.com\")", "DirectoryName"] + ), Err(webpki::Error::NameConstraintViolation) ); } @@ -201,7 +257,7 @@ fn ip4_address_san_rejected_if_in_excluded_subtree() { let ca = include_bytes!("tls_server_certs/ip4_address_san_rejected_if_in_excluded_subtree.ca.der"); assert_eq!( - check_cert(ee, ca, &[], &[]), + check_cert(ee, ca, &[], &[], &["IpAddress(12.34.56.78)"]), Err(webpki::Error::NameConstraintViolation) ); } @@ -214,7 +270,10 @@ fn ip4_address_san_allowed_if_outside_excluded_subtree() { let ca = include_bytes!( "tls_server_certs/ip4_address_san_allowed_if_outside_excluded_subtree.ca.der" ); - assert_eq!(check_cert(ee, ca, &["12.34.56.78"], &[]), Ok(())); + assert_eq!( + check_cert(ee, ca, &["12.34.56.78"], &[], &["IpAddress(12.34.56.78)"]), + Ok(()) + ); } #[test] @@ -226,7 +285,7 @@ fn ip4_address_san_rejected_if_excluded_is_sparse_cidr_mask() { "tls_server_certs/ip4_address_san_rejected_if_excluded_is_sparse_cidr_mask.ca.der" ); assert_eq!( - check_cert(ee, ca, &[], &[]), + check_cert(ee, ca, &[], &[], &["IpAddress(12.34.56.79)"]), Err(webpki::Error::InvalidNetworkMaskConstraint) ); } @@ -244,7 +303,8 @@ fn ip4_address_san_allowed() { "12.34.56.77", "12.34.56.79", "0000:0000:0000:0000:0000:ffff:0c22:384e" - ] + ], + &["IpAddress(12.34.56.78)"] ), Ok(()) ); @@ -257,7 +317,7 @@ fn ip6_address_san_rejected_if_in_excluded_subtree() { let ca = include_bytes!("tls_server_certs/ip6_address_san_rejected_if_in_excluded_subtree.ca.der"); assert_eq!( - check_cert(ee, ca, &[], &[]), + check_cert(ee, ca, &[], &[], &["IpAddress(2001:db8:0:0:0:0:0:0001)"]), Err(webpki::Error::NameConstraintViolation) ); } @@ -271,7 +331,13 @@ fn ip6_address_san_allowed_if_outside_excluded_subtree() { "tls_server_certs/ip6_address_san_allowed_if_outside_excluded_subtree.ca.der" ); assert_eq!( - check_cert(ee, ca, &["2001:0db9:0000:0000:0000:0000:0000:0001"], &[]), + check_cert( + ee, + ca, + &["2001:0db9:0000:0000:0000:0000:0000:0001"], + &[], + &["IpAddress(2001:db9:0:0:0:0:0:0001)"] + ), Ok(()) ); } @@ -285,7 +351,8 @@ fn ip6_address_san_allowed() { ee, ca, &["2001:0db9:0000:0000:0000:0000:0000:0001"], - &["12.34.56.78"] + &["12.34.56.78"], + &["IpAddress(2001:0db9:0:0:0:0:0:0001)"], ), Ok(()) ); @@ -304,7 +371,11 @@ fn ip46_mixed_address_san_allowed() { "12.34.56.77", "12.34.56.79", "0000:0000:0000:0000:0000:ffff:0c22:384e" - ] + ], + &[ + "IpAddress(12.34.56.78)", + "IpAddress(2001:0db9:0:0:0:0:0:0001)" + ], ), Ok(()) ); @@ -315,7 +386,7 @@ fn permit_directory_name_not_implemented() { let ee = include_bytes!("tls_server_certs/permit_directory_name_not_implemented.ee.der"); let ca = include_bytes!("tls_server_certs/permit_directory_name_not_implemented.ca.der"); assert_eq!( - check_cert(ee, ca, &[], &[]), + check_cert(ee, ca, &[], &[], &[]), Err(webpki::Error::NameConstraintViolation) ); } @@ -325,7 +396,16 @@ fn exclude_directory_name_not_implemented() { let ee = include_bytes!("tls_server_certs/exclude_directory_name_not_implemented.ee.der"); let ca = include_bytes!("tls_server_certs/exclude_directory_name_not_implemented.ca.der"); assert_eq!( - check_cert(ee, ca, &[], &[]), + check_cert( + ee, + ca, + &[], + &[], + &[ + "DnsName(\"{invalid}.example.com\")", + "DnsName(\"dns.example.com\")" + ] + ), Err(webpki::Error::NameConstraintViolation) ); } @@ -334,5 +414,5 @@ fn exclude_directory_name_not_implemented() { fn invalid_dns_name_matching() { let ee = include_bytes!("tls_server_certs/invalid_dns_name_matching.ee.der"); let ca = include_bytes!("tls_server_certs/invalid_dns_name_matching.ca.der"); - assert_eq!(check_cert(ee, ca, &["dns.example.com"], &[]), Ok(())); + assert_eq!(check_cert(ee, ca, &["dns.example.com"], &[], &[]), Ok(())); }