Repository navigation
Conversation
Related to php#16766
|
@Sjord: Thanks a lot for your work about Channel Binding! It will be not possible to backport to previous PHP versions too? |
and
If it's part of OpenSSL, it must have an |
|
I tested this against Prosody and Postgres, which gave me some confidence that this works at least in some situations. |
|
@iluuu1994 Could you take a look at this? Is it OK to keep the strings ("tls-unique", "tls-server-end-point", "tls-exporter") or do these need to become enums or constants? |
|
Thanks for reviewing, @TimWolla |
|
After the merging in master branch, it will be nice to backport it in other PHP branches starting 8.2.x. The goal is to have a better security with PHP... Several developers can not test it because it is not for PHP 8.2... :/ |
|
New features don't get backported to stable branches, especially not the ones in security-maintenance. Otherwise, what's the point of having different branches at all? |
|
@iluuu1994: But this PR adds an important security feature... It will be nice to add in previous branches to have more security... |
|
@LamentXU123, @shivammathur, @ndossche: What do you think? Security is very important and this feature is needed by a lot of people and projects. Thanks in advance. |
|
This is disallowed according to our policy. https://github.com/php/policies/blob/main/release-process.rst
|
|
So PHP 8.6.0 has not been released yet, it can be added into? |
|
No, because 8.6 has reached feature freeze. Anything that conflicts with our policy would need some RFC to overrule the policy. |
[citation needed] |
I do not see how the links support that claim. A barely two-digit number of projects is not “a lot”. And if this feature was actually so important that it is needed right now, I wonder why no one, including yourself, bothered to implement it in the past 7 years (or whenever the first issue was created). |
|
I changed the channel_binding_type to a enum. I also wrote an RFC: PHP RFC: openssl_get_channel_binding() |
| return PHP_OPENSSL_CHANNEL_BINDING_RESULT_ERROR; | ||
| } | ||
| *out = zend_string_init((char *)buf, 32, 0); | ||
| return *out != NULL ? PHP_OPENSSL_CHANNEL_BINDING_RESULT_OK : PHP_OPENSSL_CHANNEL_BINDING_RESULT_ERROR; |
There was a problem hiding this comment.
zend_string_init() guarantees a non-NULL return (only zend_string_finit() can fail).
| (const unsigned char *)"", 0, 1) != 1) { | ||
| return PHP_OPENSSL_CHANNEL_BINDING_RESULT_ERROR; | ||
| } | ||
| *out = zend_string_init((char *)buf, 32, 0); |
There was a problem hiding this comment.
| *out = zend_string_init((char *)buf, 32, 0); | |
| *out = zend_string_init((char *)buf, 32, false); |
| unsigned char buf[EVP_MAX_MD_SIZE]; | ||
| size_t len = 0; | ||
| php_openssl_netstream_data_t *sslsock; | ||
| SSL *ssl; |
There was a problem hiding this comment.
Move down declarations as far as possible (applies everywhere).
| * stream PHP_OPENSSL_CHANNEL_BINDING_RESULT_NOT_TLS is returned, and if an OpenSSL call fails | ||
| * PHP_OPENSSL_CHANNEL_BINDING_RESULT_ERROR is returned; in both of these cases *out is set to NULL. | ||
| */ | ||
| php_openssl_channel_binding_result php_openssl_netstream_get_channel_binding( /* {{{ */ |
There was a problem hiding this comment.
| php_openssl_channel_binding_result php_openssl_netstream_get_channel_binding( /* {{{ */ | |
| php_openssl_channel_binding_result php_openssl_netstream_get_channel_binding( |
These are not used in new code.
| return *out != NULL ? PHP_OPENSSL_CHANNEL_BINDING_RESULT_OK : PHP_OPENSSL_CHANNEL_BINDING_RESULT_ERROR; | ||
|
|
||
| default: | ||
| return PHP_OPENSSL_CHANNEL_BINDING_RESULT_ERROR; |
da9073f to
035b582
Compare
Instead of returning null.
035b582 to
81098e1
Compare
PHP RFC: openssl_get_channel_binding()
Related to #16766
The branch adds a new function to the openssl extension:
The binding type is selected with a string-backed enum:
It extracts TLS channel binding data from an established
tls://socket stream. This unblocks SASL channel binding (SCRAM-SHA-*-PLUSper RFC 5802 and RFC 5801) for clients written in PHP, which previously had no way to obtain the binding material that those mechanisms require.The enum case values are the names from the IANA "Channel Binding" registry. The
tls-uniqueselection semantics follow CPython's_ssl.get_channel_binding(); this proposal additionally supports the other two TLS channel binding types.streamresourcessl:///tls://). Must be in the connected/active state.channel_binding_typeOpenssl\ChannelBindingTypeTlsUnique,TlsServerEndPoint, orTlsExporter. A string such as"tls-unique"is not accepted.Return value
nullwhen the requested type is not applicable to the connection(currently:
TlsUniqueover TLS 1.3, where the type is not defined).Errors / exceptions
channel_binding_typeis not anOpenssl\ChannelBindingTypeTypeErrorstreamis not a stream resourceTypeErrorstreamis a stream but has no active TLS transportOpenssl\OpensslException—"Stream does not have transport encryption enabled"Openssl\OpensslException—"Failed to get channel binding data: <OpenSSL error>"Code that stores the binding type as a string can map it with
Openssl\ChannelBindingType::from($name), which raisesValueErrorfor an unknown name. The enum backing values, like the IANA names, are case-sensitive.Supported channel binding types
TlsUnique(tls-unique)nullTlsServerEndPoint(tls-server-end-point)TlsExporter(tls-exporter)EXPORTER-Channel-Bindingand an empty contextNotes on semantics
tls-uniqueselection. In a full handshake both endpoints transmit aFinished message; in a resumed handshake only the server does. The
implementation picks between the local
SSL_get_finished()andSSL_get_peer_finished()usingis_client ^ SSL_session_reused(), so that theclient and the server always derive the same value. This mirrors the
selection made by CPython's
_ssl.get_channel_binding().tls-server-end-pointdigest choice. The digest algorithm is taken fromthe certificate's own signature algorithm. If that algorithm is MD5 or SHA-1,
or cannot be determined, SHA-256 is used instead (as mandated by
RFC 5929 §4.1). For a SHA-256-signed certificate the result equals
openssl_x509_fingerprint($cert, "sha256", true). On the client side the peercertificate is used; on the server side the local certificate is used.
tls-exporter. Computed withSSL_export_keying_material()using a 32octet output, the label
EXPORTER-Channel-Bindingand an empty context(RFC 9266 §4 / RFC 5705).
Example
Obtaining a binding on a connected client and using it as the SASL
cbproperty for aSCRAM-SHA-256-PLUSnegotiation: