Recently, I was troubleshooting a problem for one of my customers. A named pipe created by a native C application was not accessible by web client. The actual product is a convention Windows application which does IPC through named pipes. Both server and client for this were Windows applications. They were trying to extend the functionality so that a Web application written in C# ASP.NET can communicate with the server over the named pipe.
Everything was fine until they deployed the web application. Web application if running on development box was able to communicate with the named pipe, however once deployed it started getting access denied on the named pipe. On a contrary windows application was able to communicate with the Named Pipe.
Following is the code of the native server, C# client and web application in order.
The code looks good, however to resolve this problem you would need to know a little about web applications. I am not much familiar with web application but here are few basic things which I know.
- - A web application is hosted in IIS under a process called W3WP.EXE this process runs under the context of Network Service account.
- - Web applications typically have a thread pool. They may or may not share the process access token depending on the authentication mechanism used for the web application.
- - Web applications are non-interactive in nature. However, this thing is not related
- To resolve an access denied typically you would need to know –
- - Who is caller asking for the access ? Typically, a thread token determines the caller.
- - What are the access caller asked? The access mask provide in the API determines this. For example READ or WRITE or FULL CONTROL
- - What are the security permissions present on the object ? DACL of the objects determines this.
Let’s try resolving this problem answering above questions
- Who is the caller ?
- o Since W3WP.EXE runs in the context of Network Service. Network Service could be a caller.
- o If the thread pool for the web application has got a different identity due to the impersonation of the user running the web application. He will act as caller.
- o Easy way to determine this is look at the ASP.NET code and find what kind of authentication and impersonation web application is using.
- o Other way would be to attach a debugger to W3WP and break on access of the named pipe, then dump the thread token. This method is guaranteed to give you right information. However, it needs a debugger on the problem machine, which may be a production machine and people usually do not encourage debugger on the production server.
- What is the access asked ?
- o You can look at the code to determine this. For bidirectional named pipe it is most likely be GENERIC_READ and GENERIC_WRITE.
- o You can break in debugger to find this. An access denied call stack typically would tell you this mask.
- o A Process Monitor log for the process (W3WP.EXE in this case)
- - What are the security permissions on the object.
- o The above code of creation of the Named Pipe tells us that it has default security permissions. Default DACL is determine by the container object or by the access token of the creator. See The Old New Thing : What is the default security descriptor? for more information.
- o You can also dump the DACLs of the object to ensure that you know exact access permissions on the object. I have user SubInAcl tool to dump the security descriptor.
I dumped access permissions on the named pipe created on my machine by a Windows application. Default access permission of the Named Pipe on my machine look like following.
The above security descriptors potentially tell me following :
- Administrators can ask for full control.
- I as the creator can ask for full control.
- Everyone and Anonymous can ask for read control.
In a typical scenario a Named Pipe server runs as a Windows Service, which would most likely be running in Local System or an Administrator’s context. However, a web application would not run with the same token as Windows service. They would present a much lower access token to the Named Pipe to access it. In this case, token of Network Service, a domain user, everyone and anonymous.
From the above assessment it is most likely that web application is getting access denied because the DACL set on the Name Pipe is not appropriate to the design of the project. My customer wanted to provide full control to the Everyone and Anonymous and that made my job easy. Which is appropriate for a duplex pipe with only read access client will not be able to write. I changed the server code as following :
Following addition creates a security descriptor which grants full control to Everyone and to the Anonymous.
The changed security descriptor is presented as following.
Now when the security descriptor has right access permissions the problem got resolved. Web application was able to access the named pipe.
This blog is not complete yet, there are few questions unanswered
- Why there was not access failure for the web application on the development machine ?
- Why not the Windows client did get the access failure.
Here is the explanation:
1) Visual Studio provides a special mechanism to run the web applications on development machines, see: Web Servers in Visual Web Developer. This process however runs in the context of logged in user, not in context of Network Service.
2) Similar to WebDev.WebServer.Exe a windows application would also run in the context of the logged in user’s context and it is less likely to get an access denied.
This post is not intend to resolve all access denied issues on a named pipe, it is just intended to brief you an approach you can use to resolve the problem.