diff --git a/src/FreeDSx/Socket/HasSocketOptions.php b/src/FreeDSx/Socket/HasSocketOptions.php index c3c8d08..cac6ba6 100644 --- a/src/FreeDSx/Socket/HasSocketOptions.php +++ b/src/FreeDSx/Socket/HasSocketOptions.php @@ -39,6 +39,8 @@ trait HasSocketOptions private bool $sslValidateCert = true; + private bool $sslCapturePeerCert = true; + private ?bool $sslVerifyPeerName = null; private ?bool $sslAllowSelfSigned = null; @@ -136,6 +138,23 @@ public function isSslValidateCert(): bool return $this->sslValidateCert; } + /** + * Whether to ask the handshake for the peer's certificate. + * + * Mostly to satisfy Swoole, which does not support this. + */ + public function setSslCapturePeerCert(bool $sslCapturePeerCert): self + { + $this->sslCapturePeerCert = $sslCapturePeerCert; + + return $this; + } + + public function isSslCapturePeerCert(): bool + { + return $this->sslCapturePeerCert; + } + /** * Whether to verify the peer's name (hostname). Null follows the validate-cert setting. * @@ -301,12 +320,14 @@ public function toStreamContextSslOptions(): array 'allow_self_signed' => $this->sslAllowSelfSigned ?? false, 'verify_peer' => $this->sslValidateCert, 'verify_peer_name' => $this->sslVerifyPeerName ?? $this->sslValidateCert, - 'capture_peer_cert' => true, 'capture_peer_cert_chain' => true, 'crypto_method' => $this->sslCryptoMethod, 'ciphers' => $this->sslCiphers, ]; + if ($this->sslCapturePeerCert) { + $opts['capture_peer_cert'] = true; + } if ($this->sslCaCert !== null) { $opts['cafile'] = $this->sslCaCert; } diff --git a/tests/unit/SocketOptionsTest.php b/tests/unit/SocketOptionsTest.php index ed1f992..0e6cd80 100644 --- a/tests/unit/SocketOptionsTest.php +++ b/tests/unit/SocketOptionsTest.php @@ -72,6 +72,22 @@ public function test_it_should_carry_the_validate_cert_flag_when_enabled(): void self::assertFalse($ctx['allow_self_signed']); } + public function test_it_should_capture_the_peer_cert_by_default(): void + { + $ctx = (new SocketOptions())->toStreamContextSslOptions(); + + self::assertTrue($ctx['capture_peer_cert']); + } + + public function test_it_should_omit_the_peer_cert_capture_when_suppressed(): void + { + $ctx = (new SocketOptions()) + ->setSslCapturePeerCert(false) + ->toStreamContextSslOptions(); + + self::assertArrayNotHasKey('capture_peer_cert', $ctx); + } + public function test_it_can_verify_the_peer_without_verifying_its_name(): void { $ctx = (new SocketOptions())