You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

91 lines
4.0 KiB

<?php
namespace p3k\HTTP\Tests;
use p3k\HTTP\Guard;
use PHPUnit\Framework\TestCase;
class GuardTest extends TestCase {
private static function guard(array $dns = [], array $allow = []) {
return new Guard($allow, function($host) use($dns) { return $dns[$host] ?? []; });
}
public static function publicAddresses() {
return [['8.8.8.8'], ['93.184.216.34'], ['2606:4700::1'], ['2001:4860:4860::8888']];
}
public static function nonPublicAddresses() {
return [
['127.0.0.1'], ['127.8.9.10'], ['10.11.11.80'], ['172.16.0.1'], ['192.168.1.1'], ['169.254.169.254'],
['100.64.0.1'], ['0.0.0.0'], ['::'], ['::1'], ['fe80::1'], ['fc00::1'], ['fd12:3456::1'],
['::ffff:127.0.0.1'], ['::ffff:10.0.0.1'], ['64:ff9b::7f00:1'], ['64:ff9b::a00:1'], ['2002:7f00:1::1'], ['2002:a9fe:a9fe::'],
];
}
#[\PHPUnit\Framework\Attributes\DataProvider('publicAddresses')]
public function testPublicAddresses($address) {
$this->assertTrue(Guard::is_public($address));
}
#[\PHPUnit\Framework\Attributes\DataProvider('nonPublicAddresses')]
public function testNonPublicAddresses($address) {
$this->assertFalse(Guard::is_public($address));
}
public static function blockedUrls() {
return [
['gopher://127.0.0.1:6379/_SET%20x%201'], ['dict://127.0.0.1:6379/info'], ['file:///etc/passwd'],
['ftp://example.com/'], ['ldap://example.com/'], ['javascript:alert(1)'], ['/relative'], ['https://'],
['http://127.0.0.1/'], ['http://localhost.example/'], ['http://[::1]/'], ['http://[::ffff:127.0.0.1]/'],
['http://2130706433/'], ['http://0x7f000001/'], ['http://0177.0.0.1/'], ['http://127.1/'], ['http://0/'],
['http://169.254.169.254/latest/meta-data/'], ['http://mixed.example/'],
];
}
#[\PHPUnit\Framework\Attributes\DataProvider('blockedUrls')]
public function testBlockedUrls($url) {
$result = self::guard(['localhost.example' => ['127.0.0.1'], 'mixed.example' => ['93.184.216.34', '10.0.0.1']])->check($url);
$this->assertSame('blocked_url', $result['error'] ?? null, $url);
}
public function testPublicHostIsAllowedWithItsAddresses() {
$result = self::guard(['example.com' => ['93.184.216.34', '2606:2800:220:1::']])->check('https://Example.com/path');
$this->assertSame(['host' => 'example.com', 'port' => 443, 'addresses' => ['93.184.216.34', '2606:2800:220:1::']], $result);
}
public function testExplicitPort() {
$result = self::guard(['example.com' => ['93.184.216.34']])->check('http://example.com:8080/');
$this->assertSame(8080, $result['port']);
}
public function testUnresolvableHost() {
$this->assertSame('dns_error', self::guard()->check('https://nowhere.example/')['error']);
}
public function testAllowedHost() {
$guard = self::guard(['dev.example' => ['10.11.11.80']], ['dev.example']);
$this->assertSame(['10.11.11.80'], $guard->check('https://dev.example/')['addresses']);
$this->assertArrayHasKey('error', $guard->check('https://other.example/'));
}
public function testAllowedRange() {
$guard = self::guard(['dev.example' => ['10.11.11.80'], 'db.example' => ['10.11.12.5']], ['10.11.11.0/24']);
$this->assertArrayNotHasKey('error', $guard->check('https://dev.example/'));
$this->assertArrayHasKey('error', $guard->check('https://db.example/'));
}
public function testAllowedSingleAddress() {
$guard = self::guard([], ['127.0.0.1', '::1']);
$this->assertArrayNotHasKey('error', $guard->check('http://127.0.0.1:8000/'));
$this->assertArrayNotHasKey('error', $guard->check('http://[::1]:8000/'));
$this->assertArrayHasKey('error', $guard->check('http://127.0.0.2/'));
}
public function testInCidr() {
$this->assertTrue(Guard::in_cidr('10.11.11.80', '10.11.11.0/24'));
$this->assertFalse(Guard::in_cidr('10.11.12.80', '10.11.11.0/24'));
$this->assertTrue(Guard::in_cidr('10.11.11.80', '10.8.0.0/13'));
$this->assertTrue(Guard::in_cidr('fd00::1', 'fc00::/7'));
$this->assertFalse(Guard::in_cidr('10.0.0.1', 'fc00::/7'));
}
}