Skip to content
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

H/3 Server Cert validation callback exception fix #55526

Merged
merged 2 commits into from
Jul 13, 2021

Conversation

ManickaP
Copy link
Member

@ManickaP ManickaP commented Jul 12, 2021

Sets and unsets HttpMessageRequest to the cert callback when opening new QuicConnection.

Fixes #55192

@ghost
Copy link

ghost commented Jul 12, 2021

Tagging subscribers to this area: @dotnet/ncl
See info in area-owners.md if you want to be subscribed.

Issue Details

This is an easy fix for the problem. It solves the exception encountered in the issue, but it doesn't solve it properly for all possible callbacks.

In case the callback is registered through SocketsHttpHandler.SslOptions.RemoteCertificateValidationCallback, you'll get MsQuicConnection in the sender argument. As is the code sending now.
In case the callback is registered through HttpClientHandler.ServerCertificateCustomValidationCallback, you'll get null in HttpRequestMessage argument.

This is because we're receiving the event on connection where we don't have any way to pair it with the request that triggered this ATM. I assume, it could be possible, but it'll need more digging and potentially a change in msquic (@wfurt).

If this is something that could unblock you @JamesNK, we can merge this "quick fix". If not and you really need the request in the callback, this might take a bit longer.

I'm not closing the issue, to track the proper solution to this.
Contributes to #55192

Author: ManickaP
Assignees: -
Labels:

area-System.Net.Http

Milestone: -

@ManickaP
Copy link
Member Author

ManickaP commented Jul 12, 2021

I got a quick chat with @wfurt and I'm working on a proper fix, please hold off your review efforts for the moment.
Fixed, ready for review.

@ManickaP ManickaP added the NO-REVIEW Experimental/testing PR, do NOT review it label Jul 12, 2021
@ManickaP ManickaP force-pushed the mapichov/55192_cert_callback_fix branch from 1118449 to 0c78487 Compare July 12, 2021 19:29
@ManickaP ManickaP force-pushed the mapichov/55192_cert_callback_fix branch from 0c78487 to f867d19 Compare July 12, 2021 19:31
@ManickaP ManickaP removed the NO-REVIEW Experimental/testing PR, do NOT review it label Jul 12, 2021
bool result = localFromHttpClientHandler(request, certificate as X509Certificate2, chain, sslPolicyErrors);
return result;
};
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like an almost duplicate of https://github.com/dotnet/runtime/pull/55526/files#diff-9eb150e0af6ce559b3ef3e99949ba3512594fe4c55fbf10e6b739d315899d469R40-R57. Why are we duplicating the code?

It also looks like as part of copying/pasting that here, you removed the localRequest... why?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For msquic, the callback gets called multiple times when the connection is established, so I couldn't unset it in the callback itself, but after the connection is opened.
So I moved the "unsetting" to finally block, where I discard the whole custom callback wrapper and put back the original, thus removing reference to the request.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also there's a similar issue with SslStream as well: #55334
I plan to put up an additional PR with the similar fix, where I could unify the logic and remove the code duplication. Unless there's something fundamentally wrong with the way I unset the callback and release the hold of the request.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok. Note the localRequest was also there as an optimization. Right now you're paying for the closure even if there is no callback.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's something I was not aware of and I'll probably bring the localRequest back, thanks.

if (clientAuthenticationOptions is not null && callback is not null)
{
// We cannot unset the request closure variable after the first callaback invocation as we do with SslStream
// since the callback will get triggered multiple times during connection establishment.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, is this why you duplicated the code?

@wfurt
Copy link
Member

wfurt commented Jul 13, 2021

The underlying issue is tracked by microsoft/msquic#1810
Seems platform specific e.g. we get the multiple invocations only on Linux -> Windows work as expected.

We could put workaround to MsQuicConnection and ignore additional validation callbacks.
That could be removed when MsQuic is fixed (or we can keep it if it never is)

Since TLS 13 does not support renegotiation there should never be case when we need to do validation more than once.

@ManickaP
Copy link
Member Author

@wfurt will do as you suggest, if feasible. If not, I'll push this through as is.

@ManickaP ManickaP force-pushed the mapichov/55192_cert_callback_fix branch from ba48796 to 6857e7a Compare July 13, 2021 14:30
@ManickaP
Copy link
Member Author

In the end, I prevented MsQuicConnection to call the cert validation callback multiple times by remembering the first value returned.
Thus, I also removed the code duplication. cc: @stephentoub
@wfurt could you give it a final review?

Copy link
Member

@wfurt wfurt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

@ManickaP ManickaP merged commit 9a9b105 into dotnet:main Jul 13, 2021
@ManickaP ManickaP deleted the mapichov/55192_cert_callback_fix branch July 13, 2021 17:18
@karelz karelz added this to the 6.0.0 milestone Jul 15, 2021
@ghost ghost locked as resolved and limited conversation to collaborators Aug 14, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[HTTP/3] ServerCertificateCustomValidationCallback causes connection error
4 participants