Dealing with OS privilege 'issues' in WCF Named Pipes scenarios


For whom this ever may be useful - I fighted a long time against this... (and got support from the WCF team, BTW)

We have this very vast .NET 3.x end-to-end sample application which covers nearly all of the (senseful :)) features in the .NET Framework. Part of this application scenario is an upload feature where users can upload media files through a common ASP.NET frontend to the web server which then in turn talks to a WCF service that is implemented by a WF state machine workflow. The communication between the ASP.NET app on the server and the WCF Upload Service is via a Named Pipes channel (netNamedPipeBinding).

Recently I ran into a problem which only occured after I moved over to Windows Vista (from XP SP2). And of course, as a lot of us (... yeah, I can hear Dominick yelling at me ...) I was always working as an admin on XP and so my primary account on Vista is also an admin account. Obviously, being an admin on Vista is very different from being an admin on XP if you have UAC (User Account Control) enabled - and you *should* have it enabled, but this is maybe worth another blog entry. When running as an admin on Vista with UAC turned on all processes are by default not running elavated and therefore do not have all the privileges the exact same admin has on an XP SP2 box.

For testing and demonstration purposes I have created a console host application for the WCF-based Upload Service. I start this console EXE and my WCF service starts successfully stating that the NP endpoint has been setup. If I run my test console client against this service everything works as expected. Please note that all processes involved until now are executed non-elevated.
As many others, I started developing and testing the Upload web app in Cassini (aka 'ASP.NET Development Server', WebDev.WebServer.exe). Everything was working like a charm :)
Problems started to occur when I switched over the ASP.NET client application from Cassini (yes - I can hear Dominick yell again) to running in IIS 7. The WCF Upload Service is still the same one, actually the process is still running. When hitting the UploadWeb with the browser and submitting data the ASP.NET app on the server side then tries to talk to the NP endpoint of my WCF service - but: bang!!!

Exception: The pipe endpoint 'net.pipe://localhost/tecTeacher/UploadService' could not be found on your local machine

The pipe endpoint 'net.pipe://localhost/tecTeacher/UploadService' could not be found on your local machine.


Hm, what's up here?
The client app (i.e. ASP.NET) doesn't seem to 'see' the Named Pipe... ASP.NET is running in IIS which is running in a Windows Service, namely w3wp.exe. Services in Vista and Windows Server 2008 run in Session0. My ConsoleHost is not running in Session0 but rather in Session1 (you can verify this by using Task Manager and adding the 'Session ID' column to the view). Usually, WCF's Named Pipe support tries to create the pipe in the Global namespace.
If my WCF server process using a Named Pipe-based endpoint doesn't have privileges to create a Global kernel object it silently fails and creates a local one which will not be visible to processes outside of its session. My ConsoleHost app has been started with common privileges, not elevated and therefore cannot create objects in the Global kernel object namespace.  This explains the problem that ASP.NET running in IIS sitting inside a Windows Service cannot see the Named Pipe offered by the console EXE.

What can we do to fix this?
 a) Run your WCF service inside a Windows Service (which you should do anyway, and not inside a Console)
 b) Host your WCF service inside of WAS/IIS (only on Vista and Server 2008) - but be sure to know about the limitations of this approach
 c) Run the Console host application elevated (for demo and testing purposes only)

Some more technical explanations can be found in an MSDN article talking about Kernel Objects Namespaces, I am just providing an excerpt which talks about the actual problem:
Starting with Windows Server 2003, Windows XP SP2, and Windows 2000 Server SP4, the creation of a file-mapping object in the global namespace (by using CreateFileMapping) from a session other than session zero is a privileged operation. Because of this, an application running in an arbitrary [...] session must have SeCreateGlobalPrivilege enabled in order to create a file-mapping object in the global namespace successfully. Note that the privilege check is limited to the creation of file-mapping objects, and does not apply to opening existing ones. For example, if a service or the system creates a file-mapping object, any process running in any session can access that file-mapping object provided that the user has the necessary access.
Lessons learned.