问题
I have created a named pipe using System.IO.Pipes
. It worked fine until I had to run the program in admin mode. When elevated, the client can no longer connect (client is not running elevated). If I run the client as administrator, it connects fine so it looks like a permissions issue. I've been researching how to fix this and have been unsuccessful (I find dealing with Windows security mind boggling). My goal is to allow any client - whether elevated or not - to be able to connect to the pipe.
The first thing I changed was opening the pipe with access rights:
pipeServer = new NamedPipeServerStream(pipeName,
PipeDirection.InOut,
1,
PipeTransmissionMode.Message,
PipeOptions.Asynchronous,
0x4000,
0x400,
null,
HandleInheritability.Inheritable,
PipeAccessRights.ChangePermissions | PipeAccessRights.AccessSystemSecurity);
Then I cobbled this code together. Everything works until the SetEntriesInAcl
call which fails with:
Error: 0x534
"No mapping between account names and security IDs was done."
IntPtr ownerSid = IntPtr.Zero;
IntPtr groupSid = IntPtr.Zero;
IntPtr dacl = IntPtr.Zero, newDacl = IntPtr.Zero;
IntPtr sacl = IntPtr.Zero;
IntPtr securityDescriptor = IntPtr.Zero;
if (SUCCEEDED(GetSecurityInfo(pipeServer.SafePipeHandle.handle.DangerousGetHandle(),
SE_OBJECT_TYPE.SE_KERNEL_OBJECT,
SECURITY_INFORMATION.DACL_SECURITY_INFORMATION,
out ownerSid,
out groupSid,
out dacl,
out sacl,
out securityDescriptor))) {
EXPLICIT_ACCESS ea = new EXPLICIT_ACCESS();
BuildExplicitAccessWithName(ref ea, "Everyone", GENERIC_ALL, ACCESS_MODE.GRANT_ACCESS, NO_INHERITANCE);
// Next line fails
if (SUCCEEDED(SetEntriesInAcl(1, ref ea, dacl, out newDacl))) {
uint retval = SetSecurityInfo(handle,
SE_OBJECT_TYPE.SE_KERNEL_OBJECT,
SECURITY_INFORMATION.DACL_SECURITY_INFORMATION,
IntPtr.Zero,
IntPtr.Zero,
newDacl,
IntPtr.Zero);
// Haven't reached this point yet
}
}
The BuildExplicitAccessWithName
function does not return a value but seems to succeed ok. This is what it looks like after the call:
I would appreciate any help here.
(All the Win32 functions and data types were found on pinvoke.net. Also, I'm using Windows 10.)
回答1:
I ended up not having to use any native calls. The PipeSecurity class worked. The trick was I had to pass it to the constructor:
// Creates a PipeSecurity that allows users read/write access
PipeSecurity CreateSystemIOPipeSecurity()
{
PipeSecurity pipeSecurity = new PipeSecurity();
var id = new SecurityIdentifier(WellKnownSidType.AuthenticatedUserSid, null);
// Allow Everyone read and write access to the pipe.
pipeSecurity.SetAccessRule(new PipeAccessRule(id, PipeAccessRights.ReadWrite, AccessControlType.Allow));
return pipeSecurity;
}
Use that function when creating the pipe:
PipeSecurity pipeSecurity = CreateSystemIOPipeSecurity();
pipeServer = new NamedPipeServerStream(pipeName,
PipeDirection.InOut,
1,
PipeTransmissionMode.Message,
PipeOptions.Asynchronous,
0x4000,
0x400,
pipeSecurity,
HandleInheritability.Inheritable);
来源:https://stackoverflow.com/questions/51546328/change-named-pipe-access-permissions