Pregunta

I'm writing a tool that can be used to manage the virtual host a web server on Ubuntu. As for many of the features I need privileged rights, I look for ways to achieve this.

Currently I realize that with "gksu" or "gksudo". This also works. The problem is that the user is prompted for any activity that requires privileged rights to enter his password. Is it possible to retrieve this password only once and remember for the rest of the duration of the program? Is there another way to implement this?

    public void OnToogledVirtualHost(object o, ToggledArgs args)
    {
        VirtualHost host = (VirtualHost)store.GetNode(new TreePath(args.Path));
        host.Enabled = !host.Enabled;
        Process process = new Process();
        process.StartInfo.UseShellExecute = false;

        if (host.Enabled)
        {
            process.StartInfo.FileName = "gksu";
            process.StartInfo.Arguments = "a2ensite " + System.IO.Path.GetFileName(host.FilePath);
        }
        else
        {
            process.StartInfo.FileName = "gksu";
            process.StartInfo.Arguments = "a2dissite " + System.IO.Path.GetFileName(host.FilePath);
        }
        process.Start();
    }
¿Fue útil?

Solución 3

Thanks for the useful approaches. Yesterday I arrived at a solution of the problem, which I have enclosed in a static class. First, a distinction is made between normal and privilligierten processes.

Whenever a process needs to be run with elevated privileges, I check if I know the user's password already. If not, I'll get it (gksudo -p) and store it in memory. Now I can execute commands with privilligierten rights. The stored password is then transferred via the standard input (sudo -S).

What do you think? Do you have any safety concerns?

public static class SystemProcess
{
    private static string output;
    private static string error;
    private static string password;

    public static void Start (string filename, string arguments)
    {
        ProcessStartInfo startInfo = SystemProcess.Prepare(filename, arguments);

        using (Process process = Process.Start(startInfo)) {
            SystemProcess.output = process.StandardOutput.ReadToEnd();
            SystemProcess.error = process.StandardError.ReadToEnd();

            process.WaitForExit();
        }
    }

    public static void StartPrivileged (string filename, string arguments)
    {
        ProcessStartInfo startInfo;

        if (SystemProcess.password == default(string))
        {
            startInfo = SystemProcess.Prepare("gksudo", "-p true -D 'MyApplication'");

            using (Process process = Process.Start(startInfo)) {
                SystemProcess.password = process.StandardOutput.ReadToEnd();
                process.WaitForExit();
            }
        }

        startInfo = SystemProcess.Prepare("sudo", "-S " + filename + " " + arguments);

        using (Process process = Process.Start(startInfo)) {
            process.StandardInput.WriteLine(SystemProcess.password);
            SystemProcess.output = process.StandardOutput.ReadToEnd();
            SystemProcess.error = process.StandardError.ReadToEnd();

            process.WaitForExit();
        }
    }

    private static ProcessStartInfo Prepare (string filename, string arguments)
    {
        ProcessStartInfo startInfo = new ProcessStartInfo (filename, arguments);

        startInfo.RedirectStandardError = true;
        startInfo.RedirectStandardOutput = true;
        startInfo.RedirectStandardInput = true;
        startInfo.UseShellExecute = false;

        return startInfo;
    }

    public static string Output {
        get {
            return SystemProcess.output;
        }
    }

    public static string Error {
        get {
            return SystemProcess.error;
        }
    }
}

Otros consejos

AFAIK, it is a security feature of 'su' not to cache the password (more properly the authentication ticket) for more than a few seconds, and thus this is designed not to be bypassed.

You can always gksu an intermediary process and try to make the sub-processes inherit its authorization, but you'll need to secure the IPC (the communication channel between your tool frontend and the intermediary process).

So my advice is to not try to lessen the security of the overall solution, so let the user be asked as many times as needed...

There are several (at least 3) "secure" solutions to this problem:

  1. Use "sudo", that allows for password caching. This is my preferred solution if I can install and configure sudo on the machine. Pros: sudo will cache the password. Cons: it depends on having an external dependency (sudo) correctly configured.
  2. Write different helper executables (for example a "modify configuration and restart apache" program) and when needed ask the user to authenticated using gksu, then launch them. Pros: user gets asked for the password only once for every group of actions. Cons: The user still get asked for the password multiple times AND you have to split the program in multiple pieces.
  3. Write a separate service that runs with root privileges and use polkit/DBUS to authenticate the user and connect to it to require services (like, "restart apache please"). Pros: credential caching and authentication dialog is managed by dekstop/polkit. Cons: more code to write and you need to run a DBUS service.

"secure" is quoted because running code (and especially managed code that depends on a large application such as Mono) as root always has security implications.

You know, I'd not use gksu or sudo for any of this, sounds like you want to look at userv instead.

You can basically permit different users to run different programs,

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top