Skip to content

Commit

Permalink
Adde SPF basic security check #13
Browse files Browse the repository at this point in the history
  • Loading branch information
brendanheywood committed Jan 11, 2024
1 parent f0c2325 commit 52b6e1b
Show file tree
Hide file tree
Showing 4 changed files with 179 additions and 0 deletions.
99 changes: 99 additions & 0 deletions classes/check/dnsspf.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
<?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 SPF check.
*
* @package tool_heartbeat
* @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\spf;

/**
* DNS Email SPF check.
*
* @package tool_heartbeat
* @author Brendan Heywood <[email protected]>
* @copyright Catalyst IT 2024
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class dnsspf extends check {

/**
* 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 = '';

$spf = new spf();

$noreply = $spf->get_noreply();
$details .= "<p>No reply email: <code>$noreply</code></p>";

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

$spf = $spf->get_spf_record();

// Does it has an SPF record at all?
if (!empty($spf)) {
$details .= "<p>SPF record:<br><code>$spf</code></p>";
$status = result::OK;
$summary = 'SPF record exists';

} else {
$status = result::CRITICAL;
$summary = 'Missing SPF record';
$details .= "<p>$domain does not have an SPF record</p>";
}

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

/**
* Find the top level domain
*
* @return domain
*/
public function get_base_domain($domain) {
$parts = explode('.', $domain);
$size = count($parts);
for ($c = $size - 1; $c >= 0; $c--) {
$end = join('.', array_slice($parts, $c, $size));
$result = @dns_get_record($end . '.', DNS_A);
if (!empty($result)) {
return $end;
}
}
return $domain;
}

}
68 changes: 68 additions & 0 deletions classes/spf.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<?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/>.

/**
* SPF utils
*
* @package tool_heartbeat
* @copyright Catalyst IT 2024
* @author Brendan Heywood <[email protected]>
* @copyright 2023 onwards Catalyst IT {@link http://www.catalyst-eu.net/}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/

namespace tool_emailutils;

/**
* SPF utils
*
* @package tool_heartbeat
* @copyright Catalyst IT 2024
* @author Brendan Heywood <[email protected]>
* @copyright 2023 onwards Catalyst IT {@link http://www.catalyst-eu.net/}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class spf {

public function get_noreply() {
global $CFG;

return $CFG->noreplyaddress;
}

public function get_noreply_domain() {
global $CFG;

$noreplydomain = substr($CFG->noreplyaddress, strpos($CFG->noreplyaddress, '@') + 1);
return $noreplydomain;
}


public function get_spf_record() {

$domain = self::get_noreply_domain();
$records = dns_get_record($domain, DNS_TXT);
foreach ($records as $record) {
$txt = $record['txt'];
if (substr($txt, 0, 6) == 'v=spf1') {
return $txt;
}
}
return '';
}

}

1 change: 1 addition & 0 deletions lang/en/tool_emailutils.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
$string['configmissing'] = 'Missing config.php setting ($CFG->handlebounces) please review config-dist.php for more information.';
$string['complaints'] = 'For a list of complaints, search for ".c.invalid"';
$string['dkimmanager'] = 'DKIM manager';
$string['checkdnsspf'] = 'DNS Email SPF 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
11 changes: 11 additions & 0 deletions lib.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,14 @@ function tool_emailutils_bulk_user_actions() {
];
}

/**
* Security checks.
*
* @return array
*/
function tool_emailutils_security_checks() {
return [
new \tool_emailutils\check\dnsspf(),
];
}

0 comments on commit 52b6e1b

Please sign in to comment.