[pve-devel] [PATCH installer 1/5] common: fqdn: do not allow overlong FQDNs as per Debian spec
Christoph Heiss
c.heiss at proxmox.com
Thu Feb 15 13:39:34 CET 2024
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.heiss at 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
More information about the pve-devel
mailing list