Skip to content

Commit

Permalink
Added DKIM security check #12
Browse files Browse the repository at this point in the history
  • Loading branch information
brendanheywood committed Jan 11, 2024
1 parent ea8acbc commit b78ce62
Show file tree
Hide file tree
Showing 5 changed files with 146 additions and 5 deletions.
103 changes: 103 additions & 0 deletions classes/check/dnsdkim.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* DNS Email DKIM check.
*
* @package tool_emailutils
* @author Brendan Heywood <[email protected]>
* @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 <[email protected]>
* @copyright Catalyst IT 2024
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class dnsdkim 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 .= "<p>No reply email: <code>$noreply</code></p>";

$noreplydomain = $dns->get_noreply_domain();
$details .= "<p>No reply domain: <code>$noreplydomain</code></p>";

$selector = $dns->get_dkim_selector();

// Does it have an DKIM record at all?
if (empty($selector)) {
$summary = 'Missing DKIM selector';
$details .= "<p>$domain does not have an DKIM selector set in \$CFG->emaildkimselector.</p>";
return new result(result::ERROR, $summary, $details);
}

$dkimdomain = $dns->get_dkim_dns_domain($selector, $noreplydomain);
$details .= "<p>DKIM domain: <code>$dkimdomain</code></p>";

$dkim = $dns->get_dkim_record($selector);

if (empty($dkim)) {
$details .= "<p>DKIM record is missing with selector '$selector'</p>";
$status = result::ERROR;
$summary = "DKIM DNS record missing for selector '$selector'";
} else {
$details .= "<p>DKI record:<br><code>$dkim</code></p>";
$status = result::OK;
$summary = "DKIM record exists with selector '$selector'";
}


return new result($status, $summary, $details);
}

}
4 changes: 2 additions & 2 deletions classes/check/dnsspf.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
/**
* DNS Email SPF check.
*
* @package tool_heartbeat
* @package tool_emailutils
* @author Brendan Heywood <[email protected]>
* @copyright Catalyst IT 2024
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
Expand All @@ -31,7 +31,7 @@
/**
* DNS Email SPF check.
*
* @package tool_heartbeat
* @package tool_emailutils
* @author Brendan Heywood <[email protected]>
* @copyright Catalyst IT 2024
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
Expand Down
42 changes: 39 additions & 3 deletions classes/dns_util.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
/**
* SPF utils
*
* @package tool_heartbeat
* @package tool_emailutils
* @copyright Catalyst IT 2024
* @author Brendan Heywood <[email protected]>
* @copyright 2023 onwards Catalyst IT {@link http://www.catalyst-eu.net/}
Expand All @@ -29,7 +29,7 @@
/**
* SPF utils
*
* @package tool_heartbeat
* @package tool_emailutils
* @copyright Catalyst IT 2024
* @author Brendan Heywood <[email protected]>
* @copyright 2023 onwards Catalyst IT {@link http://www.catalyst-eu.net/}
Expand Down Expand Up @@ -65,7 +65,10 @@ public function get_noreply_domain() {
public function get_spf_record() {

$domain = $this->get_noreply_domain();
$records = dns_get_record($domain, DNS_TXT);
$records = @dns_get_record($domain, DNS_TXT);
if (empty($records)) {
return '';
}
foreach ($records as $record) {
$txt = $record['txt'];
if (substr($txt, 0, 6) == 'v=spf1') {
Expand Down Expand Up @@ -105,5 +108,38 @@ public function include_present(string $include) {
return '';
}

/**
* Get DKIM selector
* @return string txt record
*/
public function get_dkim_selector() {
global $CFG;
return $CFG->emaildkimselector;
}

/**
* Get DKIM txt record contents
* @return string txt record
*/
public function get_dkim_dns_domain($selector, $domain) {
return "$selector._domainkey.$domain";
}

/**
* Get DKIM txt record contents
* @return string txt record
*/
public function get_dkim_record($selector) {

$domain = $this->get_noreply_domain();
$dns = $this->get_dkim_dns_domain($selector, $domain);

$records = @dns_get_record($dns, DNS_TXT);
if (empty($records)) {
return '';
}
return $records[0]['txt'];
}

}

1 change: 1 addition & 0 deletions lang/en/tool_emailutils.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
$string['complaints'] = 'For a list of complaints, search for ".c.invalid"';
$string['dkimmanager'] = 'SPF & DKIM manager';
$string['checkdnsspf'] = 'DNS Email SPF check';
$string['checkdnsdkim'] = 'DNS Email DKIM check';
$string['dkimmanagerhelp'] = '<p>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:</p>
<ol>
<li>First decide and set the <code>$CFG->noreply</code> email as the domain of the reply email is tied to the signing.
Expand Down
1 change: 1 addition & 0 deletions lib.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ function tool_emailutils_bulk_user_actions() {
function tool_emailutils_security_checks() {
return [
new \tool_emailutils\check\dnsspf(),
new \tool_emailutils\check\dnsdkim(),
];
}

0 comments on commit b78ce62

Please sign in to comment.