-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
support server ALPN on macOS #79434
support server ALPN on macOS #79434
Conversation
Tagging subscribers to this area: @dotnet/ncl, @vcsjones Issue DetailsAs noted in #27727, there is no publicly documented API how to do this with the API we use. However, Apple publish relevant code and that is most accurate documentation :) This is somewhat tacky but similar to what we for OpenSSL on Linux. Here is the long story: Fundamentally, coreTLS fail to read and process ALPN extension from ClientHello. That is OK and easy to fix. Now is the tricky part. We can use same functions to set the selected protocol but it does not work because coreTLS is unaware of client's ALPN and therefore ignores the provided data. To fix that I added header stub from coreTLS so we can dereference so far opaque
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The fact that we rely on layouts that are not guaranteed to be stable makes me slightly uncomfortable. Can we be reasonably sure this will not cause process crashes when something changes in coreTLS?
I agree. This is why I added the if (tls != NULL && tls->alpnOwnData.length == length + 1) If the TLS layout change (at least before ALPN portion) the |
Same concern here. Is there any validation for the scenario that runs BOTH on osx-arm64 and osx-x64? I know the layout is the same; specifically asking only for the validation of the fact. How does this affect iOS and tvOS platforms and is the code path tested there? Lastly, this may be worth an escape hatch (eg. environment variable?) that would disable the behavior with peeking into private structures. If Apple ever decides to change it (unlikely) then we should have a way to keep applications running without patching framework or forced updates. |
I did test on M1 arm macBook @filipnavara and all tests pass e.g. the layout is identical. As far as |
I know it is identical [now] :-) I'm just worried it may diverge in future, however unlikely, and it would not be caught by the CI.
I'd be definitely in favour of that. |
The |
Does this have any diagnostics in case things fail? How would we debug this on customer machines if things go wrong? |
If the guard I put in kicks in it would not select any ALPN e.g. it would behave as it does now. I can certainly put in more diagnostic. We could throw (PNSE?) if preferable to make it more visible. The expectation is that would see that coming during testing beta versions of new major updated as it would fail our existing tests. Now the difficult part is case when the structure would change in a way we fail to detect. In that case we would write to native memory of coreTLS. That would likely result in some crypto errors visible as TLS failures or possibly in weird crashes with stack to coreTLS if happen to mangle some pointers. |
I'm more looking for some event source event that we can fire as a diagnostic to tell the customer to turn on (use dotnet trace and turn on these events to see why it might be failing) if it fails. |
As noted in #27727, there is no publicly documented API how to do this with the API we use. However, Apple publish relevant code and that is most accurate documentation :) This is somewhat tacky but similar to what we for OpenSSL on Linux.
With that everything works just fine (tested 11.6 on x85 & M1 on real HW and 13.0.1 in VM) and macOS gets on par with Linux & Windows e.g. it opens possibility for HTTP/2 in Kestrel + gRPC for Mac developers.
Here is the long story:
Fundamentally, coreTLS fail to read and process ALPN extension from ClientHello. That is OK and easy to fix.
With small changes to existing
TlsFrameHelper
we can get the data in SslStream. Conveniently, there is option to break the handshake when ClientHello arrives. It was mostly for SNI according to docs but does not matter. We can get back to managed code and runSelectApplicationProtocol
to make selection.Now is the tricky part. We can use same functions to set the selected protocol but it does not work because coreTLS is unaware of client's ALPN and therefore ignores the provided data. To fix that I added header stub from coreTLS so we can dereference so far opaque
SSLContextRef
. While this is generally problematic this code did not changed several years and it is deprecated by Apple so it feels like it is unlikely to change ever. I put in extra sanity check to verify that the ALPN data written by public API goes to place where we expect it. If the layout ever change we should be able to detect it and avoid writing to wrong location.fixes #27727