Coder Social home page Coder Social logo

php-spf-check's People

Contributors

alexcarmel avatar btafoya avatar hluaces avatar jsonallen avatar mika56 avatar mitchellmusarra avatar slide5 avatar thedevilonline avatar thirsch avatar zeuh avatar zonuexe avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

php-spf-check's Issues

include is wrongly handled

As per RFC7208, the library wrongly handles includes. Include should only match Pass and return PermError on none. Currently it simply forwards the request to the included domain.

Consider the following records :

domaina.com IN TXT "v=spf1 include:domainb.com domainc.com -all"
domainb.com IN TXT "v=spf1 -all"
domainc.com IN TXT "v=spf1 +127.0.0.1 -all"

The result for 127.0.0.1 on domain domaina.com is Fail (coming from domainb.com) instead of Pass (from domainc.com)

manuel check

Hi,
is it possible to check manuelly the spf by comparing string and ip and get result if pass or fail or none ...

exemple :

check
v=spf1 ip4:35.190.247.0/24 ip4:64.233.160.0/19 ip4:66.102.0.0/20 ip4:66.249.80.0/20 ip4:72.14.192.0/18 ip4:74.125.0.0/16 ip4:108.177.8.0/21 ip4:173.194.0.0/16 ip4:209.85.128.0/17 ip4:216.58.192.0/19 ip4:216.239.32.0/19 ~all

against 

108.177.8.0

should return SPF PASS

PHP Fatal error

This time I have a problem with my php 5.6.30
I tested on 5.4.16 and it is ok.

<?php

require 'lib/vendor/autoload.php';
use Mika56\SPFCheck\SPFCheck;
use Mika56\SPFCheck\DNSRecordGetter;

///////////////////////////////////////////////////////////////////////////////////////

  $checker = new SPFCheck(new DNSRecordGetter());
  $result = $checker->isIPAllowed('83.206.186.9', 'etam.biz');
  print var_dump($result);

?>

[24-Mar-2017 17:47:03 Europe/Paris] PHP Warning: dns_get_record(): A temporary server error occurred. in /apache_sites/jbm/lib/vendor/mika56/spfcheck/src/DNSRecordGetter.php on line 45
[24-Mar-2017 17:47:03 Europe/Paris] PHP Fatal error: Uncaught exception 'Mika56\SPFCheck\Exception\DNSLookupException' in /apache_sites/jbm/lib/vendor/mika56/spfcheck/src/DNSRecordGetter.php:47
Stack trace:
#0 /apache_sites/jbm/lib/vendor/mika56/spfcheck/src/SPFCheck.php(252): Mika56\SPFCheck\DNSRecordGetter->resolveA('cme.rc.etam.com')
#1 /apache_sites/jbm/lib/vendor/mika56/spfcheck/src/SPFCheck.php(123): Mika56\SPFCheck\SPFCheck->ipMatchesPart('83.206.186.9', 'mx', 'etam.biz')
#2 /apache_sites/jbm/lib/vendor/mika56/spfcheck/src/SPFCheck.php(87): Mika56\SPFCheck\SPFCheck->doCheck('83.206.186.9', 'etam.biz')
#3 /apache_sites/jbm/lib/vendor/mika56/spfcheck/src/SPFCheck.php(67): Mika56\SPFCheck\SPFCheck->doIsIPAllowed('83.206.186.9', 'etam.biz', true)
#4 /apache_sites/jbm/titi.php(10): Mika56\SPFCheck\SPFCheck->isIPAllowed('83.206.186.9', 'etam.biz')
#5 {main}
thrown in /apache_sites/jbm/lib/vendor/mika56/spfcheck/src/DNSRecordGetter.php on line 47

PE when domain starts with two underscores

Original message from @Pascal76

<?php
use Mika56\SPFCheck\SPFCheck;
use Mika56\SPFCheck\DNSRecordGetter;

require('vendor/autoload.php');

$checker = new SPFCheck(new DNSRecordGetter()); // Uses php's dns_get_record method for lookup.
var_dump($checker->isIPAllowed('172.82.227.233', 'm1.email.samsung.com'));
?>

=> string(2) "PE"

dig +short TXT m1.email.samsung.com |grep spf
"v=spf1 redirect=__spf.campaign.adobe.com"

