Skip to content

Commit

Permalink
Allow for custom requests limits
Browse files Browse the repository at this point in the history
Get more data from Result (getRecord, getSteps, getRequestCount, getRequestMXCount, getRequestPTRCount, getVoidLookups)
Minor bugfixes
  • Loading branch information
Mikael Peigney committed Jan 14, 2023
1 parent 0a143ae commit 03bdf80
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 37 deletions.
29 changes: 25 additions & 4 deletions src/DNS/Session.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,16 @@ final class Session
protected int $requestCount = 0;
protected int $requestMXCount = 0;
protected int $requestPTRCount = 0;
private int $maxRequests;
private int $maxMXRequests;
private int $maxPTRRequests;

public function __construct(DNSRecordGetterInterface $DNSRecordGetter)
public function __construct(DNSRecordGetterInterface $DNSRecordGetter, int $maxRequests = 10, int $maxMXRequests = 10, int $maxPTRRequests = 10)
{
$this->DNSRecordGetter = $DNSRecordGetter;
$this->maxRequests = $maxRequests;
$this->maxMXRequests = $maxMXRequests;
$this->maxPTRRequests = $maxPTRRequests;
}

/**
Expand Down Expand Up @@ -83,6 +89,21 @@ public function resolveTXT(string $hostname): array
return $this->DNSRecordGetter->resolveTXT($hostname);
}

public function getRequestCount(): int
{
return $this->requestCount;
}

public function getRequestMXCount(): int
{
return $this->requestMXCount;
}

public function getRequestPTRCount(): int
{
return $this->requestPTRCount;
}

/**
* @throws DNSLookupLimitReachedException
*/
Expand All @@ -96,7 +117,7 @@ public function countRedirect(): void
*/
private function countRequest(): void
{
if ($this->requestCount++ == 10) {
if ($this->requestCount++ == $this->maxRequests) {
throw new DNSLookupLimitReachedException();
}
}
Expand All @@ -106,7 +127,7 @@ private function countRequest(): void
*/
private function countMXRequest(): void
{
if (++$this->requestMXCount > 10) {
if (++$this->requestMXCount > $this->maxMXRequests) {
throw new DNSLookupLimitReachedException();
}
}
Expand All @@ -116,7 +137,7 @@ private function countMXRequest(): void
*/
private function countPTRRequest(): void
{
if (++$this->requestPTRCount > 10) {
if (++$this->requestPTRCount > $this->maxPTRRequests) {
throw new DNSLookupLimitReachedException();
}
}
Expand Down
91 changes: 65 additions & 26 deletions src/Model/Result.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,13 @@ class Result
private Session $DNSSession;
private string $result;
private ?string $explanation = self::DEFAULT_RESULT; // If no "exp" modifier is present, then either a default explanation string or an empty explanation string may be returned.
private Record $record;
private ?Record $record = null;
protected int $requestCount = 0;
protected int $requestMXCount = 0;
protected int $requestPTRCount = 0;
/**
* @var array{array{0: Term, 1: ?bool}}
*/
private array $steps = [];
private int $voidLookups = 0;

Expand All @@ -43,14 +49,17 @@ public function __construct(Session $DNSSession)
$this->DNSSession = $DNSSession;
}

public function getRecord(): ?Record
{
return $this->record;
}

/**
* @internal
* @return array{array{0: Term, 1: ?bool}}
*/
public function setRecord(Record $record): self
public function getSteps(): array
{
$this->record = $record;

return $this;
return $this->steps;
}

public function hasResult(): bool
Expand Down Expand Up @@ -90,59 +99,82 @@ public function getExplanation(): ?string
return $this->explanation;
}

public function getRequestCount(): int
{
return $this->requestCount;
}

public function getRequestMXCount(): int
{
return $this->requestMXCount;
}

public function getRequestPTRCount(): int
{
return $this->requestPTRCount;
}

public function getVoidLookups(): int
{
return $this->voidLookups;
}

/**
* @internal
*/
public function setRecord(Record $record): self
{
$this->record = $record;

return $this;
}

/**
* @internal
*/
public function setResult(string $result, ?string $explanation = null): self
{
$this->result = $result;
$this->explanation = $explanation;
if($explanation) {
$this->explanation = $explanation;
}
$this->setDNSLookups();

return $this;
}

/**
* @internal
*/
public function setShortResult(string $result): self
public function setShortResult(string $result, ?string $explanation = null): self
{
switch($result) {
case '+':
$this->result = self::PASS;
$result = self::PASS;
break;
case '-':
$this->result = self::FAIL;
$result = self::FAIL;
break;
case '~':
$this->result = self::SOFTFAIL;
$result = self::SOFTFAIL;
break;
case '?':
$this->result = self::NEUTRAL;
$result = self::NEUTRAL;
break;
case 'NO':
$this->result = self::NONE;
$result = self::NONE;
break;
case 'TE':
$this->result = self::TEMPERROR;
$result = self::TEMPERROR;
break;
case 'PE':
$this->result = self::PERMERROR;
$result = self::PERMERROR;
break;
default:
throw new \InvalidArgumentException('Invalid short result '.$result);
}

return $this;
}

/**
* @internal
*/
public function setExplanation(?string $explanation): self
{
$this->explanation = $explanation;

return $this;
return $this->setResult($result, $explanation);
}

/**
Expand Down Expand Up @@ -174,4 +206,11 @@ public function countVoidLookup(): void
}
}

private function setDNSLookups()
{
$this->requestCount = $this->DNSSession->getRequestCount();
$this->requestMXCount = $this->DNSSession->getRequestMXCount();
$this->requestPTRCount = $this->DNSSession->getRequestPTRCount();
}

}
23 changes: 16 additions & 7 deletions src/SPFCheck.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,23 @@
use Mika56\SPFCheck\Model\Query;
use Mika56\SPFCheck\Model\Record;
use Mika56\SPFCheck\Model\Result;
use Mika56\SPFCheck\Modifier\Explanation;
use Mika56\SPFCheck\Modifier\Redirect;
use const true;

class SPFCheck
{

protected DNSRecordGetterInterface $DNSRecordGetter;
private int $maxRequests;
private int $maxMXRequests;
private int $maxPTRRequests;

public function __construct(DNSRecordGetterInterface $DNSRecordGetter)
public function __construct(DNSRecordGetterInterface $DNSRecordGetter, int $maxRequests = 10, int $maxMXRequests = 10, int $maxPTRRequests = 10)
{
$this->DNSRecordGetter = $DNSRecordGetter;
$this->maxRequests = $maxRequests;
$this->maxMXRequests = $maxMXRequests;
$this->maxPTRRequests = $maxPTRRequests;
}

/**
Expand Down Expand Up @@ -59,7 +64,8 @@ public function getResult(Query $query): Result
private function doGetResult(Query $query, ?Result $result = null): Result
{
$domainName = $query->getDomainName();
$result??= new Result(new Session($this->DNSRecordGetter));
$isInnerCheck = $result !== null;
$result??= new Result(new Session($this->DNSRecordGetter, $this->maxRequests, $this->maxMXRequests, $this->maxPTRRequests));

if(empty($domainName)) {
$result->setResult(Result::NONE);
Expand Down Expand Up @@ -94,7 +100,9 @@ private function doGetResult(Query $query, ?Result $result = null): Result
}

$redirect = null;
$result->setRecord($record);
if(!$isInnerCheck) {
$result->setRecord($record);
}
foreach ($record->getTerms() as $term) {
if($term instanceof AbstractMechanism) {
$evaluator = self::getEvaluatorFor($term);
Expand All @@ -116,15 +124,16 @@ private function doGetResult(Query $query, ?Result $result = null): Result
$result->addStep($term, $matches);
if($matches) {
if($record->hasExplanation()) {
unset($explanation);
try {
$explanationHost = MacroUtils::expandMacro($record->getExplanation()->getHostname(), $query, $result->getDNSSession(), true);
$explanationHost = MacroUtils::truncateDomainName($explanationHost);
$explanationTXT = $result->getDNSSession()->resolveTXT($explanationHost);
if(count($explanationTXT) === 1) {
$explanation = MacroUtils::expandMacro($explanationTXT[0], $query, $result->getDNSSession(), true);
// Only allow ASCII explanations
if(1===preg_match('`^[[:ascii:]]*$`', $explanation)) {
$result->setExplanation($explanation);
if(1!==preg_match('`^[[:ascii:]]*$`', $explanation)) {
unset($explanation);
}
}
}
Expand All @@ -133,7 +142,7 @@ private function doGetResult(Query $query, ?Result $result = null): Result
or if there are syntax errors in the explanation string then proceed as if no exp modifier was given. */
}
}
$result->setShortResult($term->getQualifier());
$result->setShortResult($term->getQualifier(), $explanation ?? null);

return $result;
}
Expand Down

0 comments on commit 03bdf80

Please sign in to comment.