Change current Linux user in a C# application runn

2019-04-25 20:19发布

I am developing a library (CLI assembly) for a Linux system. I want to provide a method for users of the library to switch the current effective user and group. The primary reason is to provide access control (certain actions only allowed by certain users), and secondarily to enable modification of file system as a certain user.

I have identified two possible approaches:

1. Start Mono as root and P/invoke libc routines like seteuid, etc

Having implemented this by setting the s bit of /usr/bin/mono and then setting back effective user from my library (i.e. after the Mono run-time is started) causes a crash in Mono when it terminates:

ERROR:handles.c:1940:_wapi_handle_update_refs: assertion failed: (thr_ret == 0)

Native stacktrace:

mono2 [0x8bb6c]
  /lib/libc.so.6(__default_rt_sa_restorer_v2+0) [0x4020a5a0]
  /lib/libc.so.6(gsignal+0x40) [0x4020920c]

Logically I understand there may be issues with changing the effective user of Mono as it is managing a number of resources, and it may cause problems doing so.

2. Handle authentication in a native daemon and not change Mono effective user

I'm not sure if there are any off-the-shelf solutions for this, but conceptually I'm thinking to have a daemon running as root, which the library will communicate with (for example through POSIX message queues) to perform the authentication. The daemon is running as root to be able to read /etc/shadow. The effective user of Mono will not be changed, but my library will keep track of which "equivalent user" the process is running as. Unfortunately this approach will not allow the library to access the file system as a different user.

Question

Am I stuck with the second option, or is there some way to actually change effective user of a Mono process?

Thank you!

标签: c# linux mono
1条回答
2楼-- · 2019-04-25 20:23

The following works on my box :)

EDIT #1: This should be executed as root. (Snippet taken from : http://msdn.microsoft.com/en-us/library/w070t6ka.aspx)

using System;
using System.Security.Permissions;
using System.Security.Principal;

public class ImpersonationDemo
{
// Test harness. 
// If you incorporate this code into a DLL, be sure to demand FullTrust.
[PermissionSetAttribute(SecurityAction.Demand, Name = "FullTrust")]
public static void Main (string[] args)
{
    try {
        // Check the identity.
        Console.WriteLine ("Before impersonation: " + WindowsIdentity.GetCurrent ().Name);

        // Impersonate a user
        using (WindowsIdentity newId = new WindowsIdentity("Your user name"))
        using (WindowsImpersonationContext impersonatedUser = newId.Impersonate())
        {
            // Check the identity.
            Console.WriteLine ("After impersonation: " + WindowsIdentity.GetCurrent ().Name);
        }

        // Releasing the context object stops the impersonation 
        // Check the identity.
        Console.WriteLine ("After closing the context: " + WindowsIdentity.GetCurrent ().Name);
    } catch (Exception ex) {
        Console.WriteLine ("Exception occurred. " + ex.Message);
    }
}
}
查看更多
登录 后发表回答