[GIT-PULLS] [php-src] PR #22638: ext/openssl: add a dtls:// stream transport. Open as Draft.
[email protected] (GianfriAur)
| Newsgroups | php.git-pulls |
|---|---|
| Message-ID | <[email protected]> |
Pull Request: https://github.com/php/php-src/pull/22638
Author: GianfriAur
Adds a `dtls://` stream transport (with the `dtlsv1.2://` alias) to `ext/openssl`:
DTLS 1.2 over UDP from the stream API, both client and server. It is the datagram
counterpart of `tls://`, with the same `ssl` context options where they apply and
the same `Openssl\Session` object.
```php
// client
$ctx = stream_context_create(['ssl' => ['cafile' => '/path/ca.pem']]);
$c = stream_socket_client('dtls://198.51.100.1:4433', $errno, $errstr, 5,
STREAM_CLIENT_CONNECT, $ctx);
fwrite($c, $datagram);
$reply = fread($c, 1500);
// server
$ctx = stream_context_create(['ssl' => ['local_cert' => '/path/server.pem']]);
$s = stream_socket_server('dtls://0.0.0.0:4433', $errno, $errstr,
STREAM_SERVER_BIND | STREAM_SERVER_LISTEN, $ctx);
$peer = stream_socket_accept($s, 5);
```
**Design.** No core changes: it only registers the schemes in `ext/openssl`,
without touching `xp_ssl.c` or the stream layer. It is a separate file
(`xp_dtls.c`) because DTLS is UDP while `xp_ssl.c` is TCP, and to avoid risking a
regression on the TLS path; it still follows `xp_ssl.c`'s patterns and style and
reuses its shared primitives (`Openssl\Session`). The server accept uses
`DTLSv1_listen()`: a stateless cookie exchange (RFC 6347 §4.2.1) against
amplification and spoofing, with a constant-time compare. It is the stable API
present in every released OpenSSL and stays valid for 1.2 even when OpenSSL caps it
in favour of the new listener API for 1.3. The server is single-peer (one peer per
bind); multi-peer is future work.
**Features** (client and server): peer verification (`verify_peer`,
`verify_peer_name`, `peer_name`, `cafile`/`capath`, `peer_fingerprint`), mutual
authentication (`local_cert` with `passphrase`), session resumption
(`session_data` on the client; an external cache via `session_new_cb`/
`session_get_cb`/`session_remove_cb` plus `session_id_context`/`no_ticket`/
`session_timeout` on the server), keying material export (RFC 5705) and Path MTU
(`dtls_link_mtu`). The session, `session_reused`, protocol and cipher are exposed
in `stream_get_meta_data()['crypto']`.
**Tests.** A `.phpt` suite under `ext/openssl/tests/dtls_*` (client against
`openssl s_server`, PHP server and client against each other, server against
`openssl s_client`): handshake and round-trip, verification by CA/name/fingerprint,
mutual auth, robustness against bogus datagrams, keying material, MTU, and full
client- and server-side resumption.
**Separate follow-ups** (outside the scheme-only scope, they touch the core or
OpenSSL's listener API): a multi-peer server, factoring the code
shared between `xp_ssl.c` and `xp_dtls.c` into an `xp_common`, and `enable_crypto`
on `udp://`. There is also a small TODO: `php_openssl_dtls_parse_ip_address()`
duplicates `parse_ip_address_ex()` from `xp_socket.c`.
Discussed on internals: <https://externals.io/message/131514>.
### TODO before removing Draft status
- [ ] DTLS 1.3 support (planned for this PR, not implemented yet)
- [ ] `UPGRADING` and `NEWS`
- [ ] php.net documentation
- [ ] Rebase on `master`, green suite, coding standards