-
Notifications
You must be signed in to change notification settings - Fork 4.9k
Fix SPN used for Negotiate authentication #33426
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,6 +4,7 @@ | |
|
|
||
| using System.Collections.Generic; | ||
| using System.Diagnostics; | ||
| using System.Net; | ||
| using System.Net.Http.Headers; | ||
| using System.Threading; | ||
| using System.Threading.Tasks; | ||
|
|
@@ -77,7 +78,28 @@ private static async Task<HttpResponseMessage> SendWithNtAuthAsync(HttpRequestMe | |
|
|
||
| string challengeData = challenge.ChallengeData; | ||
|
|
||
| string spn = "HTTP/" + authUri.IdnHost; | ||
| // Need to use FQDN normalized host so that CNAME's are traversed. | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we move the comment rather into the else-branch?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think the comment is in the right place since it describes the logic to calculate the SPN. But I will revise the comment because it needs to describe that we skip DNS lookup in cases of IP literals. |
||
| // Use DNS to do the forward lookup to an A (host) record. | ||
| // But skip DNS lookup on IP literals. Otherwise, we would end up | ||
| // doing an unintended reverse DNS lookup. | ||
| string spn; | ||
| UriHostNameType hnt = authUri.HostNameType; | ||
| if (hnt == UriHostNameType.IPv6 || hnt == UriHostNameType.IPv4) | ||
| { | ||
| spn = authUri.IdnHost; | ||
| } | ||
| else | ||
| { | ||
| IPHostEntry result = await Dns.GetHostEntryAsync(authUri.IdnHost).ConfigureAwait(false); | ||
| spn = result.HostName; | ||
| } | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: maybe instead of doing: string spn;
if (...)
{
spn = "HTTP/" + authUri.IdnHost;
}
else
{
...
spn = "HTTP/" + result.HostName;
}do: string spn;
if (...)
{
spn = authUri.IdnHost;
}
else
{
...
spn = result.HostName;
}
spn = "HTTP/" + spn;?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is this better? Is seems slower because we are doing two assignments of I don't think it is really less lines of IL or memory because the "HTTP/" string should only occur once.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
From my perspective it's better because it's centralizing some logic, namely the concatenation of the "HTTP/" prefix. There's also no additional field assignment, as But it's just a small thing. Whatever you prefer is fine.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok. I'll make the change. And I like the https://sharplab.io example! That is a nice website for this kind of analysis. |
||
| spn = "HTTP/" + spn; | ||
|
|
||
| if (NetEventSource.IsEnabled) | ||
| { | ||
| NetEventSource.Info(connection, $"Authentication: {challenge.AuthenticationType}, Host: {authUri.IdnHost}, SPN: {spn}"); | ||
| } | ||
|
|
||
| ChannelBinding channelBinding = connection.TransportContext?.GetChannelBinding(ChannelBindingKind.Endpoint); | ||
| NTAuthentication authContext = new NTAuthentication(isServer:false, challenge.SchemeName, challenge.Credential, spn, ContextFlagsPal.Connection, channelBinding); | ||
| try | ||
|
|
||
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.
We didn't already have this because we were relying on the underlying implementation (e.g. System.Net.Sockets) to do the original Dns call?
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.
Correct. I needed to add it in order to compile.