all lists on lists.proxmox.com
 help / color / mirror / Atom feed
* [pve-devel] [PATCH installer v2] tui: fix FQDN validation
@ 2023-07-19 16:31 Christoph Heiss
  2023-07-21 14:20 ` [pve-devel] applied: " Thomas Lamprecht
  0 siblings, 1 reply; 2+ messages in thread
From: Christoph Heiss @ 2023-07-19 16:31 UTC (permalink / raw)
  To: pve-devel

Add checks to ensure that:
 * It is actually has a hostname, not just a domain name
 * Properly check if the hostname is purely numeric, which was
   broken/different to how the GUI installer does it

The custom error type also allows for easier future adaptions, as the
changes can be entirely contained to the `Fqdn` type.

Signed-off-by: Christoph Heiss <c.heiss@proxmox.com>
---
v1: https://lists.proxmox.com/pipermail/pve-devel/2023-June/057845.html

Changes v1 -> v2:
 * Fix & add some more unit tests
 * Add custom error type `FqdnParseError`
 * Move hostname checks directly into `Fqdn::from()`

 proxmox-tui-installer/src/main.rs  |  5 +--
 proxmox-tui-installer/src/utils.rs | 68 ++++++++++++++++++++++++------
 2 files changed, 57 insertions(+), 16 deletions(-)

diff --git a/proxmox-tui-installer/src/main.rs b/proxmox-tui-installer/src/main.rs
index 42f278b..5dd8ef8 100644
--- a/proxmox-tui-installer/src/main.rs
+++ b/proxmox-tui-installer/src/main.rs
@@ -587,7 +587,7 @@ fn network_dialog(siv: &mut Cursive) -> InstallerView {
                     .get_value::<EditView, _>(1)
                     .ok_or("failed to retrieve host FQDN")?
                     .parse::<Fqdn>()
-                    .map_err(|_| "failed to parse hostname".to_owned())?;
+                    .map_err(|err| format!("hostname does not look valid:\n\n{err}"))?;

                 let address = view
                     .get_value::<CidrAddressEditView, _>(2)
@@ -609,9 +609,6 @@ fn network_dialog(siv: &mut Cursive) -> InstallerView {
                     Err("host and gateway IP address version must not differ".to_owned())
                 } else if address.addr().is_ipv4() != dns_server.is_ipv4() {
                     Err("host and DNS IP address version must not differ".to_owned())
-                } else if fqdn.to_string().chars().all(|c| c.is_ascii_digit()) {
-                    // Not supported/allowed on Debian
-                    Err("hostname cannot be purely numeric".to_owned())
                 } else if fqdn.to_string().ends_with(".invalid") {
                     Err("hostname does not look valid".to_owned())
                 } else {
diff --git a/proxmox-tui-installer/src/utils.rs b/proxmox-tui-installer/src/utils.rs
index 3245fac..516f9c6 100644
--- a/proxmox-tui-installer/src/utils.rs
+++ b/proxmox-tui-installer/src/utils.rs
@@ -110,20 +110,51 @@ fn mask_limit(addr: &IpAddr) -> usize {
     }
 }

-#[derive(Clone, Debug)]
+/// Possible errors that might occur when parsing FQDNs.
+#[derive(Debug, Eq, PartialEq)]
+pub enum FqdnParseError {
+    MissingHostname,
+    NumericHostname,
+    InvalidPart(String),
+}
+
+impl fmt::Display for FqdnParseError {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        use FqdnParseError::*;
+        match self {
+            MissingHostname => write!(f, "missing hostname part"),
+            NumericHostname => write!(f, "hostname cannot be purely numeric"),
+            InvalidPart(part) => write!(
+                f,
+                "FQDN must only consist of alphanumeric characters and dashes. Invalid part: '{part}'",
+            ),
+        }
+    }
+}
+
+#[derive(Clone, Debug, Eq, PartialEq)]
 pub struct Fqdn {
     parts: Vec<String>,
 }

 impl Fqdn {
-    pub fn from(fqdn: &str) -> Result<Self, ()> {
+    pub fn from(fqdn: &str) -> Result<Self, FqdnParseError> {
         let parts = fqdn
             .split('.')
             .map(ToOwned::to_owned)
             .collect::<Vec<String>>();

-        if !parts.iter().all(&Self::validate_single) {
-            Err(())
+        for part in &parts {
+            if !Self::validate_single(part) {
+                return Err(FqdnParseError::InvalidPart(part.clone()));
+            }
+        }
+
+        if parts.len() < 2 {
+            Err(FqdnParseError::MissingHostname)
+        } else if parts[0].chars().all(|c| c.is_ascii_digit()) {
+            // Not allowed/supported on Debian systems.
+            Err(FqdnParseError::NumericHostname)
         } else {
             Ok(Self { parts })
         }
@@ -143,20 +174,24 @@ impl Fqdn {
         parts.join(".")
     }

+    /// Checks whether the FQDN has a hostname associated with it, i.e. is has more than 1 part.
     fn has_host(&self) -> bool {
         self.parts.len() > 1
     }

     fn validate_single(s: &String) -> bool {
         !s.is_empty()
+            // First character must be alphanumeric
             && s.chars()
                 .next()
                 .map(|c| c.is_ascii_alphanumeric())
                 .unwrap_or_default()
+            // .. last character as well,
             && s.chars()
                 .last()
                 .map(|c| c.is_ascii_alphanumeric())
                 .unwrap_or_default()
+            // and anything between must be alphanumeric or -
             && s.chars()
                 .skip(1)
                 .take(s.len().saturating_sub(2))
@@ -165,7 +200,7 @@ impl Fqdn {
 }

 impl FromStr for Fqdn {
-    type Err = ();
+    type Err = FqdnParseError;

     fn from_str(value: &str) -> Result<Self, Self::Err> {
         Self::from(value)
@@ -194,17 +229,22 @@ mod tests {
     use super::*;

     #[test]
-    fn fqdn_validate_single() {
+    fn fqdn_construct() {
+        use FqdnParseError::*;
         assert!(Fqdn::from("foo.example.com").is_ok());
-        assert!(Fqdn::from("1.example.com").is_ok());
         assert!(Fqdn::from("foo-bar.com").is_ok());
         assert!(Fqdn::from("a-b.com").is_ok());

-        assert!(Fqdn::from("foo").is_err());
-        assert!(Fqdn::from("-foo.com").is_err());
-        assert!(Fqdn::from("foo-.com").is_err());
-        assert!(Fqdn::from("foo.com-").is_err());
-        assert!(Fqdn::from("-o-.com").is_err());
+        assert_eq!(Fqdn::from("foo"), Err(MissingHostname));
+
+        assert_eq!(Fqdn::from("-foo.com"), Err(InvalidPart("-foo".to_owned())));
+        assert_eq!(Fqdn::from("foo-.com"), Err(InvalidPart("foo-".to_owned())));
+        assert_eq!(Fqdn::from("foo.com-"), Err(InvalidPart("com-".to_owned())));
+        assert_eq!(Fqdn::from("-o-.com"), Err(InvalidPart("-o-".to_owned())));
+
+        assert_eq!(Fqdn::from("123.com"), Err(NumericHostname));
+        assert!(Fqdn::from("foo123.com").is_ok());
+        assert!(Fqdn::from("123foo.com").is_ok());
     }

     #[test]
@@ -212,6 +252,10 @@ mod tests {
         let fqdn = Fqdn::from("pve.example.com").unwrap();
         assert_eq!(fqdn.host().unwrap(), "pve");
         assert_eq!(fqdn.domain(), "example.com");
+        assert_eq!(
+            fqdn.parts,
+            &["pve".to_owned(), "example".to_owned(), "com".to_owned()]
+        );
     }

     #[test]
--
2.41.0





^ permalink raw reply	[flat|nested] 2+ messages in thread

* [pve-devel] applied: [PATCH installer v2] tui: fix FQDN validation
  2023-07-19 16:31 [pve-devel] [PATCH installer v2] tui: fix FQDN validation Christoph Heiss
@ 2023-07-21 14:20 ` Thomas Lamprecht
  0 siblings, 0 replies; 2+ messages in thread
