Skip to content

Reimplement NegotiateStream using (mostly) public NegotiateAuthenticaton API - #86948

Merged
wfurt merged 4 commits into
dotnet:mainfrom
filipnavara:negotiatestream-cleanup
Jun 16, 2023
Merged

Reimplement NegotiateStream using (mostly) public NegotiateAuthenticaton API#86948
wfurt merged 4 commits into
dotnet:mainfrom
filipnavara:negotiatestream-cleanup

Conversation

@filipnavara

Copy link
Copy Markdown
Member

Adds support for tvOS and Android as a side-effect.

@ghostghost added community-contribution Indicates that the PR has been added by a community member area-System.Net.Security new-api-needs-documentation labels May 31, 2023
@ghost

Copy link
Copy Markdown

Note regarding the new-api-needs-documentation label:

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.

@ghost

Copy link
Copy Markdown

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

Issue Details

Adds support for tvOS and Android as a side-effect.

Author:filipnavara
Assignees:-
Labels:

area-System.Net.Security, new-api-needs-documentation, community-contribution

Milestone:-

@filipnavara
filipnavara requested a review from wfurtMay 31, 2023 11:39
Comment on lines -2860 to -2649
<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>

Copy link
Copy Markdown
MemberAuthor

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.

}

private static unsafe int DecryptNtlm(
internal static unsafe void GetMIC(

Copy link
Copy Markdown
Member

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?

Copy link
Copy Markdown
MemberAuthor

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.)

Copy link
Copy Markdown
Member

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

Copy link
Copy Markdown
MemberAuthor

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 Stream contract but may be problematic if someone was using NegotiateStream to implement Negotiate algorithm, 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)];

Copy link
Copy Markdown
Member

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?

Copy link
Copy Markdown
MemberAuthor

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?

Copy link
Copy Markdown
Member

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...

@filipnavarafilipnavaraJun 8, 2023

Copy link
Copy Markdown
MemberAuthor

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.

@wfurtwfurt left a comment

Copy link
Copy Markdown
Member

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.

@filipnavara

Copy link
Copy Markdown
MemberAuthor

I wish we can test against 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.

@wfurt

wfurt commented Jun 8, 2023

Copy link
Copy Markdown
Member

I wish we can test against 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.

@filipnavara

filipnavara commented Jun 8, 2023

Copy link
Copy Markdown
MemberAuthor
Test case

