1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
use std::error::Error as StdError;
use std::fmt;
use crate::tls::rustls::verify;
/// Encodes ways a client can know the expected name of the server.
///
/// This currently covers knowing the DNS name of the server, but
/// will be extended in the future to knowing the IP address of the
/// server, as well as supporting privacy-preserving names for the
/// server ("ECH"). For this reason this enum is `non_exhaustive`.
///
/// # Making one
///
/// If you have a DNS name as a `&str`, this type implements `TryFrom<&str>`,
/// so you can do:
///
/// ```
/// # use tlspuffin::tls::rustls::client::client_conn::ServerName;
/// ServerName::try_from("example.com").expect("invalid DNS name");
///
/// // or, alternatively...
///
/// let x = "example.com".try_into().expect("invalid DNS name");
/// # let _: ServerName = x;
/// ```
#[non_exhaustive]
#[derive(Debug, PartialEq, Clone)]
pub enum ServerName {
/// The server is identified by a DNS name. The name
/// is sent in the TLS Server Name Indication (SNI)
/// extension.
DnsName(verify::DnsName),
}
impl ServerName {
/// Return the name that should go in the SNI extension.
/// If [`None`] is returned, the SNI extension is not included
/// in the handshake.
pub fn for_sni(&self) -> Option<webpki::DnsNameRef> {
match self {
Self::DnsName(dns_name) => Some(dns_name.0.as_ref()),
}
}
/// Return a prefix-free, unique encoding for the name.
pub fn encode(&self) -> Vec<u8> {
enum UniqueTypeCode {
DnsName = 0x01,
}
let Self::DnsName(dns_name) = self;
let bytes = dns_name.0.as_ref();
let mut r = Vec::with_capacity(2 + bytes.as_ref().len());
r.push(UniqueTypeCode::DnsName as u8);
r.push(bytes.as_ref().len() as u8);
r.extend_from_slice(bytes.as_ref());
r
}
}
/// Attempt to make a ServerName from a string by parsing
/// it as a DNS name.
impl TryFrom<&str> for ServerName {
type Error = InvalidDnsNameError;
fn try_from(s: &str) -> Result<Self, Self::Error> {
match webpki::DnsNameRef::try_from_ascii_str(s) {
Ok(dns) => Ok(Self::DnsName(verify::DnsName(dns.into()))),
Err(webpki::InvalidDnsNameError) => Err(InvalidDnsNameError),
}
}
}
/// The provided input could not be parsed because
/// it is not a syntactically-valid DNS Name.
#[derive(Debug)]
pub struct InvalidDnsNameError;
impl fmt::Display for InvalidDnsNameError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str("invalid dns name")
}
}
impl StdError for InvalidDnsNameError {}