Debian limits labels to 63 characters each and the total length to 253 characters [0].
While at it, reference all the RFCs that apply when parsing FQDNs. [0] https://manpages.debian.org/stable/manpages/hostname.7.en.html Signed-off-by: Christoph Heiss <c.he...@proxmox.com> --- proxmox-installer-common/src/utils.rs | 45 ++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/proxmox-installer-common/src/utils.rs b/proxmox-installer-common/src/utils.rs index c038524..067e025 100644 --- a/proxmox-installer-common/src/utils.rs +++ b/proxmox-installer-common/src/utils.rs @@ -117,6 +117,7 @@ pub enum FqdnParseError { MissingHostname, NumericHostname, InvalidPart(String), + TooLong(usize), } impl fmt::Display for FqdnParseError { @@ -129,17 +130,46 @@ impl fmt::Display for FqdnParseError { f, "FQDN must only consist of alphanumeric characters and dashes. Invalid part: '{part}'", ), + TooLong(len) => write!(f, "FQDN too long: {len} > {}", Fqdn::MAX_LENGTH), } } } +/// A type for safely representing fully-qualified domain names (FQDNs). +/// +/// It considers following RFCs: +/// https://www.ietf.org/rfc/rfc952.txt (sec. "ASSUMPTIONS", 1.) +/// https://www.ietf.org/rfc/rfc1035.txt (sec. 2.3. "Conventions") +/// https://www.ietf.org/rfc/rfc1123.txt (sec. 2.1. "Host Names and Numbers") +/// https://www.ietf.org/rfc/rfc3492.txt +/// https://www.ietf.org/rfc/rfc4343.txt +/// +/// .. and applies some restriction given by Debian, e.g. 253 instead of 255 +/// maximum total length and maximum 63 characters per label. +/// https://manpages.debian.org/stable/manpages/hostname.7.en.html +/// +/// Additionally: +/// - It enforces the restriction as per Bugzilla #1054, in that +/// purely numeric hostnames are not allowed - against RFC1123 sec. 2.1. +/// +/// Some terminology: +/// - "label" - a single part of a FQDN, e.g. <label>.<label>.<tld> #[derive(Clone, Debug, Eq, PartialEq)] pub struct Fqdn { parts: Vec<String>, } impl Fqdn { + /// Maximum length of a single label of the FQDN + const MAX_LABEL_LENGTH: usize = 63; + /// Maximum total length of the FQDN + const MAX_LENGTH: usize = 253; + pub fn from(fqdn: &str) -> Result<Self, FqdnParseError> { + if fqdn.len() > Self::MAX_LENGTH { + return Err(FqdnParseError::TooLong(fqdn.len())); + } + let parts = fqdn .split('.') .map(ToOwned::to_owned) @@ -154,7 +184,8 @@ impl Fqdn { if parts.len() < 2 { Err(FqdnParseError::MissingHostname) } else if parts[0].chars().all(|c| c.is_ascii_digit()) { - // Not allowed/supported on Debian systems. + // Do not allow a purely numeric hostname, see: + // https://bugzilla.proxmox.com/show_bug.cgi?id=1054 Err(FqdnParseError::NumericHostname) } else { Ok(Self { parts }) @@ -182,6 +213,7 @@ impl Fqdn { fn validate_single(s: &String) -> bool { !s.is_empty() + && s.len() <= Self::MAX_LABEL_LENGTH // First character must be alphanumeric && s.chars() .next() @@ -243,9 +275,20 @@ mod tests { assert_eq!(Fqdn::from("foo.com-"), Err(InvalidPart("com-".to_owned()))); assert_eq!(Fqdn::from("-o-.com"), Err(InvalidPart("-o-".to_owned()))); + // https://bugzilla.proxmox.com/show_bug.cgi?id=1054 assert_eq!(Fqdn::from("123.com"), Err(NumericHostname)); assert!(Fqdn::from("foo123.com").is_ok()); assert!(Fqdn::from("123foo.com").is_ok()); + + assert!(Fqdn::from(&format!("{}.com", "a".repeat(63))).is_ok()); + assert_eq!( + Fqdn::from(&format!("{}.com", "a".repeat(250))), + Err(TooLong(254)), + ); + assert_eq!( + Fqdn::from(&format!("{}.com", "a".repeat(64))), + Err(InvalidPart("a".repeat(64))), + ); } #[test] -- 2.43.0 _______________________________________________ pve-devel mailing list pve-devel@lists.proxmox.com https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel