-
Notifications
You must be signed in to change notification settings - Fork 5.2k
Reimplement NegotiateStream using (mostly) public NegotiateAuthenticaton API #86948
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
Conversation
|
Note regarding the This serves as a reminder for when your PR is modifying a ref *.cs file and adding/modifying public APIs, please make sure the API implementation in the src *.cs file is documented with triple slash comments, so the PR reviewers can sign off that change. |
|
Tagging subscribers to this area: @dotnet/ncl, @bartonjs, @vcsjones Issue DetailsAdds support for tvOS and Android as a side-effect.
|
| <Suppression> | ||
| <DiagnosticId>CP0015</DiagnosticId> | ||
| <Target>M:System.Type.GetEnumValues:[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute]</Target> | ||
| <Left>net7.0/mscorlib.dll</Left> | ||
| <Right>net8.0/mscorlib.dll</Right> | ||
| </Suppression> | ||
| <Suppression> | ||
| <DiagnosticId>CP0015</DiagnosticId> | ||
| <Target>M:System.Type.GetEnumValues:[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute]</Target> | ||
| <Left>net7.0/netstandard.dll</Left> | ||
| <Right>net8.0/netstandard.dll</Right> | ||
| </Suppression> | ||
| <Suppression> | ||
| <DiagnosticId>CP0015</DiagnosticId> | ||
| <Target>M:System.Type.GetEnumValues:[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute]</Target> | ||
| <Left>net7.0/System.Runtime.dll</Left> | ||
| <Right>net8.0/System.Runtime.dll</Right> | ||
| </Suppression> |
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.
This is side-effect of rebuilding the API compat file.
…iateStream to work
| } | ||
|
|
||
| private static unsafe int DecryptNtlm( | ||
| internal static unsafe void GetMIC( |
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.
Would this produce same output e.g. would it be compatible with other versions of NegotiateStream?
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.
Yes, the NTLM code should be compatible.
(There's a part of code where I fixed the on-wire transmission of error codes. It was broken ever since Unix support was added and didn't follow the spec or the .NET Framework version.)
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.
it is Kerberos what worries me more. And SqlClient uses fragments of this as well. (dotnet/SqlClient#303)
cc: @JRahnama @DavoudEshtehari for visibility
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.
There should not be any change of the on-wire data with this PR with two exceptions:
- The fixed error codes that now match the spec and .NET Framework
- Write sends the frame length separately from the data to the underlying transport stream (valid according to
Streamcontract but may be problematic if someone was usingNegotiateStreamto implementNegotiatealgorithm, and stripping the frame headers)
There's no modification of the native shim beyond what was already done in .NET 7.
| exception = new AuthenticationException(SR.Format(SR.net_auth_context_expectation, result.ToString(), _expectedProtectionLevel.ToString())); | ||
| int statusCode = ERROR_TRUST_FAILURE; | ||
| message = new byte[sizeof(long)]; | ||
| message = new byte[sizeof(long)]; |
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.
can we make it static constant?
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.
I suppose we can but I am not sure it's worth it. It's an error condition that can happen only once per connection. Is it really worth optimizing an error code path?
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.
while the impact is small it also seem super easy...
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.
It was not done previously. The code basically stayed the same. I felt the diff was hard enough to read as-is.
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.
thanks @filipnavara. generally looks good to me but it is big cleanup. I wish we can test agains previous implementation but our tests are not set up for that.
I think I can test that manually. I'll report back on the results. |
That would be great. Possibly also cover dotnet/SqlClient#1390 - probably does not need any real database. |
Test case
using System;
using System.IO.Pipes;
using System.Net.Security;
using System.Text;
class Program
{
public static void Main(string[] args)
{
if (args.Length == 0)
return;
bool isClient = args[0] == "client";
if (isClient)
{
using var pipeStream = new NamedPipeClientStream(".", "negtest", PipeDirection.InOut, PipeOptions.None);
pipeStream.Connect();
using var negStream = new NegotiateStream(pipeStream);
negStream.AuthenticateAsClient();
negStream.Write("hello"u8.ToArray(), 0, 5);
negStream.Flush();
}
else
{
using var pipeStream = new NamedPipeServerStream("negtest", PipeDirection.InOut);
pipeStream.WaitForConnection();
using var negStream = new NegotiateStream(pipeStream);
negStream.AuthenticateAsServer();
byte[] buffer = new byte[5];
negStream.Read(buffer, 0, 5);
Console.WriteLine(Encoding.UTF8.GetString(buffer));
}
}
}I tested the basic communication between all the variations of .NET 4.8, .NET 8 Preview 4 and runtime build from this PR (on Windows). In all cases the communication was successfully established and the data were transferred. I modified the code above to test both Signed-only and Encrypted-and-Signed scenarios for NTLM (on Windows) since that's the part that had the largest level of refactoring. |
|
I checked that Linux-Linux communication also works. I tried Windows-Linux too but run into W11 rejecting the NTLM exchange from Linux (unrelated to the changes in this PR) but at least it showed that the transmission of error codes over the wire works as well. |
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.
thanks @filipnavara
|
can you please resolve the conflict @filipnavara? Ill merge it. |
|
Sure, will do it in few minutes. |
suppression changes
done |
Adds support for tvOS and Android as a side-effect.