mirror of
https://github.com/mailcow/mailcow-dockerized.git
synced 2026-08-04 07:54:59 +00:00
[Web] use absolute RHS names in generated DNS zonefile
The DNS overview "Download" produces a $ORIGIN zonefile, but the right-hand side of MX, CNAME and SRV records was emitted as a relative name. A target such as mail.example.net is then read relative to the origin and expands to mail.example.net.example.org., which is wrong. The only prior attempt at making names absolute was str_replace($domain, $domain . '.', ...), which appended a dot only to targets that happened to contain the origin domain, so cross-domain targets stayed relative. That same replace also corrupted any TXT value containing the origin (e.g. a DMARC rua=mailto:x@example.org became ...@example.org.). Absolutize the RHS per record type at export time only: MX and CNAME targets, and the SRV target token, get a trailing dot; ports, the SRV root target ".", IP addresses and TXT character strings are left as is. The records used for the on-page DNS validation are untouched, so matching against dns_get_record() output still works. Fixes #6984 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
c1d75cf808
commit
e5d0ed8c4c
1 changed files with 21 additions and 1 deletions
|
|
@ -442,6 +442,16 @@ if (isset($_SESSION['mailcow_cc_role']) && ($_SESSION['mailcow_cc_role'] == "adm
|
|||
|
||||
unset($record);
|
||||
|
||||
// Make a hostname RHS absolute so it is not read relative to $ORIGIN.
|
||||
// Already-absolute names, the SRV root target "." and IP addresses are left alone.
|
||||
$absolutize = function($host) {
|
||||
$host = trim($host);
|
||||
if ($host === '' || $host === '.' || substr($host, -1) === '.' || filter_var($host, FILTER_VALIDATE_IP)) {
|
||||
return $host;
|
||||
}
|
||||
return $host . '.';
|
||||
};
|
||||
|
||||
$dns_data = sprintf("\$ORIGIN %s.\n", $domain);
|
||||
foreach ($records as $record) {
|
||||
if ($domain == substr($record[0], -strlen($domain))) {
|
||||
|
|
@ -462,16 +472,26 @@ if (isset($_SESSION['mailcow_cc_role']) && ($_SESSION['mailcow_cc_role'] == "adm
|
|||
$val = str_replace(state_optional, '', $val);
|
||||
$val = str_replace(state_good, '', $val);
|
||||
if (strlen($val) > 0) {
|
||||
// these are all TXT values, their RHS is a character string, not a name
|
||||
$vals[] = sprintf("%s\tIN\t%s\t%s\n", $label, $record[1], $val);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ($record[1] == 'MX' || $record[1] == 'CNAME') {
|
||||
$val = $absolutize($val);
|
||||
}
|
||||
elseif ($record[1] == 'SRV') {
|
||||
// format here is "target port"; only the target is a name
|
||||
$parts = explode(' ', $val, 2);
|
||||
$parts[0] = $absolutize($parts[0]);
|
||||
$val = implode(' ', $parts);
|
||||
}
|
||||
$vals[] = sprintf("%s\tIN\t%s\t%s\n", $label, $record[1], $val);
|
||||
}
|
||||
|
||||
foreach ($vals as $val) {
|
||||
$dns_data .= str_replace($domain, $domain . '.', $val);
|
||||
$dns_data .= $val;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue