Bug 17965 - Calling Thread.CurrentPrincipal blindly with the User from an HttpListenerContext can throw a NullReferenceException
Summary: Calling Thread.CurrentPrincipal blindly with the User from an HttpListenerCon...
Status: NEW
Alias: None
Product: Class Libraries
Classification: Mono
Component: System.Web (show other bugs)
Version: 3.2.x
Hardware: PC Windows
: --- normal
Target Milestone: Untriaged
Assignee: Bugzilla
URL:
Depends on:
Blocks:
 
Reported: 2014-02-24 09:35 UTC by Arne Ruhnau
Modified: 2014-02-27 12:07 UTC (History)
1 user (show)

Tags:
Is this bug a regression?: ---
Last known good build:

Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.


Please create a new report for Bug 17965 on GitHub or Developer Community if you have new information to add and do not yet see a matching new report.

If the latest results still closely match this report, you can use the original description:

  • Export the original title and description: GitHub Markdown or Developer Community HTML
  • Copy the title and description into the new report. Adjust them to be up-to-date if needed.
  • Add your new information.

In special cases on GitHub you might also want the comments: GitHub Markdown with public comments

Related Links:
Status:
NEW

Description Arne Ruhnau 2014-02-24 09:35:39 UTC
I'm currently looking into using OWIN to host a WebAPI based on the HttpListener.
I've installed various Nuget packages from the Microsoft.Owin - family:
<packages>
  <package id="Microsoft.AspNet.WebApi.Client" version="5.1.1" targetFramework="net45" />
  <package id="Microsoft.AspNet.WebApi.Core" version="5.1.1" targetFramework="net45" />
  <package id="Microsoft.AspNet.WebApi.Owin" version="5.1.1" targetFramework="net45" />
  <package id="Microsoft.Owin" version="3.0.0-alpha1" targetFramework="net45" />
  <package id="Microsoft.Owin.Host.HttpListener" version="3.0.0-alpha1" targetFramework="net45" />
  <package id="Microsoft.Owin.Hosting" version="3.0.0-alpha1" targetFramework="net45" />
  <package id="Microsoft.Owin.Security" version="3.0.0-alpha1" targetFramework="net45" />
  <package id="Owin" version="1.0" targetFramework="net45" />
</packages>
(other packages omitted)

When I register my webapi controller, the first request to it returns a 500, and all subsequent requests show

{"Message":"An error has occurred.","ExceptionMessage":"Object reference not set to an instance of an object","ExceptionType":"System.NullReferenceException","StackTrace":"  at System.Net.Http.DelegatingHandler.SendAsync (System.Net.Http.HttpRequestMessage request, CancellationToken cancellationToken) [0x00000] in C:\\cygwin\\sources\\mono\\mcs\\class\\System.Net.Http\\System.Net.Http\\DelegatingHandler.cs:64 \r\n  at System.Web.Http.HttpServer.<>n__FabricatedMethod9 (System.Net.Http.HttpRequestMessage , CancellationToken ) [0x00000] in <filename unknown>:0 \r\n  at System.Web.Http.HttpServer+<SendAsync>d__0.MoveNext () [0x00000] in <filename unknown>:0 "}

I tried to track the root cause down using mono --debug --trace=E:System.NullReferenceException

This shows, upon issueing the request targeting my controller class,

----- 8< ---------------
[00001138:] EXCEPTION handling: System.NullReferenceException: Object reference not set to an instance of an object

"Threadpool worker"  at System.Threading.Thread.SerializePrincipal (System.Threading.Thread,System.Security.Principal.IPrincipal) [0x00008] in C:\cygwin\sources\mono\mcs\class\corlib\System.Threading\
Thread.cs:223
  at System.Threading.Thread.set_CurrentPrincipal (System.Security.Principal.IPrincipal) [0x00029] in C:\cygwin\sources\mono\mcs\class\corlib\System.Threading\Thread.cs:292
  at Microsoft.Owin.Host.HttpListener.RequestProcessing.OwinHttpListenerContext.SetServerUser (System.Security.Principal.IPrincipal) <IL 0x0000d, 0x0003b>
  at Microsoft.Owin.Host.HttpListener.RequestProcessing.OwinHttpListenerContext..ctor (System.Net.HttpListenerContext,string,string,string,Microsoft.Owin.Host.HttpListener.DisconnectHandler) <IL 0x000
68, 0x00187>
  at Microsoft.Owin.Host.HttpListener.OwinHttpListener/<ProcessRequestAsync>d__5.MoveNext () <IL 0x00081, 0x0014b>
  at System.Runtime.CompilerServices.AsyncTaskMethodBuilder.Start<Microsoft.Owin.Host.HttpListener.OwinHttpListener/<ProcessRequestAsync>d__5> (Microsoft.Owin.Host.HttpListener.OwinHttpListener/<Proce
ssRequestAsync>d__5&) [0x0001b] in C:\cygwin\sources\mono\mcs\class\corlib\System.Runtime.CompilerServices\AsyncTaskMethodBuilder.cs:112
  at Microsoft.Owin.Host.HttpListener.OwinHttpListener.ProcessRequestAsync (System.Net.HttpListenerContext) <IL 0x00030, 0x00107>
  at Microsoft.Owin.Host.HttpListener.OwinHttpListener/<ProcessRequestsAsync>d__0.MoveNext () <IL 0x0017d, 0x003bb>
  at (wrapper unbox) Microsoft.Owin.Host.HttpListener.OwinHttpListener/<ProcessRequestsAsync>d__0.MoveNext () <IL 0x0000a, 0xffffffff>
  at System.Threading.Tasks.ActionContinuation.Execute () [0x00000] in C:\cygwin\sources\mono\mcs\class\corlib\System.Threading.Tasks\TaskContinuation.cs:124
  at System.Threading.Tasks.Task.ProcessCompleteDelegates () [0x00015] in C:\cygwin\sources\mono\mcs\class\corlib\System.Threading.Tasks\Task.cs:556
  at System.Threading.Tasks.Task.Finish () [0x000ce] in C:\cygwin\sources\mono\mcs\class\corlib\System.Threading.Tasks\Task.cs:539
  at System.Threading.Tasks.Task`1.TrySetResult (TResult) [0x00051] in C:\cygwin\sources\mono\mcs\class\corlib\System.Threading.Tasks\Task_T.cs:228
  at System.Threading.Tasks.TaskCompletionSource`1.TrySetResult (TResult) [0x00000] in C:\cygwin\sources\mono\mcs\class\corlib\System.Threading.Tasks\TaskCompletionSource.cs:121
  at System.Threading.Tasks.TaskCompletionSource`1.SetResult (TResult) [0x00000] in C:\cygwin\sources\mono\mcs\class\corlib\System.Threading.Tasks\TaskCompletionSource.cs:85
  at System.Threading.Tasks.TaskFactory`1.InnerInvoke (System.Threading.Tasks.TaskCompletionSource`1<TResult>,System.Func`2<System.IAsyncResult, TResult>,System.IAsyncResult) [0x00000] in C:\cygwin\so
urces\mono\mcs\class\corlib\System.Threading.Tasks\TaskFactory_T.cs:473
  at System.Threading.Tasks.TaskFactory`1/<FromAsyncBeginEnd>c__AnonStorey3E.<>m__32 (System.IAsyncResult) [0x00010] in C:\cygwin\sources\mono\mcs\class\corlib\System.Threading.Tasks\TaskFactory_T.cs:
345
  at System.Net.ListenerAsyncResult.InvokeCallback (object) [0x0001e] in C:\cygwin\sources\mono\mcs\class\System\System.Net\ListenerAsyncResult.cs:82
  at (wrapper runtime-invoke) <Module>.runtime_invoke_void__this___object (object,intptr,intptr,intptr) <IL 0x00052, 0xffffffff>
----- >8 ---------------

I looked through the source code of the packages involved in this call stack to find that:
- HttpListenerContext.User can be null, which is what's documented on MSDN as well, in case of authentication-less requests
- The OwinHttpListenerContext passes the HttpListenerContext.User to become the principal of the current thread
(https://katanaproject.codeplex.com/SourceControl/latest#src/Microsoft.Owin.Host.HttpListener/RequestProcessing/OwinHttpListenerContext.cs)
- The System.Threading.Thread.CurrentPrincipal property passes this null into the SerializePrincipal function, where the .GetType() method invocation throws.
(https://github.com/mono/mono/blob/master/mcs/class/corlib/System.Threading/Thread.cs#L294 ff)

I let the same program run on the Microsoft CLR and it works correctly, so I assume this is bug of the Mono part of the equation.
Comment 1 Arne Ruhnau 2014-02-27 04:03:42 UTC
I can work around this specific issue by using a custom build of the Microsoft.Owin.Host.HttpListener project, using a 

new GenericPrincipal(new GenericIdentity(String.Empty), new string[0])

as the anonymous identity instead of null. I "stole" this from the System.Web.Http.HttpServer class in the aspnetwebstack.

Using WebAPI in the OWIN pipeline still throws a NullReferenceException in the SendAsync of the System.Net.Http.DelegatingHandler - for every request - , but this is another problem.