The platform extension package System.IO.AccessControl package does not work as intended. This package only supports Windows and was created with the intention of providing the functionality that was removed from System.IO.Pipes related to ACLs, that are not part of .NET Standard 2.0. However, as discussed in https://github.com/dotnet/corefx/issues/30170 this does not work because the proper access right flags need to be specified at construction time, and the constructors are not available either at CoreFx or .NET Standard 2.0.
If we want this package to offer functionality to match .NET Fx we need to add factory methods to make the package functional. OTOH if we can consider that the main usage is already covered by CurrentUserOnly
that is being added to .NET Standard vNext (the next one after 2.0). In this case we likely should retire or convert this package to PNSE.
/cc @safern @danmosemsft
I have a use case which requires more than just CurrentUserOnly
. I have a program split into a local front end and local back end. The program uses named pipes for its IPC.
The problem is that the back end (which is a service) needs to run as an elevated user (i.e. Local System) but the front end only needs to run as the currently logged in user. So, I need some way to set access control to allow non-elevated clients to access the back end.
I have been using .NET Framework up until now for this project, but I'm trying to port bits and pieces of it to .NET Standard in order to make the project cross-platform.
What I know to do is create a .NET Framework project that abstracts the Windows implementation details away from the common functionality. Is there any other workaround that doesn't involve .NET Full?
Hi @kfreezen - just for me to better understand your usage: can you share the sources that you create the server and client on the full framework? Do you somehow restricts the clients?
@pjanotti
The PipeSecurity
instance is being created by https://github.com/cloudveiltech/Filter-Windows/blob/d159989ed0385d5609372cbf690c23d43e51acec/Citadel.IPC.Common/IPC/IPCServer.cs#L679
That is being consumed by https://github.com/cloudveiltech/Filter-Windows/blob/d159989ed0385d5609372cbf690c23d43e51acec/Citadel.IPC.Common/IPC/IPCServer.cs#L288
@kfreezen Did you find a solution for this? I'm trying to do the same but don't get any further than the UnauthorizedAccessException
, too.
```C#
_pipeStream = new NamedPipeServerStream(PipeName, PipeDirection.In);
PipeSecurity pipeSecurity = _pipeStream.GetAccessControl();
pipeSecurity.AddAccessRule(new PipeAccessRule(new SecurityIdentifier(WellKnownSidType.AuthenticatedUserSid, domainSid: null), PipeAccessRights.ReadWrite, AccessControlType.Allow));
_pipeStream.SetAccessControl(pipeSecurity);
```
The NamedPipeServerStream
is created inside of a .Net Core Windows-Service and a NamedPipeClientStream
should be used by an application running in the user session to communicate to that service.
I ended up using a socket TCP stream for client-server communication on macOS and then using .NET Framework rather than .NET Core for the Windows portion of the project.
@pjanotti Is there currently a way to do cross-privilege message passing with .NET Core?
Is there currently a way to do cross-privilege message passing with .NET Core?
Calling the native WinAPI is still possible.
https://stackoverflow.com/a/54896975/499466
Hey, just to make sure I understood the current situation correctly.
My use case looks like the one of @kfreezen.
I run into the same issue as @kfreezen.
My library should target .NET Standard 2.0 as it is used by .NET Framework and .NET Core applications.
In my library I use PipeSecurity so that the pipe server can run as elevated user whereas the client runs with the Windows user:
C#
var security = new PipeSecurity();
security.AddAccessRule(new PipeAccessRule(new SecurityIdentifier(
WellKnownSidType.AuthenticatedUserSid, null),
PipeAccessRights.CreateNewInstance | PipeAccessRights.ReadWrite, AccessControlType.Allow));
var server = new NamedPipeServerStream(pipeName, PipeDirection.InOut, -1,
PipeTransmissionMode.Message, PipeOptions.Asynchronous | PipeOptions.WriteThrough,
0, 0, security);
Without being able to accomplish this with .NET Standard 2.0 I have to stay with the classic .NET Framework.
@JeremyKuhne is there any feasible workaround here? This is a famliar problem, that we did not find a good solution for in 3.0
is there any feasible workaround here?
Not really. We have to do the work to allow creating the pipe from a PipeSecurity
instance. I presume we'd want to add some ref struct that contains the SECURITY_ATTRIBUTES
and add an overload that PipeSecurity
can use.
``` C#
// Some assembly higher up than NamedPipeServerStream
public ref struct SecurityDescriptor
{
// Contains SECURITY_ATTRIBUTES
}
// NamedPipeServerStream
public NamedPipeServerStream(String pipeName, PipeDirection direction, int maxNumberOfServerInstances,
PipeTransmissionMode transmissionMode, PipeOptions options, int inBufferSize, int outBufferSize,
SecurityDescriptor pipeSecurity, HandleInheritability inheritability, PipeAccessRights additionalAccessRights)
// PipeSecurity
public NamedPipeServerStream CreateNamedPipeServerStream(String pipeName, PipeDirection direction, int maxNumberOfServerInstances,
PipeTransmissionMode transmissionMode, PipeOptions options, int inBufferSize, int outBufferSize,
HandleInheritability inheritability, PipeAccessRights additionalAccessRights)
```
That's where I would start. If anyone has time to try and make this happen I'm happy to help formalize and push through an API request.
Hi All!
Are there any solutions for this? I just ran into the ACL issue when trying to port a .NET Framework app to .NET Core. We need to be able to do cross-user IPC and this is blocking for us.
@TonyValenti we have an approved API that we're working on implementing now: dotnet/corefx#41657
@JeremyKuhne It looks like this has been implemented but isn't targeted for release until .NET 5.0 - a year from now. Is there any chance we can get an update to the System.IO.Pipes.AccessControl library that makes this work today?
Seconding @TonyValenti's comment - porting a critical piece of our previously .NET 4.7.1 app to .NET Core 3.1 this is a blocker.
If there's not an official back port - I'll probably end up doing a cherry-picked merge and crank out a local System.IO.Pipes.AccessControl NuGet package and host it in my Artifactory repo.
@jcapellman we don't have a plan to do this right now - maybe if there were lots of asks we could look at it again. It's tricky publishing packages intended to replace parts of the product, without officially servicing the product. What you described sounds like it would work meantime.
Note that we have historically supported production use on certain preview releases. It's not clear yet which preview build of 5.0 that would start with, but perhaps that would unblock you when it does.
Also note as you see from the links from https://github.com/dotnet/corefx/issues/41657 we added similar API for other objects.
I think this issue is resolved as far as we plan to resolve it, and there should be a way one way or another to get the job done now, so I'll close.
Thanks for the response @danmosemsft - given my product's timetable for our upcoming release I don't think the .NET 5 preview will work. I do plan on porting over to .NET 5 this Fall, so this could just be hold over for the next couple months.
Would it be against policy to publish it to NuGet for others also needing this as a stopgap? Otherwise I'll just keep it in my private artifactory repo. I'll begin the back porting tomorrow.
We ask that folks publishing to NuGet don't publish in such a way the the package looks like a Microsoft artifact if it's not. Ideally the code would be in a different namespace as well.
Another option you have perhaps is just sharing source code that could be pasted in.
Thanks for helping the community @jcapellman
Sounds good - I'll blog the changes/source code instead. It's nice to help out the community.
Quick update:
-Cloned the .NET Core 3.1 version from dotnet/corefx (release/3.1 branch)
-Simply modified the System.IO.Pipes and System.IO.Pipes.AccessControl libraries based on the PR
-Compiled with the .\build.cmd -c Release -arch x86 --framework netcoreapp /p:BuildNative=false
No issues - however when attempting to reference the newly created System.IO.Pipes and System.IO.Pipes.AccessControl dlls I was getting conflicts with System.Runtime 5.0 and my .NET Core 3.1 library that was referencing 4.2.2.0.
I saw the global.json in the root of the repo was referencing 3.1.100 so I am confused why the output would be using System.Runtime 5.0 vs .NET Core 3.1's 4.2.2.0. Outside the scope of this ticket, but a simple point in the right direction - hadn't gone through this repo before.
@ericstj can maybe give insight there.
however when attempting to reference the newly created System.IO.Pipes and System.IO.Pipes.AccessControl dlls I was getting conflicts with System.Runtime 5.0 and my .NET Core 3.1 library that was referencing 4.2.2.0.
It sounds to be like you weren't building clean. Master of dotnet/corefx is the only place you would have gotten that 5.0.0.0 version. The SDK doesn't really matter, we build System.Runtime as part of corefx. In your steps above, double check that you build clean. If you didn't clean up build artifacts between switching branches it's possible you had an issue.
git checkout release/3.1
rd /q /s artifacts
build
If you still face an issue share more details like the error text and the built assets or a branch and someone might be able to take a look.
I was really hoping for an official fix for this. This is blocking us from adopting .NET Core as well.
Environment details:
-VS 16.4.2 & VS 16.5.0 Preview 1.0 installed (full C++& C# environments installed)
-Windows 10 Pro (Build 19041.1)
Steps to repro:
Attached the full log output with the two errors. Appreciate the assistance @ericstj.
Cmake errors are https://github.com/dotnet/corefx/issues/41441, but can be ignored: you don't need the native bits if all you are doing is building these assemblies. This looks ok. Next step: what binaries are you picking from this and referencing in your app? Once you do that, how is it failing?
I'd expect you to pick up:
C:\ghgit\corefx\artifacts\bin\System.IO.Pipes\netcoreapp-Windows_NT-Debug\System.IO.Pipes.dll
C:\ghgit\corefx\artifacts\bin\System.IO.Pipes.AccessControl\netcoreapp-Windows_NT-Debug\System.IO.Pipes.AccessControl.dll
Hello.
Recently I encountered the same problem when translating the project to .Net Core.
I added a nuget package to help with the transition: https://www.nuget.org/packages/NamedPipeServerStream.NetFrameworkVersion/
The package targets .Net Standard 2.0 and contains the original constructor from the .Net Framework (which supports PipeSecurity, HandleInheritability, and PipeAccessRights). I restored it from decompiled code without making any changes. Exceptions are fully supported, no code has been lost. Has a strong name.
The source code is also available.
Most helpful comment
Hello.
Recently I encountered the same problem when translating the project to .Net Core.
I added a nuget package to help with the transition: https://www.nuget.org/packages/NamedPipeServerStream.NetFrameworkVersion/
The package targets .Net Standard 2.0 and contains the original constructor from the .Net Framework (which supports PipeSecurity, HandleInheritability, and PipeAccessRights). I restored it from decompiled code without making any changes. Exceptions are fully supported, no code has been lost. Has a strong name.
The source code is also available.