usingSystem;usingSystem.IO.Pipes;usingSystem.Net.Security;usingSystem.Text;classProgram{publicstaticvoidMain(string[]args){if(args.Length==0)return;boolisClient=args[0]=="client";if(isClient){usingvarpipeStream=newNamedPipeClientStream(".","negtest",PipeDirection.InOut,PipeOptions.None);pipeStream.Connect();usingvarnegStream=newNegotiateStream(pipeStream);negStream.AuthenticateAsClient();negStream.Write("hello"u8.ToArray(),0,5);negStream.Flush();}else{usingvarpipeStream=newNamedPipeServerStream("negtest",PipeDirection.InOut);pipeStream.WaitForConnection();usingvarnegStream=newNegotiateStream(pipeStream);negStream.AuthenticateAsServer();byte[]buffer=newbyte[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.

@filipnavara

Copy link
Copy Markdown
MemberAuthor

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.

@wfurtwfurt left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@wfurt

Copy link
Copy Markdown
Member

can you please resolve the conflict @filipnavara? Ill merge it.

@filipnavara

Copy link
Copy Markdown
MemberAuthor

Sure, will do it in few minutes.

suppression changes
@filipnavara

Copy link
Copy Markdown
MemberAuthor

can you please resolve the conflict @filipnavara? Ill merge it.

done

@wfurt
wfurt merged commit 77ad806 into dotnet:mainJun 16, 2023
@filipnavara
filipnavara deleted the negotiatestream-cleanup branch June 16, 2023 10:50
@karelzkarelz added this to the 8.0.0 milestone Jul 3, 2023
@ghostghost locked as resolved and limited conversation to collaborators Aug 2, 2023
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-System.Net.Securitycommunity-contributionIndicates that the PR has been added by a community membernew-api-needs-documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@filipnavara@wfurt@karelz
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Reimplement NegotiateStream using (mostly) public NegotiateAuthenticaton API by filipnavara · Pull Request #86948 · dotnet/runtime · GitHub
Skip to content

Reimplement NegotiateStream using (mostly) public NegotiateAuthenticaton API - #86948

Merged
wfurt merged 4 commits into
dotnet:mainfrom
filipnavara:negotiatestream-cleanup
Jun 16, 2023
Merged

Reimplement NegotiateStream using (mostly) public NegotiateAuthenticaton API#86948
wfurt merged 4 commits into
dotnet:mainfrom
filipnavara:negotiatestream-cleanup

Conversation

@filipnavara

Copy link
Copy Markdown
Member

Adds support for tvOS and Android as a side-effect.

@ghostghost added community-contribution Indicates that the PR has been added by a community member area-System.Net.Security new-api-needs-documentation labels May 31, 2023
@ghost

Copy link
Copy Markdown

Note regarding the new-api-needs-documentation label:

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.

@ghost

Copy link
Copy Markdown

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

Issue Details

Adds support for tvOS and Android as a side-effect.

Author:filipnavara
Assignees:-
Labels:

area-System.Net.Security, new-api-needs-documentation, community-contribution

Milestone:-

@filipnavara
filipnavara requested a review from wfurtMay 31, 2023 11:39
Comment on lines -2860 to -2649
<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>

Copy link
Copy Markdown
MemberAuthor

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.

}

private static unsafe int DecryptNtlm(
internal static unsafe void GetMIC(

Copy link
Copy Markdown
Member

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?

Copy link
Copy Markdown
MemberAuthor

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.)

Copy link
Copy Markdown
Member

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

Copy link
Copy Markdown
MemberAuthor

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 Stream contract but may be problematic if someone was using NegotiateStream to implement Negotiate algorithm, 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)];

Copy link
Copy Markdown
Member

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?

Copy link
Copy Markdown
MemberAuthor

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?

Copy link
Copy Markdown
Member

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...

@filipnavarafilipnavaraJun 8, 2023

Copy link
Copy Markdown
MemberAuthor

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.

@wfurtwfurt left a comment

Copy link
Copy Markdown
Member

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.

@filipnavara

Copy link
Copy Markdown
MemberAuthor

I wish we can test against 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.

@wfurt

wfurt commented Jun 8, 2023

Copy link
Copy Markdown
Member

I wish we can test against 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.

@filipnavara

filipnavara commented Jun 8, 2023

Copy link
Copy Markdown
MemberAuthor
Test case

usingSystem;usingSystem.IO.Pipes;usingSystem.Net.Security;usingSystem.Text;classProgram{publicstaticvoidMain(string[]args){if(args.Length==0)return;boolisClient=args[0]=="client";if(isClient){usingvarpipeStream=newNamedPipeClientStream(".","negtest",PipeDirection.InOut,PipeOptions.None);pipeStream.Connect();usingvarnegStream=newNegotiateStream(pipeStream);negStream.AuthenticateAsClient();negStream.Write("hello"u8.ToArray(),0,5);negStream.Flush();}else{usingvarpipeStream=newNamedPipeServerStream("negtest",PipeDirection.InOut);pipeStream.WaitForConnection();usingvarnegStream=newNegotiateStream(pipeStream);negStream.AuthenticateAsServer();byte[]buffer=newbyte[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.

@filipnavara

Copy link
Copy Markdown
MemberAuthor

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.

@wfurtwfurt left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@wfurt

Copy link
Copy Markdown
Member

can you please resolve the conflict @filipnavara? Ill merge it.

@filipnavara

Copy link
Copy Markdown
MemberAuthor

Sure, will do it in few minutes.

suppression changes
@filipnavara

Copy link
Copy Markdown
MemberAuthor

can you please resolve the conflict @filipnavara? Ill merge it.

done

@wfurt
wfurt merged commit 77ad806 into dotnet:mainJun 16, 2023
@filipnavara
filipnavara deleted the negotiatestream-cleanup branch June 16, 2023 10:50
@karelzkarelz added this to the 8.0.0 milestone Jul 3, 2023
@ghostghost locked as resolved and limited conversation to collaborators Aug 2, 2023
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-System.Net.Securitycommunity-contributionIndicates that the PR has been added by a community membernew-api-needs-documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@filipnavara@wfurt@karelz
, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Reimplement NegotiateStream using (mostly) public NegotiateAuthenticaton API by filipnavara · Pull Request #86948 · dotnet/runtime · GitHub
Skip to content

Reimplement NegotiateStream using (mostly) public NegotiateAuthenticaton API - #86948

Merged
wfurt merged 4 commits into
dotnet:mainfrom
filipnavara:negotiatestream-cleanup
Jun 16, 2023
Merged

Reimplement NegotiateStream using (mostly) public NegotiateAuthenticaton API#86948
wfurt merged 4 commits into
dotnet:mainfrom
filipnavara:negotiatestream-cleanup

Conversation

@filipnavara

Copy link
Copy Markdown
Member

Adds support for tvOS and Android as a side-effect.

@ghostghost added community-contribution Indicates that the PR has been added by a community member area-System.Net.Security new-api-needs-documentation labels May 31, 2023
@ghost

Copy link
Copy Markdown

Note regarding the new-api-needs-documentation label:

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.

@ghost

Copy link
Copy Markdown

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

Issue Details

Adds support for tvOS and Android as a side-effect.

Author:filipnavara
Assignees:-
Labels:

area-System.Net.Security, new-api-needs-documentation, community-contribution

Milestone:-

@filipnavara
filipnavara requested a review from wfurtMay 31, 2023 11:39
Comment on lines -2860 to -2649
<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>

Copy link
Copy Markdown
MemberAuthor

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.

}

private static unsafe int DecryptNtlm(
internal static unsafe void GetMIC(

Copy link
Copy Markdown
Member

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?

Copy link
Copy Markdown
MemberAuthor

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.)

Copy link
Copy Markdown
Member

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

Copy link
Copy Markdown
MemberAuthor

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 Stream contract but may be problematic if someone was using NegotiateStream to implement Negotiate algorithm, 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)];

Copy link
Copy Markdown
Member

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?

Copy link
Copy Markdown
MemberAuthor

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?

Copy link
Copy Markdown
Member

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...

@filipnavarafilipnavaraJun 8, 2023

Copy link
Copy Markdown
MemberAuthor

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.

@wfurtwfurt left a comment

Copy link
Copy Markdown
Member

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.

@filipnavara

Copy link
Copy Markdown
MemberAuthor

I wish we can test against 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.

@wfurt

wfurt commented Jun 8, 2023

Copy link
Copy Markdown
Member

I wish we can test against 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.

@filipnavara

filipnavara commented Jun 8, 2023

Copy link
Copy Markdown
MemberAuthor
Test case

usingSystem;usingSystem.IO.Pipes;usingSystem.Net.Security;usingSystem.Text;classProgram{publicstaticvoidMain(string[]args){if(args.Length==0)return;boolisClient=args[0]=="client";if(isClient){usingvarpipeStream=newNamedPipeClientStream(".","negtest",PipeDirection.InOut,PipeOptions.None);pipeStream.Connect();usingvarnegStream=newNegotiateStream(pipeStream);negStream.AuthenticateAsClient();negStream.Write("hello"u8.ToArray(),0,5);negStream.Flush();}else{usingvarpipeStream=newNamedPipeServerStream("negtest",PipeDirection.InOut);pipeStream.WaitForConnection();usingvarnegStream=newNegotiateStream(pipeStream);negStream.AuthenticateAsServer();byte[]buffer=newbyte[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.

@filipnavara

Copy link
Copy Markdown
MemberAuthor

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.

@wfurtwfurt left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@wfurt

Copy link
Copy Markdown
Member

can you please resolve the conflict @filipnavara? Ill merge it.

@filipnavara

Copy link
Copy Markdown
MemberAuthor

Sure, will do it in few minutes.

suppression changes
@filipnavara

Copy link
Copy Markdown
MemberAuthor

can you please resolve the conflict @filipnavara? Ill merge it.

done

@wfurt
wfurt merged commit 77ad806 into dotnet:mainJun 16, 2023
@filipnavara
filipnavara deleted the negotiatestream-cleanup branch June 16, 2023 10:50
@karelzkarelz added this to the 8.0.0 milestone Jul 3, 2023
@ghostghost locked as resolved and limited conversation to collaborators Aug 2, 2023
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-System.Net.Securitycommunity-contributionIndicates that the PR has been added by a community membernew-api-needs-documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@filipnavara@wfurt@karelz
, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Reimplement NegotiateStream using (mostly) public NegotiateAuthenticaton API by filipnavara · Pull Request #86948 · dotnet/runtime · GitHub
Skip to content

Reimplement NegotiateStream using (mostly) public NegotiateAuthenticaton API - #86948

Merged
wfurt merged 4 commits into
dotnet:mainfrom
filipnavara:negotiatestream-cleanup
Jun 16, 2023
Merged

Reimplement NegotiateStream using (mostly) public NegotiateAuthenticaton API#86948
wfurt merged 4 commits into
dotnet:mainfrom
filipnavara:negotiatestream-cleanup

Conversation

@filipnavara

Copy link
Copy Markdown
Member

Adds support for tvOS and Android as a side-effect.

@ghostghost added community-contribution Indicates that the PR has been added by a community member area-System.Net.Security new-api-needs-documentation labels May 31, 2023
@ghost

Copy link
Copy Markdown

Note regarding the new-api-needs-documentation label:

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.

@ghost

Copy link
Copy Markdown

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

Issue Details

Adds support for tvOS and Android as a side-effect.

Author:filipnavara
Assignees:-
Labels:

area-System.Net.Security, new-api-needs-documentation, community-contribution

Milestone:-

@filipnavara
filipnavara requested a review from wfurtMay 31, 2023 11:39
Comment on lines -2860 to -2649
<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>

Copy link
Copy Markdown
MemberAuthor

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.

}

private static unsafe int DecryptNtlm(
internal static unsafe void GetMIC(

Copy link
Copy Markdown
Member

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?

Copy link
Copy Markdown
MemberAuthor

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.)

Copy link
Copy Markdown
Member

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

Copy link
Copy Markdown
MemberAuthor

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 Stream contract but may be problematic if someone was using NegotiateStream to implement Negotiate algorithm, 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)];

Copy link
Copy Markdown
Member

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?

Copy link
Copy Markdown
MemberAuthor

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?

Copy link
Copy Markdown
Member

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...

@filipnavarafilipnavaraJun 8, 2023

Copy link
Copy Markdown
MemberAuthor

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.

@wfurtwfurt left a comment

Copy link
Copy Markdown
Member

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.

@filipnavara

Copy link
Copy Markdown
MemberAuthor

I wish we can test against 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.

@wfurt

wfurt commented Jun 8, 2023

Copy link
Copy Markdown
Member

I wish we can test against 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.

@filipnavara

filipnavara commented Jun 8, 2023

Copy link
Copy Markdown
MemberAuthor
Test case

usingSystem;usingSystem.IO.Pipes;usingSystem.Net.Security;usingSystem.Text;classProgram{publicstaticvoidMain(string[]args){if(args.Length==0)return;boolisClient=args[0]=="client";if(isClient){usingvarpipeStream=newNamedPipeClientStream(".","negtest",PipeDirection.InOut,PipeOptions.None);pipeStream.Connect();usingvarnegStream=newNegotiateStream(pipeStream);negStream.AuthenticateAsClient();negStream.Write("hello"u8.ToArray(),0,5);negStream.Flush();}else{usingvarpipeStream=newNamedPipeServerStream("negtest",PipeDirection.InOut);pipeStream.WaitForConnection();usingvarnegStream=newNegotiateStream(pipeStream);negStream.AuthenticateAsServer();byte[]buffer=newbyte[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.

@filipnavara

Copy link
Copy Markdown
MemberAuthor

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.

@wfurtwfurt left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@wfurt

Copy link
Copy Markdown
Member

can you please resolve the conflict @filipnavara? Ill merge it.

@filipnavara

Copy link
Copy Markdown
MemberAuthor

Sure, will do it in few minutes.

suppression changes
@filipnavara

Copy link
Copy Markdown
MemberAuthor

can you please resolve the conflict @filipnavara? Ill merge it.

done

@wfurt
wfurt merged commit 77ad806 into dotnet:mainJun 16, 2023
@filipnavara
filipnavara deleted the negotiatestream-cleanup branch June 16, 2023 10:50
@karelzkarelz added this to the 8.0.0 milestone Jul 3, 2023
@ghostghost locked as resolved and limited conversation to collaborators Aug 2, 2023
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-System.Net.Securitycommunity-contributionIndicates that the PR has been added by a community membernew-api-needs-documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@filipnavara@wfurt@karelz
, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' Reimplement NegotiateStream using (mostly) public NegotiateAuthenticaton API by filipnavara · Pull Request #86948 · dotnet/runtime · GitHub
Skip to content

Reimplement NegotiateStream using (mostly) public NegotiateAuthenticaton API - #86948

Merged
wfurt merged 4 commits into
dotnet:mainfrom
filipnavara:negotiatestream-cleanup
Jun 16, 2023
Merged

Reimplement NegotiateStream using (mostly) public NegotiateAuthenticaton API#86948
wfurt merged 4 commits into
dotnet:mainfrom
filipnavara:negotiatestream-cleanup

Conversation

@filipnavara

Copy link
Copy Markdown
Member

Adds support for tvOS and Android as a side-effect.

@ghostghost added community-contribution Indicates that the PR has been added by a community member area-System.Net.Security new-api-needs-documentation labels May 31, 2023
@ghost

Copy link
Copy Markdown

Note regarding the new-api-needs-documentation label:

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.

@ghost

Copy link
Copy Markdown

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

Issue Details

Adds support for tvOS and Android as a side-effect.

Author:filipnavara
Assignees:-
Labels:

area-System.Net.Security, new-api-needs-documentation, community-contribution

Milestone:-

@filipnavara
filipnavara requested a review from wfurtMay 31, 2023 11:39
Comment on lines -2860 to -2649
<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>

Copy link
Copy Markdown
MemberAuthor

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.

}

private static unsafe int DecryptNtlm(
internal static unsafe void GetMIC(

Copy link
Copy Markdown
Member

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?

Copy link
Copy Markdown
MemberAuthor

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.)

Copy link
Copy Markdown
Member

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

Copy link
Copy Markdown
MemberAuthor

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 Stream contract but may be problematic if someone was using NegotiateStream to implement Negotiate algorithm, 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)];

Copy link
Copy Markdown
Member

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?

Copy link
Copy Markdown
MemberAuthor

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?

Copy link
Copy Markdown
Member

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...

@filipnavarafilipnavaraJun 8, 2023

Copy link
Copy Markdown
MemberAuthor

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.

@wfurtwfurt left a comment

Copy link
Copy Markdown
Member

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.

@filipnavara

Copy link
Copy Markdown
MemberAuthor

I wish we can test against 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.

@wfurt

wfurt commented Jun 8, 2023

Copy link
Copy Markdown
Member

I wish we can test against 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.

@filipnavara

filipnavara commented Jun 8, 2023

Copy link
Copy Markdown
MemberAuthor
Test case

usingSystem;usingSystem.IO.Pipes;usingSystem.Net.Security;usingSystem.Text;classProgram{publicstaticvoidMain(string[]args){if(args.Length==0)return;boolisClient=args[0]=="client";if(isClient){usingvarpipeStream=newNamedPipeClientStream(".","negtest",PipeDirection.InOut,PipeOptions.None);pipeStream.Connect();usingvarnegStream=newNegotiateStream(pipeStream);negStream.AuthenticateAsClient();negStream.Write("hello"u8.ToArray(),0,5);negStream.Flush();}else{usingvarpipeStream=newNamedPipeServerStream("negtest",PipeDirection.InOut);pipeStream.WaitForConnection();usingvarnegStream=newNegotiateStream(pipeStream);negStream.AuthenticateAsServer();byte[]buffer=newbyte[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.

@filipnavara

Copy link
Copy Markdown
MemberAuthor

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.

@wfurtwfurt left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@wfurt

Copy link
Copy Markdown
Member

can you please resolve the conflict @filipnavara? Ill merge it.

@filipnavara

Copy link
Copy Markdown
MemberAuthor

Sure, will do it in few minutes.

suppression changes
@filipnavara

Copy link
Copy Markdown
MemberAuthor

can you please resolve the conflict @filipnavara? Ill merge it.

done

@wfurt
wfurt merged commit 77ad806 into dotnet:mainJun 16, 2023
@filipnavara
filipnavara deleted the negotiatestream-cleanup branch June 16, 2023 10:50
@karelzkarelz added this to the 8.0.0 milestone Jul 3, 2023
@ghostghost locked as resolved and limited conversation to collaborators Aug 2, 2023
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-System.Net.Securitycommunity-contributionIndicates that the PR has been added by a community membernew-api-needs-documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@filipnavara@wfurt@karelz
, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Reimplement NegotiateStream using (mostly) public NegotiateAuthenticaton API by filipnavara · Pull Request #86948 · dotnet/runtime · GitHub
Skip to content

Reimplement NegotiateStream using (mostly) public NegotiateAuthenticaton API - #86948

Merged
wfurt merged 4 commits into
dotnet:mainfrom
filipnavara:negotiatestream-cleanup
Jun 16, 2023
Merged

Reimplement NegotiateStream using (mostly) public NegotiateAuthenticaton API#86948
wfurt merged 4 commits into
dotnet:mainfrom
filipnavara:negotiatestream-cleanup

Conversation

@filipnavara

Copy link
Copy Markdown
Member

Adds support for tvOS and Android as a side-effect.

@ghostghost added community-contribution Indicates that the PR has been added by a community member area-System.Net.Security new-api-needs-documentation labels May 31, 2023
@ghost

Copy link
Copy Markdown

Note regarding the new-api-needs-documentation label:

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.

@ghost

Copy link
Copy Markdown

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

Issue Details

Adds support for tvOS and Android as a side-effect.

Author:filipnavara
Assignees:-
Labels:

area-System.Net.Security, new-api-needs-documentation, community-contribution

Milestone:-

@filipnavara
filipnavara requested a review from wfurtMay 31, 2023 11:39
Comment on lines -2860 to -2649
<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>

Copy link
Copy Markdown
MemberAuthor

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.

}

private static unsafe int DecryptNtlm(
internal static unsafe void GetMIC(

Copy link
Copy Markdown
Member

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?

Copy link
Copy Markdown
MemberAuthor

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.)

Copy link
Copy Markdown
Member

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

Copy link
Copy Markdown
MemberAuthor

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 Stream contract but may be problematic if someone was using NegotiateStream to implement Negotiate algorithm, 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)];

Copy link
Copy Markdown
Member

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?

Copy link
Copy Markdown
MemberAuthor

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?

Copy link
Copy Markdown
Member

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...

@filipnavarafilipnavaraJun 8, 2023

Copy link
Copy Markdown
MemberAuthor

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.

@wfurtwfurt left a comment

Copy link
Copy Markdown
Member

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.

@filipnavara

Copy link
Copy Markdown
MemberAuthor

I wish we can test against 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.

@wfurt

wfurt commented Jun 8, 2023

Copy link
Copy Markdown
Member

I wish we can test against 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.

@filipnavara

filipnavara commented Jun 8, 2023

Copy link
Copy Markdown
MemberAuthor
Test case

usingSystem;usingSystem.IO.Pipes;usingSystem.Net.Security;usingSystem.Text;classProgram{publicstaticvoidMain(string[]args){if(args.Length==0)return;boolisClient=args[0]=="client";if(isClient){usingvarpipeStream=newNamedPipeClientStream(".","negtest",PipeDirection.InOut,PipeOptions.None);pipeStream.Connect();usingvarnegStream=newNegotiateStream(pipeStream);negStream.AuthenticateAsClient();negStream.Write("hello"u8.ToArray(),0,5);negStream.Flush();}else{usingvarpipeStream=newNamedPipeServerStream("negtest",PipeDirection.InOut);pipeStream.WaitForConnection();usingvarnegStream=newNegotiateStream(pipeStream);negStream.AuthenticateAsServer();byte[]buffer=newbyte[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.

@filipnavara

Copy link
Copy Markdown
MemberAuthor

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.

@wfurtwfurt left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@wfurt

Copy link
Copy Markdown
Member

can you please resolve the conflict @filipnavara? Ill merge it.

@filipnavara

Copy link
Copy Markdown
MemberAuthor

Sure, will do it in few minutes.

suppression changes
@filipnavara

Copy link
Copy Markdown
MemberAuthor

can you please resolve the conflict @filipnavara? Ill merge it.

done

@wfurt
wfurt merged commit 77ad806 into dotnet:mainJun 16, 2023
@filipnavara
filipnavara deleted the negotiatestream-cleanup branch June 16, 2023 10:50
@karelzkarelz added this to the 8.0.0 milestone Jul 3, 2023
@ghostghost locked as resolved and limited conversation to collaborators Aug 2, 2023
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-System.Net.Securitycommunity-contributionIndicates that the PR has been added by a community membernew-api-needs-documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@filipnavara@wfurt@karelz
, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Reimplement NegotiateStream using (mostly) public NegotiateAuthenticaton API by filipnavara · Pull Request #86948 · dotnet/runtime · GitHub
Skip to content

Reimplement NegotiateStream using (mostly) public NegotiateAuthenticaton API - #86948

Merged
wfurt merged 4 commits into
dotnet:mainfrom
filipnavara:negotiatestream-cleanup
Jun 16, 2023
Merged

Reimplement NegotiateStream using (mostly) public NegotiateAuthenticaton API#86948
wfurt merged 4 commits into
dotnet:mainfrom
filipnavara:negotiatestream-cleanup

Conversation

@filipnavara

Copy link
Copy Markdown
Member

Adds support for tvOS and Android as a side-effect.

@ghostghost added community-contribution Indicates that the PR has been added by a community member area-System.Net.Security new-api-needs-documentation labels May 31, 2023
@ghost

Copy link
Copy Markdown

Note regarding the new-api-needs-documentation label:

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.

@ghost

Copy link
Copy Markdown

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

Issue Details

Adds support for tvOS and Android as a side-effect.

Author:filipnavara
Assignees:-
Labels:

area-System.Net.Security, new-api-needs-documentation, community-contribution

Milestone:-

@filipnavara
filipnavara requested a review from wfurtMay 31, 2023 11:39
Comment on lines -2860 to -2649
<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>

Copy link
Copy Markdown
MemberAuthor

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.

}

private static unsafe int DecryptNtlm(
internal static unsafe void GetMIC(

Copy link
Copy Markdown
Member

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?

Copy link
Copy Markdown
MemberAuthor

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.)

Copy link
Copy Markdown
Member

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

Copy link
Copy Markdown
MemberAuthor

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 Stream contract but may be problematic if someone was using NegotiateStream to implement Negotiate algorithm, 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)];

Copy link
Copy Markdown
Member

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?

Copy link
Copy Markdown
MemberAuthor

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?

Copy link
Copy Markdown
Member

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...

@filipnavarafilipnavaraJun 8, 2023

Copy link
Copy Markdown
MemberAuthor

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.

@wfurtwfurt left a comment

Copy link
Copy Markdown
Member

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.

@filipnavara

Copy link
Copy Markdown
MemberAuthor

I wish we can test against 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.

@wfurt

wfurt commented Jun 8, 2023

Copy link
Copy Markdown
Member

I wish we can test against 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.

@filipnavara

filipnavara commented Jun 8, 2023

Copy link
Copy Markdown
MemberAuthor
Test case

usingSystem;usingSystem.IO.Pipes;usingSystem.Net.Security;usingSystem.Text;classProgram{publicstaticvoidMain(string[]args){if(args.Length==0)return;boolisClient=args[0]=="client";if(isClient){usingvarpipeStream=newNamedPipeClientStream(".","negtest",PipeDirection.InOut,PipeOptions.None);pipeStream.Connect();usingvarnegStream=newNegotiateStream(pipeStream);negStream.AuthenticateAsClient();negStream.Write("hello"u8.ToArray(),0,5);negStream.Flush();}else{usingvarpipeStream=newNamedPipeServerStream("negtest",PipeDirection.InOut);pipeStream.WaitForConnection();usingvarnegStream=newNegotiateStream(pipeStream);negStream.AuthenticateAsServer();byte[]buffer=newbyte[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.

@filipnavara

Copy link
Copy Markdown
MemberAuthor

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.

@wfurtwfurt left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@wfurt

Copy link
Copy Markdown
Member

can you please resolve the conflict @filipnavara? Ill merge it.

@filipnavara

Copy link
Copy Markdown
MemberAuthor

Sure, will do it in few minutes.

suppression changes
@filipnavara

Copy link
Copy Markdown
MemberAuthor

can you please resolve the conflict @filipnavara? Ill merge it.

done

@wfurt
wfurt merged commit 77ad806 into dotnet:mainJun 16, 2023
@filipnavara
filipnavara deleted the negotiatestream-cleanup branch June 16, 2023 10:50
@karelzkarelz added this to the 8.0.0 milestone Jul 3, 2023
@ghostghost locked as resolved and limited conversation to collaborators Aug 2, 2023
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-System.Net.Securitycommunity-contributionIndicates that the PR has been added by a community membernew-api-needs-documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@filipnavara@wfurt@karelz
, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })(); Reimplement NegotiateStream using (mostly) public NegotiateAuthenticaton API by filipnavara · Pull Request #86948 · dotnet/runtime · GitHub
Skip to content

Reimplement NegotiateStream using (mostly) public NegotiateAuthenticaton API - #86948

Merged
wfurt merged 4 commits into
dotnet:mainfrom
filipnavara:negotiatestream-cleanup
Jun 16, 2023
Merged

Reimplement NegotiateStream using (mostly) public NegotiateAuthenticaton API#86948
wfurt merged 4 commits into
dotnet:mainfrom
filipnavara:negotiatestream-cleanup

Conversation

@filipnavara

Copy link
Copy Markdown
Member

Adds support for tvOS and Android as a side-effect.

@ghostghost added community-contribution Indicates that the PR has been added by a community member area-System.Net.Security new-api-needs-documentation labels May 31, 2023
@ghost

Copy link
Copy Markdown

Note regarding the new-api-needs-documentation label:

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.

@ghost

Copy link
Copy Markdown

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

Issue Details

Adds support for tvOS and Android as a side-effect.

Author:filipnavara
Assignees:-
Labels:

area-System.Net.Security, new-api-needs-documentation, community-contribution

Milestone:-

@filipnavara
filipnavara requested a review from wfurtMay 31, 2023 11:39
Comment on lines -2860 to -2649
<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>

Copy link
Copy Markdown
MemberAuthor

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.

}

private static unsafe int DecryptNtlm(
internal static unsafe void GetMIC(

Copy link
Copy Markdown
Member

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?

Copy link
Copy Markdown
MemberAuthor

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.)

Copy link
Copy Markdown
Member

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

Copy link
Copy Markdown
MemberAuthor

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 Stream contract but may be problematic if someone was using NegotiateStream to implement Negotiate algorithm, 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)];

Copy link
Copy Markdown
Member

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?

Copy link
Copy Markdown
MemberAuthor

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?

Copy link
Copy Markdown
Member

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...

@filipnavarafilipnavaraJun 8, 2023

Copy link
Copy Markdown
MemberAuthor

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.

@wfurtwfurt left a comment

Copy link
Copy Markdown
Member

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.

@filipnavara

Copy link
Copy Markdown
MemberAuthor

I wish we can test against 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.

@wfurt

wfurt commented Jun 8, 2023

Copy link
Copy Markdown
Member

I wish we can test against 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.

@filipnavara

filipnavara commented Jun 8, 2023

Copy link
Copy Markdown
MemberAuthor
Test case

usingSystem;usingSystem.IO.Pipes;usingSystem.Net.Security;usingSystem.Text;classProgram{publicstaticvoidMain(string[]args){if(args.Length==0)return;boolisClient=args[0]=="client";if(isClient){usingvarpipeStream=newNamedPipeClientStream(".","negtest",PipeDirection.InOut,PipeOptions.None);pipeStream.Connect();usingvarnegStream=newNegotiateStream(pipeStream);negStream.AuthenticateAsClient();negStream.Write("hello"u8.ToArray(),0,5);negStream.Flush();}else{usingvarpipeStream=newNamedPipeServerStream("negtest",PipeDirection.InOut);pipeStream.WaitForConnection();usingvarnegStream=newNegotiateStream(pipeStream);negStream.AuthenticateAsServer();byte[]buffer=newbyte[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.

@filipnavara

Copy link
Copy Markdown
MemberAuthor

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.

@wfurtwfurt left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@wfurt

Copy link
Copy Markdown
Member

can you please resolve the conflict @filipnavara? Ill merge it.

@filipnavara

Copy link
Copy Markdown
MemberAuthor

Sure, will do it in few minutes.

suppression changes
@filipnavara

Copy link
Copy Markdown
MemberAuthor

can you please resolve the conflict @filipnavara? Ill merge it.

done

@wfurt
wfurt merged commit 77ad806 into dotnet:mainJun 16, 2023
@filipnavara
filipnavara deleted the negotiatestream-cleanup branch June 16, 2023 10:50
@karelzkarelz added this to the 8.0.0 milestone Jul 3, 2023
@ghostghost locked as resolved and limited conversation to collaborators Aug 2, 2023
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-System.Net.Securitycommunity-contributionIndicates that the PR has been added by a community membernew-api-needs-documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@filipnavara@wfurt@karelz