mirror of
https://github.com/mailcow/mailcow-dockerized.git
synced 2024-12-25 02:29:32 +02:00
b39ac8f649
When using a redirect in your SPF record, the web UI validation failed when your record contained a ipv6 address. In web/inc/ajax/dns_diagnostics.php the function get_spf_allowed_hosts is called with the second parameter to be true to expand ipv6 addresses. But when called for redirects, the value was not set to true, so it defaulted back to false. This caused an unexpanded ipv6 address to be added to the array and the in_array match for ipv6 never matched as it is always called with expand_ipv6. While looking at the code i noted some messed up in the indention, which is also "fixed" by this commit.
147 lines
3.5 KiB
PHP
147 lines
3.5 KiB
PHP
<?php
|
|
error_reporting(0);
|
|
function get_spf_allowed_hosts($check_domain, $expand_ipv6 = false) {
|
|
$hosts = array();
|
|
|
|
$records = dns_get_record($check_domain, DNS_TXT);
|
|
foreach ($records as $record)
|
|
{
|
|
$txt = explode(' ', $record['entries'][0]);
|
|
if (array_shift($txt) != 'v=spf1') // only handle SPF records
|
|
continue;
|
|
|
|
foreach ($txt as $mech)
|
|
{
|
|
$qual = substr($mech, 0, 1);
|
|
if ($qual == '-' || $qual == '~') // only handle pass or neutral records
|
|
continue(2);
|
|
|
|
if ($qual == '+' || $qual == '?')
|
|
$mech = substr($mech, 1); // remove the qualifier
|
|
|
|
if (strpos($mech, '=') !== FALSE) // handle a modifier
|
|
{
|
|
$mod = explode('=', $mech);
|
|
if ($mod[0] == 'redirect') // handle a redirect
|
|
{
|
|
$hosts = get_spf_allowed_hosts($mod[1],true);
|
|
return $hosts;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
unset($cidr);
|
|
// reset domain to check_domain
|
|
$domain = $check_domain;
|
|
if (strpos($mech, ':') !== FALSE) // handle a domain specification
|
|
{
|
|
$split = explode(':', $mech);
|
|
$mech = array_shift($split);
|
|
$domain = implode(':', $split);
|
|
if (strpos($domain, '/') !== FALSE) // remove CIDR specification
|
|
{
|
|
$split = explode('/', $domain);
|
|
$domain = $split[0];
|
|
$cidr = $split[1];
|
|
}
|
|
}
|
|
|
|
$new_hosts = array();
|
|
if ($mech == 'include' && $check_domain != $domain) // handle an inclusion
|
|
{
|
|
$new_hosts = get_spf_allowed_hosts($domain);
|
|
}
|
|
elseif ($mech == 'a') // handle a mechanism
|
|
{
|
|
$new_hosts = get_a_hosts($domain);
|
|
}
|
|
elseif ($mech == 'mx') // handle mx mechanism
|
|
{
|
|
$new_hosts = get_mx_hosts($domain);
|
|
}
|
|
elseif ($mech == 'ip4' || $mech == 'ip6') // handle ip mechanism
|
|
{
|
|
$new_hosts = array($domain);
|
|
}
|
|
|
|
if (isset($cidr)) // add CIDR specification if present
|
|
{
|
|
foreach ($new_hosts as &$host)
|
|
{
|
|
$host .= '/' . $cidr;
|
|
}
|
|
unset($host);
|
|
}
|
|
|
|
$hosts = array_unique(array_merge($hosts,$new_hosts), SORT_REGULAR);
|
|
}
|
|
}
|
|
}
|
|
foreach ($hosts as &$host) {
|
|
if (filter_var($host, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
|
|
if ($expand_ipv6 === true) {
|
|
$hex = unpack("H*hex", inet_pton($host));
|
|
$host = substr(preg_replace("/([A-f0-9]{4})/", "$1:", $hex['hex']), 0, -1);
|
|
}
|
|
else {
|
|
$host = $host;
|
|
}
|
|
}
|
|
}
|
|
return $hosts;
|
|
}
|
|
|
|
|
|
function get_mx_hosts($domain)
|
|
{
|
|
$hosts = array();
|
|
try {
|
|
$mx_records = dns_get_record($domain, DNS_MX);
|
|
if ($mx_records) {
|
|
foreach ($mx_records as $mx_record) {
|
|
$new_hosts = get_a_hosts($mx_record['target']);
|
|
$hosts = array_unique(array_merge($hosts,$new_hosts), SORT_REGULAR);
|
|
}
|
|
}
|
|
}
|
|
catch (Exception $e) {
|
|
if ($e->getMessage() !== 'dns_get_record(): A temporary server error occurred.') {
|
|
throw $e;
|
|
}
|
|
$mx_records = false;
|
|
}
|
|
return $hosts;
|
|
}
|
|
|
|
function get_a_hosts($domain)
|
|
{
|
|
$hosts = array();
|
|
|
|
$a_records = dns_get_record($domain, DNS_A);
|
|
foreach ($a_records as $a_record)
|
|
{
|
|
$hosts[] = $a_record['ip'];
|
|
}
|
|
$a_records = dns_get_record($domain, DNS_AAAA);
|
|
foreach ($a_records as $a_record) {
|
|
$hosts[] = $a_record['ipv6'];
|
|
}
|
|
|
|
return $hosts;
|
|
}
|
|
|
|
function get_outgoing_hosts_best_guess($domain)
|
|
{
|
|
// try the SPF record to get hosts that are allowed to send outgoing mails for this domain
|
|
$hosts = get_spf_allowed_hosts($domain);
|
|
if ($hosts) return $hosts;
|
|
|
|
// try the MX record to get mail servers for this domain
|
|
$hosts = get_mx_hosts($domain);
|
|
if ($hosts) return $hosts;
|
|
|
|
// fall back to the A record to get the host name for this domain
|
|
return get_a_hosts($domain);
|
|
}
|
|
?>
|