Skip to content

Commit 16e263a

Browse files
authored
support WindowsPrincipal in HttpListenerWebSocketContext (#65746)
* support WindowsPrincipal in HttpListenerWebSocketContext * user Identity is known as instance of WindowsIdentity * use TARGET_WINDOWS preprocessor
1 parent 8255f56 commit 16e263a

File tree

4 files changed

+51
-3
lines changed

4 files changed

+51
-3
lines changed

src/libraries/System.Net.HttpListener/src/System.Net.HttpListener.csproj

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<Project Sdk="Microsoft.NET.Sdk">
1+
<Project Sdk="Microsoft.NET.Sdk">
22
<PropertyGroup>
33
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
44
<ForceManagedImplementation>false</ForceManagedImplementation>
@@ -9,6 +9,7 @@
99
<PropertyGroup>
1010
<TargetPlatformIdentifier>$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)'))</TargetPlatformIdentifier>
1111
<GeneratePlatformNotSupportedAssemblyMessage Condition="'$(TargetPlatformIdentifier)' == ''">SR.SystemNetHttpListener_PlatformNotSupported</GeneratePlatformNotSupportedAssemblyMessage>
12+
<DefineConstants Condition="'$(TargetPlatformIdentifier)' == 'windows'">$(DefineConstants);TARGET_WINDOWS</DefineConstants>
1213
</PropertyGroup>
1314
<ItemGroup>
1415
<ProjectReference Include="$(LibrariesProjectRoot)System.Security.Principal.Windows\src\System.Security.Principal.Windows.csproj" />

src/libraries/System.Net.HttpListener/src/System/Net/WebSockets/HttpListenerWebSocketContext.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,13 @@ internal HttpListenerWebSocketContext(
101101
else
102102
{
103103
// AuthenticationSchemes.Digest, AuthenticationSchemes.Negotiate, AuthenticationSchemes.NTLM.
104+
#if TARGET_WINDOWS
105+
WindowsIdentity windowsIdentity = (WindowsIdentity)user.Identity!;
106+
return new WindowsPrincipal(new WindowsIdentity(windowsIdentity.Token, windowsIdentity.AuthenticationType!, WindowsAccountType.Normal, true));
107+
#else
104108
throw new PlatformNotSupportedException();
109+
#endif
110+
105111
}
106112
}
107113

src/libraries/System.Net.HttpListener/tests/HttpListenerFactory.cs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
using System.Collections.Generic;
55
using System.Linq;
66
using System.Net.Sockets;
7-
using System.Runtime.InteropServices;
87
using System.Text;
98

109
namespace System.Net.Tests
@@ -24,7 +23,7 @@ public class HttpListenerFactory : IDisposable
2423
private readonly string _path;
2524
private readonly int _port;
2625

27-
internal HttpListenerFactory(string hostname = "localhost", string path = null)
26+
internal HttpListenerFactory(string hostname = "localhost", string path = null, AuthenticationSchemes? authenticationSchemes = null)
2827
{
2928
// Find a URL prefix that is not in use on this machine *and* uses a port that's not in use.
3029
// Once we find this prefix, keep a listener on it for the duration of the process, so other processes
@@ -42,6 +41,12 @@ internal HttpListenerFactory(string hostname = "localhost", string path = null)
4241
try
4342
{
4443
listener.Prefixes.Add(prefix);
44+
45+
if (authenticationSchemes != null)
46+
{
47+
listener.AuthenticationSchemes = authenticationSchemes.Value;
48+
}
49+
4550
listener.Start();
4651

4752
_processPrefixListener = listener;

src/libraries/System.Net.HttpListener/tests/HttpListenerWebSocketTests.cs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ public class HttpListenerWebSocketTests : IDisposable
1616
{
1717
public static bool IsNotWindows7 { get; } = !PlatformDetection.IsWindows7;
1818
public static bool IsNotWindows7AndIsWindowsImplementation => IsNotWindows7 && Helpers.IsWindowsImplementation;
19+
public static bool IsWindows8OrLater { get; } = PlatformDetection.IsWindows8xOrLater;
1920

2021
private HttpListenerFactory Factory { get; }
2122
private HttpListener Listener { get; }
@@ -363,6 +364,41 @@ public async Task Abort_CallAfterAborted_Nop()
363364
Assert.Equal(WebSocketState.Aborted, context.WebSocket.State);
364365
}
365366

367+
[ConditionalFact(nameof(IsWindows8OrLater))]
368+
public async Task ReceiveAsync_ReadBuffer_WithWindowsAuthScheme_Success()
369+
{
370+
HttpListenerFactory factory = new HttpListenerFactory(authenticationSchemes: AuthenticationSchemes.IntegratedWindowsAuthentication);
371+
var uriBuilder = new UriBuilder(factory.ListeningUrl) { Scheme = "ws" };
372+
Task<HttpListenerContext> serverContextTask = factory.GetListener().GetContextAsync();
373+
ClientWebSocket client = new ClientWebSocket();
374+
client.Options.Credentials = CredentialCache.DefaultCredentials;
375+
376+
Task clientConnectTask = client.ConnectAsync(uriBuilder.Uri, CancellationToken.None);
377+
if (clientConnectTask == await Task.WhenAny(serverContextTask, clientConnectTask))
378+
{
379+
await clientConnectTask;
380+
Assert.True(false, "Client should not have completed prior to server sending response");
381+
}
382+
383+
HttpListenerContext context = await serverContextTask;
384+
HttpListenerWebSocketContext wsContext = await context.AcceptWebSocketAsync(null);
385+
await clientConnectTask;
386+
387+
const string Text = "Hello Web Socket";
388+
byte[] sentBytes = Encoding.ASCII.GetBytes(Text);
389+
390+
await client.SendAsync(new ArraySegment<byte>(sentBytes), WebSocketMessageType.Text, true, new CancellationToken());
391+
392+
byte[] receivedBytes = new byte[sentBytes.Length];
393+
WebSocketReceiveResult result = await ReceiveAllAsync(wsContext.WebSocket, receivedBytes.Length, receivedBytes);
394+
Assert.Equal(WebSocketMessageType.Text, result.MessageType);
395+
Assert.True(result.EndOfMessage);
396+
Assert.Null(result.CloseStatus);
397+
Assert.Null(result.CloseStatusDescription);
398+
399+
Assert.Equal(Text, Encoding.ASCII.GetString(receivedBytes));
400+
}
401+
366402
private static async Task<WebSocketReceiveResult> ReceiveAllAsync(WebSocket webSocket, int expectedBytes, byte[] buffer)
367403
{
368404
int totalReceived = 0;

0 commit comments

Comments
 (0)