From dfa0cc4d04d3edb391b15f053a95577a225fdbf3 Mon Sep 17 00:00:00 2001 From: Hylke Witjens Date: Thu, 18 Jun 2026 15:08:00 +0200 Subject: [PATCH 1/2] RT-17860 Support voor IsProxy TLS, enabled by default --- src/Support/IsProxyConnection.php | 33 ++++++++++++++++++ .../Domains/DomainsApiTransferTest.php | 3 +- tests/Helpers/MockedIsProxyConnection.php | 20 +++++++++++ tests/IsProxyConnectionTest.php | 34 +++++++++++++++++++ 4 files changed, 88 insertions(+), 2 deletions(-) diff --git a/src/Support/IsProxyConnection.php b/src/Support/IsProxyConnection.php index 68c5139..1e1aeca 100644 --- a/src/Support/IsProxyConnection.php +++ b/src/Support/IsProxyConnection.php @@ -34,11 +34,20 @@ public function connect(): bool } $this->socket = $socket; + + if (! $this->upgradeToTls()) { + return false; + } + return $this->login(); } public function disconnect(): void { + if (! $this->isConnected()) { + return; + } + $this->write('CLOSE'); @fclose($this->socket); @@ -84,4 +93,28 @@ protected function login(): bool return (bool) preg_match('#^100\sLogin\sok#', $response); } + + protected function upgradeToTls(): bool + { + if (! $this->write('STARTTLS')) { + return false; + } + + $response = $this->read(); + if (! preg_match('#^100\sOK#', $response)) { + return true; + } + + $methods = STREAM_CRYPTO_METHOD_TLS_CLIENT; + + if (defined('STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT')) { + $methods |= STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT; + } + + if (defined('STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT')) { + $methods |= STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT; + } + + return @stream_socket_enable_crypto($this->socket, true, $methods) === true; + } } diff --git a/tests/Clients/Domains/DomainsApiTransferTest.php b/tests/Clients/Domains/DomainsApiTransferTest.php index 8e99d5b..f30b592 100644 --- a/tests/Clients/Domains/DomainsApiTransferTest.php +++ b/tests/Clients/Domains/DomainsApiTransferTest.php @@ -31,7 +31,6 @@ public function test_transfer_quote(): void authcode: '123123123', autoRenew: true, ns: [], - transferContacts: ['REGISTRANT'], designatedAgent: 'OLD', zone: Zone::fromArray(include __DIR__ . '/../../Domain/data/dns/zones/zone_valid.php'), contacts: DomainContactCollection::fromArray([include __DIR__ . '/../../Domain/data/domains/domain_contact_valid.php']), @@ -64,7 +63,7 @@ public function test_transfer(): void '123123123', true, [], - ['ADMIN'], + null, 'OLD', Zone::fromArray(include __DIR__ . '/../../Domain/data/dns/zones/zone_valid.php'), DomainContactCollection::fromArray([include __DIR__ . '/../../Domain/data/domains/domain_contact_valid.php']), diff --git a/tests/Helpers/MockedIsProxyConnection.php b/tests/Helpers/MockedIsProxyConnection.php index b0b9692..03df2db 100644 --- a/tests/Helpers/MockedIsProxyConnection.php +++ b/tests/Helpers/MockedIsProxyConnection.php @@ -55,6 +55,11 @@ public function expectWrite(string $message): MockedIsProxyConnection public function connect(): bool { $this->connected = true; + + if (! $this->upgradeToTls()) { + return false; + } + return $this->login(); } @@ -81,4 +86,19 @@ public function isConnected(): bool { return $this->connected; } + + protected function upgradeToTls(): bool + { + if (! $this->write('STARTTLS')) { + return false; + } + + $response = $this->read(); + + if ($response !== '100 OK') { + return true; + } + + return true; + } } diff --git a/tests/IsProxyConnectionTest.php b/tests/IsProxyConnectionTest.php index aeac1e9..dc1437c 100644 --- a/tests/IsProxyConnectionTest.php +++ b/tests/IsProxyConnectionTest.php @@ -13,6 +13,8 @@ class IsProxyConnectionTest extends TestCase public function test_check(): void { $connection = (new MockedIsProxyConnection('secret', $this)) + ->expectWrite('STARTTLS') + ->expectRead('100 OK') ->expectWrite('LOGIN secret') ->expectRead('100 Login ok') ->expectWrite('IS example.com') @@ -33,6 +35,8 @@ public function test_check(): void public function test_connection_error(): void { $connection = (new MockedIsProxyConnection('secret', $this)) + ->expectWrite('STARTTLS') + ->expectRead('100 OK') ->expectWrite('LOGIN secret') ->expectRead('400 Login failed'); @@ -46,6 +50,8 @@ public function test_connection_error(): void public function test_check_wrong_answer(): void { $connection = (new MockedIsProxyConnection('secret', $this)) + ->expectWrite('STARTTLS') + ->expectRead('100 OK') ->expectWrite('LOGIN secret') ->expectRead('100 Login ok') ->expectWrite('IS example.com') @@ -63,6 +69,8 @@ public function test_check_wrong_answer(): void public function test_check_many(): void { $connection = (new MockedIsProxyConnection('secret', $this)) + ->expectWrite('STARTTLS') + ->expectRead('100 OK') ->expectWrite('LOGIN secret') ->expectRead('100 Login ok') ->expectWrite('IS example.com') @@ -110,6 +118,8 @@ public function test_check_many(): void public function test_check_many_connection_fail(): void { $connection = (new MockedIsProxyConnection('secret', $this)) + ->expectWrite('STARTTLS') + ->expectRead('100 OK') ->expectWrite('LOGIN secret') ->expectRead('400 Login failed'); @@ -123,6 +133,8 @@ public function test_check_many_connection_fail(): void public function test_check_premium(): void { $connection = (new MockedIsProxyConnection('secret', $this)) + ->expectWrite('STARTTLS') + ->expectRead('100 OK') ->expectWrite('LOGIN secret') ->expectRead('100 Login ok') ->expectWrite('ENABLE premium') @@ -182,4 +194,26 @@ public function test_check_premium(): void $this->assertEmpty($availableDomain->getExtras()); $this->assertTrue($invalidDomain->isInvalid()); } + + public function test_check_fallback_without_starttls_support(): void + { + $connection = (new MockedIsProxyConnection('secret', $this)) + ->expectWrite('STARTTLS') + ->expectRead('500 command not supported') + ->expectWrite('LOGIN secret') + ->expectRead('100 Login ok') + ->expectWrite('IS example.com') + ->expectRead('example.com available') + ->expectWrite('CLOSE'); + + $isProxy = new IsProxy('secret'); + $isProxy->setConnection($connection); + + $result = $isProxy->check('example', 'com'); + + $this->assertInstanceOf(IsProxyDomain::class, $result); + $this->assertSame(IsProxyDomain::STATUS_AVAILABLE, $result->getStatus()); + $this->assertSame('example.com', $result->getDomain()); + $this->assertTrue($result->isAvailable()); + } } From ce9fe99df0735797f3b3bca990201da632efae3e Mon Sep 17 00:00:00 2001 From: Hylke Witjens Date: Tue, 23 Jun 2026 09:53:03 +0200 Subject: [PATCH 2/2] RT-17860 Cleanup support for Isproxy tls --- README.md | 2 +- src/IsProxy.php | 4 ++-- src/Support/IsProxyConnection.php | 14 ++++++++++---- tests/Helpers/MockedIsProxyConnection.php | 12 +++++++----- tests/IsProxyConnectionTest.php | 8 +++----- 5 files changed, 23 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 23fe506..cbb1798 100644 --- a/README.md +++ b/README.md @@ -74,7 +74,7 @@ use RealtimeRegister\IsProxy; $isProxy = new IsProxy('my-secret-api-key'); foreach ($isProxy->checkMany('example', ['nl', 'com', 'net', 'org']) as $result) { - echo $result->getDomain() . $result->isAvailable() ? ' ✅' : ' ❌'; + echo $result->getDomain() . ($result->isAvailable() ? ' ✅' : ' ❌') . PHP_EOL; } // example.nl ✅ // example.com ❌ diff --git a/src/IsProxy.php b/src/IsProxy.php index e4f01e3..5863ea7 100644 --- a/src/IsProxy.php +++ b/src/IsProxy.php @@ -10,9 +10,9 @@ final class IsProxy { private IsProxyConnection $connection; - public function __construct(string $apiKey, string $host = 'is.yoursrs.com', int $port = 2001) + public function __construct(string $apiKey, string $host = 'is.yoursrs.com', int $port = 2001, bool $tls = true) { - $this->setConnection(new IsProxyConnection($apiKey, $host, $port)); + $this->setConnection(new IsProxyConnection($apiKey, $host, $port, $tls)); } public function setConnection(IsProxyConnection $connection): void diff --git a/src/Support/IsProxyConnection.php b/src/Support/IsProxyConnection.php index 1e1aeca..8e0a4fa 100644 --- a/src/Support/IsProxyConnection.php +++ b/src/Support/IsProxyConnection.php @@ -14,11 +14,14 @@ class IsProxyConnection /** @var resource */ protected $socket; - public function __construct(string $apiKey, string $host = 'is.yoursrs.com', int $port = 2001) + protected bool $tls; + + public function __construct(string $apiKey, string $host = 'is.yoursrs.com', int $port = 2001, bool $tls = true) { $this->apiKey = $apiKey; $this->host = $host; $this->port = $port; + $this->tls = $tls; } public function __destruct() @@ -35,8 +38,11 @@ public function connect(): bool $this->socket = $socket; - if (! $this->upgradeToTls()) { - return false; + // Try to set up tls, if enabled; + if ($this->tls) { + if ($this->upgradeToTls() === false) { + return false; + } } return $this->login(); @@ -115,6 +121,6 @@ protected function upgradeToTls(): bool $methods |= STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT; } - return @stream_socket_enable_crypto($this->socket, true, $methods) === true; + return stream_socket_enable_crypto($this->socket, true, $methods) === true; } } diff --git a/tests/Helpers/MockedIsProxyConnection.php b/tests/Helpers/MockedIsProxyConnection.php index 03df2db..2470833 100644 --- a/tests/Helpers/MockedIsProxyConnection.php +++ b/tests/Helpers/MockedIsProxyConnection.php @@ -19,9 +19,9 @@ class MockedIsProxyConnection extends IsProxyConnection /** @var bool */ private $connected = false; - public function __construct(string $apiKey, TestCase $testCase) + public function __construct(string $apiKey, TestCase $testCase, bool $tls = true) { - parent::__construct($apiKey); + parent::__construct($apiKey, tls: $tls); $this->testCase = $testCase; } @@ -56,8 +56,10 @@ public function connect(): bool { $this->connected = true; - if (! $this->upgradeToTls()) { - return false; + if ($this->tls) { + if ($this->upgradeToTls() === false) { + return false; + } } return $this->login(); @@ -96,7 +98,7 @@ protected function upgradeToTls(): bool $response = $this->read(); if ($response !== '100 OK') { - return true; + return false; } return true; diff --git a/tests/IsProxyConnectionTest.php b/tests/IsProxyConnectionTest.php index dc1437c..abb3cbb 100644 --- a/tests/IsProxyConnectionTest.php +++ b/tests/IsProxyConnectionTest.php @@ -195,18 +195,16 @@ public function test_check_premium(): void $this->assertTrue($invalidDomain->isInvalid()); } - public function test_check_fallback_without_starttls_support(): void + public function test_check_without_ssl_support(): void { - $connection = (new MockedIsProxyConnection('secret', $this)) - ->expectWrite('STARTTLS') - ->expectRead('500 command not supported') + $connection = (new MockedIsProxyConnection('secret', $this, false)) ->expectWrite('LOGIN secret') ->expectRead('100 Login ok') ->expectWrite('IS example.com') ->expectRead('example.com available') ->expectWrite('CLOSE'); - $isProxy = new IsProxy('secret'); + $isProxy = new IsProxy(apiKey:'secret', tls: false); $isProxy->setConnection($connection); $result = $isProxy->check('example', 'com');