There is a problem for this domain begining with 2 "_" with php < 7

                            if (version_compare(PHP_VERSION, '7', '>=')) {
                                if (!filter_var($domain, FILTER_VALIDATE_DOMAIN)) {
                                    return false;
                                }
                            } else {
                                /** @link http://stackoverflow.com/a/4694816/2898156 */
                                if (!(preg_match('/^([_a-z\d](-*[a-z\d])*)(\.([a-z\d](-*[a-z\d])*))*$/i', $domain) 
                                    && preg_match('/^.{1,253}$/', $domain)
                                    && preg_match('/^[^\.]{1,63}(\.[^\.]{1,63})*$/', $domain))
                                ) {
                                    return false;
                                }
                            }

Test DNSRecordGetter with mock DNS

Currently we don't have any tests to test DNSRecordGetter. We can use PHPUnit Bridge from symphony framework to mock DNS records. To test dns_get_record we can use:

DnsMock::withMockedHosts(array(
    'example.com' => array(
        array(
            'type' => 'A',
            'ip' => '1.2.3.4',
        )
    ),
));

MX record lookups not counted according to RFC 7208

RFC 7208 says:

When evaluating the "mx" mechanism, the number of "MX" resource records queried is included in the overall limit of 10 mechanisms/modifiers that cause DNS lookups as described above.

But countRequest() is only called once, when the MX records are looked up (but not for each record returned that causes an A lookup)

