From 93845a59b288dbebc8a1d323e2f6a3456f5bd19a Mon Sep 17 00:00:00 2001 From: Brendan Heywood Date: Thu, 11 Jan 2024 16:43:36 +1100 Subject: [PATCH] Added DMARC check #12 --- classes/check/dnsdkim.php | 1 - classes/check/dnsdmarc.php | 90 +++++++++++++++++++++++++++++++++++++ classes/check/dnsspf.php | 1 - classes/dns_util.php | 22 +++++++++ lang/en/tool_emailutils.php | 3 +- lib.php | 1 + 6 files changed, 115 insertions(+), 3 deletions(-) create mode 100644 classes/check/dnsdmarc.php diff --git a/classes/check/dnsdkim.php b/classes/check/dnsdkim.php index 7f2eb08..f88ddde 100644 --- a/classes/check/dnsdkim.php +++ b/classes/check/dnsdkim.php @@ -96,7 +96,6 @@ public function get_result() : result { $summary = "DKIM record exists with selector '$selector'"; } - return new result($status, $summary, $details); } diff --git a/classes/check/dnsdmarc.php b/classes/check/dnsdmarc.php new file mode 100644 index 0000000..498df75 --- /dev/null +++ b/classes/check/dnsdmarc.php @@ -0,0 +1,90 @@ +. +/** + * DNS Email DMARC check. + * + * @package tool_emailutils + * @author Brendan Heywood + * @copyright Catalyst IT 2024 + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * + */ + +namespace tool_emailutils\check; +use core\check\check; +use core\check\result; +use tool_emailutils\dns_util; + +/** + * DNS Email DKIM check. + * + * @package tool_emailutils + * @author Brendan Heywood + * @copyright Catalyst IT 2024 + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class dnsdmarc extends check { + + /** + * A link to a place to action this + * + * @return \action_link|null + */ + public function get_action_link(): ?\action_link { + return new \action_link( + new \moodle_url('/admin/tool/emailutils/dkim.php'), + get_string('dkimmanager', 'tool_emailutils')); + } + + /** + * Get Result. + * + * @return result + */ + public function get_result() : result { + global $DB, $CFG; + + $url = new \moodle_url($CFG->wwwroot); + $domain = $url->get_host(); + + $details = ''; + $status = result::INFO; + $summary = ''; + + $dns = new dns_util(); + + $noreply = $dns->get_noreply(); + $details .= "

No reply email: $noreply

"; + + $noreplydomain = $dns->get_noreply_domain(); + $details .= "

Start looking in domain: $noreplydomain

"; + + [$dmarcdomain, $dmarc] = $dns->get_dmarc_dns_record(); + + if (empty($dmarc)) { + $details .= "

DMARC record is missing

"; + $status = result::ERROR; + $summary = "DMARC DNS record missing"; + } else { + $details .= "

DMARC record found on domain $dmarcdomain
$dmarc

"; + $status = result::OK; + $summary = "DMARC record exists"; + } + + return new result($status, $summary, $details); + } + +} diff --git a/classes/check/dnsspf.php b/classes/check/dnsspf.php index b0b694c..c6c3d94 100644 --- a/classes/check/dnsspf.php +++ b/classes/check/dnsspf.php @@ -98,7 +98,6 @@ public function get_result() : result { } } - return new result($status, $summary, $details); } diff --git a/classes/dns_util.php b/classes/dns_util.php index e681ca1..810dbeb 100644 --- a/classes/dns_util.php +++ b/classes/dns_util.php @@ -141,5 +141,27 @@ public function get_dkim_record($selector) { return $records[0]['txt']; } + /** + * Get DKIM txt record contents + * @return string txt record + */ + public function get_dmarc_dns_record() { + $domain = $this->get_noreply_domain(); + + while ($domain) { + $dmarcdomain = '_dmarc.' . $domain; + $records = @dns_get_record($dmarcdomain, DNS_TXT); + if (!empty($records)) { + // if ( 'v=DMARC') + return [$dmarcdomain, $records[0]['txt']]; + } + + $parts = explode('.', $domain); + $domain = join('.', array_slice($parts, 1)); + + } + return ['', '']; + } + } diff --git a/lang/en/tool_emailutils.php b/lang/en/tool_emailutils.php index 4cd07d2..4ebbe10 100644 --- a/lang/en/tool_emailutils.php +++ b/lang/en/tool_emailutils.php @@ -33,6 +33,7 @@ $string['dkimmanager'] = 'SPF & DKIM manager'; $string['checkdnsspf'] = 'DNS Email SPF check'; $string['checkdnsdkim'] = 'DNS Email DKIM check'; +$string['checkdnsdmarc'] = 'DNS Email DMARC check'; $string['dkimmanagerhelp'] = '

This shows all DKIM key pairs / selectors available for email signing, including those made by this admin tool or put in place by external tools such as open-dkim. For most systems this is the end to end setup:

  1. First decide and set the $CFG->noreply email as the domain of the reply email is tied to the signing. @@ -46,7 +47,7 @@ '; $string['dnssettings'] = 'SPF / DKIM / DMARC DNS settings'; $string['dnsspfinclude'] = 'SPF include'; -$string['dnsspfinclude_help'] = '

    This is an SPF include domain which is expected to be present in the record. For example if this was set to spf.acme.org then the SPF security check would pass if the SPF record was v=spf1 include:spf.ache.org -all.

    +$string['dnsspfinclude_help'] = '

    This is an SPF include domain which is expected to be present in the record. For example if this was set to spf.acme.org then the SPF security check would pass if the SPF record was v=spf1 include:spf.acme.org -all.

    The * char can be used as a wildcard eg *acme.org would also match.

    '; $string['domaindefaultnoreply'] = 'Default noreply'; diff --git a/lib.php b/lib.php index 0718e9e..2b98f37 100644 --- a/lib.php +++ b/lib.php @@ -44,6 +44,7 @@ function tool_emailutils_security_checks() { return [ new \tool_emailutils\check\dnsspf(), new \tool_emailutils\check\dnsdkim(), + new \tool_emailutils\check\dnsdmarc(), ]; }