diff --git a/Cargo.toml b/Cargo.toml index 28a5601e..cdfd2167 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -38,6 +38,7 @@ include = [ "src/name.rs", "src/name/dns_name.rs", "src/name/ip_address.rs", + "src/name/name.rs", "src/name/verify.rs", "src/signed_data.rs", "src/time.rs", diff --git a/src/end_entity.rs b/src/end_entity.rs index 0507b65e..8a8c57df 100644 --- a/src/end_entity.rs +++ b/src/end_entity.rs @@ -13,7 +13,7 @@ // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. use crate::{ - cert, name, signed_data, verify_cert, DnsNameRef, Error, SignatureAlgorithm, Time, + cert, name, signed_data, verify_cert, Error, Name, SignatureAlgorithm, Time, TlsClientTrustAnchors, TlsServerTrustAnchors, }; @@ -27,7 +27,7 @@ use alloc::vec::Vec; /// /// * `EndEntityCert.verify_is_valid_tls_server_cert`: Verify that the server's /// certificate is currently valid *for use by a TLS server*. -/// * `EndEntityCert.verify_is_valid_for_dns_name`: Verify that the server's +/// * `EndEntityCert.verify_name`: Verify that the server's /// certificate is valid for the host that is being connected to. /// * `EndEntityCert.verify_signature`: Verify that the signature of server's /// `ServerKeyExchange` message is valid for the server's certificate. @@ -37,8 +37,8 @@ use alloc::vec::Vec; /// /// * `EndEntityCert.verify_is_valid_tls_client_cert`: Verify that the client's /// certificate is currently valid *for use by a TLS client*. -/// * `EndEntityCert.verify_is_valid_for_dns_name` or -/// `EndEntityCert.verify_is_valid_for_at_least_one_dns_name`: Verify that the +/// * `EndEntityCert.verify_name` or +/// `EndEntityCert.verify_for_at_least_one_name`: Verify that the /// client's certificate is valid for the identity or identities used to /// identify the client. (Currently client authentication only works when the /// client is identified by one or more DNS hostnames.) @@ -140,8 +140,10 @@ impl<'a> EndEntityCert<'a> { } /// Verifies that the certificate is valid for the given DNS host name. - pub fn verify_is_valid_for_dns_name(&self, dns_name: DnsNameRef) -> Result<(), Error> { - name::verify_cert_dns_name(&self, dns_name) + pub fn verify_for_name<'n>(&self, name: impl Into>) -> Result<(), Error> { + match name.into() { + Name::DnsName(dns_name) => name::verify_cert_dns_name(&self, dns_name), + } } /// Verifies that the certificate is valid for at least one of the given DNS @@ -154,12 +156,12 @@ impl<'a> EndEntityCert<'a> { /// Requires the `alloc` default feature; i.e. this isn't available in /// `#![no_std]` configurations. #[cfg(feature = "alloc")] - pub fn verify_is_valid_for_at_least_one_dns_name<'names>( + pub fn verify_for_at_least_one_name<'names>( &self, - dns_names: impl Iterator>, - ) -> Result>, Error> { - let result: Vec> = dns_names - .filter(|n| self.verify_is_valid_for_dns_name(*n).is_ok()) + dns_names: impl Iterator>, + ) -> Result>, Error> { + let result: Vec> = dns_names + .filter(|n| self.verify_for_name(*n).is_ok()) .collect(); if result.is_empty() { return Err(Error::CertNotValidForName); diff --git a/src/lib.rs b/src/lib.rs index f8146102..1a22d5d2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -48,7 +48,7 @@ mod verify_cert; pub use { end_entity::EndEntityCert, error::Error, - name::{DnsNameRef, InvalidDnsNameError}, + name::{DnsNameRef, InvalidDnsNameError, Name}, signed_data::{ SignatureAlgorithm, ECDSA_P256_SHA256, ECDSA_P256_SHA384, ECDSA_P384_SHA256, ECDSA_P384_SHA384, ED25519, diff --git a/src/name.rs b/src/name.rs index 040a8133..5658bbb5 100644 --- a/src/name.rs +++ b/src/name.rs @@ -13,7 +13,10 @@ // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. mod dns_name; -pub use dns_name::{DnsNameRef, InvalidDnsNameError}; +pub use self::{ + dns_name::{DnsNameRef, InvalidDnsNameError}, + name::Name, +}; /// Requires the `alloc` feature. #[cfg(feature = "alloc")] @@ -21,5 +24,8 @@ pub use dns_name::DnsName; mod ip_address; +#[allow(clippy::module_inception)] +mod name; + mod verify; pub(super) use verify::{check_name_constraints, verify_cert_dns_name}; diff --git a/src/name/name.rs b/src/name/name.rs new file mode 100644 index 00000000..86e776cb --- /dev/null +++ b/src/name/name.rs @@ -0,0 +1,30 @@ +// Copyright 2021 Brian Smith. +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +use super::DnsNameRef; + +/// A name that identifies a subject. +#[derive(Clone, Copy)] +#[non_exhaustive] +pub enum Name<'a> { + /// A DNS name. + DnsName(DnsNameRef<'a>), +} + +impl<'a> From> for Name<'a> { + #[inline] + fn from(name: DnsNameRef<'a>) -> Self { + Self::DnsName(name) + } +} diff --git a/tests/integration.rs b/tests/integration.rs index 598641d3..8f0b0aeb 100644 --- a/tests/integration.rs +++ b/tests/integration.rs @@ -13,6 +13,7 @@ // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. use core::convert::TryFrom; + extern crate webpki; static ALL_SIGALGS: &[&webpki::SignatureAlgorithm] = &[ @@ -51,6 +52,15 @@ pub fn netflix() { Ok(()), cert.verify_is_valid_tls_server_cert(ALL_SIGALGS, &anchors, &[inter], time) ); + + let name = webpki::DnsNameRef::try_from_ascii_str("netflix.com").unwrap(); + assert_eq!(Ok(()), cert.verify_for_name(name)); + + let wrong_name = webpki::DnsNameRef::try_from_ascii_str("netflix.co").unwrap(); + assert_eq!( + Err(webpki::Error::CertNotValidForName), + cert.verify_for_name(wrong_name) + ); } #[test]