Friday, February 22, 2008

Setting NULL DACL for NamedPipe

When using NamedPipe, security access is major concern. By default, the created NamedPipe can be accessed only by the administrator accounts. But what if you application requires it be to accessed by a client application run in a "Limited User" account ??

This is where you need to set the security attributes. The security attributes can be set using the last parameter of CreateNamedPipe API call.

Easiest ( yet not-recommended) way of giving access to Limited User Account is setting the security Attribute using a Null DACL. ( Discretionary Access Control List ).

[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr CreateNamedPipe(
String pipeName,
uint dwOpenMode,
uint dwPipeMode,
uint nMaxInstances,
uint nOutBufferSize,
uint nInBufferSize,
uint nDefaultTimeOut,
IntPtr lpSecurityAttributes);

Point To Note : Remember, setting a NULL value to lpSecurityAttributes and setting a NULL Dacl for it is two entirely different thing. If you set a Null Value for lpSecurityAttributes , it would be mean that the pipe would be having default security privileges set by the operating system.
But when you set the value as NULL Dacl, you are saying to the operating system that the pipe can be accessed by all users in the system, ie , giving Full-Control to "Everyone" user group.

So how do you set the Null Dacl for
lpSecurityAttributes ? here is a bit of code for the same


SECURITY_DESCRIPTOR sd = new SECURITY_DESCRIPTOR();
InitializeSecurityDescriptor(ref sd, SECURITY_DESCRIPTOR_REVISION);
SetSecurityDescriptorDacl(ref sd, true,IntPtr.Zero , false);
SECURITY_ATTRIBUTES sa = new SECURITY_ATTRIBUTES();
sa.nLength = Marshal.SizeOf(typeof(SECURITY_ATTRIBUTES));

IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(sd));
Marshal.StructureToPtr(sd, ptr,true);
sa.lpSecurityDescriptor = ptr;

IntPtr retPtr = Marshal.AllocHGlobal(Marshal.SizeOf(sa));
Marshal.StructureToPtr(sa,retPtr,true);

PipeHandle = CommonFunctions.CreateNamedPipe(
PIPE_NAME,
PIPE_ACCESS_DUPLEX ,
PIPE_TYPE_MESSAGE |
PIPE_READMODE_MESSAGE |
PIPE_WAIT,
PIPE_UNLIMITED_INSTANCES,
(uint)BUFFER_SIZE,
(uint)BUFFER_SIZE,
0,
retPtr);