$this->DNSRecordGetter->countRequest();
$mxServers = $this->DNSRecordGetter->resolveMx($domain);
if (count($mxServers) > 10) {
return self::RESULT_PERMERROR;
}
foreach ($mxServers as $mxServer) {

There is a check that there isn't more than 10 MX records returned, which matches the following sentence in the RFC ("In addition to that limit, the evaluation of each "MX" record MUST NOT result inmquerying more than 10 address records"), but the lookup of an MX record seems to only count for one DNS request in total (as far as countRequest() goes).

An example of a SPF record that is accepted that should not be is something like:

v=spf1 mx include:foo.example.com include:bar.example.com

with nine MX records attached to the same domain (should be over the limit as defined in the RFC, as it causes 11 DNS lookups, but this library will only count 3 - before includes are evaluated further).

pitt.edu

getIPStringResult("52.70.139.219", "pitt.edu")

leads to an preg_split(): Argument #2 ($subject) must be of type string error.

check failed

Hi Mika

can you check that please ?

  • bookatable.bounce.ed10.net / 96.47.31.237 : FAIL
  • bookatable.bounce.ed10.net / 96.47.31.238 : FAIL

Pascal

Result details

It would be nice to have details
ex1: what validated the spf (ip4:xxx / a / mx / include => ip4:xxx ...)
ex2: full list of authorized IPs + others non IP which are authorized too

Version 1 -> 2 upgrade: Usage advice for accessing requestCount.

Hi there. Thanks for the great lib. We are just upgrading our instance from 1.1.6 to latest and see there's a little bit of architectural change. I've gone through the Upgrade.md and sorted all of that.

We have a slightly unconventional implementation where we want to control our own request limits. So under 1.1.6 we extended your DnsRecordGetter and used $requestCount there to do that.

use Mika56\SPFCheck\DNS\DNSRecordGetter as BaseDNSRecordGetter;
use Mika56\SPFCheck\Exception\DNSLookupLimitReachedException;

class DNSRecordGetter extends BaseDNSRecordGetter
{
    public const LIMIT = 20;

    public function countRequest()
    {
        if (++$this->requestCount > self::LIMIT) {
            throw new DNSLookupLimitReachedException();
        }
    }

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

I see that all of this stuff has moved from old src/DNSRecordGetter.php to the new src/DNS/Session.php class. So this obviously errors due to requestCount not existing.

What's the best way to do this now? It looks like the Result object contains a Session object. And I see on the Readme that getIPStringResult() returns a Result object. Should I just access this property that way? Or is there a better way to do the above entirely?

Thanks again.

Failing SPF check

Hi @Mika56 ,

I'm running into a problem with an SPF record that has +include:universalspf.org

If you look at the SPF record of universalspf.org it has a value of v=spf1 a:%{i}._o.%{o}.y.0.universalspf.org -all.
I've never seen an SPF record like this and it seems to cause problems with this SPF checking library.

It gets to like 45 of MacroUtils.php and when it calls $query->getSender() the value is null and this causes explode to fail.

Screen Shot 2023-05-22 at 15 32 02

Limit recursion

Hi!

We had encountered problem with wrong SPF - one of our clients made spf like this:

domain.com TXT "spf=v1 include:domain.com ~all"

Of course it caused endless recursion. Due to this bug/feature https://bugs.php.net/bug.php?id=43187 it's imossible to catch this outside library, so it needs some tweaking in library itself.

Updating symfony/http-foundation to support Laravel 9

Currently getting following dependency error on Laravel and Lumen 9 frameworks. Is it possible to update symfony/http-foundation to ^6.0 ?

`Problem 1
- mika56/spfcheck 1.0.0 requires symfony/http-foundation 2.8.* -> found symfony/http-foundation[v2.8.0-BETA1, ..., 2.8.x-dev] but the package is fixed to v6.0.6 (lock file version) by a partial update and that version does not match. Make sure you list it as an argument for the update command.
- mika56/spfcheck[1.0.1, ..., 1.1.2] require symfony/http-foundation 2.8.* || ^3.0 -> found symfony/http-foundation[v2.8.0-BETA1, ..., 2.8.x-dev, v3.0.0-BETA1, ..., 3.4.x-dev] but the package is fixed to v6.0.6 (lock file version) by a partial update and that version does not match. Make sure you list it as an argument for the update command.
- mika56/spfcheck[1.1.3, ..., 1.1.5] require symfony/http-foundation 2.8.* || ^3.0 || ^4.0 -> found symfony/http-foundation[v2.8.0-BETA1, ..., 2.8.x-dev, v3.0.0-BETA1, ..., 3.4.x-dev, v4.0.0-BETA1, ..., 4.4.x-dev] but the package is fixed to v6.0.6 (lock file version) by a partial update and that version does not match. Make sure you list it as an argument for the update command.
- mika56/spfcheck[dev-master, 1.1.6] require symfony/http-foundation 2.8.* || ^3.0 || ^4.0 || ^5.0 -> found symfony/http-foundation[v2.8.0-BETA1, ..., 2.8.x-dev, v3.0.0-BETA1, ..., 3.4.x-dev, v4.0.0-BETA1, ..., 4.4.x-dev, v5.0.0-BETA1, ..., 5.4.x-dev] but the package is fixed to v6.0.6 (lock file version) by a partial update and that version does not match. Make sure you list it as an argument for the update command.
- Root composer.json requires mika56/spfcheck * -> satisfiable by mika56/spfcheck[dev-master, 1.0.0, ..., 1.1.6, 9999999-dev].

Use the option --with-all-dependencies (-W) to allow upgrades, downgrades and removals for packages currently locked to specific versions.`

Uncaught exception

Hi

did I do something wrong ?

var_dump($checker->isIPAllowed('217.109.56.203', 'news2.cdiscount.com'));

[23-Aug-2016 00:00:29 Europe/Paris] PHP Fatal error: Uncaught exception 'Mika56\SPFCheck\Exception\DNSLookupException' in /apache_sites/jbm/spf/vendor/mika56/spfcheck/src/DNSRecordGetter.php:45
Stack trace:
#0 /apache_sites/jbm/spf/vendor/mika56/spfcheck/src/SPFCheck.php(143): Mika56\SPFCheck\DNSRecordGetter->resolveA('news2.cdiscount...')
#1 /apache_sites/jbm/spf/vendor/mika56/spfcheck/src/SPFCheck.php(85): Mika56\SPFCheck\SPFCheck->ipMatchesPart('217.109.56.203', 'a', 'news2.cdiscount...')
#2 /apache_sites/jbm/spf/vendor/mika56/spfcheck/src/SPFCheck.php(61): Mika56\SPFCheck\SPFCheck->doCheck('217.109.56.203', 'news2.cdiscount...')
#3 /apache_sites/jbm/spf/test.php(9): Mika56\SPFCheck\SPFCheck->isIPAllowed('217.109.56.203', 'news2.cdiscount...')
#4 {main}

thrown in /apache_sites/jbm/spf/vendor/mika56/spfcheck/src/DNSRecordGetter.php on line 45

Cache DNS requests

When doing checks in bulk, having a cache on top of the DNS requests would be nice

Check fails on invalid recordPart

Hi Mika,

I just did a check on a SPF record like this:
"v=spf1 a mx include:_spf.external.nl ~all"

The IP is allowed by the external spf and therefore I expected an allow, however the check returned Temp Error.

Turned out that the domain did not have MX records configured, and the doCheck routine catched this as an DNSLookupException and bailed out.

I don't know how this is in the specifications, but I would expect that such a thing would be ignored and the check continue with the next part.

Regards,
Michael

Mechanisms in uppercase are failing

As of 4.6.1 of RFC 7208, mechanisms and modifiers are case-insensitive, but the lib is throwing an exception in case the mechanism is written as Ip4, iP4 or IP4 (just as a few examples). The dns result should be converted to lowercase to handle such cases.

Check fails for empty MX record

We're getting PHP Warning: dns_get_record(): An unexpected server failure occurred. in /path/to/vendor/mika56/spfcheck/src/DNS/DNSRecordGetter.php on line 18 when trying to validate SPF records for some domains. In our case the culprit seems to be in \Mika56\SPFCheck\DNS\DNSRecordGetter::resolveMx method where an empty domain is returned and it then fails down the line.

dns_get_record('example.com', DNS_MX) returns the following data

[
    [
         "host" => "example.com",
         "class" => "IN",
         "ttl" => 0,
         "type" => "MX",
         "pri" => 0,
         "target" => "",
     ],
     [
         "host" => "example.com",
         "class" => "IN",
         "ttl" => 0,
         "type" => "MX",
         "pri" => 10,
         "target" => "record.example.com",
     ],
]

And this means that resolveMx method returns the following array ["", "record.example.com"] which then fails in resolveA method.

Probably need to add check in resolveMx to skip entries with empty target or automatically return false in resolveA if an empty domain is passed.

Error on Http-foundation with composer

When i try to install through composer i get the following error:

`Using version ^1.0 for mika56/spfcheck
./composer.json has been updated
Loading composer repositories with package information Updating dependencies (including require-dev) Your requirements could not be resolved to an installable set of packages.

Problem 1
- Installation request for mika56/spfcheck ^1.0 -> satisfiable by mika56/spfcheck[1.0.0].
- Conclusion: remove symfony/http-foundation v3.1.8
- Conclusion: don't install symfony/http-foundation v3.1.8
- mika56/spfcheck 1.0.0 requires symfony/http-foundation 2.8.* -> satisfiable by symfony/http-foundation[v2.8.0, v2.8.1, v2.8.10, v2.8.11, v2.8.12, v2.8.13, v2.8.14, v2.8.15, v2.8.2, v2.8.3, v2.8.4, v2.8.5, v2.8.6, v2.8.7, v2.8.8, v2.8.9].
- Can only install one of: symfony/http-foundation[v2.8.13, v3.1.8].
- Can only install one of: symfony/http-foundation[v2.8.14, v3.1.8].
- Can only install one of: symfony/http-foundation[v2.8.15, v3.1.8].
- Can only install one of: symfony/http-foundation[v2.8.0, v3.1.8].
- Can only install one of: symfony/http-foundation[v2.8.1, v3.1.8].
- Can only install one of: symfony/http-foundation[v2.8.10, v3.1.8].
- Can only install one of: symfony/http-foundation[v2.8.11, v3.1.8].
- Can only install one of: symfony/http-foundation[v2.8.12, v3.1.8].
- Can only install one of: symfony/http-foundation[v2.8.2, v3.1.8].
- Can only install one of: symfony/http-foundation[v2.8.3, v3.1.8].
- Can only install one of: symfony/http-foundation[v2.8.4, v3.1.8].
- Can only install one of: symfony/http-foundation[v2.8.5, v3.1.8].
- Can only install one of: symfony/http-foundation[v2.8.6, v3.1.8].
- Can only install one of: symfony/http-foundation[v2.8.7, v3.1.8].
- Can only install one of: symfony/http-foundation[v2.8.8, v3.1.8].
- Can only install one of: symfony/http-foundation[v2.8.9, v3.1.8].
- Installation request for symfony/http-foundation (locked at v3.1.8) -> satisfiable by symfony/http-foundation[v3.1.8].
`

I guess its looking for an older version of http-foundation, maybe the requirements can be updated / changed for this?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.