spfcheck : Add catching of sign (+-?~) before parts of SPF record

git-svn-id: https://svn.fournier38.fr/svn/ProgSVN/trunk@6030 bf3deb0d-5f1a-0410-827f-c0cc1f45334c
This commit is contained in:
2020-08-21 09:00:29 +00:00
parent d52314e75b
commit 283109bef4
2 changed files with 74 additions and 25 deletions

View File

@@ -208,6 +208,21 @@ class spfcheckTest extends PHPUnit_Framework_TestCase
))); )));
} }
public function test_recordsWithPlus ()
{
$spfcheck = new spfcheck ();
$res = $spfcheck->getRecords ("plus.spf.tester.fournier38.fr");
$this->assertSame ($res,
array ("plus.spf.tester.fournier38.fr" => array (
"+a" => array (),
"+mx" => array (),
"+ip4:178.33.236.5" => array ("178.33.236.5"),
"+ip4:137.74.69.64" => array ("137.74.69.64"),
"+ip4:51.254.45.81" => array ("51.254.45.81"),
"-all" => array (),
)));
}
public function test_getRecords_Unknown () public function test_getRecords_Unknown ()
{ {
$spfcheck = new spfcheck (); $spfcheck = new spfcheck ();

View File

@@ -247,13 +247,22 @@ class spfcheck
continue; continue;
// "redirect=" part // "redirect=" part
$ips[$domain][$part] = array (); $ips[$domain][$part] = array ();
// Manage the sign in front of part
$sign = "";
if ($part{0} === "+" || $part{0} === "-" || $part{0} === "~" ||
$part{0} === "?")
{
$sign = $part[0];
$part = substr ($part, 1);
}
if (stripos ($part, "redirect=") === 0) if (stripos ($part, "redirect=") === 0)
// {{{ // {{{
{ {
$ext = substr ($part, 9); $ext = substr ($part, 9);
if (! is_string ($ext) || trim ($ext) === "") if (! is_string ($ext) || trim ($ext) === "")
{ {
$this->errors[$domain][$part] = sprintf (dgettext ("domframework", $this->errors[$domain][$sign.$part] =
sprintf (dgettext ("domframework",
"Invalid redirect set for domain '%s' : empty"), $domain); "Invalid redirect set for domain '%s' : empty"), $domain);
continue; continue;
} }
@@ -267,7 +276,8 @@ class spfcheck
$ext = substr ($part, 8); $ext = substr ($part, 8);
if (! is_string ($ext) || trim ($ext) === "") if (! is_string ($ext) || trim ($ext) === "")
{ {
$this->errors[$domain][$part] = sprintf (dgettext ("domframework", $this->errors[$domain][$sign.$part] =
sprintf (dgettext ("domframework",
"Invalid include set for domain '%s' : empty"), $domain); "Invalid include set for domain '%s' : empty"), $domain);
continue; continue;
} }
@@ -284,7 +294,8 @@ class spfcheck
$ext = substr ($partWithDomain, 3); $ext = substr ($partWithDomain, 3);
if (! is_string ($ext) || trim ($ext) === "") if (! is_string ($ext) || trim ($ext) === "")
{ {
$this->errors[$domain][$part] = sprintf (dgettext ("domframework", $this->errors[$domain][$sign.$part] =
sprintf (dgettext ("domframework",
"Invalid mx set for domain '%s' : empty"), $domain); "Invalid mx set for domain '%s' : empty"), $domain);
continue; continue;
} }
@@ -294,10 +305,18 @@ class spfcheck
foreach ($this->dns_get_record ($record, DNS_A | DNS_AAAA, foreach ($this->dns_get_record ($record, DNS_A | DNS_AAAA,
"$domain/$part/$record") as $ip) "$domain/$part/$record") as $ip)
{ {
$ips[$domain][$part][] = $ip; $ips[$domain][$sign.$part][] = $ip;
} }
} }
sort ($ips[$domain][$part]); if (! isset ($ips[$domain][$sign.$part]))
{
$this->errors[$domain][$sign.$part] =
sprintf (dgettext ("domframework",
"Invalid mx set for domain '%s' : not available in DNS"),
$domain);
continue;
}
sort ($ips[$domain][$sign.$part]);
} }
// }}} // }}}
// "ip4:" part // "ip4:" part
@@ -307,7 +326,8 @@ class spfcheck
$ext = substr ($part, 4); $ext = substr ($part, 4);
if (! is_string ($ext) || trim ($ext) === "") if (! is_string ($ext) || trim ($ext) === "")
{ {
$this->errors[$domain][$part] = sprintf (dgettext ("domframework", $this->errors[$domain][$sign.$part] =
sprintf (dgettext ("domframework",
"Invalid ip4 set for domain '%s' : empty"), $domain); "Invalid ip4 set for domain '%s' : empty"), $domain);
continue; continue;
} }
@@ -315,7 +335,8 @@ class spfcheck
$mask = ($mask === null) ? $mask = "" : $mask = "/$mask"; $mask = ($mask === null) ? $mask = "" : $mask = "/$mask";
if (filter_var ($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) === false) if (filter_var ($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) === false)
{ {
$this->errors[$domain][$part] = sprintf (dgettext ("domframework", $this->errors[$domain][$sign.$part] =
sprintf (dgettext ("domframework",
"Invalid ip4 set for domain '%s' : Not a valid IPv4 '%s'"), "Invalid ip4 set for domain '%s' : Not a valid IPv4 '%s'"),
$domain, $ext); $domain, $ext);
continue; continue;
@@ -324,12 +345,13 @@ class spfcheck
filter_var ($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) && filter_var ($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) &&
substr ($mask, 1) < 16) substr ($mask, 1) < 16)
{ {
$this->errors[$domain][$part] = sprintf (dgettext ("domframework", $this->errors[$domain][$sign.$part] =
sprintf (dgettext ("domframework",
"Invalid ip4 set for domain '%s' : Mask '%s' too wide"), "Invalid ip4 set for domain '%s' : Mask '%s' too wide"),
$domain, $mask); $domain, $mask);
continue; continue;
} }
$ips[$domain][$part][] = $ip.$mask; $ips[$domain][$sign.$part][] = $ip.$mask;
} }
// }}} // }}}
// "ip6:" part // "ip6:" part
@@ -339,7 +361,8 @@ class spfcheck
$ext = substr ($part, 4); $ext = substr ($part, 4);
if (! is_string ($ext) || trim ($ext) === "") if (! is_string ($ext) || trim ($ext) === "")
{ {
$this->errors[$domain][$part] = sprintf (dgettext ("domframework", $this->errors[$domain][$sign.$part] =
sprintf (dgettext ("domframework",
"Invalid ip6 set for domain '%s' : empty"), $domain); "Invalid ip6 set for domain '%s' : empty"), $domain);
continue; continue;
} }
@@ -347,7 +370,8 @@ class spfcheck
$mask = ($mask === null) ? $mask = "" : $mask = "/$mask"; $mask = ($mask === null) ? $mask = "" : $mask = "/$mask";
if (filter_var ($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) === false) if (filter_var ($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) === false)
{ {
$this->errors[$domain][$part] = sprintf (dgettext ("domframework", $this->errors[$domain][$sign.$part] =
sprintf (dgettext ("domframework",
"Invalid ip6 set for domain '%s' : Not a valid IPv6 '%s'"), "Invalid ip6 set for domain '%s' : Not a valid IPv6 '%s'"),
$domain, $ext); $domain, $ext);
continue; continue;
@@ -356,19 +380,21 @@ class spfcheck
filter_var ($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) && filter_var ($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) &&
substr ($mask, 1) < 64) substr ($mask, 1) < 64)
{ {
$this->errors[$domain][$part] = sprintf (dgettext ("domframework", $this->errors[$domain][$sign.$part] =
sprintf (dgettext ("domframework",
"Invalid ip6 set for domain '%s' : Mask '%s' too wide"), "Invalid ip6 set for domain '%s' : Mask '%s' too wide"),
$domain, $mask); $domain, $mask);
continue; continue;
} }
$ips[$domain][$part][] = $ip.$mask; $ips[$domain][$sign.$part][] = $ip.$mask;
} }
// }}} // }}}
// "ptr:" MUST NOT BE USED // "ptr:" MUST NOT BE USED
elseif (stripos ($part, "ptr:") === 0 || strtolower ($part) === "ptr") elseif (stripos ($part, "ptr:") === 0 || strtolower ($part) === "ptr")
// {{{ // {{{
{ {
$this->errors[$domain][$part] = sprintf (dgettext ("domframework", $this->errors[$domain][$sign.$part] =
sprintf (dgettext ("domframework",
"Invalid ptr set for domain '%s' : PTR must not be used anymore ". "Invalid ptr set for domain '%s' : PTR must not be used anymore ".
"(see RFC7208) : Skip it"), $domain, $part); "(see RFC7208) : Skip it"), $domain, $part);
continue; continue;
@@ -384,35 +410,42 @@ class spfcheck
$ext = substr ($partWithDomain, 2); $ext = substr ($partWithDomain, 2);
if (! is_string ($ext) || trim ($ext) === "") if (! is_string ($ext) || trim ($ext) === "")
{ {
$this->errors[$domain][$part] = sprintf (dgettext ("domframework", $this->errors[$domain][$sign.$part] =
sprintf (dgettext ("domframework",
"Invalid A set for domain '%s' : empty"), $domain); "Invalid A set for domain '%s' : empty"), $domain);
continue; continue;
} }
foreach ($this->dns_get_record ($ext, DNS_A | DNS_AAAA, foreach ($this->dns_get_record ($ext, DNS_A | DNS_AAAA,
"$domain/$part") as $record) "$domain/$part") as $record)
{ {
$ips[$domain][$part][] = $record; $ips[$domain][$sign.$part][] = $record;
} }
sort ($ips[$domain][$part]); if (! isset ($ips[$domain][$sign.$part]))
{
$this->errors[$domain][$sign.$part] =
sprintf (dgettext ("domframework",
"Invalid A set for domain '%s' : not available in DNS"), $domain);
continue;
}
sort ($ips[$domain][$sign.$part]);
} }
// }}} // }}}
// "-all" / "~all" / "+all" part // "-all" / "~all" / "+all" part
elseif (strtolower ($part) === "-all" || elseif (strtolower ($part) === "all")
strtolower ($part) === "~all" ||
strtolower ($part) === "?all" ||
strtolower ($part) === "+all")
// {{{ // {{{
{ {
$ips[$domain][$part] = array (); $ips[$domain][$sign.$part] = array ();
if ($localAll !== "") if ($localAll !== "")
{ {
$this->errors [$domain][$part] = sprintf (dgettext ("domframework", $this->errors [$domain][$sign.$part] =
sprintf (dgettext ("domframework",
"Multiple 'all' definitions for domain '%s'"), $domain); "Multiple 'all' definitions for domain '%s'"), $domain);
continue; continue;
} }
if ($nb < count ($split) -1) if ($nb < count ($split) -1)
{ {
$this->errors [$domain][$part] = sprintf (dgettext ("domframework", $this->errors [$domain][$sign.$part] =
sprintf (dgettext ("domframework",
"'all' must be the last part of the record for domain '%s'"), "'all' must be the last part of the record for domain '%s'"),
$domain); $domain);
} }
@@ -423,7 +456,8 @@ class spfcheck
// }}} // }}}
else else
{ {
$this->errors [$domain][$part] = sprintf (dgettext ("domframework", $this->errors [$domain][$sign.$part] =
sprintf (dgettext ("domframework",
"Unknown record part for domain '%s' : '%s'"), $domain, $part); "Unknown record part for domain '%s' : '%s'"), $domain, $part);
} }
} }