grpc-dotnet-namedpipes icon indicating copy to clipboard operation
grpc-dotnet-namedpipes copied to clipboard

System.UnauthorizedAccessException when contacting gRPC server from another user

Open LAB02-Admin opened this issue 3 years ago • 5 comments

Hi again,

I'm running a service under SYSTEM account, and want to contact it from a normal user. I've already set CurrentUserOnly = false in both the client and server, but I still get a System.UnauthorizedAccessException whenever I try to connect.

If I run my client application elevated, it works fine, but that's not an option for deployment.

I don't see any options to set the security options like in this thread,

I'm guessing that has to do with the fact that I'm using .NET 6. In the past I've used this library NamedPipeServerStream.NetFrameworkVersion to restore the security options from .NET Framework. Is that something that could be used here?

LAB02-Admin avatar Mar 16 '22 09:03 LAB02-Admin

Update: I enabled PipeSecurity by adding NET6_0 to NamedPipeServerOptions.cs in your library:

#if NETFRAMEWORK || NET5_0 || NET6_0
        /// <summary>
        /// Gets or sets a value indicating the access control to be used for the pipe.
        /// </summary>
        public PipeSecurity PipeSecurity { get; set; }
#endif

Also added net6.0-windows as a target framework. I can make a PR if you want.

However, the problem's still there. I initialize the server with these settings (took them from GrpcNamedPipeTests.cs -> SimpleUnaryWithACLs():

var pipeSecurity = new PipeSecurity();
var usersSid = new SecurityIdentifier(WellKnownSidType.WorldSid, null);
var systemSid = new SecurityIdentifier(WellKnownSidType.LocalSystemSid, null);
pipeSecurity.AddAccessRule(new PipeAccessRule(usersSid, PipeAccessRights.ReadWrite, AccessControlType.Allow));
pipeSecurity.AddAccessRule(new PipeAccessRule(systemSid, PipeAccessRights.FullControl, AccessControlType.Allow));

var serverOptions = new NamedPipeServerOptions
{
    PipeSecurity = pipeSecurity
};

Tried with CurrentUserOnly = false as well. The service runs as SYSTEM, the client as a normal user.

I initialize the client's channel as such:

private readonly NamedPipeChannel _serviceChannel = new(".", Variables.PipeName, new NamedPipeChannelOptions 
{ 
        ConnectionTimeout = (int)TimeSpan.FromSeconds(10).TotalMilliseconds
});

Tried a bunch of TokenImpersonationLevel types as well, and CurrentUserOnly = false - no luck.

Any idea what I'm missing or doing wrong? Thanks!

LAB02-Admin avatar Mar 16 '22 10:03 LAB02-Admin

Okay, I fixed it. Had to add NET6_0 to ServerStreamPool.cs as well:

#if NET5_0 || NET6_0
            return NamedPipeServerStreamAcl.Create(_pipeName,
                PipeDirection.InOut,
                NamedPipeServerStream.MaxAllowedServerInstances,
                PipeTransmissionMode.Message,
                pipeOptions,
                0,
                0,
                _options.PipeSecurity);
#else
            return new NamedPipeServerStream(_pipeName,
                PipeDirection.InOut,
                NamedPipeServerStream.MaxAllowedServerInstances,
                PipeTransmissionMode.Message,
                pipeOptions);
#endif

Let me know if you want me to make a PR for this, if it's the solution you'd recommend.

LAB02-Admin avatar Mar 16 '22 11:03 LAB02-Admin

Hi, thanks for figuring that out! I'd merge a PR that uses NET5_0_OR_GREATER instead of NET5_0.

cyanfish avatar Mar 21 '22 15:03 cyanfish

Done: https://github.com/cyanfish/grpc-dotnet-namedpipes/pull/39

LAB02-Admin avatar Mar 23 '22 13:03 LAB02-Admin

Hey @cyanfish, could you please take a look at the PR and possible merge it? I now compiled and added my own library and its dependencies, but it'd be cleaner if I could just add your package again :)

Thanks!

LAB02-Admin avatar Apr 15 '22 09:04 LAB02-Admin

Sorry I didn't get to this until now, but this should be in 2.0.0 (along with some other changes listed in the changelog).

cyanfish avatar Nov 11 '22 02:11 cyanfish

Awesome! ❤️

LAB02-Admin avatar Nov 11 '22 08:11 LAB02-Admin