Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

System.IO.Pipes.AccessControl package does not work #26869

Closed
pjanotti opened this issue Jul 19, 2018 · 25 comments
Closed

System.IO.Pipes.AccessControl package does not work #26869

pjanotti opened this issue Jul 19, 2018 · 25 comments

Comments

@pjanotti
Copy link
Contributor

pjanotti commented Jul 19, 2018

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

@kfreezen
Copy link

kfreezen commented Sep 10, 2018

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?

@pjanotti
Copy link
Contributor Author

pjanotti commented Sep 28, 2018

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?

@kfreezen
Copy link

kfreezen commented Oct 5, 2018

@MarcusWichelmann
Copy link

MarcusWichelmann commented Dec 5, 2018

@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.

_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.

@kfreezen
Copy link

kfreezen commented Dec 6, 2018

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?

@Jens-G
Copy link

Jens-G commented Feb 27, 2019

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

@darinkes
Copy link

darinkes commented Mar 27, 2019

Hey, just to make sure I understood the current situation correctly.
My use case looks like the one of @kfreezen.

  • It's currently just usable for two processes running under the same User?
  • There is currently no way to configure Access-Rules or Permissions on non-Windows OSes?

@omghb
Copy link

omghb commented May 10, 2019

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:

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.

@danmoseley
Copy link
Member

danmoseley commented May 14, 2019

@JeremyKuhne is there any feasible workaround here? This is a famliar problem, that we did not find a good solution for in 3.0

@JeremyKuhne
Copy link
Member

JeremyKuhne commented May 14, 2019

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.

// 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.

@TonyValenti
Copy link

TonyValenti commented Oct 14, 2019

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.

@JeremyKuhne
Copy link
Member

JeremyKuhne commented Oct 14, 2019

@TonyValenti we have an approved API that we're working on implementing now: dotnet/corefx#41657

@TonyValenti
Copy link

TonyValenti commented Dec 8, 2019

@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?

@jcapellman
Copy link

jcapellman commented Jan 7, 2020

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.

@danmoseley
Copy link
Member

danmoseley commented Jan 7, 2020

@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.

@jcapellman
Copy link

jcapellman commented Jan 8, 2020

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.

@danmoseley
Copy link
Member

danmoseley commented Jan 8, 2020

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

@jcapellman
Copy link

jcapellman commented Jan 8, 2020

Sounds good - I'll blog the changes/source code instead. It's nice to help out the community.

@jcapellman
Copy link

jcapellman commented Jan 9, 2020

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.

@danmoseley
Copy link
Member

danmoseley commented Jan 9, 2020

@ericstj can maybe give insight there.

@ericstj
Copy link
Member

ericstj commented Jan 9, 2020

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.

@TonyValenti
Copy link

TonyValenti commented Jan 9, 2020

I was really hoping for an official fix for this. This is blocking us from adopting .NET Core as well.

@jcapellman
Copy link

jcapellman commented Jan 10, 2020

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:

  1. git clone https://github.com/dotnet/corefx.git
  2. git checkout release/3.1
  3. build.cmd (no parameters)
  4. Receive 2 build errors (previously I wasn't compiling the native libraries - might have been the cause of my System.Runtime 5.0 issue?)

Attached the full log output with the two errors. Appreciate the assistance @ericstj.

log.txt

@ericstj
Copy link
Member

ericstj commented Jan 10, 2020

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

@HavenDV
Copy link

HavenDV commented Jan 12, 2020

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.

@msftgits msftgits transferred this issue from dotnet/corefx Jan 31, 2020
@msftgits msftgits added this to the Future milestone Jan 31, 2020
@msftbot msftbot bot locked as resolved and limited conversation to collaborators Dec 16, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests