Skip to content

Commit

Permalink
Utils: Port hostname validation from distinst and add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
meisenzahl committed Oct 2, 2024
1 parent a8cd3ad commit 66a74e3
Show file tree
Hide file tree
Showing 7 changed files with 88 additions and 1 deletion.
1 change: 1 addition & 0 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,4 @@ subdir('common')
subdir('daemon')
subdir('src')
subdir('data')
subdir('test')
43 changes: 43 additions & 0 deletions src/HostnameValidator.vala
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Copyright 2018-2022 System76 <[email protected]>
* Copyright 2024 elementary, Inc. (https://elementary.io)
* SPDX-License-Identifier: MIT
*/

namespace Utils {
private bool hostname_is_valid_char (char c) {
return (c.isalnum () ||
c == '-' ||
c == '.');
}

// Based on https://github.com/pop-os/hostname-validator/blob/458fa5a1df98cb663f0456dffb542e1a907861c9/src/lib.rs#L29
/// Validate a hostname according to [IETF RFC 1123](https://tools.ietf.org/html/rfc1123).
///
/// A hostname is valid if the following condition are true:
///
/// - It does not start or end with `-` or `.`.
/// - It does not contain any characters outside of the alphanumeric range, except for `-` and `.`.
/// - It is not empty.
/// - It is 253 or fewer characters.
/// - Its labels (characters separated by `.`) are not empty.
/// - Its labels are 63 or fewer characters.
/// - Its labels do not start or end with '-' or '.'.
public bool hostname_is_valid (string hostname) {
for (int i = 0; i < hostname.char_count (); i++) {
char c = hostname[i];
if (!hostname_is_valid_char (c)) {
return false;
}
}

string[] labels = hostname.split (".", -1);
foreach (string label in labels) {
if (label.char_count () == 0 || label.length > 63 || label[0] == '-' || label[label.length - 1] == '-') {
return false;
}
}

return !(hostname.char_count () == 0 || hostname.length > 253);
}
}
2 changes: 1 addition & 1 deletion src/Utils.vala
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ namespace Utils {
// If the automatic hostname logic fails in some way, it's possible we may generate an invalid
// hostname. We could fix this by trimming traling/leading hyphens or other invalid characters.
// But it's probably a bad hostname anyway, so just fallback
if (!Distinst.validate_hostname (hostname)) {
if (!hostname_is_valid (hostname)) {
hostname = "elementary-os";
}

Expand Down
1 change: 1 addition & 0 deletions src/meson.build
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
vala_files = [
'Application.vala',
'HostnameValidator.vala',
'MainWindow.vala',
'Utils.vala',
'Helpers/InstallerDaemon.vala',
Expand Down
24 changes: 24 additions & 0 deletions test/HostnameValidatorTest.vala
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
void add_hostname_validator_tests () {
Test.add_func ("/valid", () => {
assert (Utils.hostname_is_valid ("VaLiD-HoStNaMe"));
assert (Utils.hostname_is_valid ("50-name"));
assert (Utils.hostname_is_valid ("235235"));
assert (Utils.hostname_is_valid ("example.com"));
assert (Utils.hostname_is_valid ("VaLid.HoStNaMe"));
assert (Utils.hostname_is_valid ("123.456"));
});

Test.add_func ("/invalid", () => {
assert (!Utils.hostname_is_valid ("-invalid-name"));
assert (!Utils.hostname_is_valid ("also-invalid-"));
assert (!Utils.hostname_is_valid ("asdf@fasd"));
assert (!Utils.hostname_is_valid ("@asdfl"));
assert (!Utils.hostname_is_valid ("asd f@"));
assert (!Utils.hostname_is_valid (".invalid"));
assert (!Utils.hostname_is_valid ("invalid.name."));
assert (!Utils.hostname_is_valid ("foo.label-is-way-to-longgggggggggggggggggggggggggggggggggggggggggggg.org"));
assert (!Utils.hostname_is_valid ("invalid.-starting.char"));
assert (!Utils.hostname_is_valid ("invalid.ending-.char"));
assert (!Utils.hostname_is_valid ("empty..label"));
});
}
5 changes: 5 additions & 0 deletions test/Test.vala
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
void main (string[] args) {
Test.init (ref args);
add_hostname_validator_tests ();
Test.run ();
}
13 changes: 13 additions & 0 deletions test/meson.build
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
test_dependencies = [
glib_dep,
]

tests = executable(
meson.project_name() + '-tests',
'HostnameValidatorTest.vala',
'Test.vala',
meson.project_source_root() + '/src/HostnameValidator.vala',
dependencies: test_dependencies
)

test('Test', tests)

0 comments on commit 66a74e3

Please sign in to comment.