From: Thomas Lamprecht @ 2023-07-21 14:20 UTC (permalink / raw)
  To: Proxmox VE development discussion, Christoph Heiss

On 19/07/2023 18:31, Christoph Heiss wrote:
> Add checks to ensure that:
>  * It is actually has a hostname, not just a domain name
>  * Properly check if the hostname is purely numeric, which was
>    broken/different to how the GUI installer does it
> 
> The custom error type also allows for easier future adaptions, as the
> changes can be entirely contained to the `Fqdn` type.
> 
> Signed-off-by: Christoph Heiss <c.heiss@proxmox.com>
> ---
> v1: https://lists.proxmox.com/pipermail/pve-devel/2023-June/057845.html
> 
> Changes v1 -> v2:
>  * Fix & add some more unit tests
>  * Add custom error type `FqdnParseError`
>  * Move hostname checks directly into `Fqdn::from()`
> 
>  proxmox-tui-installer/src/main.rs  |  5 +--
>  proxmox-tui-installer/src/utils.rs | 68 ++++++++++++++++++++++++------
>  2 files changed, 57 insertions(+), 16 deletions(-)
> 
>

applied, thanks!




^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2023-07-21 14:20 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-07-19 16:31 [pve-devel] [PATCH installer v2] tui: fix FQDN validation Christoph Heiss
2023-07-21 14:20 ` [pve-devel] applied: " Thomas Lamprecht

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal