Fixed potential hostname validation issues

This commit is contained in:
Pinga 2025-03-07 12:13:41 +02:00
parent 1e9db418f9
commit 813dd16e82
2 changed files with 52 additions and 45 deletions

View file

@ -45,7 +45,7 @@ class HostsController extends Controller
} }
} }
if (preg_match('/^([A-Z0-9]([A-Z0-9-]{0,61}[A-Z0-9]){0,1}\.){1,125}[A-Z0-9]([A-Z0-9-]{0,61}[A-Z0-9])$/i', $hostName) && strlen($hostName) < 254) { if (isValidHostname($hostName)) {
$host_id_already_exist = $hostModel->getHostByNom($hostName); $host_id_already_exist = $hostModel->getHostByNom($hostName);
if ($host_id_already_exist) { if ($host_id_already_exist) {
$this->container->get('flash')->addMessage('error', 'Error creating host: host name ' . $hostName . ' already exists'); $this->container->get('flash')->addMessage('error', 'Error creating host: host name ' . $hostName . ' already exists');
@ -244,20 +244,6 @@ class HostsController extends Controller
// Get the current URI // Get the current URI
$uri = $request->getUri()->getPath(); $uri = $request->getUri()->getPath();
function isValidHostname($hostname) {
$hostname = trim($hostname);
// Check for IDN and convert to ASCII if necessary
if (mb_detect_encoding($hostname, 'ASCII', true) === false) {
$hostname = idn_to_ascii($hostname, IDNA_NONTRANSITIONAL_TO_ASCII, INTL_IDNA_VARIANT_UTS46);
}
// Regular expression for validating a hostname
$pattern = '/^((xn--[a-zA-Z0-9-]{1,63}|[a-zA-Z0-9-]{1,63})\.){2,}(xn--[a-zA-Z0-9-]{2,63}|[a-zA-Z]{2,63})$/';
return preg_match($pattern, $hostname);
}
if ($args && isValidHostname($args)) { if ($args && isValidHostname($args)) {
$host = $db->selectRow('SELECT id, name, clid, crdate FROM host WHERE name = ?', $host = $db->selectRow('SELECT id, name, clid, crdate FROM host WHERE name = ?',
[ $args ]); [ $args ]);
@ -318,21 +304,16 @@ class HostsController extends Controller
// Get the current URI // Get the current URI
$uri = $request->getUri()->getPath(); $uri = $request->getUri()->getPath();
function isValidHostname($hostname) {
$hostname = trim($hostname);
// Check for IDN and convert to ASCII if necessary
if (mb_detect_encoding($hostname, 'ASCII', true) === false) {
$hostname = idn_to_ascii($hostname, IDNA_NONTRANSITIONAL_TO_ASCII, INTL_IDNA_VARIANT_UTS46);
}
// Regular expression for validating a hostname
$pattern = '/^((xn--[a-zA-Z0-9-]{1,63}|[a-zA-Z0-9-]{1,63})\.){2,}(xn--[a-zA-Z0-9-]{2,63}|[a-zA-Z]{2,63})$/';
return preg_match($pattern, $hostname);
}
if ($args && isValidHostname($args)) { if ($args && isValidHostname($args)) {
$args = trim($args);
if (mb_detect_encoding($args, 'ASCII', true) === false) {
$args = idn_to_ascii($args, IDNA_NONTRANSITIONAL_TO_ASCII, INTL_IDNA_VARIANT_UTS46);
if ($args === false) {
// Redirect to the hosts view
return $response->withHeader('Location', '/hosts')->withStatus(302);
}
}
$internal_host = false; $internal_host = false;
$query = "SELECT tld FROM domain_tld"; $query = "SELECT tld FROM domain_tld";
@ -565,20 +546,6 @@ class HostsController extends Controller
// Get the current URI // Get the current URI
$uri = $request->getUri()->getPath(); $uri = $request->getUri()->getPath();
function isValidHostname($hostname) {
$hostname = trim($hostname);
// Check for IDN and convert to ASCII if necessary
if (mb_detect_encoding($hostname, 'ASCII', true) === false) {
$hostname = idn_to_ascii($hostname, 0, INTL_IDNA_VARIANT_UTS46);
}
// Regular expression for validating a hostname
$pattern = '/^((xn--[a-zA-Z0-9-]{1,63}|[a-zA-Z0-9-]{1,63})\.){2,}(xn--[a-zA-Z0-9-]{2,63}|[a-zA-Z]{2,63})$/';
return preg_match($pattern, $hostname);
}
if ($args && isValidHostname($args)) { if ($args && isValidHostname($args)) {
$host = $db->selectRow('SELECT id, clid FROM host WHERE name = ?', $host = $db->selectRow('SELECT id, clid FROM host WHERE name = ?',
[ $args ]); [ $args ]);

View file

@ -1087,3 +1087,43 @@ function generateIanaIdnTable(string $regex, array $metadata): string {
} }
return $output; return $output;
} }
function isValidHostname($hostname) {
$hostname = trim($hostname);
// Convert IDN (Unicode) to ASCII if necessary
if (mb_detect_encoding($hostname, 'ASCII', true) === false) {
$hostname = idn_to_ascii($hostname, IDNA_NONTRANSITIONAL_TO_ASCII, INTL_IDNA_VARIANT_UTS46);
if ($hostname === false) {
return false; // Invalid IDN conversion
}
}
// Ensure there is at least **one dot** (to prevent single-segment hostnames)
if (substr_count($hostname, '.') < 1) {
return false;
}
// Regular expression for validating a hostname
$pattern = '/^((xn--[a-zA-Z0-9-]{1,63}|[a-zA-Z0-9-]{1,63})\.)*([a-zA-Z0-9-]{1,63}|xn--[a-zA-Z0-9-]{2,63})$/';
// Ensure it matches the hostname pattern
if (!preg_match($pattern, $hostname)) {
return false;
}
// Ensure no label exceeds 63 characters
$labels = explode('.', $hostname);
foreach ($labels as $label) {
if (strlen($label) > 63) {
return false;
}
}
// Ensure full hostname is not longer than 255 characters
if (strlen($hostname) > 255) {
return false;
}
return true;
}