Bug #80770 [Com]: It is not possible to get client peer certificate with stream_socket_server

From: Date: Thu, 18 Feb 2021 16:34:04 +0000
Subject: Bug #80770 [Com]: It is not possible to get client peer certificate with stream_socket_server
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-232262@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=80770&edit=1 ID: 80770 Comment by: mcmic@php.net Reported by: mcmic@php.net Summary: It is not possible to get client peer certificate with stream_socket_server Status: Open Type: Bug Package: OpenSSL related PHP Version: 7.3.27 Block user comment: N Private report: N New Comment: See section 4.3 of https://gemini.circumlunar.space/docs/specification.html for more information about client certificate use in Gemini protocol. Previous Comments: ------------------------------------------------------------------------ [2021-02-18 16:32:20] mcmic@php.net @daverandom: The test you linked to is about getting the server certificate from the client, I want the other way around, get the client certificate from the server. And without making the client certificate mandatory, I still need to accept certificate-less requests. ------------------------------------------------------------------------ [2021-02-18 16:26:58] daverandom@php.net Ah no I think I see the problem, you need to pass $context instead of $conn to stream_context_get_options() ------------------------------------------------------------------------ [2021-02-18 16:26:04] daverandom@php.net Note that there is a test for this behaviour which is not marked as XFAIL, so I believe this functionality should work - although I cannot immediately see an issue with your sample code https://heap.space/xref/php-src/ext/openssl/tests/capture_peer_cert_001.phpt?r=1fab01be#38 ------------------------------------------------------------------------ [2021-02-18 16:11:25] mcmic@php.net Description: ------------ It is not possible to get the client certificate when accepting TLS connections, without forcing the client to provide a (valid) certificate. This forbids writing a fully compliant Gemini server in PHP, because it is not possible to accept client certificates without forcing them on all pages. See https://www.openssl.org/docs/man1.0.2/man3/SSL_CTX_set_verify.html Test script: --------------- $context = stream_context_create( [ 'ssl' => [ 'allow_self_signed' => true, 'SNI_enabled' => true, 'SNI_server_certs' => ['example.com' => '/path/to/cert.pem'], 'capture_peer_cert' => true, ] ] ); $socket = stream_socket_server( 'tcp://[::]:' . $port, $errno, $errstr, STREAM_SERVER_BIND | STREAM_SERVER_LISTEN, $context, ); if ($socket === false) { throw new \Exception($errstr, $errno); } else { while ($conn = stream_socket_accept($socket, -1, $peername)) { $tlsSuccess = stream_socket_enable_crypto( $conn, true, STREAM_CRYPTO_METHOD_TLS_SERVER ); if ($tlsSuccess !== true) { fclose($conn); continue; } var_dump(stream_context_get_options($conn)); } } Expected result: ---------------- Have the client certificate in 'peer_certificate' key of $conn, if the client sends one. Actual result: -------------- No 'peer_certificate' option. If I set 'verify_peer' to true, it works, but then it is not possible for a client to connect without a certificate. ------------------------------------------------------------------------ -- Edit this bug report at https://bugs.php.net/bug.php?id=80770&edit=1

« previous php.bugs (#232262) next »